Path: blob/main/src/vs/workbench/test/common/notifications.test.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import assert from 'assert';6import { NotificationsModel, NotificationViewItem, INotificationChangeEvent, NotificationChangeType, NotificationViewItemContentChangeKind, IStatusMessageChangeEvent, StatusMessageChangeType, INotificationsFilter } from '../../common/notifications.js';7import { Action } from '../../../base/common/actions.js';8import { INotification, Severity, NotificationsFilter, NotificationPriority } from '../../../platform/notification/common/notification.js';9import { createErrorWithActions } from '../../../base/common/errorMessage.js';10import { timeout } from '../../../base/common/async.js';11import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../base/test/common/utils.js';12import { DisposableStore } from '../../../base/common/lifecycle.js';1314suite('Notifications', () => {1516const disposables = new DisposableStore();17const noFilter: INotificationsFilter = { global: NotificationsFilter.OFF, sources: new Map() };1819teardown(() => {20disposables.clear();21});2223test('Items', () => {2425// Invalid26assert.ok(!NotificationViewItem.create({ severity: Severity.Error, message: '' }, noFilter));27assert.ok(!NotificationViewItem.create({ severity: Severity.Error, message: null! }, noFilter));2829// Duplicates30const item1 = NotificationViewItem.create({ severity: Severity.Error, message: 'Error Message' }, noFilter)!;31const item2 = NotificationViewItem.create({ severity: Severity.Error, message: 'Error Message' }, noFilter)!;32const item3 = NotificationViewItem.create({ severity: Severity.Info, message: 'Info Message' }, noFilter)!;33const item4 = NotificationViewItem.create({ severity: Severity.Error, message: 'Error Message', source: 'Source' }, noFilter)!;34const item5 = NotificationViewItem.create({ severity: Severity.Error, message: 'Error Message', actions: { primary: [disposables.add(new Action('id', 'label'))] } }, noFilter)!;35const item6 = NotificationViewItem.create({ severity: Severity.Error, message: 'Error Message', actions: { primary: [disposables.add(new Action('id', 'label'))] }, progress: { infinite: true } }, noFilter)!;3637assert.strictEqual(item1.equals(item1), true);38assert.strictEqual(item2.equals(item2), true);39assert.strictEqual(item3.equals(item3), true);40assert.strictEqual(item4.equals(item4), true);41assert.strictEqual(item5.equals(item5), true);4243assert.strictEqual(item1.equals(item2), true);44assert.strictEqual(item1.equals(item3), false);45assert.strictEqual(item1.equals(item4), false);46assert.strictEqual(item1.equals(item5), false);4748const itemId1 = NotificationViewItem.create({ id: 'same', message: 'Info Message', severity: Severity.Info }, noFilter)!;49const itemId2 = NotificationViewItem.create({ id: 'same', message: 'Error Message', severity: Severity.Error }, noFilter)!;5051assert.strictEqual(itemId1.equals(itemId2), true);52assert.strictEqual(itemId1.equals(item3), false);5354// Progress55assert.strictEqual(item1.hasProgress, false);56assert.strictEqual(item6.hasProgress, true);5758// Message Box59assert.strictEqual(item5.canCollapse, false);60assert.strictEqual(item5.expanded, true);6162// Events63let called = 0;64disposables.add(item1.onDidChangeExpansion(() => {65called++;66}));6768item1.expand();69item1.expand();70item1.collapse();71item1.collapse();7273assert.strictEqual(called, 2);7475called = 0;76disposables.add(item1.onDidChangeContent(e => {77if (e.kind === NotificationViewItemContentChangeKind.PROGRESS) {78called++;79}80}));8182item1.progress.infinite();83item1.progress.done();8485assert.strictEqual(called, 2);8687called = 0;88disposables.add(item1.onDidChangeContent(e => {89if (e.kind === NotificationViewItemContentChangeKind.MESSAGE) {90called++;91}92}));9394item1.updateMessage('message update');9596called = 0;97disposables.add(item1.onDidChangeContent(e => {98if (e.kind === NotificationViewItemContentChangeKind.SEVERITY) {99called++;100}101}));102103item1.updateSeverity(Severity.Error);104105called = 0;106disposables.add(item1.onDidChangeContent(e => {107if (e.kind === NotificationViewItemContentChangeKind.ACTIONS) {108called++;109}110}));111112item1.updateActions({ primary: [disposables.add(new Action('id2', 'label'))] });113114assert.strictEqual(called, 1);115116called = 0;117disposables.add(item1.onDidChangeVisibility(e => {118called++;119}));120121item1.updateVisibility(true);122item1.updateVisibility(false);123item1.updateVisibility(false);124125assert.strictEqual(called, 2);126127called = 0;128disposables.add(item1.onDidClose(() => {129called++;130}));131132item1.close();133assert.strictEqual(called, 1);134135// Error with Action136const item7 = NotificationViewItem.create({ severity: Severity.Error, message: createErrorWithActions('Hello Error', [disposables.add(new Action('id', 'label'))]) }, noFilter)!;137assert.strictEqual(item7.actions!.primary!.length, 1);138139// Filter140const item8 = NotificationViewItem.create({ severity: Severity.Error, message: 'Error Message' }, { global: NotificationsFilter.OFF, sources: new Map() })!;141assert.strictEqual(item8.priority, NotificationPriority.DEFAULT);142143const item9 = NotificationViewItem.create({ severity: Severity.Error, message: 'Error Message' }, { global: NotificationsFilter.ERROR, sources: new Map() })!;144assert.strictEqual(item9.priority, NotificationPriority.DEFAULT);145146const item10 = NotificationViewItem.create({ severity: Severity.Warning, message: 'Error Message' }, { global: NotificationsFilter.ERROR, sources: new Map() })!;147assert.strictEqual(item10.priority, NotificationPriority.SILENT);148149const sources = new Map<string, NotificationsFilter>();150sources.set('test.source', NotificationsFilter.ERROR);151const item11 = NotificationViewItem.create({ severity: Severity.Warning, message: 'Error Message', source: 'test.source' }, { global: NotificationsFilter.OFF, sources })!;152assert.strictEqual(item11.priority, NotificationPriority.DEFAULT);153const item12 = NotificationViewItem.create({ severity: Severity.Warning, message: 'Error Message', source: { id: 'test.source', label: 'foo' } }, { global: NotificationsFilter.OFF, sources })!;154assert.strictEqual(item12.priority, NotificationPriority.SILENT);155const item13 = NotificationViewItem.create({ severity: Severity.Warning, message: 'Error Message', source: { id: 'test.source2', label: 'foo' } }, { global: NotificationsFilter.OFF, sources })!;156assert.strictEqual(item13.priority, NotificationPriority.DEFAULT);157158for (const item of [item1, item2, item3, item4, item5, item6, itemId1, itemId2, item7, item8, item9, item10, item11, item12, item13]) {159item.close();160}161});162163test('Items - does not fire changed when message did not change (content, severity)', async () => {164const item1 = NotificationViewItem.create({ severity: Severity.Error, message: 'Error Message' }, noFilter)!;165166let fired = false;167disposables.add(item1.onDidChangeContent(() => {168fired = true;169}));170171item1.updateMessage('Error Message');172await timeout(0);173assert.ok(!fired, 'Expected onDidChangeContent to not be fired');174175item1.updateSeverity(Severity.Error);176await timeout(0);177assert.ok(!fired, 'Expected onDidChangeContent to not be fired');178179for (const item of [item1]) {180item.close();181}182});183184test('Model', () => {185const model = disposables.add(new NotificationsModel());186187let lastNotificationEvent!: INotificationChangeEvent;188disposables.add(model.onDidChangeNotification(e => {189lastNotificationEvent = e;190}));191192let lastStatusMessageEvent!: IStatusMessageChangeEvent;193disposables.add(model.onDidChangeStatusMessage(e => {194lastStatusMessageEvent = e;195}));196197const item1: INotification = { severity: Severity.Error, message: 'Error Message', actions: { primary: [disposables.add(new Action('id', 'label'))] } };198const item2: INotification = { severity: Severity.Warning, message: 'Warning Message', source: 'Some Source' };199const item2Duplicate: INotification = { severity: Severity.Warning, message: 'Warning Message', source: 'Some Source' };200const item3: INotification = { severity: Severity.Info, message: 'Info Message' };201202const item1Handle = model.addNotification(item1);203assert.strictEqual(lastNotificationEvent.item.severity, item1.severity);204assert.strictEqual(lastNotificationEvent.item.message.linkedText.toString(), item1.message);205assert.strictEqual(lastNotificationEvent.index, 0);206assert.strictEqual(lastNotificationEvent.kind, NotificationChangeType.ADD);207208item1Handle.updateMessage('Different Error Message');209assert.strictEqual(lastNotificationEvent.kind, NotificationChangeType.CHANGE);210assert.strictEqual(lastNotificationEvent.detail, NotificationViewItemContentChangeKind.MESSAGE);211212item1Handle.updateSeverity(Severity.Warning);213assert.strictEqual(lastNotificationEvent.kind, NotificationChangeType.CHANGE);214assert.strictEqual(lastNotificationEvent.detail, NotificationViewItemContentChangeKind.SEVERITY);215216item1Handle.updateActions({ primary: [], secondary: [] });217assert.strictEqual(lastNotificationEvent.kind, NotificationChangeType.CHANGE);218assert.strictEqual(lastNotificationEvent.detail, NotificationViewItemContentChangeKind.ACTIONS);219220item1Handle.progress.infinite();221assert.strictEqual(lastNotificationEvent.kind, NotificationChangeType.CHANGE);222assert.strictEqual(lastNotificationEvent.detail, NotificationViewItemContentChangeKind.PROGRESS);223224const item2Handle = model.addNotification(item2);225assert.strictEqual(lastNotificationEvent.item.severity, item2.severity);226assert.strictEqual(lastNotificationEvent.item.message.linkedText.toString(), item2.message);227assert.strictEqual(lastNotificationEvent.index, 0);228assert.strictEqual(lastNotificationEvent.kind, NotificationChangeType.ADD);229230const item3Handle = model.addNotification(item3);231assert.strictEqual(lastNotificationEvent.item.severity, item3.severity);232assert.strictEqual(lastNotificationEvent.item.message.linkedText.toString(), item3.message);233assert.strictEqual(lastNotificationEvent.index, 0);234assert.strictEqual(lastNotificationEvent.kind, NotificationChangeType.ADD);235236assert.strictEqual(model.notifications.length, 3);237238let called = 0;239disposables.add(item1Handle.onDidClose(() => {240called++;241}));242243item1Handle.close();244assert.strictEqual(called, 1);245assert.strictEqual(model.notifications.length, 2);246assert.strictEqual(lastNotificationEvent.item.severity, Severity.Warning);247assert.strictEqual(lastNotificationEvent.item.message.linkedText.toString(), 'Different Error Message');248assert.strictEqual(lastNotificationEvent.index, 2);249assert.strictEqual(lastNotificationEvent.kind, NotificationChangeType.REMOVE);250251const item2DuplicateHandle = model.addNotification(item2Duplicate);252assert.strictEqual(model.notifications.length, 2);253assert.strictEqual(lastNotificationEvent.item.severity, item2Duplicate.severity);254assert.strictEqual(lastNotificationEvent.item.message.linkedText.toString(), item2Duplicate.message);255assert.strictEqual(lastNotificationEvent.index, 0);256assert.strictEqual(lastNotificationEvent.kind, NotificationChangeType.ADD);257258item2Handle.close();259assert.strictEqual(model.notifications.length, 1);260assert.strictEqual(lastNotificationEvent.item.severity, item2Duplicate.severity);261assert.strictEqual(lastNotificationEvent.item.message.linkedText.toString(), item2Duplicate.message);262assert.strictEqual(lastNotificationEvent.index, 0);263assert.strictEqual(lastNotificationEvent.kind, NotificationChangeType.REMOVE);264265model.notifications[0].expand();266assert.strictEqual(lastNotificationEvent.item.severity, item3.severity);267assert.strictEqual(lastNotificationEvent.item.message.linkedText.toString(), item3.message);268assert.strictEqual(lastNotificationEvent.index, 0);269assert.strictEqual(lastNotificationEvent.kind, NotificationChangeType.EXPAND_COLLAPSE);270271const disposable = model.showStatusMessage('Hello World');272assert.strictEqual(model.statusMessage!.message, 'Hello World');273assert.strictEqual(lastStatusMessageEvent.item.message, model.statusMessage!.message);274assert.strictEqual(lastStatusMessageEvent.kind, StatusMessageChangeType.ADD);275disposable.close();276assert.ok(!model.statusMessage);277assert.strictEqual(lastStatusMessageEvent.kind, StatusMessageChangeType.REMOVE);278279const disposable2 = model.showStatusMessage('Hello World 2');280const disposable3 = model.showStatusMessage('Hello World 3');281282assert.strictEqual(model.statusMessage!.message, 'Hello World 3');283284disposable2.close();285assert.strictEqual(model.statusMessage!.message, 'Hello World 3');286287disposable3.close();288assert.ok(!model.statusMessage);289290item2DuplicateHandle.close();291item3Handle.close();292});293294ensureNoDisposablesAreLeakedInTestSuite();295});296297298