npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@otmc-sw/tester

v0.1.13

Published

Modern Playwright wrapper for concise, type-safe API and UI testing.

Readme

@otmc/tester

@otmc/tester is NOT a replacement for Playwright.

Playwright remains responsible for:

  • HTTP transport
  • Browser automation
  • Parallel execution
  • Retry
  • Fixtures
  • Reporting
  • Trace
  • Screenshots

@otmc/tester only provides a clean, type-safe DSL for defining API test cases.

The developer should describe what to test.

The framework should decide how to execute it.

📚 Hướng dẫn sử dụng

📦 Cài đặt

npm install @otmc/tester

⚙️ Cấu hình dự án

Tạo file playwright.config.ts:

import { defineConfig } from '@playwright/test';

export default defineConfig({
  globalSetup: './examples/setup.ts',
  use: {
    baseURL: 'http://localhost:3000',
  },
});

Tạo file cấu hình tester (examples/config.ts):

import { defineConfig } from '@otmc/tester';

export default defineConfig({
  baseURL: 'http://localhost:3000',
  response: {
    success: {
      successField: 'success',
      messageField: { name: 'message', required: false },
      dataField: 'data'
    },
    error: {
      successField: 'success',
      messageField: { name: 'message', required: false },
      errorField: 'error'
    }
  }
});

📝 Định nghĩa Types

Tạo file examples/types.ts để định nghĩa các types:

export class User {
  id!: string;
  username!: string;
  email!: string;
  role!: 'admin' | 'user' | 'moderator';
  createdAt!: string;
  updatedAt!: string;
}

export interface CreateUserRequest {
  username: string;
  email: string;
  password: string;
  role?: 'admin' | 'user' | 'moderator';
}

export interface UpdateUserRequest {
  username?: string;
  email?: string;
  role?: 'admin' | 'user' | 'moderator';
}

🎯 Viết Test Cases

Tạo file test (examples/api/user.spec.ts):

import { test } from '@playwright/test';
import { defineAPIs, createTestCases } from '@otmc/tester';
import { User, CreateUserRequest, UpdateUserRequest } from '../types.js';
import config from '../config.js';

const suite = defineAPIs([
  {
    title: "List Users - Get all users",
    GET: "/users",
    response: User,
    status: 200
  },

  {
    title: "Create User - Create admin user",
    POST: "/users",
    request: {
      username: "admin_user",
      email: "[email protected]",
      password: "SecurePass123!",
      role: "admin"
    } as CreateUserRequest,
    response: User,
    status: 201
  },

  {
    title: "Get User - By ID",
    GET: "/users/1",
    response: User,
    status: 200
  },

  {
    title: "Update User - Partial update - Email only",
    PATCH: "/users/1",
    request: {
      email: "[email protected]"
    } as UpdateUserRequest,
    response: User,
    status: 200
  },

  {
    title: "Delete User - Non-existent user",
    DELETE: "/users/99999",
    status: 404
  }
], config);

test.describe('Users', () => {
  const { testCases } = createTestCases(suite);
  for (const tc of testCases) {
    test(tc.title, async ({ request }) => {
      await tc.execute(request);
    });
  }
});

🚀 Chạy Tests

# Chạy tất cả tests
npx playwright test

# Chạy tests với UI mode
npx playwright test --ui

# Chạy tests với report chi tiết
npx playwright test --reporter=html

🎨 Các loại HTTP Methods

Hỗ trợ đầy đủ các HTTP methods:

1. GET - Lấy dữ liệu

{
  title: "Get User by ID",
  GET: "/users/1",
  response: User,
  status: 200
}

2. POST - Tạo mới

{
  title: "Create User",
  POST: "/users",
  request: {
    username: "new_user",
    email: "[email protected]",
    password: "password123"
  },
  response: User,
  status: 201
}

3. PUT - Cập nhật toàn bộ

{
  title: "Update User",
  PUT: "/users/1",
  request: {
    username: "updated_user",
    email: "[email protected]",
    password: "newpassword"
  },
  response: User,
  status: 200
}

4. PATCH - Cập nhật một phần

