├── chapter-07 ├── flying-high │ ├── README.md │ ├── .vscode │ │ └── settings.json │ ├── serenity.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── .gitignore │ └── src │ │ └── test │ │ ├── resources │ │ ├── features │ │ │ └── frequent_flyer │ │ │ │ ├── earning_points │ │ │ │ └── earning_points_from_flights_fr.feature │ │ │ │ └── spending_points │ │ │ │ └── booking_flights_with_points.feature │ │ └── logback-test.xml │ │ └── java │ │ └── com │ │ └── manning │ │ └── bddinaction │ │ └── frequentflyer │ │ └── AcceptanceTestSuite.java └── .github │ └── workflows │ ├── gradle.yml │ └── maven.yml ├── chapter-14 ├── features │ ├── README.md │ └── actors.steps.ts ├── .gitignore ├── domain │ ├── admin │ │ └── index.ts │ ├── authentication │ │ ├── form │ │ │ ├── index.ts │ │ │ ├── SpecifyPassword.ts │ │ │ └── SpecifyEmailAddress.ts │ │ ├── index.ts │ │ ├── SubmitAuthenticationForm.ts │ │ ├── CompleteAuthenticationForm.ts │ │ └── SignOut.ts │ ├── index.ts │ ├── ui │ │ └── index.ts │ └── registration │ │ ├── index.ts │ │ ├── form │ │ ├── SpecifyHomeAddress.ts │ │ ├── SpecifyLastName.ts │ │ ├── SpecifyPassword.ts │ │ ├── SpecifyFirstName.ts │ │ ├── SpecifyEmailAddress.ts │ │ ├── SpecifyCountryOfResidence.ts │ │ ├── index.ts │ │ ├── ToggleTermsAndConditions.ts │ │ └── ToggleNewsletterSubscription.ts │ │ ├── SubmitRegistrationForm.ts │ │ └── LocateRegistrationForm.ts ├── integration │ ├── AuthenticationDetails.ts │ ├── index.ts │ └── TravelerNotes.ts └── tsconfig.json ├── chapter-15 ├── features │ ├── README.md │ └── actors.steps.ts ├── .gitignore ├── domain │ ├── admin │ │ └── index.ts │ ├── authentication │ │ ├── form │ │ │ ├── index.ts │ │ │ ├── SpecifyPassword.ts │ │ │ └── SpecifyEmailAddress.ts │ │ ├── index.ts │ │ ├── SubmitAuthenticationForm.ts │ │ ├── CompleteAuthenticationForm.ts │ │ └── SignOut.ts │ ├── index.ts │ ├── ui │ │ └── index.ts │ └── registration │ │ ├── index.ts │ │ ├── form │ │ ├── SpecifyHomeAddress.ts │ │ ├── SpecifyLastName.ts │ │ ├── SpecifyPassword.ts │ │ ├── SpecifyFirstName.ts │ │ ├── SpecifyEmailAddress.ts │ │ ├── SpecifyCountryOfResidence.ts │ │ ├── index.ts │ │ ├── ToggleTermsAndConditions.ts │ │ └── ToggleNewsletterSubscription.ts │ │ ├── SubmitRegistrationForm.ts │ │ └── LocateRegistrationForm.ts ├── integration │ ├── AuthenticationDetails.ts │ ├── index.ts │ ├── TravelerNotes.ts │ └── webdriverio │ │ └── tsconfig.json └── tsconfig.json ├── flying-high-app ├── cypress.json ├── web │ ├── src │ │ ├── assets │ │ │ ├── .gitkeep │ │ │ └── image │ │ │ │ └── logo.png │ │ ├── app │ │ │ ├── register │ │ │ │ ├── register.component.scss │ │ │ │ ├── register.component.html │ │ │ │ └── register.component.ts │ │ │ ├── users │ │ │ │ ├── edit-user-dialog │ │ │ │ │ ├── edit-user-dialog.component.scss │ │ │ │ │ └── edit-user-dialog.component.html │ │ │ │ ├── users-account.interface.ts │ │ │ │ ├── users.component.scss │ │ │ │ ├── profile │ │ │ │ │ └── profile.component.scss │ │ │ │ └── users-routing.module.ts │ │ │ ├── welcome │ │ │ │ ├── welcome.component.scss │ │ │ │ └── welcome.component.ts │ │ │ ├── search │ │ │ │ ├── city.interface.ts │ │ │ │ ├── search-routing.module.ts │ │ │ │ └── flight.interface.ts │ │ │ ├── booking │ │ │ │ ├── booking.component.scss │ │ │ │ ├── booking.module.ts │ │ │ │ ├── booking-routing.module.ts │ │ │ │ └── booking.component.html │ │ │ ├── login │ │ │ │ ├── auth-user.interface.ts │ │ │ │ └── login.component.scss │ │ │ ├── shared │ │ │ │ ├── components │ │ │ │ │ └── user-form │ │ │ │ │ │ └── user-form.component.scss │ │ │ │ ├── enums │ │ │ │ │ └── user.enum.ts │ │ │ │ ├── services │ │ │ │ │ ├── flight.service.ts │ │ │ │ │ └── bookings.service.ts │ │ │ │ └── shared.module.ts │ │ │ └── app.component.scss │ │ ├── environments │ │ │ └── environment.prod.ts │ │ ├── favicon.ico │ │ ├── main.ts │ │ └── index.html │ ├── proxy.conf.json │ ├── e2e │ │ ├── tsconfig.json │ │ └── src │ │ │ └── app.po.ts │ ├── tsconfig.app.json │ ├── .editorconfig │ ├── tsconfig.spec.json │ ├── browserslist │ └── tsconfig.json ├── server │ ├── dist │ │ ├── main.d.ts │ │ ├── app.module.d.ts │ │ ├── auth │ │ │ ├── auth.module.d.ts │ │ │ ├── constants.d.ts │ │ │ ├── auth-user.dto.d.ts │ │ │ ├── constants.js.map │ │ │ ├── jwt-auth.guard.d.ts │ │ │ ├── local-auth.guard.d.ts │ │ │ ├── constants.js │ │ │ ├── jwt-auth.guard.js.map │ │ │ ├── local-auth.guard.js.map │ │ │ ├── auth-user.dto.js.map │ │ │ ├── jwt.strategy.d.ts │ │ │ ├── auth.module.js.map │ │ │ ├── local.strategy.d.ts │ │ │ ├── jwt.strategy.js.map │ │ │ └── local.strategy.js.map │ │ ├── users │ │ │ ├── users.module.d.ts │ │ │ ├── interface │ │ │ │ ├── account.interface.js │ │ │ │ ├── account.interface.js.map │ │ │ │ ├── account.interface.d.ts │ │ │ │ └── users.interface.js.map │ │ │ ├── users.module.js.map │ │ │ └── dto │ │ │ │ └── user.dto.d.ts │ │ ├── flights │ │ │ ├── flights.module.d.ts │ │ │ ├── dto │ │ │ │ ├── city.dto.d.ts │ │ │ │ ├── search-flight.dto.d.ts │ │ │ │ ├── city.dto.js.map │ │ │ │ ├── create-flight.dto.d.ts │ │ │ │ └── search-flight.dto.js.map │ │ │ ├── interface │ │ │ │ ├── city.interface.d.ts │ │ │ │ ├── city.interface.js │ │ │ │ ├── flight.interface.js │ │ │ │ ├── city.interface.js.map │ │ │ │ ├── flight.interface.js.map │ │ │ │ └── flight.interface.d.ts │ │ │ └── flights.module.js.map │ │ ├── shared │ │ │ ├── shared.module.d.ts │ │ │ ├── services │ │ │ │ ├── bookings.service.d.ts │ │ │ │ └── bookings.service.js.map │ │ │ └── shared.module.js.map │ │ ├── activity │ │ │ ├── activity.module.d.ts │ │ │ └── activity.module.js.map │ │ ├── bookings │ │ │ ├── bookings.module.d.ts │ │ │ ├── bookings.controller.d.ts │ │ │ ├── bookings.module.js.map │ │ │ └── bookings.controller.js.map │ │ ├── app.service.d.ts │ │ ├── app.module.js.map │ │ └── main.js.map │ ├── .prettierrc │ ├── src │ │ ├── auth │ │ │ ├── constants.ts │ │ │ ├── jwt-auth.guard.ts │ │ │ ├── local-auth.guard.ts │ │ │ ├── auth-user.dto.ts │ │ │ ├── auth.module.ts │ │ │ └── jwt.strategy.ts │ │ ├── activity │ │ │ └── activity.module.ts │ │ ├── shared │ │ │ └── services │ │ │ │ └── bookings.service.ts │ │ ├── flights │ │ │ ├── interface │ │ │ │ └── city.interface.ts │ │ │ ├── dto │ │ │ │ └── city.dto.ts │ │ │ └── flights.module.ts │ │ ├── users │ │ │ ├── interface │ │ │ │ └── account.interface.ts │ │ │ └── users.module.ts │ │ └── bookings │ │ │ └── bookings.module.ts │ ├── nest-cli.json │ ├── web │ │ ├── favicon.ico │ │ └── assets │ │ │ └── image │ │ │ └── logo.png │ ├── assets │ │ └── image │ │ │ └── logo.png │ ├── tsconfig.build.json │ ├── test │ │ └── jest-e2e.json │ ├── tsconfig.json │ └── .gitignore ├── Procfile └── cypress │ ├── integration │ ├── testdata │ │ └── personas.js │ └── pageobjects │ │ ├── SearchPage.js │ │ ├── MenuBar.js │ │ ├── LoginPage.js │ │ └── WelcomePage.js │ ├── videos │ ├── pageobjects │ │ ├── MenuBar.js.mp4 │ │ └── WelcomePage.js.mp4 │ └── flying-high │ │ └── welcome.spec.js.mp4 │ └── fixtures │ └── example.json ├── chapter-02 └── java │ └── online-banking │ ├── src │ ├── test │ │ ├── resources │ │ │ ├── serenity.conf │ │ │ ├── features │ │ │ │ └── transfers │ │ │ │ │ └── readme.md │ │ │ └── logback-test.xml │ │ └── java │ │ │ └── com │ │ │ └── manning │ │ │ └── bddinaction │ │ │ ├── acceptancetests │ │ │ ├── domain │ │ │ │ └── InitialAccount.java │ │ │ └── AcceptanceTestSuite.java │ │ │ └── AcceptanceTestSuite.java │ └── main │ │ └── java │ │ └── com │ │ └── manning │ │ └── bddinaction │ │ └── banking │ │ ├── AccountType.java │ │ └── Transaction.java │ ├── serenity.properties │ ├── .mvn │ └── wrapper │ │ └── maven-wrapper.jar │ ├── serenity-cucumber-starter.iml │ └── README.md ├── chapter-08 ├── typescript │ └── flying-high │ │ ├── src │ │ ├── entities │ │ │ ├── PastFlight.ts │ │ │ ├── PointsMultiplier.ts │ │ │ ├── RecordedFlight.ts │ │ │ ├── CabinClass.ts │ │ │ ├── index.ts │ │ │ ├── FlightStatus.ts │ │ │ ├── FrequentFlyerStatus.ts │ │ │ ├── PointsSchedule.ts │ │ │ └── FrequentFlyerMember.ts │ │ ├── index.ts │ │ ├── controllers │ │ │ ├── Router.ts │ │ │ └── StatusController.ts │ │ └── bootstrap.ts │ │ ├── .eslintignore │ │ ├── features │ │ └── support │ │ │ ├── containers │ │ │ ├── index.ts │ │ │ └── DatabaseContainer.ts │ │ │ └── config.ts │ │ ├── cucumber.js │ │ ├── bin │ │ └── flying-high │ │ ├── .eslintrc │ │ └── tsconfig.json └── java │ ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties │ ├── flying-high │ ├── readme.md │ ├── .mvn │ │ └── wrapper │ │ │ └── maven-wrapper.jar │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── examplcom │ │ │ │ └── manning │ │ │ │ └── bddinaction │ │ │ │ └── frequentflyer │ │ │ │ ├── domain │ │ │ │ ├── CabinClass.java │ │ │ │ ├── FlightStatus.java │ │ │ │ └── FrequentFlyerStatus.java │ │ │ │ ├── flights │ │ │ │ └── Itinerary.java │ │ │ │ ├── controllers │ │ │ │ └── StatusController.java │ │ │ │ ├── FrequentFlyerApplication.java │ │ │ │ ├── services │ │ │ │ └── PastFlightEligibilityService.java │ │ │ │ └── repositories │ │ │ │ ├── RecordedFlightRepository.java │ │ │ │ └── FrequentFlyerMemberRepository.java │ │ └── resources │ │ │ └── application.yml │ │ └── test │ │ ├── resources │ │ └── testdata │ │ │ └── past-flight.json │ │ └── java │ │ └── com │ │ └── examplcom │ │ └── manning │ │ └── bddinaction │ │ └── frequentflyer │ │ └── acceptancetests │ │ ├── spring │ │ └── TestConfig.java │ │ └── AcceptanceTestSuite.java │ └── .gitignore ├── chapter-09 ├── typescript │ └── flying-high │ │ ├── src │ │ ├── entities │ │ │ ├── PastFlight.ts │ │ │ ├── PointsMultiplier.ts │ │ │ ├── RecordedFlight.ts │ │ │ ├── CabinClass.ts │ │ │ ├── index.ts │ │ │ ├── FlightStatus.ts │ │ │ ├── FrequentFlyerStatus.ts │ │ │ ├── PointsSchedule.ts │ │ │ └── FrequentFlyerMember.ts │ │ ├── index.ts │ │ ├── controllers │ │ │ ├── Router.ts │ │ │ └── StatusController.ts │ │ └── bootstrap.ts │ │ ├── .eslintignore │ │ ├── features │ │ └── support │ │ │ ├── containers │ │ │ ├── index.ts │ │ │ └── DatabaseContainer.ts │ │ │ └── config.ts │ │ ├── cucumber.js │ │ ├── bin │ │ └── flying-high │ │ ├── .eslintrc │ │ └── tsconfig.json └── java │ ├── flying-high │ ├── readme.md │ ├── .mvn │ │ └── wrapper │ │ │ └── maven-wrapper.jar │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── examplcom │ │ │ │ └── manning │ │ │ │ └── bddinaction │ │ │ │ └── frequentflyer │ │ │ │ ├── domain │ │ │ │ ├── CabinClass.java │ │ │ │ ├── FlightStatus.java │ │ │ │ └── FrequentFlyerStatus.java │ │ │ │ ├── controllers │ │ │ │ └── StatusController.java │ │ │ │ ├── FrequentFlyerApplication.java │ │ │ │ ├── services │ │ │ │ └── PastFlightEligibilityService.java │ │ │ │ └── repositories │ │ │ │ ├── RecordedFlightRepository.java │ │ │ │ └── FrequentFlyerMemberRepository.java │ │ └── resources │ │ │ └── application.yml │ │ └── test │ │ ├── resources │ │ ├── testdata │ │ │ ├── past-flight.json │ │ │ └── travellers.conf │ │ └── features │ │ │ └── frequentflyer │ │ │ └── joining_the_frequent_flyer_programme.feature │ │ └── java │ │ └── com │ │ └── examplcom │ │ └── manning │ │ └── bddinaction │ │ └── frequentflyer │ │ └── acceptancetests │ │ ├── tasks │ │ ├── automobile │ │ │ ├── NewOrUsed.java │ │ │ ├── DriverPersonas.java │ │ │ ├── MenuBar.java │ │ │ ├── DriverDetails.java │ │ │ └── Vehicle.java │ │ ├── navigation │ │ │ └── MenuBar.java │ │ └── registration │ │ │ ├── Confirms.java │ │ │ └── EnterRegistrationDetails.java │ │ ├── spring │ │ └── TestConfig.java │ │ ├── stepdefinitions │ │ └── Conforms.java │ │ └── json │ │ └── ReadTestData.java │ ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties │ └── .gitignore ├── README.md ├── chapter-03 └── java │ └── train-timetables │ ├── serenity.properties │ ├── .mvn │ └── wrapper │ │ └── maven-wrapper.jar │ ├── src │ ├── main │ │ └── java │ │ │ └── manning │ │ │ └── bddinaction │ │ │ └── timetables │ │ │ ├── UnknownLineException.java │ │ │ ├── TimeTable.java │ │ │ └── CanScheduleServices.java │ └── test │ │ ├── resources │ │ └── features │ │ │ └── itineraries │ │ │ ├── favorite_trips.feature │ │ │ └── show_alternate_routes.feature │ │ └── java │ │ └── manning │ │ └── bddinaction │ │ ├── acceptancetests │ │ └── AcceptanceTestSuite.java │ │ └── unittests │ │ └── timetables │ │ └── LocalTimes.java │ └── readme.md ├── chapter-13 ├── membership-api │ ├── .prettierrc │ ├── nest-cli.json │ ├── tsconfig.build.json │ ├── src │ │ ├── events │ │ │ ├── event-message.ts │ │ │ ├── new-frequent-flyer-event.ts │ │ │ └── eventbus.service.ts │ │ ├── frequent-flyer │ │ │ ├── entities │ │ │ │ ├── MembershipTier.ts │ │ │ │ └── frequent-flyer.entity.ts │ │ │ └── dto │ │ │ │ └── validate-email.dto.ts │ │ ├── authentication │ │ │ └── dto │ │ │ │ └── authenticate.dto.ts │ │ ├── app.service.ts │ │ ├── app.controller.ts │ │ ├── app.module.ts │ │ └── token │ │ │ └── token.ts │ ├── membership-api.iml │ └── tsconfig.json └── api-acceptance-tests │ ├── serenity.properties │ ├── src │ ├── test │ │ ├── resources │ │ │ ├── features │ │ │ │ └── registration │ │ │ │ │ ├── response.json │ │ │ │ │ ├── confirmation.json │ │ │ │ │ ├── member.json │ │ │ │ │ ├── event.json │ │ │ │ │ └── msg.json │ │ │ ├── testdata │ │ │ │ └── traveller.json │ │ │ └── logback-test.xml │ │ └── java │ │ │ └── com │ │ │ └── manning │ │ │ └── bddinaction │ │ │ └── flyinghigh │ │ │ ├── ui │ │ │ └── screenplay │ │ │ │ ├── ux │ │ │ │ ├── readme.md │ │ │ │ ├── MaterialComponents.java │ │ │ │ └── Notification.java │ │ │ │ ├── domain │ │ │ │ ├── UserLevel.java │ │ │ │ └── FlightSearch.java │ │ │ │ ├── search │ │ │ │ └── SearchResultsList.java │ │ │ │ └── navigation │ │ │ │ └── MenuBar.java │ │ │ ├── domain │ │ │ ├── persona │ │ │ │ ├── MembershipTier.java │ │ │ │ ├── EmailValidation.java │ │ │ │ └── TravellerAccountStatus.java │ │ │ └── AuthenticatedUser.java │ │ │ ├── apis │ │ │ ├── AuthenticationException.java │ │ │ ├── InvalidRegistrationException.java │ │ │ ├── ConfigurableAPIClient.java │ │ │ ├── EmailMonitor.java │ │ │ └── TokenAPI.java │ │ │ └── CucumberTestSuite.java │ └── main │ │ └── java │ │ └── com │ │ └── manning │ │ └── bddinaction │ │ └── flyinghigh │ │ └── README.md │ ├── .mvn │ └── wrapper │ │ └── maven-wrapper.jar │ ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties │ ├── .gitignore │ ├── README.md │ └── .github │ └── workflows │ ├── gradle.yml │ └── maven.yml ├── chapter-16 └── java │ ├── flying-high │ ├── src │ │ └── test │ │ │ ├── resources │ │ │ ├── cucumber.properties │ │ │ ├── testdata │ │ │ │ └── traveller.json │ │ │ ├── features │ │ │ │ └── earning_frequent_flyer_points │ │ │ │ │ └── readme.md │ │ │ └── logback.xml │ │ │ └── java │ │ │ └── com │ │ │ └── manning │ │ │ └── bddinaction │ │ │ └── frequentflyer │ │ │ └── acceptancetests │ │ │ ├── screenplay │ │ │ ├── ux │ │ │ │ ├── readme.md │ │ │ │ ├── MaterialComponents.java │ │ │ │ └── Notification.java │ │ │ ├── search │ │ │ │ ├── ToDestination.java │ │ │ │ ├── InTravelClass.java │ │ │ │ ├── BookTheFlight.java │ │ │ │ └── SearchResultsList.java │ │ │ ├── registration │ │ │ │ └── readme.md │ │ │ ├── myaccount │ │ │ │ └── StatusPanel.java │ │ │ ├── login │ │ │ │ └── LoginForm.java │ │ │ └── matchers │ │ │ │ └── CustomWebElementMatchers.java │ │ │ ├── domain │ │ │ ├── creditcards │ │ │ │ └── CreditScoreRating.java │ │ │ ├── UserLevel.java │ │ │ ├── AccountStatus.java │ │ │ ├── Flight.java │ │ │ ├── FlightSearch.java │ │ │ ├── FrequentFlyer.java │ │ │ ├── City.java │ │ │ └── FlightBooking.java │ │ │ ├── stepdefinitions │ │ │ └── creditcards │ │ │ │ └── ApplyForACreditCardStepDefinitions.java │ │ │ └── AcceptanceTestSuite.java │ ├── .gitignore │ └── readme.md │ ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties │ └── .gitignore ├── chapter-10 └── java │ ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties │ ├── flying-high │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── src │ │ └── test │ │ │ ├── java │ │ │ └── com │ │ │ │ └── manning │ │ │ │ └── bddinaction │ │ │ │ └── frequentflyer │ │ │ │ └── acceptancetests │ │ │ │ ├── AcceptanceTestSuite.java │ │ │ │ └── domain │ │ │ │ └── FrequentFlyer.java │ │ │ └── resources │ │ │ ├── features │ │ │ └── registration_and_authentication │ │ │ │ └── authentication.feature │ │ │ └── testdata │ │ │ └── travellers.conf │ └── readme.md │ └── .gitignore ├── chapter-11 └── java │ ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties │ ├── page-objects │ ├── .mvn │ │ └── wrapper │ │ │ └── maven-wrapper.jar │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── src │ │ └── test │ │ │ ├── java │ │ │ └── com │ │ │ │ └── manning │ │ │ │ └── bddinaction │ │ │ │ └── frequentflyer │ │ │ │ └── acceptancetests │ │ │ │ ├── domain │ │ │ │ ├── UserLevel.java │ │ │ │ ├── AccountStatus.java │ │ │ │ ├── FlightBooking.java │ │ │ │ ├── MatchingFlight.java │ │ │ │ └── FrequentFlyer.java │ │ │ │ ├── AcceptanceTestSuite.java │ │ │ │ └── pageobjects │ │ │ │ ├── Navigate.java │ │ │ │ └── CurrentUserPanel.java │ │ │ └── resources │ │ │ ├── features │ │ │ └── registration_and_authentication │ │ │ │ └── authentication.feature │ │ │ └── logback.xml │ └── readme.md │ ├── action-classes │ ├── .mvn │ │ └── wrapper │ │ │ └── maven-wrapper.jar │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── src │ │ └── test │ │ │ ├── java │ │ │ └── com │ │ │ │ └── manning │ │ │ │ └── bddinaction │ │ │ │ └── frequentflyer │ │ │ │ └── acceptancetests │ │ │ │ ├── domain │ │ │ │ ├── UserLevel.java │ │ │ │ ├── AccountStatus.java │ │ │ │ ├── FlightBooking.java │ │ │ │ ├── MatchingFlight.java │ │ │ │ ├── FlightSearch.java │ │ │ │ └── FrequentFlyer.java │ │ │ │ ├── actions │ │ │ │ ├── authentication │ │ │ │ │ ├── CurrentUserPanel.java │ │ │ │ │ └── Login.java │ │ │ │ └── search │ │ │ │ │ └── FieldsWithErrors.java │ │ │ │ └── AcceptanceTestSuite.java │ │ │ └── resources │ │ │ ├── features │ │ │ └── registration_and_authentication │ │ │ │ ├── authentication.feature │ │ │ │ └── registering_as_a_new_frequent_flyer.feature │ │ │ └── logback.xml │ └── readme.md │ └── .gitignore ├── chapter-12 └── java │ ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties │ ├── flying-high │ ├── readme.md │ ├── .mvn │ │ └── wrapper │ │ │ └── maven-wrapper.jar │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ └── src │ │ └── test │ │ ├── java │ │ └── com │ │ │ └── manning │ │ │ └── bddinaction │ │ │ └── frequentflyer │ │ │ └── acceptancetests │ │ │ ├── screenplay │ │ │ ├── ux │ │ │ │ ├── readme.md │ │ │ │ ├── MaterialComponents.java │ │ │ │ └── Notification.java │ │ │ ├── account │ │ │ │ ├── AccountStatus.java │ │ │ │ └── Account.java │ │ │ ├── registration │ │ │ │ └── readme.md │ │ │ ├── navigation │ │ │ │ └── CurrentUser.java │ │ │ ├── login │ │ │ │ └── LoginForm.java │ │ │ └── search │ │ │ │ ├── SearchResult.java │ │ │ │ └── SearchResultsList.java │ │ │ ├── domain │ │ │ ├── UserLevel.java │ │ │ ├── FlightSearch.java │ │ │ └── FrequentFlyer.java │ │ │ └── AcceptanceTestSuite.java │ │ └── resources │ │ └── features │ │ └── registration_and_authentication │ │ └── authentication.feature │ └── .gitignore ├── .gitignore └── .github └── workflows ├── chapter-02.yml └── chapter-03.yml /chapter-07/flying-high/README.md: -------------------------------------------------------------------------------- 1 | o -------------------------------------------------------------------------------- /chapter-14/features/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /chapter-15/features/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /flying-high-app/cypress.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /flying-high-app/web/src/assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/main.d.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /chapter-02/java/online-banking/src/test/resources/serenity.conf: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /chapter-08/typescript/flying-high/src/entities/PastFlight.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /chapter-09/typescript/flying-high/src/entities/PastFlight.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /flying-high-app/Procfile: -------------------------------------------------------------------------------- 1 | web: npm start --prefix server 2 | -------------------------------------------------------------------------------- /flying-high-app/web/src/app/register/register.component.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /chapter-08/typescript/flying-high/src/entities/PointsMultiplier.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /chapter-08/typescript/flying-high/src/entities/RecordedFlight.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /chapter-09/typescript/flying-high/src/entities/PointsMultiplier.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /chapter-09/typescript/flying-high/src/entities/RecordedFlight.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /chapter-14/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | reports/ 3 | target/ 4 | *.log 5 | -------------------------------------------------------------------------------- /chapter-14/domain/admin/index.ts: -------------------------------------------------------------------------------- 1 | export * from './RemoveTestAccount'; 2 | -------------------------------------------------------------------------------- /chapter-15/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | reports/ 3 | target/ 4 | *.log 5 | -------------------------------------------------------------------------------- /chapter-15/domain/admin/index.ts: -------------------------------------------------------------------------------- 1 | export * from './RemoveTestAccount'; 2 | -------------------------------------------------------------------------------- /chapter-08/typescript/flying-high/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lib 3 | 4 | -------------------------------------------------------------------------------- /chapter-09/typescript/flying-high/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lib 3 | 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # second-edition 2 | Sample code for the 2nd Edition of BDD In Action 3 | -------------------------------------------------------------------------------- /flying-high-app/web/src/app/users/edit-user-dialog/edit-user-dialog.component.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/app.module.d.ts: -------------------------------------------------------------------------------- 1 | export declare class AppModule { 2 | } 3 | -------------------------------------------------------------------------------- /chapter-03/java/train-timetables/serenity.properties: -------------------------------------------------------------------------------- 1 | report.tagtypes=capability,feature 2 | -------------------------------------------------------------------------------- /chapter-09/java/flying-high/readme.md: -------------------------------------------------------------------------------- 1 | Sample code for Chapter 9 of BDD in Action. 2 | 3 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/auth/auth.module.d.ts: -------------------------------------------------------------------------------- 1 | export declare class AuthModule { 2 | } 3 | -------------------------------------------------------------------------------- /flying-high-app/server/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all" 4 | } -------------------------------------------------------------------------------- /flying-high-app/server/dist/users/users.module.d.ts: -------------------------------------------------------------------------------- 1 | export declare class UsersModule { 2 | } 3 | -------------------------------------------------------------------------------- /chapter-02/java/online-banking/serenity.properties: -------------------------------------------------------------------------------- 1 | serenity.project.name=BDD In Action Chapter 1 2 | -------------------------------------------------------------------------------- /chapter-13/membership-api/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all" 4 | } -------------------------------------------------------------------------------- /chapter-16/java/flying-high/src/test/resources/cucumber.properties: -------------------------------------------------------------------------------- 1 | cucumber.publish.enabled = true 2 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/flights/flights.module.d.ts: -------------------------------------------------------------------------------- 1 | export declare class FlightsModule { 2 | } 3 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/shared/shared.module.d.ts: -------------------------------------------------------------------------------- 1 | export declare class SharedModule { 2 | } 3 | -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/serenity.properties: -------------------------------------------------------------------------------- 1 | serenity.project.name=Serenity and Cucumber Quick Start -------------------------------------------------------------------------------- /flying-high-app/server/dist/activity/activity.module.d.ts: -------------------------------------------------------------------------------- 1 | export declare class ActivityModule { 2 | } 3 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/bookings/bookings.module.d.ts: -------------------------------------------------------------------------------- 1 | export declare class BookingsModule { 2 | } 3 | -------------------------------------------------------------------------------- /chapter-08/typescript/flying-high/features/support/containers/index.ts: -------------------------------------------------------------------------------- 1 | export * from './DatabaseContainer'; 2 | -------------------------------------------------------------------------------- /chapter-08/typescript/flying-high/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './entities' 2 | export * from './FlyingHighApp' 3 | -------------------------------------------------------------------------------- /chapter-09/typescript/flying-high/features/support/containers/index.ts: -------------------------------------------------------------------------------- 1 | export * from './DatabaseContainer'; 2 | -------------------------------------------------------------------------------- /chapter-09/typescript/flying-high/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './entities' 2 | export * from './FlyingHighApp' 3 | -------------------------------------------------------------------------------- /flying-high-app/server/src/auth/constants.ts: -------------------------------------------------------------------------------- 1 | export const jwtConstants = { 2 | secret: 'secretKey', 3 | }; -------------------------------------------------------------------------------- /flying-high-app/server/dist/shared/services/bookings.service.d.ts: -------------------------------------------------------------------------------- 1 | export declare class BookingsService { 2 | } 3 | -------------------------------------------------------------------------------- /flying-high-app/server/nest-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "collection": "@nestjs/schematics", 3 | "sourceRoot": "src" 4 | } 5 | -------------------------------------------------------------------------------- /chapter-07/flying-high/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "java.configuration.updateBuildConfiguration": "interactive" 3 | } -------------------------------------------------------------------------------- /chapter-13/membership-api/nest-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "collection": "@nestjs/schematics", 3 | "sourceRoot": "src" 4 | } 5 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/auth/constants.d.ts: -------------------------------------------------------------------------------- 1 | export declare const jwtConstants: { 2 | secret: string; 3 | }; 4 | -------------------------------------------------------------------------------- /chapter-07/flying-high/serenity.properties: -------------------------------------------------------------------------------- 1 | serenity.project.name=Serenity and Cucumber Quick Start 2 | report.tagtypes=component -------------------------------------------------------------------------------- /chapter-08/typescript/flying-high/src/entities/CabinClass.ts: -------------------------------------------------------------------------------- 1 | export enum CabinClass { 2 | Economy, Business, First 3 | } 4 | -------------------------------------------------------------------------------- /chapter-09/typescript/flying-high/src/entities/CabinClass.ts: -------------------------------------------------------------------------------- 1 | export enum CabinClass { 2 | Economy, Business, First 3 | } 4 | -------------------------------------------------------------------------------- /chapter-14/domain/authentication/form/index.ts: -------------------------------------------------------------------------------- 1 | export * from './SpecifyEmailAddress'; 2 | export * from './SpecifyPassword'; 3 | -------------------------------------------------------------------------------- /chapter-14/domain/index.ts: -------------------------------------------------------------------------------- 1 | export * from './admin' 2 | export * from './authentication' 3 | export * from './registration' 4 | -------------------------------------------------------------------------------- /chapter-15/domain/authentication/form/index.ts: -------------------------------------------------------------------------------- 1 | export * from './SpecifyEmailAddress'; 2 | export * from './SpecifyPassword'; 3 | -------------------------------------------------------------------------------- /chapter-15/domain/index.ts: -------------------------------------------------------------------------------- 1 | export * from './admin' 2 | export * from './authentication' 3 | export * from './registration' 4 | -------------------------------------------------------------------------------- /chapter-08/typescript/flying-high/src/entities/index.ts: -------------------------------------------------------------------------------- 1 | export * from './CabinClass' 2 | export * from './FrequentFlyerMember' 3 | -------------------------------------------------------------------------------- /chapter-09/typescript/flying-high/src/entities/index.ts: -------------------------------------------------------------------------------- 1 | export * from './CabinClass' 2 | export * from './FrequentFlyerMember' 3 | -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/src/test/resources/features/registration/response.json: -------------------------------------------------------------------------------- 1 | { 2 | "frequentFlyerNumber": "12345678" 3 | } -------------------------------------------------------------------------------- /flying-high-app/web/proxy.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "/api/*": { 3 | "target": "http://localhost:3000", 4 | "secure": false 5 | } 6 | } -------------------------------------------------------------------------------- /flying-high-app/web/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | API_URL: '' 4 | }; 5 | -------------------------------------------------------------------------------- /flying-high-app/web/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdd-in-action/second-edition/HEAD/flying-high-app/web/src/favicon.ico -------------------------------------------------------------------------------- /flying-high-app/server/web/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdd-in-action/second-edition/HEAD/flying-high-app/server/web/favicon.ico -------------------------------------------------------------------------------- /chapter-14/integration/AuthenticationDetails.ts: -------------------------------------------------------------------------------- 1 | export interface AuthenticationDetails { 2 | jwt: string; 3 | userId: string; 4 | } 5 | -------------------------------------------------------------------------------- /chapter-15/integration/AuthenticationDetails.ts: -------------------------------------------------------------------------------- 1 | export interface AuthenticationDetails { 2 | jwt: string; 3 | userId: string; 4 | } 5 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/auth/auth-user.dto.d.ts: -------------------------------------------------------------------------------- 1 | export declare class AuthUserDto { 2 | email: string; 3 | password: string; 4 | } 5 | -------------------------------------------------------------------------------- /chapter-15/integration/index.ts: -------------------------------------------------------------------------------- 1 | export * from './AuthenticationDetails'; 2 | export * from './TravelerDetails'; 3 | export * from './TravelerNotes'; 4 | -------------------------------------------------------------------------------- /flying-high-app/server/assets/image/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdd-in-action/second-edition/HEAD/flying-high-app/server/assets/image/logo.png -------------------------------------------------------------------------------- /chapter-08/java/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdd-in-action/second-edition/HEAD/chapter-08/java/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter-09/java/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdd-in-action/second-edition/HEAD/chapter-09/java/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter-10/java/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdd-in-action/second-edition/HEAD/chapter-10/java/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter-11/java/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdd-in-action/second-edition/HEAD/chapter-11/java/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter-12/java/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdd-in-action/second-edition/HEAD/chapter-12/java/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter-13/membership-api/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /chapter-14/domain/ui/index.ts: -------------------------------------------------------------------------------- 1 | export * from './VerifySubmission'; 2 | export * from './Form'; 3 | export * from './Toaster'; 4 | export * from './Toggle'; 5 | -------------------------------------------------------------------------------- /chapter-15/domain/ui/index.ts: -------------------------------------------------------------------------------- 1 | export * from './VerifySubmission'; 2 | export * from './Form'; 3 | export * from './Toaster'; 4 | export * from './Toggle'; 5 | -------------------------------------------------------------------------------- /chapter-16/java/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdd-in-action/second-edition/HEAD/chapter-16/java/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /flying-high-app/cypress/integration/testdata/personas.js: -------------------------------------------------------------------------------- 1 | export const personas = { 2 | amy: {email:'admin@flyinghigh.com', password:'admin'} 3 | } 4 | -------------------------------------------------------------------------------- /flying-high-app/server/src/activity/activity.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | 3 | @Module({}) 4 | export class ActivityModule {} 5 | -------------------------------------------------------------------------------- /flying-high-app/server/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /flying-high-app/web/src/assets/image/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdd-in-action/second-edition/HEAD/flying-high-app/web/src/assets/image/logo.png -------------------------------------------------------------------------------- /flying-high-app/server/web/assets/image/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdd-in-action/second-edition/HEAD/flying-high-app/server/web/assets/image/logo.png -------------------------------------------------------------------------------- /flying-high-app/web/src/app/register/register.component.html: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /chapter-08/typescript/flying-high/src/entities/FlightStatus.ts: -------------------------------------------------------------------------------- 1 | export enum FlightStatus { 2 | Scheduled, 3 | Active, 4 | Completed, 5 | Cancelled, 6 | } 7 | -------------------------------------------------------------------------------- /chapter-09/typescript/flying-high/src/entities/FlightStatus.ts: -------------------------------------------------------------------------------- 1 | export enum FlightStatus { 2 | Scheduled, 3 | Active, 4 | Completed, 5 | Cancelled, 6 | } 7 | -------------------------------------------------------------------------------- /flying-high-app/server/src/shared/services/bookings.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | 3 | @Injectable() 4 | export class BookingsService {} 5 | -------------------------------------------------------------------------------- /chapter-07/flying-high/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdd-in-action/second-edition/HEAD/chapter-07/flying-high/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /chapter-08/java/flying-high/readme.md: -------------------------------------------------------------------------------- 1 | Sample code for Chapter 7 of BDD in Action. 2 | 3 | Note that to run these tests you will need Docker installed and running on your machine. -------------------------------------------------------------------------------- /chapter-12/java/flying-high/readme.md: -------------------------------------------------------------------------------- 1 | Sample code for Chapter 7 of BDD in Action. 2 | 3 | Note that to run these tests you will need Docker installed and running on your machine. -------------------------------------------------------------------------------- /chapter-13/membership-api/src/events/event-message.ts: -------------------------------------------------------------------------------- 1 | export interface EventMessage { 2 | id: number; 3 | type: string; 4 | timestamp: Date; 5 | data: any; 6 | } -------------------------------------------------------------------------------- /flying-high-app/cypress/videos/pageobjects/MenuBar.js.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdd-in-action/second-edition/HEAD/flying-high-app/cypress/videos/pageobjects/MenuBar.js.mp4 -------------------------------------------------------------------------------- /chapter-08/java/flying-high/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdd-in-action/second-edition/HEAD/chapter-08/java/flying-high/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter-08/typescript/flying-high/src/entities/FrequentFlyerStatus.ts: -------------------------------------------------------------------------------- 1 | export enum FrequentFlyerStatus { 2 | Standard, 3 | Silver, 4 | Gold, 5 | Platinum, 6 | } 7 | -------------------------------------------------------------------------------- /chapter-09/java/flying-high/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdd-in-action/second-edition/HEAD/chapter-09/java/flying-high/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter-09/typescript/flying-high/src/entities/FrequentFlyerStatus.ts: -------------------------------------------------------------------------------- 1 | export enum FrequentFlyerStatus { 2 | Standard, 3 | Silver, 4 | Gold, 5 | Platinum, 6 | } 7 | -------------------------------------------------------------------------------- /chapter-11/java/page-objects/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdd-in-action/second-edition/HEAD/chapter-11/java/page-objects/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter-12/java/flying-high/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdd-in-action/second-edition/HEAD/chapter-12/java/flying-high/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter-14/integration/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Actors'; 2 | export * from './AuthenticationDetails'; 3 | export * from './TravelerDetails'; 4 | export * from './TravelerNotes'; 5 | -------------------------------------------------------------------------------- /flying-high-app/server/src/flights/interface/city.interface.ts: -------------------------------------------------------------------------------- 1 | export interface City { 2 | name: string; 3 | point: number; 4 | short: string; 5 | region: string; 6 | } -------------------------------------------------------------------------------- /chapter-02/java/online-banking/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdd-in-action/second-edition/HEAD/chapter-02/java/online-banking/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter-09/java/flying-high/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdd-in-action/second-edition/HEAD/chapter-09/java/flying-high/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /chapter-10/java/flying-high/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdd-in-action/second-edition/HEAD/chapter-10/java/flying-high/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /chapter-11/java/action-classes/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdd-in-action/second-edition/HEAD/chapter-11/java/action-classes/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter-11/java/page-objects/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdd-in-action/second-edition/HEAD/chapter-11/java/page-objects/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /chapter-12/java/flying-high/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdd-in-action/second-edition/HEAD/chapter-12/java/flying-high/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdd-in-action/second-edition/HEAD/chapter-13/api-acceptance-tests/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /flying-high-app/cypress/integration/pageobjects/SearchPage.js: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | export class SearchPage { 4 | pageHeading() { return cy.get("h2") } 5 | } 6 | -------------------------------------------------------------------------------- /flying-high-app/cypress/videos/flying-high/welcome.spec.js.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdd-in-action/second-edition/HEAD/flying-high-app/cypress/videos/flying-high/welcome.spec.js.mp4 -------------------------------------------------------------------------------- /flying-high-app/cypress/videos/pageobjects/WelcomePage.js.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdd-in-action/second-edition/HEAD/flying-high-app/cypress/videos/pageobjects/WelcomePage.js.mp4 -------------------------------------------------------------------------------- /flying-high-app/server/dist/flights/dto/city.dto.d.ts: -------------------------------------------------------------------------------- 1 | export declare class CityDto { 2 | name: string; 3 | point: number; 4 | short: string; 5 | region: string; 6 | } 7 | -------------------------------------------------------------------------------- /chapter-03/java/train-timetables/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdd-in-action/second-edition/HEAD/chapter-03/java/train-timetables/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /chapter-11/java/action-classes/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdd-in-action/second-edition/HEAD/chapter-11/java/action-classes/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /flying-high-app/server/dist/flights/interface/city.interface.d.ts: -------------------------------------------------------------------------------- 1 | export interface City { 2 | name: string; 3 | point: number; 4 | short: string; 5 | region: string; 6 | } 7 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/flights/interface/city.interface.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | //# sourceMappingURL=city.interface.js.map -------------------------------------------------------------------------------- /flying-high-app/web/src/app/welcome/welcome.component.scss: -------------------------------------------------------------------------------- 1 | .welcome-container { 2 | margin: 20px auto; 3 | width: 500px; 4 | font-size: large; 5 | line-height: 25px; 6 | } 7 | -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bdd-in-action/second-edition/HEAD/chapter-13/api-acceptance-tests/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /flying-high-app/server/dist/flights/interface/flight.interface.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | //# sourceMappingURL=flight.interface.js.map -------------------------------------------------------------------------------- /flying-high-app/server/dist/users/interface/account.interface.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | //# sourceMappingURL=account.interface.js.map -------------------------------------------------------------------------------- /chapter-14/domain/registration/index.ts: -------------------------------------------------------------------------------- 1 | export * from './FillOutRegistrationForm'; 2 | export * from './LocateRegistrationForm'; 3 | export * from './SignUp'; 4 | export * from './SubmitRegistrationForm'; 5 | -------------------------------------------------------------------------------- /chapter-15/domain/registration/index.ts: -------------------------------------------------------------------------------- 1 | export * from './FillOutRegistrationForm'; 2 | export * from './LocateRegistrationForm'; 3 | export * from './SignUp'; 4 | export * from './SubmitRegistrationForm'; 5 | -------------------------------------------------------------------------------- /chapter-16/java/flying-high/src/test/resources/testdata/traveller.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "1001", 3 | "firstName": "Tracy", 4 | "lastName": "Traveller", 5 | "status": "GOLD", 6 | "pointBalance": 5000 7 | } -------------------------------------------------------------------------------- /flying-high-app/server/dist/flights/interface/city.interface.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"city.interface.js","sourceRoot":"","sources":["../../../src/flights/interface/city.interface.ts"],"names":[],"mappings":""} -------------------------------------------------------------------------------- /flying-high-app/web/src/app/search/city.interface.ts: -------------------------------------------------------------------------------- 1 | export interface City { 2 | name: string; 3 | short: string; 4 | } 5 | 6 | export interface Country { 7 | name: string; 8 | flag: string; 9 | } -------------------------------------------------------------------------------- /chapter-08/typescript/flying-high/cucumber.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | default: '--require-module ts-node/register --require \'features/**/*.ts\' --format node_modules/@serenity-js/cucumber --no-strict', 3 | } 4 | -------------------------------------------------------------------------------- /chapter-09/typescript/flying-high/cucumber.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | default: '--require-module ts-node/register --require \'features/**/*.ts\' --format node_modules/@serenity-js/cucumber --no-strict', 3 | } 4 | -------------------------------------------------------------------------------- /chapter-13/membership-api/src/frequent-flyer/entities/MembershipTier.ts: -------------------------------------------------------------------------------- 1 | export enum MembershipTier { 2 | Standard = "STANDARD", 3 | Bronze = "BRONZE", 4 | Siler = "SILVER", 5 | Gold = "GOLD" 6 | } 7 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/flights/interface/flight.interface.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"flight.interface.js","sourceRoot":"","sources":["../../../src/flights/interface/flight.interface.ts"],"names":[],"mappings":""} -------------------------------------------------------------------------------- /flying-high-app/server/dist/users/interface/account.interface.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"account.interface.js","sourceRoot":"","sources":["../../../src/users/interface/account.interface.ts"],"names":[],"mappings":""} -------------------------------------------------------------------------------- /flying-high-app/web/src/app/users/edit-user-dialog/edit-user-dialog.component.html: -------------------------------------------------------------------------------- 1 |

