fix: make hosted plugin support testable

Hide the concrete implementation behind an interface so that tests can
`require` it.

Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
This commit is contained in:
Akos Kitta 2023-11-23 10:22:33 +01:00 committed by Akos Kitta
parent 633346a3b0
commit 5abdc18fcc
9 changed files with 49 additions and 20 deletions

View File

@ -271,8 +271,8 @@ import { MonitorModel } from './monitor-model';
import { MonitorManagerProxyClientImpl } from './monitor-manager-proxy-client-impl';
import { EditorManager as TheiaEditorManager } from '@theia/editor/lib/browser/editor-manager';
import { EditorManager } from './theia/editor/editor-manager';
import { HostedPluginEvents } from './hosted-plugin-events';
import { HostedPluginSupport } from './theia/plugin-ext/hosted-plugin';
import { HostedPluginEvents } from './hosted/hosted-plugin-events';
import { HostedPluginSupportImpl } from './theia/plugin-ext/hosted-plugin';
import { HostedPluginSupport as TheiaHostedPluginSupport } from '@theia/plugin-ext/lib/hosted/browser/hosted-plugin';
import { Formatter, FormatterPath } from '../common/protocol/formatter';
import { Format } from './contributions/format';
@ -985,8 +985,9 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
})
.inSingletonScope();
bind(HostedPluginSupport).toSelf().inSingletonScope();
rebind(TheiaHostedPluginSupport).toService(HostedPluginSupport);
bind(HostedPluginSupportImpl).toSelf().inSingletonScope();
bind(HostedPluginSupport).toService(HostedPluginSupportImpl);
rebind(TheiaHostedPluginSupport).toService(HostedPluginSupportImpl);
bind(HostedPluginEvents).toSelf().inSingletonScope();
bind(FrontendApplicationContribution).toService(HostedPluginEvents);

View File

