├── taxi ├── src │ └── main │ │ ├── resources │ │ └── accounts.csv │ │ └── java │ │ └── com │ │ └── epam │ │ └── training │ │ └── taxi │ │ └── Calculator.java ├── README.md └── pom.xml ├── README.md ├── final ├── ticket-service │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── com │ │ │ └── epam │ │ │ └── training │ │ │ └── ticketservice │ │ │ └── Application.java │ ├── checkstyle │ │ ├── suppressions.xml │ │ └── checkstyle.xml │ └── pom.xml ├── ticket-service-acceptance-tests │ ├── src │ │ └── test │ │ │ ├── java │ │ │ └── com │ │ │ │ └── training │ │ │ │ └── epam │ │ │ │ └── ticketservice │ │ │ │ └── at │ │ │ │ ├── TestExecutor.java │ │ │ │ ├── GenericCliProcessStepDefs.java │ │ │ │ └── ProcessUnderTest.java │ │ │ └── resources │ │ │ └── features │ │ │ ├── movies.feature │ │ │ ├── rooms.feature │ │ │ ├── accounts.feature │ │ │ ├── bookings.feature │ │ │ ├── pricing.feature │ │ │ └── screenings.feature │ └── pom.xml ├── pom.xml └── README.md ├── .gitignore └── money ├── src ├── main │ └── java │ │ └── com │ │ └── epam │ │ └── training │ │ └── money │ │ └── impl │ │ └── Money.java └── test │ └── java │ └── com │ └── epam │ └── training │ └── money │ └── MoneyIT.java └── pom.xml /taxi/src/main/resources/accounts.csv: -------------------------------------------------------------------------------- 1 | 1,Kiss Béla,0.1 2 | 2,Nagy Géza,1 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Java development in practice 2 | 3 | This is a repository containing resources and materials for the 'Java development in 4 | practice' course. -------------------------------------------------------------------------------- /final/ticket-service/src/main/java/com/epam/training/ticketservice/Application.java: -------------------------------------------------------------------------------- 1 | package com.epam.training.ticketservice; 2 | 3 | public class Application { 4 | public static void main(String[] args) { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /final/ticket-service/checkstyle/suppressions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | -------------------------------------------------------------------------------- /final/ticket-service-acceptance-tests/src/test/java/com/training/epam/ticketservice/at/TestExecutor.java: -------------------------------------------------------------------------------- 1 | package com.training.epam.ticketservice.at; 2 | 3 | import org.junit.runner.RunWith; 4 | 5 | import io.cucumber.junit.Cucumber; 6 | import io.cucumber.junit.CucumberOptions; 7 | 8 | @RunWith(Cucumber.class) 9 | @CucumberOptions(features="src/test/resources/features/") 10 | public class TestExecutor { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /taxi/README.md: -------------------------------------------------------------------------------- 1 | # 1. házi feladat: Taxi 2 | 3 | Ebben a feladatban lehetőségetek lesz gyakorolni a kódolvasást, különböző refaktorálási 4 | módszereket, az egységtesztek írását és a mock-ok használatát. 5 | 6 | ## Domain 7 | 8 | Egy taxi vállalat szoftverét fejleszted, ahol hamarosan nagyobb bővítés várható a 9 | számlázást végző kódban. Sajnos azonban a kód elég régi, már egy fejlesztő sincs 10 | a cégnél, aki részt vett az elkészítésében, ráadásul a commitokban említett ticketek 11 | sem túl részletesek a követelményeket illetően. Emellett a kód minősége sem a legjobb, 12 | nem könnyű olvasni, a teljes logika egyetlen osztályban található, a megoldás nehézkesen 13 | bővíthető. 14 | 15 | ## A feladat 16 | 17 | 1. Írj a jelenlegi kódot (src/main/java/com/epam/training/taxi/Calculator.java) teljesen lefedő teszt-eseteket 18 | 1. Ez segít feltárni a követelményeket, amely alapján a jelenlegi program működik, illetve 19 | 1. Biztosítja azt, hogy a rafaktorálás során nem változtatod meg a kód működését 20 | 1. Refaktoráld a jelenlegi kódot 21 | 1. Igyekezz objektum-orientáltan megoldani a feladatot 22 | 1. Figyelj a [Java kódolási konvenciókra](https://www.oracle.com/technetwork/java/codeconventions-150003.pdf) 23 | 1. Ha új osztályt vezetsz be, ne felejts el egységtesztet is készíteni hozzá 24 | 1. A fő fókusz legyen a felelősségek megfelelő elosztásán és a bővíthetőségen 25 | 26 | -------------------------------------------------------------------------------- /taxi/src/main/java/com/epam/training/taxi/Calculator.java: -------------------------------------------------------------------------------- 1 | package com.epam.training.taxi; 2 | 3 | import java.io.FileWriter; 4 | import java.io.IOException; 5 | import java.nio.file.Files; 6 | import java.nio.file.Path; 7 | 8 | public class Calculator { 9 | 10 | public static void main(String[] args) throws IOException { 11 | // Get params 12 | Long Acc_ID = Long.valueOf(args[0]); 13 | Double Dist = Double.valueOf(args[1]); 14 | 15 | // Get acc 16 | String[] Acc = Files.lines(Path.of("src/main/resources/accounts.csv")) 17 | .map(line -> line.split(",")) 18 | .filter(record -> Long.parseLong(record[0])==Acc_ID) 19 | .findFirst() 20 | .orElse(null); 21 | 22 | // Calc 23 | if (Acc!=null) { 24 | double Discount_perc = Double.parseDouble(Acc[2]); 25 | Double price = Dist * 110; 26 | price = price - price*Discount_perc; 27 | FileWriter Out = new FileWriter("./out.csv", true); 28 | Out.write(Acc_ID.toString() + "," + Dist.toString() + "," + price + "," + Dist*110*Discount_perc + System.lineSeparator()); 29 | Out.close(); 30 | } else { 31 | Double price = Dist * 110; 32 | FileWriter Out = new FileWriter("./out.csv", true); 33 | Out.write("null," + Dist.toString() + "," + price + "," + 0 + System.lineSeparator()); 34 | Out.close(); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /final/ticket-service-acceptance-tests/src/test/java/com/training/epam/ticketservice/at/GenericCliProcessStepDefs.java: -------------------------------------------------------------------------------- 1 | package com.training.epam.ticketservice.at; 2 | 3 | import static org.hamcrest.CoreMatchers.equalTo; 4 | import static org.hamcrest.MatcherAssert.assertThat; 5 | 6 | import java.io.IOException; 7 | import java.util.concurrent.ExecutionException; 8 | import java.util.concurrent.TimeoutException; 9 | 10 | import io.cucumber.java.After; 11 | import io.cucumber.java.en.Given; 12 | import io.cucumber.java.en.Then; 13 | import io.cucumber.java.en.When; 14 | 15 | public class GenericCliProcessStepDefs { 16 | 17 | private static final int OUTPUT_TIMEOUT = 15000; 18 | 19 | private ProcessUnderTest cliProcess; 20 | 21 | public GenericCliProcessStepDefs(ProcessUnderTest cliProcess) { 22 | this.cliProcess = cliProcess; 23 | } 24 | 25 | @Given("the application is started") 26 | public void applicationStarted() throws IOException, InterruptedException { 27 | cliProcess.run("java -jar -Dspring.profiles.active=ci ../ticket-service/target/ticket-service-0.0.1-SNAPSHOT.jar"); 28 | } 29 | 30 | @Given("the prompt containing {string} is printed") 31 | public void promptReturned(String expectedPrompt) throws InterruptedException, ExecutionException, TimeoutException { 32 | cliProcess.waitForOutput(expectedPrompt, OUTPUT_TIMEOUT); 33 | } 34 | 35 | @When("the user types the {string} command") 36 | public void theUserTypes(String command) throws IOException { 37 | cliProcess.writeOnInput(command + System.lineSeparator()); 38 | } 39 | 40 | @Then("the next line of the output is {string}") 41 | public void theNextLineOfOutputContains(String expectedOutput) throws InterruptedException, ExecutionException, TimeoutException { 42 | String actualLine = cliProcess.readNextLine(OUTPUT_TIMEOUT); 43 | assertThat(actualLine, equalTo(expectedOutput)); 44 | } 45 | 46 | @After 47 | public void cleanup() { 48 | cliProcess.close(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /money/src/main/java/com/epam/training/money/impl/Money.java: -------------------------------------------------------------------------------- 1 | package com.epam.training.money.impl; 2 | 3 | import java.util.Currency; 4 | 5 | public class Money { 6 | 7 | /** 8 | * val 9 | */ 10 | public double val; 11 | public Currency c; 12 | 13 | /** 14 | * Constructor for money 15 | * @param dValue double value 16 | * @param c c 17 | */ 18 | public Money(double dValue, Currency c) { 19 | this.val = dValue; 20 | this.c = c; 21 | } 22 | 23 | public double how_much() { 24 | return val; 25 | } 26 | 27 | public Currency what() { 28 | return c; 29 | } 30 | 31 | public Money add(Money moneyzToGiveMeh) { 32 | // Convert 33 | if (!this.c.equals(moneyzToGiveMeh.what())) { // If the two currency does not match 34 | if (this.what().equals(Currency.getInstance("USD")) && moneyzToGiveMeh.what().equals(Currency.getInstance("HUF"))) 35 | moneyzToGiveMeh = new Money(moneyzToGiveMeh.val *0.0034, Currency.getInstance("USD")); 36 | else if (this.what().equals(Currency.getInstance("HUF")) && moneyzToGiveMeh.what().equals(Currency.getInstance("USD"))) 37 | moneyzToGiveMeh = new Money(moneyzToGiveMeh.val *249.3, Currency.getInstance("HUF")); 38 | // else if (this.what().equals(Currency.getInstance("ASD")) && moneyzToGiveMeh.what().equals(Currency.getInstance("USD"))) 39 | // moneyzToGiveMeh = new Money(moneyzToGiveMeh.val *249.3, Currency.getInstance("ASD")); 40 | else return null; 41 | } 42 | this.val += moneyzToGiveMeh.how_much(); // Add value of the parameter to this.val 43 | return this; 44 | } 45 | 46 | public Integer compareTo(Money m) { 47 | if (!this.c.equals(m.what())) { 48 | if (this.what().equals(Currency.getInstance("USD")) && m.what().equals(Currency.getInstance("HUF"))) 49 | m = new Money(m.val*0.0034, Currency.getInstance("USD")); 50 | else if (this.what().equals(Currency.getInstance("HUF")) && m.what().equals(Currency.getInstance("USD"))) 51 | m = new Money(m.val*249.3, Currency.getInstance("HUF")); 52 | else return null; 53 | } 54 | return Double.compare(this.how_much(), m.how_much()); 55 | } 56 | } -------------------------------------------------------------------------------- /final/ticket-service-acceptance-tests/src/test/resources/features/movies.feature: -------------------------------------------------------------------------------- 1 | Feature: allows creating movie descriptions 2 | Background: 3 | Given the application is started 4 | And the prompt containing "Ticket service>" is printed 5 | 6 | @grade2-requirement 7 | Scenario: an admin user can create and list movies 8 | Given the user types the "sign in privileged admin admin" command 9 | When the user types the "create movie Sátántangó drama 450" command 10 | And the user types the "list movies" command 11 | Then the next line of the output is "Sátántangó (drama, 450 minutes)" 12 | 13 | @grade2-requirement 14 | Scenario: an admin user can update a movie 15 | Given the user types the "sign in privileged admin admin" command 16 | And the user types the "create movie Sátántangó dram 450" command 17 | When the user types the "update movie Sátántangó drama 450" command 18 | And the user types the "list movies" command 19 | Then the next line of the output is "Sátántangó (drama, 450 minutes)" 20 | 21 | @grade2-requirement 22 | Scenario: an admin user can delete a movie 23 | Given the user types the "sign in privileged admin admin" command 24 | And the user types the "create movie Sátántangó drama 450" command 25 | When the user types the "delete movie Sátántangó" command 26 | And the user types the "list movies" command 27 | Then the next line of the output is "There are no movies at the moment" 28 | 29 | @grade2-requirement 30 | Scenario: an unauthenticated user can list movies 31 | Given the user types the "sign in privileged admin admin" command 32 | And the user types the "create movie Sátántangó drama 450" command 33 | And the user types the "sign out" command 34 | When the user types the "list movies" command 35 | Then the next line of the output is "Sátántangó (drama, 450 minutes)" 36 | 37 | @grade4-requirement 38 | Scenario: an authenticated, non-privileged user can list movies 39 | Given the user types the "sign in privileged admin admin" command 40 | And the user types the "create movie Sátántangó drama 450" command 41 | And the user types the "sign out" command 42 | And the user types the "sign up sanyi asdQWE123" command 43 | When the user types the "sign in sanyi asdQWE123" command 44 | And the user types the "list movies" command 45 | Then the next line of the output is "Sátántangó (drama, 450 minutes)" 46 | -------------------------------------------------------------------------------- /final/ticket-service-acceptance-tests/src/test/resources/features/rooms.feature: -------------------------------------------------------------------------------- 1 | Feature: allow creating, reading, updating and deleting rooms where the screenings will happen 2 | 3 | Background: 4 | Given the application is started 5 | And the prompt containing "Ticket service>" is printed 6 | 7 | @grade2-requirement 8 | Scenario: an admin user can create and list rooms 9 | Given the user types the "sign in privileged admin admin" command 10 | When the user types the "create room Pedersoli 20 10" command 11 | And the user types the "list rooms" command 12 | Then the next line of the output is "Room Pedersoli with 200 seats, 20 rows and 10 columns" 13 | 14 | @grade2-requirement 15 | Scenario: an admin user can update a room 16 | Given the user types the "sign in privileged admin admin" command 17 | And the user types the "create room Pedersoli 20 10" command 18 | When the user types the "update room Pedersoli 10 10" command 19 | And the user types the "list rooms" command 20 | Then the next line of the output is "Room Pedersoli with 100 seats, 10 rows and 10 columns" 21 | 22 | @grade2-requirement 23 | Scenario: an admin user can delete a room 24 | Given the user types the "sign in privileged admin admin" command 25 | And the user types the "create room Pedersoli 20 10" command 26 | When the user types the "delete room Pedersoli" command 27 | And the user types the 'list rooms' command 28 | Then the next line of the output is "There are no rooms at the moment" 29 | 30 | @grade2-requirement 31 | Scenario: an unauthenticated user can list rooms 32 | Given the user types the "sign in privileged admin admin" command 33 | And the user types the "create room Pedersoli 20 10" command 34 | And the user types the "sign out" command 35 | When the user types the "list rooms" command 36 | Then the next line of the output is "Room Pedersoli with 200 seats, 20 rows and 10 columns" 37 | 38 | @grade4-requirement 39 | Scenario: an authenticated, non-privileged user can list rooms 40 | Given the user types the "sign in privileged admin admin" command 41 | And the user types the "create room Pedersoli 20 10" command 42 | And the user types the "sign out" command 43 | And the user types the "sign up sanyi asdQWE123" command 44 | When the user types the "sign in sanyi asdQWE123" command 45 | And the user types the "list rooms" command 46 | Then the next line of the output is "Room Pedersoli with 200 seats, 20 rows and 10 columns" 47 | -------------------------------------------------------------------------------- /final/ticket-service-acceptance-tests/src/test/resources/features/accounts.feature: -------------------------------------------------------------------------------- 1 | Feature: allow creating accounts and logging in 2 | 3 | Background: 4 | Given the application is started 5 | And the prompt containing "Ticket service>" is printed 6 | 7 | @grade2-requirement 8 | Scenario: the admin account exists by default and can be logged in with the correct password 9 | When the user types the "sign in privileged admin admin" command 10 | And the user types the "describe account" command 11 | Then the next line of the output is "Signed in with privileged account 'admin'" 12 | 13 | @grade2-requirement 14 | Scenario: the admin account can be signed out 15 | Given the user types the "sign in privileged admin admin" command 16 | When the user types the "sign out" command 17 | And the user types the "describe account" command 18 | Then the next line of the output is "You are not signed in" 19 | 20 | @grade2-requirement 21 | Scenario: the admin account can not be logged in with incorrect password 22 | When the user types the "sign in privileged admin asdQWE123" command 23 | Then the next line of the output is "Login failed due to incorrect credentials" 24 | When the user types the "describe account" command 25 | Then the next line of the output is "You are not signed in" 26 | 27 | @grade4-requirement 28 | Scenario: non-privileged accounts can be created and logged in with the correct password 29 | When the user types the "sign up sanyi asdQWE123" command 30 | And the user types the "sign in sanyi asdQWE123" command 31 | And the user types the "describe account" command 32 | Then the next line of the output is "Signed in with account 'sanyi'" 33 | And the next line of the output is "You have not booked any tickets yet" 34 | 35 | @grade4-requirement 36 | Scenario: non-privileged accounts can not be logged in with the incorrect password 37 | Given the user types the "sign up sanyi asdQWE123" command 38 | When the user types the "sign in sanyi alma" command 39 | Then the next line of the output is "Login failed due to incorrect credentials" 40 | When the user types the "describe account" command 41 | Then the next line of the output is "You are not signed in" 42 | 43 | @grade4-requirement 44 | Scenario: non-privileged accounts can be signed out 45 | Given the user types the "sign up sanyi asdQWE123" command 46 | And the user types the "sign in sanyi asdQWE123" command 47 | When the user types the "sign out" command 48 | And the user types the "describe account" command 49 | Then the next line of the output is "You are not signed in" -------------------------------------------------------------------------------- /money/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 4.0.0 6 | 7 | com.epam.training 8 | money 9 | 1.0.0-SNAPSHOT 10 | 11 | Money 12 | A library for handling monetary values 13 | 14 | 15 | 11 16 | UTF-8 17 | 18 | 19 | 20 | 21 | org.junit.jupiter 22 | junit-jupiter-api 23 | 5.7.1 24 | test 25 | 26 | 27 | 28 | org.junit.jupiter 29 | junit-jupiter-engine 30 | 5.7.1 31 | test 32 | 33 | 34 | 35 | org.junit.jupiter 36 | junit-jupiter-params 37 | 5.7.1 38 | test 39 | 40 | 41 | 42 | org.hamcrest 43 | hamcrest-core 44 | 1.3 45 | test 46 | 47 | 48 | 49 | 50 | 51 | 52 | org.apache.maven.plugins 53 | maven-compiler-plugin 54 | 55 | ${java.version} 56 | ${java.version} 57 | 58 | 59 | 60 | org.apache.maven.plugins 61 | maven-failsafe-plugin 62 | 3.0.0-M5 63 | 64 | 65 | 66 | integration-test 67 | verify 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /taxi/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 4.0.0 6 | 7 | com.epam.training 8 | taxi 9 | 1.0.0-SNAPSHOT 10 | 11 | Taxi 12 | Some code about using a taxi and paying for it - not sure I understand 13 | 14 | 15 | 11 16 | UTF-8 17 | 18 | 19 | 20 | 21 | org.junit.jupiter 22 | junit-jupiter-api 23 | 5.7.1 24 | test 25 | 26 | 27 | 28 | org.junit.jupiter 29 | junit-jupiter-engine 30 | 5.7.1 31 | test 32 | 33 | 34 | 35 | org.junit.jupiter 36 | junit-jupiter-params 37 | 5.7.1 38 | test 39 | 40 | 41 | 42 | org.hamcrest 43 | hamcrest-core 44 | 1.3 45 | test 46 | 47 | 48 | 49 | 50 | 51 | 52 | org.apache.maven.plugins 53 | maven-compiler-plugin 54 | 55 | ${java.version} 56 | ${java.version} 57 | 58 | 59 | 60 | org.apache.maven.plugins 61 | maven-failsafe-plugin 62 | 3.0.0-M5 63 | 64 | 65 | 66 | integration-test 67 | verify 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /final/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.epam.training.ticketservice 8 | ticket-service-parent 9 | pom 10 | 1.0-SNAPSHOT 11 | 12 | 13 | 11 14 | 11 15 | 16 | 17 | 18 | ticket-service 19 | ticket-service-acceptance-tests 20 | 21 | 22 | 23 | 24 | requirements-grade2 25 | 26 | true 27 | 28 | 29 | false 30 | 0.4 31 | 0.4 32 | @grade2-requirement 33 | 34 | 35 | 36 | requirements-grade3 37 | 38 | true 39 | 0.4 40 | 0.4 41 | @grade2-requirement or @grade3-requirement 42 | 43 | 44 | 45 | requirements-grade4 46 | 47 | true 48 | 0.5 49 | 0.5 50 | @grade2-requirement or @grade3-requirement or @grade4-requirement 51 | 52 | 53 | 54 | 55 | requirements-grade5 56 | 57 | true 58 | 0.7 59 | 0.7 60 | @grade2-requirement or @grade3-requirement or @grade4-requirement or 61 | @grade5-requirement 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /final/ticket-service-acceptance-tests/src/test/resources/features/bookings.feature: -------------------------------------------------------------------------------- 1 | Feature: allows users to book tickets for screenings, and show booking history 2 | 3 | Background: 4 | Given the application is started 5 | And the prompt containing "Ticket service>" is printed 6 | And the user types the "sign up sanyi asdQWE123" command 7 | And the user types the "sign up laci asdQWE123" command 8 | And the user types the "sign in privileged admin admin" command 9 | And the user types the "create room Pedersoli 20 10" command 10 | And the user types the "create room Girotti 10 10" command 11 | And the user types the "create movie Sátántangó drama 450" command 12 | And the user types the "create movie \"Spirited Away\" animation 125" command 13 | And the user types the "create screening \"Spirited Away\" Girotti \"2021-03-15 10:00\"" command 14 | And the user types the "create screening Sátántangó Pedersoli \"2021-03-15 10:45\"" command 15 | And the user types the "sign out" command 16 | 17 | @grade4-requirement 18 | Scenario: an authenticated user can book a ticket for a screening 19 | Given the user types the "sign in sanyi asdQWE123" command 20 | When the user types the "book Sátántangó Pedersoli \"2021-03-15 10:45\" \"5,5 5,6\"" command 21 | Then the next line of the output is "Seats booked: (5,5), (5,6); the price for this booking is 3000 HUF" 22 | When the user types the "describe account" command 23 | Then the next line of the output is "Signed in with account 'sanyi'" 24 | And the next line of the output is "Your previous bookings are" 25 | And the next line of the output is "Seats (5,5), (5,6) on Sátántangó in room Pedersoli starting at 2021-03-15 10:45 for 3000 HUF" 26 | 27 | @grade4-requirement 28 | Scenario: an authenticated user can not book a ticket if at least one of the seats is already taken 29 | Given the user types the "sign in sanyi asdQWE123" command 30 | And the user types the "book Sátántangó Pedersoli \"2021-03-15 10:45\" \"5,5\"" command 31 | And the user types the "sign out" command 32 | And the user types the "sign in laci asdQWE123" command 33 | When the user types the "book Sátántangó Pedersoli \"2021-03-15 10:45\" \"5,5 5,6\"" command 34 | Then the next line of the output is "Seat (5,5) is already taken" 35 | When the user types the "describe account" command 36 | Then the next line of the output is "Signed in with account 'laci'" 37 | And the next line of the output is "You have not booked any tickets yet" 38 | 39 | @grade5-requirement 40 | Scenario: the price of the ticket in the history should not change if pricing changes after the booking 41 | Given the user types the "sign in sanyi asdQWE123" command 42 | And the user types the "book Sátántangó Pedersoli \"2021-03-15 10:45\" \"5,5\"" command 43 | And the user types the "sign out" command 44 | And the user types the "sign in privileged admin admin" command 45 | And the user types the "update base price 5000" command 46 | And the user types the "sign out" command 47 | And the user types the "sign in sanyi asdQWE123" command 48 | When the user types the "describe account" command 49 | Then the next line of the output is "Signed in with account 'sanyi'" 50 | And the next line of the output is "Your previous bookings are" 51 | And the next line of the output is "Seats (5,5) on Sátántangó in room Pedersoli starting at 2021-03-15 10:45 for 1500 HUF" -------------------------------------------------------------------------------- /final/ticket-service-acceptance-tests/src/test/java/com/training/epam/ticketservice/at/ProcessUnderTest.java: -------------------------------------------------------------------------------- 1 | package com.training.epam.ticketservice.at; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.io.OutputStreamWriter; 7 | import java.io.Writer; 8 | import java.util.concurrent.Callable; 9 | import java.util.concurrent.ExecutionException; 10 | import java.util.concurrent.Executors; 11 | import java.util.concurrent.TimeUnit; 12 | import java.util.concurrent.TimeoutException; 13 | 14 | import org.slf4j.Logger; 15 | import org.slf4j.LoggerFactory; 16 | 17 | import com.google.common.util.concurrent.SimpleTimeLimiter; 18 | 19 | public class ProcessUnderTest implements AutoCloseable { 20 | 21 | private static final Logger LOGGER = LoggerFactory.getLogger(ProcessUnderTest.class); 22 | private static final int JVM_STARTUP_FAILURE_WAIT_TIME = 150; 23 | private static final int DELAY_BEFORE_CLEANING_PROCESS_OUTPUT = 250; 24 | 25 | private Process process; 26 | private BufferedReader output; 27 | private Writer input; 28 | 29 | public void run(String command) throws IOException, InterruptedException { 30 | if (this.process != null && process.isAlive()) { 31 | return; 32 | } 33 | process = Runtime.getRuntime().exec(command); 34 | output = new BufferedReader(new InputStreamReader(process.getInputStream())); 35 | input = new OutputStreamWriter(process.getOutputStream()); 36 | Thread.sleep(JVM_STARTUP_FAILURE_WAIT_TIME); 37 | verifyProcessIsRunning(); 38 | } 39 | 40 | public void waitForOutput(String expectedOutput, long timeout) throws InterruptedException, ExecutionException, TimeoutException { 41 | verifyProcessIsRunning(); 42 | runWithTimeout(() -> readOutputUntil(expectedOutput), timeout); 43 | } 44 | 45 | public String readNextLine(long timeout) throws InterruptedException, ExecutionException, TimeoutException { 46 | verifyProcessIsRunning(); 47 | return runWithTimeout(() -> output.readLine(), timeout); 48 | } 49 | 50 | 51 | @Override 52 | public void close() { 53 | process.destroy(); 54 | } 55 | 56 | public void writeOnInput(String command) throws IOException { 57 | verifyProcessIsRunning(); 58 | clearOutput(DELAY_BEFORE_CLEANING_PROCESS_OUTPUT); 59 | input.write(command + System.lineSeparator()); 60 | input.flush(); 61 | } 62 | 63 | private void clearOutput(long delayBeforeCleaning) throws IOException { 64 | try { 65 | Thread.sleep(delayBeforeCleaning); 66 | } catch (InterruptedException e) { 67 | e.printStackTrace(); 68 | } 69 | while (output.ready()) { 70 | output.read(); 71 | } 72 | } 73 | 74 | private Void readOutputUntil(String expectedOutput) throws IOException { 75 | String actualString = ""; 76 | do { 77 | actualString += (char) output.read(); 78 | if (actualString.length() > expectedOutput.length()) { 79 | actualString = actualString.substring(1); 80 | } 81 | } while (!actualString.equals(expectedOutput)); 82 | return null; // Void for the sake of generics 83 | } 84 | 85 | private T runWithTimeout(Callable callable, long timeout) throws InterruptedException, ExecutionException, TimeoutException { 86 | SimpleTimeLimiter timeLimiter = SimpleTimeLimiter.create(Executors.newSingleThreadExecutor()); 87 | return timeLimiter.callWithTimeout(callable, timeout, TimeUnit.MILLISECONDS); 88 | } 89 | 90 | private void verifyProcessIsRunning() { 91 | if (this.process == null || !process.isAlive()) { 92 | throw new AssertionError("The service is not running."); 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /money/src/test/java/com/epam/training/money/MoneyIT.java: -------------------------------------------------------------------------------- 1 | package com.epam.training.money; 2 | 3 | import static java.lang.Integer.signum; 4 | import static org.hamcrest.CoreMatchers.equalTo; 5 | import static org.hamcrest.CoreMatchers.nullValue; 6 | import static org.hamcrest.MatcherAssert.assertThat; 7 | 8 | import java.util.Currency; 9 | 10 | import org.junit.jupiter.api.Test; 11 | import org.junit.jupiter.params.ParameterizedTest; 12 | import org.junit.jupiter.params.provider.CsvSource; 13 | 14 | import com.epam.training.money.impl.Money; 15 | 16 | public class MoneyIT { 17 | 18 | private static final Currency HUF_CURRENCY = Currency.getInstance("HUF"); 19 | private static final Currency USD_CURRENCY = Currency.getInstance("USD"); 20 | private static final Currency GBP_CURRENCY = Currency.getInstance("GBP"); 21 | 22 | @Test 23 | public void testAddReturnsExpectedResultWhenDifferentCurrencyIsUsed() { 24 | // Given 25 | Money underTest = new Money(120, HUF_CURRENCY); 26 | Money moneyToAdd = new Money(1, USD_CURRENCY); 27 | 28 | // When 29 | Money result = underTest.add(moneyToAdd); 30 | 31 | // Then 32 | assertThat(result.how_much(), equalTo(369.3)); 33 | assertThat(result.what(), equalTo(HUF_CURRENCY)); 34 | } 35 | 36 | @Test 37 | public void testAddReturnsExpectedResultWhenMatchingCurrencyIsUsed() { 38 | // Given 39 | Money underTest = new Money(120, HUF_CURRENCY); 40 | Money moneyToAdd = new Money(1, HUF_CURRENCY); 41 | 42 | // When 43 | Money result = underTest.add(moneyToAdd); 44 | 45 | // Then 46 | assertThat(result.how_much(), equalTo(121.0)); 47 | assertThat(result.what(), equalTo(HUF_CURRENCY)); 48 | } 49 | 50 | @Test 51 | public void testAddReturnsNullWhenCurrencyWithUnknownRateIsUsed() { 52 | // Given 53 | Money underTest = new Money(120, HUF_CURRENCY); 54 | Money moneyToAdd = new Money(1, GBP_CURRENCY); 55 | 56 | // When 57 | Money result = underTest.add(moneyToAdd); 58 | 59 | // Then 60 | assertThat(result, nullValue()); 61 | } 62 | 63 | 64 | @ParameterizedTest 65 | @CsvSource({"249, 1, -1", "249.3, 1, 0", "250, 0, 1"}) 66 | public void testCompareToReturnsExpectedResultWhenDifferentCurrencyIsUsed(double firstValue, double secondValue, int expectedSignum) { 67 | // Given 68 | Money underTest = new Money(firstValue, HUF_CURRENCY); 69 | Money moneyToCompareWith = new Money(secondValue, USD_CURRENCY); 70 | 71 | // When 72 | Integer result = underTest.compareTo(moneyToCompareWith); 73 | 74 | // Then 75 | assertThat(signum(result), equalTo(expectedSignum)); 76 | } 77 | 78 | @ParameterizedTest 79 | @CsvSource({"0, 100, -1", "100, 100, 0", "100, 0, 1"}) 80 | public void testCompareToReturnsExpectedResultWhenMatchingCurrencyIsUsed(double firstValue, double secondValue, int expectedSignum) { 81 | // Given 82 | Money underTest = new Money(firstValue, HUF_CURRENCY); 83 | Money moneyToCompareWith = new Money(secondValue, HUF_CURRENCY); 84 | 85 | // When 86 | Integer result = underTest.compareTo(moneyToCompareWith); 87 | 88 | // Then 89 | assertThat(signum(result), equalTo(expectedSignum)); 90 | } 91 | 92 | @Test 93 | public void testCompareToReturnsNullWhenCurrencyWithUnknownRateIsUsed() { 94 | // Given 95 | Money underTest = new Money(120, HUF_CURRENCY); 96 | Money moneyToCompareWith = new Money(1, GBP_CURRENCY); 97 | 98 | // When 99 | Integer result = underTest.compareTo(moneyToCompareWith); 100 | 101 | // Then 102 | assertThat(result, nullValue()); 103 | } 104 | 105 | } -------------------------------------------------------------------------------- /final/ticket-service-acceptance-tests/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | ticket-service-parent 7 | com.epam.training.ticketservice 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | ticket-service-acceptance-tests 13 | 14 | 15 | 6.9.1 16 | 5.7.1 17 | 30.0-jre 18 | 1.7.30 19 | 20 | 21 | 22 | 23 | io.cucumber 24 | cucumber-java 25 | ${cucumber.version} 26 | test 27 | 28 | 29 | io.cucumber 30 | cucumber-junit 31 | ${cucumber.version} 32 | test 33 | 34 | 35 | io.cucumber 36 | cucumber-picocontainer 37 | ${cucumber.version} 38 | 39 | 40 | org.junit.jupiter 41 | junit-jupiter-api 42 | ${junit.version} 43 | test 44 | 45 | 46 | org.junit.jupiter 47 | junit-jupiter-engine 48 | ${junit.version} 49 | test 50 | 51 | 52 | com.google.guava 53 | guava 54 | ${guava.version} 55 | test 56 | 57 | 58 | 59 | org.slf4j 60 | slf4j-api 61 | ${slf4j.version} 62 | test 63 | 64 | 65 | org.slf4j 66 | slf4j-simple 67 | ${slf4j.version} 68 | test 69 | 70 | 71 | 72 | 73 | 74 | 75 | org.apache.maven.plugins 76 | maven-surefire-plugin 77 | 2.12.4 78 | 79 | 80 | org.junit.jupiter 81 | junit-jupiter-engine 82 | 5.3.2 83 | 84 | 85 | 86 | 87 | **/TestExecutor.java 88 | 89 | 90 | ${requirements.cucumber-tags} 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /final/ticket-service-acceptance-tests/src/test/resources/features/pricing.feature: -------------------------------------------------------------------------------- 1 | Feature: allows creating pricing components and assigning them to rooms, movies and screenings 2 | 3 | Background: 4 | Given the application is started 5 | And the prompt containing "Ticket service>" is printed 6 | And the user types the "sign in privileged admin admin" command 7 | And the user types the "create room Pedersoli 20 10" command 8 | And the user types the "create room Girotti 10 10" command 9 | And the user types the "create movie Sátántangó drama 450" command 10 | And the user types the "create movie \"Spirited Away\" aminmation 125" command 11 | And the user types the "create movie \"Pulp Fiction\" drama 154" command 12 | And the user types the "create screening Sátántangó Pedersoli \"2021-03-15 10:45\"" command 13 | And the user types the "create screening \"Spirited Away\" Pedersoli \"2021-03-14 16:00\"" command 14 | And the user types the "create screening \"Pulp Fiction\" Girotti \"2021-03-14 16:00\"" command 15 | And the user types the "sign out" command 16 | 17 | @grade5-requirement 18 | Scenario: a default per seat per screening price is defined to be 1500 HUF and is used in the calculation of the price of each seat 19 | When the user types the "show price for Sátántangó Pedersoli \"2021-03-15 10:45\" 10,5" command 20 | Then the next line of the output is "The price for this booking would be 1500 HUF" 21 | 22 | @grade5-requirement 23 | Scenario: the admin user can change the default per seat per screening price 24 | Given the user types the "sign in privileged admin admin" command 25 | When the user types the "update base price 1000" command 26 | And the user types the "show price for Sátántangó Pedersoli \"2021-03-15 10:45\" 10,5" command 27 | Then the next line of the output is "The price for this booking would be 1000 HUF" 28 | 29 | @grade5-requirement 30 | Scenario: the admin user can create price component and assign it to a movie 31 | Given the user types the "sign in privileged admin admin" command 32 | When the user types the "create price component additionalFeeForSatantango 100" command 33 | And the user types the "attach price component to movie additionalFeeForSatantango Sátántangó" command 34 | And the user types the "show price for Sátántangó Pedersoli \"2021-03-15 10:45\" 10,5" command 35 | Then the next line of the output is "The price for this booking would be 1600 HUF" 36 | When the user types the "show price for \"Spirited Away\" Pedersoli \"2021-03-14 16:00\" 10,5" command 37 | Then the next line of the output is "The price for this booking would be 1500 HUF" 38 | 39 | @grade5-requirement 40 | Scenario: the admin user can create price component and assign it to a room 41 | Given the user types the "sign in privileged admin admin" command 42 | When the user types the "create price component additionalFeeForPedersoli 100" command 43 | And the user types the "attach price component to room additionalFeeForPedersoli Pedersoli" command 44 | And the user types the "show price for Sátántangó Pedersoli \"2021-03-15 10:45\" 10,5" command 45 | Then the next line of the output is "The price for this booking would be 1600 HUF" 46 | When the user types the "show price for \"Pulp Fiction\" Girotti \"2021-03-14 16:00\" 5,5" command 47 | Then the next line of the output is "The price for this booking would be 1500 HUF" 48 | 49 | @grade5-requirement 50 | Scenario: the admin user can create price component and assign it to a screening 51 | Given the user types the "sign in privileged admin admin" command 52 | When the user types the "create price component additionalFeeForPulpFictionScreening 100" command 53 | And the user types the "attach price component to screening additionalFeeForPulpFictionScreening \"Pulp Fiction\" Girotti \"2021-03-14 16:00\"" command 54 | And the user types the "show price for \"Pulp Fiction\" Girotti \"2021-03-14 16:00\" 5,5" command 55 | Then the next line of the output is "The price for this booking would be 1600 HUF" 56 | When the user types the "show price for Sátántangó Pedersoli \"2021-03-15 10:45\" 10,5" command 57 | Then the next line of the output is "The price for this booking would be 1500 HUF" -------------------------------------------------------------------------------- /final/ticket-service-acceptance-tests/src/test/resources/features/screenings.feature: -------------------------------------------------------------------------------- 1 | Feature: allows creating, deleting and listing screenings 2 | Background: 3 | Given the application is started 4 | And the prompt containing "Ticket service>" is printed 5 | And the user types the "sign in privileged admin admin" command 6 | And the user types the "create room Pedersoli 20 10" command 7 | And the user types the "create room Girotti 10 10" command 8 | And the user types the "create movie Sátántangó drama 450" command 9 | And the user types the "create movie \"Spirited Away\" animation 125" command 10 | And the user types the "sign out" command 11 | 12 | @grade2-requirement 13 | Scenario: The admin user can create and query screenings 14 | Given the user types the "sign in privileged admin admin" command 15 | When the user types the "create screening Sátántangó Pedersoli \"2021-03-15 10:45\"" command 16 | And the user types the "create screening \"Spirited Away\" Pedersoli \"2021-03-14 16:00\"" command 17 | And the user types the "list screenings" command 18 | Then the next line of the output is "Sátántangó (drama, 450 minutes), screened in room Pedersoli, at 2021-03-15 10:45" 19 | And the next line of the output is "Spirited Away (animation, 125 minutes), screened in room Pedersoli, at 2021-03-14 16:00" 20 | 21 | @grade2-requirement 22 | Scenario: The admin can not create overlapping screenings in the same room 23 | Given the user types the "sign in privileged admin admin" command 24 | And the user types the "create screening Sátántangó Pedersoli \"2021-03-15 10:45\"" command 25 | When the user types the "create screening \"Spirited Away\" Pedersoli \"2021-03-15 10:50\"" command 26 | Then the next line of the output is "There is an overlapping screening" 27 | When the user types the "list screenings" command 28 | Then the next line of the output is "Sátántangó (drama, 450 minutes), screened in room Pedersoli, at 2021-03-15 10:45" 29 | 30 | @grade2-requirement 31 | Scenario: The admin can create overlapping screenings in different rooms 32 | Given the user types the "sign in privileged admin admin" command 33 | And the user types the "create screening Sátántangó Pedersoli \"2021-03-15 10:45\"" command 34 | When the user types the "create screening \"Spirited Away\" Girotti \"2021-03-15 10:50\"" command 35 | When the user types the "list screenings" command 36 | Then the next line of the output is "Sátántangó (drama, 450 minutes), screened in room Pedersoli, at 2021-03-15 10:45" 37 | And the next line of the output is "Spirited Away (animation, 125 minutes), screened in room Girotti, at 2021-03-15 10:50" 38 | 39 | @grade2-requirement 40 | Scenario: The admin can not create screenings during a 10 minute long breaks after another screening in the same room 41 | Given the user types the "sign in privileged admin admin" command 42 | And the user types the "create screening Sátántangó Pedersoli \"2021-03-15 11:00\"" command 43 | When the user types the "create screening \"Spirited Away\" Pedersoli \"2021-03-15 18:39\"" command 44 | Then the next line of the output is "This would start in the break period after another screening in this room" 45 | When the user types the "list screenings" command 46 | Then the next line of the output is "Sátántangó (drama, 450 minutes), screened in room Pedersoli, at 2021-03-15 11:00" 47 | 48 | @grade2-requirement 49 | Scenario: The admin can create screenings even if there is a break after a screening in a different room 50 | Given the user types the "sign in privileged admin admin" command 51 | And the user types the "create screening Sátántangó Pedersoli \"2021-03-15 11:00\"" command 52 | When the user types the "create screening \"Spirited Away\" Girotti \"2021-03-15 18:39\"" command 53 | And the user types the "list screenings" command 54 | Then the next line of the output is "Sátántangó (drama, 450 minutes), screened in room Pedersoli, at 2021-03-15 11:00" 55 | And the next line of the output is "Spirited Away (animation, 125 minutes), screened in room Girotti, at 2021-03-15 18:39" 56 | 57 | @grade2-requirement 58 | Scenario: The admin user can delete screenings 59 | Given the user types the "sign in privileged admin admin" command 60 | And the user types the "create screening \"Spirited Away\" Pedersoli \"2021-03-14 16:00\"" command 61 | When the user types the "delete screening \"Spirited Away\" Pedersoli \"2021-03-14 16:00\"" command 62 | And the user types the "list screenings" command 63 | Then the next line of the output is "There are no screenings" -------------------------------------------------------------------------------- /final/ticket-service/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | ticket-service 6 | 0.0.1-SNAPSHOT 7 | 8 | 9 | com.epam.training.ticketservice 10 | ticket-service-parent 11 | 1.0-SNAPSHOT 12 | ../pom.xml 13 | 14 | 15 | 16 | 11 17 | 11 18 | 11 19 | checkstyle 20 | 0.8.6 21 | 3.1.2 22 | 3.0.0-M5 23 | 5.7.1 24 | 25 | 26 | 27 | 28 | org.junit.jupiter 29 | junit-jupiter-api 30 | ${junit.version} 31 | test 32 | 33 | 34 | org.junit.jupiter 35 | junit-jupiter-engine 36 | ${junit.version} 37 | test 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | org.apache.maven.plugins 49 | maven-surefire-plugin 50 | ${surefire-maven-plugin.version} 51 | 52 | @{argLine} 53 | 54 | 55 | 56 | org.junit.jupiter 57 | junit-jupiter-engine 58 | ${junit.version} 59 | 60 | 61 | 62 | 63 | 64 | org.apache.maven.plugins 65 | maven-checkstyle-plugin 66 | ${checkstyle-maven-plugin.version} 67 | 68 | ${checkstyle-config-dir}/checkstyle.xml 69 | ${checkstyle-config-dir}/suppressions.xml 70 | UTF-8 71 | true 72 | ${requirements.fail-build-on-checkstyle-error} 73 | warning 74 | false 75 | 76 | 77 | 78 | validate 79 | validate 80 | 81 | check 82 | 83 | 84 | 85 | 86 | 87 | 88 | org.jacoco 89 | jacoco-maven-plugin 90 | ${jacoco-maven-plugin.version} 91 | 92 | 93 | 94 | prepare-agent 95 | 96 | 97 | 98 | report 99 | prepare-package 100 | 101 | report 102 | 103 | 104 | 105 | jacoco-check 106 | 107 | check 108 | 109 | 110 | 111 | 112 | BUNDLE 113 | 114 | 115 | LINE 116 | COVEREDRATIO 117 | ${requirements.jacoco-line-coverage} 118 | 119 | 120 | BRANCH 121 | COVEREDRATIO 122 | ${requirements.jacoco-branch-coverage} 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /final/ticket-service/checkstyle/checkstyle.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 55 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 72 | 73 | 74 | 76 | 77 | 78 | 84 | 85 | 86 | 87 | 90 | 91 | 92 | 93 | 94 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 112 | 114 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 161 | 162 | 163 | 164 | 166 | 167 | 168 | 169 | 171 | 172 | 173 | 174 | 176 | 177 | 178 | 179 | 181 | 182 | 183 | 184 | 186 | 187 | 188 | 189 | 191 | 192 | 193 | 194 | 196 | 197 | 198 | 199 | 201 | 202 | 203 | 204 | 206 | 207 | 208 | 209 | 211 | 213 | 215 | 217 | 218 | 219 | 220 | 221 | 222 | 225 | 226 | 227 | 228 | 229 | 232 | 233 | 234 | 236 | 237 | 238 | 239 | 244 | 245 | 246 | 247 | 250 | 251 | 252 | 253 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 267 | 268 | 269 | 270 | 271 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 299 | 300 | 301 | 302 | 303 | -------------------------------------------------------------------------------- /final/README.md: -------------------------------------------------------------------------------- 1 | # A félév végi beadandó program követelményei 2 | 3 | Egy interaktív, parancssori alkalmazást fogsz elkészíteni, amely 4 | adminisztrációs és információs felületként fog működni egy filmszínház 5 | személyzete és látogatói számára. 6 | 7 | ## Hasznos információ az acceptance tesztek futtatása kapcsán 8 | 9 | * A ticket-service projekt package goal-jának egy `ticket-service-0.0.1-SNAPSHOT.jar` nevű, 10 | futtatható JAR-t kell létrehoznia 11 | * Amennyiben az alkalmazás indulása sokáig (>=15 másodperc) tart, `TimeoutException`-t kaphatunk a 12 | tesztek futtatása során. Ugyanezt a kivételt kapjuk akkor is, amikor a teszt egy adott kimenetre 13 | (pl. prompt megjelenése vagy egy adott sor kiírása) vár, de nem kapunk kimenetet vagy csak a vártnak nem 14 | megfelelő kimenetet kapunk. Miután megbizonyosodtunk arról, hogy az alkalmazásunk jól működik, 15 | érdemes a `GenericCliProcessStepDefs` osztály `OUTPUT_TIMEOUT` értékét növelni. Így a teszt hosszabb ideig 16 | tud várakozni arra, hogy az alkalmazás elinduljon és megjelenjen a prompt a kimeneten. 17 | * A tesztek gyakran az egyes parancsokat követő kiementre asszertálnak. Azért, hogy csak a parancs 18 | beírása után következő kimenetet tudja vizsgálni, sok teszt a parancs elküldése előtt kiolvassa az összes 19 | rendelkezésre álló kimenetet. Sajnos azonban előfordulhat olyan eset, hogy a program túl lassan produkál 20 | kimenetet, amely így azután kerül kiírásra, hogy a teszt már elvégezte az előbb leírt "takarítást". Ezt elkerülendő 21 | a teszt egy rövid ideig várakozik, mielőtt kiolvasná a kimenetet, hogy az alkalmazásnak legyen ideje kiírnia mindent. 22 | Amennyiben azt látjuk a várt kimenet és a kapott kimenet összehasonlítása során, hogy a kapott kimenet például 23 | promptot vagy az előző parancs kimenetét tartalmazza, ez a várakozási idő nem elég hosszú. Ilyenkor érdemes megnövelni 24 | a `ProcessUnderTest` osztály `DELAY_BEFORE_CLEANING_PROCESS_OUTPUT` konstansának értékét. 25 | * A Spring Shell többféle, többé-kevésbé okos parancssort tud adni, amelyek támogatják például az automatikus kiegészítést, 26 | a history-t vagy a syntax highlighting-ot. Sajnos ezek a "haladó" funkciók problémát okoznak az acceptance tesztek futása során, 27 | ezek kapcsán láthatunk például olyat, hogy a kapott kimenetben megjelenik maga a parancs. Hogy ezt elkerüljük, érdemes 28 | rákényszeríteni a Spring Shell-t arra, hogy egy "buta" parancssort adjon, amelynek a legegyszerűbb módja az, ha a 29 | teszteket az IntelliJ-n belül futtatjuk. 30 | 31 | ## Az alkalmazással kapcsolatos követelmények: 32 | 33 | ### Követelmények a kettes jegyhez: 34 | 35 | #### Általános követelmények a forráskóddal és az alkalmazással kapcsolatban 36 | 37 | * A forráskód elérhető egy nyilvános repóban 38 | * Az `mvn clean verify` a sikeresen lefut a `ticket-service-parent` projekten. Ehhez a következők szükségesek 39 | * A `@grade2-requirements` tag-gel megjelölt acceptance tesztekben leírt követelményeknek megfelelő alkalmazás. 40 | * Legalább 40%-os unit teszt branch és line coverage az egész `ticket-service` modulra vonatkoztatva. 41 | * A forráskód könnyen kiterjeszthető és követi a clean code és OOP fejlesztésre vonatkozó irányelveket. 42 | * Az irányelvektől való eltérést meg kell tudnod indokolni. 43 | * Az alkalmazás Spring-et használ a DI megvalósításához. 44 | * Az alkalmazás Spring Data JPA-t használ az adat eléréshez 45 | * Ehhez használj egy in-memory, beágyazott (pl. H2) adatbázist 46 | * Spring Boot használható 47 | * A 'Ticket service>' prompt kerül kiírásra, amint az alkalmazás készen áll arra, hogy bemenetet fogadjon a felhasználótól 48 | * Az alkalmazás a standard kimenetre ír és a standard bemenetről olvas 49 | 50 | #### Az alkalmazás által támogatott parancsok 51 | 52 | * Az alkalmazás állapotát egy interaktív parancssor segítségével lehet módosítani. 53 | * A parancssorból az `exit` parancs segítségével bármikor ki lehet lépni, ekkor a 54 | program futása leáll. 55 | * Az egyes parancsokhoz lehetséges több szóból álló paraméter megadása úgy, 56 | ha az adott paramétert idézőjelek közé írjuk. Például a következő parancs 57 | a _Spirited Away_ című film létrehozására használható. 58 | ``` 59 | create movie "Sprited Away" animation 125 60 | ``` 61 | 62 | ##### Admin accounttal kapcsolatos parancsok 63 | 64 | ###### Admin account és bejelentkezés 65 | 66 | * Az alkalmazás indításakor létezik egy adminisztrátor account. 67 | * A felhasználónév legyen 'admin', a jelszó szintén 'admin'. 68 | * A következő parancs lehetőséget nyújt az adminisztátornak arra, hogy 69 | bejelentkezzen 70 | ``` 71 | sign in privileged 72 | ``` 73 | * Sikertelen bejelentkezés esetén a parancs kimenete a következő: 74 | ``` 75 | Login failed due to incorrect credentials 76 | ``` 77 | * Sikeres bejelentkezés esetén hozzáférhetővé 78 | vállnak az adminisztrációs parancsok (lásd később) 79 | 80 | ###### Az adminisztrátor ki tud jelentkezni 81 | 82 | * A következő parancs segítségével az adminisztrátor ki tud jelentkezni 83 | ``` 84 | sign out 85 | ``` 86 | * A kijelentkezés után ne legyenek hozzáférhetőek az adminisztrációs parancsok, 87 | amíg az adminisztrátor felhasználó újra be nem jelentkezik. 88 | 89 | ###### Az adminisztrátor account információi lekérdezhetőek 90 | 91 | * A következő paranccsal lekérdezhető az éppen bejelentkezett 92 | account típusa és állapota. 93 | ``` 94 | describe account 95 | ``` 96 | * Bejelentkezett adminisztrátor esetén a parancs kimenete: 97 | ``` 98 | Signed in with privileged account '' 99 | ``` 100 | * Amennyiben a felhasználó nincs bejelentkezve, a parancs kimenete: 101 | ``` 102 | You are not signed in 103 | ``` 104 | 105 | ##### A vetített filmekről szóló adatok kezelése 106 | 107 | ###### Filmek létrehozása 108 | 109 | * A következő paranccsal új film hozható létre. 110 | ``` 111 | create movie 112 | ``` 113 | * A parancs adminisztrációs parancs, így csak bejelentkezett 114 | adminisztrátor felhasználó számára elérhető. 115 | * A film címe azonosítja a filmet. 116 | 117 | Például: 118 | ``` 119 | create movie Sátántangó drama 450 120 | ``` 121 | 122 | ###### Filmek módosítása 123 | 124 | * A következő paranccsal egy már meglévő filmet módosíthatunk. 125 | ``` 126 | update movie 127 | ``` 128 | * A parancs adminisztrációs parancs, így csak bejelentkezett 129 | adminisztrátor felhasználó számára elérhető. 130 | * A film címe azonosítja a filmet 131 | 132 | ###### Filmek törlése 133 | 134 | * A következő paranccsal egy már meglévő filmet törölhetünk. 135 | ``` 136 | delete movie 137 | ``` 138 | * A parancs adminisztrációs parancs, így csak bejelentkezett 139 | adminisztrátor felhasználó számára elérhető. 140 | 141 | ###### Filmek lekérdezése 142 | 143 | * A következő paranccsal a meglévő filmeket kérdezhetjük le 144 | ``` 145 | list movies 146 | ``` 147 | * A parancs kimenete a következő, ha még nincs film elmentve: 148 | ``` 149 | There are no movies at the moment 150 | ``` 151 | * Ha van film elmentve, akkor a parancs kimenetében szerepelnie kell az összes 152 | filmnek. Minden sor egy-egy filmet ír le és a következőképpen épül fel. 153 | ``` 154 | (, minutes) 155 | ``` 156 | * Ez a parancs elérhető bármely bejelentkezett vagy nem bejelentkezett felhasználónak. 157 | 158 | ##### A termekről szóló információ kezelése 159 | 160 | ###### Terem létrehozása 161 | 162 | * A következő parancs lehetőséget biztosít vetítő termek létrehozására. 163 | ``` 164 | create room 165 | ``` 166 | * A parancs adminisztrációs parancs, így csak bejelentkezett 167 | adminisztrátor felhasználó számára elérhető. 168 | * A terem neve azonosítja a termet 169 | 170 | ###### Terem módosítása 171 | 172 | * A következő parancs lehetőséget biztosít már meglévő vetítő termek módosítására. 173 | ``` 174 | update room 175 | ``` 176 | * A parancs adminisztrációs parancs, így csak bejelentkezett 177 | adminisztrátor felhasználó számára elérhető. 178 | * A terem neve azonosítja a termet 179 | 180 | ###### Terem törlése 181 | 182 | * A következő parancs lehetővé teszi egy már meglévő vetítő terem törlését. 183 | ``` 184 | delete room 185 | ``` 186 | * A parancs adminisztrációs parancs, így csak bejelentkezett 187 | adminisztrátor felhasználó számára elérhető. 188 | 189 | ###### Termek listázása 190 | 191 | * A következő parancs lehetővé teszi a termek listázását 192 | ``` 193 | list rooms 194 | ``` 195 | * Amennyiben még nincs terem elmentve, a parancs kimenete a következő: 196 | ``` 197 | There are no rooms at the moment 198 | ``` 199 | * Amennyiben már van terem elmentve, akkor a parancs kimenetében 200 | szerepelnie kell minden teremnek. Minden sor egy termet ír le, az 201 | egyes sorok formátuma a következő: 202 | ``` 203 | Room with seats, rows and columns 204 | ``` 205 | * Ez a parancs elérhető bármely bejelentkezett vagy nem bejelentkezett felhasználónak. 206 | 207 | ##### A filmvetítésekről szóló információk kezelése 208 | 209 | ###### Vetítés létrehozása 210 | 211 | * A következő parancs lehetőséget biztosít egy már létező film létező teremben történő 212 | vetítésének létrehozására egy adott időpontban. 213 | ``` 214 | create screening 215 | ``` 216 | Például, ha a Pedersoli terem és a Spirited Away film léteznek, akkor egy vetítés a 2021-03-14 16:00 217 | időpontban létrehozható a következőképpen: 218 | ``` 219 | create screening "Spirited Away" Pedersoli "2021-03-14 16:00" 220 | ``` 221 | * Nem hozható létre a vetítés akkor, ha: 222 | * A vetítés időtartama bele esik egy másik, azonos teremben történő másik vetítés időtartamába. 223 | A kimenet ebben az esetben: 224 | ``` 225 | There is an overlapping screening 226 | ``` 227 | * A vetítés időtartama bele esik egy másik, azonos teremben történő vetítés utáni 10 perces szünetbe (amely lehetőséget 228 | biztosít például a terem előkészítésére a következő vetítésre). A kimenet ebben az esetben: 229 | ``` 230 | This would start in the break period after another screening in this room 231 | ``` 232 | * A parancs adminisztrációs parancs, így csak bejelentkezett 233 | adminisztrátor felhasználó számára elérhető. 234 | * Egy vetítést a film címe, a terem neve és a vetítés kezdetének dátuma és ideje azonosít 235 | 236 | ###### Vetítés törlése 237 | 238 | * A következő parancs lehetőséget biztosít egy már létező vetítés törlésére: 239 | ``` 240 | delete screening 241 | ``` 242 | * A parancs adminisztrációs parancs, így csak bejelentkezett 243 | adminisztrátor felhasználó számára elérhető. 244 | 245 | ###### Vetítések listázása 246 | 247 | * A következő parancs lehetőséget biztosít már meglévő vetítések listázására 248 | ``` 249 | list screenings 250 | ``` 251 | * Amennyiben nincs mentett vetítés, a kimenet a következő: 252 | ``` 253 | There are no screenings 254 | ``` 255 | * Amennyiben már van mentett vetítés, akkor a kimenet minden vetítést tartalmaz. 256 | A kimenet egy-egy sora egy-egy vetítés adatait tartalmazza a következő formátumban: 257 | ``` 258 | (, minutes), screened in room , at 259 | ``` 260 | Például: 261 | ``` 262 | Sátántangó (drama, 450 minutes), screened in room Pedersoli, at 2021-03-15 11:00 263 | ``` 264 | 265 | ### Követelmények a hármas jegyhez 266 | 267 | #### Általános követelmények a forráskóddal és az alkalmazással kapcsolatban 268 | 269 | * A kettes jegy minden követelménye teljesül 270 | * Az `mvn clean verify -p requirements-grade3` sikeresen lefut 271 | a `ticket-service-parent` projekten. Ehhez a kettes érdemjegy eléréséhez szükséges 272 | feltételeken túl a következők szükségesek: 273 | * Nincsenek checkstyle warning-ok. 274 | * Az alkalmazás Spring Shell-t használ. 275 | 276 | ### Követelmények a négyes jegyhez 277 | 278 | #### Általános követelmények a forráskóddal és az alkalmazással kapcsolatban 279 | 280 | * A hármas jegy minden követelménye teljesül 281 | * Az alkalmazás által használt adatbázis Spring profilok segítségével módosítható. 282 | * Alapértelmezetten az alkalmazás egy olyan adatbázist használ, amely az alkalmazás futásai között is megőrzi az állapotát 283 | * A `ci` profil esetén az alkalmazás beágyazott in-memory adatbázist használ 284 | * Az `mvn clean verify -p requirements-grade4` sikeresen lefut 285 | a `ticket-service-parent` projekten. Ehhez a hármas érdemjegy eléréséhez szükséges 286 | feltételeken túl a következők szükségesek: 287 | * Legalább 50%-os unit teszt branch és line coverage az egész `ticket-service` modulra vonatkoztatva. 288 | * A `@grade4-requirements` tag-gel megjelölt acceptance tesztekben leírt követelményeknek megfelelő alkalmazás. 289 | 290 | #### Az alkalmazás által támogatott parancsok 291 | 292 | ##### Regisztráció és bejelentkezés nem adminisztrátor felhasználók számára 293 | 294 | ###### Regisztráció nem adminisztrátor felhasználó számára 295 | 296 | * A következő parancs lehetőséget biztosít nem adminisztrátori account 297 | létrehozására. 298 | ``` 299 | sign up 300 | ``` 301 | * A parancs elérhető nem bejelentkezett és bejelentkezett felhasználóknak 302 | * A felhasználót a felhasználónév azonosítja 303 | 304 | ###### Bejelentkezés nem adminisztrátor felhasználók számára 305 | 306 | * A következő parancs lehetőséget biztosít már meglévő, nem adminisztrátori 307 | accountba történő bejelentkezéshez. 308 | ``` 309 | sign in 310 | ``` 311 | * Sikeres bejelentkezés esetén a kimenet tetszőleges lehet, a felhasználó 312 | a bejelentkezés után eléri a bejelentkezett felhasználók számára elérhető 313 | parancsokat. 314 | * Sikertelen bejelentkezés esetén a kimenet a következő: 315 | ``` 316 | Login failed due to incorrect credentials 317 | ``` 318 | 319 | ###### Account adatainak lekérdezése bejelentkezett, nem adminisztrátor felhasználók számára 320 | 321 | * A következő parancs bejelentkezett, nem adminisztrátor felhasználók esetén is 322 | az accountra vonatkozó adatok lekérdezésére szolgál 323 | ``` 324 | describe account 325 | ``` 326 | * A parancs kimenete bejelentkezett, nem adminisztrátor felhasználó esetén, ha még nem foglalt 327 | jegyet: 328 | ``` 329 | Signed in with account '' 330 | You have not booked any tickets yet 331 | ``` 332 | * A parancs kimenete bejelentkezett, nem adminisztrátor felhasználó esetén, ha már foglalt 333 | jegyet: 334 | ``` 335 | Signed in with account '' 336 | Your previous bookings are 337 | Seats ,) formátumú> on in room starting at for HUF 338 | ``` 339 | * Minden már meglévő foglaláshoz létezik egy, a foglalást leíró sor a fenti formátumban. 340 | * A foglalásra vonatkozó szabályokról (pl. az ár kiszámítása) bővebben olvashatsz a következő szekciókban. 341 | * Például: 342 | ``` 343 | Signed in with account 'sanyi' 344 | Your previous bookings are 345 | Seats (5,5), (5,6) on Sátántangó in room Pedersoli starting at 2021-03-15 10:45 for 3000 HUF 346 | ``` 347 | * A parancs kimenete más esetekben a kettes jegyhez szükséges követelmények között van leírva. 348 | 349 | ##### Jegyfoglalás 350 | 351 | ###### Foglalás létrehozása 352 | * A következő parancs lehetőséget biztosít egy már meglévő vetítésre egy vagy több ülőhelyre 353 | jegyet foglalni. 354 | ``` 355 | book ," formátumú> 356 | ``` 357 | Például: 358 | ``` 359 | book Sátántangó Pedersoli "2021-03-15 10:45" "5,5 5,6" 360 | ``` 361 | * A foglalás sikertelen akkor, ha 362 | * A megjelölt ülőhelyek közül legalább egy már foglalt. Ekkor a parancs kimenete 363 | ``` 364 | Seat <ülőhely> is already taken 365 | ``` 366 | ahol az ülőhely a listában megadottak közül az első olyan, amely nem foglalható 367 | * A megjelölt ülőhelyek valamelyike nem létezik az adott teremben. Ekkor a parancs kimenete 368 | ``` 369 | Seat <ülőhely> does not exist in this room 370 | ``` 371 | ahol az ülőhely a listában megadottak közül az első olyan, amely nem foglalható a hiba miatt. 372 | * Amennyiben a foglalás sikeres, a parancs kimenete a következő 373 | ``` 374 | Seats booked: ,)" formátumú>; the price for this booking is HUF 375 | ``` 376 | * A jegy ára 1500 HUF / ülőhely / vetítés. Az ötös érdemjegyhez tartozó követelményekben 377 | további szabályok kerülnek bevezetésre. 378 | * Ez a parancs csak bejelentkezett, nem adminisztrátor felhasználóknak elérhető 379 | 380 | ### For grade 5: 381 | #### Általános követelmények a forráskóddal és az alkalmazással kapcsolatban 382 | 383 | * A négyes érdemjegy eléréséhez tartozó összes követelmény teljesül 384 | * Az `mvn clean verify -p requirements-grade5` sikeresen lefut 385 | a `ticket-service-parent` projekten. Ehhez a négyes érdemjegy eléréséhez szükséges 386 | feltételeken túl a következők szükségesek: 387 | * Legalább 70%-os unit teszt branch és line coverage az egész `ticket-service` modulra vonatkoztatva. 388 | * A `@grade5-requirements` tag-gel megjelölt acceptance tesztekben leírt követelményeknek megfelelő alkalmazás. 389 | 390 | #### Az alkalmazás által támogatott parancsok 391 | 392 | ##### Árazással kapcsolatos funkcionalitás 393 | 394 | ###### Az alapár megváltoztatása 395 | * Egy foglalás alapára 1500 HUF / ülőhely / vetítés. 396 | A foglalás ára (/ülőhely/vetítés) kiszámítható a foglalás alapárának 397 | és a foglalásra vonatkozó árkomponensek összegzésével. Az árkomponensek 398 | leírását lásd később. 399 | * A következő parancs a foglalás alapárának megváltoztatását teszi lehetővé 400 | ``` 401 | update base price <új alapár> 402 | ``` 403 | * A parancs adminisztrációs parancs, így csak bejelentkezett 404 | adminisztrátor felhasználó számára elérhető. 405 | * A parancs nem változtathatja meg a már meglévő foglalások árát. 406 | * ezek a `describe account` paranccsal kérhetőek 407 | le az éppen bejelentkezett felhasználóhoz. 408 | * A parancs hatására az új foglalások árának számításakor már az új alapár 409 | kerül felhasználásra. 410 | 411 | ###### Új árkomponens létrehozása 412 | * Egy árkomponens egy pozitív vagy negatív fix összeg, amely az alapárhoz adódik hozzá. 413 | Ennek segítségével vállnak megvalósíthatóvá teremhez, filmhez vagy vetítéshez használható felárak 414 | vagy kedvezmények. 415 | * A következő parancs használható az árkomponensek létrehozásához: 416 | ``` 417 | create price component <árkomponens neve> <árkomponens összege> 418 | ``` 419 | * Az árkomponens neve azonosítja az árkomponenst 420 | * A parancs adminisztrációs parancs, így csak bejelentkezett 421 | adminisztrátor felhasználó számára elérhető. 422 | 423 | ###### Árkomponens teremhez történő csatolása 424 | * A következő parancs lehetővé teszi egy létező árkomponens egy létező teremhez történő csatolását. 425 | Miután megtörtént, a teremben történő összes vetítés ára tartalmazza az árkomponenst. 426 | * Például ha egy vetítésre, két ülőhelyre szeretnénk jegyet foglalni, amely csak az 1500 Ft/ülőhely/vetítés 427 | alapárat tartalmazza, akkor a foglalás teljes ára 2 * 1500 Ft, azaz 3000 Ft. Amennyiben ahhoz a teremhez, 428 | ahol a vetítés történik csatolva van egy 500 Ft-s árkomponens, akkor a fenti foglalás ára 429 | 2 * (500 Ft + 1500 Ft), tehát 4000 Ft 430 | ``` 431 | attach price component to room <árkomponens neve> 432 | ``` 433 | * A parancs adminisztrációs parancs, így csak bejelentkezett 434 | adminisztrátor felhasználó számára elérhető. 435 | * A parancs nem változtathatja meg a már meglévő foglalások árát. 436 | 437 | ###### Árkomponens filmhez történő csatolása 438 | * A következő parancs lehetővé teszi egy létező árkomponens egy létező filmhez történő csatolását. 439 | Miután megtörtént, a film összes vetítése esetén az ár tartalmazza az árkomponenst. 440 | ``` 441 | attach price component to movie <árkomponens neve> 442 | ``` 443 | * A parancs adminisztrációs parancs, így csak bejelentkezett 444 | adminisztrátor felhasználó számára elérhető. 445 | * A parancs nem változtathatja meg a már meglévő foglalások árát. 446 | 447 | ###### Árkomponens filmhez vetítéshez történő csatolása 448 | * A következő parancs lehetővé teszi egy létező árkomponens egy létező vetítéshez történő csatolását. 449 | Miután megtörtént, a vetítés ára tartalmazza az árkomponenst. 450 | ``` 451 | attach price component to screening <árkomponens neve> 452 | ``` 453 | * A parancs adminisztrációs parancs, így csak bejelentkezett 454 | adminisztrátor felhasználó számára elérhető. 455 | * A parancs nem változtathatja meg a már meglévő foglalások árát. 456 | 457 | ###### Foglalás árának lekérdezése 458 | * A következő parancs lehetővé teszi azt, hogy lekérdezhessük egy foglalás árát anélkül, hogy a foglalás megtörténne 459 | ``` 460 | show price for <ülőhelyek listája szóközzel elvállasztva, az egyes ülőhelyek "," formátumúak> 461 | ``` 462 | Például: 463 | ``` 464 | show price for Sátántangó Pedersoli "2021-03-15 10:45" "10,5 11,5" 465 | ``` 466 | * A parancs kimenete: 467 | ``` 468 | The price for this booking would be 3000 HUF 469 | ``` 470 | * A parancs elérhető bármely bejelentkezett vagy nem bejelenetkezett felhasználónak. 471 | --------------------------------------------------------------------------------