Skip to content

test(e2e): 3D scene samples on a real panel + display-modes startup read fix - #151

Merged
dfattal merged 5 commits into
mainfrom
test/samples-panel-e2e
Oct 8, 2026
Merged

dfattal merged 5 commits into
mainfrom
test/samples-panel-e2e

Conversation

@leaiss

@leaiss leaiss commented Oct 8, 2026 •

Copy link
Copy Markdown
Collaborator

What

1. A panel test for the published 3D scene samples (test/e2e/samples-panel.e2e.mjs, npm run test:e2e:samples-panel). It opens Hello Cube, Model, Splat, Camera Rig and Display Modes in the real DisplayXR Browser on a 3D panel. For each one it checks:

  • the sample's own "woven" signal;
  • that the runtime got a weave submit whose rect is the canvas (the D3D11 service's one-shot weave-input dump, #73 diag lines);
  • that the sample's control works;
  • no page or console errors (read from the browser log, so startup is covered).

It also saves a full-screen grab for review.

  • Attach timing: automation attaches only after the page has settled. Attaching while a woven page starts up provokes a raw side-by-side double image.
  • Input: it goes through CDP, so the real mouse never moves.
  • Scope: Windows only, and not part of npm test.

2. A fix it found in samples/display-modes. On a fresh page, the layer answers getDisplayInfo() with null and getRenderingModes() with [] until it has delivered a frame. So the sample's startup read told a visitor on the Leia panel "none — no glasses-free display on this machine". Pressing Re-read modes then showed the real panel. The fix awaits handle.firstWoven before the first read.

Results on the panel

Leia panel, DisplayXR Browser 1.5.4, runtime 2.26.0.

Live site: 4/5 pass. Display Modes fails on display info; it reproduced on 2 runs.

Display Modes, served locally, with and without the fix:

Build Runs Startup read
as published 2 display none, modes 0 active -1
with the fix 2 display 3840x2160px 0.344x0.194m recommended-scale 0.5,0.5, modes 2 active 1

All screen grabs were checked by eye: one clean woven image each, no double.

Open question for the SDK or browser: any page that calls getDisplayInfo() early gets the same false "no display". The SDK docs say null means no glasses-free display, so null before the first frame is ambiguous.

npm test: 845/849 on a Windows checkout. The 4 failures are the same without this branch: CRLF line endings breaking the api-snapshot and Spark source checks.

Update: media, call and shop samples (LOXR-827)

Same file, five more samples, all pass on the panel (browser 1.5.4):

Sample What the test checked
player Opens paused (by design), plays on Space, S/M/L + skin reach both players, the visible part of the tile weaves
shopify The cdn.shopify.com GLB loads and weaves; Reset reloads it
demo-gallery Five logos in one weave submit (5 rects); all five repo links resolve (200)
call ?camera=synthetic, started from its own button; the self tile weaves
call-embed A side-by-side fake camera (generated with ffmpeg), so the self tile is 3D ("You · 3D") and weaves

The call samples run on Chrome's fake camera and microphone, so no real device is opened. They use each sample's default hosted signalling.

The weave rect is now matched against the canvas's visible part, because a tile taller than the window is woven only where it is on screen. A sample can also declare browser flags, a start step and a minimum rect count.

One observation, not a failure: with Chrome's default (mono) fake camera, call-embed's self tile stays "You · 2D" and is not woven. The browser log says lift] module unavailable backend='' modes=0x0 on this box, so 2D participants are not lifted here.

Update: checking the woven picture itself

"The runtime was asked to weave the canvas" alone would have passed both bugs we chased this week. So two picture checks now run on every sample. Each was validated against pictures with a known answer before it was used.

eyePair, in what the browser submitted. The service's weave_input.png is now kept per sample. Each weave rect must hold a real stereo pair:

  • not flat, not black;
  • both eyes the same scene (a coarse intensity match over a disparity shift);
  • the eyes not identical.

8 of 8 known cases come out right. Five real pairs pass (the EarthView aerial scores 0.57). The 8 Oct zero-disparity black-box backdrop, identical untracked eyes and a mismatched pair all fail.

Samples that render live (stereo: 'tracked') only need two different eyes with VIEWER=present. Unattended, the runtime gives both eyes one viewpoint: hello-cube's eyes differ on 0.00% of pixels unattended and 5.71% with a viewer.

