mirror of
https://github.com/expo/explore.git
synced 2026-11-14 10:08:17 -10:00
Capture on this machine (local iOS simulators and Android emulators, with agent-device or Argent) as well as on EAS Simulator; name several capture targets per config (a phone, a foldable closed and open, Android) and review them in parallel with shared builds; repack locally with a local simulator; and make captures faster and harder to break: controller fault containment, an Argent fold recovery, upright captures of an opened iPhone Duo, a settle after each root reset, a route retry after an adb drop, emulator port reservation, a startup sweep of what interrupted captures leave running, and agent-device 0.21.28.
68 lines
4.1 KiB
JavaScript
68 lines
4.1 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
|
|
const { tsImport } = await import("tsx/esm/api");
|
|
const { claudeDeepLink, codexDeepLink, handoffPageUrl, handoffPrompt } = await tsImport("../../viewer/src/utils/handoff.ts", import.meta.url);
|
|
|
|
const TOKEN = "exwitrhlayedwcxt7ogiwauyiugp4vpk";
|
|
|
|
test("a hosted preview and a local review's Viewer have a link an agent can fetch; other pages do not", () => {
|
|
assert.equal(
|
|
handoffPageUrl(new URL(`https://app-explore--abc.expo.app/p/${TOKEN}?platform=android&screen=x#/map`)),
|
|
`https://app-explore--abc.expo.app/p/${TOKEN}?platform=android`,
|
|
);
|
|
assert.equal(handoffPageUrl(new URL(`https://app-explore--abc.expo.app/p/${TOKEN}/`)), `https://app-explore--abc.expo.app/p/${TOKEN}`);
|
|
assert.equal(handoffPageUrl(new URL("http://127.0.0.1:4319/#/map")), undefined);
|
|
assert.equal(handoffPageUrl(new URL(`http://127.0.0.1:4319/p/${TOKEN}?platform=ios`)), `http://127.0.0.1:4319/p/${TOKEN}?platform=ios`, "a local review's Viewer serves the agent API too");
|
|
assert.equal(handoffPageUrl(new URL("https://explore.expo.app/r?repo=a/b&run=1&attempt=1")), undefined);
|
|
assert.equal(handoffPageUrl(new URL(`https://app-explore--abc.expo.app/p/${TOKEN}?target=duo-open&view=compare&screen=x`)), `https://app-explore--abc.expo.app/p/${TOKEN}?target=duo-open`,
|
|
"a target's link keeps the agent on that target's report");
|
|
});
|
|
|
|
const input = {
|
|
pageUrl: `https://app-explore--abc.expo.app/p/${TOKEN}?platform=android`,
|
|
appName: "euxy",
|
|
pullRequest: { number: 153, title: "Splash", url: "https://github.com/brentvatne/euxy/pull/153", base: { ref: "main" }, head: { ref: "x" } },
|
|
appearances: ["Light", "Dark"],
|
|
};
|
|
|
|
test("the prompt names the pull request, links the report and asks for both appearances", () => {
|
|
const prompt = handoffPrompt(input);
|
|
assert.match(prompt, /^Review the visual changes in PR #153 of brentvatne\/euxy\.\n/);
|
|
assert.ok(prompt.includes(`\n${input.pageUrl}\n`));
|
|
assert.ok(prompt.includes("screenshots in light and dark"));
|
|
assert.ok(!prompt.includes("I'm looking at"));
|
|
});
|
|
|
|
test("the scoped prompt ends with what the reader is looking at", () => {
|
|
const prompt = handoffPrompt(input, { view: "Screens", platform: "Android", appearance: "Light", screen: "/new-pattern" });
|
|
assert.match(prompt, /\n\nI'm looking at: \/new-pattern · Screens · Android · Light$/);
|
|
});
|
|
|
|
test("a report without a pull request is reviewed by app name, in one appearance without the clause", () => {
|
|
const prompt = handoffPrompt({ ...input, pullRequest: undefined, appearances: ["Light"] });
|
|
assert.match(prompt, /^Review this Expo Explore report of euxy\./);
|
|
assert.ok(prompt.includes("compare the before and after screenshots, and"));
|
|
});
|
|
|
|
test("deep links carry the encoded prompt", () => {
|
|
assert.equal(claudeDeepLink("a & b\nc"), "claude-cli://open?q=a%20%26%20b%0Ac");
|
|
assert.equal(codexDeepLink("a & b\nc"), "codex://new?prompt=a%20%26%20b%0Ac");
|
|
});
|
|
|
|
test("a comparison of two commits is reviewed by its refs", () => {
|
|
const sha = c => c.repeat(40);
|
|
const prompt = handoffPrompt({ ...input, pullRequest: { origin: "compare", title: "v1.4.0 vs v1.3.0",
|
|
url: `https://github.com/brentvatne/euxy/compare/${sha("a")}..${sha("b")}`, base: { ref: "v1.3.0", sha: sha("a") }, head: { ref: "v1.4.0", sha: sha("b") } } });
|
|
assert.match(prompt, /^Review the visual changes from v1\.3\.0 to v1\.4\.0 of brentvatne\/euxy\.\n/);
|
|
});
|
|
|
|
test("a local review is reviewed by its refs, and its prompt says the link is local and lives while capture:review runs", () => {
|
|
const prompt = handoffPrompt({ ...input, pageUrl: `http://127.0.0.1:4319/p/${TOKEN}`,
|
|
pullRequest: { origin: "local", title: "HEAD vs main", base: { ref: "main", sha: "a".repeat(40) }, head: { ref: "HEAD", sha: "b".repeat(40) } } });
|
|
assert.match(prompt, /^Review the visual changes from main to HEAD\.\n/);
|
|
assert.ok(prompt.includes("Fetch the link first (from this machine, with curl if your fetch tool refuses local addresses)."));
|
|
assert.match(prompt, /stops working when it exits\.$/);
|
|
assert.ok(!handoffPrompt(input).includes("this machine"), "a hosted link's prompt is unchanged");
|
|
});
|