From e149eaa59b4e212e23813e0418105c4fdcddfcd7 Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Thu, 23 Nov 2023 10:56:09 +0100 Subject: [PATCH] test: test Arduino state update for extensions Signed-off-by: Akos Kitta --- .../contributions/update-arduino-state.ts | 5 +- .../browser/board-service-provider.test.ts | 3 +- .../src/test/browser/browser-test-bindings.ts | 23 +- .../test/browser/update-arduino-state.test.ts | 670 ++++++++++++++++++ .../src/test/common/common-test-bindings.ts | 17 +- .../src/test/node/node-test-bindings.ts | 2 +- arduino-ide-extension/src/test/utils.ts | 7 +- 7 files changed, 716 insertions(+), 11 deletions(-) create mode 100644 arduino-ide-extension/src/test/browser/update-arduino-state.test.ts diff --git a/arduino-ide-extension/src/browser/contributions/update-arduino-state.ts b/arduino-ide-extension/src/browser/contributions/update-arduino-state.ts index 7f4cd71f1..767fbbf8c 100644 --- a/arduino-ide-extension/src/browser/contributions/update-arduino-state.ts +++ b/arduino-ide-extension/src/browser/contributions/update-arduino-state.ts @@ -21,7 +21,10 @@ import { BoardsServiceProvider } from '../boards/boards-service-provider'; import { CurrentSketch } from '../sketches-service-client-impl'; import { SketchContribution } from './contribution'; -interface UpdateStateParams { +/** + * (non-API) exported for tests + */ +export interface UpdateStateParams { readonly key: keyof T; readonly value: T[keyof T]; } diff --git a/arduino-ide-extension/src/test/browser/board-service-provider.test.ts b/arduino-ide-extension/src/test/browser/board-service-provider.test.ts index 00d3eca5e..54d3aa8ba 100644 --- a/arduino-ide-extension/src/test/browser/board-service-provider.test.ts +++ b/arduino-ide-extension/src/test/browser/board-service-provider.test.ts @@ -39,6 +39,7 @@ import { uno, unoSerialPort, } from '../common/fixtures'; +import { bindBrowser } from './browser-test-bindings'; disableJSDOM(); @@ -390,7 +391,7 @@ describe('board-service-provider', () => { const container = new Container({ defaultScope: 'Singleton' }); container.load( new ContainerModule((bind, unbind, isBound, rebind) => { - bindCommon(bind); + bindBrowser(bind, unbind, isBound, rebind); bind(MessageService).toConstantValue({}); bind(BoardsService).toConstantValue({ getDetectedPorts() { diff --git a/arduino-ide-extension/src/test/browser/browser-test-bindings.ts b/arduino-ide-extension/src/test/browser/browser-test-bindings.ts index 9165765f7..7b950833b 100644 --- a/arduino-ide-extension/src/test/browser/browser-test-bindings.ts +++ b/arduino-ide-extension/src/test/browser/browser-test-bindings.ts @@ -1,8 +1,25 @@ +import { MockLogger } from '@theia/core/lib/common/test/mock-logger'; import { Container, ContainerModule } from '@theia/core/shared/inversify'; -import { bindCommon } from '../common/common-test-bindings'; +import { + Bind, + ConsoleLogger, + bindCommon, +} from '../common/common-test-bindings'; -export function createBaseContainer(): Container { +export function createBaseContainer(bind: Bind = bindBrowser): Container { const container = new Container({ defaultScope: 'Singleton' }); - container.load(new ContainerModule((bind) => bindCommon(bind))); + container.load(new ContainerModule(bind)); return container; } + +export const bindBrowser: Bind = function ( + ...args: Parameters +): ReturnType { + bindCommon(...args); + const [bind, , , rebind] = args; + // IDE2's test console logger does not support `Loggable` arg. + // Rebind logger to suppress `[Function (anonymous)]` messages in tests when the storage service is initialized without `window.localStorage`. + // https://github.com/eclipse-theia/theia/blob/04c8cf07843ea67402131132e033cdd54900c010/packages/core/src/browser/storage-service.ts#L60 + bind(MockLogger).toSelf().inSingletonScope(); + rebind(ConsoleLogger).toService(MockLogger); +}; diff --git a/arduino-ide-extension/src/test/browser/update-arduino-state.test.ts b/arduino-ide-extension/src/test/browser/update-arduino-state.test.ts new file mode 100644 index 000000000..c3ad66ce9 --- /dev/null +++ b/arduino-ide-extension/src/test/browser/update-arduino-state.test.ts @@ -0,0 +1,670 @@ +import { enableJSDOM } from '@theia/core/lib/browser/test/jsdom'; +const disableJSDOM = enableJSDOM(); + +import { FrontendApplicationConfigProvider } from '@theia/core/lib/browser/frontend-application-config-provider'; +FrontendApplicationConfigProvider.set({}); + +import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state'; +import { LabelProvider } from '@theia/core/lib/browser/label-provider'; +import { OpenerService } from '@theia/core/lib/browser/opener-service'; +import { + LocalStorageService, + StorageService, +} from '@theia/core/lib/browser/storage-service'; +import { WindowService } from '@theia/core/lib/browser/window/window-service'; +import { + Disposable, + DisposableCollection, +} from '@theia/core/lib/common/disposable'; +import { EnvVariablesServer } from '@theia/core/lib/common/env-variables'; +import { Emitter } from '@theia/core/lib/common/event'; +import { MessageService } from '@theia/core/lib/common/message-service'; +import { wait } from '@theia/core/lib/common/promise-util'; +import URI from '@theia/core/lib/common/uri'; +import { + Container, + ContainerModule, + injectable, +} from '@theia/core/shared/inversify'; +import { EditorManager } from '@theia/editor/lib/browser/editor-manager'; +import { FileService } from '@theia/filesystem/lib/browser/file-service'; +import { expect } from 'chai'; +import type { + BoardDetails as ApiBoardDetails, + CompileSummary as ApiCompileSummary, + Port as ApiPort, +} from 'vscode-arduino-api'; +import { URI as CodeURI } from 'vscode-uri'; +import { ArduinoPreferences } from '../../browser/arduino-preferences'; +import { BoardsDataStore } from '../../browser/boards/boards-data-store'; +import { BoardsServiceProvider } from '../../browser/boards/boards-service-provider'; +import { ConfigServiceClient } from '../../browser/config/config-service-client'; +import { CommandRegistry } from '../../browser/contributions/contribution'; +import { + UpdateArduinoState, + UpdateStateParams, +} from '../../browser/contributions/update-arduino-state'; +import { DialogService } from '../../browser/dialog-service'; +import { SettingsService } from '../../browser/dialogs/settings/settings'; +import { HostedPluginSupport } from '../../browser/hosted/hosted-plugin-support'; +import { NotificationCenter } from '../../browser/notification-center'; +import { + CurrentSketch, + SketchesServiceClientImpl, +} from '../../browser/sketches-service-client-impl'; +import { ApplicationConnectionStatusContribution } from '../../browser/theia/core/connection-status-service'; +import { OutputChannelManager } from '../../browser/theia/output/output-channel'; +import { WorkspaceService } from '../../browser/theia/workspace/workspace-service'; +import { MainMenuManager } from '../../common/main-menu-manager'; +import { + CompileSummary, + FileSystemExt, + SketchesService, +} from '../../common/protocol'; +import { + BoardDetails, + BoardsService, + Port, +} from '../../common/protocol/boards-service'; +import { NotificationServiceServer } from '../../common/protocol/notification-service'; +import { never } from '../utils'; +import { bindBrowser } from './browser-test-bindings'; + +disableJSDOM(); + +describe('update-arduino-state', function () { + this.slow(250); + + let toDisposeAfterEach: DisposableCollection; + let boardsServiceProvider: BoardsServiceProvider; + let notificationCenter: NotificationCenter; + let commandRegistry: CommandRegistry; + let updateArduinoState: UpdateArduinoState; + let stateUpdateParams: UpdateStateParams[]; + + let boardDetailsMocks: Record; + let dataStoreMocks: Record; + let currentSketchMock: CurrentSketch | undefined; + let sketchDirUriMock: URI | undefined; + let dataDirUriMock: URI | undefined; + let onCurrentSketchDidChangeEmitter: Emitter; + let onDataDirDidChangeEmitter: Emitter; + let onSketchDirDidChangeEmitter: Emitter; + let onDataStoreDidChangeEmitter: Emitter; + + beforeEach(async () => { + toDisposeAfterEach = new DisposableCollection(); + stateUpdateParams = []; + + // reset mocks + boardDetailsMocks = {}; + dataStoreMocks = {}; + currentSketchMock = undefined; + sketchDirUriMock = undefined; + dataDirUriMock = undefined; + onCurrentSketchDidChangeEmitter = new Emitter(); + onDataDirDidChangeEmitter = new Emitter(); + onSketchDirDidChangeEmitter = new Emitter(); + onDataStoreDidChangeEmitter = new Emitter(); + toDisposeAfterEach.pushAll([ + onCurrentSketchDidChangeEmitter, + onDataDirDidChangeEmitter, + onSketchDirDidChangeEmitter, + onDataStoreDidChangeEmitter, + ]); + + const container = createContainer(); + commandRegistry = container.get(CommandRegistry); + // This command is registered by vscode-arduino-api + commandRegistry.registerCommand( + { id: 'arduinoAPI.updateState' }, + { + execute: (params: UpdateStateParams) => stateUpdateParams.push(params), + } + ); + // This command is contributed by the vscode-arduino-tools VSIX + commandRegistry.registerCommand( + { id: 'arduino.languageserver.notifyBuildDidComplete' }, + { + execute: () => { + /* NOOP */ + }, + } + ); + container.get( + FrontendApplicationStateService + ).state = 'ready'; + boardsServiceProvider = container.get( + BoardsServiceProvider + ); + notificationCenter = container.get(NotificationCenter); + updateArduinoState = container.get(UpdateArduinoState); + toDisposeAfterEach.push( + Disposable.create(() => boardsServiceProvider.onStop()) + ); + boardsServiceProvider.onStart(); + await boardsServiceProvider.ready; + updateArduinoState.onStart(); + + await wait(50); + stateUpdateParams = []; + }); + + afterEach(() => { + toDisposeAfterEach.dispose(); + }); + + it('should automatically update the boards config (board+port) on ready', async () => { + const fqbn = 'a:b:c'; + const board = { fqbn, name: 'ABC' }; + const boardDetails = { + buildProperties: [], + configOptions: [], + debuggingSupported: false, + fqbn, + PID: '0', + VID: '0', + programmers: [], + requiredTools: [], + }; + boardDetailsMocks = { + 'a:b:c': boardDetails, + }; + const port = { address: 'COM1', protocol: 'serial' }; + boardsServiceProvider['_boardsConfig'] = { + selectedBoard: board, + selectedPort: port, + }; + boardsServiceProvider['_detectedPorts'] = { + [Port.keyOf(port)]: { + port: { + address: 'COM1', + addressLabel: 'COM1 Port', + protocol: 'serial', + protocolLabel: 'Serial', + }, + boards: [], + }, + }; + + updateArduinoState.onReady(); + await wait(50); + + const params = stateUpdateParams.filter( + (param) => + param.key === 'fqbn' || + param.key === 'boardDetails' || + param.key === 'port' + ); + expect(params).to.be.deep.equal([ + { key: 'fqbn', value: 'a:b:c' }, + { + key: 'boardDetails', + value: { + buildProperties: {}, + configOptions: [], + fqbn: 'a:b:c', + programmers: [], + toolsDependencies: [], + } as ApiBoardDetails, + }, + { + key: 'port', + value: { + address: 'COM1', + protocol: 'serial', + protocolLabel: 'Serial', + hardwareId: '', + label: 'COM1 Port', + properties: {}, + } as ApiPort, + }, + ]); + }); + + it('should automatically update the sketch path on ready', async () => { + const uri = 'file:///path/to/my_sketch'; + currentSketchMock = { + name: 'my_sketch', + uri, + mainFileUri: 'file:///path/to/my_sketch/my_sketch.ino', + additionalFileUris: [], + otherSketchFileUris: [], + rootFolderFileUris: [], + }; + + updateArduinoState.onReady(); + await wait(50); + + const params = stateUpdateParams.filter( + (param) => param.key === 'sketchPath' + ); + expect(params).to.be.deep.equal([ + { + key: 'sketchPath', + value: CodeURI.parse(uri).fsPath, + }, + ]); + }); + + it("should automatically update the 'directories.data' path on ready", async () => { + const uri = 'file:///path/to/data/dir'; + dataDirUriMock = new URI(uri); + + stateUpdateParams = []; + updateArduinoState.onReady(); + await wait(50); + + const params = stateUpdateParams.filter( + (param) => param.key === 'dataDirPath' + ); + expect(params).to.be.deep.equal([ + { + key: 'dataDirPath', + value: CodeURI.parse(uri).fsPath, + }, + ]); + }); + + it("should automatically update the 'directories.user' path on ready", async () => { + const uri = 'file:///path/to/sketchbook'; + sketchDirUriMock = new URI(uri); + + updateArduinoState.onReady(); + await wait(50); + + const params = stateUpdateParams.filter( + (param) => param.key === 'userDirPath' + ); + expect(params).to.be.deep.equal([ + { + key: 'userDirPath', + value: CodeURI.parse(uri).fsPath, + }, + ]); + }); + + it('should update the boards config (board only) when did change', async () => { + const fqbn = 'a:b:c'; + const board = { fqbn, name: 'ABC' }; + const boardDetails = { + buildProperties: [], + configOptions: [], + debuggingSupported: false, + fqbn, + PID: '0', + VID: '0', + programmers: [], + requiredTools: [], + }; + boardDetailsMocks = { + 'a:b:c': boardDetails, + }; + boardsServiceProvider.updateConfig(board); + await wait(50); + + const params = stateUpdateParams.filter( + (param) => + param.key === 'fqbn' || + param.key === 'boardDetails' || + param.key === 'port' + ); + expect(params).to.be.deep.equal([ + { key: 'fqbn', value: 'a:b:c' }, + { + key: 'boardDetails', + value: { + buildProperties: {}, + configOptions: [], + fqbn: 'a:b:c', + programmers: [], + toolsDependencies: [], + } as ApiBoardDetails, + }, + { key: 'port', value: undefined }, + ]); + }); + + it('should update the boards config (port only) when did change', async () => { + const port = { address: 'COM1', protocol: 'serial' }; + notificationCenter.notifyDetectedPortsDidChange({ + detectedPorts: { + [Port.keyOf(port)]: { + port: { + address: 'COM1', + addressLabel: 'COM1 Port', + protocol: 'serial', + protocolLabel: 'Serial', + }, + boards: [], + }, + }, + }); + boardsServiceProvider.updateConfig(port); + await wait(50); + + const params = stateUpdateParams.filter( + (param) => + param.key === 'fqbn' || + param.key === 'boardDetails' || + param.key === 'port' + ); + expect(params).to.be.deep.equal([ + { key: 'fqbn', value: undefined }, + { key: 'boardDetails', value: undefined }, + { + key: 'port', + value: { + address: 'COM1', + protocol: 'serial', + protocolLabel: 'Serial', + hardwareId: '', + label: 'COM1 Port', + properties: {}, + } as ApiPort, + }, + ]); + }); + + it('should update the boards config (board+port) when did change', async () => { + const fqbn = 'a:b:c'; + const board = { fqbn, name: 'ABC' }; + const boardDetails = { + buildProperties: [], + configOptions: [], + debuggingSupported: false, + fqbn, + PID: '0', + VID: '0', + programmers: [], + requiredTools: [], + }; + boardDetailsMocks = { + 'a:b:c': boardDetails, + }; + const port = { address: 'COM1', protocol: 'serial' }; + boardsServiceProvider.updateConfig({ + selectedBoard: board, + selectedPort: port, + }); + notificationCenter.notifyDetectedPortsDidChange({ + detectedPorts: { + [Port.keyOf(port)]: { + port: { + address: 'COM1', + addressLabel: 'COM1 Port', + protocol: 'serial', + protocolLabel: 'Serial', + }, + boards: [], + }, + }, + }); + await wait(50); + + const params = stateUpdateParams.filter( + (param) => + param.key === 'fqbn' || + param.key === 'boardDetails' || + param.key === 'port' + ); + expect(params).to.be.deep.equal([ + { key: 'fqbn', value: 'a:b:c' }, + { + key: 'boardDetails', + value: { + buildProperties: {}, + configOptions: [], + fqbn: 'a:b:c', + programmers: [], + toolsDependencies: [], + } as ApiBoardDetails, + }, + { + key: 'port', + value: { + address: 'COM1', + protocol: 'serial', + protocolLabel: 'Serial', + hardwareId: '', + label: 'COM1 Port', + properties: {}, + } as ApiPort, + }, + ]); + }); + + it('should update the compile summary after a verify', async () => { + const summary: CompileSummary = { + buildPath: '/path/to/build', + buildProperties: [], + executableSectionsSize: [], + usedLibraries: [], + boardPlatform: undefined, + buildPlatform: undefined, + buildOutputUri: 'file:///path/to/build', + }; + await commandRegistry.executeCommand( + 'arduino.languageserver.notifyBuildDidComplete', + summary + ); + await wait(50); + + const params = stateUpdateParams.filter( + (param) => param.key === 'compileSummary' + ); + expect(params).to.be.deep.equal([ + { + key: 'compileSummary', + value: { + buildPath: '/path/to/build', + buildProperties: {}, + executableSectionsSize: [], + usedLibraries: [], + boardPlatform: undefined, + buildPlatform: undefined, + } as ApiCompileSummary, + }, + ]); + }); + + it('should update the current sketch when did change', async () => { + const uri = 'file:///path/to/my_sketch'; + const sketch = { + name: 'my_sketch', + uri, + mainFileUri: 'file:///path/to/my_sketch/my_sketch.ino', + additionalFileUris: [], + otherSketchFileUris: [], + rootFolderFileUris: [], + }; + onCurrentSketchDidChangeEmitter.fire(sketch); + await wait(50); + + const params = stateUpdateParams.filter( + (param) => param.key === 'sketchPath' + ); + expect(params).to.be.deep.equal([ + { + key: 'sketchPath', + value: CodeURI.parse(uri).fsPath, + }, + ]); + }); + + it("should update the 'directories.data' when did change", async () => { + const uri = new URI('file:///path/to/data/dir'); + onDataDirDidChangeEmitter.fire(uri); + await wait(50); + + const params = stateUpdateParams.filter( + (param) => param.key === 'dataDirPath' + ); + expect(params).to.be.deep.equal([ + { + key: 'dataDirPath', + value: CodeURI.parse(uri.toString()).fsPath, + }, + ]); + }); + + it("should update the 'directories.user' when did change", async () => { + const uri = new URI('file:///path/to/sketchbook'); + onSketchDirDidChangeEmitter.fire(uri); + await wait(50); + + const params = stateUpdateParams.filter( + (param) => param.key === 'userDirPath' + ); + expect(params).to.be.deep.equal([ + { + key: 'userDirPath', + value: CodeURI.parse(uri.toString()).fsPath, + }, + ]); + }); + + it('should not update the board details when data store did change but the selected board does not match', async () => { + onDataStoreDidChangeEmitter.fire(['a:b:c']); + await wait(50); + + expect(stateUpdateParams).to.be.empty; + }); + + it('should update the board details when the data store did change and the selected board matches', async () => { + const fqbn = 'a:b:c'; + const board = { fqbn, name: 'ABC' }; + const boardDetails = { + buildProperties: [], + configOptions: [], + debuggingSupported: false, + fqbn, + PID: '0', + VID: '0', + programmers: [], + requiredTools: [], + }; + boardDetailsMocks = { + 'a:b:c': boardDetails, + }; + boardsServiceProvider['_boardsConfig'] = { + selectedBoard: board, + selectedPort: undefined, + }; + + onDataStoreDidChangeEmitter.fire(['a:b:c']); + await wait(50); + + const params = stateUpdateParams.filter( + (param) => + param.key === 'fqbn' || + param.key === 'boardDetails' || + param.key === 'port' + ); + expect(params).to.be.deep.equal([ + { + key: 'boardDetails', + value: { + buildProperties: {}, + configOptions: [], + fqbn: 'a:b:c', + programmers: [], + toolsDependencies: [], + } as ApiBoardDetails, + }, + ]); + }); + + function createContainer(): Container { + const container = new Container({ defaultScope: 'Singleton' }); + container.load( + new ContainerModule((bind, unbind, isBound, rebind) => { + bindBrowser(bind, unbind, isBound, rebind); + bind(MessageService).toConstantValue({}); + bind(BoardsService).toConstantValue({ + getDetectedPorts() { + return {}; + }, + async getBoardDetails({ fqbn }) { + return boardDetailsMocks[fqbn]; + }, + }); + bind(NotificationCenter).toSelf().inSingletonScope(); + bind(NotificationServiceServer).toConstantValue(< + NotificationServiceServer + >{ + // eslint-disable-next-line @typescript-eslint/no-unused-vars + setClient(_) { + // nothing + }, + }); + bind(FrontendApplicationStateService).toSelf().inSingletonScope(); + bind(BoardsDataStore).toConstantValue({ + async getData(fqbn) { + if (!fqbn) { + return BoardsDataStore.Data.EMPTY; + } + const data = dataStoreMocks[fqbn] ?? BoardsDataStore.Data.EMPTY; + return data; + }, + get onChanged() { + return onDataStoreDidChangeEmitter.event; + }, + }); + bind(LocalStorageService).toSelf().inSingletonScope(); + bind(WindowService).toConstantValue({}); + bind(StorageService).toService(LocalStorageService); + bind(BoardsServiceProvider).toSelf().inSingletonScope(); + bind(NoopHostedPluginSupport).toSelf().inSingletonScope(); + bind(HostedPluginSupport).toService(NoopHostedPluginSupport); + bind(UpdateArduinoState).toSelf().inSingletonScope(); + bind(FileService).toConstantValue({}); + bind(FileSystemExt).toConstantValue({}); + bind(ConfigServiceClient).toConstantValue({ + tryGetSketchDirUri() { + return sketchDirUriMock; + }, + tryGetDataDirUri() { + return dataDirUriMock; + }, + get onDidChangeSketchDirUri() { + return onSketchDirDidChangeEmitter.event; + }, + get onDidChangeDataDirUri() { + return onDataDirDidChangeEmitter.event; + }, + }); + bind(SketchesService).toConstantValue({}); + bind(OpenerService).toConstantValue({}); + bind(SketchesServiceClientImpl).toConstantValue(< + SketchesServiceClientImpl + >{ + tryGetCurrentSketch() { + return currentSketchMock; + }, + onCurrentSketchDidChange: onCurrentSketchDidChangeEmitter.event, + }); + bind(EditorManager).toConstantValue({}); + bind(OutputChannelManager).toConstantValue({}); + bind(EnvVariablesServer).toConstantValue({}); + bind(ApplicationConnectionStatusContribution).toConstantValue( + {} + ); + bind(WorkspaceService).toConstantValue({}); + bind(LabelProvider).toConstantValue({}); + bind(SettingsService).toConstantValue({}); + bind(ArduinoPreferences).toConstantValue({}); + bind(DialogService).toConstantValue({}); + bind(MainMenuManager).toConstantValue({}); + }) + ); + return container; + } +}); + +@injectable() +class NoopHostedPluginSupport implements HostedPluginSupport { + readonly didStart = Promise.resolve(); + readonly onDidCloseConnection = never(); + readonly onDidLoad = never(); +} diff --git a/arduino-ide-extension/src/test/common/common-test-bindings.ts b/arduino-ide-extension/src/test/common/common-test-bindings.ts index 1c1892dc2..f3e3f4373 100644 --- a/arduino-ide-extension/src/test/common/common-test-bindings.ts +++ b/arduino-ide-extension/src/test/common/common-test-bindings.ts @@ -9,14 +9,25 @@ import { LogLevel } from '@theia/core/lib/common/logger-protocol'; import { MockLogger } from '@theia/core/lib/common/test/mock-logger'; import { injectable, interfaces } from '@theia/core/shared/inversify'; -export function bindCommon(bind: interfaces.Bind): interfaces.Bind { +export interface Bind { + ( + bind: interfaces.Bind, + unbind: interfaces.Unbind, + isBound: interfaces.IsBound, + rebind: interfaces.Rebind + ): void; +} + +export const bindCommon: Bind = function ( + ...args: Parameters +): ReturnType { + const [bind] = args; bind(ConsoleLogger).toSelf().inSingletonScope(); bind(ILogger).toService(ConsoleLogger); bind(CommandRegistry).toSelf().inSingletonScope(); bind(CommandService).toService(CommandRegistry); bindContributionProvider(bind, CommandContribution); - return bind; -} +}; @injectable() export class ConsoleLogger extends MockLogger { diff --git a/arduino-ide-extension/src/test/node/node-test-bindings.ts b/arduino-ide-extension/src/test/node/node-test-bindings.ts index 2b4c651f7..29ff09f52 100644 --- a/arduino-ide-extension/src/test/node/node-test-bindings.ts +++ b/arduino-ide-extension/src/test/node/node-test-bindings.ts @@ -222,7 +222,7 @@ export async function createBaseContainer( } const container = new Container({ defaultScope: 'Singleton' }); const module = new ContainerModule((bind, unbind, isBound, rebind) => { - bindCommon(bind); + bindCommon(bind, unbind, isBound, rebind); bind(CoreClientProvider).toSelf().inSingletonScope(); bind(CoreServiceImpl).toSelf().inSingletonScope(); bind(CoreService).toService(CoreServiceImpl); diff --git a/arduino-ide-extension/src/test/utils.ts b/arduino-ide-extension/src/test/utils.ts index 799081227..148649126 100644 --- a/arduino-ide-extension/src/test/utils.ts +++ b/arduino-ide-extension/src/test/utils.ts @@ -1,3 +1,6 @@ -export function tick(): Promise { - return new Promise((res) => setTimeout(res, 1)); +import { Emitter, Event } from '@theia/core/lib/common/event'; + +const neverEmitter = new Emitter(); +export function never(): Event { + return neverEmitter.event as Event; }