Browse Source
refactor: replace hardcoded layout margins with global --app-shell-px variable and add regression tests
master
refactor: replace hardcoded layout margins with global --app-shell-px variable and add regression tests
master
11 changed files with 147 additions and 18 deletions
-
2src/app/finding-match/finding-match-client.tsx
-
10src/app/globals.css
-
2src/app/intro/intro-client.tsx
-
2src/app/questions-list/[slug]/loading.tsx
-
12src/app/questions-list/[slug]/question-detail-client.tsx
-
123src/app/questions-list/[slug]/question-dimensions.test.tsx
-
2src/app/questions-list/[slug]/test-intro-client.tsx
-
4src/components/Componentes/page-header.tsx
-
4src/components/Componentes/page-loading-skeleton.tsx
-
2src/components/Componentes/test-loading-screen.tsx
-
2src/components/Componentes/test-questions-flow.tsx
@ -0,0 +1,123 @@ |
|||||
|
import { describe, it, expect, vi, afterEach } from "vitest"; |
||||
|
import { cleanup, render } from "@testing-library/react"; |
||||
|
import fs from "fs"; |
||||
|
import path from "path"; |
||||
|
import { FixToTheEnd } from "@/components/Componentes/fix-to-the-end"; |
||||
|
import { PageHeader } from "@/components/Componentes/page-header"; |
||||
|
import StickyHeader from "@/components/Componentes/sticky-header"; |
||||
|
import { I18nProvider } from "@/translations/provider"; |
||||
|
|
||||
|
afterEach(() => { |
||||
|
cleanup(); |
||||
|
}); |
||||
|
|
||||
|
vi.mock("next/navigation", () => ({ |
||||
|
useRouter: () => ({ |
||||
|
push: vi.fn(), |
||||
|
replace: vi.fn(), |
||||
|
back: vi.fn(), |
||||
|
}), |
||||
|
})); |
||||
|
|
||||
|
vi.mock("@/hooks/marriage/use-profile-main", () => ({ |
||||
|
useMarriageProfileQuery: () => ({ |
||||
|
data: undefined, |
||||
|
isLoading: false, |
||||
|
isFetched: true, |
||||
|
}), |
||||
|
})); |
||||
|
|
||||
|
describe("Dimensions & Padding Integrity Verification", () => { |
||||
|
it("globals.css preserves --app-shell-px and padding-inline on section-overlay", () => { |
||||
|
const cssPath = path.resolve(process.cwd(), "src/app/globals.css"); |
||||
|
const cssContent = fs.readFileSync(cssPath, "utf-8"); |
||||
|
|
||||
|
// Verify .section-overlay defines --app-shell-px: 17px and padding-inline: var(--app-shell-px)
|
||||
|
expect(cssContent).toMatch( |
||||
|
/\.section-overlay\s*\{[\s\S]*?--app-shell-px:\s*17px;/, |
||||
|
); |
||||
|
expect(cssContent).toMatch( |
||||
|
/\.section-overlay\s*\{[\s\S]*?padding-inline:\s*var\(--app-shell-px\);/, |
||||
|
); |
||||
|
|
||||
|
// Verify tablet responsive padding for .section-overlay
|
||||
|
expect(cssContent).toMatch( |
||||
|
/@media\s*\(min-width:\s*600px\)\s*\{[\s\S]*?\.section-overlay\s*\{[\s\S]*?--app-shell-px:\s*clamp\(24px,\s*5vw,\s*48px\);/, |
||||
|
); |
||||
|
|
||||
|
// Verify .section-overlay does NOT have zeroed out padding or 0px app-shell-px
|
||||
|
expect(cssContent).not.toMatch( |
||||
|
/\.section-overlay\s*\{[\s\S]*?--app-shell-px:\s*0px;/, |
||||
|
); |
||||
|
|
||||
|
// Verify .question-detail-main rule exists with breakout margin
|
||||
|
expect(cssContent).toMatch( |
||||
|
/\.question-detail-main\s*\{[\s\S]*?margin-inline:\s*calc\(-1\s*\*\s*var\(--app-shell-px,\s*17px\)\);/, |
||||
|
); |
||||
|
}); |
||||
|
|
||||
|
it("FixToTheEnd retains var(--app-shell-px, 17px) padding for bottom buttons", () => { |
||||
|
const { container } = render( |
||||
|
<FixToTheEnd> |
||||
|
<button type="button">Submit</button> |
||||
|
</FixToTheEnd>, |
||||
|
); |
||||
|
|
||||
|
const fixToEndEl = container.querySelector( |
||||
|
".question-fix-to-end", |
||||
|
) as HTMLElement; |
||||
|
expect(fixToEndEl).toBeInTheDocument(); |
||||
|
expect(fixToEndEl.style.paddingInline).toBe("var(--app-shell-px, 17px)"); |
||||
|
expect(fixToEndEl.style.paddingBottom).toBe( |
||||
|
"calc(16px + var(--safe-bottom))", |
||||
|
); |
||||
|
}); |
||||
|
|
||||
|
it("PageHeader applies full breakout marginInline and content paddingInline", () => { |
||||
|
const { container } = render( |
||||
|
<I18nProvider locale="fa" dictionary={{ Marriage: "مریج" }}> |
||||
|
<PageHeader sticky title="Test Title" /> |
||||
|
</I18nProvider>, |
||||
|
); |
||||
|
|
||||
|
const headerEl = container.querySelector("header") as HTMLElement; |
||||
|
expect(headerEl).toBeInTheDocument(); |
||||
|
expect(headerEl.style.marginInline).toBe( |
||||
|
"calc(-1 * var(--app-shell-px, 17px))", |
||||
|
); |
||||
|
expect(headerEl.style.paddingInline).toBe("var(--app-shell-px, 17px)"); |
||||
|
}); |
||||
|
|
||||
|
it("StickyHeader renders correctly with safe-area + 4px and rounded bottom", () => { |
||||
|
const { container } = render( |
||||
|
<StickyHeader> |
||||
|
<h1>Question Title</h1> |
||||
|
</StickyHeader>, |
||||
|
); |
||||
|
|
||||
|
const headerEl = container.querySelector("header") as HTMLElement; |
||||
|
expect(headerEl).toBeInTheDocument(); |
||||
|
expect(headerEl.className).toContain("rounded-b-[15px]"); |
||||
|
expect(headerEl.className).toContain( |
||||
|
"bg-[linear-gradient(135deg,#E03950_0%,#FE6F82_100%)]", |
||||
|
); |
||||
|
}); |
||||
|
|
||||
|
it("all question detail main elements use question-detail-main class instead of hardcoded -mx-[17px]", () => { |
||||
|
const detailClientPath = path.resolve( |
||||
|
process.cwd(), |
||||
|
"src/app/questions-list/[slug]/question-detail-client.tsx", |
||||
|
); |
||||
|
const content = fs.readFileSync(detailClientPath, "utf-8"); |
||||
|
|
||||
|
// No hardcoded -mx-[17px] on <main>
|
||||
|
expect(content).not.toMatch(/<main[^>]*className="[^"]*-mx-\[17px\]/); |
||||
|
|
||||
|
// Matches question-detail-main on <main>
|
||||
|
const mainMatches = content.match( |
||||
|
/<main[^>]*className="[^"]*question-detail-main/g, |
||||
|
); |
||||
|
expect(mainMatches).not.toBeNull(); |
||||
|
expect(mainMatches!.length).toBeGreaterThanOrEqual(4); |
||||
|
}); |
||||
|
}); |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue