diff --git a/messages/progress-event-listener.md b/messages/progress-event-listener.md index 39f1576aa..e8f383b91 100644 --- a/messages/progress-event-listener.md +++ b/messages/progress-event-listener.md @@ -1,9 +1,12 @@ # selection-spinner.action Selecting rules -# selection-spinner.status +# selection-spinner.in-progress-status Eligible engines: %s; Completion: %d%; Elapsed time: %ds +# selection-spinner.finished-status +done. Selected rules from %s. + # execution-spinner.action Executing rules @@ -13,6 +16,5 @@ Executing rules # execution-spinner.engine-status - %s at %d% completion. -# base-spinner.done -done - +# execution-spinner.finished-status +done. Executed rules from %s. diff --git a/src/lib/listeners/ProgressEventListener.ts b/src/lib/listeners/ProgressEventListener.ts index 7a46307db..a23c7e6c2 100644 --- a/src/lib/listeners/ProgressEventListener.ts +++ b/src/lib/listeners/ProgressEventListener.ts @@ -31,20 +31,20 @@ abstract class ProgressSpinner { return; } this.startTime = Date.now(); - this.display.spinnerStart(action, this.createSpinnerStatus()); + this.display.spinnerStart(action, this.createInProgressSpinnerStatus()); if (this.tickTime > 0) { // `setInterval` means the callback will be called repeatedly. This allows us to automatically refresh the // spinner on a regular interval even if nothing happened. This is primarily useful for incrementing a timer, // so the user doesn't feel like the system is frozen. this.tickIntervalId = setInterval(() => { - this.display.spinnerUpdate(this.createSpinnerStatus()); + this.display.spinnerUpdate(this.createInProgressSpinnerStatus()); }, this.tickTime); } this._isSpinning = true; } protected updateSpinner(): void { - this.display.spinnerUpdate(this.createSpinnerStatus()); + this.display.spinnerUpdate(this.createInProgressSpinnerStatus()); } protected stopSpinning(): void { @@ -52,7 +52,7 @@ abstract class ProgressSpinner { clearInterval(this.tickIntervalId); } if (this._isSpinning) { - this.display.spinnerStop(getMessage(BundleName.ProgressEventListener, 'base-spinner.done')); + this.display.spinnerStop(this.createFinishedSpinnerStatus()); this._isSpinning = false; } } @@ -69,7 +69,9 @@ abstract class ProgressSpinner { return Math.floor((Date.now() - this.startTime) / 1000); } - protected abstract createSpinnerStatus(): string; + protected abstract createInProgressSpinnerStatus(): string; + + protected abstract createFinishedSpinnerStatus(): string; } export class RuleSelectionProgressSpinner extends ProgressSpinner implements ProgressEventListener { @@ -128,12 +130,17 @@ export class RuleSelectionProgressSpinner extends ProgressSpinner implements Pro } } - protected createSpinnerStatus(): string { + protected createInProgressSpinnerStatus(): string { const aggregateCompletionPercentage: number = Math.floor(this.completionPercentages.reduce((prevTotal, next) => prevTotal + next, 0) / this.completionPercentages.length); - return getMessage(BundleName.ProgressEventListener, 'selection-spinner.status', + return getMessage(BundleName.ProgressEventListener, 'selection-spinner.in-progress-status', [[...this.engineNames.keys()].join(', '), aggregateCompletionPercentage, this.getSecondsSpentSpinning()]); } + + protected createFinishedSpinnerStatus(): string { + return getMessage(BundleName.ProgressEventListener, 'selection-spinner.finished-status', + [[...this.engineNames.keys()].join(', ')]); + } } export class EngineRunProgressSpinner extends ProgressSpinner implements ProgressEventListener { @@ -189,7 +196,7 @@ export class EngineRunProgressSpinner extends ProgressSpinner implements Progres this.updateSpinner(); } - protected createSpinnerStatus(): string { + protected createInProgressSpinnerStatus(): string { const secondsRunning = this.getSecondsSpentSpinning(); const totalEngines = this.progressMap.size; let unfinishedEngines = 0; @@ -205,4 +212,9 @@ export class EngineRunProgressSpinner extends ProgressSpinner implements Progres ...engineLines ].join('\n'); } + + protected createFinishedSpinnerStatus(): string { + return getMessage(BundleName.ProgressEventListener, 'execution-spinner.finished-status', + [[...this.progressMap.keys()].join(', ')]); + } } diff --git a/test/lib/listeners/ProgressEventListener.test.ts b/test/lib/listeners/ProgressEventListener.test.ts index 781beb6bf..b4e48127a 100644 --- a/test/lib/listeners/ProgressEventListener.test.ts +++ b/test/lib/listeners/ProgressEventListener.test.ts @@ -87,7 +87,7 @@ describe('ProgressEventListener implementations', () => { expect(percentagesInOrder).toEqual([0, 25, 50, 100]); const endEvent = displayEvents[displayEvents.length - 1]; expect(endEvent).toHaveProperty('type', DisplayEventType.SPINNER_STOP); - expect(endEvent.data).toContain('done'); + expect(endEvent.data).toContain(`done. Selected rules from stubEngine1, stubEngine2.`); }); it('Properly aggregates percentages across multiple Cores', async () => { @@ -123,7 +123,7 @@ describe('ProgressEventListener implementations', () => { expect(percentagesInOrder).toEqual([0, 12, 25, 50, 62, 75, 100]); const endEvent = displayEvents[displayEvents.length - 1]; expect(endEvent).toHaveProperty('type', DisplayEventType.SPINNER_STOP); - expect(endEvent.data).toContain('done'); + expect(endEvent.data).toContain('done. Selected rules from stubEngine1, stubEngine2.'); }); it('Properly interleaves progress updates with ticking', async () => { @@ -159,7 +159,7 @@ describe('ProgressEventListener implementations', () => { expect(percentagesInOrder).toEqual([0, 20, 40, 50, 60, 80, 100]); const endEvent = displayEvents[displayEvents.length - 1]; expect(endEvent).toHaveProperty('type', DisplayEventType.SPINNER_STOP); - expect(endEvent.data).toContain('done'); + expect(endEvent.data).toContain('done. Selected rules from timeableEngine1, timeableEngine2.'); }); }); @@ -252,7 +252,7 @@ describe('ProgressEventListener implementations', () => { expect(percentagesInOrder).toEqual([0, 50, 100]); const endEvent = displayEvents[displayEvents.length - 1]; expect(endEvent).toHaveProperty('type', DisplayEventType.SPINNER_STOP); - expect(endEvent.data).toContain('done'); + expect(endEvent.data).toContain('done. Executed rules from stubEngine1.'); }); it('Properly interleaves progress updates from multiple engines', async () => { @@ -296,7 +296,7 @@ describe('ProgressEventListener implementations', () => { // The final event should be the Stop event. const endEvent = displayEvents[displayEvents.length - 1]; expect(endEvent).toHaveProperty('type', DisplayEventType.SPINNER_STOP); - expect(endEvent.data).toContain('done'); + expect(endEvent.data).toContain('done. Executed rules from timeableEngine1, timeableEngine2.'); }); it('Properly interleaves progress updates with ticking', async () => { @@ -332,7 +332,7 @@ describe('ProgressEventListener implementations', () => { expect(percentagesInOrder).toEqual([0, 50, 100]); const endEvent = displayEvents[displayEvents.length - 1]; expect(endEvent).toHaveProperty('type', DisplayEventType.SPINNER_STOP); - expect(endEvent.data).toContain('done'); + expect(endEvent.data).toContain('done. Executed rules from timeableEngine1.'); }, 10000); // There's currently no need for this Spinner to accept multiple Cores, so we've opted to not implement that