├── 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 |
--------------------------------------------------------------------------------