CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-loopback--testlab

A collection of test utilities specifically designed for LoopBack 4 applications and TypeScript testing

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

http-client.mddocs/

HTTP Client Testing

SuperTest integration and utilities for creating HTTP clients for testing REST applications and request handlers.

Capabilities

SuperTest Integration

Complete SuperTest library re-export for HTTP testing.

/**
 * SuperTest library for HTTP endpoint testing
 * Provides fluent API for making HTTP requests and assertions
 */
const supertest: typeof import("supertest");

/**
 * SuperTest client type for making HTTP requests
 */
type Client = supertest.SuperTest<supertest.Test>;

Usage Examples:

import { supertest } from "@loopback/testlab";
import express from "express";

const app = express();
app.get("/users", (req, res) => res.json([{id: 1, name: "Alice"}]));

// Direct SuperTest usage
await supertest(app)
  .get("/users")
  .expect(200)
  .expect("Content-Type", /json/)
  .expect([{id: 1, name: "Alice"}]);

Client for Handler Function

Creates a SuperTest client for testing HTTP handler functions without starting a server.

/**
 * Create a SuperTest client connected to an HTTP server listening
 * on an ephemeral port and calling handler to handle incoming requests
 * @param handler - Request handler function
 * @returns SuperTest client for making requests
 */
function createClientForHandler(
  handler: (req: http.IncomingMessage, res: http.ServerResponse) => void
): Client;

Usage Examples:

import { createClientForHandler, expect } from "@loopback/testlab";
import { IncomingMessage, ServerResponse } from "http";

// Simple handler
function simpleHandler(req: IncomingMessage, res: ServerResponse) {
  res.writeHead(200, {"Content-Type": "application/json"});
  res.end(JSON.stringify({message: "Hello World"}));
}

// Create client and test
const client = createClientForHandler(simpleHandler);

await client
  .get("/")
  .expect(200)
  .expect("Content-Type", /json/)
  .expect({message: "Hello World"});

// Handler with routing logic
function routingHandler(req: IncomingMessage, res: ServerResponse) {
  const url = req.url;
  res.writeHead(200, {"Content-Type": "application/json"});
  
  if (url === "/users") {
    res.end(JSON.stringify([{id: 1, name: "Alice"}]));
  } else if (url === "/status") {
    res.end(JSON.stringify({status: "ok"}));
  } else {
    res.writeHead(404);
    res.end(JSON.stringify({error: "Not found"}));
  }
}

const routingClient = createClientForHandler(routingHandler);

await routingClient.get("/users").expect(200).expect([{id: 1, name: "Alice"}]);
await routingClient.get("/status").expect(200).expect({status: "ok"});
await routingClient.get("/invalid").expect(404);

Client for REST Application

Creates a SuperTest client for testing running LoopBack REST applications.

/**
 * Create a SuperTest client for a running RestApplication instance
 * The app must be running and listening on a port
 * @param app - A running RestApplication instance
 * @returns SuperTest client for the application
 * @throws Error if the application is not listening
 */
function createRestAppClient(app: RestApplicationLike): Client;

/**
 * Interface for LoopBack-like REST applications
 */
interface RestApplicationLike {
  restServer: RestServerLike;
}

/**
 * Interface for LoopBack-like REST servers
 */
interface RestServerLike {
  url?: string;
  rootUrl?: string;
}

Usage Examples:

import { createRestAppClient, expect } from "@loopback/testlab";

// Assuming you have a LoopBack application
class MyApplication {
  restServer = {
    url: "http://localhost:3000",
    rootUrl: "http://localhost:3000"
  };
}

const app = new MyApplication();

// Create client for running application
const client = createRestAppClient(app);

// Test application endpoints
await client
  .get("/ping")
  .expect(200)
  .expect({greeting: "Hello from LoopBack"});

await client
  .post("/users")
  .send({name: "Bob", email: "bob@example.com"})
  .expect(201)
  .expect((res) => {
    expect(res.body).to.have.property("id");
    expect(res.body.name).to.equal("Bob");
  });

// Testing with different HTTP methods
await client.get("/users").expect(200);
await client.put("/users/1").send({name: "Updated"}).expect(200);
await client.delete("/users/1").expect(204);

SuperTest Test Interface

Common SuperTest methods and assertions for HTTP testing.

// SuperTest Test interface (partial - key methods)
interface Test {
  // HTTP methods
  get(url: string): Test;
  post(url: string): Test;
  put(url: string): Test;
  patch(url: string): Test;
  delete(url: string): Test;
  head(url: string): Test;
  options(url: string): Test;
  
  // Request configuration
  send(data: any): Test;
  query(params: object | string): Test;
  set(field: string, value: string): Test;
  set(fields: object): Test;
  auth(user: string, pass: string): Test;
  attach(field: string, file: string, filename?: string): Test;
  field(name: string, value: string): Test;
  
  // Response expectations
  expect(status: number): Test;
  expect(status: number, callback?: (err: Error, res: Response) => void): Test;
  expect(body: any): Test;
  expect(field: string, value: string | RegExp): Test;
  expect(callback: (res: Response) => void): Test;
  
  // Execution
  end(callback: (err: Error, res: Response) => void): void;
  then(resolve: (res: Response) => void, reject?: (err: Error) => void): Promise<Response>;
}

Usage Examples:

import { createClientForHandler } from "@loopback/testlab";

const client = createClientForHandler(handler);

// Method chaining
await client
  .post("/api/users")
  .set("Content-Type", "application/json")
  .set("Authorization", "Bearer token123")
  .send({name: "Charlie", email: "charlie@example.com"})
  .expect(201)
  .expect("Content-Type", /json/)
  .expect((res) => {
    expect(res.body).to.have.property("id");
    expect(res.body.name).to.equal("Charlie");
  });

// Query parameters
await client
  .get("/api/users")
  .query({limit: 10, offset: 0})
  .expect(200);

// File uploads
await client
  .post("/api/upload")
  .attach("file", "/path/to/file.jpg")
  .field("description", "Profile picture")
  .expect(200);

// Custom expectations
await client
  .get("/api/status")
  .expect((res) => {
    expect(res.body.uptime).to.be.greaterThan(0);
    expect(res.headers).to.have.property("x-api-version");
  });

Error Handling

Proper error handling patterns for HTTP client testing.

Usage Examples:

import { createRestAppClient, expect } from "@loopback/testlab";

// Testing error responses
await client
  .get("/api/nonexistent")
  .expect(404)
  .expect({error: "Resource not found"});

// Testing validation errors
await client
  .post("/api/users")
  .send({}) // Missing required fields
  .expect(422)
  .expect((res) => {
    expect(res.body.error.details).to.be.an.Array();
  });

// Testing authentication errors
await client
  .get("/api/protected")
  .expect(401)
  .expect({error: "Unauthorized"});

// Handling client creation errors
try {
  const nonRunningApp = { restServer: {} }; // No URL
  const client = createRestAppClient(nonRunningApp);
} catch (error) {
  expect(error.message).to.match(/not listening/);
}

docs

assertions.md

http-client.md

http-utilities.md

index.md

request-response-mocking.md

test-doubles.md

test-sandbox.md

validation-helpers.md

tile.json