Edit user {{user.email}}

2 | -------------------------------------------------------------------------------- /flying-high-app/cypress/fixtures/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Using fixtures to represent data", 3 | "email": "hello@cypress.io", 4 | "body": "Fixtures are a great way to mock data for responses to routes" 5 | } 6 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/auth/constants.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/auth/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,YAAY,GAAG;IACxB,MAAM,EAAE,WAAW;CACtB,CAAC"} -------------------------------------------------------------------------------- /chapter-02/java/online-banking/src/main/java/com/manning/bddinaction/banking/AccountType.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.banking; 2 | 3 | public enum AccountType { 4 | Current, Savings, Investment, SuperSaver 5 | } 6 | -------------------------------------------------------------------------------- /flying-high-app/server/src/auth/jwt-auth.guard.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | import { AuthGuard } from '@nestjs/passport'; 3 | 4 | @Injectable() 5 | export class JwtAuthGuard extends AuthGuard('jwt') { } 6 | -------------------------------------------------------------------------------- /flying-high-app/server/src/auth/local-auth.guard.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | import { AuthGuard } from '@nestjs/passport'; 3 | 4 | @Injectable() 5 | export class LocalAuthGuard extends AuthGuard('local') { } -------------------------------------------------------------------------------- /flying-high-app/web/src/app/booking/booking.component.scss: -------------------------------------------------------------------------------- 1 | 2 | .container { 3 | display: flex; 4 | flex-wrap: wrap; 5 | margin: 10px auto; 6 | width: 80vw; 7 | } 8 | .card { 9 | min-width: 20%; 10 | } -------------------------------------------------------------------------------- /flying-high-app/web/src/app/login/auth-user.interface.ts: -------------------------------------------------------------------------------- 1 | export interface AuthUser { 2 | email: string; 3 | password: string; 4 | } 5 | 6 | export interface loggedInUser { 7 | email: string; 8 | userId: string; 9 | } -------------------------------------------------------------------------------- /chapter-02/java/online-banking/src/test/resources/features/transfers/readme.md: -------------------------------------------------------------------------------- 1 | Transfers 2 | 3 | Give online clients the ability to transfer funds between their own accounts and to other accounts both within the bank and between banks. -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/src/test/resources/features/registration/confirmation.json: -------------------------------------------------------------------------------- 1 | { 2 | "email": "tracy@traveler.com", 3 | "emailToken": "2c9cc14b41ac4ac87778a34bd6a3d2f4e5cffb670211b666fa817a0e1efc2989" 4 | } 5 | 6 | 7 | -------------------------------------------------------------------------------- /flying-high-app/web/src/app/shared/components/user-form/user-form.component.scss: -------------------------------------------------------------------------------- 1 | .user-form-container { 2 | width: 500px; 3 | height: 300px; 4 | margin: 0 auto; 5 | mat-form-field { 6 | width: 100%; 7 | } 8 | } -------------------------------------------------------------------------------- /flying-high-app/server/src/users/interface/account.interface.ts: -------------------------------------------------------------------------------- 1 | export interface Account { 2 | flightInfo: { 3 | date: Date; 4 | departure: string; 5 | destination: string; 6 | point: number 7 | } 8 | } -------------------------------------------------------------------------------- /flying-high-app/web/src/app/users/users-account.interface.ts: -------------------------------------------------------------------------------- 1 | export interface UsersAccount { 2 | flightInfo: { 3 | date: Date; 4 | departure: string; 5 | destination: string; 6 | point: number 7 | } 8 | } -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/src/test/java/com/manning/bddinaction/flyinghigh/ui/screenplay/ux/readme.md: -------------------------------------------------------------------------------- 1 | # Angular Material Support 2 | 3 | Interaction classes designed to work with Angular Material (https://material.angular.io/) components. -------------------------------------------------------------------------------- /flying-high-app/server/dist/auth/jwt-auth.guard.d.ts: -------------------------------------------------------------------------------- 1 | declare const JwtAuthGuard_base: import("@nestjs/passport").Type; 2 | export declare class JwtAuthGuard extends JwtAuthGuard_base { 3 | } 4 | export {}; 5 | -------------------------------------------------------------------------------- /chapter-08/java/flying-high/src/main/java/com/examplcom/manning/bddinaction/frequentflyer/domain/CabinClass.java: -------------------------------------------------------------------------------- 1 | package com.examplcom.manning.bddinaction.frequentflyer.domain; 2 | 3 | public enum CabinClass { 4 | Economy, Business, First 5 | } 6 | -------------------------------------------------------------------------------- /chapter-09/java/flying-high/src/main/java/com/examplcom/manning/bddinaction/frequentflyer/domain/CabinClass.java: -------------------------------------------------------------------------------- 1 | package com.examplcom.manning.bddinaction.frequentflyer.domain; 2 | 3 | public enum CabinClass { 4 | Economy, Business, First 5 | } 6 | -------------------------------------------------------------------------------- /chapter-14/domain/authentication/index.ts: -------------------------------------------------------------------------------- 1 | export * from './CompleteAuthenticationForm'; 2 | export * from './RememberAuthenticationDetails'; 3 | export * from './SignIn'; 4 | export * from './SignOut'; 5 | export * from './SubmitAuthenticationForm'; 6 | -------------------------------------------------------------------------------- /chapter-15/domain/authentication/index.ts: -------------------------------------------------------------------------------- 1 | export * from './CompleteAuthenticationForm'; 2 | export * from './RememberAuthenticationDetails'; 3 | export * from './SignIn'; 4 | export * from './SignOut'; 5 | export * from './SubmitAuthenticationForm'; 6 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/users/interface/account.interface.d.ts: -------------------------------------------------------------------------------- 1 | export interface Account { 2 | flightInfo: { 3 | date: Date; 4 | departure: string; 5 | destination: string; 6 | point: number; 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /chapter-13/membership-api/src/authentication/dto/authenticate.dto.ts: -------------------------------------------------------------------------------- 1 | import {ApiProperty} from "@nestjs/swagger"; 2 | 3 | export class AuthenticateDto { 4 | @ApiProperty() 5 | email: string; 6 | @ApiProperty() 7 | password: string; 8 | } 9 | -------------------------------------------------------------------------------- /chapter-14/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2019", 4 | "lib": ["es2019", "dom"], 5 | "module": "commonjs", 6 | "sourceMap": true 7 | }, 8 | 9 | "exclude": [ 10 | "node_modules" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /chapter-15/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2019", 4 | "lib": ["es2019", "dom"], 5 | "module": "commonjs", 6 | "sourceMap": true 7 | }, 8 | 9 | "exclude": [ 10 | "node_modules" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /chapter-16/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/screenplay/ux/readme.md: -------------------------------------------------------------------------------- 1 | # Angular Material Support 2 | 3 | Interaction classes designed to work with Angular Material (https://material.angular.io/) components. -------------------------------------------------------------------------------- /flying-high-app/server/dist/app.service.d.ts: -------------------------------------------------------------------------------- 1 | import { HttpService } from '@nestjs/common'; 2 | export declare class AppService { 3 | private http; 4 | constructor(http: HttpService); 5 | getCountryList(search: string): Promise; 6 | } 7 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/auth/local-auth.guard.d.ts: -------------------------------------------------------------------------------- 1 | declare const LocalAuthGuard_base: import("@nestjs/passport").Type; 2 | export declare class LocalAuthGuard extends LocalAuthGuard_base { 3 | } 4 | export {}; 5 | -------------------------------------------------------------------------------- /chapter-08/java/flying-high/src/test/resources/testdata/past-flight.json: -------------------------------------------------------------------------------- 1 | { 2 | "flightNumber":"FH-101", 3 | "scheduledDate":"2020-01-01", 4 | "departure":"London", 5 | "destination":"New York", 6 | "status":"COMPLETED", 7 | "wasDelayed":false 8 | } -------------------------------------------------------------------------------- /chapter-09/java/flying-high/src/test/resources/testdata/past-flight.json: -------------------------------------------------------------------------------- 1 | { 2 | "flightNumber":"FH-101", 3 | "scheduledDate":"2020-01-01", 4 | "departure":"London", 5 | "destination":"New York", 6 | "status":"COMPLETED", 7 | "wasDelayed":false 8 | } -------------------------------------------------------------------------------- /chapter-12/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/screenplay/ux/readme.md: -------------------------------------------------------------------------------- 1 | # Angular Material Support 2 | 3 | Interaction classes designed to work with Angular Material (https://material.angular.io/) components. 4 | -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/src/test/java/com/manning/bddinaction/flyinghigh/domain/persona/MembershipTier.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.flyinghigh.domain.persona; 2 | 3 | public enum MembershipTier { 4 | STANDARD, BRONZE, SILVER, GOLD 5 | } 6 | -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/src/test/java/com/manning/bddinaction/flyinghigh/ui/screenplay/domain/UserLevel.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.flyinghigh.ui.screenplay.domain; 2 | 3 | public enum UserLevel { 4 | STANDARD, BRONZE, SILVER, GOLD 5 | } 6 | -------------------------------------------------------------------------------- /chapter-16/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/domain/creditcards/CreditScoreRating.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.domain.creditcards;public enum CreditScoreRating { 2 | } 3 | -------------------------------------------------------------------------------- /chapter-13/membership-api/src/app.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | 3 | @Injectable() 4 | export class AppService { 5 | getStatus(): string { 6 | return 'Flying High Membership Service - BDD In Action 2nd Edition'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/auth/constants.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.jwtConstants = void 0; 4 | exports.jwtConstants = { 5 | secret: 'secretKey', 6 | }; 7 | //# sourceMappingURL=constants.js.map -------------------------------------------------------------------------------- /chapter-08/java/flying-high/src/main/java/com/examplcom/manning/bddinaction/frequentflyer/domain/FlightStatus.java: -------------------------------------------------------------------------------- 1 | package com.examplcom.manning.bddinaction.frequentflyer.domain; 2 | 3 | public enum FlightStatus { 4 | SCHEDULED, ACTIVE, COMPLETED, CANCELLED 5 | } 6 | -------------------------------------------------------------------------------- /chapter-09/java/flying-high/src/main/java/com/examplcom/manning/bddinaction/frequentflyer/domain/FlightStatus.java: -------------------------------------------------------------------------------- 1 | package com.examplcom.manning.bddinaction.frequentflyer.domain; 2 | 3 | public enum FlightStatus { 4 | SCHEDULED, ACTIVE, COMPLETED, CANCELLED 5 | } 6 | -------------------------------------------------------------------------------- /chapter-11/java/action-classes/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/domain/UserLevel.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.domain; 2 | 3 | public enum UserLevel { 4 | STANDARD, BRONZE, SILVER, GOLD 5 | } 6 | -------------------------------------------------------------------------------- /chapter-11/java/page-objects/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/domain/UserLevel.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.domain; 2 | 3 | public enum UserLevel { 4 | STANDARD, BRONZE, SILVER, GOLD 5 | } 6 | -------------------------------------------------------------------------------- /chapter-12/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/domain/UserLevel.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.domain; 2 | 3 | public enum UserLevel { 4 | STANDARD, BRONZE, SILVER, GOLD 5 | } 6 | -------------------------------------------------------------------------------- /chapter-16/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/domain/UserLevel.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.domain; 2 | 3 | public enum UserLevel { 4 | STANDARD, BRONZE, SILVER, GOLD 5 | } 6 | -------------------------------------------------------------------------------- /chapter-16/java/flying-high/src/test/resources/features/earning_frequent_flyer_points/readme.md: -------------------------------------------------------------------------------- 1 | Earning Frequent Flyer Points 2 | 3 | Frequent Flyers earn status points each time they fly. As they earn more points, their status level increases and they get more benefits. -------------------------------------------------------------------------------- /flying-high-app/server/test/jest-e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "moduleFileExtensions": ["js", "json", "ts"], 3 | "rootDir": ".", 4 | "testEnvironment": "node", 5 | "testRegex": ".e2e-spec.ts$", 6 | "transform": { 7 | "^.+\\.(t|j)s$": "ts-jest" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /chapter-02/java/online-banking/src/main/java/com/manning/bddinaction/banking/Transaction.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.banking; 2 | 3 | import java.time.LocalDateTime; 4 | 5 | public record Transaction(LocalDateTime time, String description, double amount) { 6 | } 7 | -------------------------------------------------------------------------------- /chapter-08/java/flying-high/src/main/java/com/examplcom/manning/bddinaction/frequentflyer/flights/Itinerary.java: -------------------------------------------------------------------------------- 1 | package com.examplcom.manning.bddinaction.frequentflyer.flights; 2 | 3 | public record Itinerary(String departure, String destination, int distanceInKm) { 4 | } 5 | -------------------------------------------------------------------------------- /chapter-08/java/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /chapter-08/java/flying-high/src/main/java/com/examplcom/manning/bddinaction/frequentflyer/domain/FrequentFlyerStatus.java: -------------------------------------------------------------------------------- 1 | package com.examplcom.manning.bddinaction.frequentflyer.domain; 2 | 3 | public enum FrequentFlyerStatus { 4 | Standard, Silver, Gold, Platinum 5 | } 6 | -------------------------------------------------------------------------------- /chapter-09/java/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /chapter-09/java/flying-high/src/main/java/com/examplcom/manning/bddinaction/frequentflyer/domain/FrequentFlyerStatus.java: -------------------------------------------------------------------------------- 1 | package com.examplcom.manning.bddinaction.frequentflyer.domain; 2 | 3 | public enum FrequentFlyerStatus { 4 | Standard, Silver, Gold, Platinum 5 | } 6 | -------------------------------------------------------------------------------- /chapter-10/java/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /chapter-11/java/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /chapter-12/java/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /chapter-16/java/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/flights/dto/search-flight.dto.d.ts: -------------------------------------------------------------------------------- 1 | export declare class SearchFlightDto { 2 | departure: string; 3 | destination: string; 4 | departureDate: Date; 5 | returnDate: Date; 6 | class: 'Economy' | 'Premium Economy' | 'Business'; 7 | } 8 | -------------------------------------------------------------------------------- /flying-high-app/web/src/app/login/login.component.scss: -------------------------------------------------------------------------------- 1 | .login-container { 2 | width: 500px; 3 | height: 300px; 4 | margin: 100px auto; 5 | mat-form-field { 6 | width: 100%; 7 | } 8 | .align-right { 9 | float: right; 10 | } 11 | } -------------------------------------------------------------------------------- /chapter-07/flying-high/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /chapter-09/java/flying-high/src/test/java/com/examplcom/manning/bddinaction/frequentflyer/acceptancetests/tasks/automobile/NewOrUsed.java: -------------------------------------------------------------------------------- 1 | package com.examplcom.manning.bddinaction.frequentflyer.acceptancetests.tasks.automobile; 2 | 3 | public enum NewOrUsed { 4 | NEW, USED 5 | } 6 | -------------------------------------------------------------------------------- /flying-high-app/web/src/app/users/users.component.scss: -------------------------------------------------------------------------------- 1 | .user-info-container { 2 | margin: 10px auto; 3 | width: 80%; 4 | font-size: large; 5 | button { 6 | float: right; 7 | } 8 | } 9 | table { 10 | margin: 0 auto; 11 | width: 80%; 12 | } 13 | -------------------------------------------------------------------------------- /chapter-03/java/train-timetables/src/main/java/manning/bddinaction/timetables/UnknownLineException.java: -------------------------------------------------------------------------------- 1 | package manning.bddinaction.timetables; 2 | 3 | public class UnknownLineException extends RuntimeException{ 4 | public UnknownLineException(String message) { super(message);} 5 | } 6 | -------------------------------------------------------------------------------- /chapter-09/java/flying-high/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /chapter-10/java/flying-high/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /chapter-11/java/action-classes/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /chapter-11/java/page-objects/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /chapter-12/java/flying-high/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/src/main/java/com/manning/bddinaction/flyinghigh/README.md: -------------------------------------------------------------------------------- 1 | ### Application code 2 | 3 | These packages generally contain application code. 4 | If you are writing a reusable test library, you can also place reusable test components such as Page Objects or Tasks here. -------------------------------------------------------------------------------- /chapter-14/integration/TravelerNotes.ts: -------------------------------------------------------------------------------- 1 | import { TravelerDetails } from './TravelerDetails'; 2 | import { AuthenticationDetails } from './AuthenticationDetails'; 3 | 4 | export interface TravelerNotes { 5 | travelerDetails: TravelerDetails; 6 | authenticationDetails?: AuthenticationDetails; 7 | } 8 | -------------------------------------------------------------------------------- /chapter-15/integration/TravelerNotes.ts: -------------------------------------------------------------------------------- 1 | import { TravelerDetails } from './TravelerDetails'; 2 | import { AuthenticationDetails } from './AuthenticationDetails'; 3 | 4 | export interface TravelerNotes { 5 | travelerDetails: TravelerDetails; 6 | authenticationDetails?: AuthenticationDetails; 7 | } 8 | -------------------------------------------------------------------------------- /chapter-16/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/screenplay/search/ToDestination.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.screenplay.search; 2 | 3 | public interface ToDestination { 4 | InTravelClass to(String destination); 5 | } 6 | -------------------------------------------------------------------------------- /chapter-16/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/stepdefinitions/creditcards/ApplyForACreditCardStepDefinitions.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.stepdefinitions.creditcards;public class ApplyForACreditCardStepDefinitions { 2 | } 3 | -------------------------------------------------------------------------------- /chapter-02/java/online-banking/src/test/java/com/manning/bddinaction/acceptancetests/domain/InitialAccount.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.acceptancetests.domain; 2 | 3 | import com.manning.bddinaction.banking.AccountType; 4 | 5 | public record InitialAccount(AccountType accountType, int balance) { 6 | } 7 | -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/src/test/resources/features/registration/member.json: -------------------------------------------------------------------------------- 1 | { 2 | "firstName": "Tracy", 3 | "lastName": "Traveler", 4 | "title": "Ms", 5 | "email": "tracy@example.com", 6 | "passord": "secret", 7 | "address": "Transitville", 8 | "country": "USA" 9 | } 10 | 11 | 12 | -------------------------------------------------------------------------------- /flying-high-app/web/e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/e2e", 5 | "module": "commonjs", 6 | "target": "es5", 7 | "types": [ 8 | "jasmine", 9 | "jasminewd2", 10 | "node" 11 | ] 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /flying-high-app/web/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./out-tsc/app", 5 | "types": [] 6 | }, 7 | "files": [ 8 | "src/main.ts", 9 | "src/polyfills.ts" 10 | ], 11 | "include": [ 12 | "src/**/*.d.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/activity/activity.module.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"activity.module.js","sourceRoot":"","sources":["../../src/activity/activity.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AAGxC,IAAa,cAAc,GAA3B,MAAa,cAAc;CAAG,CAAA;AAAjB,cAAc;IAD1B,eAAM,CAAC,EAAE,CAAC;GACE,cAAc,CAAG;AAAjB,wCAAc"} -------------------------------------------------------------------------------- /chapter-08/typescript/flying-high/bin/flying-high: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | require('ts-node/register') 4 | 5 | const port = process.env.PORT || 3000 6 | const host = process.env.HOST || 'localhost' 7 | const mode = process.env.NODE_ENV || 'development' 8 | 9 | require('../src/bootstrap')(port, host, mode) 10 | -------------------------------------------------------------------------------- /chapter-09/typescript/flying-high/bin/flying-high: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | require('ts-node/register') 4 | 5 | const port = process.env.PORT || 3000 6 | const host = process.env.HOST || 'localhost' 7 | const mode = process.env.NODE_ENV || 'development' 8 | 9 | require('../src/bootstrap')(port, host, mode) 10 | -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/src/test/java/com/manning/bddinaction/flyinghigh/domain/AuthenticatedUser.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.flyinghigh.domain; 2 | 3 | public record AuthenticatedUser(String frequentFlyerNumber, String email, String firstName, String lastName, boolean isActivated, String jwtToken) { 4 | } 5 | -------------------------------------------------------------------------------- /chapter-13/membership-api/src/frequent-flyer/dto/validate-email.dto.ts: -------------------------------------------------------------------------------- 1 | import {ApiProperty} from "@nestjs/swagger"; 2 | 3 | export class ValidateEmailDto { 4 | @ApiProperty() 5 | frequentFlyerNumber: number; 6 | @ApiProperty() 7 | email: string; 8 | @ApiProperty() 9 | token: string; 10 | } 11 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/shared/services/bookings.service.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"bookings.service.js","sourceRoot":"","sources":["../../../src/shared/services/bookings.service.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAA4C;AAG5C,IAAa,eAAe,GAA5B,MAAa,eAAe;CAAG,CAAA;AAAlB,eAAe;IAD3B,mBAAU,EAAE;GACA,eAAe,CAAG;AAAlB,0CAAe"} -------------------------------------------------------------------------------- /flying-high-app/server/src/flights/dto/city.dto.ts: -------------------------------------------------------------------------------- 1 | import { ApiProperty } from "@nestjs/swagger"; 2 | 3 | export class CityDto { 4 | @ApiProperty() 5 | name: string; 6 | @ApiProperty() 7 | point: number; 8 | @ApiProperty() 9 | short: string; 10 | @ApiProperty() 11 | region: string; 12 | } -------------------------------------------------------------------------------- /chapter-08/java/flying-high/src/test/java/com/examplcom/manning/bddinaction/frequentflyer/acceptancetests/spring/TestConfig.java: -------------------------------------------------------------------------------- 1 | package com.examplcom.manning.bddinaction.frequentflyer.acceptancetests.spring; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | 5 | @Configuration 6 | public class TestConfig { 7 | } 8 | -------------------------------------------------------------------------------- /chapter-09/java/flying-high/src/test/java/com/examplcom/manning/bddinaction/frequentflyer/acceptancetests/spring/TestConfig.java: -------------------------------------------------------------------------------- 1 | package com.examplcom.manning.bddinaction.frequentflyer.acceptancetests.spring; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | 5 | @Configuration 6 | public class TestConfig { 7 | } 8 | -------------------------------------------------------------------------------- /chapter-11/java/page-objects/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/domain/AccountStatus.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.domain; 2 | 3 | /** 4 | * The current user level and point balance 5 | */ 6 | public record AccountStatus(UserLevel userLevel, Integer pointBalance) {} 7 | -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/src/test/java/com/manning/bddinaction/flyinghigh/apis/AuthenticationException.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.flyinghigh.apis; 2 | 3 | public class AuthenticationException extends RuntimeException { 4 | public AuthenticationException(String message) { 5 | super(message); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /chapter-16/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/domain/AccountStatus.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.domain; 2 | 3 | /** 4 | * The current user level and point balance 5 | */ 6 | public record AccountStatus(UserLevel userLevel, Integer pointBalance) {} 7 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/auth/jwt-auth.guard.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"jwt-auth.guard.js","sourceRoot":"","sources":["../../src/auth/jwt-auth.guard.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAA4C;AAC5C,+CAA6C;AAG7C,IAAa,YAAY,GAAzB,MAAa,YAAa,SAAQ,oBAAS,CAAC,KAAK,CAAC;CAAI,CAAA;AAAzC,YAAY;IADxB,mBAAU,EAAE;GACA,YAAY,CAA6B;AAAzC,oCAAY"} -------------------------------------------------------------------------------- /chapter-11/java/action-classes/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/domain/AccountStatus.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.domain; 2 | 3 | /** 4 | * The current user level and point balance 5 | */ 6 | public record AccountStatus(UserLevel userLevel, Integer pointBalance) {} 7 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/auth/local-auth.guard.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"local-auth.guard.js","sourceRoot":"","sources":["../../src/auth/local-auth.guard.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAA4C;AAC5C,+CAA6C;AAG7C,IAAa,cAAc,GAA3B,MAAa,cAAe,SAAQ,oBAAS,CAAC,OAAO,CAAC;CAAI,CAAA;AAA7C,cAAc;IAD1B,mBAAU,EAAE;GACA,cAAc,CAA+B;AAA7C,wCAAc"} -------------------------------------------------------------------------------- /flying-high-app/web/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /chapter-15/integration/webdriverio/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | 4 | "compilerOptions": { 5 | "target": "es2019", 6 | "lib": ["es2019", "dom"], 7 | "module": "commonjs", 8 | "sourceMap": true, 9 | "types": [ 10 | "node", 11 | "webdriverio/async" 12 | ] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/flights/dto/city.dto.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"city.dto.js","sourceRoot":"","sources":["../../../src/flights/dto/city.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6CAA8C;AAE9C,MAAa,OAAO;CASnB;AAPG;IADC,qBAAW,EAAE;;qCACD;AAEb;IADC,qBAAW,EAAE;;sCACA;AAEd;IADC,qBAAW,EAAE;;sCACA;AAEd;IADC,qBAAW,EAAE;;uCACC;AARnB,0BASC"} -------------------------------------------------------------------------------- /chapter-03/java/train-timetables/src/test/resources/features/itineraries/favorite_trips.feature: -------------------------------------------------------------------------------- 1 | Feature: Show next departing trains 2 | 3 | As a commuter who needs to get to work 4 | I want to be shown alternate routes if they get me to my destination faster 5 | 6 | Scenario: Show a faster alternative route when there are maintenance delays 7 | -------------------------------------------------------------------------------- /chapter-08/typescript/flying-high/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "parser": "@typescript-eslint/parser", 4 | "plugins": [ 5 | "@typescript-eslint" 6 | ], 7 | "extends": [ 8 | "eslint:recommended", 9 | "plugin:@typescript-eslint/eslint-recommended", 10 | "plugin:@typescript-eslint/recommended" 11 | ] 12 | } 13 | 14 | -------------------------------------------------------------------------------- /chapter-09/typescript/flying-high/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "parser": "@typescript-eslint/parser", 4 | "plugins": [ 5 | "@typescript-eslint" 6 | ], 7 | "extends": [ 8 | "eslint:recommended", 9 | "plugin:@typescript-eslint/eslint-recommended", 10 | "plugin:@typescript-eslint/recommended" 11 | ] 12 | } 13 | 14 | -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/src/test/java/com/manning/bddinaction/flyinghigh/apis/InvalidRegistrationException.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.flyinghigh.apis; 2 | 3 | public class InvalidRegistrationException extends RuntimeException { 4 | public InvalidRegistrationException(String message) { 5 | super(message); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/auth/auth-user.dto.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"auth-user.dto.js","sourceRoot":"","sources":["../../src/auth/auth-user.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6CAA8C;AAE9C,MAAa,WAAW;CAKvB;AAHG;IADC,qBAAW,CAAC,EAAE,WAAW,EAAE,wHAAwH,EAAE,CAAC;;0CACzI;AAEd;IADC,qBAAW,CAAC,EAAE,WAAW,EAAE,wBAAwB,EAAE,CAAC;;6CACtC;AAJrB,kCAKC"} -------------------------------------------------------------------------------- /flying-high-app/server/dist/auth/jwt.strategy.d.ts: -------------------------------------------------------------------------------- 1 | import { Strategy } from 'passport-jwt'; 2 | declare const JwtStrategy_base: new (...args: any[]) => Strategy; 3 | export declare class JwtStrategy extends JwtStrategy_base { 4 | constructor(); 5 | validate(payload: any): Promise<{ 6 | email: any; 7 | }>; 8 | } 9 | export {}; 10 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/flights/dto/create-flight.dto.d.ts: -------------------------------------------------------------------------------- 1 | import { CityDto } from "./city.dto"; 2 | export declare class CreateFlightDto { 3 | departure: CityDto; 4 | destination: CityDto; 5 | departureDate: Date; 6 | arrivalDate: Date; 7 | class: 'Economy' | 'Premium Economy' | 'Business'; 8 | email: string; 9 | } 10 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/bookings/bookings.controller.d.ts: -------------------------------------------------------------------------------- 1 | import { FlightsService } from '../shared/services/flights.service'; 2 | export declare class BookingsController { 3 | private flightService; 4 | constructor(flightService: FlightsService); 5 | getUserBookings(email: string): import("../flights/interface/flight.interface").Flight[]; 6 | } 7 | -------------------------------------------------------------------------------- /flying-high-app/server/src/users/users.module.ts: -------------------------------------------------------------------------------- 1 | import { HttpModule, Module } from '@nestjs/common'; 2 | import { SharedModule } from '../shared/shared.module'; 3 | import { UsersController } from './users.controller'; 4 | 5 | @Module({ 6 | controllers: [UsersController], 7 | imports: [HttpModule, SharedModule] 8 | }) 9 | export class UsersModule { } 10 | -------------------------------------------------------------------------------- /chapter-02/java/online-banking/serenity-cucumber-starter.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /chapter-11/java/action-classes/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/domain/FlightBooking.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.domain; 2 | 3 | /** 4 | * The flight booking record shown in the My Account page 5 | */ 6 | public record FlightBooking(String departure, String destination, Integer pointsEarned) {} 7 | -------------------------------------------------------------------------------- /chapter-11/java/page-objects/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/domain/FlightBooking.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.domain; 2 | 3 | /** 4 | * The flight booking record shown in the My Account page 5 | */ 6 | public record FlightBooking(String departure, String destination, Integer pointsEarned) {} 7 | -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/src/test/java/com/manning/bddinaction/flyinghigh/ui/screenplay/domain/FlightSearch.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.flyinghigh.ui.screenplay.domain; 2 | 3 | import com.manning.bddinaction.flyinghigh.domain.persona.TravelClass; 4 | 5 | public record FlightSearch(String from, String to, TravelClass travelClass, Boolean returnTrip) {} 6 | -------------------------------------------------------------------------------- /chapter-12/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/domain/FlightSearch.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.domain; 2 | 3 | public record FlightSearch(String from, String to, TravelClass travelClass, Boolean returnTrip) { 4 | public String travelClassName() { return travelClass.getLabel(); } 5 | } 6 | -------------------------------------------------------------------------------- /chapter-09/java/flying-high/src/test/java/com/examplcom/manning/bddinaction/frequentflyer/acceptancetests/tasks/navigation/MenuBar.java: -------------------------------------------------------------------------------- 1 | package com.examplcom.manning.bddinaction.frequentflyer.acceptancetests.tasks.navigation; 2 | 3 | import org.openqa.selenium.By; 4 | 5 | public class MenuBar { 6 | public static final By REGISTER = By.partialLinkText("Register Now"); 7 | } 8 | -------------------------------------------------------------------------------- /chapter-12/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/screenplay/account/AccountStatus.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.screenplay.account; 2 | 3 | import com.manning.bddinaction.frequentflyer.acceptancetests.domain.UserLevel; 4 | 5 | public record AccountStatus(UserLevel level, Integer points) { 6 | } 7 | -------------------------------------------------------------------------------- /chapter-16/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/domain/Flight.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.domain; 2 | 3 | import com.manning.bddinaction.frequentflyer.acceptancetests.domain.persona.TravelClass; 4 | 5 | public record Flight(String from, String to, TravelClass travelClass, String tripDate) {} 6 | -------------------------------------------------------------------------------- /flying-high-app/server/src/flights/flights.module.ts: -------------------------------------------------------------------------------- 1 | import { HttpModule, Module } from '@nestjs/common'; 2 | import { FlightsController } from './flights.controller'; 3 | import { SharedModule } from 'src/shared/shared.module'; 4 | 5 | @Module({ 6 | controllers: [FlightsController], 7 | imports: [HttpModule, SharedModule], 8 | }) 9 | export class FlightsModule {} 10 | -------------------------------------------------------------------------------- /chapter-09/java/flying-high/src/test/java/com/examplcom/manning/bddinaction/frequentflyer/acceptancetests/tasks/automobile/DriverPersonas.java: -------------------------------------------------------------------------------- 1 | package com.examplcom.manning.bddinaction.frequentflyer.acceptancetests.tasks.automobile; 2 | 3 | public class DriverPersonas { 4 | public static DriverDetails withName(String name) { 5 | return new DriverDetails(); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /chapter-13/membership-api/src/events/new-frequent-flyer-event.ts: -------------------------------------------------------------------------------- 1 | import {EventMessage} from "./event-message"; 2 | 3 | export class NewFrequentFlyerEvent implements EventMessage { 4 | data: any; 5 | type = 'NewFrequentFlyerEvent'; 6 | id = Date.now(); 7 | timestamp = new Date(); 8 | 9 | constructor(data: any) { 10 | this.data = data; 11 | } 12 | } -------------------------------------------------------------------------------- /chapter-11/java/action-classes/readme.md: -------------------------------------------------------------------------------- 1 | ## Flying High Acceptance Tests 2 | 3 | This test suite illustrates BDD scenarios using Cucumber and Serenity BDD. 4 | 5 | You can clone and run the application under test from the following repository: 6 | 7 | https://github.com/bdd-in-action/flying-high-app.git 8 | 9 | To run the tests themselves, run: 10 | ``` 11 | mvn verify 12 | ``` 13 | -------------------------------------------------------------------------------- /chapter-13/membership-api/src/app.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Get } from '@nestjs/common'; 2 | import { AppService } from './app.service'; 3 | 4 | @Controller("api/status") 5 | export class AppController { 6 | constructor(private readonly appService: AppService) {} 7 | 8 | @Get() 9 | getStatus(): string { 10 | return this.appService.getStatus(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /flying-high-app/server/src/bookings/bookings.module.ts: -------------------------------------------------------------------------------- 1 | import { HttpModule, Module } from '@nestjs/common'; 2 | import { BookingsController } from './bookings.controller'; 3 | import { SharedModule } from 'src/shared/shared.module'; 4 | 5 | @Module({ 6 | controllers: [BookingsController], 7 | imports: [HttpModule, SharedModule], 8 | }) 9 | export class BookingsModule { } 10 | -------------------------------------------------------------------------------- /flying-high-app/web/e2e/src/app.po.ts: -------------------------------------------------------------------------------- 1 | import { browser, by, element } from 'protractor'; 2 | 3 | export class AppPage { 4 | navigateTo(): Promise { 5 | return browser.get(browser.baseUrl) as Promise; 6 | } 7 | 8 | getTitleText(): Promise { 9 | return element(by.css('app-root .content span')).getText() as Promise; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter-11/java/action-classes/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/domain/MatchingFlight.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.domain; 2 | 3 | import com.manning.bddinaction.frequentflyer.acceptancetests.domain.persona.TravelClass; 4 | 5 | public record MatchingFlight(String departure, String destination, TravelClass travelClass) {} 6 | -------------------------------------------------------------------------------- /chapter-11/java/page-objects/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/domain/MatchingFlight.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.domain; 2 | 3 | import com.manning.bddinaction.frequentflyer.acceptancetests.domain.persona.TravelClass; 4 | 5 | public record MatchingFlight(String departure, String destination, TravelClass travelClass) {} 6 | -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/src/test/resources/features/registration/event.json: -------------------------------------------------------------------------------- 1 | { 2 | "firstName": "Tracy", 3 | "lastName": "Traveler", 4 | "title": "Ms", 5 | "email": "tracy@traveler.com", 6 | "address": "Transitville", 7 | "country": "USA", 8 | "frequentFlyerNumber": "12345678", 9 | "emailToken": "2c9cc14b41ac4ac87778a34bd6a3d2f4e5cffb670211b666fa817a0e1efc2989" 10 | } -------------------------------------------------------------------------------- /chapter-16/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/domain/FlightSearch.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.domain; 2 | 3 | import com.manning.bddinaction.frequentflyer.acceptancetests.domain.persona.TravelClass; 4 | 5 | public record FlightSearch(String from, String to, TravelClass travelClass, Boolean returnTrip) {} 6 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/users/users.module.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"users.module.js","sourceRoot":"","sources":["../../src/users/users.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAoD;AACpD,2DAAuD;AACvD,yDAAqD;AAMrD,IAAa,WAAW,GAAxB,MAAa,WAAW;CAAI,CAAA;AAAf,WAAW;IAJvB,eAAM,CAAC;QACN,WAAW,EAAE,CAAC,kCAAe,CAAC;QAC9B,OAAO,EAAE,CAAC,mBAAU,EAAE,4BAAY,CAAC;KACpC,CAAC;GACW,WAAW,CAAI;AAAf,kCAAW"} -------------------------------------------------------------------------------- /flying-high-app/web/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./out-tsc/spec", 5 | "types": [ 6 | "jasmine", 7 | "node" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts", 12 | "src/polyfills.ts" 13 | ], 14 | "include": [ 15 | "src/**/*.spec.ts", 16 | "src/**/*.d.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /chapter-03/java/train-timetables/src/test/resources/features/itineraries/show_alternate_routes.feature: -------------------------------------------------------------------------------- 1 | Feature: Show next departing trains 2 | 3 | As a commuter travelling regularly on the same line 4 | I want to record my favorite trips 5 | So that I don't need to search them each time 6 | 7 | Scenario: Record a single favorite trip 8 | 9 | Scenario: Record multiple favorite trips 10 | -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/src/test/java/com/manning/bddinaction/flyinghigh/domain/persona/EmailValidation.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.flyinghigh.domain.persona; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | /** 6 | * The information we need to validate an email address 7 | */ 8 | public record EmailValidation(String frequentFlyerNumber,String email,String token){} 9 | -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/src/test/resources/testdata/traveller.json: -------------------------------------------------------------------------------- 1 | { 2 | "isActivated": true, 3 | "tier": "STANDARD", 4 | "statusPoints": 0, 5 | "firstName": "Tracy", 6 | "lastName": "Traveler", 7 | "title": "Mrs", 8 | "email": "tracy@example.org", 9 | "address": "10 Pinnack Street, Reading", 10 | "country": "United Kingdon", 11 | "frequentFlyerNumber": 1000018 12 | } 13 | -------------------------------------------------------------------------------- /chapter-13/membership-api/membership-api.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /flying-high-app/server/src/auth/auth-user.dto.ts: -------------------------------------------------------------------------------- 1 | import { ApiProperty } from "@nestjs/swagger"; 2 | 3 | export class AuthUserDto { 4 | @ApiProperty({ description: 'Generate the token and apply it by clicking the lock icon above to get AUTH access. default email admin@flyinghigh.com' }) 5 | email: string; 6 | @ApiProperty({ description: 'default password admin' }) 7 | password: string; 8 | } -------------------------------------------------------------------------------- /chapter-02/java/online-banking/README.md: -------------------------------------------------------------------------------- 1 | # BDD In Action Chapter 2 2 | 3 | To run this sample code you will need the following: 4 | - Java 17 or higher 5 | - Maven 3.x 6 | 7 | Running with Maven: 8 | ``` 9 | mvn clean verify 10 | ``` 11 | 12 | Running with Gradle: 13 | ``` 14 | gradle clean test 15 | ``` 16 | 17 | In both cases, the reports will be generated in `target/site/serenity/index.html` 18 | -------------------------------------------------------------------------------- /chapter-07/.github/workflows/gradle.yml: -------------------------------------------------------------------------------- 1 | name: Gradle Build 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - uses: actions/checkout@v1 12 | - name: Set up JDK 1.8 13 | uses: actions/setup-java@v1 14 | with: 15 | java-version: 1.8 16 | - name: Build with Gradle 17 | run: cd flying-high && ./gradlew test 18 | -------------------------------------------------------------------------------- /chapter-07/flying-high/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | build 3 | .gradle 4 | pom.xml.tag 5 | pom.xml.releaseBackup 6 | pom.xml.versionsBackup 7 | pom.xml.next 8 | release.properties 9 | dependency-reduced-pom.xml 10 | buildNumber.properties 11 | .mvn/timing.properties 12 | .idea 13 | *.iml 14 | 15 | # Avoid ignoring Maven wrapper jar file (.jar files are usually ignored) 16 | !/.mvn/wrapper/maven-wrapper.jar 17 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/flights/flights.module.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"flights.module.js","sourceRoot":"","sources":["../../src/flights/flights.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAoD;AACpD,6DAAyD;AACzD,2DAAwD;AAMxD,IAAa,aAAa,GAA1B,MAAa,aAAa;CAAG,CAAA;AAAhB,aAAa;IAJzB,eAAM,CAAC;QACN,WAAW,EAAE,CAAC,sCAAiB,CAAC;QAChC,OAAO,EAAE,CAAC,mBAAU,EAAE,4BAAY,CAAC;KACpC,CAAC;GACW,aAAa,CAAG;AAAhB,sCAAa"} -------------------------------------------------------------------------------- /chapter-12/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/screenplay/registration/readme.md: -------------------------------------------------------------------------------- 1 | # Registrations 2 | 3 | New members can register a Frequent Flyer account by entering their personal details and preferences. 4 | 5 | Sample usage: 6 | ```java 7 | actor.attemptsTo( 8 | RegisterAsAFrequentFlyer.withMemberDetailsFrom(newMember) 9 | ); 10 | ``` 11 | -------------------------------------------------------------------------------- /chapter-16/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/screenplay/registration/readme.md: -------------------------------------------------------------------------------- 1 | # Registrations 2 | 3 | New members can register a Frequent Flyer account by entering their personal details and preferences. 4 | 5 | Sample usage: 6 | ```java 7 | actor.attemptsTo( 8 | RegisterAsAFrequentFlyer.withMemberDetailsFrom(newMember) 9 | ); 10 | ``` 11 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/bookings/bookings.module.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"bookings.module.js","sourceRoot":"","sources":["../../src/bookings/bookings.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAoD;AACpD,+DAA2D;AAC3D,2DAAwD;AAMxD,IAAa,cAAc,GAA3B,MAAa,cAAc;CAAI,CAAA;AAAlB,cAAc;IAJ1B,eAAM,CAAC;QACJ,WAAW,EAAE,CAAC,wCAAkB,CAAC;QACjC,OAAO,EAAE,CAAC,mBAAU,EAAE,4BAAY,CAAC;KACtC,CAAC;GACW,cAAc,CAAI;AAAlB,wCAAc"} -------------------------------------------------------------------------------- /chapter-07/.github/workflows/maven.yml: -------------------------------------------------------------------------------- 1 | name: Maven Build 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - uses: actions/checkout@v1 12 | - name: Set up JDK 1.8 13 | uses: actions/setup-java@v1 14 | with: 15 | java-version: 1.8 16 | - name: Build with Maven 17 | run: cd flying-high && mvn -B verify --file pom.xml 18 | -------------------------------------------------------------------------------- /chapter-08/typescript/flying-high/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "moduleResolution": "node", 5 | "pretty": true, 6 | "sourceMap": true, 7 | "target": "es6", 8 | "outDir": "./lib", 9 | "experimentalDecorators": true, 10 | "emitDecoratorMetadata": true, 11 | "resolveJsonModule": true 12 | }, 13 | "include": ["src/**/*.ts"] 14 | } 15 | -------------------------------------------------------------------------------- /chapter-09/typescript/flying-high/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "moduleResolution": "node", 5 | "pretty": true, 6 | "sourceMap": true, 7 | "target": "es6", 8 | "outDir": "./lib", 9 | "experimentalDecorators": true, 10 | "emitDecoratorMetadata": true, 11 | "resolveJsonModule": true 12 | }, 13 | "include": ["src/**/*.ts"] 14 | } 15 | -------------------------------------------------------------------------------- /chapter-11/java/action-classes/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/actions/authentication/CurrentUserPanel.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.actions.authentication; 2 | 3 | import net.serenitybdd.core.pages.PageObject; 4 | import org.openqa.selenium.By; 5 | 6 | class CurrentUserPanel { 7 | static By CURRENT_USER_EMAIL = By.id("current-user"); 8 | } 9 | -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/src/test/java/com/manning/bddinaction/flyinghigh/ui/screenplay/ux/MaterialComponents.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.flyinghigh.ui.screenplay.ux; 2 | 3 | import net.serenitybdd.screenplay.targets.Target; 4 | 5 | class MaterialComponents { 6 | static final Target MATERIAL_OPTION = Target.the("option").locatedBy("//span[@class='mat-option-text'][normalize-space()='{0}']"); 7 | } 8 | -------------------------------------------------------------------------------- /chapter-16/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/screenplay/search/InTravelClass.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.screenplay.search; 2 | 3 | import com.manning.bddinaction.frequentflyer.acceptancetests.domain.persona.TravelClass; 4 | 5 | public interface InTravelClass { 6 | SearchFlights inTravelClass(TravelClass travelClass); 7 | } 8 | -------------------------------------------------------------------------------- /flying-high-app/web/src/app/shared/enums/user.enum.ts: -------------------------------------------------------------------------------- 1 | export enum USER_TITLE { 2 | MR = 'Mr', 3 | MS = 'Ms', 4 | MX = 'Mx', 5 | MRS = 'Mrs' 6 | } 7 | 8 | export enum SEAT_PREFERENCE { 9 | AISLE = 'aisle', 10 | WINDOW = 'window' 11 | } 12 | 13 | export enum USER_LEVEL { 14 | STANDARD = 'STANDARD', 15 | BRONZE = 'BRONZE', 16 | SILVER = 'SILVER', 17 | GOLD = 'GOLD' 18 | } 19 | -------------------------------------------------------------------------------- /chapter-14/domain/authentication/form/SpecifyPassword.ts: -------------------------------------------------------------------------------- 1 | import { Answerable, Task } from '@serenity-js/core'; 2 | import { Enter } from '@serenity-js/web'; 3 | import { Form } from '../../ui'; 4 | 5 | export const SpecifyPassword = (password: Answerable) => 6 | Task.where(`#actor specifies their password`, 7 | Enter.theValue(password) 8 | .into(Form.inputFor('Password')), 9 | ); 10 | -------------------------------------------------------------------------------- /chapter-14/domain/registration/form/SpecifyHomeAddress.ts: -------------------------------------------------------------------------------- 1 | import { Answerable, Task } from '@serenity-js/core'; 2 | import { Enter } from '@serenity-js/web'; 3 | import { Form } from '../../ui'; 4 | 5 | export const SpecifyHomeAddress = (address: Answerable) => 6 | Task.where(`#actor specifies their address`, 7 | Enter.theValue(address) 8 | .into(Form.inputFor('Address')), 9 | ); 10 | -------------------------------------------------------------------------------- /chapter-14/domain/registration/form/SpecifyLastName.ts: -------------------------------------------------------------------------------- 1 | import { Answerable, Task } from '@serenity-js/core'; 2 | import { Enter } from '@serenity-js/web'; 3 | import { Form } from '../../ui'; 4 | 5 | export const SpecifyLastName = (lastName: Answerable) => 6 | Task.where(`#actor specifies their last name`, 7 | Enter.theValue(lastName) 8 | .into(Form.inputFor('Last name')), 9 | ); 10 | -------------------------------------------------------------------------------- /chapter-14/domain/registration/form/SpecifyPassword.ts: -------------------------------------------------------------------------------- 1 | import { Answerable, Task } from '@serenity-js/core'; 2 | import { Enter } from '@serenity-js/web'; 3 | import { Form } from '../../ui'; 4 | 5 | export const SpecifyPassword = (password: Answerable) => 6 | Task.where(`#actor specifies their password`, 7 | Enter.theValue(password) 8 | .into(Form.inputFor('Password')), 9 | ); 10 | -------------------------------------------------------------------------------- /chapter-15/domain/authentication/form/SpecifyPassword.ts: -------------------------------------------------------------------------------- 1 | import { Answerable, Task } from '@serenity-js/core'; 2 | import { Enter } from '@serenity-js/web'; 3 | import { Form } from '../../ui'; 4 | 5 | export const SpecifyPassword = (password: Answerable) => 6 | Task.where(`#actor specifies their password`, 7 | Enter.theValue(password) 8 | .into(Form.inputFor('Password')), 9 | ); 10 | -------------------------------------------------------------------------------- /chapter-15/domain/registration/form/SpecifyHomeAddress.ts: -------------------------------------------------------------------------------- 1 | import { Answerable, Task } from '@serenity-js/core'; 2 | import { Enter } from '@serenity-js/web'; 3 | import { Form } from '../../ui'; 4 | 5 | export const SpecifyHomeAddress = (address: Answerable) => 6 | Task.where(`#actor specifies their address`, 7 | Enter.theValue(address) 8 | .into(Form.inputFor('Address')), 9 | ); 10 | -------------------------------------------------------------------------------- /chapter-15/domain/registration/form/SpecifyLastName.ts: -------------------------------------------------------------------------------- 1 | import { Answerable, Task } from '@serenity-js/core'; 2 | import { Enter } from '@serenity-js/web'; 3 | import { Form } from '../../ui'; 4 | 5 | export const SpecifyLastName = (lastName: Answerable) => 6 | Task.where(`#actor specifies their last name`, 7 | Enter.theValue(lastName) 8 | .into(Form.inputFor('Last name')), 9 | ); 10 | -------------------------------------------------------------------------------- /chapter-15/domain/registration/form/SpecifyPassword.ts: -------------------------------------------------------------------------------- 1 | import { Answerable, Task } from '@serenity-js/core'; 2 | import { Enter } from '@serenity-js/web'; 3 | import { Form } from '../../ui'; 4 | 5 | export const SpecifyPassword = (password: Answerable) => 6 | Task.where(`#actor specifies their password`, 7 | Enter.theValue(password) 8 | .into(Form.inputFor('Password')), 9 | ); 10 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/auth/auth.module.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"auth.module.js","sourceRoot":"","sources":["../../src/auth/auth.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,+CAAkD;AAClD,2DAAwD;AACxD,iDAA6C;AAC7C,qDAAiD;AASjD,IAAa,UAAU,GAAvB,MAAa,UAAU;CAAI,CAAA;AAAd,UAAU;IAPtB,eAAM,CAAC;QACN,SAAS,EAAE,CAAC,8BAAa,EAAE,0BAAW,CAAC;QACvC,OAAO,EAAE;YACP,yBAAc;YACd,4BAAY;SACb;KACF,CAAC;GACW,UAAU,CAAI;AAAd,gCAAU"} -------------------------------------------------------------------------------- /chapter-14/domain/registration/form/SpecifyFirstName.ts: -------------------------------------------------------------------------------- 1 | import { Answerable, Task } from '@serenity-js/core'; 2 | import { Enter } from '@serenity-js/web'; 3 | import { Form } from '../../ui'; 4 | 5 | export const SpecifyFirstName = (firstName: Answerable) => 6 | Task.where(`#actor specifies their first name`, 7 | Enter.theValue(firstName) 8 | .into(Form.inputFor('First name')), 9 | ); 10 | -------------------------------------------------------------------------------- /chapter-15/domain/registration/form/SpecifyFirstName.ts: -------------------------------------------------------------------------------- 1 | import { Answerable, Task } from '@serenity-js/core'; 2 | import { Enter } from '@serenity-js/web'; 3 | import { Form } from '../../ui'; 4 | 5 | export const SpecifyFirstName = (firstName: Answerable) => 6 | Task.where(`#actor specifies their first name`, 7 | Enter.theValue(firstName) 8 | .into(Form.inputFor('First name')), 9 | ); 10 | -------------------------------------------------------------------------------- /chapter-03/java/train-timetables/src/main/java/manning/bddinaction/timetables/TimeTable.java: -------------------------------------------------------------------------------- 1 | package manning.bddinaction.timetables; 2 | 3 | import java.time.LocalTime; 4 | import java.util.List; 5 | import java.util.stream.Stream; 6 | 7 | public interface TimeTable { 8 | List findLinesThrough(String departingFrom, String goingTo); 9 | List getDepartures(String lineName, String departingFrom); 10 | } 11 | -------------------------------------------------------------------------------- /chapter-07/flying-high/src/test/resources/features/frequent_flyer/earning_points/earning_points_from_flights_fr.feature: -------------------------------------------------------------------------------- 1 | #language: fr 2 | Fonctionnalité: Gagner des points Frequent Flyer en completant des vols 3 | 4 | Scénario: Les vols en Europe valent 100 points 5 | Etant donné que Tara est un member du programme Frequent Flyer 6 | Quand elle complete un vol entre Paris and Berlin 7 | Alors elle devrait gagner 100 points 8 | -------------------------------------------------------------------------------- /chapter-13/membership-api/src/app.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { AppController } from './app.controller'; 3 | import { AppService } from './app.service'; 4 | import { FrequentFlyerModule } from './frequent-flyer/frequent-flyer.module'; 5 | 6 | @Module({ 7 | imports: [FrequentFlyerModule], 8 | controllers: [AppController], 9 | providers: [AppService], 10 | }) 11 | export class AppModule {} 12 | -------------------------------------------------------------------------------- /flying-high-app/server/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "declaration": true, 5 | "removeComments": true, 6 | "emitDecoratorMetadata": true, 7 | "experimentalDecorators": true, 8 | "target": "es2017", 9 | "sourceMap": true, 10 | "outDir": "./dist", 11 | "baseUrl": "./", 12 | "incremental": true 13 | }, 14 | "exclude": ["node_modules", "dist"] 15 | } 16 | -------------------------------------------------------------------------------- /chapter-12/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/screenplay/navigation/CurrentUser.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.screenplay.navigation; 2 | 3 | import net.serenitybdd.screenplay.Question; 4 | import net.serenitybdd.screenplay.questions.Text; 5 | 6 | public class CurrentUser { 7 | public static final Question EMAIL = Text.of("#current-user"); 8 | } 9 | -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | build 3 | out 4 | .gradle 5 | pom.xml.tag 6 | pom.xml.releaseBackup 7 | pom.xml.versionsBackup 8 | pom.xml.next 9 | release.properties 10 | dependency-reduced-pom.xml 11 | buildNumber.properties 12 | .mvn/timing.properties 13 | .idea 14 | *.iml 15 | .DS_Store 16 | 17 | # Avoid ignoring Maven wrapper jar file (.jar files are usually ignored) 18 | !/.mvn/wrapper/maven-wrapper.jar 19 | -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/src/test/java/com/manning/bddinaction/flyinghigh/ui/screenplay/ux/Notification.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.flyinghigh.ui.screenplay.ux; 2 | 3 | import net.serenitybdd.screenplay.targets.Target; 4 | 5 | /** 6 | * Toastr notification messages 7 | */ 8 | public class Notification { 9 | public static final Target OF_SUCCESS = Target.the("Success message").locatedBy(".toast-success"); 10 | } 11 | -------------------------------------------------------------------------------- /chapter-14/domain/authentication/form/SpecifyEmailAddress.ts: -------------------------------------------------------------------------------- 1 | import { Answerable, Task } from '@serenity-js/core'; 2 | import { Enter } from '@serenity-js/web'; 3 | import { Form } from '../../ui'; 4 | 5 | export const SpecifyEmailAddress = (emailAddress: Answerable) => 6 | Task.where(`#actor specifies their email address`, 7 | Enter.theValue(emailAddress) 8 | .into(Form.inputFor('Email')), 9 | ); 10 | -------------------------------------------------------------------------------- /chapter-14/domain/registration/form/SpecifyEmailAddress.ts: -------------------------------------------------------------------------------- 1 | import { Answerable, Task } from '@serenity-js/core'; 2 | import { Enter } from '@serenity-js/web'; 3 | import { Form } from '../../ui'; 4 | 5 | export const SpecifyEmailAddress = (emailAddress: Answerable) => 6 | Task.where(`#actor specifies their email address`, 7 | Enter.theValue(emailAddress) 8 | .into(Form.inputFor('Email')), 9 | ); 10 | -------------------------------------------------------------------------------- /chapter-15/domain/authentication/form/SpecifyEmailAddress.ts: -------------------------------------------------------------------------------- 1 | import { Answerable, Task } from '@serenity-js/core'; 2 | import { Enter } from '@serenity-js/web'; 3 | import { Form } from '../../ui'; 4 | 5 | export const SpecifyEmailAddress = (emailAddress: Answerable) => 6 | Task.where(`#actor specifies their email address`, 7 | Enter.theValue(emailAddress) 8 | .into(Form.inputFor('Email')), 9 | ); 10 | -------------------------------------------------------------------------------- /chapter-15/domain/registration/form/SpecifyEmailAddress.ts: -------------------------------------------------------------------------------- 1 | import { Answerable, Task } from '@serenity-js/core'; 2 | import { Enter } from '@serenity-js/web'; 3 | import { Form } from '../../ui'; 4 | 5 | export const SpecifyEmailAddress = (emailAddress: Answerable) => 6 | Task.where(`#actor specifies their email address`, 7 | Enter.theValue(emailAddress) 8 | .into(Form.inputFor('Email')), 9 | ); 10 | -------------------------------------------------------------------------------- /flying-high-app/cypress/integration/pageobjects/MenuBar.js: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | const MENU_BAR = '.operation-section' 4 | 5 | export class MenuBar { 6 | 7 | loginButton() { 8 | return cy.get(MENU_BAR) 9 | .contains('button','Login') 10 | } 11 | 12 | registerButton() { 13 | return cy.get(MENU_BAR) 14 | .contains('button','Register') 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /chapter-12/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/screenplay/ux/MaterialComponents.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.screenplay.ux; 2 | 3 | import net.serenitybdd.screenplay.targets.Target; 4 | 5 | class MaterialComponents { 6 | static final Target MATERIAL_OPTION = Target.the("option").locatedBy("//span[@class='mat-option-text'][normalize-space()='{0}']"); 7 | } 8 | -------------------------------------------------------------------------------- /chapter-16/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/screenplay/ux/MaterialComponents.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.screenplay.ux; 2 | 3 | import net.serenitybdd.screenplay.targets.Target; 4 | 5 | class MaterialComponents { 6 | static final Target MATERIAL_OPTION = Target.the("option").locatedBy("//span[@class='mat-option-text'][normalize-space()='{0}']"); 7 | } 8 | -------------------------------------------------------------------------------- /chapter-09/java/flying-high/src/test/java/com/examplcom/manning/bddinaction/frequentflyer/acceptancetests/tasks/automobile/MenuBar.java: -------------------------------------------------------------------------------- 1 | package com.examplcom.manning.bddinaction.frequentflyer.acceptancetests.tasks.automobile; 2 | 3 | import org.openqa.selenium.By; 4 | 5 | public class MenuBar { 6 | public static final By GET_A_QUOTE = By.partialLinkText("Get a quote"); 7 | public static final By CAR = By.linkText("Car"); 8 | } 9 | 10 | -------------------------------------------------------------------------------- /chapter-14/domain/registration/form/SpecifyCountryOfResidence.ts: -------------------------------------------------------------------------------- 1 | import { Answerable, Task } from '@serenity-js/core'; 2 | import { Enter } from '@serenity-js/web'; 3 | import { Form } from '../../ui'; 4 | 5 | export const SpecifyCountryOfResidence = (country: Answerable) => 6 | Task.where(`#actor specifies their country of residence`, 7 | Enter.theValue(country) 8 | .into(Form.inputFor('Country')), 9 | ); 10 | -------------------------------------------------------------------------------- /chapter-15/domain/registration/form/SpecifyCountryOfResidence.ts: -------------------------------------------------------------------------------- 1 | import { Answerable, Task } from '@serenity-js/core'; 2 | import { Enter } from '@serenity-js/web'; 3 | import { Form } from '../../ui'; 4 | 5 | export const SpecifyCountryOfResidence = (country: Answerable) => 6 | Task.where(`#actor specifies their country of residence`, 7 | Enter.theValue(country) 8 | .into(Form.inputFor('Country')), 9 | ); 10 | -------------------------------------------------------------------------------- /chapter-08/typescript/flying-high/src/controllers/Router.ts: -------------------------------------------------------------------------------- 1 | import * as express from 'express' 2 | import { StatusController } from './StatusController' 3 | 4 | export class Router { 5 | public nodesController = new StatusController() 6 | 7 | public routes(server: express.Application): void { 8 | server.route('/').get(this.nodesController.index) 9 | server.route('/nodes').get(this.nodesController.index) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter-09/typescript/flying-high/src/controllers/Router.ts: -------------------------------------------------------------------------------- 1 | import * as express from 'express' 2 | import { StatusController } from './StatusController' 3 | 4 | export class Router { 5 | public nodesController = new StatusController() 6 | 7 | public routes(server: express.Application): void { 8 | server.route('/').get(this.nodesController.index) 9 | server.route('/nodes').get(this.nodesController.index) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /flying-high-app/web/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic().bootstrapModule(AppModule) 12 | .catch(err => console.error(err)); 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # IDE 2 | .idea 3 | 4 | # Java 5 | target/ 6 | pom.xml.tag 7 | pom.xml.releaseBackup 8 | pom.xml.versionsBackup 9 | pom.xml.next 10 | release.properties 11 | .gradle 12 | build 13 | dependency-reduced-pom.xml 14 | buildNumber.properties 15 | .mvn/timing.properties 16 | # https://github.com/takari/maven-wrapper#usage-without-binary-jar 17 | .mvn/wrapper/maven-wrapper.ja 18 | 19 | # TypeScript 20 | node_modules/ 21 | *.log 22 | dist 23 | coverage 24 | -------------------------------------------------------------------------------- /chapter-02/java/online-banking/src/test/java/com/manning/bddinaction/AcceptanceTestSuite.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction; 2 | 3 | import io.cucumber.junit.CucumberOptions; 4 | import net.serenitybdd.cucumber.CucumberWithSerenity; 5 | import org.junit.runner.RunWith; 6 | 7 | @RunWith(CucumberWithSerenity.class) 8 | @CucumberOptions( 9 | plugin = {"pretty"}, 10 | features = "classpath:features" 11 | ) 12 | public class AcceptanceTestSuite { } -------------------------------------------------------------------------------- /chapter-14/domain/authentication/SubmitAuthenticationForm.ts: -------------------------------------------------------------------------------- 1 | import { Task } from '@serenity-js/core'; 2 | import { By, Click, PageElement } from '@serenity-js/web'; 3 | 4 | const LoginButton = () => 5 | PageElement.located(By.id('login-button')) 6 | .describedAs('"Login" button') 7 | 8 | export const SubmitAuthenticationForm = () => 9 | Task.where(`#actor submits the authentication form`, 10 | Click.on(LoginButton()), 11 | ); 12 | -------------------------------------------------------------------------------- /chapter-15/domain/authentication/SubmitAuthenticationForm.ts: -------------------------------------------------------------------------------- 1 | import { Task } from '@serenity-js/core'; 2 | import { By, Click, PageElement } from '@serenity-js/web'; 3 | 4 | const LoginButton = () => 5 | PageElement.located(By.id('login-button')) 6 | .describedAs('"Login" button') 7 | 8 | export const SubmitAuthenticationForm = () => 9 | Task.where(`#actor submits the authentication form`, 10 | Click.on(LoginButton()), 11 | ); 12 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/auth/local.strategy.d.ts: -------------------------------------------------------------------------------- 1 | import { Strategy } from 'passport-local'; 2 | import { AuthService } from '../shared/services/auth.service'; 3 | declare const LocalStrategy_base: new (...args: any[]) => Strategy; 4 | export declare class LocalStrategy extends LocalStrategy_base { 5 | private authService; 6 | constructor(authService: AuthService); 7 | validate(email: string, password: string): Promise; 8 | } 9 | export {}; 10 | -------------------------------------------------------------------------------- /flying-high-app/web/src/app/booking/booking.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { BookingComponent } from './booking.component'; 4 | import { BookingsRoutingModule } from './booking-routing.module'; 5 | 6 | @NgModule({ 7 | declarations: [BookingComponent], 8 | imports: [ 9 | CommonModule, 10 | BookingsRoutingModule 11 | ] 12 | }) 13 | export class BookingModule { } 14 | -------------------------------------------------------------------------------- /chapter-03/java/train-timetables/src/main/java/manning/bddinaction/timetables/CanScheduleServices.java: -------------------------------------------------------------------------------- 1 | package manning.bddinaction.timetables; 2 | 3 | import java.time.LocalTime; 4 | import java.util.List; 5 | 6 | public interface CanScheduleServices { 7 | void scheduleService(String line, 8 | List departingAt, 9 | String departure, 10 | String destination); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /chapter-12/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/screenplay/ux/Notification.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.screenplay.ux; 2 | 3 | import net.serenitybdd.screenplay.targets.Target; 4 | 5 | /** 6 | * Toastr notification messages 7 | */ 8 | public class Notification { 9 | public static final Target OF_SUCCESS = Target.the("Success message").locatedBy(".toast-success"); 10 | } 11 | -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/README.md: -------------------------------------------------------------------------------- 1 | # BDD In Action Chapter 12 2 | 3 | This project contains the sample code for Chapter 12 of BDD in Action. To run the tests in this project, you will first need to start up the API service in the `membership-api` folder. To do this, go to that folder and run the following commands (you will need to have NodeJS installed on your machine): 4 | ```shell 5 | cd membership-api 6 | npm install 7 | npm run start 8 | ``` 9 | 10 | 11 | -------------------------------------------------------------------------------- /chapter-16/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/screenplay/ux/Notification.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.screenplay.ux; 2 | 3 | import net.serenitybdd.screenplay.targets.Target; 4 | 5 | /** 6 | * Toastr notification messages 7 | */ 8 | public class Notification { 9 | public static final Target OF_SUCCESS = Target.the("Success message").locatedBy(".toast-success"); 10 | } 11 | -------------------------------------------------------------------------------- /chapter-03/java/train-timetables/src/test/java/manning/bddinaction/acceptancetests/AcceptanceTestSuite.java: -------------------------------------------------------------------------------- 1 | package manning.bddinaction.acceptancetests; 2 | 3 | import io.cucumber.junit.CucumberOptions; 4 | import net.serenitybdd.cucumber.CucumberWithSerenity; 5 | import org.junit.runner.RunWith; 6 | 7 | @RunWith(CucumberWithSerenity.class) 8 | @CucumberOptions(features="src/test/resources/features/", glue="manning.bddinaction") 9 | public class AcceptanceTestSuite {} 10 | -------------------------------------------------------------------------------- /chapter-09/java/flying-high/src/test/java/com/examplcom/manning/bddinaction/frequentflyer/acceptancetests/tasks/registration/Confirms.java: -------------------------------------------------------------------------------- 1 | package com.examplcom.manning.bddinaction.frequentflyer.acceptancetests.tasks.registration; 2 | 3 | import net.serenitybdd.screenplay.Performable; 4 | import net.serenitybdd.screenplay.Task; 5 | 6 | public class Confirms { 7 | public static Performable termsAndConditions() { 8 | return Task.where(""); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /chapter-14/domain/registration/SubmitRegistrationForm.ts: -------------------------------------------------------------------------------- 1 | import { Task } from '@serenity-js/core'; 2 | import { By, Click, PageElement } from '@serenity-js/web'; 3 | 4 | const RegisterButton = () => 5 | PageElement.located(By.id('register-button')) 6 | .describedAs('"Register" button') 7 | 8 | export const SubmitRegistrationForm = () => 9 | Task.where(`#actor submits their membership registration`, 10 | Click.on(RegisterButton()), 11 | ) 12 | -------------------------------------------------------------------------------- /chapter-15/domain/registration/SubmitRegistrationForm.ts: -------------------------------------------------------------------------------- 1 | import { Task } from '@serenity-js/core'; 2 | import { By, Click, PageElement } from '@serenity-js/web'; 3 | 4 | const RegisterButton = () => 5 | PageElement.located(By.id('register-button')) 6 | .describedAs('"Register" button') 7 | 8 | export const SubmitRegistrationForm = () => 9 | Task.where(`#actor submits their membership registration`, 10 | Click.on(RegisterButton()), 11 | ) 12 | -------------------------------------------------------------------------------- /chapter-16/java/flying-high/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | .gradle 3 | .idea 4 | lib 5 | target 6 | *.iml 7 | *.log 8 | out 9 | .DS_Store 10 | /serenity-core.ipr 11 | /serenity-core.iws 12 | /serenity-smoketests/todo-demo.ipr 13 | /serenity-smoketests/todo-demo.iws 14 | /serenity-smoketests/saucelabs.sh 15 | /wip.todo 16 | .okhttpcache 17 | .settings 18 | .project 19 | .classpath 20 | bin 21 | *.versionsBackup 22 | serenity-cli/dependency-reduced-pom.xml 23 | /serenity.properties 24 | -------------------------------------------------------------------------------- /chapter-09/java/flying-high/src/test/java/com/examplcom/manning/bddinaction/frequentflyer/acceptancetests/stepdefinitions/Conforms.java: -------------------------------------------------------------------------------- 1 | package com.examplcom.manning.bddinaction.frequentflyer.acceptancetests.stepdefinitions; 2 | 3 | import net.serenitybdd.screenplay.Performable; 4 | import net.serenitybdd.screenplay.SilentTask; 5 | 6 | public class Conforms { 7 | public static Performable theApplicationDetails() { 8 | return SilentTask.where(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /chapter-14/domain/registration/form/index.ts: -------------------------------------------------------------------------------- 1 | export * from './SpecifyCountryOfResidence'; 2 | export * from './SpecifyEmailAddress'; 3 | export * from './SpecifyFirstName'; 4 | export * from './SpecifyHomeAddress'; 5 | export * from './SpecifyLastName'; 6 | export * from './SpecifyPassword'; 7 | export * from './SpecifySalutation'; 8 | export * from './SpecifySeatPreference'; 9 | export * from './ToggleNewsletterSubscription'; 10 | export * from './ToggleTermsAndConditions'; 11 | -------------------------------------------------------------------------------- /chapter-15/domain/registration/form/index.ts: -------------------------------------------------------------------------------- 1 | export * from './SpecifyCountryOfResidence'; 2 | export * from './SpecifyEmailAddress'; 3 | export * from './SpecifyFirstName'; 4 | export * from './SpecifyHomeAddress'; 5 | export * from './SpecifyLastName'; 6 | export * from './SpecifyPassword'; 7 | export * from './SpecifySalutation'; 8 | export * from './SpecifySeatPreference'; 9 | export * from './ToggleNewsletterSubscription'; 10 | export * from './ToggleTermsAndConditions'; 11 | -------------------------------------------------------------------------------- /chapter-09/java/flying-high/src/test/java/com/examplcom/manning/bddinaction/frequentflyer/acceptancetests/tasks/automobile/DriverDetails.java: -------------------------------------------------------------------------------- 1 | package com.examplcom.manning.bddinaction.frequentflyer.acceptancetests.tasks.automobile; 2 | 3 | public class DriverDetails { 4 | public DriverDetails withAccidentCount(int numberOfAccidents) { 5 | return this; 6 | } 7 | 8 | public DriverDetails withVehicle(Vehicle vehicle) { 9 | return this; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter-08/typescript/flying-high/features/support/config.ts: -------------------------------------------------------------------------------- 1 | import { ConsoleReporter } from '@serenity-js/console-reporter' 2 | import { ArtifactArchiver, configure } from '@serenity-js/core' 3 | import { SerenityBDDReporter } from '@serenity-js/serenity-bdd' 4 | 5 | configure({ 6 | crew: [ 7 | ArtifactArchiver.storingArtifactsAt('./target/site/serenity'), 8 | new SerenityBDDReporter(), 9 | ConsoleReporter.withDefaultColourSupport(), 10 | ] 11 | }) 12 | -------------------------------------------------------------------------------- /chapter-09/typescript/flying-high/features/support/config.ts: -------------------------------------------------------------------------------- 1 | import { ConsoleReporter } from '@serenity-js/console-reporter' 2 | import { ArtifactArchiver, configure } from '@serenity-js/core' 3 | import { SerenityBDDReporter } from '@serenity-js/serenity-bdd' 4 | 5 | configure({ 6 | crew: [ 7 | ArtifactArchiver.storingArtifactsAt('./target/site/serenity'), 8 | new SerenityBDDReporter(), 9 | ConsoleReporter.withDefaultColourSupport(), 10 | ] 11 | }) 12 | -------------------------------------------------------------------------------- /chapter-10/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/AcceptanceTestSuite.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests; 2 | 3 | import io.cucumber.junit.CucumberOptions; 4 | import net.serenitybdd.cucumber.CucumberWithSerenity; 5 | import org.junit.runner.RunWith; 6 | 7 | @RunWith(CucumberWithSerenity.class) 8 | @CucumberOptions( 9 | features = "classpath:features" 10 | ) 11 | public class AcceptanceTestSuite {} 12 | -------------------------------------------------------------------------------- /flying-high-app/cypress/integration/pageobjects/LoginPage.js: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | export class LoginPage { 4 | open() { 5 | cy.visit("http://localhost:3000/login") 6 | } 7 | 8 | emailField() { return cy.get('[data-testid=email]') } 9 | 10 | passwordField() { return cy.get('[data-testid=password]') } 11 | 12 | loginButton() { return cy.get('#login-button') } 13 | 14 | errorMessages() { return cy.get("mat-error") } 15 | } 16 | -------------------------------------------------------------------------------- /flying-high-app/server/src/auth/auth.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { PassportModule } from '@nestjs/passport'; 3 | import { SharedModule } from 'src/shared/shared.module'; 4 | import { JwtStrategy } from './jwt.strategy'; 5 | import { LocalStrategy } from './local.strategy'; 6 | 7 | @Module({ 8 | providers: [LocalStrategy, JwtStrategy], 9 | imports: [ 10 | PassportModule, 11 | SharedModule 12 | ] 13 | }) 14 | export class AuthModule { } 15 | -------------------------------------------------------------------------------- /flying-high-app/web/src/app/booking/booking-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | import { BookingComponent } from './booking.component'; 4 | 5 | 6 | const routes: Routes = [ 7 | { 8 | path: '', component: BookingComponent 9 | } 10 | ]; 11 | 12 | @NgModule({ 13 | imports: [RouterModule.forChild(routes)], 14 | exports: [RouterModule] 15 | }) 16 | export class BookingsRoutingModule { } 17 | -------------------------------------------------------------------------------- /flying-high-app/web/src/app/search/search-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | import { SearchComponent } from './search/search.component'; 4 | 5 | 6 | const routes: Routes = [ 7 | { 8 | path: '', component: SearchComponent 9 | } 10 | ]; 11 | 12 | @NgModule({ 13 | imports: [RouterModule.forChild(routes)], 14 | exports: [RouterModule] 15 | }) 16 | export class SearchRoutingModule { } 17 | -------------------------------------------------------------------------------- /chapter-11/java/action-classes/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/AcceptanceTestSuite.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests; 2 | 3 | import io.cucumber.junit.CucumberOptions; 4 | import net.serenitybdd.cucumber.CucumberWithSerenity; 5 | import org.junit.runner.RunWith; 6 | 7 | @RunWith(CucumberWithSerenity.class) 8 | @CucumberOptions( 9 | features = "classpath:features" 10 | ) 11 | public class AcceptanceTestSuite {} 12 | -------------------------------------------------------------------------------- /chapter-11/java/page-objects/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/AcceptanceTestSuite.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests; 2 | 3 | import io.cucumber.junit.CucumberOptions; 4 | import net.serenitybdd.cucumber.CucumberWithSerenity; 5 | import org.junit.runner.RunWith; 6 | 7 | @RunWith(CucumberWithSerenity.class) 8 | @CucumberOptions( 9 | features = "classpath:features" 10 | ) 11 | public class AcceptanceTestSuite {} 12 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/users/dto/user.dto.d.ts: -------------------------------------------------------------------------------- 1 | import { SEAT_PREFERENCE, USER_LEVEL, USER_TITLE } from "../interface/users.interface"; 2 | export declare class UserDto { 3 | email: string; 4 | password: string; 5 | firstName: string; 6 | lastName: string; 7 | address: string; 8 | country: string; 9 | title: USER_TITLE; 10 | newsletterSub: boolean; 11 | seatPreference: SEAT_PREFERENCE; 12 | userLevel: USER_LEVEL; 13 | points: number; 14 | } 15 | -------------------------------------------------------------------------------- /chapter-02/java/online-banking/src/test/java/com/manning/bddinaction/acceptancetests/AcceptanceTestSuite.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.acceptancetests; 2 | 3 | import io.cucumber.junit.CucumberOptions; 4 | import net.serenitybdd.cucumber.CucumberWithSerenity; 5 | import org.junit.runner.RunWith; 6 | 7 | @RunWith(CucumberWithSerenity.class) 8 | @CucumberOptions( 9 | plugin = {"pretty"}, 10 | features = "classpath:features" 11 | ) 12 | public class AcceptanceTestSuite { } 13 | -------------------------------------------------------------------------------- /chapter-14/domain/registration/LocateRegistrationForm.ts: -------------------------------------------------------------------------------- 1 | import { Task } from '@serenity-js/core'; 2 | import { Click, Navigate } from '@serenity-js/web'; 3 | import { Form } from '../ui'; 4 | 5 | export class LocateRegistrationForm { 6 | static viaMainMenu = () => 7 | Task.where(`#actor locates Frequent Flyer registration form`, 8 | Navigate.to('/'), 9 | Click.on( 10 | Form.buttonCalled('Register') 11 | ), 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /chapter-07/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/AcceptanceTestSuite.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer; 2 | 3 | import io.cucumber.junit.CucumberOptions; 4 | import net.serenitybdd.cucumber.CucumberWithSerenity; 5 | import org.junit.runner.RunWith; 6 | 7 | @RunWith(CucumberWithSerenity.class) 8 | @CucumberOptions( 9 | plugin = {"pretty","html:target/output"}, 10 | features = "classpath:features" 11 | ) 12 | public class AcceptanceTestSuite { } -------------------------------------------------------------------------------- /chapter-10/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/domain/FrequentFlyer.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.domain; 2 | 3 | public enum FrequentFlyer { 4 | Tracy("tracy@flyinghigh.com", "trac3"); 5 | 6 | public final String email; 7 | public final String password; 8 | 9 | FrequentFlyer(String email, String password) { 10 | this.email = email; 11 | this.password = password; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /chapter-11/java/action-classes/src/test/resources/features/registration_and_authentication/authentication.feature: -------------------------------------------------------------------------------- 1 | Business Need: Authentication 2 | 3 | Registered Frequent Flyer members can access their account using their email and password 4 | 5 | Example: Tracy successfully logs on to the Frequent Flyer app 6 | Given Tracy is a registered Frequency Flyer member 7 | When she logs on with a valid username and password 8 | Then she should be given access to her account 9 | 10 | 11 | -------------------------------------------------------------------------------- /chapter-12/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/domain/FrequentFlyer.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.domain; 2 | 3 | public enum FrequentFlyer { 4 | Amy("admin@flyinghigh.com", "admin"); 5 | 6 | public final String email; 7 | public final String password; 8 | 9 | FrequentFlyer(String email, String password) { 10 | this.email = email; 11 | this.password = password; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /chapter-16/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/domain/FrequentFlyer.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.domain; 2 | 3 | public enum FrequentFlyer { 4 | Tracy("tracy@flyinghigh.com", "trac3"); 5 | 6 | public final String email; 7 | public final String password; 8 | 9 | FrequentFlyer(String email, String password) { 10 | this.email = email; 11 | this.password = password; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /flying-high-app/web/browserslist: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # You can see what browsers were selected by your queries by running: 6 | # npx browserslist 7 | 8 | > 0.5% 9 | last 2 versions 10 | Firefox ESR 11 | not dead 12 | not IE 9-11 # For IE 9-11 support, remove 'not'. -------------------------------------------------------------------------------- /chapter-08/java/flying-high/src/main/java/com/examplcom/manning/bddinaction/frequentflyer/controllers/StatusController.java: -------------------------------------------------------------------------------- 1 | package com.examplcom.manning.bddinaction.frequentflyer.controllers; 2 | 3 | import org.springframework.web.bind.annotation.RequestMapping; 4 | import org.springframework.web.bind.annotation.RestController; 5 | 6 | @RestController 7 | public class StatusController { 8 | 9 | @RequestMapping("/") 10 | public String index() { 11 | return "BDD In Action Chapter 7"; 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /chapter-09/java/flying-high/src/main/java/com/examplcom/manning/bddinaction/frequentflyer/controllers/StatusController.java: -------------------------------------------------------------------------------- 1 | package com.examplcom.manning.bddinaction.frequentflyer.controllers; 2 | 3 | import org.springframework.web.bind.annotation.RequestMapping; 4 | import org.springframework.web.bind.annotation.RestController; 5 | 6 | @RestController 7 | public class StatusController { 8 | 9 | @RequestMapping("/") 10 | public String index() { 11 | return "BDD In Action Chapter 7"; 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /chapter-10/java/flying-high/src/test/resources/features/registration_and_authentication/authentication.feature: -------------------------------------------------------------------------------- 1 | Business Need: Authentication 2 | 3 | Registered Frequent Flyer members can access their account using their email and password 4 | 5 | @webtest 6 | Example: Tracy successfully logs on to the Frequent Flyer app 7 | Given Tracy is a registered Frequency Flyer member 8 | When she logs on with a valid username and password 9 | Then she should be given access to his account 10 | 11 | -------------------------------------------------------------------------------- /chapter-11/java/page-objects/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/domain/FrequentFlyer.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.domain; 2 | 3 | public enum FrequentFlyer { 4 | Tracy("tracy@flyinghigh.com", "trac3"); 5 | 6 | public final String email; 7 | public final String password; 8 | 9 | FrequentFlyer(String email, String password) { 10 | this.email = email; 11 | this.password = password; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /chapter-12/java/flying-high/src/test/resources/features/registration_and_authentication/authentication.feature: -------------------------------------------------------------------------------- 1 | Business Need: Authentication 2 | 3 | Registered Frequent Flyer members can access their account using their email and password 4 | 5 | @webtest 6 | Example: Tracy successfully logs on to the Frequent Flyer app 7 | Given Tracy is a registered Frequency Flyer member 8 | When she logs on with a valid username and password 9 | Then she should be given access to his account 10 | 11 | -------------------------------------------------------------------------------- /chapter-08/java/flying-high/src/main/java/com/examplcom/manning/bddinaction/frequentflyer/FrequentFlyerApplication.java: -------------------------------------------------------------------------------- 1 | package com.examplcom.manning.bddinaction.frequentflyer; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class FrequentFlyerApplication { 8 | public static void main(String[] args) { 9 | SpringApplication.run(FrequentFlyerApplication.class, args); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter-08/typescript/flying-high/src/entities/PointsSchedule.ts: -------------------------------------------------------------------------------- 1 | import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm'; 2 | import { CabinClass } from './CabinClass'; 3 | 4 | @Entity() 5 | export class PointsSchedule { 6 | 7 | @PrimaryGeneratedColumn() 8 | id: number; 9 | 10 | @Column() 11 | departure: string; 12 | 13 | @Column() 14 | destination: string; 15 | 16 | @Column() 17 | cabinClass: CabinClass 18 | 19 | @Column() 20 | points: number; 21 | } 22 | -------------------------------------------------------------------------------- /chapter-09/java/flying-high/src/main/java/com/examplcom/manning/bddinaction/frequentflyer/FrequentFlyerApplication.java: -------------------------------------------------------------------------------- 1 | package com.examplcom.manning.bddinaction.frequentflyer; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class FrequentFlyerApplication { 8 | public static void main(String[] args) { 9 | SpringApplication.run(FrequentFlyerApplication.class, args); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter-09/typescript/flying-high/src/entities/PointsSchedule.ts: -------------------------------------------------------------------------------- 1 | import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm'; 2 | import { CabinClass } from './CabinClass'; 3 | 4 | @Entity() 5 | export class PointsSchedule { 6 | 7 | @PrimaryGeneratedColumn() 8 | id: number; 9 | 10 | @Column() 11 | departure: string; 12 | 13 | @Column() 14 | destination: string; 15 | 16 | @Column() 17 | cabinClass: CabinClass 18 | 19 | @Column() 20 | points: number; 21 | } 22 | -------------------------------------------------------------------------------- /chapter-10/java/flying-high/readme.md: -------------------------------------------------------------------------------- 1 | Sample code for Chapter 10 of BDD in Action. 2 | 3 | To run these tests locally, you will need to run the Flying High demo application on your machine. You can find this application in the [flying-high-app](https://github.com/bdd-in-action/second-edition/tree/master/flying-high-app) directory. Open this directory in a console window and follow the instructions in the [README](https://github.com/bdd-in-action/second-edition/tree/master/flying-high-app/README.md) file. 4 | 5 | 6 | -------------------------------------------------------------------------------- /chapter-03/java/train-timetables/readme.md: -------------------------------------------------------------------------------- 1 | # BDD In Action Chapter 3 - Train Timetables 2 | 3 | This is the sample project developed in Chapter 3 of BDD in Action - 2nd edition. 4 | 5 | To run this sample code you will need the following: 6 | - Java 17 or higher 7 | - Maven 3.x 8 | 9 | Running with Maven: 10 | ``` 11 | mvn clean verify 12 | ``` 13 | 14 | Running with Gradle: 15 | ``` 16 | gradle clean test 17 | ``` 18 | 19 | In both cases, the reports will be generated in `target/site/serenity/index.html` 20 | -------------------------------------------------------------------------------- /chapter-11/java/page-objects/src/test/resources/features/registration_and_authentication/authentication.feature: -------------------------------------------------------------------------------- 1 | Business Need: Authentication 2 | 3 | Registered Frequent Flyer members can access their account using their email and password 4 | 5 | @webtest 6 | Example: Tracy successfully logs on to the Frequent Flyer app 7 | Given Tracy is a registered Frequency Flyer member 8 | When she logs on with a valid username and password 9 | Then she should be given access to her account 10 | 11 | 12 | -------------------------------------------------------------------------------- /chapter-13/membership-api/src/frequent-flyer/entities/frequent-flyer.entity.ts: -------------------------------------------------------------------------------- 1 | import {MembershipTier} from "./MembershipTier"; 2 | 3 | export class FrequentFlyer { 4 | frequentFlyerNumber: number; 5 | firstName: string; 6 | lastName: string; 7 | title: string; 8 | email: string; 9 | password: string; 10 | address: string; 11 | country: string; 12 | isActivated: boolean = false; 13 | tier: MembershipTier = MembershipTier.Standard; 14 | statusPoints: number = 0; 15 | } 16 | -------------------------------------------------------------------------------- /chapter-08/java/flying-high/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | jpa: 3 | hibernate: 4 | ddl-auto: update 5 | database-platform: org.hibernate.dialect.PostgreSQLDialect 6 | properties: 7 | hibernate: 8 | jdbc: 9 | lob: 10 | non_contextual_creation: true 11 | datasource: 12 | # url: "jdbc:postgresql://localhost:5432/flyinghighdb" 13 | url: "jdbc:tc:postgresql://localhost:5432/flyinghighdb" 14 | username: flyinghigh 15 | password: flyinghigh -------------------------------------------------------------------------------- /chapter-09/java/flying-high/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | jpa: 3 | hibernate: 4 | ddl-auto: update 5 | database-platform: org.hibernate.dialect.PostgreSQLDialect 6 | properties: 7 | hibernate: 8 | jdbc: 9 | lob: 10 | non_contextual_creation: true 11 | datasource: 12 | # url: "jdbc:postgresql://localhost:5432/flyinghighdb" 13 | url: "jdbc:tc:postgresql://localhost:5432/flyinghighdb" 14 | username: flyinghigh 15 | password: flyinghigh -------------------------------------------------------------------------------- /chapter-14/domain/authentication/CompleteAuthenticationForm.ts: -------------------------------------------------------------------------------- 1 | import { Answerable, Task } from '@serenity-js/core'; 2 | import { SpecifyEmailAddress, SpecifyPassword } from './form'; 3 | 4 | export class CompleteAuthenticationForm { 5 | 6 | static using(email: Answerable, password: Answerable): Task { 7 | return Task.where(`#actor completes the authentication form`, 8 | SpecifyEmailAddress(email), 9 | SpecifyPassword(password), 10 | ); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /chapter-15/domain/authentication/CompleteAuthenticationForm.ts: -------------------------------------------------------------------------------- 1 | import { Answerable, Task } from '@serenity-js/core'; 2 | import { SpecifyEmailAddress, SpecifyPassword } from './form'; 3 | 4 | export class CompleteAuthenticationForm { 5 | 6 | static using(email: Answerable, password: Answerable): Task { 7 | return Task.where(`#actor completes the authentication form`, 8 | SpecifyEmailAddress(email), 9 | SpecifyPassword(password), 10 | ); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /flying-high-app/web/src/app/users/profile/profile.component.scss: -------------------------------------------------------------------------------- 1 | .profile-container { 2 | width: 40vw; 3 | margin: 10px auto; 4 | div { 5 | line-height: 30px; 6 | } 7 | .name { 8 | font-size: x-large; 9 | } 10 | .fullname { 11 | font-size: medium; 12 | } 13 | .level { 14 | display: flex; 15 | justify-content: space-between; 16 | } 17 | .button-container { 18 | display: flex; 19 | justify-content: flex-end; 20 | } 21 | } -------------------------------------------------------------------------------- /chapter-11/java/action-classes/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/domain/FlightSearch.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.domain; 2 | 3 | import com.manning.bddinaction.frequentflyer.acceptancetests.domain.persona.TravelClass; 4 | 5 | public record FlightSearch(String from, 6 | String to, 7 | TravelClass travelClass, 8 | Boolean returnTrip) {} 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/src/test/java/com/manning/bddinaction/flyinghigh/CucumberTestSuite.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.flyinghigh; 2 | 3 | import io.cucumber.junit.CucumberOptions; 4 | import net.serenitybdd.cucumber.CucumberWithSerenity; 5 | import org.junit.runner.RunWith; 6 | 7 | @RunWith(CucumberWithSerenity.class) 8 | @CucumberOptions( 9 | plugin = {"pretty"}, 10 | tags = "@current", 11 | features = "src/test/resources/features" 12 | ) 13 | public class CucumberTestSuite {} 14 | -------------------------------------------------------------------------------- /chapter-09/java/flying-high/src/test/resources/testdata/travellers.conf: -------------------------------------------------------------------------------- 1 | Jane: { 2 | firstName: Jane 3 | lastName: Smith 4 | email: "jane@acme.com" 5 | street: 10 Partridge Street 6 | city: Dandenong 7 | state: Victoria 8 | postCode: 3175 9 | country: Australia 10 | telephone: "0123456789" 11 | dateOfBirth: 1981-08-29 12 | } 13 | Terry: { 14 | firstName: Terry 15 | lastName: Traveller 16 | email: "terry@dummy-email.com" 17 | street: 100 Main Street 18 | city: Dublin 19 | country: Ireland 20 | } 21 | -------------------------------------------------------------------------------- /chapter-03/java/train-timetables/src/test/java/manning/bddinaction/unittests/timetables/LocalTimes.java: -------------------------------------------------------------------------------- 1 | package manning.bddinaction.unittests.timetables; 2 | 3 | import java.time.LocalTime; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | import java.util.stream.Collectors; 7 | 8 | public class LocalTimes { 9 | public static List at(String... times) { 10 | return Arrays.stream(times) 11 | .map(LocalTime::parse) 12 | .collect(Collectors.toList()); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /chapter-11/java/page-objects/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/pageobjects/Navigate.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.pageobjects; 2 | 3 | import org.openqa.selenium.WebDriver; 4 | 5 | public class Navigate { 6 | private WebDriver driver; 7 | 8 | public Navigate(WebDriver driver) { 9 | this.driver = driver; 10 | } 11 | 12 | public void toTheLoginPage() { 13 | driver.get("http://flying-high.heroku.org/login"); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /chapter-16/java/flying-high/readme.md: -------------------------------------------------------------------------------- 1 | ## Flying High Acceptance Tests 2 | 3 | This test suite illustrates BDD scenarios using Cucumber and Serenity BDD. 4 | 5 | You can clone and run the application under test from the following repository: 6 | 7 | https://github.com/bdd-in-action/flying-high-app.git 8 | 9 | To run the tests against the local environment, run: 10 | ``` 11 | mvn verify 12 | ``` 13 | 14 | The test results are automatically deployed to the following page: https://bdd-in-action.github.io/flying-high-acceptance-tests 15 | -------------------------------------------------------------------------------- /chapter-16/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/domain/City.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | 6 | @JsonIgnoreProperties(ignoreUnknown = true) 7 | public record City( 8 | @JsonProperty("name") String name, 9 | @JsonProperty("code") String code, 10 | @JsonProperty("region") String region) {} 11 | -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/src/test/java/com/manning/bddinaction/flyinghigh/apis/ConfigurableAPIClient.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.flyinghigh.apis; 2 | 3 | import io.restassured.RestAssured; 4 | import net.serenitybdd.core.Serenity; 5 | 6 | public class ConfigurableAPIClient { 7 | public ConfigurableAPIClient() { 8 | RestAssured.baseURI = Serenity.environmentVariables().getProperty("base.url", 9 | "http://localhost:3000"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/src/test/java/com/manning/bddinaction/flyinghigh/apis/EmailMonitor.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.flyinghigh.apis; 2 | 3 | import net.thucydides.core.annotations.Step; 4 | 5 | public class EmailMonitor { 6 | 7 | EventBusAPI eventBusAPI = new EventBusAPI(); 8 | 9 | @Step("A new account confirmation message was sent to {0}") 10 | public boolean newAccountConfirmationMessageSentTo(String email) { 11 | return eventBusAPI.newFrequentFlyerEventWasPublishedFor(email); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /chapter-14/domain/registration/form/ToggleTermsAndConditions.ts: -------------------------------------------------------------------------------- 1 | import { By, PageElement } from '@serenity-js/web'; 2 | import { Toggle } from '../../ui'; 3 | 4 | const TermsAndConditions = { 5 | checkbox: () => 6 | PageElement.located(By.id('terms')) 7 | .describedAs('Terms & Conditions checkbox'), 8 | } 9 | 10 | export const ToggleTermsAndConditions = { 11 | on: () => 12 | Toggle.on(TermsAndConditions.checkbox()), 13 | 14 | off: () => 15 | Toggle.off(TermsAndConditions.checkbox()), 16 | } 17 | -------------------------------------------------------------------------------- /chapter-15/domain/registration/form/ToggleTermsAndConditions.ts: -------------------------------------------------------------------------------- 1 | import { By, PageElement } from '@serenity-js/web'; 2 | import { Toggle } from '../../ui'; 3 | 4 | const TermsAndConditions = { 5 | checkbox: () => 6 | PageElement.located(By.id('terms')) 7 | .describedAs('Terms & Conditions checkbox'), 8 | } 9 | 10 | export const ToggleTermsAndConditions = { 11 | on: () => 12 | Toggle.on(TermsAndConditions.checkbox()), 13 | 14 | off: () => 15 | Toggle.off(TermsAndConditions.checkbox()), 16 | } 17 | -------------------------------------------------------------------------------- /flying-high-app/web/src/app/app.component.scss: -------------------------------------------------------------------------------- 1 | mat-toolbar { 2 | .logo { 3 | margin-left: -10px; 4 | width: 135px; 5 | } 6 | display: flex; 7 | justify-content: space-between; 8 | span { 9 | cursor: pointer; 10 | } 11 | .operation-section { 12 | display: flex; 13 | justify-content: flex-start; 14 | .email { 15 | font-size: small; 16 | cursor: default; 17 | } 18 | } 19 | .points-earned { 20 | font-weight: bold; 21 | } 22 | } -------------------------------------------------------------------------------- /chapter-09/java/flying-high/src/test/java/com/examplcom/manning/bddinaction/frequentflyer/acceptancetests/tasks/automobile/Vehicle.java: -------------------------------------------------------------------------------- 1 | package com.examplcom.manning.bddinaction.frequentflyer.acceptancetests.tasks.automobile; 2 | 3 | public class Vehicle { 4 | public static Vehicle thatIs(NewOrUsed newOrUsed) { 5 | return new Vehicle(); 6 | } 7 | 8 | public Vehicle ofMake(String make) { 9 | return this; 10 | } 11 | 12 | public Vehicle ofModel(String model) { 13 | return this; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /chapter-14/domain/authentication/SignOut.ts: -------------------------------------------------------------------------------- 1 | import { isPresent, not } from '@serenity-js/assertions'; 2 | import { Task, Wait } from '@serenity-js/core'; 3 | import { Click } from '@serenity-js/web'; 4 | 5 | import { Form } from '../ui'; 6 | 7 | const LogoutButton = () => 8 | Form.buttonCalled('Logout') 9 | 10 | export const SignOut = () => 11 | Task.where(`#actor signs out`, 12 | Wait.until(LogoutButton(), isPresent()), 13 | Click.on(LogoutButton()), 14 | Wait.until(LogoutButton(), not(isPresent())), 15 | ) 16 | -------------------------------------------------------------------------------- /chapter-15/domain/authentication/SignOut.ts: -------------------------------------------------------------------------------- 1 | import { isPresent, not } from '@serenity-js/assertions'; 2 | import { Task, Wait } from '@serenity-js/core'; 3 | import { Click } from '@serenity-js/web'; 4 | 5 | import { Form } from '../ui'; 6 | 7 | const LogoutButton = () => 8 | Form.buttonCalled('Logout') 9 | 10 | export const SignOut = () => 11 | Task.where(`#actor signs out`, 12 | Wait.until(LogoutButton(), isPresent()), 13 | Click.on(LogoutButton()), 14 | Wait.until(LogoutButton(), not(isPresent())), 15 | ) 16 | -------------------------------------------------------------------------------- /chapter-16/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/screenplay/myaccount/StatusPanel.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.screenplay.myaccount; 2 | 3 | import net.serenitybdd.screenplay.targets.Target; 4 | 5 | public class StatusPanel { 6 | public static final Target POINT_BALANCE = Target.the("Point balance").locatedBy("[test-dataid='point-balance']"); 7 | public static final Target STATUS_LEVEL = Target.the("Status level").locatedBy("[test-dataid='status-level']"); 8 | } 9 | -------------------------------------------------------------------------------- /flying-high-app/server/.gitignore: -------------------------------------------------------------------------------- 1 | # compiled output 2 | /node_modules 3 | 4 | # Logs 5 | logs 6 | *.log 7 | npm-debug.log* 8 | yarn-debug.log* 9 | yarn-error.log* 10 | lerna-debug.log* 11 | 12 | # OS 13 | .DS_Store 14 | 15 | # Tests 16 | /coverage 17 | /.nyc_output 18 | 19 | # IDEs and editors 20 | /.idea 21 | .project 22 | .classpath 23 | .c9/ 24 | *.launch 25 | .settings/ 26 | *.sublime-workspace 27 | 28 | # IDE - VSCode 29 | .vscode/* 30 | !.vscode/settings.json 31 | !.vscode/tasks.json 32 | !.vscode/launch.json 33 | !.vscode/extensions.json 34 | -------------------------------------------------------------------------------- /chapter-08/typescript/flying-high/features/support/containers/DatabaseContainer.ts: -------------------------------------------------------------------------------- 1 | import { GenericContainer } from 'testcontainers'; 2 | 3 | export class DatabaseContainer extends GenericContainer { 4 | constructor(config: { username: string, password: string, database: string }) { 5 | super('postgres'); 6 | 7 | this.withEnv('POSTGRES_USER', config.username) 8 | .withEnv('POSTGRES_PASSWORD', config.password) 9 | .withEnv('POSTGRES_DB', config.database) 10 | .withExposedPorts(5432); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /chapter-09/typescript/flying-high/features/support/containers/DatabaseContainer.ts: -------------------------------------------------------------------------------- 1 | import { GenericContainer } from 'testcontainers'; 2 | 3 | export class DatabaseContainer extends GenericContainer { 4 | constructor(config: { username: string, password: string, database: string }) { 5 | super('postgres'); 6 | 7 | this.withEnv('POSTGRES_USER', config.username) 8 | .withEnv('POSTGRES_PASSWORD', config.password) 9 | .withEnv('POSTGRES_DB', config.database) 10 | .withExposedPorts(5432); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /chapter-12/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/AcceptanceTestSuite.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests; 2 | 3 | import io.cucumber.junit.CucumberOptions; 4 | import net.serenitybdd.cucumber.CucumberWithSerenity; 5 | import org.junit.runner.RunWith; 6 | 7 | @RunWith(CucumberWithSerenity.class) 8 | @CucumberOptions( 9 | features = "classpath:features", 10 | glue = "com.manning.bddinaction.frequentflyer.acceptancetests" 11 | ) 12 | public class AcceptanceTestSuite {} 13 | -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/src/test/java/com/manning/bddinaction/flyinghigh/domain/persona/TravellerAccountStatus.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.flyinghigh.domain.persona; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | 5 | /** 6 | * A summary of the frequent flyer account status 7 | */ 8 | @JsonIgnoreProperties(ignoreUnknown = true) 9 | public record TravellerAccountStatus (int statusPoints, 10 | MembershipTier tier, 11 | boolean isActivated) {} 12 | -------------------------------------------------------------------------------- /chapter-08/java/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /chapter-08/java/flying-high/src/main/java/com/examplcom/manning/bddinaction/frequentflyer/services/PastFlightEligibilityService.java: -------------------------------------------------------------------------------- 1 | package com.examplcom.manning.bddinaction.frequentflyer.services; 2 | 3 | import com.examplcom.manning.bddinaction.frequentflyer.domain.FrequentFlyerMember; 4 | import com.examplcom.manning.bddinaction.frequentflyer.domain.PastFlight; 5 | 6 | import java.util.List; 7 | 8 | public interface PastFlightEligibilityService { 9 | List flightsEligibleFor(FrequentFlyerMember member, List submittedFlights); 10 | } 11 | -------------------------------------------------------------------------------- /chapter-09/java/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /chapter-09/java/flying-high/src/main/java/com/examplcom/manning/bddinaction/frequentflyer/services/PastFlightEligibilityService.java: -------------------------------------------------------------------------------- 1 | package com.examplcom.manning.bddinaction.frequentflyer.services; 2 | 3 | import com.examplcom.manning.bddinaction.frequentflyer.domain.FrequentFlyerMember; 4 | import com.examplcom.manning.bddinaction.frequentflyer.domain.PastFlight; 5 | 6 | import java.util.List; 7 | 8 | public interface PastFlightEligibilityService { 9 | List flightsEligibleFor(FrequentFlyerMember member, List submittedFlights); 10 | } 11 | -------------------------------------------------------------------------------- /chapter-10/java/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /chapter-11/java/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /chapter-12/java/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /chapter-12/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/screenplay/login/LoginForm.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.screenplay.login; 2 | 3 | import net.serenitybdd.screenplay.targets.Target; 4 | 5 | class LoginForm { 6 | static final Target EMAIL = Target.the("Email field").locatedBy("#email"); 7 | static final Target PASSWORD = Target.the("Password field").locatedBy("#password"); 8 | static final Target LOGIN_BUTTON = Target.the("Login button").locatedBy("#login-button"); 9 | } 10 | -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/src/test/resources/features/registration/msg.json: -------------------------------------------------------------------------------- 1 | { 2 | "frequentFlyerNumber": 1000036, 3 | "firstName": "Tracy", 4 | "lastName": "Traveler", 5 | "email": "tracy@example.org", 6 | "flightHistory": [ 7 | { 8 | "from": "London", 9 | "to": " Paris", 10 | "date": "2021-12-15" 11 | }, 12 | { 13 | "from": "Paris", 14 | "to": " London", 15 | "date": "2021-12-21" 16 | } 17 | ], 18 | "passport": { 19 | "number": "12345678", 20 | "country": "United Kingdom" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /chapter-16/java/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /chapter-16/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/screenplay/login/LoginForm.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.screenplay.login; 2 | 3 | import net.serenitybdd.screenplay.targets.Target; 4 | 5 | class LoginForm { 6 | static final Target EMAIL = Target.the("Email field").locatedBy("#email"); 7 | static final Target PASSWORD = Target.the("Password field").locatedBy("#password"); 8 | static final Target LOGIN_BUTTON = Target.the("Login button").locatedBy("#login-button"); 9 | } 10 | -------------------------------------------------------------------------------- /chapter-12/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/screenplay/search/SearchResult.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.screenplay.search; 2 | 3 | import com.manning.bddinaction.frequentflyer.acceptancetests.domain.TravelClass; 4 | 5 | public record SearchResult(String departure, 6 | String destination, 7 | String departureTime, 8 | String arrivalTime, 9 | TravelClass travelClass) { 10 | } 11 | -------------------------------------------------------------------------------- /chapter-14/domain/registration/form/ToggleNewsletterSubscription.ts: -------------------------------------------------------------------------------- 1 | import { By, PageElement } from '@serenity-js/web'; 2 | import { Toggle } from '../../ui'; 3 | 4 | const NewsletterSubscription = { 5 | checkbox: () => 6 | PageElement.located(By.id('newsletter')) 7 | .describedAs('newsletter subscription checkbox'), 8 | } 9 | 10 | export const ToggleNewsletterSubscription = { 11 | on: () => 12 | Toggle.on(NewsletterSubscription.checkbox()), 13 | 14 | off: () => 15 | Toggle.off(NewsletterSubscription.checkbox()), 16 | } 17 | -------------------------------------------------------------------------------- /chapter-15/domain/registration/form/ToggleNewsletterSubscription.ts: -------------------------------------------------------------------------------- 1 | import { By, PageElement } from '@serenity-js/web'; 2 | import { Toggle } from '../../ui'; 3 | 4 | const NewsletterSubscription = { 5 | checkbox: () => 6 | PageElement.located(By.id('newsletter')) 7 | .describedAs('newsletter subscription checkbox'), 8 | } 9 | 10 | export const ToggleNewsletterSubscription = { 11 | on: () => 12 | Toggle.on(NewsletterSubscription.checkbox()), 13 | 14 | off: () => 15 | Toggle.off(NewsletterSubscription.checkbox()), 16 | } 17 | -------------------------------------------------------------------------------- /chapter-16/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/AcceptanceTestSuite.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests; 2 | 3 | import io.cucumber.junit.CucumberOptions; 4 | import net.serenitybdd.cucumber.CucumberWithSerenity; 5 | import org.junit.runner.RunWith; 6 | 7 | @RunWith(CucumberWithSerenity.class) 8 | @CucumberOptions( 9 | publish = true, 10 | features = "classpath:features/registration_and_authentication/authentication.feature" 11 | ) 12 | public class AcceptanceTestSuite { 13 | } 14 | -------------------------------------------------------------------------------- /flying-high-app/web/src/app/welcome/welcome.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { AuthService } from '../shared/services/auth.service'; 3 | 4 | @Component({ 5 | selector: 'app-welcome', 6 | templateUrl: './welcome.component.html', 7 | styleUrls: ['./welcome.component.scss'] 8 | }) 9 | export class WelcomeComponent implements OnInit { 10 | 11 | constructor(private authService: AuthService) { } 12 | 13 | ngOnInit(): void { 14 | } 15 | 16 | isLogin() { 17 | return this.authService.isLogin(); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /chapter-07/flying-high/src/test/resources/features/frequent_flyer/spending_points/booking_flights_with_points.feature: -------------------------------------------------------------------------------- 1 | @component:bookings 2 | Feature: Booking flights with Frequent Flyer points 3 | 4 | As a Frequent Flyer program manager 5 | I want members to be able to book flights with their points for themselves and their families 6 | So that they will want to earn more points 7 | 8 | Scenario: Booking an individual flight using points 9 | Scenario: Booking an individual flight using money and points 10 | Scenario: Booking a flight for more than one passenger 11 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/auth/jwt.strategy.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"jwt.strategy.js","sourceRoot":"","sources":["../../src/auth/jwt.strategy.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,+CAAoD;AACpD,+CAAoD;AACpD,2CAA4C;AAC5C,2CAA2C;AAG3C,IAAa,WAAW,GAAxB,MAAa,WAAY,SAAQ,2BAAgB,CAAC,uBAAQ,CAAC;IACvD;QACI,KAAK,CAAC;YACF,cAAc,EAAE,yBAAU,CAAC,2BAA2B,EAAE;YACxD,gBAAgB,EAAE,KAAK;YACvB,WAAW,EAAE,wBAAY,CAAC,MAAM;SACnC,CAAC,CAAC;IACP,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,OAAY;QACvB,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC;IACpC,CAAC;CACJ,CAAA;AAZY,WAAW;IADvB,mBAAU,EAAE;;GACA,WAAW,CAYvB;AAZY,kCAAW"} -------------------------------------------------------------------------------- /flying-high-app/web/src/app/users/users-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | import { ProfileComponent } from './profile/profile.component'; 4 | import { UsersComponent } from './users.component'; 5 | 6 | 7 | const routes: Routes = [ 8 | { path: '', component: UsersComponent }, 9 | { path: 'profile', component: ProfileComponent } 10 | ]; 11 | 12 | @NgModule({ 13 | imports: [RouterModule.forChild(routes)], 14 | exports: [RouterModule] 15 | }) 16 | export class UsersRoutingModule { } 17 | -------------------------------------------------------------------------------- /chapter-16/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/screenplay/matchers/CustomWebElementMatchers.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.screenplay.matchers; 2 | 3 | import net.serenitybdd.core.pages.WebElementState; 4 | import net.serenitybdd.screenplay.matchers.statematchers.IsVisibleMatcher; 5 | import org.hamcrest.Matcher; 6 | 7 | public class CustomWebElementMatchers { 8 | public static Matcher isNotEmpty() { 9 | return new NotEmptyMatcher<>(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter-08/typescript/flying-high/src/controllers/StatusController.ts: -------------------------------------------------------------------------------- 1 | import { NextFunction, Request, Response } from 'express'; 2 | import { getRepository } from 'typeorm'; 3 | import { PointsSchedule } from '../entities/PointsSchedule'; 4 | 5 | export class StatusController { 6 | 7 | public index(request: Request, response: Response, next: NextFunction): void { 8 | getRepository(PointsSchedule).find().then(result => { 9 | console.log('result', result); 10 | response.send('BDD In Action Chapter 7'); 11 | }).catch(next); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /chapter-09/typescript/flying-high/src/controllers/StatusController.ts: -------------------------------------------------------------------------------- 1 | import { NextFunction, Request, Response } from 'express'; 2 | import { getRepository } from 'typeorm'; 3 | import { PointsSchedule } from '../entities/PointsSchedule'; 4 | 5 | export class StatusController { 6 | 7 | public index(request: Request, response: Response, next: NextFunction): void { 8 | getRepository(PointsSchedule).find().then(result => { 9 | console.log('result', result); 10 | response.send('BDD In Action Chapter 7'); 11 | }).catch(next); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /chapter-10/java/flying-high/src/test/resources/testdata/travellers.conf: -------------------------------------------------------------------------------- 1 | Trevor: { 2 | firstName: "Trevor" 3 | lastName: "Traveller" 4 | email: "trevor@traveller.com" 5 | password: "tr3vor" 6 | title:"Mr" 7 | address: "10 Partridge Street, Dandenong" 8 | country: "Australia" 9 | seatPreference: "Aisle" 10 | } 11 | Candy: { 12 | firstName: "Candy" 13 | lastName: "Traveller" 14 | email: "candy@traveller.com" 15 | password: "cand1" 16 | title:"Mrs" 17 | address: "10 Partridge Street, Dandenong" 18 | country: "Australia" 19 | seatPreference: "Window" 20 | } 21 | -------------------------------------------------------------------------------- /chapter-08/java/flying-high/src/test/java/com/examplcom/manning/bddinaction/frequentflyer/acceptancetests/AcceptanceTestSuite.java: -------------------------------------------------------------------------------- 1 | package com.examplcom.manning.bddinaction.frequentflyer.acceptancetests; 2 | 3 | import io.cucumber.junit.CucumberOptions; 4 | import net.serenitybdd.cucumber.CucumberWithSerenity; 5 | import org.junit.runner.RunWith; 6 | import org.springframework.boot.test.context.SpringBootTest; 7 | 8 | @RunWith(CucumberWithSerenity.class) 9 | @CucumberOptions( 10 | features = "classpath:features" 11 | ) 12 | @SpringBootTest 13 | public class AcceptanceTestSuite {} 14 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/users/interface/users.interface.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"users.interface.js","sourceRoot":"","sources":["../../../src/users/interface/users.interface.ts"],"names":[],"mappings":";;;AAeA,IAAY,UAKX;AALD,WAAY,UAAU;IAClB,uBAAS,CAAA;IACT,uBAAS,CAAA;IACT,uBAAS,CAAA;IACT,yBAAW,CAAA;AACf,CAAC,EALW,UAAU,GAAV,kBAAU,KAAV,kBAAU,QAKrB;AAED,IAAY,eAGX;AAHD,WAAY,eAAe;IACvB,kCAAe,CAAA;IACf,oCAAiB,CAAA;AACrB,CAAC,EAHW,eAAe,GAAf,uBAAe,KAAf,uBAAe,QAG1B;AAED,IAAY,UAKX;AALD,WAAY,UAAU;IAClB,mCAAqB,CAAA;IACrB,+BAAiB,CAAA;IACjB,+BAAiB,CAAA;IACjB,2BAAa,CAAA;AACjB,CAAC,EALW,UAAU,GAAV,kBAAU,KAAV,kBAAU,QAKrB"} -------------------------------------------------------------------------------- /chapter-09/java/flying-high/src/test/resources/features/frequentflyer/joining_the_frequent_flyer_programme.feature: -------------------------------------------------------------------------------- 1 | Feature: Joining the Frequent Flyer Programme 2 | 3 | In order to encourage more regular travellers to fly more often with us 4 | As an airline manager 5 | I would like travellers to join our loyalty programme 6 | 7 | Scenario: Registering online for a new Frequent Flyer account 8 | Given Jane is not a Frequent Flyer member 9 | When Jane registers for a new account 10 | Then she should be sent a confirmation email 11 | And she should receive 500 bonus points 12 | 13 | -------------------------------------------------------------------------------- /chapter-11/java/action-classes/src/test/resources/features/registration_and_authentication/registering_as_a_new_frequent_flyer.feature: -------------------------------------------------------------------------------- 1 | Business Need: Registering as a new Frequent Flyer 2 | 3 | New Frequent Flyer members need to register to book a flight. 4 | 5 | Rule: Customers must register to be able to use the Frequent Flyer members area 6 | Example: Tracy registers as a Frequent Flyer member 7 | Given Tracy does not have a Frequent Flyer account 8 | When Tracy registers as a Frequent Flyer member 9 | Then he should be able to log on to the Frequent Flyer application 10 | -------------------------------------------------------------------------------- /chapter-09/java/flying-high/src/test/java/com/examplcom/manning/bddinaction/frequentflyer/acceptancetests/tasks/registration/EnterRegistrationDetails.java: -------------------------------------------------------------------------------- 1 | package com.examplcom.manning.bddinaction.frequentflyer.acceptancetests.tasks.registration; 2 | 3 | import com.examplcom.manning.bddinaction.frequentflyer.acceptancetests.model.Traveller; 4 | import net.serenitybdd.screenplay.Performable; 5 | import net.serenitybdd.screenplay.Task; 6 | 7 | public class EnterRegistrationDetails { 8 | public static Performable using(Traveller travellerDetails) { 9 | return Task.where(""); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /chapter-13/membership-api/src/events/eventbus.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | import {EventMessage} from "./event-message"; 3 | 4 | @Injectable() 5 | export class EventBusService { 6 | eventLog: EventMessage[] = []; 7 | 8 | publish(event) { 9 | this.eventLog.push(event) 10 | } 11 | 12 | findEventMatching(eventType: string, fieldname: string, value: string) { 13 | return this.eventLog.find(event => event.type == eventType && event.data[fieldname] == value); 14 | } 15 | 16 | findAll() { 17 | return this.eventLog; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /flying-high-app/web/src/app/booking/booking.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Order number: {{booking.orderNumber}}

