Compare commits

...

1 Commits

Author SHA1 Message Date
Elliot DeNolf
6c650a5e8d test: migrate unit tests to vitest 2025-01-15 13:37:30 -05:00
12 changed files with 823 additions and 73 deletions

View File

@@ -94,7 +94,7 @@
"test:int:postgres": "cross-env NODE_OPTIONS=\"--no-deprecation\" NODE_NO_WARNINGS=1 PAYLOAD_DATABASE=postgres DISABLE_LOGGING=true jest --forceExit --detectOpenHandles --config=test/jest.config.js --runInBand",
"test:int:sqlite": "cross-env NODE_OPTIONS=\"--no-deprecation\" NODE_NO_WARNINGS=1 PAYLOAD_DATABASE=sqlite DISABLE_LOGGING=true jest --forceExit --detectOpenHandles --config=test/jest.config.js --runInBand",
"test:types": "tstyche",
"test:unit": "cross-env NODE_OPTIONS=\"--no-deprecation\" NODE_NO_WARNINGS=1 DISABLE_LOGGING=true jest --forceExit --detectOpenHandles --config=jest.config.js --runInBand",
"test:unit": "cross-env NODE_OPTIONS=\"--no-deprecation\" NODE_NO_WARNINGS=1 DISABLE_LOGGING=true vitest --run packages",
"translateNewKeys": "pnpm --filter translations run translateNewKeys"
},
"lint-staged": {
@@ -171,7 +171,8 @@
"tstyche": "^3.1.1",
"tsx": "4.19.2",
"turbo": "^2.3.3",
"typescript": "5.7.2"
"typescript": "5.7.2",
"vitest": "^2.1.8"
},
"peerDependencies": {
"react": "^19.0.0 || ^19.0.0-rc-65a56d0e-20241020",

View File

@@ -1,4 +1,4 @@
import { jest } from '@jest/globals'
import { vi, describe } from 'vitest'
import fs from 'fs'
import fse from 'fs-extra'
import globby from 'globby'
@@ -15,7 +15,7 @@ describe('createProject', () => {
let projectDir: string
beforeAll(() => {
// eslint-disable-next-line no-console
console.log = jest.fn()
console.log = vi.fn()
})
beforeEach(() => {
@@ -29,7 +29,7 @@ describe('createProject', () => {
}
})
describe('#createProject', () => {
describe('#createProject', { timeout: 30_000 }, () => {
const args = {
_: ['project-name'],
'--db': 'mongodb',

View File

@@ -1,5 +1,5 @@
import * as p from '@clack/prompts'
import { jest } from '@jest/globals'
import { vi } from 'vitest'
import { parseAndModifyConfigContent, withPayloadStatement } from './wrap-next-config.js'
@@ -159,7 +159,7 @@ describe('parseAndInsertWithPayload', () => {
// Unsupported: export { wrapped as default }
it('should give warning with a named export as default', async () => {
const warnLogSpy = jest.spyOn(p.log, 'warn').mockImplementation(() => {})
const warnLogSpy = vi.spyOn(p.log, 'warn').mockImplementation(() => {})
const { modifiedConfigContent, success } = await parseAndModifyConfigContent(
esmConfigs.nextConfigExportNamedDefault,

View File

@@ -1,6 +1,6 @@
import type { Transporter } from 'nodemailer'
import { jest } from '@jest/globals'
import { MockedFunction, vi } from 'vitest'
import nodemailer from 'nodemailer'
import type { NodemailerAdapterArgs } from './index.js'
@@ -14,11 +14,11 @@ const defaultArgs: NodemailerAdapterArgs = {
describe('email-nodemailer', () => {
describe('transport verification', () => {
let mockedVerify: jest.Mock<Transporter['verify']>
let mockedVerify: MockedFunction<Transporter['verify']>
let mockTransport: Transporter
beforeEach(() => {
mockedVerify = jest.fn<Transporter['verify']>()
mockedVerify = vi.fn()
mockTransport = nodemailer.createTransport({
name: 'existing-transport',
// eslint-disable-next-line @typescript-eslint/require-await, @typescript-eslint/no-misused-promises

View File

@@ -1,6 +1,6 @@
import type { Payload } from 'payload'
import { jest } from '@jest/globals'
import { vi } from 'vitest'
import { resendAdapter } from './index.js'
@@ -16,19 +16,19 @@ describe('email-resend', () => {
const mockPayload = {} as unknown as Payload
afterEach(() => {
jest.clearAllMocks()
vi.clearAllMocks()
})
it('should handle sending an email', async () => {
global.fetch = jest.spyOn(global, 'fetch').mockImplementation(
jest.fn(() =>
global.fetch = vi.spyOn(global, 'fetch').mockImplementation(
vi.fn(() =>
Promise.resolve({
json: () => {
return { id: 'test-id' }
},
}),
) as jest.Mock,
) as jest.Mock
),
)
const adapter = resendAdapter({
apiKey,
@@ -62,13 +62,15 @@ describe('email-resend', () => {
message: 'error information',
statusCode: 403,
}
global.fetch = jest.spyOn(global, 'fetch').mockImplementation(
jest.fn(() =>
// @ts-expect-error
global.fetch = vi.spyOn(global, 'fetch').mockImplementation(
// @ts-expect-error
vi.fn(() =>
Promise.resolve({
json: () => errorResponse,
}),
) as jest.Mock,
) as jest.Mock
),
)
const adapter = resendAdapter({
apiKey,

View File

@@ -1,6 +1,6 @@
import type { Config, Payload } from 'payload'
import { jest } from '@jest/globals'
import { vi } from 'vitest'
import nodemailer from 'nodemailer'
import { defaults } from 'payload'
@@ -12,11 +12,11 @@ describe('email', () => {
const defaultDomain = 'test.com'
const apiKey = 'test'
const mockedPayload: Payload = jest.fn() as unknown as Payload
const mockedPayload: Payload = vi.fn() as unknown as Payload
beforeAll(() => {
// Mock createTestAccount to prevent calling external services
jest.spyOn(nodemailer, 'createTestAccount').mockImplementation(() => {
vi.spyOn(nodemailer, 'createTestAccount').mockImplementation(() => {
return Promise.resolve({
imap: { host: 'imap.test.com', port: 993, secure: true },
pass: 'testpass',

View File

@@ -1,32 +1,32 @@
import type { Config, Payload } from 'payload'
import { jest } from '@jest/globals'
import { vi, MockedFunction } from 'vitest'
import { nodemailerAdapter } from '@payloadcms/email-nodemailer'
import nodemailer from 'nodemailer'
import { defaults } from 'payload'
// TO-DO: this would be needed for the TO-DO tests below.
// maybe we have to use jest.unstable_mockModule? (already tried)
// jest.mock('./plugin.ts', () => ({
// // generateRandomString: jest.fn<() => string>().mockReturnValue('instance'),
// generateRandomString: jest.fn().mockReturnValue('instance'),
// maybe we have to use vi.unstable_mockModule? (already tried)
// vi.mock('./plugin.ts', () => ({
// // generateRandomString: vi.fn<() => string>().mockReturnValue('instance'),
// generateRandomString: vi.fn().mockReturnValue('instance'),
// }))
const mockedPayload: Payload = {
updateGlobal: jest.fn(),
findGlobal: jest.fn().mockReturnValue('instance'),
updateGlobal: vi.fn(),
findGlobal: vi.fn().mockReturnValue('instance'),
} as unknown as Payload
import { payloadCloudPlugin } from './plugin.js'
describe('plugin', () => {
let createTransportSpy: jest.Spied<any>
let createTransportSpy: MockedFunction<typeof nodemailer.createTransport>
const skipVerify = true
beforeAll(() => {
// Mock createTestAccount to prevent calling external services
jest.spyOn(nodemailer, 'createTestAccount').mockImplementation(() => {
vi.spyOn(nodemailer, 'createTestAccount').mockImplementation(() => {
return Promise.resolve({
imap: { host: 'imap.test.com', port: 993, secure: true },
pass: 'testpass',
@@ -39,12 +39,13 @@ describe('plugin', () => {
})
beforeEach(() => {
createTransportSpy = jest.spyOn(nodemailer, 'createTransport').mockImplementationOnce(() => {
// @ts-expect-error
createTransportSpy = vi.spyOn(nodemailer, 'createTransport').mockImplementationOnce(() => {
return {
transporter: {
name: 'Nodemailer - SMTP',
},
verify: jest.fn(),
verify: vi.fn(),
} as unknown as ReturnType<typeof nodemailer.createTransport>
})
})
@@ -67,7 +68,6 @@ describe('plugin', () => {
})
describe('storage', () => {
// eslint-disable-next-line jest/expect-expect
it('should default to using payload cloud storage', async () => {
const plugin = payloadCloudPlugin()
const config = await plugin(createConfig())
@@ -75,7 +75,6 @@ describe('plugin', () => {
assertCloudStorage(config)
})
// eslint-disable-next-line jest/expect-expect
it('should allow opt-out', async () => {
const plugin = payloadCloudPlugin({ storage: false })
const config = await plugin(createConfig())
@@ -114,7 +113,7 @@ describe('plugin', () => {
})
it('should not modify existing email transport', async () => {
const logSpy = jest.spyOn(console, 'log')
const logSpy = vi.spyOn(console, 'log')
const existingTransport = nodemailer.createTransport({
name: 'existing-transport',

View File

@@ -1,10 +1,10 @@
import { jest } from '@jest/globals'
import { vi } from 'vitest'
import type { ValidateOptions } from './config/types.js'
import { number, password, point, relationship, select, text, textarea } from './validations.js'
const t = jest.fn((string) => string)
const t = vi.fn((string) => string)
let options: ValidateOptions<any, any, any> = {
data: undefined,

View File

@@ -1,6 +1,7 @@
import type { AfterErrorHook, AfterErrorHookArgs, Config, PayloadRequest } from 'payload'
import { APIError, defaults } from 'payload'
import { vi } from 'vitest'
import { sentryPlugin } from './index'
import { randomUUID } from 'crypto'
@@ -70,7 +71,7 @@ describe('@payloadcms/plugin-sentry - unit', () => {
collection: { slug: 'mock-slug' } as any,
}
const captureExceptionSpy = jest.spyOn(mockSentry, 'captureException')
const captureExceptionSpy = vi.spyOn(mockSentry, 'captureException')
await hook(afterApiErrorHookArgs)

800
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -59,6 +59,6 @@
"@payloadcms/next": ["./packages/next/src/exports/*"]
}
},
"include": ["${configDir}/src"],
"include": ["${configDir}/src", "vite.config.ts"],
"exclude": ["${configDir}/dist", "${configDir}/build", "${configDir}/temp", "**/*.spec.ts"]
}

11
vite.config.ts Normal file
View File

@@ -0,0 +1,11 @@
import { configDefaults, defineConfig } from 'vitest/config'
export default defineConfig({
test: {
environment: 'node',
globals: true,
testTimeout: 20_000,
// setupFiles: ['./src/test/setup.ts'],
exclude: [...configDefaults.exclude, 'src/app/**/*'],
include: ['**/*.spec.ts'],
},
})