Skip to content

Commit

Permalink
test(webhooks): add tests for webhooks and macros using them
Browse files Browse the repository at this point in the history
  • Loading branch information
benforshey committed Nov 20, 2024
1 parent 1ecf685 commit 2378672
Show file tree
Hide file tree
Showing 3 changed files with 208 additions and 0 deletions.
76 changes: 76 additions & 0 deletions packages/app/macros/__tests__/macros.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import { getModel } from '../../models/service'
import GLDAS_CLM10SUBP_3H_001 from '../../models/__tests__/__fixtures__/collection-metadata/GLDAS_CLM10SUBP_3H_001.json'
import OML1BRVG_003 from '../../models/__tests__/__fixtures__/collection-metadata/OML1BRVG_003.json'
import collectionMetadataModel from '../../models/__tests__/__fixtures__/models/collection-metadata.json'
import { getAllWebhookURLs } from '../service'
import faqsModelWithOneMacro from './__fixtures__/faqs-model-one-macro.json'

describe('Template Macros', () => {
const env = process.env
let db

beforeAll(async () => {
Expand All @@ -23,6 +25,14 @@ describe('Template Macros', () => {
await db.collection('Collection Metadata').deleteMany({})
})

beforeEach(() => {
process.env = { ...env }
})

afterEach(() => {
process.env = { ...env }
})

describe('list', () => {
it('gets values from the path to populate the schema', async () => {
const [error, model] = await getModel('FAQs', {
Expand Down Expand Up @@ -75,4 +85,70 @@ describe('Template Macros', () => {
`)
})
})

describe('webhooks', () => {
test('gets webhook URLs as ErrorData', async () => {
// NOTE: this line needs to be left as escaped JSON.
// prettier-ignore
process.env.UI_WEBHOOKS =
"[{\"token\":\"an-example-token-for-endpoint-1\",\"URL\":\"http://example.com/1\"}]"

const [error, webhookURLs] = await getAllWebhookURLs()

expect(error).toBeNull()
expect(webhookURLs).toMatchInlineSnapshot(`
Array [
"http://example.com/1",
]
`)
})

test('requires escaped JSON only because the env parser does', async () => {
process.env.UI_WEBHOOKS =
'[{"token":"an-example-token-for-endpoint-1","URL":"http://example.com/1"}]'

const [stringError, stringWebhookURLs] = await getAllWebhookURLs()

expect(stringError).toBeNull()
expect(stringWebhookURLs).toMatchInlineSnapshot(`
Array [
"http://example.com/1",
]
`)

// @ts-ignore
process.env.UI_WEBHOOKS = [
{
token: 'an-example-token-for-endpoint-1',
URL: 'http://example.com/1',
},
]

const [literalError, literalWebhookURLs] = await getAllWebhookURLs()

expect(literalError).toBeNull()
expect(literalWebhookURLs).toMatchInlineSnapshot(`
Array [
"http://example.com/1",
]
`)
})

test('handles unset and nullish env values', async () => {
process.env.UI_WEBHOOKS = null

const [nullError, nullWebhookURLs] = await getAllWebhookURLs()

expect(nullError).toBeNull()
expect(nullWebhookURLs).toMatchInlineSnapshot(`Array []`)

// @ts-ignore
delete process.env.UI_WEBHOOKS

const [unsetError, unsetWebhookURLs] = await getAllWebhookURLs()

expect(unsetError).toBeNull()
expect(unsetWebhookURLs).toMatchInlineSnapshot(`Array []`)
})
})
})
37 changes: 37 additions & 0 deletions packages/app/utils/__tests__/api.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { parseResponse } from '../api'

describe('parseResponse', () => {
const responseMock = {
headers: null,
async json() {
return { foo: 'bar' }
},
async text() {
return 'foo is bar'
},
} as unknown as Response

beforeAll(() => {
// @ts-ignore
responseMock.headers = new Map()
})

test('reads Content-Type header to determine parse type', async () => {
responseMock.headers.set('content-type', 'text/plain; charset=utf-8')
const resultText = await parseResponse(responseMock)
expect(resultText).toEqual(await responseMock.text())

responseMock.headers.set('content-type', 'application/json; charset=utf-8')
const resultJSON = await parseResponse(responseMock)
expect(resultJSON).toEqual(await responseMock.json())
})

test('defaults to text()', async () => {
responseMock.headers.set(
'content-type',
'multipart/form-data; boundary=ExampleBoundaryString'
)
const resultText = await parseResponse(responseMock)
expect(resultText).toEqual(await responseMock.text())
})
})
95 changes: 95 additions & 0 deletions packages/app/webhooks/__tests__/webhooks.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import type { ModelWithWorkflow } from '../../models/types'
import { getAllWebhookConfigs, getWebhookConfig, invokeWebhook } from '../service'

describe('Webhook Service', () => {
const env = process.env

beforeAll(() => {
global.fetch = jest.fn(() =>
Promise.resolve({
headers: {
get() {
return 'text/plain; charset=utf-8'
},
},
ok: true,
json: () => Promise.resolve({ foo: 'bar' }),
text: () => Promise.resolve('foo is bar'),
})
) as jest.Mock
})

beforeEach(() => {
process.env = { ...env }
})

afterEach(() => {
process.env = { ...env }
})

describe('getAllWebhookConfigs', () => {
test('gets all webhook configs as ErrorData', () => {
// NOTE: this line needs to be left as escaped JSON.
// prettier-ignore
process.env.UI_WEBHOOKS =
"[{\"token\":\"an-example-token-for-endpoint-1\",\"URL\":\"http://example.com/1\"}, {\"token\":\"an-example-token-for-endpoint-2\",\"URL\":\"http://example.com/2\"}]"

const [error, data] = getAllWebhookConfigs()

expect(error).toBeNull()
expect(data).toMatchInlineSnapshot(`
Array [
Object {
"URL": "http://example.com/1",
"token": "an-example-token-for-endpoint-1",
},
Object {
"URL": "http://example.com/2",
"token": "an-example-token-for-endpoint-2",
},
]
`)
})
})

describe('getWebhookConfig', () => {
test('gets webhook config, matching by URL', () => {
// NOTE: this line needs to be left as escaped JSON.
// prettier-ignore
process.env.UI_WEBHOOKS =
"[{\"token\":\"an-example-token-for-endpoint-1\",\"URL\":\"http://example.com/1\"}, {\"token\":\"an-example-token-for-endpoint-2\",\"URL\":\"http://example.com/2\"}]"

const [error, data] = getWebhookConfig('http://example.com/2')

expect(error).toBeNull()
expect(data).toMatchInlineSnapshot(`
Object {
"URL": "http://example.com/2",
"token": "an-example-token-for-endpoint-2",
}
`)
})
})

describe('invokeWebhook', () => {
test('invokes (fetches) a webhook URL', async () => {
const fetchSpy = jest.spyOn(global, 'fetch')
// NOTE: this line needs to be left as escaped JSON.
// prettier-ignore
process.env.UI_WEBHOOKS =
"[{\"token\":\"an-example-token-for-endpoint-1\",\"URL\":\"http://example.com/1\"}, {\"token\":\"an-example-token-for-endpoint-2\",\"URL\":\"http://example.com/2\"}]"

const [configError, webhook] = getWebhookConfig('http://example.com/2')
const [error, result] = await invokeWebhook(webhook, {
model: {} as ModelWithWorkflow,
document: {},
state: 'Draft',
})

expect(configError).toBeNull()
expect(error).toBeNull()
expect(result).toMatchInlineSnapshot(`"foo is bar"`)
expect(fetchSpy).toHaveBeenCalledTimes(1)
})
})
})

0 comments on commit 2378672

Please sign in to comment.