Skip to content

Commit

Permalink
feat(nextjs): Replace jest with vitest for unit tests (#4298)
Browse files Browse the repository at this point in the history
Co-authored-by: Bryce Kalow <[email protected]>
  • Loading branch information
jacekradko and BRKalow authored Oct 31, 2024
1 parent 188bf40 commit 18545c7
Show file tree
Hide file tree
Showing 23 changed files with 1,705 additions and 3,203 deletions.
2 changes: 2 additions & 0 deletions .changeset/small-cougars-protect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ packages/*/examples
package-lock.json
**/integration/templates/**/*
commitlint.config.ts
vitest.workspace.mjs
4,782 changes: 1,631 additions & 3,151 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@
"turbo-ignore": "^2.0.6",
"typescript": "^5.6.2",
"verdaccio": "^5.26.3",
"vitest": "2.1.3",
"zx": "^7.2.3"
},
"optionalDependencies": {
Expand Down
16 changes: 0 additions & 16 deletions packages/nextjs/jest.config.js

This file was deleted.

1 change: 0 additions & 1 deletion packages/nextjs/jest.setup.js

This file was deleted.

4 changes: 1 addition & 3 deletions packages/nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,7 @@
"lint:attw": "attw --pack . --ignore-rules no-resolution unexpected-module-syntax",
"lint:publint": "publint",
"publish:local": "npx yalc push --replace --sig",
"test": "jest",
"test:cache:clear": "jest --clearCache --useStderr",
"test:ci": "jest --maxWorkers=70%"
"test": "vitest"
},
"dependencies": {
"@clerk/backend": "1.15.1",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`/client public exports should not include a breaking change 1`] = `
exports[`/client public exports > should not include a breaking change 1`] = `
{
"ClerkProvider": [Function],
}
Expand Down
2 changes: 2 additions & 0 deletions packages/nextjs/src/pages/__tests__/exports.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { describe, expect, it } from 'vitest';

import * as publicExports from '../ClerkProvider';

