From ab98b1a2c9018eb8fa738501de7c3bb744b7f6db Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 2 Nov 2025 16:50:15 +0000 Subject: [PATCH 1/8] Initial plan From c3cd0ee2d3202a18f6e27e19b0dd71c846b12ebf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 2 Nov 2025 16:56:27 +0000 Subject: [PATCH 2/8] Add comprehensive UI tests and GitHub Actions workflow Co-authored-by: yogeshpaliyal <9381846+yogeshpaliyal@users.noreply.github.com> --- .github/workflows/integrated-tests.yml | 91 ++++++ .../deepr/ui/DeeprIntegratedTest.kt | 279 ++++++++++++++++++ 2 files changed, 370 insertions(+) create mode 100644 .github/workflows/integrated-tests.yml create mode 100644 app/src/androidTest/java/com/yogeshpaliyal/deepr/ui/DeeprIntegratedTest.kt diff --git a/.github/workflows/integrated-tests.yml b/.github/workflows/integrated-tests.yml new file mode 100644 index 00000000..614be0c8 --- /dev/null +++ b/.github/workflows/integrated-tests.yml @@ -0,0 +1,91 @@ +name: Integrated Tests + +on: + pull_request: + branches: [ master ] + paths-ignore: + - 'fastlane/**' + - 'icons/**' + - 'images/**' + - 'scripts/**' + - 'whatsnew/**' + - '**.md' + - '**.MD' + +# If two events are triggered within a short time in the same PR, cancel the run of the oldest event +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number }} + cancel-in-progress: true + +permissions: + contents: read + pull-requests: write + +jobs: + integrated-tests: + name: 'Run Integrated UI Tests' + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'jetbrains' + + - name: Grant execute permission for gradlew + run: chmod +x ./gradlew + + - name: ๐Ÿ— Disable Firebase + run: | + bash ./scripts/enableDisableFirebase.sh false + + - name: Enable KVM group perms + run: | + echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules + sudo udevadm control --reload-rules + sudo udevadm trigger --name-match=kvm + + - name: Run instrumented tests on Android Emulator + uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: 29 + target: default + arch: x86_64 + profile: Nexus 6 + script: ./gradlew connectedFreeDebugAndroidTest --stacktrace + + - name: Upload test results + if: always() + uses: actions/upload-artifact@v4 + with: + name: test-results + path: app/build/reports/androidTests/connected/ + retention-days: 7 + + - name: ๐Ÿ’ฌ Comment on PR with test results + uses: actions/github-script@v7 + if: always() && github.event_name == 'pull_request' + with: + script: | + const runId = context.runId; + const repo = context.repo; + const prNumber = context.issue.number; + const runUrl = `https://github.com/${repo.owner}/${repo.repo}/actions/runs/${runId}`; + + const comment = `## ๐Ÿงช Integrated Test Results + + The integrated UI tests have completed. + + **View full test results:** [Test Run #${runId}](${runUrl}) + + Test reports are available in the artifacts section of the workflow run.`; + + github.rest.issues.createComment({ + owner: repo.owner, + repo: repo.repo, + issue_number: prNumber, + body: comment + }); diff --git a/app/src/androidTest/java/com/yogeshpaliyal/deepr/ui/DeeprIntegratedTest.kt b/app/src/androidTest/java/com/yogeshpaliyal/deepr/ui/DeeprIntegratedTest.kt new file mode 100644 index 00000000..4b183282 --- /dev/null +++ b/app/src/androidTest/java/com/yogeshpaliyal/deepr/ui/DeeprIntegratedTest.kt @@ -0,0 +1,279 @@ +package com.yogeshpaliyal.deepr.ui + +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.hasContentDescription +import androidx.compose.ui.test.hasTestTag +import androidx.compose.ui.test.hasText +import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.onNodeWithContentDescription +import androidx.compose.ui.test.onNodeWithTag +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.performScrollTo +import androidx.compose.ui.test.performTextClearance +import androidx.compose.ui.test.performTextInput +import androidx.compose.ui.test.performTouchInput +import androidx.compose.ui.test.swipeLeft +import androidx.compose.ui.test.swipeRight +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.yogeshpaliyal.deepr.MainActivity +import com.yogeshpaliyal.deepr.R +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +/** + * Integrated UI tests for Deepr app covering: + * - Add new link + * - Edit link + * - Delete link + * - Search functionality + * - Filter by tag + * - Add/remove favorites + */ +@RunWith(AndroidJUnit4::class) +@OptIn(ExperimentalTestApi::class) +class DeeprIntegratedTest { + + @get:Rule + val composeTestRule = createAndroidComposeRule() + + private fun getString(resId: Int): String { + return composeTestRule.activity.getString(resId) + } + + @Test + fun testAddNewLink() { + // Wait for the app to load + composeTestRule.waitForIdle() + + // Click the FAB to add a new link + composeTestRule.onNodeWithContentDescription(getString(R.string.add_link)) + .performClick() + + // Wait for the bottom sheet to appear + composeTestRule.waitForIdle() + + // Enter a deeplink + composeTestRule.onNodeWithText(getString(R.string.enter_deeplink_command)) + .performTextInput("myapp://test") + + // Enter a name + composeTestRule.onNodeWithText(getString(R.string.enter_link_name)) + .performTextInput("Test Link") + + // Click save button + composeTestRule.onNodeWithText(getString(R.string.save)) + .performScrollTo() + .performClick() + + // Wait for the link to be saved + composeTestRule.waitForIdle() + + // Verify the link appears in the list + composeTestRule.onNodeWithText("Test Link") + .assertIsDisplayed() + } + + @Test + fun testEditLink() { + // First add a link + testAddNewLink() + + // Wait for the list to update + composeTestRule.waitForIdle() + + // Find the link and swipe right to edit + composeTestRule.onNodeWithText("Test Link") + .performTouchInput { + swipeRight() + } + + // Wait for the edit dialog to appear + composeTestRule.waitForIdle() + + // Verify we're in edit mode by checking for the Edit title + composeTestRule.onNodeWithText(getString(R.string.edit)) + .assertIsDisplayed() + + // Clear and update the name + val nameField = composeTestRule.onNodeWithText(getString(R.string.enter_link_name)) + nameField.performTextClearance() + nameField.performTextInput("Updated Test Link") + + // Save changes + composeTestRule.onNodeWithText(getString(R.string.save)) + .performScrollTo() + .performClick() + + // Wait for changes to be saved + composeTestRule.waitForIdle() + + // Verify the updated link appears + composeTestRule.onNodeWithText("Updated Test Link") + .assertIsDisplayed() + } + + @Test + fun testDeleteLink() { + // First add a link + testAddNewLink() + + // Wait for the list to update + composeTestRule.waitForIdle() + + // Swipe left to delete + composeTestRule.onNodeWithText("Test Link") + .performTouchInput { + swipeLeft() + } + + // Wait for the delete action + composeTestRule.waitForIdle() + + // Confirm deletion if there's a dialog + composeTestRule.onNode( + hasText(getString(R.string.delete)) or hasText(getString(R.string.yes)) + ).performClick() + + // Wait for deletion to complete + composeTestRule.waitForIdle() + + // Verify the link is no longer displayed + composeTestRule.onNodeWithText("Test Link") + .assertDoesNotExist() + } + + @Test + fun testSearchFunctionality() { + // Add a couple of links + addLinkWithDetails("myapp://test1", "First Test Link") + addLinkWithDetails("myapp://test2", "Second Test Link") + + composeTestRule.waitForIdle() + + // Click on the search bar to expand it + composeTestRule.onNodeWithContentDescription(getString(R.string.search)) + .performClick() + + composeTestRule.waitForIdle() + + // Enter search query + composeTestRule.onNodeWithText(getString(R.string.search)) + .performTextInput("First") + + composeTestRule.waitForIdle() + + // Verify only the matching link is displayed + composeTestRule.onNodeWithText("First Test Link") + .assertIsDisplayed() + } + + @Test + fun testAddRemoveFavorite() { + // Add a link + testAddNewLink() + + composeTestRule.waitForIdle() + + // Find and click the favorite button + composeTestRule.onNodeWithContentDescription(getString(R.string.add_to_favourites)) + .performClick() + + composeTestRule.waitForIdle() + + // Verify the favorite icon changed + composeTestRule.onNodeWithContentDescription(getString(R.string.remove_from_favourites)) + .assertIsDisplayed() + + // Click again to remove from favorites + composeTestRule.onNodeWithContentDescription(getString(R.string.remove_from_favourites)) + .performClick() + + composeTestRule.waitForIdle() + + // Verify it's back to unfavorited state + composeTestRule.onNodeWithContentDescription(getString(R.string.add_to_favourites)) + .assertIsDisplayed() + } + + @Test + fun testFilterByTag() { + // Add a link with a tag + addLinkWithTag("myapp://tagged", "Tagged Link", "TestTag") + + composeTestRule.waitForIdle() + + // Verify the link is displayed + composeTestRule.onNodeWithText("Tagged Link") + .assertIsDisplayed() + + // Click on the tag to filter + composeTestRule.onNodeWithText("TestTag") + .performClick() + + composeTestRule.waitForIdle() + + // Verify only the tagged link is displayed + composeTestRule.onNodeWithText("Tagged Link") + .assertIsDisplayed() + } + + // Helper method to add a link with specific details + private fun addLinkWithDetails(link: String, name: String) { + // Click the FAB + composeTestRule.onNodeWithContentDescription(getString(R.string.add_link)) + .performClick() + + composeTestRule.waitForIdle() + + // Enter deeplink + composeTestRule.onNodeWithText(getString(R.string.enter_deeplink_command)) + .performTextInput(link) + + // Enter name + composeTestRule.onNodeWithText(getString(R.string.enter_link_name)) + .performTextInput(name) + + // Save + composeTestRule.onNodeWithText(getString(R.string.save)) + .performScrollTo() + .performClick() + + composeTestRule.waitForIdle() + } + + // Helper method to add a link with a tag + private fun addLinkWithTag(link: String, name: String, tag: String) { + // Click the FAB + composeTestRule.onNodeWithContentDescription(getString(R.string.add_link)) + .performClick() + + composeTestRule.waitForIdle() + + // Enter deeplink + composeTestRule.onNodeWithText(getString(R.string.enter_deeplink_command)) + .performTextInput(link) + + // Enter name + composeTestRule.onNodeWithText(getString(R.string.enter_link_name)) + .performTextInput(name) + + // Add tag + composeTestRule.onNodeWithText(getString(R.string.new_tag)) + .performTextInput(tag) + + composeTestRule.onNodeWithText(getString(R.string.create_tag)) + .performClick() + + composeTestRule.waitForIdle() + + // Save + composeTestRule.onNodeWithText(getString(R.string.save)) + .performScrollTo() + .performClick() + + composeTestRule.waitForIdle() + } +} From 4ee0ea85ae5f7b2dd022aad3100c79dc86d9c186 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 2 Nov 2025 17:02:06 +0000 Subject: [PATCH 3/8] Refine test code - fix delete confirmation and clean unused imports Co-authored-by: yogeshpaliyal <9381846+yogeshpaliyal@users.noreply.github.com> --- .../com/yogeshpaliyal/deepr/ui/DeeprIntegratedTest.kt | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/app/src/androidTest/java/com/yogeshpaliyal/deepr/ui/DeeprIntegratedTest.kt b/app/src/androidTest/java/com/yogeshpaliyal/deepr/ui/DeeprIntegratedTest.kt index 4b183282..1b5b933b 100644 --- a/app/src/androidTest/java/com/yogeshpaliyal/deepr/ui/DeeprIntegratedTest.kt +++ b/app/src/androidTest/java/com/yogeshpaliyal/deepr/ui/DeeprIntegratedTest.kt @@ -2,12 +2,8 @@ package com.yogeshpaliyal.deepr.ui import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.assertIsDisplayed -import androidx.compose.ui.test.hasContentDescription -import androidx.compose.ui.test.hasTestTag -import androidx.compose.ui.test.hasText import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.compose.ui.test.onNodeWithContentDescription -import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performScrollTo @@ -132,10 +128,9 @@ class DeeprIntegratedTest { // Wait for the delete action composeTestRule.waitForIdle() - // Confirm deletion if there's a dialog - composeTestRule.onNode( - hasText(getString(R.string.delete)) or hasText(getString(R.string.yes)) - ).performClick() + // Confirm deletion by clicking the Delete button in the dialog + composeTestRule.onNodeWithText(getString(R.string.delete)) + .performClick() // Wait for deletion to complete composeTestRule.waitForIdle() From 4f781c4a60e2e903409fe09b0ebcf9b83deb5e08 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 2 Nov 2025 17:03:14 +0000 Subject: [PATCH 4/8] Add missing assertDoesNotExist import Co-authored-by: yogeshpaliyal <9381846+yogeshpaliyal@users.noreply.github.com> --- .../java/com/yogeshpaliyal/deepr/ui/DeeprIntegratedTest.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/androidTest/java/com/yogeshpaliyal/deepr/ui/DeeprIntegratedTest.kt b/app/src/androidTest/java/com/yogeshpaliyal/deepr/ui/DeeprIntegratedTest.kt index 1b5b933b..f0a3a0b5 100644 --- a/app/src/androidTest/java/com/yogeshpaliyal/deepr/ui/DeeprIntegratedTest.kt +++ b/app/src/androidTest/java/com/yogeshpaliyal/deepr/ui/DeeprIntegratedTest.kt @@ -1,6 +1,7 @@ package com.yogeshpaliyal.deepr.ui import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.assertDoesNotExist import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.compose.ui.test.onNodeWithContentDescription From 68c7325681cc814ac9fcaa63a672521eeea1bbd3 Mon Sep 17 00:00:00 2001 From: Yogesh Choudhary Paliyal Date: Tue, 4 Nov 2025 23:02:51 +0530 Subject: [PATCH 5/8] Add automated testing workflow and update backup rules --- app/build.gradle.kts | 8 ++ .../deepr/ui/DeeprIntegratedTest.kt | 113 ++++++++++++------ .../debug/res/xml/data_extraction_rules.xml | 20 ++++ .../deepr/ui/screens/home/DeeprItem.kt | 2 + app/src/main/res/xml/backup_rules.xml | 5 +- .../res/xml/data_extraction_rules.xml | 1 + gradle/libs.versions.toml | 2 + 7 files changed, 108 insertions(+), 43 deletions(-) create mode 100644 app/src/debug/res/xml/data_extraction_rules.xml rename app/src/{main => release}/res/xml/data_extraction_rules.xml (99%) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 499da4b9..fd724366 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -22,6 +22,13 @@ android { versionName = "1.0.18" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + testInstrumentationRunnerArguments += mapOf( + "clearPackageData" to "true", + ) + } + + testOptions { + execution = "ANDROIDX_TEST_ORCHESTRATOR" } productFlavors { @@ -115,6 +122,7 @@ dependencies { testImplementation(libs.ktor.client.mock) testImplementation(libs.kotlinx.coroutines.test) androidTestImplementation(libs.androidx.junit) + androidTestUtil(libs.orchestrator) androidTestImplementation(libs.androidx.espresso.core) androidTestImplementation(platform(libs.androidx.compose.bom)) androidTestImplementation(libs.androidx.ui.test.junit4) diff --git a/app/src/androidTest/java/com/yogeshpaliyal/deepr/ui/DeeprIntegratedTest.kt b/app/src/androidTest/java/com/yogeshpaliyal/deepr/ui/DeeprIntegratedTest.kt index f0a3a0b5..22b4644c 100644 --- a/app/src/androidTest/java/com/yogeshpaliyal/deepr/ui/DeeprIntegratedTest.kt +++ b/app/src/androidTest/java/com/yogeshpaliyal/deepr/ui/DeeprIntegratedTest.kt @@ -1,7 +1,6 @@ package com.yogeshpaliyal.deepr.ui import androidx.compose.ui.test.ExperimentalTestApi -import androidx.compose.ui.test.assertDoesNotExist import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.compose.ui.test.onNodeWithContentDescription @@ -32,13 +31,10 @@ import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) @OptIn(ExperimentalTestApi::class) class DeeprIntegratedTest { - @get:Rule val composeTestRule = createAndroidComposeRule() - private fun getString(resId: Int): String { - return composeTestRule.activity.getString(resId) - } + private fun getString(resId: Int): String = composeTestRule.activity.getString(resId) @Test fun testAddNewLink() { @@ -46,22 +42,26 @@ class DeeprIntegratedTest { composeTestRule.waitForIdle() // Click the FAB to add a new link - composeTestRule.onNodeWithContentDescription(getString(R.string.add_link)) + composeTestRule + .onNodeWithContentDescription(getString(R.string.add_link)) .performClick() // Wait for the bottom sheet to appear composeTestRule.waitForIdle() // Enter a deeplink - composeTestRule.onNodeWithText(getString(R.string.enter_deeplink_command)) + composeTestRule + .onNodeWithText(getString(R.string.enter_deeplink_command)) .performTextInput("myapp://test") // Enter a name - composeTestRule.onNodeWithText(getString(R.string.enter_link_name)) + composeTestRule + .onNodeWithText(getString(R.string.enter_link_name)) .performTextInput("Test Link") // Click save button - composeTestRule.onNodeWithText(getString(R.string.save)) + composeTestRule + .onNodeWithText(getString(R.string.save)) .performScrollTo() .performClick() @@ -69,7 +69,8 @@ class DeeprIntegratedTest { composeTestRule.waitForIdle() // Verify the link appears in the list - composeTestRule.onNodeWithText("Test Link") + composeTestRule + .onNodeWithText("Test Link") .assertIsDisplayed() } @@ -82,7 +83,8 @@ class DeeprIntegratedTest { composeTestRule.waitForIdle() // Find the link and swipe right to edit - composeTestRule.onNodeWithText("Test Link") + composeTestRule + .onNodeWithText("Test Link") .performTouchInput { swipeRight() } @@ -91,7 +93,8 @@ class DeeprIntegratedTest { composeTestRule.waitForIdle() // Verify we're in edit mode by checking for the Edit title - composeTestRule.onNodeWithText(getString(R.string.edit)) + composeTestRule + .onNodeWithText(getString(R.string.edit)) .assertIsDisplayed() // Clear and update the name @@ -100,7 +103,8 @@ class DeeprIntegratedTest { nameField.performTextInput("Updated Test Link") // Save changes - composeTestRule.onNodeWithText(getString(R.string.save)) + composeTestRule + .onNodeWithText(getString(R.string.save)) .performScrollTo() .performClick() @@ -108,7 +112,8 @@ class DeeprIntegratedTest { composeTestRule.waitForIdle() // Verify the updated link appears - composeTestRule.onNodeWithText("Updated Test Link") + composeTestRule + .onNodeWithText("Updated Test Link") .assertIsDisplayed() } @@ -121,7 +126,8 @@ class DeeprIntegratedTest { composeTestRule.waitForIdle() // Swipe left to delete - composeTestRule.onNodeWithText("Test Link") + composeTestRule + .onNodeWithText("Test Link") .performTouchInput { swipeLeft() } @@ -130,14 +136,16 @@ class DeeprIntegratedTest { composeTestRule.waitForIdle() // Confirm deletion by clicking the Delete button in the dialog - composeTestRule.onNodeWithText(getString(R.string.delete)) + composeTestRule + .onNodeWithText(getString(R.string.delete)) .performClick() // Wait for deletion to complete composeTestRule.waitForIdle() // Verify the link is no longer displayed - composeTestRule.onNodeWithText("Test Link") + composeTestRule + .onNodeWithText("Test Link") .assertDoesNotExist() } @@ -150,19 +158,22 @@ class DeeprIntegratedTest { composeTestRule.waitForIdle() // Click on the search bar to expand it - composeTestRule.onNodeWithContentDescription(getString(R.string.search)) + composeTestRule + .onNodeWithContentDescription(getString(R.string.search)) .performClick() composeTestRule.waitForIdle() // Enter search query - composeTestRule.onNodeWithText(getString(R.string.search)) + composeTestRule + .onNodeWithContentDescription(getString(R.string.search)) .performTextInput("First") composeTestRule.waitForIdle() // Verify only the matching link is displayed - composeTestRule.onNodeWithText("First Test Link") + composeTestRule + .onNodeWithText("First Test Link") .assertIsDisplayed() } @@ -174,23 +185,27 @@ class DeeprIntegratedTest { composeTestRule.waitForIdle() // Find and click the favorite button - composeTestRule.onNodeWithContentDescription(getString(R.string.add_to_favourites)) + composeTestRule + .onNodeWithContentDescription(getString(R.string.add_to_favourites)) .performClick() composeTestRule.waitForIdle() // Verify the favorite icon changed - composeTestRule.onNodeWithContentDescription(getString(R.string.remove_from_favourites)) + composeTestRule + .onNodeWithContentDescription(getString(R.string.remove_from_favourites)) .assertIsDisplayed() // Click again to remove from favorites - composeTestRule.onNodeWithContentDescription(getString(R.string.remove_from_favourites)) + composeTestRule + .onNodeWithContentDescription(getString(R.string.remove_from_favourites)) .performClick() composeTestRule.waitForIdle() // Verify it's back to unfavorited state - composeTestRule.onNodeWithContentDescription(getString(R.string.add_to_favourites)) + composeTestRule + .onNodeWithContentDescription(getString(R.string.add_to_favourites)) .assertIsDisplayed() } @@ -202,38 +217,48 @@ class DeeprIntegratedTest { composeTestRule.waitForIdle() // Verify the link is displayed - composeTestRule.onNodeWithText("Tagged Link") + composeTestRule + .onNodeWithText("Tagged Link") .assertIsDisplayed() // Click on the tag to filter - composeTestRule.onNodeWithText("TestTag") + composeTestRule + .onNodeWithText("TestTag") .performClick() composeTestRule.waitForIdle() // Verify only the tagged link is displayed - composeTestRule.onNodeWithText("Tagged Link") + composeTestRule + .onNodeWithText("Tagged Link") .assertIsDisplayed() } // Helper method to add a link with specific details - private fun addLinkWithDetails(link: String, name: String) { + private fun addLinkWithDetails( + link: String, + name: String, + ) { // Click the FAB - composeTestRule.onNodeWithContentDescription(getString(R.string.add_link)) + composeTestRule + .onNodeWithContentDescription(getString(R.string.add_link)) .performClick() composeTestRule.waitForIdle() // Enter deeplink - composeTestRule.onNodeWithText(getString(R.string.enter_deeplink_command)) + composeTestRule + .onNodeWithText(getString(R.string.enter_deeplink_command)) .performTextInput(link) // Enter name - composeTestRule.onNodeWithText(getString(R.string.enter_link_name)) + composeTestRule + .onNodeWithText(getString(R.string.enter_link_name)) .performTextInput(name) // Save - composeTestRule.onNodeWithText(getString(R.string.save)) + composeTestRule + .onNodeWithText(getString(R.string.save)) .performScrollTo() .performClick() @@ -241,32 +266,42 @@ class DeeprIntegratedTest { } // Helper method to add a link with a tag - private fun addLinkWithTag(link: String, name: String, tag: String) { + private fun addLinkWithTag( + link: String, + name: String, + tag: String, + ) { // Click the FAB - composeTestRule.onNodeWithContentDescription(getString(R.string.add_link)) + composeTestRule + .onNodeWithContentDescription(getString(R.string.add_link)) .performClick() composeTestRule.waitForIdle() // Enter deeplink - composeTestRule.onNodeWithText(getString(R.string.enter_deeplink_command)) + composeTestRule + .onNodeWithText(getString(R.string.enter_deeplink_command)) .performTextInput(link) // Enter name - composeTestRule.onNodeWithText(getString(R.string.enter_link_name)) + composeTestRule + .onNodeWithText(getString(R.string.enter_link_name)) .performTextInput(name) // Add tag - composeTestRule.onNodeWithText(getString(R.string.new_tag)) + composeTestRule + .onNodeWithText(getString(R.string.new_tag)) .performTextInput(tag) - composeTestRule.onNodeWithText(getString(R.string.create_tag)) + composeTestRule + .onNodeWithText(getString(R.string.create_tag)) .performClick() composeTestRule.waitForIdle() // Save - composeTestRule.onNodeWithText(getString(R.string.save)) + composeTestRule + .onNodeWithText(getString(R.string.save)) .performScrollTo() .performClick() diff --git a/app/src/debug/res/xml/data_extraction_rules.xml b/app/src/debug/res/xml/data_extraction_rules.xml new file mode 100644 index 00000000..9e78c630 --- /dev/null +++ b/app/src/debug/res/xml/data_extraction_rules.xml @@ -0,0 +1,20 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/yogeshpaliyal/deepr/ui/screens/home/DeeprItem.kt b/app/src/main/java/com/yogeshpaliyal/deepr/ui/screens/home/DeeprItem.kt index 6c571a5e..20a14327 100644 --- a/app/src/main/java/com/yogeshpaliyal/deepr/ui/screens/home/DeeprItem.kt +++ b/app/src/main/java/com/yogeshpaliyal/deepr/ui/screens/home/DeeprItem.kt @@ -47,6 +47,7 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow @@ -228,6 +229,7 @@ fun DeeprItem( ), modifier = Modifier + .testTag("DeeprItem") .fillMaxWidth() .combinedClickable( onClick = { onItemClick(MenuItem.Click(account)) }, diff --git a/app/src/main/res/xml/backup_rules.xml b/app/src/main/res/xml/backup_rules.xml index 4df92558..25b13fd8 100644 --- a/app/src/main/res/xml/backup_rules.xml +++ b/app/src/main/res/xml/backup_rules.xml @@ -6,8 +6,5 @@ See https://developer.android.com/about/versions/12/backup-restore --> - + \ No newline at end of file diff --git a/app/src/main/res/xml/data_extraction_rules.xml b/app/src/release/res/xml/data_extraction_rules.xml similarity index 99% rename from app/src/main/res/xml/data_extraction_rules.xml rename to app/src/release/res/xml/data_extraction_rules.xml index 9ee9997b..2e4a8ff3 100644 --- a/app/src/main/res/xml/data_extraction_rules.xml +++ b/app/src/release/res/xml/data_extraction_rules.xml @@ -9,6 +9,7 @@ --> +