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

Feature/38 split modules #39

Open
wants to merge 41 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
4b64076
Create ui testing assertion module
corrado4eyes Sep 20, 2023
8e01f4c
Update strings structure and references
corrado4eyes Sep 20, 2023
261df5a
Update unit tests
corrado4eyes Sep 20, 2023
0c126d5
Update gradle files so that platforms can use the new module
corrado4eyes Sep 20, 2023
d0b1367
Update platforms tests and layout
corrado4eyes Sep 20, 2023
5052d8f
Add simple stub implementation for Node
corrado4eyes Sep 20, 2023
ea46cd7
Update tests
corrado4eyes Sep 20, 2023
9a8435d
Update TestCase class with sealed class and cases
corrado4eyes Sep 20, 2023
4fb3b11
Update assertion library
corrado4eyes Sep 20, 2023
bef8a79
Remove prints and update feature file
corrado4eyes Sep 20, 2023
8946885
Use identifier in android source set instead of Hardcoded string. Add…
corrado4eyes Sep 25, 2023
9f08e91
Add usage of application map for arguments
corrado4eyes Sep 25, 2023
157d5b5
Add doc for applicationArguments
corrado4eyes Sep 25, 2023
d928217
Rename exceptions removing prefix
corrado4eyes Sep 25, 2023
b3aced6
Update feature file
corrado4eyes Sep 26, 2023
ae07b35
Remove waitUntil from assertion method
corrado4eyes Sep 26, 2023
3eccea1
Rename files
corrado4eyes Sep 26, 2023
379c97f
Extract interface
corrado4eyes Sep 27, 2023
9f1a71a
Refactor so that TestCase interface is used. Also add platform specif…
corrado4eyes Sep 27, 2023
0f68652
Update view model and views created unit test
corrado4eyes Sep 27, 2023
1a51498
Update feature files
corrado4eyes Sep 27, 2023
32171a5
Update ui test files
corrado4eyes Sep 27, 2023
9109529
Update mock auth service and LoginVMTest
corrado4eyes Sep 27, 2023
223e289
Add `launchScreen` paramenter. Put arguments in different lines
corrado4eyes Sep 29, 2023
1d0af2c
Add APIs to scroll scroll views
corrado4eyes Sep 29, 2023
521bf85
Add SKIE to convert kotlin sealed classes into exhaustive enums in sw…
corrado4eyes Oct 2, 2023
dbfa64e
Remove empty lines
corrado4eyes Oct 2, 2023
9507f10
Add example for cross platform code
corrado4eyes Oct 2, 2023
57ffde9
Surround call by try/catches and add 25 retries on scrolls
corrado4eyes Oct 2, 2023
bd05f28
Update ui tests
corrado4eyes Oct 2, 2023
61b37da
Add logout call if the test configuration states that the user is log…
corrado4eyes Oct 2, 2023
da1690c
Add documentation
corrado4eyes Oct 2, 2023
4f606b3
Merge branch 'main' into feature/36-create-shared-button-finder
corrado4eyes Oct 2, 2023
1a57e8a
Remove pistakio and cucumber module and add them from mavenLocal
corrado4eyes Oct 3, 2023
e9010aa
Rename package id
corrado4eyes Oct 4, 2023
588b512
Add gradle property for composite builds
corrado4eyes Oct 6, 2023
1cfb049
Include module as a composite build
corrado4eyes Oct 6, 2023
a60f348
Add gitsubmodules
corrado4eyes Oct 6, 2023
9f6bad9
Update versions and create iOS framework in cucumberShared
corrado4eyes Oct 26, 2023
51bd2e9
Rename references from kilka to kaluga
corrado4eyes Oct 26, 2023
8fff267
Update ios files
corrado4eyes Oct 26, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
[submodule "dependencies/kaluga-swiftui"]
path = dependencies/kaluga-swiftui
url = https://github.com/splendo/kaluga-swiftui.git
[submodule "dependencies/kaluga-uitest"]
path = dependencies/kaluga-uitest
url = [email protected]:splendo/kaluga-uitest.git
[submodule "dependencies/kaluga-cucumber"]
path = dependencies/kaluga-cucumber
url = [email protected]:splendo/kaluga-cucumber.git
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ While the Android implementation will be split into 2+ files. A test runner file
@RunWith(Cucumber::class)
@CucumberOptions(
features = ["features"],
glue = ["com.corrado4eyes.cucumberplayground.test"]
glue = ["com.splendo.cucumberplayground.test"]
)
class TestRunner : CucumberAndroidJUnitRunner()
```
Expand Down
31 changes: 15 additions & 16 deletions android/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ plugins {
}

android {
namespace = "com.corrado4eyes.cucumberplayground.android"
compileSdk = 33
namespace = "com.splendo.cucumberplayground.android"
compileSdk = 34
defaultConfig {
applicationId = "com.corrado4eyes.cucumberplayground.android"
applicationId = "com.splendo.cucumberplayground.android"
minSdk = 29
targetSdk = 33
targetSdk = 34
versionCode = 1
versionName = "1.0"

testApplicationId = "com.corrado4eyes.cucumberplayground.test"
testInstrumentationRunner = "com.corrado4eyes.cucumberplayground.test.CucumberTests"
testApplicationId = "com.splendo.cucumberplayground.test"
testInstrumentationRunner = "com.splendo.cucumberplayground.test.CucumberTests"
}

buildFeatures {
Expand Down Expand Up @@ -52,17 +52,16 @@ dependencies {
val kalugaVersion: String by project

implementation(project(":shared"))
implementation(project(":cucumber"))
implementation("androidx.compose.ui:ui:1.4.3")
implementation("androidx.compose.ui:ui-tooling:1.4.3")
implementation("androidx.compose.ui:ui-tooling-preview:1.4.3")
implementation("androidx.compose.foundation:foundation:1.4.3")
implementation("androidx.compose.material:material:1.4.3")
implementation("androidx.activity:activity-compose:1.7.2")
implementation("androidx.compose.ui:ui:1.5.3")
implementation("androidx.compose.ui:ui-tooling:1.5.3")
implementation("androidx.compose.ui:ui-tooling-preview:1.5.3")
implementation("androidx.compose.foundation:foundation:1.5.3")
implementation("androidx.compose.material:material:1.5.3")
implementation("androidx.activity:activity-compose:1.8.0")

androidTestImplementation(kotlin("test"))
androidTestImplementation("androidx.compose.ui:ui-test-junit4:1.4.3")
debugImplementation("androidx.compose.ui:ui-test-manifest:$1.4.3")
androidTestImplementation("androidx.compose.ui:ui-test-junit4:1.5.3")
debugImplementation("androidx.compose.ui:ui-test-manifest:1.5.3")

implementation("com.splendo.kaluga:architecture-compose:$kalugaVersion")
implementation("com.splendo.kaluga:resources-compose:$kalugaVersion")
Expand All @@ -73,5 +72,5 @@ dependencies {
// TODO figure out how it can be updated without breeaking the project
androidTestImplementation("io.cucumber:cucumber-java8:4.8.1")

implementation("io.insert-koin:koin-androidx-compose:3.4.1")
implementation("io.insert-koin:koin-androidx-compose:3.4.4")
}
3 changes: 2 additions & 1 deletion android/src/androidTest/assets/features/Home.feature
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ Feature: Home
And I am in the "Home" screen
Then I see "[email protected]" text
And I see the "Logout" button
And I see "15" in the scrollview
When I press the "Logout" button
Then I see the "Login" screen
Then I see the "Login" screen
2 changes: 1 addition & 1 deletion android/src/androidTest/assets/features/Login.feature
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Feature: Login
And I see the "Password" textfield with text "Password"
And I see the "Login" button
When I type "[email protected]" in the "Email" textfield
And I type "1234" in the "Password" secure textfield
And I type "1234" in the "Password" textfield
And I press the "Login" button
Then I see the "Home" screen
And I see "[email protected]" text
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.corrado4eyes.cucumberplayground.test
package com.splendo.cucumberplayground.test

import io.cucumber.android.runner.CucumberAndroidJUnitRunner
import io.cucumber.junit.Cucumber
Expand All @@ -8,6 +8,6 @@ import org.junit.runner.RunWith
@RunWith(Cucumber::class)
@CucumberOptions(
features = ["features"],
glue = ["com.corrado4eyes.cucumberplayground.test"]
glue = ["com.splendo.cucumberplayground.test"]
)
class CucumberTests : CucumberAndroidJUnitRunner()
Original file line number Diff line number Diff line change
@@ -1,114 +1,80 @@
package com.corrado4eyes.cucumberplayground.test
package com.splendo.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.errors.UIElementException
import com.corrado4eyes.cucumberplayground.android.MainActivity
import com.corrado4eyes.cucumberplayground.models.Strings
import com.corrado4eyes.cucumbershared.tests.Definitions
import androidx.compose.ui.test.performScrollToIndex
import com.splendo.cucumberplayground.models.Strings
import com.splendo.cucumbershared.tests.AppDefinitions
import com.splendo.kaluga.uitest.DefaultApplicationAdapter
import io.cucumber.java8.En
import io.cucumber.junit.WithJunitRule
import org.junit.Rule

@WithJunitRule
class StepDefinitions : En {

private val arguments = mutableMapOf<String, String>()
private var scenario: ActivityScenario<*>? = null

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

init {
Definitions.values().forEach {
AppDefinitions.allCases.forEach {
val definitionString = it.definition.definitionString
when (it) {
Definitions.I_AM_IN_THE_EXPECT_VALUE_STRING_SCREEN -> Given(definitionString) { screenName: String ->
val screenTitleTag = when (screenName) {
Strings.Screen.Tag.login -> {
arguments["isLoggedIn"] = "false"
arguments["testEmail"] = ""
Strings.Screen.Title.login
}

Strings.Screen.Tag.home -> {
arguments["isLoggedIn"] = "true"
Strings.Screen.Title.home
}

else -> throw UIElementException.Screen.NotFound(screenName)
}
setLaunchScreen()
testRule.onNodeWithTag(screenTitleTag).assertIsDisplayed()
is AppDefinitions.CrossPlatform.IAmInScreen -> Given(definitionString) { screenName: String ->
val assertions = AppDefinitions.CrossPlatform.IAmInScreen(
"MainActivity",
application,
listOf(screenName)
).runAndGetAssertions()
application.assertAll(assertions)
}
Definitions.I_SEE_EXPECT_VALUE_STRING_TEXT -> Then(definitionString) { title: String ->
testRule.onNodeWithText(title).assertIsDisplayed()
is AppDefinitions.CrossPlatform.ISeeText -> Then(definitionString) { textViewTitle: String ->
val assertions = AppDefinitions.CrossPlatform.ISeeText(application, listOf(textViewTitle)).runAndGetAssertions()
application.assertAll(assertions)
}
Definitions.I_SEE_THE_EXPECT_VALUE_STRING_BUTTON -> Then(definitionString) { buttonName: String ->
when (buttonName) {
Strings.Button.Text.login -> testRule.onNodeWithText(Strings.Button.Text.login).assertIsDisplayed().assertHasClickAction()
Strings.Button.Text.logout -> testRule.onNodeWithTag(Strings.Button.Text.logout).assertIsDisplayed().assertHasClickAction()
else -> throw UIElementException.Button.NotFound(buttonName)
}
is AppDefinitions.CrossPlatform.ISeeButton -> Then(definitionString) { buttonTitle: String ->
val assertions = AppDefinitions.CrossPlatform.ISeeButton(application, listOf(buttonTitle)).runAndGetAssertions()
application.assertAll(assertions)
}
Definitions.I_SEE_THE_EXPECT_VALUE_STRING_SCREEN -> Then(definitionString) { screenName: String ->
Thread.sleep(1000)
when (screenName) {
Strings.Screen.Tag.login -> testRule.onNodeWithTag(Strings.Screen.Title.login).assertIsDisplayed()
Strings.Screen.Tag.home -> testRule.onNodeWithTag(Strings.Screen.Title.home).assertIsDisplayed()
else -> throw UIElementException.Screen.NotFound(screenName)
}
is AppDefinitions.CrossPlatform.ISeeScreen -> Then(definitionString) { screenTitle: String ->
val assertions = AppDefinitions.CrossPlatform.ISeeScreen(application, listOf(screenTitle)).runAndGetAssertions()
application.assertAll(assertions)
}
Definitions.I_SEE_THE_EXPECT_VALUE_STRING_TEXT_FIELD_WITH_TEXT_EXPECT_VALUE_STRING -> Then(definitionString) { tag: String, text: String ->
val elementNode = try {
testRule.onNodeWithTag(tag).assertIsDisplayed()
} catch (e: AssertionError) {
throw UIElementException.TextField.NotFound(tag)
}

elementNode.assertTextContains(text)
is AppDefinitions.CrossPlatform.ISeeTextFieldWithText -> Then(definitionString) { textFieldTag: String, textFieldText: String ->
val assertions = AppDefinitions.CrossPlatform.ISeeTextFieldWithText(application, listOf(textFieldTag, textFieldText)).runAndGetAssertions()
application.assertAll(assertions)
}
Definitions.I_TYPE_EXPECT_VALUE_STRING_IN_THE_EXPECT_VALUE_STRING_TEXT_FIELD -> When(definitionString) { textInput: String, tag: String, ->
testRule.onNodeWithText(tag).performTextInput(textInput)
is AppDefinitions.CrossPlatform.ITypeTextIntoTextField -> When(definitionString) { textInput: String, tag: String, ->
val assertions = AppDefinitions.CrossPlatform.ITypeTextIntoTextField(application, listOf(textInput, tag)).runAndGetAssertions()
application.assertAll(assertions)
}
Definitions.I_TYPE_EXPECT_VALUE_STRING_IN_THE_EXPECT_VALUE_STRING_SECURE_TEXT_FIELD -> When(definitionString) { textInput: String, tag: String ->
testRule.onNodeWithText(tag).performTextInput(textInput)
is AppDefinitions.CrossPlatform.IPressTheButton -> When(definitionString) { buttonTag: String ->
val assertions = AppDefinitions.CrossPlatform.IPressTheButton(application, listOf(buttonTag)).runAndGetAssertions()
application.assertAll(assertions)
}
Definitions.I_PRESS_THE_EXPECT_VALUE_STRING_BUTTON -> When(definitionString) { buttonName: String ->
val elementNode = try {
testRule.onNodeWithTag(buttonName).assertIsDisplayed()
} catch (e: AssertionError) {
throw UIElementException.TextField.NotFound(buttonName)
}
elementNode.performClick()
is AppDefinitions.CrossPlatform.SetLoggedInUserEmail -> Given(definitionString) { loggedInEmail: String ->
application.assertAll(AppDefinitions.CrossPlatform.SetLoggedInUserEmail(application, listOf(loggedInEmail)).runAndGetAssertions())
}
Definitions.EMAIL_IS_EXPECT_VALUE_STRING -> Given(definitionString) { loggedInEmail: String ->
arguments["testEmail"] = loggedInEmail
is AppDefinitions.Platform.ISeeValueInScrollView -> When(definitionString) { index: String ->

// Platform implementation
testRule
.onNodeWithTag(Strings.ScrollView.Tag.homeScrollView)
.performScrollToIndex(index.toInt())

testRule.onNodeWithText(index).assertIsDisplayed()

// Cross-platform implementation
// val element = application.findView(Strings.ScrollView.Tag.homeScrollView)
// element.swipeUntilIndex(index.toInt())
// val text = application.findView(index)
// application.assert(text.isVisible())
}

}
}
}

private fun setLaunchScreen() {
val instrumentation = InstrumentationRegistry.getInstrumentation()
launch<MainActivity>(
Intent(instrumentation.targetContext, MainActivity::class.java)
.putExtra("isLoggedIn", arguments["isLoggedIn"])
.putExtra("testEmail", arguments["testEmail"])
)
}

private fun <T: Activity> launch(intent: Intent) {
scenario = ActivityScenario.launch<T>(intent)
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.corrado4eyes.cucumberplayground.android
package com.splendo.cucumberplayground.android

import android.app.Application
import com.corrado4eyes.cucumberplayground.di.initKoin
import com.splendo.cucumberplayground.di.initKoin
import com.splendo.kaluga.base.ApplicationHolder

class CucumberApp : Application() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package com.corrado4eyes.cucumberplayground.android
package com.splendo.cucumberplayground.android

import android.content.Intent
import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity
import com.corrado4eyes.cucumberplayground.models.DefaultTestConfiguration
import com.corrado4eyes.cucumberplayground.models.TestConfiguration
import com.splendo.cucumberplayground.models.DefaultTestConfiguration
import com.splendo.cucumberplayground.models.TestConfiguration

class MainActivity : AppCompatActivity() {
private lateinit var testConfiguration: TestConfiguration
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.corrado4eyes.cucumberplayground.android
package com.splendo.cucumberplayground.android

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.MaterialTheme
Expand All @@ -8,12 +8,12 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.corrado4eyes.cucumberplayground.android.home.HomeLayout
import com.corrado4eyes.cucumberplayground.android.login.LoginLayout
import com.corrado4eyes.cucumberplayground.models.DefaultTestConfiguration
import com.corrado4eyes.cucumberplayground.models.TestConfiguration
import com.corrado4eyes.cucumberplayground.viewModels.main.AppNavigator
import com.corrado4eyes.cucumberplayground.viewModels.main.MainViewModel
import com.splendo.cucumberplayground.android.home.HomeLayout
import com.splendo.cucumberplayground.android.login.LoginLayout
import com.splendo.cucumberplayground.models.DefaultTestConfiguration
import com.splendo.cucumberplayground.models.TestConfiguration
import com.splendo.cucumberplayground.viewModels.main.AppNavigator
import com.splendo.cucumberplayground.viewModels.main.MainViewModel
import com.splendo.kaluga.architecture.compose.state
import com.splendo.kaluga.architecture.compose.viewModel.ViewModelComposable
import org.koin.androidx.compose.koinViewModel
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.corrado4eyes.cucumberplayground.android
package com.splendo.cucumberplayground.android

import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.shape.RoundedCornerShape
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
package com.corrado4eyes.cucumberplayground.android.home
package com.splendo.cucumberplayground.android.home

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.tooling.preview.Preview
import com.corrado4eyes.cucumberplayground.viewModels.home.HomeViewModel
import androidx.compose.ui.unit.dp
import com.splendo.cucumberplayground.models.Strings
import com.splendo.cucumberplayground.viewModels.home.HomeViewModel
import com.splendo.kaluga.architecture.compose.viewModel.ViewModelComposable
import org.koin.androidx.compose.koinViewModel

Expand All @@ -19,15 +26,33 @@ fun HomeLayout() {
Column(modifier = Modifier.fillMaxSize()) {
Text(
[email protected],
modifier = Modifier.testTag([email protected])
modifier = Modifier.testTag(Strings.Screen.Tag.home)
)
Text(
[email protected]().email,
modifier = Modifier.testTag([email protected]().email)
)
Text([email protected]().email)
Button(
this@ViewModelComposable::logout,
modifier = Modifier.testTag([email protected])
modifier = Modifier.testTag(Strings.Button.Tag.logout)
) {
Text([email protected])
}

LazyColumn(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxWidth()
.height(200.dp)
.testTag(Strings.ScrollView.Tag.homeScrollView)
) {
items(
viewModel.scrollableItems,
key = { it }
) {
Text(it.toString())
}
}
}
}
}
Expand Down
Loading