Modern API Testing Toolkit - Browser Extension + PWA + CLI + Fetch + Core
A powerful, fast, and beautiful API testing solution available as a browser extension, Progressive Web App (PWA), command-line tool, universal HTTP client, and testing utilities library.
π Visit the Official Website - Comprehensive documentation, guides, and blog
Looking for specific package documentation?
- Official Website - Homepage and guides
- Extension Docs - Browser extension documentation
- CLI Docs - Command-line tool documentation
- Fetch Docs - Universal HTTP client documentation
- Core Docs - Testing utilities API reference
- CLI README - CLI package details
- Fetch README - Fetch package details
- Core README - Core library details
- Website README - Website development
- Extension Changelog - Browser extension history
- CLI Changelog - CLI version history
- Core Changelog - Core version history
PingPong is a comprehensive API testing toolkit with five products:
| Product | Description | Best For |
|---|---|---|
| π Browser Extension | Full-featured API client in Chrome/Firefox | Interactive testing, debugging, quick experiments |
| π± Progressive Web App | Installable standalone web app | Cross-platform testing without extension stores |
| β‘ CLI Tool | Fast command-line API testing | CI/CD, automation, scripting, load testing |
| π Fetch Library | Universal HTTP client for Node.js & browsers | Building apps, integrating HTTP in any environment |
| π¦ Core Library | Testing utilities (variables, assertions, cookies) | Advanced testing features, CLI internals |
# Install dependencies
npm install
# Build for Chrome
npm run build:chrome
# Build for Firefox
npm run build:firefox
# Load extension from builds/chrome or builds/firefoxThen install the unpacked extension in your browser.
# Install dependencies
npm install
# Build PWA
npm run build:pwa
# Preview locally
npm run preview:pwaThen visit http://localhost:3000 and install the PWA by clicking the install icon in your browser's address bar. For deployment, see PWA_DEPLOYMENT.md.
# Install globally
npm install -g @pingpong-js/cli
# Simple GET request
pingpong send GET https://api.mockly.codes/users
# POST with JSON
pingpong send POST https://api.mockly.codes/users \
-H "Content-Type: application/json" \
-d '{"name":"John","email":"john@example.com"}'
# Interactive mode
pingpong request
# Load testing
pingpong load https://api.mockly.codes/health -n 100 -c 10npm install @pingpong-js/fetchimport { HttpClient } from '@pingpong-js/fetch';
// Works in both Node.js and browser!
const client = new HttpClient({ timeout: 5000 });
const response = await client.get('https://api.mockly.codes/users');
console.log(response.status, response.body);npm install @pingpong-js/coreimport { VariableResolver, JSONPath, AssertionEngine } from '@pingpong-js/core';
const resolver = new VariableResolver({ API_KEY: 'secret' });
const url = resolver.resolve('https://api.mockly.codes?key={{API_KEY}}');The PWA version provides the same full-featured experience as the browser extension, but installable directly from your browser without needing an extension store!
- Install the PingPong browser extension
- Open the extension - you'll see a banner at the top
- Click "Install" in the banner
- Browser opens the PWA URL with install prompt
- Click the install icon (β) and confirm
- Done! PingPong opens as a standalone app
Benefits:
- Discover via extension stores (better SEO)
- Try extension first, upgrade to PWA later
- Both versions can coexist
See detailed guide: PWA_FROM_EXTENSION.md
- Visit the hosted PWA URL (e.g.,
https://app.pingpong.codes) - Click the install icon (β) in the browser address bar
- Click "Install" in the popup
- PingPong opens as a standalone app!
- β No Extension Store - Install directly from any URL
- β Cross-Browser - Works on Chrome, Edge, Firefox, Safari
- β Offline Support - Service worker caching for offline use
- β Standalone App - Runs in its own window like a native app
- β Easy Sharing - Just share a URL
- β Auto Updates - Updates automatically when you refresh
The PWA can be deployed to:
- GitHub Pages (free)
- Netlify (free)
- Vercel (free)
- Self-hosted (requires HTTPS)
Documentation:
- PWA_FROM_EXTENSION.md - Install from extension (user flow)
- PWA_DEPLOYMENT.md - Complete deployment guide
- PWA_SUMMARY.md - Technical details
The PWA uses the same codebase but with a few platform-specific adaptations:
- Storage: Uses
localStorageinstead ofchrome.storage(seamless to users) - Tabs: Opens links in browser tabs/windows
- Offline: Full offline support with service worker
- Updates: Automatic via service worker (no manual updates needed)
Request Building:
- HTTP Methods: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS
- URL editing with automatic query parameter parsing
- Headers management with enable/disable toggles
- Multiple content types: form-data, x-www-form-urlencoded, binary, raw
- Full-featured code editor with syntax highlighting (JSON, XML, HTML)
- File upload for binary content
- Authentication: Basic Auth and Bearer Token support
Request Management:
- cURL Import - Paste cURL commands to auto-fill requests
- Request history with automatic sync across tabs
- Collections - Organize requests into collections with folders
- Collection Runner - Run collections sequentially with variable chaining
- Field checkboxes to enable/disable without deletion
- Collapsible sections for better organization
- Multi-tab support for working on multiple requests simultaneously
Environments & Variables:
- Multiple environments (dev, staging, prod, etc.)
- Environment variable substitution with
{{VAR}}syntax - Variable chaining across requests in collections
- Environment switching with keyboard shortcuts
Response Viewing:
- Formatted responses with status indicators
- Response headers inspection
- Syntax highlighting for JSON/XML/HTML
- JSONPath filtering - Extract specific data from responses
- Response size and timing information
Assertions:
- Response validation with assertion engine
- Status code, header, body, and timing assertions
- Visual assertion results panel
UI/UX:
- Dark theme optimized for developers
- Responsive design for different window sizes
- Modern, clean interface with Tailwind CSS
- Settings panel for customization
- Help panel with built-in documentation
- Chrome: Manifest V3 (Chrome 88+)
- Firefox: Manifest V2 (Firefox 91+)
- Cross-browser compatibility via webextension-polyfill
# Development with file watching
npm run dev:chrome
npm run dev:firefox
# Production builds
npm run build:chrome
npm run build:firefox
npm run build:all
# Type checking
npm run type-check- React 18, TypeScript, Tailwind CSS
- CodeMirror 6 (code editor)
- Lucide React (icons)
- Webextension Polyfill (cross-browser)
- Vite 5 (bundling)
- π Blazing fast - Built with Undici (2-3x faster than native fetch)
- π¨ Beautiful output - Colorful responses with syntax highlighting
- π Interactive mode - Build requests with guided prompts
- π Collections - Organize and reuse requests
- π Environments - Switch between dev/staging/prod with variables
- π Request chaining - Extract values from responses, use in next requests
- πͺ Cookie management - Automatic cookie handling with persistent storage
- β Assertions - Validate responses for CI/CD pipelines
- β‘ Load testing - Performance testing with concurrent requests and detailed metrics
- π€ File uploads - Multipart form data support
- π Proxy support - Route requests through HTTP proxies
- π Request history - Auto-saves with full management
- πΎ Export/Import - Backup and share collections & history
# Global installation
npm install -g @pingpong-js/cli
# Or use with npx (no install needed)
npx pingpong-cli send GET https://api.mockly.codes/userspingpong send <METHOD> <URL> [options]
Options:
-H, --header <key:value> Headers (repeatable)
-d, --data <body> Request body (JSON or @file)
-f, --file <name=@path> Upload files
-t, --timeout <ms> Request timeout
-x, --proxy <url> HTTP proxy URL
-a, --assert <assertion> Response assertions
-e, --extract <var=path> Extract variables from response
--no-redirect Don't follow redirects
--no-cookies Disable cookie handling
--no-save Don't save to history
Examples:
pingpong send GET https://httpbin.org/get
pingpong send POST https://api.mockly.codes/users -d @body.json
pingpong send POST https://api.mockly.codes/upload -f "avatar=@photo.jpg"
# With assertions for CI/CD
pingpong send GET https://api.mockly.codes/health \
--assert "status == 200" \
--assert "time < 1000" \
--assert "body.status == 'ok'"Build requests with guided prompts:
pingpong request
# or shorthand
pingpong iOrganize and reuse requests:
# List collections
pingpong collection
# Create collection
pingpong collection:create <name> [--base-url <url>]
# Add request to collection
pingpong collection:add <collection> <request-name> \
--method <METHOD> --url <url> \
[-H <headers...>] [-d <body>] \
[-e <extracts...>] [-a <assertions...>]
# Run collection
pingpong collection:run <collection> [request-name] [-e <environment>]
# Run from JSON file
pingpong collection:run <file.json> --file [-e <environment>]
# Export/Import
pingpong collection:export <name> <file>
pingpong collection:import <file>
Examples:
# Create API collection with chaining
pingpong collection:create my-api --base-url https://api.mockly.codes
# Add login request that extracts token
pingpong collection:add my-api login --method POST --url /auth/login \
-d '{"email":"user@example.com","password":"pass"}' \
-e "token=$.token" \
-a "status == 200"
# Add profile request using token
pingpong collection:add my-api get-profile --method GET --url /users/me \
-H "Authorization: Bearer {{token}}" \
-e "userId=$.id"
# Run entire flow (variables chain automatically)
pingpong collection:run my-api -e dev
# Run from exported file
pingpong collection:run collection.json --fileCreate environments with variables:
# List environments
pingpong env
# Create and set variables
pingpong env:create dev
pingpong env:set dev BASE_URL https://pingpong.codes/
pingpong env:set dev API_KEY dev_key_123
pingpong env:create prod
pingpong env:set prod BASE_URL https://api.mockly.codes
pingpong env:set prod API_KEY prod_key_456
# Activate environment
pingpong env:use dev
# Use variables in requests
pingpong send GET "{{BASE_URL}}/users" -H "X-API-Key: {{API_KEY}}"Performance testing with detailed metrics:
# Simple load test
pingpong load https://api.mockly.codes/users -n 100 -c 10
# Duration-based test
pingpong load https://api.mockly.codes/health \
--duration 60 \
--rate 20 \
-c 20
# Collection load test
pingpong collection:run my-api --load -n 50 -c 5 -e prod
# Load test from JSON file
pingpong collection:run collection.json --file --load -n 100 -c 20
Options:
-n, --requests <number> Total requests (default: 100)
-c, --concurrency <number> Concurrent requests (default: 10)
-t, --duration <seconds> Test duration in seconds
-r, --ramp-up <seconds> Ramp-up time
--rate <rps> Requests per second
--timeout <ms> Request timeout
-o, --output <file> Export results to JSON
-q, --quiet Minimal outputMetrics Provided:
- Requests: total, completed, failed, errors
- Latency: min, mean, median, p95, p99, max
- Throughput: requests/sec, bytes/sec
- Status code distribution
- Virtual user statistics
Example Output:
π Starting Load Test
[10.2s] 100/100 reqs β’ 9.8 req/s β’ 245ms avg β’ 100.0% success
ββββββββββββββββββ¬ββββββββββββββββββ
β Metric β Value β
ββββββββββββββββββΌββββββββββββββββββ€
β Total Requests β 100 β
β Completed β 100 (100.00%) β
β Failed β 0 β
β Requests/sec β 9.80 β
β Throughput β 98.5 KB β
ββββββββββββββββββ΄ββββββββββββββββββ
βββββββββββ¬ββββββββ
β Latency β Time β
βββββββββββΌββββββββ€
β Min β 89ms β
β Mean β 245ms β
β Median β 234ms β
β P95 β 389ms β
β P99 β 456ms β
β Max β 567ms β
βββββββββββ΄ββββββββ
β Excellent success rate β Fast response times
# View recent requests
pingpong history
# Export/Import
pingpong history --export backup.json
pingpong history --import backup.json
# Clear history
pingpong history --clear# List cookies
pingpong cookies
# Clear cookies
pingpong cookies:clear [domain]
# Export/Import
pingpong cookies:export cookies.json
pingpong cookies:import cookies.jsonExtract values from responses and use them in subsequent requests:
# Extract token from login
pingpong send POST https://api.mockly.codes/auth/login \
-d '{"email":"user@example.com","password":"pass"}' \
--extract "token=$.token"
# Use token in next request
pingpong send GET https://api.mockly.codes/users/me \
-H "Authorization: Bearer {{token}}" \
--extract "userId=$.id"JSONPath Syntax:
$.property- Root property$.nested.value- Nested property$.array[0]- Array element$.items[*]- All array items
Validate responses for CI/CD:
# Status and timing
pingpong send GET https://api.mockly.codes/health \
-a "status == 200" \
-a "time < 1000"
# Headers
pingpong send GET https://api.mockly.codes \
-a "header.content-type == 'application/json'" \
-a "header.server contains 'nginx'"
# JSON body
pingpong send GET https://api.mockly.codes/users/1 \
-a "body.id == 1" \
-a "body.email exists" \
-a "body.name startsWith 'John'"# .github/workflows/api-tests.yml
name: API Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install PingPong CLI
run: npm install -g @pingpong-js/cli
- name: Run API tests
run: |
pingpong send GET ${{ secrets.API_URL }}/health \
--assert "status == 200" \
--assert "time < 2000" \
--no-save| Feature | PingPong | curl | httpie | Postman CLI |
|---|---|---|---|---|
| Speed | β‘β‘β‘ | β‘β‘ | β‘β‘ | β‘β‘ |
| Beautiful output | β | β | β | β |
| Interactive mode | β | β | β | β |
| Collections | β | β | β | β |
| Load testing | β | β | β | |
| Request chaining | β | β | β | β |
| Assertions | β | β | β | β |
| Lightweight | β | β | β | β |
| Free & Open Source | β | β | β |
Universal HTTP client that works in both Node.js and browsers with automatic environment detection.
npm install @pingpong-js/fetch- π Universal: Works in both Node.js and browser environments
- β‘ Fast: Uses
undiciin Node.js, nativefetchin browsers - π Automatic: Environment detection with zero configuration
- π¦ Small: Minimal dependencies, tree-shakeable
- π― Type-safe: Full TypeScript support
import { HttpClient } from '@pingpong-js/fetch';
const client = new HttpClient({
timeout: 5000,
followRedirects: true
});
// Simple GET
const response = await client.get('https://api.mockly.codes/users');
console.log(response.status, response.body);
// POST with JSON
const createResponse = await client.post('https://api.mockly.codes/users', {
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'John Doe', email: 'john@example.com' })
});For browser applications, the library automatically uses the browser entry point:
// Works in React, Vue, Angular, browser extensions, etc.
import { HttpClient } from '@pingpong-js/fetch';
const client = new HttpClient();
const response = await client.get('https://api.mockly.codes/data');// Vite/webpack.config.js - automatic via browser field
resolve: {
alias: {
'@pingpong-js/fetch': 'pingpong-fetch/browser' // Optional: explicit browser entry
}
}Testing utilities for API testing: variables, assertions, cookies, JSONPath, and load testing.
npm install @pingpong-js/coreVariableResolver - Environment variable substitution
import { VariableResolver } from '@pingpong-js/core';
const resolver = new VariableResolver({ API_KEY: 'secret123' });
const url = resolver.resolve('https://api.mockly.codes?key={{API_KEY}}');CookieJar - Cookie management
import { CookieJar } from '@pingpong-js/core';
const jar = new CookieJar();
jar.setCookie('session=abc123; Domain=example.com; Path=/');
const cookies = jar.getCookiesForRequest('https://example.com/api');JSONPath - Extract values from JSON
import { JSONPath } from '@pingpong-js/core';
const data = { auth: { token: 'abc123' } };
const token = JSONPath.extract(data, '$.auth.token');AssertionEngine - Response validation
import { AssertionEngine } from '@pingpong-js/core';
const assertions = AssertionEngine.runAssertions(response, [
'status == 200',
'body.user.email exists',
'time < 1000'
]);LoadTester - Performance testing
import { LoadTester } from '@pingpong-js/core';
const tester = new LoadTester({
target: 'https://api.mockly.codes/users',
phases: [{ duration: 60, arrivalRate: 10 }]
});
const results = await tester.run(async () => {
// Your request logic here
});pingpong-extension/
βββ extension/ # Browser extension source
β βββ background/ # Background scripts
β βββ components/ # React components
β βββ pages/ # Main pages
β βββ utils/ # Utilities
βββ packages/
β βββ fetch/ # Fetch library (pingpong-fetch - universal HTTP client)
β β βββ src/
β β β βββ httpClient/ # Node.js & Browser implementations
β β β βββ types.ts # HTTP types
β β β βββ index.ts # Auto-detection entry
β β β βββ browser.ts # Browser-only entry
β β β βββ node.ts # Node.js-only entry
β β βββ package.json
β βββ cli/ # CLI tool (pingpong-cli)
β β βββ src/
β β β βββ index.ts # Main CLI entry
β β β βββ storage.ts
β β β βββ formatter.ts
β β β βββ collectionStorage.ts
β β β βββ cookieStorage.ts
β β β βββ multipart.ts
β β β βββ loadTestReporter.ts
β β βββ package.json
β βββ core/ # Core library (pingpong-core - testing utilities)
β βββ src/
β β βββ types.ts # TypeScript types
β β βββ utils/ # VariableResolver, JSONPath, AssertionEngine, LoadTester, CookieJar
β βββ package.json
βββ builds/ # Built extensions
βββ assets/ # Static assets
βββ manifests/ # Browser manifests
βββ website/ # Documentation website
# Install dependencies
npm install
# Build all packages
npm run build:all
# Build individual packages
npm run build:fetch
npm run build:core
npm run build:cli
# Build browser extension
npm run build:chrome
npm run build:firefox
npm run build:extension
# Type checking
npm run type-checkBrowser Extension:
- React 18, TypeScript, Tailwind CSS
- CodeMirror 6, Lucide React
- Webextension Polyfill, Vite 5
CLI (pingpong-cli):
- TypeScript, Commander
- Uses
pingpong-fetchfor HTTP requests - Uses
pingpong-corefor utilities (variables, assertions, cookies, load testing) - Chalk, Ora, Inquirer (UI)
- Conf (storage), CLI Table3
Fetch (pingpong-fetch):
- TypeScript (strict mode)
- Undici (Node.js), Fetch API (browser)
- Conditional exports for universal support
- Minimal dependencies
- Automatic environment detection
Core (pingpong-core):
- TypeScript (strict mode)
- Testing utilities: variables, assertions, cookies, JSONPath, load testing
- Zero external dependencies
- Works in both Node.js and browser environments
# 1. Create collection
pingpong collection:create my-api --base-url https://api.mockly.codes
# 2. Add login (extracts token)
pingpong collection:add my-api login \
-m POST -u /auth/login \
-d '{"email":"user@example.com","password":"pass"}' \
-e "token=$.token" \
-a "status == 200"
# 3. Add profile request (uses token, extracts userId)
pingpong collection:add my-api get-profile \
-m GET -u /users/me \
-H "Authorization: Bearer {{token}}" \
-e "userId=$.id" \
-a "status == 200"
# 4. Add update (uses token and userId)
pingpong collection:add my-api update-profile \
-m PATCH -u "/users/{{userId}}" \
-H "Authorization: Bearer {{token}}" \
-d '{"bio":"Updated"}' \
-a "status == 200"
# 5. Run entire flow
pingpong collection:run my-api -e dev
# 6. Load test the flow
pingpong collection:run my-api --load -n 50 -c 5 -e prod
# 7. Export and share
pingpong collection:export my-api my-api.json
# 8. Run from JSON
pingpong collection:run my-api.json --file# View config
pingpong config
# Set values
pingpong config --set defaultTimeout=5000
pingpong config --set maxHistoryItems=200Config Keys:
defaultTimeout- Request timeout (default: 30000ms)maxHistoryItems- Max history entries (default: 100)autoSaveHistory- Auto-save (default: true)theme- Color theme (default: 'dark')
CLI data stored in ~/.config/pingpong/:
collections.json- Request collectionsenvironments.json- Environment variableshistory.json- Request historycookies.json- Cookie storageconfig.json- CLI configuration
- Fork the repository
- Create a feature branch from
trunk - Make your changes
- Test thoroughly (browser + CLI + core)
- Run
npm run type-check - Submit a pull request
MIT License - see LICENSE file for details.
Browser Extension:
- β Local-first (no data sent to servers)
- β Dark theme for developers
- β Full-featured request builder
- β cURL import for easy migration
- β Cross-browser (Chrome & Firefox)
CLI Tool:
- β Faster than Postman CLI (Undici-powered)
- β Beautiful output (better than curl)
- β Advanced features (collections, chaining, load testing)
- β CI/CD ready (assertions, exit codes)
- β Local storage (no cloud dependencies)
Fetch Library:
- β Universal (Node.js + Browser)
- β Fast (undici + fetch)
- β Automatic environment detection
- β Type-safe with full TypeScript support
- β Tree-shakeable and minimal
Core Library:
- β Reusable testing utilities
- β Variable resolution and JSONPath
- β Assertions and load testing
- β Type-safe
- β Easy to integrate
Made with β€οΈ by 0xdps
π PingPong - The complete API testing toolkit π