Skip to content

Commit 8966edc

Browse files
authored
test(notifications): unit tests for notification rendering (#5947)
Unit testing for notifications rendering Using locally generated notifications, test covers: - new notification on-receive modal/toast windows - panel on-click txt/url pop up - modal button actions (update&restart, txt, url)
1 parent 09a0db7 commit 8966edc

File tree

3 files changed

+215
-7
lines changed

3 files changed

+215
-7
lines changed

packages/core/src/notifications/panelNode.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ export class NotificationsNode implements TreeNode {
128128
* Fired when a notification is clicked on in the panel. It will run any rendering
129129
* instructions included in the notification. See {@link ToolkitNotification.uiRenderInstructions}.
130130
*/
131-
private async openNotification(notification: ToolkitNotification) {
131+
public async openNotification(notification: ToolkitNotification) {
132132
switch (notification.uiRenderInstructions.onClick.type) {
133133
case 'modal':
134134
// Render blocking modal

packages/core/src/shared/utilities/textDocumentUtilities.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import * as _path from 'path'
77
import * as vscode from 'vscode'
8-
import { getTabSizeSetting } from './editorUtilities'
8+
import { disposeOnEditorClose, getTabSizeSetting } from './editorUtilities'
99
import { tempDirPath } from '../filesystemUtilities'
1010
import { getLogger } from '../logger'
1111
import fs from '../fs/fs'
@@ -247,22 +247,22 @@ class ReadonlyDocument {
247247
private readonly scheme = 'AWStoolkit-readonly'
248248
private readonly provider = new ReadonlyTextDocumentProvider()
249249

250-
constructor() {
251-
vscode.workspace.registerTextDocumentContentProvider(this.scheme, this.provider)
252-
}
253-
254250
public async show(content: string, filename: string) {
251+
const disposableProvider = vscode.workspace.registerTextDocumentContentProvider(this.scheme, this.provider)
255252
this.provider.setContent(content)
256253
const uri = vscode.Uri.parse(`${this.scheme}:/${filename}.txt`)
254+
// txt document on side column, in focus and preview
257255
const options: vscode.TextDocumentShowOptions = {
258256
viewColumn: vscode.ViewColumn.Beside,
259-
preserveFocus: true,
257+
preserveFocus: false,
260258
preview: true,
261259
}
262260

263261
// Open the document with the updated content
264262
const document = await vscode.workspace.openTextDocument(uri)
265263
await vscode.window.showTextDocument(document, options)
264+
265+
disposeOnEditorClose(uri, disposableProvider)
266266
}
267267
}
268268

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import * as vscode from 'vscode'
7+
import * as sinon from 'sinon'
8+
import assert from 'assert'
9+
import { ToolkitNotification } from '../../notifications/types'
10+
import { panelNode } from './controller.test'
11+
import { getTestWindow } from '../shared/vscode/window'
12+
import * as VsCodeUtils from '../../shared/utilities/vsCodeUtils'
13+
import { assertTextEditorContains } from '../testUtil'
14+
15+
describe('Notifications Rendering', function () {
16+
let sandbox: sinon.SinonSandbox
17+
18+
beforeEach(function () {
19+
sandbox = sinon.createSandbox()
20+
})
21+
22+
afterEach(function () {
23+
sandbox.restore()
24+
})
25+
26+
// util to test txt pop-up under different senarios
27+
async function verifyTxtNotification(notification: ToolkitNotification) {
28+
const expectedContent = notification.uiRenderInstructions.content['en-US'].description
29+
void panelNode.openNotification(notification)
30+
31+
await assertTextEditorContains(expectedContent)
32+
}
33+
34+
// util to test open url under different senarios
35+
async function verifyOpenExternalUrl(notification: ToolkitNotification) {
36+
const openUrlStub = sandbox.stub(VsCodeUtils, 'openUrl')
37+
await panelNode.openNotification(notification)
38+
39+
assert.ok(openUrlStub.calledWith(vscode.Uri.parse('https://aws.amazon.com/visualstudiocode/')))
40+
}
41+
42+
// test on-receive behaviors
43+
it('displays a toast with correct message on receive', async function () {
44+
const testWindow = getTestWindow()
45+
testWindow.onDidShowMessage((message) => {})
46+
47+
const notification = getToastURLTestNotification()
48+
await panelNode.onReceiveNotifications([notification])
49+
50+
const expectedMessage =
51+
notification.uiRenderInstructions.content['en-US'].toastPreview ??
52+
notification.uiRenderInstructions.content['en-US'].title
53+
54+
const shownMessages = testWindow.shownMessages
55+
assert.ok(shownMessages.some((msg) => msg.message === expectedMessage))
56+
})
57+
58+
it('displays a modal with correct buttons on receive', async function () {
59+
const testWindow = getTestWindow()
60+
const notification = getModalNotification()
61+
62+
testWindow.onDidShowMessage((message) => {
63+
const expectedButtons =
64+
notification.uiRenderInstructions.actions?.map((actions) => actions.displayText['en-US']) ?? []
65+
expectedButtons.forEach((buttonText) => {
66+
assert.ok(
67+
message.items.some((item) => item.title === buttonText),
68+
`Button "${buttonText}" is missing`
69+
)
70+
})
71+
})
72+
73+
await panelNode.onReceiveNotifications([notification])
74+
})
75+
76+
// test on-lick behaviors
77+
it('open a txt with correct content on-click', async function () {
78+
const notification = getTxtNotification()
79+
await verifyTxtNotification(notification)
80+
})
81+
82+
it('opens a URL with correct link on-click', async function () {
83+
const notification = getToastURLTestNotification()
84+
await verifyOpenExternalUrl(notification)
85+
})
86+
87+
// test modal buttons behavior
88+
it('executes updateAndReload type button', async function () {
89+
const testWindow = getTestWindow()
90+
testWindow.onDidShowMessage((message) => {
91+
// Simulate user clicking update and reload type
92+
message.selectItem('Update and Reload')
93+
})
94+
const excuteCommandStub = sandbox.stub(vscode.commands, 'executeCommand').resolves()
95+
const notification = getModalNotification()
96+
await panelNode.openNotification(notification)
97+
98+
assert.ok(excuteCommandStub.calledWith('workbench.extensions.installExtension', 'aws.toolkit.fake.extension'))
99+
assert.ok(excuteCommandStub.calledWith('workbench.action.reloadWindow'))
100+
})
101+
102+
it('executes openURL type button', async function () {
103+
const testWindow = getTestWindow()
104+
testWindow.onDidShowMessage((message) => {
105+
// Simulate user clicking open URL type
106+
message.selectItem('Proceed to Wiki')
107+
})
108+
const notification = getModalNotification()
109+
await verifyOpenExternalUrl(notification)
110+
})
111+
112+
it('executes openTxt type button', async function () {
113+
const testWindow = getTestWindow()
114+
testWindow.onDidShowMessage((message) => {
115+
// Simulate user clicking open txt type
116+
message.selectItem('Read More')
117+
})
118+
const notification = getModalNotification()
119+
await verifyTxtNotification(notification)
120+
})
121+
})
122+
123+
// generate test notifications
124+
function getToastURLTestNotification(): ToolkitNotification {
125+
return {
126+
id: 'test notification 1',
127+
displayIf: {
128+
extensionId: 'aws.toolkit.fake.extension',
129+
},
130+
uiRenderInstructions: {
131+
content: {
132+
[`en-US`]: {
133+
title: 'test',
134+
description: 'This is a url notification.',
135+
toastPreview: 'test toast preview',
136+
},
137+
},
138+
onRecieve: 'toast',
139+
onClick: {
140+
type: 'openUrl',
141+
url: 'https://aws.amazon.com/visualstudiocode/',
142+
},
143+
},
144+
}
145+
}
146+
147+
function getTxtNotification(): ToolkitNotification {
148+
return {
149+
id: 'test notification 2',
150+
displayIf: {
151+
extensionId: 'aws.toolkit.fake.extension',
152+
},
153+
uiRenderInstructions: {
154+
content: {
155+
[`en-US`]: {
156+
title: 'test',
157+
description: 'This is a text document notification.',
158+
},
159+
},
160+
onRecieve: 'toast',
161+
onClick: {
162+
type: 'openTextDocument',
163+
},
164+
},
165+
}
166+
}
167+
168+
function getModalNotification(): ToolkitNotification {
169+
return {
170+
id: 'test notification 3',
171+
displayIf: {
172+
extensionId: 'aws.toolkit.fake.extension',
173+
},
174+
uiRenderInstructions: {
175+
content: {
176+
[`en-US`]: {
177+
title: 'test',
178+
description: 'This is a modal notification.',
179+
},
180+
},
181+
onRecieve: 'modal',
182+
onClick: {
183+
type: 'modal',
184+
},
185+
actions: [
186+
{
187+
type: 'updateAndReload',
188+
displayText: {
189+
'en-US': 'Update and Reload',
190+
},
191+
},
192+
{
193+
type: 'openUrl',
194+
url: 'https://aws.amazon.com/visualstudiocode/',
195+
displayText: {
196+
'en-US': 'Proceed to Wiki',
197+
},
198+
},
199+
{
200+
type: 'openTxt',
201+
displayText: {
202+
'en-US': 'Read More',
203+
},
204+
},
205+
],
206+
},
207+
}
208+
}

0 commit comments

Comments
 (0)