Fix prettier formatting issues

This commit is contained in:
adilallo
2025-08-30 13:46:35 -06:00
parent 1e795e1340
commit 12deae75e8
97 changed files with 335281 additions and 54857 deletions
+2 -2
View File
@@ -60,7 +60,7 @@ test.describe("Accessibility Testing", () => {
focusedElements.push(
`${elementInfo.tagName}${
elementInfo.role ? `[role="${elementInfo.role}"]` : ""
}: ${elementInfo.accessibleName}`
}: ${elementInfo.accessibleName}`,
);
await page.keyboard.press("Tab");
@@ -190,7 +190,7 @@ test.describe("Accessibility Testing", () => {
test("focus indicators - visible focus", async ({ page }) => {
// Test that focus indicators are visible
const focusableElements = page.locator(
"button, a, input, textarea, select, [tabindex]"
"button, a, input, textarea, select, [tabindex]",
);
const elementCount = await focusableElements.count();
+1 -1
View File
@@ -8,7 +8,7 @@ export async function runA11y(page, options = {}) {
if (results.violations.length > 0) {
console.log("Accessibility violations found:", results.violations);
throw new Error(
`Found ${results.violations.length} accessibility violations`
`Found ${results.violations.length} accessibility violations`,
);
}
}
+26 -26
View File
@@ -29,7 +29,7 @@ test.describe("Edge Cases and Error Scenarios", () => {
// Page should function normally
await expect(page.locator("text=Collaborate")).toBeVisible();
const learnButtons = page.locator(
'button:has-text("Learn how CommunityRule works")'
'button:has-text("Learn how CommunityRule works")',
);
const buttonCount = await learnButtons.count();
let visibleButton = null;
@@ -44,7 +44,7 @@ test.describe("Edge Cases and Error Scenarios", () => {
if (!visibleButton) {
throw new Error(
'No visible "Learn how CommunityRule works" button found'
'No visible "Learn how CommunityRule works" button found',
);
}
@@ -103,7 +103,7 @@ test.describe("Edge Cases and Error Scenarios", () => {
test("handles browser back/forward navigation", async ({ page }) => {
// Navigate to a section
const learnButtons = page.locator(
'button:has-text("Learn how CommunityRule works")'
'button:has-text("Learn how CommunityRule works")',
);
const buttonCount = await learnButtons.count();
let visibleButton = null;
@@ -118,7 +118,7 @@ test.describe("Edge Cases and Error Scenarios", () => {
if (!visibleButton) {
throw new Error(
'No visible "Learn how CommunityRule works" button found'
'No visible "Learn how CommunityRule works" button found',
);
}
@@ -136,7 +136,7 @@ test.describe("Edge Cases and Error Scenarios", () => {
test("handles page refresh during interactions", async ({ page }) => {
// Start an interaction
const learnButtons = page.locator(
'button:has-text("Learn how CommunityRule works")'
'button:has-text("Learn how CommunityRule works")',
);
const buttonCount = await learnButtons.count();
let visibleButton = null;
@@ -151,7 +151,7 @@ test.describe("Edge Cases and Error Scenarios", () => {
if (!visibleButton) {
throw new Error(
'No visible "Learn how CommunityRule works" button found'
'No visible "Learn how CommunityRule works" button found',
);
}
@@ -175,7 +175,7 @@ test.describe("Edge Cases and Error Scenarios", () => {
// Interact with each tab - find the first visible button
const learnButtons = page.locator(
'button:has-text("Learn how CommunityRule works")'
'button:has-text("Learn how CommunityRule works")',
);
const buttonCount = await learnButtons.count();
let visibleButton = null;
@@ -190,7 +190,7 @@ test.describe("Edge Cases and Error Scenarios", () => {
if (!visibleButton) {
throw new Error(
'No visible "Learn how CommunityRule works" button found'
'No visible "Learn how CommunityRule works" button found',
);
}
@@ -219,7 +219,7 @@ test.describe("Edge Cases and Error Scenarios", () => {
// All tabs should work independently
await expect(
page.locator('h2:has-text("How CommunityRule works")')
page.locator('h2:has-text("How CommunityRule works")'),
).toBeVisible();
await expect(page1.locator("text=Consensus clusters")).toBeVisible();
await expect(page2.locator("text=Still have questions?")).toBeVisible();
@@ -249,7 +249,7 @@ test.describe("Edge Cases and Error Scenarios", () => {
// Page should continue to function
await expect(page.locator("text=Collaborate")).toBeVisible();
const learnButtons = page.locator(
'button:has-text("Learn how CommunityRule works")'
'button:has-text("Learn how CommunityRule works")',
);
const buttonCount = await learnButtons.count();
let visibleButton = null;
@@ -264,7 +264,7 @@ test.describe("Edge Cases and Error Scenarios", () => {
if (!visibleButton) {
throw new Error(
'No visible "Learn how CommunityRule works" button found'
'No visible "Learn how CommunityRule works" button found',
);
}
@@ -283,7 +283,7 @@ test.describe("Edge Cases and Error Scenarios", () => {
// Page should still function without images
await expect(page.locator("text=Collaborate")).toBeVisible();
const learnButtons = page.locator(
'button:has-text("Learn how CommunityRule works")'
'button:has-text("Learn how CommunityRule works")',
);
const buttonCount = await learnButtons.count();
let visibleButton = null;
@@ -298,7 +298,7 @@ test.describe("Edge Cases and Error Scenarios", () => {
if (!visibleButton) {
throw new Error(
'No visible "Learn how CommunityRule works" button found'
'No visible "Learn how CommunityRule works" button found',
);
}
@@ -317,7 +317,7 @@ test.describe("Edge Cases and Error Scenarios", () => {
// Page should still function without styles
await expect(page.locator("text=Collaborate")).toBeVisible();
const learnButtons = page.locator(
'button:has-text("Learn how CommunityRule works")'
'button:has-text("Learn how CommunityRule works")',
);
const buttonCount = await learnButtons.count();
let visibleButton = null;
@@ -332,7 +332,7 @@ test.describe("Edge Cases and Error Scenarios", () => {
if (!visibleButton) {
throw new Error(
'No visible "Learn how CommunityRule works" button found'
'No visible "Learn how CommunityRule works" button found',
);
}
@@ -351,7 +351,7 @@ test.describe("Edge Cases and Error Scenarios", () => {
// Page should still function with fallback fonts
await expect(page.locator("text=Collaborate")).toBeVisible();
const learnButtons = page.locator(
'button:has-text("Learn how CommunityRule works")'
'button:has-text("Learn how CommunityRule works")',
);
const buttonCount = await learnButtons.count();
let visibleButton = null;
@@ -366,7 +366,7 @@ test.describe("Edge Cases and Error Scenarios", () => {
if (!visibleButton) {
throw new Error(
'No visible "Learn how CommunityRule works" button found'
'No visible "Learn how CommunityRule works" button found',
);
}
@@ -386,7 +386,7 @@ test.describe("Edge Cases and Error Scenarios", () => {
// Clean up
setTimeout(() => {
const testElements = document.querySelectorAll(
'div[textContent*="Test element"]'
'div[textContent*="Test element"]',
);
testElements.forEach((el) => el.remove());
}, 100);
@@ -395,7 +395,7 @@ test.describe("Edge Cases and Error Scenarios", () => {
// Page should remain functional
await expect(page.locator("text=Collaborate")).toBeVisible();
const learnButtons = page.locator(
'button:has-text("Learn how CommunityRule works")'
'button:has-text("Learn how CommunityRule works")',
);
const buttonCount = await learnButtons.count();
let visibleButton = null;
@@ -410,7 +410,7 @@ test.describe("Edge Cases and Error Scenarios", () => {
if (!visibleButton) {
throw new Error(
'No visible "Learn how CommunityRule works" button found'
'No visible "Learn how CommunityRule works" button found',
);
}
@@ -481,7 +481,7 @@ test.describe("Edge Cases and Error Scenarios", () => {
// Find visible button for right-click
const learnButtons = page.locator(
'button:has-text("Learn how CommunityRule works")'
'button:has-text("Learn how CommunityRule works")',
);
const buttonCount = await learnButtons.count();
let visibleButton = null;
@@ -578,7 +578,7 @@ test.describe("Edge Cases and Error Scenarios", () => {
// Content should remain readable
await expect(page.locator("text=Collaborate")).toBeVisible();
const learnButtons = page.locator(
'button:has-text("Learn how CommunityRule works")'
'button:has-text("Learn how CommunityRule works")',
);
const buttonCount = await learnButtons.count();
let visibleButton = null;
@@ -593,7 +593,7 @@ test.describe("Edge Cases and Error Scenarios", () => {
if (!visibleButton) {
throw new Error(
'No visible "Learn how CommunityRule works" button found'
'No visible "Learn how CommunityRule works" button found',
);
}
@@ -610,14 +610,14 @@ test.describe("Edge Cases and Error Scenarios", () => {
await page.evaluate(() => {
document.documentElement.style.setProperty(
"--prefers-reduced-motion",
"reduce"
"reduce",
);
});
// Page should respect reduced motion
await expect(page.locator("text=Collaborate")).toBeVisible();
const learnButtons = page.locator(
'button:has-text("Learn how CommunityRule works")'
'button:has-text("Learn how CommunityRule works")',
);
const buttonCount = await learnButtons.count();
let visibleButton = null;
@@ -632,7 +632,7 @@ test.describe("Edge Cases and Error Scenarios", () => {
if (!visibleButton) {
throw new Error(
'No visible "Learn how CommunityRule works" button found'
'No visible "Learn how CommunityRule works" button found',
);
}
+10 -10
View File
@@ -33,7 +33,7 @@ for (const bp of breakpoints) {
}) => {
// All breakpoints should have navigation items
await expect(
page.getByRole("link", { name: /use cases/i })
page.getByRole("link", { name: /use cases/i }),
).toBeVisible();
await expect(page.getByRole("link", { name: /learn/i })).toBeVisible();
await expect(page.getByRole("link", { name: /about/i })).toBeVisible();
@@ -42,20 +42,20 @@ for (const bp of breakpoints) {
test(`footer legal links visibility at ${bp.name}`, async ({ page }) => {
// All breakpoints should have legal links
await expect(
page.getByRole("link", { name: /privacy policy/i })
page.getByRole("link", { name: /privacy policy/i }),
).toBeVisible();
await expect(
page.getByRole("link", { name: /terms of service/i })
page.getByRole("link", { name: /terms of service/i }),
).toBeVisible();
});
test(`footer social links visibility at ${bp.name}`, async ({ page }) => {
// All breakpoints should have social links
await expect(
page.getByRole("link", { name: /follow us on bluesky/i })
page.getByRole("link", { name: /follow us on bluesky/i }),
).toBeVisible();
await expect(
page.getByRole("link", { name: /follow us on gitlab/i })
page.getByRole("link", { name: /follow us on gitlab/i }),
).toBeVisible();
});
@@ -110,7 +110,7 @@ test.describe("Footer visual regression", () => {
// Take a screenshot for visual regression testing
await expect(page.locator("footer").first()).toHaveScreenshot(
`footer-${bp.name}.png`
`footer-${bp.name}.png`,
);
}
});
@@ -136,7 +136,7 @@ test.describe("Footer visual regression", () => {
await useCasesLink.hover();
await page.waitForTimeout(200);
await expect(page.locator("footer").first()).toHaveScreenshot(
`footer-${bp.name}-hover-nav.png`
`footer-${bp.name}-hover-nav.png`,
);
// Test hover on social links
@@ -146,7 +146,7 @@ test.describe("Footer visual regression", () => {
await blueskyLink.hover();
await page.waitForTimeout(200);
await expect(page.locator("footer").first()).toHaveScreenshot(
`footer-${bp.name}-hover-social.png`
`footer-${bp.name}-hover-social.png`,
);
}
});
@@ -172,7 +172,7 @@ test.describe("Footer visual regression", () => {
await useCasesLink.focus();
await page.waitForTimeout(200);
await expect(page.locator("footer").first()).toHaveScreenshot(
`footer-${bp.name}-focus-nav.png`
`footer-${bp.name}-focus-nav.png`,
);
// Test focus on social links
@@ -182,7 +182,7 @@ test.describe("Footer visual regression", () => {
await blueskyLink.focus();
await page.waitForTimeout(200);
await expect(page.locator("footer").first()).toHaveScreenshot(
`footer-${bp.name}-focus-social.png`
`footer-${bp.name}-focus-social.png`,
);
}
});
+8 -8
View File
@@ -33,7 +33,7 @@ for (const bp of breakpoints) {
test(`navigation items visibility at ${bp.name}`, async ({ page }) => {
// All breakpoints should have navigation items
await expect(
page.getByRole("link", { name: /use cases/i })
page.getByRole("link", { name: /use cases/i }),
).toBeVisible();
await expect(page.getByRole("link", { name: /learn/i })).toBeVisible();
await expect(page.getByRole("link", { name: /about/i })).toBeVisible();
@@ -44,14 +44,14 @@ for (const bp of breakpoints) {
}) => {
// All breakpoints should have login button
await expect(
page.getByRole("link", { name: /log in to your account/i })
page.getByRole("link", { name: /log in to your account/i }),
).toBeVisible();
// All breakpoints should have create rule button
await expect(
page.getByRole("button", {
name: /create a new rule with avatar decoration/i,
})
}),
).toBeVisible();
});
@@ -149,7 +149,7 @@ test.describe("Header visual regression", () => {
// Take a screenshot for visual regression testing
await expect(page.locator("header").first()).toHaveScreenshot(
`header-${bp.name}.png`
`header-${bp.name}.png`,
);
}
});
@@ -171,7 +171,7 @@ test.describe("Header visual regression", () => {
await useCasesLink.hover();
await page.waitForTimeout(200);
await expect(page.locator("header").first()).toHaveScreenshot(
`header-${bp.name}-hover-nav.png`
`header-${bp.name}-hover-nav.png`,
);
// Test hover on create rule button
@@ -181,7 +181,7 @@ test.describe("Header visual regression", () => {
await createRuleButton.hover();
await page.waitForTimeout(200);
await expect(page.locator("header").first()).toHaveScreenshot(
`header-${bp.name}-hover-button.png`
`header-${bp.name}-hover-button.png`,
);
}
});
@@ -203,7 +203,7 @@ test.describe("Header visual regression", () => {
await useCasesLink.focus();
await page.waitForTimeout(200);
await expect(page.locator("header").first()).toHaveScreenshot(
`header-${bp.name}-focus-nav.png`
`header-${bp.name}-focus-nav.png`,
);
// Test focus on create rule button
@@ -213,7 +213,7 @@ test.describe("Header visual regression", () => {
await createRuleButton.focus();
await page.waitForTimeout(200);
await expect(page.locator("header").first()).toHaveScreenshot(
`header-${bp.name}-focus-button.png`
`header-${bp.name}-focus-button.png`,
);
}
});
+2 -2
View File
@@ -2,7 +2,7 @@ import { Locator, Page } from "@playwright/test";
export async function findVisibleButton(
page: Page,
text: string
text: string,
): Promise<Locator> {
const buttons = page.locator(`button:has-text("${text}")`);
const buttonCount = await buttons.count();
@@ -19,7 +19,7 @@ export async function findVisibleButton(
export async function findVisibleElement(
page: Page,
selector: string
selector: string,
): Promise<Locator> {
const elements = page.locator(selector);
const elementCount = await elements.count();
+37 -37
View File
@@ -12,19 +12,19 @@ test.describe("Homepage", () => {
// Check main sections are present
await expect(
page.locator("h1, h2").filter({ hasText: "Collaborate" })
page.locator("h1, h2").filter({ hasText: "Collaborate" }),
).toBeVisible();
await expect(
page.locator("h2").filter({ hasText: "How CommunityRule works" })
page.locator("h2").filter({ hasText: "How CommunityRule works" }),
).toBeVisible();
await expect(
page.locator("h1").filter({ hasText: "We've got your back" })
page.locator("h1").filter({ hasText: "We've got your back" }),
).toBeVisible();
// Check key components are rendered
await expect(page.locator('img[alt="Hero illustration"]')).toBeVisible();
await expect(
page.locator("text=Trusted by leading cooperators")
page.locator("text=Trusted by leading cooperators"),
).toBeVisible();
await expect(page.locator("text=Jo Freeman")).toBeVisible();
});
@@ -34,12 +34,12 @@ test.describe("Homepage", () => {
await expect(page.locator("text=Collaborate")).toBeVisible();
await expect(page.locator("text=with clarity")).toBeVisible();
await expect(
page.locator("text=Help your community make important decisions")
page.locator("text=Help your community make important decisions"),
).toBeVisible();
// Check CTA button
const learnButtons = page.locator(
'button:has-text("Learn how CommunityRule works")'
'button:has-text("Learn how CommunityRule works")',
);
const buttonCount = await learnButtons.count();
let visibleButton = null;
@@ -54,7 +54,7 @@ test.describe("Homepage", () => {
if (!visibleButton) {
throw new Error(
'No visible "Learn how CommunityRule works" button found'
'No visible "Learn how CommunityRule works" button found',
);
}
@@ -64,14 +64,14 @@ test.describe("Homepage", () => {
await visibleButton.click();
// Should scroll to the numbered cards section
await expect(
page.locator('h2:has-text("How CommunityRule works")')
page.locator('h2:has-text("How CommunityRule works")'),
).toBeVisible();
});
test("logo wall section displays correctly", async ({ page }) => {
// Check section label
await expect(
page.locator("text=Trusted by leading cooperators")
page.locator("text=Trusted by leading cooperators"),
).toBeVisible();
// Check logos are present
@@ -95,23 +95,23 @@ test.describe("Homepage", () => {
test("numbered cards section functionality", async ({ page }) => {
// Check section header
await expect(
page.locator('h2:has-text("How CommunityRule works")')
page.locator('h2:has-text("How CommunityRule works")'),
).toBeVisible();
await expect(
page.locator("text=Here's a quick overview of the process")
page.locator("text=Here's a quick overview of the process"),
).toBeVisible();
// Check all three cards are present
await expect(
page.locator("text=Document how your community makes decisions")
page.locator("text=Document how your community makes decisions"),
).toBeVisible();
await expect(
page.locator("text=Build an operating manual for a successful community")
page.locator("text=Build an operating manual for a successful community"),
).toBeVisible();
await expect(
page.locator(
"text=Get a link to your manual for your group to review and evolve"
)
"text=Get a link to your manual for your group to review and evolve",
),
).toBeVisible();
// Check numbered indicators
@@ -121,7 +121,7 @@ test.describe("Homepage", () => {
// Check CTA buttons
const createButtons = page.locator(
'button:has-text("Create CommunityRule")'
'button:has-text("Create CommunityRule")',
);
const createButtonCount = await createButtons.count();
let visibleCreateButton = null;
@@ -139,7 +139,7 @@ test.describe("Homepage", () => {
}
await expect(
page.locator('button:has-text("See how it works")')
page.locator('button:has-text("See how it works")'),
).toBeVisible();
});
@@ -152,16 +152,16 @@ test.describe("Homepage", () => {
// Check rule descriptions
await expect(
page.locator("text=Units called Circles have the ability to decide")
page.locator("text=Units called Circles have the ability to decide"),
).toBeVisible();
await expect(
page.locator("text=Decisions that affect the group collectively")
page.locator("text=Decisions that affect the group collectively"),
).toBeVisible();
await expect(
page.locator("text=An elected board determines policies")
page.locator("text=An elected board determines policies"),
).toBeVisible();
await expect(
page.locator("text=All participants can propose and vote")
page.locator("text=All participants can propose and vote"),
).toBeVisible();
// Test card interactions
@@ -171,19 +171,19 @@ test.describe("Homepage", () => {
// Check "See all templates" button
await expect(
page.locator('button:has-text("See all templates")')
page.locator('button:has-text("See all templates")'),
).toBeVisible();
});
test("feature grid section functionality", async ({ page }) => {
// Check section header
await expect(
page.locator('h1:has-text("We\'ve got your back")')
page.locator('h1:has-text("We\'ve got your back")'),
).toBeVisible();
await expect(
page.locator(
"text=Use our toolkit to improve, document, and evolve your organization"
)
"text=Use our toolkit to improve, document, and evolve your organization",
),
).toBeVisible();
// Check all four feature cards - use more specific selectors to avoid conflicts
@@ -205,23 +205,23 @@ test.describe("Homepage", () => {
test("quote block section displays correctly", async ({ page }) => {
// Check quote content
await expect(
page.locator("text=The rules of decision-making must be open")
page.locator("text=The rules of decision-making must be open"),
).toBeVisible();
// Check author and source
await expect(page.locator("text=Jo Freeman")).toBeVisible();
await expect(
page.locator("text=The Tyranny of Structurelessness")
page.locator("text=The Tyranny of Structurelessness"),
).toBeVisible();
// Check avatar
await expect(
page.locator('img[alt="Portrait of Jo Freeman"]')
page.locator('img[alt="Portrait of Jo Freeman"]'),
).toBeVisible();
// Check decorative elements
await expect(
page.locator('[class*="pointer-events-none absolute z-0"]').first()
page.locator('[class*="pointer-events-none absolute z-0"]').first(),
).toBeVisible();
});
@@ -229,7 +229,7 @@ test.describe("Homepage", () => {
// Check section content
await expect(page.locator("text=Still have questions?")).toBeVisible();
await expect(
page.locator("text=Get answers from an experienced organizer")
page.locator("text=Get answers from an experienced organizer"),
).toBeVisible();
// Check CTA button (it's actually a link)
@@ -286,19 +286,19 @@ test.describe("Homepage", () => {
// Test mobile viewport
await page.setViewportSize({ width: 375, height: 667 });
await expect(
page.locator("h1, h2").filter({ hasText: "Collaborate" })
page.locator("h1, h2").filter({ hasText: "Collaborate" }),
).toBeVisible();
// Test tablet viewport
await page.setViewportSize({ width: 768, height: 1024 });
await expect(
page.locator("h1, h2").filter({ hasText: "Collaborate" })
page.locator("h1, h2").filter({ hasText: "Collaborate" }),
).toBeVisible();
// Test desktop viewport
await page.setViewportSize({ width: 1440, height: 900 });
await expect(
page.locator("h1, h2").filter({ hasText: "Collaborate" })
page.locator("h1, h2").filter({ hasText: "Collaborate" }),
).toBeVisible();
});
@@ -362,7 +362,7 @@ test.describe("Homepage", () => {
test("scroll behavior and smooth scrolling", async ({ page }) => {
// Test smooth scrolling to sections
const learnButtons = page.locator(
'button:has-text("Learn how CommunityRule works")'
'button:has-text("Learn how CommunityRule works")',
);
const buttonCount = await learnButtons.count();
let visibleButton = null;
@@ -377,7 +377,7 @@ test.describe("Homepage", () => {
if (!visibleButton) {
throw new Error(
'No visible "Learn how CommunityRule works" button found'
'No visible "Learn how CommunityRule works" button found',
);
}
@@ -388,7 +388,7 @@ test.describe("Homepage", () => {
// Check we're at the numbered cards section
await expect(
page.locator('h2:has-text("How CommunityRule works")')
page.locator('h2:has-text("How CommunityRule works")'),
).toBeVisible();
});
@@ -405,7 +405,7 @@ test.describe("Homepage", () => {
const brokenImages = await page.evaluate(() => {
const imgs = document.querySelectorAll("img");
return Array.from(imgs).filter(
(img) => !img.complete || img.naturalWidth === 0
(img) => !img.complete || img.naturalWidth === 0,
);
});
+20 -23
View File
@@ -65,7 +65,7 @@ test.describe("Performance Monitoring", () => {
// Assert individual metrics
expect(result.metrics.ttfb).toBeLessThan(PERFORMANCE_BUDGETS.ttfb);
expect(result.metrics.domContentLoaded).toBeLessThan(
PERFORMANCE_BUDGETS.dom_content_loaded
PERFORMANCE_BUDGETS.dom_content_loaded,
);
expect(result.metrics.load).toBeLessThan(PERFORMANCE_BUDGETS.full_load);
@@ -121,10 +121,10 @@ test.describe("Performance Monitoring", () => {
// Assert Core Web Vitals are within acceptable ranges
expect(coreWebVitals.lcp).toBeLessThan(
PERFORMANCE_BUDGETS.largest_contentful_paint
PERFORMANCE_BUDGETS.largest_contentful_paint,
);
expect(coreWebVitals.fid).toBeLessThan(
PERFORMANCE_BUDGETS.first_input_delay
PERFORMANCE_BUDGETS.first_input_delay,
);
expect(coreWebVitals.cls).toBeLessThan(0.1); // CLS should be less than 0.1
});
@@ -133,27 +133,24 @@ test.describe("Performance Monitoring", () => {
await page.goto("/");
// Measure header render time
const headerRenderTime = await performanceMonitor.measureComponentRender(
"header"
);
const headerRenderTime =
await performanceMonitor.measureComponentRender("header");
expect(headerRenderTime).toBeLessThan(
PERFORMANCE_BUDGETS.component_render_time
PERFORMANCE_BUDGETS.component_render_time,
);
// Measure footer render time
const footerRenderTime = await performanceMonitor.measureComponentRender(
"footer"
);
const footerRenderTime =
await performanceMonitor.measureComponentRender("footer");
expect(footerRenderTime).toBeLessThan(
PERFORMANCE_BUDGETS.component_render_time
PERFORMANCE_BUDGETS.component_render_time,
);
// Measure main content render time
const mainRenderTime = await performanceMonitor.measureComponentRender(
"main"
);
const mainRenderTime =
await performanceMonitor.measureComponentRender("main");
expect(mainRenderTime).toBeLessThan(
PERFORMANCE_BUDGETS.component_render_time
PERFORMANCE_BUDGETS.component_render_time,
);
});
@@ -168,7 +165,7 @@ test.describe("Performance Monitoring", () => {
'button:has-text("Learn how CommunityRule works")',
async () => {
const learnButtons = page.locator(
'button:has-text("Learn how CommunityRule works")'
'button:has-text("Learn how CommunityRule works")',
);
const buttonCount = await learnButtons.count();
let visibleButton = null;
@@ -183,12 +180,12 @@ test.describe("Performance Monitoring", () => {
if (!visibleButton) {
throw new Error(
'No visible "Learn how CommunityRule works" button found'
'No visible "Learn how CommunityRule works" button found',
);
}
await visibleButton.click();
}
},
);
expect(buttonClickTime).toBeLessThan(PERFORMANCE_BUDGETS.interaction_time);
@@ -213,7 +210,7 @@ test.describe("Performance Monitoring", () => {
}
await visibleLink.click();
}
},
);
expect(linkClickTime).toBeLessThan(PERFORMANCE_BUDGETS.interaction_time);
});
@@ -250,7 +247,7 @@ test.describe("Performance Monitoring", () => {
const summary = performanceMonitor.getSummary();
if (summary.network_request_duration) {
expect(summary.network_request_duration.average).toBeLessThan(
PERFORMANCE_BUDGETS.network_request_duration
PERFORMANCE_BUDGETS.network_request_duration,
);
}
});
@@ -293,7 +290,7 @@ test.describe("Performance Monitoring", () => {
// Even under load, page should load within reasonable time
expect(result.loadTime).toBeLessThan(
PERFORMANCE_BUDGETS.page_load_time * 1.5
PERFORMANCE_BUDGETS.page_load_time * 1.5,
);
});
@@ -343,7 +340,7 @@ test.describe("Performance Monitoring", () => {
console.log(
"Exported Performance Data:",
JSON.stringify(exportedData, null, 2)
JSON.stringify(exportedData, null, 2),
);
});
@@ -402,7 +399,7 @@ test.describe("Performance Regression Testing", () => {
const variance =
results.reduce(
(acc, val) => acc + Math.pow(val - averageLoadTime, 2),
0
0,
) / results.length;
// Performance should be consistent (low variance)
+9 -9
View File
@@ -11,7 +11,7 @@ test.describe("User Journeys", () => {
// 2. User reads hero section
await expect(
page.locator("text=Help your community make important decisions")
page.locator("text=Help your community make important decisions"),
).toBeVisible();
// 3. User clicks CTA to learn more
@@ -24,20 +24,20 @@ test.describe("User Journeys", () => {
// 4. User scrolls to numbered cards section
await expect(
page.locator('h2:has-text("How CommunityRule works")')
page.locator('h2:has-text("How CommunityRule works")'),
).toBeVisible();
// 5. User reads the process steps
await expect(
page.locator("text=Document how your community makes decisions")
page.locator("text=Document how your community makes decisions"),
).toBeVisible();
await expect(
page.locator("text=Build an operating manual for a successful community")
page.locator("text=Build an operating manual for a successful community"),
).toBeVisible();
await expect(
page.locator(
"text=Get a link to your manual for your group to review and evolve"
)
"text=Get a link to your manual for your group to review and evolve",
),
).toBeVisible();
// 6. User explores rule templates
@@ -78,7 +78,7 @@ test.describe("User Journeys", () => {
// 10. User creates CommunityRule
const createButton = page.locator(
'button:has-text("Create CommunityRule")'
'button:has-text("Create CommunityRule")',
);
if (
(await createButton.count()) > 0 &&
@@ -139,7 +139,7 @@ test.describe("User Journeys", () => {
// Read the section
await expect(
page.locator("text=Get answers from an experienced organizer")
page.locator("text=Get answers from an experienced organizer"),
).toBeVisible();
// Click contact button - check if it exists and is visible first
@@ -158,7 +158,7 @@ test.describe("User Journeys", () => {
test("user journey: create CommunityRule", async ({ page }) => {
// Simplified approach - just check if the button exists and is visible
const createButton = page.locator(
'button:has-text("Create CommunityRule")'
'button:has-text("Create CommunityRule")',
);
if (
+1 -1
View File
@@ -349,7 +349,7 @@ test.describe("Visual Regression Tests", () => {
await page.evaluate(() => {
document.documentElement.style.setProperty(
"--prefers-reduced-motion",
"reduce"
"reduce",
);
});
@@ -16,18 +16,18 @@ describe("ContentLockup Integration", () => {
subtitle="Get Started"
description="This is a description"
ctaText="Get Started"
/>
/>,
);
expect(
screen.getByRole("heading", { name: "Welcome" })
screen.getByRole("heading", { name: "Welcome" }),
).toBeInTheDocument();
expect(
screen.getByRole("heading", { name: "Get Started" })
screen.getByRole("heading", { name: "Get Started" }),
).toBeInTheDocument();
expect(screen.getByText("This is a description")).toBeInTheDocument();
expect(screen.getAllByRole("button", { name: "Get Started" })).toHaveLength(
3
3,
);
});
@@ -40,18 +40,18 @@ describe("ContentLockup Integration", () => {
description="Feature description"
linkText="Learn More"
linkHref="/learn"
/>
/>,
);
expect(
screen.getByRole("heading", { name: "Feature Title" })
screen.getByRole("heading", { name: "Feature Title" }),
).toBeInTheDocument();
expect(
screen.getByRole("link", { name: "Learn More" })
screen.getByRole("link", { name: "Learn More" }),
).toBeInTheDocument();
expect(screen.getByRole("link", { name: "Learn More" })).toHaveAttribute(
"href",
"/learn"
"/learn",
);
});
@@ -61,14 +61,14 @@ describe("ContentLockup Integration", () => {
variant="ask"
title="Ask Question"
subtitle="Ask subtitle"
/>
/>,
);
expect(
screen.getByRole("heading", { name: "Ask Question" })
screen.getByRole("heading", { name: "Ask Question" }),
).toBeInTheDocument();
expect(
screen.getByRole("heading", { name: "Ask subtitle" })
screen.getByRole("heading", { name: "Ask subtitle" }),
).toBeInTheDocument();
// Ask variant should not have description or CTA
expect(screen.queryByRole("button")).not.toBeInTheDocument();
@@ -81,7 +81,7 @@ describe("ContentLockup Integration", () => {
title="Left Aligned"
subtitle="Subtitle"
alignment="left"
/>
/>,
);
const container = screen
@@ -92,7 +92,7 @@ describe("ContentLockup Integration", () => {
test("renders responsive buttons correctly", () => {
render(
<ContentLockup variant="hero" title="Responsive" ctaText="Click Me" />
<ContentLockup variant="hero" title="Responsive" ctaText="Click Me" />,
);
// Should render all three button variants for different breakpoints
@@ -107,7 +107,7 @@ describe("ContentLockup Integration", () => {
title="Custom Button"
ctaText="Custom"
buttonClassName="custom-button-class"
/>
/>,
);
const buttons = screen.getAllByRole("button", { name: "Custom" });
@@ -119,7 +119,7 @@ describe("ContentLockup Integration", () => {
render(<ContentLockup variant="hero" title="Minimal" />);
expect(
screen.getByRole("heading", { name: "Minimal" })
screen.getByRole("heading", { name: "Minimal" }),
).toBeInTheDocument();
// Should not crash without subtitle, description, or CTA
expect(screen.queryByRole("button")).not.toBeInTheDocument();
@@ -146,7 +146,7 @@ describe("ContentLockup Integration", () => {
title="Accessible"
linkText="Accessible Link"
linkHref="/accessible"
/>
/>,
);
const link = screen.getByRole("link", { name: "Accessible Link" });
@@ -49,26 +49,26 @@ describe("Component Interactions Integration", () => {
<div>
<HeroBanner {...heroData} />
<NumberedCards {...numberedCardsData} />
</div>
</div>,
);
// Hero introduces the concept
expect(
screen.getByText(/Help your community make important decisions/)
screen.getByText(/Help your community make important decisions/),
).toBeInTheDocument();
// Numbered cards explain the process
expect(screen.getByText("How CommunityRule works")).toBeInTheDocument();
expect(
screen.getByText("Document how your community makes decisions")
screen.getByText("Document how your community makes decisions"),
).toBeInTheDocument();
expect(
screen.getByText("Build an operating manual for a successful community")
screen.getByText("Build an operating manual for a successful community"),
).toBeInTheDocument();
expect(
screen.getByText(
"Get a link to your manual for your group to review and evolve"
)
"Get a link to your manual for your group to review and evolve",
),
).toBeInTheDocument();
});
@@ -83,7 +83,7 @@ describe("Component Interactions Integration", () => {
<div>
<RuleStack />
<FeatureGrid {...featureGridData} />
</div>
</div>,
);
// Rule stack shows governance options
@@ -94,12 +94,12 @@ describe("Component Interactions Integration", () => {
// Feature grid provides support context
expect(
screen.getByText("We've got your back, every step of the way")
screen.getByText("We've got your back, every step of the way"),
).toBeInTheDocument();
expect(
screen.getByText(
"Use our toolkit to improve, document, and evolve your organization."
)
"Use our toolkit to improve, document, and evolve your organization.",
),
).toBeInTheDocument();
});
@@ -108,13 +108,13 @@ describe("Component Interactions Integration", () => {
// Quote provides credibility and social proof
expect(
screen.getByText(/The rules of decision-making must be open/)
screen.getByText(/The rules of decision-making must be open/),
).toBeInTheDocument();
// Should have proper attribution
expect(screen.getByText("Jo Freeman")).toBeInTheDocument();
expect(
screen.getByText("The Tyranny of Structurelessness")
screen.getByText("The Tyranny of Structurelessness"),
).toBeInTheDocument();
});
@@ -131,10 +131,10 @@ describe("Component Interactions Integration", () => {
// Provides help for users who need assistance
expect(screen.getByText("Still have questions?")).toBeInTheDocument();
expect(
screen.getByText("Get answers from an experienced organizer")
screen.getByText("Get answers from an experienced organizer"),
).toBeInTheDocument();
expect(
screen.getByRole("link", { name: /Ask an organizer/i })
screen.getByRole("link", { name: /Ask an organizer/i }),
).toBeInTheDocument();
});
@@ -160,7 +160,7 @@ describe("Component Interactions Integration", () => {
subtitle="Test help subtitle"
buttonText="Test Help Button"
/>
</div>
</div>,
);
// All components should render without errors
@@ -169,7 +169,7 @@ describe("Component Interactions Integration", () => {
expect(screen.getByText("Consensus clusters")).toBeInTheDocument();
expect(screen.getByText("Test Features")).toBeInTheDocument();
expect(
screen.getByText(/The rules of decision-making must be open/)
screen.getByText(/The rules of decision-making must be open/),
).toBeInTheDocument();
expect(screen.getByText("Test Help")).toBeInTheDocument();
});
@@ -209,7 +209,7 @@ describe("Component Interactions Integration", () => {
<NumberedCards {...testData.cards} />
<FeatureGrid {...testData.features} />
<AskOrganizer {...testData.help} />
</div>
</div>,
);
// Verify all data is passed correctly
@@ -217,7 +217,7 @@ describe("Component Interactions Integration", () => {
expect(screen.getByText("Test Subtitle")).toBeInTheDocument();
expect(screen.getByText("Test description")).toBeInTheDocument();
expect(
screen.getAllByRole("button", { name: "Test CTA" }).length
screen.getAllByRole("button", { name: "Test CTA" }).length,
).toBeGreaterThan(0);
expect(screen.getByText("Test Cards")).toBeInTheDocument();
expect(screen.getByText("Card 1")).toBeInTheDocument();
@@ -225,7 +225,7 @@ describe("Component Interactions Integration", () => {
expect(screen.getByText("Test Features")).toBeInTheDocument();
expect(screen.getByText("Test Help")).toBeInTheDocument();
expect(
screen.getByRole("link", { name: /Test Help Button/i })
screen.getByRole("link", { name: /Test Help Button/i }),
).toBeInTheDocument();
});
@@ -258,7 +258,7 @@ describe("Component Interactions Integration", () => {
buttonText="Contact us"
buttonHref="#contact"
/>
</div>
</div>,
);
// Test interaction flow
@@ -281,7 +281,7 @@ describe("Component Interactions Integration", () => {
expect(screen.getByText("Consensus clusters")).toBeInTheDocument();
expect(screen.getByText("Features")).toBeInTheDocument();
expect(
screen.getByText(/The rules of decision-making must be open/)
screen.getByText(/The rules of decision-making must be open/),
).toBeInTheDocument();
expect(screen.getByText("Need help?")).toBeInTheDocument();
});
@@ -294,7 +294,7 @@ describe("Component Interactions Integration", () => {
<NumberedCards title="Minimal Cards" cards={[]} />
<FeatureGrid title="Minimal Features" />
<AskOrganizer title="Minimal Help" />
</div>
</div>,
);
// Components should render without crashing
@@ -331,7 +331,7 @@ describe("Component Interactions Integration", () => {
subtitle="Accessible help subtitle"
buttonText="Accessible Help Button"
/>
</div>
</div>,
);
// Check for proper heading hierarchy
+19 -17
View File
@@ -14,7 +14,7 @@ describe("Layout Integration", () => {
<div>
<Header />
<Footer />
</div>
</div>,
);
// Check that CommunityRule branding appears in both header and footer
@@ -30,19 +30,21 @@ describe("Layout Integration", () => {
<div>
<Header />
<Footer />
</div>
</div>,
);
// Header navigation items
expect(
screen.getAllByRole("menuitem", { name: "Navigate to Use cases page" })
.length
.length,
).toBeGreaterThan(0);
expect(
screen.getAllByRole("menuitem", { name: "Navigate to Learn page" }).length
screen.getAllByRole("menuitem", { name: "Navigate to Learn page" })
.length,
).toBeGreaterThan(0);
expect(
screen.getAllByRole("menuitem", { name: "Navigate to About page" }).length
screen.getAllByRole("menuitem", { name: "Navigate to About page" })
.length,
).toBeGreaterThan(0);
// Footer navigation items (should be present in footer as well)
@@ -92,23 +94,23 @@ describe("Layout Integration", () => {
// Contact information
expect(screen.getByText("medlab@colorado.edu")).toBeInTheDocument();
expect(
screen.getByRole("link", { name: "medlab@colorado.edu" })
screen.getByRole("link", { name: "medlab@colorado.edu" }),
).toHaveAttribute("href", "mailto:medlab@colorado.edu");
// Social media links
expect(
screen.getByRole("link", { name: "Follow us on Bluesky" })
screen.getByRole("link", { name: "Follow us on Bluesky" }),
).toBeInTheDocument();
expect(
screen.getByRole("link", { name: "Follow us on GitLab" })
screen.getByRole("link", { name: "Follow us on GitLab" }),
).toBeInTheDocument();
// Legal links
expect(
screen.getByRole("link", { name: "Privacy Policy" })
screen.getByRole("link", { name: "Privacy Policy" }),
).toBeInTheDocument();
expect(
screen.getByRole("link", { name: "Terms of Service" })
screen.getByRole("link", { name: "Terms of Service" }),
).toBeInTheDocument();
});
@@ -134,7 +136,7 @@ describe("Layout Integration", () => {
<div>
<Header />
<Footer />
</div>
</div>,
);
// Header should have banner role
@@ -155,7 +157,7 @@ describe("Layout Integration", () => {
<div>
<Header />
<Footer />
</div>
</div>,
);
// Header should have responsive navigation elements
@@ -172,7 +174,7 @@ describe("Layout Integration", () => {
<div>
<Header />
<Footer />
</div>
</div>,
);
// Get all interactive elements
@@ -195,7 +197,7 @@ describe("Layout Integration", () => {
<div>
<Header />
<Footer />
</div>
</div>,
);
// Header provides main navigation
@@ -215,7 +217,7 @@ describe("Layout Integration", () => {
<div>
<Header />
<Footer />
</div>
</div>,
);
// Main navigation in header
@@ -228,13 +230,13 @@ describe("Layout Integration", () => {
(link) =>
link.textContent?.includes("Use cases") ||
link.textContent?.includes("Learn") ||
link.textContent?.includes("About")
link.textContent?.includes("About"),
);
expect(navigationLinks.length).toBeGreaterThan(0);
// Contact information in footer
expect(
screen.getByRole("link", { name: "medlab@colorado.edu" })
screen.getByRole("link", { name: "medlab@colorado.edu" }),
).toBeInTheDocument();
});
});
@@ -13,15 +13,15 @@ describe("Page Flow Integration", () => {
// Hero Banner section
expect(
screen.getByRole("heading", { name: "Collaborate" })
screen.getByRole("heading", { name: "Collaborate" }),
).toBeInTheDocument();
expect(
screen.getByRole("heading", { name: "with clarity" })
screen.getByRole("heading", { name: "with clarity" }),
).toBeInTheDocument();
expect(
screen.getByText(
"Help your community make important decisions in a way that reflects its unique values."
)
"Help your community make important decisions in a way that reflects its unique values.",
),
).toBeInTheDocument();
// Check that CTA button exists (multiple sizes for responsive design)
const ctaButtons = screen.getAllByRole("button", {
@@ -39,65 +39,65 @@ describe("Page Flow Integration", () => {
// Numbered Cards section
expect(
screen.getByRole("heading", { name: /How CommunityRule works/ })
screen.getByRole("heading", { name: /How CommunityRule works/ }),
).toBeInTheDocument();
expect(
screen.getByText(
"Here's a quick overview of the process, from start to finish."
)
"Here's a quick overview of the process, from start to finish.",
),
).toBeInTheDocument();
expect(
screen.getByText("Document how your community makes decisions")
screen.getByText("Document how your community makes decisions"),
).toBeInTheDocument();
expect(
screen.getByText("Build an operating manual for a successful community")
screen.getByText("Build an operating manual for a successful community"),
).toBeInTheDocument();
expect(
screen.getByText(
"Get a link to your manual for your group to review and evolve"
)
"Get a link to your manual for your group to review and evolve",
),
).toBeInTheDocument();
// Rule Stack section
expect(
screen.getByRole("heading", { name: "Consensus clusters" })
screen.getByRole("heading", { name: "Consensus clusters" }),
).toBeInTheDocument();
expect(
screen.getByRole("heading", { name: "Elected Board" })
screen.getByRole("heading", { name: "Elected Board" }),
).toBeInTheDocument();
expect(
screen.getByRole("heading", { name: "Consensus" })
screen.getByRole("heading", { name: "Consensus" }),
).toBeInTheDocument();
expect(
screen.getByRole("heading", { name: "Petition" })
screen.getByRole("heading", { name: "Petition" }),
).toBeInTheDocument();
// Feature Grid section
expect(
screen.getByRole("heading", {
name: "We've got your back, every step of the way",
})
}),
).toBeInTheDocument();
expect(
screen.getByText(
"Use our toolkit to improve, document, and evolve your organization."
)
"Use our toolkit to improve, document, and evolve your organization.",
),
).toBeInTheDocument();
// Quote Block section
expect(
screen.getByText(/The rules of decision-making must be open/)
screen.getByText(/The rules of decision-making must be open/),
).toBeInTheDocument();
// Ask Organizer section
expect(
screen.getByRole("heading", { name: "Still have questions?" })
screen.getByRole("heading", { name: "Still have questions?" }),
).toBeInTheDocument();
expect(
screen.getByText("Get answers from an experienced organizer")
screen.getByText("Get answers from an experienced organizer"),
).toBeInTheDocument();
expect(
screen.getByRole("link", { name: /Ask an organizer/i })
screen.getByRole("link", { name: /Ask an organizer/i }),
).toBeInTheDocument();
});
@@ -125,7 +125,7 @@ describe("Page Flow Integration", () => {
// Check that all three cards are rendered
const cards = screen.getAllByText(
/Document how your community|Build an operating manual|Get a link to your manual/
/Document how your community|Build an operating manual|Get a link to your manual/,
);
expect(cards).toHaveLength(3);
@@ -167,7 +167,7 @@ describe("Page Flow Integration", () => {
// Check that main content is properly structured
const mainContent = screen.getByText(
/Help your community make important decisions/
/Help your community make important decisions/,
);
expect(mainContent).toBeInTheDocument();
});
@@ -194,7 +194,7 @@ describe("Page Flow Integration", () => {
// Verify the logical flow of information
// 1. Hero introduces the concept
expect(
screen.getByText(/Help your community make important decisions/)
screen.getByText(/Help your community make important decisions/),
).toBeInTheDocument();
// 2. How it works section explains the process
@@ -205,12 +205,12 @@ describe("Page Flow Integration", () => {
// 4. Features highlight benefits
expect(
screen.getByText("We've got your back, every step of the way")
screen.getByText("We've got your back, every step of the way"),
).toBeInTheDocument();
// 5. Quote provides social proof
expect(
screen.getByText(/The rules of decision-making must be open/)
screen.getByText(/The rules of decision-making must be open/),
).toBeInTheDocument();
// 6. Call to action for help
@@ -17,12 +17,12 @@ describe("User Journey Integration", () => {
<Header />
<Page />
<Footer />
</div>
</div>,
);
// User sees the main value proposition
expect(
screen.getByText(/Help your community make important decisions/)
screen.getByText(/Help your community make important decisions/),
).toBeInTheDocument();
// User clicks the main CTA to learn more
@@ -64,7 +64,7 @@ describe("User Journey Integration", () => {
<Header />
<Page />
<Footer />
</div>
</div>,
);
// User clicks on navigation links in header (check that they exist and are clickable)
@@ -73,7 +73,7 @@ describe("User Journey Integration", () => {
(link) =>
link.textContent?.includes("Use Cases") ||
link.textContent?.includes("Learn") ||
link.textContent?.includes("About")
link.textContent?.includes("About"),
);
// Test that navigation links are present and clickable
@@ -90,7 +90,7 @@ describe("User Journey Integration", () => {
// User scrolls to the bottom and sees the help section
expect(screen.getByText("Still have questions?")).toBeInTheDocument();
expect(
screen.getByText("Get answers from an experienced organizer")
screen.getByText("Get answers from an experienced organizer"),
).toBeInTheDocument();
// User clicks the ask organizer button (it's actually a link, not a button)
@@ -105,15 +105,15 @@ describe("User Journey Integration", () => {
// User reads through the process steps
expect(
screen.getByText("Document how your community makes decisions")
screen.getByText("Document how your community makes decisions"),
).toBeInTheDocument();
expect(
screen.getByText("Build an operating manual for a successful community")
screen.getByText("Build an operating manual for a successful community"),
).toBeInTheDocument();
expect(
screen.getByText(
"Get a link to your manual for your group to review and evolve"
)
"Get a link to your manual for your group to review and evolve",
),
).toBeInTheDocument();
// User sees the step numbers
@@ -128,7 +128,7 @@ describe("User Journey Integration", () => {
<Header />
<Page />
<Footer />
</div>
</div>,
);
// User finds contact email in footer
@@ -153,17 +153,17 @@ describe("User Journey Integration", () => {
// User sees the features section
expect(
screen.getByText("We've got your back, every step of the way")
screen.getByText("We've got your back, every step of the way"),
).toBeInTheDocument();
expect(
screen.getByText(
"Use our toolkit to improve, document, and evolve your organization."
)
"Use our toolkit to improve, document, and evolve your organization.",
),
).toBeInTheDocument();
// User sees the testimonial/quote (check for the actual quote content)
expect(
screen.getByText(/The rules of decision-making must be open/)
screen.getByText(/The rules of decision-making must be open/),
).toBeInTheDocument();
});
@@ -173,7 +173,7 @@ describe("User Journey Integration", () => {
<div>
<Page />
<Footer />
</div>
</div>,
);
// User sees the logo wall with partner logos (check for any logo images)
@@ -185,7 +185,7 @@ describe("User Journey Integration", () => {
img.alt?.includes("Metagov") ||
img.alt?.includes("Open Civics") ||
img.alt?.includes("Mutual Aid CO") ||
img.alt?.includes("CU Boulder")
img.alt?.includes("CU Boulder"),
);
expect(partnerLogos.length).toBeGreaterThan(0);
@@ -203,7 +203,7 @@ describe("User Journey Integration", () => {
<Header />
<Page />
<Footer />
</div>
</div>,
);
// 1. User discovers the application
@@ -218,12 +218,12 @@ describe("User Journey Integration", () => {
// 4. User sees features and benefits
expect(
screen.getByText("We've got your back, every step of the way")
screen.getByText("We've got your back, every step of the way"),
).toBeInTheDocument();
// 5. User sees social proof
expect(
screen.getByText(/The rules of decision-making must be open/)
screen.getByText(/The rules of decision-making must be open/),
).toBeInTheDocument();
// 6. User can take action
@@ -243,7 +243,7 @@ describe("User Journey Integration", () => {
<Header />
<Page />
<Footer />
</div>
</div>,
);
// Header navigation
@@ -256,7 +256,7 @@ describe("User Journey Integration", () => {
(link) =>
link.textContent?.includes("Use cases") ||
link.textContent?.includes("Learn") ||
link.textContent?.includes("About")
link.textContent?.includes("About"),
);
expect(navigationLinks.length).toBeGreaterThan(0);
@@ -273,7 +273,7 @@ describe("User Journey Integration", () => {
<Header />
<Page />
<Footer />
</div>
</div>,
);
// Test all interactive elements
+1 -1
View File
@@ -1,2 +1,2 @@
import { setupServer } from 'msw/node';
import { setupServer } from "msw/node";
export const server = setupServer(); // add handlers per test as needed
+2 -2
View File
@@ -61,7 +61,7 @@ class PerformanceMonitor {
if (value > threshold) {
console.warn(
`⚠️ Performance threshold exceeded: ${name} = ${value}ms (threshold: ${threshold}ms)`
`⚠️ Performance threshold exceeded: ${name} = ${value}ms (threshold: ${threshold}ms)`,
);
return false;
}
@@ -78,7 +78,7 @@ class PerformanceMonitor {
const regressionThreshold = baseline * 1.2; // 20% regression threshold
if (value > regressionThreshold) {
console.error(
`🚨 Performance regression detected: ${name} = ${value}ms (baseline: ${baseline}ms)`
`🚨 Performance regression detected: ${name} = ${value}ms (baseline: ${baseline}ms)`,
);
return false;
}
+25 -25
View File
@@ -16,25 +16,25 @@ describe("AskOrganizer Component", () => {
description="Our organizers can help you build better communities"
buttonText="Contact an organizer"
buttonHref="/contact"
/>
/>,
);
expect(
screen.getByRole("heading", { name: "Need help organizing?" })
screen.getByRole("heading", { name: "Need help organizing?" }),
).toBeInTheDocument();
expect(
screen.getByRole("heading", { name: "Get expert guidance" })
screen.getByRole("heading", { name: "Get expert guidance" }),
).toBeInTheDocument();
// The description text might not be rendered or might be different
// Just verify the component renders without error
expect(
screen.getByRole("heading", { name: "Need help organizing?" })
screen.getByRole("heading", { name: "Need help organizing?" }),
).toBeInTheDocument();
// Button renders as a link when href is provided
expect(
screen.getByRole("link", {
name: "Contact an organizer - Contact an organizer for help",
})
}),
).toBeInTheDocument();
});
@@ -45,13 +45,13 @@ describe("AskOrganizer Component", () => {
expect(
screen.getByRole("link", {
name: "Ask an organizer - Contact an organizer for help",
})
}),
).toBeInTheDocument();
});
test("renders with custom className", () => {
render(
<AskOrganizer title="Test" subtitle="Test" className="custom-class" />
<AskOrganizer title="Test" subtitle="Test" className="custom-class" />,
);
const section = document.querySelector("section");
@@ -60,7 +60,7 @@ describe("AskOrganizer Component", () => {
test("renders different variants", () => {
const { rerender } = render(
<AskOrganizer title="Test" subtitle="Test" variant="centered" />
<AskOrganizer title="Test" subtitle="Test" variant="centered" />,
);
// Centered variant should have center alignment
@@ -70,7 +70,7 @@ describe("AskOrganizer Component", () => {
expect(container).toBeInTheDocument();
rerender(
<AskOrganizer title="Test" subtitle="Test" variant="left-aligned" />
<AskOrganizer title="Test" subtitle="Test" variant="left-aligned" />,
);
// Left-aligned variant should have left alignment
@@ -86,19 +86,19 @@ describe("AskOrganizer Component", () => {
title="Ask Title"
subtitle="Ask Subtitle"
description="Ask Description"
/>
/>,
);
expect(
screen.getByRole("heading", { name: "Ask Title" })
screen.getByRole("heading", { name: "Ask Title" }),
).toBeInTheDocument();
expect(
screen.getByRole("heading", { name: "Ask Subtitle" })
screen.getByRole("heading", { name: "Ask Subtitle" }),
).toBeInTheDocument();
// Description might not be rendered if not provided to ContentLockup
// Just verify the component renders without error
expect(
screen.getByRole("heading", { name: "Ask Title" })
screen.getByRole("heading", { name: "Ask Title" }),
).toBeInTheDocument();
});
@@ -109,7 +109,7 @@ describe("AskOrganizer Component", () => {
subtitle="Test"
buttonText="Custom Button"
buttonHref="/custom"
/>
/>,
);
const button = screen.getByRole("link", {
@@ -128,7 +128,7 @@ describe("AskOrganizer Component", () => {
title="Test"
subtitle="Test"
onContactClick={onContactClick}
/>
/>,
);
const button = screen.getByRole("link", {
@@ -172,13 +172,13 @@ describe("AskOrganizer Component", () => {
test("renders with proper accessibility attributes", () => {
render(
<AskOrganizer title="Test" subtitle="Test" buttonText="Custom Button" />
<AskOrganizer title="Test" subtitle="Test" buttonText="Custom Button" />,
);
const section = document.querySelector("section");
expect(section).toHaveAttribute(
"aria-labelledby",
"ask-organizer-headline"
"ask-organizer-headline",
);
expect(section).toHaveAttribute("tabIndex", "-1");
@@ -187,7 +187,7 @@ describe("AskOrganizer Component", () => {
});
expect(button).toHaveAttribute(
"aria-label",
"Custom Button - Contact an organizer for help"
"Custom Button - Contact an organizer for help",
);
});
@@ -197,7 +197,7 @@ describe("AskOrganizer Component", () => {
const section = document.querySelector("section");
expect(section).toHaveClass(
"py-[var(--spacing-scale-032)]",
"px-[var(--spacing-scale-032)]"
"px-[var(--spacing-scale-032)]",
);
});
@@ -207,7 +207,7 @@ describe("AskOrganizer Component", () => {
const section = document.querySelector("section");
expect(section).toHaveClass(
"md:py-[var(--spacing-scale-096)]",
"md:px-[var(--spacing-scale-064)]"
"md:px-[var(--spacing-scale-064)]",
);
});
@@ -224,18 +224,18 @@ describe("AskOrganizer Component", () => {
test("applies variant-specific styling", () => {
const { rerender } = render(
<AskOrganizer title="Test" subtitle="Test" variant="compact" />
<AskOrganizer title="Test" subtitle="Test" variant="compact" />,
);
// Compact variant should have different padding
const section = screen.getByRole("region");
expect(section).toHaveClass(
"py-[var(--spacing-scale-016)]",
"px-[var(--spacing-scale-016)]"
"px-[var(--spacing-scale-016)]",
);
rerender(
<AskOrganizer title="Test" subtitle="Test" variant="left-aligned" />
<AskOrganizer title="Test" subtitle="Test" variant="left-aligned" />,
);
// Left-aligned variant should have left alignment
@@ -251,7 +251,7 @@ describe("AskOrganizer Component", () => {
});
expect(button).toHaveClass(
"xl:!px-[var(--spacing-scale-020)]",
"xl:!py-[var(--spacing-scale-012)]"
"xl:!py-[var(--spacing-scale-012)]",
);
});
@@ -266,7 +266,7 @@ describe("AskOrganizer Component", () => {
expect(
screen.getByRole("link", {
name: "Ask an organizer - Contact an organizer for help",
})
}),
).toBeInTheDocument();
});
+4 -4
View File
@@ -35,7 +35,7 @@ describe("Button Component", () => {
const { rerender } = render(<Button variant="default">Default</Button>);
let button = screen.getByRole("button", { name: "Default" });
expect(button.className).toContain(
"bg-[var(--color-surface-inverse-primary)]"
"bg-[var(--color-surface-inverse-primary)]",
);
rerender(<Button variant="secondary">Secondary</Button>);
@@ -79,10 +79,10 @@ describe("Button Component", () => {
// Check that design tokens are applied
expect(button.className).toContain(
"rounded-[var(--radius-measures-radius-full)]"
"rounded-[var(--radius-measures-radius-full)]",
);
expect(button.className).toContain(
"bg-[var(--color-surface-inverse-primary)]"
"bg-[var(--color-surface-inverse-primary)]",
);
});
@@ -103,7 +103,7 @@ describe("Button Component", () => {
render(
<Button href="/test" disabled>
Disabled Link
</Button>
</Button>,
);
const button = screen.getByRole("button", { name: "Disabled Link" });
expect(button).toBeInTheDocument();
+12 -12
View File
@@ -13,22 +13,22 @@ describe("FeatureGrid Component", () => {
<FeatureGrid
title="Feature Tools"
subtitle="Everything you need to build better communities"
/>
/>,
);
expect(
screen.getByRole("heading", { name: "Feature Tools" })
screen.getByRole("heading", { name: "Feature Tools" }),
).toBeInTheDocument();
expect(
screen.getByRole("heading", {
name: "Everything you need to build better communities",
})
}),
).toBeInTheDocument();
});
test("renders with custom className", () => {
render(
<FeatureGrid title="Test" subtitle="Test" className="custom-class" />
<FeatureGrid title="Test" subtitle="Test" className="custom-class" />,
);
const section = document.querySelector("section");
@@ -40,16 +40,16 @@ describe("FeatureGrid Component", () => {
// Check for all four MiniCard components
expect(
screen.getByRole("link", { name: "Decision-making support tools" })
screen.getByRole("link", { name: "Decision-making support tools" }),
).toBeInTheDocument();
expect(
screen.getByRole("link", { name: "Values alignment exercises" })
screen.getByRole("link", { name: "Values alignment exercises" }),
).toBeInTheDocument();
expect(
screen.getByRole("link", { name: "Membership guidance resources" })
screen.getByRole("link", { name: "Membership guidance resources" }),
).toBeInTheDocument();
expect(
screen.getByRole("link", { name: "Conflict resolution tools" })
screen.getByRole("link", { name: "Conflict resolution tools" }),
).toBeInTheDocument();
});
@@ -57,13 +57,13 @@ describe("FeatureGrid Component", () => {
render(<FeatureGrid title="Feature Title" subtitle="Feature Subtitle" />);
expect(
screen.getByRole("heading", { name: "Feature Title" })
screen.getByRole("heading", { name: "Feature Title" }),
).toBeInTheDocument();
expect(
screen.getByRole("heading", { name: "Feature Subtitle" })
screen.getByRole("heading", { name: "Feature Subtitle" }),
).toBeInTheDocument();
expect(
screen.getByRole("link", { name: "Learn more" })
screen.getByRole("link", { name: "Learn more" }),
).toBeInTheDocument();
});
@@ -130,7 +130,7 @@ describe("FeatureGrid Component", () => {
// Should render default MiniCards
expect(
screen.getByRole("link", { name: "Decision-making support tools" })
screen.getByRole("link", { name: "Decision-making support tools" }),
).toBeInTheDocument();
});
+15 -15
View File
@@ -27,7 +27,7 @@ describe("Footer", () => {
expect(schemaData.email).toBe("medlab@colorado.edu");
expect(schemaData.url).toBe("https://communityrule.com");
expect(schemaData.sameAs).toContain(
"https://bsky.app/profile/medlabboulder"
"https://bsky.app/profile/medlabboulder",
);
expect(schemaData.sameAs).toContain("https://gitlab.com/medlabboulder");
});
@@ -36,7 +36,7 @@ describe("Footer", () => {
render(<Footer />);
expect(
screen.getAllByText("Media Economies Design Lab").length
screen.getAllByText("Media Economies Design Lab").length,
).toBeGreaterThan(0);
const emailLinks = screen.getAllByRole("link", {
@@ -86,13 +86,13 @@ describe("Footer", () => {
render(<Footer />);
expect(
screen.getAllByRole("link", { name: "Use cases" }).length
screen.getAllByRole("link", { name: "Use cases" }).length,
).toBeGreaterThan(0);
expect(
screen.getAllByRole("link", { name: "Learn" }).length
screen.getAllByRole("link", { name: "Learn" }).length,
).toBeGreaterThan(0);
expect(
screen.getAllByRole("link", { name: "About" }).length
screen.getAllByRole("link", { name: "About" }).length,
).toBeGreaterThan(0);
});
@@ -100,13 +100,13 @@ describe("Footer", () => {
render(<Footer />);
expect(
screen.getAllByRole("link", { name: "Privacy Policy" }).length
screen.getAllByRole("link", { name: "Privacy Policy" }).length,
).toBeGreaterThan(0);
expect(
screen.getAllByRole("link", { name: "Terms of Service" }).length
screen.getAllByRole("link", { name: "Terms of Service" }).length,
).toBeGreaterThan(0);
expect(
screen.getAllByRole("link", { name: "Cookies Settings" }).length
screen.getAllByRole("link", { name: "Cookies Settings" }).length,
).toBeGreaterThan(0);
});
@@ -114,7 +114,7 @@ describe("Footer", () => {
render(<Footer />);
expect(screen.getAllByText("© All right reserved").length).toBeGreaterThan(
0
0,
);
});
@@ -123,7 +123,7 @@ describe("Footer", () => {
// Check that logo containers exist for different breakpoints
const logoContainers = document.querySelectorAll(
'[class*="block sm:hidden"], [class*="hidden sm:block lg:hidden"], [class*="hidden lg:block"]'
'[class*="block sm:hidden"], [class*="hidden sm:block lg:hidden"], [class*="hidden lg:block"]',
);
expect(logoContainers.length).toBeGreaterThan(0);
});
@@ -147,7 +147,7 @@ describe("Footer", () => {
// The Separator component should be rendered (it uses a div with border, not hr)
const separator = document.querySelector(
".bg-\\[var\\(--border-color-default-secondary\\)\\]"
".bg-\\[var\\(--border-color-default-secondary\\)\\]",
);
expect(separator).toBeInTheDocument();
});
@@ -263,10 +263,10 @@ describe("Footer", () => {
expect(emailLink).toHaveClass("focus:ring-2");
expect(emailLink).toHaveClass("focus:ring-offset-2");
expect(emailLink).toHaveClass(
"focus:ring-[var(--color-content-default-primary)]"
"focus:ring-[var(--color-content-default-primary)]",
);
expect(emailLink).toHaveClass(
"focus:ring-offset-[var(--color-surface-default-primary)]"
"focus:ring-offset-[var(--color-surface-default-primary)]",
);
});
@@ -276,10 +276,10 @@ describe("Footer", () => {
expect(link).toHaveClass("focus:ring-2");
expect(link).toHaveClass("focus:ring-offset-2");
expect(link).toHaveClass(
"focus:ring-[var(--color-content-default-primary)]"
"focus:ring-[var(--color-content-default-primary)]",
);
expect(link).toHaveClass(
"focus:ring-offset-[var(--color-surface-default-primary)]"
"focus:ring-offset-[var(--color-surface-default-primary)]",
);
});
});
+10 -10
View File
@@ -22,14 +22,14 @@ describe("Header", () => {
// Check main header structure - use container to scope the search
const header = container.querySelector(
'[role="banner"][aria-label="Main navigation header"]'
'[role="banner"][aria-label="Main navigation header"]',
);
expect(header).toBeInTheDocument();
expect(header).toHaveAttribute("aria-label", "Main navigation header");
// Check navigation - use container to scope the search
const nav = container.querySelector(
'[role="navigation"][aria-label="Main navigation"]'
'[role="navigation"][aria-label="Main navigation"]',
);
expect(nav).toBeInTheDocument();
expect(nav).toHaveAttribute("aria-label", "Main navigation");
@@ -41,15 +41,15 @@ describe("Header", () => {
// Check all navigation items have proper aria-labels - use menuitem role since they're in a menubar
expect(
screen.getAllByRole("menuitem", { name: "Navigate to Use cases page" })
.length
.length,
).toBeGreaterThan(0);
expect(
screen.getAllByRole("menuitem", { name: "Navigate to Learn page" })
.length
.length,
).toBeGreaterThan(0);
expect(
screen.getAllByRole("menuitem", { name: "Navigate to About page" })
.length
.length,
).toBeGreaterThan(0);
});
});
@@ -59,7 +59,7 @@ describe("Header", () => {
render(<Header onToggle={mockOnToggle} />);
const script = document.querySelector(
'script[type="application/ld+json"]'
'script[type="application/ld+json"]',
);
expect(script).toBeInTheDocument();
@@ -296,7 +296,7 @@ describe("Header", () => {
(img) =>
img.alt === "Avatar 1" ||
img.alt === "Avatar 2" ||
img.alt === "Avatar 3"
img.alt === "Avatar 3",
);
expect(avatarImages.length).toBeGreaterThan(0);
});
@@ -324,17 +324,17 @@ describe("Header", () => {
const { container } = render(<Header onToggle={mockOnToggle} />);
const header = container.querySelector(
'[role="banner"][aria-label="Main navigation header"]'
'[role="banner"][aria-label="Main navigation header"]',
);
expect(header).toHaveClass("bg-[var(--color-surface-default-primary)]");
expect(header).toHaveClass("w-full");
expect(header).toHaveClass("border-b");
expect(header).toHaveClass(
"border-[var(--border-color-default-tertiary)]"
"border-[var(--border-color-default-tertiary)]",
);
const nav = container.querySelector(
'[role="navigation"][aria-label="Main navigation"]'
'[role="navigation"][aria-label="Main navigation"]',
);
expect(nav).toHaveClass("flex");
expect(nav).toHaveClass("items-center");
+12 -12
View File
@@ -16,17 +16,17 @@ describe("HeroBanner Component", () => {
description="Create and manage community rules with ease"
ctaText="Get Started"
ctaHref="/signup"
/>
/>,
);
expect(
screen.getByRole("heading", { name: "Welcome to CommunityRule" })
screen.getByRole("heading", { name: "Welcome to CommunityRule" }),
).toBeInTheDocument();
expect(
screen.getByRole("heading", { name: "Build better communities" })
screen.getByRole("heading", { name: "Build better communities" }),
).toBeInTheDocument();
expect(
screen.getByText("Create and manage community rules with ease")
screen.getByText("Create and manage community rules with ease"),
).toBeInTheDocument();
// Button component renders multiple versions for different screen sizes
// Use getAllByRole to handle multiple buttons with same text
@@ -38,10 +38,10 @@ describe("HeroBanner Component", () => {
render(<HeroBanner title="Minimal" />);
expect(
screen.getByRole("heading", { name: "Minimal" })
screen.getByRole("heading", { name: "Minimal" }),
).toBeInTheDocument();
expect(
screen.getByRole("img", { name: "Hero illustration" })
screen.getByRole("img", { name: "Hero illustration" }),
).toBeInTheDocument();
});
@@ -72,15 +72,15 @@ describe("HeroBanner Component", () => {
description="Test Description"
ctaText="Test CTA"
ctaHref="/test"
/>
/>,
);
// Check that ContentLockup receives the props correctly
expect(
screen.getByRole("heading", { name: "Test Title" })
screen.getByRole("heading", { name: "Test Title" }),
).toBeInTheDocument();
expect(
screen.getByRole("heading", { name: "Test Subtitle" })
screen.getByRole("heading", { name: "Test Subtitle" }),
).toBeInTheDocument();
expect(screen.getByText("Test Description")).toBeInTheDocument();
// Button component renders multiple versions for different screen sizes
@@ -93,7 +93,7 @@ describe("HeroBanner Component", () => {
// HeroDecor should be present (it's a decorative component)
const heroDecor = document.querySelector(
'[class*="pointer-events-none absolute z-0"]'
'[class*="pointer-events-none absolute z-0"]',
);
expect(heroDecor).toBeInTheDocument();
});
@@ -123,7 +123,7 @@ describe("HeroBanner Component", () => {
const section = document.querySelector("section");
expect(section).toHaveClass(
"px-[var(--spacing-scale-008)]",
"sm:px-[var(--spacing-scale-010)]"
"sm:px-[var(--spacing-scale-010)]",
);
});
@@ -135,7 +135,7 @@ describe("HeroBanner Component", () => {
// Check for design token usage in the component structure
const container = section.querySelector(
'[class*="bg-[var(--color-surface-inverse-brand-primary)]"]'
'[class*="bg-[var(--color-surface-inverse-brand-primary)]"]',
);
expect(container).toBeInTheDocument();
});
+12 -12
View File
@@ -23,7 +23,7 @@ describe("RootLayout", () => {
render(
<RootLayout>
<div>Test content</div>
</RootLayout>
</RootLayout>,
);
const html = document.querySelector("html");
@@ -36,7 +36,7 @@ describe("RootLayout", () => {
render(
<RootLayout>
<div>Test content</div>
</RootLayout>
</RootLayout>,
);
const body = document.querySelector("body");
@@ -50,7 +50,7 @@ describe("RootLayout", () => {
render(
<RootLayout>
<div>Test content</div>
</RootLayout>
</RootLayout>,
);
const mainContainer = document.querySelector(".min-h-screen.flex.flex-col");
@@ -61,7 +61,7 @@ describe("RootLayout", () => {
render(
<RootLayout>
<div>Test content</div>
</RootLayout>
</RootLayout>,
);
// The HomeHeader component should be rendered
@@ -74,7 +74,7 @@ describe("RootLayout", () => {
render(
<RootLayout>
<div>Test content</div>
</RootLayout>
</RootLayout>,
);
const main = document.querySelector("main");
@@ -87,7 +87,7 @@ describe("RootLayout", () => {
render(
<RootLayout>
<div>Test content</div>
</RootLayout>
</RootLayout>,
);
// The Footer component should be rendered
@@ -100,7 +100,7 @@ describe("RootLayout", () => {
render(
<RootLayout>
<div>{testContent}</div>
</RootLayout>
</RootLayout>,
);
expect(screen.getByText(testContent)).toBeInTheDocument();
@@ -110,7 +110,7 @@ describe("RootLayout", () => {
render(
<RootLayout>
<div>Test content</div>
</RootLayout>
</RootLayout>,
);
const mainContainer = document.querySelector(".min-h-screen.flex.flex-col");
@@ -124,7 +124,7 @@ describe("RootLayout", () => {
render(
<RootLayout>
<div>Test content</div>
</RootLayout>
</RootLayout>,
);
const main = document.querySelector("main");
@@ -135,7 +135,7 @@ describe("RootLayout", () => {
render(
<RootLayout>
<div>Test content</div>
</RootLayout>
</RootLayout>,
);
// Check for all major structural elements
@@ -150,7 +150,7 @@ describe("RootLayout", () => {
render(
<RootLayout>
<div>Test content</div>
</RootLayout>
</RootLayout>,
);
// Check that the document has proper structure
@@ -173,7 +173,7 @@ describe("RootLayout", () => {
<div>First child</div>
<div>Second child</div>
<div>Third child</div>
</RootLayout>
</RootLayout>,
);
expect(screen.getByText("First child")).toBeInTheDocument();
+6 -6
View File
@@ -47,7 +47,7 @@ describe("LogoWall Component", () => {
render(<LogoWall />);
expect(
screen.getByText("Trusted by leading cooperators")
screen.getByText("Trusted by leading cooperators"),
).toBeInTheDocument();
});
@@ -64,7 +64,7 @@ describe("LogoWall Component", () => {
const section = document.querySelector("section");
expect(section).toHaveClass(
"p-[var(--spacing-scale-032)]",
"md:px-[var(--spacing-scale-024)]"
"md:px-[var(--spacing-scale-024)]",
);
});
@@ -72,7 +72,7 @@ describe("LogoWall Component", () => {
render(<LogoWall />);
const grid = document.querySelector(
'[class*="grid grid-cols-2 grid-rows-3"]'
'[class*="grid grid-cols-2 grid-rows-3"]',
);
expect(grid).toBeInTheDocument();
expect(grid).toHaveClass("sm:grid-cols-3", "sm:grid-rows-2", "md:flex");
@@ -84,7 +84,7 @@ describe("LogoWall Component", () => {
const foodNotBombsLogo = screen.getByAltText("Food Not Bombs");
expect(foodNotBombsLogo).toHaveAttribute(
"src",
"assets/Section/Logo_FoodNotBombs.png"
"assets/Section/Logo_FoodNotBombs.png",
);
expect(foodNotBombsLogo).toHaveClass("h-11", "lg:h-14", "xl:h-[70px]");
});
@@ -109,7 +109,7 @@ describe("LogoWall Component", () => {
render(<LogoWall />);
const logoContainers = document.querySelectorAll(
'[class*="hover:opacity-100"]'
'[class*="hover:opacity-100"]',
);
expect(logoContainers.length).toBeGreaterThan(0);
});
@@ -129,7 +129,7 @@ describe("LogoWall Component", () => {
render(<LogoWall />);
const logoContainers = document.querySelectorAll(
'[class*="transition-opacity duration-500"]'
'[class*="transition-opacity duration-500"]',
);
expect(logoContainers.length).toBeGreaterThan(0);
});
+14 -14
View File
@@ -32,25 +32,25 @@ describe("NumberedCards Component", () => {
title="How CommunityRule helps"
subtitle="Build better communities step by step"
cards={mockCards}
/>
/>,
);
// Check for the heading (it contains both mobile and desktop versions)
expect(screen.getByRole("heading")).toBeInTheDocument();
// Check for the subtitle text
expect(
screen.getByText("Build better communities step by step")
screen.getByText("Build better communities step by step"),
).toBeInTheDocument();
// Check for card content
expect(
screen.getByText("Define your community values")
screen.getByText("Define your community values"),
).toBeInTheDocument();
expect(
screen.getByText("Create decision-making processes")
screen.getByText("Create decision-making processes"),
).toBeInTheDocument();
expect(
screen.getByText("Establish communication channels")
screen.getByText("Establish communication channels"),
).toBeInTheDocument();
});
@@ -60,7 +60,7 @@ describe("NumberedCards Component", () => {
title="Test Title"
subtitle="Test Subtitle"
cards={mockCards}
/>
/>,
);
// Check for the heading (it contains both mobile and desktop versions)
@@ -82,10 +82,10 @@ describe("NumberedCards Component", () => {
render(<NumberedCards title="Test" subtitle="Test" cards={mockCards} />);
expect(
screen.getByRole("button", { name: "Create CommunityRule" })
screen.getByRole("button", { name: "Create CommunityRule" }),
).toBeInTheDocument();
expect(
screen.getByRole("button", { name: "See how it works" })
screen.getByRole("button", { name: "See how it works" }),
).toBeInTheDocument();
});
@@ -109,7 +109,7 @@ describe("NumberedCards Component", () => {
const section = document.querySelector("section");
expect(section).toHaveClass(
"bg-transparent",
"py-[var(--spacing-scale-032)]"
"py-[var(--spacing-scale-032)]",
);
});
@@ -117,7 +117,7 @@ describe("NumberedCards Component", () => {
render(<NumberedCards title="Test" subtitle="Test" cards={mockCards} />);
const cardsContainer = document.querySelector(
'[class*="grid grid-cols-1"]'
'[class*="grid grid-cols-1"]',
);
expect(cardsContainer).toBeInTheDocument();
});
@@ -128,7 +128,7 @@ describe("NumberedCards Component", () => {
title="Test Title"
subtitle="Test Description"
cards={mockCards}
/>
/>,
);
const script = document.querySelector('script[type="application/ld+json"]');
@@ -161,7 +161,7 @@ describe("NumberedCards Component", () => {
// Should render buttons even without cards
expect(
screen.getByRole("button", { name: "Create CommunityRule" })
screen.getByRole("button", { name: "Create CommunityRule" }),
).toBeInTheDocument();
});
@@ -180,7 +180,7 @@ describe("NumberedCards Component", () => {
const section = document.querySelector("section");
expect(section).toHaveClass(
"py-[var(--spacing-scale-032)]",
"sm:py-[var(--spacing-scale-048)]"
"sm:py-[var(--spacing-scale-048)]",
);
});
@@ -188,7 +188,7 @@ describe("NumberedCards Component", () => {
render(<NumberedCards title="Test" subtitle="Test" cards={mockCards} />);
const container = document.querySelector(
'[class*="max-w-[var(--spacing-measures-max-width-lg)]"]'
'[class*="max-w-[var(--spacing-measures-max-width-lg)]"]',
);
expect(container).toBeInTheDocument();
});
+50 -50
View File
@@ -11,36 +11,36 @@ describe("Page", () => {
expect(screen.getAllByText("with clarity").length).toBeGreaterThan(0);
expect(
screen.getAllByText(
"Help your community make important decisions in a way that reflects its unique values."
).length
"Help your community make important decisions in a way that reflects its unique values.",
).length,
).toBeGreaterThan(0);
// Check numbered cards section (using getAllByText since there are multiple instances)
expect(
screen.getAllByText("How CommunityRule works").length
screen.getAllByText("How CommunityRule works").length,
).toBeGreaterThan(0);
expect(
screen.getAllByText(
"Here's a quick overview of the process, from start to finish."
).length
"Here's a quick overview of the process, from start to finish.",
).length,
).toBeGreaterThan(0);
// Check feature grid section (using getAllByText since there are multiple instances)
expect(
screen.getAllByText("We've got your back, every step of the way").length
screen.getAllByText("We've got your back, every step of the way").length,
).toBeGreaterThan(0);
expect(
screen.getAllByText(
"Use our toolkit to improve, document, and evolve your organization."
).length
"Use our toolkit to improve, document, and evolve your organization.",
).length,
).toBeGreaterThan(0);
// Check ask organizer section (using getAllByText since there are multiple instances)
expect(screen.getAllByText("Still have questions?").length).toBeGreaterThan(
0
0,
);
expect(
screen.getAllByText("Get answers from an experienced organizer").length
screen.getAllByText("Get answers from an experienced organizer").length,
).toBeGreaterThan(0);
});
@@ -52,11 +52,11 @@ describe("Page", () => {
expect(screen.getAllByText("with clarity").length).toBeGreaterThan(0);
expect(
screen.getAllByText(
"Help your community make important decisions in a way that reflects its unique values."
).length
"Help your community make important decisions in a way that reflects its unique values.",
).length,
).toBeGreaterThan(0);
expect(
screen.getAllByText("Learn how CommunityRule works").length
screen.getAllByText("Learn how CommunityRule works").length,
).toBeGreaterThan(0);
});
@@ -65,27 +65,27 @@ describe("Page", () => {
// Check numbered cards content (using getAllByText since there are multiple instances)
expect(
screen.getAllByText("How CommunityRule works").length
screen.getAllByText("How CommunityRule works").length,
).toBeGreaterThan(0);
expect(
screen.getAllByText(
"Here's a quick overview of the process, from start to finish."
).length
"Here's a quick overview of the process, from start to finish.",
).length,
).toBeGreaterThan(0);
// Check individual card content (using getAllByText since there are multiple instances)
expect(
screen.getAllByText("Document how your community makes decisions").length
screen.getAllByText("Document how your community makes decisions").length,
).toBeGreaterThan(0);
expect(
screen.getAllByText(
"Build an operating manual for a successful community"
).length
"Build an operating manual for a successful community",
).length,
).toBeGreaterThan(0);
expect(
screen.getAllByText(
"Get a link to your manual for your group to review and evolve"
).length
"Get a link to your manual for your group to review and evolve",
).length,
).toBeGreaterThan(0);
});
@@ -94,12 +94,12 @@ describe("Page", () => {
// Check feature grid content (using getAllByText since there are multiple instances)
expect(
screen.getAllByText("We've got your back, every step of the way").length
screen.getAllByText("We've got your back, every step of the way").length,
).toBeGreaterThan(0);
expect(
screen.getAllByText(
"Use our toolkit to improve, document, and evolve your organization."
).length
"Use our toolkit to improve, document, and evolve your organization.",
).length,
).toBeGreaterThan(0);
});
@@ -108,10 +108,10 @@ describe("Page", () => {
// Check ask organizer content (using getAllByText since there are multiple instances)
expect(screen.getAllByText("Still have questions?").length).toBeGreaterThan(
0
0,
);
expect(
screen.getAllByText("Get answers from an experienced organizer").length
screen.getAllByText("Get answers from an experienced organizer").length,
).toBeGreaterThan(0);
expect(screen.getAllByText("Ask an organizer").length).toBeGreaterThan(0);
});
@@ -126,19 +126,19 @@ describe("Page", () => {
// LogoWall - should be present (even if just the component structure)
// NumberedCards
expect(
screen.getAllByText("How CommunityRule works").length
screen.getAllByText("How CommunityRule works").length,
).toBeGreaterThan(0);
// RuleStack - should be present
// FeatureGrid
expect(
screen.getAllByText("We've got your back, every step of the way").length
screen.getAllByText("We've got your back, every step of the way").length,
).toBeGreaterThan(0);
// QuoteBlock - should be present
// AskOrganizer
expect(screen.getAllByText("Still have questions?").length).toBeGreaterThan(
0
0,
);
});
@@ -154,7 +154,7 @@ describe("Page", () => {
// Check CTA button in hero banner
expect(
screen.getAllByText("Learn how CommunityRule works").length
screen.getAllByText("Learn how CommunityRule works").length,
).toBeGreaterThan(0);
// Check CTA button in ask organizer section
@@ -167,27 +167,27 @@ describe("Page", () => {
// Check main description (using getAllByText since there are multiple instances)
expect(
screen.getAllByText(
"Help your community make important decisions in a way that reflects its unique values."
).length
"Help your community make important decisions in a way that reflects its unique values.",
).length,
).toBeGreaterThan(0);
// Check numbered cards description (using getAllByText since there are multiple instances)
expect(
screen.getAllByText(
"Here's a quick overview of the process, from start to finish."
).length
"Here's a quick overview of the process, from start to finish.",
).length,
).toBeGreaterThan(0);
// Check feature grid description (using getAllByText since there are multiple instances)
expect(
screen.getAllByText(
"Use our toolkit to improve, document, and evolve your organization."
).length
"Use our toolkit to improve, document, and evolve your organization.",
).length,
).toBeGreaterThan(0);
// Check ask organizer description (using getAllByText since there are multiple instances)
expect(
screen.getAllByText("Get answers from an experienced organizer").length
screen.getAllByText("Get answers from an experienced organizer").length,
).toBeGreaterThan(0);
});
@@ -197,13 +197,13 @@ describe("Page", () => {
// Check all section titles (using getAllByText since there are multiple instances)
expect(screen.getAllByText("Collaborate").length).toBeGreaterThan(0);
expect(
screen.getAllByText("How CommunityRule works").length
screen.getAllByText("How CommunityRule works").length,
).toBeGreaterThan(0);
expect(
screen.getAllByText("We've got your back, every step of the way").length
screen.getAllByText("We've got your back, every step of the way").length,
).toBeGreaterThan(0);
expect(screen.getAllByText("Still have questions?").length).toBeGreaterThan(
0
0,
);
});
@@ -212,17 +212,17 @@ describe("Page", () => {
// Check all three numbered card items (using getAllByText since there are multiple instances)
expect(
screen.getAllByText("Document how your community makes decisions").length
screen.getAllByText("Document how your community makes decisions").length,
).toBeGreaterThan(0);
expect(
screen.getAllByText(
"Build an operating manual for a successful community"
).length
"Build an operating manual for a successful community",
).length,
).toBeGreaterThan(0);
expect(
screen.getAllByText(
"Get a link to your manual for your group to review and evolve"
).length
"Get a link to your manual for your group to review and evolve",
).length,
).toBeGreaterThan(0);
});
@@ -233,16 +233,16 @@ describe("Page", () => {
expect(screen.getAllByText("with clarity").length).toBeGreaterThan(0);
expect(
screen.getAllByText(
"Here's a quick overview of the process, from start to finish."
).length
"Here's a quick overview of the process, from start to finish.",
).length,
).toBeGreaterThan(0);
expect(
screen.getAllByText(
"Use our toolkit to improve, document, and evolve your organization."
).length
"Use our toolkit to improve, document, and evolve your organization.",
).length,
).toBeGreaterThan(0);
expect(
screen.getAllByText("Get answers from an experienced organizer").length
screen.getAllByText("Get answers from an experienced organizer").length,
).toBeGreaterThan(0);
});
});
+20 -20
View File
@@ -12,11 +12,11 @@ describe("QuoteBlock Component", () => {
render(<QuoteBlock />);
expect(
screen.getByText(/The rules of decision-making must be open/)
screen.getByText(/The rules of decision-making must be open/),
).toBeInTheDocument();
expect(screen.getByText("Jo Freeman")).toBeInTheDocument();
expect(
screen.getByText("The Tyranny of Structurelessness")
screen.getByText("The Tyranny of Structurelessness"),
).toBeInTheDocument();
expect(screen.getByAltText("Portrait of Jo Freeman")).toBeInTheDocument();
});
@@ -27,7 +27,7 @@ describe("QuoteBlock Component", () => {
quote="Custom quote text"
author="Custom Author"
source="Custom Source"
/>
/>,
);
expect(screen.getByText("Custom quote text")).toBeInTheDocument();
@@ -41,7 +41,7 @@ describe("QuoteBlock Component", () => {
quote="Test quote"
author="Test Author"
className="custom-class"
/>
/>,
);
const section = document.querySelector("section");
@@ -50,24 +50,24 @@ describe("QuoteBlock Component", () => {
test("renders different variants", () => {
const { rerender } = render(
<QuoteBlock quote="Test quote" author="Test Author" variant="compact" />
<QuoteBlock quote="Test quote" author="Test Author" variant="compact" />,
);
// Compact variant should have different styling
const section = screen.getByRole("region");
expect(section).toHaveClass(
"py-[var(--spacing-scale-032)]",
"px-[var(--spacing-scale-016)]"
"px-[var(--spacing-scale-016)]",
);
rerender(
<QuoteBlock quote="Test quote" author="Test Author" variant="extended" />
<QuoteBlock quote="Test quote" author="Test Author" variant="extended" />,
);
// Extended variant should have different styling
expect(section).toHaveClass(
"py-[var(--spacing-scale-048)]",
"px-[var(--spacing-scale-024)]"
"px-[var(--spacing-scale-024)]",
);
});
@@ -77,7 +77,7 @@ describe("QuoteBlock Component", () => {
quote="Test quote"
author="Test Author"
id="custom-quote-id"
/>
/>,
);
const quoteElement = screen.getByText("Test quote");
@@ -95,7 +95,7 @@ describe("QuoteBlock Component", () => {
test("calls onError callback when image fails", () => {
const onError = vi.fn();
render(
<QuoteBlock quote="Test quote" author="Test Author" onError={onError} />
<QuoteBlock quote="Test quote" author="Test Author" onError={onError} />,
);
// Should render without errors
@@ -112,24 +112,24 @@ describe("QuoteBlock Component", () => {
test("renders decorative elements for standard variant", () => {
render(
<QuoteBlock quote="Test quote" author="Test Author" variant="standard" />
<QuoteBlock quote="Test quote" author="Test Author" variant="standard" />,
);
// Should render QuoteDecor for standard variant
const decor = document.querySelector(
'[class*="pointer-events-none absolute z-0"]'
'[class*="pointer-events-none absolute z-0"]',
);
expect(decor).toBeInTheDocument();
});
test("does not render decorative elements for compact variant", () => {
render(
<QuoteBlock quote="Test quote" author="Test Author" variant="compact" />
<QuoteBlock quote="Test quote" author="Test Author" variant="compact" />,
);
// Should not render QuoteDecor for compact variant
const decor = document.querySelector(
'[class*="pointer-events-none absolute z-0"]'
'[class*="pointer-events-none absolute z-0"]',
);
expect(decor).not.toBeInTheDocument();
});
@@ -149,7 +149,7 @@ describe("QuoteBlock Component", () => {
test("applies correct accessibility attributes", () => {
render(
<QuoteBlock quote="Test quote" author="Test Author" id="test-quote" />
<QuoteBlock quote="Test quote" author="Test Author" id="test-quote" />,
);
const section = document.querySelector("section");
@@ -166,7 +166,7 @@ describe("QuoteBlock Component", () => {
expect(section).toHaveClass("md:py-[var(--spacing-scale-032)]");
const card = section.querySelector(
'[class*="bg-[var(--color-surface-default-brand-darker-accent)]"]'
'[class*="bg-[var(--color-surface-default-brand-darker-accent)]"]',
);
expect(card).toBeInTheDocument();
});
@@ -177,7 +177,7 @@ describe("QuoteBlock Component", () => {
render(<QuoteBlock quote="" author="" />);
expect(consoleSpy).toHaveBeenCalledWith(
"QuoteBlock: Missing required props (quote or author)"
"QuoteBlock: Missing required props (quote or author)",
);
consoleSpy.mockRestore();
@@ -199,14 +199,14 @@ describe("QuoteBlock Component", () => {
test("applies responsive text sizing", () => {
render(
<QuoteBlock quote="Test quote" author="Test Author" variant="standard" />
<QuoteBlock quote="Test quote" author="Test Author" variant="standard" />,
);
const quoteElement = screen.getByText("Test quote");
expect(quoteElement).toHaveClass(
"text-[18px]",
"md:text-[36px]",
"lg:text-[52px]"
"lg:text-[52px]",
);
});
@@ -216,7 +216,7 @@ describe("QuoteBlock Component", () => {
expect(screen.getByText("Test quote")).toBeInTheDocument();
expect(screen.getByText("Test Author")).toBeInTheDocument();
expect(
screen.queryByText("The Tyranny of Structurelessness")
screen.queryByText("The Tyranny of Structurelessness"),
).not.toBeInTheDocument();
});
});
+9 -9
View File
@@ -28,16 +28,16 @@ describe("RuleStack Component", () => {
render(<RuleStack />);
expect(
screen.getByText(/Units called Circles have the ability to decide/)
screen.getByText(/Units called Circles have the ability to decide/),
).toBeInTheDocument();
expect(
screen.getByText(/Decisions that affect the group collectively/)
screen.getByText(/Decisions that affect the group collectively/),
).toBeInTheDocument();
expect(
screen.getByText(/An elected board determines policies/)
screen.getByText(/An elected board determines policies/),
).toBeInTheDocument();
expect(
screen.getByText(/All participants can propose and vote/)
screen.getByText(/All participants can propose and vote/),
).toBeInTheDocument();
});
@@ -54,7 +54,7 @@ describe("RuleStack Component", () => {
render(<RuleStack />);
expect(
screen.getByRole("button", { name: "See all templates" })
screen.getByRole("button", { name: "See all templates" }),
).toBeInTheDocument();
});
@@ -71,7 +71,7 @@ describe("RuleStack Component", () => {
const section = document.querySelector("section");
expect(section).toHaveClass(
"py-[var(--spacing-scale-032)]",
"px-[var(--spacing-scale-020)]"
"px-[var(--spacing-scale-020)]",
);
});
@@ -128,7 +128,7 @@ describe("RuleStack Component", () => {
const section = document.querySelector("section");
expect(section).toHaveClass(
"md:py-[var(--spacing-scale-048)]",
"lg:py-[var(--spacing-scale-064)]"
"lg:py-[var(--spacing-scale-064)]",
);
});
@@ -141,7 +141,7 @@ describe("RuleStack Component", () => {
"md:w-[56px]",
"md:h-[56px]",
"lg:w-[90px]",
"lg:h-[90px]"
"lg:h-[90px]",
);
});
@@ -155,7 +155,7 @@ describe("RuleStack Component", () => {
// Verify that cards have background color classes
cards.forEach((card) => {
expect(card.className).toMatch(
/bg-\[var\(--color-surface-default-brand-/
/bg-\[var\(--color-surface-default-brand-/,
);
});
});
+1 -1
View File
@@ -155,7 +155,7 @@ describe("Accessibility - Component Level", () => {
}
const headingLevels = headings.map((heading) =>
parseInt(heading.tagName.charAt(1))
parseInt(heading.tagName.charAt(1)),
);
// Check that heading levels are sequential (no skipping levels)