diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/docs/README.md b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/docs/README.md new file mode 100644 index 000000000000..ec4a255e039a --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/docs/README.md @@ -0,0 +1,82 @@ +# Android Test Automation Framework (POM-Based) + +## 🚀 Introduction +This framework introduces a modern, scalable approach to Android UI testing using the Page Object Model (POM). It combines Espresso, UIAutomator2, and Jetpack Compose testing under a single unified abstraction, making test code clean, reusable, and easy to maintain. + +Tests written with this system read like user journeys, not code. Teams can define pages once and reuse them throughout tests—encouraging ownership, modularity, and clarity across features. + +## 🛠️ Getting Started + +### Prerequisites +- Android Studio Arctic Fox or newer +- Kotlin 1.9+ +- Compose UI Test library +- Enabled Test Orchestrator (optional for retries) + +### Writing Your First Test +```kotlin +@Test +fun verifyHomeLoads() { + on.homePage.navigateToPage() + .mozVerifyElementsByGroup("requiredForPage") +} +``` + +### Structure Overview +- `BasePage.kt`: Common actions (clicks, verification, navigation) +- `Selector.kt`: Describes UI elements in a flexible, tool-agnostic way +- `PageContext.kt`: Entry point for test pages via `on.` +- `NavigationRegistry.kt`: Stores how to move between pages + +## 🧪 Test Development Workflow + +1. **Define Selectors** +```kotlin +val TITLE = Selector( + strategy = SelectorStrategy.ESPRESSO_BY_TEXT, + value = "Welcome", + description = "Welcome title on Home Page", + groups = listOf("requiredForPage") +) +``` + +2. **Create a Page Object** +```kotlin +object HomePage : BasePage() { + override val pageName = "HomePage" + + override fun mozGetSelectorsByGroup(group: String) = HomePageSelectors.all.filter { + it.groups.contains(group) + } +} +``` + +3. **Add to Context** +```kotlin +val homePage = HomePage +``` + +4. **Write a Test** +```kotlin +on.homePage.navigateToPage() + .mozVerifyElementsByGroup("requiredForPage") +``` + +## 📚 Additional Resources +- 📖 [Test Automation Strategy](./docs/TestAutomationStrategy.md): Roadmap for phases and long-term goals +- 💡 Example tests: See `ui/efficiency/tests/` +- 📎 Diagrams: (Coming soon) + +## 👥 Contributing +When adding new pages or selectors: +- Follow the fluent interface pattern +- Group selectors meaningfully (e.g., `"requiredForPage"`, `"toolbar"`) +- Register navigation paths explicitly in each `Page`'s `init` block + +## ✅ Best Practices +- Use clear, readable selector descriptions +- Avoid direct interaction with Espresso/UIAutomator in tests +- Build tests in Given/When/Then structure + +--- +This framework enables powerful, flexible testing—but starts simple. With it, we empower teams to own their features *and* their tests. diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/docs/TestAutomationStrategy.md b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/docs/TestAutomationStrategy.md new file mode 100644 index 000000000000..5461723bad30 --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/docs/TestAutomationStrategy.md @@ -0,0 +1,114 @@ +# Test Automation as a Service: Multi-Phase Strategy + +## Overview +This document outlines a multi-phase strategy for building a scalable, maintainable, and dynamic Android test automation system. The goal is to support testing at scale—ranging from dozens to tens of thousands of tests—while enabling individual development teams to own their test logic confidently. + +The system is designed not just to enable automated UI tests, but to act as a test orchestration framework that can: +- Generate tests dynamically +- Support efficient test suite creation and execution +- Optimize coverage with minimal redundancy +- Allow runtime customization of test input, state, and configuration + +## Summary of Phases + +### **Phase 0: Ad-Hoc Testing** +- Common pattern seen in early automation efforts or tutorials +- Tests are brittle, hard to maintain +- Difficult to scale beyond ~100-200 tests + +### **Phase 1: Standardization with Page Object Model (POM)** +- Introduce BasePage + Selector abstractions for cross-device/platform consistency +- Define navigation flows using a navigation graph (nodes = pages, edges = steps) +- Fluent interface pattern for clean and readable test flows +- Reuse components and improve stability +- Targets ~1,000 to ~2,000 tests + +**Key Outcomes:** +- Reduced maintenance overhead +- Stable and composable test structure +- Foundation for dynamic navigation and grouped element validation + +### **Phase 2: Data-Driven Tests & Dynamic Test Factories** +- Use metadata and reflection to define what each test requires +- Centralized test data service that dynamically prepares: + - Test data + - Test environments + - Targeted test suites based on code changes +- Enables composable, on-demand test generation +- Replaces tags and decorators with runtime configuration +- Coverage optimization using Orthogonal Arrays (e.g. pairwise testing) + +**Key Outcomes:** +- Tests generated from config or runtime context +- Faster feedback cycles by running most relevant tests first +- Easier root cause analysis in CI +- Teams can define and manage their own test scope + +### **Phase 3: Test Factory of Test Factories** +- Fully leverage standardized infrastructure from Phases 1–2 +- Enable AI and/or rule-based helpers to: + - Propose tests based on heuristics or code changes + - Self-heal flaking or broken tests + - Minimize human intervention while scaling coverage +- Libraries for setup, steps, and assertions are highly structured +- Fluent interfaces make automation predictable and parseable + +**Key Outcomes:** +- Automation becomes intelligent and context-aware +- Reduced cost of test maintenance and authoring +- Human involvement focused on novel or edge-case testing + +## Current State (Phase 1 MVP) + +### Helper Modules Implemented: +- `BasePage.kt`: Common logic for all screens (navigation, verification, interaction) +- `Selector.kt`: Declarative wrapper around UI selectors with grouping and description +- `NavigationRegistry.kt`: Graph structure for defining navigation steps between pages +- `PageContext.kt`: Central access point to all page objects +- `BaseTest.kt`: Test rule harness including Compose + Retry rules + +**Why this matters:** +These modules abstract away repetitive test logic and create a clean DSL-like interface for writing readable, robust, and maintainable UI tests. + +```kotlin +on.settingsPage.navigateToPage() + .mozVerifyElementsByGroup("requiredForPage") +``` + +## How This Enables the Future +- Pages describe their *structure* via selectors +- Navigation is described declaratively +- Test code focuses only on *what to test*, not *how to get there* +- Data-driven factories can then define *what to test* programmatically + +## Low-Level Developer Guidelines + +### Writing a New Test +- Extend `BaseTest` +- Use `on..navigateToPage()` to transition +- Use `.mozVerifyElementsByGroup("...group...")` to check structure +- Use `.mozClick(selector)` or define `NavigationStep.Click()` to interact + +### Adding a New Page +- Create new object that extends `BasePage` +- Implement `mozGetSelectorsByGroup()` +- Register all navigation edges in `init {}` block + +### Creating a Dynamic Test +- Define input data and selectors declaratively +- Feed test data into a factory that builds navigation + verification steps + +--- + +## Final Thoughts +This framework is not just about making UI tests easier. It’s about enabling: +- Reusable automation primitives +- Team autonomy +- Data- and AI-assisted test generation +- Long-term maintainability + +It positions test automation as a *strategic capability*, not just a tactical tool. + +--- + +*For more implementation details, see internal documentation and examples in the `helpers/`, `navigation/`, and `pageObjects/` packages.* diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/helpers/BasePage.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/helpers/BasePage.kt new file mode 100644 index 000000000000..175555270b7b --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/helpers/BasePage.kt @@ -0,0 +1,285 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.ui.efficiency.helpers + +import android.util.Log +import androidx.compose.ui.test.SemanticsNodeInteraction +import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.junit4.AndroidComposeTestRule +import androidx.compose.ui.test.onNodeWithTag +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performClick +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.ViewInteraction +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.withContentDescription +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText +import androidx.test.uiautomator.By +import androidx.test.uiautomator.UiObject +import androidx.test.uiautomator.UiSelector +import org.mozilla.fenix.helpers.HomeActivityIntentTestRule +import org.mozilla.fenix.helpers.TestHelper.mDevice +import org.mozilla.fenix.helpers.TestHelper.packageName +import org.mozilla.fenix.ui.efficiency.navigation.NavigationRegistry +import org.mozilla.fenix.ui.efficiency.navigation.NavigationStep + +abstract class BasePage( + protected val composeRule: AndroidComposeTestRule, +) { + abstract val pageName: String + + open fun navigateToPage(): BasePage { + if (mozWaitForPageToLoad()) { + PageStateTracker.currentPageName = pageName + return this + } + + val fromPage = PageStateTracker.currentPageName + Log.i("PageNavigation", "🔍 Trying to find path from '$fromPage' to '$pageName'") + + val path = NavigationRegistry.findPath(fromPage, pageName) + + if (path == null) { + NavigationRegistry.logGraph() + throw AssertionError("❌ No navigation path found from '$fromPage' to '$pageName'") + } else { + Log.i("PageNavigation", "✅ Navigation path found from '$fromPage' to '$pageName':") + path.forEachIndexed { i, step -> Log.i("PageNavigation", " Step ${i + 1}: $step") } + } + + path.forEach { step -> + when (step) { + is NavigationStep.Click -> mozClick(step.selector) + is NavigationStep.Swipe -> mozSwipeTo(step.selector, step.direction) + } + } + + if (!mozWaitForPageToLoad()) { + throw AssertionError("Failed to navigate to $pageName") + } + + PageStateTracker.currentPageName = pageName + return this + } + + private fun mozWaitForPageToLoad(timeout: Long = 10_000, interval: Long = 500): Boolean { + val requiredSelectors = mozGetSelectorsByGroup("requiredForPage") + val deadline = System.currentTimeMillis() + timeout + + while (System.currentTimeMillis() < deadline) { + if (requiredSelectors.all { mozVerifyElement(it) }) { + return true + } + android.os.SystemClock.sleep(interval) + } + + return false + } + + abstract fun mozGetSelectorsByGroup(group: String = "requiredForPage"): List + + fun mozVerifyElementsByGroup(group: String = "requiredForPage"): BasePage { + val selectors = mozGetSelectorsByGroup(group) + val allPresent = selectors.all { mozVerifyElement(it) } + + if (!allPresent) { + throw AssertionError("Not all elements in group '$group' are present") + } + + return this + } + + fun mozClick(selector: Selector): BasePage { + val element = mozGetElement(selector) + + if (element == null) { + throw AssertionError("Element not found for selector: ${selector.description} (${selector.strategy} -> ${selector.value})") + } + + when (element) { + is ViewInteraction -> { + try { + element.perform(click()) + } catch (e: Exception) { + throw AssertionError("Failed to click on Espresso element for selector: ${selector.description}", e) + } + } + + is UiObject -> { + if (!element.exists()) { + throw AssertionError("UiObject does not exist for selector: ${selector.description}") + } + if (!element.click()) { + throw AssertionError("Failed to click on UiObject for selector: ${selector.description}") + } + } + + is SemanticsNodeInteraction -> { + try { + element.assertExists() + element.assertIsDisplayed() + element.performClick() + } catch (e: Exception) { + throw AssertionError("Failed to click on Compose node for selector: ${selector.description}", e) + } + } + + else -> { + throw AssertionError("Unsupported element type (${element::class.simpleName}) for selector: ${selector.description}") + } + } + + return this + } + + fun mozSwipeTo( + selector: Selector, + direction: SwipeDirection = SwipeDirection.DOWN, + maxSwipes: Int = 5, + ): BasePage { + repeat(maxSwipes) { attempt -> + val element = mozGetElement(selector) + + val isVisible = when (element) { + is ViewInteraction -> try { + element.check(matches(isDisplayed())) + true + } catch (_: Exception) { + false + } + + is UiObject -> element.exists() + + is SemanticsNodeInteraction -> try { + element.assertExists() + element.assertIsDisplayed() + true + } catch (_: AssertionError) { + false + } + + else -> false + } + + if (isVisible) { + Log.i("MozSwipeTo", "✅ Element '${selector.description}' found after $attempt swipe(s)") + return this + } + + Log.i("MozSwipeTo", "🔄 Swipe attempt ${attempt + 1} for selector '${selector.description}'") + performSwipe(direction) + Thread.sleep(500) + } + + throw AssertionError("❌ Element '${selector.description}' not found after $maxSwipes swipe(s)") + } + + private fun performSwipe(direction: SwipeDirection) { + val height = mDevice.displayHeight + val width = mDevice.displayWidth + + val (startX, startY, endX, endY) = when (direction) { + SwipeDirection.UP -> listOf(width / 2, height / 2, width / 2, height / 4) + SwipeDirection.DOWN -> listOf(width / 2, height / 2, width / 2, height * 3 / 4) + SwipeDirection.LEFT -> listOf(width * 3 / 4, height / 2, width / 4, height / 2) + SwipeDirection.RIGHT -> listOf(width / 4, height / 2, width * 3 / 4, height / 2) + } + + mDevice.swipe(startX, startY, endX, endY, 10) + } + + private fun mozGetElement(selector: Selector): Any? { + if (selector.value.isBlank()) { + Log.i("mozGetElement", "Empty or blank selector value: ${selector.description}") + return null + } + + return when (selector.strategy) { + SelectorStrategy.COMPOSE_BY_TAG -> { + try { + composeRule.onNodeWithTag(selector.value) + } catch (e: Exception) { + Log.i("mozGetElement", "Compose node not found for tag: ${selector.value}") + null + } + } + + SelectorStrategy.COMPOSE_BY_TEXT -> { + try { + composeRule.onNodeWithText(selector.value, useUnmergedTree = true) + } catch (e: Exception) { + Log.i("mozGetElement", "Compose node not found for text: ${selector.value}") + null + } + } + + SelectorStrategy.ESPRESSO_BY_ID -> { + val resId = selector.toResourceId() + if (resId == 0) { + Log.i("mozGetElement", "Invalid resource ID for: ${selector.value}") + null + } else { + onView(withId(resId)) + } + } + + SelectorStrategy.ESPRESSO_BY_TEXT -> onView(withText(selector.value)) + SelectorStrategy.ESPRESSO_BY_CONTENT_DESC -> onView(withContentDescription(selector.value)) + + SelectorStrategy.UIAUTOMATOR2_BY_CLASS -> { + val obj = mDevice.findObject(UiSelector().className(selector.value)) + if (!obj.exists()) null else obj + } + + SelectorStrategy.UIAUTOMATOR2_BY_TEXT -> { + val obj = mDevice.findObject(UiSelector().text(selector.value)) + if (!obj.exists()) null else obj + } + + SelectorStrategy.UIAUTOMATOR2_BY_RES -> { + val obj = mDevice.findObject(By.res(selector.value)) + if (obj == null) { + Log.i("MozGetElement", "mozGetElement: UIObject2 not found for res: ${selector.value}") + null + } else { obj } + } + + SelectorStrategy.UIAUTOMATOR2_BY_RES_ID -> { + val fullResId = "$packageName:${selector.value}" + val obj = mDevice.findObject(UiSelector().resourceId(fullResId)) + if (!obj.exists()) null else obj + } + } + } + + private fun mozVerifyElement(selector: Selector): Boolean { + val element = mozGetElement(selector) + + return when (element) { + is ViewInteraction -> { + try { + element.check(matches(isDisplayed())) + true + } catch (e: Exception) { + false + } + } + is UiObject -> element.exists() + is SemanticsNodeInteraction -> { + try { + element.assertExists() + element.assertIsDisplayed() + true + } catch (e: AssertionError) { + false + } + } + else -> false + } + } +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/helpers/BaseTest.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/helpers/BaseTest.kt new file mode 100644 index 000000000000..cd015c81b591 --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/helpers/BaseTest.kt @@ -0,0 +1,44 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.ui.efficiency.helpers + +import android.util.Log +import androidx.compose.ui.test.junit4.AndroidComposeTestRule +import org.junit.Before +import org.junit.Rule +import org.mozilla.fenix.helpers.HomeActivityIntentTestRule +import org.mozilla.fenix.helpers.RetryTestRule +import org.mozilla.fenix.helpers.TestSetup + +abstract class BaseTest( + private val skipOnboarding: Boolean = true, + private val isMenuRedesignEnabled: Boolean = true, + private val isMenuRedesignCFREnabled: Boolean = false, + private val isPageLoadTranslationsPromptEnabled: Boolean = false, +) : TestSetup() { + + @get:Rule(order = 0) + val composeRule: AndroidComposeTestRule = + AndroidComposeTestRule( + HomeActivityIntentTestRule( + skipOnboarding = skipOnboarding, + isMenuRedesignEnabled = isMenuRedesignEnabled, + isMenuRedesignCFREnabled = isMenuRedesignCFREnabled, + isPageLoadTranslationsPromptEnabled = isPageLoadTranslationsPromptEnabled, + ), + ) { it.activity } + + protected val on: PageContext = PageContext(composeRule) + + @get:Rule(order = 1) + val retryTestRule = RetryTestRule(3) + + @Before + override fun setUp() { + super.setUp() + PageStateTracker.currentPageName = "AppEntry" + Log.i("BaseTest", "🚀 Starting test with page: AppEntry") + } +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/helpers/PageContext.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/helpers/PageContext.kt new file mode 100644 index 000000000000..7f310fec5c52 --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/helpers/PageContext.kt @@ -0,0 +1,45 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.ui.efficiency.helpers + +import androidx.compose.ui.test.junit4.AndroidComposeTestRule +import org.mozilla.fenix.helpers.HomeActivityIntentTestRule +import org.mozilla.fenix.ui.efficiency.pageObjects.HomePage +import org.mozilla.fenix.ui.efficiency.pageObjects.SettingsAccessibilityPage +import org.mozilla.fenix.ui.efficiency.pageObjects.SettingsAutofillPage +import org.mozilla.fenix.ui.efficiency.pageObjects.SettingsCustomizePage +import org.mozilla.fenix.ui.efficiency.pageObjects.SettingsHomepagePage +import org.mozilla.fenix.ui.efficiency.pageObjects.SettingsPage +import org.mozilla.fenix.ui.efficiency.pageObjects.SettingsPasswordsPage +import org.mozilla.fenix.ui.efficiency.pageObjects.SettingsSearchPage +import org.mozilla.fenix.ui.efficiency.pageObjects.SettingsTabsPage + +class PageContext(val composeRule: AndroidComposeTestRule) { + val home = HomePage(composeRule) + val settings = SettingsPage(composeRule) + val settingsAccessibility = SettingsAccessibilityPage(composeRule) + val settingsAutofill = SettingsAutofillPage(composeRule) + val settingsCustomize = SettingsCustomizePage(composeRule) + val settingsHomepage = SettingsHomepagePage(composeRule) + val settingsPasswords = SettingsPasswordsPage(composeRule) + val settingsSearch = SettingsSearchPage(composeRule) + val settingsTabs = SettingsTabsPage(composeRule) + + fun initTestRule( + skipOnboarding: Boolean = true, + isMenuRedesignEnabled: Boolean = true, + isMenuRedesignCFREnabled: Boolean = false, + isPageLoadTranslationsPromptEnabled: Boolean = false, + ): AndroidComposeTestRule { + return AndroidComposeTestRule( + HomeActivityIntentTestRule( + skipOnboarding = skipOnboarding, + isMenuRedesignEnabled = isMenuRedesignEnabled, + isMenuRedesignCFREnabled = isMenuRedesignCFREnabled, + isPageLoadTranslationsPromptEnabled = isPageLoadTranslationsPromptEnabled, + ), + ) { it.activity } + } +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/helpers/PageStateTracker.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/helpers/PageStateTracker.kt new file mode 100644 index 000000000000..b1365735ac99 --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/helpers/PageStateTracker.kt @@ -0,0 +1,9 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.ui.efficiency.helpers + +object PageStateTracker { + var currentPageName: String = "AppEntry" +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/helpers/Selector.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/helpers/Selector.kt new file mode 100644 index 000000000000..99557ed43b79 --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/helpers/Selector.kt @@ -0,0 +1,39 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.ui.efficiency.helpers + +import org.mozilla.fenix.R + +data class Selector( + val strategy: SelectorStrategy, + val value: String, + val description: String, + val groups: List = listOf(), +) { + fun toResourceId(): Int { + return try { + val rClass = R.id::class.java + val field = rClass.getField(value) + field.getInt(null) + } catch (e: Exception) { + throw IllegalArgumentException("Could not resolve resource ID for selector value: '$value' using R.id", e) + } + } +} + +enum class SelectorStrategy { + /** + * Supported strategies for locating UI elements. + */ + COMPOSE_BY_TAG, + COMPOSE_BY_TEXT, + ESPRESSO_BY_ID, + ESPRESSO_BY_TEXT, + ESPRESSO_BY_CONTENT_DESC, + UIAUTOMATOR2_BY_RES, + UIAUTOMATOR2_BY_CLASS, + UIAUTOMATOR2_BY_TEXT, + UIAUTOMATOR2_BY_RES_ID, +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/helpers/SwipeDirection.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/helpers/SwipeDirection.kt new file mode 100644 index 000000000000..21168f988950 --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/helpers/SwipeDirection.kt @@ -0,0 +1,5 @@ +package org.mozilla.fenix.ui.efficiency.helpers + +enum class SwipeDirection { + UP, DOWN, LEFT, RIGHT +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/navigation/NavigationEdge.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/navigation/NavigationEdge.kt new file mode 100644 index 000000000000..6324eb8df619 --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/navigation/NavigationEdge.kt @@ -0,0 +1,11 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.ui.efficiency.navigation + +data class NavigationEdge( + val from: String, + val to: String, + val steps: List, +) diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/navigation/NavigationRegistry.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/navigation/NavigationRegistry.kt new file mode 100644 index 000000000000..aeb6ae6a53ca --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/navigation/NavigationRegistry.kt @@ -0,0 +1,51 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.ui.efficiency.navigation + +import android.util.Log + +object NavigationRegistry { + private val graph = mutableMapOf>() + + fun register(from: String, to: String, steps: List) { + val edge = NavigationEdge(from, to, steps) + graph.getOrPut(from) { mutableListOf() }.add(edge) + + Log.i("NavigationRegistry", "📌 Registered navigation: $from -> $to with ${steps.size} step(s)") + steps.forEachIndexed { index, step -> + Log.i("NavigationRegistry", " Step ${index + 1}: $step") + } + } + + fun findPath(from: String, to: String): List? { + val visited = mutableSetOf() + val path = mutableListOf() + return dfs(from, to, visited, path) + } + + private fun dfs(current: String, target: String, visited: MutableSet, path: MutableList): List? { + if (current == target) return path.toList() + visited.add(current) + + for (edge in graph[current].orEmpty()) { + if (edge.to !in visited) { + path.addAll(edge.steps) + val result = dfs(edge.to, target, visited, path) + if (result != null) return result + path.removeAll(edge.steps) + } + } + return null + } + + fun logGraph() { + Log.i("NavigationRegistry", "🧭 Current navigation graph:") + for ((from, edges) in graph) { + for (edge in edges) { + Log.i("NavigationRegistry", " - $from -> ${edge.to} [${edge.steps.size} step(s)]") + } + } + } +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/navigation/NavigationStep.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/navigation/NavigationStep.kt new file mode 100644 index 000000000000..a9177feb473c --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/navigation/NavigationStep.kt @@ -0,0 +1,13 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.ui.efficiency.navigation + +import org.mozilla.fenix.ui.efficiency.helpers.Selector +import org.mozilla.fenix.ui.efficiency.helpers.SwipeDirection + +sealed class NavigationStep { + data class Click(val selector: Selector) : NavigationStep() + data class Swipe(val selector: Selector, val direction: SwipeDirection = SwipeDirection.UP) : NavigationStep() +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/pageObjects/HomePage.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/pageObjects/HomePage.kt new file mode 100644 index 000000000000..2c9795ff0ae9 --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/pageObjects/HomePage.kt @@ -0,0 +1,65 @@ +package org.mozilla.fenix.ui.efficiency.pageObjects + +import androidx.compose.ui.test.junit4.AndroidComposeTestRule +import org.mozilla.fenix.helpers.HomeActivityIntentTestRule +import org.mozilla.fenix.ui.efficiency.helpers.BasePage +import org.mozilla.fenix.ui.efficiency.helpers.Selector +import org.mozilla.fenix.ui.efficiency.navigation.NavigationRegistry +import org.mozilla.fenix.ui.efficiency.navigation.NavigationStep +import org.mozilla.fenix.ui.efficiency.selectors.HomeSelectors + +class HomePage(composeRule: AndroidComposeTestRule) : BasePage(composeRule) { + + override val pageName = "HomePage" + + init { + NavigationRegistry.register( + from = "AppEntry", + to = pageName, + steps = listOf(), + ) + + NavigationRegistry.register( + from = pageName, + to = "ThreeDotMenu", + steps = listOf(NavigationStep.Click(HomeSelectors.THREE_DOT_MENU)), + ) + + NavigationRegistry.register( + from = "ThreeDotMenu", + to = "BookmarksPage", + steps = listOf(NavigationStep.Click(HomeSelectors.TDM_BOOKMARKS_BUTTON)), + ) + + NavigationRegistry.register( + from = "ThreeDotMenu", + to = "SettingsPage", + steps = listOf( + NavigationStep.Swipe(HomeSelectors.TDM_SETTINGS_BUTTON_COMPOSE), + NavigationStep.Click(HomeSelectors.TDM_SETTINGS_BUTTON_COMPOSE), + ), + ) + + NavigationRegistry.register( + from = "ThreeDotMenu", + to = "HistoryPage", + steps = listOf(NavigationStep.Click(HomeSelectors.TDM_HISTORY_BUTTON)), + ) + + NavigationRegistry.register( + from = "ThreeDotMenu", + to = "DownloadsPage", + steps = listOf(NavigationStep.Click(HomeSelectors.TDM_DOWNLOADS_BUTTON)), + ) + + NavigationRegistry.register( + from = "ThreeDotMenu", + to = "PasswordsPage", + steps = listOf(NavigationStep.Click(HomeSelectors.TDM_PASSWORDS_BUTTON)), + ) + } + + override fun mozGetSelectorsByGroup(group: String): List { + return HomeSelectors.all.filter { it.groups.contains(group) } + } +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/pageObjects/SettingsAccessibilityPage.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/pageObjects/SettingsAccessibilityPage.kt new file mode 100644 index 000000000000..74e602ec356f --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/pageObjects/SettingsAccessibilityPage.kt @@ -0,0 +1,26 @@ +package org.mozilla.fenix.ui.efficiency.pageObjects + +import androidx.compose.ui.test.junit4.AndroidComposeTestRule +import org.mozilla.fenix.helpers.HomeActivityIntentTestRule +import org.mozilla.fenix.ui.efficiency.helpers.BasePage +import org.mozilla.fenix.ui.efficiency.helpers.Selector +import org.mozilla.fenix.ui.efficiency.navigation.NavigationRegistry +import org.mozilla.fenix.ui.efficiency.navigation.NavigationStep +import org.mozilla.fenix.ui.efficiency.selectors.SettingsAccessibilitySelectors +import org.mozilla.fenix.ui.efficiency.selectors.SettingsSelectors + +class SettingsAccessibilityPage(composeRule: AndroidComposeTestRule) : BasePage(composeRule) { + override val pageName = "SettingsAccessibilityPage" + + init { + NavigationRegistry.register( + from = pageName, + to = "SettingsPage", + steps = listOf(NavigationStep.Click(SettingsSelectors.GO_BACK_BUTTON)), + ) + } + + override fun mozGetSelectorsByGroup(group: String): List { + return SettingsAccessibilitySelectors.all.filter { it.groups.contains(group) } + } +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/pageObjects/SettingsAutofillPage.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/pageObjects/SettingsAutofillPage.kt new file mode 100644 index 000000000000..7aaef4e51754 --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/pageObjects/SettingsAutofillPage.kt @@ -0,0 +1,26 @@ +package org.mozilla.fenix.ui.efficiency.pageObjects + +import androidx.compose.ui.test.junit4.AndroidComposeTestRule +import org.mozilla.fenix.helpers.HomeActivityIntentTestRule +import org.mozilla.fenix.ui.efficiency.helpers.BasePage +import org.mozilla.fenix.ui.efficiency.helpers.Selector +import org.mozilla.fenix.ui.efficiency.navigation.NavigationRegistry +import org.mozilla.fenix.ui.efficiency.navigation.NavigationStep +import org.mozilla.fenix.ui.efficiency.selectors.SettingsAutofillSelectors +import org.mozilla.fenix.ui.efficiency.selectors.SettingsSelectors + +class SettingsAutofillPage(composeRule: AndroidComposeTestRule) : BasePage(composeRule) { + override val pageName = "SettingsAutofillPage" + + init { + NavigationRegistry.register( + from = pageName, + to = "SettingsPage", + steps = listOf(NavigationStep.Click(SettingsSelectors.GO_BACK_BUTTON)), + ) + } + + override fun mozGetSelectorsByGroup(group: String): List { + return SettingsAutofillSelectors.all.filter { it.groups.contains(group) } + } +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/pageObjects/SettingsCustomizePage.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/pageObjects/SettingsCustomizePage.kt new file mode 100644 index 000000000000..de063ead5a91 --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/pageObjects/SettingsCustomizePage.kt @@ -0,0 +1,26 @@ +package org.mozilla.fenix.ui.efficiency.pageObjects + +import androidx.compose.ui.test.junit4.AndroidComposeTestRule +import org.mozilla.fenix.helpers.HomeActivityIntentTestRule +import org.mozilla.fenix.ui.efficiency.helpers.BasePage +import org.mozilla.fenix.ui.efficiency.helpers.Selector +import org.mozilla.fenix.ui.efficiency.navigation.NavigationRegistry +import org.mozilla.fenix.ui.efficiency.navigation.NavigationStep +import org.mozilla.fenix.ui.efficiency.selectors.SettingsCustomizeSelectors +import org.mozilla.fenix.ui.efficiency.selectors.SettingsSelectors + +class SettingsCustomizePage(composeRule: AndroidComposeTestRule) : BasePage(composeRule) { + override val pageName = "SettingsCustomizePage" + + init { + NavigationRegistry.register( + from = pageName, + to = "SettingsPage", + steps = listOf(NavigationStep.Click(SettingsSelectors.GO_BACK_BUTTON)), + ) + } + + override fun mozGetSelectorsByGroup(group: String): List { + return SettingsCustomizeSelectors.all.filter { it.groups.contains(group) } + } +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/pageObjects/SettingsHomepagePage.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/pageObjects/SettingsHomepagePage.kt new file mode 100644 index 000000000000..13a2f7e0a243 --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/pageObjects/SettingsHomepagePage.kt @@ -0,0 +1,26 @@ +package org.mozilla.fenix.ui.efficiency.pageObjects + +import androidx.compose.ui.test.junit4.AndroidComposeTestRule +import org.mozilla.fenix.helpers.HomeActivityIntentTestRule +import org.mozilla.fenix.ui.efficiency.helpers.BasePage +import org.mozilla.fenix.ui.efficiency.helpers.Selector +import org.mozilla.fenix.ui.efficiency.navigation.NavigationRegistry +import org.mozilla.fenix.ui.efficiency.navigation.NavigationStep +import org.mozilla.fenix.ui.efficiency.selectors.SettingsHomepageSelectors +import org.mozilla.fenix.ui.efficiency.selectors.SettingsSelectors + +class SettingsHomepagePage(composeRule: AndroidComposeTestRule) : BasePage(composeRule) { + override val pageName = "SettingsHomepagePage" + + init { + NavigationRegistry.register( + from = "SettingsPage", + to = pageName, + steps = listOf(NavigationStep.Click(SettingsSelectors.GO_BACK_BUTTON)), + ) + } + + override fun mozGetSelectorsByGroup(group: String): List { + return SettingsHomepageSelectors.all.filter { it.groups.contains(group) } + } +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/pageObjects/SettingsPage.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/pageObjects/SettingsPage.kt new file mode 100644 index 000000000000..e25e7cd74738 --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/pageObjects/SettingsPage.kt @@ -0,0 +1,69 @@ +package org.mozilla.fenix.ui.efficiency.pageObjects + +import androidx.compose.ui.test.junit4.AndroidComposeTestRule +import org.mozilla.fenix.helpers.HomeActivityIntentTestRule +import org.mozilla.fenix.ui.efficiency.helpers.BasePage +import org.mozilla.fenix.ui.efficiency.helpers.Selector +import org.mozilla.fenix.ui.efficiency.navigation.NavigationRegistry +import org.mozilla.fenix.ui.efficiency.navigation.NavigationStep +import org.mozilla.fenix.ui.efficiency.selectors.HomeSelectors +import org.mozilla.fenix.ui.efficiency.selectors.SettingsSelectors + +class SettingsPage(composeRule: AndroidComposeTestRule) : BasePage(composeRule) { + override val pageName = "SettingsPage" + + init { + NavigationRegistry.register( + from = "ThreeDotMenu", + to = pageName, + steps = listOf(NavigationStep.Click(HomeSelectors.TDM_SETTINGS_BUTTON)), + ) + NavigationRegistry.register( + from = pageName, + to = "HomePage", + steps = listOf(NavigationStep.Click(SettingsSelectors.GO_BACK_BUTTON)), + ) + NavigationRegistry.register( + from = pageName, + to = "SettingsAccessibilityPage", + steps = listOf( + NavigationStep.Swipe(SettingsSelectors.ACCESSIBILITY_BUTTON), + NavigationStep.Click(SettingsSelectors.ACCESSIBILITY_BUTTON), + ), + ) + NavigationRegistry.register( + from = pageName, + to = "SettingsAutofillPage", + steps = listOf(NavigationStep.Click(SettingsSelectors.AUTOFILL_BUTTON)), + ) + NavigationRegistry.register( + from = pageName, + to = "SettingsCustomizePage", + steps = listOf(NavigationStep.Click(SettingsSelectors.CUSTOMIZE_BUTTON)), + ) + NavigationRegistry.register( + from = pageName, + to = "SettingsHomepagePage", + steps = listOf(NavigationStep.Click(SettingsSelectors.HOMEPAGE_BUTTON)), + ) + NavigationRegistry.register( + from = pageName, + to = "SettingsPasswordsPage", + steps = listOf(NavigationStep.Click(SettingsSelectors.PASSWORDS_BUTTON)), + ) + NavigationRegistry.register( + from = pageName, + to = "SettingsSearchPage", + steps = listOf(NavigationStep.Click(SettingsSelectors.SEARCH_BUTTON)), + ) + NavigationRegistry.register( + from = pageName, + to = "SettingsTabsPage", + steps = listOf(NavigationStep.Click(SettingsSelectors.TABS_BUTTON)), + ) + } + + override fun mozGetSelectorsByGroup(group: String): List { + return SettingsSelectors.all.filter { it.groups.contains(group) } + } +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/pageObjects/SettingsPasswordsPage.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/pageObjects/SettingsPasswordsPage.kt new file mode 100644 index 000000000000..69907ba18ba5 --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/pageObjects/SettingsPasswordsPage.kt @@ -0,0 +1,26 @@ +package org.mozilla.fenix.ui.efficiency.pageObjects + +import androidx.compose.ui.test.junit4.AndroidComposeTestRule +import org.mozilla.fenix.helpers.HomeActivityIntentTestRule +import org.mozilla.fenix.ui.efficiency.helpers.BasePage +import org.mozilla.fenix.ui.efficiency.helpers.Selector +import org.mozilla.fenix.ui.efficiency.navigation.NavigationRegistry +import org.mozilla.fenix.ui.efficiency.navigation.NavigationStep +import org.mozilla.fenix.ui.efficiency.selectors.SettingsPasswordsSelectors +import org.mozilla.fenix.ui.efficiency.selectors.SettingsSelectors + +class SettingsPasswordsPage(composeRule: AndroidComposeTestRule) : BasePage(composeRule) { + override val pageName = "SettingsPasswordsPage" + + init { + NavigationRegistry.register( + from = pageName, + to = "SettingsPage", + steps = listOf(NavigationStep.Click(SettingsSelectors.GO_BACK_BUTTON)), + ) + } + + override fun mozGetSelectorsByGroup(group: String): List { + return SettingsPasswordsSelectors.all.filter { it.groups.contains(group) } + } +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/pageObjects/SettingsSearchPage.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/pageObjects/SettingsSearchPage.kt new file mode 100644 index 000000000000..9733f7e92ea7 --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/pageObjects/SettingsSearchPage.kt @@ -0,0 +1,26 @@ +package org.mozilla.fenix.ui.efficiency.pageObjects + +import androidx.compose.ui.test.junit4.AndroidComposeTestRule +import org.mozilla.fenix.helpers.HomeActivityIntentTestRule +import org.mozilla.fenix.ui.efficiency.helpers.BasePage +import org.mozilla.fenix.ui.efficiency.helpers.Selector +import org.mozilla.fenix.ui.efficiency.navigation.NavigationRegistry +import org.mozilla.fenix.ui.efficiency.navigation.NavigationStep +import org.mozilla.fenix.ui.efficiency.selectors.SettingsSearchSelectors +import org.mozilla.fenix.ui.efficiency.selectors.SettingsSelectors + +class SettingsSearchPage(composeRule: AndroidComposeTestRule) : BasePage(composeRule) { + override val pageName = "SettingsSearchPage" + + init { + NavigationRegistry.register( + from = pageName, + to = "SettingsPage", + steps = listOf(NavigationStep.Click(SettingsSelectors.GO_BACK_BUTTON)), + ) + } + + override fun mozGetSelectorsByGroup(group: String): List { + return SettingsSearchSelectors.all.filter { it.groups.contains(group) } + } +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/pageObjects/SettingsTabsPage.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/pageObjects/SettingsTabsPage.kt new file mode 100644 index 000000000000..ff52466dd43f --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/pageObjects/SettingsTabsPage.kt @@ -0,0 +1,26 @@ +package org.mozilla.fenix.ui.efficiency.pageObjects + +import androidx.compose.ui.test.junit4.AndroidComposeTestRule +import org.mozilla.fenix.helpers.HomeActivityIntentTestRule +import org.mozilla.fenix.ui.efficiency.helpers.BasePage +import org.mozilla.fenix.ui.efficiency.helpers.Selector +import org.mozilla.fenix.ui.efficiency.navigation.NavigationRegistry +import org.mozilla.fenix.ui.efficiency.navigation.NavigationStep +import org.mozilla.fenix.ui.efficiency.selectors.SettingsSelectors +import org.mozilla.fenix.ui.efficiency.selectors.SettingsTabsSelectors + +class SettingsTabsPage(composeRule: AndroidComposeTestRule) : BasePage(composeRule) { + override val pageName = "SettingsTabsPage" + + init { + NavigationRegistry.register( + from = pageName, + to = "SettingsPage", + steps = listOf(NavigationStep.Click(SettingsSelectors.GO_BACK_BUTTON)), + ) + } + + override fun mozGetSelectorsByGroup(group: String): List { + return SettingsTabsSelectors.all.filter { it.groups.contains(group) } + } +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/selectors/HomeSelectors.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/selectors/HomeSelectors.kt new file mode 100644 index 000000000000..52daeecf1880 --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/selectors/HomeSelectors.kt @@ -0,0 +1,84 @@ +package org.mozilla.fenix.ui.efficiency.selectors + +import org.mozilla.fenix.R +import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource +import org.mozilla.fenix.ui.efficiency.helpers.Selector +import org.mozilla.fenix.ui.efficiency.helpers.SelectorStrategy + +object HomeSelectors { + val TOP_SITES_LIST = Selector( + strategy = SelectorStrategy.UIAUTOMATOR2_BY_RES_ID, + value = "id/top_sites_list", + description = "Top Sites List", + groups = listOf("topSites"), + ) + + val TOP_SITES_LIST_COMPOSE = Selector( + strategy = SelectorStrategy.COMPOSE_BY_TAG, + value = "top_sites_list", + description = "Top Sites List", + groups = listOf("topSitesCompose"), + ) + + val THREE_DOT_MENU = Selector( + strategy = SelectorStrategy.ESPRESSO_BY_ID, + value = "menuButton", + description = "Three Dot Menu", + groups = listOf("requiredForPage"), + ) + + // TODO (Jackie J. 4/18/25): move THREE_DOT_MENU to component object file in next phase + + // TODO (Jackie J. 4/18/25): add support for resId as text + val TDM_SETTINGS_BUTTON_COMPOSE = Selector( + strategy = SelectorStrategy.COMPOSE_BY_TEXT, + value = "Settings", + description = "Menu item with text 'Settings'", + groups = listOf("threeDotMenu", "compose"), + ) + + val TDM_SETTINGS_BUTTON = Selector( + strategy = SelectorStrategy.UIAUTOMATOR2_BY_TEXT, + value = getStringResource(R.string.browser_menu_settings), + description = "the Settings Button", + groups = listOf("threeDotMenu"), + ) + + val TDM_HISTORY_BUTTON = Selector( + strategy = SelectorStrategy.UIAUTOMATOR2_BY_TEXT, + value = getStringResource(R.string.library_history), + description = "the History button", + groups = listOf("threeDotMenu", "Bug-1234"), + ) + + val TDM_BOOKMARKS_BUTTON = Selector( + strategy = SelectorStrategy.UIAUTOMATOR2_BY_TEXT, + value = getStringResource(R.string.library_bookmarks), + description = "the Bookmarks button", + groups = listOf("threeDotMenu"), + ) + + val TDM_DOWNLOADS_BUTTON = Selector( + strategy = SelectorStrategy.UIAUTOMATOR2_BY_TEXT, + value = getStringResource(R.string.library_downloads), + description = "the Downloads button", + groups = listOf("threeDotMenu"), + ) + + val TDM_PASSWORDS_BUTTON = Selector( + strategy = SelectorStrategy.UIAUTOMATOR2_BY_TEXT, + value = getStringResource(R.string.browser_menu_passwords), + description = "the Passwords button", + groups = listOf("threeDotMenu"), + ) + + val all = listOf( + THREE_DOT_MENU, + TDM_HISTORY_BUTTON, + TDM_BOOKMARKS_BUTTON, + TDM_DOWNLOADS_BUTTON, + TDM_PASSWORDS_BUTTON, + TDM_SETTINGS_BUTTON, + TOP_SITES_LIST, + ) +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/selectors/SettingsAccessibilitySelectors.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/selectors/SettingsAccessibilitySelectors.kt new file mode 100644 index 000000000000..32e63e75b75a --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/selectors/SettingsAccessibilitySelectors.kt @@ -0,0 +1,27 @@ +package org.mozilla.fenix.ui.efficiency.selectors + +import org.mozilla.fenix.R +import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource +import org.mozilla.fenix.ui.efficiency.helpers.Selector +import org.mozilla.fenix.ui.efficiency.helpers.SelectorStrategy + +object SettingsAccessibilitySelectors { + val SETTINGS_ACCESSIBILITY_TITLE = Selector( + strategy = SelectorStrategy.UIAUTOMATOR2_BY_TEXT, + value = getStringResource(R.string.preferences_accessibility), + description = "The Accessibility Settings header", + groups = listOf("requiredForPage"), + ) + + val USE_SYSTEM_FONT_SIZE_TOGGLE = Selector( + strategy = SelectorStrategy.ESPRESSO_BY_ID, + value = "use_system_font_size_toggle", + description = "Use System Font Size Toggle", + groups = listOf("accessibilitySettings"), + ) + + val all = listOf( + SETTINGS_ACCESSIBILITY_TITLE, + USE_SYSTEM_FONT_SIZE_TOGGLE, + ) +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/selectors/SettingsAutofillSelectors.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/selectors/SettingsAutofillSelectors.kt new file mode 100644 index 000000000000..29fdaaa8fbee --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/selectors/SettingsAutofillSelectors.kt @@ -0,0 +1,25 @@ +package org.mozilla.fenix.ui.efficiency.selectors + +import org.mozilla.fenix.ui.efficiency.helpers.Selector +import org.mozilla.fenix.ui.efficiency.helpers.SelectorStrategy + +object SettingsAutofillSelectors { + val SETTINGS_AUTOFILL_TITLE = Selector( + strategy = SelectorStrategy.UIAUTOMATOR2_BY_TEXT, + value = "Autofill", + description = "The Autofill Settings title", + groups = listOf("requiredForPage"), + ) + + val AUTOFILL_ADDRESSES_TOGGLE = Selector( + strategy = SelectorStrategy.ESPRESSO_BY_ID, + value = "autofill_addresses_toggle", + description = "Autofill Addresses Toggle", + groups = listOf("autofillSettings"), + ) + + val all = listOf( + SETTINGS_AUTOFILL_TITLE, + AUTOFILL_ADDRESSES_TOGGLE, + ) +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/selectors/SettingsCustomizeSelectors.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/selectors/SettingsCustomizeSelectors.kt new file mode 100644 index 000000000000..4e24355c4e22 --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/selectors/SettingsCustomizeSelectors.kt @@ -0,0 +1,25 @@ +package org.mozilla.fenix.ui.efficiency.selectors + +import org.mozilla.fenix.ui.efficiency.helpers.Selector +import org.mozilla.fenix.ui.efficiency.helpers.SelectorStrategy + +object SettingsCustomizeSelectors { + val SETTINGS_CUSTOMIZE_TITLE = Selector( + strategy = SelectorStrategy.UIAUTOMATOR2_BY_TEXT, + value = "Customize", + description = "The Customize Settings title", + groups = listOf("requiredForPage"), + ) + + val SHOW_TOOLBAR_TOGGLE = Selector( + strategy = SelectorStrategy.ESPRESSO_BY_ID, + value = "show_toolbar_toggle", + description = "Show Toolbar Toggle", + groups = listOf("customizeSettings"), + ) + + val all = listOf( + SETTINGS_CUSTOMIZE_TITLE, + SHOW_TOOLBAR_TOGGLE, + ) +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/selectors/SettingsHomepageSelectors.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/selectors/SettingsHomepageSelectors.kt new file mode 100644 index 000000000000..ec43d8497ea8 --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/selectors/SettingsHomepageSelectors.kt @@ -0,0 +1,25 @@ +package org.mozilla.fenix.ui.efficiency.selectors + +import org.mozilla.fenix.ui.efficiency.helpers.Selector +import org.mozilla.fenix.ui.efficiency.helpers.SelectorStrategy + +object SettingsHomepageSelectors { + val SETTINGS_HOMEPAGE_TITLE = Selector( + strategy = SelectorStrategy.UIAUTOMATOR2_BY_TEXT, + value = "Homepage", + description = "The Homepage Settings menu item", + groups = listOf("requiredForPage"), + ) + + val SHOW_TOP_SITES_TOGGLE = Selector( + strategy = SelectorStrategy.ESPRESSO_BY_ID, + value = "show_top_sites_toggle", + description = "Show Top Sites Toggle", + groups = listOf("homepageSettings"), + ) + + val all = listOf( + SETTINGS_HOMEPAGE_TITLE, + SHOW_TOP_SITES_TOGGLE, + ) +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/selectors/SettingsPasswordsSelectors.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/selectors/SettingsPasswordsSelectors.kt new file mode 100644 index 000000000000..45aed26568f8 --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/selectors/SettingsPasswordsSelectors.kt @@ -0,0 +1,25 @@ +package org.mozilla.fenix.ui.efficiency.selectors + +import org.mozilla.fenix.ui.efficiency.helpers.Selector +import org.mozilla.fenix.ui.efficiency.helpers.SelectorStrategy + +object SettingsPasswordsSelectors { + val SETTINGS_PASSWORDS_TITLE = Selector( + strategy = SelectorStrategy.UIAUTOMATOR2_BY_TEXT, + value = "Passwords", + description = "The Passwords Settings title", + groups = listOf("requiredForPage"), + ) + + val SAVE_PASSWORDS_TOGGLE = Selector( + strategy = SelectorStrategy.ESPRESSO_BY_ID, + value = "save_passwords_toggle", + description = "Save Passwords Toggle", + groups = listOf("passwordSettings"), + ) + + val all = listOf( + SETTINGS_PASSWORDS_TITLE, + SAVE_PASSWORDS_TOGGLE, + ) +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/selectors/SettingsSearchSelectors.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/selectors/SettingsSearchSelectors.kt new file mode 100644 index 000000000000..8efa6acf89ae --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/selectors/SettingsSearchSelectors.kt @@ -0,0 +1,15 @@ +package org.mozilla.fenix.ui.efficiency.selectors + +import org.mozilla.fenix.ui.efficiency.helpers.Selector +import org.mozilla.fenix.ui.efficiency.helpers.SelectorStrategy + +object SettingsSearchSelectors { + val SETTINGS_SEARCH_TITLE = Selector( + strategy = SelectorStrategy.ESPRESSO_BY_TEXT, + value = "Search", + description = "the Settings Search title", + groups = listOf("requiredForPage"), + ) + + val all = listOf(SETTINGS_SEARCH_TITLE) +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/selectors/SettingsSelectors.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/selectors/SettingsSelectors.kt new file mode 100644 index 000000000000..598e8c814be1 --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/selectors/SettingsSelectors.kt @@ -0,0 +1,81 @@ +package org.mozilla.fenix.ui.efficiency.selectors + +import org.mozilla.fenix.ui.efficiency.helpers.Selector +import org.mozilla.fenix.ui.efficiency.helpers.SelectorStrategy + +object SettingsSelectors { + val GO_BACK_BUTTON = Selector( + strategy = SelectorStrategy.ESPRESSO_BY_CONTENT_DESC, + value = "Navigate up", + description = "the Back Arrow button", + groups = listOf("requiredForPage"), + ) + + val GENERAL_HEADING = Selector( + strategy = SelectorStrategy.ESPRESSO_BY_TEXT, + value = "General", + description = "the General heading", + groups = listOf("requiredForPage"), + ) + + val SEARCH_BUTTON = Selector( + strategy = SelectorStrategy.UIAUTOMATOR2_BY_TEXT, + value = "Search", + description = "the Search button", + groups = listOf("requiredForPage"), + ) + + val TABS_BUTTON = Selector( + strategy = SelectorStrategy.UIAUTOMATOR2_BY_TEXT, + value = "Tabs", + description = "the Tabs button", + groups = listOf("requiredForPage"), + ) + + val ACCESSIBILITY_BUTTON = Selector( + strategy = SelectorStrategy.ESPRESSO_BY_TEXT, + value = "Accessibility", + description = "the Accessibility button", + groups = listOf("requiredForPage"), + ) + + val AUTOFILL_BUTTON = Selector( + strategy = SelectorStrategy.ESPRESSO_BY_TEXT, + value = "Autofill", + description = "the Autofill button", + groups = listOf("requiredForPage"), + ) + + val CUSTOMIZE_BUTTON = Selector( + strategy = SelectorStrategy.ESPRESSO_BY_TEXT, + value = "Customize", + description = "the Customize button", + groups = listOf("requiredForPage"), + ) + + val HOMEPAGE_BUTTON = Selector( + strategy = SelectorStrategy.ESPRESSO_BY_TEXT, + value = "Homepage", + description = "the Homepage button", + groups = listOf("requiredForPage"), + ) + + val PASSWORDS_BUTTON = Selector( + strategy = SelectorStrategy.ESPRESSO_BY_TEXT, + value = "Passwords", + description = "the Passwords button", + groups = listOf("requiredForPage"), + ) + + val all = listOf( + GO_BACK_BUTTON, + GENERAL_HEADING, + SEARCH_BUTTON, + TABS_BUTTON, + ACCESSIBILITY_BUTTON, + AUTOFILL_BUTTON, + CUSTOMIZE_BUTTON, + HOMEPAGE_BUTTON, + PASSWORDS_BUTTON, + ) +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/selectors/SettingsTabsSelectors.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/selectors/SettingsTabsSelectors.kt new file mode 100644 index 000000000000..232ad8b12e6f --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/selectors/SettingsTabsSelectors.kt @@ -0,0 +1,25 @@ +package org.mozilla.fenix.ui.efficiency.selectors + +import org.mozilla.fenix.ui.efficiency.helpers.Selector +import org.mozilla.fenix.ui.efficiency.helpers.SelectorStrategy + +object SettingsTabsSelectors { + val SETTINGS_TABS_TITLE = Selector( + strategy = SelectorStrategy.UIAUTOMATOR2_BY_TEXT, + value = "Tabs", + description = "The Settings Tabs title", + groups = listOf("requiredForPage"), + ) + + val NEW_TAB_PAGE_TOGGLE = Selector( + strategy = SelectorStrategy.ESPRESSO_BY_ID, + value = "new_tab_page_toggle", + description = "New Tab Page Toggle Switch", + groups = listOf("tabSettings"), + ) + + val all = listOf( + SETTINGS_TABS_TITLE, + NEW_TAB_PAGE_TOGGLE, + ) +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/tests/HomeTest.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/tests/HomeTest.kt new file mode 100644 index 000000000000..feac34051b97 --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/tests/HomeTest.kt @@ -0,0 +1,20 @@ +package org.mozilla.fenix.ui.efficiency.tests + +import org.junit.Test +import org.mozilla.fenix.ui.efficiency.helpers.BaseTest + +class HomeTest : BaseTest() { + // TestRail link: https://mozilla.testrail.io/index.php?/cases/view/235396 + @Test + fun homeScreenItemsTest() { + // Given: App is loaded with default settings + // on = AndroidComposeTestRule with app defaults + + // When: We navigate to the Settings page and back to the Home page + on.settings.navigateToPage() + on.home.navigateToPage() + + // Then: the browser chrome, page components, and elements should load + on.home.mozVerifyElementsByGroup("topSitesCompose") + } +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/tests/SettingsAccessibilityTest.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/tests/SettingsAccessibilityTest.kt new file mode 100644 index 000000000000..0514501feffb --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/tests/SettingsAccessibilityTest.kt @@ -0,0 +1,12 @@ +package org.mozilla.fenix.ui.efficiency.tests + +import org.junit.Test +import org.mozilla.fenix.ui.efficiency.helpers.BaseTest + +class SettingsAccessibilityTest : BaseTest() { + + @Test + fun verifySettingsAccessibilityPageLoadsTest() { + on.settingsAccessibility.navigateToPage() + } +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/tests/SettingsAutofillTest.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/tests/SettingsAutofillTest.kt new file mode 100644 index 000000000000..557722fb8742 --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/tests/SettingsAutofillTest.kt @@ -0,0 +1,12 @@ +package org.mozilla.fenix.ui.efficiency.tests + +import org.junit.Test +import org.mozilla.fenix.ui.efficiency.helpers.BaseTest + +class SettingsAutofillTest : BaseTest() { + + @Test + fun verifySettingsAutofillLoadsTest() { + on.settingsAutofill.navigateToPage() + } +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/tests/SettingsCustomizeTest.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/tests/SettingsCustomizeTest.kt new file mode 100644 index 000000000000..60a8df4d2168 --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/tests/SettingsCustomizeTest.kt @@ -0,0 +1,12 @@ +package org.mozilla.fenix.ui.efficiency.tests + +import org.junit.Test +import org.mozilla.fenix.ui.efficiency.helpers.BaseTest + +class SettingsCustomizeTest : BaseTest() { + + @Test + fun verifySettingsCustomizeLoadsTest() { + on.settingsCustomize.navigateToPage() + } +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/tests/SettingsHomepageTest.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/tests/SettingsHomepageTest.kt new file mode 100644 index 000000000000..eae9040154be --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/tests/SettingsHomepageTest.kt @@ -0,0 +1,12 @@ +package org.mozilla.fenix.ui.efficiency.tests + +import org.junit.Test +import org.mozilla.fenix.ui.efficiency.helpers.BaseTest + +class SettingsHomepageTest : BaseTest() { + + @Test + fun verifySettingsHomepageLoadsTest() { + on.settingsHomepage.navigateToPage() + } +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/tests/SettingsPasswordsTest.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/tests/SettingsPasswordsTest.kt new file mode 100644 index 000000000000..821534b738db --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/tests/SettingsPasswordsTest.kt @@ -0,0 +1,12 @@ +package org.mozilla.fenix.ui.efficiency.tests + +import org.junit.Test +import org.mozilla.fenix.ui.efficiency.helpers.BaseTest + +class SettingsPasswordsTest : BaseTest() { + + @Test + fun verifySettingsPasswordsLoadsTest() { + on.settingsPasswords.navigateToPage() + } +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/tests/SettingsSearchTest.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/tests/SettingsSearchTest.kt new file mode 100644 index 000000000000..21da1c3d4396 --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/tests/SettingsSearchTest.kt @@ -0,0 +1,20 @@ +package org.mozilla.fenix.ui.efficiency.tests + +import org.junit.Test +import org.mozilla.fenix.ui.efficiency.helpers.BaseTest + +class SettingsSearchTest : BaseTest() { + + // TestRail link: https://mozilla.testrail.io/index.php?/cases/view/2203333 + @Test + fun verifySearchSettingsMenuItemsTest() { + // Given: App is loaded with default settings + // on = AndroidComposeTestRule with app defaults + + // When: We navigate to the Settings 'Search' page + on.settingsSearch.navigateToPage() + + // Then: all elements should load + // by default navigateToPage() asserts all 'requiredForPage' elements are present + } +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/tests/SettingsTabsTest.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/tests/SettingsTabsTest.kt new file mode 100644 index 000000000000..33440ab9f1aa --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/tests/SettingsTabsTest.kt @@ -0,0 +1,12 @@ +package org.mozilla.fenix.ui.efficiency.tests + +import org.junit.Test +import org.mozilla.fenix.ui.efficiency.helpers.BaseTest + +class SettingsTabsTest : BaseTest() { + + @Test + fun verifySettingsTabsLoadsTest() { + on.settingsTabs.navigateToPage() + } +} diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/tests/SettingsTest.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/tests/SettingsTest.kt new file mode 100644 index 000000000000..b5271ae1999e --- /dev/null +++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/efficiency/tests/SettingsTest.kt @@ -0,0 +1,20 @@ +package org.mozilla.fenix.ui.efficiency.tests + +import org.junit.Test +import org.mozilla.fenix.ui.efficiency.helpers.BaseTest + +class SettingsTest : BaseTest() { + + // TestRail link: https://mozilla.testrail.io/index.php?/cases/view/2092697 + @Test + fun verifyGeneralSettingsItemsTest() { + // Given: App is loaded with default settings + // on = AndroidComposeTestRule with app defaults + + // When: We navigate to the Settings page + on.settings.navigateToPage() + + // Then: all elements should load + // by default navigateToPage() asserts all 'requiredForPage' elements are present + } +} diff --git a/mobile/android/fenix/automation/taskcluster/androidTest/flank-arm-experimental-api-tests.yml b/mobile/android/fenix/automation/taskcluster/androidTest/flank-arm-experimental-api-tests.yml index 6c8adce4100d..279855c64156 100644 --- a/mobile/android/fenix/automation/taskcluster/androidTest/flank-arm-experimental-api-tests.yml +++ b/mobile/android/fenix/automation/taskcluster/androidTest/flank-arm-experimental-api-tests.yml @@ -17,10 +17,13 @@ gcloud: directories-to-pull: - /sdcard/screenshots performance-metrics: true + other-files: + /data/local/tmp/org.mozilla.fenix.debug-geckoview-config.yaml: ./automation/taskcluster/androidTest/geckoview-configs/org.mozilla.fenix.debug-geckoview-config.yaml test-targets: - notPackage org.mozilla.fenix.syncintegration - notPackage org.mozilla.fenix.experimentintegration + - package org.mozilla.fenix.ui.efficiency.tests device: - model: MediumPhone.arm diff --git a/mobile/android/fenix/automation/taskcluster/androidTest/flank-arm64-v8a.yml b/mobile/android/fenix/automation/taskcluster/androidTest/flank-arm64-v8a.yml index 64dfc1a95eec..9c9056ecf95b 100644 --- a/mobile/android/fenix/automation/taskcluster/androidTest/flank-arm64-v8a.yml +++ b/mobile/android/fenix/automation/taskcluster/androidTest/flank-arm64-v8a.yml @@ -23,6 +23,7 @@ gcloud: test-targets: - notPackage org.mozilla.fenix.syncintegration - notPackage org.mozilla.fenix.experimentintegration + - notPackage org.mozilla.fenix.ui.efficiency.tests device: - model: MediumPhone.arm diff --git a/taskcluster/kinds/ui-test-apk/kind.yml b/taskcluster/kinds/ui-test-apk/kind.yml index e47ca63a1b4e..ee808b96b694 100644 --- a/taskcluster/kinds/ui-test-apk/kind.yml +++ b/taskcluster/kinds/ui-test-apk/kind.yml @@ -379,7 +379,7 @@ tasks: attributes: build-type: fenix-debug-firebase shipping-product: fenix - description: Run Fenix tests on newer Android API levels (ARM64-v8a) + description: Run Fenix tests using experimental POM design dependencies: signed-apk-debug-apk: signing-apk-fenix-debug signed-apk-android-test: signing-apk-fenix-android-test-debug @@ -397,7 +397,7 @@ tasks: - [wget, {artifact-reference: ''}, '-O', app.apk] - [wget, {artifact-reference: ''}, '-O', android-test.apk] - [python3, ../../../taskcluster/scripts/tests/test-lab.py, arm-experimental-api-tests, app.apk, --apk_test, android-test.apk] - run-on-projects: [] + run-on-projects: [trunk] treeherder: platform: 'fenix-android-all/opt' symbol: fenix-debug(experimental-arm)