fast-browser-with-jev
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Runtime live validation __TAB__</title>
|
||||
<style>
|
||||
body { font: 16px system-ui, sans-serif; margin: 2rem; max-width: 42rem; }
|
||||
button { display: block; margin: 1rem 0; padding: .5rem .8rem; }
|
||||
input { display: block; min-width: 20rem; padding: .4rem; }
|
||||
</style>
|
||||
</head>
|
||||
<body data-tab="__TAB__">
|
||||
<h1>Runtime fixture __TAB__</h1>
|
||||
<p id="ready">Initial runtime fixture __TAB__</p>
|
||||
<p id="readable">READABLE_SENTINEL___TAB__</p>
|
||||
<label for="private-input">Input sentinel</label>
|
||||
<input id="private-input" value="READ_INPUT_SENTINEL___TAB__" autocomplete="off">
|
||||
<button id="popup" type="button">Open popup</button>
|
||||
<script>
|
||||
const tab = document.body.dataset.tab;
|
||||
const peerOrigin = __PEER_ORIGIN__;
|
||||
const selfOrigin = __SELF_ORIGIN__;
|
||||
const ready = document.getElementById("ready");
|
||||
const popup = document.getElementById("popup");
|
||||
const consoleMarker = `RUNTIME_LIVE_CONSOLE_${tab}`;
|
||||
const networkPath = `/runtime-live-network-${tab}`;
|
||||
const shouldEmitDiagnostics = tab === "A" || new URL(window.location.href).searchParams.get("emit") === "1";
|
||||
|
||||
// These are intentionally owned-local requests. They produce origin-only
|
||||
// evidence, while the console markers distinguish the two tabs. Tab B is
|
||||
// silent until the validator explicitly navigates it with emit=1.
|
||||
if (shouldEmitDiagnostics) {
|
||||
console.error(consoleMarker);
|
||||
void fetch(`${selfOrigin}${networkPath}?sentinel=${encodeURIComponent(consoleMarker)}`);
|
||||
if (tab === "A" && new URL(window.location.href).searchParams.get("thirdparty") === "1") {
|
||||
void fetch(`${peerOrigin}/runtime-live-third-party?sentinel=RUNTIME_LIVE_THIRD_PARTY_A`);
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
ready.textContent = `ASSERT_READY_${tab}`;
|
||||
}, 150);
|
||||
|
||||
popup.addEventListener("click", () => {
|
||||
if (tab === "A") {
|
||||
ready.textContent = "POPUP_OPEN_REQUESTED";
|
||||
window.open(`${peerOrigin}/runtime-live-validation.html?tab=B`, "runtime-live-popup", "popup,width=640,height=480");
|
||||
}
|
||||
});
|
||||
|
||||
if (new URL(window.location.href).searchParams.get("tab") === "NAV") {
|
||||
ready.textContent = "NAVIGATION_READY";
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,69 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Fast browser development fixture</title>
|
||||
<style>
|
||||
body { font: 16px system-ui, sans-serif; margin: 2rem; max-width: 42rem; }
|
||||
label, input, button { display: block; margin: .6rem 0; }
|
||||
input { min-width: 18rem; padding: .4rem; }
|
||||
button { padding: .5rem .8rem; }
|
||||
#status { min-height: 1.5rem; }
|
||||
</style>
|
||||
</head>
|
||||
<body data-mode="__MODE__" data-retained="__RETAINED__" data-cookie-check="__COOKIE_CHECK__" data-cookie-forbid="__COOKIE_FORBID__">
|
||||
<h1>Fast browser local development fixture</h1>
|
||||
<p id="status">__INITIAL_STATUS__</p>
|
||||
<label for="display-name">Display name</label>
|
||||
<input id="display-name" name="display-name" type="text" autocomplete="off">
|
||||
<button id="action" type="button">__BUTTON_LABEL__</button>
|
||||
<script>
|
||||
const readyCase = __READY_CASE__;
|
||||
const body = document.body;
|
||||
const status = document.getElementById("status");
|
||||
const input = document.getElementById("display-name");
|
||||
const button = document.getElementById("action");
|
||||
let retained = body.dataset.retained === "true";
|
||||
const cookieCheck = body.dataset.cookieCheck;
|
||||
const cookieForbid = body.dataset.cookieForbid;
|
||||
if (cookieCheck) {
|
||||
const names = document.cookie.split(";").map((item) => item.trim().split("=", 1)[0]);
|
||||
retained = names.includes(cookieCheck) && (!cookieForbid || !names.includes(cookieForbid));
|
||||
body.dataset.retained = String(retained);
|
||||
}
|
||||
|
||||
button.addEventListener("click", () => {
|
||||
if (body.dataset.mode === "retained" && retained && input.value === "Milestone") {
|
||||
status.textContent = "Retained session verified";
|
||||
} else if (body.dataset.mode === "headless" && input.value === "Ada") {
|
||||
status.textContent = "Headless bounded action verified";
|
||||
} else if (body.dataset.mode === "isolation-a" && retained) {
|
||||
status.textContent = "Profile A isolated";
|
||||
} else if (body.dataset.mode === "isolation-b" && retained) {
|
||||
status.textContent = "Profile B isolated";
|
||||
} else {
|
||||
status.textContent = "Fixture action did not meet its bounded condition";
|
||||
}
|
||||
if (body.dataset.mode === "retained") {
|
||||
void fetch(`/automation-outcome?status=${encodeURIComponent(status.textContent ?? "")}`, { cache: "no-store" }).catch(() => {});
|
||||
}
|
||||
});
|
||||
|
||||
async function notifyReady() {
|
||||
if (!readyCase) return;
|
||||
for (let attempt = 0; attempt < 50; attempt += 1) {
|
||||
try {
|
||||
const response = await fetch(`/ready?case=${encodeURIComponent(readyCase)}`, { cache: "no-store" });
|
||||
if (response.ok) return;
|
||||
} catch (_) {
|
||||
// The local server is expected to be available; the finite retry is
|
||||
// only for the first renderer turn while the fixture is starting.
|
||||
}
|
||||
await new Promise((resolve) => setTimeout(resolve, 50));
|
||||
}
|
||||
}
|
||||
void notifyReady();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,26 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head><meta charset="utf-8"><title>Fast Browser local test fixture</title></head>
|
||||
<body>
|
||||
<h1>Fast Browser test fixture</h1>
|
||||
<p>This page stores nothing, makes no requests, and never submits a form.</p>
|
||||
<label for="display-name">Display name</label>
|
||||
<input id="display-name" type="text" autocomplete="off">
|
||||
<p><label for="greeting">Demo greeting</label></p>
|
||||
<textarea id="greeting" rows="3" cols="60" placeholder="Generated text can go here"></textarea>
|
||||
<p><button id="continue" type="button">Continue</button></p>
|
||||
<p id="result" role="status"></p>
|
||||
<label for="hidden-secret" hidden>Hidden secret</label>
|
||||
<input id="hidden-secret" hidden value="must-not-be-observed">
|
||||
<label for="password">Test password</label>
|
||||
<input id="password" type="password" autocomplete="off">
|
||||
<button type="button" disabled>Unavailable action</button>
|
||||
<script>
|
||||
document.getElementById('continue').addEventListener('click', () => {
|
||||
document.getElementById('result').textContent =
|
||||
document.getElementById('display-name').value === 'Ada'
|
||||
? 'Fixture complete' : 'Enter Ada to complete the fixture';
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,24 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head><meta charset="utf-8"><title>Fast Browser test login</title></head>
|
||||
<body>
|
||||
<h1>Local test-account login</h1>
|
||||
<p>This disposable fixture sends no requests and stores no credentials.</p>
|
||||
<form id="login">
|
||||
<label for="username">Username</label>
|
||||
<input id="username" name="username" autocomplete="off">
|
||||
<label for="password">Password</label>
|
||||
<input id="password" name="password" type="password" autocomplete="off">
|
||||
<button type="submit">Sign in</button>
|
||||
</form>
|
||||
<p id="status" role="status"></p>
|
||||
<script>
|
||||
document.getElementById('login').addEventListener('submit', (event) => {
|
||||
event.preventDefault();
|
||||
const accepted = document.getElementById('username').value === 'demo-user'
|
||||
&& document.getElementById('password').value === 'demo-password';
|
||||
document.getElementById('status').textContent = accepted ? 'Test login complete' : 'Test login failed';
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,8 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head><meta charset="utf-8"><title>Fast Browser scenario popup</title></head>
|
||||
<body>
|
||||
<h1>Scenario popup</h1>
|
||||
<p id="status" role="status">Popup ready</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,9 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head><meta charset="utf-8"><title>Fast Browser scenario next page</title></head>
|
||||
<body>
|
||||
<h1>Scenario navigation destination</h1>
|
||||
<p id="status" role="status">Navigation complete</p>
|
||||
<a href="/scenario-suite.html">Back to scenario suite</a>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,30 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head><meta charset="utf-8"><title>Fast Browser scenario suite</title></head>
|
||||
<body>
|
||||
<h1>Fast Browser local scenario suite</h1>
|
||||
<p id="status" role="status">Scenario fixture ready</p>
|
||||
<button id="delayed" type="button">Show delayed state</button>
|
||||
<button id="popup" type="button">Open local popup</button>
|
||||
<button id="console-error" type="button">Emit controlled console error</button>
|
||||
<button id="failed-request" type="button">Request controlled failure</button>
|
||||
<a id="navigate" href="/scenario-suite-next.html">Navigate local fixture</a>
|
||||
<script>
|
||||
document.getElementById('delayed').addEventListener('click', () => {
|
||||
setTimeout(() => { document.getElementById('status').textContent = 'Delayed state ready'; }, 100);
|
||||
});
|
||||
document.getElementById('popup').addEventListener('click', () => {
|
||||
document.getElementById('status').textContent = 'Popup opened';
|
||||
window.open('/scenario-popup.html', 'fast-browser-scenario-popup', 'popup,width=480,height=320');
|
||||
});
|
||||
document.getElementById('console-error').addEventListener('click', () => {
|
||||
console.error('controlled local scenario failure');
|
||||
});
|
||||
document.getElementById('failed-request').addEventListener('click', () => {
|
||||
fetch('/controlled-failure', { cache: 'no-store' }).catch(() => {
|
||||
document.getElementById('status').textContent = 'Controlled request failed';
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user