const adapterFixture = true;',
- },
- promptFiles: {},
- runtimeUrl: 'https://runtime.test/parity',
- narrativeDocs: [
- {
- title: 'Adapter narrative',
- html: 'Shared Docs fixture.
', - sourceFile: 'adapter.md', - }, - ], - docSections: [ - { - title: 'adapterApi', - signature: 'adapterApi(value: string): boolean', - description: 'Shared API fixture.', - params: [{ name: 'value', description: 'Fixture input.' }], - returns: 'Whether the fixture is active.', - sourceFile: 'adapter.ts', - language: 'typescript', - }, - ], - }} - routePath={model.canonicalPath} - requestedMode="run" - /> -
-
-
+ Runtime bridge fixture
`; +} diff --git a/apps/cockpit/e2e/production-smoke.spec.ts b/apps/website/e2e/platform-production-smoke.spec.ts similarity index 61% rename from apps/cockpit/e2e/production-smoke.spec.ts rename to apps/website/e2e/platform-production-smoke.spec.ts index 84080a1bc..da9799740 100644 --- a/apps/cockpit/e2e/production-smoke.spec.ts +++ b/apps/website/e2e/platform-production-smoke.spec.ts @@ -1,30 +1,56 @@ import { expect, test } from '@playwright/test'; -import { capabilities } from '../scripts/capability-registry'; +import { readFileSync } from 'node:fs'; +import { validateRuntimeParentOrigins } from '@threadplane/cockpit-runtime-bridge'; import { - getRedirectDisabledProbePath, - getRegistryWebsiteDestinations, -} from '../scripts/deploy-smoke'; + cockpitManifest, + getCanonicalWebsiteWorkspaceHref, + getWorkspaceDestinationPath, + resolveLegacyPath, + resolveLegacyRequestMode, +} from '@threadplane/cockpit-registry'; /** - * Production smoke test: verifies the deployed cockpit shell and deployed - * example apps are reachable after production deploy. + * Production platform smoke: verifies the Website, legacy Cockpit redirects, + * deployed examples, canonical demo, and shared runtimes as one product. * * Requires: - * BASE_URL - e.g. https://cockpit.threadplane.ai + * COCKPIT_URL - e.g. https://cockpit.threadplane.ai * EXAMPLES_URL - e.g. https://examples.threadplane.ai * OPENAI_API_KEY - optional; enables the single live-provider canary * * Run: - * BASE_URL=https://cockpit.threadplane.ai \ + * PRODUCTION_SMOKE=true COCKPIT_URL=https://cockpit.threadplane.ai \ * EXAMPLES_URL=https://examples.threadplane.ai \ - * npx playwright test apps/cockpit/e2e/production-smoke.spec.ts + * npx playwright test apps/website/e2e/platform-production-smoke.spec.ts */ -const COCKPIT_URL = process.env['BASE_URL'] ?? 'https://cockpit.threadplane.ai'; +const COCKPIT_URL = + process.env['COCKPIT_URL'] ?? 'https://cockpit.threadplane.ai'; const EXAMPLES_URL = process.env['EXAMPLES_URL'] ?? 'https://examples.threadplane.ai'; const DEMO_URL = process.env['DEMO_URL'] ?? 'https://demo.threadplane.ai'; const WEBSITE_URL = process.env['WEBSITE_URL'] ?? 'https://threadplane.ai'; +const runtimeParentOriginSource = JSON.parse( + readFileSync( + new URL('../../../runtime-parent-origins.json', import.meta.url), + 'utf8' + ) +) as { readonly baseOrigins?: unknown }; +const runtimeParentPreviewOrigins = ( + process.env['RUNTIME_PARENT_PREVIEW_ORIGINS'] ?? '' +) + .split(/\r?\n/) + .filter(Boolean); +const baseRuntimeParentOrigins = validateRuntimeParentOrigins( + runtimeParentOriginSource.baseOrigins +); +const expectedRuntimeParentOrigins = validateRuntimeParentOrigins([ + ...(baseRuntimeParentOrigins ?? []), + ...runtimeParentPreviewOrigins, +]); +if (baseRuntimeParentOrigins === null || expectedRuntimeParentOrigins === null) { + throw new Error('Invalid runtime parent origin smoke policy'); +} const CHAT_CAPABILITIES = [ 'langgraph/streaming', @@ -84,13 +110,75 @@ const RENDER_CAPABILITIES = [ * runtime but are not yet in the examples route table, so they have no * /ag-ui/
l.group === 'library')
@@ -44,23 +44,78 @@ beforeEach(() => {
});
describe('DocsControlPlane', () => {
- it('styles the preview hooks for forced colors and reduced motion', () => {
- expect(docsCss).toMatch(/\[data-docs-runtime-preview\]/);
- expect(docsCss).toMatch(/@media \(forced-colors:\s*active\)/);
- expect(docsCss).toMatch(/Canvas/);
- expect(docsCss).toMatch(/HighlightText/);
- expect(docsCss).toMatch(
- /@media \(prefers-reduced-motion:\s*reduce\)[\s\S]*?transition:\s*none/
+ it('keeps context headings on the shared sentence-case sans contract', () => {
+ for (const selector of [
+ '[data-docs-control-plane-context] [data-control-plane-section-trigger]',
+ '[data-docs-control-plane-context] [data-control-plane-section-heading]',
+ ]) {
+ const declarations = declarationsFor(docsCss, selector);
+ expect(declarations).toMatch(/font-family:\s*var\(--font-inter\)/);
+ expect(declarations).toMatch(/font-size:\s*12px/);
+ expect(declarations).toMatch(/font-weight:\s*600/);
+ expect(declarations).toMatch(/letter-spacing:\s*normal/);
+ expect(declarations).toMatch(/color:\s*var\(--color-text-muted\)/);
+ expect(declarations).toMatch(/text-transform:\s*none/);
+ }
+ });
+
+ it('rotates the shared disclosure chevron as a complete icon', () => {
+ const chevron = declarationsFor(
+ docsCss,
+ '[data-docs-control-plane-context] [data-control-plane-section-trigger] [data-control-plane-section-chevron]'
+ );
+ const expanded = declarationsFor(
+ docsCss,
+ '[data-docs-control-plane-context] [data-control-plane-section-trigger][aria-expanded="true"] [data-control-plane-section-chevron]'
+ );
+
+ expect(chevron).toMatch(/transition:[^;]*transform\s+150ms\s+ease/);
+ expect(chevron).toMatch(/transform:\s*rotate\(0deg\)/);
+ expect(expanded).toMatch(/transform:\s*rotate\(90deg\)/);
+ });
+
+ it('uses complete rounded sidebar states without a left marker', () => {
+ for (const selector of [
+ '.docs-sidebar-top-link',
+ '.docs-sidebar-section-link',
+ ]) {
+ const declarations = declarationsFor(docsCss, selector);
+ expect(declarations).toMatch(/border-radius:\s*7px/);
+ expect(declarations).not.toMatch(
+ /border-(?:left|inline-start)(?:-(?:color|style|width))?\s*:/
+ );
+ }
+
+ const hover = declarationsFor(
+ docsCss,
+ '[data-docs-navlink]:not([data-active]):hover'
+ );
+ const active = declarationsFor(
+ docsCss,
+ '[data-docs-navlink][data-active]'
+ );
+ expect(hover).toMatch(/background:\s*var\(--color-surface-dim\)/);
+ expect(active).toMatch(/background:\s*var\(--color-accent-surface\)/);
+ expect(hover).not.toMatch(
+ /border-(?:left|inline-start)(?:-(?:color|style|width))?\s*:/
);
+ expect(active).not.toMatch(
+ /border-(?:left|inline-start)(?:-(?:color|style|width))?\s*:/
+ );
+ });
+
+ it('does not retain style contracts for the retired Runtime preview or environment rows', () => {
+ expect(docsCss).not.toMatch(/\[data-docs-runtime-preview\]/);
+ expect(docsCss).not.toMatch(/\[data-control-plane-environment-/);
});
- it('renders the stable labeled mode rail with deterministic Cockpit links', () => {
+ it('keeps standalone docs-only modes disabled without handoff links', () => {
render(
Custom runtime targets are unavailable for this capability.
+
+ Active
+ {view.location}
+
+ {runtimeOrigin + ? `Allow Origin: ${runtimeOrigin}. This is the embedded Angular runtime origin, not necessarily the top-level workspace origin.` + : 'The embedded Angular runtime origin is unavailable for this capability.'} +
++ Kept in this tab until refresh. Nothing is saved. +
+