Skip to content

Commit 87a0553

Browse files
committed
[v8] Update Dependencies (#1368)
This pull request primarily updates dependencies and refactors test suites to improve consistency and compatibility with newer libraries. The most significant changes are grouped below: **Dependency Upgrades:** * Updated several dependencies in `package.json`, including major upgrades to `jose`, `eslint`, `jest`, `babel-jest`, `miniflare`, `nock`, `supertest`, `ts-jest`, `tsx`, `typescript`, and related type packages. These upgrades ensure compatibility with the latest features and security patches. [[1]](diffhunk://#diff-7ae45ad102eab3b6d7e7896acd08c427a9b25b346470d7bc6507b6481575d519L44-R44) [[2]](diffhunk://#diff-7ae45ad102eab3b6d7e7896acd08c427a9b25b346470d7bc6507b6481575d519L53-R78) **Testing Consistency & Modernization:** * Replaced all usages of `.toThrowError` in Jest test assertions with `.toThrow` for error checking across multiple test files, aligning with best practices for newer Jest versions. [[1]](diffhunk://#diff-674b12b55633a96dd5a8eb3177311ff4d2253741edc2a281166a829225aba040L129-R135) [[2]](diffhunk://#diff-674b12b55633a96dd5a8eb3177311ff4d2253741edc2a281166a829225aba040L284-R286) [[3]](diffhunk://#diff-674b12b55633a96dd5a8eb3177311ff4d2253741edc2a281166a829225aba040L346-R344) [[4]](diffhunk://#diff-cd36b281a0abacada2f46ce13c54911e6c24a720de104792fec5f1b529f10f74L183-R185) [[5]](diffhunk://#diff-cd36b281a0abacada2f46ce13c54911e6c24a720de104792fec5f1b529f10f74L203-R205) [[6]](diffhunk://#diff-6b41d79b4db8c635487ebe8aa7e41eae6e10899ed0876c1de5f81e3b8a97b529L205-R205) [[7]](diffhunk://#diff-6b41d79b4db8c635487ebe8aa7e41eae6e10899ed0876c1de5f81e3b8a97b529L357-R357) [[8]](diffhunk://#diff-f5f65d907d4110a523dd2249817af8ee20f4f9e2f8259fd0594f0ba909237b47L154-R154) [[9]](diffhunk://#diff-f5f65d907d4110a523dd2249817af8ee20f4f9e2f8259fd0594f0ba909237b47L178-R178) [[10]](diffhunk://#diff-59f7ea4f069122023e354579e47852aa960f15a06c522ceedde35f7c66db0400L2201-R2203) [[11]](diffhunk://#diff-6e2a0e50ff73fa9faf5240a7705aabf4e870e3c3126c877fafc136cc723d346bL102-R104) [[12]](diffhunk://#diff-6e2a0e50ff73fa9faf5240a7705aabf4e870e3c3126c877fafc136cc723d346bL113-R115) [[13]](diffhunk://#diff-6e2a0e50ff73fa9faf5240a7705aabf4e870e3c3126c877fafc136cc723d346bL124-R126) [[14]](diffhunk://#diff-6e2a0e50ff73fa9faf5240a7705aabf4e870e3c3126c877fafc136cc723d346bL136-R138) [[15]](diffhunk://#diff-6e2a0e50ff73fa9faf5240a7705aabf4e870e3c3126c877fafc136cc723d346bL148-R150) * Updated Jest snapshot file headers to reference the current Jest documentation URL instead of the deprecated link. [[1]](diffhunk://#diff-51e4a0fec533fa983dab0091ee91e95a2de52e2c42836ff8de594153df44bbecL1-R1) [[2]](diffhunk://#diff-e3850ae39761cff3333b5cf46beb64fb7171cc18c9a91eaa3693ba3c6a4985dcL1-R1) **Mocking Improvements for JWT Handling:** * Refactored mocking of the `jose` library in tests, switching from `jest.spyOn` to `jest.mocked` for `jwtVerify` and `createRemoteJWKSet`. This approach is more robust and compatible with newer Jest and TypeScript versions. [[1]](diffhunk://#diff-19c19386dcd41859de57e28e16189fe3fa794ae5bb588b15ddde89eee5c9b327R9-R13) [[2]](diffhunk://#diff-19c19386dcd41859de57e28e16189fe3fa794ae5bb588b15ddde89eee5c9b327L69-R74) [[3]](diffhunk://#diff-19c19386dcd41859de57e28e16189fe3fa794ae5bb588b15ddde89eee5c9b327L102-R107) [[4]](diffhunk://#diff-19c19386dcd41859de57e28e16189fe3fa794ae5bb588b15ddde89eee5c9b327L250-R254) [[5]](diffhunk://#diff-19c19386dcd41859de57e28e16189fe3fa794ae5bb588b15ddde89eee5c9b327L338-R342) [[6]](diffhunk://#diff-19c19386dcd41859de57e28e16189fe3fa794ae5bb588b15ddde89eee5c9b327L384-R387) [[7]](diffhunk://#diff-59f7ea4f069122023e354579e47852aa960f15a06c522ceedde35f7c66db0400R25-R30) [[8]](diffhunk://#diff-59f7ea4f069122023e354579e47852aa960f15a06c522ceedde35f7c66db0400L888-R900) [[9]](diffhunk://#diff-59f7ea4f069122023e354579e47852aa960f15a06c522ceedde35f7c66db0400L974-R978) [[10]](diffhunk://#diff-59f7ea4f069122023e354579e47852aa960f15a06c522ceedde35f7c66db0400L1001-R1005) [[11]](diffhunk://#diff-59f7ea4f069122023e354579e47852aa960f15a06c522ceedde35f7c66db0400L1043-R1046) **Error Handling Standardization:** * Standardized error throwing in tests by using direct error classes (e.g., `UnauthorizedException`, `SignatureVerificationException`) instead of custom error objects, simplifying the test logic and improving clarity. [[1]](diffhunk://#diff-674b12b55633a96dd5a8eb3177311ff4d2253741edc2a281166a829225aba040L129-R135) [[2]](diffhunk://#diff-674b12b55633a96dd5a8eb3177311ff4d2253741edc2a281166a829225aba040L284-R286) [[3]](diffhunk://#diff-674b12b55633a96dd5a8eb3177311ff4d2253741edc2a281166a829225aba040L346-R344) [[4]](diffhunk://#diff-6e2a0e50ff73fa9faf5240a7705aabf4e870e3c3126c877fafc136cc723d346bL102-R104) [[5]](diffhunk://#diff-6e2a0e50ff73fa9faf5240a7705aabf4e870e3c3126c877fafc136cc723d346bL113-R115) [[6]](diffhunk://#diff-6e2a0e50ff73fa9faf5240a7705aabf4e870e3c3126c877fafc136cc723d346bL124-R126) [[7]](diffhunk://#diff-6e2a0e50ff73fa9faf5240a7705aabf4e870e3c3126c877fafc136cc723d346bL136-R138) [[8]](diffhunk://#diff-6e2a0e50ff73fa9faf5240a7705aabf4e870e3c3126c877fafc136cc723d346bL148-R150) **Minor Test Maintenance:** * Removed unused imports and made minor code cleanups in test files to reduce noise and improve maintainability. These changes collectively modernize the codebase, improve test reliability, and ensure compatibility with the latest tooling. Does this require changes to the WorkOS Docs? E.g. the [API Reference](https://workos.com/docs/reference) or code snippets need updates. ``` [ ] Yes ``` If yes, link a related docs PR and add a docs maintainer as a reviewer. Their approval is required.
1 parent 6db1091 commit 87a0553

File tree

12 files changed

+2413
-1213
lines changed

12 files changed

+2413
-1213
lines changed

package-lock.json

Lines changed: 2336 additions & 1134 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -41,39 +41,39 @@
4141
},
4242
"dependencies": {
4343
"iron-session": "^8.0.4",
44-
"jose": "~5.6.3",
44+
"jose": "~6.1.0",
4545
"leb": "^1.0.0",
4646
"qs": "6.14.0"
4747
},
4848
"devDependencies": {
4949
"@babel/plugin-transform-modules-commonjs": "^7.26.3",
5050
"@babel/preset-env": "^7.26.9",
5151
"@babel/preset-typescript": "^7.27.0",
52-
"@eslint/js": "^9.21.0",
52+
"@eslint/js": "^9.37.0",
5353
"@types/cookie": "^0.6.0",
5454
"@types/glob": "^8.1.0",
55-
"@types/jest": "^29.5.14",
55+
"@types/jest": "^30.0.0",
5656
"@types/node": "~20",
5757
"@types/qs": "^6.14.0",
58-
"@typescript-eslint/parser": "^8.25.0",
59-
"babel-jest": "^29.7.0",
58+
"@typescript-eslint/parser": "^8.46.0",
59+
"babel-jest": "^30.2.0",
6060
"esbuild-fix-imports-plugin": "^1.0.21",
61-
"eslint": "^9.21.0",
62-
"eslint-plugin-jest": "^28.11.0",
63-
"eslint-plugin-n": "^17.15.1",
61+
"eslint": "^9.37.0",
62+
"eslint-plugin-jest": "^29.0.1",
63+
"eslint-plugin-n": "^17.23.1",
6464
"glob": "^11.0.3",
65-
"jest": "29.7.0",
65+
"jest": "30.2.0",
6666
"jest-environment-miniflare": "^2.14.2",
6767
"jest-fetch-mock": "^3.0.3",
68-
"miniflare": "^3.20250408.2",
69-
"nock": "^13.5.5",
68+
"miniflare": "^4.20251004.0",
69+
"nock": "^14.0.10",
7070
"prettier": "^3.5.3",
71-
"supertest": "7.1.0",
72-
"ts-jest": "29.3.1",
71+
"supertest": "^7.1.4",
72+
"ts-jest": "29.4.4",
7373
"tsup": "^8.5.0",
74-
"tsx": "^4.19.0",
75-
"typescript": "5.9.2",
76-
"typescript-eslint": "^8.25.0"
74+
"tsx": "^4.20.6",
75+
"typescript": "5.9.3",
76+
"typescript-eslint": "^8.46.0"
7777
},
7878
"exports": {
7979
".": {

src/audit-logs/audit-logs.spec.ts

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import {
1717
serializeCreateAuditLogEventOptions,
1818
serializeCreateAuditLogSchemaOptions,
1919
} from './serializers';
20-
import { FetchError } from '../common/utils/fetch-error';
2120

2221
const event: CreateAuditLogEventOptions = {
2322
action: 'document.updated',
@@ -126,18 +125,14 @@ describe('AuditLogs', () => {
126125
const workosSpy = jest.spyOn(WorkOS.prototype, 'post');
127126

128127
workosSpy.mockImplementationOnce(() => {
129-
throw new FetchError({
130-
message:
131-
'Could not authorize the request. Maybe your API key is invalid?',
132-
response: { status: 401, headers: new Headers(), data: {} },
133-
});
128+
throw new UnauthorizedException('a-request-id');
134129
});
135130

136131
const workos = new WorkOS('invalid apikey');
137132

138133
await expect(
139134
workos.auditLogs.createEvent('org_123', event),
140-
).rejects.toThrowError(new UnauthorizedException('a-request-id'));
135+
).rejects.toThrow(UnauthorizedException);
141136
});
142137
});
143138

@@ -281,18 +276,14 @@ describe('AuditLogs', () => {
281276
};
282277

283278
workosSpy.mockImplementationOnce(() => {
284-
throw new FetchError({
285-
message:
286-
'Could not authorize the request. Maybe your API key is invalid?',
287-
response: { status: 401, headers: new Headers(), data: {} },
288-
});
279+
throw new UnauthorizedException('a-request-id');
289280
});
290281

291282
const workos = new WorkOS('invalid apikey');
292283

293-
await expect(
294-
workos.auditLogs.createExport(options),
295-
).rejects.toThrowError(new UnauthorizedException('a-request-id'));
284+
await expect(workos.auditLogs.createExport(options)).rejects.toThrow(
285+
UnauthorizedException,
286+
);
296287
});
297288
});
298289
});
@@ -343,18 +334,14 @@ describe('AuditLogs', () => {
343334
const workosSpy = jest.spyOn(WorkOS.prototype, 'get');
344335

345336
workosSpy.mockImplementationOnce(() => {
346-
throw new FetchError({
347-
message:
348-
'Could not authorize the request. Maybe your API key is invalid?',
349-
response: { status: 401, headers: new Headers(), data: {} },
350-
});
337+
throw new UnauthorizedException('a-request-id');
351338
});
352339

353340
const workos = new WorkOS('invalid apikey');
354341

355342
await expect(
356343
workos.auditLogs.getExport('audit_log_export_1234'),
357-
).rejects.toThrowError(new UnauthorizedException('a-request-id'));
344+
).rejects.toThrow(UnauthorizedException);
358345

359346
expect(workosSpy).toHaveBeenCalledWith(
360347
`/audit_logs/exports/audit_log_export_1234`,

src/common/net/fetch-client.spec.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -236,9 +236,9 @@ describe('Fetch client', () => {
236236
const mockSleep = jest.spyOn(fetchClient, 'sleep');
237237
mockSleep.mockImplementation(() => Promise.resolve());
238238

239-
await expect(
240-
fetchClient.get('/fga/v1/resources', {}),
241-
).rejects.toThrowError('Gateway Timeout');
239+
await expect(fetchClient.get('/fga/v1/resources', {})).rejects.toThrow(
240+
'Gateway Timeout',
241+
);
242242

243243
expect(mockShouldRetryRequest).toHaveBeenCalledTimes(4);
244244
expect(mockSleep).toHaveBeenCalledTimes(3);
@@ -256,9 +256,9 @@ describe('Fetch client', () => {
256256
'shouldRetryRequest',
257257
);
258258

259-
await expect(
260-
fetchClient.get('/fga/v1/resources', {}),
261-
).rejects.toThrowError('Bad Request');
259+
await expect(fetchClient.get('/fga/v1/resources', {})).rejects.toThrow(
260+
'Bad Request',
261+
);
262262

263263
expect(mockShouldRetryRequest).toHaveBeenCalledTimes(1);
264264
});

src/organizations/organizations.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ describe('Organizations', () => {
202202
],
203203
name: 'Test Organization',
204204
}),
205-
).rejects.toThrowError(
205+
).rejects.toThrow(
206206
'An Organization with the domain example.com already exists.',
207207
);
208208
expect(fetchBody()).toEqual({
@@ -354,7 +354,7 @@ describe('Organizations', () => {
354354
organization: 'org_01EHT88Z8J8795GZNQ4ZP1J81T',
355355
stripeCustomerId: 'cus_MX8J9nfK4lP2Yw',
356356
}),
357-
).rejects.toThrowError(
357+
).rejects.toThrow(
358358
'stripe_customer_id is not enabled for this environment',
359359
);
360360

src/portal/portal.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ describe('Portal', () => {
151151
organization: 'bogus-id',
152152
returnUrl: 'https://www.example.com',
153153
}),
154-
).rejects.toThrowError(
154+
).rejects.toThrow(
155155
'Could not find an organization with the id, bogus-id.',
156156
);
157157
expect(fetchBody()).toEqual({
@@ -175,7 +175,7 @@ describe('Portal', () => {
175175
organization: 'bogus-id',
176176
returnUrl: 'https://www.example.com',
177177
}),
178-
).rejects.toThrowError(
178+
).rejects.toThrow(
179179
'Could not find an organization with the id, bogus-id.',
180180
);
181181
expect(fetchBody()).toEqual({

src/sso/__snapshots__/sso.spec.ts.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Jest Snapshot v1, https://goo.gl/fbAQLP
1+
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
22

33
exports[`SSO SSO getAuthorizationUrl with a connection generates an authorize url with the connection 1`] = `"https://api.workos.dev/sso/authorize?client_id=proj_123&connection=connection_123&redirect_uri=example.com%2Fsso%2Fworkos%2Fcallback&response_type=code"`;
44

src/user-management/__snapshots__/user-management.spec.ts.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Jest Snapshot v1, https://goo.gl/fbAQLP
1+
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
22

33
exports[`UserManagement getAuthorizationUrl with a code_challenge and code_challenge_method generates an authorize url 1`] = `"https://api.workos.com/user_management/authorize?client_id=proj_123&code_challenge=code_challenge_value&code_challenge_method=S256&provider=authkit&redirect_uri=example.com%2Fauth%2Fworkos%2Fcallback&response_type=code"`;
44

src/user-management/session.spec.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ import userFixture from './fixtures/user.json';
66
import fetch from 'jest-fetch-mock';
77
import { fetchOnce } from '../common/utils/test-utils';
88

9+
jest.mock('jose', () => ({
10+
...jest.requireActual('jose'),
11+
jwtVerify: jest.fn(),
12+
}));
13+
914
describe('Session', () => {
1015
let workos: WorkOS;
1116

@@ -66,7 +71,7 @@ describe('Session', () => {
6671
});
6772

6873
it('returns a failed response if the accessToken is not a valid JWT', async () => {
69-
jest.spyOn(jose, 'jwtVerify').mockImplementation(() => {
74+
jest.mocked(jose.jwtVerify).mockImplementation(() => {
7075
throw new Error('Invalid JWT');
7176
});
7277

@@ -100,7 +105,7 @@ describe('Session', () => {
100105

101106
it('returns a successful response if the sessionData is valid', async () => {
102107
jest
103-
.spyOn(jose, 'jwtVerify')
108+
.mocked(jose.jwtVerify)
104109
.mockResolvedValue({} as jose.JWTVerifyResult & jose.ResolvedKey);
105110

106111
const cookiePassword = 'alongcookiesecretmadefortestingsessions';
@@ -247,7 +252,7 @@ describe('Session', () => {
247252
});
248253

249254
jest
250-
.spyOn(jose, 'jwtVerify')
255+
.mocked(jose.jwtVerify)
251256
.mockResolvedValue({} as jose.JWTVerifyResult & jose.ResolvedKey);
252257

253258
const cookiePassword = 'alongcookiesecretmadefortestingsessions';
@@ -336,7 +341,7 @@ describe('Session', () => {
336341
describe('getLogoutUrl', () => {
337342
it('returns a logout URL for the user', async () => {
338343
jest
339-
.spyOn(jose, 'jwtVerify')
344+
.mocked(jose.jwtVerify)
340345
.mockResolvedValue({} as jose.JWTVerifyResult & jose.ResolvedKey);
341346

342347
const cookiePassword = 'alongcookiesecretmadefortestingsessions';
@@ -381,7 +386,7 @@ describe('Session', () => {
381386
describe('when a returnTo URL is provided', () => {
382387
it('returns a logout URL for the user', async () => {
383388
jest
384-
.spyOn(jose, 'jwtVerify')
389+
.mocked(jose.jwtVerify)
385390
.mockResolvedValue({} as jose.JWTVerifyResult & jose.ResolvedKey);
386391

387392
const cookiePassword = 'alongcookiesecretmadefortestingsessions';

src/user-management/user-management.spec.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ import identityFixture from './fixtures/identity.json';
2323
import * as jose from 'jose';
2424
import { sealData } from 'iron-session';
2525

26+
jest.mock('jose', () => ({
27+
...jest.requireActual('jose'),
28+
jwtVerify: jest.fn(),
29+
createRemoteJWKSet: jest.fn(),
30+
}));
31+
2632
const userId = 'user_01H5JQDV7R7ATEYZDEG0W5PRYS';
2733
const organizationMembershipId = 'om_01H5JQDV7R7ATEYZDEG0W5PRYS';
2834
const emailVerificationId = 'email_verification_01H5JQDV7R7ATEYZDEG0W5PRYS';
@@ -889,14 +895,14 @@ describe('UserManagement', () => {
889895
beforeEach(() => {
890896
// Mock createRemoteJWKSet
891897
jest
892-
.spyOn(jose, 'createRemoteJWKSet')
898+
.mocked(jose.createRemoteJWKSet)
893899
.mockImplementation(
894900
(_url: URL, _options?: jose.RemoteJWKSetOptions) => {
895901
// This function simulates the token verification process
896902
const verifyFunction = (
897903
_protectedHeader: jose.JWSHeaderParameters,
898904
_token: jose.FlattenedJWSInput,
899-
): Promise<jose.KeyLike> => {
905+
): Promise<any> => {
900906
return Promise.resolve({
901907
type: 'public',
902908
});
@@ -974,7 +980,7 @@ describe('UserManagement', () => {
974980
});
975981

976982
it('returns authenticated = false when the JWT is invalid', async () => {
977-
jest.spyOn(jose, 'jwtVerify').mockImplementationOnce(() => {
983+
jest.mocked(jose.jwtVerify).mockImplementationOnce(() => {
978984
throw new Error('Invalid JWT');
979985
});
980986

@@ -1002,7 +1008,7 @@ describe('UserManagement', () => {
10021008

10031009
it('returns the JWT claims when provided a valid JWT', async () => {
10041010
jest
1005-
.spyOn(jose, 'jwtVerify')
1011+
.mocked(jose.jwtVerify)
10061012
.mockResolvedValue({} as jose.JWTVerifyResult & jose.ResolvedKey);
10071013

10081014
const cookiePassword = 'alongcookiesecretmadefortestingsessions';
@@ -1044,7 +1050,7 @@ describe('UserManagement', () => {
10441050

10451051
it('returns the JWT claims when provided a valid JWT with multiple roles', async () => {
10461052
jest
1047-
.spyOn(jose, 'jwtVerify')
1053+
.mocked(jose.jwtVerify)
10481054
.mockResolvedValue({} as jose.JWTVerifyResult & jose.ResolvedKey);
10491055

10501056
const cookiePassword = 'alongcookiesecretmadefortestingsessions';
@@ -2332,7 +2338,7 @@ describe('UserManagement', () => {
23322338

23332339
expect(() => {
23342340
workos.userManagement.getJwksUrl('');
2335-
}).toThrowError(TypeError);
2341+
}).toThrow(TypeError);
23362342
});
23372343
});
23382344
});

0 commit comments

Comments
 (0)