Skip to content

Commit

Permalink
test(notifications): unit tests for notification rendering (#5947)
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
tomcat323 authored Nov 13, 2024
1 parent 09a0db7 commit 8966edc
Show file tree
Hide file tree
Showing 3 changed files with 215 additions and 7 deletions.
2 changes: 1 addition & 1 deletion packages/core/src/notifications/panelNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ export class NotificationsNode implements TreeNode {
* Fired when a notification is clicked on in the panel. It will run any rendering
* instructions included in the notification. See {@link ToolkitNotification.uiRenderInstructions}.
*/
private async openNotification(notification: ToolkitNotification) {
public async openNotification(notification: ToolkitNotification) {
switch (notification.uiRenderInstructions.onClick.type) {
case 'modal':
// Render blocking modal
Expand Down
12 changes: 6 additions & 6 deletions packages/core/src/shared/utilities/textDocumentUtilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import * as _path from 'path'
import * as vscode from 'vscode'
import { getTabSizeSetting } from './editorUtilities'
import { disposeOnEditorClose, getTabSizeSetting } from './editorUtilities'
import { tempDirPath } from '../filesystemUtilities'
import { getLogger } from '../logger'
import fs from '../fs/fs'
Expand Down Expand Up @@ -247,22 +247,22 @@ class ReadonlyDocument {
private readonly scheme = 'AWStoolkit-readonly'
private readonly provider = new ReadonlyTextDocumentProvider()

constructor() {
vscode.workspace.registerTextDocumentContentProvider(this.scheme, this.provider)
}

public async show(content: string, filename: string) {
const disposableProvider = vscode.workspace.registerTextDocumentContentProvider(this.scheme, this.provider)
this.provider.setContent(content)
const uri = vscode.Uri.parse(`${this.scheme}:/${filename}.txt`)
// txt document on side column, in focus and preview
const options: vscode.TextDocumentShowOptions = {
viewColumn: vscode.ViewColumn.Beside,
preserveFocus: true,
preserveFocus: false,
preview: true,
}

// Open the document with the updated content
const document = await vscode.workspace.openTextDocument(uri)
await vscode.window.showTextDocument(document, options)

disposeOnEditorClose(uri, disposableProvider)
}
}

Expand Down
208 changes: 208 additions & 0 deletions packages/core/src/test/notifications/rendering.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
/*!
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

import * as vscode from 'vscode'
import * as sinon from 'sinon'
import assert from 'assert'
import { ToolkitNotification } from '../../notifications/types'
import { panelNode } from './controller.test'
import { getTestWindow } from '../shared/vscode/window'
import * as VsCodeUtils from '../../shared/utilities/vsCodeUtils'
import { assertTextEditorContains } from '../testUtil'

describe('Notifications Rendering', function () {
let sandbox: sinon.SinonSandbox

beforeEach(function () {
sandbox = sinon.createSandbox()
})

afterEach(function () {
sandbox.restore()
})

// util to test txt pop-up under different senarios
async function verifyTxtNotification(notification: ToolkitNotification) {
const expectedContent = notification.uiRenderInstructions.content['en-US'].description
void panelNode.openNotification(notification)

await assertTextEditorContains(expectedContent)
}

// util to test open url under different senarios
async function verifyOpenExternalUrl(notification: ToolkitNotification) {
const openUrlStub = sandbox.stub(VsCodeUtils, 'openUrl')
await panelNode.openNotification(notification)

assert.ok(openUrlStub.calledWith(vscode.Uri.parse('https://aws.amazon.com/visualstudiocode/')))
}

// test on-receive behaviors
it('displays a toast with correct message on receive', async function () {
const testWindow = getTestWindow()
testWindow.onDidShowMessage((message) => {})

const notification = getToastURLTestNotification()
await panelNode.onReceiveNotifications([notification])

const expectedMessage =
notification.uiRenderInstructions.content['en-US'].toastPreview ??
notification.uiRenderInstructions.content['en-US'].title

const shownMessages = testWindow.shownMessages
assert.ok(shownMessages.some((msg) => msg.message === expectedMessage))
})

it('displays a modal with correct buttons on receive', async function () {
const testWindow = getTestWindow()
const notification = getModalNotification()

testWindow.onDidShowMessage((message) => {
const expectedButtons =
notification.uiRenderInstructions.actions?.map((actions) => actions.displayText['en-US']) ?? []
expectedButtons.forEach((buttonText) => {
assert.ok(
message.items.some((item) => item.title === buttonText),
`Button "${buttonText}" is missing`
)
})
})

await panelNode.onReceiveNotifications([notification])
})

// test on-lick behaviors
it('open a txt with correct content on-click', async function () {
const notification = getTxtNotification()
await verifyTxtNotification(notification)
})

it('opens a URL with correct link on-click', async function () {
const notification = getToastURLTestNotification()
await verifyOpenExternalUrl(notification)
})

// test modal buttons behavior
it('executes updateAndReload type button', async function () {
const testWindow = getTestWindow()
testWindow.onDidShowMessage((message) => {
// Simulate user clicking update and reload type
message.selectItem('Update and Reload')
})
const excuteCommandStub = sandbox.stub(vscode.commands, 'executeCommand').resolves()
const notification = getModalNotification()
await panelNode.openNotification(notification)

assert.ok(excuteCommandStub.calledWith('workbench.extensions.installExtension', 'aws.toolkit.fake.extension'))
assert.ok(excuteCommandStub.calledWith('workbench.action.reloadWindow'))
})

it('executes openURL type button', async function () {
const testWindow = getTestWindow()
testWindow.onDidShowMessage((message) => {
// Simulate user clicking open URL type
message.selectItem('Proceed to Wiki')
})
const notification = getModalNotification()
await verifyOpenExternalUrl(notification)
})

it('executes openTxt type button', async function () {
const testWindow = getTestWindow()
testWindow.onDidShowMessage((message) => {
// Simulate user clicking open txt type
message.selectItem('Read More')
})
const notification = getModalNotification()
await verifyTxtNotification(notification)
})
})

// generate test notifications
function getToastURLTestNotification(): ToolkitNotification {
return {
id: 'test notification 1',
displayIf: {
extensionId: 'aws.toolkit.fake.extension',
},
uiRenderInstructions: {
content: {
[`en-US`]: {
title: 'test',
description: 'This is a url notification.',
toastPreview: 'test toast preview',
},
},
onRecieve: 'toast',
onClick: {
type: 'openUrl',
url: 'https://aws.amazon.com/visualstudiocode/',
},
},
}
}

function getTxtNotification(): ToolkitNotification {
return {
id: 'test notification 2',
displayIf: {
extensionId: 'aws.toolkit.fake.extension',
},
uiRenderInstructions: {
content: {
[`en-US`]: {
title: 'test',
description: 'This is a text document notification.',
},
},
onRecieve: 'toast',
onClick: {
type: 'openTextDocument',
},
},
}
}

function getModalNotification(): ToolkitNotification {
return {
id: 'test notification 3',
displayIf: {
extensionId: 'aws.toolkit.fake.extension',
},
uiRenderInstructions: {
content: {
[`en-US`]: {
title: 'test',
description: 'This is a modal notification.',
},
},
onRecieve: 'modal',
onClick: {
type: 'modal',
},
actions: [
{
type: 'updateAndReload',
displayText: {
'en-US': 'Update and Reload',
},
},
{
type: 'openUrl',
url: 'https://aws.amazon.com/visualstudiocode/',
displayText: {
'en-US': 'Proceed to Wiki',
},
},
{
type: 'openTxt',
displayText: {
'en-US': 'Read More',
},
},
],
},
}
}

0 comments on commit 8966edc

Please sign in to comment.