describe('/client public exports', () => {
Expand Down
1 change: 1 addition & 0 deletions packages/nextjs/src/pages/__tests__/index.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { expectTypeOf } from 'expect-type';
import { describe, it } from 'vitest';

import type { ClerkProvider } from '../ClerkProvider';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`/server public exports should not include a breaking change 1`] = `
exports[`/server public exports > should not include a breaking change 1`] = `
[
"auth",
"buildClerkProps",
Expand Down
26 changes: 16 additions & 10 deletions packages/nextjs/src/server/__tests__/clerkClient.test.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
global.fetch = jest.fn(() => Promise.resolve(new Response(null)));
import { createClerkClient } from '@clerk/backend';
import type { Mock } from 'vitest';
import { describe, expect, it, vi } from 'vitest';

import { clerkClient } from '../clerkClient';

describe('clerkClient', () => {
it('should pass version package to userAgent', async () => {
const resolvedClerkClient = await clerkClient();
vi.mock('@clerk/backend', async importOriginal => {
const mod: any = await importOriginal();
return {
...mod,
// replace some exports
createClerkClient: vi.fn().mockReturnValue({ users: { getUser: vi.fn() } }),
};
});

await resolvedClerkClient.users.getUser('user_test');
describe('clerkClient', () => {
it('should pass package-specific userAgent', async () => {
await clerkClient();

expect(global.fetch).toBeCalled();
expect((global.fetch as any).mock.calls[0][1].headers).toMatchObject({
Authorization: 'Bearer TEST_SECRET_KEY',
'Content-Type': 'application/json',
'User-Agent': '@clerk/[email protected]',
expect((createClerkClient as Mock).mock.lastCall?.[0]).toMatchObject({
userAgent: '@clerk/[email protected]',
});
});
});
22 changes: 12 additions & 10 deletions packages/nextjs/src/server/__tests__/clerkMiddleware.test.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
// There is no need to execute the complete authenticateRequest to test clerkMiddleware
// This mock SHOULD exist before the import of authenticateRequest
import { AuthStatus, constants } from '@clerk/backend/internal';
import { describe, expect } from '@jest/globals';
// used to assert the mock
import assert from 'assert';
import type { NextFetchEvent } from 'next/server';
import { NextRequest, NextResponse } from 'next/server';
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';

import { clerkClient } from '../clerkClient';
import { clerkMiddleware } from '../clerkMiddleware';
import { createRouteMatcher } from '../routeMatcher';
import { decryptClerkRequestData } from '../utils';

const publishableKey = 'pk_test_Y2xlcmsuaW5jbHVkZWQua2F0eWRpZC05Mi5sY2wuZGV2JA';
const authenticateRequestMock = jest.fn().mockResolvedValue({
const authenticateRequestMock = vi.fn().mockResolvedValue({
toAuth: () => ({
debug: (d: any) => d,
}),
headers: new Headers(),
publishableKey,
});

jest.mock('../clerkClient', () => {
vi.mock('../clerkClient', () => {
return {
clerkClient: () => ({
authenticateRequest: authenticateRequestMock,
telemetry: { record: jest.fn() },
telemetry: { record: vi.fn() },
}),
};
});
Expand All @@ -37,8 +37,8 @@ const consoleWarn = console.warn;
const consoleLog = console.log;

beforeAll(() => {
global.console.warn = jest.fn();
global.console.log = jest.fn();
global.console.warn = vi.fn();
global.console.log = vi.fn();
});
afterAll(() => {
global.console.warn = consoleWarn;
Expand All @@ -47,11 +47,13 @@ afterAll(() => {

// Removing this mock will cause the clerkMiddleware tests to fail due to missing publishable key
// This mock SHOULD exist before the imports
jest.mock('../constants', () => {
vi.mock(import('../constants.js'), async importOriginal => {
const actual = await importOriginal();
return {
...actual,
ENCRYPTION_KEY: 'encryption-key',
PUBLISHABLE_KEY: 'pk_test_Y2xlcmsuaW5jbHVkZWQua2F0eWRpZC05Mi5sY2wuZGV2JA',
SECRET_KEY: 'sk_test_xxxxxxxxxxxxxxxxxx',
ENCRYPTION_KEY: 'encryption-key',
};
});

Expand All @@ -74,7 +76,7 @@ const mockRequest = (params: MockRequestParams) => {
describe('ClerkMiddleware type tests', () => {
// create a copy to test the types only
// running this function does nothing, it is used purely for type checking
const clerkMiddlewareMock = jest.fn() as typeof clerkMiddleware;
const clerkMiddlewareMock = vi.fn() as typeof clerkMiddleware;
it('can receive the appropriate keys', () => {
clerkMiddlewareMock({ publishableKey: '', secretKey: '' });
clerkMiddlewareMock({ secretKey: '' });
Expand Down Expand Up @@ -589,7 +591,7 @@ describe('clerkMiddleware(params)', () => {

describe('debug', () => {
beforeEach(() => {
(global.console.log as jest.Mock).mockClear();
global.console.log.mockClear();
});

it('outputs debug logs when used with only params', async () => {
Expand Down
1 change: 1 addition & 0 deletions packages/nextjs/src/server/__tests__/createGetAuth.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { AuthStatus, constants } from '@clerk/backend/internal';
import hmacSHA1 from 'crypto-js/hmac-sha1';
import { NextRequest } from 'next/server';
import { describe, expect, it } from 'vitest';

import { createGetAuth, getAuth } from '../createGetAuth';

Expand Down
2 changes: 1 addition & 1 deletion packages/nextjs/src/server/__tests__/exports.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
jest.mock('server-only', () => null);
import { describe, expect, it } from 'vitest';

import * as publicExports from '../index';

Expand Down
9 changes: 5 additions & 4 deletions packages/nextjs/src/utils/__tests__/debugLogger.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { expectTypeOf } from 'expect-type';
import { beforeEach, describe, expect, it, vi } from 'vitest';

import { withLogger } from '../debugLogger';

Expand All @@ -7,9 +8,9 @@ describe('withLogger', () => {

beforeEach(() => {
logger = {
enable: jest.fn(),
log: jest.fn(),
commit: jest.fn(),
enable: vi.fn(),
log: vi.fn(),
commit: vi.fn(),
};
});

Expand Down Expand Up @@ -116,7 +117,7 @@ describe('withLogger', () => {
// setup: mock vercel environment, mock console log so we can intercept its value
process.env.VERCEL = 'true';
const oldConsoleLog = console.log.bind(console);
const log = jest.fn();
const log = vi.fn();
console.log = log;

const veryLongString = new Array(6000).join('a');
Expand Down
1 change: 1 addition & 0 deletions packages/nextjs/src/utils/__tests__/matcher.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { pathToRegexp } from '@clerk/shared/pathToRegexp';
import { describe, expect, it } from 'vitest';

const createMatcher = (config: { matcher: string[] }) => (path: string) => {
return config.matcher.some(matcher => {
Expand Down
2 changes: 2 additions & 0 deletions packages/nextjs/src/utils/__tests__/removeBasePath.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { afterAll, describe, expect, it } from 'vitest';

import { removeBasePath } from '../removeBasePath';

describe('removeBasePath', () => {
Expand Down
13 changes: 13 additions & 0 deletions packages/nextjs/vitest.config.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { defineConfig } from 'vitest/config';

export default defineConfig({
plugins: [],
test: {
env: {
CLERK_SECRET_KEY: 'TEST_SECRET_KEY',
},
environment: 'jsdom',
includeSource: ['**/*.{js,ts,jsx,tsx}'],
setupFiles: './vitest.setup.mts',
},
});
6 changes: 6 additions & 0 deletions packages/nextjs/vitest.setup.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { beforeAll } from 'vitest';

globalThis.PACKAGE_NAME = '@clerk/nextjs';
globalThis.PACKAGE_VERSION = '0.0.0-test';

beforeAll(() => {});
3 changes: 1 addition & 2 deletions packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@
"@vitejs/plugin-react": "^4.3.1",
"bundlewatch": "^0.4.0",
"concurrently": "^8.2.2",
"jsdom": "^24.1.1",
"vitest": "^2.0.5"
"jsdom": "^24.1.1"
}
}
2 changes: 1 addition & 1 deletion packages/upgrade/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
"@babel/preset-react": "^7.24.7",
"@types/jscodeshift": "^0.12.0",
"eslint-config-custom": "*",
"vitest": "^2.1.3"
"vitest": "2.1.3"
},
"engines": {
"node": ">=18.17.0"
Expand Down
3 changes: 3 additions & 0 deletions vitest.workspace.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { defineWorkspace } from 'vitest/config';

export default defineWorkspace(['./packages/*/vitest.config.{mts,mjs,js,ts}']);

0 comments on commit 18545c7

Please sign in to comment.