screenTile, on the screen over the canvas. It must show one picture:

  • a raw side-by-side pair (its halves match edge for edge) fails;
  • a flat dark tile fails.

15 of 15 labelled 8 Oct grabs come out right (doubles score 0.83–0.92, singles 0.04 or less). The browser is raised first. If the screen resembles neither the submitted pair nor one eye, the check reports a covered canvas instead of guessing; a terminal over a tile would otherwise have read as a double.

🤖 Generated with Claude Code

https://claude.ai/code/session_0122B8TjqkRgdikyu3edTegH

leaiss and others added 5 commits October 8, 2026 09:04
…wser

samples-panel.e2e.mjs opens each published sample (hello-cube, model, splat,
camera-rig, display-modes) in the real DisplayXR Browser on a 3D panel and checks:
the sample's own woven signal; that the runtime received a weave submit whose
rect is the canvas (the service's one-shot weave-input dump); that the sample's
control works; no page or console errors (the browser log covers startup); plus
a full-screen grab for review.

Automation attaches only after the page has settled (attaching while a woven
page starts up provokes a raw side-by-side double image), and input goes through
CDP so the real mouse never moves. Windows only; not part of `npm test`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0122B8TjqkRgdikyu3edTegH
On a fresh page the layer answers getDisplayInfo() with null and
getRenderingModes() with an empty list until it has delivered a frame, so the
sample's startup read told a visitor on a 3D panel "no glasses-free display on
this machine" (Re-read modes then showed the real panel). Await
handle.firstWoven before the first read. On the panel: 2 of 2 runs "display
none" before, 2 of 2 "display 3840x2160px 0.344x0.194m" after.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0122B8TjqkRgdikyu3edTegH
The browser writes every console message as `INFO:CONSOLE:<n>]` whatever its
level, so the old pattern (`ERROR:CONSOLE(`) could never match and the check
passed vacuously. Recognise an error by its text instead (an uncaught exception,
an Error type, "failed"), exported as isConsoleError() and checked against
known-bad and known-good lines; the 29 logs saved from the earlier panel runs
still have none. The entry point only runs main() when executed directly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0122B8TjqkRgdikyu3edTegH
…, demo-gallery, call, call-embed)

Adds the LOXR-827 group to samples-panel.e2e.mjs. All five pass on the Leia panel
(DisplayXR Browser 1.5.4):
- player: opens paused (no autoplay, by design), plays on Space, size/skin reach both players
- shopify: the cdn.shopify.com GLB loads and weaves; Reset reloads it
- demo-gallery: five logos in one weave submit; all five repo links resolve
- call: ?camera=synthetic, started from its own button; the self tile weaves
- call-embed: a side-by-side fake camera (generated with ffmpeg), so the self tile is 3D and weaves

Runner changes: a sample can declare browser flags and a start step, demand a minimum rect
count, and the weave rect is matched against the canvas's VISIBLE part (a tile taller than
the window is woven only where it is on screen).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0122B8TjqkRgdikyu3edTegH
Two picture checks per sample, each validated against pictures with a known answer
before use:

- eyePair: in what the browser submitted (the service's weave_input.png dump, now
  kept per sample), each weave rect must hold a real stereo pair: not flat, not black,
  both eyes the same scene (coarse intensity match over a disparity shift), and the
  eyes not identical. 8 of 8 known cases right: five real pairs pass (incl. the
  EarthView aerial at 0.57); the 8 Oct zero-disparity black-box backdrop, identical
  untracked eyes and a mismatched pair fail. Samples that render live
  (stereo: 'tracked') only need two different eyes with VIEWER=present: unattended,
  the runtime gives both eyes one viewpoint (hello-cube 0.00% of pixels differ
  unattended, 5.71% with a viewer).
- screenTile: the screen over the canvas must show ONE picture: a raw side-by-side
  pair (its halves matching edge for edge) fails, as does a flat dark tile. 15 of 15
  labelled 8 Oct grabs right (doubles 0.83-0.92, singles <= 0.04). The browser is
  raised first, and if the screen resembles neither the submitted pair nor one eye,
  the check reports a covered canvas instead of guessing (a terminal over a tile
  would otherwise have read as a double).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0122B8TjqkRgdikyu3edTegH

@dfattal dfattal left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed: the samples panel test and the display-modes first-read fix. The SDK-level change (display reads waiting for the first frame) follows separately on #147.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants