## 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
194 lines
8.1 KiB
TypeScript
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();
|
|
});
|