@ -1,8 +1,4 @@
import { inject, injectable } from '@theia/core/shared/inversify';
import { Event, Emitter } from '@theia/core/lib/common/event';
import { HostedPluginSupport } from '@theia/plugin-ext/lib/hosted/browser/hosted-plugin';
import { ArduinoToolbar } from '../toolbar/arduino-toolbar';
import { NotificationCenter } from '../notification-center';
import {
Board,
BoardIdentifier,
@ -12,6 +8,11 @@ import {
Sketch,
} from '../../common/protocol';
import { BoardsServiceProvider } from '../boards/boards-service-provider';
import { HostedPluginSupport } from '../hosted/hosted-plugin-support';
import { ArduinoMenus } from '../menu/arduino-menus';
import { NotificationCenter } from '../notification-center';
import { CurrentSketch } from '../sketches-service-client-impl';
import { ArduinoToolbar } from '../toolbar/arduino-toolbar';
import {
URI,
Command,
@ -97,6 +98,22 @@ export class Debug extends SketchContribution {
});
this.notificationCenter.onPlatformDidInstall(() => this.refreshState());
this.notificationCenter.onPlatformDidUninstall(() => this.refreshState());
this.boardsDataStore.onDidChange((event) => {
const selectedFqbn =
this.boardsServiceProvider.boardsConfig.selectedBoard?.fqbn;
if (event.changes.find((change) => change.fqbn === selectedFqbn)) {
this.refreshState();
}
});
this.commandService.onDidExecuteCommand((event) => {
const { commandId, args } = event;
if (
commandId === 'arduino.languageserver.notifyBuildDidComplete' &&
isCompileSummary(args[0])
) {
this.refreshState();
}
});
}
override onReady(): void {

View File

@ -15,7 +15,7 @@ import {
} from '../../common/protocol';
import { CurrentSketch } from '../sketches-service-client-impl';
import { BoardsServiceProvider } from '../boards/boards-service-provider';
import { HostedPluginEvents } from '../hosted-plugin-events';
import { HostedPluginEvents } from '../hosted/hosted-plugin-events';
import { NotificationCenter } from '../notification-center';
import { SketchContribution, URI } from './contribution';
import { BoardsDataStore } from '../boards/boards-data-store';

View File

@ -1,7 +1,7 @@
import { DisposableCollection } from '@theia/core/lib/common/disposable';
import URI from '@theia/core/lib/common/uri';
import { inject, injectable } from '@theia/core/shared/inversify';
import { HostedPluginSupport } from '@theia/plugin-ext/lib/hosted/browser/hosted-plugin';
import { HostedPluginSupport } from '../hosted/hosted-plugin-support';
import type { ArduinoState } from 'vscode-arduino-api';
import {
BoardsService,

View File

@ -1,7 +1,7 @@
import { DisposableCollection, Emitter, Event } from '@theia/core';
import { FrontendApplicationContribution } from '@theia/core/lib/browser';
import { inject, injectable } from '@theia/core/shared/inversify';
import { HostedPluginSupport } from './theia/plugin-ext/hosted-plugin';
import { HostedPluginSupport } from './hosted-plugin-support';
/**
* Frontend contribution to watch VS Code extension start/stop events from Theia.

View File

@ -0,0 +1,14 @@
import type { Event } from '@theia/core/lib/common/event';
/*
This implementation hides the default HostedPluginSupport implementation from Theia to be able to test it.
Otherwise, the default implementation fails at require time due to the `import.meta` in the Theia plugin worker code.
https://github.com/eclipse-theia/theia/blob/964f69ca3b3a5fb87ffa0177fb300b74ba0ca39f/packages/plugin-ext/src/hosted/browser/plugin-worker.ts#L30-L32
*/
export const HostedPluginSupport = Symbol('HostedPluginSupport');
export interface HostedPluginSupport {
readonly didStart: Promise<void>;
readonly onDidLoad: Event<void>;
readonly onDidCloseConnection: Event<void>;
}

View File

@ -20,7 +20,7 @@ import {
} from '@theia/monaco/lib/browser/monaco-theming-service';
import { MonacoThemeRegistry as TheiaMonacoThemeRegistry } from '@theia/monaco/lib/browser/textmate/monaco-theme-registry';
import type { ThemeMix } from '@theia/monaco/lib/browser/textmate/monaco-theme-types';
import { HostedPluginSupport } from '@theia/plugin-ext/lib/hosted/browser/hosted-plugin';
import { HostedPluginSupport } from '../../hosted/hosted-plugin-support';
import { ArduinoThemes, compatibleBuiltInTheme } from '../core/theming';
import { WindowServiceExt } from '../core/window-service-ext';

View File

@ -5,9 +5,13 @@ import {
PluginContributions,
HostedPluginSupport as TheiaHostedPluginSupport,
} from '@theia/plugin-ext/lib/hosted/browser/hosted-plugin';
import { HostedPluginSupport } from '../../hosted/hosted-plugin-support';
@injectable()
export class HostedPluginSupport extends TheiaHostedPluginSupport {
export class HostedPluginSupportImpl
extends TheiaHostedPluginSupport
implements HostedPluginSupport
{
private readonly onDidLoadEmitter = new Emitter<void>();
private readonly onDidCloseConnectionEmitter = new Emitter<void>();

View File

@ -15,7 +15,6 @@ import {
DisposableCollection,
} from '@theia/core/lib/common/disposable';
import { MessageService } from '@theia/core/lib/common/message-service';
import { MockLogger } from '@theia/core/lib/common/test/mock-logger';
import { Container, ContainerModule } from '@theia/core/shared/inversify';
import { expect } from 'chai';
import { BoardsDataStore } from '../../browser/boards/boards-data-store';
@ -31,7 +30,6 @@ import {
PortIdentifierChangeEvent,
} from '../../common/protocol/boards-service';
import { NotificationServiceServer } from '../../common/protocol/notification-service';
import { bindCommon, ConsoleLogger } from '../common/common-test-bindings';
import {
detectedPort,
esp32S3DevModule,
@ -414,11 +412,6 @@ describe('board-service-provider', () => {
bind(WindowService).toConstantValue(<WindowService>{});
bind(StorageService).toService(LocalStorageService);
bind(BoardsServiceProvider).toSelf().inSingletonScope();
// 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);
})
);
return container;