mappersmith
Version:
It is a lightweight rest client for node.js and the browser
272 lines (248 loc) • 10.1 kB
text/typescript
import forge from '../index'
import type { Middleware } from './index'
import { install, uninstall, mockRequest, m } from '../test/index'
describe('middleware', () => {
beforeAll(install)
afterAll(uninstall)
const host = 'http://example.org'
const path = '/api/test'
describe('prepareRequest', () => {
beforeEach(() => {
mockRequest({
method: 'get',
url: `${host}${path}`,
body: undefined,
headers: {},
response: {
body: { ok: true },
status: 200,
},
})
})
const createContextMiddleware =
(spy: jest.Mock, context: Record<string, unknown>): Middleware =>
() => ({
prepareRequest: async (next) => {
const request = await next()
const contextBefore = request.context()
spy(contextBefore)
const newRequest = request.enhance({}, context)
const contextAfter = newRequest.context()
spy(contextAfter)
return newRequest
},
})
it('invokes middleware and extends request context in given order', async () => {
const spy = jest.fn()
const mw1 = createContextMiddleware(spy, { foo: 'bar' })
const mw2 = createContextMiddleware(spy, { ctx: 'yup' })
const mw3 = createContextMiddleware(spy, { ctx: 'bts' })
const client = forge({
clientId: 'testMw',
middleware: [mw1, mw2, mw3],
host,
resources: { Resource: { find: { path } } },
})
await client.Resource.find()
// mw1 applied
expect(spy).toHaveBeenNthCalledWith(1, {})
expect(spy).toHaveBeenNthCalledWith(2, { foo: 'bar' })
// mw2 applied
expect(spy).toHaveBeenNthCalledWith(3, { foo: 'bar' })
expect(spy).toHaveBeenNthCalledWith(4, { ctx: 'yup', foo: 'bar' })
// mw3 applied
expect(spy).toHaveBeenNthCalledWith(5, { ctx: 'yup', foo: 'bar' })
expect(spy).toHaveBeenNthCalledWith(6, { ctx: 'bts', foo: 'bar' })
})
it('invokes resource specific middleware first', async () => {
const spy = jest.fn()
const mw1 = createContextMiddleware(spy, { foo: 'bar' })
const mw2 = createContextMiddleware(spy, { ctx: 'yup' })
const mw3 = createContextMiddleware(spy, { ctx: 'bts' })
const client = forge({
clientId: 'testMw',
middleware: [mw1, mw3],
host,
resources: { Resource: { find: { path, middleware: [mw2] } } },
})
await client.Resource.find()
// mw2 applied
expect(spy).toHaveBeenNthCalledWith(1, {})
expect(spy).toHaveBeenNthCalledWith(2, { ctx: 'yup' })
// mw1 applied
expect(spy).toHaveBeenNthCalledWith(3, { ctx: 'yup' })
expect(spy).toHaveBeenNthCalledWith(4, { ctx: 'yup', foo: 'bar' })
// mw3 applied
expect(spy).toHaveBeenNthCalledWith(5, { ctx: 'yup', foo: 'bar' })
expect(spy).toHaveBeenNthCalledWith(6, { ctx: 'bts', foo: 'bar' })
})
})
describe('response', () => {
beforeEach(() => {
mockRequest({
method: 'post',
url: `${host}${path}`,
body: m.anything(),
headers: {},
response: {
body: { ok: true },
status: 200,
},
})
})
const createMiddleware =
(spy: jest.Mock, params: Record<string, string>): Middleware =>
() => ({
prepareRequest: async (next) => {
const request = await next()
return request.enhance({}, params)
},
response: async (next, _renew, request) => {
const context = request.context()
spy(params)
spy(context)
const response = await next()
return response
},
})
it('invokes middleware and extends response context in given order', async () => {
const spy = jest.fn()
const mw1 = createMiddleware(spy, { foo: 'mw1' })
const mw2 = createMiddleware(spy, { ctx: 'mw2' })
const mw3 = createMiddleware(spy, { ctx: 'mw3' })
const client = forge({
clientId: 'testMw',
middleware: [mw1, mw2, mw3],
host,
resources: { Resource: { create: { method: 'post', path } } },
})
await client.Resource.create()
// mw3 applied
expect(spy).toHaveBeenNthCalledWith(1, { ctx: 'mw3' })
expect(spy).toHaveBeenNthCalledWith(2, { foo: 'mw1', ctx: 'mw3' })
// mw2 applied
expect(spy).toHaveBeenNthCalledWith(3, { ctx: 'mw2' })
expect(spy).toHaveBeenNthCalledWith(4, { foo: 'mw1', ctx: 'mw3' })
// mw1 applied
expect(spy).toHaveBeenNthCalledWith(5, { foo: 'mw1' })
expect(spy).toHaveBeenNthCalledWith(6, { foo: 'mw1', ctx: 'mw3' })
})
it('invokes resource specific middleware first', async () => {
const spy = jest.fn()
const mw1 = createMiddleware(spy, { foo: 'mw1' })
const mw2 = createMiddleware(spy, { ctx: 'mw2' })
const mw3 = createMiddleware(spy, { ctx: 'mw3' })
const client = forge({
clientId: 'testMw',
middleware: [mw1, mw3],
host,
resources: { Resource: { post: { method: 'post', path, middleware: [mw2] } } },
})
await client.Resource.post()
// mw3 applied
expect(spy).toHaveBeenNthCalledWith(1, { ctx: 'mw3' })
expect(spy).toHaveBeenNthCalledWith(2, { foo: 'mw1', ctx: 'mw3' })
// mw1 applied
expect(spy).toHaveBeenNthCalledWith(3, { foo: 'mw1' })
expect(spy).toHaveBeenNthCalledWith(4, { foo: 'mw1', ctx: 'mw3' })
// mw2 applied
expect(spy).toHaveBeenNthCalledWith(5, { ctx: 'mw2' })
expect(spy).toHaveBeenNthCalledWith(6, { foo: 'mw1', ctx: 'mw3' })
})
})
describe('both', () => {
beforeEach(() => {
mockRequest({
method: 'post',
url: `${host}${path}`,
body: m.anything(),
headers: {},
response: {
body: { ok: true },
status: 200,
},
})
})
const createMiddleware =
(
prepareRequestSpy: jest.Mock,
responseSpy: jest.Mock,
beforeParams: Record<string, string>,
afterParams: Record<string, string>
): Middleware =>
() => ({
prepareRequest: async (next) => {
prepareRequestSpy(beforeParams)
const request = await next()
prepareRequestSpy(afterParams)
return request
},
response: async (next) => {
responseSpy(beforeParams)
const response = await next()
responseSpy(afterParams)
return response
},
})
it('invokes middleware and extends response context in given order', async () => {
const prepareRequestSpy = jest.fn()
const responseSpy = jest.fn()
const mw1 = createMiddleware(prepareRequestSpy, responseSpy, { foo: 'mw1' }, { bar: 'mw1' })
const mw2 = createMiddleware(prepareRequestSpy, responseSpy, { ctx: 'mw2' }, { fizz: 'mw2' })
const mw3 = createMiddleware(prepareRequestSpy, responseSpy, { ctx: 'mw3' }, { buzz: 'mw3' })
const client = forge({
clientId: 'testMw',
middleware: [mw1, mw2, mw3],
host,
resources: { Resource: { create: { method: 'post', path } } },
})
await client.Resource.create()
// order of prepareRequest
expect(prepareRequestSpy).toHaveBeenCalledTimes(6)
expect(prepareRequestSpy).toHaveBeenNthCalledWith(1, { ctx: 'mw3' })
expect(prepareRequestSpy).toHaveBeenNthCalledWith(2, { ctx: 'mw2' })
expect(prepareRequestSpy).toHaveBeenNthCalledWith(3, { foo: 'mw1' })
expect(prepareRequestSpy).toHaveBeenNthCalledWith(4, { bar: 'mw1' })
expect(prepareRequestSpy).toHaveBeenNthCalledWith(5, { fizz: 'mw2' })
expect(prepareRequestSpy).toHaveBeenNthCalledWith(6, { buzz: 'mw3' })
// order of response
expect(responseSpy).toHaveBeenCalledTimes(6)
expect(responseSpy).toHaveBeenNthCalledWith(1, { ctx: 'mw3' })
expect(responseSpy).toHaveBeenNthCalledWith(2, { ctx: 'mw2' })
expect(responseSpy).toHaveBeenNthCalledWith(3, { foo: 'mw1' })
expect(responseSpy).toHaveBeenNthCalledWith(4, { bar: 'mw1' })
expect(responseSpy).toHaveBeenNthCalledWith(5, { fizz: 'mw2' })
expect(responseSpy).toHaveBeenNthCalledWith(6, { buzz: 'mw3' })
})
it('invokes resource specific middleware first', async () => {
const prepareRequestSpy = jest.fn()
const responseSpy = jest.fn()
const mw1 = createMiddleware(prepareRequestSpy, responseSpy, { foo: 'mw1' }, { bar: 'mw1' })
const mw2 = createMiddleware(prepareRequestSpy, responseSpy, { ctx: 'mw2' }, { fizz: 'mw2' })
const mw3 = createMiddleware(prepareRequestSpy, responseSpy, { ctx: 'mw3' }, { buzz: 'mw3' })
const client = forge({
clientId: 'testMw',
middleware: [mw1, mw3],
host,
resources: { Resource: { post: { method: 'post', path, middleware: [mw2] } } },
})
await client.Resource.post()
// order of prepareRequest
expect(prepareRequestSpy).toHaveBeenCalledTimes(6)
expect(prepareRequestSpy).toHaveBeenNthCalledWith(1, { ctx: 'mw3' })
expect(prepareRequestSpy).toHaveBeenNthCalledWith(2, { foo: 'mw1' })
expect(prepareRequestSpy).toHaveBeenNthCalledWith(3, { ctx: 'mw2' })
expect(prepareRequestSpy).toHaveBeenNthCalledWith(4, { fizz: 'mw2' })
expect(prepareRequestSpy).toHaveBeenNthCalledWith(5, { bar: 'mw1' })
expect(prepareRequestSpy).toHaveBeenNthCalledWith(6, { buzz: 'mw3' })
// order of response
expect(responseSpy).toHaveBeenCalledTimes(6)
expect(responseSpy).toHaveBeenNthCalledWith(1, { ctx: 'mw3' })
expect(responseSpy).toHaveBeenNthCalledWith(2, { foo: 'mw1' })
expect(responseSpy).toHaveBeenNthCalledWith(3, { ctx: 'mw2' })
expect(responseSpy).toHaveBeenNthCalledWith(4, { fizz: 'mw2' })
expect(responseSpy).toHaveBeenNthCalledWith(5, { bar: 'mw1' })
expect(responseSpy).toHaveBeenNthCalledWith(6, { buzz: 'mw3' })
})
})
})