-
Notifications
You must be signed in to change notification settings - Fork 251
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(core): use user configured npm registry #4937
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.
Thanks for the PR. I have some remarks.
@@ -65,7 +65,7 @@ export class NpmClient { | |||
const response = await this.innerNpmClient.get<NpmSearchResult>(path); | |||
return handleResult(path)(response); | |||
} catch (err) { | |||
this.log.error(`Unable to reach 'https://registry.npmjs.com' (for query ${path}). Please check your internet connection.`, errorToString(err)); | |||
this.log.error(`Unable to reach '${getRegistry()}' (for query ${path}). Please check your internet connection.`, errorToString(err)); |
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.
Instead of using getRegistry
here, you can simply let the npm registry location be injected, see previous comment about dependency injection
const NPM_REGISTRY = 'https://registry.npmjs.com'; | ||
let currentRegistry: string | undefined; | ||
|
||
function getRegistry(): string { |
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.
Can you add unit tests for this function? Also, move it to a separate file.
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 am having some issues with the last case where I would need to use the execaSync
, I have a few ways I can test this:
Mocking:
Would result in not actually testing the functionality of it, wouldn't do anything.
Editing the npm config
:
This may cause a problem if I do beforeEach
and afterEach
to edit the npm config
there are multiple things that could happen:
- If the command fails it can ruin the person's npm configuration.
- If the person aborts mid test it could ruin the person's npm configuration.
Seems like too be too many points of failure.
I have no idea how to test this or if I even should, as I gave a default value if it fails and warned them.
I would wait for your input.
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.
Ah yes, great question. Please add 2 more unit tests, 1 for the happy flow and one for the alternate flow using mocking of execaSync
. You are right that we won't test the actual command npm config get registry
, but I would expect that to work as documented. However, if you want to add a test for that, you are welcome to add an integration test (see test/integration
).
To mock out execSync
, we can't simply use sinon.stub(execa, 'execSync')
, since it isn't a method that's being called, but rather a function that is directly exported. To mock it away, we can use the same approach as we did for execaCommand
, see the coreTokens.execa
for an example. So you can add a coreTokens.execaSync
token.
currentRegistry = 'https://registry.npmjs.com'; | ||
} else { | ||
// Using global as when trying to get the registry inside npm workspace it would fail | ||
const registry = execaSync('npm', ['config', 'get', '--global', 'registry'], { |
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.
Please also add a try ... catch
here, because a lot of stuff can go wrong here. If an error occurs we should log a warning (using the logger that you can inject) and use the default value,
timeout: 20000, | ||
}); | ||
|
||
currentRegistry = registry.stdout; |
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.
Should the result be trim
med here?
currentRegistry = registry.stdout; | |
currentRegistry = registry.stdout.trim(); |
move getRegistry to a different file, wrap `execaSync` in try-catch, and use dependency injection, and changed tests to run
@nicojs I've applied the changes. |
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.
Thanks for fixing my review comments. I have some final remarks regarding the tests.
Note: if you need help to create a mock for execSync
, feel free to ask, I would be happy to help out.
|
||
process.env.npm_command = 'value'; | ||
|
||
const registry = getRegistry(log4js.getLogger()); |
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.
Please use testInjector.logger
. It contains a logger mock that is ready to be used. You can verify log messages on it using sinon.asserts.calledOnceWithExactly(testInjector.logger.warn, '...');
|
||
process.env.npm_command = 'value'; | ||
|
||
const registry = getRegistry(log4js.getLogger()); |
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.
Same here
@@ -55,7 +56,8 @@ describe(StrykerInitializer.name, () => { | |||
syncBuiltinESMExports(); | |||
sut = testInjector.injector | |||
.provideValue(initializerTokens.out, out as unknown as typeof console.log) | |||
.provideValue(initializerTokens.restClientNpm, npmRestClient) | |||
.provideFactory(initializerTokens.npmRegistry, getRegistry) | |||
.provideFactory(initializerTokens.restClientNpm, createNpmRegistryClient) |
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.
Since this is a unit test for the StrykerInitializer
, I wouldn't expect the "real" getRegistry
to be used here. Instead, you can keep using provideValue
here for the npmRestClient
sinon mock here.
Indeed, the tests are failing, see https://github.com/stryker-mutator/stryker-js/actions/runs/10341544430/job/28626286827?pr=4937
@nicojs I've applied the changes you've asked for, would love to get them reviewed. |
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.
Thanks a lot for implementing the requested changes! I've got small remarks about the use of test hooks and assertions. Other than that this looks good.
let oldNpmConfigRegistry: string | undefined; | ||
let oldNpmCommand: string | undefined; | ||
|
||
before(() => { |
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 should be beforeEach
instead of before
(or change afterEach
to be after
)
sinon.assert.callCount(execaCommandSyncMock, 1); | ||
sinon.assert.calledWith(execaCommandSyncMock, 'npm config get --global registry', { | ||
stdout: 'pipe', | ||
timeout: 20000, | ||
}); |
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.
Can be simplified to calledOnceWithExactly
sinon.assert.callCount(execaCommandSyncMock, 1); | ||
sinon.assert.calledWith(execaCommandSyncMock, 'npm config get --global registry', { | ||
stdout: 'pipe', | ||
timeout: 20000, | ||
}); |
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.
Same here
Thank you for the remarks, I've applied them. |
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.
LGTM
Fix:
npm init stryker
use default npm registry instead of the one configured in npm config #4936