Skip to content

Commit

Permalink
test: increase coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
Uzlopak committed Apr 15, 2024
1 parent d6010fb commit bd481eb
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 27 deletions.
6 changes: 3 additions & 3 deletions lib/core/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const {
const assert = require('node:assert')
const {
isValidHTTPToken,
isValidHeaderChar,
isValidHeaderValue,
isStream,
destroy,
isBuffer,
Expand Down Expand Up @@ -336,7 +336,7 @@ function processHeader (request, key, val) {
const arr = []
for (let i = 0; i < val.length; i++) {
if (typeof val[i] === 'string') {
if (!isValidHeaderChar(val[i])) {
if (!isValidHeaderValue(val[i])) {
throw new InvalidArgumentError(`invalid ${key} header`)
}
arr.push(val[i])
Expand All @@ -350,7 +350,7 @@ function processHeader (request, key, val) {
}
val = arr
} else if (typeof val === 'string') {
if (!isValidHeaderChar(val)) {
if (!isValidHeaderValue(val)) {
throw new InvalidArgumentError(`invalid ${key} header`)
}
} else if (val === null) {
Expand Down
4 changes: 2 additions & 2 deletions lib/core/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/
/**
* @param {string} characters
*/
function isValidHeaderChar (characters) {
function isValidHeaderValue (characters) {
return !headerCharRegex.test(characters)
}

Expand Down Expand Up @@ -627,7 +627,7 @@ module.exports = {
buildURL,
addAbortListener,
isValidHTTPToken,
isValidHeaderChar,
isValidHeaderValue,
isTokenCharCode,
parseRangeHeader,
isValidPort,
Expand Down
159 changes: 137 additions & 22 deletions test/client-request.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
'use strict'

const { tspl } = require('@matteo.collina/tspl')
const { test, after } = require('node:test')
const { test, after, describe, before } = require('node:test')
const { Client, errors } = require('..')
const { createServer } = require('node:http')
const EE = require('node:events')
const { kConnect } = require('../lib/core/symbols')
const { Readable } = require('node:stream')
const net = require('node:net')
const { promisify } = require('node:util')
const { NotSupportedError } = require('../lib/core/errors')
const { NotSupportedError, InvalidArgumentError } = require('../lib/core/errors')
const { parseFormDataString } = require('./utils/formdata')

test('request dump big', async (t) => {
Expand Down Expand Up @@ -53,6 +53,7 @@ test('request dump', async (t) => {
t = tspl(t, { plan: 3 })

const server = createServer((req, res) => {
res.setHeader('content-length', 5)
res.end('hello')
})
after(() => server.close())
Expand Down Expand Up @@ -391,34 +392,148 @@ test('request text', async (t) => {
await t.completed
})

test('empty host header', async (t) => {
t = tspl(t, { plan: 3 })
describe('headers', () => {
describe('invalid headers', () => {
test('invalid header value - array with string with invalid character', async (t) => {
t = tspl(t, { plan: 1 })

const server = createServer((req, res) => {
res.end(req.headers.host)
})
after(() => server.close())
const client = new Client('http://localhost:8080')
after(() => client.destroy())

server.listen(0, async () => {
const serverAddress = `localhost:${server.address().port}`
const client = new Client(`http://${serverAddress}`)
after(() => client.destroy())
t.rejects(client.request({
path: '/',
method: 'GET',
headers: { name: ['test\0'] }
}), new InvalidArgumentError('invalid name header'))

await t.completed
})
test('invalid header value - array with POJO', async (t) => {
t = tspl(t, { plan: 1 })

const client = new Client('http://localhost:8080')
after(() => client.destroy())

const getWithHost = async (host, wanted) => {
const { body } = await client.request({
t.rejects(client.request({
path: '/',
method: 'GET',
headers: { host }
})
t.strictEqual(await body.text(), wanted)
}
headers: { name: [{}] }
}), new InvalidArgumentError('invalid name header'))

await t.completed
})

test('invalid header value - string with invalid character', async (t) => {
t = tspl(t, { plan: 1 })

await getWithHost('test', 'test')
await getWithHost(undefined, serverAddress)
await getWithHost('', '')
const client = new Client('http://localhost:8080')
after(() => client.destroy())

t.rejects(client.request({
path: '/',
method: 'GET',
headers: { name: 'test\0' }
}), new InvalidArgumentError('invalid name header'))

await t.completed
})
})

await t.completed
describe('array', () => {
let serverAddress
const server = createServer((req, res) => {
res.end(JSON.stringify(req.headers))
})

before(async () => {
server.listen(0)
await EE.once(server, 'listening')
serverAddress = `localhost:${server.address().port}`
})

after(() => server.close())

test('empty host header', async (t) => {
t = tspl(t, { plan: 4 })

const client = new Client(`http://${serverAddress}`)
after(() => client.destroy())

const testCase = async (expected, actual) => {
const { body } = await client.request({
path: '/',
method: 'GET',
headers: expected
})

const result = await body.json()
t.deepStrictEqual(result, { ...result, ...actual })
}

await testCase({ key: [null] }, { key: '' })
await testCase({ key: ['test'] }, { key: 'test' })
await testCase({ key: ['test', 'true'] }, { key: 'test, true' })
await testCase({ key: ['test', true] }, { key: 'test, true' })

await t.completed
})
})

describe('host', () => {
let serverAddress
const server = createServer((req, res) => {
res.end(req.headers.host)
})

before(async () => {
server.listen(0)
await EE.once(server, 'listening')
serverAddress = `localhost:${server.address().port}`
})

after(() => server.close())

test('invalid host header', async (t) => {
t = tspl(t, { plan: 1 })

const client = new Client(`http://${serverAddress}`)
after(() => client.destroy())

t.rejects(client.request({
path: '/',
method: 'GET',
headers: {
host: [
'www.example.com'
]
}
}), new InvalidArgumentError('invalid host header'))

await t.completed
})

test('empty host header', async (t) => {
t = tspl(t, { plan: 3 })

const client = new Client(`http://${serverAddress}`)
after(() => client.destroy())

const getWithHost = async (host, wanted) => {
const { body } = await client.request({
path: '/',
method: 'GET',
headers: { host }
})
t.strictEqual(await body.text(), wanted)
}

await getWithHost('test', 'test')
await getWithHost(undefined, serverAddress)
await getWithHost('', '')

await t.completed
})
})
})

test('request long multibyte text', async (t) => {
Expand Down
14 changes: 14 additions & 0 deletions test/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,20 @@ test('Absolute URL as pathname should be included in req.path', async (t) => {
t.end()
})

describe('DispatchOptions#expectContinue', () => {
test('Should throw if invalid expectContinue option', async t => {
t = tspl(t, { plan: 1 })

await t.rejects(request({
method: 'GET',
origin: 'http://somehost.xyz',
expectContinue: 0
}), /invalid expectContinue/)

await t.completed
})
})

describe('DispatchOptions#reset', () => {
test('Should throw if invalid reset option', async t => {
t = tspl(t, { plan: 1 })
Expand Down

0 comments on commit bd481eb

Please sign in to comment.