p19-bug-fixes
This commit is contained in:
164
e2e/tests/fixtures/selectors.ts
vendored
Normal file
164
e2e/tests/fixtures/selectors.ts
vendored
Normal 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",
|
||||
};
|
||||
Reference in New Issue
Block a user