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.ext:junit:1.2.1")
|
||||||
androidTestImplementation("androidx.test:runner:1.6.2")
|
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(platform("androidx.compose:compose-bom:2024.12.01"))
|
||||||
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
|
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
|
||||||
debugImplementation("androidx.compose.ui:ui-test-manifest")
|
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.performTextClearance
|
||||||
import androidx.compose.ui.test.performTextInput
|
import androidx.compose.ui.test.performTextInput
|
||||||
import androidx.compose.ui.test.printToString
|
import androidx.compose.ui.test.printToString
|
||||||
|
import androidx.test.rule.GrantPermissionRule
|
||||||
import androidx.test.platform.app.InstrumentationRegistry
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import org.junit.Assume.assumeTrue
|
import org.junit.Assume.assumeTrue
|
||||||
@@ -36,7 +37,24 @@ import org.junit.runner.RunWith
|
|||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class ChatFlowTest {
|
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.
|
* 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.performTextClearance
|
||||||
import androidx.compose.ui.test.performTextInput
|
import androidx.compose.ui.test.performTextInput
|
||||||
import androidx.compose.ui.test.printToString
|
import androidx.compose.ui.test.printToString
|
||||||
|
import androidx.test.rule.GrantPermissionRule
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.platform.app.InstrumentationRegistry
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
@@ -33,7 +34,24 @@ import org.junit.runner.RunWith
|
|||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class CrossPlatformTest {
|
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 args get() = InstrumentationRegistry.getArguments()
|
||||||
private val relay: String get() = args.getString("relay") ?: "relay1.flamenet.io"
|
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.performTextClearance
|
||||||
import androidx.compose.ui.test.performTextInput
|
import androidx.compose.ui.test.performTextInput
|
||||||
import androidx.compose.ui.test.printToString
|
import androidx.compose.ui.test.printToString
|
||||||
|
import androidx.test.rule.GrantPermissionRule
|
||||||
import androidx.test.platform.app.InstrumentationRegistry
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import org.junit.Assume.assumeTrue
|
import org.junit.Assume.assumeTrue
|
||||||
@@ -35,7 +36,24 @@ import org.junit.runner.RunWith
|
|||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class CrudSurfaceTest {
|
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.
|
* 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.performTextClearance
|
||||||
import androidx.compose.ui.test.performTextInput
|
import androidx.compose.ui.test.performTextInput
|
||||||
import androidx.compose.ui.test.printToString
|
import androidx.compose.ui.test.printToString
|
||||||
|
import androidx.test.rule.GrantPermissionRule
|
||||||
import androidx.test.platform.app.InstrumentationRegistry
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import org.junit.Assume.assumeTrue
|
import org.junit.Assume.assumeTrue
|
||||||
@@ -40,7 +41,24 @@ import org.junit.runner.RunWith
|
|||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class FeatureUseTest {
|
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.
|
* 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.performTextClearance
|
||||||
import androidx.compose.ui.test.performTextInput
|
import androidx.compose.ui.test.performTextInput
|
||||||
import androidx.compose.ui.test.printToString
|
import androidx.compose.ui.test.printToString
|
||||||
|
import androidx.test.rule.GrantPermissionRule
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.platform.app.InstrumentationRegistry
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
import org.junit.Assume.assumeTrue
|
import org.junit.Assume.assumeTrue
|
||||||
@@ -50,7 +51,24 @@ import org.junit.runner.RunWith
|
|||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class LiveSignUpFleetTest {
|
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()
|
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.performClick
|
||||||
import androidx.compose.ui.test.performTextClearance
|
import androidx.compose.ui.test.performTextClearance
|
||||||
import androidx.compose.ui.test.performTextInput
|
import androidx.compose.ui.test.performTextInput
|
||||||
|
import androidx.test.rule.GrantPermissionRule
|
||||||
import androidx.test.platform.app.InstrumentationRegistry
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import org.junit.Assume.assumeTrue
|
import org.junit.Assume.assumeTrue
|
||||||
@@ -36,7 +37,24 @@ import org.junit.runner.RunWith
|
|||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class SignUpFlowTest {
|
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.
|
* Which relay to drive.
|
||||||
|
|||||||
Reference in New Issue
Block a user