BUPKIS
    Preparing search index...

    @bupkis/supertest

    HTTP response assertions for Bupkis.

    Works with supertest, superagent, fetch responses, axios responses, or any object with a numeric status property.

    npm install @bupkis/supertest bupkis
    
    import { use } from 'bupkis';
    import supertestAssertions from '@bupkis/supertest';
    import request from 'supertest';

    const { expect } = use(supertestAssertions);

    // Status assertions
    const response = await request(app).get('/api/users');
    expect(response, 'to have status', 200);
    expect(response, 'to have status', 'ok');

    // Header assertions
    expect(response, 'to have header', 'content-type');
    expect(response, 'to have header', 'content-type', 'application/json');
    expect(response, 'to have header', 'content-type', /json/);

    // Body assertions
    expect(response, 'to have body');
    expect(response, 'to have JSON body');
    expect(response, 'to have JSON body satisfying', { users: [] });

    // Redirect assertions
    const redirect = await request(app).get('/old-page');
    expect(redirect, 'to redirect');
    expect(redirect, 'to redirect to', '/new-page');

    Aliases:

    {Response} to have status {number}
    {Response} to respond with status {number}
    

    Asserts that a response has a specific HTTP status code.

    Success:

    expect({ status: 200 }, 'to have status', 200);
    expect({ status: 404 }, 'to have status', 404);
    expect({ status: 500 }, 'to respond with status', 500);

    Failure:

    expect({ status: 404 }, 'to have status', 200);
    // AssertionError: Expected response to have status 200

    Negation:

    expect({ status: 404 }, 'not to have status', 200);
    

    Aliases:

    {Response} to have status {category}
    {Response} to respond with status {category}
    

    Asserts that a response has a status code within a category. Valid categories are:

    • 'ok' - 2xx status codes (200-299)
    • 'redirect' - 3xx status codes (300-399)
    • 'client error' - 4xx status codes (400-499)
    • 'server error' - 5xx status codes (500-599)

    Success:

    expect({ status: 200 }, 'to have status', 'ok');
    expect({ status: 201 }, 'to have status', 'ok');
    expect({ status: 301 }, 'to have status', 'redirect');
    expect({ status: 404 }, 'to have status', 'client error');
    expect({ status: 500 }, 'to have status', 'server error');

    Failure:

    expect({ status: 404 }, 'to have status', 'ok');
    // AssertionError: Expected response to have ok status

    Negation:

    expect({ status: 404 }, 'not to have status', 'ok');
    

    Aliases:

    {Response} to have header {string}
    {Response} to include header {string}
    

    Asserts that a response has a specific header (existence check only). Header names are matched case-insensitively.

    Success:

    const response = {
    status: 200,
    headers: { 'Content-Type': 'application/json' },
    };
    expect(response, 'to have header', 'content-type');
    expect(response, 'to have header', 'Content-Type');
    expect(response, 'to include header', 'CONTENT-TYPE');

    Failure:

    const response = {
    status: 200,
    headers: { 'content-type': 'application/json' },
    };
    expect(response, 'to have header', 'x-custom-header');
    // AssertionError: Expected response to have header "x-custom-header"

    Negation:

    const response = {
    status: 200,
    headers: { 'content-type': 'application/json' },
    };
    expect(response, 'not to have header', 'x-custom-header');

    Aliases:

    {Response} to have header {string} {string}
    {Response} to include header {string} {string}
    

    Asserts that a response has a header with an exact value.

    Success:

    const response = {
    status: 200,
    headers: { 'content-type': 'application/json' },
    };
    expect(response, 'to have header', 'content-type', 'application/json');

    Failure:

    const response = {
    status: 200,
    headers: { 'content-type': 'text/html' },
    };
    expect(response, 'to have header', 'content-type', 'application/json');
    // AssertionError: Expected header "content-type" to equal "application/json"

    With array header values (e.g., multiple Set-Cookie headers):

    const response = {
    status: 200,
    headers: { 'set-cookie': ['a=1', 'b=2'] },
    };
    expect(response, 'to have header', 'set-cookie', 'a=1, b=2');

    Negation:

    const response = {
    status: 200,
    headers: { 'content-type': 'text/html' },
    };
    expect(response, 'not to have header', 'content-type', 'application/json');

    Aliases:

    {Response} to have header {string} {RegExp}
    {Response} to include header {string} {RegExp}
    

    Asserts that a response has a header matching a regex pattern.

    Success:

    const response = {
    status: 200,
    headers: { 'content-type': 'application/json; charset=utf-8' },
    };
    expect(response, 'to have header', 'content-type', /json/);
    expect(response, 'to have header', 'content-type', /^application\//);

    const cacheResponse = {
    status: 200,
    headers: { 'cache-control': 'max-age=3600, public' },
    };
    expect(cacheResponse, 'to have header', 'cache-control', /max-age=\d+/);

    Failure:

    const response = {
    status: 200,
    headers: { 'content-type': 'text/html' },
    };
    expect(response, 'to have header', 'content-type', /json/);
    // AssertionError: Expected header "content-type" to match /json/

    Negation:

    const response = {
    status: 200,
    headers: { 'content-type': 'text/html' },
    };
    expect(response, 'not to have header', 'content-type', /json/);

    Asserts that a response has a non-empty body. Empty objects {} and empty arrays [] are considered to have a body (they're valid JSON responses).

    Success:

    expect({ status: 200, text: 'Hello' }, 'to have body');
    expect({ status: 200, body: { users: [] } }, 'to have body');
    expect({ status: 200, body: {} }, 'to have body'); // empty object counts
    expect({ status: 200, body: [] }, 'to have body'); // empty array counts

    Failure:

    expect({ status: 200 }, 'to have body');
    // AssertionError: Expected response to have a body

    expect({ status: 200, text: '', body: '' }, 'to have body');
    // AssertionError: Expected response to have a body

    Negation:

    expect({ status: 204 }, 'not to have body');
    

    Asserts that a response has an exact string body.

    Success:

    expect({ status: 200, text: 'Hello, World!' }, 'to have body', 'Hello, World!');

    // Object bodies are stringified for comparison
    expect({ status: 200, body: { id: 1 } }, 'to have body', '{"id":1}');

    Failure:

    expect({ status: 200, text: 'Hello' }, 'to have body', 'Goodbye');
    // AssertionError: Expected response body to equal string

    Negation:

    expect({ status: 200, text: 'Hello' }, 'not to have body', 'Goodbye');
    

    Asserts that a response has a JSON content-type and a body. Checks for application/json in either the type property or content-type header.

    Success:

    const response = {
    status: 200,
    type: 'application/json',
    body: { users: [] },
    };
    expect(response, 'to have JSON body');

    // Also works with content-type header
    const response2 = {
    status: 200,
    headers: { 'content-type': 'application/json; charset=utf-8' },
    body: { data: 'test' },
    };
    expect(response2, 'to have JSON body');

    Failure:

    const htmlResponse = {
    status: 200,
    type: 'text/html',
    body: '<html></html>',
    };
    expect(htmlResponse, 'to have JSON body');
    // AssertionError: Expected response to have JSON content-type

    const emptyResponse = {
    status: 204,
    type: 'application/json',
    };
    expect(emptyResponse, 'to have JSON body');
    // AssertionError: Expected response to have a JSON body

    Negation:

    const htmlResponse = {
    status: 200,
    type: 'text/html',
    body: '<html></html>',
    };
    expect(htmlResponse, 'not to have JSON body');

    Asserts that a response has a JSON body containing all specified properties with matching values. Uses partial/subset matching - the response may contain additional properties beyond those specified.

    Success:

    const response = {
    status: 200,
    body: { id: 1, name: 'John', email: 'john@example.com' },
    };

    // Partial match - only checks specified properties
    expect(response, 'to have JSON body satisfying', { id: 1 });
    expect(response, 'to have JSON body satisfying', { name: 'John' });
    expect(response, 'to have JSON body satisfying', { id: 1, name: 'John' });

    // Nested objects
    const nestedResponse = {
    status: 200,
    body: {
    user: { id: 1, profile: { name: 'John', age: 30 } },
    meta: { version: '1.0' },
    },
    };
    expect(nestedResponse, 'to have JSON body satisfying', {
    user: { profile: { name: 'John' } },
    });

    // Arrays
    const arrayResponse = {
    status: 200,
    body: { users: [{ id: 1 }, { id: 2 }] },
    };
    expect(arrayResponse, 'to have JSON body satisfying', {
    users: [{ id: 1 }, { id: 2 }],
    });

    Failure:

    const response = {
    status: 200,
    body: { id: 1 },
    };
    expect(response, 'to have JSON body satisfying', { name: 'John' });
    // AssertionError: Expected response body to satisfy specification

    const response2 = {
    status: 200,
    body: { id: 1, name: 'Jane' },
    };
    expect(response2, 'to have JSON body satisfying', { name: 'John' });
    // AssertionError: Expected response body to satisfy specification

    Negation:

    const response = {
    status: 200,
    body: { id: 1, name: 'Jane' },
    };
    expect(response, 'not to have JSON body satisfying', { name: 'John' });

    Asserts that a response body (as text) matches a regex pattern.

    Success:

    expect(
    { status: 200, text: 'Hello, World!' },
    'to have body satisfying',
    /World/,
    );
    expect(
    { status: 200, text: '{"id":123}' },
    'to have body satisfying',
    /"id":\d+/,
    );

    Failure:

    expect({ status: 200, text: 'Hello' }, 'to have body satisfying', /Goodbye/);
    // AssertionError: Expected response body to match /Goodbye/

    expect({ status: 200 }, 'to have body satisfying', /anything/);
    // AssertionError: Expected response to have a body

    Negation:

    expect(
    { status: 200, text: 'Hello' },
    'not to have body satisfying',
    /Goodbye/,
    );

    Asserts that a response body satisfies a partial object match. Similar to to have JSON body satisfying but doesn't require JSON content-type.

    Success:

    const response = {
    status: 200,
    body: { id: 1, name: 'John', extra: 'ignored' },
    };
    expect(response, 'to have body satisfying', { id: 1 });

    Failure:

    const response = {
    status: 200,
    body: { id: 1 },
    };
    expect(response, 'to have body satisfying', { name: 'John' });
    // AssertionError: Expected response body to satisfy specification

    Negation:

    const response = {
    status: 200,
    body: { id: 1 },
    };
    expect(response, 'not to have body satisfying', { name: 'John' });

    Asserts that a response is a redirect (has a 3xx status code).

    Success:

    expect({ status: 301 }, 'to redirect');
    expect({ status: 302 }, 'to redirect');
    expect({ status: 307 }, 'to redirect');
    expect({ status: 308 }, 'to redirect');

    Failure:

    expect({ status: 200 }, 'to redirect');
    // AssertionError: Expected response to be a redirect, but got status 200

    expect({ status: 404 }, 'to redirect');
    // AssertionError: Expected response to be a redirect, but got status 404

    Negation:

    expect({ status: 200 }, 'not to redirect');
    

    Asserts that a response redirects to a specific URL. The response must be a redirect (3xx) and have a Location header matching the expected URL exactly.

    Success:

    const response = {
    status: 302,
    headers: { location: '/login' },
    };
    expect(response, 'to redirect to', '/login');

    const fullUrl = {
    status: 301,
    headers: { location: 'https://example.com/new-page' },
    };
    expect(fullUrl, 'to redirect to', 'https://example.com/new-page');

    Failure:

    // Not a redirect
    const okResponse = {
    status: 200,
    headers: { location: '/somewhere' },
    };
    expect(okResponse, 'to redirect to', '/somewhere');
    // AssertionError: Expected response to be a redirect, but got status 200

    // Missing Location header
    expect({ status: 302 }, 'to redirect to', '/login');
    // AssertionError: Expected redirect response to have a Location header

    // Location doesn't match
    const response = {
    status: 302,
    headers: { location: '/dashboard' },
    };
    expect(response, 'to redirect to', '/login');
    // AssertionError: Expected redirect to "/login"

    Negation:

    const response = {
    status: 302,
    headers: { location: '/dashboard' },
    };
    expect(response, 'not to redirect to', '/login');

    Asserts that a response redirects to a URL matching a pattern. The response must be a redirect (3xx) and have a Location header matching the regex.

    Success:

    const response = {
    status: 302,
    headers: { location: '/auth/login?redirect=/dashboard' },
    };
    expect(response, 'to redirect to', /\/auth/);
    expect(response, 'to redirect to', /redirect=/);
    expect(response, 'to redirect to', /^\/auth\/login/);

    Failure:

    // Not a redirect
    const okResponse = {
    status: 200,
    headers: { location: '/somewhere' },
    };
    expect(okResponse, 'to redirect to', /somewhere/);
    // AssertionError: Expected response to be a redirect, but got status 200

    // Location doesn't match pattern
    const response = {
    status: 302,
    headers: { location: '/dashboard' },
    };
    expect(response, 'to redirect to', /login/);
    // AssertionError: Expected redirect Location to match /login/

    Negation:

    const response = {
    status: 302,
    headers: { location: '/dashboard' },
    };
    expect(response, 'not to redirect to', /login/);

    This library works with any object that has a numeric status property. It's designed to be compatible with:

    • supertest responses
    • superagent responses (uses header instead of headers)
    • fetch responses (after calling .json() or similar)
    • axios responses
    • Plain objects for testing
    // Minimal response
    expect({ status: 200 }, 'to have status', 200);

    // supertest/superagent style
    expect(
    {
    status: 200,
    headers: { 'content-type': 'application/json' },
    body: { users: [] },
    text: '{"users":[]}',
    type: 'application/json',
    },
    'to have JSON body',
    );

    // superagent uses 'header' (singular)
    expect(
    {
    status: 200,
    header: { 'content-type': 'text/html' },
    },
    'to have header',
    'content-type',
    );

    Copyright © 2026 Christopher "boneskull" Hiller. Licensed under BlueOak-1.0.0.