feat(curriculum): add spy helper (#42566)
* Added initial version of spy helper * add missing backslashes * update to check for line start * change __fixtures file extensions to .ts from .tsx * add to exports and add documentation * add tests * update event.preventDefault() test
This commit is contained in:
@ -31,11 +31,40 @@ function nonMutatingPush(original, newItem) {
|
||||
return original.push(newItem);
|
||||
}`;
|
||||
|
||||
const jsCodeWithNoCall = `function myFunc() {
|
||||
return Math.random();
|
||||
}
|
||||
`;
|
||||
|
||||
const jsCodeWithNoArgCall = `function myFunc() {
|
||||
return Math.random();
|
||||
}
|
||||
myFunc();
|
||||
`;
|
||||
|
||||
const jsCodeWithArgCall = `function myFunc() {
|
||||
return Math.random();
|
||||
}
|
||||
myFunc('this shouldn't be here');
|
||||
`;
|
||||
|
||||
const jsCodeWithCommentedCall = `function myFunc() {
|
||||
return Math.random();
|
||||
}
|
||||
/*
|
||||
myFunc();
|
||||
*/
|
||||
`;
|
||||
|
||||
const testValues = {
|
||||
jsCodeWithSingleAndMultLineComments,
|
||||
jsCodeWithSingleAndMultLineCommentsRemoved,
|
||||
jsCodeWithUrl,
|
||||
jsCodeWithUrlUnchanged
|
||||
jsCodeWithUrlUnchanged,
|
||||
jsCodeWithNoCall,
|
||||
jsCodeWithNoArgCall,
|
||||
jsCodeWithArgCall,
|
||||
jsCodeWithCommentedCall
|
||||
};
|
||||
|
||||
export default testValues;
|
@ -15,7 +15,11 @@ const {
|
||||
jsCodeWithSingleAndMultLineComments,
|
||||
jsCodeWithSingleAndMultLineCommentsRemoved,
|
||||
jsCodeWithUrl,
|
||||
jsCodeWithUrlUnchanged
|
||||
jsCodeWithUrlUnchanged,
|
||||
jsCodeWithNoCall,
|
||||
jsCodeWithNoArgCall,
|
||||
jsCodeWithArgCall,
|
||||
jsCodeWithCommentedCall
|
||||
} = jsTestValues;
|
||||
|
||||
describe('removeWhiteSpace', () => {
|
||||
@ -83,3 +87,22 @@ describe('removeHtmlComments', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isCalledWithNoArgs', () => {
|
||||
const { isCalledWithNoArgs } = __testHelpers;
|
||||
it('returns a boolean', () => {
|
||||
expect(typeof isCalledWithNoArgs('foo', 'bar')).toBe('boolean');
|
||||
});
|
||||
it('returns false when not called', () => {
|
||||
expect(isCalledWithNoArgs('myFunc', jsCodeWithNoCall)).toBe(false);
|
||||
});
|
||||
it('returns true for a call with no arguments', () => {
|
||||
expect(isCalledWithNoArgs('myFunc', jsCodeWithNoArgCall)).toBe(true);
|
||||
});
|
||||
it('returns false for a call with arguments', () => {
|
||||
expect(isCalledWithNoArgs('myFunc', jsCodeWithArgCall)).toBe(false);
|
||||
});
|
||||
it('returns false for a commented out call', () => {
|
||||
expect(isCalledWithNoArgs('myFunc', jsCodeWithCommentedCall)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
@ -21,10 +21,37 @@ const removeWhiteSpace = (str = ''): string => {
|
||||
return str.replace(/\s/g, '');
|
||||
};
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
|
||||
function escapeRegExp(exp: string): string {
|
||||
return exp.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
}
|
||||
|
||||
/*
|
||||
This helper checks if a function/method is called with no arguments.
|
||||
|
||||
Because Safari does not support lookbehinds (as of writing this on
|
||||
July 14 2021), avoiding false matches on function definitions is done by
|
||||
checking that only whitespace characters preceed the calling name on the line
|
||||
it is found on. That makes this helper incompatible with
|
||||
removeWhiteSpace() above, which removes all whitespace characters.
|
||||
*/
|
||||
function isCalledWithNoArgs(
|
||||
calledFuncName: string,
|
||||
callingCode: string
|
||||
): boolean {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
const noCommentsCallingCode = strip(callingCode) as string;
|
||||
const funcExp = `^\\s*?${escapeRegExp(calledFuncName)}\\(\\s*?\\)`;
|
||||
const matches = new RegExp(funcExp, 'gm').exec(noCommentsCallingCode) ?? [];
|
||||
|
||||
return !!matches.length;
|
||||
}
|
||||
|
||||
const curriculumHelpers = {
|
||||
removeHtmlComments,
|
||||
removeCssComments,
|
||||
removeWhiteSpace,
|
||||
isCalledWithNoArgs,
|
||||
CSSHelp
|
||||
};
|
||||
|
||||
|
@ -101,19 +101,11 @@ Submitting the form should run `handleSubmit` which should set the `submit` prop
|
||||
`handleSubmit` should call `event.preventDefault`
|
||||
|
||||
```js
|
||||
const handleSubmit = MyForm.prototype.handleSubmit.toString();
|
||||
const allMatches = handleSubmit.match(/\bevent\.preventDefault\(\s*?\)/g) ?? [];
|
||||
const blockCommented = handleSubmit.match(
|
||||
/\/\*.*?\bevent\.preventDefault\(\s*?\).*?\*\//gs
|
||||
);
|
||||
const lineCommented = handleSubmit.match(
|
||||
/\/\/.*?\bevent\.preventDefault\(\s*?\)/g
|
||||
);
|
||||
const commentedMatches = [...(blockCommented ?? []), ...(lineCommented ?? [])];
|
||||
|
||||
assert(
|
||||
// At least one event.preventDefault() call exists and is not commented out
|
||||
allMatches.length > commentedMatches.length
|
||||
__helpers.isCalledWithNoArgs(
|
||||
'event.preventDefault',
|
||||
MyForm.prototype.handleSubmit.toString()
|
||||
)
|
||||
);
|
||||
```
|
||||
|
||||
|
Reference in New Issue
Block a user