Skip to content

Commit

Permalink
chore: add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
eduardoboucas committed Oct 11, 2023
1 parent e70b66f commit 542c520
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 1 deletion.
2 changes: 2 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ module.exports = {
files: 'test/**/*.+(t|j)s',
rules: {
'no-magic-numbers': 'off',
'no-undef': 'off',
'promise/prefer-await-to-callbacks': 'off',
'unicorn/filename-case': 'off',
'unicorn/consistent-function-scoping': 'off',
},
},
],
Expand Down
74 changes: 74 additions & 0 deletions test/helpers/mock_fetch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
const assert = require('assert')

module.exports = class MockFetch {
constructor() {
this.requests = []
}

addExpectedRequest({ body, headers = {}, method, response, url }) {
this.requests.push({ body, fulfilled: false, headers, method, response, url })

return this
}

delete(options) {
return this.addExpectedRequest({ ...options, method: 'delete' })
}

get(options) {
return this.addExpectedRequest({ ...options, method: 'get' })
}

post(options) {
return this.addExpectedRequest({ ...options, method: 'post' })
}

put(options) {
return this.addExpectedRequest({ ...options, method: 'put' })
}

get fetcher() {
// eslint-disable-next-line require-await
return async (...args) => {
const [url, options] = args
const headers = options?.headers
const urlString = url.toString()
const match = this.requests.find(
(request) =>
request.method.toLowerCase() === options?.method.toLowerCase() &&
request.url === urlString &&
!request.fulfilled,
)

if (!match) {
throw new Error(`Unexpected fetch call: ${url}`)
}

for (const key in match.headers) {
assert.equal(headers[key], match.headers[key])
}

if (typeof match.body === 'string') {
assert.equal(options?.body, match.body)
} else if (typeof match.body === 'function') {
const bodyFn = match.body

bodyFn(options?.body)
} else {
assert.equal(options?.body, undefined)
}

match.fulfilled = true

if (match.response instanceof Error) {
throw match.response
}

return match.response
}
}

get fulfilled() {
return this.requests.every((request) => request.fulfilled)
}
}
2 changes: 1 addition & 1 deletion test/types/Handler.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Handler } from '../../src/main.js'

// Ensure void is NOT a valid return type in async handlers
expectError(() => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars, unicorn/consistent-function-scoping
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const handler: Handler = async () => {
// void
}
Expand Down
78 changes: 78 additions & 0 deletions test/unit/purge_cache.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
const process = require('process')

const test = require('ava')

const { purgeCache } = require('../../dist/lib/purge_cache')
const { invokeLambda } = require('../helpers/main')
const MockFetch = require('../helpers/mock_fetch')

const globalFetch = globalThis.fetch

test.beforeEach(() => {
delete process.env.NETLIFY_PURGE_API_TOKEN
delete process.env.SITE_ID
})

test.afterEach(() => {
globalThis.fetch = globalFetch
})

test.serial('Calls the purge API endpoint and returns `undefined` if the operation was successful', async (t) => {
const mockSiteID = '123456789'
const mockToken = '1q2w3e4r5t6y7u8i9o0p'

process.env.NETLIFY_PURGE_API_TOKEN = mockToken
process.env.SITE_ID = mockSiteID

const mockAPI = new MockFetch().post({
body: (payload) => {
const data = JSON.parse(payload)

t.is(data.site_id, mockSiteID)
},
headers: { Authorization: `Bearer ${mockToken}` },
method: 'post',
response: new Response(null, { status: 202 }),
url: `https://api.netlify.com/api/v1/purge`,
})
const myFunction = async () => {
await purgeCache()
}

globalThis.fetch = mockAPI.fetcher

const response = await invokeLambda(myFunction)

t.is(response, undefined)
t.true(mockAPI.fulfilled)
})

test.serial('Throws if the API response does not have a successful status code', async (t) => {
const mockSiteID = '123456789'
const mockToken = '1q2w3e4r5t6y7u8i9o0p'

process.env.NETLIFY_PURGE_API_TOKEN = mockToken
process.env.SITE_ID = mockSiteID

const mockAPI = new MockFetch().post({
body: (payload) => {
const data = JSON.parse(payload)

t.is(data.site_id, mockSiteID)
},
headers: { Authorization: `Bearer ${mockToken}` },
method: 'post',
response: new Response(null, { status: 500 }),
url: `https://api.netlify.com/api/v1/purge`,
})
const myFunction = async () => {
await purgeCache()
}

globalThis.fetch = mockAPI.fetcher

await t.throwsAsync(
async () => await invokeLambda(myFunction),
'Cache purge API call returned an unexpected status code: 500',
)
})

0 comments on commit 542c520

Please sign in to comment.