mirror of
https://github.com/hanzo-apps/hanzo.ai.git
synced 2026-10-29 07:20:43 +00:00
The mocks of the app's reads move with the addresses they answer. Claude-Session: https://claude.ai/code/session_017vrVus6PPBgP5YRzKV1iqW
83 lines
4.1 KiB
TypeScript
83 lines
4.1 KiB
TypeScript
// The customize directory, DRAWING THE ORG'S OWN LISTS.
|
|
//
|
|
// `directory.spec.ts` holds the taxonomy and the not-asked empty states — what
|
|
// the panel shows a reader with nothing connected. This file holds the other
|
|
// half, the one the wiring in `Directory.tsx` exists for: when the org HAS
|
|
// connected an app, a channel, a plugin and a skill, each tab draws those rows
|
|
// from its registry rather than a hand-typed list.
|
|
//
|
|
// It is a real drive of :3000 — the panel is opened the way a reader opens it,
|
|
// and the rows are read off the rendered DOM. The four registry reads are
|
|
// answered locally (the same `answer`/route shape `chat-thread` and `session`
|
|
// already use), because "this org connected Slack" is a fact about an account
|
|
// no test should need, and the subject here is whether the panel RENDERS what a
|
|
// registry returns — not whether this laptop happens to have Slack connected.
|
|
//
|
|
// BASE_URL=http://localhost:3000 pnpm exec playwright test --project=chromium e2e/directory-live.spec.ts
|
|
|
|
import { test, expect } from '@playwright/test'
|
|
import { directory, open, shot } from './app'
|
|
import { signIn } from './session'
|
|
|
|
test.describe.configure({ timeout: 240_000 })
|
|
|
|
/** One connected account per registry, shaped as each endpoint answers it. */
|
|
const CONNECTORS = { connectors: [{ provider: 'github-copilot' }] }
|
|
const CHANNELS = {
|
|
providers: [
|
|
{ id: 'slack', name: 'Slack', category: 'Communication', available: true, connected: true, connection: { account: 'The Foundation' } },
|
|
],
|
|
}
|
|
const PLUGINS = { plugins: [{ name: 'search', enabled: true, prefixes: ['/search'] }] }
|
|
const SKILLS = { tools: [{ id: 'summarize', name: 'Summarize', publisher: 'Hanzo' }] }
|
|
|
|
test.describe('the customize directory draws the org registries', () => {
|
|
test('each tab renders the row its registry returns', async ({ page }) => {
|
|
await signIn(page, { org: 'hanzo' })
|
|
|
|
// The four org-scoped reads, answered before the panel asks. Globs match
|
|
// whatever host `NEXT_PUBLIC_HANZO_API_URL` resolved to.
|
|
const json = (body: unknown) => (route: import('@playwright/test').Route) =>
|
|
route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(body) })
|
|
await page.route('**/v1/connection', json(CONNECTORS))
|
|
await page.route('**/v1/provider', json(CHANNELS))
|
|
await page.route('**/v1/tools/plugins', json(PLUGINS))
|
|
await page.route('**/v1/tools/skills', json(SKILLS))
|
|
|
|
await open(page, '/chat')
|
|
const panel = await directory(page)
|
|
|
|
// APPS — the public catalog, with the org's connected provider marked. The
|
|
// badge is what the connectors read adds; a catalog with nothing connected
|
|
// draws none, so its presence is the assertion.
|
|
await expect(
|
|
panel.getByLabel('Connected').first(),
|
|
'a connected provider must wear the Connected badge on Apps',
|
|
).toBeVisible({ timeout: 30_000 })
|
|
await shot(page, 'directory-live-apps')
|
|
|
|
// CHANNELS — the id becomes the title, the account label the publisher, the
|
|
// capability map a sentence. All three come from the row, none is invented.
|
|
await panel.getByRole('button', { name: 'Channels', exact: true }).click()
|
|
await expect(panel.getByText('Slack', { exact: true }), 'the channel id titles the row').toBeVisible({
|
|
timeout: 30_000,
|
|
})
|
|
await expect(panel.getByText('The Foundation', { exact: false }), 'the account label is the publisher').toBeVisible()
|
|
await shot(page, 'directory-live-channels')
|
|
|
|
// PLUGINS — the registry name titles the row and its prefixes name what it serves.
|
|
await panel.getByRole('button', { name: 'Plugins', exact: true }).click()
|
|
await expect(panel.getByText('Search', { exact: true }), 'the plugin name titles the row').toBeVisible({
|
|
timeout: 30_000,
|
|
})
|
|
await shot(page, 'directory-live-plugins')
|
|
|
|
// SKILLS — the tools list, whichever key the source used.
|
|
await panel.getByRole('button', { name: 'Skills', exact: true }).click()
|
|
await expect(panel.getByText('Summarize', { exact: true }), 'the skill name titles the row').toBeVisible({
|
|
timeout: 30_000,
|
|
})
|
|
await shot(page, 'directory-live-skills')
|
|
})
|
|
})
|