/** * Property-Based Test: Section Header Count Accuracy * * Feature: queue-collapsible-sections, Property 4: Section Header Count Accuracy * **Validates: Requirements 3.1, 3.2** * * For every section in the grouped output, the items array length equals the count * that would be displayed in the header. The sum of all section item counts equals * the total input array length. */ import fc from 'fast-check'; // Replicate the grouping logic inline (utility file not yet extracted) function groupQueueItems(visibleItems) { const INVENTORY_TYPES = new Set(['CARD', 'GRANITE', 'DECOM']); const inventoryItems = []; const vendorMap = new Map(); for (const item of visibleItems) { if (INVENTORY_TYPES.has(item.workflow_type)) { inventoryItems.push(item); } else { const vendor = item.vendor?.trim() || 'Unknown'; if (!vendorMap.has(vendor)) vendorMap.set(vendor, []); vendorMap.get(vendor).push(item); } } const sections = []; if (inventoryItems.length > 0) { sections.push({ key: 'inventory', label: 'Inventory', type: 'inventory', items: inventoryItems }); } const sortedVendors = [...vendorMap.entries()].sort((a, b) => a[0].localeCompare(b[0])); for (const [vendor, items] of sortedVendors) { sections.push({ key: `vendor:${vendor}`, label: vendor, type: 'vendor', items }); } return sections; } // Generator for queue items with realistic workflow types and vendor names const workflowTypeArb = fc.constantFrom('CARD', 'GRANITE', 'DECOM', 'FP', 'Archer'); const vendorArb = fc.oneof( fc.constantFrom('Microsoft', 'Adobe', 'Cisco', 'Oracle', 'VMware', 'Apple'), fc.constant(''), fc.constant(null), fc.constant(undefined) ); const queueItemArb = fc.record({ id: fc.uuid(), workflow_type: workflowTypeArb, vendor: vendorArb, hostname: fc.string({ minLength: 1, maxLength: 20 }), status: fc.constant('pending'), }); const queueItemsArb = fc.array(queueItemArb, { minLength: 1, maxLength: 50 }); describe('Queue Grouping — Property 4: Section Header Count Accuracy', () => { it('each section items.length is a positive integer (the displayed count)', () => { fc.assert( fc.property(queueItemsArb, (items) => { const sections = groupQueueItems(items); for (const section of sections) { // items.length is the count that would be displayed in the header expect(Number.isInteger(section.items.length)).toBe(true); expect(section.items.length).toBeGreaterThan(0); } }), { numRuns: 200 } ); }); it('sum of all section item counts equals total input array length', () => { fc.assert( fc.property(queueItemsArb, (items) => { const sections = groupQueueItems(items); const totalItemsInSections = sections.reduce( (sum, section) => sum + section.items.length, 0 ); expect(totalItemsInSections).toBe(items.length); }), { numRuns: 200 } ); }); });