Back to Repositories

Testing Disposable Resource Management in Parcel Bundler

This test suite validates the Disposable class implementation in Parcel’s utility package, focusing on resource cleanup and disposal management. The tests ensure proper handling of disposable objects, functions, and multiple disposal scenarios.

Test Coverage Overview

The test suite provides comprehensive coverage of the Disposable class functionality.

Key areas tested include:
  • Wrapping IDisposable objects
  • Function-based disposal
  • Multiple disposable handling
  • Dynamic addition of disposables
  • Prevention of multiple disposals
  • Disposal state tracking

Implementation Analysis

The testing approach employs Jest’s describe/it pattern for organized test cases. Tests validate both synchronous disposal operations and error handling scenarios, using a combination of function-based and object-based disposables.

Technical patterns include:
  • Closure-based state tracking
  • Multiple disposal prevention
  • Error case validation
  • State verification assertions

Technical Details

Testing infrastructure includes:
  • Jest test framework
  • Flow type checking with strict-local mode
  • Native assert module for validations
  • Custom AlreadyDisposedError handling
  • Modular test organization

Best Practices Demonstrated

The test suite exemplifies several testing best practices in JavaScript unit testing.

Notable practices include:
  • Isolated test cases with clear purposes
  • Comprehensive edge case coverage
  • Proper error handling validation
  • State verification before and after operations
  • Clean test organization and readability

parcel-bundler/parcel

packages/utils/events/test/Disposable.test.js

            
// @flow strict-local

import assert from 'assert';
import Disposable from '../src/Disposable';
import {AlreadyDisposedError} from '../src/errors';

describe('Disposable', () => {
  it('can wrap an IDisposable', () => {
    let disposed;

    new Disposable({
      dispose() {
        disposed = true;
      },
    }).dispose();
    assert.equal(disposed, true);
  });

  it('can wrap a function to dispose', () => {
    let disposed;
    new Disposable(() => {
      disposed = true;
    }).dispose();
    assert.equal(disposed, true);
  });

  it('can wrap many disposable-likes', () => {
    let disposed1;
    let disposed2;

    new Disposable(
      {
        dispose() {
          disposed1 = true;
        },
      },
      () => {
        disposed2 = true;
      },
    ).dispose();
    assert.equal(disposed1, true);
    assert.equal(disposed2, true);
  });

  it('can add disposables after construction', () => {
    let disposed1;
    let disposed2;
    let disposed3;
    let disposed4;

    let disposable = new Disposable(
      {
        dispose() {
          disposed1 = true;
        },
      },
      () => {
        disposed2 = true;
      },
    );

    disposable.add(
      () => {
        disposed3 = true;
      },
      {
        dispose() {
          disposed4 = true;
        },
      },
    );

    assert.notEqual(disposed1, true);
    assert.notEqual(disposed2, true);
    assert.notEqual(disposed3, true);
    assert.notEqual(disposed4, true);

    disposable.dispose();

    assert.equal(disposed1, true);
    assert.equal(disposed2, true);
    assert.equal(disposed3, true);
    assert.equal(disposed4, true);
  });

  it(
    'does not dispose inner disposables more than once,' +
      ' and does not throw on subsequent disposals',
    () => {
      let disposed;
      let disposable = new Disposable(() => {
        if (disposed) {
          // $FlowFixMe
          assert.fail();
        }
        disposed = true;
      });

      disposable.dispose();
      disposable.dispose();
    },
  );

  it('throws if `add` is called after it has been disposed', () => {
    let disposable = new Disposable();
    disposable.dispose();
    assert.throws(() => {
      disposable.add(() => {});
    }, AlreadyDisposedError);
  });

  it('can be checked for disposal state', () => {
    let disposable = new Disposable();
    assert.equal(disposable.disposed, false);
    disposable.dispose();
    assert.equal(disposable.disposed, true);
  });
});