summaryrefslogtreecommitdiff
path: root/packages/integrations/node/test/api-route.test.js
blob: 313819188015bd52162f50c1126d46e71bab2068 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import nodejs from '../dist/index.js';
import { loadFixture, createRequestAndResponse } from './test-utils.js';
import { expect } from 'chai';
import crypto from 'node:crypto';

describe('API routes', () => {
	/** @type {import('./test-utils').Fixture} */
	let fixture;

	before(async () => {
		fixture = await loadFixture({
			root: './fixtures/api-route/',
			output: 'server',
			adapter: nodejs({ mode: 'middleware' }),
		});
		await fixture.build();
	});

	it('Can get the request body', async () => {
		const { handler } = await import('./fixtures/api-route/dist/server/entry.mjs');
		let { req, res, done } = createRequestAndResponse({
			method: 'POST',
			url: '/recipes',
		});

		req.once('async_iterator', () => {
			req.send(JSON.stringify({ id: 2 }));
		});

		handler(req, res);

		let [buffer] = await done;

		let json = JSON.parse(buffer.toString('utf-8'));

		expect(json.length).to.equal(1);

		expect(json[0].name).to.equal('Broccoli Soup');
	});

	it('Can get binary data', async () => {
		const { handler } = await import('./fixtures/api-route/dist/server/entry.mjs');

		let { req, res, done } = createRequestAndResponse({
			method: 'POST',
			url: '/binary',
		});

		req.once('async_iterator', () => {
			req.send(Buffer.from(new Uint8Array([1, 2, 3, 4, 5])));
		});

		handler(req, res);

		let [out] = await done;
		let arr = Array.from(new Uint8Array(out.buffer));
		expect(arr).to.deep.equal([5, 4, 3, 2, 1]);
	});

	it('Can post large binary data', async () => {
		const { handler } = await import('./fixtures/api-route/dist/server/entry.mjs');

		let { req, res, done } = createRequestAndResponse({
			method: 'POST',
			url: '/hash',
		});

		handler(req, res);

		let expectedDigest = null;
		req.once('async_iterator', () => {
			// Send 256MB of garbage data in 256KB chunks. This should be fast (< 1sec).
			let remainingBytes = 256 * 1024 * 1024;
			const chunkSize = 256 * 1024;

			const hash = crypto.createHash('sha256');
			while (remainingBytes > 0) {
				const size = Math.min(remainingBytes, chunkSize);
				const chunk = Buffer.alloc(size, Math.floor(Math.random() * 256));
				hash.update(chunk);
				req.emit('data', chunk);
				remainingBytes -= size;
			}

			req.emit('end');
			expectedDigest = hash.digest();
		});

		let [out] = await done;
		expect(new Uint8Array(out.buffer)).to.deep.equal(expectedDigest);
	});

	it('Can bail on streaming', async () => {
		const { handler } = await import('./fixtures/api-route/dist/server/entry.mjs');
		let { req, res, done } = createRequestAndResponse({
			url: '/streaming',
		});

		let locals = { cancelledByTheServer: false };

		handler(req, res, () => {}, locals);
		req.send();

		await new Promise((resolve) => setTimeout(resolve, 500));
		res.emit('close');

		await done;

		expect(locals).to.deep.include({ cancelledByTheServer: true });
	});
});