chore(nests): mv nestsClient-browser-interop/ → nestsClient/tests/browser-interop/

Mirrors the existing nestsClient/tests/hang-interop/ layout — all
T16 cross-stack interop test infrastructure (Rust sidecars + bun
browser harness) now lives under nestsClient/tests/.

Updates:
- nestsClient/build.gradle.kts: browserInteropDir path.
- PlaywrightDriver.kt + BrowserInteropTest.kt: kdoc comments.
- All plan docs in nestsClient/plans/ that referenced the old
  path.

Compiles clean post-move. No CI changes (those jobs are
intentionally not wired per 2026-05-07-cross-stack-interop-ci-gating.md;
when re-added they'll reference the new path).
This commit is contained in:
Claude
2026-05-07 14:43:55 +00:00
parent 32065901c8
commit bd7b166fda
21 changed files with 33 additions and 33 deletions
+2 -2
View File
@@ -232,7 +232,7 @@ tasks.withType<Test>().configureEach {
// ---- Cross-stack interop: BROWSER (Phase 4 of T16) --------------------------
//
// Adds the bun + Playwright + headless Chromium harness at
// `nestsClient-browser-interop/`. Mirrors the hang-interop wiring above
// `nestsClient/tests/browser-interop/`. Mirrors the hang-interop wiring above
// but with bun/npx subprocesses instead of cargo. Opt-in via
// `-DnestsBrowserInterop=true`. See:
// nestsClient/plans/2026-05-06-phase4-browser-harness.md
@@ -249,7 +249,7 @@ tasks.withType<Test>().configureEach {
// paths the agents/host runner ship with.
val browserInteropDir =
rootProject.layout.projectDirectory.dir("nestsClient-browser-interop")
rootProject.layout.projectDirectory.dir("nestsClient/tests/browser-interop")
// `bun` lives at `/root/.bun/bin/bun` on the agent runner. CI may put it
// elsewhere; allow override via env / system property. Falls back to
@@ -379,7 +379,7 @@ adds an explicit goaway frame, the test would slot in here.
Running in agent worktree (`feat/nests-browser-interop`). Adds:
- `nestsClient-browser-interop/` — TypeScript + Vite project shipping
- `nestsClient/tests/browser-interop/` — TypeScript + Vite project shipping
the upstream `@kixelated/moq` and `@kixelated/hang-wasm` consumers/
publishers, bundled into static `listen.html` / `publish.html`
pages.
@@ -492,7 +492,7 @@ nestsClient/src/jvmTest/kotlin/com/vitorpamplona/nestsclient/
# In sister branches (not yet merged):
# feat/nests-i6-multi-listener -> HangInteropMultiListenerTest.kt (I6)
# feat/nests-i7-publisher-reconnect -> HangInteropReverseTest.kt (I7)
# feat/nests-browser-interop -> nestsClient-browser-interop/ +
# feat/nests-browser-interop -> nestsClient/tests/browser-interop/ +
# BrowserInteropTest.kt (Phase 4)
nestsClient/plans/2026-05-06-cross-stack-interop-test-results.md # this file
@@ -196,10 +196,10 @@ Behaviour: standard tokio UDP relay. For each datagram received,
### Browser harness (bun + Playwright)
New module at `nestsClient-browser-interop/`.
New module at `nestsClient/tests/browser-interop/`.
```
nestsClient-browser-interop/
nestsClient/tests/browser-interop/
├── package.json
├── tsconfig.json
├── src/
@@ -225,7 +225,7 @@ nestsClient-browser-interop/
```
Pin to the same npm versions that `nostrnests/nests` `NestsUI-v2/package.json`
ships. Document the rev in `nestsClient-browser-interop/REV`.
ships. Document the rev in `nestsClient/tests/browser-interop/REV`.
#### `listen.ts`
Mirrors NostrNests' `transport/moq-transport.ts` `Watch.Broadcast`
@@ -552,7 +552,7 @@ Total: ~5 days. P0 deliverable (1+2+4) is **3 days**.
### Phase 4 — Browser harness (1.5 days)
15. Bootstrap `nestsClient-browser-interop/`: bun init, install
15. Bootstrap `nestsClient/tests/browser-interop/`: bun init, install
`@moq/lite` `@moq/watch` `@moq/publish` `@moq/hang` at pinned
versions matching `nostrnests/nests` `NestsUI-v2`. Document rev.
16. Write `listen.ts` + `pcm-tap-worklet.ts` + `listen.html`. Mirror
@@ -618,8 +618,8 @@ jobs:
path: |
~/.cargo/registry
~/.cache/ms-playwright
nestsClient-browser-interop/node_modules
key: ${{ runner.os }}-browser-${{ hashFiles('nestsClient-browser-interop/bun.lockb', 'nestsClient/tests/hang-interop/Cargo.lock') }}
nestsClient/tests/browser-interop/node_modules
key: ${{ runner.os }}-browser-${{ hashFiles('nestsClient/tests/browser-interop/bun.lockb', 'nestsClient/tests/hang-interop/Cargo.lock') }}
- run: ./gradlew :nestsClient:jvmTest -DnestsBrowserInterop=true
```
@@ -664,7 +664,7 @@ Acceptable for PR-level CI.
committed at `nestsClient/plans/2026-05-06-cross-stack-interop-test-gap-matrix.md`.
6. Both `-DnestsHangInterop=true` and `-DnestsBrowserInterop=true`
in the default PR-level GitHub Actions config.
7. `nestsClient/tests/hang-interop/REV` and `nestsClient-browser-interop/REV`
7. `nestsClient/tests/hang-interop/REV` and `nestsClient/tests/browser-interop/REV`
document the pinned upstream revs.
8. New plan filed at
`nestsClient/plans/2026-05-06-cross-stack-interop-test-results.md`
@@ -331,7 +331,7 @@ tests stay green.
- **5.1 / spatial audio.** Catalog field is `numberOfChannels`,
but the audio pipeline assumes interleaved planar — beyond
stereo would need a separate plan.
- **Browser side I4.** `nestsClient-browser-interop/` doesn't
- **Browser side I4.** `nestsClient/tests/browser-interop/` doesn't
exist yet (Phase 4 of the parent plan); when it lands the
same I4 shape ports straight to a `BrowserInteropTest`.
- **Per-channel mute.** The existing `setMuted(true)` mutes the
@@ -6,7 +6,7 @@ the spec at `nestsClient/plans/2026-05-06-phase4-browser-harness.md`.
## Where it landed
- New top-level `nestsClient-browser-interop/` workspace:
- New top-level `nestsClient/tests/browser-interop/` workspace:
- `package.json` pins `@moq/lite@0.2.2`, `@moq/hang@0.2.4`,
`@moq/watch@0.2.10`, `@moq/publish@0.2.6`, `@playwright/test@1.56.1`.
- `REV` documents the pinned versions next to the
@@ -65,7 +65,7 @@ Phase 1 — no Docker, no second relay, no fake auth sidecar.
▼ ▼ ▼
┌──────────────────────┐ ┌──────────────────┐ ┌─────────────────────────────┐
│ NativeMoqRelayHarness│ │ Kotlin in-proc │ │ Browser harness │
│ (existing — Phase 1) │ │ speaker / listener│ │ nestsClient-browser-interop/│
│ (existing — Phase 1) │ │ speaker / listener│ │ nestsClient/tests/browser-interop/│
│ moq-relay subprocess │ │ via │ │ - bun static + WS server │
│ 127.0.0.1:<rand> │ │ connectNestsSpeaker │ - listen.html + listen.ts │
│ --auth-public "" │ │ connectNestsListener │ - publish.html+publish.ts │
@@ -79,13 +79,13 @@ Phase 1 — no Docker, no second relay, no fake auth sidecar.
## Components
### 1. `nestsClient-browser-interop/` — bun + Playwright workspace
### 1. `nestsClient/tests/browser-interop/` — bun + Playwright workspace
New top-level directory, mirrors the parent plan's
specification. Contents:
```
nestsClient-browser-interop/
nestsClient/tests/browser-interop/
├── package.json
├── tsconfig.json
├── bun.lockb # pinned via REV file
@@ -103,7 +103,7 @@ nestsClient-browser-interop/
Pin all `@moq/*` deps to the same versions `nostrnests/nests`
ships in `NestsUI-v2/package.json`. Document the rev in
`nestsClient-browser-interop/REV` (parallel to
`nestsClient/tests/browser-interop/REV` (parallel to
`nestsClient/tests/hang-interop/REV`).
### 2. `listen.ts` — browser listener
@@ -168,14 +168,14 @@ the relay's auto-generated cert without parsing).
val interopBuildBrowserHarness by tasks.registering(Exec::class) {
description = "bun install && bun build for the browser interop harness"
group = "interop"
workingDir = file("nestsClient-browser-interop")
workingDir = file("nestsClient/tests/browser-interop")
commandLine("bash", "-c", "bun install && bun build src/listen.ts src/publish.ts src/pcm-tap-worklet.ts --outdir dist --target browser")
inputs.files(
fileTree("nestsClient-browser-interop") {
fileTree("nestsClient/tests/browser-interop") {
include("package.json", "bun.lockb", "src/**/*")
}
)
outputs.dir("nestsClient-browser-interop/dist")
outputs.dir("nestsClient/tests/browser-interop/dist")
}
```
@@ -185,7 +185,7 @@ A second task installs Playwright's Chromium:
val interopInstallPlaywrightChromium by tasks.registering(Exec::class) {
description = "Install Playwright Chromium + dependencies"
group = "interop"
workingDir = file("nestsClient-browser-interop")
workingDir = file("nestsClient/tests/browser-interop")
commandLine("bash", "-c", "npx playwright install --with-deps chromium")
onlyIf {
// Skip if Chromium binary exists in the cache
@@ -205,7 +205,7 @@ tasks.withType<Test>().configureEach {
}
systemProperty(
"nestsBrowserInteropHarnessDir",
file("nestsClient-browser-interop").absolutePath,
file("nestsClient/tests/browser-interop").absolutePath,
)
System.getProperty("nestsBrowserInterop")?.let {
systemProperty("nestsBrowserInterop", it)
@@ -288,7 +288,7 @@ Total: ~1.5 days.
### Phase 4.A — bun harness scaffold (~3 hr)
1. `bun init` in `nestsClient-browser-interop/`. Pin `@moq/lite`,
1. `bun init` in `nestsClient/tests/browser-interop/`. Pin `@moq/lite`,
`@moq/watch`, `@moq/publish`, `@moq/hang` to the versions
`nostrnests/nests` `NestsUI-v2/package.json` ships at the
time of implementation. Document in `REV`.
@@ -351,7 +351,7 @@ method).
13. Add `browser-interop` job to `.github/workflows/build.yml`
parallel to `hang-interop`. Cache
`nestsClient-browser-interop/node_modules` and
`nestsClient/tests/browser-interop/node_modules` and
`~/.cache/ms-playwright` on the bun.lockb hash.
14. Run `./gradlew :nestsClient:jvmTest -DnestsBrowserInterop=true`
on Linux runners. macOS / Windows would double the matrix
@@ -373,7 +373,7 @@ method).
## Definition of done
1. `nestsClient-browser-interop/` directory complete with
1. `nestsClient/tests/browser-interop/` directory complete with
bun + Playwright + sources building cleanly via
`interopBuildBrowserHarness`.
2. P0 scenarios green: I1 forward, I2, I3, I13, I14 (and I4
@@ -73,13 +73,13 @@ browser-interop:
- uses: actions/cache@v4
with:
path: |
nestsClient-browser-interop/node_modules
nestsClient-browser-interop/dist
key: ${{ runner.os }}-bun-${{ hashFiles('nestsClient-browser-interop/package.json', 'nestsClient-browser-interop/bun.lock') }}
nestsClient/tests/browser-interop/node_modules
nestsClient/tests/browser-interop/dist
key: ${{ runner.os }}-bun-${{ hashFiles('nestsClient/tests/browser-interop/package.json', 'nestsClient/tests/browser-interop/bun.lock') }}
- uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: ${{ runner.os }}-playwright-${{ hashFiles('nestsClient-browser-interop/package.json') }}
key: ${{ runner.os }}-playwright-${{ hashFiles('nestsClient/tests/browser-interop/package.json') }}
- name: Run browser cross-stack interop suite
run: |
./gradlew :nestsClient:jvmTest \
@@ -92,8 +92,8 @@ browser-interop:
name: Browser Interop Test Reports
path: |
nestsClient/build/reports/tests/jvmTest/
nestsClient-browser-interop/test-results/
nestsClient-browser-interop/playwright-report/
nestsClient/tests/browser-interop/test-results/
nestsClient/tests/browser-interop/playwright-report/
```
Same `git show b94737de7 -- .github/workflows/build.yml` reverse
@@ -138,7 +138,7 @@ class BrowserInteropTest {
* `Container.Consumer`", but two constraints reshape this here:
*
* 1. `@moq/hang` 0.2.4 (the published version pinned in
* `nestsClient-browser-interop/package.json`) does not export
* `nestsClient/tests/browser-interop/package.json`) does not export
* the high-level `Container.Consumer` / `Format` API. Phase 4
* uses `Container.Legacy.Consumer` directly same data path
* `@moq/watch` uses internally for `container.kind = "legacy"`.
@@ -52,7 +52,7 @@ internal object PlaywrightDriver {
const val ENABLE_PROPERTY = "nestsBrowserInterop"
/**
* Forwarded by Gradle: absolute path to `nestsClient-browser-interop/`.
* Forwarded by Gradle: absolute path to `nestsClient/tests/browser-interop/`.
*/
const val HARNESS_DIR_PROPERTY = "nestsBrowserInteropHarnessDir"