mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-07-14 23:06:34 +00:00
test: test Arduino state update for extensions
Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
This commit is contained in:
parent
5abdc18fcc
commit
42bf1a0e99
@ -21,7 +21,10 @@ import { BoardsServiceProvider } from '../boards/boards-service-provider';
|
|||||||
import { CurrentSketch } from '../sketches-service-client-impl';
|
import { CurrentSketch } from '../sketches-service-client-impl';
|
||||||
import { SketchContribution } from './contribution';
|
import { SketchContribution } from './contribution';
|
||||||
|
|
||||||
interface UpdateStateParams<T extends ArduinoState> {
|
/**
|
||||||
|
* (non-API) exported for tests
|
||||||
|
*/
|
||||||
|
export interface UpdateStateParams<T extends ArduinoState = ArduinoState> {
|
||||||
readonly key: keyof T;
|
readonly key: keyof T;
|
||||||
readonly value: T[keyof T];
|
readonly value: T[keyof T];
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,7 @@ import {
|
|||||||
uno,
|
uno,
|
||||||
unoSerialPort,
|
unoSerialPort,
|
||||||
} from '../common/fixtures';
|
} from '../common/fixtures';
|
||||||
|
import { bindBrowser } from './browser-test-bindings';
|
||||||
|
|
||||||
disableJSDOM();
|
disableJSDOM();
|
||||||
|
|
||||||
@ -390,7 +391,7 @@ describe('board-service-provider', () => {
|
|||||||
const container = new Container({ defaultScope: 'Singleton' });
|
const container = new Container({ defaultScope: 'Singleton' });
|
||||||
container.load(
|
container.load(
|
||||||
new ContainerModule((bind, unbind, isBound, rebind) => {
|
new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||||
bindCommon(bind);
|
bindBrowser(bind, unbind, isBound, rebind);
|
||||||
bind(MessageService).toConstantValue(<MessageService>{});
|
bind(MessageService).toConstantValue(<MessageService>{});
|
||||||
bind(BoardsService).toConstantValue(<BoardsService>{
|
bind(BoardsService).toConstantValue(<BoardsService>{
|
||||||
getDetectedPorts() {
|
getDetectedPorts() {
|
||||||
|
@ -1,8 +1,25 @@
|
|||||||
|
import { MockLogger } from '@theia/core/lib/common/test/mock-logger';
|
||||||
import { Container, ContainerModule } from '@theia/core/shared/inversify';
|
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' });
|
const container = new Container({ defaultScope: 'Singleton' });
|
||||||
container.load(new ContainerModule((bind) => bindCommon(bind)));
|
container.load(new ContainerModule(bind));
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const bindBrowser: Bind = function (
|
||||||
|
...args: Parameters<Bind>
|
||||||
|
): ReturnType<Bind> {
|
||||||
|
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);
|
||||||
|
};
|
||||||
|
@ -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<string, BoardDetails>;
|
||||||
|
let dataStoreMocks: Record<string, BoardsDataStore.Data>;
|
||||||
|
let currentSketchMock: CurrentSketch | undefined;
|
||||||
|
let sketchDirUriMock: URI | undefined;
|
||||||
|
let dataDirUriMock: URI | undefined;
|
||||||
|
let onCurrentSketchDidChangeEmitter: Emitter<CurrentSketch>;
|
||||||
|
let onDataDirDidChangeEmitter: Emitter<URI | undefined>;
|
||||||
|
let onSketchDirDidChangeEmitter: Emitter<URI | undefined>;
|
||||||
|
let onDataStoreDidChangeEmitter: Emitter<string[]>;
|
||||||
|
|
||||||
|
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>(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>(
|
||||||
|
FrontendApplicationStateService
|
||||||
|
).state = 'ready';
|
||||||
|
boardsServiceProvider = container.get<BoardsServiceProvider>(
|
||||||
|
BoardsServiceProvider
|
||||||
|
);
|
||||||
|
notificationCenter = container.get<NotificationCenter>(NotificationCenter);
|
||||||
|
updateArduinoState = container.get<UpdateArduinoState>(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(<MessageService>{});
|
||||||
|
bind(BoardsService).toConstantValue(<BoardsService>{
|
||||||
|
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(<BoardsDataStore>{
|
||||||
|
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(<WindowService>{});
|
||||||
|
bind(StorageService).toService(LocalStorageService);
|
||||||
|
bind(BoardsServiceProvider).toSelf().inSingletonScope();
|
||||||
|
bind(NoopHostedPluginSupport).toSelf().inSingletonScope();
|
||||||
|
bind(HostedPluginSupport).toService(NoopHostedPluginSupport);
|
||||||
|
bind(UpdateArduinoState).toSelf().inSingletonScope();
|
||||||
|
bind(FileService).toConstantValue(<FileService>{});
|
||||||
|
bind(FileSystemExt).toConstantValue(<FileSystemExt>{});
|
||||||
|
bind(ConfigServiceClient).toConstantValue(<ConfigServiceClient>{
|
||||||
|
tryGetSketchDirUri() {
|
||||||
|
return sketchDirUriMock;
|
||||||
|
},
|
||||||
|
tryGetDataDirUri() {
|
||||||
|
return dataDirUriMock;
|
||||||
|
},
|
||||||
|
get onDidChangeSketchDirUri() {
|
||||||
|
return onSketchDirDidChangeEmitter.event;
|
||||||
|
},
|
||||||
|
get onDidChangeDataDirUri() {
|
||||||
|
return onDataDirDidChangeEmitter.event;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
bind(SketchesService).toConstantValue(<SketchesService>{});
|
||||||
|
bind(OpenerService).toConstantValue(<OpenerService>{});
|
||||||
|
bind(SketchesServiceClientImpl).toConstantValue(<
|
||||||
|
SketchesServiceClientImpl
|
||||||
|
>{
|
||||||
|
tryGetCurrentSketch() {
|
||||||
|
return currentSketchMock;
|
||||||
|
},
|
||||||
|
onCurrentSketchDidChange: onCurrentSketchDidChangeEmitter.event,
|
||||||
|
});
|
||||||
|
bind(EditorManager).toConstantValue(<EditorManager>{});
|
||||||
|
bind(OutputChannelManager).toConstantValue(<OutputChannelManager>{});
|
||||||
|
bind(EnvVariablesServer).toConstantValue(<EnvVariablesServer>{});
|
||||||
|
bind(ApplicationConnectionStatusContribution).toConstantValue(
|
||||||
|
<ApplicationConnectionStatusContribution>{}
|
||||||
|
);
|
||||||
|
bind(WorkspaceService).toConstantValue(<WorkspaceService>{});
|
||||||
|
bind(LabelProvider).toConstantValue(<LabelProvider>{});
|
||||||
|
bind(SettingsService).toConstantValue(<SettingsService>{});
|
||||||
|
bind(ArduinoPreferences).toConstantValue(<ArduinoPreferences>{});
|
||||||
|
bind(DialogService).toConstantValue(<DialogService>{});
|
||||||
|
bind(MainMenuManager).toConstantValue(<MainMenuManager>{});
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
@injectable()
|
||||||
|
class NoopHostedPluginSupport implements HostedPluginSupport {
|
||||||
|
readonly didStart = Promise.resolve();
|
||||||
|
readonly onDidCloseConnection = never();
|
||||||
|
readonly onDidLoad = never();
|
||||||
|
}
|
@ -9,14 +9,25 @@ import { LogLevel } from '@theia/core/lib/common/logger-protocol';
|
|||||||
import { MockLogger } from '@theia/core/lib/common/test/mock-logger';
|
import { MockLogger } from '@theia/core/lib/common/test/mock-logger';
|
||||||
import { injectable, interfaces } from '@theia/core/shared/inversify';
|
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<Bind>
|
||||||
|
): ReturnType<Bind> {
|
||||||
|
const [bind] = args;
|
||||||
bind(ConsoleLogger).toSelf().inSingletonScope();
|
bind(ConsoleLogger).toSelf().inSingletonScope();
|
||||||
bind(ILogger).toService(ConsoleLogger);
|
bind(ILogger).toService(ConsoleLogger);
|
||||||
bind(CommandRegistry).toSelf().inSingletonScope();
|
bind(CommandRegistry).toSelf().inSingletonScope();
|
||||||
bind(CommandService).toService(CommandRegistry);
|
bind(CommandService).toService(CommandRegistry);
|
||||||
bindContributionProvider(bind, CommandContribution);
|
bindContributionProvider(bind, CommandContribution);
|
||||||
return bind;
|
};
|
||||||
}
|
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class ConsoleLogger extends MockLogger {
|
export class ConsoleLogger extends MockLogger {
|
||||||
|
@ -222,7 +222,7 @@ export async function createBaseContainer(
|
|||||||
}
|
}
|
||||||
const container = new Container({ defaultScope: 'Singleton' });
|
const container = new Container({ defaultScope: 'Singleton' });
|
||||||
const module = new ContainerModule((bind, unbind, isBound, rebind) => {
|
const module = new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||||
bindCommon(bind);
|
bindCommon(bind, unbind, isBound, rebind);
|
||||||
bind(CoreClientProvider).toSelf().inSingletonScope();
|
bind(CoreClientProvider).toSelf().inSingletonScope();
|
||||||
bind(CoreServiceImpl).toSelf().inSingletonScope();
|
bind(CoreServiceImpl).toSelf().inSingletonScope();
|
||||||
bind(CoreService).toService(CoreServiceImpl);
|
bind(CoreService).toService(CoreServiceImpl);
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
export function tick(): Promise<void> {
|
import { Emitter, Event } from '@theia/core/lib/common/event';
|
||||||
return new Promise((res) => setTimeout(res, 1));
|
|
||||||
|
const neverEmitter = new Emitter<unknown>();
|
||||||
|
export function never<T = void>(): Event<T> {
|
||||||
|
return neverEmitter.event as Event<T>;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user