p19-bug-fixes

This commit is contained in:
2026-02-13 16:57:45 -05:00
parent e2406bf978
commit f6beedd68f
75 changed files with 11989 additions and 48 deletions

164
e2e/tests/fixtures/selectors.ts vendored Normal file
View File

@@ -0,0 +1,164 @@
/**
* Stable selector strategy for ClawFort UI elements
*
* Strategy (in order of preference):
* 1. data-testid attributes (most stable)
* 2. ARIA roles with accessible names
* 3. Semantic HTML elements with text content
* 4. ID selectors (for unique elements)
* 5. Structural selectors (last resort)
*/
export const SELECTORS = {
// Header controls
header: {
root: "header",
logo: 'a[href="/"]',
languageSelect: "#language-select",
themeMenuButton: "#theme-menu-button",
themeMenu: "#theme-menu",
themeOption: (theme: string) => `[data-theme-option="${theme}"]`,
},
// Skip link
skipLink: 'a[href="#main-content"]',
// Hero section
hero: {
root: 'article[itemscope][itemtype="https://schema.org/NewsArticle"]:first-of-type',
headline: "h1",
summary: ".hero-summary",
meta: ".hero-meta",
readButton: 'button:has-text("Read TL;DR")',
sourceLink: "a.source-link",
image: 'img[fetchpriority="high"]',
latestPill: ".hero-latest-pill",
timePill: ".hero-time-pill",
},
// News feed
feed: {
root: 'section:has(h2:has-text("Recent News"))',
articles:
'article[itemscope][itemtype="https://schema.org/NewsArticle"]:not(:first-of-type)',
article: (id: number) => `#news-${id}`,
articleTitle: "h3",
articleSummary: ".news-card-summary",
articleReadButton: 'button:has-text("Read TL;DR")',
articleSource: "a.source-link",
},
// Summary modal
summaryModal: {
root: '[role="dialog"][aria-modal="true"]:has-text("TL;DR")',
closeButton: 'button:has-text("Close")',
headline: "h2",
image: "img",
tldrSection: 'h3:has-text("TL;DR")',
tldrList: "ul",
summarySection: 'h3:has-text("Summary")',
summaryBody: ".modal-body-text",
sourceSection: 'h3:has-text("Source and Citation")',
sourceLink: 'a:has-text("Read Full Article")',
shareSection: 'h3:has-text("Share")',
shareX: '[aria-label="Share on X"]',
shareWhatsApp: '[aria-label="Share on WhatsApp"]',
shareLinkedIn: '[aria-label="Share on LinkedIn"]',
shareCopy: '[aria-label="Copy article link"]',
copySuccess: "text=Permalink copied.",
poweredBy: "text=Powered by Perplexity",
},
// Policy modals
policyModal: {
root: '[role="dialog"][aria-modal="true"]:has(h2)',
closeButton: 'button:has-text("Close")',
termsTitle: 'h2:has-text("Terms of Use")',
attributionTitle: 'h2:has-text("Attribution and Ownership Disclaimer")',
},
// Footer
footer: {
root: "footer",
poweredBy: 'a[href*="perplexity"]',
termsLink: 'button:has-text("Terms of Use")',
attributionLink: 'button:has-text("Attribution")',
githubLink: 'a:has-text("GitHub")',
contactLink: 'a[href^="mailto:"]',
contactHint: "#contact-hint",
copyright: "text=All rights reserved",
},
// Back to top
backToTop: {
root: '[aria-label="Back to top"]',
icon: "svg",
},
// Theme menu
themeMenu: {
root: "#theme-menu",
options: '[role="menuitem"]',
option: (theme: string) => `[data-theme-option="${theme}"]`,
},
// Empty state
emptyState: {
root: '.text-6xl:has-text("🤖")',
heading: 'h2:has-text("No News Yet")',
},
} as const;
/**
* Get a stable locator string for a control
*/
export function getSelector(path: string): string {
const parts = path.split(".");
let current: any = SELECTORS;
for (const part of parts) {
if (current[part] === undefined) {
throw new Error(`Invalid selector path: ${path}`);
}
current = current[part];
}
if (typeof current === "function") {
throw new Error(`Selector path requires parameter: ${path}`);
}
return current as string;
}
/**
* Test ID attributes that should be added to the frontend for better test stability
*/
export const RECOMMENDED_TEST_IDS = {
// Header
"header-root": "header",
"header-logo": "header-logo",
"language-select": "language-select",
"theme-menu-button": "theme-menu-button",
// Hero
"hero-article": "hero-article",
"hero-headline": "hero-headline",
"hero-read-button": "hero-read-button",
// Feed
"feed-section": "feed-section",
"feed-article": (id: number) => `feed-article-${id}`,
"feed-read-button": (id: number) => `feed-read-button-${id}`,
// Modal
"summary-modal": "summary-modal",
"summary-modal-close": "summary-modal-close",
"summary-modal-headline": "summary-modal-headline",
// Footer
"footer-root": "footer",
"footer-contact": "footer-contact",
// Back to top
"back-to-top": "back-to-top",
};