JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 24
  • Score
    100M100P100Q48025F
  • License MIT

A robust testing toolkit for JavaScript and TypeScript projects, offering custom assertions, advanced mocking utilities, performance profiling, benchmarking tools, flexible logging options, and seamless integration with Jest and Husky for enhanced test-driven development workflows.

Package Exports

  • goobs-testing
  • goobs-testing/src/index.ts

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (goobs-testing) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

goobs-testing

A comprehensive collection of testing utilities for JavaScript and TypeScript projects.

Description

goobs-testing is a package that provides a set of utilities to enhance your testing workflow. It includes custom assertions, mocking utilities, performance measurement tools, benchmarking, and logging helpers. This package is designed to work seamlessly with Jest and TypeScript projects, and includes integration with Husky for pre-commit hooks.

Installation

To install the package, run:

npm install goobs-testing

or if you're using Yarn:

yarn add goobs-testing

To set up Husky for pre-commit hooks, run:

npx goobs-testing setup-husky

This will install Husky and set up a pre-commit hook to run your tests.

Modules and Usage

Assertions (assertions/index.ts)

Custom assertion functions to make your tests more readable and maintainable.

import {
  expectToBeWithinRange,
  expectToBeCloseToNow,
  expectToHaveBeenCalledOnceWith,
  expectToBeValidEmail,
  expectToBeNonEmptyString,
  expectToBePositiveNumber,
  expectToBeValidUUID,
  expectToHaveProperty,
  expectToBeEmptyArray,
  expectToBeNonEmptyArray,
  expectToBeTrue,
  expectToBeFalse,
  expectToBeNull,
  expectToBeUndefined,
  expectToBeNullOrUndefined,
  expectToThrowError,
  expectToBePromise,
  expectToBeDate,
  expectToBeSorted,
} from 'goobs-testing';

describe('Assertion Tests', () => {
  it('should be within range', () => {
    expectToBeWithinRange(5, 1, 10);
  });

  it('should be close to now', () => {
    expectToBeCloseToNow(new Date());
  });

  it('should have been called once with specific arguments', () => {
    const mock = jest.fn();
    mock('test');
    expectToHaveBeenCalledOnceWith(mock, 'test');
  });

  it('should be a valid email', () => {
    expectToBeValidEmail('test@example.com');
  });

  it('should be a non-empty string', () => {
    expectToBeNonEmptyString('test');
  });

  it('should be a positive number', () => {
    expectToBePositiveNumber(5);
  });

  it('should be a valid UUID', () => {
    expectToBeValidUUID('123e4567-e89b-12d3-a456-426614174000');
  });

  it('should have property', () => {
    expectToHaveProperty({ test: 'value' }, 'test');
  });

  it('should be an empty array', () => {
    expectToBeEmptyArray([]);
  });

  it('should be a non-empty array', () => {
    expectToBeNonEmptyArray([1, 2, 3]);
  });

  it('should be true', () => {
    expectToBeTrue(true);
  });

  it('should be false', () => {
    expectToBeFalse(false);
  });

  it('should be null', () => {
    expectToBeNull(null);
  });

  it('should be undefined', () => {
    expectToBeUndefined(undefined);
  });

  it('should be null or undefined', () => {
    expectToBeNullOrUndefined(null);
    expectToBeNullOrUndefined(undefined);
  });

  it('should throw error', () => {
    expectToThrowError(() => {
      throw new Error('Test error');
    });
  });

  it('should be a promise', () => {
    expectToBePromise(Promise.resolve());
  });

  it('should be a date', () => {
    expectToBeDate(new Date());
  });

  it('should be sorted', () => {
    expectToBeSorted([1, 2, 3, 4, 5]);
  });
});

Error Handling (error/index.ts)

Utilities for setting up global error handling in your tests.

import { setupErrorHandling, restoreConsoleError } from 'goobs-testing';

describe('Error Handling', () => {
  let teardown: () => void;

  beforeAll(() => {
    teardown = setupErrorHandling((message) => console.log(message));
  });

  afterAll(() => {
    teardown();
    restoreConsoleError();
  });

  it('should handle uncaught exception', () => {
    // This will be caught by the global error handler
    throw new Error('Uncaught exception');
  });

  it('should handle unhandled rejection', async () => {
    // This will be caught by the global error handler
    await Promise.reject(new Error('Unhandled rejection'));
  });
});

Logging (logging/index.ts)

Functions to assist with logging during test execution, including support for local logging and GitHub pre-commit logging.

import { setupLogging, logTestResults, closeLogStreams } from 'goobs-testing';

describe('Logging Tests', () => {
  let log: (message: string) => void;

  beforeAll(() => {
    log = setupLogging('test-log.txt', 'TestSuite');
  });

  afterAll(() => {
    closeLogStreams();
  });

  it('should log test results', () => {
    log('Test passed');
    // Assertions would go here
  });

  it('should log failed tests', () => {
    log('Test failed');
    // Assertions would go here
  });

  afterAll(() => {
    logTestResults(log, 1, 1, 2, 'TestSuite');
  });
});

Mocking (mock/index.ts)

Helper functions for mocking various JavaScript/TypeScript features.

import {
  mockPerformanceNow,
  realPerformanceNow,
  mockConsole,
  mockFetch,
  mockAsyncFunction,
  createMockEvent,
  mockLocalStorage,
  mockTimer,
  mockModule,
  mockEnvironment,
} from 'goobs-testing';

describe('Mocking Tests', () => {
  it('should mock performance.now', () => {
    const mockNow = mockPerformanceNow();
    expect(mockNow()).toBe(0);
    mockNow.advanceTime(100);
    expect(mockNow()).toBe(100);
  });

  it('should use real performance.now', () => {
    const now = realPerformanceNow();
    expect(typeof now).toBe('number');
  });

  it('should mock console', () => {
    const { mockLog, mockError, mockWarn, mockInfo } = mockConsole();
    console.log('test');
    expect(mockLog).toHaveBeenCalledWith('test');
  });

  it('should mock fetch', async () => {
    const mockFetchFn = mockFetch({ data: 'mocked data' });
    const response = await mockFetchFn('https://api.example.com');
    const data = await response.json();
    expect(data).toEqual({ data: 'mocked data' });
  });

  it('should mock async function', async () => {
    const mockAsync = mockAsyncFunction('result', 100);
    const result = await mockAsync();
    expect(result).toBe('result');
  });

  it('should create mock event', () => {
    const mockEvent = createMockEvent({ target: { value: 'test' } });
    expect(mockEvent.preventDefault).toBeDefined();
    expect(mockEvent.target.value).toBe('test');
  });

  it('should mock localStorage', () => {
    const mockStorage = mockLocalStorage();
    mockStorage.setItem('key', 'value');
    expect(mockStorage.getItem('key')).toBe('value');
  });

  it('should mock timer', () => {
    const { advanceTimersByTime, runAllTimers, clearAllTimers } = mockTimer();
    const callback = jest.fn();
    setTimeout(callback, 1000);
    advanceTimersByTime(1000);
    expect(callback).toHaveBeenCalled();
  });

  it('should mock module', () => {
    mockModule('fake-module', { fakeFunction: jest.fn() });
    const fakeModule = require('fake-module');
    fakeModule.fakeFunction();
    expect(fakeModule.fakeFunction).toHaveBeenCalled();
  });

  it('should mock environment', () => {
    mockEnvironment({ NODE_ENV: 'test' });
    expect(process.env.NODE_ENV).toBe('test');
  });
});

Performance Measurement (performance/index.ts)

Tools for measuring the performance of asynchronous functions.

import { measureAsyncExecutionTime, measureMultipleAsyncExecutionTimes } from 'goobs-testing';

