OverviewFilesCommitsIssuesDocsReleasesPeers

P2P-Hiverelay / test / unit / api-body.test.js

63 lines · javascript ref:
import test from 'brittle'
import { PassThrough } from 'stream'
import { readJsonBody } from 'p2p-hiverelay/core/relay-node/api-body.js'

function bodyStream (body) {
  const stream = new PassThrough()
  stream.end(body)
  return stream
}

test('api body: parses JSON objects and empty bodies', async (t) => {
  t.alike(await readJsonBody(bodyStream('{"ok":true,"count":2}')), { ok: true, count: 2 })
  t.alike(await readJsonBody(bodyStream('')), {})
})

test('api body: rejects malformed JSON with stable error message', async (t) => {
  try {
    await readJsonBody(bodyStream('{"ok":'))
    t.fail('malformed body should reject')
  } catch (err) {
    t.is(err.message, 'Invalid JSON body')
  }
})

test('api body: rejects top-level arrays and primitives with stable error message', async (t) => {
  for (const body of ['[]', 'null', '"string"', '42', 'true']) {
    try {
      await readJsonBody(bodyStream(body))
      t.fail(`${body} should reject`)
    } catch (err) {
      t.is(err.message, 'JSON body must be an object')
    }
  }
})

test('api body: rejects oversized bodies while draining the stream', async (t) => {
  const stream = new PassThrough()
  const originalResume = stream.resume
  let resumed = false
  stream.resume = function resume () {
    resumed = true
    return originalResume.call(this)
  }

  const result = readJsonBody(stream, 4).catch(err => err)
  stream.write(Buffer.from('{"tooLarge":true}'))
  const err = await result
  stream.end()

  t.is(err.message, 'Request body too large')
  t.ok(resumed, 'oversized body is drained instead of destroying the socket')
})

test('api body: forwards stream errors once', async (t) => {
  const stream = new PassThrough()
  const boom = new Error('socket read failed')
  const result = readJsonBody(stream).catch(err => err)
  stream.emit('error', boom)
  stream.end('{"ignored":true}')

  t.is(await result, boom)
})