chromogen
Version:
simple, interaction-driven Jest test generator for Recoil and React Hooks apps
218 lines (210 loc) • 11.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.testSetters = exports.testSelectors = exports.initializeSelectorFamilies = exports.initializeSelectors = exports.returnSelectorFamily = exports.returnAtomFamily = exports.returnReadable = exports.returnWriteable = exports.selectorFamilyHook = exports.atomFamilyHook = exports.readableHook = exports.writeableHook = exports.importRecoilFamily = exports.importRecoilState = exports.assertState = exports.initializeAtoms = void 0;
function initializeAtoms(state, current) {
return state.reduce((initializers, { key, value, previous }) => `${initializers}\t\t\tresult.current.set${key}(${JSON.stringify(current ? value : previous)});\n\n`, '');
}
exports.initializeAtoms = initializeAtoms;
function assertState(updates) {
return updates.reduce((assertions, { key, value }) => `${assertions}\t\texpect(result.current.${key}Value).toStrictEqual(${JSON.stringify(value)});\n\n`, '');
}
exports.assertState = assertState;
function importRecoilState(keyArray) {
return keyArray.reduce((fullStr, key) => `${fullStr}\t${key},\n`, '');
}
exports.importRecoilState = importRecoilState;
function importRecoilFamily(familyObj) {
return Object.keys(familyObj).reduce((importStr, familyName) => `${importStr}\t${familyName},\n`, '');
}
exports.importRecoilFamily = importRecoilFamily;
function writeableHook(keyArray) {
return keyArray.reduce((fullStr, key) => `${fullStr}\tconst [${key}Value, set${key}] = useRecoilState(${key});\n`, '');
}
exports.writeableHook = writeableHook;
function readableHook(keyArray) {
return keyArray.reduce((fullStr, key) => `${fullStr}\tconst ${key}Value = useRecoilValue(${key});\n`, '');
}
exports.readableHook = readableHook;
function atomFamilyHook(transactionArray) {
const len = transactionArray.length;
return len
? transactionArray[len - 1].atomFamilyState.reduce((str, atomState) => {
const { family, key } = atomState;
const params = key.substring(family.length + 2);
const scrubbedParams = params.replace(/[^\w\s]/gi, '');
const parsedParams = JSON.parse(params);
return `${str}\tconst [${`${family}__${scrubbedParams}__Value`}, ${`set${family}__${scrubbedParams}`}] = useRecoilState(${family}(${typeof parsedParams === 'string' ? `${params}` : `${parsedParams}`}));\n`;
}, '')
: '';
}
exports.atomFamilyHook = atomFamilyHook;
function selectorFamilyHook(selectorFamilyTracker, isSettable) {
return Object.entries(selectorFamilyTracker)
.filter((familyArr) => familyArr[1].isSettable === isSettable)
.reduce((str, familyArr) => {
const [familyName, { prevParams }] = familyArr;
return `${str}${[...prevParams].reduce((innerStr, param) => {
let scrubbedParams;
if (typeof param === 'string') {
scrubbedParams = param.replace(/[^\w\s]/gi, '');
}
return isSettable
? `${innerStr}\tconst [${`${familyName}__${scrubbedParams !== undefined ? scrubbedParams : param}__Value`}, ${`set${familyName}__${scrubbedParams !== undefined ? scrubbedParams : param}`}] = useRecoilState(${familyName}(${typeof param === 'string' ? `"${param}"` : `${JSON.parse(param)}`}));\n`
: `${innerStr}\tconst ${`${familyName}__${scrubbedParams !== undefined ? scrubbedParams : param}__Value`} = useRecoilValue(${familyName}(${typeof param === 'string' ? `"${param}"` : `${JSON.parse(param)}`}));\n`;
}, '')}`;
}, '');
}
exports.selectorFamilyHook = selectorFamilyHook;
function returnWriteable(keyArray) {
return keyArray.reduce((fullStr, key) => `${fullStr}\t\t${key}Value,\n\t\tset${key},\n`, '');
}
exports.returnWriteable = returnWriteable;
function returnReadable(keyArray) {
return keyArray.reduce((fullStr, key) => `${fullStr}\t\t${key}Value,\n`, '');
}
exports.returnReadable = returnReadable;
function returnAtomFamily(transactionArray) {
const len = transactionArray.length;
return len
? transactionArray[len - 1].atomFamilyState.reduce((value, atomState) => {
const { family, key } = atomState;
const params = key.substring(family.length + 2);
const scrubbedParams = params.replace(/[^\w\s]/gi, '');
return `${value}\t\t${`${family}__${scrubbedParams}__Value`},
\t\t${`set${family}__${scrubbedParams}`},\n`;
}, '')
: '';
}
exports.returnAtomFamily = returnAtomFamily;
function returnSelectorFamily(selectorFamilyTracker, isSettable) {
return Object.entries(selectorFamilyTracker)
.filter((familyArr) => familyArr[1].isSettable === isSettable)
.reduce((str, familyArr) => {
const [familyName, { prevParams }] = familyArr;
if (isSettable) {
return `${str}${[...prevParams].reduce((innerStr, param) => {
let scrubbedParams;
if (typeof param === 'string') {
scrubbedParams = param.replace(/[^\w\s]/gi, '');
}
return `${innerStr}\t\t${`${familyName}__${scrubbedParams !== undefined ? scrubbedParams : param}__Value`},
${`set${familyName}__${scrubbedParams !== undefined ? scrubbedParams : param}`},\n`;
}, '')}`;
}
return `${str}${[...prevParams].reduce((innerStr, param) => {
let scrubbedParams;
if (typeof param === 'string') {
scrubbedParams = param.replace(/[^\w\s]/gi, '');
}
return `${innerStr}\t\t${`${familyName}__${scrubbedParams !== undefined ? scrubbedParams : param}__Value`},\n`;
}, '')}`;
}, '');
}
exports.returnSelectorFamily = returnSelectorFamily;
function initializeSelectors(initialRender) {
return initialRender.reduce((fullStr, { key, value }) => `${fullStr}\tit('${key} should initialize correctly', () => {
\t\texpect(result.current.${key}Value).toStrictEqual(${JSON.stringify(value)});
\t});\n\n`, '');
}
exports.initializeSelectors = initializeSelectors;
function initializeSelectorFamilies(initialRenderFamilies) {
return initialRenderFamilies.reduce((initialTests, { key, params, value }) => {
let scrubbedParams;
if (typeof params === 'string') {
scrubbedParams = params.replace(/[^\w\s]/gi, '');
}
return `${initialTests}\tit('${key}__${scrubbedParams !== undefined ? scrubbedParams : JSON.stringify(params)} should initialize correctly', () => {
\t\texpect(result.current.${key}__${scrubbedParams !== undefined ? scrubbedParams : JSON.stringify(params)}__Value).toStrictEqual(${JSON.stringify(value)});
\t});\n`;
}, '');
}
exports.initializeSelectorFamilies = initializeSelectorFamilies;
function testSelectors(transactionArray) {
return transactionArray.reduce((selectorTests, { state, updates, atomFamilyState, familyUpdates }) => {
const allUpdatedAtoms = [
...state.filter(({ updated }) => updated),
...atomFamilyState.filter(({ updated }) => updated),
];
const allUpdatedSelectors = [...updates, ...familyUpdates];
const atomLen = allUpdatedAtoms.length;
const selectorLen = allUpdatedSelectors.length;
return atomLen !== 0 && selectorLen !== 0
? `${selectorTests}\tit('${selectorLen > 1
? allUpdatedSelectors.reduce((list, selectorState, i) => {
const { key } = selectorState;
const isLastElement = i === selectorLen - 1;
if ('params' in selectorState) {
let scrubbedParams;
if (typeof selectorState.params === 'string') {
scrubbedParams = selectorState.params.replace(/[^\w\s]/gi, '');
}
return `${list}${isLastElement ? 'and ' : ''}${key}__${scrubbedParams !== undefined ? scrubbedParams : selectorState.params}${isLastElement ? '' : ', '}`;
}
return `${list}${isLastElement ? 'and ' : ''}${key}${isLastElement ? '' : ', '}`;
}, '')
: `${allUpdatedSelectors[0].params !== undefined
? `${allUpdatedSelectors[0].key}__${typeof allUpdatedSelectors[0].params === 'string'
? allUpdatedSelectors[0].params.replace(/[^\w\s]/gi, '')
: allUpdatedSelectors[0].params}`
: allUpdatedSelectors[0].key}`} should properly derive state when ${atomLen > 1
? allUpdatedAtoms.reduce((list, { key }, i) => {
const isLastElement = i === atomLen - 1;
const scrubbedKey = key.replace(/[^\w\s]/gi, '');
return `${list}${isLastElement ? 'and ' : ''}${scrubbedKey}${isLastElement ? ' update' : ', '}`;
}, '')
: `${allUpdatedAtoms[0].key.replace(/[^\w\s]/gi, '')} updates`}', () => {
\t\tconst { result } = renderRecoilHook(useStoreHook);
\t\tact(() => {
${state.reduce((initializers, { key, value }) => `${initializers}\t\t\tresult.current.set${key}(${JSON.stringify(value)});\n\n`, '')}
${atomFamilyState.reduce((initializers, { key, value }) => {
const scrubbedKey = key.replace(/[^\w\s]/gi, '');
return `${initializers}\t\t\tresult.current.set${scrubbedKey}(${JSON.stringify(value)});\n\n`;
}, '')}
\t\t});
${selectorLen !== 0
? allUpdatedSelectors.reduce((assertions, selectorState) => {
const { key, value } = selectorState;
let scrubbedParams;
if (typeof selectorState.params === 'string') {
scrubbedParams = selectorState.params.replace(/[^\w\s]/gi, '');
}
if (selectorState.params !== undefined)
return `${assertions}\t\texpect(result.current.${key}__${scrubbedParams !== undefined ? scrubbedParams : selectorState.params}__Value).toStrictEqual(${JSON.stringify(value)});\n\n`;
return `${assertions}\t\texpect(result.current.${key}Value).toStrictEqual(${JSON.stringify(value)});\n\n`;
}, '')
: ''}\t});\n\n`
: selectorTests;
}, '');
}
exports.testSelectors = testSelectors;
function testSetters(setTransactionArray) {
return setTransactionArray.reduce((setterTests, { state, setter }) => {
const updatedAtoms = state.filter(({ updated }) => updated);
if (setter) {
const { params } = setter;
let scrubbedParams;
if (typeof params === 'string') {
scrubbedParams = params.replace(/[^\w\s]/gi, '');
}
return params !== undefined
? `${setterTests}\tit('${setter.key}__${scrubbedParams !== undefined ? scrubbedParams : JSON.stringify(params)} should properly set state', () => {
\t\tconst { result } = renderRecoilHook(useStoreHook);
\t\tact(() => {
${initializeAtoms(state, false)}\t\t});
\t\tact(() => {
\t\t\tresult.current.set${setter.key}__${scrubbedParams !== undefined ? scrubbedParams : JSON.stringify(params)}(${JSON.stringify(setter.newValue)});
\t\t});
${assertState(updatedAtoms)}\t});\n\n`
: `${setterTests}\tit('${setter.key} should properly set state', () => {
\t\tconst { result } = renderRecoilHook(useStoreHook);
\t\tact(() => {
${initializeAtoms(state, false)}\t\t});
\t\tact(() => {
\t\t\tresult.current.set${setter.key}(${JSON.stringify(setter.newValue)});
\t\t});
${assertState(updatedAtoms)}\t});\n\n`;
}
return setterTests;
}, '');
}
exports.testSetters = testSetters;