Grant notification permission before the activity launches
Every instrumented test died with "No compose hierarchies found in the
app". MainActivity.onCreate asks for POST_NOTIFICATIONS before it calls
setContent, and the permission dialog is a separate activity that takes
focus — so the Compose rule attached to a window with no hierarchy yet.
GrantPermissionRule at order = 0, outside the Compose rule at order = 1, so
the grant happens first and no dialog ever appears.
With this, the three fixes in the previous commit, and a relay on the host,
aPersonCanCreateAnAccountOnASelfHostedRelay passes: a real account created
on a real relay, driven by test tags. That is the first end-to-end pass this
harness has produced.
./gradlew :app:connectedDebugAndroidTest \
-Pandroid.testInstrumentationRunnerArguments.relay=10.0.2.2:18810
This commit is contained in:
@@ -225,6 +225,9 @@ dependencies {
|
||||
|
||||
androidTestImplementation("androidx.test.ext:junit:1.2.1")
|
||||
androidTestImplementation("androidx.test:runner:1.6.2")
|
||||
// GrantPermissionRule: permissions have to be granted before the
|
||||
// activity launches, or its permission dialog steals focus from Compose.
|
||||
androidTestImplementation("androidx.test:rules:1.6.1")
|
||||
androidTestImplementation(platform("androidx.compose:compose-bom:2024.12.01"))
|
||||
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
|
||||
debugImplementation("androidx.compose.ui:ui-test-manifest")
|
||||
|
||||
@@ -10,6 +10,7 @@ import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.performTextClearance
|
||||
import androidx.compose.ui.test.performTextInput
|
||||
import androidx.compose.ui.test.printToString
|
||||
import androidx.test.rule.GrantPermissionRule
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import org.junit.Assume.assumeTrue
|
||||
@@ -36,7 +37,24 @@ import org.junit.runner.RunWith
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ChatFlowTest {
|
||||
|
||||
@get:Rule val compose = createAndroidComposeRule<MainActivity>()
|
||||
/**
|
||||
* 🔴 Granted BEFORE the activity launches, and that ordering is the point.
|
||||
*
|
||||
* `MainActivity.onCreate` asks for POST_NOTIFICATIONS before it calls
|
||||
* `setContent`. The permission dialog is a separate activity and takes
|
||||
* focus, so the Compose rule attaches to a window that has no hierarchy
|
||||
* yet and every test dies with "No compose hierarchies found in the app".
|
||||
*
|
||||
* `order = 0` puts this outside the Compose rule, so the grant happens
|
||||
* first and no dialog ever appears.
|
||||
*/
|
||||
@get:Rule(order = 0)
|
||||
val permissions: GrantPermissionRule = GrantPermissionRule.grant(
|
||||
android.Manifest.permission.POST_NOTIFICATIONS,
|
||||
)
|
||||
|
||||
@get:Rule(order = 1)
|
||||
val compose = createAndroidComposeRule<MainActivity>()
|
||||
|
||||
/**
|
||||
* Which relay to drive.
|
||||
|
||||
@@ -10,6 +10,7 @@ import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.performTextClearance
|
||||
import androidx.compose.ui.test.performTextInput
|
||||
import androidx.compose.ui.test.printToString
|
||||
import androidx.test.rule.GrantPermissionRule
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import org.junit.Rule
|
||||
@@ -33,7 +34,24 @@ import org.junit.runner.RunWith
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class CrossPlatformTest {
|
||||
|
||||
@get:Rule val compose = createAndroidComposeRule<MainActivity>()
|
||||
/**
|
||||
* 🔴 Granted BEFORE the activity launches, and that ordering is the point.
|
||||
*
|
||||
* `MainActivity.onCreate` asks for POST_NOTIFICATIONS before it calls
|
||||
* `setContent`. The permission dialog is a separate activity and takes
|
||||
* focus, so the Compose rule attaches to a window that has no hierarchy
|
||||
* yet and every test dies with "No compose hierarchies found in the app".
|
||||
*
|
||||
* `order = 0` puts this outside the Compose rule, so the grant happens
|
||||
* first and no dialog ever appears.
|
||||
*/
|
||||
@get:Rule(order = 0)
|
||||
val permissions: GrantPermissionRule = GrantPermissionRule.grant(
|
||||
android.Manifest.permission.POST_NOTIFICATIONS,
|
||||
)
|
||||
|
||||
@get:Rule(order = 1)
|
||||
val compose = createAndroidComposeRule<MainActivity>()
|
||||
|
||||
private val args get() = InstrumentationRegistry.getArguments()
|
||||
private val relay: String get() = args.getString("relay") ?: "relay1.flamenet.io"
|
||||
|
||||
@@ -10,6 +10,7 @@ import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.performTextClearance
|
||||
import androidx.compose.ui.test.performTextInput
|
||||
import androidx.compose.ui.test.printToString
|
||||
import androidx.test.rule.GrantPermissionRule
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import org.junit.Assume.assumeTrue
|
||||
@@ -35,7 +36,24 @@ import org.junit.runner.RunWith
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class CrudSurfaceTest {
|
||||
|
||||
@get:Rule val compose = createAndroidComposeRule<MainActivity>()
|
||||
/**
|
||||
* 🔴 Granted BEFORE the activity launches, and that ordering is the point.
|
||||
*
|
||||
* `MainActivity.onCreate` asks for POST_NOTIFICATIONS before it calls
|
||||
* `setContent`. The permission dialog is a separate activity and takes
|
||||
* focus, so the Compose rule attaches to a window that has no hierarchy
|
||||
* yet and every test dies with "No compose hierarchies found in the app".
|
||||
*
|
||||
* `order = 0` puts this outside the Compose rule, so the grant happens
|
||||
* first and no dialog ever appears.
|
||||
*/
|
||||
@get:Rule(order = 0)
|
||||
val permissions: GrantPermissionRule = GrantPermissionRule.grant(
|
||||
android.Manifest.permission.POST_NOTIFICATIONS,
|
||||
)
|
||||
|
||||
@get:Rule(order = 1)
|
||||
val compose = createAndroidComposeRule<MainActivity>()
|
||||
|
||||
/**
|
||||
* Which relay to drive.
|
||||
|
||||
@@ -8,6 +8,7 @@ import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.performTextClearance
|
||||
import androidx.compose.ui.test.performTextInput
|
||||
import androidx.compose.ui.test.printToString
|
||||
import androidx.test.rule.GrantPermissionRule
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import org.junit.Assume.assumeTrue
|
||||
@@ -40,7 +41,24 @@ import org.junit.runner.RunWith
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class FeatureUseTest {
|
||||
|
||||
@get:Rule val compose = createAndroidComposeRule<MainActivity>()
|
||||
/**
|
||||
* 🔴 Granted BEFORE the activity launches, and that ordering is the point.
|
||||
*
|
||||
* `MainActivity.onCreate` asks for POST_NOTIFICATIONS before it calls
|
||||
* `setContent`. The permission dialog is a separate activity and takes
|
||||
* focus, so the Compose rule attaches to a window that has no hierarchy
|
||||
* yet and every test dies with "No compose hierarchies found in the app".
|
||||
*
|
||||
* `order = 0` puts this outside the Compose rule, so the grant happens
|
||||
* first and no dialog ever appears.
|
||||
*/
|
||||
@get:Rule(order = 0)
|
||||
val permissions: GrantPermissionRule = GrantPermissionRule.grant(
|
||||
android.Manifest.permission.POST_NOTIFICATIONS,
|
||||
)
|
||||
|
||||
@get:Rule(order = 1)
|
||||
val compose = createAndroidComposeRule<MainActivity>()
|
||||
|
||||
/**
|
||||
* Which relay to drive.
|
||||
|
||||
@@ -9,6 +9,7 @@ import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.performTextClearance
|
||||
import androidx.compose.ui.test.performTextInput
|
||||
import androidx.compose.ui.test.printToString
|
||||
import androidx.test.rule.GrantPermissionRule
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import org.junit.Assume.assumeTrue
|
||||
@@ -50,7 +51,24 @@ import org.junit.runner.RunWith
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class LiveSignUpFleetTest {
|
||||
|
||||
@get:Rule val compose = createAndroidComposeRule<MainActivity>()
|
||||
/**
|
||||
* 🔴 Granted BEFORE the activity launches, and that ordering is the point.
|
||||
*
|
||||
* `MainActivity.onCreate` asks for POST_NOTIFICATIONS before it calls
|
||||
* `setContent`. The permission dialog is a separate activity and takes
|
||||
* focus, so the Compose rule attaches to a window that has no hierarchy
|
||||
* yet and every test dies with "No compose hierarchies found in the app".
|
||||
*
|
||||
* `order = 0` puts this outside the Compose rule, so the grant happens
|
||||
* first and no dialog ever appears.
|
||||
*/
|
||||
@get:Rule(order = 0)
|
||||
val permissions: GrantPermissionRule = GrantPermissionRule.grant(
|
||||
android.Manifest.permission.POST_NOTIFICATIONS,
|
||||
)
|
||||
|
||||
@get:Rule(order = 1)
|
||||
val compose = createAndroidComposeRule<MainActivity>()
|
||||
|
||||
private val args get() = InstrumentationRegistry.getArguments()
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import androidx.compose.ui.test.printToString
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.performTextClearance
|
||||
import androidx.compose.ui.test.performTextInput
|
||||
import androidx.test.rule.GrantPermissionRule
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import org.junit.Assume.assumeTrue
|
||||
@@ -36,7 +37,24 @@ import org.junit.runner.RunWith
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class SignUpFlowTest {
|
||||
|
||||
@get:Rule val compose = createAndroidComposeRule<MainActivity>()
|
||||
/**
|
||||
* 🔴 Granted BEFORE the activity launches, and that ordering is the point.
|
||||
*
|
||||
* `MainActivity.onCreate` asks for POST_NOTIFICATIONS before it calls
|
||||
* `setContent`. The permission dialog is a separate activity and takes
|
||||
* focus, so the Compose rule attaches to a window that has no hierarchy
|
||||
* yet and every test dies with "No compose hierarchies found in the app".
|
||||
*
|
||||
* `order = 0` puts this outside the Compose rule, so the grant happens
|
||||
* first and no dialog ever appears.
|
||||
*/
|
||||
@get:Rule(order = 0)
|
||||
val permissions: GrantPermissionRule = GrantPermissionRule.grant(
|
||||
android.Manifest.permission.POST_NOTIFICATIONS,
|
||||
)
|
||||
|
||||
@get:Rule(order = 1)
|
||||
val compose = createAndroidComposeRule<MainActivity>()
|
||||
|
||||
/**
|
||||
* Which relay to drive.
|
||||
|
||||
Reference in New Issue
Block a user