From e08fc97f83b6dc8a6ae09d784a7c3c99d2953f45 Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 3 Jul 2023 12:14:23 +0200 Subject: [PATCH 01/10] Made login example more complex to showcase cucumber --- android/build.gradle.kts | 2 +- .../androidTest/assets/features/Home.feature | 3 +- .../androidTest/assets/features/Login.feature | 36 +++++++++++++++- .../test/StepDefinitions.kt | 43 ++++++++++++++++++- ios/Podfile.lock | 2 +- shared/build.gradle.kts | 1 - .../cucumber/viewModels/LoginViewModelTest.kt | 5 +-- 7 files changed, 82 insertions(+), 10 deletions(-) diff --git a/android/build.gradle.kts b/android/build.gradle.kts index 15799f7..3c98e02 100644 --- a/android/build.gradle.kts +++ b/android/build.gradle.kts @@ -70,7 +70,7 @@ dependencies { androidTestImplementation(project(":cucumberShared")) androidTestImplementation("io.cucumber:cucumber-android:4.10.0") - // TODO figure out how it can be updated without breeaking the project + // TODO figure out how it can be updated without breaking the project androidTestImplementation("io.cucumber:cucumber-java8:4.8.1") implementation("io.insert-koin:koin-androidx-compose:3.4.1") diff --git a/android/src/androidTest/assets/features/Home.feature b/android/src/androidTest/assets/features/Home.feature index 177cb42..6d66b3e 100644 --- a/android/src/androidTest/assets/features/Home.feature +++ b/android/src/androidTest/assets/features/Home.feature @@ -1,5 +1,6 @@ Feature: Home - Scenario: Home screen + + Scenario: Logout Given Email is "test@test.com" Given I am in the "Home" screen Then I see "test@test.com" text diff --git a/android/src/androidTest/assets/features/Login.feature b/android/src/androidTest/assets/features/Login.feature index ec36c05..7c66172 100644 --- a/android/src/androidTest/assets/features/Login.feature +++ b/android/src/androidTest/assets/features/Login.feature @@ -1,5 +1,37 @@ Feature: Login - Scenario: Login screen + + Scenario: Failed attempt with wrong credentials + Given I am in the "Login" screen + Then I see the "Email" textfield with text "Email" + Then I type "test@test.comunism" in the email field + Then I see the "Password" textfield with text "Password" + Then I type "1234" in the password field + Then I see the "Login" button + Then I press the login button + Then I see the "Login" screen + Then I see the "Incorrect email or password" screen + + Scenario: Failed attempt with empty email + Given I am in the "Login" screen + Then I see the "Email" textfield with text "Email" + Then I see the "Password" textfield with text "Password" + Then I type "1234" in the password field + Then I see the "Login" button + Then I press the login button + Then I see the "Login" screen + Then I see the "Missing email" screen + + Scenario: Failed attempt with empty password + Given I am in the "Login" screen + Then I see the "Email" textfield with text "Email" + Then I see the "Password" textfield with text "Password" + Then I type "1234" in the password field + Then I see the "Login" button + Then I press the login button + Then I see the "Login" screen + Then I see the "Missing password" screen + + Scenario: Successful attempt Given I am in the "Login" screen Then I see the "Email" textfield with text "Email" Then I type "test@test.com" in the email field @@ -8,4 +40,4 @@ Feature: Login Then I see the "Login" button Then I press the login button Then I see the "Home" screen - Then I see "test@test.com" text + Then I see "test@test.com" text \ No newline at end of file diff --git a/android/src/androidTest/kotlin/com/corrado4eyes/cucumberplayground/test/StepDefinitions.kt b/android/src/androidTest/kotlin/com/corrado4eyes/cucumberplayground/test/StepDefinitions.kt index 918eede..10610f6 100644 --- a/android/src/androidTest/kotlin/com/corrado4eyes/cucumberplayground/test/StepDefinitions.kt +++ b/android/src/androidTest/kotlin/com/corrado4eyes/cucumberplayground/test/StepDefinitions.kt @@ -17,6 +17,11 @@ import com.corrado4eyes.cucumber.GherkinLambda1 import com.corrado4eyes.cucumber.GherkinLambda2 import com.corrado4eyes.cucumberplayground.android.MainActivity import com.corrado4eyes.cucumbershared.tests.TestCase +import io.cucumber.core.api.Scenario +import io.cucumber.java.After +import io.cucumber.java.AfterStep +import io.cucumber.java.Before +import io.cucumber.java.BeforeStep import io.cucumber.java8.En import io.cucumber.junit.WithJunitRule import org.junit.Rule @@ -30,6 +35,41 @@ class StepDefinitions : En { @get:Rule(order = 0) val testRule = createComposeRule() + @Before(order = 0) + fun beforeScenarioStart(scenario: Scenario) { + // Will run before each scenario + println("-----------------Start of Scenario ${scenario.name}-----------------") + } + + @Before(order = 1) + fun beforeScenario(scenario: Scenario) { + // Will run before each scenario but second in order + println("Running steps:") + } + + @After(order = 1) + fun afterScenarioFinish(scenario: Scenario) { + // Will run after each scenario + println("Steps completed") + } + + @After(order = 0) + fun afterScenario(scenario: Scenario) { + // Will run after each scenario but second in order + println("-----------------End of Scenario ${scenario.name}-----------------") + } + + // TODO figure out for specific step, crashes the app with exception if you try @BeforeStep("some step") + @BeforeStep + fun beforeStep(scenario: Scenario) { + // Run stuff before each scenario step + } + + @AfterStep + fun afterStep(scenario: Scenario) { + // Run stuff after each scenario step + } + init { TestCase.Common.ScreenIsVisible( GherkinLambda1 { screenName -> @@ -39,6 +79,7 @@ class StepDefinitions : En { arguments["testEmail"] = "" "Login screen" } + "Home" -> { arguments["isLoggedIn"] = "true" "Home screen" @@ -116,7 +157,7 @@ class StepDefinitions : En { ) } - private fun launch(intent: Intent) { + private fun launch(intent: Intent) { scenario = ActivityScenario.launch(intent) } } \ No newline at end of file diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 5d198fb..74e28cc 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -13,4 +13,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 628c667357c176acb30372b1f5ac2574ef0cf182 -COCOAPODS: 1.11.3 +COCOAPODS: 1.12.1 diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index 461ee2d..17f5de9 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -62,7 +62,6 @@ kotlin { val commonTest by getting { dependencies { api(kotlin("test")) - api(kotlin("test-junit")) api("com.splendo.kaluga:test-utils:$kalugaVersion") api("io.insert-koin:koin-test:$koinVersion") } diff --git a/shared/src/commonTest/kotlin/com/corrado4eyes/cucumberplayground/cucumber/viewModels/LoginViewModelTest.kt b/shared/src/commonTest/kotlin/com/corrado4eyes/cucumberplayground/cucumber/viewModels/LoginViewModelTest.kt index a311605..3832ad5 100644 --- a/shared/src/commonTest/kotlin/com/corrado4eyes/cucumberplayground/cucumber/viewModels/LoginViewModelTest.kt +++ b/shared/src/commonTest/kotlin/com/corrado4eyes/cucumberplayground/cucumber/viewModels/LoginViewModelTest.kt @@ -19,14 +19,13 @@ class LoginViewModelTest : KoinUIThreadViewModelTest() as AuthServiceMock - override val viewModel: LoginViewModel = LoginViewModel(authService) + override val viewModel: LoginViewModel = LoginViewModel() } @Test fun test_on_login_button_pressed_fail_with_empty_email() = testOnUIThread { viewModel.login() assertTrue(viewModel.emailText.stateFlow.value.isEmpty()) -// assertEquals(Colors.red, viewModel.emailTextFieldBorderColor.stateFlow.value) assertEquals("Missing email", viewModel.emailErrorText.stateFlow.value) } @@ -54,7 +53,7 @@ class LoginViewModelTest : KoinUIThreadViewModelTest Date: Wed, 23 Aug 2023 14:43:28 +0200 Subject: [PATCH 02/10] Made login example more complex to showcase cucumber --- .../androidTest/assets/features/Home.feature | 9 +- .../androidTest/assets/features/Login.feature | 44 ++--- .../test/CommonStepDefinitions.kt | 117 +++++++++++++ .../test/StepDefinitions.kt | 163 ------------------ .../android/login/LoginLayout.kt | 8 +- .../cucumbershared/tests/TestCase.kt | 41 ++--- ios/Podfile | 8 + ios/Podfile.lock | 2 +- shared/build.gradle.kts | 1 + .../di/CucumberDependencyInjection.kt | 9 +- .../viewModels/home/HomeViewModel.kt | 23 ++- .../viewModels/login/LoginViewModel.kt | 44 ++--- .../viewModels/main/MainViewModel.kt | 6 +- 13 files changed, 218 insertions(+), 257 deletions(-) create mode 100644 android/src/androidTest/kotlin/com/corrado4eyes/cucumberplayground/test/CommonStepDefinitions.kt delete mode 100644 android/src/androidTest/kotlin/com/corrado4eyes/cucumberplayground/test/StepDefinitions.kt diff --git a/android/src/androidTest/assets/features/Home.feature b/android/src/androidTest/assets/features/Home.feature index 6d66b3e..02a1f5b 100644 --- a/android/src/androidTest/assets/features/Home.feature +++ b/android/src/androidTest/assets/features/Home.feature @@ -1,9 +1,8 @@ Feature: Home Scenario: Logout - Given Email is "test@test.com" - Given I am in the "Home" screen - Then I see "test@test.com" text + Given I see the "Home screen" screen + Then I see the "test@test.com" text Then I see the "Logout" button - Then I press the logout button - Then I see the "Login" screen + Then I press the "Logout" button + Then I see the "Login screen" text \ No newline at end of file diff --git a/android/src/androidTest/assets/features/Login.feature b/android/src/androidTest/assets/features/Login.feature index 7c66172..8633d26 100644 --- a/android/src/androidTest/assets/features/Login.feature +++ b/android/src/androidTest/assets/features/Login.feature @@ -1,43 +1,43 @@ Feature: Login Scenario: Failed attempt with wrong credentials - Given I am in the "Login" screen + Given I see the "Login screen" screen Then I see the "Email" textfield with text "Email" - Then I type "test@test.comunism" in the email field + Then I type "test@test.comunism" in the "Email" field Then I see the "Password" textfield with text "Password" - Then I type "1234" in the password field + Then I type "1234" in the "Password" field Then I see the "Login" button - Then I press the login button - Then I see the "Login" screen - Then I see the "Incorrect email or password" screen + Then I press the "Login" button + Then I see the "Login" text + Then I see the "Incorrect email or password" text Scenario: Failed attempt with empty email - Given I am in the "Login" screen + Given I see the "Login screen" screen Then I see the "Email" textfield with text "Email" Then I see the "Password" textfield with text "Password" - Then I type "1234" in the password field + Then I type "1234" in the "Password" field Then I see the "Login" button - Then I press the login button - Then I see the "Login" screen - Then I see the "Missing email" screen + Then I press the "Login" button + Then I see the "Login" text + Then I see the "Missing email" text Scenario: Failed attempt with empty password - Given I am in the "Login" screen + Given I see the "Login screen" screen Then I see the "Email" textfield with text "Email" Then I see the "Password" textfield with text "Password" - Then I type "1234" in the password field + Then I type "alex@alex" in the "Email" field Then I see the "Login" button - Then I press the login button - Then I see the "Login" screen - Then I see the "Missing password" screen + Then I press the "Login" button + Then I see the "Login" text + Then I see the "Missing password" text Scenario: Successful attempt - Given I am in the "Login" screen + Given I see the "Login screen" screen Then I see the "Email" textfield with text "Email" - Then I type "test@test.com" in the email field + Then I type "test@test.com" in the "Email" field Then I see the "Password" textfield with text "Password" - Then I type "1234" in the password field + Then I type "1234" in the "Password" field Then I see the "Login" button - Then I press the login button - Then I see the "Home" screen - Then I see "test@test.com" text \ No newline at end of file + Then I press the "Login" button + Then I see the "Home screen" text + Then I see the "test@test.com" text \ No newline at end of file diff --git a/android/src/androidTest/kotlin/com/corrado4eyes/cucumberplayground/test/CommonStepDefinitions.kt b/android/src/androidTest/kotlin/com/corrado4eyes/cucumberplayground/test/CommonStepDefinitions.kt new file mode 100644 index 0000000..5d08b1c --- /dev/null +++ b/android/src/androidTest/kotlin/com/corrado4eyes/cucumberplayground/test/CommonStepDefinitions.kt @@ -0,0 +1,117 @@ +package com.corrado4eyes.cucumberplayground.test + +import android.content.Intent +import androidx.compose.ui.test.assertHasClickAction +import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.assertTextContains +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithTag +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.performTextInput +import androidx.test.core.app.ActivityScenario +import androidx.test.platform.app.InstrumentationRegistry +import com.corrado4eyes.cucumber.GherkinLambda1 +import com.corrado4eyes.cucumber.GherkinLambda2 +import com.corrado4eyes.cucumberplayground.android.MainActivity +import com.corrado4eyes.cucumbershared.tests.TestCase +import io.cucumber.java.After +import io.cucumber.java.AfterStep +import io.cucumber.java.Before +import io.cucumber.java.BeforeStep +import io.cucumber.java8.En +import io.cucumber.junit.WithJunitRule +import org.junit.Rule + +@WithJunitRule +class CommonStepDefinitions : En { + + private val arguments = mutableMapOf() + private var scenario: ActivityScenario<*>? = null + + @get:Rule(order = 0) + val testRule = createComposeRule() + + @Before(order = 0) + fun beforeScenarioStart1(scenario: io.cucumber.core.api.Scenario) { + // Will run before each scenario + println("-----------------Start of Scenario ${scenario.name}-----------------") + when (val scenarioName = scenario.name) { + "Failed attempt with wrong credentials", + "Failed attempt with empty email", + "Failed attempt with empty password", + "Successful attempt" -> { + arguments["isLoggedIn"] = "false" + arguments["testEmail"] = "" + } + "Logout" -> { + arguments["isLoggedIn"] = "true" + arguments["testEmail"] = "test@test.com" + } + + else -> throw IllegalArgumentException("Couldn't find scenario: $scenarioName ") + } + launchApp() + } + + @After(order = 0) + fun afterScenarioFinish2(cucuScenario: io.cucumber.core.api.Scenario) { + // Will run after each scenario but first in order + println("-----------------End of Scenario ${cucuScenario.name}-----------------") + } + + // TODO figure out for specific step, crashes the app with exception if you try @BeforeStep("some step") + @BeforeStep(order = 0) + fun beforeStep(scenario: io.cucumber.core.api.Scenario) { + // Run stuff before each scenario step + } + + @AfterStep(order = 0) + fun afterStep(scenario: io.cucumber.core.api.Scenario) { + // Run stuff after each scenario step + } + + init { + TestCase.Common.TextIsVisible( + GherkinLambda1 { + testRule.onNodeWithText(it).assertIsDisplayed() + } + ) + TestCase.Common.GivenTextIsVisible( + GherkinLambda1 { + testRule.onNodeWithText(it).assertIsDisplayed() + } + ) + TestCase.Common.ButtonIsVisible( + GherkinLambda1 { + testRule.onNodeWithText(it).assertIsDisplayed().assertHasClickAction() + } + ) + // TODO make into generic view is visible with tag is swift ui supports it + TestCase.Common.TextFieldIsVisible( + GherkinLambda2 { tag, text -> + testRule.onNodeWithTag(tag).assertIsDisplayed().assertTextContains(text) + } + ) + TestCase.Common.FillTextField( + GherkinLambda2 { input, tag -> + testRule.onNodeWithText(tag).assertIsDisplayed().performTextInput(input) + } + ) + TestCase.Common.PressButton( + GherkinLambda1 { + testRule.onNodeWithText(it).assertIsDisplayed().performClick() + } + ) + } + + private fun launchApp() { + // TODO figure out if destroying activity is needed after each test (try reordering Login.Feature scenarios to get into situations where this matters) + val instrumentation = InstrumentationRegistry.getInstrumentation() + scenario = ActivityScenario.launch( + Intent(instrumentation.targetContext, MainActivity::class.java) + .putExtra("isLoggedIn", arguments["isLoggedIn"]) + .putExtra("testEmail", arguments["testEmail"]) + ) + } +} diff --git a/android/src/androidTest/kotlin/com/corrado4eyes/cucumberplayground/test/StepDefinitions.kt b/android/src/androidTest/kotlin/com/corrado4eyes/cucumberplayground/test/StepDefinitions.kt deleted file mode 100644 index 10610f6..0000000 --- a/android/src/androidTest/kotlin/com/corrado4eyes/cucumberplayground/test/StepDefinitions.kt +++ /dev/null @@ -1,163 +0,0 @@ -package com.corrado4eyes.cucumberplayground.test - -import android.app.Activity -import android.content.Intent -import androidx.compose.ui.test.assertHasClickAction -import androidx.compose.ui.test.assertIsDisplayed -import androidx.compose.ui.test.assertTextContains -import androidx.compose.ui.test.junit4.createComposeRule -import androidx.compose.ui.test.onNodeWithTag -import androidx.compose.ui.test.onNodeWithText -import androidx.compose.ui.test.performClick -import androidx.compose.ui.test.performTextInput -import androidx.test.core.app.ActivityScenario -import androidx.test.platform.app.InstrumentationRegistry -import com.corrado4eyes.cucumber.GherkinLambda0 -import com.corrado4eyes.cucumber.GherkinLambda1 -import com.corrado4eyes.cucumber.GherkinLambda2 -import com.corrado4eyes.cucumberplayground.android.MainActivity -import com.corrado4eyes.cucumbershared.tests.TestCase -import io.cucumber.core.api.Scenario -import io.cucumber.java.After -import io.cucumber.java.AfterStep -import io.cucumber.java.Before -import io.cucumber.java.BeforeStep -import io.cucumber.java8.En -import io.cucumber.junit.WithJunitRule -import org.junit.Rule - -@WithJunitRule -class StepDefinitions : En { - - private val arguments = mutableMapOf() - private var scenario: ActivityScenario<*>? = null - - @get:Rule(order = 0) - val testRule = createComposeRule() - - @Before(order = 0) - fun beforeScenarioStart(scenario: Scenario) { - // Will run before each scenario - println("-----------------Start of Scenario ${scenario.name}-----------------") - } - - @Before(order = 1) - fun beforeScenario(scenario: Scenario) { - // Will run before each scenario but second in order - println("Running steps:") - } - - @After(order = 1) - fun afterScenarioFinish(scenario: Scenario) { - // Will run after each scenario - println("Steps completed") - } - - @After(order = 0) - fun afterScenario(scenario: Scenario) { - // Will run after each scenario but second in order - println("-----------------End of Scenario ${scenario.name}-----------------") - } - - // TODO figure out for specific step, crashes the app with exception if you try @BeforeStep("some step") - @BeforeStep - fun beforeStep(scenario: Scenario) { - // Run stuff before each scenario step - } - - @AfterStep - fun afterStep(scenario: Scenario) { - // Run stuff after each scenario step - } - - init { - TestCase.Common.ScreenIsVisible( - GherkinLambda1 { screenName -> - val screenTitleTag = when (screenName) { - "Login" -> { - arguments["isLoggedIn"] = "false" - arguments["testEmail"] = "" - "Login screen" - } - - "Home" -> { - arguments["isLoggedIn"] = "true" - "Home screen" - } - - else -> throw IllegalArgumentException("Couldn't find any $screenName screen") - } - setLaunchScreen() - testRule.onNodeWithTag(screenTitleTag).assertIsDisplayed() - } - ) - TestCase.Common.TitleIsVisible( - GherkinLambda1 { - val title = it - testRule.onNodeWithText(title).assertIsDisplayed() - } - ) - - TestCase.Common.ButtonIsVisible( - GherkinLambda1 { - when (it) { - "Login" -> testRule.onNodeWithText("Login").assertIsDisplayed().assertHasClickAction() - "Logout" -> testRule.onNodeWithTag("Logout").assertIsDisplayed().assertHasClickAction() - else -> throw IllegalArgumentException("Couldn't find $it button") - } - } - ) - TestCase.Common.NavigateToScreen( - GherkinLambda1 { - Thread.sleep(1000) - when (it) { - "Login" -> testRule.onNodeWithTag("Login screen").assertIsDisplayed() - "Home" -> testRule.onNodeWithTag("Home screen").assertIsDisplayed() - } - } - ) - TestCase.Login.Common.TextFieldIsVisible( - GherkinLambda2 { tag, text -> - testRule.onNodeWithTag(tag).assertIsDisplayed().assertTextContains(text) - } - ) - TestCase.Login.FillEmailTextField( - GherkinLambda1 { - testRule.onNodeWithText("Email").performTextInput(it) - } - ) - TestCase.Login.FillPasswordTextField( - GherkinLambda1 { - testRule.onNodeWithText("Password").performTextInput(it) - } - ) - TestCase.Login.PressLoginButton( - GherkinLambda0 { - testRule.onNodeWithText("Login").assertIsDisplayed().performClick() - } - ) - TestCase.Home.PressLogoutButton( - GherkinLambda0 { - testRule.onNodeWithTag("Logout").assertIsDisplayed().performClick() - } - ) - TestCase.Home.LoggedInEmail( - GherkinLambda1 { - arguments["testEmail"] = "test@test.com" - } - ) - } - - private fun setLaunchScreen() { - val instrumentation = InstrumentationRegistry.getInstrumentation() - launch( - Intent(instrumentation.targetContext, MainActivity::class.java) - .putExtra("isLoggedIn", arguments["isLoggedIn"]) - .putExtra("testEmail", arguments["testEmail"]) - ) - } - - private fun launch(intent: Intent) { - scenario = ActivityScenario.launch(intent) - } -} \ No newline at end of file diff --git a/android/src/main/java/com/corrado4eyes/cucumberplayground/android/login/LoginLayout.kt b/android/src/main/java/com/corrado4eyes/cucumberplayground/android/login/LoginLayout.kt index e241528..34bfc45 100644 --- a/android/src/main/java/com/corrado4eyes/cucumberplayground/android/login/LoginLayout.kt +++ b/android/src/main/java/com/corrado4eyes/cucumberplayground/android/login/LoginLayout.kt @@ -29,15 +29,15 @@ fun LoginLayout() { Text(text = this@ViewModelComposable.screenTitle, modifier = Modifier.testTag("Login screen")) CustomTextField( value = this@ViewModelComposable.emailText, - label = "Email", - modifier = Modifier.testTag("Email") + label = viewModel.emailPlaceholder, + modifier = Modifier.testTag(viewModel.emailPlaceholder) ) val emailErrorText by this@ViewModelComposable.emailErrorText.state() Text(text = emailErrorText, color = Color.Red) CustomTextField( value = this@ViewModelComposable.passwordText, - label = "Password", - modifier = Modifier.testTag("Password") + label = viewModel.passwordPlaceholder, + modifier = Modifier.testTag(viewModel.passwordPlaceholder) ) val passwordErrorText by this@ViewModelComposable.passwordErrorText.state() Text(text = passwordErrorText, color = Color.Red) diff --git a/cucumberShared/src/commonMain/kotlin/com/corrado4eyes/cucumbershared/tests/TestCase.kt b/cucumberShared/src/commonMain/kotlin/com/corrado4eyes/cucumbershared/tests/TestCase.kt index 732b29e..8760544 100644 --- a/cucumberShared/src/commonMain/kotlin/com/corrado4eyes/cucumbershared/tests/TestCase.kt +++ b/cucumberShared/src/commonMain/kotlin/com/corrado4eyes/cucumbershared/tests/TestCase.kt @@ -10,47 +10,28 @@ import com.corrado4eyes.cucumber.GherkinTestCase sealed class TestCase : GherkinTestCase { sealed class Common : TestCase() { - class ScreenIsVisible(override val lambda: GherkinLambda1) : Common() { - override val step: CucumberDefinition = CucumberDefinition.Step.GivenSingle("I am in the $EXPECT_VALUE_STRING screen", lambda) + + class TextIsVisible(override val lambda: GherkinLambda1) : Common() { + override val step: CucumberDefinition = CucumberDefinition.Step.ThenSingle("I see the $EXPECT_VALUE_STRING text", lambda) } - class TitleIsVisible(override val lambda: GherkinLambda1) : Common() { - override val step: CucumberDefinition = CucumberDefinition.Step.ThenSingle("I see $EXPECT_VALUE_STRING text", lambda) + class GivenTextIsVisible(override val lambda: GherkinLambda1) : Common() { + override val step: CucumberDefinition = CucumberDefinition.Step.GivenSingle("I see the $EXPECT_VALUE_STRING screen", lambda) } class ButtonIsVisible(override val lambda: GherkinLambda1) : Common() { override val step: CucumberDefinition = CucumberDefinition.Step.ThenSingle("I see the $EXPECT_VALUE_STRING button", lambda) } - class NavigateToScreen(override val lambda: GherkinLambda1) : Common() { - override val step: CucumberDefinition = CucumberDefinition.Step.ThenSingle("I see the $EXPECT_VALUE_STRING screen", lambda) - } - } - - sealed class Login : TestCase() { - sealed class Common : Login() { - class TextFieldIsVisible(override val lambda: GherkinLambda2) : Common() { - override val step: CucumberDefinition = CucumberDefinition.Step.ThenMultiple("I see the $EXPECT_VALUE_STRING textfield with text $EXPECT_VALUE_STRING", lambda) - } - } - class FillEmailTextField(override val lambda: GherkinLambda1) : Login() { - override val step: CucumberDefinition = CucumberDefinition.Step.ThenSingle("I type $EXPECT_VALUE_STRING in the email field", lambda) + class PressButton(override val lambda: GherkinLambda1): Common() { + override val step: CucumberDefinition = CucumberDefinition.Step.ThenSingle("I press the $EXPECT_VALUE_STRING button", lambda) } - class FillPasswordTextField(override val lambda: GherkinLambda1) : Login() { - override val step: CucumberDefinition = CucumberDefinition.Step.ThenSingle("I type $EXPECT_VALUE_STRING in the password field", lambda) - } - - class PressLoginButton(override val lambda: GherkinLambda0) : Login() { - override val step: CucumberDefinition = CucumberDefinition.Step.Then("I press the login button", lambda) - } - } - sealed class Home : TestCase() { - class LoggedInEmail(override val lambda: GherkinLambda1) : Home() { - override val step: CucumberDefinition = CucumberDefinition.Step.GivenSingle("Email is $EXPECT_VALUE_STRING", lambda) + class TextFieldIsVisible(override val lambda: GherkinLambda2) : Common() { + override val step: CucumberDefinition = CucumberDefinition.Step.ThenMultiple("I see the $EXPECT_VALUE_STRING textfield with text $EXPECT_VALUE_STRING", lambda) } - class PressLogoutButton(override val lambda: GherkinLambda0) : Login() { - override val step: CucumberDefinition = CucumberDefinition.Step.Then("I press the logout button", lambda) + class FillTextField(override val lambda: GherkinLambda2) : Common() { + override val step: CucumberDefinition = CucumberDefinition.Step.ThenMultiple("I type $EXPECT_VALUE_STRING in the $EXPECT_VALUE_STRING field", lambda) } } } \ No newline at end of file diff --git a/ios/Podfile b/ios/Podfile index 07525ae..428af09 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -3,3 +3,11 @@ target 'CucumberTests' do platform :ios, '14.1' pod 'Cucumberish' end + +post_install do |installer| + installer.pods_project.targets.each do |target| + target.build_configurations.each do |config| + config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = Gem::Version.new('14.1') + end + end +end diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 74e28cc..a37a092 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -11,6 +11,6 @@ SPEC REPOS: SPEC CHECKSUMS: Cucumberish: 6cbd0c1f50306b369acebfe7d9f514c9c287d26c -PODFILE CHECKSUM: 628c667357c176acb30372b1f5ac2574ef0cf182 +PODFILE CHECKSUM: a416e91f0850ff41496968699d0a5073dfa8a80f COCOAPODS: 1.12.1 diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index 17f5de9..b9cadf6 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -17,6 +17,7 @@ kotlin { val target: org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget.() -> Unit = { binaries { framework { + transitiveExport = true baseName = "shared" export("com.splendo.kaluga:alerts:$kalugaVersion") diff --git a/shared/src/androidMain/kotlin/com/corrado4eyes/cucumberplayground/di/CucumberDependencyInjection.kt b/shared/src/androidMain/kotlin/com/corrado4eyes/cucumberplayground/di/CucumberDependencyInjection.kt index 28bc1b4..4fbcda6 100644 --- a/shared/src/androidMain/kotlin/com/corrado4eyes/cucumberplayground/di/CucumberDependencyInjection.kt +++ b/shared/src/androidMain/kotlin/com/corrado4eyes/cucumberplayground/di/CucumberDependencyInjection.kt @@ -6,7 +6,12 @@ import com.corrado4eyes.cucumberplayground.models.TestConfiguration import com.corrado4eyes.cucumberplayground.viewModels.home.HomeViewModel import com.corrado4eyes.cucumberplayground.viewModels.login.LoginViewModel import com.corrado4eyes.cucumberplayground.viewModels.main.MainViewModel +import com.splendo.kaluga.alerts.AlertPresenter +import com.splendo.kaluga.alerts.BaseAlertPresenter +import com.splendo.kaluga.architecture.navigation.Navigator import com.splendo.kaluga.base.ApplicationHolder +import com.splendo.kaluga.hud.BaseHUD +import com.splendo.kaluga.hud.HUD import kotlinx.coroutines.Dispatchers import org.koin.android.ext.koin.androidContext import org.koin.androidx.viewmodel.dsl.viewModel @@ -18,11 +23,13 @@ import kotlin.coroutines.CoroutineContext internal actual object PlatformModuleFactory : BasePlatformModuleFactory() { override val declaration: ModuleDeclaration = { + factory { AlertPresenter.Builder() } + factory { HUD.Builder() } viewModel { LoginViewModel() } viewModel { - HomeViewModel() + HomeViewModel(get(), get()) } viewModel { (testConfig: TestConfiguration?) -> MainViewModel(testConfig) diff --git a/shared/src/commonMain/kotlin/com/corrado4eyes/cucumberplayground/viewModels/home/HomeViewModel.kt b/shared/src/commonMain/kotlin/com/corrado4eyes/cucumberplayground/viewModels/home/HomeViewModel.kt index dbc9391..365e3e3 100644 --- a/shared/src/commonMain/kotlin/com/corrado4eyes/cucumberplayground/viewModels/home/HomeViewModel.kt +++ b/shared/src/commonMain/kotlin/com/corrado4eyes/cucumberplayground/viewModels/home/HomeViewModel.kt @@ -1,12 +1,18 @@ package com.corrado4eyes.cucumberplayground.viewModels.home import com.corrado4eyes.cucumberplayground.services.AuthService +import com.splendo.kaluga.alerts.BaseAlertPresenter +import com.splendo.kaluga.alerts.buildAlert import com.splendo.kaluga.architecture.viewmodel.BaseLifecycleViewModel +import com.splendo.kaluga.hud.BaseHUD import kotlinx.coroutines.launch import org.koin.core.component.KoinComponent import org.koin.core.component.inject -class HomeViewModel : BaseLifecycleViewModel(), KoinComponent { +class HomeViewModel( + private val alertPresenterBuilder: BaseAlertPresenter.Builder, + private val hudBuilder: BaseHUD.Builder, +) : BaseLifecycleViewModel(alertPresenterBuilder), KoinComponent { private val authService: AuthService by inject() @@ -16,9 +22,24 @@ class HomeViewModel : BaseLifecycleViewModel(), KoinComponent { fun getCurrentUser() = authService.getCurrentUserIfAny()!! val user = authService.getCurrentUserIfAny()!! + private fun displayConfirmationDialog() { + alertPresenterBuilder.buildAlert(coroutineScope) { + setTitle("Are you sure you want to logout?") + setPositiveButton("Yes") { + coroutineScope.launch { + authService.logout() + } + } + setNegativeButton("No") { + // Do nothing + } + }.showAsync() + } + fun logout() { coroutineScope.launch { authService.logout() } + //displayConfirmationDialog() } } diff --git a/shared/src/commonMain/kotlin/com/corrado4eyes/cucumberplayground/viewModels/login/LoginViewModel.kt b/shared/src/commonMain/kotlin/com/corrado4eyes/cucumberplayground/viewModels/login/LoginViewModel.kt index 38641f2..f9e7cfe 100644 --- a/shared/src/commonMain/kotlin/com/corrado4eyes/cucumberplayground/viewModels/login/LoginViewModel.kt +++ b/shared/src/commonMain/kotlin/com/corrado4eyes/cucumberplayground/viewModels/login/LoginViewModel.kt @@ -82,33 +82,25 @@ class LoginViewModel : BaseLifecycleViewModel(), KoinComponent { fun login() { viewState.value = LoginViewState.Loading - coroutineScope.launch { - val password by passwordText - val email by emailText - - when { - email.value.isEmpty() -> { - viewState.value = LoginViewState.Error.EmptyField( - LoginViewState.Error.MissingField.EMAIL - ) - return@launch - } - - password.value.isEmpty() -> { - viewState.value = LoginViewState.Error.EmptyField( - LoginViewState.Error.MissingField.PASSWORD - ) - return@launch - } + val password by passwordText + val email by emailText + when { + email.value.isEmpty() -> { + viewState.value = LoginViewState.Error.EmptyField( + LoginViewState.Error.MissingField.EMAIL + ) + return } - delay(1000) - when (authService.login(email.value, password.value)) { - is AuthResponse.Success -> viewState.value = - LoginViewState.Idle // navigate to Home screen - is AuthResponse.Error -> { - viewState.value = LoginViewState.Error.IncorrectEmailOrPassword - return@launch - } + password.value.isEmpty() -> { + viewState.value = LoginViewState.Error.EmptyField( + LoginViewState.Error.MissingField.PASSWORD + ) + return + } + } + coroutineScope.launch { + if (authService.login(email.value, password.value) is AuthResponse.Error) { + viewState.value = LoginViewState.Error.IncorrectEmailOrPassword } } } diff --git a/shared/src/commonMain/kotlin/com/corrado4eyes/cucumberplayground/viewModels/main/MainViewModel.kt b/shared/src/commonMain/kotlin/com/corrado4eyes/cucumberplayground/viewModels/main/MainViewModel.kt index c206a92..1761294 100644 --- a/shared/src/commonMain/kotlin/com/corrado4eyes/cucumberplayground/viewModels/main/MainViewModel.kt +++ b/shared/src/commonMain/kotlin/com/corrado4eyes/cucumberplayground/viewModels/main/MainViewModel.kt @@ -14,9 +14,7 @@ sealed class AppNavigator { object Loading : AppNavigator() object Login : AppNavigator() - data class Home( - val user: User, - ) : AppNavigator() + object Home : AppNavigator() } class MainViewModel( @@ -37,7 +35,7 @@ class MainViewModel( } authService.observeUser.collect { user -> user?.let { - _navState.value = AppNavigator.Home(it) + _navState.value = AppNavigator.Home } ?: run { _navState.value = AppNavigator.Login } From f1cd024629ace49a8f4668f0f69deaf43cf4ccc8 Mon Sep 17 00:00:00 2001 From: corrado4eyes Date: Thu, 24 Aug 2023 16:12:33 +0200 Subject: [PATCH 03/10] Update feature files --- .../androidTest/assets/features/Login.feature | 2 +- ios/CucumberTests/Features/Home.feature | 6 +-- ios/CucumberTests/Features/Login.feature | 46 ++++++++++++++++--- 3 files changed, 44 insertions(+), 10 deletions(-) diff --git a/android/src/androidTest/assets/features/Login.feature b/android/src/androidTest/assets/features/Login.feature index 8633d26..bc1c551 100644 --- a/android/src/androidTest/assets/features/Login.feature +++ b/android/src/androidTest/assets/features/Login.feature @@ -3,7 +3,7 @@ Feature: Login Scenario: Failed attempt with wrong credentials Given I see the "Login screen" screen Then I see the "Email" textfield with text "Email" - Then I type "test@test.comunism" in the "Email" field + Then I type "test@test.fail" in the "Email" field Then I see the "Password" textfield with text "Password" Then I type "1234" in the "Password" field Then I see the "Login" button diff --git a/ios/CucumberTests/Features/Home.feature b/ios/CucumberTests/Features/Home.feature index 177cb42..fe405e7 100644 --- a/ios/CucumberTests/Features/Home.feature +++ b/ios/CucumberTests/Features/Home.feature @@ -1,8 +1,8 @@ Feature: Home Scenario: Home screen Given Email is "test@test.com" - Given I am in the "Home" screen - Then I see "test@test.com" text + Given I see the "Home screen" screen + Then I see the "test@test.com" text Then I see the "Logout" button - Then I press the logout button + Then I press the "Logout" button Then I see the "Login" screen diff --git a/ios/CucumberTests/Features/Login.feature b/ios/CucumberTests/Features/Login.feature index ec36c05..0c6ed93 100644 --- a/ios/CucumberTests/Features/Login.feature +++ b/ios/CucumberTests/Features/Login.feature @@ -1,11 +1,45 @@ Feature: Login Scenario: Login screen - Given I am in the "Login" screen + Given I see the "Login screen" screen Then I see the "Email" textfield with text "Email" - Then I type "test@test.com" in the email field Then I see the "Password" textfield with text "Password" - Then I type "1234" in the password field Then I see the "Login" button - Then I press the login button - Then I see the "Home" screen - Then I see "test@test.com" text + + Scenario: Failed attempt with wrong credentials + Given I see the "Login screen" screen + Then I see the "Email" textfield with text "Email" + Then I type "test@test.fail" in the "Email" field + Then I see the "Password" textfield with text "Password" + Then I type "1234" in the password field called "Password" + Then I see the "Login" button + Then I press the "Login" button + Then I see the "Incorrect email or password" text + + Scenario: Failed attempt with empty email + Given I see the "Login screen" screen + Then I see the "Email" textfield with text "Email" + Then I see the "Password" textfield with text "Password" + Then I type "1234" in the password field called "Password" + Then I see the "Login" button + Then I press the "Login" button + Then I see the "Missing email" text + + Scenario: Failed attempt with empty password + Given I see the "Login screen" screen + Then I see the "Email" textfield with text "Email" + Then I see the "Password" textfield with text "Password" + Then I type "alex@alex" in the "Email" field + Then I see the "Login" button + Then I press the "Login" button + Then I see the "Missing password" text + + Scenario: Successful attempt + Given I see the "Login screen" screen + Then I see the "Email" textfield with text "Email" + Then I type "test@test.com" in the "Email" field + Then I see the "Password" textfield with text "Password" + Then I type "1234" in the password field called "Password" + Then I see the "Login" button + Then I press the "Login" button + Then I see the "Home screen" text + Then I see the "test@test.com" text From 9ee329121f388b3342a4bd9ce6a61c7d2dab9ca7 Mon Sep 17 00:00:00 2001 From: corrado4eyes Date: Thu, 24 Aug 2023 16:15:30 +0200 Subject: [PATCH 04/10] Update ios views --- ios/CucumberTests/CucumberTests.swift | 46 +++++++++++---------------- ios/ios/ContentView.swift | 5 +-- ios/ios/Screens/Home/HomeView.swift | 12 +++++-- ios/ios/Screens/Login/LoginView.swift | 3 +- 4 files changed, 33 insertions(+), 33 deletions(-) diff --git a/ios/CucumberTests/CucumberTests.swift b/ios/CucumberTests/CucumberTests.swift index 0110e27..2aa9c6b 100644 --- a/ios/CucumberTests/CucumberTests.swift +++ b/ios/CucumberTests/CucumberTests.swift @@ -21,15 +21,16 @@ import Cucumberish app.launchArguments.append("test") } + TestCaseCommonScreenIsVisible { args, userInfo in guard let screenName = args?[0] as? String else { return KotlinUnit() } let text: XCUIElement switch(screenName) { - case "Home": + case "Home screen": app.launchEnvironment["isLoggedIn"] = "true" text = app.staticTexts["Home screen"] - case "Login": + case "Login screen": app.launchEnvironment["isLoggedIn"] = "false" text = app.staticTexts["Login screen"] @@ -40,18 +41,18 @@ import Cucumberish app.launch() - XCTAssert(text.exists(timeout: .short), "Couldn't validate to be in \(screenName)") + XCTAssert(text.exists(timeout: .long), "Couldn't validate to be in \(screenName)") return KotlinUnit() } - TestCaseCommonTitleIsVisible { args, userInfo in + TestCaseCommonTextIsVisible { args, userInfo in guard let textString = args?[0] as? String else { return KotlinUnit() } let text = app.staticTexts[textString] XCTAssert(text.exists(timeout: .short), "Couldn't find \(text) text") return KotlinUnit() } - TestCaseLoginCommonTextFieldIsVisible { args, userInfo in + TestCaseCommonTextFieldIsVisible { args, userInfo in guard let textfieldName = args?[0] as? String else { return KotlinUnit() } guard let textfieldText = args?[1] as? String else { return KotlinUnit() } let textfield: XCUIElement? = { @@ -73,15 +74,16 @@ import Cucumberish return KotlinUnit() } - TestCaseLoginFillEmailTextField { args, userInfo in - guard let email = args?[0] as? String else { return KotlinUnit() } - let textfield = app.textFields["Email"] + TestCaseCommonFillTextField { args, userInfo in + guard let textFieldText = args?[1] as? String else { return KotlinUnit() } + guard let text = args?[0] as? String else { return KotlinUnit() } + let textfield = app.textFields[textFieldText] textfield.tap() - textfield.typeText(email) + textfield.typeText(text) return KotlinUnit() } - TestCaseLoginFillPasswordTextField { args, userInfo in + TestCaseCommonFillPasswordTextField { args, userInfo in guard let password = args?[0] as? String else { return KotlinUnit() } let textfield = app.secureTextFields["Password"] textfield.tap() @@ -96,20 +98,21 @@ import Cucumberish return KotlinUnit() } - TestCaseLoginPressLoginButton { args, userInfo in - let button = app.buttons["Login"] - let link = app.links["Login"] + TestCaseCommonPressButton { args, userInfo in + guard let buttonString = args?[0] as? String else { return KotlinUnit() } + let button = app.buttons[buttonString] + let link = app.links[buttonString] if button.exists(timeout: .medium) && button.isEnabled(timeout: .short) { button.tap() } else if link.exists(timeout: .medium) && link.isEnabled(timeout: .short) { link.tap() } else { - XCTFail("I press Login button failed") + XCTFail("I press \(buttonString) button failed") } return KotlinUnit() } - TestCaseHomeLoggedInEmail { args, userInfo in + TestCaseCommonLoggedInEmail { args, userInfo in guard let email = args?[0] as? String else { return KotlinUnit() } app.launchEnvironment["testEmail"] = email return KotlinUnit() @@ -129,19 +132,6 @@ import Cucumberish return KotlinUnit() } - TestCaseHomePressLogoutButton { args, userInfo in - let button = app.buttons["Logout"] - let link = app.links["Logout"] - if button.exists(timeout: .medium) && button.isEnabled(timeout: .short) { - button.tap() - } else if link.exists(timeout: .medium) && link.isEnabled(timeout: .short) { - link.tap() - } else { - XCTFail("I press Logout button failed") - } - return KotlinUnit() - } - let bundle = Bundle(for: CucumberishInitializer.self) Cucumberish.executeFeatures(inDirectory: "Features", from: bundle, includeTags: nil, excludeTags: ["ignore"]) } diff --git a/ios/ios/ContentView.swift b/ios/ios/ContentView.swift index 4a5d865..fe4efff 100644 --- a/ios/ios/ContentView.swift +++ b/ios/ios/ContentView.swift @@ -27,12 +27,13 @@ struct ContentView: View { viewModel = LifecycleViewModel(mainViewModel) navState = ObjectObservable(mainViewModel.navState) } + var body: some View { NavigationView { if navState.value is AppNavigator.Home { - HomeView(user: (navState.value as! AppNavigator.Home).user, authService: authService) + HomeView() } else if navState.value is AppNavigator.Login{ - LoginView(authService: authService) + LoginView() } else { ProgressView() } diff --git a/ios/ios/Screens/Home/HomeView.swift b/ios/ios/Screens/Home/HomeView.swift index fc557f0..d20c7c7 100644 --- a/ios/ios/Screens/Home/HomeView.swift +++ b/ios/ios/Screens/Home/HomeView.swift @@ -11,9 +11,16 @@ import shared struct HomeView: SwiftUI.View { private let viewModel: LifecycleViewModel + private let containerView = ContainerView(.alert, .hud) - init(user: User, authService: AuthService) { - viewModel = LifecycleViewModel(HomeViewModel()) + init() { + viewModel = LifecycleViewModel( + HomeViewModel( + alertPresenterBuilder: containerView.alertBuilder, + hudBuilder: containerView.hudBuilder + ), + containerView: containerView + ) } var body: some View { @@ -29,6 +36,7 @@ struct HomeView: SwiftUI.View { }.toolbar { ToolbarItem(placement: .principal) { Text(viewModel.screenTitle) + .accessibilityLabel(viewModel.screenTitle) } }.navigationBarTitleDisplayMode(.inline) } diff --git a/ios/ios/Screens/Login/LoginView.swift b/ios/ios/Screens/Login/LoginView.swift index 69ab862..63c58f2 100644 --- a/ios/ios/Screens/Login/LoginView.swift +++ b/ios/ios/Screens/Login/LoginView.swift @@ -22,7 +22,7 @@ struct LoginView: SwiftUI.View { private let viewModel: LifecycleViewModel - init(authService: AuthService) { + init() { let loginViewModel = LoginViewModel() viewModel = LifecycleViewModel(loginViewModel) emailText = StringSubject(loginViewModel.emailText) @@ -67,6 +67,7 @@ struct LoginView: SwiftUI.View { .toolbar { ToolbarItem(placement: .principal) { Text(viewModel.screenTitle) + .accessibilityLabel(viewModel.screenTitle) } }.navigationBarTitleDisplayMode(.inline) } From 6c9f56eeef0fe5cbfc6ec679483faa36d3d16ad8 Mon Sep 17 00:00:00 2001 From: corrado4eyes Date: Thu, 24 Aug 2023 16:16:04 +0200 Subject: [PATCH 05/10] Update test cases and usages --- .../test/CommonStepDefinitions.kt | 2 +- .../corrado4eyes/cucumber/CucumberDefinition.kt | 4 ++-- .../cucumbershared/tests/TestCase.kt | 17 ++++++++++++++--- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/android/src/androidTest/kotlin/com/corrado4eyes/cucumberplayground/test/CommonStepDefinitions.kt b/android/src/androidTest/kotlin/com/corrado4eyes/cucumberplayground/test/CommonStepDefinitions.kt index 5d08b1c..50cb20f 100644 --- a/android/src/androidTest/kotlin/com/corrado4eyes/cucumberplayground/test/CommonStepDefinitions.kt +++ b/android/src/androidTest/kotlin/com/corrado4eyes/cucumberplayground/test/CommonStepDefinitions.kt @@ -77,7 +77,7 @@ class CommonStepDefinitions : En { testRule.onNodeWithText(it).assertIsDisplayed() } ) - TestCase.Common.GivenTextIsVisible( + TestCase.Common.ScreenIsVisible( GherkinLambda1 { testRule.onNodeWithText(it).assertIsDisplayed() } diff --git a/cucumber/src/commonMain/kotlin/com/corrado4eyes/cucumber/CucumberDefinition.kt b/cucumber/src/commonMain/kotlin/com/corrado4eyes/cucumber/CucumberDefinition.kt index c37df4e..db1ca93 100644 --- a/cucumber/src/commonMain/kotlin/com/corrado4eyes/cucumber/CucumberDefinition.kt +++ b/cucumber/src/commonMain/kotlin/com/corrado4eyes/cucumber/CucumberDefinition.kt @@ -157,8 +157,8 @@ sealed class CucumberDefinition(val regex: String, execute: () -> Unit = {}): Ba } } -interface GherkinTestCase { - val step: D +interface GherkinTestCase { + val step: CucumberDefinition val lambda: L } diff --git a/cucumberShared/src/commonMain/kotlin/com/corrado4eyes/cucumbershared/tests/TestCase.kt b/cucumberShared/src/commonMain/kotlin/com/corrado4eyes/cucumbershared/tests/TestCase.kt index 8760544..3065729 100644 --- a/cucumberShared/src/commonMain/kotlin/com/corrado4eyes/cucumbershared/tests/TestCase.kt +++ b/cucumberShared/src/commonMain/kotlin/com/corrado4eyes/cucumbershared/tests/TestCase.kt @@ -3,9 +3,8 @@ package com.corrado4eyes.cucumbershared.tests import com.corrado4eyes.cucumber.CucumberDefinition import com.corrado4eyes.cucumber.EXPECT_VALUE_STRING import com.corrado4eyes.cucumber.GherkinLambda -import com.corrado4eyes.cucumber.GherkinLambda0 -import com.corrado4eyes.cucumber.GherkinLambda2 import com.corrado4eyes.cucumber.GherkinLambda1 +import com.corrado4eyes.cucumber.GherkinLambda2 import com.corrado4eyes.cucumber.GherkinTestCase sealed class TestCase : GherkinTestCase { @@ -15,7 +14,7 @@ sealed class TestCase : GherkinTestCase { override val step: CucumberDefinition = CucumberDefinition.Step.ThenSingle("I see the $EXPECT_VALUE_STRING text", lambda) } - class GivenTextIsVisible(override val lambda: GherkinLambda1) : Common() { + class ScreenIsVisible(override val lambda: GherkinLambda1) : Common() { override val step: CucumberDefinition = CucumberDefinition.Step.GivenSingle("I see the $EXPECT_VALUE_STRING screen", lambda) } @@ -33,5 +32,17 @@ sealed class TestCase : GherkinTestCase { class FillTextField(override val lambda: GherkinLambda2) : Common() { override val step: CucumberDefinition = CucumberDefinition.Step.ThenMultiple("I type $EXPECT_VALUE_STRING in the $EXPECT_VALUE_STRING field", lambda) } + + class FillPasswordTextField(override val lambda: GherkinLambda2) : Common() { + override val step: CucumberDefinition = CucumberDefinition.Step.ThenMultiple("I type $EXPECT_VALUE_STRING in the password field called $EXPECT_VALUE_STRING", lambda) + } + + class NavigateToScreen(override val lambda: GherkinLambda1) : Common() { + override val step: CucumberDefinition.Step.ThenSingle = CucumberDefinition.Step.ThenSingle("I see the $EXPECT_VALUE_STRING screen", lambda) + } + + class LoggedInEmail(override val lambda: GherkinLambda1) : Common() { + override val step: CucumberDefinition.Step.GivenSingle = CucumberDefinition.Step.GivenSingle("Email is $EXPECT_VALUE_STRING", lambda) + } } } \ No newline at end of file From 3be75fbf4a4821ec1bebcc894d002b997d1e4189 Mon Sep 17 00:00:00 2001 From: corrado4eyes Date: Thu, 24 Aug 2023 16:16:23 +0200 Subject: [PATCH 06/10] Update kaluga-swiftui --- ios/ios.xcodeproj/project.pbxproj | 4 ++++ ios/kaluga.sourcery.yml | 3 +-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ios/ios.xcodeproj/project.pbxproj b/ios/ios.xcodeproj/project.pbxproj index 0323218..56b9047 100644 --- a/ios/ios.xcodeproj/project.pbxproj +++ b/ios/ios.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 019B36888F555E147DF0B2B3 /* KeyboardManager.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0771BA10F31A50A9BC22A18 /* KeyboardManager.generated.swift */; }; 04754A9886060761775E2E1B /* KalugaLabel+SwiftUI.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3A826344DD859D1A70A50DA /* KalugaLabel+SwiftUI.generated.swift */; }; 058557BB273AAA24004C7B11 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 058557BA273AAA24004C7B11 /* Assets.xcassets */; }; 058557D9273AAEEB004C7B11 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 058557D8273AAEEB004C7B11 /* Preview Assets.xcassets */; }; @@ -117,6 +118,7 @@ D963EF3C4F0C141A4A80C891 /* KalugaStyledString+SwiftUI.generated.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; path = "KalugaStyledString+SwiftUI.generated.swift"; sourceTree = ""; }; E52FF51F397E317F81326758 /* TintedImage+Image.generated.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; path = "TintedImage+Image.generated.swift"; sourceTree = ""; }; EA6CBAFDA191747DE6BFB4B0 /* LazyView.generated.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; path = LazyView.generated.swift; sourceTree = ""; }; + F0771BA10F31A50A9BC22A18 /* KeyboardManager.generated.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; lastKnownFileType = sourcecode.swift; name = KeyboardManager.generated.swift; path = KeyboardManager.generated.swift; sourceTree = ""; }; F3A826344DD859D1A70A50DA /* KalugaLabel+SwiftUI.generated.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; path = "KalugaLabel+SwiftUI.generated.swift"; sourceTree = ""; }; F45727342CFD5BEA57D61051 /* Subject.generated.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; path = Subject.generated.swift; sourceTree = ""; }; F91AE96E17B56B56CB7AF766 /* KalugaBackgroundStyle+SwiftUI.generated.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; path = "KalugaBackgroundStyle+SwiftUI.generated.swift"; sourceTree = ""; }; @@ -285,6 +287,7 @@ E52FF51F397E317F81326758 /* TintedImage+Image.generated.swift */, 48B350D3EB640C8B7B253753 /* UninitializedObservable.generated.swift */, 191BB22D1226AD539DDC6631 /* UninitializedSubject.generated.swift */, + F0771BA10F31A50A9BC22A18 /* KeyboardManager.generated.swift */, ); path = KalugaSwiftUI; sourceTree = ""; @@ -539,6 +542,7 @@ A0E41188A70FBC3218884E58 /* TintedImage+Image.generated.swift in Sources */, E0B3E5622CB67E29A284CAAC /* UninitializedObservable.generated.swift in Sources */, FAF26C36EFC614CD413B9488 /* UninitializedSubject.generated.swift in Sources */, + 019B36888F555E147DF0B2B3 /* KeyboardManager.generated.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/ios/kaluga.sourcery.yml b/ios/kaluga.sourcery.yml index 4ea1618..3ce9529 100644 --- a/ios/kaluga.sourcery.yml +++ b/ios/kaluga.sourcery.yml @@ -15,8 +15,7 @@ args: sharedFrameworkName: shared includeResources: true includeAlerts: true - includeHud: false + includeHud: true includeDatePicker: false - includeKeyboard: true includePartialSheet: false includeKeyboard: false From bf4e195a4adec6ee05c3777e7b175bab25a5a85d Mon Sep 17 00:00:00 2001 From: corrado4eyes Date: Thu, 24 Aug 2023 16:16:43 +0200 Subject: [PATCH 07/10] Update kaluga-swiftui --- dependencies/kaluga-swiftui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/kaluga-swiftui b/dependencies/kaluga-swiftui index 260db7b..10572cb 160000 --- a/dependencies/kaluga-swiftui +++ b/dependencies/kaluga-swiftui @@ -1 +1 @@ -Subproject commit 260db7bd1ec2552d407433d4ebd3ec1ab27cadb1 +Subproject commit 10572cb05e4df9f2fe1b7e8cde6b48df29d6b4b3 From 2d837d71635b794b8edc0df5a18042620181018f Mon Sep 17 00:00:00 2001 From: corrado4eyes Date: Fri, 25 Aug 2023 09:19:58 +0200 Subject: [PATCH 08/10] Delete unused case --- .../kotlin/com/corrado4eyes/cucumbershared/tests/TestCase.kt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cucumberShared/src/commonMain/kotlin/com/corrado4eyes/cucumbershared/tests/TestCase.kt b/cucumberShared/src/commonMain/kotlin/com/corrado4eyes/cucumbershared/tests/TestCase.kt index 3065729..b9b1cdc 100644 --- a/cucumberShared/src/commonMain/kotlin/com/corrado4eyes/cucumbershared/tests/TestCase.kt +++ b/cucumberShared/src/commonMain/kotlin/com/corrado4eyes/cucumbershared/tests/TestCase.kt @@ -37,10 +37,6 @@ sealed class TestCase : GherkinTestCase { override val step: CucumberDefinition = CucumberDefinition.Step.ThenMultiple("I type $EXPECT_VALUE_STRING in the password field called $EXPECT_VALUE_STRING", lambda) } - class NavigateToScreen(override val lambda: GherkinLambda1) : Common() { - override val step: CucumberDefinition.Step.ThenSingle = CucumberDefinition.Step.ThenSingle("I see the $EXPECT_VALUE_STRING screen", lambda) - } - class LoggedInEmail(override val lambda: GherkinLambda1) : Common() { override val step: CucumberDefinition.Step.GivenSingle = CucumberDefinition.Step.GivenSingle("Email is $EXPECT_VALUE_STRING", lambda) } From 94be8493487d47a12338d5b86a3d444e000f844d Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 30 Aug 2023 14:48:54 +0200 Subject: [PATCH 09/10] Minor changes. --- .../androidTest/assets/features/Login.feature | 24 ++++----------- .../test/CommonStepDefinitions.kt | 11 +++---- .../android/login/LoginLayout.kt | 10 +++++-- dependencies/kaluga-swiftui | 2 +- ios/CucumberTests/Features/Login.feature | 30 +++++-------------- ios/ios.xcodeproj/project.pbxproj | 18 ++++++----- ios/ios/Info.plist | 6 ++-- 7 files changed, 42 insertions(+), 59 deletions(-) diff --git a/android/src/androidTest/assets/features/Login.feature b/android/src/androidTest/assets/features/Login.feature index bc1c551..1259d1a 100644 --- a/android/src/androidTest/assets/features/Login.feature +++ b/android/src/androidTest/assets/features/Login.feature @@ -1,43 +1,31 @@ Feature: Login - Scenario: Failed attempt with wrong credentials + # will run before each scenario + Background: Given I see the "Login screen" screen Then I see the "Email" textfield with text "Email" - Then I type "test@test.fail" in the "Email" field Then I see the "Password" textfield with text "Password" - Then I type "1234" in the "Password" field Then I see the "Login" button + + Scenario: Failed attempt with wrong credentials + Then I type "test@test.fail" in the "Email" field + Then I type "1234" in the "Password" field Then I press the "Login" button - Then I see the "Login" text Then I see the "Incorrect email or password" text Scenario: Failed attempt with empty email - Given I see the "Login screen" screen - Then I see the "Email" textfield with text "Email" - Then I see the "Password" textfield with text "Password" Then I type "1234" in the "Password" field - Then I see the "Login" button Then I press the "Login" button - Then I see the "Login" text Then I see the "Missing email" text Scenario: Failed attempt with empty password - Given I see the "Login screen" screen - Then I see the "Email" textfield with text "Email" - Then I see the "Password" textfield with text "Password" Then I type "alex@alex" in the "Email" field - Then I see the "Login" button Then I press the "Login" button - Then I see the "Login" text Then I see the "Missing password" text Scenario: Successful attempt - Given I see the "Login screen" screen - Then I see the "Email" textfield with text "Email" Then I type "test@test.com" in the "Email" field - Then I see the "Password" textfield with text "Password" Then I type "1234" in the "Password" field - Then I see the "Login" button Then I press the "Login" button Then I see the "Home screen" text Then I see the "test@test.com" text \ No newline at end of file diff --git a/android/src/androidTest/kotlin/com/corrado4eyes/cucumberplayground/test/CommonStepDefinitions.kt b/android/src/androidTest/kotlin/com/corrado4eyes/cucumberplayground/test/CommonStepDefinitions.kt index 50cb20f..440e675 100644 --- a/android/src/androidTest/kotlin/com/corrado4eyes/cucumberplayground/test/CommonStepDefinitions.kt +++ b/android/src/androidTest/kotlin/com/corrado4eyes/cucumberplayground/test/CommonStepDefinitions.kt @@ -33,7 +33,7 @@ class CommonStepDefinitions : En { val testRule = createComposeRule() @Before(order = 0) - fun beforeScenarioStart1(scenario: io.cucumber.core.api.Scenario) { + fun beforeScenarioStart(scenario: io.cucumber.core.api.Scenario) { // Will run before each scenario println("-----------------Start of Scenario ${scenario.name}-----------------") when (val scenarioName = scenario.name) { @@ -55,7 +55,7 @@ class CommonStepDefinitions : En { } @After(order = 0) - fun afterScenarioFinish2(cucuScenario: io.cucumber.core.api.Scenario) { + fun afterScenarioFinish(cucuScenario: io.cucumber.core.api.Scenario) { // Will run after each scenario but first in order println("-----------------End of Scenario ${cucuScenario.name}-----------------") } @@ -78,8 +78,9 @@ class CommonStepDefinitions : En { } ) TestCase.Common.ScreenIsVisible( + // TODO consider using UI tags for this as it is not necessary the view will contain text GherkinLambda1 { - testRule.onNodeWithText(it).assertIsDisplayed() + testRule.onNodeWithTag(it).assertIsDisplayed() } ) TestCase.Common.ButtonIsVisible( @@ -95,12 +96,12 @@ class CommonStepDefinitions : En { ) TestCase.Common.FillTextField( GherkinLambda2 { input, tag -> - testRule.onNodeWithText(tag).assertIsDisplayed().performTextInput(input) + testRule.onNodeWithTag(tag).assertIsDisplayed().performTextInput(input) } ) TestCase.Common.PressButton( GherkinLambda1 { - testRule.onNodeWithText(it).assertIsDisplayed().performClick() + testRule.onNodeWithTag(it).assertIsDisplayed().performClick() } ) } diff --git a/android/src/main/java/com/corrado4eyes/cucumberplayground/android/login/LoginLayout.kt b/android/src/main/java/com/corrado4eyes/cucumberplayground/android/login/LoginLayout.kt index 34bfc45..b4a6f91 100644 --- a/android/src/main/java/com/corrado4eyes/cucumberplayground/android/login/LoginLayout.kt +++ b/android/src/main/java/com/corrado4eyes/cucumberplayground/android/login/LoginLayout.kt @@ -26,7 +26,10 @@ fun LoginLayout() { ViewModelComposable(viewModel) { val isLoading by this.isLoading.state() Column { - Text(text = this@ViewModelComposable.screenTitle, modifier = Modifier.testTag("Login screen")) + Text( + text = this@ViewModelComposable.screenTitle, + modifier = Modifier.testTag("Login screen") + ) CustomTextField( value = this@ViewModelComposable.emailText, label = viewModel.emailPlaceholder, @@ -48,7 +51,10 @@ fun LoginLayout() { CircularProgressIndicator() } - Button(this@ViewModelComposable::login) { + Button( + onClick = this@ViewModelComposable::login, + modifier = Modifier.testTag("Login") + ) { Text("Login") } } diff --git a/dependencies/kaluga-swiftui b/dependencies/kaluga-swiftui index 10572cb..260db7b 160000 --- a/dependencies/kaluga-swiftui +++ b/dependencies/kaluga-swiftui @@ -1 +1 @@ -Subproject commit 10572cb05e4df9f2fe1b7e8cde6b48df29d6b4b3 +Subproject commit 260db7bd1ec2552d407433d4ebd3ec1ab27cadb1 diff --git a/ios/CucumberTests/Features/Login.feature b/ios/CucumberTests/Features/Login.feature index 0c6ed93..1259d1a 100644 --- a/ios/CucumberTests/Features/Login.feature +++ b/ios/CucumberTests/Features/Login.feature @@ -1,45 +1,31 @@ Feature: Login - Scenario: Login screen + + # will run before each scenario + Background: Given I see the "Login screen" screen Then I see the "Email" textfield with text "Email" Then I see the "Password" textfield with text "Password" Then I see the "Login" button - + Scenario: Failed attempt with wrong credentials - Given I see the "Login screen" screen - Then I see the "Email" textfield with text "Email" Then I type "test@test.fail" in the "Email" field - Then I see the "Password" textfield with text "Password" - Then I type "1234" in the password field called "Password" - Then I see the "Login" button + Then I type "1234" in the "Password" field Then I press the "Login" button Then I see the "Incorrect email or password" text Scenario: Failed attempt with empty email - Given I see the "Login screen" screen - Then I see the "Email" textfield with text "Email" - Then I see the "Password" textfield with text "Password" - Then I type "1234" in the password field called "Password" - Then I see the "Login" button + Then I type "1234" in the "Password" field Then I press the "Login" button Then I see the "Missing email" text Scenario: Failed attempt with empty password - Given I see the "Login screen" screen - Then I see the "Email" textfield with text "Email" - Then I see the "Password" textfield with text "Password" Then I type "alex@alex" in the "Email" field - Then I see the "Login" button Then I press the "Login" button Then I see the "Missing password" text Scenario: Successful attempt - Given I see the "Login screen" screen - Then I see the "Email" textfield with text "Email" Then I type "test@test.com" in the "Email" field - Then I see the "Password" textfield with text "Password" - Then I type "1234" in the password field called "Password" - Then I see the "Login" button + Then I type "1234" in the "Password" field Then I press the "Login" button Then I see the "Home screen" text - Then I see the "test@test.com" text + Then I see the "test@test.com" text \ No newline at end of file diff --git a/ios/ios.xcodeproj/project.pbxproj b/ios/ios.xcodeproj/project.pbxproj index 56b9047..584cf1f 100644 --- a/ios/ios.xcodeproj/project.pbxproj +++ b/ios/ios.xcodeproj/project.pbxproj @@ -7,7 +7,6 @@ objects = { /* Begin PBXBuildFile section */ - 019B36888F555E147DF0B2B3 /* KeyboardManager.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0771BA10F31A50A9BC22A18 /* KeyboardManager.generated.swift */; }; 04754A9886060761775E2E1B /* KalugaLabel+SwiftUI.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3A826344DD859D1A70A50DA /* KalugaLabel+SwiftUI.generated.swift */; }; 058557BB273AAA24004C7B11 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 058557BA273AAA24004C7B11 /* Assets.xcassets */; }; 058557D9273AAEEB004C7B11 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 058557D8273AAEEB004C7B11 /* Preview Assets.xcassets */; }; @@ -118,7 +117,6 @@ D963EF3C4F0C141A4A80C891 /* KalugaStyledString+SwiftUI.generated.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; path = "KalugaStyledString+SwiftUI.generated.swift"; sourceTree = ""; }; E52FF51F397E317F81326758 /* TintedImage+Image.generated.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; path = "TintedImage+Image.generated.swift"; sourceTree = ""; }; EA6CBAFDA191747DE6BFB4B0 /* LazyView.generated.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; path = LazyView.generated.swift; sourceTree = ""; }; - F0771BA10F31A50A9BC22A18 /* KeyboardManager.generated.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; lastKnownFileType = sourcecode.swift; name = KeyboardManager.generated.swift; path = KeyboardManager.generated.swift; sourceTree = ""; }; F3A826344DD859D1A70A50DA /* KalugaLabel+SwiftUI.generated.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; path = "KalugaLabel+SwiftUI.generated.swift"; sourceTree = ""; }; F45727342CFD5BEA57D61051 /* Subject.generated.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; path = Subject.generated.swift; sourceTree = ""; }; F91AE96E17B56B56CB7AF766 /* KalugaBackgroundStyle+SwiftUI.generated.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; path = "KalugaBackgroundStyle+SwiftUI.generated.swift"; sourceTree = ""; }; @@ -287,7 +285,6 @@ E52FF51F397E317F81326758 /* TintedImage+Image.generated.swift */, 48B350D3EB640C8B7B253753 /* UninitializedObservable.generated.swift */, 191BB22D1226AD539DDC6631 /* UninitializedSubject.generated.swift */, - F0771BA10F31A50A9BC22A18 /* KeyboardManager.generated.swift */, ); path = KalugaSwiftUI; sourceTree = ""; @@ -401,10 +398,14 @@ inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-CucumberTests/Pods-CucumberTests-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); + inputPaths = ( + ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-CucumberTests/Pods-CucumberTests-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); + outputPaths = ( + ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-CucumberTests/Pods-CucumberTests-frameworks.sh\"\n"; @@ -542,7 +543,6 @@ A0E41188A70FBC3218884E58 /* TintedImage+Image.generated.swift in Sources */, E0B3E5622CB67E29A284CAAC /* UninitializedObservable.generated.swift in Sources */, FAF26C36EFC614CD413B9488 /* UninitializedSubject.generated.swift in Sources */, - 019B36888F555E147DF0B2B3 /* KeyboardManager.generated.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -559,7 +559,7 @@ CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = dwarf; DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = NHQ559J67Q; + DEVELOPMENT_TEAM = AQA8K92RVA; FRAMEWORK_SEARCH_PATHS = ( "\"$(PLATFORM_DIR)/Developer/Library/Frameworks\"", "$(inherited)", @@ -600,7 +600,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = NHQ559J67Q; + DEVELOPMENT_TEAM = AQA8K92RVA; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(FRAMEWORK_SEARCH_PATHS)", @@ -752,6 +752,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_ASSET_PATHS = "\"ios/Preview Content\""; + DEVELOPMENT_TEAM = AQA8K92RVA; ENABLE_PREVIEWS = YES; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -768,7 +769,7 @@ "-framework", shared, ); - PRODUCT_BUNDLE_IDENTIFIER = orgIdentifier.ios; + PRODUCT_BUNDLE_IDENTIFIER = orgIdentifier.ios.alex; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -781,6 +782,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_ASSET_PATHS = "\"ios/Preview Content\""; + DEVELOPMENT_TEAM = AQA8K92RVA; ENABLE_PREVIEWS = YES; FRAMEWORK_SEARCH_PATHS = "$(SRCROOT)/../shared/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)"; INFOPLIST_FILE = ios/Info.plist; @@ -793,7 +795,7 @@ "-framework", shared, ); - PRODUCT_BUNDLE_IDENTIFIER = orgIdentifier.ios; + PRODUCT_BUNDLE_IDENTIFIER = orgIdentifier.ios.alex; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/ios/ios/Info.plist b/ios/ios/Info.plist index 8044709..9a269f5 100644 --- a/ios/ios/Info.plist +++ b/ios/ios/Info.plist @@ -25,6 +25,8 @@ UIApplicationSupportsMultipleScenes + UILaunchScreen + UIRequiredDeviceCapabilities armv7 @@ -42,7 +44,5 @@ UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight - UILaunchScreen - - \ No newline at end of file + From 7b4bfe8ccd77c6d0e4a84c942f59f4a0d0ca1445 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 31 Aug 2023 11:19:06 +0200 Subject: [PATCH 10/10] Replaced sequential When / Then with And --- .../src/androidTest/assets/features/Login.feature | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/android/src/androidTest/assets/features/Login.feature b/android/src/androidTest/assets/features/Login.feature index 1259d1a..d414320 100644 --- a/android/src/androidTest/assets/features/Login.feature +++ b/android/src/androidTest/assets/features/Login.feature @@ -4,19 +4,19 @@ Feature: Login Background: Given I see the "Login screen" screen Then I see the "Email" textfield with text "Email" - Then I see the "Password" textfield with text "Password" - Then I see the "Login" button + And I see the "Password" textfield with text "Password" + And I see the "Login" button Scenario: Failed attempt with wrong credentials Then I type "test@test.fail" in the "Email" field - Then I type "1234" in the "Password" field - Then I press the "Login" button - Then I see the "Incorrect email or password" text + And I type "1234" in the "Password" field + And I press the "Login" button + And I see the "Incorrect email or password" text Scenario: Failed attempt with empty email Then I type "1234" in the "Password" field - Then I press the "Login" button - Then I see the "Missing email" text + And I press the "Login" button + And I see the "Missing email" text Scenario: Failed attempt with empty password Then I type "alex@alex" in the "Email" field