mirror of
https://github.com/hanzo-apps/hanzo.ai.git
synced 2026-10-29 07:20:43 +00:00
components/family/Splash is the one first screen for a model: its painting across the screen, what kind it is, the release's name as the heading (Zen 6, Koma 1), its line, a sentence and two ways on, light on dark in both themes. The creative pages and /zen both open on it. Under it /zen sets Zen 6 and Zen 7 side by side as cards with their names large, Zen 6's linking to its and Zen 6 Flash's pages under /models; the earlier models the gateway still answers are one row of ids, each a link to its page, and the section that listed every served model by job is gone, with the ZEN word-and-rail figure it opened on. The landing's panels name each model as released (Zen 6, Enso 1, Kai 1, Koma 1), larger.
91 lines
4.1 KiB
TypeScript
91 lines
4.1 KiB
TypeScript
import { expect, test } from '@playwright/test'
|
|
import { DESKS } from '../../components/zen/desks'
|
|
import { NEXT, NOW } from '../../lib/zen'
|
|
import { serveExport } from './export'
|
|
|
|
/**
|
|
* /ZEN TELLS THE WHOLE STORY, AND EVERY NUMBER ON IT HAS A SOURCE.
|
|
*
|
|
* The page opens on its painting and the release's name, then markets two
|
|
* releases, the one that answers and the research preview, each a card with its
|
|
* name large; every earlier Zen model is a link to its own page under /models.
|
|
* Then a run of short headlines, each with the content that backs it: the open
|
|
* lineage, the three machines Hanzo measured, what the board scored, and the
|
|
* one call that reaches it. Held
|
|
* at every width the site designs for, with motion on and with it off — a
|
|
* reduced-motion reader gets every word and every figure, finished.
|
|
*/
|
|
const WIDTHS = [375, 430, 768, 1024, 1440, 1728] as const
|
|
|
|
const HEADLINES = [
|
|
NOW.name,
|
|
NEXT.name,
|
|
`${NOW.name}.`,
|
|
'Laptop-sized.',
|
|
'On your desk.',
|
|
'Weights don',
|
|
'Seven generations. One line.',
|
|
'Scored where',
|
|
'Any SDK.',
|
|
'survive your vendor.',
|
|
] as const
|
|
|
|
test.describe('/zen', () => {
|
|
let base: string
|
|
let stop: () => Promise<void>
|
|
test.beforeAll(async () => {
|
|
const served = await serveExport()
|
|
base = served.url
|
|
stop = served.close
|
|
})
|
|
test.afterAll(async () => stop())
|
|
|
|
for (const width of WIDTHS) {
|
|
test(`at ${width}px it tells the story with nothing off the side`, async ({ page }) => {
|
|
const errors: string[] = []
|
|
page.on('pageerror', (e) => errors.push(String(e)))
|
|
page.on('console', (m) => m.type() === 'error' && errors.push(m.text()))
|
|
await page.setViewportSize({ width, height: 900 })
|
|
await page.goto(`${base}/zen`, { waitUntil: 'domcontentloaded' })
|
|
|
|
const heads = (await page.locator('h1, h2').allInnerTexts()).join(' \n ')
|
|
for (const h of HEADLINES) expect(heads, `a headline that says "${h}"`).toContain(h)
|
|
|
|
// The three machines, each with its two readings in tabular figures.
|
|
const desks = page.locator('#desks')
|
|
for (const d of DESKS) {
|
|
await expect(desks.getByRole('heading', { name: d.machine })).toBeVisible()
|
|
await expect(desks).toContainText(d.prefill)
|
|
await expect(desks).toContainText(d.decode)
|
|
}
|
|
const figure = desks.getByText(DESKS[0].prefill, { exact: true })
|
|
expect(await figure.evaluate((el) => getComputedStyle(el).fontVariantNumeric)).toContain('tabular-nums')
|
|
|
|
// No Hanzo score of the family is a research run yet, so none is printed; Zen 6 is not on a board either.
|
|
const scored = page.locator('#scored')
|
|
await expect(scored).toContainText('none is filed yet, so this page shows none')
|
|
await expect(scored).not.toContainText('GPQA-Diamond')
|
|
await expect(scored).toContainText(`${NOW.name} is not on the board yet`)
|
|
|
|
expect(await page.evaluate(() => document.documentElement.scrollWidth > document.documentElement.clientWidth + 1)).toBe(false)
|
|
expect(errors, errors.join('\n')).toEqual([])
|
|
})
|
|
}
|
|
|
|
test('it opens on the painting and the release, and links every earlier model to its own page', async ({ page }) => {
|
|
await page.setViewportSize({ width: 1440, height: 900 })
|
|
await page.goto(`${base}/zen`, { waitUntil: 'domcontentloaded' })
|
|
await expect(page.locator('h1')).toHaveText(NOW.name)
|
|
await expect(page.locator('section').first().locator('img')).toHaveAttribute('src', '/images/models/zen.webp')
|
|
await expect(page.getByText('Open models. Yours to run.')).toBeVisible()
|
|
const now = page.locator('#now')
|
|
await expect(now.getByRole('heading', { name: NOW.name, exact: true })).toBeVisible()
|
|
await expect(now.getByRole('heading', { name: NEXT.name, exact: true })).toBeVisible()
|
|
const earlier = await now.locator('a[href^="/models/"]').evaluateAll((as) => as.map((a) => a.getAttribute('href')!))
|
|
expect(earlier.length).toBeGreaterThan(4)
|
|
for (const href of earlier) expect(href).toMatch(/^\/models\/[^/]+\/[^/]+$/)
|
|
// No section markets the earlier models one by one.
|
|
await expect(page.getByRole('heading', { name: /Every sense/ })).toHaveCount(0)
|
|
})
|
|
})
|