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
Implementation Analysis
Technical Details
Best Practices Demonstrated
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);
});
});