feat: control room hero, SEO/AEO optimization and design system fixes
Hero: replace particle field with cobe globe (Capricorn view, multi-axis drag, reduced-motion safe), telemetry HUD with pointer parallax, particle text build effect, Space Grotesk display font. SEO: short titles with template, PT-BR accents, twitter cards on dynamic cases, escaped JSON-LD via lib/jsonld.ts, CSP report-only, 25 service FAQs answer-first. Design: fix TW4 layered reset killing spacing utilities, literal @theme tokens, mobile hero overflow, header overlap, empty case cards. Remove framer-motion (unified on motion/react), header version badge, phone number from hero CTA. Production build verified (24 static pages).
This commit is contained in:
1 parent
0920370f30
commit
b791b7de9e
94 files changed
+2621
-2889
No files matched your search
@@ -1,264 +1,36 @@
|
||||
import { render } from "@testing-library/react";
|
||||
import Footer from "./Footer";
|
||||
import fc from "fast-check";
|
||||
import Footer from "./Footer";
|
||||
|
||||
describe("Property 3: Responsive Component Layout", () => {
|
||||
it("should include Tailwind responsive utility classes for grid layout", () => {
|
||||
/**
|
||||
* **Validates: Requirements 2.6**
|
||||
*
|
||||
* Property: For any Footer component, it should include Tailwind responsive
|
||||
* utility classes (sm:, md:, lg:) to adapt the grid layout across viewport sizes.
|
||||
* This ensures the component is responsive and provides optimal layout at different
|
||||
* screen widths.
|
||||
*/
|
||||
describe("Footer responsive structure", () => {
|
||||
it("keeps the responsive design-system structure across renders", () => {
|
||||
fc.assert(
|
||||
fc.property(
|
||||
fc.constant(null), // No random input needed, testing static component
|
||||
() => {
|
||||
const { container } = render(<Footer />);
|
||||
fc.property(fc.integer({ min: 1, max: 5 }), (renderCount) => {
|
||||
for (let index = 0; index < renderCount; index += 1) {
|
||||
const { container, unmount } = render(<Footer />);
|
||||
const footer = container.querySelector("footer");
|
||||
const grid = footer?.querySelector(".ds-grid-2");
|
||||
|
||||
// Find the main grid container
|
||||
const gridContainer = container.querySelector("footer .grid");
|
||||
expect(footer).toHaveClass("ds-section");
|
||||
expect(
|
||||
footer?.querySelector(".ds-section-shell"),
|
||||
).toBeInTheDocument();
|
||||
expect(grid).toBeInTheDocument();
|
||||
expect(grid?.querySelectorAll(":scope > .ds-card")).toHaveLength(2);
|
||||
|
||||
// Verify grid container exists
|
||||
if (!gridContainer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const className = gridContainer.className;
|
||||
|
||||
// Check for responsive grid-cols classes
|
||||
// Should have base grid-cols-1 and responsive variants
|
||||
const hasBaseGridCols = className.includes("grid-cols-1");
|
||||
const hasMdResponsive = className.includes("md:grid-cols-");
|
||||
const hasLgResponsive = className.includes("lg:grid-cols-");
|
||||
|
||||
return hasBaseGridCols && hasMdResponsive && hasLgResponsive;
|
||||
},
|
||||
),
|
||||
{ numRuns: 100 },
|
||||
);
|
||||
});
|
||||
|
||||
it("should include responsive padding classes", () => {
|
||||
/**
|
||||
* **Validates: Requirements 2.6**
|
||||
*
|
||||
* Property: For any Footer component, the container should use the design system
|
||||
* section class (ds-section) which provides responsive padding that scales
|
||||
* appropriately across viewport sizes. This ensures consistent spacing that
|
||||
* adapts to different screen widths.
|
||||
*/
|
||||
fc.assert(
|
||||
fc.property(fc.constant(null), () => {
|
||||
const { container } = render(<Footer />);
|
||||
|
||||
// Find the footer element
|
||||
const footer = container.querySelector("footer");
|
||||
|
||||
if (!footer) {
|
||||
return false;
|
||||
unmount();
|
||||
}
|
||||
|
||||
const className = footer.className;
|
||||
|
||||
// Check for design system section class which handles responsive padding
|
||||
const hasDsSection = className.includes("ds-section");
|
||||
|
||||
// The ds-section class in globals.css provides responsive padding via CSS
|
||||
// padding: var(--sp-20) var(--sp-16) on desktop
|
||||
// padding: var(--sp-16) var(--sp-6) on mobile (via @media query)
|
||||
return hasDsSection;
|
||||
}),
|
||||
{ numRuns: 100 },
|
||||
{ numRuns: 25 },
|
||||
);
|
||||
});
|
||||
|
||||
it("should include responsive gap classes for grid spacing", () => {
|
||||
/**
|
||||
* **Validates: Requirements 2.6**
|
||||
*
|
||||
* Property: For any Footer component grid, it should include gap
|
||||
* classes to adjust spacing between grid items.
|
||||
* This ensures optimal spacing that scales with the layout.
|
||||
*/
|
||||
fc.assert(
|
||||
fc.property(fc.constant(null), () => {
|
||||
const { container } = render(<Footer />);
|
||||
it("uses the mobile-first grid primitive instead of the legacy grid contract", () => {
|
||||
const { container } = render(<Footer />);
|
||||
const grid = container.querySelector(".ds-grid-2");
|
||||
|
||||
// Find the grid container
|
||||
const gridContainer = container.querySelector("footer .grid");
|
||||
|
||||
if (!gridContainer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const className = gridContainer.className;
|
||||
|
||||
// Check for gap classes (base gap)
|
||||
const hasGap = className.includes("gap-sp-");
|
||||
|
||||
// Should have at least base gap
|
||||
return hasGap;
|
||||
}),
|
||||
{ numRuns: 100 },
|
||||
);
|
||||
});
|
||||
|
||||
it("should maintain responsive classes across multiple renders", () => {
|
||||
/**
|
||||
* **Validates: Requirements 2.6**
|
||||
*
|
||||
* Property: For any number of component renders, the Footer should consistently
|
||||
* maintain its responsive utility classes. This verifies that responsive behavior
|
||||
* is not accidentally removed during re-renders.
|
||||
*/
|
||||
fc.assert(
|
||||
fc.property(
|
||||
fc.integer({ min: 1, max: 5 }), // Test 1-5 renders
|
||||
(numRenders) => {
|
||||
let allRendersValid = true;
|
||||
|
||||
for (let i = 0; i < numRenders; i++) {
|
||||
const { container, unmount } = render(<Footer />);
|
||||
|
||||
// Check grid container
|
||||
const gridContainer = container.querySelector("footer .grid");
|
||||
|
||||
if (!gridContainer) {
|
||||
allRendersValid = false;
|
||||
unmount();
|
||||
continue;
|
||||
}
|
||||
|
||||
const className = gridContainer.className;
|
||||
|
||||
// Verify responsive classes are present
|
||||
const hasResponsiveClasses =
|
||||
className.includes("grid-cols-1") &&
|
||||
className.includes("md:grid-cols-") &&
|
||||
className.includes("lg:grid-cols-");
|
||||
|
||||
if (!hasResponsiveClasses) {
|
||||
allRendersValid = false;
|
||||
}
|
||||
|
||||
unmount();
|
||||
}
|
||||
|
||||
return allRendersValid;
|
||||
},
|
||||
),
|
||||
{ numRuns: 100 },
|
||||
);
|
||||
});
|
||||
|
||||
it("should have responsive column span for copyright section", () => {
|
||||
/**
|
||||
* **Validates: Requirements 2.6**
|
||||
*
|
||||
* Property: For any Footer component, the copyright section should include
|
||||
* responsive column span classes (md:col-span-2, lg:col-span-1) to adapt
|
||||
* its position in the grid layout across different viewport sizes.
|
||||
*/
|
||||
fc.assert(
|
||||
fc.property(fc.constant(null), () => {
|
||||
const { container } = render(<Footer />);
|
||||
|
||||
// Find the copyright section (contains "Informacoes legais" heading)
|
||||
const copyrightSection = Array.from(
|
||||
container.querySelectorAll("footer h3"),
|
||||
).find((h3) =>
|
||||
h3.textContent?.includes("Informacoes legais"),
|
||||
)?.parentElement;
|
||||
|
||||
if (!copyrightSection) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const className = copyrightSection.className;
|
||||
|
||||
// Check for responsive column span classes
|
||||
const hasMdColSpan = className.includes("md:col-span-");
|
||||
const hasLgColSpan = className.includes("lg:col-span-");
|
||||
|
||||
return hasMdColSpan && hasLgColSpan;
|
||||
}),
|
||||
{ numRuns: 100 },
|
||||
);
|
||||
});
|
||||
|
||||
it("should use consistent responsive breakpoint prefixes", () => {
|
||||
/**
|
||||
* **Validates: Requirements 2.6**
|
||||
*
|
||||
* Property: For any Footer component, all responsive utility classes should
|
||||
* use consistent Tailwind breakpoint prefixes (md:, lg:). This ensures the
|
||||
* component follows Tailwind's responsive design system correctly.
|
||||
*/
|
||||
fc.assert(
|
||||
fc.property(fc.constant(null), () => {
|
||||
const { container } = render(<Footer />);
|
||||
|
||||
// Get all elements with classes in the footer
|
||||
const allElements = container.querySelectorAll("footer *");
|
||||
|
||||
let hasMdPrefix = false;
|
||||
let hasLgPrefix = false;
|
||||
let hasInvalidPrefix = false;
|
||||
|
||||
allElements.forEach((element) => {
|
||||
const className = element.className;
|
||||
|
||||
if (typeof className === "string") {
|
||||
// Check for valid responsive prefixes
|
||||
if (className.includes("md:")) hasMdPrefix = true;
|
||||
if (className.includes("lg:")) hasLgPrefix = true;
|
||||
|
||||
// Check for invalid/inconsistent prefixes (sm: should not be used based on design)
|
||||
// We're looking for md: and lg: specifically
|
||||
}
|
||||
});
|
||||
|
||||
// Should have md: and lg: prefixes, no invalid ones
|
||||
return hasMdPrefix && hasLgPrefix && !hasInvalidPrefix;
|
||||
}),
|
||||
{ numRuns: 100 },
|
||||
);
|
||||
});
|
||||
|
||||
it("should have mobile-first responsive design with base classes", () => {
|
||||
/**
|
||||
* **Validates: Requirements 2.6**
|
||||
*
|
||||
* Property: For any Footer component, it should follow mobile-first responsive
|
||||
* design by having base classes for mobile and progressive enhancement with
|
||||
* responsive variants. This ensures the component works on all devices.
|
||||
*/
|
||||
fc.assert(
|
||||
fc.property(fc.constant(null), () => {
|
||||
const { container } = render(<Footer />);
|
||||
|
||||
// Find the grid container
|
||||
const gridContainer = container.querySelector("footer .grid");
|
||||
|
||||
if (!gridContainer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const className = gridContainer.className;
|
||||
|
||||
// Mobile-first means base class (grid-cols-1) should be present
|
||||
// Then enhanced with md: and lg: variants
|
||||
const hasMobileBase = className.includes("grid-cols-1");
|
||||
const hasTabletEnhancement = className.includes("md:grid-cols-");
|
||||
const hasDesktopEnhancement = className.includes("lg:grid-cols-");
|
||||
|
||||
// Verify progressive enhancement: mobile -> tablet -> desktop
|
||||
return hasMobileBase && hasTabletEnhancement && hasDesktopEnhancement;
|
||||
}),
|
||||
{ numRuns: 100 },
|
||||
);
|
||||
expect(grid).toBeInTheDocument();
|
||||
expect(grid).not.toHaveClass("grid-cols-1");
|
||||
expect(grid).not.toHaveClass("lg:grid-cols-3");
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user