/**
* @vitest-environment jsdom
*/
import 'whatwg-fetch';
import { describe, it, expect, vitest, beforeAll, afterAll } from 'vitest';
import getPort from 'get-port';
import cors from 'cors';
import express from 'express';
import { createFetchApi } from './create';
describe('Create fetch API Module', () => {
let terminate = () => {};
let port: number;
beforeAll(async () => {
const app = express();
port = await getPort();
app.use(cors());
app.get('/json', (_, res) => {
res.json([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
});
app.get('/xml', (_, res) => {
res.set('Content-Type', 'text/xml');
res.send(
Buffer.from(`
Tove
Jani
Reminder
Don't forget me this weekend!
`),
);
});
let server = app.listen(port);
terminate = () => server.close();
});
afterAll(() => terminate());
it('works with default options against a JSON API', async () => {
const context = { emit: vitest.fn() } as any;
const { fetch } = createFetchApi({
base: `http://localhost:${port}`,
})(context) as any;
const response = await fetch('json');
const result = response.body;
expect(Array.isArray(result)).toBeTruthy();
expect(result.length).toBe(10);
expect(result[0]).toBe(1);
});
it('interprets the result as text if explicitly used despite JSON API', async () => {
const context = { emit: vitest.fn() } as any;
const { fetch } = createFetchApi({
base: `http://localhost:${port}`,
})(context) as any;
const response = await fetch('json', { result: 'text' });
const result = response.body;
expect(typeof result).toBe('string');
expect(Array.isArray(JSON.parse(result))).toBeTruthy();
});
it('has the correct response code', async () => {
const context = { emit: vitest.fn() } as any;
const { fetch } = createFetchApi({
base: `http://localhost:${port}`,
})(context) as any;
const response = await fetch('json');
const result = response.code;
expect(result).toBe(200);
});
it('works with default options against a non-JSON API', async () => {
const context = { emit: vitest.fn() } as any;
const { fetch } = createFetchApi({
base: `http://localhost:${port}`,
})(context) as any;
const response = await fetch('xml');
const result = response.body;
expect(result.substr(0, 5)).toBe(` {
const context = { emit: vitest.fn() } as any;
const middleware = vitest.fn((path, options, next) => next(path, options));
const { fetch } = createFetchApi({
base: `http://localhost:${port}`,
middlewares: [middleware],
})(context) as any;
const response = await fetch('json');
const result = response.body;
expect(Array.isArray(result)).toBeTruthy();
expect(result.length).toBe(10);
expect(result[0]).toBe(1);
expect(middleware).toHaveBeenCalledOnce();
});
it('invokes middleware functions in top-down order', async () => {
const context = { emit: vitest.fn() } as any;
const invocationOrder: Array = [];
const createMiddleware = (myPosition: number) => (path: string, options: any, next: any) => {
invocationOrder.push(myPosition);
return next(path, options);
};
const { fetch } = createFetchApi({
base: `http://localhost:${port}`,
middlewares: [createMiddleware(1), createMiddleware(2), createMiddleware(3)],
})(context) as any;
await fetch('json');
expect(invocationOrder).toEqual([1, 2, 3]);
});
it('allows middleware functions to terminate middleware chain', async () => {
const context = { emit: vitest.fn() } as any;
const expectedResponse = { code: 200, body: 'Terminated by middleware', text: 'Terminated by middleware' };
const middleware = () => Promise.resolve(expectedResponse);
const { fetch } = createFetchApi({
base: `http://localhost:${port}`,
middlewares: [middleware],
})(context) as any;
const globalFetch = vitest.spyOn(global, 'fetch');
const response = await fetch('json');
expect(response).toBe(expectedResponse);
expect(globalFetch).not.toHaveBeenCalled();
});
});