-
Notifications
You must be signed in to change notification settings - Fork 29.7k
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
lib: allow mocking primordials with --expose-internals #40733
lib: allow mocking primordials with --expose-internals #40733
Conversation
Initially I thought to optionally do this only if I'm not sure how to test this (similar PRs did not contain tests) but I can add a test with |
Ooh, this would be super useful for Node > 15.7 where the @sinonjs/fake-timers implementations used by Jest and Sinon is not able to do touch the Date implementation used by Node internals like |
I think the real question here is what value we get out of always reading the primordial |
--expose-internals is not a public API. I'm pretty worried that popular libraries think about using it |
As they say about API design; make the common things easy and the difficult things possible. Currently, a certain use case is no longer possible, and this would make it possible for the ones that cared for it. |
I'm not saying we shouldn't make it possible. I'm saying that making it possible through |
Note that mutating primordials is not necessary to achieve what is being discussed in the other issue for someone daring enough to use require('internal/http').utcDate = function utcDate() {
return 'custom string';
};
const http = require('http');
server = http.createServer((req, res) => {
req.on('data', () => void null);
req.on('end', () => {
res.writeHead(200);
res.end();
});
});
server.listen(8008, () => {
const opts = {
hostname: 'localhost',
method: 'GET',
path: '/',
port: 8008,
family: 4,
};
const req = http.request(opts, (res) => {
res.on('data', () => void null);
res.on('end', () => {
console.log(res.headers.date === 'custom string');
});
});
req.end();
}); |
What if we just mock .utcDate if --expose-internals is passed? |
@benjamingr Yeah, I saw that was possible to begin with, but it would not allow us to fully control Date and all that jazz. But then maybe they need to employ DI or something to avoid the |
I suggest we close this PR and instead open a feature request issue with a description of what API you would like to have (with the goal of not relying on monkey-patching to change the behavior of Node internals). |
I don't think discussion has died down - but I am not set on this particular solution. The ask is to be able to mock dates (internally) - one (easy) way to achieve this is to be able to override primordials.Date - this is for testing only basically. |
This assumes that Node.js uses the |
It does, and in general mocking libraries like fake-timers work under the assumption that things like this can/may break. It also "breaks" whenever node adds additional properties to timers and the sinon code would have to be adjusted in those cases. We can choose to just not enable that use case (it's not a timer, sinon only mocks a few properties etc) and allow passing a "start time" or similar to Node.js or suggest the user mocks system time instead for example? |
@benjamingr Did an alternative suggestion come up? |
@fatso83 no, this just stalled and people haven't asked a lot for this before and sinon never made the guarantee to allow mocking node internal usage of Date (which may be replaced with C++ anyway code in which case it won't help). I can work on a flag for Node.js that allows setting the data on http headers but it's not a common ask |
This pull request allows swapping primordials when
--expose-interals
is passed. This is required for libraries like SinonJS to mockDate
.I am not sure why primordials was frozen in the first place since the object is not user-accessible as far as I'm aware.
cc @aduh95 @fatso83
Refs: sinonjs/fake-timers#344
Refs: #36872