From 276a625997721666999389f1671021215f7e326a Mon Sep 17 00:00:00 2001 From: Ben Stull Date: Sun, 7 Jun 2026 17:41:04 -0700 Subject: [PATCH] =?UTF-8?q?test(slice3):=20Catalog=20faceted-pane=20compon?= =?UTF-8?q?ent=20test=20(=C2=A722.4a=20PUC-3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Catalog.test.jsx | 63 ++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 frontend/src/components/Catalog.test.jsx diff --git a/frontend/src/components/Catalog.test.jsx b/frontend/src/components/Catalog.test.jsx new file mode 100644 index 0000000..71b91cf --- /dev/null +++ b/frontend/src/components/Catalog.test.jsx @@ -0,0 +1,63 @@ +import React from 'react' +import { describe, it, expect, vi, beforeEach } from 'vitest' +import { render, screen, fireEvent, waitFor } from '@testing-library/react' +import { MemoryRouter } from 'react-router-dom' + +// §22.4a SLICE-3 — the faceted catalog pane (PUC-3). Mock the api so +// getCollection drives the field schema and listRFCs returns { items, facets }. +const listRFCs = vi.fn() +const getCollection = vi.fn() +vi.mock('../api', () => ({ + listRFCs: (...a) => listRFCs(...a), + listProposals: () => Promise.resolve({ items: [] }), + getCollection: (...a) => getCollection(...a), +})) +vi.mock('../lib/entryPaths', () => ({ + entryPath: () => '/x', proposalPath: () => '/p', + useProjectId: () => 'ohm', useCollectionId: () => 'default', +})) +import Catalog from './Catalog.jsx' + +const renderCatalog = () => + render( {}} version={0} />) + +describe('Catalog faceted pane', () => { + beforeEach(() => { listRFCs.mockReset(); getCollection.mockReset() }) + + it('renders facet groups with counts when the collection declares fields', async () => { + getCollection.mockResolvedValue({ + fields: { priority: { type: 'enum', values: ['P0', 'P1'] } }, + viewer: { can_contribute: false }, entry_noun: 'RFC', + }) + listRFCs.mockResolvedValue({ + items: [{ slug: 'a', title: 'A', state: 'active', tags: [], starred_by_me: false }], + facets: { priority: { P0: 3, P1: 1 }, state: { active: 4 } }, + }) + renderCatalog() + expect(await screen.findByText('P0')).toBeInTheDocument() + expect(screen.getByText('3')).toBeInTheDocument() + }) + + it('re-fetches with the selection when a facet checkbox is toggled', async () => { + getCollection.mockResolvedValue({ + fields: { priority: { type: 'enum', values: ['P0'] } }, + viewer: {}, entry_noun: 'RFC', + }) + listRFCs.mockResolvedValue({ items: [], facets: { priority: { P0: 2 }, state: {} } }) + renderCatalog() + const box = await screen.findByText('P0') + fireEvent.click(box.closest('label').querySelector('input')) + await waitFor(() => { + const last = listRFCs.mock.calls.at(-1) + expect(last[2].selections.priority).toContain('P0') + }) + }) + + it('renders legacy state chips when the collection declares no fields', async () => { + getCollection.mockResolvedValue({ fields: null, viewer: {}, entry_noun: 'RFC' }) + listRFCs.mockResolvedValue({ items: [], facets: {} }) + renderCatalog() + expect(await screen.findByText('Super-draft')).toBeInTheDocument() + expect(screen.getByText('Active')).toBeInTheDocument() + }) +})