import { expect, test } from '@playwright/test'; import { expectCompatibilityRedirect, expectCtaHierarchy, expectDisclosureLayer, expectFooterLinks, expectHomepageHeroCtaPair, expectHomepageHeroOrder, expectHomepageHeroRouteTargets, expectHomepageHeroStructure, expectHomepageHeroVisibleOnMobile, expectHomepageSectionOrder, expectMobileReadability, expectNavigationVsCtaDifferentiation, expectNoBodyHorizontalOverflow, expectOnwardRouteReachable, expectPageFamily, expectPrimaryNavigation, expectShell, visitPage, } from './smoke-helpers'; const forbiddenHomepageTerms = [ 'AstroDeck', 'Open Source', 'MIT Licensed', 'TenantCTRL', 'TenantPilot', 'TenantAtlas', ] as const; const forbiddenPlatformTerms: Array<[string, RegExp]> = [ ['AstroDeck', /AstroDeck/i], ['TemplateDeck', /TemplateDeck/i], ['Open Source', /Open Source/i], ['MIT', /\bMIT\b/i], ['TenantAtlas', /TenantAtlas/i], ['TenantPilot', /TenantPilot/i], ['TenantCTRL', /TenantCTRL/i], ] as const; const unsupportedPlatformClaims = [ /SOC 2/i, /\bISO(?:\s?\d+)?\b/i, /HIPAA/i, /blanket GDPR/i, /end-to-end encryption/i, /guaranteed recovery/i, /guaranteed compliance/i, /zero drift/i, /real-time everywhere/i, /trusted by/i, /customer logos/i, /Microsoft certification/i, /Microsoft partnership/i, ] as const; async function expectForbiddenHomepageResidueAbsent(page: import('@playwright/test').Page): Promise { const body = page.locator('body'); const metadata = await page.locator('head').evaluate((head) => { const title = document.title; const meta = Array.from(head.querySelectorAll('meta')) .map((element) => element.getAttribute('content') ?? '') .join(' '); const canonical = head.querySelector('link[rel="canonical"]')?.getAttribute('href') ?? ''; return `${title} ${meta} ${canonical}`; }); for (const term of forbiddenHomepageTerms) { await expect(body).not.toContainText(new RegExp(term, 'i')); expect(metadata, `Homepage metadata should not contain ${term}`).not.toMatch(new RegExp(term, 'i')); } } async function expectPlatformResidueAbsent(page: import('@playwright/test').Page): Promise { const body = page.locator('body'); const metadata = await page.locator('head').evaluate((head) => { const title = document.title; const meta = Array.from(head.querySelectorAll('meta')) .map((element) => element.getAttribute('content') ?? '') .join(' '); const canonical = head.querySelector('link[rel="canonical"]')?.getAttribute('href') ?? ''; return `${title} ${meta} ${canonical}`; }); for (const [term, pattern] of forbiddenPlatformTerms) { await expect(body).not.toContainText(pattern); expect(metadata, `Platform metadata should not contain ${term}`).not.toMatch(pattern); } } test('home first read positions Tenantial with one clear action hierarchy', async ({ page }) => { await visitPage(page, '/'); await expectShell(page, 'Evidence-first governance for Microsoft tenants.'); await expectPageFamily(page, 'landing'); await expectDisclosureLayer(page, '1'); await expectDisclosureLayer(page, '2'); await expectPrimaryNavigation(page); await expectNavigationVsCtaDifferentiation(page); await expectFooterLinks(page); await expectCtaHierarchy(page, 'Book a demo', 'Explore the platform'); await expect(page.getByRole('main').getByRole('link', { name: 'Book a demo' }).first()).toBeVisible(); await expect(page.getByRole('main').getByRole('link', { name: 'Explore the platform' }).first()).toBeVisible(); await expect(page.getByRole('heading', { level: 1 })).toHaveCount(1); await expectForbiddenHomepageResidueAbsent(page); const skipLink = page.getByRole('link', { name: 'Skip to content' }); await page.keyboard.press('Tab'); await expect(skipLink).toBeFocused(); }); test('homepage hero explains Tenantial, Microsoft tenant context, and platform CTA route', async ({ page }) => { await visitPage(page, '/'); await expectHomepageHeroStructure(page); await expect(page.locator('[data-homepage-hero="true"] [data-hero-eyebrow]')).toContainText( /governance that earns trust/i, ); await expect( page.locator('[data-homepage-hero="true"] [data-hero-heading]').getByRole('heading', { level: 1, name: 'Evidence-first governance for Microsoft tenants.', }), ).toBeVisible(); await expect(page.locator('[data-homepage-hero="true"] [data-hero-supporting-copy]')).toContainText( /backup and restore with confidence\. detect drift before it becomes audit work\. preserve snapshot history/i, ); await expectHomepageHeroCtaPair(page, 'Book a demo', 'Explore the platform'); await expectHomepageHeroRouteTargets(page, ['/contact', '/platform']); }); test('homepage uses neutral trust statements and the six required feature pillars', async ({ page }) => { await visitPage(page, '/'); await expect(page.locator('[data-section="trustbar"]')).toBeVisible(); await expect(page.locator('[data-section="trustbar"]')).toContainText(/Microsoft tenant focused/i); await expect(page.locator('[data-section="trustbar"]')).toContainText(/Evidence-oriented workflows/i); await expect(page.locator('[data-section="trustbar"]')).toContainText(/Designed for audit review/i); await expect(page.locator('[data-section="trustbar"]')).toContainText(/Operator-led governance/i); const pillars = page.locator('[data-section="feature-pillars"]'); await expect(pillars).toBeVisible(); for (const capability of ['Backup', 'Restore', 'Drift Detection', 'Evidence', 'Audit Trail', 'Governance Reviews']) { await expect(pillars.getByRole('heading', { name: capability, exact: true })).toBeVisible(); } await expect(page.locator('body')).not.toContainText(/SOC 2|ISO\s?\d*|99\.9%|trusted by|customer logos/i); }); test('homepage dashboard preview is static, responsive, and explains status without color alone', async ({ page, }) => { await visitPage(page, '/'); const preview = page.locator('[data-dashboard-preview]').first(); await expect(preview).toBeVisible(); await expect(preview).toContainText('Static demo preview'); await expect(preview).toContainText('Demo values'); await expect(preview).toContainText('92%'); await expect(preview).toContainText('14'); await expect(preview).toContainText('7'); await expect(preview).toContainText('1,248'); await expect(preview).toContainText('98%'); for (const panel of [ 'Recent findings', 'Drift timeline', 'Backups and restores', 'Governance reviews', 'Evidence spotlight', ]) { await expect(preview.getByText(panel, { exact: true })).toBeVisible(); } for (const status of ['Healthy', 'Review required', 'Critical', 'Review-ready']) { await expect(preview.getByText(status, { exact: true }).first()).toBeVisible(); } await expect(preview).not.toContainText(/real[- ]?time|streaming|live tenant feed|May 19|Updated 2m ago/i); }); test('homepage keeps the final CTA and launch-readiness sections in order', async ({ page }) => { await visitPage(page, '/'); await expectHomepageSectionOrder(page, ['hero', 'trustbar', 'feature-pillars', 'cta']); await expect(page.locator('[data-section="cta"]')).toContainText( 'Build tenant governance on evidence, not assumptions.', ); await expectOnwardRouteReachable(page, ['/platform', '/contact']); }); test.describe('homepage mobile', () => { test.use({ viewport: { width: 390, height: 844 } }); test('homepage remains readable on narrow screens without body overflow', async ({ page }) => { await visitPage(page, '/'); await expectMobileReadability(page); await expectNoBodyHorizontalOverflow(page); await expect(page.locator('[data-section="trustbar"]')).toBeVisible(); await expect(page.locator('[data-section="feature-pillars"]')).toBeVisible(); await expect(page.locator('[data-dashboard-preview]').first()).toBeVisible(); }); test('homepage hero preserves meaning order and hero route intent on narrow screens', async ({ page }) => { await visitPage(page, '/'); await expectHomepageHeroOrder(page, [ 'eyebrow', 'headline', 'supporting-copy', 'cta-pair', 'trust-subclaims', 'product-near-visual', ]); await expectHomepageHeroVisibleOnMobile(page); await expectHomepageHeroRouteTargets(page, ['/contact', '/platform']); }); }); test('platform hero explains Tenantial governance model', async ({ page }) => { await visitPage(page, '/platform'); await expectShell(page, /govern Microsoft tenants through evidence/i); await expectPageFamily(page, 'landing'); await expectDisclosureLayer(page, '1'); await expectDisclosureLayer(page, '2'); await expectPrimaryNavigation(page); await expectNavigationVsCtaDifferentiation(page); await expectFooterLinks(page); const main = page.getByRole('main'); await expect(main.locator('[data-hero-eyebrow]').first()).toContainText(/TENANTIAL PLATFORM/i); await expect(page.getByRole('heading', { level: 1 })).toHaveCount(1); await expect(page.getByRole('heading', { level: 1 })).toContainText( /govern Microsoft tenants through evidence/i, ); await expect(main.locator('[data-hero-supporting-copy]').first()).toContainText(/backup records/i); await expect(main.locator('[data-hero-supporting-copy]').first()).toContainText(/configuration drift/i); await expect(main.locator('[data-hero-supporting-copy]').first()).toContainText(/structured reviews/i); await expectCtaHierarchy(page, 'Book a demo', 'See the governance loop'); await expect(main.locator('a[href="/contact"]').filter({ hasText: 'Book a demo' }).first()).toBeVisible(); await expect(main.locator('a[href="#governance-loop"]').filter({ hasText: 'See the governance loop' }).first()).toBeVisible(); await expect(main.locator('[data-platform-dashboard-preview]').first()).toBeVisible(); await expect(main.locator('[data-platform-dashboard-preview]').first()).toContainText(/Governance overview/i); await expect(main.locator('[data-platform-dashboard-preview]').first()).toContainText(/Static demo preview/i); await expect(main.locator('[data-platform-dashboard-preview]').first()).toContainText(/Evidence spotlight/i); for (const signal of [ 'Microsoft tenant focused', 'Evidence-oriented workflows', 'Reviewable decisions', 'Operator-led governance', ]) { await expect(main.locator('[data-hero-trust-subclaims]').getByText(signal, { exact: true })).toBeVisible(); } }); test('platform metadata is Tenantial clean', async ({ page }) => { await visitPage(page, '/platform'); await expect(page).toHaveTitle(/Tenantial Platform/i); await expect(page).toHaveTitle(/Evidence-first governance/i); await expect(page.locator('meta[name="description"]')).toHaveAttribute('content', /backup/i); await expect(page.locator('meta[name="description"]')).toHaveAttribute('content', /restore/i); await expect(page.locator('meta[name="description"]')).toHaveAttribute('content', /drift detection/i); await expect(page.locator('meta[name="description"]')).toHaveAttribute('content', /findings/i); await expect(page.locator('meta[name="description"]')).toHaveAttribute('content', /evidence/i); await expect(page.locator('meta[name="description"]')).toHaveAttribute('content', /audit trails/i); await expect(page.locator('meta[name="description"]')).toHaveAttribute('content', /exceptions/i); await expect(page.locator('meta[name="description"]')).toHaveAttribute('content', /reviews/i); await expect(page.locator('link[rel="canonical"]')).toHaveAttribute('href', /\/platform$/); await expectPlatformResidueAbsent(page); }); test('platform governance flow explains reviewable evidence', async ({ page }) => { await visitPage(page, '/platform'); const operatingModel = page.locator('[data-section="operating-model"]'); const governanceLoop = page.locator('[data-section="governance-loop"]'); await expect(operatingModel).toBeVisible(); await expect(operatingModel.locator('[data-operating-flow]')).toBeVisible(); for (const step of ['Snapshot', 'Drift', 'Finding', 'Review', 'Evidence', 'Audit trail']) { await expect(operatingModel.getByText(step, { exact: true })).toBeVisible(); } await expect(governanceLoop).toBeVisible(); await expect(governanceLoop.locator('[data-governance-loop-diagram]')).toBeVisible(); for (const label of [ 'Source of truth', 'Snapshot', 'Diff', 'Finding', 'Exception', 'Review', 'Evidence', 'Audit trail', ]) { await expect(governanceLoop.getByText(label, { exact: true })).toBeVisible(); } await expect(governanceLoop).toContainText(/operator reviews/i); await expect(governanceLoop).toContainText(/evidence/i); await expect(governanceLoop).toContainText(/auditability/i); }); test('platform governance flow avoids automation guarantees', async ({ page }) => { await visitPage(page, '/platform'); await expect(page.locator('body')).not.toContainText( /automatic remediation|guaranteed recovery|live device actions|real-time tenant operations/i, ); }); test('platform capabilities cover governance primitives', async ({ page }) => { await visitPage(page, '/platform'); const capabilities = page.locator('[data-section="platform-capabilities"]'); await expect(capabilities).toBeVisible(); await expect(capabilities.locator('[data-capability-system-grid]')).toBeVisible(); await expect(capabilities.locator('[data-capability-primary]')).toBeVisible(); await expect(capabilities.getByRole('heading', { name: 'Backup & Restore', exact: true })).toBeVisible(); for (const capability of [ 'Drift Detection', 'Findings', 'Evidence', 'Audit Trail', 'Exceptions', 'Governance Reviews', ]) { await expect(capabilities.getByRole('heading', { name: capability, exact: true })).toBeVisible(); } }); test('platform boundaries keep claims conservative', async ({ page }) => { await visitPage(page, '/platform'); const boundaries = page.locator('[data-section="platform-boundaries"]'); await expect(boundaries).toBeVisible(); await expect(boundaries).toContainText(/Built for governance of record/i); await expect(boundaries).toContainText(/do not take actions on your behalf/i); await expect(boundaries).toContainText(/do not manage devices/i); await expect(boundaries).toContainText(/do not replace your ITSM/i); await expect(boundaries).toContainText(/support reviewable decisions/i); for (const claim of unsupportedPlatformClaims) { await expect(page.locator('body')).not.toContainText(claim); } }); test.describe('platform mobile', () => { test.use({ viewport: { width: 390, height: 844 } }); test('platform mobile layout stays readable without overflow', async ({ page }) => { await visitPage(page, '/platform'); await expectMobileReadability(page); await expectNoBodyHorizontalOverflow(page); await expect(page.locator('[data-section="platform-capabilities"]').first()).toBeVisible(); await expect(page.locator('[data-section="platform-boundaries"]').first()).toBeVisible(); await expect(page.locator('[data-section="platform-capabilities"]').first()).toContainText(/Backup/i); await expect(page.locator('[data-truth-layer-stack]').first()).toBeVisible(); await expect(page.locator('[data-governance-loop-diagram]').first()).toBeVisible(); await expect(page.locator('[data-section="platform-boundaries"]').first()).toContainText(/governance of record/i); expect(await page.locator('[data-color-meaning="with-text"]').count()).toBeGreaterThan(0); }); }); test('primary navigation and footer point Platform links to platform', async ({ page }) => { await visitPage(page, '/platform'); await expectPrimaryNavigation(page); await expectFooterLinks(page); await expect(page.getByRole('contentinfo')).toHaveAttribute('data-footer-intent', 'quiet'); await expect(page.locator('[data-section="platform-final-cta"]')).toBeVisible(); await expect(page.getByRole('contentinfo')).not.toContainText(/Build tenant governance on evidence/i); }); test('product redirects to platform', async ({ page }) => { await expectCompatibilityRedirect(page, '/product', '/platform'); await expect(page.locator('body')).not.toContainText( /AstroDeck|TemplateDeck|Open Source|MIT Licensed|TenantAtlas|TenantPilot|TenantCTRL/i, ); });