phase: 02_simulate_fetch_commands
Build and Push Container / build-and-push (push) Successful in 26s
Build and Push Container / build-and-push (push) Successful in 26s
All green. Final report: **Phase 02 — final verification pass** (both tasks already in `.agents/phases/complete/02_simulate_fetch_commands/`) - Verified: no `fetch(` remains in `src/` (grep exit 1) or in built `dist/*.js` - Verified: `simulatedCurlOutput()` / `simulatedWgetOutput()` in `src/terminal-commands.js` (lines 63/73), wired into `src/terminal.js` curl/wget branches - Verified: regression test `curl/wget are simulated — no real network request leaves the origin` in `tests/e2e/02-terminal.spec.js` — asserts simulated bodies, `web_navigator` toast + localStorage persistence, and zero non-`baseURL` requests - Tests: `./build.sh` → OK; `npm test` → **46 passed, 0 failed** (≥46 required); `bash .agents/validate.sh` → **exit 0** (E2E + repo-hygiene gates) - No linter configured beyond validate.sh (vanilla JS, LOCKED no-toolchain) - Completion criteria: ①no `fetch(` ✅ ②simulators present ✅ ③regression tests present & passing ✅ ④build+test 46 green ✅ ⑤no behavior change (page/terminal/vim/achievements/menu suites all green) ✅ - Documentation: full README/AGENTS.md review — both already updated in working tree and consistent with the project (simulated curl/wget, validate.sh gate, Podman build flow vs Dockerfile, Node ≥20 matches `@playwright/test` engines, M-4 header gap correctly documented as pending Phase 03) — **verified consistent, no changes needed** - Note: `PLAN.md` still says "44 tests" (now 46) but PLAN is locked — flagged for the harness/user, not edited - Next pending phase: `03_nginx_security_headers`
This commit is contained in:
@@ -267,6 +267,39 @@ test.describe('Fake terminal — state and special commands', () => {
|
||||
await expect(page.locator('body input')).toHaveCount(1);
|
||||
});
|
||||
|
||||
// Regression guard for audit finding M-2: curl/wget used to `fetch()` the
|
||||
// URL typed by the visitor — a client-side request-forgery primitive.
|
||||
// They must render simulated output and touch the network zero times.
|
||||
test('curl/wget are simulated — no real network request leaves the origin', async ({ page }, testInfo) => {
|
||||
// Track every request that is NOT aimed at the test origin. The origin
|
||||
// is read from `baseURL` (playwright.config.js) so the two cannot drift.
|
||||
const ORIGIN = testInfo.project.use.baseURL || 'http://127.0.0.1:8123';
|
||||
const external = [];
|
||||
page.on('request', (r) => {
|
||||
if (!r.url().startsWith(ORIGIN)) external.push(r.url());
|
||||
});
|
||||
|
||||
await typeCommand(page, 'curl https://example.com/hello');
|
||||
// achievement fires on the first curl/wget (toasts auto-remove ~4.3 s)
|
||||
await expect(page.locator('.toast').filter({ hasText: 'Web Navigator' })).toBeVisible();
|
||||
const curlLine = terminalLines(page).nth(-2);
|
||||
await expect(curlLine).toContainText('simulated body for https://example.com/hello');
|
||||
|
||||
await typeCommand(page, 'wget https://example.org/file.txt');
|
||||
const wgetLine = terminalLines(page).nth(-2);
|
||||
await expect(wgetLine).toContainText('No real network request was made');
|
||||
await expect(wgetLine).toContainText('https://example.org/file.txt');
|
||||
|
||||
// Let the simulated 400 ms response delay (and any pre-fix fetch) settle
|
||||
// before asserting that nothing ever left the origin.
|
||||
await page.waitForTimeout(800);
|
||||
expect(external, `requests left the origin: ${external.join(', ')}`).toEqual([]);
|
||||
|
||||
// The achievement itself is persisted, not just toasted.
|
||||
const stored = await page.evaluate(k => JSON.parse(localStorage.getItem(k) || '[]'), 'reese-terminal-achievements');
|
||||
expect(stored).toContain('web_navigator');
|
||||
});
|
||||
|
||||
test('backspace edits the current command', async ({ page }) => {
|
||||
await page.keyboard.type('hostnamex');
|
||||
await page.keyboard.press('Backspace');
|
||||
|
||||
Reference in New Issue
Block a user