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: Add error handling for nonexistent file case with --file option #5086
base: master
Are you sure you want to change the base?
Conversation
- added error handling when using the --file flag to do it the way --require does - added a test to assert that we throw the same type of error
- require.resolve() by Node.js follows a Node.js module resolution algo which includes checking if the resolved path actually exists on the file system.
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.
Cool! 😎
Requesting changes on adding a bit more testing. But also let's talk about the direction a bit - I feel nervous adding in process.exit
/throw
s deep within code. Thanks for sending!
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.
[Testing] Since the implementation uses require.resolve
, I think it'd be good to make sure there is at least one test each for CJS and ESM. Using module-specific APIs such as require
or import
scares me, even for ones that should always work... Thoughts?
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.
I thought to use require.resolve
here because the original stack trace showed require
being used. Alternatively, I could use fs.existsSync
like how our --require
flag does it. If we do go down the route of using require.resolve
I agree with adding one test for each CJS and ESM.
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.
I removed the use of require.resolve
and instead opted to use the path
and fs
modules to check for file existence instead.
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.
Wait, require.resolve
is a good thing to use though! If someone is in CJS mode and passes path/to/place
they'll expect that both path/to/place.js
and path/to/place/index.js
would work. Not to mention .js
vs .cjs
shenanigans. Right?
I just meant to ask for more testing, not a refactor.
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.
Oops I misunderstood, yeah that makes sense. I'll add the tests and revert back to using require.resolve
.
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.
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.
That looks pretty good to me!
Though, would it be a lot of work to reduce it to two lines? That screenshot has two saying nothing found and one mentioning the absolutePath. I wonder if it would be cleaner for users to reduce down to, say...
No test file(s) found with the given pattern(s), exiting with code 1
absolutePath: /home/ka9/dev/mocha/nonexistent.js
...if that's a lot of work to reorder to, then I'd say let's treat that as a followup issue and not a blocker here.
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.
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.
Beautiful! I'm happy with that. Nice 🔥
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.
Pushed changes and added tests for esm + cjs!
lib/cli/collect-files.js
Outdated
`${symbols.warning} Warning: Cannot find test file "${file}" at the path "${fileAbsolutePath}"` | ||
); | ||
console.warn(`${warningMessage}\n`); | ||
process.exit(1); |
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.
[Refactor] I don't love having a process.exit
deep within code. n/no-process-exit
has good reasoning around it.
It's also not really a "warning" yellow if the whole thing exits. At that point it's an error (red).
I think a more future-facing, approach would be either:
- (less work, but still partially flawed) have this function throw a special error that any higher-up handler(s) know how to log nicely
- (more work, but more understandable long-term) have this function return an object explaining its results, and have higher-up handler(s) work nicely with it
I haven't looked deeply enough to know whether either or both is feasible. Before we go into a whole deep dive, what do you think about this direction?
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.
Good to learn about the no-process-exit
, thanks! I think the latter where we return an object and having the higher-up handler(s) deal with it sounds like the approach here. The error wasn't handled in run-helpers
so maybe we can add something so that bubbles up to run.js
like the other methods?
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.
Yeah that approach sounds like a good one to try!
@@ -30,7 +32,7 @@ module.exports = ({ | |||
sort, | |||
spec | |||
} = {}) => { | |||
const unmatched = []; | |||
const unmatchedSpecFiles = []; |
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.
Renamed variable for semantic clarity
🔎 Overview
Fixes #4047
--file
option by resolving the argument to an absolute path and check for its existence. We now log a warning and exit if the file does not exist.--require
bubble up to the middleware inlib/cli/run.js
. See here. This specific error occurs inlib/cli/run-helpers.js
in thesingleRun
method when we load files asynchronously. Since we were lacking error handling there, the errors appeared the way they previously did before these changes.