Back to Repositories

Testing PromiseQueue Async Operations in Parcel Bundler

This test suite validates the PromiseQueue implementation in Parcel, focusing on asynchronous queue management and promise handling. The tests verify core queue functionality, error handling, and subscription mechanisms for async operations.

Test Coverage Overview

The test suite provides comprehensive coverage of PromiseQueue functionality, including:
  • Queue execution and completion verification
  • Error propagation and rejection handling
  • Empty queue scenarios
  • Promise resolution and rejection cases
  • Concurrent execution limits
  • Subscription mechanism testing

Implementation Analysis

The testing approach utilizes Jest’s async/await patterns for promise-based testing. The implementation employs sinon for spy functionality and assertion-based validation, with careful attention to promise chain handling and error scenarios.

Key patterns include async function testing, promise resolution verification, and concurrent execution management.

Technical Details

Testing infrastructure includes:
  • Jest test framework
  • Sinon for spy functionality
  • Flow type checking
  • Native Promise API
  • Custom PromiseQueue implementation
  • Assert module for validations

Best Practices Demonstrated

The test suite exemplifies robust testing practices including:
  • Isolated test cases with clear purpose
  • Proper async/await handling
  • Error case coverage
  • Edge case testing
  • Subscription pattern validation
  • Concurrent execution verification
  • Clean test organization and structure

parcel-bundler/parcel

packages/core/utils/test/PromiseQueue.test.js

            
// @flow
import assert from 'assert';

import PromiseQueue from '../src/PromiseQueue';
import sinon from 'sinon';

describe('PromiseQueue', () => {
  it('run() should resolve when all async functions in queue have completed', async () => {
    let queue = new PromiseQueue();

    let someBooleanToBeChanged = false;
    queue.add(() =>
      Promise.resolve().then(() => {
        someBooleanToBeChanged = true;
      }),
    );
    await queue.run();
    assert(someBooleanToBeChanged);
  });

  it('run() should reject if any of the async functions in the queue failed', async () => {
    let error = new Error('some failure');
    try {
      let queue = new PromiseQueue();
      queue
        .add(() => Promise.reject(error))
        .catch(
          /* catch this to prevent an unhandled promise rejection*/ () => {},
        );
      await queue.run();
    } catch (e) {
      assert.equal(e, error);
    }
  });

  it('.run() should instantly resolve when the queue is empty', async () => {
    let queue = new PromiseQueue();
    await queue.run();
    // no need to assert, test will hang or throw an error if condition fails
  });

  it(".add() should resolve with the same result when the passed in function's promise resolves", async () => {
    let queue = new PromiseQueue();
    let promise = queue.add(() => Promise.resolve(42));
    await queue.run();
    let result = await promise;
    assert.equal(result, 42);
  });

  it(".add() should reject with the same error when the passed in function's promise rejects", async () => {
    let queue = new PromiseQueue();
    let error = new Error('Oh no!');
    let promise = queue.add(() => Promise.reject(error));
    await queue.run().catch(() => null);
    await promise.then(null, e => assert.equal(e, error));
  });

  it('constructor() should allow for configuration of max concurrent running functions', async () => {
    const maxConcurrent = 5;
    const queue = new PromiseQueue({maxConcurrent});
    let running = 0;

    new Array(100).fill(0).map(() =>
      queue.add(async () => {
        running++;
        assert(queue._numRunning === running);
        assert(running <= maxConcurrent);
        await Promise.resolve(Math.floor(Math.random() * 10) + 1);
        running--;
      }),
    );

    await queue.run();
  });

  it('.add() should notify subscribers', async () => {
    const queue = new PromiseQueue();

    const subscribedFn = sinon.spy();
    queue.subscribeToAdd(subscribedFn);

    const promise = queue.add(() => Promise.resolve());
    await queue.run();
    await promise;

    assert(subscribedFn.called);
  });

  it('.subscribeToAdd() should allow unsubscribing', async () => {
    const queue = new PromiseQueue();

    const subscribedFn = sinon.spy();
    const unsubscribe = queue.subscribeToAdd(subscribedFn);
    unsubscribe();

    const promise = queue.add(() => Promise.resolve());
    await queue.run();
    await promise;

    assert(!subscribedFn.called);
  });
});