mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[JEWEL-1390] Add Spectre and the standalone headful test lane
Declare Spectre in jewel_deps.MODULE.bazel rather than in lib, and expose it through the testonly //platform/jewel:spectre target. Bazel then refuses to let any production target reach it, so it cannot end up in the IDE or in a published artifact. Add a spectre_test macro that runs the JUnit Platform console launcher directly. jps_test is unusable here twice over: it forces -Djava.awt.headless=true, and it puts the IntelliJ test runtime on the classpath, which would hide exactly the standalone-runtime leaks these tests exist to catch. StandaloneRuntimeSmokeTest now asserts that property instead of leaving it to a reviewer's word: com.intellij classes are barred from the lane apart from the icons API, which standalone Jewel depends on deliberately. Spectre targets are ordinary test targets, tagged requires-display: they run under `bazel test //platform/jewel/...` on any machine with a display, and a lane that has none opts out with --test_tag_filters=-requires-display. Two CI jobs run them, on Linux under Xvfb and on Windows, both selecting by tag so new targets join without a workflow change. The internal TeamCity/Patronus lanes should route on the same requires-display tag; nothing in this repository drives that config. Windows is not redundant: JDialogRenderer renders popups through RenderSettings.SwingGraphics there rather than Compose's default, so it is a different code path. Three things that are easy to get wrong, and were, each caught only by running on a real Linux or Windows machine: - Bazel scrubs the environment of test actions, so DISPLAY and XAUTHORITY have to be inherited explicitly. Without that the JVM falls back to :0.0 and every test dies in XToolkit's static initialiser under Xvfb, while passing on macOS. - Discovery has to be by package, which JUnit resolves through the class loader. A bare --scan-classpath scans only classpath directories and every entry here is a jar, while --scan-classpath=<jar path> assumes a runfiles symlink tree and finds nothing on Windows, where Bazel uses a runfiles manifest. --fail-if-no-tests turns either mistake into a red lane rather than a green one that ran nothing. - The X11 package list is what libawt_xawt and libskiko actually link against, plus libxrandr2 and libxinerama1, which they dlopen and which therefore no linker error would ever flag. The JEWEL-1396 popup tests are the first users of the lane. closes https://github.com/JetBrains/intellij-community/pull/3618 (cherry picked from commit df8e3747affaae3d6be8d6e78a4613d08f088020) IJ-MR-220560 GitOrigin-RevId: 42b78cda5b2200cb275ae18ce1cc2b0615e9389e
This commit is contained in:
committed by
intellij-monorepo-bot
parent
5552a03bb3
commit
c64d1cc386
@@ -214,6 +214,81 @@ jobs:
|
||||
fi
|
||||
echo "Bazel build files look up-to-date."
|
||||
|
||||
spectre_tests:
|
||||
name: Jewel Spectre tests
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: .
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v7.0.1
|
||||
name: Check out repository
|
||||
|
||||
- name: Install Xvfb
|
||||
# libxrandr2 and libxinerama1 are dlopened, so nothing reports them missing.
|
||||
# language=bash
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
xvfb \
|
||||
libxrender1 \
|
||||
libxtst6 \
|
||||
libxi6 \
|
||||
libxrandr2 \
|
||||
libxinerama1 \
|
||||
libgl1 \
|
||||
libfontconfig1
|
||||
|
||||
- name: Run the Spectre headful UI tests
|
||||
run: |
|
||||
xvfb-run --auto-servernum --server-args="-screen 0 1920x1080x24" \
|
||||
./bazel.cmd test //platform/jewel/... \
|
||||
--build_tests_only \
|
||||
--test_tag_filters=requires-display \
|
||||
--test_output=errors
|
||||
|
||||
- name: Upload Bazel test logs
|
||||
uses: actions/upload-artifact@v7.0.1
|
||||
if: failure()
|
||||
with:
|
||||
name: spectre-test-logs
|
||||
path: out/bazel-testlogs/platform/jewel/**
|
||||
retention-days: 7
|
||||
if-no-files-found: ignore
|
||||
|
||||
spectre_tests_windows:
|
||||
name: Jewel Spectre tests (Windows)
|
||||
runs-on: windows-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: .
|
||||
|
||||
steps:
|
||||
# Kotlin test data blows past MAX_PATH, so checkout fails with "Filename too long" without this.
|
||||
- name: Enable long paths
|
||||
run: git config --global core.longpaths true
|
||||
|
||||
- uses: actions/checkout@v7.0.1
|
||||
name: Check out repository
|
||||
|
||||
- name: Run the Spectre headful UI tests
|
||||
# Not redundant: JDialogRenderer uses RenderSettings.SwingGraphics on Windows.
|
||||
run: >
|
||||
./bazel.cmd test //platform/jewel/...
|
||||
--build_tests_only
|
||||
--test_tag_filters=requires-display
|
||||
--test_output=errors
|
||||
|
||||
- name: Upload Bazel test logs
|
||||
uses: actions/upload-artifact@v7.0.1
|
||||
if: failure()
|
||||
with:
|
||||
name: spectre-test-logs-windows
|
||||
path: out/bazel-testlogs/platform/jewel/**
|
||||
retention-days: 7
|
||||
if-no-files-found: ignore
|
||||
|
||||
metalava:
|
||||
name: Check for breaking API changes with Metalava
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
load("@rules_java//java:defs.bzl", "java_library")
|
||||
load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_import")
|
||||
|
||||
filegroup(
|
||||
name = "jewel_build_metadata",
|
||||
srcs = [
|
||||
"JEWEL_MARKER",
|
||||
"gradle.properties",
|
||||
"gradle/libs.versions.toml",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
# Spectre (JEWEL-1390). `testonly` is what keeps it out of the IDE and published artifacts.
|
||||
|
||||
kt_jvm_import(
|
||||
name = "spectre-core",
|
||||
testonly = True,
|
||||
jar = "@jewel_deps_spectre_core//file",
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
kt_jvm_import(
|
||||
name = "spectre-testing",
|
||||
testonly = True,
|
||||
jar = "@jewel_deps_spectre_testing//file",
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
kt_jvm_import(
|
||||
name = "spectre-agent",
|
||||
testonly = True,
|
||||
jar = "@jewel_deps_spectre_agent//file",
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
kt_jvm_import(
|
||||
name = "spectre-recording",
|
||||
testonly = True,
|
||||
jar = "@jewel_deps_spectre_recording//file",
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
kt_jvm_import(
|
||||
name = "androidx-tracing-wire-desktop",
|
||||
testonly = True,
|
||||
jar = "@jewel_deps_androidx_tracing_wire_desktop//file",
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
kt_jvm_import(
|
||||
name = "kotlinx-coroutines-swing",
|
||||
testonly = True,
|
||||
jar = "@jewel_deps_kotlinx_coroutines_swing//file",
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
# Compose, coroutines and kotlin-stdlib are deliberately not exported: the tested module
|
||||
# brings them, and a second copy would shadow the monorepo's versions.
|
||||
java_library(
|
||||
name = "spectre",
|
||||
testonly = True,
|
||||
visibility = ["//visibility:public"],
|
||||
exports = [
|
||||
":spectre-core",
|
||||
":spectre-testing",
|
||||
],
|
||||
runtime_deps = [
|
||||
":androidx-tracing-wire-desktop",
|
||||
":kotlinx-coroutines-swing",
|
||||
":spectre-agent",
|
||||
":spectre-recording",
|
||||
],
|
||||
)
|
||||
|
||||
kt_jvm_import(
|
||||
name = "junit-platform-console",
|
||||
testonly = True,
|
||||
jar = "@jewel_deps_junit_platform_console//file",
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
kt_jvm_import(
|
||||
name = "junit-platform-reporting",
|
||||
testonly = True,
|
||||
jar = "@jewel_deps_junit_platform_reporting//file",
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
# Only the console front end is Jewel-local; the JUnit Platform itself comes from //libraries.
|
||||
java_library(
|
||||
name = "spectre-junit-console",
|
||||
testonly = True,
|
||||
visibility = ["//visibility:public"],
|
||||
runtime_deps = [
|
||||
":junit-platform-console",
|
||||
":junit-platform-reporting",
|
||||
"//libraries/junit5",
|
||||
"//libraries/junit5-jupiter",
|
||||
"//libraries/junit5-launcher",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -61,6 +61,76 @@ diff --git a/platform/testFramework/monorepo/BUILD.bazel b/platform/testFramewor
|
||||
|
||||
But... Please double-check the dumps it changed before pushing.
|
||||
|
||||
## Running the Spectre headful UI tests
|
||||
|
||||
[Spectre](https://spectre.sebastiano.dev) drives a real Compose Desktop window, so its tests need a display and a
|
||||
non-headless JVM. That rules out `jps_test`, which forces `-Djava.awt.headless=true` and puts the IntelliJ test
|
||||
runtime on the classpath — the latter would hide exactly the standalone-runtime leaks these tests exist to catch.
|
||||
The lane therefore uses the `spectre_test` macro in [spectre.bzl](../spectre.bzl), which runs the JUnit Platform
|
||||
console launcher on a classpath containing only the module under test, Compose, and Spectre.
|
||||
|
||||
These are ordinary test targets. On any machine with a display they run as part of `bazel test //platform/jewel/...`,
|
||||
or on their own:
|
||||
|
||||
```bash
|
||||
./bazel.cmd test //platform/jewel/int-ui/int-ui-standalone-tests:jewel-intUi-standalone-spectre-tests
|
||||
```
|
||||
|
||||
Windows will open and close on your desktop while they run; synthetic input goes to the test window, so you can keep
|
||||
working, but do not be surprised by the flicker.
|
||||
|
||||
Every Spectre target is tagged `requires-display`. That tag is both the CI routing hint and the escape hatch: a lane
|
||||
that genuinely has no display skips them with `--test_tag_filters=-requires-display`.
|
||||
|
||||
### Scope: standalone only
|
||||
|
||||
This lane covers **standalone** Jewel, and cannot be extended to the IJP bridge. Spectre automates a Compose Desktop
|
||||
window; inside the IDE a Jewel popup is a `JBPopup` hosting a `ComposePanel`, and the application under test is the
|
||||
IDE itself. So `JBPopupRenderer` and the other bridge renderers currently have **no headful coverage at all** — only
|
||||
the Compose UI unit tests in `ui-tests`. That gap is JEWEL-1397, which is IDE Starter / UI Driver work rather than
|
||||
Spectre work. Do not try to add a bridge test to `src/spectreTest`; it cannot run there.
|
||||
|
||||
### Adding a Spectre test
|
||||
|
||||
Put the class under a `src/spectreTest/kotlin` source root, in a package under `org.jetbrains.jewel`, and you are
|
||||
done — there is no list of test classes to keep in sync.
|
||||
|
||||
Discovery is by package (`--select-package`), which JUnit resolves through the class loader. Both obvious
|
||||
alternatives are broken under Bazel, and each fails silently rather than loudly:
|
||||
|
||||
- a bare `--scan-classpath` scans only classpath *directories*, and under Bazel every classpath entry is a jar;
|
||||
- `--scan-classpath=<jar path>` assumes a runfiles symlink tree, so it finds nothing on Windows, where Bazel uses a
|
||||
runfiles manifest instead.
|
||||
|
||||
That is why the macro also passes `--fail-if-no-tests`: it turns any future variant of that mistake into a red lane
|
||||
instead of a green one that ran nothing.
|
||||
|
||||
### CI
|
||||
|
||||
Spectre targets are meant to run on **both** CI systems, and neither needs a target list — both select by tag, so a
|
||||
new `spectre_test` target anywhere under `platform/jewel` joins CI on its own:
|
||||
|
||||
```bash
|
||||
bazel test //platform/jewel/... --build_tests_only --test_tag_filters=requires-display
|
||||
```
|
||||
|
||||
**GitHub Actions** runs two jobs from [jewel-checks.yml](../../../.github/workflows/jewel-checks.yml): `Jewel Spectre
|
||||
tests` on Linux under Xvfb, and `Jewel Spectre tests (Windows)`, which needs no display setup because Windows always
|
||||
hands the process a window station.
|
||||
|
||||
**TeamCity / Patronus** should run them alongside the headful IJP tests, on display-capable agents. That
|
||||
configuration lives internally and there is nothing in this repository that drives it — the command above is the
|
||||
whole contract, and `requires-display` is the tag to route on. A headless agent that picks up `//platform/jewel/...`
|
||||
must exclude them with `--test_tag_filters=-requires-display`, or every Spectre test will fail in `XToolkit`'s
|
||||
static initialiser.
|
||||
|
||||
Windows is not redundant coverage: `JDialogRenderer` renders popups through `RenderSettings.SwingGraphics` there
|
||||
rather than Compose's default, with a different transparency hack, so it is a genuinely different code path.
|
||||
|
||||
Spectre itself is declared in [jewel_deps.MODULE.bazel](../jewel_deps.MODULE.bazel) and exposed as the `testonly`
|
||||
target `//platform/jewel:spectre`. Keep it that way: `testonly` is what makes Bazel refuse to let a production target
|
||||
depend on it, which is how Spectre stays out of the IDE and out of published Jewel artifacts.
|
||||
|
||||
## Add Devkit to IDE Build
|
||||
|
||||
On JPS we had a handy run configuration that built the IDE with the devkit bundled. On Bazel, the `idea_community`
|
||||
|
||||
@@ -1,6 +1,45 @@
|
||||
load("@community//build:tests-options.bzl", "jps_test")
|
||||
load("@rules_jvm//:jvm.bzl", "jvm_library")
|
||||
load("//build:compiler-options.bzl", "create_kotlinc_options")
|
||||
load("//platform/jewel:spectre.bzl", "spectre_test")
|
||||
|
||||
# Headful Spectre UI tests (JEWEL-1390). Hand-written, and outside the JPS model on purpose:
|
||||
# the closure must stay standalone; StandaloneRuntimeSmokeTest is what enforces that.
|
||||
create_kotlinc_options(
|
||||
name = "custom_jewel-intUi-standalone-spectre-tests",
|
||||
opt_in = [
|
||||
"androidx.compose.ui.ExperimentalComposeUiApi",
|
||||
"androidx.compose.foundation.ExperimentalFoundationApi",
|
||||
"org.jetbrains.jewel.foundation.ExperimentalJewelApi",
|
||||
"org.jetbrains.jewel.foundation.InternalJewelApi",
|
||||
],
|
||||
x_context_parameters = True,
|
||||
)
|
||||
|
||||
spectre_test(
|
||||
name = "jewel-intUi-standalone-spectre-tests",
|
||||
srcs = glob(
|
||||
["src/spectreTest/kotlin/**/*.kt"],
|
||||
allow_empty = True,
|
||||
),
|
||||
# The tests assert that JDialogRenderer, not the Compose popup, is the renderer under test.
|
||||
jvm_flags = ["-Djewel.customPopupRender=true"],
|
||||
kotlinc_opts = ":custom_jewel-intUi-standalone-spectre-tests",
|
||||
module_name = "intellij.platform.jewel.intUi.standalone.spectreTests",
|
||||
visibility = ["//visibility:public"],
|
||||
# Icon resources only; adds no IntelliJ Platform classes to the closure.
|
||||
runtime_deps = ["//platform/icons"],
|
||||
deps = [
|
||||
"//libraries/compose-foundation-desktop",
|
||||
"//libraries/junit5",
|
||||
"//libraries/kotlinx/coroutines/core",
|
||||
"//platform/jewel/foundation",
|
||||
"//platform/jewel/int-ui/int-ui-standalone:jewel-intUi-standalone",
|
||||
"//platform/jewel/ui",
|
||||
"@lib//:kotlin-stdlib",
|
||||
"@lib//:kotlin-test",
|
||||
],
|
||||
)
|
||||
|
||||
### auto-generated section `build intellij.platform.jewel.intUi.standalone.tests` start
|
||||
|
||||
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.jewel.intui.standalone
|
||||
|
||||
import java.io.File
|
||||
import java.util.jar.JarFile
|
||||
import kotlin.test.assertTrue
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
// Guards the property that makes this lane worth having, and the reason it is not a jps_test: that runner puts the
|
||||
// IntelliJ test runtime on the classpath itself, so it could never assert this.
|
||||
class StandaloneRuntimeSmokeTest {
|
||||
@Test
|
||||
fun `only the icons API is on the classpath from com dot intellij`() {
|
||||
val offenders = classpathJars().map { it to it.unexpectedIntellijClassCount() }.filter { (_, n) -> n > 0 }
|
||||
|
||||
assertTrue(
|
||||
offenders.isEmpty(),
|
||||
"The IntelliJ Platform has leaked into the standalone lane via: " +
|
||||
offenders.joinToString { (jar, n) -> "${jar.name} ($n classes)" },
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `the IntelliJ Application class cannot be loaded`() {
|
||||
val loaded = runCatching { Class.forName("com.intellij.openapi.application.Application") }.isSuccess
|
||||
|
||||
assertTrue(!loaded, "com.intellij.openapi.application.Application must not be reachable from this lane")
|
||||
}
|
||||
|
||||
private fun classpathJars(): List<File> =
|
||||
System.getProperty("java.class.path").split(File.pathSeparatorChar).map(::File).filter {
|
||||
it.isFile && it.name.endsWith(".jar")
|
||||
}
|
||||
|
||||
private fun File.unexpectedIntellijClassCount(): Int =
|
||||
JarFile(this).use { jar ->
|
||||
jar.entries().asSequence().count { entry ->
|
||||
entry.name.startsWith("com/intellij/") &&
|
||||
entry.name.endsWith(".class") &&
|
||||
ALLOWED_PACKAGES.none { entry.name.startsWith(it) }
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
// Standalone Jewel depends on the icons API and its implementation on purpose (the jb-icons-* modules), so
|
||||
// this is the one com.intellij package the lane is allowed to see. Anything else is a leak.
|
||||
private val ALLOWED_PACKAGES = listOf("com/intellij/platform/icons/")
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -41,7 +41,9 @@ import org.jetbrains.jewel.ui.component.rememberSpeedSearchState
|
||||
import org.jetbrains.jewel.ui.component.search.SpeedSearchableComboBox
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
// Note: these tests run intentionally Gradle-only until JEWEL-1390
|
||||
// Headful, and deliberately not a jps_test: the app under test must keep a standalone-only runtime closure,
|
||||
// with no IntelliJ Platform classes on the classpath. Runs in CI on any agent with a display:
|
||||
// bazel test //platform/jewel/int-ui/int-ui-standalone-tests:jewel-intUi-standalone-spectre-tests
|
||||
class CustomPopupRendererSpectreTest {
|
||||
@Test
|
||||
fun `escape closes a hovered combo box`(): Unit = runSpectreTestWithCustomPopupRenderer {
|
||||
|
||||
@@ -20,3 +20,66 @@ http_file(
|
||||
sha256 = "3afe89a11120303c73c9bdda3d8fe558dd9070a6937d27819ddc04b275381245",
|
||||
url = "https://cache-redirector.jetbrains.com/repo1.maven.org/maven2/io/gitlab/arturbosch/detekt/detekt-cli/1.23.8/detekt-cli-1.23.8-all.jar",
|
||||
)
|
||||
|
||||
# Spectre (JEWEL-1390). Declared here rather than in `lib/MODULE.bazel` so it cannot reach the
|
||||
# IDE or a published artifact.
|
||||
http_file(
|
||||
name = "jewel_deps_spectre_core",
|
||||
downloaded_file_path = "spectre-core-0.5.0.jar",
|
||||
sha256 = "1a81c7a259f38646673e8ddc75477f067f13615bc0bbe54454fd3d32b2980bd9",
|
||||
url = "https://cache-redirector.jetbrains.com/repo1.maven.org/maven2/dev/sebastiano/spectre/spectre-core/0.5.0/spectre-core-0.5.0.jar",
|
||||
)
|
||||
|
||||
http_file(
|
||||
name = "jewel_deps_spectre_testing",
|
||||
downloaded_file_path = "spectre-testing-0.5.0.jar",
|
||||
sha256 = "0856b8d2758ffb436910bde53cd35f947d9873ff37173787c796fc6a49f6ff94",
|
||||
url = "https://cache-redirector.jetbrains.com/repo1.maven.org/maven2/dev/sebastiano/spectre/spectre-testing/0.5.0/spectre-testing-0.5.0.jar",
|
||||
)
|
||||
|
||||
# Compile dependency of spectre-testing; unused by the in-process lane, but must resolve.
|
||||
http_file(
|
||||
name = "jewel_deps_spectre_agent",
|
||||
downloaded_file_path = "spectre-agent-0.5.0.jar",
|
||||
sha256 = "6a6e81b0986456ecb1bce0b79c31a2ece46e747666be284fe12cdc1cebb2fb3d",
|
||||
url = "https://cache-redirector.jetbrains.com/repo1.maven.org/maven2/dev/sebastiano/spectre/spectre-agent/0.5.0/spectre-agent-0.5.0.jar",
|
||||
)
|
||||
|
||||
# Runtime dependency of spectre-testing.
|
||||
http_file(
|
||||
name = "jewel_deps_spectre_recording",
|
||||
downloaded_file_path = "spectre-recording-0.5.0.jar",
|
||||
sha256 = "ab44895f231546d0209924caa4f429f9a2fd700f499f9d1b34dcb92a39431f80",
|
||||
url = "https://cache-redirector.jetbrains.com/repo1.maven.org/maven2/dev/sebastiano/spectre/spectre-recording/0.5.0/spectre-recording-0.5.0.jar",
|
||||
)
|
||||
|
||||
# Runtime dependency of spectre-core, not otherwise in the monorepo.
|
||||
http_file(
|
||||
name = "jewel_deps_androidx_tracing_wire_desktop",
|
||||
downloaded_file_path = "tracing-wire-desktop-2.0.0-alpha06.jar",
|
||||
sha256 = "c6cb73c39f1179673686ca4dc56152844e0ace52087243cfef60fee261ec1934",
|
||||
url = "https://cache-redirector.jetbrains.com/dl.google.com/dl/android/maven2/androidx/tracing/tracing-wire-desktop/2.0.0-alpha06/tracing-wire-desktop-2.0.0-alpha06.jar",
|
||||
)
|
||||
|
||||
# Runtime dependency of spectre-core.
|
||||
http_file(
|
||||
name = "jewel_deps_kotlinx_coroutines_swing",
|
||||
downloaded_file_path = "kotlinx-coroutines-swing-1.10.2.jar",
|
||||
sha256 = "02bdb85f20ec08004429abf6887e8d0e40f3ab637d7462f817f0f8abbe7d1eb5",
|
||||
url = "https://cache-redirector.jetbrains.com/repo1.maven.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-swing/1.10.2/kotlinx-coroutines-swing-1.10.2.jar",
|
||||
)
|
||||
|
||||
# Entry point of the headful lane. Version must match the JUnit Platform in `lib`.
|
||||
http_file(
|
||||
name = "jewel_deps_junit_platform_console",
|
||||
downloaded_file_path = "junit-platform-console-1.14.4.jar",
|
||||
sha256 = "8fba295a9aaced613062b7a8486758b71418e1545a3775de8df9ed76cc062383",
|
||||
url = "https://cache-redirector.jetbrains.com/repo1.maven.org/maven2/org/junit/platform/junit-platform-console/1.14.4/junit-platform-console-1.14.4.jar",
|
||||
)
|
||||
|
||||
http_file(
|
||||
name = "jewel_deps_junit_platform_reporting",
|
||||
downloaded_file_path = "junit-platform-reporting-1.14.4.jar",
|
||||
sha256 = "4a1d32f0f09d29f046ca51a81b8bfbc0f829392892672ea2e2cd530cd9c4b212",
|
||||
url = "https://cache-redirector.jetbrains.com/repo1.maven.org/maven2/org/junit/platform/junit-platform-reporting/1.14.4/junit-platform-reporting-1.14.4.jar",
|
||||
)
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
"""Headful Compose Desktop UI tests driven by Spectre (JEWEL-1390).
|
||||
|
||||
Runs the JUnit Platform console launcher rather than `jps_test`, which forces headless mode and
|
||||
pulls in the IntelliJ test runtime. See platform/jewel/docs/bazel-build-tips.md.
|
||||
"""
|
||||
|
||||
load("@rules_java//java:defs.bzl", "java_test")
|
||||
load("@rules_jvm//:jvm.bzl", "jvm_library")
|
||||
|
||||
SPECTRE_JVM_FLAGS = [
|
||||
"-Djava.awt.headless=false",
|
||||
# Keeps the test window out of the macOS Dock.
|
||||
"-Dapple.awt.UIElement=true",
|
||||
"-ea",
|
||||
]
|
||||
|
||||
# Not `manual`: CI is meant to run these. `requires-display` is the opt-out handle.
|
||||
SPECTRE_TAGS = [
|
||||
"requires-display",
|
||||
"no-sandbox",
|
||||
"local",
|
||||
"external",
|
||||
]
|
||||
|
||||
def spectre_test(
|
||||
name,
|
||||
srcs,
|
||||
module_name,
|
||||
test_packages = ["org.jetbrains.jewel"],
|
||||
deps = [],
|
||||
runtime_deps = [],
|
||||
kotlinc_opts = None,
|
||||
jvm_flags = [],
|
||||
tags = [],
|
||||
size = "medium",
|
||||
data = [],
|
||||
visibility = None,
|
||||
**kwargs):
|
||||
"""Compiles and runs a set of headful Spectre UI tests.
|
||||
|
||||
Args:
|
||||
name: Target name. The compiled test sources land in `<name>_lib`.
|
||||
srcs: Kotlin sources of the tests.
|
||||
module_name: Kotlin module name for the compiled test sources.
|
||||
test_packages: Root packages to discover tests in. The default covers all of Jewel.
|
||||
deps: Compile dependencies. `//platform/jewel:spectre` is always added.
|
||||
runtime_deps: Extra runtime-only dependencies.
|
||||
kotlinc_opts: Label of the `create_kotlinc_options` target to compile with.
|
||||
jvm_flags: Extra JVM flags, appended after `SPECTRE_JVM_FLAGS`.
|
||||
tags: Extra tags, appended after `SPECTRE_TAGS`.
|
||||
size: Bazel test size. Headful tests start a real app, so the default is `medium`.
|
||||
data: Runfiles needed by the tests.
|
||||
visibility: Visibility of the test target.
|
||||
**kwargs: Passed through to `java_test`.
|
||||
"""
|
||||
lib_name = name + "_lib"
|
||||
|
||||
jvm_library(
|
||||
name = lib_name,
|
||||
testonly = True,
|
||||
srcs = srcs,
|
||||
kotlinc_opts = kotlinc_opts,
|
||||
module_name = module_name,
|
||||
visibility = ["//visibility:private"],
|
||||
deps = deps + ["//platform/jewel:spectre"],
|
||||
runtime_deps = runtime_deps,
|
||||
)
|
||||
|
||||
java_test(
|
||||
name = name,
|
||||
main_class = "org.junit.platform.console.ConsoleLauncher",
|
||||
use_testrunner = False,
|
||||
# Both `--scan-classpath` forms silently find nothing under Bazel: bare scans only
|
||||
# directories, and `=<jar>` needs a runfiles symlink tree, which Windows lacks.
|
||||
args = [
|
||||
"execute",
|
||||
"--fail-if-no-tests",
|
||||
"--details=tree",
|
||||
"--disable-ansi-colors",
|
||||
] + ["--select-package=" + test_package for test_package in test_packages],
|
||||
jvm_flags = SPECTRE_JVM_FLAGS + jvm_flags,
|
||||
# Bazel scrubs the test environment; without these AWT falls back to `:0.0` and fails.
|
||||
env_inherit = [
|
||||
"DISPLAY",
|
||||
"XAUTHORITY",
|
||||
],
|
||||
runtime_deps = [
|
||||
":" + lib_name,
|
||||
"//platform/jewel:spectre-junit-console",
|
||||
],
|
||||
tags = SPECTRE_TAGS + tags,
|
||||
size = size,
|
||||
data = data,
|
||||
visibility = visibility,
|
||||
**kwargs
|
||||
)
|
||||
Reference in New Issue
Block a user