mirror of
https://github.com/KRTirtho/spotube.git
synced 2026-08-05 19:59:51 +00:00
166 lines
6.9 KiB
Markdown
166 lines
6.9 KiB
Markdown
---
|
|
name: verifying_compose_ui
|
|
description: >
|
|
Visually verifies Compose UI components by rendering @Composable/@Preview functions to images from the project's JVM runtime;
|
|
STRONGLY PREFERRED for rapid UI iteration and visual feedback on any composable.
|
|
Do NOT use for build lifecycle tasks or dependency auditing.
|
|
license: Apache-2.0
|
|
metadata:
|
|
author: https://github.com/rnett/gradle-mcp
|
|
version: "2.2"
|
|
---
|
|
|
|
## ⚠️ FUNDAMENTAL ANDROID LIMITATION
|
|
|
|
**IMPORTANT: `runComposeUiTest` and image capture methods (`node.captureToImage()`) are NOT supported on Android and CANNOT work.**
|
|
|
|
### Why This Cannot Work
|
|
|
|
The `runComposeUiTest` function requires a JVM-based test runtime with desktop Compose rendering (via Skiko on JVM/Desktop). Android's ART (Android Runtime) does not support the desktop Compose testing APIs, and image capture via
|
|
`captureToImage()` relies on desktop-specific rendering pipelines that are fundamentally incompatible with Android.
|
|
|
|
### The Solution: Use a JVM Target
|
|
|
|
**For visual verification of Composables, you MUST use a JVM or Desktop target source set.** This is not a workaround—it is the only supported method.
|
|
|
|
Recommended approach:
|
|
|
|
1. **Put your Composables in a common source set** (`commonMain`) that is shared across all targets
|
|
2. **Create or use a JVM target** (e.g., `jvmMain`, `desktopMain`) that depends on `commonMain`
|
|
3. **Run the REPL on the JVM target** (`sourceSet: "jvmMain"` or `sourceSet: "jvmTest"`)
|
|
|
|
This is the standard KMP pattern and allows you to verify your UI code without needing an Android device or emulator.
|
|
|
|
### What WILL NOT Work
|
|
|
|
- ❌ Running the REPL with `sourceSet: "androidMain"`
|
|
- ❌ Running the REPL with `sourceSet: "androidTest"`
|
|
- ❌ Any attempt to use `runComposeUiTest` on Android
|
|
- ❌ Any attempt to use `captureToImage()` on Android
|
|
|
|
### What WILL Work
|
|
|
|
- ✅ Running the REPL with `sourceSet: "jvmMain"` or `sourceSet: "jvmTest"`
|
|
- ✅ Running the REPL with `sourceSet: "desktopMain"` or `sourceSet: "desktopTest"`
|
|
- ✅ Using `runComposeUiTest` with `captureToImage()` on JVM/Desktop targets
|
|
|
|
---
|
|
|
|
# Authoritative Compose UI Preview & Visual Verification
|
|
|
|
Visually verifies and renders any @Composable or @Preview directly to high-quality images from the project-aware REPL for instant, authoritative visual feedback.
|
|
|
|
## Constitution
|
|
|
|
- **ALWAYS** use `kotlin_repl` to render Compose components instead of running the full application for visual checks.
|
|
- **ALWAYS** provide absolute paths for `projectRoot`.
|
|
- **ALWAYS** use `node.captureToImage()` and `responder.render(bitmap)` to return the visual output.
|
|
- **ALWAYS** ensure the correct Compose UI testing dependencies are on the classpath, using `additionalDependencies` if necessary.
|
|
- **NEVER** assume a UI component renders correctly without visual verification.
|
|
- **ALWAYS** search for existing `@Preview` functions in the project source code before creating new ones.
|
|
|
|
## Directives
|
|
|
|
- **ALWAYS provide absolute `projectRoot`**: Ensure `projectRoot` is an **absolute file system path** for all `kotlin_repl` calls.
|
|
- **Ensure dependencies**: ALWAYS ensure Compose UI testing dependencies (e.g., `androidx.compose.ui:ui-test-junit4`) are on the classpath.
|
|
- **Note on versions**: ALWAYS check your project's version catalog and existing tests for the correct imports for `runComposeUiTest`.
|
|
- **Render as image**: ALWAYS use `node.captureToImage()` and `responder.render(bitmap)` to return the visual output.
|
|
- **Kotlin Multiplatform (KMP) Note**: The `kotlin_repl` currently only supports **JVM-based** source sets. ALWAYS select a JVM or Desktop target source set for visual checks.
|
|
- **Use `envSource: SHELL` if environment variables are missing**: Set `env: { envSource: "SHELL" }` (REPL start) or `invocationArguments: { envSource: "SHELL" }` (Gradle tasks) if expected env vars (e.g., `JAVA_HOME`) are not found.
|
|
|
|
## When to Use
|
|
|
|
- **Rapid UI Prototyping & Iteration**: When you need to see the visual result of a Composable change instantly without the latency of a full application launch.
|
|
- **Authoritative @Preview Verification**: When you want to verify the visual correctness of existing `@Preview` functions.
|
|
- **Complex UI State & Interaction Testing**: When you need to capture visual state before and after interactions (like clicks or state changes).
|
|
- **Multi-Configuration Visual Auditing**: When checking how a component renders across different data states or configurations (e.g., different view models or mock data).
|
|
|
|
## Workflows
|
|
|
|
### 1. Identifying the Component
|
|
|
|
1. Find the fully qualified name of the `@Composable` or `@Preview` function.
|
|
2. Search for existing previews in the source code via `grep_search(pattern="@Preview")`.
|
|
|
|
### 2. Orchestrating the Session
|
|
|
|
1. Start the REPL with the `test` source set (preferred) or `main` with `additionalDependencies`.
|
|
2. Use `kotlin_repl(command="start")`.
|
|
3. Use `kotlin_repl(command="run")` to execute the rendering script.
|
|
|
|
### 3. Rendering & Verifying
|
|
|
|
1. Execute a script that uses `runComposeUiTest` to render and capture the component.
|
|
2. Inspect the returned image for visual correctness.
|
|
|
|
## Examples
|
|
|
|
### Viewing a simple Composable
|
|
|
|
```kotlin
|
|
import androidx.compose.ui.test.*
|
|
import com.example.ui.MyButton
|
|
|
|
runComposeUiTest {
|
|
setContent {
|
|
MyButton(text = "Click Me")
|
|
}
|
|
val node = onRoot()
|
|
responder.render(node.captureToImage())
|
|
}
|
|
// Reasoning: Using kotlin_repl to render a specific component and retrieve its visual representation via the responder API.
|
|
```
|
|
|
|
### Viewing an existing @Preview
|
|
|
|
```kotlin
|
|
import androidx.compose.ui.test.*
|
|
import com.example.ui.MyButtonPreview // Top-level preview function
|
|
|
|
runComposeUiTest {
|
|
setContent {
|
|
MyButtonPreview()
|
|
}
|
|
val node = onRoot()
|
|
responder.render(node.captureToImage())
|
|
}
|
|
// Reasoning: Reusing an existing authoritative preview function to verify its visual correctness.
|
|
```
|
|
|
|
### Capturing State Transitions
|
|
|
|
```kotlin
|
|
import androidx.compose.ui.test.*
|
|
import com.example.ui.MyCounter
|
|
import com.example.viewmodel.MyViewModel
|
|
|
|
runComposeUiTest {
|
|
val viewModel = MyViewModel()
|
|
setContent {
|
|
MyCounter(viewModel)
|
|
}
|
|
|
|
// Capture state before interaction
|
|
responder.render("State before: ${viewModel.count}")
|
|
responder.render(onRoot().captureToImage())
|
|
|
|
// Perform interaction
|
|
onNodeWithText("Increment").performClick()
|
|
|
|
// Capture state after interaction
|
|
responder.render("State after: ${viewModel.count}")
|
|
responder.render(onRoot().captureToImage())
|
|
}
|
|
// Reasoning: Capturing visual snapshots before and after an interaction to verify state-dependent UI changes.
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
- **No Image Returned**: Ensure you are calling `responder.render(bitmap)`.
|
|
- **ClassNotFoundException**: Check if you have the correct imports and that the required testing dependencies are on the classpath.
|
|
- **Empty Image**: If the Composable is empty or has zero size, the image will be empty. Verify your Composable's modifiers.
|
|
|
|
## Resources
|
|
|
|
- [Troubleshooting]({baseDir}/references/troubleshooting.md)
|