package social.grain import androidx.compose.ui.test.hasSetTextAction import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performTextInput import androidx.test.ext.junit.runners.AndroidJUnit4 import org.junit.After import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import social.grain.feature.login.LoginScreen import social.grain.feature.login.LoginViewModel import social.grain.support.Harness import social.grain.support.awaitContentDescription import social.grain.support.awaitText import social.grain.support.MainDispatcherRule import social.grain.support.awaitCall /** * The sign-in screen, which is the only screen a signed-out reader ever sees. * * It forces its own dark scheme over a photograph rather than following the * device, so it is also the one screen where a theme regression would be * invisible everywhere else. */ @RunWith(AndroidJUnit4::class) class LoginScreenTest { @get:Rule val mainDispatcher = MainDispatcherRule() @get:Rule val composeRule = createComposeRule() private lateinit var harness: Harness @Before fun setUp() { harness = Harness(signedIn = false) harness.server .on( "social.grain.unspecced.searchActorsTypeahead", """{"actors":[{"did":"did:plc:alice","handle":"alice.grain.social"}]}""", ) .on("par", """{"request_uri":"urn:abc"}""") } @After fun tearDown() = harness.tearDown() private fun show() { val model = LoginViewModel(harness.auth, harness.client) composeRule.setContent { LoginScreen(viewModel = model) } composeRule.waitForIdle() } @Test fun theScreenInvitesAnAtmosphereAccount() { show() composeRule.awaitText("Sign in with your atmosphere account") composeRule.awaitText("Handle") composeRule.awaitText("Sign in") composeRule.awaitText("Create account") } @Test fun typingAHandleOffersMatchesFromTheServer() { show() composeRule.onNode(hasSetTextAction()).performTextInput("ali") composeRule.waitUntil(10_000) { harness.server.countOf("social.grain.unspecced.searchActorsTypeahead") >= 1 } composeRule.waitForIdle() composeRule.awaitText("alice.grain.social", substring = true) } @Test fun signingInRunsThePushedAuthorizationRequest() { show() composeRule.onNode(hasSetTextAction()).performTextInput("alice.grain.social") composeRule.onNodeWithText("Sign in").performClick() composeRule.waitUntil(10_000) { harness.server.countOf("par") >= 1 } } @Test fun creatingAnAccountAsksForTheSignUpPage() { show() composeRule.onNodeWithText("Create account").performClick() composeRule.waitUntil(10_000) { harness.server.countOf("par") >= 1 } val par = harness.server.lastCall("par") assert(par.body.contains("prompt=create")) } }