Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -421,14 +421,19 @@ export default class CLIProgressManager {

if (!this.showConsoleLogs && process.progressBar) {
const totalProcessed = process.current;
const percentage = Math.round((totalProcessed / process.total) * 100);
// Reconcile the bar's total with the number of items actually processed so the
// rendered "value/total" matches the "Complete (success/processed)" summary. A
// process registered with an estimated total larger than the items actually ticked
// would otherwise render mismatched counts, e.g. "37/37 | Complete (27/27)".
process.progressBar.setTotal(totalProcessed);
const percentage = totalProcessed > 0 ? 100 : 0;
const formattedPercentage = this.formatPercentage(percentage);
const statusText = success
? getChalk().green(`✓ Complete (${process.successCount}/${process.current})`)
: getChalk().red(`✗ Failed (${process.successCount}/${process.current})`);
? getChalk().green(`✓ Complete (${process.successCount}/${totalProcessed})`)
: getChalk().red(`✗ Failed (${process.successCount}/${totalProcessed})`);
const displayName = this.formatProcessName(processName);
const indentedLabel = ` ├─ ${displayName}`.padEnd(25);
process.progressBar.update(process.total, {
process.progressBar.update(totalProcessed, {
label: success ? getChalk().green(indentedLabel) : getChalk().red(indentedLabel),
status: statusText,
percentage: formattedPercentage,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const mockProgressBar = {
stop: sinon.stub(),
increment: sinon.stub(),
update: sinon.stub(),
setTotal: sinon.stub(),
};

const mockMultiBar = {
Expand Down Expand Up @@ -335,6 +336,74 @@ describe('CLIProgressManager', () => {
});
});

describe('Complete count reconciliation', () => {
let bar: { update: sinon.SinonStub; setTotal: sinon.SinonStub; increment: sinon.SinonStub };

// Inject a stub bar at the rendering seam so assertions do not depend on the
// load-order-sensitive cli-progress module mock (which does not bind in CI).
function injectBar(processName: string) {
bar = { update: sinon.stub(), setTotal: sinon.stub(), increment: sinon.stub() };
(progressManager as any).processes.get(processName).progressBar = bar;
}

beforeEach(() => {
progressManager = new CLIProgressManager({
enableNestedProgress: true,
moduleName: 'RECONCILE_TEST',
showConsoleLogs: false,
});
});

fancy.it('renders the processed count, not the registered estimate, when fewer items were ticked', () => {
progressManager.addProcess('gf-update', 37);
injectBar('gf-update');
for (let i = 0; i < 27; i++) {
progressManager.tick(true, `item-${i}`, null, 'gf-update');
}

progressManager.completeProcess('gf-update', true);

expect(bar.setTotal.calledWith(27)).to.equal(true);
expect(bar.update.lastCall.args[0]).to.equal(27);
});

fancy.it('renders the full count unchanged when every registered item was ticked', () => {
progressManager.addProcess('entries-create', 59);
injectBar('entries-create');
for (let i = 0; i < 59; i++) {
progressManager.tick(true, `item-${i}`, null, 'entries-create');
}

progressManager.completeProcess('entries-create', true);

expect(bar.update.lastCall.args[0]).to.equal(59);
});

fancy.it('renders the registered total when a process completes with no ticks (skip case)', () => {
progressManager.addProcess('skipped', 5);
injectBar('skipped');

progressManager.completeProcess('skipped', true);

expect(bar.update.lastCall.args[0]).to.equal(5);
});

fancy.it('reconciles the denominator for a failed process with partial ticks', () => {
progressManager.addProcess('entries', 59);
injectBar('entries');
for (let i = 0; i < 38; i++) {
progressManager.tick(true, `ok-${i}`, null, 'entries');
}
for (let i = 0; i < 3; i++) {
progressManager.tick(false, `err-${i}`, 'boom', 'entries');
}

progressManager.completeProcess('entries', false);

expect(bar.update.lastCall.args[0]).to.equal(41);
});
});

describe('Progress Tracking', () => {
beforeEach(() => {
progressManager = new CLIProgressManager({
Expand Down
Loading