122 lines
4.6 KiB
JavaScript
122 lines
4.6 KiB
JavaScript
|
|
/**
|
||
|
|
* 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 }
|
||
|
|
);
|
||
|
|
});
|
||
|
|
});
|