/** * Bug Condition Exploration Property Test: Compliance Remediation Display Fix * * Spec: .kiro/specs/compliance-remediation-display-fix/ (bugfix) * * BUG CONDITION: * isBugCondition(row) = row.resolution_date != null OR row.remediation_plan != null * Any row with metadata set will lose it through groupByHostname() because the * function does not propagate resolution_date or remediation_plan into device objects. * * THIS TEST IS EXPECTED TO FAIL ON UNFIXED CODE. * Failure confirms the bug exists — resolution_date and remediation_plan are undefined * in the grouped device objects returned by groupByHostname(). * * **Validates: Requirements 1.1, 1.2, 2.2** */ const fc = require('fast-check'); // --- Mocks (must be installed BEFORE requiring the route module) --- jest.mock('../middleware/auth', () => ({ requireAuth: () => (req, res, next) => next(), requireGroup: () => (req, res, next) => next(), })); jest.mock('../helpers/auditLog', () => jest.fn()); jest.mock('../helpers/driftChecker', () => ({ loadConfig: jest.fn(() => ({})), compareSchemaToDrift: jest.fn(() => null), reconcileConfig: jest.fn(() => ({ changes: [] })), })); jest.mock('../helpers/vclHelpers', () => ({ isValidDateString: jest.fn(() => true), validateRemediationPlan: jest.fn(() => ({ valid: true })), computeVCLStats: jest.fn(() => ({})), categorizeNonCompliant: jest.fn(() => []), rankHeavyHitters: jest.fn(() => []), computeForecastBurndown: jest.fn(() => ({})), matchByHostname: jest.fn(() => []), computeBulkDiff: jest.fn(() => ({})), mapColumnHeaders: jest.fn(() => ({})), })); const mockPool = { query: jest.fn(() => Promise.resolve({ rows: [], rowCount: 0 })), connect: jest.fn(() => Promise.resolve({ query: jest.fn(() => Promise.resolve({ rows: [], rowCount: 0 })), release: jest.fn(), })), }; jest.mock('../db', () => mockPool); const { groupByHostname } = require('../routes/compliance'); // --- Generators --- /** Generate a date string in YYYY-MM-DD format (avoid toISOString on shrunk invalid dates) */ const arbDateString = fc.tuple( fc.integer({ min: 2020, max: 2030 }), fc.integer({ min: 1, max: 12 }), fc.integer({ min: 1, max: 28 }) ).map(([y, m, d]) => `${y}-${String(m).padStart(2, '0')}-${String(d).padStart(2, '0')}`); /** Generate a non-empty remediation plan string */ const arbRemediationPlan = fc.string({ minLength: 1, maxLength: 200 }).filter(s => s.trim().length > 0); /** Generate a hostname (alphanumeric with dashes, realistic) */ const arbHostname = fc.stringMatching(/^[A-Z][A-Z0-9\-]{2,20}$/); /** Generate a metric_id like "7.1.1" or "3.2" */ const arbMetricId = fc.tuple( fc.integer({ min: 1, max: 9 }), fc.integer({ min: 1, max: 9 }), fc.integer({ min: 1, max: 9 }) ).map(([a, b, c]) => `${a}.${b}.${c}`); /** * Generate a compliance row with non-null resolution_date and/or remediation_plan. * This is the bug condition: rows that have metadata which should be propagated. */ const arbComplianceRowWithMetadata = fc.record({ hostname: arbHostname, ip_address: fc.ipV4(), device_type: fc.constantFrom('Switch', 'Router', 'Firewall', 'Server'), team: fc.constantFrom('STEAM', 'ACCESS-ENG'), status: fc.constant('active'), metric_id: arbMetricId, metric_desc: fc.string({ minLength: 3, maxLength: 50 }), category: fc.constantFrom('Configuration', 'Patching', 'Access Control'), seen_count: fc.integer({ min: 1, max: 20 }), first_seen: arbDateString, last_seen: arbDateString, resolved_on: fc.constant(null), resolution_date: arbDateString, remediation_plan: arbRemediationPlan, }); // --- Property Test --- describe('Bug Condition Exploration: resolution_date and remediation_plan in groupByHostname()', () => { it('Property 1: groupByHostname() should propagate resolution_date from rows to device objects', () => { fc.assert( fc.property(arbComplianceRowWithMetadata, (row) => { const rows = [row]; const noteHostnames = new Set(); const devices = groupByHostname(rows, noteHostnames); // There should be exactly one device for the single hostname expect(devices).toHaveLength(1); const device = devices[0]; // BUG CONDITION: resolution_date should be propagated but is undefined on unfixed code expect(device.resolution_date).toBe(row.resolution_date); }), { numRuns: 100 } ); }); it('Property 2: groupByHostname() should propagate remediation_plan from rows to device objects', () => { fc.assert( fc.property(arbComplianceRowWithMetadata, (row) => { const rows = [row]; const noteHostnames = new Set(); const devices = groupByHostname(rows, noteHostnames); expect(devices).toHaveLength(1); const device = devices[0]; // BUG CONDITION: remediation_plan should be propagated but is undefined on unfixed code expect(device.remediation_plan).toBe(row.remediation_plan); }), { numRuns: 100 } ); }); it('Property 3: groupByHostname() should pick first non-null resolution_date across multiple rows for same hostname', () => { fc.assert( fc.property( arbHostname, fc.array(arbMetricId, { minLength: 2, maxLength: 5 }), arbDateString, (hostname, metricIds, resolutionDate) => { // Create multiple rows for the same hostname, first row has resolution_date const rows = metricIds.map((mid, idx) => ({ hostname, ip_address: '10.0.0.1', device_type: 'Switch', team: 'STEAM', status: 'active', metric_id: mid, metric_desc: `Metric ${mid}`, category: 'Configuration', seen_count: 1, first_seen: '2025-01-01', last_seen: '2025-06-01', resolved_on: null, resolution_date: idx === 0 ? resolutionDate : null, remediation_plan: null, })); const noteHostnames = new Set(); const devices = groupByHostname(rows, noteHostnames); expect(devices).toHaveLength(1); const device = devices[0]; // The first non-null resolution_date should be propagated expect(device.resolution_date).toBe(resolutionDate); } ), { numRuns: 100 } ); }); it('Property 4: groupByHostname() should pick first non-null remediation_plan across multiple rows for same hostname', () => { fc.assert( fc.property( arbHostname, fc.array(arbMetricId, { minLength: 2, maxLength: 5 }), arbRemediationPlan, (hostname, metricIds, plan) => { // Create multiple rows for the same hostname, first row has remediation_plan const rows = metricIds.map((mid, idx) => ({ hostname, ip_address: '10.0.0.1', device_type: 'Switch', team: 'STEAM', status: 'active', metric_id: mid, metric_desc: `Metric ${mid}`, category: 'Configuration', seen_count: 1, first_seen: '2025-01-01', last_seen: '2025-06-01', resolved_on: null, resolution_date: null, remediation_plan: idx === 0 ? plan : null, })); const noteHostnames = new Set(); const devices = groupByHostname(rows, noteHostnames); expect(devices).toHaveLength(1); const device = devices[0]; // The first non-null remediation_plan should be propagated expect(device.remediation_plan).toBe(plan); } ), { numRuns: 100 } ); }); });