-
-
Notifications
You must be signed in to change notification settings - Fork 6.6k
feat: add unstable_allowJsdomMutations option (#15556)
#15652
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
Conversation
✅ Deploy Preview for jestjs ready!Built without sensitive environment variables
To edit notification comments on pull requests, go to your Netlify project configuration. |
be57ac9 to
ac4012c
Compare
ac4012c to
be05c87
Compare
|
I have a bunch of jest
.spyOn(window, 'location', 'get')
.mockImplementation(
() => new URL('https://game.com') as unknown as Location
);or things like this (global as any).location = new URL(
'https://example.com/?use_social_login=true'
);const expectedRedirectUrl = async (
client: AuthorizeResponse,
response_type: 'token' | 'code',
expectedUrl: string
) => {
/**
* Given there is an active session
* And the client is already authorized
*/
const store = setup({ client, response_type });
/**
* Then, when redirection occurs
*/
store.dispatch(redirect());
/**
* I expect the redirect url to be a well-formed one
*/
await waitFor(() => {
expect(window.location.assign).toHaveBeenCalledWith(expectedUrl);
});
};
const windowLocation = window.location;
describe('modules/redirect', () => {
afterAll(() => {
window.location = windowLocation;
});
beforeEach(() => {
// @ts-ignore - Need to delete property first in test environment
delete window.location;
window.location = {
...windowLocation,
assign: jest.fn()
} as Location;
});
const redirect_uri_1 = 'https://client-site.com/';
const redirect_uri_2 = 'https://client-site.com/?page=1';
const expectedToken = '682a5-c9bb-4da6-9da7-7d93a9540306';
const expectedCode = '123xyz';
const testCases: RedirectType[] = [
{
description:
'should redirect to a well-formed URL with token (no qs params)',
client: mockAuthorizedClient({
redirect_uri: redirect_uri_1,
code: undefined,
token: expectedToken
}),
response_type: 'token',
expectedUrl: `${redirect_uri_1}#token=${expectedToken}`
},
{
description:
'should redirect to a well-formed URL with code (no qs params)',
client: mockAuthorizedClient({
redirect_uri: redirect_uri_1,
code: expectedCode
}),
response_type: 'code',
expectedUrl: `${redirect_uri_1}?code=${expectedCode}`
},
{
description:
'should redirect to a well-formed URL with token (existing qs params)',
client: mockAuthorizedClient({
redirect_uri: redirect_uri_2,
code: undefined,
token: expectedToken
}),
response_type: 'token',
expectedUrl: `${redirect_uri_2}#token=${expectedToken}`
},
{
description:
'should redirect to a well-formed URL with code (existing qs params)',
client: mockAuthorizedClient({
redirect_uri: redirect_uri_2,
code: expectedCode
}),
response_type: 'code',
expectedUrl: `${redirect_uri_2}&code=${expectedCode}`
}
];
it.each(testCases)(
'should redirect to a well-formed URL with $description',
async ({ client, response_type, expectedUrl }) => {
await expectedRedirectUrl(client, response_type, expectedUrl);
}
);
it('should redirect to the exact `redirect_uri` in Zendesk login flow', async () => {
const store = setup({ isZendeskLoginFlow: true });
const zendeskRedirectUri = redirect_uri_2;
/**
* Given there is an active session
* And no `client_id` or `response_type` in the qs params
* Then, when redirection occurs
*/
store.dispatch(redirect({ redirect_uri: zendeskRedirectUri }));
/**
* I expect the redirect url to match whatever is returned
* in the `return_to` property in the `/api/v1/zendesk/token`
* endpoint's response payload
*/
await waitFor(() =>
expect(window.location.assign).toHaveBeenCalledWith(zendeskRedirectUri)
);
});
});/**
* Checks if specified url has the same top domain as current
* window hostname and hence can be considered safe for redirect.
*
* In case of a complete match for url origin `false` is return and
* the url not considered a subdomain of the current window hostname.
*
* @param url - Url to check
* @returns `true` if subdomain of current hostname top-level domain, `false`
* otherwise
*/
export function isSubdomainRedirect(url: URL) {
if (window.location.origin === url.origin) {
return false;
}
const [topDomain, secondLevelDomain] = url.hostname.split('.').reverse();
const [allowedTopDomain, allowedSecondLevelDomain] = window.location.hostname
.split('.')
.reverse();
return (
topDomain === allowedTopDomain &&
secondLevelDomain === allowedSecondLevelDomain
);
}
export default isSubdomainRedirect; |
|
My main concern is that this is going to massively impact performance. |
|
@cpojer yes, I haven't tested the performance yet, but I agree with you. So I made it a separate option. It's just a backup solution in case nothing better comes along. |
|
I really appreciate the work on this, but I really don't think this is the way forward. I can see how somebody might provide their own version of a jsdom environment for Jest with this that they maintain and publish, but it should probably not be part of Jest Core. I'll write about how to work around the location.href situation. |
|
This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Fixed jsdom overriding problems from #15556
Guys, please share some examples with overriding JSDOM properties. I'll add test cases for it.