{
  title: "Update User Email",
  PATCH: "/users/1",
  request: {
    email: "[email protected]"
  },
  response: User,
  status: 200
}

5. DELETE - Xóa

{
  title: "Delete User",
  DELETE: "/users/1",
  status: 204
}

🔧 Các tùy chọn nâng cao

Query Parameters

{
  title: "List Users with pagination",
  GET: "/users?page=1&limit=10",
  response: User,
  status: 200
}

Custom Headers

{
  title: "Get with Auth",
  GET: "/users/me",
  headers: {
    'Authorization': 'Bearer token123'
  },
  response: User,
  status: 200
}

Error Testing

{
  title: "Invalid credentials",
  POST: "/auth/login",
  request: {
    username: "wrong",
    password: "wrong"
  },
  status: 401  // Chỉ kiểm tra status, không cần response type
}

Multiple Status Codes

// Chấp nhận một status code
{
  title: "List all products",
  GET: "/products",
  response: Product,
  status: 200
}

// Chấp nhận một status code (dạng mảng)
{
  title: "List all products",
  GET: "/products",
  response: Product,
  status: [200]
}

// Chấp nhận nhiều status code
{
  title: "List all products",
  GET: "/products",
  response: Product,
  status: [200, 201]
}

Response với Envelope

{
  title: "Get User with envelope",
  GET: "/users/1",
  response: User,
  status: 200,
  envelope: {
    successField: 'success',
    dataField: 'data'
  }
}

💡 Ví dụ thực tế

1. Testing với Pagination

const suite = defineAPIs([
  {
    title: "Page 1",
    GET: "/users?page=1&limit=10",
    response: User,
    status: 200
  },
  {
    title: "Page 2",
    GET: "/users?page=2&limit=10",
    response: User,
    status: 200
  }
]);

2. Testing với Filters

{
  title: "Filter by role",
  GET: "/users?role=admin",
  response: User,
  status: 200
}

3. Testing các trường hợp lỗi

{
  title: "Invalid email format",
  POST: "/users",
  request: {
    username: "bad_user",
    email: "invalid-email",
    password: "Pass123!"
  },
  status: 400
}

{
  title: "Missing required fields",
  POST: "/users",
  request: {
    username: "incomplete_user"
  },
  status: 400
}

{
  title: "Non-existent user",
  GET: "/users/99999",
  status: 404
}

📊 Validation

@otmc/tester tự động validate:

HTTP Status - Status code khớp với expected
Content-Type - Đảm bảo response là JSON
JSON Parsing - Parse JSON thành TypeScript object
Success/Error Contract - Validate cấu trúc envelope
Required Fields - Kiểm tra các trường bắt buộc
Field Types - Validate kiểu dữ liệu
Response Mapping - Unwrap response envelope tự động

🏗️ Kiến trúc

defineConfig() → Cấu hình toàn cục
       ↓
defineAPIs() → Định nghĩa test cases
       ↓
normalize() → Chuẩn hóa format
       ↓
run() → Chạy tests
       ↓
Executor → Điều phối
       ↓
RequestBuilder → Tạo request
       ↓
Playwright APIRequestContext → Thực thi HTTP
       ↓
ResponseParser → Parse response
       ↓
EnvelopeProcessor → Xử lý envelope
       ↓
ResponseValidator → Validate response
       ↓
ResponseMapper → Map dữ liệu
       ↓
Reporter → Báo cáo kết quả

🔍 Best Practices

  1. Tách types ra file riêng - Dễ maintain và reuse
  2. Đặt tên test rõ ràng - Mô tả đúng mục đích của test
  3. Test happy path trước - Sau đó đến error cases
  4. Sử dụng constants cho URLs và test data
  5. Setup test data trong globalSetup hoặc beforeEach
  6. Cleanup sau khi test nếu cần

📚 Resources

📜 License

  • Apache License 2.0
  • Copyright (c) 2026 OTMC Softwares.

✨ Contributors

  • 🌿 Nguyen Van Trung
  • 🌿 Nguyen Thi Hoai
  • 🌿 OTMC Contributors