# @git.zone/tstest/tapbundle > ๐Ÿงช Core TAP testing framework with enhanced assertions and lifecycle hooks ## Installation ```bash # tapbundle is typically included as part of @git.zone/tstest pnpm install --save-dev @git.zone/tstest ``` ## Overview `@git.zone/tstest/tapbundle` is the core testing framework module that provides the TAP (Test Anything Protocol) implementation for tstest. It offers a comprehensive API for writing and organizing tests with support for lifecycle hooks, test suites, enhanced assertions with diff generation, and flexible test configuration. ## Key Features - ๐ŸŽฏ **TAP Protocol Compliant** - Full TAP version 13 support - ๐Ÿ” **Enhanced Assertions** - Built on smartexpect with automatic diff generation - ๐Ÿ—๏ธ **Test Suites** - Organize tests with `describe()` blocks - ๐Ÿ”„ **Lifecycle Hooks** - beforeEach/afterEach at suite and global levels - ๐Ÿท๏ธ **Test Tagging** - Filter tests by tags for selective execution - โšก **Parallel Testing** - Run tests concurrently with `testParallel()` - ๐Ÿ” **Automatic Retries** - Configure retry logic for flaky tests - โฑ๏ธ **Timeout Control** - Set timeouts at global, file, or test level - ๐ŸŽจ **Fluent API** - Chain test configurations with builder pattern - ๐Ÿ“Š **Protocol Events** - Real-time test execution events ## Basic Usage ### Simple Test File ```typescript import { tap, expect } from '@git.zone/tstest/tapbundle'; tap.test('should add numbers correctly', async () => { const result = 2 + 2; expect(result).toEqual(4); }); export default tap.start(); ``` ### Using Test Suites ```typescript import { tap, expect } from '@git.zone/tstest/tapbundle'; tap.describe('Calculator', () => { tap.beforeEach(async (tapTools) => { // Setup before each test in this suite }); tap.test('should add', async () => { expect(2 + 2).toEqual(4); }); tap.test('should subtract', async () => { expect(5 - 3).toEqual(2); }); tap.afterEach(async (tapTools) => { // Cleanup after each test in this suite }); }); export default tap.start(); ``` ## API Reference ### Main Test Methods #### `tap.test(description, testFunction)` Define a standard test that runs sequentially. ```typescript tap.test('should validate user input', async () => { // test code }); ``` #### `tap.testParallel(description, testFunction)` Define a test that runs in parallel with other parallel tests. ```typescript tap.testParallel('should fetch user data', async () => { // test code }); ``` #### `tap.describe(description, suiteFunction)` Create a test suite to group related tests. ```typescript tap.describe('User Authentication', () => { tap.test('should login', async () => { }); tap.test('should logout', async () => { }); }); ``` ### Test Modes #### Skip Tests ```typescript tap.skip.test('not ready yet', async () => { // This test will be skipped }); ``` #### Only Mode ```typescript tap.only.test('focus on this test', async () => { // Only tests marked with 'only' will run }); ``` #### Todo Tests ```typescript tap.todo.test('implement feature X'); ``` ### Fluent Test Builder Chain test configurations for expressive test definitions: ```typescript tap .tags('integration', 'database') .priority('high') .retry(3) .timeout(5000) .test('should handle database connection', async () => { // test with configured settings }); ``` ### Lifecycle Hooks #### Suite-Level Hooks ```typescript tap.describe('Database Tests', () => { tap.beforeEach(async (tapTools) => { // Runs before each test in this suite }); tap.afterEach(async (tapTools) => { // Runs after each test in this suite }); tap.test('test 1', async () => { }); tap.test('test 2', async () => { }); }); ``` #### Global Hooks ```typescript tap.settings({ beforeAll: async () => { // Runs once before all tests }, afterAll: async () => { // Runs once after all tests }, beforeEach: async (testName) => { // Runs before every test }, afterEach: async (testName, passed) => { // Runs after every test } }); ``` ### Global Settings Configure test behavior at the file level: ```typescript tap.settings({ timeout: 10000, // Default timeout for all tests retries: 2, // Retry failed tests retryDelay: 1000, // Delay between retries bail: false, // Stop on first failure suppressConsole: false, // Hide console output verboseErrors: true, // Show full stack traces showTestDuration: true, // Display test durations maxConcurrency: 4, // Max parallel tests }); ``` ### Enhanced Assertions The `expect` function is an enhanced wrapper around [@push.rocks/smartexpect](https://code.foss.global/push.rocks/smartexpect) that automatically generates diffs for failed assertions. ```typescript import { expect } from '@git.zone/tstest/tapbundle'; tap.test('should compare objects', async () => { const actual = { name: 'John', age: 30 }; const expected = { name: 'John', age: 31 }; // Will show a detailed diff of the differences expect(actual).toEqual(expected); }); ``` #### Available Assertions ```typescript // Equality expect(value).toEqual(expected); expect(value).toBe(expected); // Truthiness expect(value).toBeTruthy(); expect(value).toBeFalsy(); // Type checks expect(value).toBeType('string'); // Strings expect(string).toMatch(/pattern/); expect(string).toContain('substring'); // Arrays expect(array).toContain(item); // Exceptions expect(fn).toThrow(); expect(fn).toThrow('error message'); // Async await expect(promise).toResolve(); await expect(promise).toReject(); ``` ### Test Tagging and Filtering Tag tests for selective execution: ```typescript // Define tests with tags tap.tags('integration', 'slow').test('complex test', async () => { // test code }); tap.tags('unit').test('fast test', async () => { // test code }); ``` Filter tests by setting the environment variable: ```bash TSTEST_FILTER_TAGS=unit tstest test/mytest.node.ts ``` ### TapTools Each test receives a `tapTools` instance with utilities: ```typescript tap.test('should have utilities', async (tapTools) => { // Mark test as skipped tapTools.markAsSkipped('reason'); // Mark as todo tapTools.todo('not implemented'); // Configure retries tapTools.retry(3); // Log test output tapTools.log('debug message'); }); ``` ## Advanced Features ### Pre-Tasks Run setup tasks before any tests execute: ```typescript tap.preTask('setup database', async () => { // Runs before any tests }); tap.test('first test', async () => { // Database is ready }); ``` ### Test Priority Organize tests by priority level: ```typescript tap.priority('high').test('critical test', async () => { }); tap.priority('medium').test('normal test', async () => { }); tap.priority('low').test('optional test', async () => { }); ``` ### Nested Suites Create deeply nested test organization: ```typescript tap.describe('API', () => { tap.describe('Users', () => { tap.describe('GET /users', () => { tap.test('should return all users', async () => { }); }); }); }); ``` ### Protocol Events Access real-time test events for custom tooling: ```typescript import { setProtocolEmitter } from '@git.zone/tstest/tapbundle'; // Get access to protocol emitter for custom event handling // Events: test:started, test:completed, assertion:failed, suite:started, suite:completed ``` ## Best Practices 1. **Always export `tap.start()`** at the end of test files: ```typescript export default tap.start(); ``` 2. **Use descriptive test names** that explain what is being tested: ```typescript tap.test('should return 404 when user does not exist', async () => { }); ``` 3. **Group related tests** with `describe()` blocks: ```typescript tap.describe('User validation', () => { // All user validation tests }); ``` 4. **Leverage lifecycle hooks** to reduce duplication: ```typescript tap.beforeEach(async () => { // Common setup }); ``` 5. **Tag tests appropriately** for flexible test execution: ```typescript tap.tags('integration', 'database').test('...', async () => { }); ``` ## TypeScript Support tapbundle is written in TypeScript and provides full type definitions. The `Tap` class accepts a generic type for shared context: ```typescript interface MyTestContext { db: DatabaseConnection; user: User; } const tap = new Tap(); tap.test('should use context', async (tapTools) => { // tapTools is typed with MyTestContext }); ``` ## Legal This project is licensed under MIT. ยฉ 2025 Task Venture Capital GmbH. All rights reserved.