diff --git a/test/client-fetch.js b/test/client-fetch.js deleted file mode 100644 index d94aa3cf525..00000000000 --- a/test/client-fetch.js +++ /dev/null @@ -1,328 +0,0 @@ -/* globals AbortController */ - -'use strict' - -const { test } = require('tap') -const { createServer } = require('http') -const nodeMajor = Number(process.versions.node.split('.')[0]) -const { ReadableStream } = require('stream/web') -const { Blob } = require('buffer') - -test('fetch', { - skip: nodeMajor < 16 -}, t => { - const { fetch, Response, Request, FormData, File } = require('..') - - t.test('request json', (t) => { - t.plan(1) - - const obj = { asd: true } - const server = createServer((req, res) => { - res.end(JSON.stringify(obj)) - }) - t.teardown(server.close.bind(server)) - - server.listen(0, async () => { - const body = await fetch(`http://localhost:${server.address().port}`) - t.strictSame(obj, await body.json()) - }) - }) - - t.test('request text', (t) => { - t.plan(1) - - const obj = { asd: true } - const server = createServer((req, res) => { - res.end(JSON.stringify(obj)) - }) - t.teardown(server.close.bind(server)) - - server.listen(0, async () => { - const body = await fetch(`http://localhost:${server.address().port}`) - t.strictSame(JSON.stringify(obj), await body.text()) - }) - }) - - t.test('request arrayBuffer', (t) => { - t.plan(1) - - const obj = { asd: true } - const server = createServer((req, res) => { - res.end(JSON.stringify(obj)) - }) - t.teardown(server.close.bind(server)) - - server.listen(0, async () => { - const body = await fetch(`http://localhost:${server.address().port}`) - t.strictSame(Buffer.from(JSON.stringify(obj)), Buffer.from(await body.arrayBuffer())) - }) - }) - - t.test('should set type of blob object to the value of the `Content-Type` header from response', (t) => { - t.plan(1) - - const obj = { asd: true } - const server = createServer((req, res) => { - res.setHeader('Content-Type', 'application/json') - res.end(JSON.stringify(obj)) - }) - t.teardown(server.close.bind(server)) - - server.listen(0, async () => { - const response = await fetch(`http://localhost:${server.address().port}`) - t.equal('application/json', (await response.blob()).type) - }) - }) - - t.test('pre aborted with readable request body', (t) => { - t.plan(2) - - const server = createServer((req, res) => { - }) - t.teardown(server.close.bind(server)) - - server.listen(0, async () => { - const ac = new AbortController() - ac.abort() - await fetch(`http://localhost:${server.address().port}`, { - signal: ac.signal, - method: 'POST', - body: new ReadableStream({ - async cancel (reason) { - t.equal(reason.name, 'AbortError') - } - }) - }).catch(err => { - t.equal(err.name, 'AbortError') - }) - }) - }) - - t.test('pre aborted with closed readable request body', (t) => { - t.plan(2) - - const server = createServer((req, res) => { - }) - t.teardown(server.close.bind(server)) - - server.listen(0, async () => { - const ac = new AbortController() - ac.abort() - const body = new ReadableStream({ - async start (c) { - t.pass() - c.close() - }, - async cancel (reason) { - t.fail() - } - }) - queueMicrotask(() => { - fetch(`http://localhost:${server.address().port}`, { - signal: ac.signal, - method: 'POST', - body - }).catch(err => { - t.equal(err.name, 'AbortError') - }) - }) - }) - }) - - t.test('unsupported formData 1', (t) => { - t.plan(1) - - const server = createServer((req, res) => { - res.setHeader('content-type', 'asdasdsad') - res.end() - }) - t.teardown(server.close.bind(server)) - - server.listen(0, () => { - fetch(`http://localhost:${server.address().port}`) - .then(res => res.formData()) - .catch(err => { - t.equal(err.name, 'TypeError') - }) - }) - }) - - t.test('unsupported formData 2', (t) => { - t.plan(1) - - const server = createServer((req, res) => { - res.setHeader('content-type', 'multipart/form-data') - res.end() - }) - t.teardown(server.close.bind(server)) - - server.listen(0, () => { - fetch(`http://localhost:${server.address().port}`) - .then(res => res.formData()) - .catch(err => { - t.equal(err.name, 'NotSupportedError') - }) - }) - }) - - t.test('urlencoded formData', (t) => { - t.plan(2) - - const server = createServer((req, res) => { - res.setHeader('content-type', 'application/x-www-form-urlencoded') - res.end('field1=value1&field2=value2') - }) - t.teardown(server.close.bind(server)) - - server.listen(0, () => { - fetch(`http://localhost:${server.address().port}`) - .then(res => res.formData()) - .then(formData => { - t.equal(formData.get('field1'), 'value1') - t.equal(formData.get('field2'), 'value2') - }) - }) - }) - - t.test('locked blob body', (t) => { - t.plan(1) - - const server = createServer((req, res) => { - res.end() - }) - t.teardown(server.close.bind(server)) - - server.listen(0, async () => { - const res = await fetch(`http://localhost:${server.address().port}`) - const reader = res.body.getReader() - res.blob().catch(err => { - t.equal(err.message, 'locked') - reader.cancel() - }) - }) - }) - - t.test('disturbed blob body', (t) => { - t.plan(2) - - const server = createServer((req, res) => { - res.end() - }) - t.teardown(server.close.bind(server)) - - server.listen(0, async () => { - const res = await fetch(`http://localhost:${server.address().port}`) - res.blob().then(() => { - t.pass(2) - }) - res.blob().catch(err => { - t.equal(err.message, 'disturbed') - }) - }) - }) - - t.test('redirect with body', (t) => { - t.plan(3) - - let count = 0 - const server = createServer(async (req, res) => { - let body = '' - for await (const chunk of req) { - body += chunk - } - t.equal(body, 'asd') - if (count++ === 0) { - res.setHeader('location', 'asd') - res.statusCode = 302 - res.end() - } else { - res.end(String(count)) - } - }) - t.teardown(server.close.bind(server)) - - server.listen(0, async () => { - const res = await fetch(`http://localhost:${server.address().port}`, { - method: 'PUT', - body: 'asd' - }) - t.equal(await res.text(), '2') - }) - }) - - t.test('fail to extract locked body', (t) => { - t.plan(1) - - const stream = new ReadableStream({}) - const reader = stream.getReader() - try { - // eslint-disable-next-line - new Response(stream) - } catch (err) { - t.equal(err.name, 'TypeError') - } - reader.cancel() - }) - - t.test('fail to extract locked body', (t) => { - t.plan(1) - - const stream = new ReadableStream({}) - const reader = stream.getReader() - try { - // eslint-disable-next-line - new Request('http://asd', { - method: 'PUT', - body: stream, - keepalive: true - }) - } catch (err) { - t.equal(err.message, 'keepalive') - } - reader.cancel() - }) - - t.test('post FormData with Blob', (t) => { - t.plan(1) - - const body = new FormData() - body.append('field1', new Blob(['asd1'])) - - const server = createServer((req, res) => { - req.pipe(res) - }) - t.teardown(server.close.bind(server)) - - server.listen(0, async () => { - const res = await fetch(`http://localhost:${server.address().port}`, { - method: 'PUT', - body - }) - t.ok(/asd1/.test(await res.text())) - }) - }) - - t.test('post FormData with File', (t) => { - t.plan(2) - - const body = new FormData() - body.append('field1', new File(['asd1'], 'filename123')) - - const server = createServer((req, res) => { - req.pipe(res) - }) - t.teardown(server.close.bind(server)) - - server.listen(0, async () => { - const res = await fetch(`http://localhost:${server.address().port}`, { - method: 'PUT', - body - }) - const result = await res.text() - t.ok(/asd1/.test(result)) - t.ok(/filename123/.test(result)) - }) - }) - - t.end() -}) diff --git a/test/fetch/body.js b/test/fetch/body.js deleted file mode 100644 index b61d294e3a6..00000000000 --- a/test/fetch/body.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict' - -const tap = require('tap') -const { - cancelBody, - extractBody, - safelyExtractBody, - cloneBody, - mixinBody -} = require('../../lib/fetch/body') - -tap.todo('cancelBody') -tap.todo('extractBody') -tap.todo('safelyExtractBody') -tap.todo('cloneBody') -tap.todo('mixinBody') diff --git a/test/fetch/client-fetch.js b/test/fetch/client-fetch.js new file mode 100644 index 00000000000..3ee6dc880bc --- /dev/null +++ b/test/fetch/client-fetch.js @@ -0,0 +1,320 @@ +/* globals AbortController */ + +'use strict' + +const { test } = require('tap') +const { createServer } = require('http') +const { ReadableStream } = require('stream/web') +const { Blob } = require('buffer') +const { fetch, Response, Request, FormData, File } = require('../..') + +test('request json', (t) => { + t.plan(1) + + const obj = { asd: true } + const server = createServer((req, res) => { + res.end(JSON.stringify(obj)) + }) + t.teardown(server.close.bind(server)) + + server.listen(0, async () => { + const body = await fetch(`http://localhost:${server.address().port}`) + t.strictSame(obj, await body.json()) + }) +}) + +test('request text', (t) => { + t.plan(1) + + const obj = { asd: true } + const server = createServer((req, res) => { + res.end(JSON.stringify(obj)) + }) + t.teardown(server.close.bind(server)) + + server.listen(0, async () => { + const body = await fetch(`http://localhost:${server.address().port}`) + t.strictSame(JSON.stringify(obj), await body.text()) + }) +}) + +test('request arrayBuffer', (t) => { + t.plan(1) + + const obj = { asd: true } + const server = createServer((req, res) => { + res.end(JSON.stringify(obj)) + }) + t.teardown(server.close.bind(server)) + + server.listen(0, async () => { + const body = await fetch(`http://localhost:${server.address().port}`) + t.strictSame(Buffer.from(JSON.stringify(obj)), Buffer.from(await body.arrayBuffer())) + }) +}) + +test('should set type of blob object to the value of the `Content-Type` header from response', (t) => { + t.plan(1) + + const obj = { asd: true } + const server = createServer((req, res) => { + res.setHeader('Content-Type', 'application/json') + res.end(JSON.stringify(obj)) + }) + t.teardown(server.close.bind(server)) + + server.listen(0, async () => { + const response = await fetch(`http://localhost:${server.address().port}`) + t.equal('application/json', (await response.blob()).type) + }) +}) + +test('pre aborted with readable request body', (t) => { + t.plan(2) + + const server = createServer((req, res) => { + }) + t.teardown(server.close.bind(server)) + + server.listen(0, async () => { + const ac = new AbortController() + ac.abort() + await fetch(`http://localhost:${server.address().port}`, { + signal: ac.signal, + method: 'POST', + body: new ReadableStream({ + async cancel (reason) { + t.equal(reason.name, 'AbortError') + } + }) + }).catch(err => { + t.equal(err.name, 'AbortError') + }) + }) +}) + +test('pre aborted with closed readable request body', (t) => { + t.plan(2) + + const server = createServer((req, res) => { + }) + t.teardown(server.close.bind(server)) + + server.listen(0, async () => { + const ac = new AbortController() + ac.abort() + const body = new ReadableStream({ + async start (c) { + t.pass() + c.close() + }, + async cancel (reason) { + t.fail() + } + }) + queueMicrotask(() => { + fetch(`http://localhost:${server.address().port}`, { + signal: ac.signal, + method: 'POST', + body + }).catch(err => { + t.equal(err.name, 'AbortError') + }) + }) + }) +}) + +test('unsupported formData 1', (t) => { + t.plan(1) + + const server = createServer((req, res) => { + res.setHeader('content-type', 'asdasdsad') + res.end() + }) + t.teardown(server.close.bind(server)) + + server.listen(0, () => { + fetch(`http://localhost:${server.address().port}`) + .then(res => res.formData()) + .catch(err => { + t.equal(err.name, 'TypeError') + }) + }) +}) + +test('unsupported formData 2', (t) => { + t.plan(1) + + const server = createServer((req, res) => { + res.setHeader('content-type', 'multipart/form-data') + res.end() + }) + t.teardown(server.close.bind(server)) + + server.listen(0, () => { + fetch(`http://localhost:${server.address().port}`) + .then(res => res.formData()) + .catch(err => { + t.equal(err.name, 'NotSupportedError') + }) + }) +}) + +test('urlencoded formData', (t) => { + t.plan(2) + + const server = createServer((req, res) => { + res.setHeader('content-type', 'application/x-www-form-urlencoded') + res.end('field1=value1&field2=value2') + }) + t.teardown(server.close.bind(server)) + + server.listen(0, () => { + fetch(`http://localhost:${server.address().port}`) + .then(res => res.formData()) + .then(formData => { + t.equal(formData.get('field1'), 'value1') + t.equal(formData.get('field2'), 'value2') + }) + }) +}) + +test('locked blob body', (t) => { + t.plan(1) + + const server = createServer((req, res) => { + res.end() + }) + t.teardown(server.close.bind(server)) + + server.listen(0, async () => { + const res = await fetch(`http://localhost:${server.address().port}`) + const reader = res.body.getReader() + res.blob().catch(err => { + t.equal(err.message, 'locked') + reader.cancel() + }) + }) +}) + +test('disturbed blob body', (t) => { + t.plan(2) + + const server = createServer((req, res) => { + res.end() + }) + t.teardown(server.close.bind(server)) + + server.listen(0, async () => { + const res = await fetch(`http://localhost:${server.address().port}`) + res.blob().then(() => { + t.pass(2) + }) + res.blob().catch(err => { + t.equal(err.message, 'disturbed') + }) + }) +}) + +test('redirect with body', (t) => { + t.plan(3) + + let count = 0 + const server = createServer(async (req, res) => { + let body = '' + for await (const chunk of req) { + body += chunk + } + t.equal(body, 'asd') + if (count++ === 0) { + res.setHeader('location', 'asd') + res.statusCode = 302 + res.end() + } else { + res.end(String(count)) + } + }) + t.teardown(server.close.bind(server)) + + server.listen(0, async () => { + const res = await fetch(`http://localhost:${server.address().port}`, { + method: 'PUT', + body: 'asd' + }) + t.equal(await res.text(), '2') + }) +}) + +test('fail to extract locked body', (t) => { + t.plan(1) + + const stream = new ReadableStream({}) + const reader = stream.getReader() + try { + // eslint-disable-next-line + new Response(stream) + } catch (err) { + t.equal(err.name, 'TypeError') + } + reader.cancel() +}) + +test('fail to extract locked body', (t) => { + t.plan(1) + + const stream = new ReadableStream({}) + const reader = stream.getReader() + try { + // eslint-disable-next-line + new Request('http://asd', { + method: 'PUT', + body: stream, + keepalive: true + }) + } catch (err) { + t.equal(err.message, 'keepalive') + } + reader.cancel() +}) + +test('post FormData with Blob', (t) => { + t.plan(1) + + const body = new FormData() + body.append('field1', new Blob(['asd1'])) + + const server = createServer((req, res) => { + req.pipe(res) + }) + t.teardown(server.close.bind(server)) + + server.listen(0, async () => { + const res = await fetch(`http://localhost:${server.address().port}`, { + method: 'PUT', + body + }) + t.ok(/asd1/.test(await res.text())) + }) +}) + +test('post FormData with File', (t) => { + t.plan(2) + + const body = new FormData() + body.append('field1', new File(['asd1'], 'filename123')) + + const server = createServer((req, res) => { + req.pipe(res) + }) + t.teardown(server.close.bind(server)) + + server.listen(0, async () => { + const res = await fetch(`http://localhost:${server.address().port}`, { + method: 'PUT', + body + }) + const result = await res.text() + t.ok(/asd1/.test(result)) + t.ok(/filename123/.test(result)) + }) +}) diff --git a/test/fetch/headers.js b/test/fetch/headers.js index 277d2904b3b..96bb404f6dc 100644 --- a/test/fetch/headers.js +++ b/test/fetch/headers.js @@ -3,8 +3,6 @@ const tap = require('tap') const { Headers, - normalizeAndValidateHeaderName, - normalizeAndValidateHeaderValue, binarySearch } = require('../../lib/fetch/headers') const { kHeadersList } = require('../../lib/core/symbols') @@ -398,20 +396,6 @@ tap.test('Headers as Iterable', t => { }) }) -tap.test('Headers normalize and validate', t => { - t.plan(2) - const name = 'UNDICI' - const value = ' fetch ' // eslint-disable-line no-tabs - t.equal( - normalizeAndValidateHeaderName(name), - 'undici' - ) - t.strictSame( - normalizeAndValidateHeaderValue(name, value), - 'fetch' - ) -}) - tap.test('binary search', t => { // 0 1 2 3 4 5 6 7 const l1 = ['b', 1, 'c', 2, 'd', 3, 'f', 4] @@ -446,4 +430,4 @@ tap.test('binary search', t => { tests.forEach(({ input: [list, target], expected, message }) => { t.equal(expected, binarySearch(list, target), message) }) -}) \ No newline at end of file +}) diff --git a/test/fetch/request.js b/test/fetch/request.js deleted file mode 100644 index 8e9fe73190e..00000000000 --- a/test/fetch/request.js +++ /dev/null @@ -1,10 +0,0 @@ -'use strict' - -const tap = require('tap') -const { - Request, - makeRequest -} = require('../../lib/fetch/request') - -tap.todo('Request') -tap.todo('makeRequest') diff --git a/test/fetch/response.js b/test/fetch/response.js deleted file mode 100644 index 7ffbcd8e270..00000000000 --- a/test/fetch/response.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict' - -const tap = require('tap') -const { - makeNetworkError, - makeResponse, - filterResponse, - Response -} = require('../../lib/fetch/response') - -tap.todo('makeNetworkError') -tap.todo('makeResponse') -tap.todo('filterResponse') -tap.todo('Response')