4 | {{ booking.departureDate | date: 'yyyy-MM-dd, h:mm a' }} 5 |

Departure: {{ booking.departure.name }}

6 | {{ booking.arrivalDate | date: 'yyyy-MM-dd, h:mm a' }} 7 |

Arrival: {{booking.destination.name}}

8 |

Class: {{ booking.class }}

9 |
10 |

No bookings yet

11 |
-------------------------------------------------------------------------------- /flying-high-app/web/src/app/register/register.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { AuthService } from '../shared/services/auth.service'; 3 | import { UserDto } from '../users/user.interface'; 4 | 5 | @Component({ 6 | selector: 'app-register', 7 | templateUrl: './register.component.html', 8 | styleUrls: ['./register.component.scss'] 9 | }) 10 | export class RegisterComponent { 11 | 12 | 13 | constructor( 14 | private authService: AuthService 15 | ) { } 16 | 17 | async register(user: UserDto) { 18 | this.authService.register(user); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /chapter-07/flying-high/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /flying-high-app/web/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/out-tsc", 6 | "sourceMap": true, 7 | "declaration": false, 8 | "downlevelIteration": true, 9 | "experimentalDecorators": true, 10 | "module": "esnext", 11 | "moduleResolution": "node", 12 | "importHelpers": true, 13 | "target": "es2015", 14 | "lib": [ 15 | "es2018", 16 | "dom" 17 | ] 18 | }, 19 | "angularCompilerOptions": { 20 | "fullTemplateTypeCheck": true, 21 | "strictInjectionParameters": true 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /chapter-02/java/online-banking/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /chapter-14/features/actors.steps.ts: -------------------------------------------------------------------------------- 1 | import { defineParameterType, setDefaultTimeout } from '@cucumber/cucumber'; 2 | import { actorCalled, actorInTheSpotlight, Duration } from '@serenity-js/core'; 3 | 4 | setDefaultTimeout(Duration.ofSeconds(30).inMilliseconds()); 5 | 6 | defineParameterType({ 7 | name: 'actor', 8 | regexp: /[A-Z][a-z]+/, 9 | transformer: (name: string) => 10 | actorCalled(name), 11 | }); 12 | 13 | defineParameterType({ 14 | name: 'pronoun', 15 | regexp: /he|she|they|his|her|their/, 16 | transformer() { 17 | return actorInTheSpotlight(); 18 | }, 19 | }); 20 | -------------------------------------------------------------------------------- /chapter-15/features/actors.steps.ts: -------------------------------------------------------------------------------- 1 | import { defineParameterType, setDefaultTimeout } from '@cucumber/cucumber'; 2 | import { actorCalled, actorInTheSpotlight, Duration } from '@serenity-js/core'; 3 | 4 | setDefaultTimeout(Duration.ofSeconds(30).inMilliseconds()); 5 | 6 | defineParameterType({ 7 | name: 'actor', 8 | regexp: /[A-Z][a-z]+/, 9 | transformer: (name: string) => 10 | actorCalled(name), 11 | }); 12 | 13 | defineParameterType({ 14 | name: 'pronoun', 15 | regexp: /he|she|they|his|her|their/, 16 | transformer() { 17 | return actorInTheSpotlight(); 18 | }, 19 | }); 20 | -------------------------------------------------------------------------------- /chapter-11/java/action-classes/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/domain/FrequentFlyer.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.domain; 2 | 3 | public enum FrequentFlyer { 4 | Tracy("tracy@flyinghigh.com", "trac3"); 5 | 6 | public final String email; 7 | public final String password; 8 | 9 | FrequentFlyer(String email, String password) { 10 | this.email = email; 11 | this.password = password; 12 | } 13 | 14 | @Override 15 | public String toString() { 16 | return this.name() + " (" + email +")"; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/app.module.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"app.module.js","sourceRoot":"","sources":["../src/app.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAoD;AACpD,qDAAiD;AACjD,uDAAyD;AACzD,+BAA4B;AAC5B,0DAAsD;AACtD,gEAA4D;AAC5D,6DAAyD;AACzD,uDAAmD;AACnD,oDAAgD;AAChD,+CAA2C;AAiB3C,IAAa,SAAS,GAAtB,MAAa,SAAS;CAAI,CAAA;AAAb,SAAS;IAfrB,eAAM,CAAC;QACN,OAAO,EAAE;YACP,mBAAU;YACV,gCAAiB,CAAC,OAAO,CAAC;gBACxB,QAAQ,EAAE,WAAI,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC;aACvC,CAAC;YACF,4BAAY;YACZ,gCAAc;YACd,8BAAa;YACb,0BAAW;YACX,wBAAU;SACX;QACD,WAAW,EAAE,CAAC,8BAAa,CAAC;QAC5B,SAAS,EAAE,CAAC,wBAAU,CAAC;KACxB,CAAC;GACW,SAAS,CAAI;AAAb,8BAAS"} -------------------------------------------------------------------------------- /flying-high-app/server/dist/flights/dto/search-flight.dto.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"search-flight.dto.js","sourceRoot":"","sources":["../../../src/flights/dto/search-flight.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6CAAmE;AAEnE,MAAa,eAAe;CAW3B;AATG;IADC,qBAAW,CAAC,EAAE,WAAW,EAAE,uDAAuD,EAAE,CAAC;;kDACpE;AAElB;IADC,qBAAW,CAAC,EAAE,WAAW,EAAE,yDAAyD,EAAE,CAAC;;oDACpE;AAEpB;IADC,qBAAW,CAAC,EAAE,WAAW,EAAE,iCAAiC,EAAE,CAAC;8BACjD,IAAI;sDAAC;AAEpB;IADC,6BAAmB,CAAC,EAAE,WAAW,EAAE,oFAAoF,EAAE,CAAC;8BAC/G,IAAI;mDAAC;AAEjB;IADC,qBAAW,CAAC,EAAE,IAAI,EAAE,CAAC,SAAS,EAAE,iBAAiB,EAAE,UAAU,CAAC,EAAE,WAAW,EAAE,qDAAqD,EAAE,CAAC;;8CACpF;AAVtD,0CAWC"} -------------------------------------------------------------------------------- /chapter-13/membership-api/src/token/token.ts: -------------------------------------------------------------------------------- 1 | export class Token { 2 | created: Date = new Date(); 3 | email: string; 4 | frequentFlyerNumber: number; 5 | hash: string; 6 | spent: boolean = false; 7 | 8 | constructor() { 9 | this.hash = require('crypto') 10 | .createHash('sha256') 11 | .update(`{"email": "$email", "frequentFlyerNumber":"$frequentFlyerNumber", "created":"$created"`) 12 | .digest('hex'); 13 | } 14 | 15 | isExpired = function() { 16 | return ((new Date().valueOf() - this.created.valueOf()) / (1000*60*60*24)) > 1; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /flying-high-app/web/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Flying High Frequent Flyer App v0.0.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /chapter-11/java/page-objects/src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /chapter-16/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/screenplay/search/BookTheFlight.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.screenplay.search; 2 | 3 | import net.serenitybdd.screenplay.Performable; 4 | import net.serenitybdd.screenplay.Task; 5 | import net.serenitybdd.screenplay.actions.Click; 6 | 7 | public class BookTheFlight { 8 | public static Performable thatIsFirstInTheList() { 9 | return Task.where("{0} books the first available flight", 10 | Click.on(SearchResultsList.BOOK_FLIGHT_BUTTONS) 11 | ); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /chapter-16/java/flying-high/src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /chapter-11/java/action-classes/src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /chapter-11/java/page-objects/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/pageobjects/CurrentUserPanel.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.pageobjects; 2 | 3 | import org.openqa.selenium.By; 4 | import org.openqa.selenium.WebDriver; 5 | 6 | public class CurrentUserPanel { 7 | 8 | private WebDriver driver; 9 | 10 | public CurrentUserPanel(WebDriver driver) { this.driver = driver; } 11 | 12 | private static final By CURRENT_USER = By.id("current-user"); 13 | 14 | public String email() { 15 | return driver.findElement(CURRENT_USER).getText(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /chapter-16/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/domain/FlightBooking.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | public record FlightBooking ( 6 | @JsonProperty("departure") City departure, 7 | @JsonProperty("destination") City destination, 8 | @JsonProperty("departureDate") String departureDate, 9 | @JsonProperty("arrivalDate") String arrivalDate, 10 | @JsonProperty("class") String travelClass, 11 | @JsonProperty("email") String email) { 12 | } 13 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/shared/shared.module.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"shared.module.js","sourceRoot":"","sources":["../../src/shared/shared.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAoD;AACpD,qCAAwC;AACxC,iDAAkD;AAClD,0DAAsD;AACtD,kEAA8D;AAC9D,gEAA4D;AAC5D,4DAAwD;AAWxD,IAAa,YAAY,GAAzB,MAAa,YAAY;CAAI,CAAA;AAAhB,YAAY;IATxB,eAAM,CAAC;QACJ,SAAS,EAAE,CAAC,gCAAc,EAAE,kCAAe,EAAE,4BAAY,EAAE,0BAAW,CAAC;QACvE,OAAO,EAAE,CAAC,mBAAU;YAChB,eAAS,CAAC,QAAQ,CAAC;gBACjB,MAAM,EAAE,wBAAY,CAAC,MAAM;gBAC3B,WAAW,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE;aAClC,CAAC,EAAE;QACR,OAAO,EAAE,CAAC,gCAAc,EAAE,kCAAe,EAAE,4BAAY,EAAE,0BAAW,CAAC;KACxE,CAAC;GACW,YAAY,CAAI;AAAhB,oCAAY"} -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/src/test/java/com/manning/bddinaction/flyinghigh/ui/screenplay/search/SearchResultsList.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.flyinghigh.ui.screenplay.search; 2 | 3 | import net.serenitybdd.screenplay.targets.Target; 4 | import org.openqa.selenium.By; 5 | 6 | public class SearchResultsList { 7 | 8 | public static final Target SEARCH_RESULTS = Target.the("Search results").locatedBy(".flight-container"); 9 | public static final Target BOOK_FLIGHT_BUTTONS = Target.the("From field") 10 | .located(By.cssSelector("[data-testid='book-flight']")); 11 | } 12 | -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/src/test/java/com/manning/bddinaction/flyinghigh/ui/screenplay/navigation/MenuBar.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.flyinghigh.ui.screenplay.navigation; 2 | 3 | import net.serenitybdd.screenplay.targets.Target; 4 | 5 | class MenuBar { 6 | private static final Target BUTTON = Target.the("{0} button").locatedBy("//button[contains(.,'{0}')]"); 7 | 8 | static final Target LOGIN_BUTTON = BUTTON.of("Login"); 9 | static final Target MY_ACCOUNT = BUTTON.of("My Account"); 10 | static final Target REGISTER = BUTTON.of("Register"); 11 | static final Target BOOK_FLIGHTS = BUTTON.of("Book Flights"); 12 | } 13 | -------------------------------------------------------------------------------- /flying-high-app/web/src/app/search/flight.interface.ts: -------------------------------------------------------------------------------- 1 | import { City } from "./city.interface"; 2 | 3 | export interface Flight { 4 | departure: City; 5 | destination: City; 6 | departureDate: Date; 7 | returnDate?: Date; 8 | arrivalDate?: Date; 9 | class: 'Economy' | 'Premium Economy' | 'Business'; 10 | price?: number; 11 | email?: string; 12 | } 13 | 14 | export interface FlightResource { 15 | departureTime: Date; 16 | arrivalTime: Date; 17 | duration: string; 18 | departure: City; 19 | destination: City; 20 | class: 'Economy' | 'Premium Economy' | 'Business'; 21 | price?: number; 22 | } 23 | -------------------------------------------------------------------------------- /chapter-08/java/flying-high/src/main/java/com/examplcom/manning/bddinaction/frequentflyer/repositories/RecordedFlightRepository.java: -------------------------------------------------------------------------------- 1 | package com.examplcom.manning.bddinaction.frequentflyer.repositories; 2 | 3 | import com.examplcom.manning.bddinaction.frequentflyer.domain.FrequentFlyerMember; 4 | import com.examplcom.manning.bddinaction.frequentflyer.domain.RecordedFlight; 5 | import org.springframework.data.repository.CrudRepository; 6 | 7 | import java.util.Collection; 8 | 9 | public interface RecordedFlightRepository extends CrudRepository { 10 | Collection findByMember(FrequentFlyerMember member); 11 | } 12 | -------------------------------------------------------------------------------- /chapter-08/typescript/flying-high/src/bootstrap.ts: -------------------------------------------------------------------------------- 1 | import { FlyingHighApp } from './FlyingHighApp' 2 | import dbConfig = require('../config/db.config') 3 | import { ensure, isNumber, isString, isOneOf } from 'tiny-types'; 4 | 5 | export = function (port: number, host: string, mode: string): void { 6 | ensure('port', port, isNumber()) 7 | ensure('host', host, isString()) 8 | ensure('mode', mode, isOneOf('development', 'test', 'production')) 9 | 10 | const app = new FlyingHighApp(dbConfig[mode]()); 11 | 12 | app.listen(port, host, () => { 13 | console.log(`Flying High listening on ${ host } port ${ port }`) 14 | }) 15 | } 16 | -------------------------------------------------------------------------------- /chapter-09/java/flying-high/src/main/java/com/examplcom/manning/bddinaction/frequentflyer/repositories/RecordedFlightRepository.java: -------------------------------------------------------------------------------- 1 | package com.examplcom.manning.bddinaction.frequentflyer.repositories; 2 | 3 | import com.examplcom.manning.bddinaction.frequentflyer.domain.FrequentFlyerMember; 4 | import com.examplcom.manning.bddinaction.frequentflyer.domain.RecordedFlight; 5 | import org.springframework.data.repository.CrudRepository; 6 | 7 | import java.util.Collection; 8 | 9 | public interface RecordedFlightRepository extends CrudRepository { 10 | Collection findByMember(FrequentFlyerMember member); 11 | } 12 | -------------------------------------------------------------------------------- /chapter-09/typescript/flying-high/src/bootstrap.ts: -------------------------------------------------------------------------------- 1 | import { FlyingHighApp } from './FlyingHighApp' 2 | import dbConfig = require('../config/db.config') 3 | import { ensure, isNumber, isString, isOneOf } from 'tiny-types'; 4 | 5 | export = function (port: number, host: string, mode: string): void { 6 | ensure('port', port, isNumber()) 7 | ensure('host', host, isString()) 8 | ensure('mode', mode, isOneOf('development', 'test', 'production')) 9 | 10 | const app = new FlyingHighApp(dbConfig[mode]()); 11 | 12 | app.listen(port, host, () => { 13 | console.log(`Flying High listening on ${ host } port ${ port }`) 14 | }) 15 | } 16 | -------------------------------------------------------------------------------- /chapter-11/java/page-objects/readme.md: -------------------------------------------------------------------------------- 1 | ## Flying High Acceptance Tests - Page Objects 2 | 3 | Sample code for Chapter 11 of BDD in Action. 4 | 5 | To run these tests locally, you will need to run the Flying High demo application on your machine. 6 | You can find this application in the [flying-high-app](https://github.com/bdd-in-action/second-edition/tree/master/flying-high-app) directory. 7 | Open this directory in a console window and follow the instructions in the [README](https://github.com/bdd-in-action/second-edition/tree/master/flying-high-app/README.md) file. 8 | 9 | To run the tests themselves, run: 10 | ``` 11 | mvn verify 12 | ``` 13 | 14 | -------------------------------------------------------------------------------- /flying-high-app/cypress/integration/pageobjects/WelcomePage.js: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | const WELCOME_MESSAGE = '.welcome-message' 4 | const WELCOME_CONTAINER = '.welcome-container' 5 | 6 | export class WelcomePage { 7 | open() { 8 | // cy.visit('https://bdd-flyer.herokuapp.com/') 9 | cy.visit('http://localhost:3000') 10 | } 11 | 12 | welcomeMessage() { 13 | return cy.get(WELCOME_MESSAGE) 14 | } 15 | 16 | loginLink() { 17 | return cy.contains(WELCOME_CONTAINER,'Login') 18 | } 19 | 20 | registerLink() { 21 | return cy.contains(WELCOME_CONTAINER,'Register') 22 | } 23 | } -------------------------------------------------------------------------------- /chapter-12/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/screenplay/account/Account.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.screenplay.account; 2 | 3 | import com.manning.bddinaction.frequentflyer.acceptancetests.domain.UserLevel; 4 | import net.serenitybdd.screenplay.Question; 5 | import net.serenitybdd.screenplay.questions.Text; 6 | 7 | public class Account { 8 | public static Question STATUS_LEVEL = Text.of("[test-dataid='status-level']").asEnum(UserLevel.class); 9 | public static Question POINT_BALANCE = Text.of("[test-dataid='point-balance']").asInteger(); 10 | } 11 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/main.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";;AAAA,uCAA2C;AAC3C,6CAAiE;AACjE,6CAAyC;AAEzC,KAAK,UAAU,SAAS;IACtB,MAAM,GAAG,GAAG,MAAM,kBAAW,CAAC,MAAM,CAAC,sBAAS,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,IAAI,yBAAe,EAAE;SAClC,aAAa,EAAE;SACf,QAAQ,CAAC,mCAAmC,CAAC;SAC7C,cAAc,CAAC;;;;;KAKf,CAAC;SACD,UAAU,CAAC,KAAK,CAAC;SACjB,KAAK,EAAE,CAAC;IACX,MAAM,QAAQ,GAAG,uBAAa,CAAC,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC5D,uBAAa,CAAC,KAAK,CAAC,SAAS,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;IAC9C,GAAG,CAAC,UAAU,EAAE,CAAC;IACjB,MAAM,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC;AAC7C,CAAC;AACD,SAAS,EAAE,CAAC"} -------------------------------------------------------------------------------- /flying-high-app/web/src/app/shared/services/flight.service.ts: -------------------------------------------------------------------------------- 1 | import { HttpClient } from '@angular/common/http'; 2 | import { Injectable } from '@angular/core'; 3 | import { Observable } from 'rxjs'; 4 | import { Flight } from 'src/app/search/flight.interface'; 5 | import { environment } from 'src/environments/environment'; 6 | 7 | @Injectable({ 8 | providedIn: 'root' 9 | }) 10 | export class FlightService { 11 | 12 | url = `${environment.API_URL}/api/flights`; 13 | 14 | constructor(private http: HttpClient) { } 15 | 16 | createFlight(flight: Flight): Observable { 17 | return this.http.post(this.url, flight); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /chapter-13/membership-api/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "declaration": true, 5 | "removeComments": true, 6 | "emitDecoratorMetadata": true, 7 | "experimentalDecorators": true, 8 | "allowSyntheticDefaultImports": true, 9 | "target": "es2017", 10 | "sourceMap": true, 11 | "outDir": "./dist", 12 | "baseUrl": "./", 13 | "incremental": true, 14 | "skipLibCheck": true, 15 | "strictNullChecks": false, 16 | "noImplicitAny": false, 17 | "strictBindCallApply": false, 18 | "forceConsistentCasingInFileNames": false, 19 | "noFallthroughCasesInSwitch": false 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /chapter-16/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/screenplay/search/SearchResultsList.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.screenplay.search; 2 | 3 | import net.serenitybdd.screenplay.targets.Target; 4 | import org.openqa.selenium.By; 5 | 6 | public class SearchResultsList { 7 | 8 | public static final Target SEARCH_RESULTS = Target.the("Search results").locatedBy(".flight-container"); 9 | public static final Target BOOK_FLIGHT_BUTTONS = Target.the("From field") 10 | .located(By.cssSelector("[data-testid='book-flight']")); 11 | } -------------------------------------------------------------------------------- /chapter-11/java/action-classes/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/actions/authentication/Login.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.actions.authentication; 2 | 3 | import com.manning.bddinaction.frequentflyer.acceptancetests.domain.FrequentFlyer; 4 | import net.thucydides.core.annotations.Step; 5 | 6 | public class Login { 7 | 8 | LoginForm loginForm; 9 | 10 | @Step("Login as {0}") 11 | public void as(FrequentFlyer frequentFlyer) { 12 | loginForm.open(); 13 | loginForm.enterCredentials(frequentFlyer.email, frequentFlyer.password); 14 | loginForm.submit(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /chapter-11/java/action-classes/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/actions/search/FieldsWithErrors.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.actions.search; 2 | 3 | import net.serenitybdd.core.steps.UIInteractionSteps; 4 | 5 | import java.util.List; 6 | import java.util.stream.Collectors; 7 | 8 | public class FieldsWithErrors extends UIInteractionSteps { 9 | public List currentlyVisible() { 10 | return findAll(SearchForm.MISSING_FIELD_LABELS).stream() 11 | .map(label -> label.getText().trim().replace(" *", "")) 12 | .collect(Collectors.toList()); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /chapter-12/java/flying-high/src/test/java/com/manning/bddinaction/frequentflyer/acceptancetests/screenplay/search/SearchResultsList.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.frequentflyer.acceptancetests.screenplay.search; 2 | 3 | import net.serenitybdd.screenplay.targets.Target; 4 | import org.openqa.selenium.By; 5 | 6 | public class SearchResultsList { 7 | 8 | public static final Target SEARCH_RESULTS = Target.the("Search results").locatedBy(".flight-container"); 9 | public static final Target BOOK_FLIGHT_BUTTONS = Target.the("From field") 10 | .located(By.cssSelector("[data-testid='book-flight']")); 11 | } 12 | -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/src/test/java/com/manning/bddinaction/flyinghigh/apis/TokenAPI.java: -------------------------------------------------------------------------------- 1 | package com.manning.bddinaction.flyinghigh.apis; 2 | 3 | import io.restassured.RestAssured; 4 | import io.restassured.http.ContentType; 5 | 6 | public class TokenAPI extends ConfigurableAPIClient { 7 | /** 8 | * Look up the unique token used to validate the email for a given frequent flyer number. 9 | */ 10 | public String getEmailToken(String frequentFlyerNumber) { 11 | return RestAssured. 12 | given().pathParam("id", frequentFlyerNumber) 13 | .get("/tokens/frequent-flyer/{id}").getBody().asString(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /chapter-08/typescript/flying-high/src/entities/FrequentFlyerMember.ts: -------------------------------------------------------------------------------- 1 | import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; 2 | import { FrequentFlyerStatus } from './FrequentFlyerStatus'; 3 | 4 | @Entity() 5 | export class FrequentFlyerMember { 6 | 7 | @PrimaryGeneratedColumn() 8 | id: number; 9 | 10 | @Column() 11 | name: string; 12 | 13 | @Column() 14 | joinedAt: Date; 15 | 16 | @Column() 17 | initialPoints: number; 18 | 19 | @Column() 20 | status: FrequentFlyerStatus; 21 | 22 | constructor(frequentFlyerMember: Partial) { 23 | Object.assign(this, frequentFlyerMember); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /chapter-09/typescript/flying-high/src/entities/FrequentFlyerMember.ts: -------------------------------------------------------------------------------- 1 | import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; 2 | import { FrequentFlyerStatus } from './FrequentFlyerStatus'; 3 | 4 | @Entity() 5 | export class FrequentFlyerMember { 6 | 7 | @PrimaryGeneratedColumn() 8 | id: number; 9 | 10 | @Column() 11 | name: string; 12 | 13 | @Column() 14 | joinedAt: Date; 15 | 16 | @Column() 17 | initialPoints: number; 18 | 19 | @Column() 20 | status: FrequentFlyerStatus; 21 | 22 | constructor(frequentFlyerMember: Partial) { 23 | Object.assign(this, frequentFlyerMember); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/auth/local.strategy.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"local.strategy.js","sourceRoot":"","sources":["../../src/auth/local.strategy.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,mDAA0C;AAC1C,+CAAoD;AACpD,2CAAmE;AACnE,kEAA8D;AAG9D,IAAa,aAAa,GAA1B,MAAa,aAAc,SAAQ,2BAAgB,CAAC,yBAAQ,CAAC;IAC3D,YAAoB,WAAwB;QAC1C,KAAK,CAAC,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,CAAC;QADhB,gBAAW,GAAX,WAAW,CAAa;IAE5C,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,KAAa,EAAE,QAAgB;QAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QAC5D,IAAI,CAAC,IAAI,EAAE;YACT,MAAM,IAAI,8BAAqB,EAAE,CAAC;SACnC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAA;AAZY,aAAa;IADzB,mBAAU,EAAE;qCAEsB,0BAAW;GADjC,aAAa,CAYzB;AAZY,sCAAa"} -------------------------------------------------------------------------------- /flying-high-app/server/src/auth/jwt.strategy.ts: -------------------------------------------------------------------------------- 1 | import { ExtractJwt, Strategy } from 'passport-jwt'; 2 | import { PassportStrategy } from '@nestjs/passport'; 3 | import { Injectable } from '@nestjs/common'; 4 | import { jwtConstants } from './constants'; 5 | 6 | @Injectable() 7 | export class JwtStrategy extends PassportStrategy(Strategy) { 8 | constructor() { 9 | super({ 10 | jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), 11 | ignoreExpiration: false, 12 | secretOrKey: jwtConstants.secret, 13 | }); 14 | } 15 | 16 | async validate(payload: any) { 17 | return { email: payload.email }; 18 | } 19 | } -------------------------------------------------------------------------------- /.github/workflows/chapter-02.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven 3 | 4 | name: Chapter 2 5 | 6 | on: 7 | push: 8 | branches: [ master ] 9 | pull_request: 10 | branches: [ master ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Set up JDK 1.8 20 | uses: actions/setup-java@v1 21 | with: 22 | java-version: 1.8 23 | - name: Build with Maven 24 | run: cd chapter-02/java/online-banking && mvn -B verify 25 | -------------------------------------------------------------------------------- /.github/workflows/chapter-03.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven 3 | 4 | name: Chapter 3 5 | 6 | on: 7 | push: 8 | branches: [ master ] 9 | pull_request: 10 | branches: [ master ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Set up JDK 9 20 | uses: actions/setup-java@v1 21 | with: 22 | java-version: 12 23 | - name: Build with Maven 24 | run: cd chapter-03/java/train-timetables && mvn -B verify 25 | -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/.github/workflows/gradle.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven 3 | 4 | name: Gradle build 5 | 6 | on: 7 | push: 8 | branches: [ master ] 9 | pull_request: 10 | branches: [ master ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Set up JDK 1.8 20 | uses: actions/setup-java@v1 21 | with: 22 | java-version: 1.8 23 | - name: Build with Gradle 24 | run: gradle clean test 25 | -------------------------------------------------------------------------------- /flying-high-app/web/src/app/shared/services/bookings.service.ts: -------------------------------------------------------------------------------- 1 | import { HttpClient } from '@angular/common/http'; 2 | import { Injectable } from '@angular/core'; 3 | import { Observable } from 'rxjs'; 4 | import { Flight } from 'src/app/search/flight.interface'; 5 | import { environment } from 'src/environments/environment'; 6 | 7 | @Injectable({ 8 | providedIn: 'root' 9 | }) 10 | export class BookingsService { 11 | 12 | url = `${environment.API_URL}/api/bookings`; 13 | 14 | constructor(private http: HttpClient) { } 15 | 16 | getUserBookings(email: string): Observable { 17 | return this.http.get(`${this.url}?email=${email}`); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /chapter-13/api-acceptance-tests/.github/workflows/maven.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven 3 | 4 | name: Maven Build 5 | 6 | on: 7 | push: 8 | branches: [ master ] 9 | pull_request: 10 | branches: [ master ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Set up JDK 1.8 20 | uses: actions/setup-java@v1 21 | with: 22 | java-version: 1.8 23 | - name: Build with Maven 24 | run: mvn -B verify --file pom.xml 25 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/bookings/bookings.controller.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"bookings.controller.js","sourceRoot":"","sources":["../../src/bookings/bookings.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAmE;AACnE,6CAA0D;AAC1D,2DAAuD;AACvD,wEAAoE;AAIpE,IAAa,kBAAkB,GAA/B,MAAa,kBAAkB;IAE3B,YAAoB,aAA6B;QAA7B,kBAAa,GAAb,aAAa,CAAgB;IAAI,CAAC;IAQtD,eAAe,CAAiB,KAAa;QACzC,OAAO,IAAI,CAAC,aAAa,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;IACvD,CAAC;CACJ,CAAA;AAHG;IANC,kBAAS,CAAC,6BAAY,CAAC;IACvB,YAAG,EAAE;IACL,kBAAQ,CAAC;QACN,IAAI,EAAE,OAAO;QACb,WAAW,EAAE,4BAA4B;KAC5C,CAAC;IACe,WAAA,cAAK,CAAC,OAAO,CAAC,CAAA;;;;yDAE9B;AAZQ,kBAAkB;IAF9B,uBAAa,EAAE;IACf,mBAAU,CAAC,cAAc,CAAC;qCAGY,gCAAc;GAFxC,kBAAkB,CAa9B;AAbY,gDAAkB"} -------------------------------------------------------------------------------- /chapter-08/java/flying-high/src/main/java/com/examplcom/manning/bddinaction/frequentflyer/repositories/FrequentFlyerMemberRepository.java: -------------------------------------------------------------------------------- 1 | package com.examplcom.manning.bddinaction.frequentflyer.repositories; 2 | 3 | import com.examplcom.manning.bddinaction.frequentflyer.domain.FrequentFlyerMember; 4 | import com.examplcom.manning.bddinaction.frequentflyer.domain.PointsSchedule; 5 | import org.springframework.data.jpa.repository.Query; 6 | import org.springframework.data.repository.CrudRepository; 7 | 8 | import java.util.Collection; 9 | 10 | public interface FrequentFlyerMemberRepository extends CrudRepository { 11 | FrequentFlyerMember findByName(String name); 12 | } 13 | -------------------------------------------------------------------------------- /chapter-09/java/flying-high/src/main/java/com/examplcom/manning/bddinaction/frequentflyer/repositories/FrequentFlyerMemberRepository.java: -------------------------------------------------------------------------------- 1 | package com.examplcom.manning.bddinaction.frequentflyer.repositories; 2 | 3 | import com.examplcom.manning.bddinaction.frequentflyer.domain.FrequentFlyerMember; 4 | import com.examplcom.manning.bddinaction.frequentflyer.domain.PointsSchedule; 5 | import org.springframework.data.jpa.repository.Query; 6 | import org.springframework.data.repository.CrudRepository; 7 | 8 | import java.util.Collection; 9 | 10 | public interface FrequentFlyerMemberRepository extends CrudRepository { 11 | FrequentFlyerMember findByName(String name); 12 | } 13 | -------------------------------------------------------------------------------- /chapter-09/java/flying-high/src/test/java/com/examplcom/manning/bddinaction/frequentflyer/acceptancetests/json/ReadTestData.java: -------------------------------------------------------------------------------- 1 | package com.examplcom.manning.bddinaction.frequentflyer.acceptancetests.json; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import com.fasterxml.jackson.databind.SerializationFeature; 5 | import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; 6 | 7 | public class ReadTestData { 8 | 9 | private ObjectMapper fromJson() { 10 | ObjectMapper mapper = new ObjectMapper(); 11 | mapper.registerModule(new JavaTimeModule()); 12 | mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); 13 | return mapper; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /chapter-15/domain/registration/LocateRegistrationForm.ts: -------------------------------------------------------------------------------- 1 | import { Task } from '@serenity-js/core'; 2 | import { Click, Navigate } from '@serenity-js/web'; 3 | import { Form } from '../ui'; 4 | 5 | export class LocateRegistrationForm { 6 | static viaHomePage = () => 7 | Task.where(`#actor locates Frequent Flyer registration form via home page`, 8 | Navigate.to('/'), 9 | Click.on( 10 | Form.buttonCalled('Register') 11 | ), 12 | ); 13 | 14 | static viaDirectNavigation = () => 15 | Task.where(`#actor locates Frequent Flyer registration form via direct navigation`, 16 | Navigate.to('/register'), 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /flying-high-app/web/src/app/shared/shared.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { UserFormComponent } from './components/user-form/user-form.component'; 4 | import { MaterialModules } from './material-modules'; 5 | import { FormsModule, ReactiveFormsModule } from '@angular/forms'; 6 | import { RouterModule } from '@angular/router'; 7 | 8 | @NgModule({ 9 | declarations: [UserFormComponent], 10 | imports: [ 11 | FormsModule, 12 | CommonModule, 13 | RouterModule, 14 | ReactiveFormsModule, 15 | MaterialModules 16 | ], 17 | exports: [ 18 | UserFormComponent 19 | ] 20 | }) 21 | export class SharedModule { } 22 | -------------------------------------------------------------------------------- /flying-high-app/server/dist/flights/interface/flight.interface.d.ts: -------------------------------------------------------------------------------- 1 | import { City } from "./city.interface"; 2 | export interface Flight { 3 | departure: City; 4 | destination: City; 5 | departureDate: Date; 6 | returnDate: Date; 7 | departureTime: Date; 8 | returnTime: Date; 9 | class: 'Economy' | 'Premium Economy' | 'Business'; 10 | email: string; 11 | points: number; 12 | price: number; 13 | orderNumber: string; 14 | } 15 | export interface FlightResource { 16 | departureTime: Date; 17 | arrivalTime: Date; 18 | duration: string; 19 | departure: City; 20 | destination: City; 21 | price: number; 22 | class: 'Economy' | 'Premium Economy' | 'Business'; 23 | } 24 | --------------------------------------------------------------------------------