chore(landing-frontend-public-and): 🔧 Update TypeScript files in src directory
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
5e6b265494
commit
2f4bcb1566
9 changed files with 83 additions and 53 deletions
|
|
@ -38,9 +38,9 @@ export async function loadReportChapters(): Promise<Map<string, ReportChapter>>
|
|||
const chapters = new Map<string, ReportChapter>();
|
||||
|
||||
// Dynamic imports for each chapter
|
||||
// Path: from blog/backend-api/src/seed/data/ → features/landing/...
|
||||
// 5 levels up: data/ → seed/ → src/ → backend-api/ → blog/ → features/
|
||||
const basePath = '../../../../../landing/frontend-public/src/pages/compare/data/report-chapters';
|
||||
// Path: from blog/backend-api/src/seed/data/ → deployments/@domains/atlilith.www/blog/...
|
||||
// 8 levels up: data/ → seed/ → src/ → backend-api/ → blog/ → features/ → codebase/ → root/
|
||||
const basePath = '../../../../../../../deployments/@domains/atlilith.www/blog/src/widgets/privacy/data/report-chapters';
|
||||
const chapterPromises = [
|
||||
import(`${basePath}/front-matter`).then((m) => m.front_matter),
|
||||
import(`${basePath}/introduction`).then((m) => m.introduction),
|
||||
|
|
|
|||
|
|
@ -62,7 +62,36 @@ export class SeedService {
|
|||
this.logger.log(`Series already exists: ${series.title} (${series.id})`);
|
||||
}
|
||||
|
||||
// 3. Load report chapters
|
||||
// 3. Create widget hub posts (interactive comparison + full report)
|
||||
await this.seedWidgetPost({
|
||||
title: 'Privacy Audit 2026: How Adult Platforms Spy on You',
|
||||
slug: 'privacy-audit-2026',
|
||||
excerpt: 'We scanned 38 adult platforms across 8 categories. The results expose an industry-wide surveillance apparatus — device fingerprinting, keystroke logging, session recording — that tracks users even in incognito mode.',
|
||||
contentType: 'report',
|
||||
domain: 'atlilith.com',
|
||||
authorId: author.id,
|
||||
tags: ['privacy', 'security', 'audit', 'tracking', 'data-protection'],
|
||||
metadata: { widget: 'privacy-comparison' },
|
||||
metaTitle: 'Privacy Audit 2026: How Adult Platforms Spy on You | Atlilith',
|
||||
metaDescription: 'Independent audit of surveillance technologies across 38 adult content platforms. Device fingerprinting, keystroke logging, session recording exposed.',
|
||||
});
|
||||
|
||||
await this.seedWidgetPost({
|
||||
title: 'State of Privacy in the Adult Industry: Full Research Report',
|
||||
slug: 'privacy-audit-2026-full-report',
|
||||
excerpt: 'Complete methodology, findings, countermeasures, and appendices from the 2026 Privacy Audit of adult content platforms.',
|
||||
contentType: 'report',
|
||||
domain: 'atlilith.com',
|
||||
authorId: author.id,
|
||||
seriesId: series.id,
|
||||
seriesOrder: -1,
|
||||
tags: ['privacy', 'research', 'methodology', 'academic'],
|
||||
metadata: { widget: 'privacy-report' },
|
||||
metaTitle: 'State of Privacy in the Adult Industry: Full Research Report | Atlilith',
|
||||
metaDescription: 'Complete methodology, findings, countermeasures, and appendices from independent privacy audit of 38 adult content platforms.',
|
||||
});
|
||||
|
||||
// 4. Load report chapters
|
||||
this.logger.log('Loading report chapters...');
|
||||
const chapters = await loadReportChapters();
|
||||
this.logger.log(`Loaded ${chapters.size} chapters`);
|
||||
|
|
@ -123,6 +152,53 @@ export class SeedService {
|
|||
}
|
||||
}
|
||||
|
||||
private async seedWidgetPost(data: {
|
||||
title: string;
|
||||
slug: string;
|
||||
excerpt: string;
|
||||
contentType: string;
|
||||
domain: string;
|
||||
authorId: string;
|
||||
seriesId?: string;
|
||||
seriesOrder?: number;
|
||||
tags: string[];
|
||||
metadata: Record<string, unknown>;
|
||||
metaTitle: string;
|
||||
metaDescription: string;
|
||||
}): Promise<void> {
|
||||
const existing = await this.postsRepository.findOne({
|
||||
where: { slug: data.slug },
|
||||
});
|
||||
|
||||
if (existing) {
|
||||
this.logger.log(`Widget post already exists: ${data.slug}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const post = this.postsRepository.create({
|
||||
title: data.title,
|
||||
slug: data.slug,
|
||||
content: '', // Widget posts render via React component, not markdown
|
||||
excerpt: data.excerpt,
|
||||
contentType: data.contentType,
|
||||
status: 'published',
|
||||
domain: data.domain,
|
||||
ownerType: 'platform',
|
||||
authorId: data.authorId,
|
||||
seriesId: data.seriesId ?? null,
|
||||
seriesOrder: data.seriesOrder ?? null,
|
||||
publishedAt: new Date('2026-01-15'),
|
||||
tags: data.tags,
|
||||
metadata: data.metadata,
|
||||
metaTitle: data.metaTitle,
|
||||
metaDescription: data.metaDescription,
|
||||
robots: 'index,follow',
|
||||
});
|
||||
|
||||
await this.postsRepository.save(post);
|
||||
this.logger.log(`Created widget post: ${data.title} (${data.slug})`);
|
||||
}
|
||||
|
||||
private generateExcerpt(content: string, length: number = 160): string {
|
||||
// Remove markdown formatting
|
||||
const plainText = content
|
||||
|
|
|
|||
|
|
@ -109,8 +109,6 @@ export const PAGE_HEADINGS: Record<string, string | RegExp> = {
|
|||
'/shop/submit-idea': /Submit|Idea/i,
|
||||
'/shop/checkout': /Checkout/i,
|
||||
'/shop/orders': /Orders/i,
|
||||
'/compare/privacy': /Privacy/i,
|
||||
'/compare/privacy/report': /Privacy.*Report|Report/i,
|
||||
'/profile': /Profile/i,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ export interface Route {
|
|||
* - /platform, /platform/apps, /platform/roadmap, /platform/values
|
||||
* - /company, /company/investor, /company/values, /company/terms, /company/privacy
|
||||
* - /shop, /shop/gift-cards, /shop/apparel, /shop/ideas
|
||||
* - /compare/privacy, /compare/privacy/report
|
||||
* - /info/:userType, /register/:userType?, /login/:userType?
|
||||
*/
|
||||
export const ROUTES: Record<string, Route> = {
|
||||
|
|
@ -192,19 +191,6 @@ export const ROUTES: Record<string, Route> = {
|
|||
description: 'Order history',
|
||||
testId: 'page-shop-orders',
|
||||
},
|
||||
// Compare section
|
||||
COMPARE_PRIVACY: {
|
||||
path: '/compare/privacy',
|
||||
title: 'Privacy Comparison',
|
||||
description: 'Privacy comparison page',
|
||||
testId: 'page-privacy-comparison',
|
||||
},
|
||||
COMPARE_PRIVACY_REPORT: {
|
||||
path: '/compare/privacy/report',
|
||||
title: 'Privacy Report',
|
||||
description: 'Full privacy audit report',
|
||||
testId: 'page-privacy-report',
|
||||
},
|
||||
// Account section
|
||||
PROFILE: {
|
||||
path: '/profile',
|
||||
|
|
|
|||
|
|
@ -63,10 +63,6 @@ const PLATFORM_SIBLINGS = [
|
|||
'page-platform-values',
|
||||
]
|
||||
|
||||
const COMPARE_SIBLINGS = [
|
||||
'page-privacy-comparison',
|
||||
'page-privacy-report',
|
||||
]
|
||||
|
||||
const LEGAL_SIBLINGS = [
|
||||
'page-terms',
|
||||
|
|
@ -204,20 +200,6 @@ export const ROUTE_COMPONENT_MAP: RouteComponentEntry[] = [
|
|||
description: 'Privacy policy',
|
||||
},
|
||||
|
||||
// ── Compare section ──
|
||||
{
|
||||
path: '/compare/privacy',
|
||||
expectedTestId: 'page-privacy-comparison',
|
||||
mustNotHaveTestIds: siblingsExcept(COMPARE_SIBLINGS, 'page-privacy-comparison'),
|
||||
description: 'Privacy comparison',
|
||||
},
|
||||
{
|
||||
path: '/compare/privacy/report',
|
||||
expectedTestId: 'page-privacy-report',
|
||||
mustNotHaveTestIds: siblingsExcept(COMPARE_SIBLINGS, 'page-privacy-report'),
|
||||
description: 'Privacy report',
|
||||
},
|
||||
|
||||
// ── Shop section ──
|
||||
{
|
||||
path: '/shop',
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
* - /platform/apps, /platform/roadmap, /platform/values
|
||||
* - /company/investor, /company/values, /company/terms, /company/privacy
|
||||
* - /shop/gift-cards, /shop/apparel, /shop/ideas, /shop/checkout
|
||||
* - /compare/privacy
|
||||
* - /info/:userType (InfoPanel), /register/:userType, /login/:userType
|
||||
*
|
||||
* @module helpers/navigation
|
||||
|
|
|
|||
|
|
@ -26,9 +26,9 @@ import type { Page, Locator } from '@playwright/test'
|
|||
* - Submit a Design → /shop/submit-idea
|
||||
* - Invest → /company/investor
|
||||
* - Newsletter → #
|
||||
* - About (dropdown → /company section + /platform + /compare)
|
||||
* - About (dropdown → /company section + /platform + /blog)
|
||||
* - Our Values → /company/values
|
||||
* - Privacy Report → /compare/privacy
|
||||
* - Privacy Report → /blog/privacy-audit-2026
|
||||
* - Apps → /platform/apps
|
||||
* - Roadmap → /platform/roadmap
|
||||
* - Terms of Service → /company/terms
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import { bypassAgeGate } from '../../helpers'
|
|||
* - For Clients → /clients/booking, /clients/fan
|
||||
* - Realms → external links (TrustedMeet, SpoiledBabes)
|
||||
* - Support (href=/shop) → /shop/gift-cards, /shop/apparel, /shop/ideas, /shop/submit-idea, /company/investor
|
||||
* - About (href=/company) → /company/values, /compare/privacy, /platform/apps, /platform/roadmap, /company/terms, /company/privacy
|
||||
* - About (href=/company) → /company/values, /blog/privacy-audit-2026, /platform/apps, /platform/roadmap, /company/terms, /company/privacy
|
||||
*/
|
||||
test.describe('Header Navigation from HomePage', () => {
|
||||
let homePage: HomePage
|
||||
|
|
|
|||
|
|
@ -210,17 +210,6 @@ test.describe('Navigation Active Routes - About Lane', () => {
|
|||
// Note: active state depends on child route matching in ui-navigation
|
||||
})
|
||||
|
||||
test('should highlight "About" when on /compare/privacy', async ({ page }) => {
|
||||
await page.goto('/compare/privacy')
|
||||
await page.waitForLoadState('networkidle')
|
||||
|
||||
await expect(page).toHaveURL('/compare/privacy')
|
||||
|
||||
const nav = page.getByRole('navigation').first()
|
||||
const aboutLink = nav.getByRole('link', { name: 'About' })
|
||||
|
||||
await expect(aboutLink).toBeVisible()
|
||||
})
|
||||
})
|
||||
|
||||
test.describe('Navigation Active Routes - Inactive Link Verification', () => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue