diff --git a/libraries/pom.xml b/libraries/pom.xml
index e893572cf9..bf50e699b8 100644
--- a/libraries/pom.xml
+++ b/libraries/pom.xml
@@ -169,26 +169,31 @@
net.serenity-bdd
serenity-core
${serenity.version}
+ test
net.serenity-bdd
serenity-junit
${serenity.version}
+ test
net.serenity-bdd
serenity-jbehave
${serenity.jbehave.version}
+ test
net.serenity-bdd
serenity-rest-assured
${serenity.version}
+ test
net.serenity-bdd
serenity-jira-requirements-provider
${serenity.jira.version}
+ test
com.fasterxml.jackson.core
@@ -231,17 +236,36 @@
datanucleus-xml
5.0.0-release
-
- com.zaxxer
- HikariCP
- 2.6.1
- compile
-
-
- org.postgresql
- postgresql
- 42.0.0
-
+
+
+ org.springframework
+ spring-web
+ 4.3.8.RELEASE
+
+
+ net.serenity-bdd
+ serenity-spring
+ ${serenity.version}
+ test
+
+
+ io.rest-assured
+ spring-mock-mvc
+ 3.0.3
+ test
+
+
+ com.zaxxer
+ HikariCP
+ 2.6.1
+ compile
+
+
+ org.postgresql
+ postgresql
+ 42.0.0
+
+
@@ -261,10 +285,10 @@
2.5
1.2.0
2.8.5
- 1.2.5-rc.11
+ 1.4.0
1.24.0
1.1.3-rc.5
- 1.2.5-rc.6
+ 1.4.0
diff --git a/libraries/src/main/java/com/baeldung/serenity/spring/KonamiCodeController.java b/libraries/src/main/java/com/baeldung/serenity/spring/KonamiCodeController.java
new file mode 100644
index 0000000000..f8ae66c229
--- /dev/null
+++ b/libraries/src/main/java/com/baeldung/serenity/spring/KonamiCodeController.java
@@ -0,0 +1,28 @@
+package com.baeldung.serenity.spring;
+
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author aiet
+ */
+@RequestMapping(value = "/konamicode", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+@RestController
+public class KonamiCodeController {
+
+ private final String classicCode = "↑↑↓↓←→←→BA";
+
+ @GetMapping("/classic")
+ public String classicCode() {
+ return classicCode;
+ }
+
+ @GetMapping("/cheatable")
+ public boolean cheatCheck(@RequestParam String cheatcode){
+ return classicCode.equals(cheatcode);
+ }
+
+}
diff --git a/libraries/src/main/java/com/baeldung/serenity/spring/KonamiCodeService.java b/libraries/src/main/java/com/baeldung/serenity/spring/KonamiCodeService.java
new file mode 100644
index 0000000000..2aa1804ba5
--- /dev/null
+++ b/libraries/src/main/java/com/baeldung/serenity/spring/KonamiCodeService.java
@@ -0,0 +1,39 @@
+package com.baeldung.serenity.spring;
+
+import org.springframework.stereotype.Service;
+
+/**
+ * refer to Konami Code
+ */
+@Service
+public class KonamiCodeService {
+
+ private String classicCode = "↑↑↓↓←→←→BA";
+
+ public String getClassicCode() {
+ return classicCode;
+ }
+
+ public void alterClassicCode(String newCode) {
+ classicCode = newCode;
+ }
+
+ public boolean cheatWith(String cheatcode) {
+ if ("↑↑↓↓←→←→BA".equals(cheatcode)) {
+ stageLeft++;
+ return true;
+ }
+ return false;
+ }
+
+ private int stageLeft = 1;
+
+ public void clearStage() {
+ stageLeft = 0;
+ }
+
+ public int stageLeft() {
+ return stageLeft;
+ }
+
+}
diff --git a/libraries/src/main/java/com/baeldung/serenity/spring/KonamiCodeServiceInjectionController.java b/libraries/src/main/java/com/baeldung/serenity/spring/KonamiCodeServiceInjectionController.java
new file mode 100644
index 0000000000..bb80963aa3
--- /dev/null
+++ b/libraries/src/main/java/com/baeldung/serenity/spring/KonamiCodeServiceInjectionController.java
@@ -0,0 +1,41 @@
+package com.baeldung.serenity.spring;
+
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * @author aiet
+ */
+@RequestMapping(value = "/konamicode", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+@RestController
+public class KonamiCodeServiceInjectionController {
+
+ private KonamiCodeService konamiCodeService;
+
+ public KonamiCodeServiceInjectionController(KonamiCodeService konamiCodeService) {
+ this.konamiCodeService = konamiCodeService;
+ }
+
+ @PutMapping("/stages")
+ public void clearStage(@RequestParam String action) {
+ if ("clear".equals(action)) {
+ konamiCodeService.clearStage();
+ }
+ }
+
+ @GetMapping("/classic")
+ public String classicCode() {
+ return konamiCodeService.getClassicCode();
+ }
+
+ @GetMapping("/cheatable")
+ public boolean cheatCheck(@RequestParam String cheatcode) {
+ return konamiCodeService.cheatWith(cheatcode);
+ }
+
+ @GetMapping("/stages")
+ public int stageLeft() {
+ return konamiCodeService.stageLeft();
+ }
+
+}
diff --git a/libraries/src/test/java/com/baeldung/serenity/spring/KonamCheatClassDirtiesContextTest.java b/libraries/src/test/java/com/baeldung/serenity/spring/KonamCheatClassDirtiesContextTest.java
new file mode 100644
index 0000000000..6331b548eb
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/serenity/spring/KonamCheatClassDirtiesContextTest.java
@@ -0,0 +1,74 @@
+package com.baeldung.serenity.spring;
+
+import com.baeldung.serenity.spring.steps.KonamiCodeServiceInjectionSteps;
+import net.serenitybdd.junit.runners.SerenityRunner;
+import net.serenitybdd.junit.spring.integration.SpringIntegrationClassRule;
+import net.thucydides.core.annotations.Steps;
+import net.thucydides.core.annotations.Title;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+
+import static org.springframework.test.annotation.DirtiesContext.ClassMode.AFTER_CLASS;
+
+/**
+ * @author aiet
+ */
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ KonamCheatClassDirtiesContextTest.DirtiesContextTest.class, KonamCheatClassDirtiesContextTest.AnotherDirtiesContextTest.class
+ })
+public class KonamCheatClassDirtiesContextTest {
+
+ @RunWith(SerenityRunner.class)
+ @ContextConfiguration(classes = KonamiCodeService.class)
+ public static abstract class Base {
+
+ @Steps KonamiCodeServiceInjectionSteps cheatSteps;
+
+ @ClassRule public static SpringIntegrationClassRule springIntegrationClassRule = new SpringIntegrationClassRule();
+
+ void hiddenStageShouldBeUnlockedAfterCheating() {
+ fetchAndCheat();
+ cheatSteps.aStageRemains();
+
+ cheatSteps.letsHack();
+
+ fetchAndCheat();
+ cheatSteps.noStageRemains();
+ }
+
+ private void fetchAndCheat() {
+ cheatSteps.gameStageCleared();
+ cheatSteps.fetchLatestCheatcode();
+ cheatSteps.cheatWithLatestcode();
+ }
+
+ }
+
+ @DirtiesContext(classMode = AFTER_CLASS)
+ public static class AnotherDirtiesContextTest extends Base {
+
+ @Test
+ @Title("altering the cheatcode after unlocking would stop others from cheating, not affected by other tests (another)")
+ public void givenGameStageCleared_whenCheat_thenHiddenStageUnlocked() {
+ super.hiddenStageShouldBeUnlockedAfterCheating();
+ }
+ }
+
+ @DirtiesContext(classMode = AFTER_CLASS)
+ public static class DirtiesContextTest extends Base {
+
+ @Test
+ @Title("altering the cheatcode after unlocking would stop others from cheating, not affected by other tests")
+ public void givenGameStageCleared_whenCheat_thenHiddenStageUnlocked() {
+ super.hiddenStageShouldBeUnlockedAfterCheating();
+ }
+ }
+
+
+}
diff --git a/libraries/src/test/java/com/baeldung/serenity/spring/KonamCheatWithDirtyActionTest.java b/libraries/src/test/java/com/baeldung/serenity/spring/KonamCheatWithDirtyActionTest.java
new file mode 100644
index 0000000000..213e54d557
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/serenity/spring/KonamCheatWithDirtyActionTest.java
@@ -0,0 +1,62 @@
+package com.baeldung.serenity.spring;
+
+import com.baeldung.serenity.spring.steps.KonamiCodeConstructorDependencySteps;
+import net.serenitybdd.junit.runners.SerenityRunner;
+import net.serenitybdd.junit.spring.integration.SpringIntegrationMethodRule;
+import net.thucydides.core.annotations.Title;
+import org.junit.Before;
+import org.junit.FixMethodOrder;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+
+/**
+ * @author aiet
+ */
+@RunWith(SerenityRunner.class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@ContextConfiguration(classes = KonamiCodeService.class)
+public class KonamCheatWithDirtyActionTest {
+
+ private KonamiCodeConstructorDependencySteps cheatSteps;
+
+ @Autowired private KonamiCodeService codeService;
+
+ @Before
+ public void init() {
+ cheatSteps = new KonamiCodeConstructorDependencySteps(codeService);
+ }
+
+ @Test
+ @Title("hidden stage should be unlocked after cheating (run in service with dirty action)")
+ public void givenGameStageCleared_whenCheat_thenHiddenStageUnlocked() {
+ fetchCodeAndCheat();
+ cheatSteps.aStageRemains();
+ }
+
+ @Rule public SpringIntegrationMethodRule springIntegration = new SpringIntegrationMethodRule();
+
+ @DirtiesContext
+ @Test
+ @Title("altering the cheatcode after unlocking would stop others from cheating")
+ public void givenGameStageCleared_whenCheatAndHack_thenAnotherCheatFail() {
+ fetchCodeAndCheat();
+ cheatSteps.aStageRemains();
+
+ cheatSteps.letsHack();
+
+ fetchCodeAndCheat();
+ cheatSteps.noStageRemains();
+ }
+
+ private void fetchCodeAndCheat() {
+ cheatSteps.gameStageCleared();
+ cheatSteps.fetchLatestCheatcode();
+ cheatSteps.cheatWithLatestcode();
+ }
+
+}
diff --git a/libraries/src/test/java/com/baeldung/serenity/spring/KonamCheatWithDirtyActionWithImplicitInjectionTest.java b/libraries/src/test/java/com/baeldung/serenity/spring/KonamCheatWithDirtyActionWithImplicitInjectionTest.java
new file mode 100644
index 0000000000..76143156bf
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/serenity/spring/KonamCheatWithDirtyActionWithImplicitInjectionTest.java
@@ -0,0 +1,54 @@
+package com.baeldung.serenity.spring;
+
+import com.baeldung.serenity.spring.steps.KonamiCodeServiceInjectionSteps;
+import net.serenitybdd.junit.runners.SerenityRunner;
+import net.serenitybdd.junit.spring.integration.SpringIntegrationMethodRule;
+import net.thucydides.core.annotations.Steps;
+import net.thucydides.core.annotations.Title;
+import org.junit.FixMethodOrder;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+
+/**
+ * @author aiet
+ */
+@RunWith(SerenityRunner.class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@ContextConfiguration(classes = KonamiCodeService.class)
+public class KonamCheatWithDirtyActionWithImplicitInjectionTest {
+
+ @Steps private KonamiCodeServiceInjectionSteps cheatSteps;
+
+ @Test
+ @Title("hidden stage is not unlocked after cheating (cheatcode hacked)")
+ public void givenGameStageCleared_whenCheat_thenCheatFail() {
+ fetchCodeAndCheat();
+ cheatSteps.noStageRemains();
+ }
+
+ private void fetchCodeAndCheat() {
+ cheatSteps.gameStageCleared();
+ cheatSteps.fetchLatestCheatcode();
+ cheatSteps.cheatWithLatestcode();
+ }
+
+ @Rule public SpringIntegrationMethodRule springIntegration = new SpringIntegrationMethodRule();
+
+ @DirtiesContext
+ @Test
+ @Title("altering the cheatcode after unlocking would stop others from cheating")
+ public void givenGameStageCleared_whenCheatAndHack_thenAnotherCheatFail() {
+ fetchCodeAndCheat();
+ cheatSteps.aStageRemains();
+
+ cheatSteps.letsHack();
+
+ fetchCodeAndCheat();
+ cheatSteps.noStageRemains();
+ }
+
+}
diff --git a/libraries/src/test/java/com/baeldung/serenity/spring/KonamCheatWithServiceTest.java b/libraries/src/test/java/com/baeldung/serenity/spring/KonamCheatWithServiceTest.java
new file mode 100644
index 0000000000..ea59931324
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/serenity/spring/KonamCheatWithServiceTest.java
@@ -0,0 +1,27 @@
+package com.baeldung.serenity.spring;
+
+import com.baeldung.serenity.spring.steps.KonamiCodeServiceInjectionSteps;
+import net.serenitybdd.junit.runners.SerenityRunner;
+import net.thucydides.core.annotations.Steps;
+import net.thucydides.core.annotations.Title;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * @author aiet
+ */
+@RunWith(SerenityRunner.class)
+public class KonamCheatWithServiceTest {
+
+ @Steps private KonamiCodeServiceInjectionSteps cheatSteps;
+
+ @Test
+ @Title("hidden stage should be unlocked after cheating (mockmvc)")
+ public void givenGameStageCleared_whenCheat_thenHiddenStageUnlocked() {
+ cheatSteps.gameStageCleared();
+ cheatSteps.fetchLatestCheatcode();
+ cheatSteps.cheatWithLatestcode();
+ cheatSteps.aStageRemains();
+ }
+
+}
diff --git a/libraries/src/test/java/com/baeldung/serenity/spring/KonamiCheatWithIntegrationMethodRulesTest.java b/libraries/src/test/java/com/baeldung/serenity/spring/KonamiCheatWithIntegrationMethodRulesTest.java
new file mode 100644
index 0000000000..9d19cefba9
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/serenity/spring/KonamiCheatWithIntegrationMethodRulesTest.java
@@ -0,0 +1,61 @@
+package com.baeldung.serenity.spring;
+
+import com.baeldung.serenity.spring.steps.KonamiCheatSteps;
+import net.serenitybdd.junit.runners.SerenityRunner;
+import net.serenitybdd.junit.spring.integration.SpringIntegrationMethodRule;
+import net.thucydides.core.annotations.Steps;
+import net.thucydides.core.annotations.Title;
+import org.junit.*;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.test.context.ContextConfiguration;
+
+/**
+ * Unit test for simple App.
+ */
+@RunWith(SerenityRunner.class)
+@ContextConfiguration(locations = "classpath:konami-cheat-beans.xml")
+public class KonamiCheatWithIntegrationMethodRulesTest {
+
+ private static Logger LOG = LoggerFactory.getLogger(KonamiCheatWithIntegrationMethodRulesTest.class);
+
+ @BeforeClass
+ public static void initClass() {
+ LOG.info("static chaincode before test class: {}", staticCheatCode);
+ }
+
+ @AfterClass
+ public static void destroyClass() {
+ LOG.info("static chaincode after test class: {}", staticCheatCode);
+ }
+
+ @Before
+ public void init() {
+ staticCheatCode = cheatCode;
+ LOG.info("cheatcode before test: {}", cheatCode);
+ }
+
+ @After
+ public void destroy() {
+ LOG.info("cheatcode after test: {}", cheatCode);
+ }
+
+ @Rule public SpringIntegrationMethodRule springMethodIntegration = new SpringIntegrationMethodRule();
+
+ @Steps private KonamiCheatSteps konamiCheatSteps;
+
+ @Value("#{konami_props['code']}") private String cheatCode;
+
+ private static String staticCheatCode;
+
+ @Test
+ @Title("hidden stage should be unlocked after cheating (rule integration)")
+ public void givenGameStageCleared_whenCheat_thenHiddenStageUnlocked() {
+ konamiCheatSteps.gameStageCleared();
+ konamiCheatSteps.cheatWith(cheatCode);
+ konamiCheatSteps.aStageRemains();
+ }
+
+}
diff --git a/libraries/src/test/java/com/baeldung/serenity/spring/KonamiCheatWithIntegrationRunnerTest.java b/libraries/src/test/java/com/baeldung/serenity/spring/KonamiCheatWithIntegrationRunnerTest.java
new file mode 100644
index 0000000000..9aa70ddb12
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/serenity/spring/KonamiCheatWithIntegrationRunnerTest.java
@@ -0,0 +1,58 @@
+package com.baeldung.serenity.spring;
+
+import com.baeldung.serenity.spring.steps.KonamiCheatSteps;
+import net.serenitybdd.junit.spring.integration.SpringIntegrationSerenityRunner;
+import net.thucydides.core.annotations.Steps;
+import net.thucydides.core.annotations.Title;
+import org.junit.*;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.test.context.ContextConfiguration;
+
+/**
+ * Unit test for simple App.
+ */
+@RunWith(SpringIntegrationSerenityRunner.class)
+@ContextConfiguration(locations = "classpath:konami-cheat-beans.xml")
+public class KonamiCheatWithIntegrationRunnerTest {
+
+ private static Logger LOG = LoggerFactory.getLogger(KonamiCheatWithIntegrationRunnerTest.class);
+
+ @BeforeClass
+ public static void initClass() {
+ LOG.info("static chaincode before test class: {}", staticCheatCode);
+ }
+
+ @AfterClass
+ public static void destroyClass() {
+ LOG.info("static chaincode after test class: {}", staticCheatCode);
+ }
+
+ @Before
+ public void init() {
+ staticCheatCode = cheatCode;
+ LOG.info("cheatcode before test: {}", cheatCode);
+ }
+
+ @After
+ public void destroy() {
+ LOG.info("cheatcode after test: {}", cheatCode);
+ }
+
+ @Steps private KonamiCheatSteps konamiCheatSteps;
+
+ @Value("#{konami_props['code']}") private String cheatCode;
+
+ private static String staticCheatCode;
+
+ @Test
+ @Title("hidden stage should be unlocked after cheating (with integration runner)")
+ public void givenGameStageCleared_whenCheat_thenHiddenStageUnlocked() {
+ konamiCheatSteps.gameStageCleared();
+ konamiCheatSteps.cheatWith(cheatCode);
+ konamiCheatSteps.aStageRemains();
+ }
+
+}
diff --git a/libraries/src/test/java/com/baeldung/serenity/spring/KonamiCodeMockMvcTest.java b/libraries/src/test/java/com/baeldung/serenity/spring/KonamiCodeMockMvcTest.java
new file mode 100644
index 0000000000..2ae6cdcd84
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/serenity/spring/KonamiCodeMockMvcTest.java
@@ -0,0 +1,31 @@
+package com.baeldung.serenity.spring;
+
+import com.baeldung.serenity.spring.steps.KonamiCodeRestSteps;
+import io.restassured.module.mockmvc.RestAssuredMockMvc;
+import net.serenitybdd.junit.runners.SerenityRunner;
+import net.thucydides.core.annotations.Steps;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * @author aiet
+ */
+@RunWith(SerenityRunner.class)
+public class KonamiCodeMockMvcTest {
+
+ @Before
+ public void init() {
+ RestAssuredMockMvc.standaloneSetup(new KonamiCodeController());
+ }
+
+ @Steps KonamiCodeRestSteps steps;
+
+ @Test
+ public void givenOfficialClassicCheatcode_whenCheat_ThenTheCodeShouldDoTheTrick() throws Exception {
+ steps.givenClassicCheatCode();
+ steps.whenCheat();
+ steps.thenClassicCodeCanDoTheTrick();
+ }
+
+}
diff --git a/libraries/src/test/java/com/baeldung/serenity/spring/KonamiCodeTest.java b/libraries/src/test/java/com/baeldung/serenity/spring/KonamiCodeTest.java
new file mode 100644
index 0000000000..d2e5fd30f6
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/serenity/spring/KonamiCodeTest.java
@@ -0,0 +1,22 @@
+package com.baeldung.serenity.spring;
+
+import io.restassured.module.mockmvc.RestAssuredMockMvc;
+import net.serenitybdd.jbehave.SerenityStory;
+import org.jbehave.core.annotations.BeforeStory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+
+/**
+ * @author aiet
+ */
+@ContextConfiguration(classes = { KonamiCodeServiceInjectionController.class, KonamiCodeService.class })
+public class KonamiCodeTest extends SerenityStory {
+
+ @Autowired private KonamiCodeService konamiCodeService;
+
+ @BeforeStory
+ public void init() {
+ RestAssuredMockMvc.standaloneSetup(new KonamiCodeServiceInjectionController(konamiCodeService));
+ }
+
+}
diff --git a/libraries/src/test/java/com/baeldung/serenity/spring/steps/KonamiCheatSteps.java b/libraries/src/test/java/com/baeldung/serenity/spring/steps/KonamiCheatSteps.java
new file mode 100644
index 0000000000..0bb408bda0
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/serenity/spring/steps/KonamiCheatSteps.java
@@ -0,0 +1,25 @@
+package com.baeldung.serenity.spring.steps;
+
+import net.thucydides.core.annotations.Step;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author aiet
+ */
+public class KonamiCheatSteps {
+
+ @Step("all stages of the game are cleared")
+ public void gameStageCleared() {
+ }
+
+ @Step("input the classic 'Konami Code': {0} ")
+ public void cheatWith(String cheatcode) {
+ assertEquals("cheatcode wrong", "↑↑↓↓←→←→BA", cheatcode);
+ }
+
+ @Step("there is still a stage left")
+ public void aStageRemains() {
+ }
+
+}
diff --git a/libraries/src/test/java/com/baeldung/serenity/spring/steps/KonamiCodeConstructorDependencySteps.java b/libraries/src/test/java/com/baeldung/serenity/spring/steps/KonamiCodeConstructorDependencySteps.java
new file mode 100644
index 0000000000..2bec25b58f
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/serenity/spring/steps/KonamiCodeConstructorDependencySteps.java
@@ -0,0 +1,58 @@
+package com.baeldung.serenity.spring.steps;
+
+import com.baeldung.serenity.spring.KonamiCodeService;
+import net.thucydides.core.annotations.Step;
+import org.apache.commons.lang3.RandomStringUtils;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.*;
+
+/**
+ * @author aiet
+ */
+public class KonamiCodeConstructorDependencySteps {
+
+ private String latestCheatcode;
+ private boolean cheatSuccess;
+
+ private KonamiCodeService konamiCodeService;
+
+ public KonamiCodeConstructorDependencySteps(KonamiCodeService konamiCodeService) {
+ this.konamiCodeService = konamiCodeService;
+ }
+
+ @Step("fetch latest cheat code")
+ public void fetchLatestCheatcode() {
+ latestCheatcode = konamiCodeService.getClassicCode();
+ }
+
+ @Step("cheat with latest code")
+ public void cheatWithLatestcode() {
+ cheatSuccess = konamiCodeService.cheatWith(latestCheatcode);
+ }
+
+ @Step("all stages of the game are cleared")
+ public void gameStageCleared() {
+ konamiCodeService.clearStage();
+ }
+
+ @Step("there is still a stage left")
+ public void aStageRemains() {
+ assertTrue("cheatcode wrong", cheatSuccess);
+ assertThat(konamiCodeService.stageLeft(), equalTo(1));
+ }
+
+ // @Rule public SpringIntegrationMethodRule methodRule = new SpringIntegrationMethodRule();
+
+ // @DirtiesContext
+ @Step
+ public void letsHack() {
+ konamiCodeService.alterClassicCode(RandomStringUtils.random(4));
+ }
+
+ @Step("there is no stage left")
+ public void noStageRemains() {
+ assertFalse(cheatSuccess);
+ assertThat(konamiCodeService.stageLeft(), equalTo(0));
+ }
+}
diff --git a/libraries/src/test/java/com/baeldung/serenity/spring/steps/KonamiCodeRestSteps.java b/libraries/src/test/java/com/baeldung/serenity/spring/steps/KonamiCodeRestSteps.java
new file mode 100644
index 0000000000..3f06d42414
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/serenity/spring/steps/KonamiCodeRestSteps.java
@@ -0,0 +1,68 @@
+package com.baeldung.serenity.spring.steps;
+
+import io.restassured.module.mockmvc.response.MockMvcResponse;
+import net.thucydides.core.annotations.Step;
+
+import java.io.UnsupportedEncodingException;
+
+import static io.restassured.module.mockmvc.RestAssuredMockMvc.given;
+import static org.hamcrest.core.IsEqual.equalTo;
+
+/**
+ * @author aiet
+ */
+public class KonamiCodeRestSteps {
+
+ MockMvcResponse mockMvcResponse;
+ String cheatcode;
+
+ @Step("get the classic cheat code")
+ public void givenClassicCheatCode() throws UnsupportedEncodingException {
+ cheatcode = given()
+ .when()
+ .get("/konamicode/classic")
+ .mvcResult()
+ .getResponse()
+ .getContentAsString();
+ }
+
+ @Step("check if the cheat code works")
+ public void whenCheat() {
+ mockMvcResponse = given()
+ .queryParam("cheatcode", cheatcode)
+ .when()
+ .get("/konamicode/cheatable");
+ }
+
+ @Step("classic cheat code matches")
+ public void thenClassicCodeCanDoTheTrick() {
+ mockMvcResponse
+ .then()
+ .statusCode(200)
+ .body(equalTo("true"));
+ }
+
+ @Step("all stage cleared")
+ public void stageCleared() {
+ given()
+ .queryParam("action", "clear")
+ .when()
+ .put("/konamicode/stages");
+ given()
+ .when()
+ .get("/konamicode/stages")
+ .then()
+ .body(equalTo("0"));
+ }
+
+ @Step("one more stage to play")
+ public void thenMoreStages() {
+ given()
+ .when()
+ .get("/konamicode/stages")
+ .then()
+ .body(equalTo("1"));
+ }
+
+}
+
diff --git a/libraries/src/test/java/com/baeldung/serenity/spring/steps/KonamiCodeServiceInjectionSteps.java b/libraries/src/test/java/com/baeldung/serenity/spring/steps/KonamiCodeServiceInjectionSteps.java
new file mode 100644
index 0000000000..b57186ba14
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/serenity/spring/steps/KonamiCodeServiceInjectionSteps.java
@@ -0,0 +1,55 @@
+package com.baeldung.serenity.spring.steps;
+
+import com.baeldung.serenity.spring.KonamiCodeService;
+import net.thucydides.core.annotations.Step;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.*;
+
+/**
+ * @author aiet
+ */
+@ContextConfiguration(classes = KonamiCodeService.class)
+public class KonamiCodeServiceInjectionSteps {
+
+ private String latestCheatcode;
+ private boolean cheatSuccess;
+
+ @Autowired private KonamiCodeService konamiCodeService;
+
+ @Step("fetch latest cheat code")
+ public void fetchLatestCheatcode() {
+ latestCheatcode = konamiCodeService.getClassicCode();
+ }
+
+ @Step("cheat with latest code")
+ public void cheatWithLatestcode() {
+ cheatSuccess = konamiCodeService.cheatWith(latestCheatcode);
+ }
+
+ @Step("all stages of the game are cleared")
+ public void gameStageCleared() {
+ konamiCodeService.clearStage();
+ }
+
+ @Step("there is still a stage left")
+ public void aStageRemains() {
+ assertTrue("cheatcode wrong", cheatSuccess);
+ assertThat(konamiCodeService.stageLeft(), equalTo(1));
+ }
+
+ @Step("altering default cheat code")
+ public void letsHack() {
+ konamiCodeService.alterClassicCode(RandomStringUtils.random(4));
+ }
+
+ @Step("there is no stage left")
+ public void noStageRemains() {
+ assertFalse(cheatSuccess);
+ assertThat(konamiCodeService.stageLeft(), equalTo(0));
+ }
+
+}
diff --git a/libraries/src/test/java/com/baeldung/serenity/spring/stories/KonamiCodeStory.java b/libraries/src/test/java/com/baeldung/serenity/spring/stories/KonamiCodeStory.java
new file mode 100644
index 0000000000..090eb63215
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/serenity/spring/stories/KonamiCodeStory.java
@@ -0,0 +1,37 @@
+package com.baeldung.serenity.spring.stories;
+
+import com.baeldung.serenity.spring.steps.KonamiCodeRestSteps;
+import net.thucydides.core.annotations.Steps;
+import org.jbehave.core.annotations.Given;
+import org.jbehave.core.annotations.Then;
+import org.jbehave.core.annotations.When;
+
+/**
+ * @author aiet
+ */
+public class KonamiCodeStory {
+
+ @Steps KonamiCodeRestSteps restSteps;
+
+ @Given("game stage cleared")
+ public void givenStageCleared(){
+ restSteps.stageCleared();
+ }
+
+ @Given("KONAMI cheat code")
+ public void givenKONAMICheatCode() throws Exception{
+ restSteps.givenClassicCheatCode();
+ }
+
+ @When("I input the cheat code")
+ public void whenIInputTheCheatCode() {
+ restSteps.whenCheat();
+ }
+
+ @Then("a hidden stage will be unlocked")
+ public void thenAHiddenStageWillBeUnlocked() {
+ restSteps.thenClassicCodeCanDoTheTrick();
+ restSteps.thenMoreStages();
+ }
+
+}
diff --git a/libraries/src/test/resources/konami-cheat-beans.xml b/libraries/src/test/resources/konami-cheat-beans.xml
new file mode 100644
index 0000000000..221d058337
--- /dev/null
+++ b/libraries/src/test/resources/konami-cheat-beans.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+ ↑↑↓↓←→←→BA
+
+
+
+
+
diff --git a/libraries/src/test/resources/stories/spring/konami_code_test.story b/libraries/src/test/resources/stories/spring/konami_code_test.story
new file mode 100644
index 0000000000..bba8ad7ade
--- /dev/null
+++ b/libraries/src/test/resources/stories/spring/konami_code_test.story
@@ -0,0 +1,12 @@
+Meta:
+
+Narrative:
+As a KONAMI player
+I want to cheat
+So that I can unlock hidden stages of the game
+
+Scenario: A KONAMI player can use the cheatcode to unlock hidden stages
+Given game stage cleared
+And KONAMI cheat code
+When I input the cheat code
+Then a hidden stage will be unlocked
\ No newline at end of file