desktop: adapt to the new Quartz listener/auth APIs + hermetic tests

Master's Quartz upgrade made RelayConnectionListener.onIncomingMessage a
suspend fun and gave RelayAuthenticator's auth lambda (relay, event,
isReconnect) parameters; the desktop module still compiled against the
old shapes, breaking the build after the rebase. Update the overrides in
BunkerEngine, RelayChecker and the E2E test, and the auth lambda in
AmberDesktop, to the new signatures (same launch-inside-listener pattern
as NotificationSubscription).

The desktop test suite also failed on machines with a real install:
AppDirs resolves XDG_DATA_HOME before user.home, so a real
~/.local/share/amber holding a passphrase-wrapped master.key.enc leaked
into the worker JVMs and every DesktopKeyStore operation threw
LockedException. Point the test workers' XDG_DATA_HOME and user.home at
a pristine dir under build/ that is wiped per run (config-cache safe;
note Gradle cannot remove worker env vars — null becomes the literal
string "null" and previously materialized desktop/null/amber, now
gitignored).

:desktop:test 51/51 green, :desktop:ktlintCheck and
:app:compileFreeDebugKotlin pass.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
greenart7c3
2026-09-28 10:50:28 -03:00
co-authored by Claude
parent e150daea73
commit 8a59268738
6 changed files with 25 additions and 4 deletions
+1
View File
@@ -139,3 +139,4 @@ quartz/
.ai-jail .ai-jail
trace_processor trace_processor
perf-traces perf-traces
/desktop/null/
+20
View File
@@ -1,3 +1,4 @@
import java.io.File
import org.jetbrains.compose.desktop.application.dsl.TargetFormat import org.jetbrains.compose.desktop.application.dsl.TargetFormat
plugins { plugins {
@@ -11,6 +12,25 @@ kotlin {
jvmToolchain(21) jvmToolchain(21)
} }
// Tests must never see the developer machine's real desktop state: AppDirs.dataDir
// resolves from XDG_DATA_HOME *before* user.home, so a real ~/.local/share/amber
// with a passphrase-locked master.key.enc freezes into the suite and fails every
// DesktopKeyStore operation with LockedException. Scrub XDG_DATA_HOME from the
// worker env, point user.home at a pristine dir under build/, and wipe it per run.
tasks.test {
useJUnit()
val testHome = layout.buildDirectory.dir("desktop-test-home").get().asFile
// Gradle cannot remove env vars for workers (null becomes the literal string
// "null", which AppDirs happily uses as a directory name), so point
// XDG_DATA_HOME at the pristine home instead.
environment("XDG_DATA_HOME", File(testHome, "xdg-data").absolutePath)
systemProperty("user.home", testHome.absolutePath)
doFirst {
testHome.deleteRecursively()
testHome.mkdirs()
}
}
dependencies { dependencies {
implementation(compose.desktop.currentOs) implementation(compose.desktop.currentOs)
implementation(compose.material3) implementation(compose.material3)
@@ -48,7 +48,7 @@ object AmberDesktop {
// Authenticates with relays that request NIP-42 AUTH. // Authenticates with relays that request NIP-42 AUTH.
@Suppress("unused") @Suppress("unused")
private val authCoordinator by lazy { private val authCoordinator by lazy {
RelayAuthenticator(client, applicationIOScope) { event -> RelayAuthenticator(client, applicationIOScope) { _, event, _ ->
accounts().map { it.signer.sign(event) } accounts().map { it.signer.sign(event) }
} }
} }
@@ -95,7 +95,7 @@ class BunkerEngine(
client.addConnectionListener(this) client.addConnectionListener(this)
} }
override fun onIncomingMessage(relay: IRelayClient, msgStr: String, msg: Message) { override suspend fun onIncomingMessage(relay: IRelayClient, msgStr: String, msg: Message) {
if (msg is EventMessage) { if (msg is EventMessage) {
if (subIds.containsValue(msg.subId)) { if (subIds.containsValue(msg.subId)) {
scope.launch { scope.launch {
@@ -98,7 +98,7 @@ object RelayChecker {
super.onConnected(relay, pingMillis, compressed) super.onConnected(relay, pingMillis, compressed)
} }
override fun onIncomingMessage(relay: IRelayClient, msgStr: String, msg: Message) { override suspend fun onIncomingMessage(relay: IRelayClient, msgStr: String, msg: Message) {
if (msg is EventMessage && msg.subId == subId && msg.event.id == signedEvent.id) { if (msg is EventMessage && msg.subId == subId && msg.event.id == signedEvent.id) {
filterResult = true filterResult = true
} }
@@ -84,7 +84,7 @@ class BunkerE2eTest {
init { init {
client.addConnectionListener( client.addConnectionListener(
object : RelayConnectionListener { object : RelayConnectionListener {
override fun onIncomingMessage(relay: IRelayClient, msgStr: String, msg: Message) { override suspend fun onIncomingMessage(relay: IRelayClient, msgStr: String, msg: Message) {
if (msg is EventMessage && msg.event.kind == NostrConnectEvent.KIND) { if (msg is EventMessage && msg.event.kind == NostrConnectEvent.KIND) {
scope.launch { scope.launch {
runCatching { runCatching {