diff --git a/src/components/faq/__tests__/FaqItem.test.jsx b/src/components/faq/__tests__/FaqItem.test.jsx new file mode 100644 index 00000000..5d82c80b --- /dev/null +++ b/src/components/faq/__tests__/FaqItem.test.jsx @@ -0,0 +1,39 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import FaqItem from '../FaqItem'; + +describe('FaqItem', () => { + const faq = { + title: 'What is Syscoin?', + description: '

Syscoin is a blockchain protocol.

' + }; + + test('renders title and index, content collapsed by default (height 0)', () => { + const { container } = render(); + + expect(screen.getByText('1')).toBeInTheDocument(); + expect(screen.getByText('What is Syscoin?')).toBeInTheDocument(); + const collapse = container.querySelector('.ReactCollapse--collapse'); + expect(collapse).toBeTruthy(); + expect(collapse.style.height).toBe('0px'); + }); + + test('toggles content height when clicking header', () => { + const { container } = render(); + + const header = screen.getByText('What is Syscoin?'); + const collapse = container.querySelector('.ReactCollapse--collapse'); + expect(collapse.style.height).toBe('0px'); + + userEvent.click(header); + // Opened: height should no longer be 0px (react-collapse sets pixel height during animation) + expect(collapse.style.height).not.toBe('0px'); + + userEvent.click(header); + // Closed again + expect(collapse.style.height).toBe('0px'); + }); +}); + + diff --git a/src/components/faq/__tests__/FaqList.test.jsx b/src/components/faq/__tests__/FaqList.test.jsx new file mode 100644 index 00000000..d7a20901 --- /dev/null +++ b/src/components/faq/__tests__/FaqList.test.jsx @@ -0,0 +1,62 @@ +import React from 'react'; +import { render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import FaqList from '../FaqList'; + +// Mock i18n hook +jest.mock('react-i18next', () => ({ + useTranslation: () => ({ t: (k) => k }) +})); + +// Mock request util +jest.mock('../../../utils/request', () => ({ + getPublicFaqs: jest.fn() +})); + +describe('FaqList', () => { + const { getPublicFaqs } = require('../../../utils/request'); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + test('renders loading then empty state', async () => { + getPublicFaqs.mockResolvedValue({ data: { faqs: [] } }); + + render(); + + expect(screen.getByText('admin.faqs.loading')).toBeInTheDocument(); + + expect(await screen.findByText('There are no questions.')).toBeInTheDocument(); + }); + + test('renders list and allows toggling an item (via height)', async () => { + getPublicFaqs.mockResolvedValue({ data: { faqs: [ + { title: 'Question A', description: '

Answer A

' }, + { title: 'Question B', description: '

Answer B

' } + ] } }); + + const { container } = render(); + + // Wait for one of the items + await screen.findByText('Question A'); + + // Initially collapsed (height 0) + const collapse = container.querySelector('.ReactCollapse--collapse'); + expect(collapse.style.height).toBe('0px'); + + // Toggle via clicking the title + userEvent.click(screen.getByText('Question A')); + expect(collapse.style.height).not.toBe('0px'); + }); + + test('renders error state on request failure', async () => { + getPublicFaqs.mockRejectedValue(new Error('network')); + + render(); + + expect(await screen.findByText("The data couldn't be fetched.")).toBeInTheDocument(); + }); +}); + +