Back to Repositories

Testing Content Negotiation Acceptance Handling in Koa Framework

This test suite evaluates the content negotiation functionality in Koa’s request handling through the ctx.accepts() method. It comprehensively tests MIME type acceptance, header parsing, and content type matching capabilities.

Test Coverage Overview

The test suite provides extensive coverage of content negotiation scenarios in Koa applications.

Key areas tested include:
  • Empty Accept headers handling
  • Multiple MIME type acceptance
  • File extension to MIME type conversion
  • Exact and wildcard MIME type matching
  • Array-based content type negotiations

Implementation Analysis

The testing approach uses Node’s built-in test framework with a modular structure focused on context manipulation. The tests employ descriptive nesting with describe blocks to organize different acceptance scenarios, using isolated context creation for each test case.

Technical patterns include:
  • Context object mocking
  • Header manipulation testing
  • MIME type conversion verification
  • Priority-based content negotiation

Technical Details

Testing infrastructure includes:
  • Node.js test runner (node:test)
  • Native assert module for validations
  • Custom test helpers for context creation
  • Strict mode JavaScript execution
  • Isolated test context per case

Best Practices Demonstrated

The test suite exemplifies high-quality testing practices through well-structured test organization and comprehensive coverage.

Notable practices include:
  • Isolated test contexts
  • Descriptive test case naming
  • Comprehensive edge case coverage
  • Consistent assertion patterns
  • Hierarchical test organization

koajs/koa

__tests__/request/accepts.test.js

            
'use strict'

const { describe, it } = require('node:test')
const assert = require('assert')
const context = require('../../test-helpers/context')

describe('ctx.accepts(types)', () => {
  describe('with no arguments', () => {
    describe('when Accept is populated', () => {
      it('should return all accepted types', () => {
        const ctx = context()
        ctx.req.headers.accept = 'application/*;q=0.2, image/jpeg;q=0.8, text/html, text/plain'
        assert.deepStrictEqual(ctx.accepts(), ['text/html', 'text/plain', 'image/jpeg', 'application/*'])
      })
    })
  })

  describe('with no valid types', () => {
    describe('when Accept is populated', () => {
      it('should return false', () => {
        const ctx = context()
        ctx.req.headers.accept = 'application/*;q=0.2, image/jpeg;q=0.8, text/html, text/plain'
        assert.strictEqual(ctx.accepts('image/png', 'image/tiff'), false)
      })
    })

    describe('when Accept is not populated', () => {
      it('should return the first type', () => {
        const ctx = context()
        assert.strictEqual(ctx.accepts('text/html', 'text/plain', 'image/jpeg', 'application/*'), 'text/html')
      })
    })
  })

  describe('when extensions are given', () => {
    it('should convert to mime types', () => {
      const ctx = context()
      ctx.req.headers.accept = 'text/plain, text/html'
      assert.strictEqual(ctx.accepts('html'), 'html')
      assert.strictEqual(ctx.accepts('.html'), '.html')
      assert.strictEqual(ctx.accepts('txt'), 'txt')
      assert.strictEqual(ctx.accepts('.txt'), '.txt')
      assert.strictEqual(ctx.accepts('png'), false)
    })
  })

  describe('when an array is given', () => {
    it('should return the first match', () => {
      const ctx = context()
      ctx.req.headers.accept = 'text/plain, text/html'
      assert.strictEqual(ctx.accepts(['png', 'text', 'html']), 'text')
      assert.strictEqual(ctx.accepts(['png', 'html']), 'html')
    })
  })

  describe('when multiple arguments are given', () => {
    it('should return the first match', () => {
      const ctx = context()
      ctx.req.headers.accept = 'text/plain, text/html'
      assert.strictEqual(ctx.accepts('png', 'text', 'html'), 'text')
      assert.strictEqual(ctx.accepts('png', 'html'), 'html')
    })
  })

  describe('when value present in Accept is an exact match', () => {
    it('should return the type', () => {
      const ctx = context()
      ctx.req.headers.accept = 'text/plain, text/html'
      assert.strictEqual(ctx.accepts('text/html'), 'text/html')
      assert.strictEqual(ctx.accepts('text/plain'), 'text/plain')
    })
  })

  describe('when value present in Accept is a type match', () => {
    it('should return the type', () => {
      const ctx = context()
      ctx.req.headers.accept = 'application/json, */*'
      assert.strictEqual(ctx.accepts('text/html'), 'text/html')
      assert.strictEqual(ctx.accepts('text/plain'), 'text/plain')
      assert.strictEqual(ctx.accepts('image/png'), 'image/png')
    })
  })

  describe('when value present in Accept is a subtype match', () => {
    it('should return the type', () => {
      const ctx = context()
      ctx.req.headers.accept = 'application/json, text/*'
      assert.strictEqual(ctx.accepts('text/html'), 'text/html')
      assert.strictEqual(ctx.accepts('text/plain'), 'text/plain')
      assert.strictEqual(ctx.accepts('image/png'), false)
      assert.strictEqual(ctx.accepts('png'), false)
    })
  })
})