Skip to content

Commit

Permalink
add API tests for typescript language
Browse files Browse the repository at this point in the history
Signed-off-by: Anton Kosyakov <anton.kosyakov@typefox.io>
  • Loading branch information
akosyakov committed Mar 9, 2020
1 parent 1669e59 commit 2d5a19d
Show file tree
Hide file tree
Showing 7 changed files with 223 additions and 41 deletions.
2 changes: 1 addition & 1 deletion dev-packages/application-manager/src/expose-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export = function (this: webpack.loader.LoaderContext, source: string, sourceMap
this.cacheable();
}

let modulePackage = modulePackages.find(({ dir }) => this.resourcePath.startsWith(dir));
let modulePackage = modulePackages.find(({ dir }) => this.resourcePath.startsWith(dir + '/'));
if (modulePackage) {
this.callback(undefined, exposeModule(modulePackage, this.resourcePath, source), sourceMap);
return;
Expand Down
22 changes: 11 additions & 11 deletions examples/api-tests/src/saveable.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ describe('Saveable', function () {
assert.isTrue(Saveable.isDirty(widget), `should be dirty before '${edit}' save`);
await Saveable.save(widget);
assert.isFalse(Saveable.isDirty(widget), `should NOT be dirty after '${edit}' save`);
assert.equal(editor.getControl().getValue(), edit, `model should be updated with '${edit}'`);
assert.equal(editor.getControl().getValue().trimRight(), edit, `model should be updated with '${edit}'`);
const state = await fileSystem.resolveContent(fileUri.toString());
assert.equal(state.content, edit, `fs should be updated with '${edit}'`);
assert.equal(state.content.trimRight(), edit, `fs should be updated with '${edit}'`);
}
});

