426e9eeabd
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
ci / test (push) Has been cancelled
ci / lint-and-format (push) Has been cancelled
ci / build (push) Has been cancelled
ci / dev-startup (push) Has been cancelled
gitleaks / gitleaks (push) Has been cancelled
Markdown Links / Relative Markdown Links (push) Has been cancelled
Quality (Extended) / Homepage Build (PR smoke) (push) Has been cancelled
Quality (Extended) / Comment-only diff guard (push) Has been cancelled
Quality (Extended) / Format + Type Safety Ratchet (push) Has been cancelled
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Has been cancelled
Quality (Extended) / Develop Gate (lint) (push) Has been cancelled
Chat shell gestures / Chat shell gesture + parity e2e (push) Has been cancelled
Cloud Gateway Discord / Test (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Has been cancelled
Build Agent Image / build-and-push (push) Has been cancelled
Dev Smoke / bun run dev onboarding chat (push) Has been cancelled
Dev Smoke / Vite HMR dependency-level smoke (push) Has been cancelled
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Has been cancelled
Publish @elizaos/example-code / check_npm (push) Has been cancelled
Publish @elizaos/example-code / publish_npm (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / verify_version (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / publish_npm (push) Has been cancelled
Sandbox Live Smoke / Sandbox live smoke (push) Has been cancelled
Snap Build & Test / Build Snap (amd64) (push) Has been cancelled
Snap Build & Test / Build Snap (arm64) (push) Has been cancelled
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Has been cancelled
Cloud Gateway Webhook / Test (push) Has been cancelled
Cloud Tests / lint-and-types (push) Has been cancelled
Cloud Tests / unit-tests (push) Has been cancelled
Cloud Tests / integration-tests (push) Has been cancelled
Cloud Tests / e2e-tests (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Apps Worker (Product 2) / Determine environment (push) Has been cancelled
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Has been cancelled
Deploy Eliza Provisioning Worker / Determine environment (push) Has been cancelled
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Has been cancelled
Dev Smoke / Classify changed paths (push) Has been cancelled
supply-chain / sbom (push) Has been cancelled
supply-chain / vulnerability-scan (push) Has been cancelled
Build, Push & Deploy to Phala Cloud / build-and-push (push) Has been cancelled
Test Packaging / Validate Packaging Configs (push) Has been cancelled
Test Packaging / Build & Test PyPI Package (push) Has been cancelled
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Has been cancelled
Test Packaging / Pack & Test JS Tarballs (push) Has been cancelled
UI Fixture E2E / ui-fixture-e2e (push) Has been cancelled
UI Fixture E2E / fixture-e2e (push) Has been cancelled
UI Story Gate / story-gate (push) Has been cancelled
vault-ci / test (macos-latest) (push) Has been cancelled
vault-ci / test (ubuntu-latest) (push) Has been cancelled
vault-ci / test (windows-latest) (push) Has been cancelled
vault-ci / app-core wiring tests (push) Has been cancelled
verify-patches / verify patches/CHECKSUMS.sha256 (push) Has been cancelled
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Has been cancelled
Voice Benchmark Smoke / voice bench smoke summary (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Has been cancelled
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Has been cancelled
298 lines
9.6 KiB
JavaScript
298 lines
9.6 KiB
JavaScript
/**
|
|
* Unit coverage for the pure logic of the live visual-QA sweep: the seed the
|
|
* renderer reads to skip onboarding, the state matrix, and the no-blue verdict
|
|
* fold. The capture/analyze shell is not exercised here (it needs a running
|
|
* server + Chromium); these are the decision functions a broken change would
|
|
* silently corrupt.
|
|
*/
|
|
import { describe, expect, it } from "vitest";
|
|
import {
|
|
aggregateVerdict,
|
|
buildCaptureUrl,
|
|
buildOnboardedSeed,
|
|
buildOverallVerdict,
|
|
buildStateMatrix,
|
|
COMPOSER_PROBE_TEXT,
|
|
evaluateCaptureReadiness,
|
|
FIRST_RUN_COMPLETE_KEY,
|
|
STEWARD_SESSION_TOKEN_KEY,
|
|
seedDriftOffenders,
|
|
} from "./visual-qa-live.mjs";
|
|
|
|
describe("buildOnboardedSeed", () => {
|
|
it("sets both keys the renderer gates on and a decodable-but-unsigned JWT", () => {
|
|
const seed = buildOnboardedSeed();
|
|
expect(seed[FIRST_RUN_COMPLETE_KEY]).toBe("1");
|
|
const token = seed[STEWARD_SESSION_TOKEN_KEY];
|
|
const [header, payload, sig] = token.split(".");
|
|
expect(sig).toBe("unsigned"); // never passes real API auth — surfaces the error state
|
|
const claims = JSON.parse(Buffer.from(payload, "base64").toString("utf8"));
|
|
expect(claims.sub).toBe("visual-qa-user");
|
|
expect(JSON.parse(Buffer.from(header, "base64").toString("utf8")).alg).toBe(
|
|
"none",
|
|
);
|
|
});
|
|
|
|
it("honours a custom subject", () => {
|
|
const token = buildOnboardedSeed({ subject: "elderly-dot" })[
|
|
STEWARD_SESSION_TOKEN_KEY
|
|
];
|
|
const claims = JSON.parse(
|
|
Buffer.from(token.split(".")[1], "base64").toString("utf8"),
|
|
);
|
|
expect(claims.sub).toBe("elderly-dot");
|
|
});
|
|
});
|
|
|
|
describe("buildStateMatrix", () => {
|
|
const matrix = buildStateMatrix();
|
|
it("covers both viewports with fresh first-run and onboarded shell profiles", () => {
|
|
expect(
|
|
matrix.some((s) => s.id === "desktop-onboarding" && s.seed === "fresh"),
|
|
).toBe(true);
|
|
expect(
|
|
matrix.some((s) => s.id === "mobile-shell" && s.seed === "onboarded"),
|
|
).toBe(true);
|
|
});
|
|
it("attaches DOM expectations so nonblank-but-wrong screens fail", () => {
|
|
expect(
|
|
matrix.find((s) => s.id === "desktop-onboarding")
|
|
?.expectedAnyTextIncludes,
|
|
).toEqual(
|
|
expect.arrayContaining(["Swipe for apps", "Sign in to Eliza Cloud"]),
|
|
);
|
|
expect(
|
|
matrix.find((s) => s.id === "desktop-shell")?.expectedAnyTextIncludes,
|
|
).toEqual(expect.arrayContaining(["Settings", "Backend Unreachable"]));
|
|
expect(
|
|
matrix.find((s) => s.id === "mobile-chat")?.expectedAnyTextIncludes,
|
|
).toEqual(expect.arrayContaining(["Pull chat up", "Backend Unreachable"]));
|
|
});
|
|
it("only exercises the keyboard-adjacent composer on mobile", () => {
|
|
const focused = matrix.filter((s) => s.focusComposer);
|
|
expect(focused).toHaveLength(2);
|
|
expect(focused.every((s) => s.viewport === "mobile")).toBe(true);
|
|
expect(focused.map((s) => s.id)).toEqual([
|
|
"mobile-onboarding-composer-focused",
|
|
"mobile-composer-focused",
|
|
]);
|
|
expect(focused.map((s) => s.seed)).toEqual(["fresh", "onboarded"]);
|
|
expect(focused.map((s) => s.route)).toEqual(["/", "/chat"]);
|
|
});
|
|
it("gives every state a unique id", () => {
|
|
const ids = matrix.map((s) => s.id);
|
|
expect(new Set(ids).size).toBe(ids.length);
|
|
});
|
|
});
|
|
|
|
describe("buildCaptureUrl", () => {
|
|
it("joins routes against a base with or without a trailing slash", () => {
|
|
expect(buildCaptureUrl("http://127.0.0.1:2138", "/views")).toBe(
|
|
"http://127.0.0.1:2138/views",
|
|
);
|
|
expect(buildCaptureUrl("http://127.0.0.1:2138/", "/chat")).toBe(
|
|
"http://127.0.0.1:2138/chat",
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("aggregateVerdict", () => {
|
|
it("passes when every state is under the blue ceiling", () => {
|
|
const v = aggregateVerdict([
|
|
{ id: "a", color_fractions: { blue_fraction: 0 } },
|
|
{ id: "b", color_fractions: { blue_fraction: 0.01 } },
|
|
]);
|
|
expect(v.pass).toBe(true);
|
|
expect(v.offenders).toEqual([]);
|
|
});
|
|
it("fails and names the offending state when blue exceeds the ceiling", () => {
|
|
const v = aggregateVerdict([
|
|
{ id: "clean", color_fractions: { blue_fraction: 0.0 } },
|
|
{ id: "bluish", color_fractions: { blue_fraction: 0.15 } },
|
|
]);
|
|
expect(v.pass).toBe(false);
|
|
expect(v.offenders.map((o) => o.id)).toEqual(["bluish"]);
|
|
});
|
|
it("fails closed when a capture has no measured blue fraction", () => {
|
|
const v = aggregateVerdict([{ id: "x" }]);
|
|
expect(v.pass).toBe(false);
|
|
expect(v.offenders).toEqual([
|
|
{ id: "x", blue: null, reason: "blue_fraction not measured" },
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe("seedDriftOffenders", () => {
|
|
it("passes when the seeded shell differs materially from the first-run surface", () => {
|
|
expect(
|
|
seedDriftOffenders([
|
|
{ viewport: "desktop", changedFraction: 0.41 },
|
|
{ viewport: "mobile", changedFraction: 0.35 },
|
|
]),
|
|
).toEqual([]);
|
|
});
|
|
it("flags a viewport whose seeded shell re-rendered the first-run surface", () => {
|
|
const offenders = seedDriftOffenders([
|
|
{ viewport: "desktop", changedFraction: 0.41 },
|
|
{ viewport: "mobile", changedFraction: 0.001 },
|
|
]);
|
|
expect(offenders).toEqual([{ viewport: "mobile", changedFraction: 0.001 }]);
|
|
});
|
|
it("treats an unmeasured delta as drift, never as a pass", () => {
|
|
expect(seedDriftOffenders([{ viewport: "desktop" }])).toEqual([
|
|
{ viewport: "desktop", changedFraction: undefined },
|
|
]);
|
|
});
|
|
it("preserves the reason when a seed-drift measurement could not run", () => {
|
|
expect(
|
|
seedDriftOffenders([
|
|
{
|
|
viewport: "desktop",
|
|
changedFraction: undefined,
|
|
reason: "missing onboarding or shell capture",
|
|
},
|
|
]),
|
|
).toEqual([
|
|
{
|
|
viewport: "desktop",
|
|
changedFraction: undefined,
|
|
reason: "missing onboarding or shell capture",
|
|
},
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe("buildOverallVerdict", () => {
|
|
it("passes only when color, capture readiness, and seed drift all pass", () => {
|
|
expect(
|
|
buildOverallVerdict({
|
|
colorVerdict: { pass: true },
|
|
captureFailures: [],
|
|
driftOffenders: [],
|
|
}).pass,
|
|
).toBe(true);
|
|
});
|
|
|
|
it("fails when a capture is invalid even if color analysis passes", () => {
|
|
const verdict = buildOverallVerdict({
|
|
colorVerdict: { pass: true },
|
|
captureFailures: [
|
|
{
|
|
id: "mobile-composer-focused",
|
|
failedChecks: [{ name: "composer:focus_and_type", ok: false }],
|
|
},
|
|
],
|
|
driftOffenders: [],
|
|
});
|
|
expect(verdict.pass).toBe(false);
|
|
expect(verdict.colorPass).toBe(true);
|
|
expect(verdict.captureFailures.map((f) => f.id)).toEqual([
|
|
"mobile-composer-focused",
|
|
]);
|
|
});
|
|
|
|
it("fails when the onboarded seed drifts back to the first-run surface", () => {
|
|
const verdict = buildOverallVerdict({
|
|
colorVerdict: { pass: true },
|
|
captureFailures: [],
|
|
driftOffenders: [{ viewport: "mobile", changedFraction: 0.001 }],
|
|
});
|
|
expect(verdict.pass).toBe(false);
|
|
expect(verdict.driftOffenders.map((o) => o.viewport)).toEqual(["mobile"]);
|
|
});
|
|
});
|
|
|
|
describe("evaluateCaptureReadiness", () => {
|
|
it("passes for a nonblank state with visible DOM text", () => {
|
|
const v = evaluateCaptureReadiness({
|
|
state: { id: "desktop-shell" },
|
|
domText: "Backend Unreachable Try again",
|
|
});
|
|
expect(v.pass).toBe(true);
|
|
});
|
|
|
|
it("requires each expected text fragment for state-specific captures", () => {
|
|
const state = {
|
|
id: "desktop-onboarding",
|
|
expectedTextIncludes: ["Swipe for apps", "Pull chat up"],
|
|
};
|
|
expect(
|
|
evaluateCaptureReadiness({
|
|
state,
|
|
domText: "Good night. Swipe for apps. Pull chat up.",
|
|
}).pass,
|
|
).toBe(true);
|
|
const v = evaluateCaptureReadiness({
|
|
state,
|
|
domText: "Good night. Ask Dev Smoke.",
|
|
});
|
|
expect(v.pass).toBe(false);
|
|
expect(v.checks.filter((c) => c.name === "dom:expected_text")).toEqual([
|
|
{
|
|
name: "dom:expected_text",
|
|
ok: false,
|
|
detail: 'visible DOM text does not contain "Swipe for apps"',
|
|
},
|
|
{
|
|
name: "dom:expected_text",
|
|
ok: false,
|
|
detail: 'visible DOM text does not contain "Pull chat up"',
|
|
},
|
|
]);
|
|
});
|
|
|
|
it("accepts any one of the configured degraded chat surfaces", () => {
|
|
const state = {
|
|
id: "mobile-chat",
|
|
expectedAnyTextIncludes: ["Pull chat up", "Backend Unreachable"],
|
|
};
|
|
expect(
|
|
evaluateCaptureReadiness({
|
|
state,
|
|
domText: "Startup failed: Backend Unreachable. Open App.",
|
|
}).pass,
|
|
).toBe(true);
|
|
const v = evaluateCaptureReadiness({
|
|
state,
|
|
domText: "Settings Wallet Tasks",
|
|
});
|
|
expect(v.pass).toBe(false);
|
|
expect(v.checks).toContainEqual({
|
|
name: "dom:expected_any_text",
|
|
ok: false,
|
|
detail:
|
|
'visible DOM text does not contain any of "Pull chat up", "Backend Unreachable"',
|
|
});
|
|
});
|
|
|
|
it("fails blank captures before color heuristics can hide them", () => {
|
|
const v = evaluateCaptureReadiness({
|
|
state: { id: "desktop-shell" },
|
|
domText: " ",
|
|
});
|
|
expect(v.pass).toBe(false);
|
|
expect(v.checks.map((c) => c.name)).toContain("dom:not_blank");
|
|
});
|
|
|
|
it("requires the mobile composer probe to survive focus and typing", () => {
|
|
const state = {
|
|
id: "mobile-composer-focused",
|
|
expectedComposerText: COMPOSER_PROBE_TEXT,
|
|
};
|
|
expect(
|
|
evaluateCaptureReadiness({
|
|
state,
|
|
domText: "Sign in to Eliza Cloud",
|
|
composerText: COMPOSER_PROBE_TEXT,
|
|
}).pass,
|
|
).toBe(true);
|
|
expect(
|
|
evaluateCaptureReadiness({
|
|
state,
|
|
domText: "Sign in to Eliza Cloud",
|
|
composerText: "",
|
|
}).pass,
|
|
).toBe(false);
|
|
});
|
|
});
|