Astro + Vite 7 Fixture
+Static Astro page rendered server-side, hydrated nothing.
+diff --git a/package.json b/package.json index ee253fc6e..44805b2ed 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "preview": "bun run build && wrangler pages dev", "deploy": "bun run build && wrangler pages deploy build/", "test": "bun test tests/build.test.js tests/detect-antipatterns.test.js && node --test tests/detect-antipatterns-fixtures.test.mjs && node --test tests/detect-antipatterns-browser.test.mjs && node --test tests/cleanup-deprecated.test.mjs && node --test tests/live-wrap.test.mjs && node --test tests/live-accept.test.mjs && node --test tests/live-inject.test.mjs && node --test tests/live-server.test.mjs && node --test tests/framework-fixtures.test.mjs", + "test:live-e2e": "node --test --test-timeout=600000 tests/live-e2e.test.mjs", "prepack": "cp README.md README.repo.md && cp README.npm.md README.md", "postpack": "cp README.repo.md README.md && rm README.repo.md", "screenshot": "bun run scripts/screenshot-antipatterns.js", diff --git a/tests/framework-fixtures.test.mjs b/tests/framework-fixtures.test.mjs index d447be059..84bb699ff 100644 --- a/tests/framework-fixtures.test.mjs +++ b/tests/framework-fixtures.test.mjs @@ -12,7 +12,7 @@ import { describe, it } from 'node:test'; import assert from 'node:assert/strict'; import { execFileSync } from 'node:child_process'; -import { cpSync, mkdtempSync, readdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'; +import { cpSync, existsSync, mkdtempSync, readdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join, dirname } from 'node:path'; import { fileURLToPath } from 'node:url'; @@ -27,6 +27,7 @@ const FIXTURES_DIR = join(__dirname, 'framework-fixtures'); function listFixtures() { return readdirSync(FIXTURES_DIR, { withFileTypes: true }) .filter((e) => e.isDirectory()) + .filter((e) => existsSync(join(FIXTURES_DIR, e.name, 'fixture.json'))) .map((e) => e.name); } diff --git a/tests/framework-fixtures/README.md b/tests/framework-fixtures/README.md index ad953f3d8..7f7865fcf 100644 --- a/tests/framework-fixtures/README.md +++ b/tests/framework-fixtures/README.md @@ -2,6 +2,8 @@ Representative project shapes for exercising live mode against different framework conventions. Each fixture is a small directory tree that the test harness copies into a temp git repo, then drives `live-inject.mjs`, `live-wrap.mjs`, `live-accept.mjs`, and `is-generated.mjs` against. +Fixtures can also opt into a **runtime E2E** pass that actually installs dependencies, boots the framework dev server, and drives a Playwright browser to verify the live handshake. See the `runtime` block below. + ## Layout ``` @@ -32,12 +34,43 @@ Representative project shapes for exercising live mode against different framewo "signals": ["diagnostic hints — paths where CSP was detected"], "patchTarget": "which file the agent should modify", "expectedAfter": "filename of the reference post-patch output inside this fixture" + }, + "runtime": { + "styling": "plain-css | tailwind-v4 | styled-components | ...", + "install": ["npm", "install"], + "devCommand": ["npm", "run", "dev"], + "scheme": "http", + "ignoreHTTPSErrors": false, + "readyPattern": "Local:\\s+https?://[^:]+:(\\d+)", + "readyTimeoutMs": 120000, + "pickSelector": "h1.hero-title", + "preActions": [ + { "type": "click", "selector": "[data-testid='open-modal']" }, + { "type": "goto", "path": "/about" } + ], + "reloadProbe": { + "preActions": [{ "type": "click", "selector": "[data-testid='open-modal']" }], + "expectSelector": "h1.hero-title" + }, + "probe": { + "expectLiveInit": true, + "expectConsoleClean": true + } } } ``` The `expectedAfter` file lives alongside `fixture.json` (not inside `files/`) and is a human/agent-review reference — tests don't auto-apply the patch. +The `runtime` block is optional. Fixtures without it only run the static unit checks (is-generated, inject, wrap, csp-detect). Fixtures *with* it additionally run the E2E suite in `tests/live-e2e.test.mjs` (`bun run test:live-e2e`), which: + +1. Stages the fixture into a tmp repo. +2. Runs `runtime.install` to install real deps. +3. Starts `live-server.mjs --background` and runs `live-inject.mjs --port` against it. +4. Spawns `runtime.devCommand` and scrapes the port from stdout using `runtime.readyPattern` (the first capture group must be the port). +5. Opens Playwright Chromium at the dev URL and asserts `window.__IMPECCABLE_LIVE_INIT__ === true` (the browser-side handshake oracle) within `runtime.readyTimeoutMs`. +6. Tears everything down (Playwright close, dev server SIGTERM, live-server stop, tmp rm). + ## Current fixtures | Fixture | Shape | diff --git a/tests/framework-fixtures/astro-vite7/files/astro.config.mjs b/tests/framework-fixtures/astro-vite7/files/astro.config.mjs new file mode 100644 index 000000000..fa5bcb799 --- /dev/null +++ b/tests/framework-fixtures/astro-vite7/files/astro.config.mjs @@ -0,0 +1,5 @@ +import { defineConfig } from 'astro/config'; + +export default defineConfig({ + server: { host: '127.0.0.1' }, +}); diff --git a/tests/framework-fixtures/astro-vite7/files/package.json b/tests/framework-fixtures/astro-vite7/files/package.json new file mode 100644 index 000000000..33ba1a69d --- /dev/null +++ b/tests/framework-fixtures/astro-vite7/files/package.json @@ -0,0 +1,14 @@ +{ + "name": "astro-vite7-fixture", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "astro dev --host 127.0.0.1", + "build": "astro build", + "preview": "astro preview" + }, + "devDependencies": { + "astro": "^6.0.0" + } +} diff --git a/tests/framework-fixtures/astro-vite7/files/src/layouts/Layout.astro b/tests/framework-fixtures/astro-vite7/files/src/layouts/Layout.astro new file mode 100644 index 000000000..1c5b88e85 --- /dev/null +++ b/tests/framework-fixtures/astro-vite7/files/src/layouts/Layout.astro @@ -0,0 +1,13 @@ +--- +const { title } = Astro.props; +--- + + +
+ +Static Astro page rendered server-side, hydrated nothing.
+