describe('Performance Tests', () => {
  it('should measure async execution time', async () => {
    const time = await measureAsyncExecutionTime(async () => {
      await new Promise((resolve) => setTimeout(resolve, 100));
    });
    expect(time).toBeGreaterThanOrEqual(100);
  });

  it('should measure multiple async execution times', async () => {
    const times = await measureMultipleAsyncExecutionTimes(async () => {
      await new Promise((resolve) => setTimeout(resolve, 100));
    }, 3);
    expect(times.length).toBe(3);
    times.forEach((time) => {
      expect(time).toBeGreaterThanOrEqual(100);
    });
  });
});

Benchmarking (benchmark/index.ts)

Utilities for benchmarking functions and comparing their performance.

import { benchmark, compareBenchmarks, formatBenchmarkResults, runBenchmarks } from 'goobs-testing';

describe('Benchmark Tests', () => {
  it('should benchmark a function', async () => {
    const result = await benchmark(() => {
      for (let i = 0; i < 1000000; i++) {}
    });
    expect(typeof result).toBe('number');
  });

  it('should compare benchmarks', async () => {
    const results = await compareBenchmarks({
      slowFunction: () => {
        for (let i = 0; i < 1000000; i++) {}
      },
      fastFunction: () => {
        for (let i = 0; i < 100000; i++) {}
      },
    });
    expect(results.slowFunction).toBeGreaterThan(results.fastFunction);
  });

  it('should format benchmark results', () => {
    const results = {
      slowFunction: 10.5,
      fastFunction: 1.2,
    };
    const formatted = formatBenchmarkResults(results);
    expect(formatted).toContain('slowFunction: 10.5000 ms');
    expect(formatted).toContain('fastFunction: 1.2000 ms');
  });

  it('should run benchmarks and return formatted results', async () => {
    const results = await runBenchmarks({
      slowFunction: () => {
        for (let i = 0; i < 1000000; i++) {}
      },
      fastFunction: () => {
        for (let i = 0; i < 100000; i++) {}
      },
    });
    expect(results).toContain('Benchmark Results:');
    expect(results).toContain('slowFunction:');
    expect(results).toContain('fastFunction:');
  });
});

Full Example

Here's an example of how you might use multiple utilities from goobs-testing in a single test suite:

import {
  expectToBeWithinRange,
  mockFetch,
  measureAsyncExecutionTime,
  setupErrorHandling,
  setupLogging,
  logTestResults,
  closeLogStreams,
  benchmark,
} from 'goobs-testing';

describe('Comprehensive Test Suite', () => {
  let log: (message: string) => void;
  let teardown: () => void;

  beforeAll(() => {
    // Set up error handling
    teardown = setupErrorHandling((message) => console.error(message));

    // Set up logging
    log = setupLogging('comprehensive-test.log', 'ComprehensiveTestSuite');
  });

  afterAll(() => {
    teardown();
    closeLogStreams();
  });

  it('should perform a complex test scenario', async () => {
    // Use custom assertion
    expectToBeWithinRange(5, 1, 10);

    // Use mocking
    const mockFetchFn = mockFetch({ data: 'mocked data' });
    const response = await mockFetchFn('https://api.example.com');
    const data = await response.json();
    expect(data).toEqual({ data: 'mocked data' });

    // Measure performance
    const time = await measureAsyncExecutionTime(async () => {
      await new Promise((resolve) => setTimeout(resolve, 100));
    });
    expect(time).toBeGreaterThanOrEqual(100);

    // Benchmark a function
    const benchmarkResult = await benchmark(() => {
      for (let i = 0; i < 1000000; i++) {}
    });

    // Log results
    log(`Test completed in ${time}ms`);
    log(`Benchmark result: ${benchmarkResult}ms`);
  });

  afterAll(() => {
    logTestResults(log, 0, 1, 1, 'ComprehensiveTestSuite');
  });
});

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License.

Author

Matthew Goluba

Repository

https://github.com/goobz22/goobs-testing