-
Notifications
You must be signed in to change notification settings - Fork 236
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(expect-expect): support glob patterns for assertFunctionNames (#471) #509
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a massive fan of having globbing b/c of the extra dependency + people might start expecting it to work everywhere, which'd open up a can of worms for easy footguns, but that's just me being overly paranoid.
Cheers for the PR - lets see what happens :D
(I'll merge later in the day w/ a few other things, so they can be released together)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❤️This is wonderful.
micromatch is a pretty slim dependency, so overall the plugin still says pretty barebones.
If you think it would make more sense to create a simple utility function to match wildcards instead of using micromatch, then I could definitely look into that as well. Ultimately, we don't really need full blown glob pattern matching for this use case. Our import aren't path names, so any functionality related to glob patterns for file paths etc, are not needed. Imho the only two expression that seem useful are Example of request.get().expect('foo')
request.post().expect('foo')
assertionFunctionNames = ["request.*.expect"] Example of request.get().foo().bar().alpha().whatever().expect('foo')
assertionFunctionNames = ["request.**.expect"] Both expressions could be easily implemented with a |
I'd be keen to what you could come up with! I'm not against using micromatch - my dependency point was a weak one; it's just more about avoiding a new dependency is nice, and globbing tends to be the sort of thing people expect to work everywhere, and so as soon as you add it it has the potential to open a whole can of worms as people assume it's everywhere. While my main concerns are valid concerns, that's relative to the actual size of the issue, which is very small 🙂 In saying that I'd be very interested in seeing what you could come up with if you want to have a play around! (I'm going to merge this in the meantime, since we can remove the dependency later) |
🎉 This PR is included in version 23.5.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
@G-Rath See below: var assert = require('assert');
function starRegex(pattern: string) {
return RegExp(
pattern
.split('.')
.map(x => {
if (x === '**') return '[a-zA-Z\\.]*';
if (x.includes('**'))
throw `Double star wildcards can only occur between dots as in request.**.expect`;
return x.replace('*', '[a-zA-Z]*');
})
.join('\\.'),
);
}
export function starMatch(string: string, pattern: string): boolean;
export function starMatch(string: string, pattern: string[]): boolean;
export function starMatch(string: string, pattern: string | string[]): boolean {
const patterns = Array.isArray(pattern) ? pattern : [pattern];
for (const p of patterns) {
if (starRegex(p).test(string)) return true;
}
return false;
}
const test: Array<[string, string, boolean]> = [
['request.get.post.expect', 'request.**.expect', true],
['request.get.post.expect', 'request.*.expect', false],
['request.get.expect', 'request.*.expect', true],
['request.get.expect', 'request.**.expect', true],
['request.get.expectSomething', 'request.**.expect*', true],
];
for (const [string, pattern, expectedResult] of test) {
const result = starMatch(string, pattern);
console.log({
string,
pattern,
regex: starRegex(pattern),
result,
});
assert(result === expectedResult);
} Outputs: [
{
"string": "request.get.post.expect",
"pattern": "request.**.expect",
"regex": /request\.[a-zA-Z\.]*\.expect/,
"result": true
},
{
"string": "request.get.post.expect",
"pattern": "request.*.expect",
"regex": /request\.[a-zA-Z]*\.expect/,
"result": false
},
{
"string": "request.get.expect",
"pattern": "request.*.expect",
"regex": /request\.[a-zA-Z]*\.expect/,
"result": true
},
{
"string": "request.get.expect",
"pattern": "request.**.expect",
"regex": /request\.[a-zA-Z\.]*\.expect/,
"result": true
},
{
"string": "request.get.expectSomething",
"pattern": "request.**.expect*",
"regex": /request\.[a-zA-Z\.]*\.expect[a-zA-Z]*/,
"result": true
}
]
Should I create a PR with this change? I'm happy with this approach or using micromatch :) |
@folke go wild! Even if it doesn't get merged, I'm keen to check it out, as it looks impressive :D |
@G-Rath should I add this to rules/utils.ts? Or in a seperate file like rules/starmatch.ts? |
utils.ts seems to be the best location. Function is pretty small: /**
* Checks if node names returned by getNodeName matches any of the given star patterns
* Pattern examples:
* request.*.expect
* request.**.expect
* request.**.expect*
*/
export function nodeNameMatch(nodeName: string, pattern: string): boolean;
export function nodeNameMatch(
nodeName: string,
pattern: readonly string[],
): boolean;
export function nodeNameMatch(
nodeName: string,
pattern: string | readonly string[],
): boolean {
const patterns: string[] = Array.isArray(pattern) ? pattern : [pattern];
for (const p of patterns) {
if (
new RegExp(
`^${p
.split('.')
.map(x => {
if (x === '**') return '[a-zA-Z\\.]*';
if (x.includes('**'))
throw `Double star wildcards can only occur between dots as in request.**.expect`;
return x.replace('*', '[a-zA-Z]*');
})
.join('\\.')}$`,
).test(nodeName)
)
return true;
}
return false;
} |
Added support for glob patterns to specify assertion function names like
request.*.expect
(seemicromatch for syntax)
Implements #471
Examples of correct code for working with the HTTP assertions library
SuperTest with the
{ "assertFunctionNames": ["expect", "request.*.expect"] }
option: