Skip to content

Commit 31bbd79

Browse files
committed
test(notification): add integ tests with stubbed auth
Create a fake auth instance so we can simulate activating the notifications module with a "working" auth, to see how it behaves and displays notifications.
1 parent 87ea4d9 commit 31bbd79

File tree

14 files changed

+298
-18
lines changed

14 files changed

+298
-18
lines changed

packages/amazonq/.vscode/launch.json

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,51 @@
118118
"order": 3
119119
}
120120
},
121+
{
122+
"name": "Integration Tests",
123+
"type": "extensionHost",
124+
"request": "launch",
125+
"runtimeExecutable": "${execPath}",
126+
"args": [
127+
"--disable-extension=amazonwebservices.aws-toolkit-vscode",
128+
"${workspaceFolder}/../core/dist/src/testFixtures/workspaceFolder",
129+
"--extensionDevelopmentPath=${workspaceFolder}",
130+
"--extensionTestsPath=${workspaceFolder}/dist/test/integ/index.js"
131+
],
132+
"env": {
133+
"DEVELOPMENT_PATH": "${workspaceFolder}",
134+
"AWS_TOOLKIT_AUTOMATION": "local"
135+
},
136+
"outFiles": ["${workspaceFolder}/dist/**/*.js", "${workspaceFolder}/../core/dist/**/*.js"],
137+
"preLaunchTask": "watch",
138+
"presentation": {
139+
"group": "6_IntegrationTests",
140+
"order": 1
141+
}
142+
},
143+
{
144+
"name": "Integration Tests (current file)",
145+
"type": "extensionHost",
146+
"request": "launch",
147+
"runtimeExecutable": "${execPath}",
148+
"args": [
149+
"--disable-extension=amazonwebservices.aws-toolkit-vscode",
150+
"${workspaceFolder}/../core/dist/src/testFixtures/workspaceFolder",
151+
"--extensionDevelopmentPath=${workspaceFolder}",
152+
"--extensionTestsPath=${workspaceFolder}/dist/test/integ/index.js"
153+
],
154+
"env": {
155+
"TEST_FILE": "${relativeFile}",
156+
"DEVELOPMENT_PATH": "${workspaceFolder}",
157+
"AWS_TOOLKIT_AUTOMATION": "local"
158+
},
159+
"outFiles": ["${workspaceFolder}/dist/**/*.js", "${workspaceFolder}/../core/dist/**/*.js"],
160+
"preLaunchTask": "watch",
161+
"presentation": {
162+
"group": "5_IntegrationTestsCurrentFile",
163+
"order": 1
164+
}
165+
},
121166
{
122167
"name": "E2E Test (current file)",
123168
"type": "extensionHost",

packages/amazonq/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
"watch": "npm run clean && npm run buildScripts && tsc -watch -p ./",
5959
"testCompile": "npm run clean && npm run buildScripts && npm run compileOnly",
6060
"test": "npm run testCompile && c8 --allowExternal ts-node ../core/scripts/test/launchTest.ts unit dist/test/unit/index.js ../core/dist/src/testFixtures/workspaceFolder",
61+
"testInteg": "npm run testCompile && c8 --allowExternal ts-node ../core/scripts/test/launchTest.ts integration dist/test/integ/index.js ../core/dist/src/testFixtures/workspaceFolder",
6162
"testE2E": "npm run testCompile && c8 --allowExternal ts-node ../core/scripts/test/launchTest.ts e2e dist/test/e2e/index.js ../core/dist/src/testFixtures/workspaceFolder",
6263
"testWeb": "npm run compileDev && c8 --allowExternal ts-node ../core/scripts/test/launchTest.ts web dist/test/web/testRunnerWebCore.js",
6364
"webRun": "npx @vscode/test-web --open-devtools --browserOption=--disable-web-security --waitForDebugger=9222 --extensionDevelopmentPath=. .",

packages/amazonq/src/extensionNode.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { Auth, AuthUtils, getTelemetryMetadataForConn, isAnySsoConnection } from
1818
import api from './api'
1919
import { activate as activateCWChat } from './app/chat/activation'
2020
import { beta } from 'aws-core-vscode/dev'
21-
import { activate as activateNotifications } from 'aws-core-vscode/notifications'
21+
import { activate as activateNotifications, deactivate as deactivateNotifications } from 'aws-core-vscode/notifications'
2222
import { AuthState, AuthUtil } from 'aws-core-vscode/codewhisperer'
2323
import { telemetry, AuthUserState } from 'aws-core-vscode/telemetry'
2424

@@ -78,7 +78,7 @@ async function activateAmazonQNode(context: vscode.ExtensionContext) {
7878
await activateNotifications(context, authState, getAuthState)
7979
}
8080

81-
async function getAuthState(): Promise<Omit<AuthUserState, 'source'>> {
81+
export async function getAuthState(): Promise<Omit<AuthUserState, 'source'>> {
8282
let authState: AuthState = 'disconnected'
8383
try {
8484
// May call connection validate functions that try to refresh the token.
@@ -147,4 +147,5 @@ async function setupDevMode(context: vscode.ExtensionContext) {
147147
export async function deactivate() {
148148
// Run concurrently to speed up execution. stop() does not throw so it is safe
149149
await Promise.all([(await CrashMonitoring.instance())?.shutdown(), deactivateCommon()])
150+
deactivateNotifications()
150151
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import { runTests } from 'aws-core-vscode/test'
7+
import { VSCODE_EXTENSION_ID } from 'aws-core-vscode/utils'
8+
9+
export function run(): Promise<void> {
10+
return runTests(process.env.TEST_DIR ?? 'test/integ', VSCODE_EXTENSION_ID.amazonq, [
11+
'../../core/dist/src/testInteg/globalSetup.test.ts',
12+
])
13+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0 fort
4+
*/
5+
6+
import { getNotificationsSuite } from 'aws-core-vscode/test'
7+
import { getAuthState } from '../../../src/extensionNode'
8+
9+
getNotificationsSuite(getAuthState)

packages/core/src/extensionNode.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ import * as beta from './dev/beta'
3939
import { activate as activateApplicationComposer } from './applicationcomposer/activation'
4040
import { activate as activateRedshift } from './awsService/redshift/activation'
4141
import { activate as activateIamPolicyChecks } from './awsService/accessanalyzer/activation'
42-
import { activate as activateNotifications } from './notifications/activation'
42+
import { activate as activateNotifications, deactivate as deactivateNotifications } from './notifications/activation'
4343
import { SchemaService } from './shared/schemas'
4444
import { AwsResourceManager } from './dynamicResources/awsResourceManager'
4545
import globals from './shared/extensionGlobals'
@@ -270,6 +270,7 @@ export async function deactivate() {
270270
// Run concurrently to speed up execution. stop() does not throw so it is safe
271271
await Promise.all([await (await CrashMonitoring.instance())?.shutdown(), deactivateCommon(), deactivateEc2()])
272272
await globals.resourceManager.dispose()
273+
deactivateNotifications()
273274
}
274275

275276
async function handleAmazonQInstall() {
@@ -338,7 +339,7 @@ function recordToolkitInitialization(activationStartedOn: number, settingsValid:
338339
}
339340
}
340341

341-
async function getAuthState(): Promise<Omit<AuthUserState, 'source'>> {
342+
export async function getAuthState(): Promise<Omit<AuthUserState, 'source'>> {
342343
let authStatus: AuthStatus = 'notConnected'
343344
const enabledConnections: Set<AuthFormId> = new Set()
344345
const enabledScopes: Set<string> = new Set()

packages/core/src/notifications/activation.ts

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,23 @@
55

66
import * as vscode from 'vscode'
77
import { DevSettings } from '../shared/settings'
8-
import { NotificationsController } from './controller'
8+
import { NotificationsController, ControllerOptions, RemoteFetcher } from './controller'
99
import { NotificationsNode } from './panelNode'
1010
import { RuleEngine, getRuleContext } from './rules'
1111
import globals from '../shared/extensionGlobals'
1212
import { AuthState } from './types'
1313
import { getLogger } from '../shared/logger/logger'
1414
import { oneMinute } from '../shared/datetime'
15+
import { globalKey } from '../shared/globalState'
1516

1617
/** Time in MS to poll for emergency notifications */
1718
const emergencyPollTime = oneMinute * 10
1819

20+
/** Key in global state to store notification data */
21+
const storageKey: globalKey = 'aws.notifications'
22+
23+
let interval: NodeJS.Timer
24+
1925
/**
2026
* Activate the in-IDE notifications module and begin receiving notifications.
2127
*
@@ -26,7 +32,8 @@ const emergencyPollTime = oneMinute * 10
2632
export async function activate(
2733
context: vscode.ExtensionContext,
2834
initialState: AuthState,
29-
authStateFn: () => Promise<AuthState>
35+
authStateFn: () => Promise<AuthState>,
36+
options?: Partial<Omit<ControllerOptions, 'node'>>
3037
) {
3138
// TODO: Currently gated behind feature-flag.
3239
if (!DevSettings.instance.get('notifications', false)) {
@@ -36,16 +43,29 @@ export async function activate(
3643
const panelNode = NotificationsNode.instance
3744
panelNode.registerView(context)
3845

39-
const controller = new NotificationsController(panelNode)
46+
const controller = new NotificationsController({
47+
node: panelNode,
48+
fetcher: options?.fetcher ?? new RemoteFetcher(),
49+
storageKey: options?.storageKey ?? storageKey,
50+
})
4051
const engine = new RuleEngine(await getRuleContext(context, initialState))
4152

4253
await controller.pollForStartUp(engine)
4354
await controller.pollForEmergencies(engine)
4455

45-
globals.clock.setInterval(async () => {
56+
if (interval !== undefined) {
57+
globals.clock.clearInterval(interval)
58+
}
59+
60+
interval = globals.clock.setInterval(async () => {
4661
const ruleContext = await getRuleContext(context, await authStateFn())
4762
await controller.pollForEmergencies(new RuleEngine(ruleContext))
4863
}, emergencyPollTime)
4964

5065
getLogger('notifications').debug('Activated in-IDE notifications polling module')
5166
}
67+
68+
export function deactivate() {
69+
globals.clock.clearInterval(interval)
70+
getLogger('notifications').debug('Deactivated in-IDE notifications polling module')
71+
}

packages/core/src/notifications/controller.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ import { FileResourceFetcher } from '../shared/resourcefetcher/fileResourceFetch
2626
import { isAmazonQ } from '../shared/extensionUtilities'
2727
import { telemetry } from '../shared/telemetry/telemetry'
2828

29+
export type ControllerOptions = {
30+
node: NotificationsNode
31+
storageKey: globalKey
32+
fetcher: NotificationFetcher
33+
}
34+
2935
/**
3036
* Handles fetching and maintaining the state of in-IDE notifications.
3137
* Notifications are constantly polled from a known endpoint and then stored in global state.
@@ -39,24 +45,25 @@ import { telemetry } from '../shared/telemetry/telemetry'
3945
* Emergency notifications - fetched at a regular interval.
4046
*/
4147
export class NotificationsController {
42-
public static readonly suggestedPollIntervalMs = 1000 * 60 * 10 // 10 minutes
48+
public readonly storageKey: globalKey
4349

4450
/** Internal memory state that is written to global state upon modification. */
4551
private readonly state: NotificationsState
52+
private readonly notificationsNode: NotificationsNode
53+
private readonly fetcher: NotificationFetcher
4654

4755
static #instance: NotificationsController | undefined
4856

49-
constructor(
50-
private readonly notificationsNode: NotificationsNode,
51-
private readonly fetcher: NotificationFetcher = new RemoteFetcher(),
52-
public readonly storageKey: globalKey = 'aws.notifications'
53-
) {
57+
constructor(options: ControllerOptions) {
5458
if (!NotificationsController.#instance) {
5559
// Register on first creation only.
5660
registerDismissCommand()
5761
}
5862
NotificationsController.#instance = this
5963

64+
this.notificationsNode = options.node
65+
this.storageKey = options.storageKey
66+
this.fetcher = options.fetcher
6067
this.state = this.getDefaultState()
6168
}
6269

packages/core/src/notifications/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6-
export { activate } from './activation'
6+
export { activate, deactivate } from './activation'

packages/core/src/test/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export { getTestLogger } from './globalSetup.test'
1919
export { testCommand } from './shared/vscode/testUtils'
2020
export { FakeAwsContext } from './utilities/fakeAwsContext'
2121
export { getTestWorkspaceFolder } from '../testInteg/integrationTestsUtilities'
22+
export { getNotificationsSuite } from '../testInteg/notifications/suite'
2223
export * from './codewhisperer/testUtil'
2324
export * from './credentials/testUtil'
2425
export * from './testUtil'

0 commit comments

Comments
 (0)