{"id":12119,"library":"tap","title":"Node-TAP Test Framework","description":"TAP (Test-Anything-Protocol) is a robust and opinionated test framework for Node.js, currently in version 21.7.1. It provides a comprehensive command-line test runner and a JavaScript/TypeScript framework for writing tests that output in the TAP format. A key differentiator is its philosophy of treating test files as \"normal\" programs, running each test in its own process to prevent state leakage and inter-test dependencies. Since version 18, `tap` has been entirely rewritten in TypeScript, offering first-class support for ESM, CommonJS, and TypeScript out-of-the-box, including rich, machine-generated type definitions for an enhanced developer experience with editor auto-completion. It features built-in test coverage (powered by `c8`), various reporter formats, and an extensive API leveraging a plugin-based architecture for core functionalities like assertions and mocking. The project maintains an active release cadence with frequent updates.","status":"active","version":"21.7.1","language":"javascript","source_language":"en","source_url":"ssh://git@github.com/tapjs/tapjs","tags":["javascript","assert","tap","test","testing","framework","cli","tapjs","tapjs plugin","typescript"],"install":[{"cmd":"npm install tap","lang":"bash","label":"npm"},{"cmd":"yarn add tap","lang":"bash","label":"yarn"},{"cmd":"pnpm add tap","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"While CommonJS `require('tap')` still works for basic usage, ESM `import tap from 'tap'` is the idiomatic way since v18. Older Node versions or incorrect `package.json` configuration might lead to module resolution errors.","wrong":"const tap = require('tap')","symbol":"tap","correct":"import tap from 'tap'"},{"note":"The `test` function is a named export for convenience, allowing direct access to the primary test definition function without needing the default `tap` object. The main `tap` object itself is the default export.","wrong":"import { tap } from 'tap'","symbol":"test","correct":"import { test } from 'tap'"},{"note":"This imports the TypeScript type for the `t` object passed to test callbacks. It should be imported as a type, not a runtime value. The `Test` class is what your test programs interact with and is the base for the default `tap` export.","wrong":"import { Test } from 'tap'","symbol":"Test","correct":"import type { Test } from 'tap'"}],"quickstart":{"code":"import tap from 'tap';\nimport type { Test } from 'tap';\n\ninterface MyApiResult {\n  data: string;\n  status: number;\n}\n\nasync function fetchData(): Promise<MyApiResult> {\n  // Simulate an API call\n  return new Promise(resolve => {\n    setTimeout(() => {\n      resolve({ data: 'Hello TAP!', status: 200 });\n    }, 50);\n  });\n}\n\ntap.test('Basic assertions and async test', async (t: Test) => {\n  t.plan(3); // Declare the number of assertions expected\n\n  t.ok(true, 'should be truthy');\n  t.equal(1 + 1, 2, 'addition works');\n\n  const result = await fetchData();\n  t.deepEqual(result, { data: 'Hello TAP!', status: 200 }, 'async data matches expected structure');\n});\n\ntap.test('Skipping a test', (t: Test) => {\n  t.skip('This test is intentionally skipped for now');\n  t.end(); // Must call t.end() for non-async tests unless t.plan() is used.\n});\n\ntap.test('Synchronous operations', (t: Test) => {\n  const arr = [1, 2, 3];\n  t.notHas(arr, 4, 'array should not contain 4');\n  t.throws(() => {\n    throw new Error('Expected error');\n  }, 'Expected error was thrown');\n  t.end();\n});","lang":"typescript","description":"Demonstrates basic synchronous and asynchronous tests, including assertions, type usage for the 't' object, and how to skip tests."},"warnings":[{"fix":"Upgrade your Node.js runtime to version 20 or 22 (LTS versions are recommended). Use a Node Version Manager (like nvm) to manage multiple Node.js installations.","message":"Node.js version 20 or >=22 is now required. Older Node.js versions (e.g., Node.js 18 or 16) are no longer supported and will cause `tap` to fail at runtime.","severity":"breaking","affected_versions":">=20.0"},{"fix":"Ensure consistent module syntax (ESM `import`/`export` or CommonJS `require`/`module.exports`) across your project, especially for files imported by `tap`. For hybrid projects, verify `package.json`'s `type` field and appropriate file extensions (`.mjs`, `.cjs`).","message":"Starting with `tap` v18, the module system was rewritten to be a hybrid ESM/CommonJS package. Projects upgrading from versions prior to v18 might encounter `ERR_REQUIRE_ESM` or similar module resolution errors if they incorrectly mix `require()` with ESM modules.","severity":"breaking","affected_versions":">=18.0"},{"fix":"Review your test suite to ensure comprehensive code coverage. If 100% coverage is not feasible or desired for specific files, configure `tap` to adjust thresholds or ignore specific paths in your `.taprc` or `package.json` configuration.","message":"As of `tap` v18, code coverage is enabled by default, and a 100% coverage threshold is enforced by default. Tests will fail if code is not fully covered or if coverage reports are missing.","severity":"breaking","affected_versions":">=18.0"},{"fix":"Migrate to the standard assertion methods like `t.notEqual()`, `t.deepEqual()`, etc. Refer to the `tap` API documentation for the current assertion method names.","message":"Assertion synonyms (e.g., `t.is_not_equal()`) were deprecated in v16 and largely removed in v18. Using these older assertion names will result in errors.","severity":"deprecated","affected_versions":">=18.0"},{"fix":"Enable `typecheck: true` cautiously, perhaps primarily in CI environments. Consider using `skipLibCheck: true` in your `tsconfig.json` for development to speed up local runs, or pre-compile TypeScript tests before running `tap`.","message":"While `tap` fully supports TypeScript, enabling strict type checking (`typecheck: true`) can significantly increase test run times, especially in large projects with many test files, potentially adding 500-750ms per file.","severity":"gotcha","affected_versions":">=18.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Update your Node.js environment to version 20 or 22. Use `nvm install 20 && nvm use 20` or similar commands for your Node.js version manager.","cause":"The installed Node.js version is below the minimum required by `tap` (20 or 22).","error":"Error: The current Node.js version (X.Y.Z) is not supported. Please upgrade to Node.js 20 or newer."},{"fix":"Ensure `import` statements are used for ES Modules. If running a CommonJS test file, either rewrite it to ESM or ensure all its dependencies are also CommonJS or correctly hybrid-compatible. For `.js` files that are ESM, add `\"type\": \"module\"` to your `package.json` or use `.mjs` extension.","cause":"Attempting to `require()` an ES Module or running a CommonJS file that imports an ESM-only dependency, particularly in projects that haven't fully migrated to ESM or correctly configured hybrid modules.","error":"Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: ... require() of ES modules is not supported."},{"fix":"Inspect the assertion's `diff` output to understand the discrepancy between the actual and expected values. Adjust either your assertion's expected value or the code under test.","cause":"A `t.deepEqual()` (or similar assertion) failed because the actual value does not strictly match the expected value, often due to differences in object structure or primitive values.","error":"AssertionError: Values are not deeply equal"},{"fix":"For asynchronous tests, ensure the test callback is an `async` function (which implicitly returns a Promise) or explicitly call `t.end()` when all asynchronous operations are complete. If `t.plan(N)` is used, verify that exactly N assertions are run.","cause":"An asynchronous test or subtest did not explicitly signal its completion via `t.end()` or by returning a Promise. Or `t.plan()` was used with an incorrect count.","error":"Test suite hangs, never finishes, or passes without running assertions."}],"ecosystem":"npm"}