Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/test/common/notifications.test.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import assert from 'assert';
7
import { NotificationsModel, NotificationViewItem, INotificationChangeEvent, NotificationChangeType, NotificationViewItemContentChangeKind, IStatusMessageChangeEvent, StatusMessageChangeType, INotificationsFilter } from '../../common/notifications.js';
8
import { Action } from '../../../base/common/actions.js';
9
import { INotification, Severity, NotificationsFilter, NotificationPriority } from '../../../platform/notification/common/notification.js';
10
import { createErrorWithActions } from '../../../base/common/errorMessage.js';
11
import { timeout } from '../../../base/common/async.js';
12
import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../base/test/common/utils.js';
13
import { DisposableStore } from '../../../base/common/lifecycle.js';
14
15
suite('Notifications', () => {
16
17
const disposables = new DisposableStore();
18
const noFilter: INotificationsFilter = { global: NotificationsFilter.OFF, sources: new Map() };
19
20
teardown(() => {
21
disposables.clear();
22
});
23
24
test('Items', () => {
25
26
// Invalid
27
assert.ok(!NotificationViewItem.create({ severity: Severity.Error, message: '' }, noFilter));
28
assert.ok(!NotificationViewItem.create({ severity: Severity.Error, message: null! }, noFilter));
29
30
// Duplicates
31
const item1 = NotificationViewItem.create({ severity: Severity.Error, message: 'Error Message' }, noFilter)!;
32
const item2 = NotificationViewItem.create({ severity: Severity.Error, message: 'Error Message' }, noFilter)!;
33
const item3 = NotificationViewItem.create({ severity: Severity.Info, message: 'Info Message' }, noFilter)!;
34
const item4 = NotificationViewItem.create({ severity: Severity.Error, message: 'Error Message', source: 'Source' }, noFilter)!;
35
const item5 = NotificationViewItem.create({ severity: Severity.Error, message: 'Error Message', actions: { primary: [disposables.add(new Action('id', 'label'))] } }, noFilter)!;
36
const item6 = NotificationViewItem.create({ severity: Severity.Error, message: 'Error Message', actions: { primary: [disposables.add(new Action('id', 'label'))] }, progress: { infinite: true } }, noFilter)!;
37
38
assert.strictEqual(item1.equals(item1), true);
39
assert.strictEqual(item2.equals(item2), true);
40
assert.strictEqual(item3.equals(item3), true);
41
assert.strictEqual(item4.equals(item4), true);
42
assert.strictEqual(item5.equals(item5), true);
43
44
assert.strictEqual(item1.equals(item2), true);
45
assert.strictEqual(item1.equals(item3), false);
46
assert.strictEqual(item1.equals(item4), false);
47
assert.strictEqual(item1.equals(item5), false);
48
49
const itemId1 = NotificationViewItem.create({ id: 'same', message: 'Info Message', severity: Severity.Info }, noFilter)!;
50
const itemId2 = NotificationViewItem.create({ id: 'same', message: 'Error Message', severity: Severity.Error }, noFilter)!;
51
52
assert.strictEqual(itemId1.equals(itemId2), true);
53
assert.strictEqual(itemId1.equals(item3), false);
54
55
// Progress
56
assert.strictEqual(item1.hasProgress, false);
57
assert.strictEqual(item6.hasProgress, true);
58
59
// Message Box
60
assert.strictEqual(item5.canCollapse, false);
61
assert.strictEqual(item5.expanded, true);
62
63
// Events
64
let called = 0;
65
disposables.add(item1.onDidChangeExpansion(() => {
66
called++;
67
}));
68
69
item1.expand();
70
item1.expand();
71
item1.collapse();
72
item1.collapse();
73
74
assert.strictEqual(called, 2);
75
76
called = 0;
77
disposables.add(item1.onDidChangeContent(e => {
78
if (e.kind === NotificationViewItemContentChangeKind.PROGRESS) {
79
called++;
80
}
81
}));
82
83
item1.progress.infinite();
84
item1.progress.done();
85
86
assert.strictEqual(called, 2);
87
88
called = 0;
89
disposables.add(item1.onDidChangeContent(e => {
90
if (e.kind === NotificationViewItemContentChangeKind.MESSAGE) {
91
called++;
92
}
93
}));
94
95
item1.updateMessage('message update');
96
97
called = 0;
98
disposables.add(item1.onDidChangeContent(e => {
99
if (e.kind === NotificationViewItemContentChangeKind.SEVERITY) {
100
called++;
101
}
102
}));
103
104
item1.updateSeverity(Severity.Error);
105
106
called = 0;
107
disposables.add(item1.onDidChangeContent(e => {
108
if (e.kind === NotificationViewItemContentChangeKind.ACTIONS) {
109
called++;
110
}
111
}));
112
113
item1.updateActions({ primary: [disposables.add(new Action('id2', 'label'))] });
114
115
assert.strictEqual(called, 1);
116
117
called = 0;
118
disposables.add(item1.onDidChangeVisibility(e => {
119
called++;
120
}));
121
122
item1.updateVisibility(true);
123
item1.updateVisibility(false);
124
item1.updateVisibility(false);
125
126
assert.strictEqual(called, 2);
127
128
called = 0;
129
disposables.add(item1.onDidClose(() => {
130
called++;
131
}));
132
133
item1.close();
134
assert.strictEqual(called, 1);
135
136
// Error with Action
137
const item7 = NotificationViewItem.create({ severity: Severity.Error, message: createErrorWithActions('Hello Error', [disposables.add(new Action('id', 'label'))]) }, noFilter)!;
138
assert.strictEqual(item7.actions!.primary!.length, 1);
139
140
// Filter
141
const item8 = NotificationViewItem.create({ severity: Severity.Error, message: 'Error Message' }, { global: NotificationsFilter.OFF, sources: new Map() })!;
142
assert.strictEqual(item8.priority, NotificationPriority.DEFAULT);
143
144
const item9 = NotificationViewItem.create({ severity: Severity.Error, message: 'Error Message' }, { global: NotificationsFilter.ERROR, sources: new Map() })!;
145
assert.strictEqual(item9.priority, NotificationPriority.DEFAULT);
146
147
const item10 = NotificationViewItem.create({ severity: Severity.Warning, message: 'Error Message' }, { global: NotificationsFilter.ERROR, sources: new Map() })!;
148
assert.strictEqual(item10.priority, NotificationPriority.SILENT);
149
150
const sources = new Map<string, NotificationsFilter>();
151
sources.set('test.source', NotificationsFilter.ERROR);
152
const item11 = NotificationViewItem.create({ severity: Severity.Warning, message: 'Error Message', source: 'test.source' }, { global: NotificationsFilter.OFF, sources })!;
153
assert.strictEqual(item11.priority, NotificationPriority.DEFAULT);
154
const item12 = NotificationViewItem.create({ severity: Severity.Warning, message: 'Error Message', source: { id: 'test.source', label: 'foo' } }, { global: NotificationsFilter.OFF, sources })!;
155
assert.strictEqual(item12.priority, NotificationPriority.SILENT);
156
const item13 = NotificationViewItem.create({ severity: Severity.Warning, message: 'Error Message', source: { id: 'test.source2', label: 'foo' } }, { global: NotificationsFilter.OFF, sources })!;
157
assert.strictEqual(item13.priority, NotificationPriority.DEFAULT);
158
159
for (const item of [item1, item2, item3, item4, item5, item6, itemId1, itemId2, item7, item8, item9, item10, item11, item12, item13]) {
160
item.close();
161
}
162
});
163
164
test('Items - does not fire changed when message did not change (content, severity)', async () => {
165
const item1 = NotificationViewItem.create({ severity: Severity.Error, message: 'Error Message' }, noFilter)!;
166
167
let fired = false;
168
disposables.add(item1.onDidChangeContent(() => {
169
fired = true;
170
}));
171
172
item1.updateMessage('Error Message');
173
await timeout(0);
174
assert.ok(!fired, 'Expected onDidChangeContent to not be fired');
175
176
item1.updateSeverity(Severity.Error);
177
await timeout(0);
178
assert.ok(!fired, 'Expected onDidChangeContent to not be fired');
179
180
for (const item of [item1]) {
181
item.close();
182
}
183
});
184
185
test('Model', () => {
186
const model = disposables.add(new NotificationsModel());
187
188
let lastNotificationEvent!: INotificationChangeEvent;
189
disposables.add(model.onDidChangeNotification(e => {
190
lastNotificationEvent = e;
191
}));
192
193
let lastStatusMessageEvent!: IStatusMessageChangeEvent;
194
disposables.add(model.onDidChangeStatusMessage(e => {
195
lastStatusMessageEvent = e;
196
}));
197
198
const item1: INotification = { severity: Severity.Error, message: 'Error Message', actions: { primary: [disposables.add(new Action('id', 'label'))] } };
199
const item2: INotification = { severity: Severity.Warning, message: 'Warning Message', source: 'Some Source' };
200
const item2Duplicate: INotification = { severity: Severity.Warning, message: 'Warning Message', source: 'Some Source' };
201
const item3: INotification = { severity: Severity.Info, message: 'Info Message' };
202
203
const item1Handle = model.addNotification(item1);
204
assert.strictEqual(lastNotificationEvent.item.severity, item1.severity);
205
assert.strictEqual(lastNotificationEvent.item.message.linkedText.toString(), item1.message);
206
assert.strictEqual(lastNotificationEvent.index, 0);
207
assert.strictEqual(lastNotificationEvent.kind, NotificationChangeType.ADD);
208
209
item1Handle.updateMessage('Different Error Message');
210
assert.strictEqual(lastNotificationEvent.kind, NotificationChangeType.CHANGE);
211
assert.strictEqual(lastNotificationEvent.detail, NotificationViewItemContentChangeKind.MESSAGE);
212
213
item1Handle.updateSeverity(Severity.Warning);
214
assert.strictEqual(lastNotificationEvent.kind, NotificationChangeType.CHANGE);
215
assert.strictEqual(lastNotificationEvent.detail, NotificationViewItemContentChangeKind.SEVERITY);
216
217
item1Handle.updateActions({ primary: [], secondary: [] });
218
assert.strictEqual(lastNotificationEvent.kind, NotificationChangeType.CHANGE);
219
assert.strictEqual(lastNotificationEvent.detail, NotificationViewItemContentChangeKind.ACTIONS);
220
221
item1Handle.progress.infinite();
222
assert.strictEqual(lastNotificationEvent.kind, NotificationChangeType.CHANGE);
223
assert.strictEqual(lastNotificationEvent.detail, NotificationViewItemContentChangeKind.PROGRESS);
224
225
const item2Handle = model.addNotification(item2);
226
assert.strictEqual(lastNotificationEvent.item.severity, item2.severity);
227
assert.strictEqual(lastNotificationEvent.item.message.linkedText.toString(), item2.message);
228
assert.strictEqual(lastNotificationEvent.index, 0);
229
assert.strictEqual(lastNotificationEvent.kind, NotificationChangeType.ADD);
230
231
const item3Handle = model.addNotification(item3);
232
assert.strictEqual(lastNotificationEvent.item.severity, item3.severity);
233
assert.strictEqual(lastNotificationEvent.item.message.linkedText.toString(), item3.message);
234
assert.strictEqual(lastNotificationEvent.index, 0);
235
assert.strictEqual(lastNotificationEvent.kind, NotificationChangeType.ADD);
236
237
assert.strictEqual(model.notifications.length, 3);
238
239
let called = 0;
240
disposables.add(item1Handle.onDidClose(() => {
241
called++;
242
}));
243
244
item1Handle.close();
245
assert.strictEqual(called, 1);
246
assert.strictEqual(model.notifications.length, 2);
247
assert.strictEqual(lastNotificationEvent.item.severity, Severity.Warning);
248
assert.strictEqual(lastNotificationEvent.item.message.linkedText.toString(), 'Different Error Message');
249
assert.strictEqual(lastNotificationEvent.index, 2);
250
assert.strictEqual(lastNotificationEvent.kind, NotificationChangeType.REMOVE);
251
252
const item2DuplicateHandle = model.addNotification(item2Duplicate);
253
assert.strictEqual(model.notifications.length, 2);
254
assert.strictEqual(lastNotificationEvent.item.severity, item2Duplicate.severity);
255
assert.strictEqual(lastNotificationEvent.item.message.linkedText.toString(), item2Duplicate.message);
256
assert.strictEqual(lastNotificationEvent.index, 0);
257
assert.strictEqual(lastNotificationEvent.kind, NotificationChangeType.ADD);
258
259
item2Handle.close();
260
assert.strictEqual(model.notifications.length, 1);
261
assert.strictEqual(lastNotificationEvent.item.severity, item2Duplicate.severity);
262
assert.strictEqual(lastNotificationEvent.item.message.linkedText.toString(), item2Duplicate.message);
263
assert.strictEqual(lastNotificationEvent.index, 0);
264
assert.strictEqual(lastNotificationEvent.kind, NotificationChangeType.REMOVE);
265
266
model.notifications[0].expand();
267
assert.strictEqual(lastNotificationEvent.item.severity, item3.severity);
268
assert.strictEqual(lastNotificationEvent.item.message.linkedText.toString(), item3.message);
269
assert.strictEqual(lastNotificationEvent.index, 0);
270
assert.strictEqual(lastNotificationEvent.kind, NotificationChangeType.EXPAND_COLLAPSE);
271
272
const disposable = model.showStatusMessage('Hello World');
273
assert.strictEqual(model.statusMessage!.message, 'Hello World');
274
assert.strictEqual(lastStatusMessageEvent.item.message, model.statusMessage!.message);
275
assert.strictEqual(lastStatusMessageEvent.kind, StatusMessageChangeType.ADD);
276
disposable.close();
277
assert.ok(!model.statusMessage);
278
assert.strictEqual(lastStatusMessageEvent.kind, StatusMessageChangeType.REMOVE);
279
280
const disposable2 = model.showStatusMessage('Hello World 2');
281
const disposable3 = model.showStatusMessage('Hello World 3');
282
283
assert.strictEqual(model.statusMessage!.message, 'Hello World 3');
284
285
disposable2.close();
286
assert.strictEqual(model.statusMessage!.message, 'Hello World 3');
287
288
disposable3.close();
289
assert.ok(!model.statusMessage);
290
291
item2DuplicateHandle.close();
292
item3Handle.close();
293
});
294
295
ensureNoDisposablesAreLeakedInTestSuite();
296
});
297
298