Files
hanzo.ai/e2e/smoke.spec.ts
zeekayandHanzo Dev 9bbdc64ee0 One /dev: the builder is platform.hanzo.ai/dev
This export carried a second copy of the builder at /dev — the composer,
a run's transcript and a project pane (app/(app)/dev and
components/workspace/{Build,Session,project}.tsx), plus DevStudio.tsx and
enter.ts, which nothing else used. They are deleted, and dev.hanzo.ai is no
longer published from this export.

Every link to the builder is DEV or dev(ref) from lib/host.ts. dev() carries
a run id or a project slug into the path only when it is exactly one, so no
caller can make it name another address. The shell's Dev tile, Projects and
Runs open it there; /code forwards there. The edge's permanent redirects for
hanzo.ai/dev, /code, dev.hanzo.ai and hanzo.app live in universe.

Gates and specs that drove the old /dev drive /chat where they tested the
shared shell, and are removed where the builder itself was the subject.



Co-authored-by: Hanzo Dev <[email protected]>
2026-09-24 15:53:59 -07:00

43 lines
1.5 KiB
TypeScript

import { expect, test } from '@playwright/test'
import { signIn } from './session'
/**
* EVERY ROOM DRAWS ITS OWN AFFORDANCE.
*
* The responsive gate says the shell holds its shape; this says the room has
* something in it — a blank pane and a broken one both "hold" at every width.
* Each expectation is the thing that room is FOR, so a room that loses its
* point fails here rather than looking fine.
*
* Runs against whatever BASE_URL names, so the same assertions answer for a dev
* server and for production.
*/
const ROOMS: [string, RegExp][] = [
['/work', /working|no runs yet|start a run/i],
['/inbox', /inbox|nothing has arrived/i],
['/drive', /drive/i],
['/board', /board/i],
]
for (const [route, wants] of ROOMS) {
test(`${route} draws its own affordance`, async ({ page }) => {
await signIn(page)
await page.setViewportSize({ width: 1440, height: 900 })
await page.goto(route)
await page.waitForLoadState('domcontentloaded')
await page.waitForLoadState('networkidle').catch(() => {})
const room = page.locator('main')
await expect(room).toBeVisible({ timeout: 20_000 })
await expect
.poll(async () => (await room.innerText()).replace(/\s+/g, ' '), { timeout: 20_000 })
.toMatch(wants)
// And nothing in it is the estate talking to itself.
const text = await room.innerText()
for (const leak of ['no instance running', 'ECONNREFUSED', 'Load failed']) {
expect(text, `"${leak}" is plumbing, not an answer`).not.toContain(leak)
}
})
}