diff --git a/tests/integration/component-interactions.integration.test.jsx b/tests/integration/component-interactions.integration.test.jsx
new file mode 100644
index 0000000..636b899
--- /dev/null
+++ b/tests/integration/component-interactions.integration.test.jsx
@@ -0,0 +1,353 @@
+import { render, screen, cleanup } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";
+import { vi, describe, test, expect, afterEach } from "vitest";
+import HeroBanner from "../../app/components/HeroBanner";
+import NumberedCards from "../../app/components/NumberedCards";
+import RuleStack from "../../app/components/RuleStack";
+import FeatureGrid from "../../app/components/FeatureGrid";
+import QuoteBlock from "../../app/components/QuoteBlock";
+import AskOrganizer from "../../app/components/AskOrganizer";
+
+afterEach(() => {
+ cleanup();
+});
+
+describe("Component Interactions Integration", () => {
+ test("hero banner and numbered cards work together to explain the process", () => {
+ const heroData = {
+ title: "Collaborate",
+ subtitle: "with clarity",
+ description:
+ "Help your community make important decisions in a way that reflects its unique values.",
+ ctaText: "Learn how CommunityRule works",
+ ctaHref: "#",
+ };
+
+ const numberedCardsData = {
+ title: "How CommunityRule works",
+ subtitle: "Here's a quick overview of the process, from start to finish.",
+ cards: [
+ {
+ text: "Document how your community makes decisions",
+ iconShape: "blob",
+ iconColor: "green",
+ },
+ {
+ text: "Build an operating manual for a successful community",
+ iconShape: "gear",
+ iconColor: "purple",
+ },
+ {
+ text: "Get a link to your manual for your group to review and evolve",
+ iconShape: "star",
+ iconColor: "orange",
+ },
+ ],
+ };
+
+ render(
+
+
+
+
+ );
+
+ // Hero introduces the concept
+ expect(
+ 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")
+ ).toBeInTheDocument();
+ expect(
+ 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"
+ )
+ ).toBeInTheDocument();
+ });
+
+ test("rule stack and feature grid complement each other", () => {
+ const featureGridData = {
+ title: "We've got your back, every step of the way",
+ subtitle:
+ "Use our toolkit to improve, document, and evolve your organization.",
+ };
+
+ render(
+
+
+
+
+ );
+
+ // Rule stack shows governance options
+ expect(screen.getByText("Consensus clusters")).toBeInTheDocument();
+ expect(screen.getByText("Elected Board")).toBeInTheDocument();
+ expect(screen.getByText("Consensus")).toBeInTheDocument();
+ expect(screen.getByText("Petition")).toBeInTheDocument();
+
+ // Feature grid provides support context
+ expect(
+ 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."
+ )
+ ).toBeInTheDocument();
+ });
+
+ test("quote block provides social proof for the entire application", () => {
+ render();
+
+ // Quote provides credibility and social proof
+ expect(
+ 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")
+ ).toBeInTheDocument();
+ });
+
+ test("ask organizer provides help context for all components", () => {
+ const askOrganizerData = {
+ title: "Still have questions?",
+ subtitle: "Get answers from an experienced organizer",
+ buttonText: "Ask an organizer",
+ buttonHref: "#contact",
+ };
+
+ render();
+
+ // Provides help for users who need assistance
+ expect(screen.getByText("Still have questions?")).toBeInTheDocument();
+ expect(
+ screen.getByText("Get answers from an experienced organizer")
+ ).toBeInTheDocument();
+ expect(
+ screen.getByRole("link", { name: /Ask an organizer/i })
+ ).toBeInTheDocument();
+ });
+
+ test("all components maintain consistent styling and branding", () => {
+ render(
+
+ );
+
+ // All components should render without errors
+ expect(screen.getAllByText("Test").length).toBeGreaterThan(0);
+ expect(screen.getByText("Test Cards")).toBeInTheDocument();
+ expect(screen.getByText("Consensus clusters")).toBeInTheDocument();
+ expect(screen.getByText("Test Features")).toBeInTheDocument();
+ expect(
+ screen.getByText(/The rules of decision-making must be open/)
+ ).toBeInTheDocument();
+ expect(screen.getByText("Test Help")).toBeInTheDocument();
+ });
+
+ test("components handle data flow and prop passing correctly", () => {
+ const testData = {
+ hero: {
+ title: "Test Hero",
+ subtitle: "Test Subtitle",
+ description: "Test description",
+ ctaText: "Test CTA",
+ ctaHref: "/test",
+ },
+ cards: {
+ title: "Test Cards",
+ subtitle: "Test subtitle",
+ cards: [
+ { text: "Card 1", iconShape: "blob", iconColor: "green" },
+ { text: "Card 2", iconShape: "gear", iconColor: "purple" },
+ ],
+ },
+ features: {
+ title: "Test Features",
+ subtitle: "Test features subtitle",
+ },
+ help: {
+ title: "Test Help",
+ subtitle: "Test help subtitle",
+ buttonText: "Test Help Button",
+ buttonHref: "/help",
+ },
+ };
+
+ render(
+
+ );
+
+ // Verify all data is passed correctly
+ expect(screen.getByText("Test Hero")).toBeInTheDocument();
+ expect(screen.getByText("Test Subtitle")).toBeInTheDocument();
+ expect(screen.getByText("Test description")).toBeInTheDocument();
+ expect(
+ screen.getAllByRole("button", { name: "Test CTA" }).length
+ ).toBeGreaterThan(0);
+ expect(screen.getByText("Test Cards")).toBeInTheDocument();
+ expect(screen.getByText("Card 1")).toBeInTheDocument();
+ expect(screen.getByText("Card 2")).toBeInTheDocument();
+ expect(screen.getByText("Test Features")).toBeInTheDocument();
+ expect(screen.getByText("Test Help")).toBeInTheDocument();
+ expect(
+ screen.getByRole("link", { name: /Test Help Button/i })
+ ).toBeInTheDocument();
+ });
+
+ test("components work together to create a cohesive user experience", async () => {
+ const user = userEvent.setup();
+
+ render(
+
+ );
+
+ // Test interaction flow
+ const learnButtons = screen.getAllByRole("button", { name: "Learn more" });
+ await user.click(learnButtons[0]);
+
+ const createButtons = screen.getAllByRole("button", {
+ name: "Create CommunityRule",
+ });
+ if (createButtons.length > 0) {
+ await user.click(createButtons[0]);
+ }
+
+ const contactButton = screen.getByRole("link", { name: /Contact us/i });
+ await user.click(contactButton);
+
+ // All components should remain functional
+ expect(screen.getByText("Collaborate")).toBeInTheDocument();
+ expect(screen.getByText("How it works")).toBeInTheDocument();
+ expect(screen.getByText("Consensus clusters")).toBeInTheDocument();
+ expect(screen.getByText("Features")).toBeInTheDocument();
+ expect(
+ screen.getByText(/The rules of decision-making must be open/)
+ ).toBeInTheDocument();
+ expect(screen.getByText("Need help?")).toBeInTheDocument();
+ });
+
+ test("components handle edge cases and missing data gracefully", () => {
+ // Test with minimal data
+ render(
+
+ );
+
+ // Components should render without crashing
+ expect(screen.getByText("Minimal Hero")).toBeInTheDocument();
+ expect(screen.getByText("Minimal Cards")).toBeInTheDocument();
+ expect(screen.getByText("Minimal Features")).toBeInTheDocument();
+ expect(screen.getByText("Minimal Help")).toBeInTheDocument();
+ });
+
+ test("components maintain accessibility when used together", () => {
+ render(
+
+ );
+
+ // Check for proper heading hierarchy
+ const headings = screen.getAllByRole("heading");
+ expect(headings.length).toBeGreaterThan(0);
+
+ // Check for proper button roles
+ const buttons = screen.getAllByRole("button");
+ buttons.forEach((button) => {
+ expect(button).toBeInTheDocument();
+ });
+
+ // Check for proper link roles
+ const links = screen.getAllByRole("link");
+ links.forEach((link) => {
+ expect(link).toBeInTheDocument();
+ });
+ });
+});
diff --git a/tests/integration/layout.integration.test.jsx b/tests/integration/layout.integration.test.jsx
new file mode 100644
index 0000000..7daac5d
--- /dev/null
+++ b/tests/integration/layout.integration.test.jsx
@@ -0,0 +1,240 @@
+import { render, screen, cleanup } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";
+import { vi, describe, test, expect, afterEach } from "vitest";
+import Header from "../../app/components/Header";
+import Footer from "../../app/components/Footer";
+
+afterEach(() => {
+ cleanup();
+});
+
+describe("Layout Integration", () => {
+ test("header and footer provide consistent branding", () => {
+ render(
+
+
+
+
+ );
+
+ // Check that CommunityRule branding appears in both header and footer
+ const headerLogos = screen.getAllByAltText("CommunityRule Logo Icon");
+ expect(headerLogos.length).toBeGreaterThan(0);
+
+ // Footer should have the organization name
+ expect(screen.getByText("Media Economies Design Lab")).toBeInTheDocument();
+ });
+
+ test("navigation is consistent between header and footer", () => {
+ render(
+
+
+
+
+ );
+
+ // Header navigation items
+ expect(
+ screen.getAllByRole("menuitem", { name: "Navigate to Use cases page" })
+ .length
+ ).toBeGreaterThan(0);
+ expect(
+ screen.getAllByRole("menuitem", { name: "Navigate to Learn page" }).length
+ ).toBeGreaterThan(0);
+ expect(
+ screen.getAllByRole("menuitem", { name: "Navigate to About page" }).length
+ ).toBeGreaterThan(0);
+
+ // Footer navigation items (should be present in footer as well)
+ const useCasesLinks = screen.getAllByRole("link", { name: "Use cases" });
+ const learnLinks = screen.getAllByRole("link", { name: "Learn" });
+ const aboutLinks = screen.getAllByRole("link", { name: "About" });
+
+ expect(useCasesLinks.length).toBeGreaterThan(0);
+ expect(learnLinks.length).toBeGreaterThan(0);
+ expect(aboutLinks.length).toBeGreaterThan(0);
+ });
+
+ test("header navigation is interactive", async () => {
+ const user = userEvent.setup();
+ render();
+
+ // Test navigation links
+ const useCasesLinks = screen.getAllByRole("menuitem", {
+ name: "Navigate to Use cases page",
+ });
+ const learnLinks = screen.getAllByRole("menuitem", {
+ name: "Navigate to Learn page",
+ });
+ const aboutLinks = screen.getAllByRole("menuitem", {
+ name: "Navigate to About page",
+ });
+
+ const useCasesLink = useCasesLinks[0];
+ const learnLink = learnLinks[0];
+ const aboutLink = aboutLinks[0];
+
+ expect(useCasesLink).toHaveAttribute("href", "#");
+ expect(learnLink).toHaveAttribute("href", "#");
+ expect(aboutLink).toHaveAttribute("href", "#");
+
+ // Test button interactions
+ const createRuleButtons = screen.getAllByRole("button", {
+ name: "Create a new rule with avatar decoration",
+ });
+ await user.click(createRuleButtons[0]);
+ expect(createRuleButtons[0]).toBeInTheDocument();
+ });
+
+ test("footer provides contact and social information", () => {
+ render();
+
+ // Contact information
+ expect(screen.getByText("medlab@colorado.edu")).toBeInTheDocument();
+ expect(
+ 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" })
+ ).toBeInTheDocument();
+ expect(
+ screen.getByRole("link", { name: "Follow us on GitLab" })
+ ).toBeInTheDocument();
+
+ // Legal links
+ expect(
+ screen.getByRole("link", { name: "Privacy Policy" })
+ ).toBeInTheDocument();
+ expect(
+ screen.getByRole("link", { name: "Terms of Service" })
+ ).toBeInTheDocument();
+ });
+
+ test("header provides proper authentication options", () => {
+ render();
+
+ // Login button should be present
+ const loginButtons = screen.getAllByRole("menuitem", {
+ name: "Log in to your account",
+ });
+ const loginButton = loginButtons[0];
+ expect(loginButton).toBeInTheDocument();
+
+ // Create rule button should be present
+ const createRuleButtons = screen.getAllByRole("button", {
+ name: "Create a new rule with avatar decoration",
+ });
+ expect(createRuleButtons.length).toBeGreaterThan(0);
+ });
+
+ test("layout maintains proper semantic structure", () => {
+ render(
+
+
+
+
+ );
+
+ // Header should have banner role
+ const header = screen.getByRole("banner");
+ expect(header).toBeInTheDocument();
+
+ // Navigation should be present
+ const navigation = screen.getByRole("navigation");
+ expect(navigation).toBeInTheDocument();
+
+ // Footer should be present
+ const footer = screen.getByRole("contentinfo");
+ expect(footer).toBeInTheDocument();
+ });
+
+ test("responsive design elements are present", () => {
+ render(
+
+
+
+
+ );
+
+ // Header should have responsive navigation elements
+ const headerContainer = screen.getByRole("banner");
+ expect(headerContainer).toBeInTheDocument();
+
+ // Footer should have responsive layout
+ const footerContainer = screen.getByRole("contentinfo");
+ expect(footerContainer).toBeInTheDocument();
+ });
+
+ test("all interactive elements have proper focus management", () => {
+ render(
+
+
+
+
+ );
+
+ // Get all interactive elements
+ const buttons = screen.getAllByRole("button");
+ const links = screen.getAllByRole("link");
+
+ // All buttons should be focusable
+ buttons.forEach((button) => {
+ expect(button).not.toHaveAttribute("tabindex", "-1");
+ });
+
+ // All links should be focusable
+ links.forEach((link) => {
+ expect(link).not.toHaveAttribute("tabindex", "-1");
+ });
+ });
+
+ test("layout provides consistent user experience", () => {
+ render(
+
+
+
+
+ );
+
+ // Header provides main navigation
+ expect(screen.getByRole("navigation")).toBeInTheDocument();
+
+ // Footer provides additional navigation and contact info
+ expect(screen.getByText("Media Economies Design Lab")).toBeInTheDocument();
+ expect(screen.getByText("medlab@colorado.edu")).toBeInTheDocument();
+
+ // Both header and footer should have CommunityRule branding
+ const logos = screen.getAllByAltText("CommunityRule Logo Icon");
+ expect(logos.length).toBeGreaterThan(0);
+ });
+
+ test("header and footer work together for complete navigation", () => {
+ render(
+
+
+
+
+ );
+
+ // Main navigation in header
+ const headerNav = screen.getByRole("navigation");
+ expect(headerNav).toBeInTheDocument();
+
+ // Additional navigation in footer
+ const footerLinks = screen.getAllByRole("link");
+ const navigationLinks = footerLinks.filter(
+ (link) =>
+ link.textContent?.includes("Use cases") ||
+ link.textContent?.includes("Learn") ||
+ link.textContent?.includes("About")
+ );
+ expect(navigationLinks.length).toBeGreaterThan(0);
+
+ // Contact information in footer
+ expect(
+ screen.getByRole("link", { name: "medlab@colorado.edu" })
+ ).toBeInTheDocument();
+ });
+});
diff --git a/tests/integration/page-flow.integration.test.jsx b/tests/integration/page-flow.integration.test.jsx
new file mode 100644
index 0000000..1547fb7
--- /dev/null
+++ b/tests/integration/page-flow.integration.test.jsx
@@ -0,0 +1,219 @@
+import { render, screen, cleanup } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";
+import { vi, describe, test, expect, afterEach } from "vitest";
+import Page from "../../app/page";
+
+afterEach(() => {
+ cleanup();
+});
+
+describe("Page Flow Integration", () => {
+ test("renders complete page with all sections in correct order", () => {
+ render();
+
+ // Hero Banner section
+ expect(
+ screen.getByRole("heading", { name: "Collaborate" })
+ ).toBeInTheDocument();
+ expect(
+ screen.getByRole("heading", { name: "with clarity" })
+ ).toBeInTheDocument();
+ expect(
+ screen.getByText(
+ "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", {
+ name: "Learn how CommunityRule works",
+ });
+ expect(ctaButtons.length).toBeGreaterThan(0);
+
+ // Logo Wall section - check for partner logos
+ expect(screen.getByAltText("Food Not Bombs")).toBeInTheDocument();
+ expect(screen.getByAltText("Start COOP")).toBeInTheDocument();
+ expect(screen.getByAltText("Metagov")).toBeInTheDocument();
+ expect(screen.getByAltText("Open Civics")).toBeInTheDocument();
+ expect(screen.getByAltText("Mutual Aid CO")).toBeInTheDocument();
+ expect(screen.getByAltText("CU Boulder")).toBeInTheDocument();
+
+ // Numbered Cards section
+ expect(
+ screen.getByRole("heading", { name: /How CommunityRule works/ })
+ ).toBeInTheDocument();
+ expect(
+ screen.getByText(
+ "Here's a quick overview of the process, from start to finish."
+ )
+ ).toBeInTheDocument();
+ expect(
+ screen.getByText("Document how your community makes decisions")
+ ).toBeInTheDocument();
+ expect(
+ 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"
+ )
+ ).toBeInTheDocument();
+
+ // Rule Stack section
+ expect(
+ screen.getByRole("heading", { name: "Consensus clusters" })
+ ).toBeInTheDocument();
+ expect(
+ screen.getByRole("heading", { name: "Elected Board" })
+ ).toBeInTheDocument();
+ expect(
+ screen.getByRole("heading", { name: "Consensus" })
+ ).toBeInTheDocument();
+ expect(
+ 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."
+ )
+ ).toBeInTheDocument();
+
+ // Quote Block section
+ expect(
+ screen.getByText(/The rules of decision-making must be open/)
+ ).toBeInTheDocument();
+
+ // Ask Organizer section
+ expect(
+ screen.getByRole("heading", { name: "Still have questions?" })
+ ).toBeInTheDocument();
+ expect(
+ screen.getByText("Get answers from an experienced organizer")
+ ).toBeInTheDocument();
+ expect(
+ screen.getByRole("link", { name: /Ask an organizer/i })
+ ).toBeInTheDocument();
+ });
+
+ test("hero banner CTA button is interactive", async () => {
+ const user = userEvent.setup();
+ render();
+
+ // Get the first CTA button (multiple sizes for responsive design)
+ const ctaButtons = screen.getAllByRole("button", {
+ name: "Learn how CommunityRule works",
+ });
+ const ctaButton = ctaButtons[0];
+ expect(ctaButton).toBeInTheDocument();
+ // Button should be clickable (no href needed for button elements)
+ expect(ctaButton).toBeEnabled();
+
+ // Test button interaction
+ await user.click(ctaButton);
+ // Button should remain visible after click
+ expect(ctaButton).toBeInTheDocument();
+ });
+
+ test("numbered cards display with correct icons and colors", () => {
+ render();
+
+ // 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/
+ );
+ expect(cards).toHaveLength(3);
+
+ // Check that section numbers are present
+ const sectionNumbers = screen.getAllByText(/1|2|3/);
+ expect(sectionNumbers.length).toBeGreaterThan(0);
+ });
+
+ test("rule stack displays all four governance types", () => {
+ render();
+
+ // Check all four rule types are present
+ expect(screen.getByText("Consensus clusters")).toBeInTheDocument();
+ expect(screen.getByText("Elected Board")).toBeInTheDocument();
+ expect(screen.getByText("Consensus")).toBeInTheDocument();
+ expect(screen.getByText("Petition")).toBeInTheDocument();
+
+ // Check that create rule button is present
+ const createButton = screen.getByRole("button", {
+ name: "Create CommunityRule",
+ });
+ expect(createButton).toBeInTheDocument();
+ });
+
+ test("ask organizer section has proper call-to-action", () => {
+ render();
+
+ const askLink = screen.getByRole("link", { name: /Ask an organizer/i });
+ expect(askLink).toBeInTheDocument();
+ expect(askLink).toHaveAttribute("href", "#contact");
+ });
+
+ test("page maintains proper semantic structure", () => {
+ render();
+
+ // Check for proper heading hierarchy
+ const headings = screen.getAllByRole("heading");
+ expect(headings.length).toBeGreaterThan(5); // Should have multiple headings
+
+ // Check that main content is properly structured
+ const mainContent = screen.getByText(
+ /Help your community make important decisions/
+ );
+ expect(mainContent).toBeInTheDocument();
+ });
+
+ test("all interactive elements are accessible", () => {
+ render();
+
+ // Check all buttons have proper roles
+ const buttons = screen.getAllByRole("button");
+ buttons.forEach((button) => {
+ expect(button).toBeInTheDocument();
+ });
+
+ // Check all links have proper roles
+ const links = screen.getAllByRole("link");
+ links.forEach((link) => {
+ expect(link).toBeInTheDocument();
+ });
+ });
+
+ test("page content flows logically from top to bottom", () => {
+ render();
+
+ // Verify the logical flow of information
+ // 1. Hero introduces the concept
+ expect(
+ screen.getByText(/Help your community make important decisions/)
+ ).toBeInTheDocument();
+
+ // 2. How it works section explains the process
+ expect(screen.getByText("How CommunityRule works")).toBeInTheDocument();
+
+ // 3. Rule types show different governance options
+ expect(screen.getByText("Consensus clusters")).toBeInTheDocument();
+
+ // 4. Features highlight benefits
+ expect(
+ 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/)
+ ).toBeInTheDocument();
+
+ // 6. Call to action for help
+ expect(screen.getByText("Still have questions?")).toBeInTheDocument();
+ });
+});
diff --git a/tests/integration/user-journey.integration.test.jsx b/tests/integration/user-journey.integration.test.jsx
new file mode 100644
index 0000000..1536d2a
--- /dev/null
+++ b/tests/integration/user-journey.integration.test.jsx
@@ -0,0 +1,295 @@
+import { render, screen, cleanup } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";
+import { vi, describe, test, expect, afterEach } from "vitest";
+import Page from "../../app/page";
+import Header from "../../app/components/Header";
+import Footer from "../../app/components/Footer";
+
+afterEach(() => {
+ cleanup();
+});
+
+describe("User Journey Integration", () => {
+ test("new user discovers the application through hero section", async () => {
+ const user = userEvent.setup();
+ render(
+
+ );
+
+ // User sees the main value proposition
+ expect(
+ screen.getByText(/Help your community make important decisions/)
+ ).toBeInTheDocument();
+
+ // User clicks the main CTA to learn more
+ const learnButtons = screen.getAllByRole("button", {
+ name: "Learn how CommunityRule works",
+ });
+ const learnButton = learnButtons[0];
+ await user.click(learnButton);
+
+ // User should see the "How it works" section
+ expect(screen.getByText("How CommunityRule works")).toBeInTheDocument();
+ });
+
+ test("user explores different governance types", async () => {
+ const user = userEvent.setup();
+ render();
+
+ // User sees all four governance options
+ expect(screen.getByText("Consensus clusters")).toBeInTheDocument();
+ expect(screen.getByText("Elected Board")).toBeInTheDocument();
+ expect(screen.getByText("Consensus")).toBeInTheDocument();
+ expect(screen.getByText("Petition")).toBeInTheDocument();
+
+ // User clicks on a governance type to create a rule
+ const createButtons = screen.getAllByRole("button", {
+ name: "Create CommunityRule",
+ });
+ expect(createButtons.length).toBeGreaterThan(0);
+
+ await user.click(createButtons[0]);
+ // Button should remain interactive
+ expect(createButtons[0]).toBeInTheDocument();
+ });
+
+ test("user navigates through the application using header navigation", async () => {
+ const user = userEvent.setup();
+ render(
+
+ );
+
+ // User clicks on navigation links in header (check that they exist and are clickable)
+ const navigationLinks = screen.getAllByRole("link");
+ const headerNavLinks = navigationLinks.filter(
+ (link) =>
+ link.textContent?.includes("Use Cases") ||
+ link.textContent?.includes("Learn") ||
+ link.textContent?.includes("About")
+ );
+
+ // Test that navigation links are present and clickable
+ for (const link of headerNavLinks) {
+ await user.click(link);
+ expect(link).toBeInTheDocument();
+ }
+ });
+
+ test("user seeks help through ask organizer section", async () => {
+ const user = userEvent.setup();
+ render();
+
+ // 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")
+ ).toBeInTheDocument();
+
+ // User clicks the ask organizer button (it's actually a link, not a button)
+ const askLink = screen.getByRole("link", { name: /Ask an organizer/i });
+ await user.click(askLink);
+ expect(askLink).toHaveAttribute("href", "#contact");
+ });
+
+ test("user explores the process through numbered cards", async () => {
+ const user = userEvent.setup();
+ render();
+
+ // User reads through the process steps
+ expect(
+ screen.getByText("Document how your community makes decisions")
+ ).toBeInTheDocument();
+ expect(
+ 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"
+ )
+ ).toBeInTheDocument();
+
+ // User sees the step numbers
+ const stepNumbers = screen.getAllByText(/1|2|3/);
+ expect(stepNumbers.length).toBeGreaterThan(0);
+ });
+
+ test("user accesses contact information through footer", async () => {
+ const user = userEvent.setup();
+ render(
+
+ );
+
+ // User finds contact email in footer
+ const emailLink = screen.getByRole("link", { name: "medlab@colorado.edu" });
+ expect(emailLink).toHaveAttribute("href", "mailto:medlab@colorado.edu");
+
+ // User finds social media links
+ const blueskyLink = screen.getByRole("link", {
+ name: "Follow us on Bluesky",
+ });
+ const gitlabLink = screen.getByRole("link", {
+ name: "Follow us on GitLab",
+ });
+
+ expect(blueskyLink).toBeInTheDocument();
+ expect(gitlabLink).toBeInTheDocument();
+ });
+
+ test("user explores features and benefits", async () => {
+ const user = userEvent.setup();
+ render();
+
+ // User sees the features section
+ expect(
+ 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."
+ )
+ ).toBeInTheDocument();
+
+ // User sees the testimonial/quote (check for the actual quote content)
+ expect(
+ screen.getByText(/The rules of decision-making must be open/)
+ ).toBeInTheDocument();
+ });
+
+ test("user interacts with logo wall and social proof", async () => {
+ const user = userEvent.setup();
+ render(
+
+ );
+
+ // User sees the logo wall with partner logos (check for any logo images)
+ const logoImages = screen.getAllByRole("img");
+ const partnerLogos = logoImages.filter(
+ (img) =>
+ img.alt?.includes("Food Not Bombs") ||
+ img.alt?.includes("Start COOP") ||
+ img.alt?.includes("Metagov") ||
+ img.alt?.includes("Open Civics") ||
+ img.alt?.includes("Mutual Aid CO") ||
+ img.alt?.includes("CU Boulder")
+ );
+ expect(partnerLogos.length).toBeGreaterThan(0);
+
+ // Social links should be present in footer
+ const blueskyLink = screen.getByRole("link", { name: /Bluesky/i });
+ const gitlabLink = screen.getByRole("link", { name: /GitLab/i });
+ expect(blueskyLink).toBeInTheDocument();
+ expect(gitlabLink).toBeInTheDocument();
+ });
+
+ test("user completes the full journey from discovery to action", async () => {
+ const user = userEvent.setup();
+ render(
+
+ );
+
+ // 1. User discovers the application
+ expect(screen.getByText("Collaborate")).toBeInTheDocument();
+ expect(screen.getByText("with clarity")).toBeInTheDocument();
+
+ // 2. User learns how it works
+ expect(screen.getByText("How CommunityRule works")).toBeInTheDocument();
+
+ // 3. User sees governance options
+ expect(screen.getByText("Consensus clusters")).toBeInTheDocument();
+
+ // 4. User sees features and benefits
+ expect(
+ 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/)
+ ).toBeInTheDocument();
+
+ // 6. User can take action
+ const createButtons = screen.getAllByRole("button", {
+ name: "Create CommunityRule",
+ });
+ expect(createButtons.length).toBeGreaterThan(0);
+
+ // 7. User can get help if needed
+ expect(screen.getByText("Still have questions?")).toBeInTheDocument();
+ });
+
+ test("user can access all navigation options consistently", async () => {
+ const user = userEvent.setup();
+ render(
+
+ );
+
+ // Header navigation
+ const headerNav = screen.getByRole("navigation");
+ expect(headerNav).toBeInTheDocument();
+
+ // Footer navigation
+ const footerLinks = screen.getAllByRole("link");
+ const navigationLinks = footerLinks.filter(
+ (link) =>
+ link.textContent?.includes("Use cases") ||
+ link.textContent?.includes("Learn") ||
+ link.textContent?.includes("About")
+ );
+ expect(navigationLinks.length).toBeGreaterThan(0);
+
+ // All navigation links should be accessible
+ navigationLinks.forEach((link) => {
+ expect(link).not.toHaveAttribute("tabindex", "-1");
+ });
+ });
+
+ test("user can complete actions without errors", async () => {
+ const user = userEvent.setup();
+ render(
+
+ );
+
+ // Test all interactive elements
+ const buttons = screen.getAllByRole("button");
+ const links = screen.getAllByRole("link");
+
+ // All buttons should be clickable
+ for (const button of buttons) {
+ await user.click(button);
+ expect(button).toBeInTheDocument();
+ }
+
+ // All links should be accessible
+ for (const link of links) {
+ expect(link).toBeInTheDocument();
+ expect(link).not.toHaveAttribute("tabindex", "-1");
+ }
+ });
+});