Expand Down Expand Up @@ -129,7 +129,7 @@ describe('Saveable', function () {
assert.isTrue(outOfSync, 'file should be out of sync');
assert.equal(outOfSyncCount, 1, 'user should be prompted only once with out of sync dialog');
assert.isTrue(Saveable.isDirty(widget), 'should be dirty after rejected save');
assert.equal(editor.getControl().getValue(), longContent.substring(3), 'model should be updated');
assert.equal(editor.getControl().getValue().trimRight(), longContent.substring(3), 'model should be updated');
const state = await fileSystem.resolveContent(fileUri.toString());
assert.equal(state.content, 'baz', 'fs should NOT be updated');
});
Expand All @@ -151,7 +151,7 @@ describe('Saveable', function () {
await Saveable.save(widget);
assert.isTrue(outOfSync, 'file should be out of sync');
assert.isTrue(Saveable.isDirty(widget), 'should be dirty after rejected save');
assert.equal(editor.getControl().getValue(), 'bar', 'model should be updated');
assert.equal(editor.getControl().getValue().trimRight(), 'bar', 'model should be updated');
let state = await fileSystem.resolveContent(fileUri.toString());
assert.equal(state.content, 'baz', 'fs should NOT be updated');

Expand All @@ -164,9 +164,9 @@ describe('Saveable', function () {
await Saveable.save(widget);
assert.isTrue(outOfSync, 'file should be out of sync');
assert.isFalse(Saveable.isDirty(widget), 'should NOT be dirty after save');
assert.equal(editor.getControl().getValue(), 'bar', 'model should be updated');
assert.equal(editor.getControl().getValue().trimRight(), 'bar', 'model should be updated');
state = await fileSystem.resolveContent(fileUri.toString());
assert.equal(state.content, 'bar', 'fs should be updated');
assert.equal(state.content.trimRight(), 'bar', 'fs should be updated');
});

it('accept new save', async () => {
Expand All @@ -181,9 +181,9 @@ describe('Saveable', function () {
await Saveable.save(widget);
assert.isTrue(outOfSync, 'file should be out of sync');
assert.isFalse(Saveable.isDirty(widget), 'should NOT be dirty after save');
assert.equal(editor.getControl().getValue(), 'bar', 'model should be updated');
assert.equal(editor.getControl().getValue().trimRight(), 'bar', 'model should be updated');
const state = await fileSystem.resolveContent(fileUri.toString());
assert.equal(state.content, 'bar', 'fs should be updated');
assert.equal(state.content.trimRight(), 'bar', 'fs should be updated');
});

it('cancel save on close', async () => {
Expand Down Expand Up @@ -243,7 +243,7 @@ describe('Saveable', function () {
assert.isTrue(outOfSync, 'file should be out of sync');
assert.isTrue(widget.isDisposed, 'model should be disposed after close');
const state = await fileSystem.resolveContent(fileUri.toString());
assert.equal(state.content, 'bar', 'fs should be updated');
assert.equal(state.content.trimRight(), 'bar', 'fs should be updated');
});

it('normal close', async () => {
Expand All @@ -254,7 +254,7 @@ describe('Saveable', function () {
});
assert.isTrue(widget.isDisposed, 'model should be disposed after close');
const state = await fileSystem.resolveContent(fileUri.toString());
assert.equal(state.content, 'bar', 'fs should be updated');
assert.equal(state.content.trimRight(), 'bar', 'fs should be updated');
});

it('delete file for saved', async () => {
Expand Down Expand Up @@ -320,7 +320,7 @@ describe('Saveable', function () {
assert.isFalse(Saveable.isDirty(widget), 'should NOT be dirty after save');
assert.isTrue(editor.document.valid, 'should be valid after save');
const state = await fileSystem.resolveContent(fileUri.toString());
assert.equal(state.content, 'bar', 'fs should be updated');
assert.equal(state.content.trimRight(), 'bar', 'fs should be updated');
});

it('move file for saved', async function () {
Expand Down
156 changes: 156 additions & 0 deletions examples/api-tests/src/typescript.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
/********************************************************************************
* Copyright (C) 2020 TypeFox and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

// @ts-check
describe('TypeScript', function () {
this.timeout(15000);

const { assert } = chai;

const Uri = require('@theia/core/lib/common/uri');
const { BrowserMainMenuFactory } = require('@theia/core/lib/browser/menu/browser-menu-plugin');
const { EditorManager } = require('@theia/editor/lib/browser/editor-manager');
const { EditorWidget } = require('@theia/editor/lib/browser/editor-widget');
const { EDITOR_CONTEXT_MENU } = require('@theia/editor/lib/browser/editor-menu');
const { WorkspaceService } = require('@theia/workspace/lib/browser/workspace-service');
const { MonacoEditor } = require('@theia/monaco/lib/browser/monaco-editor');
const { HostedPluginSupport } = require('@theia/plugin-ext/lib/hosted/browser/hosted-plugin');
const { ContextKeyService } = require('@theia/core/lib/browser/context-key-service');
const { CommandRegistry } = require('@theia/core/lib/common/command');
const { OpenerService, open } = require('@theia/core/lib/browser/opener-service');
const { EditorPreviewWidget } = require('@theia/editor-preview/lib/browser/editor-preview-widget');

/** @type {import('inversify').Container} */
const container = window['theia'].container;
const editorManager = container.get(EditorManager);
const workspaceService = container.get(WorkspaceService);
const menuFactory = container.get(BrowserMainMenuFactory);
const pluginService = container.get(HostedPluginSupport);
const contextKeyService = container.get(ContextKeyService);
const commands = container.get(CommandRegistry);
const openerService = container.get(OpenerService);

const rootUri = new Uri.default(workspaceService.tryGetRoots()[0].uri);
const serverUri = rootUri.resolve('src-gen/backend/server.js');
const inversifyUri = rootUri.resolve('../../node_modules/inversify/dts/inversify.d.ts').normalizePath();

before(async function () {
await pluginService.load();
const plugin = pluginService.plugins.find(p => p.model.id === 'vscode.typescript-language-features');
await pluginService.activatePlugin(plugin.model.id);
});

beforeEach(async function () {
await editorManager.closeAll({ save: false });

})

/**
* @param {Uri.default} uri
* @param {boolean} preview
*/
async function openEditor(uri, preview = false) {
const widget = await open(openerService, uri, { mode: 'activate', preview });
const editorWidget = widget instanceof EditorPreviewWidget ? widget.editorWidget : widget instanceof EditorWidget ? widget : undefined;
const editor = MonacoEditor.get(editorWidget);
// wait till tsserver is running, see:
// https://github.com/microsoft/vscode/blob/93cbbc5cae50e9f5f5046343c751b6d010468200/extensions/typescript-language-features/src/extension.ts#L98-L103
await new Promise(resolve => {
if (contextKeyService.match('typescript.isManagedFile')) {
resolve();
return;
}
contextKeyService.onDidChange(() => {
if (contextKeyService.match('typescript.isManagedFile')) {
resolve();
}
});
});
return editor;
}

afterEach(async () => {
await editorManager.closeAll({ save: false });
});

it('document formating should be visible and enabled', async () => {
await openEditor(serverUri);
const menu = menuFactory.createContextMenu(EDITOR_CONTEXT_MENU);
const item = menu.items.find(i => i.command === 'editor.action.formatDocument');
assert.isDefined(item);
assert.isTrue(item.isVisible);
assert.isTrue(item.isEnabled);
});

describe('reveal definition', function () {
for (const preview of [false, true]) {
let from = 'an editor' + (preview ? ' preview' : '');
it('within ' + from, async function () {
const editor = await openEditor(serverUri, preview);
// con|tainer.load(backendApplicationModule);
editor.getControl().setPosition({ lineNumber: 12, column: 4 });
assert.equal(editor.getControl().getModel().getWordAtPosition(editor.getControl().getPosition()).word, 'container');

await commands.executeCommand('editor.action.revealDefinition');

const activeEditor = MonacoEditor.get(editorManager.activeEditor);
assert.equal(editorManager.activeEditor.parent instanceof EditorPreviewWidget, preview);
assert.equal(activeEditor.uri.toString(), serverUri.toString());
// const |container = new Container();
const { lineNumber, column } = activeEditor.getControl().getPosition();
assert.deepEqual({ lineNumber, column }, { lineNumber: 11, column: 7 });
assert.equal(activeEditor.getControl().getModel().getWordAtPosition({ lineNumber, column }).word, 'container');
});

it(`from ${from} to another editor`, async function () {
await editorManager.open(inversifyUri, { mode: 'open' });

const editor = await openEditor(serverUri, preview);
// const { Cont|ainer } = require('inversify');
editor.getControl().setPosition({ lineNumber: 5, column: 13 });
assert.equal(editor.getControl().getModel().getWordAtPosition(editor.getControl().getPosition()).word, 'Container');

await commands.executeCommand('editor.action.revealDefinition');

const activeEditor = MonacoEditor.getActive(editorManager);
assert.isFalse(editorManager.activeEditor.parent instanceof EditorPreviewWidget);
assert.equal(activeEditor.uri.toString(), inversifyUri.toString());
// export { |Container } from "./container/container";
const { lineNumber, column } = activeEditor.getControl().getPosition();
assert.deepEqual({ lineNumber, column }, { lineNumber: 3, column: 10 });
assert.equal(activeEditor.getControl().getModel().getWordAtPosition({ lineNumber, column }).word, 'Container');
});

it(`from ${from} to an editor preview`, async function () {
const editor = await openEditor(serverUri);
// const { Cont|ainer } = require('inversify');
editor.getControl().setPosition({ lineNumber: 5, column: 13 });
assert.equal(editor.getControl().getModel().getWordAtPosition(editor.getControl().getPosition()).word, 'Container');

await commands.executeCommand('editor.action.revealDefinition');

const activeEditor = MonacoEditor.getActive(editorManager);
assert.isTrue(editorManager.activeEditor.parent instanceof EditorPreviewWidget);
assert.equal(activeEditor.uri.toString(), inversifyUri.toString());
// export { |Container } from "./container/container";
const { lineNumber, column } = activeEditor.getControl().getPosition();
assert.deepEqual({ lineNumber, column }, { lineNumber: 3, column: 10 });
assert.equal(activeEditor.getControl().getModel().getWordAtPosition({ lineNumber, column }).word, 'Container');
});
}
});

});
2 changes: 1 addition & 1 deletion examples/browser/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
"watch": "yarn build --watch",
"start": "theia start --plugins=local-dir:../../plugins",
"start:debug": "yarn start --log-level=debug",
"test": "theia test . --test-spec=../api-tests/**/*.spec.js",
"test": "theia test . --plugins=local-dir:../../plugins --test-spec=../api-tests/**/*.spec.js",
"test:debug": "yarn test --test-inspect",
"coverage": "yarn test --test-coverage && yarn coverage:report",
"coverage:report": "nyc report --reporter=html",
Expand Down
2 changes: 2 additions & 0 deletions packages/plugin-ext/src/common/plugin-api-rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ export interface PluginManagerExt {
$updateStoragePath(path: string | undefined): Promise<void>;

$activateByEvent(event: string): Promise<void>;

$activatePlugin(id: string): Promise<void>;
}

export interface CommandRegistryMain {
Expand Down
8 changes: 8 additions & 0 deletions packages/plugin-ext/src/hosted/browser/hosted-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,14 @@ export class HostedPluginSupport {
}
}

async activatePlugin(id: string): Promise<void> {
const activation = [];
for (const manager of this.managers.values()) {
activation.push(manager.$activatePlugin(id));
}
await Promise.all(activation);
}

protected createMeasurement(name: string): () => number {
const startMarker = `${name}-start`;
const endMarker = `${name}-end`;
Expand Down
Loading

0 comments on commit 2d5a19d

Please sign in to comment.