import { render, screen } from '@testing-library/react';
import { afterEach, beforeAll, describe, expect, it } from 'vitest';
import '@/lib/i18n';
import en from '@/locales/en.json';
import { FAQSection } from '@/components/FAQSection';
// jsdom has no IntersectionObserver; framer-motion's `whileInView` needs one
// to mount without throwing. A no-op stub is enough for rendering assertions.
beforeAll(() => {
class IntersectionObserverStub {
observe() {}
unobserve() {}
disconnect() {}
takeRecords() {
return [];
}
}
// @ts-expect-error: minimal test stub, not a spec-complete implementation
globalThis.IntersectionObserver = IntersectionObserverStub;
});
afterEach(() => {
// FAQSection uses AccordionItem's `value={faq.question}`: a duplicate
// question string across renders would collide, so nothing to clean up
// beyond RTL's own auto-cleanup (setup-rtl.ts) between tests.
});
describe('', () => {
it('renders every question in locales/en.json landing.faq, q10 included (I6 regression)', () => {
render();
const faqKeys = Object.keys(en.landing.faq).filter((k) => k.startsWith('q'));
// Guards the guard: if this ever drops back to 9, the assertion below
// would vacuously pass on a component that dropped q10 right along with
// the locale entry disappearing, so pin the count from the fixture too.
expect(faqKeys.length).toBeGreaterThanOrEqual(10);
for (const key of faqKeys) {
const { question } = (en.landing.faq as Record)[
key
];
expect(screen.getByText(question)).toBeInTheDocument();
}
});
it('renders exactly one accordion item per FAQ entry (no silent truncation)', () => {
render();
const faqKeys = Object.keys(en.landing.faq).filter((k) => k.startsWith('q'));
expect(screen.getAllByRole('button')).toHaveLength(faqKeys.length);
});
});