Output:
Chunk ID: dd2244
Wall time: 0.1882 seconds
Process exited with code 0
Original token count: 3714
Output:
<?xml version="1.0" encoding="UTF-8"?>
<testsuite name="com.yorvana.ui.util.EmailLaunchRequestTest" tests="2" skipped="0" failures="2" errors="0" timestamp="2026-05-18T18:41:10.250Z" hostname="home-pc" time="0.805">
  <properties/>
  <testcase name="launchEmail starts mailto email intent" classname="com.yorvana.ui.util.EmailLaunchRequestTest" time="0.74">
    <failure message="java.lang.RuntimeException: Method parse in android.net.Uri not mocked. See https://developer.android.com/r/studio-ui/build/not-mocked for details." type="java.lang.RuntimeException">java.lang.RuntimeException: Method parse in android.net.Uri not mocked. See https://developer.android.com/r/studio-ui/build/not-mocked for details.
	at android.net.Uri.parse(Uri.java)
	at com.yorvana.ui.util.EmailLaunchRequestKt.launchEmail(EmailLaunchRequest.kt:38)
	at com.yorvana.ui.util.EmailLaunchRequestTest$launchEmail starts mailto email intent$1.invokeSuspend(EmailLaunchRequestTest.kt:28)
	at com.yorvana.ui.util.EmailLaunchRequestTest$launchEmail starts mailto email intent$1.invoke(EmailLaunchRequestTest.kt)
	at com.yorvana.ui.util.EmailLaunchRequestTest$launchEmail starts mailto email intent$1.invoke(EmailLaunchRequestTest.kt)
	at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt$runTest$2$1$1.invokeSuspend(TestBuilders.kt:317)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:34)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:100)
	at kotlinx.coroutines.test.TestDispatcher.processEvent$kotlinx_coroutines_test(TestDispatcher.kt:24)
	at kotlinx.coroutines.test.TestCoroutineScheduler.tryRunNextTaskUnless$kotlinx_coroutines_test(TestCoroutineScheduler.kt:98)
	at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt$runTest$2$1$workRunner$1.invokeSuspend(TestBuilders.kt:326)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:34)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:100)
	at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:256)
	at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:54)
	at kotlinx.coroutines.BuildersKt__BuildersKt.runBlockingImpl(Builders.kt:30)
	at kotlinx.coroutines.BuildersKt.runBlockingImpl(Unknown Source)
	at kotlinx.coroutines.BuildersKt__Builders_concurrentKt.runBlockingK(Builders.concurrent.kt:172)
	at kotlinx.coroutines.BuildersKt.runBlockingK(Unknown Source)
	at kotlinx.coroutines.BuildersKt__Builders_concurrentKt.runBlockingK$default(Builders.concurrent.kt:157)
	at kotlinx.coroutines.BuildersKt.runBlockingK$default(Unknown Source)
	at kotlinx.coroutines.test.TestBuildersJvmKt.createTestResult(TestBuildersJvm.kt:10)
	at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt.runTest-8Mi8wO0(TestBuilders.kt:309)
	at kotlinx.coroutines.test.TestBuildersKt.runTest-8Mi8wO0(TestBuilders.kt:1)
	at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt.runTest-8Mi8wO0(TestBuilders.kt:167)
	at kotlinx.coroutines.test.TestBuildersKt.runTest-8Mi8wO0(TestBuilders.kt:1)
	at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt.runTest-8Mi8wO0$default(TestBuilders.kt:159)
	at kotlinx.coroutines.test.TestBuildersKt.runTest-8Mi8wO0$default(TestBuilders.kt:1)
	at com.yorvana.ui.util.EmailLaunchRequestTest.launchEmail starts mailto email intent(EmailLaunchRequestTest.kt:23)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
	at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
	at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
	at org.gradle.api.internal.tasks.testing.junit.JUnitTestExecutor.runRequest(JUnitTestExecutor.java:175)
	at org.gradle.api.internal.tasks.testing.junit.JUnitTestExecutor.accept(JUnitTestExecutor.java:84)
	at org.gradle.api.internal.tasks.testing.junit.JUnitTestExecutor.accept(JUnitTestExecutor.java:47)
	at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestDefinitionProcessor.processTestDefinition(AbstractJUnitTestDefinitionProcessor.java:65)
	at org.gradle.api.internal.tasks.testing.SuiteTestDefinitionProcessor.processTestDefinition(SuiteTestDefinitionProcessor.java:53)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.gradle.internal.dispatch.MethodInvocation.invokeOn(MethodInvocation.java:77)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:28)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:19)
	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:88)
	at jdk.proxy1/jdk.proxy1.$Proxy4.processTestDefinition(Unknown Source)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:178)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:126)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:103)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:63)
	at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:122)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:72)
	at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
	at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
</failure>
  </testcase>
  <testcase name="launchEmail shows snackbar when no email app is available" classname="com.yorvana.ui.util.EmailLaunchRequestTest" time="0.064">
    <failure message="java.lang.RuntimeException: Method parse in android.net.Uri not mocked. See https://developer.android.com/r/studio-ui/build/not-mocked for details." type="java.lang.RuntimeException">java.lang.RuntimeException: Method parse in android.net.Uri not mocked. See https://developer.android.com/r/studio-ui/build/not-mocked for details.
	at android.net.Uri.parse(Uri.java)
	at com.yorvana.ui.util.EmailLaunchRequestKt.launchEmail(EmailLaunchRequest.kt:38)
	at com.yorvana.ui.util.EmailLaunchRequestTest$launchEmail shows snackbar when no email app is available$1$launchJob$1.invokeSuspend(EmailLaunchRequestTest.kt:58)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:34)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:100)
	at kotlinx.coroutines.test.TestDispatcher.processEvent$kotlinx_coroutines_test(TestDispatcher.kt:24)
	at kotlinx.coroutines.test.TestCoroutineScheduler.runCurrent(TestCoroutineScheduler.kt:131)
	at kotlinx.coroutines.test.TestScopeKt.runCurrent(TestScope.kt:91)
	at com.yorvana.ui.util.EmailLaunchRequestTest$launchEmail shows snackbar when no email app is available$1.invokeSuspend(EmailLaunchRequestTest.kt:69)
	at com.yorvana.ui.util.EmailLaunchRequestTest$launchEmail shows snackbar when no email app is available$1.invoke(EmailLaunchRequestTest.kt)
	at com.yorvana.ui.util.EmailLaunchRequestTest$launchEmail shows snackbar when no email app is available$1.invoke(EmailLaunchRequestTest.kt)
	at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt$runTest$2$1$1.invokeSuspend(TestBuilders.kt:317)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:34)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:100)
	at kotlinx.coroutines.test.TestDispatcher.processEvent$kotlinx_coroutines_test(TestDispatcher.kt:24)
	at kotlinx.coroutines.test.TestCoroutineScheduler.tryRunNextTaskUnless$kotlinx_coroutines_test(TestCoroutineScheduler.kt:98)
	at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt$runTest$2$1$workRunner$1.invokeSuspend(TestBuilders.kt:326)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:34)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:100)
	at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:256)
	at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:54)
	at kotlinx.coroutines.BuildersKt__BuildersKt.runBlockingImpl(Builders.kt:30)
	at kotlinx.coroutines.BuildersKt.runBlockingImpl(Unknown Source)
	at kotlinx.coroutines.BuildersKt__Builders_concurrentKt.runBlockingK(Builders.concurrent.kt:172)
	at kotlinx.coroutines.BuildersKt.runBlockingK(Unknown Source)
	at kotlinx.coroutines.BuildersKt__Builders_concurrentKt.runBlockingK$default(Builders.concurrent.kt:157)
	at kotlinx.coroutines.BuildersKt.runBlockingK$default(Unknown Source)
	at kotlinx.coroutines.test.TestBuildersJvmKt.createTestResult(TestBuildersJvm.kt:10)
	at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt.runTest-8Mi8wO0(TestBuilders.kt:309)
	at kotlinx.coroutines.test.TestBuildersKt.runTest-8Mi8wO0(TestBuilders.kt:1)
	at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt.runTest-8Mi8wO0(TestBuilders.kt:167)
	at kotlinx.coroutines.test.TestBuildersKt.runTest-8Mi8wO0(TestBuilders.kt:1)
	at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt.runTest-8Mi8wO0$default(TestBuilders.kt:159)
	at kotlinx.coroutines.test.TestBuildersKt.runTest-8Mi8wO0$default(TestBuilders.kt:1)
	at com.yorvana.ui.util.EmailLaunchRequestTest.launchEmail shows snackbar when no email app is available(EmailLaunchRequestTest.kt:50)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
	at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
	at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
	at org.gradle.api.internal.tasks.testing.junit.JUnitTestExecutor.runRequest(JUnitTestExecutor.java:175)
	at org.gradle.api.internal.tasks.testing.junit.JUnitTestExecutor.accept(JUnitTestExecutor.java:84)
	at org.gradle.api.internal.tasks.testing.junit.JUnitTestExecutor.accept(JUnitTestExecutor.java:47)
	at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestDefinitionProcessor.processTestDefinition(AbstractJUnitTestDefinitionProcessor.java:65)
	at org.gradle.api.internal.tasks.testing.SuiteTestDefinitionProcessor.processTestDefinition(SuiteTestDefinitionProcessor.java:53)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.gradle.internal.dispatch.MethodInvocation.invokeOn(MethodInvocation.java:77)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:28)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:19)
	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:88)
	at jdk.proxy1/jdk.proxy1.$Proxy4.processTestDefinition(Unknown Source)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:178)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:126)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:103)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:63)
	at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:122)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:72)
	at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
	at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
	Suppressed: expected: No email app found
but was : null
		at com.yorvana.ui.util.EmailLaunchRequestTest$launchEmail shows snackbar when no email app is available$1.invokeSuspend(EmailLaunchRequestTest.kt:71)


Output:
Chunk ID: 3b1618
Wall time: 0.1837 seconds
Process exited with code 0
Original token count: 854
Output:
     1	package com.yorvana.ui.util
     2
     3	import android.content.ActivityNotFoundException
     4	import android.content.Context
     5	import android.content.Intent
     6	import androidx.compose.material3.SnackbarHostState
     7	import androidx.core.net.toUri
     8	import com.google.common.truth.Truth.assertThat
     9	import com.yorvana.R
    10	import io.mockk.every
    11	import io.mockk.just
    12	import io.mockk.mockk
    13	import io.mockk.runs
    14	import io.mockk.slot
    15	import kotlinx.coroutines.launch
    16	import kotlinx.coroutines.test.runCurrent
    17	import kotlinx.coroutines.test.runTest
    18	import org.junit.Test
    19
    20	class EmailLaunchRequestTest {
    21	    @Test
    22	    fun `launchEmail starts mailto email intent`() =
    23	        runTest {
    24	            val context = mockk<Context>()
    25	            val intentSlot = slot<Intent>()
    26	            every { context.startActivity(capture(intentSlot)) } just runs
    27
    28	            launchEmail(
    29	                context = context,
    30	                snackbarHostState = SnackbarHostState(),
    31	                noEmailAppMessageRes = R.string.email_no_app_found,
    32	                request =
    33	                    EmailLaunchRequest(
    34	                        recipient = "support@example.com",
    35	                        subject = "Subject",
    36	                        body = "Body",
    37	                    ),
    38	            )
    39
    40	            val intent = intentSlot.captured
    41	            assertThat(intent.action).isEqualTo(Intent.ACTION_SENDTO)
    42	            assertThat(intent.data).isEqualTo("mailto:".toUri())
    43	            assertThat(intent.getStringArrayExtra(Intent.EXTRA_EMAIL)).asList().containsExactly("support@example.com")
    44	            assertThat(intent.getStringExtra(Intent.EXTRA_SUBJECT)).isEqualTo("Subject")
    45	            assertThat(intent.getStringExtra(Intent.EXTRA_TEXT)).isEqualTo("Body")
    46	        }
    47
    48	    @Test
    49	    fun `launchEmail shows snackbar when no email app is available`() =
    50	        runTest {
    51	            val context = mockk<Context>()
    52	            val snackbarHostState = SnackbarHostState()
    53	            every { context.startActivity(any()) } throws ActivityNotFoundException()
    54	            every { context.getString(R.string.email_no_app_found) } returns "No email app found"
    55
    56	            val launchJob =
    57	                launch {
    58	                    launchEmail(
    59	                        context = context,
    60	                        snackbarHostState = snackbarHostState,
    61	                        noEmailAppMessageRes = R.string.email_no_app_found,
    62	                        request =
    63	                            EmailLaunchRequest(
    64	                                recipient = "support@example.com",
    65	                                subject = "Subject",
    66	                            ),
    67	                    )
    68	                }
    69	            runCurrent()
    70
    71	            assertThat(snackbarHostState.currentSnackbarData?.visuals?.message).isEqualTo("No email app found")
    72	            snackbarHostState.currentSnackbarData?.dismiss()
    73	            launchJob.join()
    74	        }
    75	}


rg -n "RobolectricTestRunner|@Config|mockkStatic\(Uri|android.net.Uri" app/src/test/java


Output:
Chunk ID: d4301d
Wall time: 0.1203 seconds
Process exited with code 0
Original token count: 3381
Output:
app/src/test/java/com/yorvana/YorvanaApplicationTest.kt:18:import org.robolectric.RobolectricTestRunner
app/src/test/java/com/yorvana/YorvanaApplicationTest.kt:81:@RunWith(RobolectricTestRunner::class)
app/src/test/java/com/yorvana/YorvanaApplicationTest.kt:84:    @Config(application = SentryEnabledApp::class, sdk = [34])
app/src/test/java/com/yorvana/YorvanaApplicationTest.kt:91:    @Config(application = SentryDisabledApp::class, sdk = [34])
app/src/test/java/com/yorvana/YorvanaApplicationTest.kt:98:    @Config(application = SentryEmptyDsnApp::class, sdk = [34])
app/src/test/java/com/yorvana/YorvanaApplicationTest.kt:105:    @Config(application = SentryEnabledApp::class, sdk = [34])
app/src/test/java/com/yorvana/YorvanaApplicationTest.kt:120:    @Config(application = SentryDisabledApp::class, sdk = [34])
app/src/test/java/com/yorvana/YorvanaApplicationTest.kt:127:    @Config(application = SentryEnabledApp::class, sdk = [34])
app/src/test/java/com/yorvana/YorvanaApplicationTest.kt:149:    @Config(application = EnableNowApp::class, sdk = [34])
app/src/test/java/com/yorvana/YorvanaApplicationTest.kt:157:    @Config(application = EnableNowEmptyDsnApp::class, sdk = [34])
app/src/test/java/com/yorvana/YorvanaApplicationTest.kt:165:    @Config(application = SentryEnabledApp::class, sdk = [34])
app/src/test/java/com/yorvana/YorvanaApplicationTest.kt:183:    @Config(application = SentryEnabledApp::class, sdk = [34])
app/src/test/java/com/yorvana/util/VaultPathHelperTest.kt:3:import android.net.Uri
app/src/test/java/com/yorvana/util/VaultPathHelperTest.kt:17:        mockkStatic(Uri::class)
app/src/test/java/com/yorvana/util/VaultPathHelperTest.kt:23:        unmockkStatic(Uri::class)
app/src/test/java/com/yorvana/MainActivityTest.kt:20:import org.robolectric.RobolectricTestRunner
app/src/test/java/com/yorvana/MainActivityTest.kt:23:@RunWith(RobolectricTestRunner::class)
app/src/test/java/com/yorvana/MainActivityTest.kt:24:@Config(application = TestYorvanaApplication::class, sdk = [34])
app/src/test/java/com/yorvana/util/SentryWrapperTest.kt:18:import org.robolectric.RobolectricTestRunner
app/src/test/java/com/yorvana/util/SentryWrapperTest.kt:21:@RunWith(RobolectricTestRunner::class)
app/src/test/java/com/yorvana/util/SentryWrapperTest.kt:22:@Config(sdk = [34])
app/src/test/java/com/yorvana/util/FileProviderHelperTest.kt:6:import android.net.Uri
app/src/test/java/com/yorvana/data/storage/VaultStorageImplTest.kt:4:import android.net.Uri
app/src/test/java/com/yorvana/data/storage/VaultStorageImplTest.kt:18:import org.robolectric.RobolectricTestRunner
app/src/test/java/com/yorvana/data/storage/VaultStorageImplTest.kt:23:@RunWith(RobolectricTestRunner::class)
app/src/test/java/com/yorvana/data/storage/VaultStorageImplTest.kt:24:@Config(sdk = [34])
app/src/test/java/com/yorvana/ui/records/AddEditRecordScreenTest.kt:19:import org.robolectric.RobolectricTestRunner
app/src/test/java/com/yorvana/ui/records/AddEditRecordScreenTest.kt:22:@RunWith(RobolectricTestRunner::class)
app/src/test/java/com/yorvana/ui/records/AddEditRecordScreenTest.kt:23:@Config(application = TestYorvanaApplication::class, sdk = [34])
app/src/test/java/com/yorvana/data/storage/VaultStorageImplIT.kt:4:import android.net.Uri
app/src/test/java/com/yorvana/data/storage/VaultStorageImplIT.kt:15:import org.robolectric.RobolectricTestRunner
app/src/test/java/com/yorvana/data/storage/VaultStorageImplIT.kt:19:@Config(application = TestYorvanaApplication::class, sdk = [34])
app/src/test/java/com/yorvana/data/storage/VaultStorageImplIT.kt:20:@RunWith(RobolectricTestRunner::class)
app/src/test/java/com/yorvana/ui/records/AddEditRecordScreenIT.kt:20:import org.robolectric.RobolectricTestRunner
app/src/test/java/com/yorvana/ui/records/AddEditRecordScreenIT.kt:23:@Config(application = TestYorvanaApplication::class, sdk = [34])
app/src/test/java/com/yorvana/ui/records/AddEditRecordScreenIT.kt:24:@RunWith(RobolectricTestRunner::class)
app/src/test/java/com/yorvana/ui/records/VehicleDetailScreenTest.kt:23:import org.robolectric.RobolectricTestRunner
app/src/test/java/com/yorvana/ui/records/VehicleDetailScreenTest.kt:26:@Config(application = TestYorvanaApplication::class, sdk = [34])
app/src/test/java/com/yorvana/ui/records/VehicleDetailScreenTest.kt:27:@RunWith(RobolectricTestRunner::class)
app/src/test/java/com/yorvana/data/repository/WorkflowIntegrationIT.kt:4:import android.net.Uri
app/src/test/java/com/yorvana/data/repository/WorkflowIntegrationIT.kt:18:import org.robolectric.RobolectricTestRunner
app/src/test/java/com/yorvana/data/repository/WorkflowIntegrationIT.kt:24:@RunWith(RobolectricTestRunner::class)
app/src/test/java/com/yorvana/data/repository/WorkflowIntegrationIT.kt:25:@Config(sdk = [34])
app/src/test/java/com/yorvana/ui/records/VehicleDetailScreenIT.kt:21:import org.robolectric.RobolectricTestRunner
app/src/test/java/com/yorvana/ui/records/VehicleDetailScreenIT.kt:24:@Config(application = TestYorvanaApplication::class, sdk = [34])
app/src/test/java/com/yorvana/ui/records/VehicleDetailScreenIT.kt:25:@RunWith(RobolectricTestRunner::class)
app/src/test/java/com/yorvana/ui/records/RecordDetailViewModelIT.kt:4:import android.net.Uri
app/src/test/java/com/yorvana/ui/records/RecordDetailViewModelIT.kt:37:import org.robolectric.RobolectricTestRunner
app/src/test/java/com/yorvana/ui/records/RecordDetailViewModelIT.kt:42:@Config(application = TestYorvanaApplication::class, sdk = [34])
app/src/test/java/com/yorvana/ui/records/RecordDetailViewModelIT.kt:43:@RunWith(RobolectricTestRunner::class)
app/src/test/java/com/yorvana/data/repository/RecordRepositoryImplTest.kt:3:import android.net.Uri
app/src/test/java/com/yorvana/ui/vehicles/AddEditVehicleScreenTest.kt:19:import org.robolectric.RobolectricTestRunner
app/src/test/java/com/yorvana/ui/vehicles/AddEditVehicleScreenTest.kt:22:@RunWith(RobolectricTestRunner::class)
app/src/test/java/com/yorvana/ui/vehicles/AddEditVehicleScreenTest.kt:23:@Config(application = TestYorvanaApplication::class, sdk = [34])
app/src/test/java/com/yorvana/ui/vehicles/VehicleListViewModelTest.kt:3:import android.net.Uri
app/src/test/java/com/yorvana/ui/vehicles/VehicleListViewModelTest.kt:55:        mockkStatic(Uri::class)
app/src/test/java/com/yorvana/ui/vehicles/VehicleListViewModelTest.kt:77:        unmockkStatic(Uri::class)
app/src/test/java/com/yorvana/ui/vehicles/AddEditVehicleScreenIT.kt:19:import org.robolectric.RobolectricTestRunner
app/src/test/java/com/yorvana/ui/vehicles/AddEditVehicleScreenIT.kt:22:@Config(application = TestYorvanaApplication::class, sdk = [34])
app/src/test/java/com/yorvana/ui/vehicles/AddEditVehicleScreenIT.kt:23:@RunWith(RobolectricTestRunner::class)
app/src/test/java/com/yorvana/ui/records/RecordDetailScreenIT.kt:16:import org.robolectric.RobolectricTestRunner
app/src/test/java/com/yorvana/ui/records/RecordDetailScreenIT.kt:19:@Config(application = TestYorvanaApplication::class, sdk = [34])
app/src/test/java/com/yorvana/ui/records/RecordDetailScreenIT.kt:20:@RunWith(RobolectricTestRunner::class)
app/src/test/java/com/yorvana/data/repository/DataIntegrationIT.kt:4:import android.net.Uri
app/src/test/java/com/yorvana/data/repository/DataIntegrationIT.kt:18:import org.robolectric.RobolectricTestRunner
app/src/test/java/com/yorvana/data/repository/DataIntegrationIT.kt:24:@Config(application = TestYorvanaApplication::class, sdk = [34])
app/src/test/java/com/yorvana/data/repository/DataIntegrationIT.kt:25:@RunWith(RobolectricTestRunner::class)
app/src/test/java/com/yorvana/ui/util/BaseScreenshotTest.kt:8:import org.robolectric.RobolectricTestRunner
app/src/test/java/com/yorvana/ui/util/BaseScreenshotTest.kt:11:@RunWith(RobolectricTestRunner::class)
app/src/test/java/com/yorvana/ui/util/BaseScreenshotTest.kt:12:@Config(sdk = [34])
app/src/test/java/com/yorvana/ui/util/ViewModelFactoryTest.kt:3:import android.net.Uri
app/src/test/java/com/yorvana/ui/util/ViewModelFactoryTest.kt:46:import org.robolectric.RobolectricTestRunner
app/src/test/java/com/yorvana/ui/util/ViewModelFactoryTest.kt:49:@RunWith(RobolectricTestRunner::class)
app/src/test/java/com/yorvana/ui/util/ViewModelFactoryTest.kt:50:@Config(sdk = [33])
app/src/test/java/com/yorvana/ui/util/ViewModelFactoryTest.kt:58:        mockkStatic(Uri::class)
app/src/test/java/com/yorvana/ui/util/ViewModelFactoryTest.kt:96:        unmockkStatic(Uri::class)
app/src/test/java/com/yorvana/ui/records/AddEditRecordViewModelTest.kt:3:import android.net.Uri
app/src/test/java/com/yorvana/ui/vehicles/VehicleListConsentDialogTest.kt:27:import org.robolectric.RobolectricTestRunner
app/src/test/java/com/yorvana/ui/vehicles/VehicleListConsentDialogTest.kt:30:@Config(application = TestYorvanaApplication::class, sdk = [34])
app/src/test/java/com/yorvana/ui/vehicles/VehicleListConsentDialogTest.kt:31:@RunWith(RobolectricTestRunner::class)
app/src/test/java/com/yorvana/ui/vehicles/VehicleListScreenIT.kt:23:import org.robolectric.RobolectricTestRunner
app/src/test/java/com/yorvana/ui/vehicles/VehicleListScreenIT.kt:26:@Config(application = TestYorvanaApplication::class, sdk = [34])
app/src/test/java/com/yorvana/ui/vehicles/VehicleListScreenIT.kt:27:@RunWith(RobolectricTestRunner::class)
app/src/test/java/com/yorvana/ui/components/UpgradeDialogTest.kt:12:import org.robolectric.RobolectricTestRunner
app/src/test/java/com/yorvana/ui/components/UpgradeDialogTest.kt:15:@RunWith(RobolectricTestRunner::class)
app/src/test/java/com/yorvana/ui/components/UpgradeDialogTest.kt:16:@Config(sdk = [33])
app/src/test/java/com/yorvana/ui/components/PaywallScaffoldScreenshotTest.kt:22:@Config(sdk = [34], qualifiers = "xxhdpi")
app/src/test/java/com/yorvana/ui/reportbug/ReportBugScreenshotTest.kt:81:    @Config(qualifiers = "w411dp-h1000dp")
app/src/test/java/com/yorvana/ui/components/PaywallInfoSheetScreenshotTest.kt:15:@Config(sdk = [34], qualifiers = "xxhdpi")
app/src/test/java/com/yorvana/ui/components/RequiredLabelTest.kt:20:import org.robolectric.RobolectricTestRunner
app/src/test/java/com/yorvana/ui/components/RequiredLabelTest.kt:23:@RunWith(RobolectricTestRunner::class)
app/src/test/java/com/yorvana/ui/components/RequiredLabelTest.kt:24:@Config(application = TestYorvanaApplication::class, sdk = [34])
app/src/test/java/com/yorvana/ui/reportbug/ReportBugScreenTest.kt:22:import org.robolectric.RobolectricTestRunner
app/src/test/java/com/yorvana/ui/reportbug/ReportBugScreenTest.kt:26:@RunWith(RobolectricTestRunner::class)
app/src/test/java/com/yorvana/ui/reportbug/ReportBugScreenTest.kt:27:@Config(application = TestYorvanaApplication::class, sdk = [34])
app/src/test/java/com/yorvana/ui/components/PaywallStatusCardScreenshotTest.kt:17:@Config(sdk = [34], qualifiers = "xxhdpi")
app/src/test/java/com/yorvana/ui/navigation/SetupScreenTest.kt:10:import org.robolectric.RobolectricTestRunner
app/src/test/java/com/yorvana/ui/navigation/SetupScreenTest.kt:13:@RunWith(RobolectricTestRunner::class)
app/src/test/java/com/yorvana/ui/navigation/SetupScreenTest.kt:14:@Config(application = TestYorvanaApplication::class, sdk = [34])
app/src/test/java/com/yorvana/ui/reportbug/ReportBugViewModelTest.kt:29:import org.robolectric.RobolectricTestRunner
app/src/test/java/com/yorvana/ui/reportbug/ReportBugViewModelTest.kt:33:@RunWith(RobolectricTestRunner::class)
app/src/test/java/com/yorvana/ui/reportbug/ReportBugViewModelTest.kt:34:@Config(sdk = [34])
app/src/test/java/com/yorvana/ui/util/ContextExtensionsTest.kt:11:import org.robolectric.RobolectricTestRunner
app/src/test/java/com/yorvana/ui/util/ContextExtensionsTest.kt:14:@RunWith(RobolectricTestRunner::class)
app/src/test/java/com/yorvana/ui/util/ContextExtensionsTest.kt:15:@Config(sdk = [33])
app/src/test/java/com/yorvana/ui/settings/CategoriesScreenTest.kt:17:import org.robolectric.RobolectricTestRunner
app/src/test/java/com/yorvana/ui/settings/CategoriesScreenTest.kt:20:@RunWith(RobolectricTestRunner::class)
app/src/test/java/com/yorvana/ui/settings/CategoriesScreenTest.kt:21:@Config(application = TestYorvanaApplication::class, sdk = [34])
app/src/test/java/com/yorvana/ui/vehicles/AddEditVehicleViewModelIT.kt:33:import org.robolectric.RobolectricTestRunner
app/src/test/java/com/yorvana/ui/vehicles/AddEditVehicleViewModelIT.kt:38:@Config(application = TestYorvanaApplication::class, sdk = [34])
app/src/test/java/com/yorvana/ui/vehicles/AddEditVehicleViewModelIT.kt:39:@RunWith(RobolectricTestRunner::class)
app/src/test/java/com/yorvana/ui/settings/CategoriesScreenIT.kt:20:import org.robolectric.RobolectricTestRunner
app/src/test/java/com/yorvana/ui/settings/CategoriesScreenIT.kt:23:@Config(application = TestYorvanaApplication::class, sdk = [34])
app/src/test/java/com/yorvana/ui/settings/CategoriesScreenIT.kt:24:@RunWith(RobolectricTestRunner::class)
app/src/test/java/com/yorvana/ui/settings/SettingsScreenIT.kt:20:import org.robolectric.RobolectricTestRunner
app/src/test/java/com/yorvana/ui/settings/SettingsScreenIT.kt:23:@Config(application = TestYorvanaApplication::class, sdk = [34])
app/src/test/java/com/yorvana/ui/settings/SettingsScreenIT.kt:24:@RunWith(RobolectricTestRunner::class)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelIT.kt:5:import android.net.Uri
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelIT.kt:41:import org.robolectric.RobolectricTestRunner
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelIT.kt:46:@Config(application = TestYorvanaApplication::class, sdk = [34])
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelIT.kt:47:@RunWith(RobolectricTestRunner::class)


