Skip to content
This repository was archived by the owner on Jun 9, 2025. It is now read-only.

Commit a0cbd23

Browse files
committed
chore: replace ava with vitest
1 parent 53b7bd0 commit a0cbd23

File tree

8 files changed

+6163
-12149
lines changed

8 files changed

+6163
-12149
lines changed

package-lock.json

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

package.json

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,21 +50,15 @@
5050
"format:fix:prettier": "cross-env-shell prettier --write $npm_package_config_prettier",
5151
"test:dev": "run-s build test:dev:*",
5252
"test:ci": "run-s test:ci:*",
53-
"test:dev:ava": "ava",
53+
"test:dev:vitest": "vitest",
5454
"test:dev:tsd": "tsd",
5555
"test:publish": "publint && attw --pack",
56-
"test:ci:ava": "nyc -r lcovonly -r text -r json ava"
56+
"test:ci:vitest": "vitest run --coverage"
5757
},
5858
"config": {
5959
"eslint": "--ignore-pattern README.md --ignore-path .gitignore --cache --format=codeframe --max-warnings=0 \"{src,scripts,.github,test}/**/*.{ts,js,md,html}\" \"*.{ts,js,md,html}\" \".*.{ts,js,md,html}\"",
6060
"prettier": "--ignore-path .gitignore --loglevel=warn \"{src,scripts,.github}/**/*.{ts,js,md,yml,json,html}\" \"*.{ts,js,yml,json,html}\" \".*.{ts,js,yml,json,html}\" \"!**/package-lock.json\" \"!package-lock.json\""
6161
},
62-
"ava": {
63-
"files": [
64-
"test/unit/*.js"
65-
],
66-
"verbose": true
67-
},
6862
"tsd": {
6963
"directory": "test/types/"
7064
},
@@ -86,15 +80,15 @@
8680
"@commitlint/cli": "^17.0.0",
8781
"@commitlint/config-conventional": "^17.0.0",
8882
"@netlify/eslint-config-node": "^7.0.1",
89-
"ava": "^2.4.0",
83+
"@types/semver": "^7.5.8",
9084
"husky": "^7.0.4",
9185
"npm-run-all2": "^5.0.0",
92-
"nyc": "^15.0.0",
9386
"publint": "^0.2.7",
9487
"semver": "^7.5.4",
9588
"tsd": "^0.31.0",
9689
"tsup": "^8.0.2",
97-
"typescript": "^4.4.4"
90+
"typescript": "^4.4.4",
91+
"vitest": "^2.1.8"
9892
},
9993
"engines": {
10094
"node": ">=14.0.0"

test/unit/builder.js renamed to src/lib/builder.test.ts

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
1-
const test = require('ava')
1+
import { expect, test } from 'vitest'
22

3-
const { builder } = require('../../dist/lib/builder')
4-
const { invokeLambda } = require('../helpers/main')
3+
import { invokeLambda } from '../../test/helpers/main.mjs'
4+
import { BaseHandler } from '../function/handler.js'
5+
import { HandlerEvent } from '../main.js'
6+
7+
import { builder } from './builder.js'
58

69
const METADATA_OBJECT = { metadata: { version: 1, builder_function: true, ttl: 0 } }
710

8-
test('Injects the metadata object into an asynchronous handler', async (t) => {
11+
test('Injects the metadata object into an asynchronous handler', async () => {
12+
const ttl = 3600
913
const originalResponse = {
1014
body: ':thumbsup:',
1115
statusCode: 200,
12-
ttl: 3600,
16+
ttl,
1317
}
1418
const myHandler = async () => {
1519
const asyncTask = new Promise((resolve) => {
@@ -22,23 +26,25 @@ test('Injects the metadata object into an asynchronous handler', async (t) => {
2226
}
2327
const response = await invokeLambda(builder(myHandler))
2428

25-
t.deepEqual(response, { ...originalResponse, metadata: { version: 1, builder_function: true, ttl: 3600 } })
29+
expect(response).toStrictEqual({ ...originalResponse, metadata: { version: 1, builder_function: true, ttl } })
2630
})
2731

28-
test('Injects the metadata object into a synchronous handler', async (t) => {
32+
test('Injects the metadata object into a synchronous handler', async () => {
2933
const originalResponse = {
3034
body: ':thumbsup:',
3135
statusCode: 200,
3236
}
33-
const myHandler = (event, context, callback) => {
34-
callback(null, originalResponse)
37+
// eslint-disable-next-line promise/prefer-await-to-callbacks
38+
const myHandler: BaseHandler = (event, context, callback) => {
39+
// eslint-disable-next-line n/callback-return, promise/prefer-await-to-callbacks
40+
callback?.(null, originalResponse)
3541
}
3642
const response = await invokeLambda(builder(myHandler))
3743

38-
t.deepEqual(response, { ...originalResponse, ...METADATA_OBJECT })
44+
expect(response).toStrictEqual({ ...originalResponse, ...METADATA_OBJECT })
3945
})
4046

41-
test('Injects the metadata object for non-200 responses', async (t) => {
47+
test('Injects the metadata object for non-200 responses', async () => {
4248
const originalResponse = {
4349
body: ':thumbsdown:',
4450
statusCode: 404,
@@ -54,10 +60,10 @@ test('Injects the metadata object for non-200 responses', async (t) => {
5460
}
5561
const response = await invokeLambda(builder(myHandler))
5662

57-
t.deepEqual(response, { ...originalResponse, ...METADATA_OBJECT })
63+
expect(response).toStrictEqual({ ...originalResponse, ...METADATA_OBJECT })
5864
})
5965

60-
test('Returns a 405 error for requests using the POST method', async (t) => {
66+
test('Returns a 405 error for requests using the POST method', async () => {
6167
const originalResponse = {
6268
body: ':thumbsup:',
6369
statusCode: 200,
@@ -73,10 +79,10 @@ test('Returns a 405 error for requests using the POST method', async (t) => {
7379
}
7480
const response = await invokeLambda(builder(myHandler), { method: 'POST' })
7581

76-
t.deepEqual(response, { body: 'Method Not Allowed', statusCode: 405 })
82+
expect(response).toStrictEqual({ body: 'Method Not Allowed', statusCode: 405 })
7783
})
7884

79-
test('Returns a 405 error for requests using the PUT method', async (t) => {
85+
test('Returns a 405 error for requests using the PUT method', async () => {
8086
const originalResponse = {
8187
body: ':thumbsup:',
8288
statusCode: 200,
@@ -92,10 +98,10 @@ test('Returns a 405 error for requests using the PUT method', async (t) => {
9298
}
9399
const response = await invokeLambda(builder(myHandler), { method: 'PUT' })
94100

95-
t.deepEqual(response, { body: 'Method Not Allowed', statusCode: 405 })
101+
expect(response).toStrictEqual({ body: 'Method Not Allowed', statusCode: 405 })
96102
})
97103

98-
test('Returns a 405 error for requests using the DELETE method', async (t) => {
104+
test('Returns a 405 error for requests using the DELETE method', async () => {
99105
const originalResponse = {
100106
body: ':thumbsup:',
101107
statusCode: 200,
@@ -111,10 +117,10 @@ test('Returns a 405 error for requests using the DELETE method', async (t) => {
111117
}
112118
const response = await invokeLambda(builder(myHandler), { method: 'DELETE' })
113119

114-
t.deepEqual(response, { body: 'Method Not Allowed', statusCode: 405 })
120+
expect(response).toStrictEqual({ body: 'Method Not Allowed', statusCode: 405 })
115121
})
116122

117-
test('Returns a 405 error for requests using the PATCH method', async (t) => {
123+
test('Returns a 405 error for requests using the PATCH method', async () => {
118124
const originalResponse = {
119125
body: ':thumbsup:',
120126
statusCode: 200,
@@ -130,12 +136,13 @@ test('Returns a 405 error for requests using the PATCH method', async (t) => {
130136
}
131137
const response = await invokeLambda(builder(myHandler), { method: 'PATCH' })
132138

133-
t.deepEqual(response, { body: 'Method Not Allowed', statusCode: 405 })
139+
expect(response).toStrictEqual({ body: 'Method Not Allowed', statusCode: 405 })
134140
})
135141

136-
test('Preserves errors thrown inside the wrapped handler', async (t) => {
142+
test('Preserves errors thrown inside the wrapped handler', async () => {
137143
const error = new Error('Uh-oh!')
138144

145+
// @ts-expect-error There's no type for this custom property.
139146
error.someProperty = ':thumbsdown:'
140147

141148
const myHandler = async () => {
@@ -148,27 +155,32 @@ test('Preserves errors thrown inside the wrapped handler', async (t) => {
148155
throw error
149156
}
150157

151-
await t.throwsAsync(invokeLambda(builder(myHandler)), { is: error })
158+
try {
159+
await invokeLambda(builder(myHandler))
160+
161+
throw new Error('Invocation should have failed')
162+
} catch {}
152163
})
153164

154-
test('Does not pass query parameters to the wrapped handler', async (t) => {
165+
test('Does not pass query parameters to the wrapped handler', async () => {
155166
const originalResponse = {
156167
body: ':thumbsup:',
157168
statusCode: 200,
158169
}
159170
// eslint-disable-next-line require-await
160-
const myHandler = async (event) => {
161-
t.deepEqual(event.multiValueQueryStringParameters, {})
162-
t.deepEqual(event.queryStringParameters, {})
171+
const myHandler = async (event: HandlerEvent) => {
172+
expect(event.multiValueQueryStringParameters).toStrictEqual({})
173+
expect(event.queryStringParameters).toStrictEqual({})
163174

164175
return originalResponse
165176
}
166177
const multiValueQueryStringParameters = { foo: ['bar'], bar: ['baz'] }
167178
const queryStringParameters = { foo: 'bar', bar: 'baz' }
168179
const response = await invokeLambda(builder(myHandler), {
180+
// @ts-expect-error TODO: Fic types.
169181
multiValueQueryStringParameters,
170182
queryStringParameters,
171183
})
172184

173-
t.deepEqual(response, { ...originalResponse, ...METADATA_OBJECT })
185+
expect(response).toStrictEqual({ ...originalResponse, ...METADATA_OBJECT })
174186
})
Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,31 @@
1-
const process = require('process')
1+
import process from 'node:process'
22

3-
const test = require('ava')
4-
const semver = require('semver')
3+
import semver from 'semver'
4+
import { beforeEach, afterEach, expect, test } from 'vitest'
55

6-
const { purgeCache } = require('../../dist/lib/purge_cache')
7-
const { invokeLambda } = require('../helpers/main')
8-
const MockFetch = require('../helpers/mock_fetch')
6+
import { invokeLambda } from '../../test/helpers/main.mjs'
7+
import { MockFetch } from '../../test/helpers/mock_fetch.mjs'
8+
9+
import { purgeCache } from './purge_cache.js'
910

1011
const globalFetch = globalThis.fetch
1112
const hasFetchAPI = semver.gte(process.version, '18.0.0')
1213

13-
test.beforeEach(() => {
14+
beforeEach(() => {
1415
delete process.env.NETLIFY_PURGE_API_TOKEN
1516
delete process.env.SITE_ID
1617
delete process.env.NETLIFY_LOCAL
1718
})
1819

19-
test.afterEach(() => {
20+
afterEach(() => {
2021
globalThis.fetch = globalFetch
2122
})
2223

23-
test.serial('Calls the purge API endpoint and returns `undefined` if the operation was successful', async (t) => {
24+
test('Calls the purge API endpoint and returns `undefined` if the operation was successful', async () => {
2425
if (!hasFetchAPI) {
2526
console.warn('Skipping test requires the fetch API')
2627

27-
return t.pass()
28+
return
2829
}
2930

3031
const mockSiteID = '123456789'
@@ -34,16 +35,17 @@ test.serial('Calls the purge API endpoint and returns `undefined` if the operati
3435
process.env.SITE_ID = mockSiteID
3536

3637
const mockAPI = new MockFetch().post({
37-
body: (payload) => {
38+
body: (payload: string) => {
3839
const data = JSON.parse(payload)
3940

40-
t.is(data.site_id, mockSiteID)
41+
expect(data.site_id).toBe(mockSiteID)
4142
},
4243
headers: { Authorization: `Bearer ${mockToken}` },
4344
method: 'post',
4445
response: new Response(null, { status: 202 }),
4546
url: `https://api.netlify.com/api/v1/purge`,
4647
})
48+
// eslint-disable-next-line unicorn/consistent-function-scoping
4749
const myFunction = async () => {
4850
await purgeCache()
4951
}
@@ -52,15 +54,13 @@ test.serial('Calls the purge API endpoint and returns `undefined` if the operati
5254

5355
const response = await invokeLambda(myFunction)
5456

55-
t.is(response, undefined)
56-
t.true(mockAPI.fulfilled)
57+
expect(response).toBeUndefined()
58+
expect(mockAPI.fulfilled).toBeTruthy()
5759
})
5860

59-
test.serial('Throws if the API response does not have a successful status code', async (t) => {
61+
test('Throws if the API response does not have a successful status code', async () => {
6062
if (!hasFetchAPI) {
6163
console.warn('Skipping test requires the fetch API')
62-
63-
return t.pass()
6464
}
6565

6666
const mockSiteID = '123456789'
@@ -70,42 +70,49 @@ test.serial('Throws if the API response does not have a successful status code',
7070
process.env.SITE_ID = mockSiteID
7171

7272
const mockAPI = new MockFetch().post({
73-
body: (payload) => {
73+
body: (payload: string) => {
7474
const data = JSON.parse(payload)
7575

76-
t.is(data.site_id, mockSiteID)
76+
expect(data.site_id).toBe(mockSiteID)
7777
},
7878
headers: { Authorization: `Bearer ${mockToken}` },
7979
method: 'post',
8080
response: new Response(null, { status: 500 }),
8181
url: `https://api.netlify.com/api/v1/purge`,
8282
})
83+
// eslint-disable-next-line unicorn/consistent-function-scoping
8384
const myFunction = async () => {
8485
await purgeCache()
8586
}
8687

8788
globalThis.fetch = mockAPI.fetcher
8889

89-
await t.throwsAsync(
90-
async () => await invokeLambda(myFunction),
91-
'Cache purge API call returned an unexpected status code: 500',
92-
)
90+
try {
91+
await invokeLambda(myFunction)
92+
93+
throw new Error('Invocation should have failed')
94+
} catch (error) {
95+
expect((error as NodeJS.ErrnoException).message).toBe(
96+
'Cache purge API call returned an unexpected status code: 500',
97+
)
98+
}
9399
})
94100

95-
test.serial('Ignores purgeCache if in local dev with no token or site', async (t) => {
101+
test('Ignores purgeCache if in local dev with no token or site', async () => {
96102
if (!hasFetchAPI) {
97103
console.warn('Skipping test requires the fetch API')
98104

99-
return t.pass()
105+
return
100106
}
101107

102108
process.env.NETLIFY_LOCAL = '1'
103109

104110
const mockAPI = new MockFetch().post({
105111
body: () => {
106-
t.fail()
107-
}
112+
throw new Error('Unexpected request')
113+
},
108114
})
115+
// eslint-disable-next-line unicorn/consistent-function-scoping
109116
const myFunction = async () => {
110117
await purgeCache()
111118
}
@@ -114,5 +121,5 @@ test.serial('Ignores purgeCache if in local dev with no token or site', async (t
114121

115122
const response = await invokeLambda(myFunction)
116123

117-
t.is(response, undefined)
124+
expect(response).toBeUndefined()
118125
})

0 commit comments

Comments
 (0)