diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3983ef8..1389178 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,7 +11,6 @@ jobs: name: Android E2E (Maestro) runs-on: ubuntu-latest timeout-minutes: 20 - needs: test steps: - name: Free disk space uses: jlumbroso/free-disk-space@v1.3.1 @@ -77,6 +76,7 @@ jobs: test: name: Run tests runs-on: ubuntu-latest + needs: test-android-e2e steps: - name: Checkout uses: actions/checkout@v4 @@ -103,7 +103,6 @@ jobs: name: Desktop smoke runs-on: ubuntu-latest # Own runner so HOME/config/temp are not shared with jvmTest or Maestro. - needs: test steps: - name: Checkout uses: actions/checkout@v4 @@ -129,18 +128,21 @@ jobs: Xvfb :99 -screen 0 1024x768x24 & DISPLAY=:99 ./gradlew :shared:jvmSmokeTest - - name: Upload smoke test reports + - name: Upload smoke test artifacts uses: actions/upload-artifact@v4 - if: always() + if: failure() with: - name: smoke-test-reports - path: "**/build/reports/tests/jvmSmokeTest/" + name: smoke-test-artifacts + path: | + **/build/reports/tests/jvmSmokeTest/ + **/build/jvmSmokeTest-screenshots/ if-no-files-found: ignore + retention-days: 3 build-android: name: Build Android runs-on: ubuntu-latest - needs: test-android-e2e + needs: test steps: - name: Checkout uses: actions/checkout@v4 @@ -176,7 +178,7 @@ jobs: build-desktop-macos: name: Build Desktop macOS runs-on: macos-latest - needs: test-desktop-smoke + needs: [test, test-desktop-smoke] steps: - name: Checkout uses: actions/checkout@v4 @@ -197,7 +199,7 @@ jobs: build-desktop-windows: name: Build Desktop Windows runs-on: windows-latest - needs: test-desktop-smoke + needs: [test, test-desktop-smoke] steps: - name: Checkout uses: actions/checkout@v4 @@ -218,7 +220,7 @@ jobs: build-desktop-linux: name: Build Desktop Linux runs-on: ubuntu-latest - needs: test-desktop-smoke + needs: [test, test-desktop-smoke] steps: - name: Checkout uses: actions/checkout@v4 diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index 28855df..c2036ef 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -221,11 +221,18 @@ tasks.register("jvmSmokeTest") { // Isolated work/home/temp so smoke never reuses prefs/library from jvmTest or prior runs. val smokeRoot = layout.buildDirectory.dir("jvmSmokeTest-env") + val smokeScreenshotsDir = layout.buildDirectory.dir("jvmSmokeTest-screenshots") doFirst { val root = smokeRoot.get().asFile root.deleteRecursively() listOf("home", "config", "tmp", "work").forEach { File(root, it).mkdirs() } + smokeScreenshotsDir.get().asFile.deleteRecursively() + smokeScreenshotsDir.get().asFile.mkdirs() } + systemProperty( + "btt.writer.smoke.screenshots.dir", + smokeScreenshotsDir.map { it.asFile.absolutePath }.get(), + ) workingDir = smokeRoot.map { it.dir("work") }.get().asFile systemProperty("java.io.tmpdir", smokeRoot.map { it.dir("tmp").asFile.absolutePath }.get()) environment("HOME", smokeRoot.map { it.dir("home").asFile.absolutePath }.get()) diff --git a/shared/src/jvmTest/kotlin/org/bibletranslationtools/writer/uitest/SmokeFlow.kt b/shared/src/jvmTest/kotlin/org/bibletranslationtools/writer/uitest/SmokeFlow.kt index 92f6c8b..032a47c 100644 --- a/shared/src/jvmTest/kotlin/org/bibletranslationtools/writer/uitest/SmokeFlow.kt +++ b/shared/src/jvmTest/kotlin/org/bibletranslationtools/writer/uitest/SmokeFlow.kt @@ -41,13 +41,16 @@ fun ComposeUiTest.completeSmokeSettings() { onNodeWithText("I Agree").performClick() waitUntilVisible("Your Translation Projects", timeoutMillis = 3_000) + takeSmokeScreenshot("smoke-settings/projects-home") onNodeWithContentDescription("More Options").performClick() onNodeWithText("Settings").performClick() onNodeWithText("General").assertIsDisplayed() + takeSmokeScreenshot("smoke-settings/settings-general") onNodeWithContentDescription("back").performClick() - waitUntilVisible("Your Translation Projects", timeoutMillis = 3_000) + waitUntilVisible("Your Translation Projects", timeoutMillis = 5_000) + takeSmokeScreenshot("smoke-settings/projects-home-after-settings") } @OptIn(ExperimentalTestApi::class) diff --git a/shared/src/jvmTest/kotlin/org/bibletranslationtools/writer/uitest/SmokeScreenshots.kt b/shared/src/jvmTest/kotlin/org/bibletranslationtools/writer/uitest/SmokeScreenshots.kt new file mode 100644 index 0000000..a5b9024 --- /dev/null +++ b/shared/src/jvmTest/kotlin/org/bibletranslationtools/writer/uitest/SmokeScreenshots.kt @@ -0,0 +1,30 @@ +package org.bibletranslationtools.writer.uitest + +import androidx.compose.ui.graphics.asSkiaBitmap +import androidx.compose.ui.test.ComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.captureToImage +import androidx.compose.ui.test.onRoot +import org.jetbrains.skia.EncodedImageFormat +import org.jetbrains.skia.Image +import java.io.File + +private val screenshotRoot: File by lazy { + File( + System.getProperty("btt.writer.smoke.screenshots.dir") + ?: System.getenv("BTT_WRITER_SMOKE_SCREENSHOTS_DIR") + ?: "build/smoke-screenshots", + ).also { it.mkdirs() } +} + +@OptIn(ExperimentalTestApi::class) +fun ComposeUiTest.takeSmokeScreenshot(name: String) { + waitForIdle() + val pngBytes = Image.makeFromBitmap(onRoot().captureToImage().asSkiaBitmap()) + .encodeToData(EncodedImageFormat.PNG) + ?.bytes + ?: error("Failed to encode screenshot as PNG: $name") + val file = File(screenshotRoot, "$name.png") + file.parentFile?.mkdirs() + file.writeBytes(pngBytes) +}