diff --git a/package.json b/package.json index a52222ce200..1ce1a058b1b 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "lint:fix": "standard --fix | snazzy", "test": "node scripts/generate-pem && npm run test:tap && npm run test:node-fetch && npm run test:fetch && npm run test:cookies && npm run test:eventsource && npm run test:wpt && npm run test:websocket && npm run test:jest && npm run test:typescript && npm run test:node-test", "test:cookies": "borp --coverage -p \"test/cookie/*.js\"", - "test:node-fetch": "mocha --exit test/node-fetch", + "test:node-fetch": "borp --coverage -p \"test/node-fetch/**/*.js\"", "test:eventsource": "npm run build:node && borp --expose-gc --coverage -p \"test/eventsource/*.js\"", "test:fetch": "npm run build:node && borp --expose-gc --coverage -p \"test/fetch/*.js\" && borp --coverage -p \"test/webidl/*.js\"", "test:jest": "jest", @@ -104,17 +104,15 @@ "@sinonjs/fake-timers": "^11.1.0", "@types/node": "^18.0.3", "abort-controller": "^3.0.0", + "axios": "^1.6.5", "borp": "^0.9.1", - "chai": "^4.3.4", - "chai-as-promised": "^7.1.1", - "chai-iterator": "^3.0.2", - "chai-string": "^1.5.0", "concurrently": "^8.0.1", "cronometro": "^2.0.2", "dns-packet": "^5.4.0", "docsify-cli": "^4.4.3", "form-data": "^4.0.0", "formdata-node": "^6.0.3", + "got": "^14.0.0", "https-pem": "^3.0.0", "husky": "^9.0.7", "import-fresh": "^3.3.0", @@ -122,11 +120,11 @@ "jsdom": "^24.0.0", "jsfuzz": "^1.0.15", "mitata": "^0.1.8", - "mocha": "^10.0.0", - "p-timeout": "^3.2.0", + "node-fetch": "^3.3.2", "pre-commit": "^1.2.2", "proxy": "^1.0.2", "proxyquire": "^2.1.3", + "request": "^2.88.2", "sinon": "^17.0.1", "snazzy": "^9.0.0", "standard": "^17.0.0", @@ -134,18 +132,14 @@ "tsd": "^0.30.1", "typescript": "^5.0.2", "wait-on": "^7.0.1", - "ws": "^8.11.0", - "axios": "^1.6.5", - "got": "^14.0.0", - "node-fetch": "^3.3.2", - "request": "^2.88.2" + "ws": "^8.11.0" }, "engines": { "node": ">=18.0" }, "standard": { "env": [ - "mocha" + "jest" ], "ignore": [ "lib/llhttp/constants.js", diff --git a/test/node-fetch/headers.js b/test/node-fetch/headers.js index 2001e976efa..8500818f354 100644 --- a/test/node-fetch/headers.js +++ b/test/node-fetch/headers.js @@ -1,18 +1,14 @@ -/* eslint no-unused-expressions: "off" */ +'use strict' +const assert = require('node:assert') +const { describe, it } = require('node:test') const { format } = require('node:util') -const chai = require('chai') -const chaiIterator = require('chai-iterator') -const { Headers } = require('../../lib/fetch/headers.js') - -chai.use(chaiIterator) - -const { expect } = chai +const { Headers } = require('../../index.js') describe('Headers', () => { it('should have attributes conforming to Web IDL', () => { const headers = new Headers() - expect(Object.getOwnPropertyNames(headers)).to.be.empty + assert.strictEqual(Object.getOwnPropertyNames(headers).length, 0) const enumerableProperties = [] for (const property in headers) { @@ -30,7 +26,7 @@ describe('Headers', () => { 'set', 'values' ]) { - expect(enumerableProperties).to.contain(toCheck) + assert.strictEqual(enumerableProperties.includes(toCheck), true) } }) @@ -41,14 +37,14 @@ describe('Headers', () => { ['b', '3'], ['a', '1'] ]) - expect(headers).to.have.property('forEach') + assert.strictEqual(typeof headers.forEach, 'function') const result = [] for (const [key, value] of headers.entries()) { result.push([key, value]) } - expect(result).to.deep.equal([ + assert.deepStrictEqual(result, [ ['a', '1'], ['b', '2, 3'], ['c', '4'] @@ -66,15 +62,15 @@ describe('Headers', () => { results.push({ value, key, object }) }) - expect(results.length).to.equal(2) - expect({ key: 'accept', value: 'application/json, text/plain', object: headers }).to.deep.equal(results[0]) - expect({ key: 'content-type', value: 'text/html', object: headers }).to.deep.equal(results[1]) + assert.strictEqual(results.length, 2) + assert.deepStrictEqual(results[0], { key: 'accept', value: 'application/json, text/plain', object: headers }) + assert.deepStrictEqual(results[1], { key: 'content-type', value: 'text/html', object: headers }) }) - xit('should set "this" to undefined by default on forEach', () => { + it.skip('should set "this" to undefined by default on forEach', () => { const headers = new Headers({ Accept: 'application/json' }) headers.forEach(function () { - expect(this).to.be.undefined + assert.strictEqual(this, undefined) }) }) @@ -82,7 +78,7 @@ describe('Headers', () => { const headers = new Headers({ Accept: 'application/json' }) const thisArg = {} headers.forEach(function () { - expect(this).to.equal(thisArg) + assert.strictEqual(this, thisArg) }, thisArg) }) @@ -93,14 +89,14 @@ describe('Headers', () => { ['a', '1'] ]) headers.append('b', '3') - expect(headers).to.be.iterable + assert.strictEqual(typeof headers[Symbol.iterator], 'function') const result = [] for (const pair of headers) { result.push(pair) } - expect(result).to.deep.equal([ + assert.deepStrictEqual(result, [ ['a', '1'], ['b', '2, 3'], ['c', '4'] @@ -115,12 +111,22 @@ describe('Headers', () => { ]) headers.append('b', '3') - expect(headers.entries()).to.be.iterable - .and.to.deep.iterate.over([ - ['a', '1'], - ['b', '2, 3'], - ['c', '4'] - ]) + assert.strictEqual(typeof headers.entries, 'function') + assert.strictEqual(typeof headers.entries()[Symbol.iterator], 'function') + + const entries = headers.entries() + assert.strictEqual(typeof entries.next, 'function') + assert.deepStrictEqual(entries.next().value, ['a', '1']) + assert.strictEqual(typeof entries.next, 'function') + assert.deepStrictEqual(entries.next().value, ['b', '2, 3']) + assert.strictEqual(typeof entries.next, 'function') + assert.deepStrictEqual(entries.next().value, ['c', '4']) + + assert.deepStrictEqual([...headers.entries()], [ + ['a', '1'], + ['b', '2, 3'], + ['c', '4'] + ]) }) it('should allow iterating through all headers with keys()', () => { @@ -131,8 +137,18 @@ describe('Headers', () => { ]) headers.append('b', '3') - expect(headers.keys()).to.be.iterable - .and.to.iterate.over(['a', 'b', 'c']) + assert.strictEqual(typeof headers.keys, 'function') + assert.strictEqual(typeof headers.keys()[Symbol.iterator], 'function') + + const keys = headers.keys() + assert.strictEqual(typeof keys.next, 'function') + assert.strictEqual(keys.next().value, 'a') + assert.strictEqual(typeof keys.next, 'function') + assert.strictEqual(keys.next().value, 'b') + assert.strictEqual(typeof keys.next, 'function') + assert.strictEqual(keys.next().value, 'c') + + assert.deepStrictEqual([...headers.keys()], ['a', 'b', 'c']) }) it('should allow iterating through all headers with values()', () => { @@ -143,26 +159,37 @@ describe('Headers', () => { ]) headers.append('b', '3') - expect(headers.values()).to.be.iterable - .and.to.iterate.over(['1', '2, 3', '4']) + assert.strictEqual(typeof headers.values, 'function') + assert.strictEqual(typeof headers.values()[Symbol.iterator], 'function') + + const values = headers.values() + assert.strictEqual(typeof values.next, 'function') + assert.strictEqual(values.next().value, '1') + assert.strictEqual(typeof values.next, 'function') + assert.strictEqual(values.next().value, '2, 3') + assert.strictEqual(typeof values.next, 'function') + assert.strictEqual(values.next().value, '4') + + assert.deepStrictEqual([...headers.values()], ['1', '2, 3', '4']) }) it('should reject illegal header', () => { const headers = new Headers() - expect(() => new Headers({ 'He y': 'ok' })).to.throw(TypeError) - expect(() => new Headers({ 'Hé-y': 'ok' })).to.throw(TypeError) - expect(() => new Headers({ 'He-y': 'ăk' })).to.throw(TypeError) - expect(() => headers.append('Hé-y', 'ok')).to.throw(TypeError) - expect(() => headers.delete('Hé-y')).to.throw(TypeError) - expect(() => headers.get('Hé-y')).to.throw(TypeError) - expect(() => headers.has('Hé-y')).to.throw(TypeError) - expect(() => headers.set('Hé-y', 'ok')).to.throw(TypeError) + + assert.throws(() => new Headers({ 'He y': 'ok' }), TypeError) + assert.throws(() => new Headers({ 'Hé-y': 'ok' }), TypeError) + assert.throws(() => new Headers({ 'He-y': 'ăk' }), TypeError) + assert.throws(() => headers.append('Hé-y', 'ok'), TypeError) + assert.throws(() => headers.delete('Hé-y'), TypeError) + assert.throws(() => headers.get('Hé-y'), TypeError) + assert.throws(() => headers.has('Hé-y'), TypeError) + assert.throws(() => headers.set('Hé-y', 'ok'), TypeError) // Should reject empty header - expect(() => headers.append('', 'ok')).to.throw(TypeError) + assert.throws(() => headers.append('', 'ok'), TypeError) }) - xit('should ignore unsupported attributes while reading headers', () => { - const FakeHeader = function () {} + it.skip('should ignore unsupported attributes while reading headers', () => { + const FakeHeader = function () { } // Prototypes are currently ignored // This might change in the future: #181 FakeHeader.prototype.z = 'fake' @@ -188,26 +215,26 @@ describe('Headers', () => { const h1Raw = h1.raw() - expect(h1Raw.a).to.include('string') - expect(h1Raw.b).to.include('1,2') - expect(h1Raw.c).to.include('') - expect(h1Raw.d).to.include('') - expect(h1Raw.e).to.include('1') - expect(h1Raw.f).to.include('1,2') - expect(h1Raw.g).to.include('[object Object]') - expect(h1Raw.h).to.include('undefined') - expect(h1Raw.i).to.include('null') - expect(h1Raw.j).to.include('NaN') - expect(h1Raw.k).to.include('true') - expect(h1Raw.l).to.include('false') - expect(h1Raw.m).to.include('test') - expect(h1Raw.n).to.include('1,2') - expect(h1Raw.n).to.include('3,4') - - expect(h1Raw.z).to.be.undefined + assert.strictEqual(h1Raw.a.includes('string'), true) + assert.strictEqual(h1Raw.b.includes('1,2'), true) + assert.strictEqual(h1Raw.c.includes(''), true) + assert.strictEqual(h1Raw.d.includes(''), true) + assert.strictEqual(h1Raw.e.includes('1'), true) + assert.strictEqual(h1Raw.f.includes('1,2'), true) + assert.strictEqual(h1Raw.g.includes('[object Object]'), true) + assert.strictEqual(h1Raw.h.includes('undefined'), true) + assert.strictEqual(h1Raw.i.includes('null'), true) + assert.strictEqual(h1Raw.j.includes('NaN'), true) + assert.strictEqual(h1Raw.k.includes('true'), true) + assert.strictEqual(h1Raw.l.includes('false'), true) + assert.strictEqual(h1Raw.m.includes('test'), true) + assert.strictEqual(h1Raw.n.includes('1,2'), true) + assert.strictEqual(h1Raw.n.includes('3,4'), true) + + assert.strictEqual(h1Raw.z, undefined) }) - xit('should wrap headers', () => { + it.skip('should wrap headers', () => { const h1 = new Headers({ a: '1' }) @@ -221,16 +248,16 @@ describe('Headers', () => { h3.append('a', '2') const h3Raw = h3.raw() - expect(h1Raw.a).to.include('1') - expect(h1Raw.a).to.not.include('2') + assert.strictEqual(h1Raw.a.includes('1'), true) + assert.strictEqual(h1Raw.a.includes('2'), false) - expect(h2Raw.a).to.include('1') - expect(h2Raw.a).to.not.include('2') - expect(h2Raw.b).to.include('1') + assert.strictEqual(h2Raw.a.includes('1'), true) + assert.strictEqual(h2Raw.a.includes('2'), false) + assert.strictEqual(h2Raw.b.includes('1'), true) - expect(h3Raw.a).to.include('1') - expect(h3Raw.a).to.include('2') - expect(h3Raw.b).to.include('1') + assert.strictEqual(h3Raw.a.includes('1'), true) + assert.strictEqual(h3Raw.a.includes('2'), true) + assert.strictEqual(h3Raw.b.includes('1'), true) }) it('should accept headers as an iterable of tuples', () => { @@ -241,33 +268,33 @@ describe('Headers', () => { ['b', '2'], ['a', '3'] ]) - expect(headers.get('a')).to.equal('1, 3') - expect(headers.get('b')).to.equal('2') + assert.strictEqual(headers.get('a'), '1, 3') + assert.strictEqual(headers.get('b'), '2') headers = new Headers([ new Set(['a', '1']), ['b', '2'], new Map([['a', null], ['3', null]]).keys() ]) - expect(headers.get('a')).to.equal('1, 3') - expect(headers.get('b')).to.equal('2') + assert.strictEqual(headers.get('a'), '1, 3') + assert.strictEqual(headers.get('b'), '2') headers = new Headers(new Map([ ['a', '1'], ['b', '2'] ])) - expect(headers.get('a')).to.equal('1') - expect(headers.get('b')).to.equal('2') + assert.strictEqual(headers.get('a'), '1') + assert.strictEqual(headers.get('b'), '2') }) it('should throw a TypeError if non-tuple exists in a headers initializer', () => { - expect(() => new Headers([['b', '2', 'huh?']])).to.throw(TypeError) - expect(() => new Headers(['b2'])).to.throw(TypeError) - expect(() => new Headers('b2')).to.throw(TypeError) - expect(() => new Headers({ [Symbol.iterator]: 42 })).to.throw(TypeError) + assert.throws(() => new Headers([['b', '2', 'huh?']]), TypeError) + assert.throws(() => new Headers(['b2']), TypeError) + assert.throws(() => new Headers('b2'), TypeError) + assert.throws(() => new Headers({ [Symbol.iterator]: 42 }), TypeError) }) - xit('should use a custom inspect function', () => { + it.skip('should use a custom inspect function', () => { const headers = new Headers([ ['Host', 'thehost'], ['Host', 'notthehost'], @@ -277,6 +304,6 @@ describe('Headers', () => { ]) // eslint-disable-next-line quotes - expect(format(headers)).to.equal("{ a: [ '1', '3' ], b: '2', host: 'thehost' }") + assert.strictEqual(format(headers), "{ a: [ '1', '3' ], b: '2', host: 'thehost' }") }) }) diff --git a/test/node-fetch/main.js b/test/node-fetch/main.js index 7e6da3f984f..e4b13b1f482 100644 --- a/test/node-fetch/main.js +++ b/test/node-fetch/main.js @@ -1,17 +1,14 @@ -/* eslint no-unused-expressions: "off" */ -/* globals AbortController */ +'use strict' // Test tools +const assert = require('node:assert') +const { describe, it, before, beforeEach, after } = require('node:test') +const { setTimeout: delay } = require('node:timers/promises') const zlib = require('node:zlib') const stream = require('node:stream') const vm = require('node:vm') -const chai = require('chai') const crypto = require('node:crypto') -const chaiPromised = require('chai-as-promised') -const chaiIterator = require('chai-iterator') -const chaiString = require('chai-string') const { Blob } = require('node:buffer') -const { setTimeout: delay } = require('timers/promises') const { fetch, @@ -23,25 +20,14 @@ const { Agent } = require('../../index.js') const HeadersOrig = require('../../lib/fetch/headers.js').Headers -const RequestOrig = require('../../lib/fetch/request.js').Request const ResponseOrig = require('../../lib/fetch/response.js').Response +const RequestOrig = require('../../lib/fetch/request.js').Request const TestServer = require('./utils/server.js') -const chaiTimeout = require('./utils/chai-timeout.js') - -function isNodeLowerThan (version) { - return !~process.version.localeCompare(version, undefined, { numeric: true }) -} const { Uint8Array: VMUint8Array } = vm.runInNewContext('this') -chai.use(chaiPromised) -chai.use(chaiIterator) -chai.use(chaiString) -chai.use(chaiTimeout) -const { expect } = chai - describe('node-fetch', () => { const local = new TestServer() let base @@ -63,87 +49,86 @@ describe('node-fetch', () => { it('should return a promise', () => { const url = `${base}hello` const p = fetch(url) - expect(p).to.be.an.instanceof(Promise) - expect(p).to.have.property('then') + assert.ok(p instanceof Promise) + assert.strictEqual(typeof p.then, 'function') }) it('should expose Headers, Response and Request constructors', () => { - expect(Headers).to.equal(HeadersOrig) - expect(Response).to.equal(ResponseOrig) - expect(Request).to.equal(RequestOrig) + assert.strictEqual(Headers, HeadersOrig) + assert.strictEqual(Response, ResponseOrig) + assert.strictEqual(Request, RequestOrig) }) it('should support proper toString output for Headers, Response and Request objects', () => { - expect(new Headers().toString()).to.equal('[object Headers]') - expect(new Response().toString()).to.equal('[object Response]') - expect(new Request(base).toString()).to.equal('[object Request]') + assert.strictEqual(new Headers().toString(), '[object Headers]') + assert.strictEqual(new Response().toString(), '[object Response]') + assert.strictEqual(new Request(base).toString(), '[object Request]') }) - + // TODO Should we reflect the input? it('should reject with error if url is protocol relative', () => { const url = '//example.com/' - return expect(fetch(url)).to.eventually.be.rejectedWith(TypeError) + return assert.rejects(fetch(url), new TypeError('Failed to parse URL from //example.com/')) }) it('should reject with error if url is relative path', () => { const url = '/some/path' - return expect(fetch(url)).to.eventually.be.rejectedWith(TypeError) + return assert.rejects(fetch(url), new TypeError('Failed to parse URL from /some/path')) }) + // TODO: This seems odd it('should reject with error if protocol is unsupported', () => { const url = 'ftp://example.com/' - return expect(fetch(url)).to.eventually.be.rejectedWith(TypeError) + return assert.rejects(fetch(url), new TypeError('fetch failed')) }) - it('should reject with error on network failure', function () { - this.timeout(5000) + it('should reject with error on network failure', { timeout: 5000 }, function () { const url = 'http://localhost:50000/' - return expect(fetch(url)).to.eventually.be.rejected - .and.be.an.instanceOf(TypeError) + return assert.rejects(fetch(url), new TypeError('fetch failed')) }) it('should resolve into response', () => { const url = `${base}hello` return fetch(url).then(res => { - expect(res).to.be.an.instanceof(Response) - expect(res.headers).to.be.an.instanceof(Headers) - expect(res.body).to.be.an.instanceof(ReadableStream) - expect(res.bodyUsed).to.be.false + assert.ok(res instanceof Response) + assert.ok(res.headers instanceof Headers) + assert.ok(res.body instanceof ReadableStream) + assert.strictEqual(res.bodyUsed, false) - expect(res.url).to.equal(url) - expect(res.ok).to.be.true - expect(res.status).to.equal(200) - expect(res.statusText).to.equal('OK') + assert.strictEqual(res.url, url) + assert.strictEqual(res.ok, true) + assert.strictEqual(res.status, 200) + assert.strictEqual(res.statusText, 'OK') }) }) it('Response.redirect should resolve into response', () => { const res = Response.redirect('http://localhost') - expect(res).to.be.an.instanceof(Response) - expect(res.headers).to.be.an.instanceof(Headers) - expect(res.headers.get('location')).to.equal('http://localhost/') - expect(res.status).to.equal(302) + assert.ok(res instanceof Response) + assert.ok(res.headers instanceof Headers) + assert.strictEqual(res.headers.get('location'), 'http://localhost/') + assert.strictEqual(res.status, 302) }) it('Response.redirect /w invalid url should fail', () => { - expect(() => { + assert.throws(() => { Response.redirect('localhost') - }).to.throw() + }) }) it('Response.redirect /w invalid status should fail', () => { - expect(() => { + assert.throws(() => { Response.redirect('http://localhost', 200) - }).to.throw() + }) }) it('should accept plain text response', () => { const url = `${base}plain` return fetch(url).then(res => { - expect(res.headers.get('content-type')).to.equal('text/plain') + assert.strictEqual(res.headers.get('content-type'), 'text/plain') return res.text().then(result => { - expect(res.bodyUsed).to.be.true - expect(result).to.be.a('string') - expect(result).to.equal('text') + assert.strictEqual(res.bodyUsed, true) + assert.strictEqual(typeof result, 'string') + assert.strictEqual(result, 'text') }) }) }) @@ -151,11 +136,11 @@ describe('node-fetch', () => { it('should accept html response (like plain text)', () => { const url = `${base}html` return fetch(url).then(res => { - expect(res.headers.get('content-type')).to.equal('text/html') + assert.strictEqual(res.headers.get('content-type'), 'text/html') return res.text().then(result => { - expect(res.bodyUsed).to.be.true - expect(result).to.be.a('string') - expect(result).to.equal('') + assert.strictEqual(res.bodyUsed, true) + assert.strictEqual(typeof result, 'string') + assert.strictEqual(result, '') }) }) }) @@ -163,11 +148,11 @@ describe('node-fetch', () => { it('should accept json response', () => { const url = `${base}json` return fetch(url).then(res => { - expect(res.headers.get('content-type')).to.equal('application/json') + assert.strictEqual(res.headers.get('content-type'), 'application/json') return res.json().then(result => { - expect(res.bodyUsed).to.be.true - expect(result).to.be.an('object') - expect(result).to.deep.equal({ name: 'value' }) + assert.strictEqual(res.bodyUsed, true) + assert.strictEqual(typeof result, 'object') + assert.deepStrictEqual(result, { name: 'value' }) }) }) }) @@ -180,7 +165,7 @@ describe('node-fetch', () => { return fetch(url, options).then(res => { return res.json() }).then(res => { - expect(res.headers['x-custom-header']).to.equal('abc') + assert.strictEqual(res.headers['x-custom-header'], 'abc') }) }) @@ -192,7 +177,7 @@ describe('node-fetch', () => { return fetch(url, options).then(res => { return res.json() }).then(res => { - expect(res.headers['x-custom-header']).to.equal('abc') + assert.strictEqual(res.headers['x-custom-header'], 'abc') }) }) @@ -204,7 +189,7 @@ describe('node-fetch', () => { return fetch(url, options).then(res => { return res.json() }).then(res => { - expect(res.headers['x-custom-header']).to.equal('abc,123') + assert.strictEqual(res.headers['x-custom-header'], 'abc,123') }) }) @@ -216,56 +201,56 @@ describe('node-fetch', () => { return fetch(url, options).then(res => { return res.json() }).then(res => { - expect(res.headers['x-custom-header']).to.equal('abc') + assert.strictEqual(res.headers['x-custom-header'], 'abc') }) }) it('should follow redirect code 301', () => { const url = `${base}redirect/301` return fetch(url).then(res => { - expect(res.url).to.equal(`${base}inspect`) - expect(res.status).to.equal(200) - expect(res.ok).to.be.true + assert.strictEqual(res.url, `${base}inspect`) + assert.strictEqual(res.status, 200) + assert.strictEqual(res.ok, true) }) }) it('should follow redirect code 302', () => { const url = `${base}redirect/302` return fetch(url).then(res => { - expect(res.url).to.equal(`${base}inspect`) - expect(res.status).to.equal(200) + assert.strictEqual(res.url, `${base}inspect`) + assert.strictEqual(res.status, 200) }) }) it('should follow redirect code 303', () => { const url = `${base}redirect/303` return fetch(url).then(res => { - expect(res.url).to.equal(`${base}inspect`) - expect(res.status).to.equal(200) + assert.strictEqual(res.url, `${base}inspect`) + assert.strictEqual(res.status, 200) }) }) it('should follow redirect code 307', () => { const url = `${base}redirect/307` return fetch(url).then(res => { - expect(res.url).to.equal(`${base}inspect`) - expect(res.status).to.equal(200) + assert.strictEqual(res.url, `${base}inspect`) + assert.strictEqual(res.status, 200) }) }) it('should follow redirect code 308', () => { const url = `${base}redirect/308` return fetch(url).then(res => { - expect(res.url).to.equal(`${base}inspect`) - expect(res.status).to.equal(200) + assert.strictEqual(res.url, `${base}inspect`) + assert.strictEqual(res.status, 200) }) }) it('should follow redirect chain', () => { const url = `${base}redirect/chain` return fetch(url).then(res => { - expect(res.url).to.equal(`${base}inspect`) - expect(res.status).to.equal(200) + assert.strictEqual(res.url, `${base}inspect`) + assert.strictEqual(res.status, 200) }) }) @@ -276,11 +261,11 @@ describe('node-fetch', () => { body: 'a=1' } return fetch(url, options).then(res => { - expect(res.url).to.equal(`${base}inspect`) - expect(res.status).to.equal(200) + assert.strictEqual(res.url, `${base}inspect`) + assert.strictEqual(res.status, 200) return res.json().then(result => { - expect(result.method).to.equal('GET') - expect(result.body).to.equal('') + assert.strictEqual(result.method, 'GET') + assert.strictEqual(result.body, '') }) }) }) @@ -292,11 +277,11 @@ describe('node-fetch', () => { body: 'a=1' } return fetch(url, options).then(res => { - expect(res.url).to.equal(`${base}inspect`) - expect(res.status).to.equal(200) + assert.strictEqual(res.url, `${base}inspect`) + assert.strictEqual(res.status, 200) return res.json().then(res => { - expect(res.method).to.equal('PATCH') - expect(res.body).to.equal('a=1') + assert.strictEqual(res.method, 'PATCH') + assert.strictEqual(res.body, 'a=1') }) }) }) @@ -308,11 +293,11 @@ describe('node-fetch', () => { body: 'a=1' } return fetch(url, options).then(res => { - expect(res.url).to.equal(`${base}inspect`) - expect(res.status).to.equal(200) + assert.strictEqual(res.url, `${base}inspect`) + assert.strictEqual(res.status, 200) return res.json().then(result => { - expect(result.method).to.equal('GET') - expect(result.body).to.equal('') + assert.strictEqual(result.method, 'GET') + assert.strictEqual(result.body, '') }) }) }) @@ -324,11 +309,11 @@ describe('node-fetch', () => { body: 'a=1' } return fetch(url, options).then(res => { - expect(res.url).to.equal(`${base}inspect`) - expect(res.status).to.equal(200) + assert.strictEqual(res.url, `${base}inspect`) + assert.strictEqual(res.status, 200) return res.json().then(res => { - expect(res.method).to.equal('PATCH') - expect(res.body).to.equal('a=1') + assert.strictEqual(res.method, 'PATCH') + assert.strictEqual(res.body, 'a=1') }) }) }) @@ -340,11 +325,11 @@ describe('node-fetch', () => { body: 'a=1' } return fetch(url, options).then(res => { - expect(res.url).to.equal(`${base}inspect`) - expect(res.status).to.equal(200) + assert.strictEqual(res.url, `${base}inspect`) + assert.strictEqual(res.status, 200) return res.json().then(result => { - expect(result.method).to.equal('GET') - expect(result.body).to.equal('') + assert.strictEqual(result.method, 'GET') + assert.strictEqual(result.body, '') }) }) }) @@ -356,11 +341,11 @@ describe('node-fetch', () => { body: 'a=1' } return fetch(url, options).then(res => { - expect(res.url).to.equal(`${base}inspect`) - expect(res.status).to.equal(200) + assert.strictEqual(res.url, `${base}inspect`) + assert.strictEqual(res.status, 200) return res.json().then(result => { - expect(result.method).to.equal('PATCH') - expect(result.body).to.equal('a=1') + assert.strictEqual(result.method, 'PATCH') + assert.strictEqual(result.body, 'a=1') }) }) }) @@ -371,21 +356,19 @@ describe('node-fetch', () => { method: 'PATCH', body: stream.Readable.from('tada') } - return expect(fetch(url, options)).to.eventually.be.rejected - .and.be.an.instanceOf(TypeError) + return assert.rejects(fetch(url, options), new TypeError('RequestInit: duplex option is required when sending a body.')) }) it('should obey maximum redirect, reject case', () => { const url = `${base}redirect/chain/20` - return expect(fetch(url)).to.eventually.be.rejected - .and.be.an.instanceOf(TypeError) + return assert.rejects(fetch(url), new TypeError('fetch failed')) }) it('should obey redirect chain, resolve case', () => { const url = `${base}redirect/chain/19` return fetch(url).then(res => { - expect(res.url).to.equal(`${base}inspect`) - expect(res.status).to.equal(200) + assert.strictEqual(res.url, `${base}inspect`) + assert.strictEqual(res.status, 200) }) }) @@ -394,8 +377,7 @@ describe('node-fetch', () => { const options = { redirect: 'error' } - return expect(fetch(url, options)).to.eventually.be.rejected - .and.be.an.instanceOf(TypeError) + return assert.rejects(fetch(url, options), new TypeError('fetch failed')) }) it('should support redirect mode, manual flag when there is no redirect', () => { @@ -404,9 +386,9 @@ describe('node-fetch', () => { redirect: 'manual' } return fetch(url, options).then(res => { - expect(res.url).to.equal(url) - expect(res.status).to.equal(200) - expect(res.headers.get('location')).to.be.null + assert.strictEqual(res.url, url) + assert.strictEqual(res.status, 200) + assert.strictEqual(res.headers.get('location'), null) }) }) @@ -416,19 +398,19 @@ describe('node-fetch', () => { headers: new Headers({ 'x-custom-header': 'abc' }) } return fetch(url, options).then(res => { - expect(res.url).to.equal(`${base}inspect`) + assert.strictEqual(res.url, `${base}inspect`) return res.json() }).then(res => { - expect(res.headers['x-custom-header']).to.equal('abc') + assert.strictEqual(res.headers['x-custom-header'], 'abc') }) }) it('should treat broken redirect as ordinary response (follow)', () => { const url = `${base}redirect/no-location` return fetch(url).then(res => { - expect(res.url).to.equal(url) - expect(res.status).to.equal(301) - expect(res.headers.get('location')).to.be.null + assert.strictEqual(res.url, url) + assert.strictEqual(res.status, 301) + assert.strictEqual(res.headers.get('location'), null) }) }) @@ -438,9 +420,9 @@ describe('node-fetch', () => { redirect: 'manual' } return fetch(url, options).then(res => { - expect(res.url).to.equal(url) - expect(res.status).to.equal(301) - expect(res.headers.get('location')).to.be.null + assert.strictEqual(res.url, url) + assert.strictEqual(res.status, 301) + assert.strictEqual(res.headers.get('location'), null) }) }) @@ -450,37 +432,37 @@ describe('node-fetch', () => { redirect: 'foobar' } return fetch(url, options).then(() => { - expect.fail() + assert.fail() }, error => { - expect(error).to.be.an.instanceOf(TypeError) + assert.ok(error instanceof TypeError) }) }) it('should set redirected property on response when redirect', () => { const url = `${base}redirect/301` return fetch(url).then(res => { - expect(res.redirected).to.be.true + assert.strictEqual(res.redirected, true) }) }) it('should not set redirected property on response without redirect', () => { const url = `${base}hello` return fetch(url).then(res => { - expect(res.redirected).to.be.false + assert.strictEqual(res.redirected, false) }) }) it('should handle client-error response', () => { const url = `${base}error/400` return fetch(url).then(res => { - expect(res.headers.get('content-type')).to.equal('text/plain') - expect(res.status).to.equal(400) - expect(res.statusText).to.equal('Bad Request') - expect(res.ok).to.be.false + assert.strictEqual(res.headers.get('content-type'), 'text/plain') + assert.strictEqual(res.status, 400) + assert.strictEqual(res.statusText, 'Bad Request') + assert.strictEqual(res.ok, false) return res.text().then(result => { - expect(res.bodyUsed).to.be.true - expect(result).to.be.a('string') - expect(result).to.equal('client error') + assert.strictEqual(res.bodyUsed, true) + assert.strictEqual(typeof result, 'string') + assert.strictEqual(result, 'client error') }) }) }) @@ -488,37 +470,37 @@ describe('node-fetch', () => { it('should handle server-error response', () => { const url = `${base}error/500` return fetch(url).then(res => { - expect(res.headers.get('content-type')).to.equal('text/plain') - expect(res.status).to.equal(500) - expect(res.statusText).to.equal('Internal Server Error') - expect(res.ok).to.be.false + assert.strictEqual(res.headers.get('content-type'), 'text/plain') + assert.strictEqual(res.status, 500) + assert.strictEqual(res.statusText, 'Internal Server Error') + assert.strictEqual(res.ok, false) return res.text().then(result => { - expect(res.bodyUsed).to.be.true - expect(result).to.be.a('string') - expect(result).to.equal('server error') + assert.strictEqual(res.bodyUsed, true) + assert.strictEqual(typeof result, 'string') + assert.strictEqual(result, 'server error') }) }) }) it('should handle network-error response', () => { const url = `${base}error/reset` - return expect(fetch(url)).to.eventually.be.rejectedWith(TypeError) + return assert.rejects(fetch(url), new TypeError('fetch failed')) }) it('should handle network-error partial response', () => { const url = `${base}error/premature` return fetch(url).then(res => { - expect(res.status).to.equal(200) - expect(res.ok).to.be.true - return expect(res.text()).to.eventually.be.rejectedWith(Error) + assert.strictEqual(res.status, 200) + assert.strictEqual(res.ok, true) + return assert.rejects(() => res.text(), new TypeError('terminated')) }) }) it('should handle network-error in chunked response async iterator', () => { const url = `${base}error/premature/chunked` return fetch(url).then(res => { - expect(res.status).to.equal(200) - expect(res.ok).to.be.true + assert.strictEqual(res.status, 200) + assert.strictEqual(res.ok, true) const read = async body => { const chunks = [] @@ -529,74 +511,75 @@ describe('node-fetch', () => { return chunks } - return expect(read(res.body)) - .to.eventually.be.rejectedWith(Error) + return assert.rejects(read(res.body), new TypeError('terminated')) }) }) it('should handle network-error in chunked response in consumeBody', () => { const url = `${base}error/premature/chunked` return fetch(url).then(res => { - expect(res.status).to.equal(200) - expect(res.ok).to.be.true + assert.strictEqual(res.status, 200) + assert.strictEqual(res.ok, true) - return expect(res.text()).to.eventually.be.rejectedWith(Error) + return assert.rejects(res.text(), new TypeError('terminated')) }) }) it('should handle DNS-error response', () => { const url = 'http://domain.invalid' - return expect(fetch(url)).to.eventually.be.rejectedWith(TypeError) + return assert.rejects(fetch(url), new TypeError('fetch failed')) }) + // TODO: Should we pass through the error message? it('should reject invalid json response', () => { const url = `${base}error/json` return fetch(url).then(res => { - expect(res.headers.get('content-type')).to.equal('application/json') - return expect(res.json()).to.eventually.be.rejectedWith(Error) + assert.strictEqual(res.headers.get('content-type'), 'application/json') + return assert.rejects(res.json(), SyntaxError) }) }) it('should handle response with no status text', () => { const url = `${base}no-status-text` return fetch(url).then(res => { - expect(res.statusText).to.equal('') + assert.strictEqual(res.statusText, '') }) }) it('should handle no content response', () => { const url = `${base}no-content` return fetch(url).then(res => { - expect(res.status).to.equal(204) - expect(res.statusText).to.equal('No Content') - expect(res.ok).to.be.true + assert.strictEqual(res.status, 204) + assert.strictEqual(res.statusText, 'No Content') + assert.strictEqual(res.ok, true) return res.text().then(result => { - expect(result).to.be.a('string') - expect(result).to.be.empty + assert.strictEqual(typeof result, 'string') + assert.strictEqual(result, '') }) }) }) + // TODO: Should we pass through the error message? it('should reject when trying to parse no content response as json', () => { const url = `${base}no-content` return fetch(url).then(res => { - expect(res.status).to.equal(204) - expect(res.statusText).to.equal('No Content') - expect(res.ok).to.be.true - return expect(res.json()).to.eventually.be.rejectedWith(Error) + assert.strictEqual(res.status, 204) + assert.strictEqual(res.statusText, 'No Content') + assert.strictEqual(res.ok, true) + return assert.rejects(res.json(), new SyntaxError('Unexpected end of JSON input')) }) }) it('should handle no content response with gzip encoding', () => { const url = `${base}no-content/gzip` return fetch(url).then(res => { - expect(res.status).to.equal(204) - expect(res.statusText).to.equal('No Content') - expect(res.headers.get('content-encoding')).to.equal('gzip') - expect(res.ok).to.be.true + assert.strictEqual(res.status, 204) + assert.strictEqual(res.statusText, 'No Content') + assert.strictEqual(res.headers.get('content-encoding'), 'gzip') + assert.strictEqual(res.ok, true) return res.text().then(result => { - expect(result).to.be.a('string') - expect(result).to.be.empty + assert.strictEqual(typeof result, 'string') + assert.strictEqual(result, '') }) }) }) @@ -604,12 +587,12 @@ describe('node-fetch', () => { it('should handle not modified response', () => { const url = `${base}not-modified` return fetch(url).then(res => { - expect(res.status).to.equal(304) - expect(res.statusText).to.equal('Not Modified') - expect(res.ok).to.be.false + assert.strictEqual(res.status, 304) + assert.strictEqual(res.statusText, 'Not Modified') + assert.strictEqual(res.ok, false) return res.text().then(result => { - expect(result).to.be.a('string') - expect(result).to.be.empty + assert.strictEqual(typeof result, 'string') + assert.strictEqual(result, '') }) }) }) @@ -617,13 +600,13 @@ describe('node-fetch', () => { it('should handle not modified response with gzip encoding', () => { const url = `${base}not-modified/gzip` return fetch(url).then(res => { - expect(res.status).to.equal(304) - expect(res.statusText).to.equal('Not Modified') - expect(res.headers.get('content-encoding')).to.equal('gzip') - expect(res.ok).to.be.false + assert.strictEqual(res.status, 304) + assert.strictEqual(res.statusText, 'Not Modified') + assert.strictEqual(res.headers.get('content-encoding'), 'gzip') + assert.strictEqual(res.ok, false) return res.text().then(result => { - expect(result).to.be.a('string') - expect(result).to.be.empty + assert.strictEqual(typeof result, 'string') + assert.strictEqual(result, '') }) }) }) @@ -631,10 +614,10 @@ describe('node-fetch', () => { it('should decompress gzip response', () => { const url = `${base}gzip` return fetch(url).then(res => { - expect(res.headers.get('content-type')).to.equal('text/plain') + assert.strictEqual(res.headers.get('content-type'), 'text/plain') return res.text().then(result => { - expect(result).to.be.a('string') - expect(result).to.equal('hello world') + assert.strictEqual(typeof result, 'string') + assert.strictEqual(result, 'hello world') }) }) }) @@ -642,19 +625,19 @@ describe('node-fetch', () => { it('should decompress slightly invalid gzip response', async () => { const url = `${base}gzip-truncated` const res = await fetch(url) - expect(res.headers.get('content-type')).to.equal('text/plain') + assert.strictEqual(res.headers.get('content-type'), 'text/plain') const result = await res.text() - expect(result).to.be.a('string') - expect(result).to.equal('hello world') + assert.strictEqual(typeof result, 'string') + assert.strictEqual(result, 'hello world') }) it('should decompress deflate response', () => { const url = `${base}deflate` return fetch(url).then(res => { - expect(res.headers.get('content-type')).to.equal('text/plain') + assert.strictEqual(res.headers.get('content-type'), 'text/plain') return res.text().then(result => { - expect(result).to.be.a('string') - expect(result).to.equal('hello world') + assert.strictEqual(typeof result, 'string') + assert.strictEqual(result, 'hello world') }) }) }) @@ -662,10 +645,10 @@ describe('node-fetch', () => { it('should decompress deflate raw response from old apache server', () => { const url = `${base}deflate-raw` return fetch(url).then(res => { - expect(res.headers.get('content-type')).to.equal('text/plain') + assert.strictEqual(res.headers.get('content-type'), 'text/plain') return res.text().then(result => { - expect(result).to.be.a('string') - expect(result).to.equal('hello world') + assert.strictEqual(typeof result, 'string') + assert.strictEqual(result, 'hello world') }) }) }) @@ -677,10 +660,10 @@ describe('node-fetch', () => { const url = `${base}brotli` return fetch(url).then(res => { - expect(res.headers.get('content-type')).to.equal('text/plain') + assert.strictEqual(res.headers.get('content-type'), 'text/plain') return res.text().then(result => { - expect(result).to.be.a('string') - expect(result).to.equal('hello world') + assert.strictEqual(typeof result, 'string') + assert.strictEqual(result, 'hello world') }) }) }) @@ -692,13 +675,13 @@ describe('node-fetch', () => { const url = `${base}no-content/brotli` return fetch(url).then(res => { - expect(res.status).to.equal(204) - expect(res.statusText).to.equal('No Content') - expect(res.headers.get('content-encoding')).to.equal('br') - expect(res.ok).to.be.true + assert.strictEqual(res.status, 204) + assert.strictEqual(res.statusText, 'No Content') + assert.strictEqual(res.headers.get('content-encoding'), 'br') + assert.strictEqual(res.ok, true) return res.text().then(result => { - expect(result).to.be.a('string') - expect(result).to.be.empty + assert.strictEqual(typeof result, 'string') + assert.strictEqual(result, '') }) }) }) @@ -706,10 +689,10 @@ describe('node-fetch', () => { it('should skip decompression if unsupported', () => { const url = `${base}sdch` return fetch(url).then(res => { - expect(res.headers.get('content-type')).to.equal('text/plain') + assert.strictEqual(res.headers.get('content-type'), 'text/plain') return res.text().then(result => { - expect(result).to.be.a('string') - expect(result).to.equal('fake sdch string') + assert.strictEqual(typeof result, 'string') + assert.strictEqual(result, 'fake sdch string') }) }) }) @@ -717,10 +700,10 @@ describe('node-fetch', () => { it('should skip decompression if unsupported codings', () => { const url = `${base}multiunsupported` return fetch(url).then(res => { - expect(res.headers.get('content-type')).to.equal('text/plain') + assert.strictEqual(res.headers.get('content-type'), 'text/plain') return res.text().then(result => { - expect(result).to.be.a('string') - expect(result).to.equal('multiunsupported') + assert.strictEqual(typeof result, 'string') + assert.strictEqual(result, 'multiunsupported') }) }) }) @@ -728,10 +711,10 @@ describe('node-fetch', () => { it('should decompress multiple coding', () => { const url = `${base}multisupported` return fetch(url).then(res => { - expect(res.headers.get('content-type')).to.equal('text/plain') + assert.strictEqual(res.headers.get('content-type'), 'text/plain') return res.text().then(result => { - expect(result).to.be.a('string') - expect(result).to.equal('hello world') + assert.strictEqual(typeof result, 'string') + assert.strictEqual(result, 'hello world') }) }) }) @@ -739,8 +722,8 @@ describe('node-fetch', () => { it('should reject if response compression is invalid', () => { const url = `${base}invalid-content-encoding` return fetch(url).then(res => { - expect(res.headers.get('content-type')).to.equal('text/plain') - return expect(res.text()).to.eventually.be.rejected + assert.strictEqual(res.headers.get('content-type'), 'text/plain') + return assert.rejects(res.text(), new TypeError('terminated')) }) }) @@ -748,22 +731,22 @@ describe('node-fetch', () => { const url = `${base}invalid-content-encoding` fetch(url) .then(res => { - expect(res.status).to.equal(200) + assert.strictEqual(res.status, 200) }) - .catch(() => {}) - .then(() => { + .catch(() => { }) + .then(new Promise((resolve) => { // Wait a few ms to see if a uncaught error occurs setTimeout(() => { - done() + resolve() }, 20) - }) + })) }) it('should collect handled errors on the body stream to reject if the body is used later', () => { const url = `${base}invalid-content-encoding` return fetch(url).then(delay(20)).then(res => { - expect(res.headers.get('content-type')).to.equal('text/plain') - return expect(res.text()).to.eventually.be.rejected + assert.strictEqual(res.headers.get('content-type'), 'text/plain') + return assert.rejects(res.text(), new TypeError('terminated')) }) }) @@ -776,7 +759,7 @@ describe('node-fetch', () => { } } return fetch(url, options).then(res => res.json()).then(res => { - expect(res.headers['accept-encoding']).to.equal('gzip') + assert.strictEqual(res.headers['accept-encoding'], 'gzip') }) }) @@ -804,11 +787,15 @@ describe('node-fetch', () => { controller.abort() - return Promise.all(fetches.map(fetched => expect(fetched) - .to.eventually.be.rejected - .and.be.an.instanceOf(Error) - .and.have.property('name', 'AbortError') - )) + return Promise.all(fetches.map(async fetched => { + try { + await fetched + assert.fail('should have thrown') + } catch (error) { + assert.ok(error instanceof Error) + assert.strictEqual(error.name, 'AbortError') + } + })) }) it('should support multiple request cancellation with signal', () => { @@ -829,100 +816,118 @@ describe('node-fetch', () => { controller.abort() - return Promise.all(fetches.map(fetched => expect(fetched) - .to.eventually.be.rejected - .and.be.an.instanceOf(Error) - .and.have.property('name', 'AbortError') - )) + return Promise.all(fetches.map(async fetched => { + try { + await fetched + assert.fail('should have thrown') + } catch (error) { + assert.ok(error instanceof Error) + assert.strictEqual(error.name, 'AbortError') + } + })) }) - it('should reject immediately if signal has already been aborted', () => { + it('should reject immediately if signal has already been aborted', async () => { const url = `${base}timeout` const options = { signal: controller.signal } controller.abort() const fetched = fetch(url, options) - return expect(fetched).to.eventually.be.rejected - .and.be.an.instanceOf(Error) - .and.have.property('name', 'AbortError') + + try { + await fetched + assert.fail('should have thrown') + } catch (error) { + assert.ok(error instanceof Error) + assert.strictEqual(error.name, 'AbortError') + } }) - it('should allow redirects to be aborted', () => { + it('should allow redirects to be aborted', async () => { const request = new Request(`${base}redirect/slow`, { signal: controller.signal }) setTimeout(() => { controller.abort() }, 20) - return expect(fetch(request)).to.be.eventually.rejected - .and.be.an.instanceOf(Error) - .and.have.property('name', 'AbortError') + + try { + await fetch(request) + assert.fail('should have thrown') + } catch (error) { + assert.ok(error instanceof Error) + assert.strictEqual(error.name, 'AbortError') + } }) - it('should allow redirected response body to be aborted', () => { + it('should allow redirected response body to be aborted', async () => { const request = new Request(`${base}redirect/slow-stream`, { signal: controller.signal }) - return expect(fetch(request).then(res => { - expect(res.headers.get('content-type')).to.equal('text/plain') + const fetched = fetch(request).then(res => { + assert.strictEqual(res.headers.get('content-type'), 'text/plain') const result = res.text() controller.abort() return result - })).to.be.eventually.rejected - .and.be.an.instanceOf(Error) - .and.have.property('name', 'AbortError') + }) + + try { + await fetched + assert.fail('should have thrown') + } catch (error) { + assert.ok(error instanceof Error) + assert.strictEqual(error.name, 'AbortError') + } }) - it('should reject response body with AbortError when aborted before stream has been read completely', () => { - return expect(fetch( + it('should reject response body with AbortError when aborted before stream has been read completely', async () => { + const response = await fetch( `${base}slow`, { signal: controller.signal } - )) - .to.eventually.be.fulfilled - .then(res => { - const promise = res.text() - controller.abort() - return expect(promise) - .to.eventually.be.rejected - .and.be.an.instanceof(Error) - .and.have.property('name', 'AbortError') - }) + ) + + const promise = response.text() + controller.abort() + + try { + await promise + assert.fail('should have thrown') + } catch (error) { + assert.ok(error instanceof Error) + assert.strictEqual(error.name, 'AbortError') + } }) - it('should reject response body methods immediately with AbortError when aborted before stream is disturbed', () => { - return expect(fetch( + it('should reject response body methods immediately with AbortError when aborted before stream is disturbed', async () => { + const response = await fetch( `${base}slow`, { signal: controller.signal } - )) - .to.eventually.be.fulfilled - .then(res => { - controller.abort() - return expect(res.text()) - .to.eventually.be.rejected - .and.be.an.instanceof(Error) - .and.have.property('name', 'AbortError') - }) + ) + + controller.abort() + const promise = response.text() + try { + await promise + assert.fail('should have thrown') + } catch (error) { + assert.ok(error instanceof Error) + assert.strictEqual(error.name, 'AbortError') + } }) }) it('should throw a TypeError if a signal is not of type AbortSignal or EventTarget', () => { return Promise.all([ - expect(fetch(`${base}inspect`, { signal: {} })) - .to.be.eventually.rejected - .and.be.an.instanceof(TypeError), - expect(fetch(`${base}inspect`, { signal: '' })) - .to.be.eventually.rejected - .and.be.an.instanceof(TypeError), - expect(fetch(`${base}inspect`, { signal: Object.create(null) })) - .to.be.eventually.rejected - .and.be.an.instanceof(TypeError) + assert.rejects(fetch(`${base}inspect`, { signal: {} }), new TypeError("Failed to construct 'Request': member signal is not of type AbortSignal.")), + assert.rejects(fetch(`${base}inspect`, { signal: '' }), new TypeError("Failed to construct 'Request': member signal is not of type AbortSignal.")), + assert.rejects(fetch(`${base}inspect`, { signal: Object.create(null) }), new TypeError("Failed to construct 'Request': member signal is not of type AbortSignal.")) ]) }) it('should gracefully handle a null signal', () => { return fetch(`${base}hello`, { signal: null }).then(res => { - return expect(res.ok).to.be.true + return assert.strictEqual(res.ok, true) }) }) @@ -934,14 +939,14 @@ describe('node-fetch', () => { } } return fetch(url, options).then(res => res.json()).then(res => { - expect(res.headers['user-agent']).to.equal('faked') + assert.strictEqual(res.headers['user-agent'], 'faked') }) }) it('should set default Accept header', () => { const url = `${base}inspect` fetch(url).then(res => res.json()).then(res => { - expect(res.headers.accept).to.equal('*/*') + assert.strictEqual(res.headers.accept, '*/*') }) }) @@ -953,7 +958,7 @@ describe('node-fetch', () => { } } return fetch(url, options).then(res => res.json()).then(res => { - expect(res.headers.accept).to.equal('application/json') + assert.strictEqual(res.headers.accept, 'application/json') }) }) @@ -965,10 +970,10 @@ describe('node-fetch', () => { return fetch(url, options).then(res => { return res.json() }).then(res => { - expect(res.method).to.equal('POST') - expect(res.headers['transfer-encoding']).to.be.undefined - expect(res.headers['content-type']).to.be.undefined - expect(res.headers['content-length']).to.equal('0') + assert.strictEqual(res.method, 'POST') + assert.strictEqual(res.headers['transfer-encoding'], undefined) + assert.strictEqual(res.headers['content-type'], undefined) + assert.strictEqual(res.headers['content-length'], '0') }) }) @@ -981,11 +986,11 @@ describe('node-fetch', () => { return fetch(url, options).then(res => { return res.json() }).then(res => { - expect(res.method).to.equal('POST') - expect(res.body).to.equal('a=1') - expect(res.headers['transfer-encoding']).to.be.undefined - expect(res.headers['content-type']).to.equal('text/plain;charset=UTF-8') - expect(res.headers['content-length']).to.equal('3') + assert.strictEqual(res.method, 'POST') + assert.strictEqual(res.body, 'a=1') + assert.strictEqual(res.headers['transfer-encoding'], undefined) + assert.strictEqual(res.headers['content-type'], 'text/plain;charset=UTF-8') + assert.strictEqual(res.headers['content-length'], '3') }) }) @@ -998,11 +1003,11 @@ describe('node-fetch', () => { return fetch(url, options).then(res => { return res.json() }).then(res => { - expect(res.method).to.equal('POST') - expect(res.body).to.equal('a=1') - expect(res.headers['transfer-encoding']).to.be.undefined - expect(res.headers['content-type']).to.be.undefined - expect(res.headers['content-length']).to.equal('3') + assert.strictEqual(res.method, 'POST') + assert.strictEqual(res.body, 'a=1') + assert.strictEqual(res.headers['transfer-encoding'], undefined) + assert.strictEqual(res.headers['content-type'], undefined) + assert.strictEqual(res.headers['content-length'], '3') }) }) @@ -1014,11 +1019,11 @@ describe('node-fetch', () => { body: encoder.encode('Hello, world!\n').buffer } return fetch(url, options).then(res => res.json()).then(res => { - expect(res.method).to.equal('POST') - expect(res.body).to.equal('Hello, world!\n') - expect(res.headers['transfer-encoding']).to.be.undefined - expect(res.headers['content-type']).to.be.undefined - expect(res.headers['content-length']).to.equal('14') + assert.strictEqual(res.method, 'POST') + assert.strictEqual(res.body, 'Hello, world!\n') + assert.strictEqual(res.headers['transfer-encoding'], undefined) + assert.strictEqual(res.headers['content-type'], undefined) + assert.strictEqual(res.headers['content-length'], '14') }) }) @@ -1029,11 +1034,11 @@ describe('node-fetch', () => { body: new VMUint8Array(Buffer.from('Hello, world!\n')).buffer } return fetch(url, options).then(res => res.json()).then(res => { - expect(res.method).to.equal('POST') - expect(res.body).to.equal('Hello, world!\n') - expect(res.headers['transfer-encoding']).to.be.undefined - expect(res.headers['content-type']).to.be.undefined - expect(res.headers['content-length']).to.equal('14') + assert.strictEqual(res.method, 'POST') + assert.strictEqual(res.body, 'Hello, world!\n') + assert.strictEqual(res.headers['transfer-encoding'], undefined) + assert.strictEqual(res.headers['content-type'], undefined) + assert.strictEqual(res.headers['content-length'], '14') }) }) @@ -1045,11 +1050,11 @@ describe('node-fetch', () => { body: encoder.encode('Hello, world!\n') } return fetch(url, options).then(res => res.json()).then(res => { - expect(res.method).to.equal('POST') - expect(res.body).to.equal('Hello, world!\n') - expect(res.headers['transfer-encoding']).to.be.undefined - expect(res.headers['content-type']).to.be.undefined - expect(res.headers['content-length']).to.equal('14') + assert.strictEqual(res.method, 'POST') + assert.strictEqual(res.body, 'Hello, world!\n') + assert.strictEqual(res.headers['transfer-encoding'], undefined) + assert.strictEqual(res.headers['content-type'], undefined) + assert.strictEqual(res.headers['content-length'], '14') }) }) @@ -1061,11 +1066,11 @@ describe('node-fetch', () => { body: new BigUint64Array(encoder.encode('0123456789abcdef').buffer) } return fetch(url, options).then(res => res.json()).then(res => { - expect(res.method).to.equal('POST') - expect(res.body).to.equal('0123456789abcdef') - expect(res.headers['transfer-encoding']).to.be.undefined - expect(res.headers['content-type']).to.be.undefined - expect(res.headers['content-length']).to.equal('16') + assert.strictEqual(res.method, 'POST') + assert.strictEqual(res.body, '0123456789abcdef') + assert.strictEqual(res.headers['transfer-encoding'], undefined) + assert.strictEqual(res.headers['content-type'], undefined) + assert.strictEqual(res.headers['content-length'], '16') }) }) @@ -1077,11 +1082,11 @@ describe('node-fetch', () => { body: new DataView(encoder.encode('Hello, world!\n').buffer) } return fetch(url, options).then(res => res.json()).then(res => { - expect(res.method).to.equal('POST') - expect(res.body).to.equal('Hello, world!\n') - expect(res.headers['transfer-encoding']).to.be.undefined - expect(res.headers['content-type']).to.be.undefined - expect(res.headers['content-length']).to.equal('14') + assert.strictEqual(res.method, 'POST') + assert.strictEqual(res.body, 'Hello, world!\n') + assert.strictEqual(res.headers['transfer-encoding'], undefined) + assert.strictEqual(res.headers['content-type'], undefined) + assert.strictEqual(res.headers['content-length'], '14') }) }) @@ -1092,11 +1097,11 @@ describe('node-fetch', () => { body: new VMUint8Array(Buffer.from('Hello, world!\n')) } return fetch(url, options).then(res => res.json()).then(res => { - expect(res.method).to.equal('POST') - expect(res.body).to.equal('Hello, world!\n') - expect(res.headers['transfer-encoding']).to.be.undefined - expect(res.headers['content-type']).to.be.undefined - expect(res.headers['content-length']).to.equal('14') + assert.strictEqual(res.method, 'POST') + assert.strictEqual(res.body, 'Hello, world!\n') + assert.strictEqual(res.headers['transfer-encoding'], undefined) + assert.strictEqual(res.headers['content-type'], undefined) + assert.strictEqual(res.headers['content-length'], '14') }) }) @@ -1108,11 +1113,11 @@ describe('node-fetch', () => { body: encoder.encode('Hello, world!\n').subarray(7, 13) } return fetch(url, options).then(res => res.json()).then(res => { - expect(res.method).to.equal('POST') - expect(res.body).to.equal('world!') - expect(res.headers['transfer-encoding']).to.be.undefined - expect(res.headers['content-type']).to.be.undefined - expect(res.headers['content-length']).to.equal('6') + assert.strictEqual(res.method, 'POST') + assert.strictEqual(res.body, 'world!') + assert.strictEqual(res.headers['transfer-encoding'], undefined) + assert.strictEqual(res.headers['content-type'], undefined) + assert.strictEqual(res.headers['content-length'], '6') }) }) @@ -1125,11 +1130,11 @@ describe('node-fetch', () => { return fetch(url, options).then(res => { return res.json() }).then(res => { - expect(res.method).to.equal('POST') - expect(res.body).to.equal('a=1') - expect(res.headers['transfer-encoding']).to.be.undefined - // expect(res.headers['content-type']).to.be.undefined - expect(res.headers['content-length']).to.equal('3') + assert.strictEqual(res.method, 'POST') + assert.strictEqual(res.body, 'a=1') + assert.strictEqual(res.headers['transfer-encoding'], undefined) + // assert.strictEqual(res.headers['content-type'], undefined) + assert.strictEqual(res.headers['content-length'], '3') }) }) @@ -1144,11 +1149,11 @@ describe('node-fetch', () => { return fetch(url, options).then(res => { return res.json() }).then(res => { - expect(res.method).to.equal('POST') - expect(res.body).to.equal('a=1') - expect(res.headers['transfer-encoding']).to.be.undefined - expect(res.headers['content-type']).to.equal('text/plain;charset=utf-8') - expect(res.headers['content-length']).to.equal('3') + assert.strictEqual(res.method, 'POST') + assert.strictEqual(res.body, 'a=1') + assert.strictEqual(res.headers['transfer-encoding'], undefined) + assert.strictEqual(res.headers['content-type'], 'text/plain;charset=utf-8') + assert.strictEqual(res.headers['content-length'], '3') }) }) @@ -1162,11 +1167,11 @@ describe('node-fetch', () => { return fetch(url, options).then(res => { return res.json() }).then(res => { - expect(res.method).to.equal('POST') - expect(res.body).to.equal('a=1') - expect(res.headers['transfer-encoding']).to.equal('chunked') - expect(res.headers['content-type']).to.be.undefined - expect(res.headers['content-length']).to.be.undefined + assert.strictEqual(res.method, 'POST') + assert.strictEqual(res.body, 'a=1') + assert.strictEqual(res.headers['transfer-encoding'], 'chunked') + assert.strictEqual(res.headers['content-type'], undefined) + assert.strictEqual(res.headers['content-length'], undefined) }) }) @@ -1180,10 +1185,10 @@ describe('node-fetch', () => { return fetch(url, options).then(res => { return res.json() }).then(res => { - expect(res.method).to.equal('POST') - expect(res.body).to.equal('[object Object]') - expect(res.headers['content-type']).to.equal('text/plain;charset=UTF-8') - expect(res.headers['content-length']).to.equal('15') + assert.strictEqual(res.method, 'POST') + assert.strictEqual(res.body, '[object Object]') + assert.strictEqual(res.headers['content-type'], 'text/plain;charset=UTF-8') + assert.strictEqual(res.headers['content-length'], '15') }) }) @@ -1199,9 +1204,9 @@ describe('node-fetch', () => { return fetch(url, options).then(res => { return res.json() }).then(res => { - expect(res.method).to.equal('POST') - expect(res.headers['content-type']).to.startWith('multipart/form-data; boundary=') - expect(res.body).to.equal('a=1') + assert.strictEqual(res.method, 'POST') + assert.ok(res.headers['content-type'].startsWith('multipart/form-data; boundary=')) + assert.strictEqual(res.body, 'a=1') }) }) @@ -1209,20 +1214,20 @@ describe('node-fetch', () => { const parameters = new URLSearchParams() const res = new Response(parameters) res.headers.get('Content-Type') - expect(res.headers.get('Content-Type')).to.equal('application/x-www-form-urlencoded;charset=UTF-8') + assert.strictEqual(res.headers.get('Content-Type'), 'application/x-www-form-urlencoded;charset=UTF-8') }) it('constructing a Request with URLSearchParams as body should have a Content-Type', () => { const parameters = new URLSearchParams() const request = new Request(base, { method: 'POST', body: parameters }) - expect(request.headers.get('Content-Type')).to.equal('application/x-www-form-urlencoded;charset=UTF-8') + assert.strictEqual(request.headers.get('Content-Type'), 'application/x-www-form-urlencoded;charset=UTF-8') }) it('Reading a body with URLSearchParams should echo back the result', () => { const parameters = new URLSearchParams() parameters.append('a', '1') return new Response(parameters).text().then(text => { - expect(text).to.equal('a=1') + assert.strictEqual(text, 'a=1') }) }) @@ -1232,7 +1237,7 @@ describe('node-fetch', () => { const request = new Request(`${base}inspect`, { method: 'POST', body: parameters }) parameters.append('a', '1') return request.text().then(text => { - expect(text).to.equal('') + assert.strictEqual(text, '') }) }) @@ -1248,15 +1253,15 @@ describe('node-fetch', () => { return fetch(url, options).then(res => { return res.json() }).then(res => { - expect(res.method).to.equal('POST') - expect(res.headers['content-type']).to.equal('application/x-www-form-urlencoded;charset=UTF-8') - expect(res.headers['content-length']).to.equal('3') - expect(res.body).to.equal('a=1') + assert.strictEqual(res.method, 'POST') + assert.strictEqual(res.headers['content-type'], 'application/x-www-form-urlencoded;charset=UTF-8') + assert.strictEqual(res.headers['content-length'], '3') + assert.strictEqual(res.body, 'a=1') }) }) it('should still recognize URLSearchParams when extended', () => { - class CustomSearchParameters extends URLSearchParams {} + class CustomSearchParameters extends URLSearchParams { } const parameters = new CustomSearchParameters() parameters.append('a', '1') @@ -1268,10 +1273,10 @@ describe('node-fetch', () => { return fetch(url, options).then(res => { return res.json() }).then(res => { - expect(res.method).to.equal('POST') - expect(res.headers['content-type']).to.equal('application/x-www-form-urlencoded;charset=UTF-8') - expect(res.headers['content-length']).to.equal('3') - expect(res.body).to.equal('a=1') + assert.strictEqual(res.method, 'POST') + assert.strictEqual(res.headers['content-type'], 'application/x-www-form-urlencoded;charset=UTF-8') + assert.strictEqual(res.headers['content-length'], '3') + assert.strictEqual(res.body, 'a=1') }) }) @@ -1284,8 +1289,8 @@ describe('node-fetch', () => { return fetch(url, options).then(res => { return res.json() }).then(res => { - expect(res.method).to.equal('PUT') - expect(res.body).to.equal('a=1') + assert.strictEqual(res.method, 'PUT') + assert.strictEqual(res.body, 'a=1') }) }) @@ -1297,7 +1302,7 @@ describe('node-fetch', () => { return fetch(url, options).then(res => { return res.json() }).then(res => { - expect(res.method).to.equal('DELETE') + assert.strictEqual(res.method, 'DELETE') }) }) @@ -1310,10 +1315,10 @@ describe('node-fetch', () => { return fetch(url, options).then(res => { return res.json() }).then(res => { - expect(res.method).to.equal('DELETE') - expect(res.body).to.equal('a=1') - expect(res.headers['transfer-encoding']).to.be.undefined - expect(res.headers['content-length']).to.equal('3') + assert.strictEqual(res.method, 'DELETE') + assert.strictEqual(res.body, 'a=1') + assert.strictEqual(res.headers['transfer-encoding'], undefined) + assert.strictEqual(res.headers['content-length'], '3') }) }) @@ -1326,8 +1331,8 @@ describe('node-fetch', () => { return fetch(url, options).then(res => { return res.json() }).then(res => { - expect(res.method).to.equal('PATCH') - expect(res.body).to.equal('a=1') + assert.strictEqual(res.method, 'PATCH') + assert.strictEqual(res.body, 'a=1') }) }) @@ -1337,13 +1342,13 @@ describe('node-fetch', () => { method: 'HEAD' } return fetch(url, options).then(res => { - expect(res.status).to.equal(200) - expect(res.statusText).to.equal('OK') - expect(res.headers.get('content-type')).to.equal('text/plain') - // expect(res.body).to.be.an.instanceof(stream.Transform) + assert.strictEqual(res.status, 200) + assert.strictEqual(res.statusText, 'OK') + assert.strictEqual(res.headers.get('content-type'), 'text/plain') + // assert.ok(res.body instanceof stream.Transform) return res.text() }).then(text => { - expect(text).to.equal('') + assert.strictEqual(text, '') }) }) @@ -1353,11 +1358,11 @@ describe('node-fetch', () => { method: 'HEAD' } return fetch(url, options).then(res => { - expect(res.status).to.equal(404) - expect(res.headers.get('content-encoding')).to.equal('gzip') + assert.strictEqual(res.status, 404) + assert.strictEqual(res.headers.get('content-encoding'), 'gzip') return res.text() }).then(text => { - expect(text).to.equal('') + assert.strictEqual(text, '') }) }) @@ -1367,20 +1372,20 @@ describe('node-fetch', () => { method: 'OPTIONS' } return fetch(url, options).then(res => { - expect(res.status).to.equal(200) - expect(res.statusText).to.equal('OK') - expect(res.headers.get('allow')).to.equal('GET, HEAD, OPTIONS') - // expect(res.body).to.be.an.instanceof(stream.Transform) + assert.strictEqual(res.status, 200) + assert.strictEqual(res.statusText, 'OK') + assert.strictEqual(res.headers.get('allow'), 'GET, HEAD, OPTIONS') + // assert.ok(res.body instanceof stream.Transform) }) }) it('should reject decoding body twice', () => { const url = `${base}plain` return fetch(url).then(res => { - expect(res.headers.get('content-type')).to.equal('text/plain') + assert.strictEqual(res.headers.get('content-type'), 'text/plain') return res.text().then(() => { - expect(res.bodyUsed).to.be.true - return expect(res.text()).to.eventually.be.rejectedWith(Error) + assert.strictEqual(res.bodyUsed, true) + return assert.rejects(res.text(), new TypeError('Body is unusable')) }) }) }) @@ -1390,8 +1395,8 @@ describe('node-fetch', () => { return fetch(url).then(res => { const r1 = res.clone() return Promise.all([res.json(), r1.text()]).then(results => { - expect(results[0]).to.deep.equal({ name: 'value' }) - expect(results[1]).to.equal('{"name":"value"}') + assert.deepStrictEqual(results[0], { name: 'value' }) + assert.strictEqual(results[1], '{"name":"value"}') }) }) }) @@ -1401,9 +1406,9 @@ describe('node-fetch', () => { return fetch(url).then(res => { const r1 = res.clone() return res.json().then(result => { - expect(result).to.deep.equal({ name: 'value' }) + assert.deepStrictEqual(result, { name: 'value' }) return r1.text().then(result => { - expect(result).to.equal('{"name":"value"}') + assert.strictEqual(result, '{"name":"value"}') }) }) }) @@ -1414,9 +1419,9 @@ describe('node-fetch', () => { return fetch(url).then(res => { const r1 = res.clone() return r1.text().then(result => { - expect(result).to.equal('{"name":"value"}') + assert.strictEqual(result, '{"name":"value"}') return res.json().then(result => { - expect(result).to.deep.equal({ name: 'value' }) + assert.deepStrictEqual(result, { name: 'value' }) }) }) }) @@ -1426,15 +1431,15 @@ describe('node-fetch', () => { const url = `${base}hello` return fetch(url).then(res => res.text().then(() => { - expect(() => { + assert.throws(() => { res.clone() - }).to.throw(Error) + }, new TypeError('Response.clone: Body has already been consumed.')) }) ) }) - xit('should timeout on cloning response without consuming one of the streams when the second packet size is equal default highWaterMark', function () { - this.timeout(300) + // TODO: fix test. + it.skip('should timeout on cloning response without consuming one of the streams when the second packet size is equal default highWaterMark', { timeout: 300 }, function () { const url = local.mockState(res => { // Observed behavior of TCP packets splitting: // - response body size <= 65438 → single packet sent @@ -1450,8 +1455,8 @@ describe('node-fetch', () => { ).to.timeout }) - xit('should timeout on cloning response without consuming one of the streams when the second packet size is equal custom highWaterMark', function () { - this.timeout(300) + // TODO: fix test. + it.skip('should timeout on cloning response without consuming one of the streams when the second packet size is equal custom highWaterMark', { timeout: 300 }, function () { const url = local.mockState(res => { const firstPacketMaxSize = 65438 const secondPacketSize = 10 @@ -1462,13 +1467,8 @@ describe('node-fetch', () => { ).to.timeout }) - xit('should not timeout on cloning response without consuming one of the streams when the second packet size is less than default highWaterMark', function () { - // TODO: fix test. - if (!isNodeLowerThan('v16.0.0')) { - this.skip() - } - - this.timeout(300) + // TODO: fix test. + it.skip('should not timeout on cloning response without consuming one of the streams when the second packet size is less than default highWaterMark', { timeout: 300 }, async function () { const url = local.mockState(res => { const firstPacketMaxSize = 65438 const secondPacketSize = 16 * 1024 // = defaultHighWaterMark @@ -1479,13 +1479,8 @@ describe('node-fetch', () => { ).not.to.timeout }) - xit('should not timeout on cloning response without consuming one of the streams when the second packet size is less than custom highWaterMark', function () { - // TODO: fix test. - if (!isNodeLowerThan('v16.0.0')) { - this.skip() - } - - this.timeout(300) + // TODO: fix test. + it.skip('should not timeout on cloning response without consuming one of the streams when the second packet size is less than custom highWaterMark', { timeout: 300 }, function () { const url = local.mockState(res => { const firstPacketMaxSize = 65438 const secondPacketSize = 10 @@ -1496,13 +1491,8 @@ describe('node-fetch', () => { ).not.to.timeout }) - xit('should not timeout on cloning response without consuming one of the streams when the response size is double the custom large highWaterMark - 1', function () { - // TODO: fix test. - if (!isNodeLowerThan('v16.0.0')) { - this.skip() - } - - this.timeout(300) + // TODO: fix test. + it.skip('should not timeout on cloning response without consuming one of the streams when the response size is double the custom large highWaterMark - 1', { timeout: 300 }, function () { const url = local.mockState(res => { res.end(crypto.randomBytes((2 * 512 * 1024) - 1)) }) @@ -1511,13 +1501,13 @@ describe('node-fetch', () => { ).not.to.timeout }) - xit('should allow get all responses of a header', () => { - // TODO: fix test. + // TODO: fix test. + it.skip('should allow get all responses of a header', () => { const url = `${base}cookie` return fetch(url).then(res => { const expected = 'a=1, b=1' - expect(res.headers.get('set-cookie')).to.equal(expected) - expect(res.headers.get('Set-Cookie')).to.equal(expected) + assert.strictEqual(res.headers.get('set-cookie'), expected) + assert.strictEqual(res.headers.get('Set-Cookie'), expected) }) }) @@ -1525,9 +1515,9 @@ describe('node-fetch', () => { const url = `${base}hello` const request = new Request(url) return fetch(request).then(res => { - expect(res.url).to.equal(url) - expect(res.ok).to.be.true - expect(res.status).to.equal(200) + assert.strictEqual(res.url, url) + assert.strictEqual(res.ok, true) + assert.strictEqual(res.status, 200) }) }) @@ -1536,9 +1526,9 @@ describe('node-fetch', () => { const urlObject = new URL(url) const request = new Request(urlObject) return fetch(request).then(res => { - expect(res.url).to.equal(url) - expect(res.ok).to.be.true - expect(res.status).to.equal(200) + assert.strictEqual(res.url, url) + assert.strictEqual(res.ok, true) + assert.strictEqual(res.status, 200) }) }) @@ -1547,9 +1537,9 @@ describe('node-fetch', () => { const urlObject = new URL(url) const request = new Request(urlObject) return fetch(request).then(res => { - expect(res.url).to.equal(url) - expect(res.ok).to.be.true - expect(res.status).to.equal(200) + assert.strictEqual(res.url, url) + assert.strictEqual(res.ok, true) + assert.strictEqual(res.status, 200) }) }) @@ -1558,9 +1548,9 @@ describe('node-fetch', () => { const urlObject = new URL(url) const request = new Request(urlObject) return fetch(request).then(res => { - expect(res.url).to.equal(url) - expect(res.ok).to.be.true - expect(res.status).to.equal(200) + assert.strictEqual(res.url, url) + assert.strictEqual(res.ok, true) + assert.strictEqual(res.status, 200) }) }) @@ -1569,7 +1559,7 @@ describe('node-fetch', () => { .blob() .then(blob => blob.text()) .then(body => { - expect(body).to.equal('hello') + assert.strictEqual(body, 'hello') }) }) @@ -1579,7 +1569,7 @@ describe('node-fetch', () => { .then(blob => blob.arrayBuffer()) .then(ab => { const string = String.fromCharCode.apply(null, new Uint8Array(ab)) - expect(string).to.equal('hello') + assert.strictEqual(string, 'hello') }) }) @@ -1598,9 +1588,9 @@ describe('node-fetch', () => { body: blob }) }).then(res => res.json()).then(({ body, headers }) => { - expect(body).to.equal('world') - expect(headers['content-type']).to.equal(type) - expect(headers['content-length']).to.equal(String(length)) + assert.strictEqual(body, 'world') + assert.strictEqual(headers['content-type'], type) + assert.strictEqual(headers['content-length'], String(length)) }) }) @@ -1620,41 +1610,39 @@ describe('node-fetch', () => { }).then(res => { return res.json() }).then(body => { - expect(body.method).to.equal('GET') - expect(body.headers.a).to.equal('2') + assert.strictEqual(body.method, 'GET') + assert.strictEqual(body.headers.a, '2') }) }) - it('should support http request', function () { - this.timeout(5000) + it('should support http request', { timeout: 5000 }, function () { const url = 'https://github.com/' const options = { method: 'HEAD' } return fetch(url, options).then(res => { - expect(res.status).to.equal(200) - expect(res.ok).to.be.true + assert.strictEqual(res.status, 200) + assert.strictEqual(res.ok, true) }) }) it('should encode URLs as UTF-8', async () => { const url = `${base}möbius` const res = await fetch(url) - expect(res.url).to.equal(`${base}m%C3%B6bius`) + assert.strictEqual(res.url, `${base}m%C3%B6bius`) }) - it('should allow manual redirect handling', function () { - this.timeout(5000) + it('should allow manual redirect handling', { timeout: 5000 }, function () { const url = `${base}redirect/302` const options = { redirect: 'manual' } return fetch(url, options).then(res => { - expect(res.status).to.equal(302) - expect(res.url).to.equal(url) - expect(res.type).to.equal('basic') - expect(res.headers.get('Location')).to.equal('/inspect') - expect(res.ok).to.be.false + assert.strictEqual(res.status, 302) + assert.strictEqual(res.url, url) + assert.strictEqual(res.type, 'basic') + assert.strictEqual(res.headers.get('Location'), '/inspect') + assert.strictEqual(res.ok, false) }) }) }) diff --git a/test/node-fetch/mock.js b/test/node-fetch/mock.js index a53f464a1a9..f9835484328 100644 --- a/test/node-fetch/mock.js +++ b/test/node-fetch/mock.js @@ -1,7 +1,8 @@ -/* eslint no-unused-expressions: "off" */ +'use strict' // Test tools -const chai = require('chai') +const assert = require('node:assert') +const { describe, it } = require('node:test') const { fetch, @@ -10,8 +11,6 @@ const { Headers } = require('../../index.js') -const { expect } = chai - describe('node-fetch with MockAgent', () => { it('should match the url', async () => { const mockAgent = new MockAgent() @@ -30,8 +29,8 @@ describe('node-fetch with MockAgent', () => { method: 'GET' }) - expect(res.status).to.equal(200) - expect(await res.json()).to.deep.equal({ success: true }) + assert.strictEqual(res.status, 200) + assert.deepStrictEqual(await res.json(), { success: true }) }) it('should match the body', async () => { @@ -55,8 +54,8 @@ describe('node-fetch with MockAgent', () => { body: 'request body' }) - expect(res.status).to.equal(200) - expect(await res.json()).to.deep.equal({ success: true }) + assert.strictEqual(res.status, 200) + assert.deepStrictEqual(await res.json(), { success: true }) }) it('should match the headers', async () => { @@ -79,8 +78,9 @@ describe('node-fetch with MockAgent', () => { method: 'GET', headers: new Headers({ 'User-Agent': 'undici' }) }) - expect(res.status).to.equal(200) - expect(await res.json()).to.deep.equal({ success: true }) + + assert.strictEqual(res.status, 200) + assert.deepStrictEqual(await res.json(), { success: true }) }) it('should match the headers with a matching function', async () => { @@ -93,8 +93,8 @@ describe('node-fetch with MockAgent', () => { path: '/test', method: 'GET', headers (headers) { - expect(headers).to.be.an('object') - expect(headers).to.have.property('user-agent', 'undici') + assert.strictEqual(typeof headers, 'object') + assert.strictEqual(headers['user-agent'], 'undici') return true } }) @@ -106,7 +106,7 @@ describe('node-fetch with MockAgent', () => { headers: new Headers({ 'User-Agent': 'undici' }) }) - expect(res.status).to.equal(200) - expect(await res.json()).to.deep.equal({ success: true }) + assert.strictEqual(res.status, 200) + assert.deepStrictEqual(await res.json(), { success: true }) }) }) diff --git a/test/node-fetch/request.js b/test/node-fetch/request.js index 405bc2c467e..505dcc3eebb 100644 --- a/test/node-fetch/request.js +++ b/test/node-fetch/request.js @@ -1,14 +1,14 @@ +'use strict' + +const assert = require('node:assert') +const { describe, it, before, after } = require('node:test') const stream = require('node:stream') const http = require('node:http') - -const chai = require('chai') const { Blob } = require('node:buffer') -const Request = require('../../lib/fetch/request.js').Request +const { Request } = require('../../index.js') const TestServer = require('./utils/server.js') -const { expect } = chai - describe('Request', () => { const local = new TestServer() let base @@ -43,47 +43,47 @@ describe('Request', () => { 'clone', 'signal' ]) { - expect(enumerableProperties).to.contain(toCheck) + assert.ok(enumerableProperties.includes(toCheck)) } - // for (const toCheck of [ - // 'body', 'bodyUsed', 'method', 'url', 'headers', 'redirect', 'signal' - // ]) { - // expect(() => { - // request[toCheck] = 'abc' - // }).to.throw() - // } + for (const toCheck of [ + 'body', 'bodyUsed', 'method', 'url', 'headers', 'redirect', 'signal' + ]) { + assert.throws(() => { + request[toCheck] = 'abc' + }, new TypeError(`Cannot set property ${toCheck} of # which has only a getter`)) + } }) - // it('should support wrapping Request instance', () => { - // const url = `${base}hello` + it.skip('should support wrapping Request instance', () => { + const url = `${base}hello` - // const form = new FormData() - // form.append('a', '1') - // const { signal } = new AbortController() + const form = new FormData() + form.append('a', '1') + const { signal } = new AbortController() - // const r1 = new Request(url, { - // method: 'POST', - // follow: 1, - // body: form, - // signal - // }) - // const r2 = new Request(r1, { - // follow: 2 - // }) + const r1 = new Request(url, { + method: 'POST', + follow: 1, + body: form, + signal + }) + const r2 = new Request(r1, { + follow: 2 + }) - // expect(r2.url).to.equal(url) - // expect(r2.method).to.equal('POST') - // expect(r2.signal).to.equal(signal) - // // Note that we didn't clone the body - // expect(r2.body).to.equal(form) - // expect(r1.follow).to.equal(1) - // expect(r2.follow).to.equal(2) - // expect(r1.counter).to.equal(0) - // expect(r2.counter).to.equal(0) - // }) + assert.strictEqual(r2.url, url) + assert.strictEqual(r2.method, 'POST') + assert.strictEqual(r2.signal[Symbol.toStringTag], 'AbortSignal') + // Note that we didn't clone the body + assert.strictEqual(r2.body, form) + assert.strictEqual(r1.follow, 1) + assert.strictEqual(r2.follow, 2) + assert.strictEqual(r1.counter, 0) + assert.strictEqual(r2.counter, 0) + }) - xit('should override signal on derived Request instances', () => { + it.skip('should override signal on derived Request instances', () => { const parentAbortController = new AbortController() const derivedAbortController = new AbortController() const parentRequest = new Request(`${base}hello`, { @@ -92,11 +92,11 @@ describe('Request', () => { const derivedRequest = new Request(parentRequest, { signal: derivedAbortController.signal }) - expect(parentRequest.signal).to.equal(parentAbortController.signal) - expect(derivedRequest.signal).to.equal(derivedAbortController.signal) + assert.strictEqual(parentRequest.signal, parentAbortController.signal) + assert.strictEqual(derivedRequest.signal, derivedAbortController.signal) }) - xit('should allow removing signal on derived Request instances', () => { + it.skip('should allow removing signal on derived Request instances', () => { const parentAbortController = new AbortController() const parentRequest = new Request(`${base}hello`, { signal: parentAbortController.signal @@ -104,29 +104,25 @@ describe('Request', () => { const derivedRequest = new Request(parentRequest, { signal: null }) - expect(parentRequest.signal).to.equal(parentAbortController.signal) - expect(derivedRequest.signal).to.equal(null) + assert.strictEqual(parentRequest.signal, parentAbortController.signal) + assert.strictEqual(derivedRequest.signal, null) }) it('should throw error with GET/HEAD requests with body', () => { - expect(() => new Request(base, { body: '' })) - .to.throw(TypeError) - expect(() => new Request(base, { body: 'a' })) - .to.throw(TypeError) - expect(() => new Request(base, { body: '', method: 'HEAD' })) - .to.throw(TypeError) - expect(() => new Request(base, { body: 'a', method: 'HEAD' })) - .to.throw(TypeError) - expect(() => new Request(base, { body: 'a', method: 'get' })) - .to.throw(TypeError) - expect(() => new Request(base, { body: 'a', method: 'head' })) - .to.throw(TypeError) + assert.throws(() => new Request(base, { body: '' }), new TypeError('Request with GET/HEAD method cannot have body.')) + assert.throws(() => new Request(base, { body: 'a' }), new TypeError('Request with GET/HEAD method cannot have body.')) + assert.throws(() => new Request(base, { body: '', method: 'HEAD' }), new TypeError('Request with GET/HEAD method cannot have body.')) + assert.throws(() => new Request(base, { body: 'a', method: 'HEAD' }), new TypeError('Request with GET/HEAD method cannot have body.')) + assert.throws(() => new Request(base, { body: '', method: 'get' }), new TypeError('Request with GET/HEAD method cannot have body.')) + assert.throws(() => new Request(base, { body: 'a', method: 'get' }), new TypeError('Request with GET/HEAD method cannot have body.')) + assert.throws(() => new Request(base, { body: '', method: 'head' }), new TypeError('Request with GET/HEAD method cannot have body.')) + assert.throws(() => new Request(base, { body: 'a', method: 'head' }), new TypeError('Request with GET/HEAD method cannot have body.')) }) it('should default to null as body', () => { const request = new Request(base) - expect(request.body).to.equal(null) - return request.text().then(result => expect(result).to.equal('')) + assert.strictEqual(request.body, null) + return request.text().then(result => assert.strictEqual(result, '')) }) it('should support parsing headers', () => { @@ -136,8 +132,8 @@ describe('Request', () => { a: '1' } }) - expect(request.url).to.equal(url) - expect(request.headers.get('a')).to.equal('1') + assert.strictEqual(request.url, url) + assert.strictEqual(request.headers.get('a'), '1') }) it('should support arrayBuffer() method', () => { @@ -146,11 +142,11 @@ describe('Request', () => { method: 'POST', body: 'a=1' }) - expect(request.url).to.equal(url) + assert.strictEqual(request.url, url) return request.arrayBuffer().then(result => { - expect(result).to.be.an.instanceOf(ArrayBuffer) + assert.ok(result instanceof ArrayBuffer) const string = String.fromCharCode.apply(null, new Uint8Array(result)) - expect(string).to.equal('a=1') + assert.strictEqual(string, 'a=1') }) }) @@ -160,9 +156,9 @@ describe('Request', () => { method: 'POST', body: 'a=1' }) - expect(request.url).to.equal(url) + assert.strictEqual(request.url, url) return request.text().then(result => { - expect(result).to.equal('a=1') + assert.strictEqual(result, 'a=1') }) }) @@ -172,9 +168,9 @@ describe('Request', () => { method: 'POST', body: '{"a":1}' }) - expect(request.url).to.equal(url) + assert.strictEqual(request.url, url) return request.json().then(result => { - expect(result.a).to.equal(1) + assert.strictEqual(result.a, 1) }) }) @@ -184,11 +180,11 @@ describe('Request', () => { method: 'POST', body: Buffer.from('a=1') }) - expect(request.url).to.equal(url) + assert.strictEqual(request.url, url) return request.blob().then(result => { - expect(result).to.be.an.instanceOf(Blob) - expect(result.size).to.equal(3) - expect(result.type).to.equal('') + assert.ok(result instanceof Blob) + assert.strictEqual(result.size, 3) + assert.strictEqual(result.type, '') }) }) @@ -211,16 +207,16 @@ describe('Request', () => { duplex: 'half' }) const cl = request.clone() - expect(cl.url).to.equal(url) - expect(cl.method).to.equal('POST') - expect(cl.redirect).to.equal('manual') - expect(cl.headers.get('b')).to.equal('2') - expect(cl.method).to.equal('POST') + assert.strictEqual(cl.url, url) + assert.strictEqual(cl.method, 'POST') + assert.strictEqual(cl.redirect, 'manual') + assert.strictEqual(cl.headers.get('b'), '2') + assert.strictEqual(cl.method, 'POST') // Clone body shouldn't be the same body - expect(cl.body).to.not.equal(body) + assert.notDeepEqual(cl.body, body) return Promise.all([cl.text(), request.text()]).then(results => { - expect(results[0]).to.equal('a=1') - expect(results[1]).to.equal('a=1') + assert.strictEqual(results[0], 'a=1') + assert.strictEqual(results[1], 'a=1') }) }) @@ -233,7 +229,7 @@ describe('Request', () => { }) new Uint8Array(body)[0] = 0 return request.text().then(result => { - expect(result).to.equal('a=12345678901234') + assert.strictEqual(result, 'a=12345678901234') }) }) @@ -247,7 +243,7 @@ describe('Request', () => { }) body[0] = 0 return request.text().then(result => { - expect(result).to.equal('123456789') + assert.strictEqual(result, '123456789') }) }) @@ -261,7 +257,7 @@ describe('Request', () => { }) body[0] = 0n return request.text().then(result => { - expect(result).to.equal('78901234') + assert.strictEqual(result, '78901234') }) }) @@ -275,7 +271,7 @@ describe('Request', () => { }) body[0] = 0 return request.text().then(result => { - expect(result).to.equal('123456789') + assert.strictEqual(result, '123456789') }) }) }) diff --git a/test/node-fetch/response.js b/test/node-fetch/response.js index b928651edfa..e28dcb37119 100644 --- a/test/node-fetch/response.js +++ b/test/node-fetch/response.js @@ -1,14 +1,13 @@ -/* eslint no-unused-expressions: "off" */ +'use strict' -const chai = require('chai') +const assert = require('node:assert') +const { describe, it, before, after } = require('node:test') const stream = require('node:stream') -const { Response } = require('../../lib/fetch/response.js') +const { Response } = require('../../index.js') const TestServer = require('./utils/server.js') const { Blob } = require('node:buffer') const { kState } = require('../../lib/fetch/symbols.js') -const { expect } = chai - describe('Response', () => { const local = new TestServer() let base @@ -45,32 +44,30 @@ describe('Response', () => { 'headers', 'clone' ]) { - expect(enumerableProperties).to.contain(toCheck) + assert.ok(enumerableProperties.includes(toCheck)) } - // TODO - // for (const toCheck of [ - // 'body', - // 'bodyUsed', - // 'type', - // 'url', - // 'status', - // 'ok', - // 'redirected', - // 'statusText', - // 'headers' - // ]) { - // expect(() => { - // res[toCheck] = 'abc' - // }).to.throw() - // } - }) - - it('should support empty options', () => { + for (const toCheck of [ + 'body', + 'bodyUsed', + 'type', + 'url', + 'status', + 'ok', + 'redirected', + 'statusText', + 'headers' + ]) { + assert.throws(() => { + res[toCheck] = 'abc' + }, new TypeError(`Cannot set property ${toCheck} of # which has only a getter`)) + } + }) + + it('should support empty options', async () => { const res = new Response(stream.Readable.from('a=1')) - return res.text().then(result => { - expect(result).to.equal('a=1') - }) + const result = await res.text() + assert.strictEqual(result, 'a=1') }) it('should support parsing headers', () => { @@ -79,36 +76,33 @@ describe('Response', () => { a: '1' } }) - expect(res.headers.get('a')).to.equal('1') + assert.strictEqual(res.headers.get('a'), '1') }) - it('should support text() method', () => { + it('should support text() method', async () => { const res = new Response('a=1') - return res.text().then(result => { - expect(result).to.equal('a=1') - }) + const result = await res.text() + assert.strictEqual(result, 'a=1') }) - it('should support json() method', () => { + it('should support json() method', async () => { const res = new Response('{"a":1}') - return res.json().then(result => { - expect(result.a).to.equal(1) - }) + const result = await res.json() + assert.deepStrictEqual(result, { a: 1 }) }) if (Blob) { - it('should support blob() method', () => { + it('should support blob() method', async () => { const res = new Response('a=1', { method: 'POST', headers: { 'Content-Type': 'text/plain' } }) - return res.blob().then(result => { - expect(result).to.be.an.instanceOf(Blob) - expect(result.size).to.equal(3) - expect(result.type).to.equal('text/plain') - }) + const result = await res.blob() + assert.ok(result instanceof Blob) + assert.strictEqual(result.size, 3) + assert.strictEqual(result.type, 'text/plain') }) } @@ -123,129 +117,129 @@ describe('Response', () => { }) res[kState].urlList = [new URL(base)] const cl = res.clone() - expect(cl.headers.get('a')).to.equal('1') - expect(cl.type).to.equal('default') - expect(cl.url).to.equal(base) - expect(cl.status).to.equal(346) - expect(cl.statusText).to.equal('production') - expect(cl.ok).to.be.false + assert.strictEqual(cl.headers.get('a'), '1') + assert.strictEqual(cl.type, 'default') + assert.strictEqual(cl.url, base) + assert.strictEqual(cl.status, 346) + assert.strictEqual(cl.statusText, 'production') + assert.strictEqual(cl.ok, false) // Clone body shouldn't be the same body - expect(cl.body).to.not.equal(body) + assert.notStrictEqual(cl.body, body) return Promise.all([cl.text(), res.text()]).then(results => { - expect(results[0]).to.equal('a=1') - expect(results[1]).to.equal('a=1') + assert.strictEqual(results[0], 'a=1') + assert.strictEqual(results[1], 'a=1') }) }) - it('should support stream as body', () => { + it('should support stream as body', async () => { const body = stream.Readable.from('a=1') const res = new Response(body) - return res.text().then(result => { - expect(result).to.equal('a=1') - }) + const result = await res.text() + + assert.strictEqual(result, 'a=1') }) - it('should support string as body', () => { + it('should support string as body', async () => { const res = new Response('a=1') - return res.text().then(result => { - expect(result).to.equal('a=1') - }) + const result = await res.text() + + assert.strictEqual(result, 'a=1') }) - it('should support buffer as body', () => { + it('should support buffer as body', async () => { const res = new Response(Buffer.from('a=1')) - return res.text().then(result => { - expect(result).to.equal('a=1') - }) + const result = await res.text() + + assert.strictEqual(result, 'a=1') }) - it('should support ArrayBuffer as body', () => { + it('should support ArrayBuffer as body', async () => { const encoder = new TextEncoder() const fullbuffer = encoder.encode('a=12345678901234').buffer const res = new Response(fullbuffer) new Uint8Array(fullbuffer)[0] = 0 - return res.text().then(result => { - expect(result).to.equal('a=12345678901234') - }) + + const result = await res.text() + assert.strictEqual(result, 'a=12345678901234') }) it('should support blob as body', async () => { const res = new Response(new Blob(['a=1'])) - return res.text().then(result => { - expect(result).to.equal('a=1') - }) + const result = await res.text() + + assert.strictEqual(result, 'a=1') }) - it('should support Uint8Array as body', () => { + it('should support Uint8Array as body', async () => { const encoder = new TextEncoder() const fullbuffer = encoder.encode('a=12345678901234').buffer const body = new Uint8Array(fullbuffer, 2, 9) const res = new Response(body) body[0] = 0 - return res.text().then(result => { - expect(result).to.equal('123456789') - }) + + const result = await res.text() + assert.strictEqual(result, '123456789') }) - it('should support BigUint64Array as body', () => { + it('should support BigUint64Array as body', async () => { const encoder = new TextEncoder() const fullbuffer = encoder.encode('a=12345678901234').buffer const body = new BigUint64Array(fullbuffer, 8, 1) const res = new Response(body) body[0] = 0n - return res.text().then(result => { - expect(result).to.equal('78901234') - }) + + const result = await res.text() + assert.strictEqual(result, '78901234') }) - it('should support DataView as body', () => { + it('should support DataView as body', async () => { const encoder = new TextEncoder() const fullbuffer = encoder.encode('a=12345678901234').buffer const body = new Uint8Array(fullbuffer, 2, 9) const res = new Response(body) body[0] = 0 - return res.text().then(result => { - expect(result).to.equal('123456789') - }) + + const result = await res.text() + assert.strictEqual(result, '123456789') }) it('should default to null as body', () => { const res = new Response() - expect(res.body).to.equal(null) + assert.strictEqual(res.body, null) - return res.text().then(result => expect(result).to.equal('')) + return res.text().then(result => assert.strictEqual(result, '')) }) it('should default to 200 as status code', () => { const res = new Response(null) - expect(res.status).to.equal(200) + assert.strictEqual(res.status, 200) }) it('should default to empty string as url', () => { const res = new Response() - expect(res.url).to.equal('') + assert.strictEqual(res.url, '') }) it('should support error() static method', () => { const res = Response.error() - expect(res).to.be.an.instanceof(Response) - expect(res.type).to.equal('error') - expect(res.status).to.equal(0) - expect(res.statusText).to.equal('') + assert.ok(res instanceof Response) + assert.strictEqual(res.status, 0) + assert.strictEqual(res.statusText, '') + assert.strictEqual(res.type, 'error') }) it('should support undefined status', () => { const res = new Response(null, { status: undefined }) - expect(res.status).to.equal(200) + assert.strictEqual(res.status, 200) }) it('should support undefined statusText', () => { const res = new Response(null, { statusText: undefined }) - expect(res.statusText).to.equal('') + assert.strictEqual(res.statusText, '') }) it('should not set bodyUsed to undefined', () => { const res = new Response() - expect(res.bodyUsed).to.be.false + assert.strictEqual(res.bodyUsed, false) }) }) diff --git a/test/node-fetch/utils/chai-timeout.js b/test/node-fetch/utils/chai-timeout.js deleted file mode 100644 index 6838a4cc322..00000000000 --- a/test/node-fetch/utils/chai-timeout.js +++ /dev/null @@ -1,15 +0,0 @@ -const pTimeout = require('p-timeout') - -module.exports = ({ Assertion }, utils) => { - utils.addProperty(Assertion.prototype, 'timeout', async function () { - let timeouted = false - await pTimeout(this._obj, 150, () => { - timeouted = true - }) - return this.assert( - timeouted, - 'expected promise to timeout but it was resolved', - 'expected promise not to timeout but it timed out' - ) - }) -}