Input:
*** Begin Patch
*** Update File: /home/Messier82/projects/service-book/app/src/test/java/com/yorvana/ui/util/EmailLaunchRequestTest.kt
@@
 import io.mockk.runs
 import io.mockk.slot
+import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
 import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.annotation.Config

+@OptIn(ExperimentalCoroutinesApi::class)
+@RunWith(RobolectricTestRunner::class)
+@Config(sdk = [34])
 class EmailLaunchRequestTest {
*** End Patch


Success. Updated the following files:
M /home/Messier82/projects/service-book/app/src/test/java/com/yorvana/ui/util/EmailLaunchRequestTest.kt

@@ -14,2 +14,3 @@
 import io.mockk.slot
+import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.launch
@@ -18,3 +19,9 @@
 import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.annotation.Config

+@OptIn(ExperimentalCoroutinesApi::class)
+@RunWith(RobolectricTestRunner::class)
+@Config(sdk = [34])
 class EmailLaunchRequestTest {


Output: {"output":"Success. Updated the following files:\nM /home/Messier82/projects/service-book/app/src/test/java/com/yorvana/ui/util/EmailLaunchRequestTest.kt\n","metadata":{"exit_code":0,"duration_seconds":0.9}}


./gradlew :app:testDebugUnitTest --tests com.yorvana.ui.util.EmailLaunchRequestTest --tests com.yorvana.ui.settings.SettingsViewModelTest --tests com.yorvana.ui.settings.SettingsScreenIT --tests com.yorvana.ui.reportbug.ReportBugViewModelTest


Output:
Chunk ID: a08ec9
Wall time: 1.0007 seconds
Process running with session ID 33203
Original token count: 45
Output:
Picked up JAVA_TOOL_OPTIONS: -Xlog:os+container=off

> Configure project :app
WARNING: The option setting 'android.testoptions.manageddevices.emulator.gpu=host' is experimental.


Output:
Chunk ID: 243c18
Wall time: 5.0003 seconds
Process running with session ID 33203
Original token count: 545
Output:

> Task :app:preBuild UP-TO-DATE
> Task :app:preDebugBuild UP-TO-DATE
> Task :app:generateDebugBuildConfig UP-TO-DATE
> Task :app:generateDebugResources UP-TO-DATE
> Task :app:packageDebugResources UP-TO-DATE
> Task :app:processDebugNavigationResources UP-TO-DATE
> Task :app:parseDebugLocalResources UP-TO-DATE
> Task :app:generateDebugRFile UP-TO-DATE
> Task :app:compileDebugKotlin UP-TO-DATE
> Task :app:javaPreCompileDebug UP-TO-DATE
> Task :app:compileDebugJavaWithJavac UP-TO-DATE
> Task :app:checkDebugAarMetadata UP-TO-DATE
> Task :app:mapDebugSourceSetPaths UP-TO-DATE
> Task :app:compileDebugNavigationResources UP-TO-DATE
> Task :app:mergeDebugResources UP-TO-DATE
> Task :app:createDebugCompatibleScreenManifests UP-TO-DATE
> Task :app:extractDeepLinksDebug UP-TO-DATE
> Task :app:processDebugMainManifest UP-TO-DATE
> Task :app:processDebugManifest UP-TO-DATE
> Task :app:processDebugManifestForPackage UP-TO-DATE
> Task :app:processDebugResources UP-TO-DATE
> Task :app:bundleDebugClassesToRuntimeJar UP-TO-DATE
> Task :app:bundleDebugClassesToCompileJar UP-TO-DATE
> Task :app:preDebugUnitTestBuild UP-TO-DATE
> Task :app:javaPreCompileDebugUnitTest UP-TO-DATE
> Task :app:generateDebugAssets UP-TO-DATE
> Task :app:mergeDebugAssets UP-TO-DATE
> Task :app:packageDebugUnitTestForUnitTest UP-TO-DATE
> Task :app:processDebugUnitTestManifest UP-TO-DATE
> Task :app:generateDebugUnitTestConfig UP-TO-DATE
> Task :app:processDebugJavaRes UP-TO-DATE
> Task :app:restoreOutputDirRoborazzi SKIPPED
> Task :app:compileDebugUnitTestKotlin
> Task :app:compileDebugUnitTestJavaWithJavac NO-SOURCE
> Task :app:processDebugUnitTestJavaRes UP-TO-DATE

> Task :app:testDebugUnitTest
Picked up JAVA_TOOL_OPTIONS: -Xlog:os+container=off
Picked up JAVA_TOOL_OPTIONS: -Xlog:os+container=off

OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended


Output:
Chunk ID: 9269f2
Wall time: 2.8301 seconds
Process exited with code 0
Original token count: 196
Output:

> Task :app:finalizeTestRoborazziDebug SKIPPED

[Incubating] Problems report is available at: file:///home/Messier82/projects/service-book/build/reports/problems/problems-report.html

Deprecated Gradle features were used in this build, making it incompatible with Gradle 10.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

For more on this, please refer to https://docs.gradle.org/9.5.1/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.

BUILD SUCCESSFUL in 17s
30 actionable tasks: 2 executed, 28 up-to-date
Consider enabling configuration cache to speed up this build: https://docs.gradle.org/9.5.1/userguide/configuration_cache_enabling.html


The helper fallback test is now stable under Robolectric and the focused suite passes. I’m doing one final quality pass, then I’ll amend the PR commit and force-push with lease.


Output:
Chunk ID: 14b875
Wall time: 1.0025 seconds
Process running with session ID 39342
Original token count: 39
Output:
Picked up JAVA_TOOL_OPTIONS: -Xlog:os+container=off
Starting a Gradle Daemon, 2 busy and 1 stopped Daemons could not be reused, use --status for details


Output:
Chunk ID: 4f6743
Wall time: 1.0013 seconds
Process running with session ID 91992
Original token count: 45
Output:
Picked up JAVA_TOOL_OPTIONS: -Xlog:os+container=off

> Configure project :app
WARNING: The option setting 'android.testoptions.manageddevices.emulator.gpu=host' is experimental.


Output:
Chunk ID: d93583
Wall time: 5.0017 seconds
Process running with session ID 39342
Original token count: 32
Output:

> Configure project :app
WARNING: The option setting 'android.testoptions.manageddevices.emulator.gpu=host' is experimental.


Output:
Chunk ID: c033ad
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 184
Output:

> Task :app:detekt

[Incubating] Problems report is available at: file:///home/Messier82/projects/service-book/build/reports/problems/problems-report.html

Deprecated Gradle features were used in this build, making it incompatible with Gradle 10.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

For more on this, please refer to https://docs.gradle.org/9.5.1/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.

BUILD SUCCESSFUL in 8s
1 actionable task: 1 executed
Consider enabling configuration cache to speed up this build: https://docs.gradle.org/9.5.1/userguide/configuration_cache_enabling.html


Output:
Chunk ID: 4037a7
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 225
Output:

> Task :app:loadKtlintReporters UP-TO-DATE
> Task :app:runKtlintCheckOverKotlinScripts UP-TO-DATE
> Task :app:ktlintKotlinScriptCheck UP-TO-DATE
> Task :app:ktlintCheck UP-TO-DATE

[Incubating] Problems report is available at: file:///home/Messier82/projects/service-book/build/reports/problems/problems-report.html

Deprecated Gradle features were used in this build, making it incompatible with Gradle 10.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

For more on this, please refer to https://docs.gradle.org/9.5.1/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.

BUILD SUCCESSFUL in 10s
3 actionable tasks: 3 up-to-date
Consider enabling configuration cache to speed up this build: https://docs.gradle.org/9.5.1/userguide/configuration_cache_enabling.html


git diff -- app/src/test/java/com/yorvana/ui/util/EmailLaunchRequestTest.kt app/src/main/java/com/yorvana/ui/util/EmailLaunchRequest.kt app/src/main/res/values/strings.xml


Output:
Chunk ID: 6dee8d
Wall time: 0.2808 seconds
Process exited with code 0
Original token count: 122
Output:
## add-settings-contact...origin/add-settings-contact
 M app/src/main/java/com/yorvana/ui/reportbug/ReportBugScreen.kt
 M app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt
 M app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt
 M app/src/main/java/com/yorvana/ui/util/EmailLaunchRequest.kt
 M app/src/main/res/values/strings.xml
 M app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt
?? app/src/test/java/com/yorvana/ui/util/EmailLaunchRequestTest.kt


Output:
Chunk ID: 3af4a1
Wall time: 0.2937 seconds
Process exited with code 0
Original token count: 127
Output:
 app/src/main/java/com/yorvana/ui/reportbug/ReportBugScreen.kt      | 4 +---
 app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt        | 3 +--
 app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt     | 2 +-
 app/src/main/java/com/yorvana/ui/util/EmailLaunchRequest.kt        | 5 +++--
 app/src/main/res/values/strings.xml                                | 3 ++-
 app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt | 1 +
 6 files changed, 9 insertions(+), 9 deletions(-)


Output:
Chunk ID: a389f6
Wall time: 0.3130 seconds
Process exited with code 0
Original token count: 625
Output:
diff --git a/app/src/main/java/com/yorvana/ui/util/EmailLaunchRequest.kt b/app/src/main/java/com/yorvana/ui/util/EmailLaunchRequest.kt
index e6e50be..607baa2 100644
--- a/app/src/main/java/com/yorvana/ui/util/EmailLaunchRequest.kt
+++ b/app/src/main/java/com/yorvana/ui/util/EmailLaunchRequest.kt
@@ -3,6 +3,7 @@ package com.yorvana.ui.util
 import android.content.ActivityNotFoundException
 import android.content.Context
 import android.content.Intent
+import androidx.annotation.StringRes
 import androidx.compose.material3.SnackbarHostState
 import androidx.core.net.toUri

@@ -15,7 +16,7 @@ data class EmailLaunchRequest(
 suspend fun launchEmail(
     context: Context,
     snackbarHostState: SnackbarHostState,
-    noEmailAppMessage: String,
+    @StringRes noEmailAppMessageRes: Int,
     request: EmailLaunchRequest,
 ) {
     val intent =
@@ -30,6 +31,6 @@ suspend fun launchEmail(
     try {
         context.startActivity(intent)
     } catch (_: ActivityNotFoundException) {
-        snackbarHostState.showSnackbar(noEmailAppMessage)
+        snackbarHostState.showSnackbar(context.getString(noEmailAppMessageRes))
     }
 }
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index f7e30b7..158e7c8 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -109,6 +109,7 @@
     <string name="settings_about">About</string>
     <string name="settings_contact">Contact</string>
     <string name="settings_contact_subtitle">Email Yorvana support</string>
+    <string name="settings_contact_email_subject">[Yorvana] Contact</string>
     <string name="settings_report_bug">Report a bug or suggest a feature</string>
     <string name="settings_version">Version %s</string>

@@ -122,7 +123,7 @@
     <string name="report_bug_contact_email_invalid">Please enter a valid email address</string>
     <string name="report_bug_email_contact_label">Contact email</string>
     <string name="report_bug_type_section">Type</string>
-    <string name="report_bug_no_email_app">No email app found</string>
+    <string name="email_no_app_found">No email app found</string>
     <string name="report_bug_include_device_info">Include additional app state</string>
     <string name="report_bug_device_info_payload">Device information</string>
     <string name="report_bug_sentry_opt_out_disclosure">Submitting will connect to our error reporting service for this report only. Basic device info is always attached.</string>


All review-driven changes are now staged for the PR: localized subject, neutral fallback string, helper API cleanup, and direct tests for intent creation plus missing-app snackbar behavior. I’m amending the existing PR commit rather than adding another stack commit.


Output:
Chunk ID: 60cad8
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 0
Output:


Output:
Chunk ID: 14c490
Wall time: 1.0014 seconds
Process running with session ID 56701
Original token count: 13
Output:
Picked up JAVA_TOOL_OPTIONS: -Xlog:os+container=off


Output:
Chunk ID: af34ab
Wall time: 5.0014 seconds
Process running with session ID 56701
Original token count: 407
Output:

> Configure project :app
WARNING: The option setting 'android.testoptions.manageddevices.emulator.gpu=host' is experimental.

> Task :app:loadKtlintReporters UP-TO-DATE
> Task :app:runKtlintCheckOverKotlinScripts UP-TO-DATE
> Task :app:ktlintKotlinScriptCheck UP-TO-DATE
> Task :app:ktlintCheck UP-TO-DATE
> Task :app:detekt UP-TO-DATE
> Task :app:preBuild UP-TO-DATE
> Task :app:preDebugBuild UP-TO-DATE
> Task :app:generateDebugBuildConfig UP-TO-DATE
> Task :app:generateDebugResources UP-TO-DATE
> Task :app:packageDebugResources UP-TO-DATE
> Task :app:processDebugNavigationResources UP-TO-DATE
> Task :app:parseDebugLocalResources UP-TO-DATE
> Task :app:generateDebugRFile UP-TO-DATE
> Task :app:compileDebugKotlin UP-TO-DATE
> Task :app:javaPreCompileDebug UP-TO-DATE
> Task :app:compileDebugJavaWithJavac UP-TO-DATE
> Task :app:checkDebugAarMetadata UP-TO-DATE
> Task :app:mapDebugSourceSetPaths UP-TO-DATE
> Task :app:compileDebugNavigationResources UP-TO-DATE
> Task :app:mergeDebugResources UP-TO-DATE
> Task :app:createDebugCompatibleScreenManifests UP-TO-DATE
> Task :app:extractDeepLinksDebug UP-TO-DATE
> Task :app:processDebugMainManifest UP-TO-DATE
> Task :app:processDebugManifest UP-TO-DATE
> Task :app:processDebugManifestForPackage UP-TO-DATE
> Task :app:processDebugResources UP-TO-DATE
> Task :app:bundleDebugClassesToCompileJar UP-TO-DATE
> Task :app:preDebugAndroidTestBuild SKIPPED
> Task :app:generateDebugAndroidTestLintModel
> Task :app:extractProguardFiles UP-TO-DATE
> Task :app:generateDebugLintReportModel
> Task :app:preDebugUnitTestBuild UP-TO-DATE
> Task :app:generateDebugUnitTestLintModel


Output:
Chunk ID: d7a028
Wall time: 5.0004 seconds
Process running with session ID 56701
Original token count: 10
Output:
> Task :app:lintAnalyzeDebugAndroidTest


Output:
Chunk ID: 1200f3
Wall time: 5.0005 seconds
Process running with session ID 56701
Original token count: 0
Output:


Output:
Chunk ID: d9008a
Wall time: 5.0004 seconds
Process running with session ID 56701
Original token count: 0
Output:


The amend hook is running the repository’s lint stack now. It is past ktlint and detekt, and currently in Android lint.


Output:
Chunk ID: f5d816
Wall time: 5.0011 seconds
Process running with session ID 56701
Original token count: 17
Output:
> Task :app:lintAnalyzeDebug
> Task :app:lintAnalyzeDebugUnitTest


Output:
Chunk ID: f98e01
Wall time: 5.0017 seconds
Process running with session ID 56701
Original token count: 0
Output:


Output:
Chunk ID: ec1b79
Wall time: 5.0002 seconds
Process running with session ID 56701
Original token count: 0
Output:


Output:
Chunk ID: c74b10
Wall time: 5.0015 seconds
Process running with session ID 56701
Original token count: 0
Output:


Output:
Chunk ID: 925e3c
Wall time: 5.0007 seconds
Process running with session ID 56701
Original token count: 0
Output:


Output:
Chunk ID: 36325e
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 369
Output:

> Task :app:lintReportDebug
Wrote HTML report to file:///home/Messier82/projects/service-book/app/build/reports/lint-results-debug.html
Lint found 13 warnings, 1 hint (and 34 warnings filtered by baseline lint-baseline.xml)

41 errors/warnings were listed in the baseline file (/home/Messier82/projects/service-book/app/lint-baseline.xml) but not found in the project; perhaps they have been fixed?

> Task :app:lintDebug

[Incubating] Problems report is available at: file:///home/Messier82/projects/service-book/build/reports/problems/problems-report.html

Deprecated Gradle features were used in this build, making it incompatible with Gradle 10.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

For more on this, please refer to https://docs.gradle.org/9.5.1/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.

BUILD SUCCESSFUL in 1m 10s
33 actionable tasks: 8 executed, 25 up-to-date
Consider enabling configuration cache to speed up this build: https://docs.gradle.org/9.5.1/userguide/configuration_cache_enabling.html
[add-settings-contact 3fabd15] Add contact option to settings
 Date: Mon May 18 16:28:08 2026 +0300
 8 files changed, 235 insertions(+), 18 deletions(-)
 create mode 100644 app/src/main/java/com/yorvana/ui/util/EmailLaunchRequest.kt
 create mode 100644 app/src/test/java/com/yorvana/ui/util/EmailLaunchRequestTest.kt


The commit amended successfully after the full hook passed. Android lint still reports the repo’s existing baseline-staleness warning, but it did not fail the build. I’m pushing the amended commit to the PR branch now.


Output:
Chunk ID: a42563
Wall time: 1.0007 seconds
Process running with session ID 30370
Original token count: 0
Output:


Output:
Chunk ID: 87db3e
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 29
Output:
To github.com:yorvana/android.git
 + 2ff6bc0...3fabd15 add-settings-contact -> add-settings-contact (forced update)


Output:
Chunk ID: 5205fb
Wall time: 0.2121 seconds
Process exited with code 0
Original token count: 14
Output:
## add-settings-contact...origin/add-settings-contact


Output:
Chunk ID: c85b4a
Wall time: 0.2047 seconds
Process exited with code 0
Original token count: 10
Output:
3fabd15 Add contact option to settings


Resolved the latest review follow-ups and pushed the amended PR branch.

Changes made:
- Localized the Contact email subject via `settings_contact_email_subject`.
- Renamed the generic fallback string to `email_no_app_found`.
- Updated `launchEmail` to take a `@StringRes` and resolve the message internally.
- Added `EmailLaunchRequestTest` covering both intent creation and missing-email-app snackbar fallback.

Verification passed:
- `./gradlew :app:testDebugUnitTest --tests com.yorvana.ui.util.EmailLaunchRequestTest --tests com.yorvana.ui.settings.SettingsViewModelTest --tests com.yorvana.ui.settings.SettingsScreenIT --tests com.yorvana.ui.reportbug.ReportBugViewModelTest`
- `./gradlew :app:ktlintCheck`
- `./gradlew :app:detekt`
- Pre-commit hook including `lintDebug`

Pushed amended commit `3fabd15` to PR #102. Worktree is clean.


<environment_context>
  <current_date>2026-05-19</current_date>
  <timezone>Etc/UTC</timezone>
</environment_context>


# Collaboration Mode: Default

You are now in Default mode. Any previous instructions for other modes (e.g. Plan mode) are no longer active.

Your active mode changes only when new developer instructions with a different `<collaboration_mode>...</collaboration_mode>` change it; user requests or tool descriptions do not change mode by themselves. Known mode names are Default and Plan.

## request_user_input availability

Use the `request_user_input` tool only when it is listed in the available tools for this turn.

In Default mode, strongly prefer making reasonable assumptions and executing the user's request rather than stopping to ask questions. If you absolutely must ask a question because the answer cannot be discovered from local context and a reasonable assumption would be risky, ask the user directly with a concise plain-text question. Never write a multiple choice question as a textual assistant message.


Claude said that there's 2 unresolved items left still


I’ll check the current PR review/comments directly and separate unresolved actionable items from comments that are already addressed in the latest commit.


gh pr view 102 --json number,title,headRefName,baseRefName,comments,reviews,latestReviews,files,url,headRefOid

Allow reading the latest PR #102 review comments from GitHub?


Output:
Chunk ID: 662773
Wall time: 0.7004 seconds
Process exited with code 0
Original token count: 1998
Output:
{"baseRefName":"master","comments":[{"id":"IC_kwDOR2Hmq88AAAABCuuiOg","author":{"login":"github-actions"},"authorAssociation":"NONE","body":"🔁 **Coverage baseline may need a refresh.**\n\nThis PR touches `app/src/main/**`. If the changes affect what smoke covers, please refresh the baseline before merging:\n\n```bash\n./gradlew generateGmdCoverage\ngit add app/coverage-baselines/gmd_smoke.ec\ngit commit -m \"chore: refresh smoke coverage baseline\"\n```\n\n_Last checked: 2026-05-18 18:44 UTC · commit `3fabd15`_\n<!-- Sticky Pull Request Commentbaseline-reminder-bot -->","createdAt":"2026-05-18T13:30:42Z","includesCreatedEdit":true,"isMinimized":false,"minimizedReason":"","reactionGroups":[],"url":"https://github.com/yorvana/android/pull/102#issuecomment-4478181946","viewerDidAuthor":false},{"id":"IC_kwDOR2Hmq88AAAABCux65Q","author":{"login":"Mesya82"},"authorAssociation":"MEMBER","body":"## Code Review\n\n### Overview\nAdds a \"Contact\" row above \"Report a bug\" in the Feedback section that opens the user's email app with the support address pre-filled, via a new `SettingsEvent.OpenContact` → `SettingsEffect.LaunchContactEmail` round-trip. Reuses the existing `report_bug_support_email` and `report_bug_no_email_app` strings.\n\n### Strengths\n- **MVVM discipline** preserved: side-effect launched from a one-shot `Channel` effect; UI is dumb. Matches the existing `ReportBugEffect.FallbackToEmail` pattern.\n- **Grouped-card visual pattern** (`24/4` top corners + `2.dp` Spacer + `4/24` bottom corners) is already used in 4 other places in `SettingsScreen.kt`, so this is consistent — not bespoke styling.\n- **Subject prefix `[Yorvana] …`** matches the existing convention in `ReportBugViewModel.kt:193`.\n- **Test coverage** is appropriate for the change: ViewModel emits the right effect; Screen IT verifies the click dispatches `OpenContact`.\n\n### Issues / suggestions\n- **Email intent code duplicated.** `SettingsScreen.kt:138-148` is a near-verbatim copy of `ReportBugScreen.kt:86-97` (same `ACTION_SENDTO`, same `mailto:`, same `try/catch (_: Exception)` with the same fallback string). Extracting a small `launchEmail(context, snackbarHostState, recipient, subject, body?)` helper would remove the duplication now, before a third caller appears.\n- **No test for the missing-email-app fallback.** The `catch (_: Exception)` branch isn't exercised. Pre-existing precedent (ReportBug has none either), so a nit — but easy to add via a Screen IT that asserts the snackbar after emitting the effect with no resolver.\n- **Hardcoded subject `\"[Yorvana] Contact\"`** is not localized. `ReportBug` does the same for the prefix, but the suffix there is dynamic; here the whole subject is a fixed user-facing English string. Consider a `@string/contact_email_subject` if localization is on the roadmap.\n- **Catching `Exception`** — broad, but consistent with `ReportBugScreen`. `ActivityNotFoundException` would be tighter and matches what `startActivity` actually throws for an unresolved `ACTION_SENDTO`.\n\n### Risks\nLow. The change is additive, behind a new event/effect, and doesn't alter existing flows. No new permissions, no new dependencies, no preference-state changes.\n\n### Verdict\nLGTM. The duplicated intent block is the only thing I'd address before merge; everything else is nit-level.","createdAt":"2026-05-18T13:37:05Z","includesCreatedEdit":false,"isMinimized":false,"minimizedReason":"","reactionGroups":[],"url":"https://github.com/yorvana/android/pull/102#issuecomment-4478237413","viewerDidAuthor":true},{"id":"IC_kwDOR2Hmq88AAAABCwPP9Q","author":{"login":"Mesya82"},"authorAssociation":"MEMBER","body":"## Code Review\n\n### Overview\nAdds a Contact row to the Settings Feedback section that opens the user's email client with the support address pre-filled. Routes through `SettingsViewModel` via a new `OpenContact` event → `LaunchContactEmail` effect. Notably, this revision extracts the email-launch logic into a shared `launchEmail` helper and refactors `ReportBugScreen` to use it.\n\n### Strengths\n- **Duplication eliminated.** The earlier review flagged copy-pasted intent code between `SettingsScreen` and `ReportBugScreen`; this revision factors both into `ui/util/EmailLaunchRequest.kt:18`. `ReportBugScreen.kt:85-97` now calls the helper.\n- **Exception narrowing.** Replaces the broad `catch (_: Exception)` with `ActivityNotFoundException` (`EmailLaunchRequest.kt:32`) — the only exception `startActivity` documents for this case. Good tightening.\n- **MVVM discipline preserved.** ViewModel does not touch `Context`/`Intent`; recipient/subject flow as plain strings through the effect (`SettingsViewModel.kt:210-218`).\n- **Grouped-card pattern consistent.** Asymmetric `RoundedCornerShape` + 2.dp `Spacer` between Contact and Report Bug matches the other grouped cards in this screen.\n- **Test coverage matches the pattern.** ViewModel emits the right effect (`SettingsViewModelTest.kt:150-166`); Screen dispatches the right event on click (`SettingsScreenIT.kt:97-122`).\n\n### Suggestions\n\n- **Subject not localized.** `subject = \"[Yorvana] Contact\"` (`SettingsViewModel.kt:215`) is a hardcoded English literal. Other user-facing strings in this PR went through `strings.xml`. Extract to e.g. `settings_contact_email_subject` so it can be translated.\n\n- **`noEmailAppMessage` string key is misnamed for shared use.** Both call sites resolve `R.string.report_bug_no_email_app` — the *text* is generic (\"No email app installed\"), but the *resource name* is tied to Report Bug. Now that two features share it, rename to something feature-neutral (e.g. `email_no_app_installed`).\n\n- **Helper resolves at call site, not internally.** `launchEmail` takes `noEmailAppMessage: String` rather than a `@StringRes` id or resolving from `context` itself. Forces every caller to remember the `stringResource` plumbing. Minor — fine as-is, but resolving inside the helper would shrink each call site by two lines and make the next adopter's path obvious.\n\n- **Test for the missing-email-app fallback.** Neither `SettingsScreenIT` nor `ReportBugScreen` tests cover the `ActivityNotFoundException` → snackbar path. Worth a unit test on `launchEmail` itself (it's a plain suspend function now — easy to test with a fake `Context`).\n\n### Risks\nLow. Additive feature, narrowed exception type, the refactor of `ReportBugScreen` preserves identical runtime behavior.\n\n### Verdict\n**LGTM with minor follow-ups.** The shared-helper refactor is a genuine improvement over the prior revision. Worth fixing the subject localization before merge; the rename and helper-shape cleanup are quick and worth doing while the file is in flight.","createdAt":"2026-05-18T16:37:07Z","includesCreatedEdit":false,"isMinimized":false,"minimizedReason":"","reactionGroups":[],"url":"https://github.com/yorvana/android/pull/102#issuecomment-4479766517","viewerDidAuthor":true}],"files":[{"path":"app/src/main/java/com/yorvana/ui/reportbug/ReportBugScreen.kt","additions":13,"deletions":16},{"path":"app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt","additions":35,"deletions":1},{"path":"app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt","additions":17,"deletions":0},{"path":"app/src/main/java/com/yorvana/ui/util/EmailLaunchRequest.kt","additions":36,"deletions":0},{"path":"app/src/main/res/values/strings.xml","additions":4,"deletions":1},{"path":"app/src/test/java/com/yorvana/ui/settings/SettingsScreenIT.kt","additions":28,"deletions":0},{"path":"app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt","additions":20,"deletions":0},{"path":"app/src/test/java/com/yorvana/ui/util/EmailLaunchRequestTest.kt","additions":82,"deletions":0}],"headRefName":"add-settings-contact","headRefOid":"3fabd15fc4b91ac62619ad11a164547128c833f7","latestReviews":[],"number":102,"reviews":[],"title":"Add Contact option to Settings","url":"https://github.com/yorvana/android/pull/102"}


Output:
Chunk ID: b7039c
Wall time: 0.4056 seconds
Process exited with code 0
Original token count: 1
Output:
[]


Output:
Chunk ID: 46a3d7
Wall time: 0.1371 seconds
Process exited with code 0
Original token count: 14
Output:
## add-settings-contact...origin/add-settings-contact


GitHub shows no inline review comments, and the latest PR body comments are the same ones we already handled. I’m going to query review threads via GraphQL too, because unresolved conversations can be hidden from the simpler `gh pr view` output.


gh api graphql -f query='query { repository(owner:"yorvana", name:"android") { pullRequest(number:102) { reviewThreads(first:50) { nodes { isResolved isOutdated path line comments(first:10) { nodes { author { login } body createdAt url } } } } } } }'

Allow checking PR #102 unresolved review thread status on GitHub?


Approved command prefix saved:
- ["gh", "api", "graphql"]


Output:
Chunk ID: 7047a5
Wall time: 0.5305 seconds
Process exited with code 0
Original token count: 18
Output:
{"data":{"repository":{"pullRequest":{"reviewThreads":{"nodes":[]}}}}}


The GraphQL review-thread query also reports zero review threads, so there aren’t any GitHub “unresolved conversation” threads on the PR. I’m checking current checks/status now to see whether Claude meant unresolved CI/bot items instead of review threads.


Allow checking current PR #102 CI status to identify unresolved bot items?


Output: aborted by user after 8.6s


<turn_aborted>
The user interrupted the previous turn on purpose. Any running unified exec processes may still be running in the background. If any tools/commands were aborted, they may have partially executed.
</turn_aborted>


Its still the same comment that you were looking before. You havent addressed all the items. If you havent, because there were reasons for that - you must've left a comment


Understood. I checked the latest GitHub state: there are no unresolved review threads, but the PR still has the bot coverage-baseline comment. I’ll handle that explicitly by either refreshing the baseline if it changes, or leaving a PR comment explaining why it’s not applicable.


rg -n "generateGmdCoverage|gmd_smoke|coverage-baselines|Settings" .github app build.gradle.kts settings.gradle.kts


Output:
Chunk ID: 5f5d0a
Wall time: 0.2336 seconds
Process exited with code 0
Original token count: 8485
Output:
app/build.gradle.kts:36:                it.contains("generateGmdCoverage", ignoreCase = true)
app/build.gradle.kts:155:tasks.register<Copy>("generateGmdCoverage") {
app/build.gradle.kts:164:    into(layout.projectDirectory.dir("coverage-baselines"))
app/build.gradle.kts:165:    rename { "gmd_smoke.ec" }
app/build.gradle.kts:171:        val destFile = layout.projectDirectory.file("coverage-baselines/gmd_smoke.ec").asFile
app/build.gradle.kts:231:            layout.projectDirectory.file("coverage-baselines/gmd_smoke.ec"),
app/build.gradle.kts:238:        val lfsBaseline = layout.projectDirectory.file("coverage-baselines/gmd_smoke.ec").asFile
app/build.gradle.kts:242:                    "Run 'git lfs pull' to fetch tracked baselines or './gradlew generateGmdCoverage' to regenerate it.",
app/build.gradle.kts:253:        val dynamicExecutionFiles = existingFiles.filter { it.name != "gmd_smoke.ec" }
app/lint-baseline.xml:809:            file="src/main/java/com/yorvana/ui/settings/SettingsScreen.kt"
app/detekt-baseline.xml:14:    <ID>LongParameterList:SettingsScreenshotTest.kt$SettingsScreenshotTest$( showConflict: Boolean = false, isValidating: Boolean = false, showExistingVault: Boolean = false, isDark: Boolean = false, crashReportingEnabled: Boolean = false, isPremium: Boolean = false, )</ID>
app/detekt-baseline.xml:62:    <ID>MagicNumber:SettingsViewModel.kt$SettingsViewModel$400</ID>
app/src/main/java/com/yorvana/ui/TestTags.kt:18:    const val SETTINGS_BUTTON = "SettingsButton"
app/src/main/java/com/yorvana/ui/TestTags.kt:68:    // Settings
app/src/main/java/com/yorvana/ui/vehicles/VehicleListViewModel.kt:46:    object OpenSettings : VehicleListEvent()
app/src/main/java/com/yorvana/ui/vehicles/VehicleListViewModel.kt:66:    object NavigateToSettings : VehicleListEffect()
app/src/main/java/com/yorvana/ui/vehicles/VehicleListViewModel.kt:191:            is VehicleListEvent.OpenSettings ->
app/src/main/java/com/yorvana/ui/vehicles/VehicleListViewModel.kt:192:                viewModelScope.launch { _effects.send(VehicleListEffect.NavigateToSettings) }
app/src/main/java/com/yorvana/MainActivity.kt:89:    // tests and the Settings screen — automatically navigates without an Activity recreate.
app/src/main/java/com/yorvana/ui/vehicles/VehicleListScreen.kt:25:import androidx.compose.material.icons.outlined.Settings
app/src/main/java/com/yorvana/ui/vehicles/VehicleListScreen.kt:77:import com.yorvana.ui.navigation.Settings
app/src/main/java/com/yorvana/ui/vehicles/VehicleListScreen.kt:142:                VehicleListEffect.NavigateToSettings ->
app/src/main/java/com/yorvana/ui/vehicles/VehicleListScreen.kt:143:                    backStack.add(Settings)
app/src/main/java/com/yorvana/ui/vehicles/VehicleListScreen.kt:205:                        onClick = { viewModel.onEvent(VehicleListEvent.OpenSettings) },
app/src/main/java/com/yorvana/ui/vehicles/VehicleListScreen.kt:208:                        Icon(Icons.Outlined.Settings, contentDescription = stringResource(R.string.settings_title))
app/src/androidTest/java/com/yorvana/SmokeTest.kt:110:    private fun navigateToSettings() {
app/src/androidTest/java/com/yorvana/SmokeTest.kt:245:    fun s11_navigateToSettings_works() {
app/src/androidTest/java/com/yorvana/SmokeTest.kt:248:        navigateToSettings()
app/src/androidTest/java/com/yorvana/SmokeTest.kt:353:        step("S19", "navigating to Settings and verifying status")
app/src/androidTest/java/com/yorvana/SmokeTest.kt:356:        navigateToSettings()
app/src/androidTest/java/com/yorvana/SmokeTest.kt:357:        // SettingsScreen doesn't show the StatusCard but has a Premium section
app/src/androidTest/java/com/yorvana/SmokeTest.kt:399:        navigateToSettings()
app/src/androidTest/java/com/yorvana/SmokeTest.kt:409:        // Nav state is preserved via rememberSaveable — app restores to SettingsScreen
app/src/androidTest/java/com/yorvana/SmokeTest.kt:422:        // Nav state is preserved via rememberSaveable — app restores to SettingsScreen
app/src/androidTest/java/com/yorvana/SmokeTest.kt:433:        navigateToSettings()
app/src/test/java/com/yorvana/ui/util/ViewModelFactoryTest.kt:25:import com.yorvana.ui.settings.SettingsViewModel
app/src/test/java/com/yorvana/ui/util/ViewModelFactoryTest.kt:181:    fun `create SettingsViewModel returns instance`() {
app/src/test/java/com/yorvana/ui/util/ViewModelFactoryTest.kt:183:        val viewModel = factory.create(SettingsViewModel::class.java)
app/src/main/java/com/yorvana/ui/util/ViewModelFactory.kt:14:import com.yorvana.ui.settings.SettingsViewModel
app/src/main/java/com/yorvana/ui/util/ViewModelFactory.kt:74:                modelClass.isAssignableFrom(SettingsViewModel::class.java) -> {
app/src/main/java/com/yorvana/ui/util/ViewModelFactory.kt:75:                    SettingsViewModel(dependencies)
app/src/main/java/com/yorvana/ui/navigation/Screen.kt:22:@Serializable object Settings : NavKey
app/src/main/java/com/yorvana/ui/navigation/AppNavGraph.kt:77:import com.yorvana.ui.settings.SettingsScreen
app/src/main/java/com/yorvana/ui/navigation/AppNavGraph.kt:168:                    entry<Settings> {
app/src/main/java/com/yorvana/ui/navigation/AppNavGraph.kt:170:                            SettingsScreen(backStack = backStack)
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:32:data class SettingsState(
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:52:sealed class SettingsEvent {
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:53:    data object OpenCategories : SettingsEvent()
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:55:    data object OpenReportBug : SettingsEvent()
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:57:    data object OpenContact : SettingsEvent()
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:59:    data object OpenFileManager : SettingsEvent()
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:61:    data class VaultFolderPicked(val uri: Uri) : SettingsEvent()
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:63:    data object MoveVault : SettingsEvent()
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:65:    data object StartFresh : SettingsEvent()
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:67:    data object DismissMoveDialog : SettingsEvent()
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:69:    data object DismissConflictDialog : SettingsEvent()
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:71:    data object DismissUseExistingVaultDialog : SettingsEvent()
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:73:    data class OdometerUnitChanged(val unit: OdometerUnit) : SettingsEvent()
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:75:    data class CurrencyChanged(val currency: String) : SettingsEvent()
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:77:    data object RequestUpgrade : SettingsEvent()
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:79:    data object RestorePurchases : SettingsEvent()
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:81:    data object SimulatePurchaseSuccess : SettingsEvent()
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:83:    data object ResetBillingState : SettingsEvent()
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:85:    data class SetDebugOverride(val mode: DebugBillingOverrideMode) : SettingsEvent()
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:87:    data class CrashReportingToggled(val enabled: Boolean) : SettingsEvent()
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:90:sealed class SettingsEffect {
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:91:    data object NavigateToCategories : SettingsEffect()
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:93:    data object NavigateToReportBug : SettingsEffect()
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:98:    ) : SettingsEffect()
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:100:    data class LaunchFileManager(val vaultUriString: String) : SettingsEffect()
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:102:    data class ShowSnackbar(val message: String) : SettingsEffect()
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:104:    data object LaunchPurchaseFlow : SettingsEffect()
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:108: * SettingsViewModel manages vault selection, preferences, and billing actions.
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:111: * - `_state` (`MutableStateFlow<SettingsState>`) holds billing/internal fields (isPremium,
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:114: *   `initialValue = SettingsState()` when there is no active subscriber.
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:119: * This distinction applies to every field added to [SettingsState] in the future.
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:121:class SettingsViewModel(
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:128:    private val _state = MutableStateFlow(SettingsState())
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:129:    val state: StateFlow<SettingsState> =
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:144:            initialValue = SettingsState(),
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:149:    private val _effects = Channel<SettingsEffect>(Channel.BUFFERED)
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:174:            Log.w("SettingsViewModel", "Could not get app version", e)
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:180:    fun onEvent(event: SettingsEvent) {
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:182:            is SettingsEvent.VaultFolderPicked -> handleVaultPicked(event.uri)
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:183:            is SettingsEvent.OdometerUnitChanged ->
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:185:            is SettingsEvent.CurrencyChanged -> {
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:193:            SettingsEvent.MoveVault -> moveVault()
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:194:            SettingsEvent.StartFresh -> startFresh()
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:195:            SettingsEvent.DismissMoveDialog -> _state.update { it.copy(showMoveOrFreshDialog = false, pendingNewUri = null) }
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:196:            SettingsEvent.DismissConflictDialog -> _state.update { it.copy(showConflictDialog = false) }
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:197:            SettingsEvent.DismissUseExistingVaultDialog ->
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:204:            SettingsEvent.OpenCategories -> {
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:205:                viewModelScope.launch { _effects.send(SettingsEffect.NavigateToCategories) }
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:207:            SettingsEvent.OpenReportBug -> {
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:208:                viewModelScope.launch { _effects.send(SettingsEffect.NavigateToReportBug) }
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:210:            SettingsEvent.OpenContact -> {
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:213:                        SettingsEffect.LaunchContactEmail(
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:220:            SettingsEvent.OpenFileManager -> {
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:223:                    _effects.send(SettingsEffect.LaunchFileManager(uriString))
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:226:            SettingsEvent.RequestUpgrade ->
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:228:                    viewModelScope.launch { _effects.send(SettingsEffect.LaunchPurchaseFlow) }
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:230:            SettingsEvent.RestorePurchases -> restorePurchases()
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:231:            SettingsEvent.SimulatePurchaseSuccess -> handleSimulatePurchaseSuccess()
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:232:            SettingsEvent.ResetBillingState -> handleResetBillingState()
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:233:            is SettingsEvent.SetDebugOverride -> handleSetDebugOverride(event.mode)
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:234:            is SettingsEvent.CrashReportingToggled -> handleCrashReportingToggled(event.enabled)
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:242:                _effects.send(SettingsEffect.ShowSnackbar(app.getString(R.string.settings_debug_purchase_success)))
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:251:                _effects.send(SettingsEffect.ShowSnackbar(app.getString(R.string.settings_debug_billing_reset)))
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:260:            Log.w("SettingsViewModel", "SetDebugOverride called in non-debug build")
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:296:                _effects.send(SettingsEffect.ShowSnackbar(message))
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:300:                Log.e("SettingsViewModel", "restorePurchases failed", e)
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:302:                _effects.send(SettingsEffect.ShowSnackbar(app.getString(R.string.billing_error, errorSuffix)))
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:345:                _effects.send(SettingsEffect.ShowSnackbar(app.getString(R.string.settings_vault_changed_success)))
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:351:                    _effects.send(SettingsEffect.ShowSnackbar(app.getString(R.string.settings_vault_move_error, e.message ?: "")))
app/src/main/java/com/yorvana/ui/settings/SettingsViewModel.kt:362:            _effects.send(SettingsEffect.ShowSnackbar(app.getString(R.string.settings_vault_changed_success)))
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:95:fun SettingsScreen(
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:97:    viewModel: SettingsViewModel =
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:128:            viewModel.onEvent(SettingsEvent.VaultFolderPicked(uri))
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:134:                SettingsEffect.NavigateToCategories ->
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:136:                SettingsEffect.NavigateToReportBug ->
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:138:                is SettingsEffect.LaunchContactEmail -> {
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:150:                is SettingsEffect.ShowSnackbar ->
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:152:                is SettingsEffect.LaunchFileManager -> {
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:170:                SettingsEffect.LaunchPurchaseFlow -> {
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:179:            onDismissRequest = { viewModel.onEvent(SettingsEvent.DismissMoveDialog) },
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:183:                TextButton(onClick = { viewModel.onEvent(SettingsEvent.MoveVault) }) {
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:189:                    TextButton(onClick = { viewModel.onEvent(SettingsEvent.StartFresh) }) {
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:192:                    TextButton(onClick = { viewModel.onEvent(SettingsEvent.DismissMoveDialog) }) {
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:216:            onDismissRequest = { viewModel.onEvent(SettingsEvent.DismissUseExistingVaultDialog) },
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:220:                TextButton(onClick = { viewModel.onEvent(SettingsEvent.StartFresh) }) {
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:225:                TextButton(onClick = { viewModel.onEvent(SettingsEvent.DismissUseExistingVaultDialog) }) {
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:234:            onDismissRequest = { viewModel.onEvent(SettingsEvent.DismissConflictDialog) },
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:238:                TextButton(onClick = { viewModel.onEvent(SettingsEvent.DismissConflictDialog) }) {
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:251:                viewModel.onEvent(SettingsEvent.OdometerUnitChanged(unit))
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:262:                viewModel.onEvent(SettingsEvent.CurrencyChanged(currency))
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:276:                viewModel.onEvent(SettingsEvent.CurrencyChanged(currency))
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:374:                        modifier = Modifier.clickable { viewModel.onEvent(SettingsEvent.OpenFileManager) },
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:449:                    modifier = Modifier.clickable { viewModel.onEvent(SettingsEvent.OpenCategories) },
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:516:                        modifier = Modifier.clickable { viewModel.onEvent(SettingsEvent.RequestUpgrade) },
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:542:                            viewModel.onEvent(SettingsEvent.RestorePurchases)
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:577:                                        .clickable { viewModel.onEvent(SettingsEvent.SetDebugOverride(mode)) }
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:582:                                    onClick = { viewModel.onEvent(SettingsEvent.SetDebugOverride(mode)) },
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:589:                            onClick = { viewModel.onEvent(SettingsEvent.SimulatePurchaseSuccess) },
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:595:                            onClick = { viewModel.onEvent(SettingsEvent.ResetBillingState) },
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:676:                                onCheckedChange = { viewModel.onEvent(SettingsEvent.CrashReportingToggled(it)) },
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:717:                    modifier = Modifier.clickable { viewModel.onEvent(SettingsEvent.OpenContact) },
app/src/main/java/com/yorvana/ui/settings/SettingsScreen.kt:738:                    modifier = Modifier.clickable { viewModel.onEvent(SettingsEvent.OpenReportBug) },
app/src/main/res/values/strings.xml:81:    <!-- Settings -->
app/src/main/res/values/strings.xml:82:    <string name="settings_title">Settings</string>
app/src/main/res/values/strings.xml:214:    <!-- Settings Developer Panel -->
.github/workflows/baseline-reminder.yml:37:            echo './gradlew generateGmdCoverage'
.github/workflows/baseline-reminder.yml:38:            echo 'git add app/coverage-baselines/gmd_smoke.ec'
app/src/test/java/com/yorvana/ui/settings/SettingsScreenIT.kt:25:class SettingsScreenIT {
app/src/test/java/com/yorvana/ui/settings/SettingsScreenIT.kt:31:        val mockViewModel = mockk<SettingsViewModel>(relaxed = true)
app/src/test/java/com/yorvana/ui/settings/SettingsScreenIT.kt:34:                SettingsState(
app/src/test/java/com/yorvana/ui/settings/SettingsScreenIT.kt:46:            SettingsScreen(
app/src/test/java/com/yorvana/ui/settings/SettingsScreenIT.kt:69:        val mockViewModel = mockk<SettingsViewModel>(relaxed = true)
app/src/test/java/com/yorvana/ui/settings/SettingsScreenIT.kt:72:                SettingsState(
app/src/test/java/com/yorvana/ui/settings/SettingsScreenIT.kt:84:            SettingsScreen(
app/src/test/java/com/yorvana/ui/settings/SettingsScreenIT.kt:94:        verify { mockViewModel.onEvent(SettingsEvent.OpenCategories) }
app/src/test/java/com/yorvana/ui/settings/SettingsScreenIT.kt:99:        val mockViewModel = mockk<SettingsViewModel>(relaxed = true)
app/src/test/java/com/yorvana/ui/settings/SettingsScreenIT.kt:102:                SettingsState(
app/src/test/java/com/yorvana/ui/settings/SettingsScreenIT.kt:114:            SettingsScreen(
app/src/test/java/com/yorvana/ui/settings/SettingsScreenIT.kt:122:        verify { mockViewModel.onEvent(SettingsEvent.OpenContact) }
app/src/test/java/com/yorvana/ui/settings/SettingsScreenIT.kt:127:        val mockViewModel = mockk<SettingsViewModel>(relaxed = true)
app/src/test/java/com/yorvana/ui/settings/SettingsScreenIT.kt:130:                SettingsState(
app/src/test/java/com/yorvana/ui/settings/SettingsScreenIT.kt:140:            SettingsScreen(
app/src/test/java/com/yorvana/ui/settings/SettingsScreenIT.kt:154:        verify { mockViewModel.onEvent(SettingsEvent.DismissConflictDialog) }
app/src/test/java/com/yorvana/ui/settings/SettingsScreenIT.kt:159:        val mockViewModel = mockk<SettingsViewModel>(relaxed = true)
app/src/test/java/com/yorvana/ui/settings/SettingsScreenIT.kt:162:                SettingsState(isValidating = true),
app/src/test/java/com/yorvana/ui/settings/SettingsScreenIT.kt:167:            SettingsScreen(
app/src/test/java/com/yorvana/ui/settings/SettingsScreenIT.kt:178:        val mockViewModel = mockk<SettingsViewModel>(relaxed = true)
app/src/test/java/com/yorvana/ui/settings/SettingsScreenIT.kt:181:                SettingsState(showUseExistingVaultDialog = true),
app/src/test/java/com/yorvana/ui/settings/SettingsScreenIT.kt:186:            SettingsScreen(
app/src/test/java/com/yorvana/ui/settings/SettingsScreenIT.kt:195:        verify { mockViewModel.onEvent(SettingsEvent.StartFresh) }
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:45:class SettingsViewModelTest {
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:49:    private lateinit var viewModel: SettingsViewModel
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:73:        // Setup PackageManager mocks because SettingsViewModel reads the app version name on init.
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:102:        SettingsViewModel(
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:134:            viewModel.onEvent(SettingsEvent.OdometerUnitChanged(OdometerUnit.MI))
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:145:                viewModel.onEvent(SettingsEvent.OpenCategories)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:146:                assertThat(awaitItem()).isEqualTo(SettingsEffect.NavigateToCategories)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:157:                viewModel.onEvent(SettingsEvent.OpenContact)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:160:                        SettingsEffect.LaunchContactEmail(
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:176:                viewModel.onEvent(SettingsEvent.RequestUpgrade)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:177:                assertThat(awaitItem()).isEqualTo(SettingsEffect.LaunchPurchaseFlow)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:190:                viewModel.onEvent(SettingsEvent.RequestUpgrade)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:201:            viewModel.onEvent(SettingsEvent.CurrencyChanged("EUR"))
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:222:                    viewModel.onEvent(SettingsEvent.OpenFileManager)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:224:                    assertThat(effect).isInstanceOf(SettingsEffect.LaunchFileManager::class.java)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:236:                viewModel.onEvent(SettingsEvent.RequestUpgrade)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:237:                assertThat(awaitItem()).isEqualTo(SettingsEffect.LaunchPurchaseFlow)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:250:                viewModel.onEvent(SettingsEvent.RestorePurchases)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:252:                assertThat(effect).isInstanceOf(SettingsEffect.ShowSnackbar::class.java)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:253:                assertThat((effect as SettingsEffect.ShowSnackbar).message).isEqualTo("Purchase restored successfully")
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:266:                viewModel.onEvent(SettingsEvent.RestorePurchases)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:268:                assertThat(effect).isInstanceOf(SettingsEffect.ShowSnackbar::class.java)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:269:                assertThat((effect as SettingsEffect.ShowSnackbar).message).isEqualTo("No previous purchases found")
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:282:                viewModel.onEvent(SettingsEvent.RestorePurchases)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:284:                assertThat(effect).isInstanceOf(SettingsEffect.ShowSnackbar::class.java)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:285:                assertThat((effect as SettingsEffect.ShowSnackbar).message).isEqualTo("Restore failed: billing unavailable")
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:298:                viewModel.onEvent(SettingsEvent.RestorePurchases)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:300:                assertThat(effect).isInstanceOf(SettingsEffect.ShowSnackbar::class.java)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:301:                assertThat((effect as SettingsEffect.ShowSnackbar).message).isEqualTo("Restore failed (code 3)")
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:314:            viewModel.onEvent(SettingsEvent.RestorePurchases)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:330:            viewModel.onEvent(SettingsEvent.RestorePurchases)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:334:            viewModel.onEvent(SettingsEvent.RestorePurchases)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:386:                SettingsViewModel(
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:399:                vm.onEvent(SettingsEvent.RestorePurchases)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:401:                assertThat(effect).isEqualTo(SettingsEffect.ShowSnackbar("Purchase failed: SDK error"))
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:412:            viewModel.onEvent(SettingsEvent.SetDebugOverride(DebugBillingOverrideMode.FORCE_PREMIUM))
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:422:            viewModel.onEvent(SettingsEvent.CrashReportingToggled(true))
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:432:            viewModel.onEvent(SettingsEvent.CrashReportingToggled(false))
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:443:                viewModel.onEvent(SettingsEvent.SimulatePurchaseSuccess)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:446:                assertThat(effect).isInstanceOf(SettingsEffect.ShowSnackbar::class.java)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:447:                assertThat((effect as SettingsEffect.ShowSnackbar).message).isEqualTo("Simulated purchase success")
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:475:                viewModel.onEvent(SettingsEvent.ResetBillingState)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:478:                assertThat(effect).isInstanceOf(SettingsEffect.ShowSnackbar::class.java)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelTest.kt:479:                assertThat((effect as SettingsEffect.ShowSnackbar).message).isEqualTo("Billing state reset")
app/src/test/java/com/yorvana/ui/settings/SettingsScreenshotTest.kt:22:class SettingsScreenshotTest : BaseScreenshotTest() {
app/src/test/java/com/yorvana/ui/settings/SettingsScreenshotTest.kt:34:        val mockViewModel = mockk<SettingsViewModel>(relaxed = true)
app/src/test/java/com/yorvana/ui/settings/SettingsScreenshotTest.kt:37:                SettingsState(
app/src/test/java/com/yorvana/ui/settings/SettingsScreenshotTest.kt:53:                SettingsScreen(
app/src/test/java/com/yorvana/ui/settings/SettingsScreenshotTest.kt:64:        composeTestRule.onRoot().captureScreen("SettingsScreen_light")
app/src/test/java/com/yorvana/ui/settings/SettingsScreenshotTest.kt:70:        composeTestRule.onRoot().captureScreen("SettingsScreen_dark")
app/src/test/java/com/yorvana/ui/settings/SettingsScreenshotTest.kt:76:        composeTestRule.onRoot().captureScreen("SettingsScreen_premium_light")
app/src/test/java/com/yorvana/ui/settings/SettingsScreenshotTest.kt:82:        composeTestRule.onRoot().captureScreen("SettingsScreen_premium_dark")
app/src/test/java/com/yorvana/ui/settings/SettingsScreenshotTest.kt:88:        captureFull("SettingsScreen_conflict_light")
app/src/test/java/com/yorvana/ui/settings/SettingsScreenshotTest.kt:94:        captureFull("SettingsScreen_validating_light")
app/src/test/java/com/yorvana/ui/settings/SettingsScreenshotTest.kt:100:        captureFull("SettingsScreen_existing_vault_light")
app/src/test/java/com/yorvana/ui/settings/SettingsScreenshotTest.kt:106:        composeTestRule.onRoot().captureScreen("SettingsScreen_crash_reporting_on_light")
app/src/test/java/com/yorvana/ui/settings/SettingsScreenshotTest.kt:114:        captureFull("SettingsScreen_privacy_dialog")
app/src/test/java/com/yorvana/ui/settings/SettingsScreenshotTest.kt:123:        captureFull("SettingsScreen_privacy_section_light")
app/src/test/java/com/yorvana/ui/settings/SettingsScreenshotTest.kt:133:        captureFull("SettingsScreen_debug_crash_section_light")
app/src/test/java/com/yorvana/ui/settings/SettingsScreenshotTest.kt:143:        captureFull("SettingsScreen_debug_crash_section_dark")
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelIT.kt:48:class SettingsViewModelIT {
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelIT.kt:55:    private lateinit var viewModel: SettingsViewModel
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelIT.kt:96:                SettingsViewModel(
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelIT.kt:112:                viewModel.onEvent(SettingsEvent.VaultFolderPicked(mockUri))
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelIT.kt:120:                viewModel.onEvent(SettingsEvent.MoveVault)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelIT.kt:141:                SettingsViewModel(
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelIT.kt:156:                viewModel.onEvent(SettingsEvent.VaultFolderPicked(mockUri))
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelIT.kt:163:                viewModel.onEvent(SettingsEvent.StartFresh)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelIT.kt:183:                SettingsViewModel(
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelIT.kt:199:                viewModel.onEvent(SettingsEvent.VaultFolderPicked(mockUri))
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelIT.kt:204:                viewModel.onEvent(SettingsEvent.DismissMoveDialog)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelIT.kt:215:                viewModel.onEvent(SettingsEvent.VaultFolderPicked(mockUri))
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelIT.kt:219:                viewModel.onEvent(SettingsEvent.DismissConflictDialog)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelIT.kt:227:                viewModel.onEvent(SettingsEvent.VaultFolderPicked(mockUri))
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelIT.kt:231:                viewModel.onEvent(SettingsEvent.DismissUseExistingVaultDialog)
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelIT.kt:250:                SettingsViewModel(
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelIT.kt:265:                viewModel.onEvent(SettingsEvent.VaultFolderPicked(newUri))
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelIT.kt:285:                SettingsViewModel(
app/src/test/java/com/yorvana/ui/settings/SettingsViewModelIT.kt:300:                viewModel.onEvent(SettingsEvent.VaultFolderPicked(newUri))
app/src/test/java/com/yorvana/ui/vehicles/VehicleListViewModelTest.kt:332:    fun `onEvent OpenSettings should emit NavigateToSettings effect`() =
app/src/test/java/com/yorvana/ui/vehicles/VehicleListViewModelTest.kt:337:                viewModel.onEvent(VehicleListEvent.OpenSettings)
app/src/test/java/com/yorvana/ui/vehicles/VehicleListViewModelTest.kt:338:                assertThat(awaitItem()).isEqualTo(VehicleListEffect.NavigateToSettings)


Output:
Chunk ID: 7462c7
Wall time: 0.2780 seconds
Process exited with code 0
Original token count: 4
Output:
gmd_smoke.ec


Output:
Chunk ID: bd3658
Wall time: 0.2526 seconds
Process exited with code 0
Original token count: 14
Output:
## add-settings-contact...origin/add-settings-contact


The smoke test does navigate through Settings, so the coverage reminder is plausibly applicable. I’m going to run the repo’s baseline generation task and only commit it if the baseline file actually changes.


Output:
Chunk ID: 310c32
Wall time: 0.2050 seconds
Process exited with code 0
Original token count: 293
Output:
detekt {
    config.setFrom(rootProject.file("config/detekt/detekt.yml"))
    buildUponDefaultConfig = true
    autoCorrect = true
}

tasks.named("check") {
    dependsOn("lintDebug")
}

tasks.register<Copy>("generateGmdCoverage") {
    group = "Verification"
    description = "Runs GMD tests and copies the coverage file to the baseline directory."

    dependsOn("pixel2api33DebugAndroidTest")

    from(layout.buildDirectory.dir("outputs/managed_device_code_coverage/debug/pixel2api33")) {
        include("coverage.ec")
    }
    into(layout.projectDirectory.dir("coverage-baselines"))
    rename { "gmd_smoke.ec" }

    includeEmptyDirs = false
    duplicatesStrategy = DuplicatesStrategy.FAIL

    doLast {
        val destFile = layout.projectDirectory.file("coverage-baselines/gmd_smoke.ec").asFile
        if (!destFile.exists()) {
            throw GradleException("Failed to generate GMD coverage. Expected file not found: $destFile")
        }
    }
}

tasks.register<JacocoReport>("verifyWithCoverage") {
    group = "Verification"
    description = "Runs JVM unit tests and generates a combined coverage report using JaCoCo with the static GMD baseline."