/** * Property-Based Tests: Config Wizard Frontend Build Skip Logic * * Feature: config-wizard * * Tests the shouldSkipFrontendBuild function from `configure.js`. * * Validates: Requirements 14.4, 14.5 */ const fc = require('fast-check'); const { shouldSkipFrontendBuild } = require('../../configure.js'); // ───────────────────────────────────────────────────────────────────────────── // Helpers // ───────────────────────────────────────────────────────────────────────────── /** Generate a REACT_APP_* key name */ const reactAppKeyArb = fc.stringMatching(/^REACT_APP_[A-Z][A-Z0-9_]{0,15}$/) .filter(k => k.length > 10); /** Generate a non-empty env value */ const envValueArb = fc.string({ minLength: 1, maxLength: 50 }) .filter(s => s.trim().length > 0 && !s.includes('\n')); // ───────────────────────────────────────────────────────────────────────────── // Property 19: Frontend build skip determination // ───────────────────────────────────────────────────────────────────────────── describe('Property 19: Frontend build skip determination', () => { /** * **Validates: Requirements 14.4, 14.5** * * shouldSkipFrontendBuild returns true iff all REACT_APP_* keys have identical * values in old and new maps and old map is non-null. */ test('when old map is null, always returns false', () => { fc.assert( fc.property( fc.array(fc.tuple(reactAppKeyArb, envValueArb), { minLength: 1, maxLength: 5 }), (entries) => { const newMap = new Map(entries); return shouldSkipFrontendBuild(null, newMap) === false; } ), { numRuns: 100 } ); }); test('when old and new have identical REACT_APP_* values, returns true', () => { fc.assert( fc.property( fc.array(fc.tuple(reactAppKeyArb, envValueArb), { minLength: 1, maxLength: 5 }), (entries) => { // Deduplicate keys by using a Map const deduped = [...new Map(entries).entries()]; const oldMap = new Map(deduped); const newMap = new Map(deduped); return shouldSkipFrontendBuild(oldMap, newMap) === true; } ), { numRuns: 100 } ); }); test('when any REACT_APP_* value differs, returns false', () => { fc.assert( fc.property( fc.array(fc.tuple(reactAppKeyArb, envValueArb), { minLength: 1, maxLength: 5 }), envValueArb, (entries, differentValue) => { // Deduplicate keys const deduped = [...new Map(entries).entries()]; if (deduped.length === 0) return true; // skip trivial case const oldMap = new Map(deduped); const newMap = new Map(deduped); // Change one value in the new map to be different const keyToChange = deduped[0][0]; const originalValue = deduped[0][1]; // Ensure the new value is actually different const newValue = differentValue === originalValue ? differentValue + '_changed' : differentValue; newMap.set(keyToChange, newValue); return shouldSkipFrontendBuild(oldMap, newMap) === false; } ), { numRuns: 100 } ); }); test('when new map has additional REACT_APP_* keys not in old, returns false', () => { fc.assert( fc.property( fc.array(fc.tuple(reactAppKeyArb, envValueArb), { minLength: 1, maxLength: 3 }), reactAppKeyArb, envValueArb, (entries, extraKey, extraValue) => { // Deduplicate keys const deduped = [...new Map(entries).entries()]; const oldMap = new Map(deduped); const newMap = new Map(deduped); // Add an extra key to new that doesn't exist in old // Ensure the extra key is not already in the map const uniqueExtraKey = deduped.some(([k]) => k === extraKey) ? extraKey + '_EXTRA' : extraKey; newMap.set(uniqueExtraKey, extraValue); return shouldSkipFrontendBuild(oldMap, newMap) === false; } ), { numRuns: 100 } ); }); });