TenantAtlas/apps/website/tests/smoke/home-product.spec.ts
ahmido be314c577f Spec 400: rebuild Tenantial homepage visuals (#387)
## Summary
- rebuild the public Tenantial homepage around an evidence-first Microsoft tenant governance narrative
- replace the old hero visual with a new static dashboard preview and add dedicated Trust Bar and Feature Pillars sections
- update the shared public shell, navigation, footer, dark design tokens, assets, and homepage content to match the new brand direction
- align website smoke coverage and Spec 400 artifacts with the rebuilt homepage

## Testing
- not run in this pass
- updated website smoke specs under apps/website/tests/smoke

## Note
- `website-dev` was pushed to `origin` so the requested PR base exists remotely
- the remote `website-dev` branch is an ancestor of `origin/dev`, so this PR may also show upstream `dev` history relative to that base

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #387
2026-05-18 14:38:11 +00:00

194 lines
8.1 KiB
TypeScript

import { expect, test } from '@playwright/test';
import {
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;
async function expectForbiddenHomepageResidueAbsent(page: import('@playwright/test').Page): Promise<void> {
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'));
}
}
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 required CTA routes', 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', '/product']);
});
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, ['/product', '/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', '/product']);
});
});
test('product keeps the connected operating model readable without collapsing into a feature list', async ({
page,
}) => {
await visitPage(page, '/product');
await expectShell(page, /operating model|restore posture|governance/i);
await expectPageFamily(page, 'landing');
await expectDisclosureLayer(page, '1');
await expectDisclosureLayer(page, '2');
await expectPrimaryNavigation(page);
await expectNavigationVsCtaDifferentiation(page);
await expectFooterLinks(page);
await expect(
page.getByRole('heading', { name: 'Explain what the product does before asking for buyer trust.' }),
).toBeVisible();
await expectCtaHierarchy(page, 'Review the trust posture', 'Start the working session');
await expect(page.getByRole('main').getByRole('link', { name: 'Read the changelog' }).first()).toBeVisible();
});