Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Made examples more generic and added some more printing examples #24

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
2 changes: 1 addition & 1 deletion android/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
12 changes: 6 additions & 6 deletions android/src/androidTest/assets/features/Home.feature
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
Feature: Home
Scenario: Home screen
Given Email is "[email protected]"
Given I am in the "Home" screen
Then I see "[email protected]" text

Scenario: Logout
Given I see the "Home screen" screen
Then I see the "[email protected]" 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
38 changes: 29 additions & 9 deletions android/src/androidTest/assets/features/Login.feature
Original file line number Diff line number Diff line change
@@ -1,11 +1,31 @@
Feature: Login
Scenario: Login screen
Given I am in the "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 type "[email protected]" 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 "[email protected]" text
And I see the "Password" textfield with text "Password"
And I see the "Login" button

Scenario: Failed attempt with wrong credentials
Then I type "[email protected]" in the "Email" field
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
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
Then I press the "Login" button
Then I see the "Missing password" text

Scenario: Successful attempt
Then I type "[email protected]" in the "Email" field
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 "[email protected]" text
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
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<String, String>()
private var scenario: ActivityScenario<*>? = null

@get:Rule(order = 0)
val testRule = createComposeRule()

@Before(order = 0)
fun beforeScenarioStart(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"] = "[email protected]"
}

else -> throw IllegalArgumentException("Couldn't find scenario: $scenarioName ")
}
launchApp()
}

@After(order = 0)
fun afterScenarioFinish(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.ScreenIsVisible(
// TODO consider using UI tags for this as it is not necessary the view will contain text
GherkinLambda1 {
testRule.onNodeWithTag(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.onNodeWithTag(tag).assertIsDisplayed().performTextInput(input)
}
)
TestCase.Common.PressButton(
GherkinLambda1 {
testRule.onNodeWithTag(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<MainActivity>(
Intent(instrumentation.targetContext, MainActivity::class.java)
.putExtra("isLoggedIn", arguments["isLoggedIn"])
.putExtra("testEmail", arguments["testEmail"])
)
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,21 @@ fun LoginLayout() {
ViewModelComposable(viewModel) {
val isLoading by this.isLoading.state()
Column {
Text(text = [email protected], modifier = Modifier.testTag("Login screen"))
Text(
text = [email protected],
modifier = Modifier.testTag("Login screen")
)
CustomTextField(
value = [email protected],
label = "Email",
modifier = Modifier.testTag("Email")
label = viewModel.emailPlaceholder,
modifier = Modifier.testTag(viewModel.emailPlaceholder)
)
val emailErrorText by [email protected]()
Text(text = emailErrorText, color = Color.Red)
CustomTextField(
value = [email protected],
label = "Password",
modifier = Modifier.testTag("Password")
label = viewModel.passwordPlaceholder,
modifier = Modifier.testTag(viewModel.passwordPlaceholder)
)
val passwordErrorText by [email protected]()
Text(text = passwordErrorText, color = Color.Red)
Expand All @@ -48,7 +51,10 @@ fun LoginLayout() {
CircularProgressIndicator()
}

Button(this@ViewModelComposable::login) {
Button(
onClick = this@ViewModelComposable::login,
modifier = Modifier.testTag("Login")
) {
Text("Login")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,8 @@ sealed class CucumberDefinition(val regex: String, execute: () -> Unit = {}): Ba
}
}

interface GherkinTestCase<D: Definition, L: GherkinLambda> {
val step: D
interface GherkinTestCase<L: GherkinLambda> {
val step: CucumberDefinition
val lambda: L
}

Expand Down
Loading