ConusAI vendor v0.1.0-beta.114
ci / gate (push) Waiting to run

This commit is contained in:
ConusAI vendor v0.1.0-beta.114
2026-11-14 09:56:45 +00:00
commit 1ce8d23c35
867 changed files with 122104 additions and 0 deletions
+184
View File
@@ -0,0 +1,184 @@
// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
// What every spec does: sign in through the dev adapter, call a procedure the way the page's own
// forms do (with the page's CSRF token), and make an organization to work in.
import { randomBytes } from "node:crypto"
import { type APIRequestContext, expect, type Page } from "@playwright/test"
import axe from "axe-core"
export const unique = (prefix: string): string => `${prefix}-${randomBytes(3).toString("hex")}`
/**
* Waits until the page is interactive: the shell sets `data-hydrated` on <html> once React has hydrated it
* (`apps/web/src/ui/hydrated.ts`). A click or a key before that is lost, so act after this, not in a retry loop.
*/
export async function ready(page: Page): Promise<void> {
await expect(page.locator("html")).toHaveAttribute("data-hydrated", "true")
}
/** Signs in as `email` (created on first use) and lands on the home page, ready to be used. */
export async function signIn(page: Page, email: string): Promise<void> {
await page.goto(`/auth/dev-login?email=${encodeURIComponent(email)}`)
await expect(page.locator('meta[name="csrf-token"]')).toHaveCount(1)
await ready(page)
}
/** The CSRF token of the page the browser is on: what the page's own forms send back. */
const csrfOf = (page: Page): Promise<string> =>
page
.locator('meta[name="csrf-token"]')
.getAttribute("content")
.then((value) => value ?? "")
/** Calls a procedure with the session of `page`. Throws on a refusal, with the problem's own words. */
export async function call<T = unknown>(page: Page, procedure: string, input: unknown): Promise<T> {
const response = await callRaw(page.request, await csrfOf(page), procedure, input)
const body = (await response.json().catch(() => null)) as T
if (!response.ok()) throw new Error(`${procedure} answered ${response.status()}: ${JSON.stringify(body)}`)
return body
}
export const callRaw = (request: APIRequestContext, csrf: string, procedure: string, input: unknown) =>
request.post(`/api/v1/${procedure}`, {
data: input,
headers: { "x-csrf-token": csrf, "content-type": "application/json", "sec-fetch-site": "same-origin" },
})
export interface Workspace {
/** The organization's id: the app tenant a business-service binding names. */
orgId: string
org: string
workspace: string
project: string
}
/** The signed-in user's own organization with one workspace and one project. */
export async function makeOrganization(page: Page, prefix = "acme"): Promise<Workspace> {
const org = unique(prefix)
const { orgId } = await call<{ orgId: string }>(page, "tenancy.org.create", { slug: org, name: `Org ${org}` })
const workspace = (
await call<{ slug: string }>(page, "tenancy.workspace.create", {
org,
slug: "main",
name: "Main",
visibility: "org",
})
).slug
const project = (
await call<{ slug: string }>(page, "tenancy.project.create", {
org,
workspace,
slug: "review",
name: "Review",
moduleKey: "documents",
})
).slug
return { orgId, org, workspace, project }
}
/**
* Binds an organization to the deployment on the fake platform, with exactly the service scopes the app's selected
* business modules declare (`declaredBusinessScopes`, as `pnpm dev` binds its demo organizations). In Cloud this is a
* project administrator's explicit act, and a lookup never creates a binding; a spec does it on purpose, after it has
* seen the refusal an unbound organization gets.
*/
export async function bindBusinessServices(
orgId: string,
grants: Readonly<Record<string, readonly string[]>>,
): Promise<void> {
const base = process.env.E2E_PLATFORM_URL
if (!base) throw new Error("e2e: E2E_PLATFORM_URL is set by the global setup")
const response = await fetch(`${base}/__e2e/app-bindings`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ app_tenant_id: orgId, grants }),
})
if (!response.ok)
throw new Error(`e2e: the fake platform refused the binding (${response.status}: ${await response.text()})`)
}
/** Puts axe into the page. */
async function injectAxe(page: Page): Promise<void> {
await page.addScriptTag({ content: axe.source })
}
/** WCAG 2.2 AA violations on the page the browser is on, as axe finds them. */
export async function violations(page: Page): Promise<string[]> {
await injectAxe(page)
// Finite entrance/hover transitions temporarily blend text and backgrounds.
// Audit their settled paint without disabling motion or waiting on continuous busy indicators.
await page.waitForFunction(
() =>
document
.getAnimations()
.every(
(animation) =>
!Number.isFinite(animation.effect?.getComputedTiming().endTime) ||
animation.playState === "finished" ||
animation.playState === "idle",
),
undefined,
{ timeout: 5000 },
)
const results = await page.evaluate(() =>
(
globalThis as unknown as {
axe: {
run(
context: unknown,
options: unknown,
): Promise<{ violations: Array<{ id: string; nodes: Array<{ target: unknown[] }> }> }>
}
}
).axe.run(document, { runOnly: { type: "tag", values: ["wcag2a", "wcag2aa", "wcag21a", "wcag21aa", "wcag22aa"] } }),
)
return results.violations.map(
(violation) => `${violation.id}: ${violation.nodes.map((node) => node.target.join(" ")).join(", ")}`,
)
}
/** What the fake platform has recorded: the audit events and usage facts the worker sent, and the blobs it stored. */
export interface PlatformState {
audit: Array<{ action: string; resource_id: string | null }>
usage: Array<Record<string, unknown>>
blobs: Array<{ pathname: string; contentType: string; size: number }>
otel: { logs: Array<Record<string, unknown>>; traces: Array<Record<string, unknown>> }
}
export async function platformState(): Promise<PlatformState> {
const base = process.env.E2E_PLATFORM_URL
if (!base) throw new Error("e2e: E2E_PLATFORM_URL is set by the global setup")
const response = await fetch(`${base}/__e2e/state`)
if (!response.ok) throw new Error(`e2e: the fake platform answered ${response.status}`)
const state = (await response.json()) as PlatformState
// Audit and objects use the fake token’s tenant. Billing is scoped to the
// server-pinned deployment organization, as it is on Cloud.
const organization = process.env.E2E_USAGE_ORGANIZATION
if (!organization) throw new Error("e2e: the global setup pins E2E_USAGE_ORGANIZATION")
const billed = await fetch(`${base}/__e2e/state`, { headers: { "x-conusai-organization": organization } })
if (!billed.ok) throw new Error(`e2e: the fake billing state answered ${billed.status}`)
return { ...state, usage: ((await billed.json()) as PlatformState).usage }
}
/** Opens the person's menu at the foot of the frame's sidebar. */
export async function openPersonMenu(page: Page): Promise<void> {
await ready(page)
await page.locator('[data-guide="frame.person"]').click()
}
/**
* Chooses a language from the person's menu. The page changes language in place (the loaders run again, nothing
* reloads), so this waits for the document's `lang` to move off the one it had.
*/
export async function chooseLanguage(page: Page, language: string): Promise<void> {
const before = await page.locator("html").getAttribute("lang")
await openPersonMenu(page)
await page.getByRole("menuitemradio", { name: language }).click()
await expect(page.locator("html")).not.toHaveAttribute("lang", before ?? "")
}
/** Opens the scope switcher in the frame's sidebar. */
export async function openScope(page: Page): Promise<void> {
await ready(page)
await page.locator('[data-guide="frame.scope"]').click()
}