diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml
index 7b6eed9..e97fe5c 100644
--- a/.github/workflows/ci-cd.yml
+++ b/.github/workflows/ci-cd.yml
@@ -7,6 +7,8 @@ on:
pull_request:
branches:
- master
+ schedule:
+ - cron: '0 23 * * *'
jobs:
build:
@@ -35,3 +37,7 @@ jobs:
- name: Test
shell: bash
run: yarn test
+
+ - name: Generate and Build Templates
+ shell: bash
+ run: ./.github/workflows/generate-and-build-all-templates.sh
diff --git a/.github/workflows/generate-and-build-all-templates.sh b/.github/workflows/generate-and-build-all-templates.sh
new file mode 100755
index 0000000..858ce8b
--- /dev/null
+++ b/.github/workflows/generate-and-build-all-templates.sh
@@ -0,0 +1,14 @@
+npm install -g yo
+npm link
+mkdir tmp
+cd tmp
+exit_code=0
+for d in ../templates/*/ ; do
+ extension=$(basename $d)
+ mkdir $extension
+ cd $extension
+ yo theia-extension $extension -y $extension || exit_code=$?
+ cd ..
+done
+cd ..
+exit $exit_code
diff --git a/README.md b/README.md
index a84c805..f242707 100644
--- a/README.md
+++ b/README.md
@@ -2,11 +2,17 @@
-
THEIA - EXTENSION GENERATOR
+ECLIPSE THEIA - EXTENSION GENERATOR
+
+
[![Build](https://github.com/theia-ide/generator-theia-extension/workflows/Build/badge.svg?branch=master)](https://github.com/theia-ide/generator-theia-extension/actions?query=branch%3Amaster)
+![npm](https://img.shields.io/npm/v/generator-theia-extension?color=blue)
+
+
+
+A [yeoman](https://yeoman.io/) generator that scaffolds a project structure for developing [Eclipse Theia](https://github.com/eclipse-theia/theia) extensions.
-A [Yeoman](yeoman.io) generator that scaffolds a project structure for developing extensions to the [Theia IDE](https://github.com/theia-ide/theia).
@@ -28,18 +34,25 @@ mkdir my-extension && cd my-extension
yo theia-extension
```
-Extension options
-1. `hello-world`: creates a simple extension which provides a command and menu item which displays a message.
-2. `widget`: creates the basis for a simple widget including a toggle command, alert message and button displaying a message.
-3. `labelprovider`: create a simple extension which adds a custom label (with icon) for `.my` files.
-4. `tree-editor`: create a tree editor extension.
-
-For configuration options, see
+For configuration options, see:
```
yo theia-extension --help
```
+## Extension Options
+
+
+| Template Option | Description | Documentation |
+|:---|:---|:---|
+| `hello-world` | Creates a simple extension which provides a command and menu item which displays a message | [readme](https://github.com/eclipse-theia/generator-theia-extension/blob/master/templates/hello-world/README.md) |
+| `widget` | Creates the basis for a simple widget including a toggle command, alert message and button displaying a message. The template also contains an example unit test. | [readme](https://github.com/eclipse-theia/generator-theia-extension/blob/master/templates/widget/README.md) |
+| `labelprovider` | Creates a simple extension which adds a custom label (with icon) for .my files | [readme](https://github.com/eclipse-theia/generator-theia-extension/blob/master/templates/labelprovider/README.md) |
+| `tree-editor` | Creates a tree editor extension | [readme](https://github.com/eclipse-theia/generator-theia-extension/blob/master/templates/tree-editor/README.md) |
+| `empty` | Creates a simple, minimal extension | [readme](https://github.com/eclipse-theia/generator-theia-extension/blob/master/templates/empty/README.md) |
+| `backend` | Creates a backend communication extension | [readme](https://github.com/eclipse-theia/generator-theia-extension/blob/master/templates/backend/README.md) |
+
+
## Publishing
diff --git a/package.json b/package.json
index 6c0e4e4..10bd68d 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "generator-theia-extension",
- "version": "0.1.21",
+ "version": "0.1.25",
"description": "Helps to setup the project structure for developing extensions to the Theia IDE",
"repository": {
"type": "git",
diff --git a/src/app/index.ts b/src/app/index.ts
index 87ed555..1a65ef8 100644
--- a/src/app/index.ts
+++ b/src/app/index.ts
@@ -46,6 +46,11 @@ module.exports = class TheiaExtension extends Base {
skipInstall: boolean
standalone: boolean
dependencies: string
+ browserDevDependencies: string
+ devdependencies: string
+ scripts: string
+ rootscripts: string
+ containsTests: boolean
};
constructor(args: string | string[], options: any) {
@@ -147,7 +152,7 @@ module.exports = class TheiaExtension extends Base {
message: "The extension's type",
choices: [
{ value: ExtensionType.HelloWorld, name: 'Hello World' },
- { value: ExtensionType.Widget, name: 'Widget' },
+ { value: ExtensionType.Widget, name: 'Widget (with unit tests)' },
{ value: ExtensionType.LabelProvider, name: 'LabelProvider' },
{ value: ExtensionType.TreeEditor, name: 'TreeEditor' },
{ value: ExtensionType.Backend, name: 'Backend Communication' },
@@ -192,10 +197,17 @@ module.exports = class TheiaExtension extends Base {
lernaVersion: options["lerna-version"],
backend: options["extensionType"] === ExtensionType.Backend
}
+ this.params.dependencies = '';
+ this.params.browserDevDependencies = '';
if (this.params.extensionType === ExtensionType.TreeEditor) {
this.params.dependencies = `,\n "@theia/editor": "${this.params.theiaVersion}",\n "@theia/filesystem": "${this.params.theiaVersion}",\n "@theia/workspace": "${this.params.theiaVersion}",\n "@eclipse-emfcloud/theia-tree-editor": "latest",\n "uuid": "^3.3.2"`;
- } else {
- this.params.dependencies = '';
+ this.params.browserDevDependencies = `,\n "node-polyfill-webpack-plugin": "latest"`;
+ }
+ if (this.params.extensionType === ExtensionType.Widget) {
+ this.params.devdependencies = `,\n "@testing-library/react": "^11.2.7",\n "@types/jest": "^26.0.20",\n "jest": "^26.6.3",\n "ts-node": "^9.1.1",\n "ts-jest": "^26.5.6"`;
+ this.params.scripts = `,\n "test": "jest --config configs/jest.config.ts"`;
+ this.params.rootscripts =`,\n "test": "cd ${this.params.extensionPath} && yarn test"`;
+ this.params.containsTests = true;
}
options.params = this.params
if (!options.standalone) {
@@ -317,7 +329,17 @@ module.exports = class TheiaExtension extends Base {
this.extensionPath('README.md'),
{ params: this.params }
);
- }
+ this.fs.copyTpl(
+ this.templatePath('widget/widget.test.ts'),
+ this.extensionPath(`src/browser/${this.params.extensionPath}-widget.test.ts`),
+ { params: this.params }
+ );
+ this.fs.copyTpl(
+ this.templatePath('widget/configs/jest.config.ts'),
+ this.extensionPath(`configs/jest.config.ts`),
+ { params: this.params }
+ );
+ }
/** backend */
if (this.params.extensionType === ExtensionType.Backend) {
@@ -409,7 +431,13 @@ module.exports = class TheiaExtension extends Base {
install() {
if (!(this.options as any).skipInstall) {
- this.spawnCommand('yarn', []);
+ var command = this.spawnCommand('yarn', []);
+
+ command.on('close', function(code: number){
+ if (code !== 0 ) {
+ process.exit(code);
+ }
+ })
}
}
@@ -417,3 +445,5 @@ module.exports = class TheiaExtension extends Base {
return name.substring(0, 1).toUpperCase() + name.substring(1)
}
}
+
+module.exports.ExtensionType = ExtensionType;
\ No newline at end of file
diff --git a/src/browser/index.ts b/src/browser/index.ts
index c8aea96..0c0de9d 100644
--- a/src/browser/index.ts
+++ b/src/browser/index.ts
@@ -23,13 +23,21 @@ module.exports = class TheiaBrowser extends Base {
}
writing() {
+ const params = (this.options as any).params
this.fs.copyTpl(
this.templatePath('app-browser-package.json'),
this.destinationPath('browser-app/package.json'),
{
appMode: 'browser',
- params: (this.options as any).params
+ params
}
);
+ if (params.extensionType === 'tree-editor') {
+ this.fs.copyTpl(
+ this.templatePath('app-browser-webpack-config.js'),
+ this.destinationPath('browser-app/webpack.config.js'),
+ {}
+ );
+ }
}
}
diff --git a/templates/README.md b/templates/README.md
index cad29df..64e0e4e 100644
--- a/templates/README.md
+++ b/templates/README.md
@@ -41,6 +41,18 @@ Open http://localhost:3000 in the browser.
yarn start
*or:* launch `Start Electron Backend` configuration from VS code.
+
+<%if(params.containsTests){%>
+## Running the tests
+
+ yarn test
+
+*or* run the tests of a specific package with
+
+ cd <%= params.extensionPath %>
+ yarn test
+
+<%}%>
## Developing with the browser example
Start watching all packages, including `browser-app`, of your application with
diff --git a/templates/app-browser-package.json b/templates/app-browser-package.json
index b521b78..5a6d3f1 100644
--- a/templates/app-browser-package.json
+++ b/templates/app-browser-package.json
@@ -17,7 +17,7 @@
"<%= params.extensionName %>": "<%= params.version %>"
},
"devDependencies": {
- "@theia/cli": "<%= params.theiaVersion %>"
+ "@theia/cli": "<%= params.theiaVersion %>"<% if (params.browserDevDependencies) { %><%- params.browserDevDependencies %><% } %>
},
"scripts": {
"prepare": "theia build --mode development",
diff --git a/templates/app-browser-webpack-config.js b/templates/app-browser-webpack-config.js
new file mode 100644
index 0000000..72861ce
--- /dev/null
+++ b/templates/app-browser-webpack-config.js
@@ -0,0 +1,21 @@
+/**
+ * This file can be edited to customize webpack configuration.
+ * To reset delete this file and rerun theia build again.
+ */
+// @ts-check
+const config = require('./gen-webpack.config.js');
+
+/**
+ * Expose bundled modules on window.theia.moduleName namespace, e.g.
+ * window['theia']['@theia/core/lib/common/uri'].
+ * Such syntax can be used by external code, for instance, for testing.
+config.module.rules.push({
+ test: /\.js$/,
+ loader: require.resolve('@theia/application-manager/lib/expose-loader')
+}); */
+
+// Load node polyfills as they are no longer automatically included with webpack 5.
+const NodePolyfillPlugin = require("node-polyfill-webpack-plugin")
+config.plugins.push(new NodePolyfillPlugin());
+
+module.exports = config;
diff --git a/templates/backend/backend-module.ts b/templates/backend/backend-module.ts
index 9886856..7e6d983 100644
--- a/templates/backend/backend-module.ts
+++ b/templates/backend/backend-module.ts
@@ -1,8 +1,8 @@
-import { ConnectionHandler, JsonRpcConnectionHandler } from "@theia/core";
-import { ContainerModule } from "inversify";
-import { BackendClient, HelloBackendWithClientService, HelloBackendService, HELLO_BACKEND_PATH, HELLO_BACKEND_WITH_CLIENT_PATH } from "../common/protocol";
-import { HelloBackendWithClientServiceImpl } from "./hello-backend-with-client-service";
-import { HelloBackendServiceImpl } from "./hello-backend-service";
+import { ConnectionHandler, JsonRpcConnectionHandler } from '@theia/core';
+import { ContainerModule } from '@theia/core/shared/inversify';
+import { BackendClient, HelloBackendWithClientService, HelloBackendService, HELLO_BACKEND_PATH, HELLO_BACKEND_WITH_CLIENT_PATH } from '../common/protocol';
+import { HelloBackendWithClientServiceImpl } from './hello-backend-with-client-service';
+import { HelloBackendServiceImpl } from './hello-backend-service';
export default new ContainerModule(bind => {
bind(HelloBackendService).to(HelloBackendServiceImpl).inSingletonScope()
diff --git a/templates/backend/contribution.ts b/templates/backend/contribution.ts
index 889a16b..9b03d9c 100644
--- a/templates/backend/contribution.ts
+++ b/templates/backend/contribution.ts
@@ -1,5 +1,5 @@
import { Command, CommandContribution, CommandRegistry} from '@theia/core/lib/common';
-import { inject, injectable } from 'inversify';
+import { inject, injectable } from '@theia/core/shared/inversify';
import { HelloBackendWithClientService, HelloBackendService } from '../common/protocol';
const SayHelloViaBackendCommandWithCallBack: Command = {
diff --git a/templates/backend/frontend-module.ts b/templates/backend/frontend-module.ts
index 381c1ba..3f1435c 100644
--- a/templates/backend/frontend-module.ts
+++ b/templates/backend/frontend-module.ts
@@ -1,6 +1,6 @@
import { CommandContribution} from '@theia/core';
-import { WebSocketConnectionProvider } from "@theia/core/lib/browser";
-import { ContainerModule, injectable } from "inversify";
+import { WebSocketConnectionProvider } from '@theia/core/lib/browser';
+import { ContainerModule, injectable } from '@theia/core/shared/inversify';
import { BackendClient, HelloBackendWithClientService, HelloBackendService, HELLO_BACKEND_PATH, HELLO_BACKEND_WITH_CLIENT_PATH } from '../common/protocol';
import { <%= params.extensionPrefix %>CommandContribution} from './<%= params.extensionPath %>-contribution';
diff --git a/templates/backend/hello-backend-service.ts b/templates/backend/hello-backend-service.ts
index 8b4f22c..51dfc10 100644
--- a/templates/backend/hello-backend-service.ts
+++ b/templates/backend/hello-backend-service.ts
@@ -1,5 +1,5 @@
-import { injectable } from "inversify";
-import { HelloBackendService } from "../common/protocol";
+import { injectable } from '@theia/core/shared/inversify';
+import { HelloBackendService } from '../common/protocol';
@injectable()
export class HelloBackendServiceImpl implements HelloBackendService {
diff --git a/templates/backend/hello-backend-with-client-service.ts b/templates/backend/hello-backend-with-client-service.ts
index 02cf352..0a491d9 100644
--- a/templates/backend/hello-backend-with-client-service.ts
+++ b/templates/backend/hello-backend-with-client-service.ts
@@ -1,5 +1,5 @@
-import { injectable } from "inversify";
-import { BackendClient, HelloBackendWithClientService } from "../common/protocol";
+import { injectable } from '@theia/core/shared/inversify';
+import { BackendClient, HelloBackendWithClientService } from '../common/protocol';
@injectable()
export class HelloBackendWithClientServiceImpl implements HelloBackendWithClientService {
diff --git a/templates/empty/contribution.ts b/templates/empty/contribution.ts
index 8980cf5..8c139b0 100644
--- a/templates/empty/contribution.ts
+++ b/templates/empty/contribution.ts
@@ -1,4 +1,4 @@
-import { injectable } from 'inversify';
+import { injectable } from '@theia/core/shared/inversify';
@injectable()
// Add contribution interface to be implemented, e.g. "<%= params.extensionPrefix %>Contribution implements CommandContribution"
diff --git a/templates/empty/frontend-module.ts b/templates/empty/frontend-module.ts
index 68dd7c5..74b7368 100644
--- a/templates/empty/frontend-module.ts
+++ b/templates/empty/frontend-module.ts
@@ -1,7 +1,7 @@
/**
* Generated using theia-extension-generator
*/
-import { ContainerModule } from 'inversify';
+import { ContainerModule } from '@theia/core/shared/inversify';
import { <%= params.extensionPrefix %>Contribution } from './<%= params.extensionPath %>-contribution';
diff --git a/templates/extension-package.json b/templates/extension-package.json
index 8f68f13..ec007e8 100644
--- a/templates/extension-package.json
+++ b/templates/extension-package.json
@@ -31,13 +31,13 @@
},
"devDependencies": {
"rimraf": "latest",
- "typescript": "latest"
+ "typescript": "latest"<% if (params.devdependencies) { %><%- params.devdependencies %><% } %>
},
"scripts": {
"prepare": "yarn run clean && yarn run build",
"clean": "rimraf lib",
"build": "tsc",
- "watch": "tsc -w"
+ "watch": "tsc -w"<% if (params.scripts) { %><%- params.scripts %><% } %>
},
"theiaExtensions": [
{
diff --git a/templates/hello-world/contribution.ts b/templates/hello-world/contribution.ts
index 93de0b8..d548c01 100644
--- a/templates/hello-world/contribution.ts
+++ b/templates/hello-world/contribution.ts
@@ -1,10 +1,10 @@
-import { injectable, inject } from "inversify";
+import { injectable, inject } from '@theia/core/shared/inversify';
import { Command, CommandContribution, CommandRegistry, MenuContribution, MenuModelRegistry, MessageService } from "@theia/core/lib/common";
import { CommonMenus } from "@theia/core/lib/browser";
export const <%= params.extensionPrefix %>Command: Command = {
id: '<%= params.extensionPrefix %>.command',
- label: "Say Hello"
+ label: 'Say Hello'
};
@injectable()
diff --git a/templates/hello-world/frontend-module.ts b/templates/hello-world/frontend-module.ts
index 1db5809..b014191 100644
--- a/templates/hello-world/frontend-module.ts
+++ b/templates/hello-world/frontend-module.ts
@@ -2,11 +2,8 @@
* Generated using theia-extension-generator
*/
import { <%= params.extensionPrefix %>CommandContribution, <%= params.extensionPrefix %>MenuContribution } from './<%= params.extensionPath %>-contribution';
-import {
- CommandContribution,
- MenuContribution
-} from "@theia/core/lib/common";
-import { ContainerModule } from "inversify";
+import { CommandContribution, MenuContribution } from '@theia/core/lib/common';
+import { ContainerModule } from '@theia/core/shared/inversify';
export default new ContainerModule(bind => {
// add your contribution bindings here
diff --git a/templates/labelprovider/contribution.ts b/templates/labelprovider/contribution.ts
index 512ec40..a583d50 100644
--- a/templates/labelprovider/contribution.ts
+++ b/templates/labelprovider/contribution.ts
@@ -1,6 +1,6 @@
-import { FileStatNode } from "@theia/filesystem/lib/browser/file-tree/file-tree";
-import { FileTreeLabelProvider } from "@theia/filesystem/lib/browser/file-tree/file-tree-label-provider";
-import { injectable, } from "inversify";
+import { FileStatNode } from '@theia/filesystem/lib/browser/file-tree/file-tree';
+import { FileTreeLabelProvider } from '@theia/filesystem/lib/browser/file-tree/file-tree-label-provider';
+import { injectable } from '@theia/core/shared/inversify';
@injectable()
export class <%= params.extensionPrefix %>LabelProviderContribution extends FileTreeLabelProvider {
diff --git a/templates/labelprovider/frontend-module.ts b/templates/labelprovider/frontend-module.ts
index ca34b5e..03df5b6 100644
--- a/templates/labelprovider/frontend-module.ts
+++ b/templates/labelprovider/frontend-module.ts
@@ -2,7 +2,7 @@
* Generated using theia-extension-generator
*/
import { LabelProviderContribution } from "@theia/core/lib/browser";
-import { ContainerModule } from "inversify";
+import { ContainerModule } from "@theia/core/shared/inversify";
import { <%= params.extensionPrefix %>LabelProviderContribution } from './<%= params.extensionPath %>-contribution';
import '../../src/browser/style/example.css';
diff --git a/templates/launch.json b/templates/launch.json
index 63be103..58b45a2 100644
--- a/templates/launch.json
+++ b/templates/launch.json
@@ -20,7 +20,7 @@
"sourceMaps": true,
"outFiles": [
"${workspaceRoot}/node_modules/@theia/*/lib/**/*.js",
- "${workspaceRoot}/browser-app/lib/**/*.js",
+ "${workspaceRoot}/*/lib/**/*.js",
"${workspaceRoot}/browser-app/src-gen/**/*.js"
],
"smartStep": true,
@@ -49,7 +49,7 @@
"outFiles": [
"${workspaceRoot}/electron-app/src-gen/frontend/electron-main.js",
"${workspaceRoot}/electron-app/src-gen/backend/main.js",
- "${workspaceRoot}/electron-app/lib/**/*.js",
+ "${workspaceRoot}/*/lib/**/*.js",
"${workspaceRoot}/node_modules/@theia/*/lib/**/*.js"
],
"smartStep": true,
diff --git a/templates/root-package.json b/templates/root-package.json
index bfe1a62..55e3961 100644
--- a/templates/root-package.json
+++ b/templates/root-package.json
@@ -6,7 +6,7 @@
"rebuild:electron": "theia rebuild:electron",
"start:browser": "yarn rebuild:browser && yarn --cwd browser-app start",
"start:electron": "yarn rebuild:electron && yarn --cwd electron-app start",
- "watch": "lerna run --parallel watch"
+ "watch": "lerna run --parallel watch"<% if (params.rootscripts) { %><%- params.rootscripts %><% } %>
},
"devDependencies": {
"lerna": "<%= params.lernaVersion %>"
diff --git a/templates/tree-editor/example-file/example-file-command.ts b/templates/tree-editor/example-file/example-file-command.ts
index bdd7b76..c8b552e 100644
--- a/templates/tree-editor/example-file/example-file-command.ts
+++ b/templates/tree-editor/example-file/example-file-command.ts
@@ -6,7 +6,7 @@ import URI from '@theia/core/lib/common/uri';
import { SingleUriCommandHandler } from '@theia/core/lib/common/uri-command-handler';
import { FileService } from '@theia/filesystem/lib/browser/file-service';
import { FileSystemUtils } from '@theia/filesystem/lib/common';
-import { inject, injectable } from 'inversify';
+import { inject, injectable } from '@theia/core/shared/inversify';
import { OpenerService } from '@theia/core/lib/browser';
import { WorkspaceService } from '@theia/workspace/lib/browser';
diff --git a/templates/tree-editor/example-file/example-file-contribution.ts b/templates/tree-editor/example-file/example-file-contribution.ts
index ac31ad0..31dc7d2 100644
--- a/templates/tree-editor/example-file/example-file-contribution.ts
+++ b/templates/tree-editor/example-file/example-file-contribution.ts
@@ -1,5 +1,5 @@
import { CommandContribution, CommandRegistry, MenuContribution, MenuModelRegistry, SelectionService, MAIN_MENU_BAR } from '@theia/core/lib/common';
-import { inject, injectable } from 'inversify';
+import { inject, injectable } from '@theia/core/shared/inversify';
import { WorkspaceRootUriAwareCommandHandler } from '@theia/workspace/lib/browser/workspace-commands';
import { WorkspaceService } from '@theia/workspace/lib/browser';
import { NewTreeExampleFileCommandHandler, NewTreeExampleFileCommand } from './example-file-command';
diff --git a/templates/tree-editor/tree-contribution.ts b/templates/tree-editor/tree-contribution.ts
index 3131bde..129759a 100644
--- a/templates/tree-editor/tree-contribution.ts
+++ b/templates/tree-editor/tree-contribution.ts
@@ -1,16 +1,11 @@
+import URI from '@theia/core/lib/common/uri';
import { CommandRegistry, MenuModelRegistry } from '@theia/core';
import { ApplicationShell, NavigatableWidgetOptions, OpenerService, WidgetOpenerOptions } from '@theia/core/lib/browser';
-import URI from '@theia/core/lib/common/uri';
-import { inject, injectable } from 'inversify';
-import {
- BaseTreeEditorContribution,
- MasterTreeWidget,
- TreeEditor,
-} from '@eclipse-emfcloud/theia-tree-editor';
-
+import { inject, injectable } from '@theia/core/shared/inversify';
import { TreeModelService } from './tree/tree-model-service';
import { TreeEditorWidget } from './tree/tree-editor-widget';
import { TreeLabelProvider } from './tree/tree-label-provider';
+import { BaseTreeEditorContribution, MasterTreeWidget, TreeEditor,} from '@eclipse-emfcloud/theia-tree-editor';
@injectable()
export class TreeContribution extends BaseTreeEditorContribution {
diff --git a/templates/tree-editor/tree-frontend-module.ts b/templates/tree-editor/tree-frontend-module.ts
index 5b6db3d..f0a0ccd 100644
--- a/templates/tree-editor/tree-frontend-module.ts
+++ b/templates/tree-editor/tree-frontend-module.ts
@@ -5,9 +5,7 @@ import '../../src/browser/style/editor.css';
import { CommandContribution, MenuContribution } from '@theia/core';
import { LabelProviderContribution, NavigatableWidgetOptions, OpenHandler, WidgetFactory } from '@theia/core/lib/browser';
import URI from '@theia/core/lib/common/uri';
-import { ContainerModule } from 'inversify';
-import { createBasicTreeContainer, NavigatableTreeEditorOptions } from '@eclipse-emfcloud/theia-tree-editor';
-
+import { ContainerModule } from '@theia/core/shared/inversify';
import { TreeContribution } from './tree-contribution';
import { TreeModelService } from './tree/tree-model-service';
import { TreeNodeFactory } from './tree/tree-node-factory';
@@ -16,6 +14,7 @@ import { TreeLabelProvider } from './tree/tree-label-provider';
import { TreeLabelProviderContribution } from './tree-label-provider-contribution';
import { NewTreeExampleFileCommandHandler } from './example-file/example-file-command';
import { NewTreeExampleFileCommandContribution, NewTreeExampleFileMenuContribution } from './example-file/example-file-contribution';
+import { createBasicTreeContainer, NavigatableTreeEditorOptions } from '@eclipse-emfcloud/theia-tree-editor';
export default new ContainerModule(bind => {
// Bind Theia IDE contributions for the example file creation menu entry.
diff --git a/templates/tree-editor/tree-label-provider-contribution.ts b/templates/tree-editor/tree-label-provider-contribution.ts
index 806e64e..45fd91d 100644
--- a/templates/tree-editor/tree-label-provider-contribution.ts
+++ b/templates/tree-editor/tree-label-provider-contribution.ts
@@ -1,7 +1,7 @@
import { LabelProviderContribution } from '@theia/core/lib/browser';
import URI from '@theia/core/lib/common/uri';
import { FileStat } from '@theia/filesystem/lib/common';
-import { injectable } from 'inversify';
+import { injectable } from '@theia/core/shared/inversify';
@injectable()
export class TreeLabelProviderContribution implements LabelProviderContribution {
diff --git a/templates/tree-editor/tree/tree-editor-widget.ts b/templates/tree-editor/tree/tree-editor-widget.ts
index 952beed..f1d6e19 100644
--- a/templates/tree-editor/tree/tree-editor-widget.ts
+++ b/templates/tree-editor/tree/tree-editor-widget.ts
@@ -2,7 +2,7 @@ import { Title, Widget } from '@theia/core/lib/browser';
import { DefaultResourceProvider, ILogger } from '@theia/core/lib/common';
import { EditorPreferences } from '@theia/editor/lib/browser';
import { WorkspaceService } from '@theia/workspace/lib/browser/workspace-service';
-import { inject, injectable } from 'inversify';
+import { inject, injectable } from '@theia/core/shared/inversify';
import {
MasterTreeWidget,
DetailFormWidget,
diff --git a/templates/tree-editor/tree/tree-label-provider.ts b/templates/tree-editor/tree/tree-label-provider.ts
index 4e86655..c2331ef 100644
--- a/templates/tree-editor/tree/tree-label-provider.ts
+++ b/templates/tree-editor/tree/tree-label-provider.ts
@@ -1,9 +1,8 @@
+import { injectable } from '@theia/core/shared/inversify';
import { LabelProviderContribution } from '@theia/core/lib/browser';
-import { injectable } from 'inversify';
-import { TreeEditor } from '@eclipse-emfcloud/theia-tree-editor';
-
import { CoffeeModel } from './tree-model';
import { TreeEditorWidget } from './tree-editor-widget';
+import { TreeEditor } from '@eclipse-emfcloud/theia-tree-editor';
const DEFAULT_COLOR = 'black';
diff --git a/templates/tree-editor/tree/tree-model-service.ts b/templates/tree-editor/tree/tree-model-service.ts
index 25b1102..904ad8a 100644
--- a/templates/tree-editor/tree/tree-model-service.ts
+++ b/templates/tree-editor/tree/tree-model-service.ts
@@ -1,8 +1,7 @@
import { ILogger } from '@theia/core';
-import { inject, injectable } from 'inversify';
-import { TreeEditor } from '@eclipse-emfcloud/theia-tree-editor';
-
+import { inject, injectable } from '@theia/core/shared/inversify';
import { CoffeeModel } from './tree-model';
+import { TreeEditor } from '@eclipse-emfcloud/theia-tree-editor';
import {
brewingView,
coffeeSchema,
diff --git a/templates/tree-editor/tree/tree-node-factory.ts b/templates/tree-editor/tree/tree-node-factory.ts
index 3c80c60..e10e99a 100644
--- a/templates/tree-editor/tree/tree-node-factory.ts
+++ b/templates/tree-editor/tree/tree-node-factory.ts
@@ -1,11 +1,10 @@
-import { ILogger } from '@theia/core';
-import { inject, injectable } from 'inversify';
-import { TreeEditor } from '@eclipse-emfcloud/theia-tree-editor';
import { v4 } from 'uuid';
-
+import { ILogger } from '@theia/core';
+import { inject, injectable } from '@theia/core/shared/inversify';
import { CoffeeModel } from './tree-model';
import { TreeEditorWidget } from './tree-editor-widget';
import { TreeLabelProvider } from './tree-label-provider';
+import { TreeEditor } from '@eclipse-emfcloud/theia-tree-editor';
@injectable()
export class TreeNodeFactory implements TreeEditor.NodeFactory {
diff --git a/templates/tsconfig.json b/templates/tsconfig.json
index 889b54d..8419101 100644
--- a/templates/tsconfig.json
+++ b/templates/tsconfig.json
@@ -14,10 +14,10 @@
"resolveJsonModule": true,
"module": "commonjs",
"moduleResolution": "node",
- "target": "es5",
+ "target": "ES2017",
"jsx": "react",
"lib": [
- "es6",
+ "ES2017",
"dom"
],
"sourceMap": true,
diff --git a/templates/widget/README.md b/templates/widget/README.md
index 6e1507e..99df021 100644
--- a/templates/widget/README.md
+++ b/templates/widget/README.md
@@ -1,7 +1,9 @@
# Example Widget
-The example extension demonstrates how to contribute a custom widget (i.e. a view or editor) to Eclipse Theia.
+The example extension demonstrates how to contribute a custom widget (i.e. a view or editor) to Eclipse Theia. Furthermore, the template contains an example unit test.
## How to use the widget example
In the running application, open the widget using the menu "View" => "<%= params.extensionPrefix %> Widget"
+To execute the test, run
+ yarn test
\ No newline at end of file
diff --git a/templates/widget/configs/jest.config.ts b/templates/widget/configs/jest.config.ts
new file mode 100644
index 0000000..1a7f8a2
--- /dev/null
+++ b/templates/widget/configs/jest.config.ts
@@ -0,0 +1,10 @@
+import type { Config } from '@jest/types';
+
+export default async (): Promise => ({
+ preset: 'ts-jest',
+ testMatch: ['**.test.ts'],
+ rootDir: '../',
+ transform: {
+ '^.+\\.(ts)$': 'ts-jest',
+ }
+});
diff --git a/templates/widget/contribution.ts b/templates/widget/contribution.ts
index 09dcbf6..90f20e5 100644
--- a/templates/widget/contribution.ts
+++ b/templates/widget/contribution.ts
@@ -1,4 +1,4 @@
-import { injectable } from 'inversify';
+import { injectable } from '@theia/core/shared/inversify';
import { MenuModelRegistry } from '@theia/core';
import { <%= params.extensionPrefix %>Widget } from './<%= params.extensionPath %>-widget';
import { AbstractViewContribution } from '@theia/core/lib/browser';
diff --git a/templates/widget/frontend-module.ts b/templates/widget/frontend-module.ts
index ba01abc..333101c 100644
--- a/templates/widget/frontend-module.ts
+++ b/templates/widget/frontend-module.ts
@@ -1,4 +1,4 @@
-import { ContainerModule } from 'inversify';
+import { ContainerModule } from '@theia/core/shared/inversify';
import { <%= params.extensionPrefix %>Widget } from './<%= params.extensionPath %>-widget';
import { <%= params.extensionPrefix %>Contribution } from './<%= params.extensionPath %>-contribution';
import { bindViewContribution, FrontendApplicationContribution, WidgetFactory } from '@theia/core/lib/browser';
diff --git a/templates/widget/widget.test.ts b/templates/widget/widget.test.ts
new file mode 100644
index 0000000..817e787
--- /dev/null
+++ b/templates/widget/widget.test.ts
@@ -0,0 +1,36 @@
+import 'reflect-metadata';
+import { MessageService } from '@theia/core';
+import { ContainerModule, Container } from '@theia/core/shared/inversify';
+import { <%= params.extensionPrefix %>Widget } from './<%= params.extensionPath %>-widget';
+import { render } from '@testing-library/react'
+
+describe('<%= params.extensionPrefix %>Widget', () => {
+
+ let widget: <%= params.extensionPrefix %>Widget;
+
+ beforeEach(async () => {
+ const module = new ContainerModule( bind => {
+ bind(MessageService).toConstantValue({
+ info(message: string): void {
+ console.log(message);
+ }
+ } as MessageService);
+ bind(<%= params.extensionPrefix %>Widget).toSelf();
+ });
+ const container = new Container();
+ container.load(module);
+ widget = container.resolve<<%= params.extensionPrefix %>Widget>(<%= params.extensionPrefix %>Widget);
+ });
+
+ it('should render react node correctly', async () => {
+ const element = render(widget.render());
+ expect(element.queryByText('Display Message')).toBeTruthy();
+ });
+
+ it('should inject \'MessageService\'', () => {
+ const spy = jest.spyOn(widget as any, 'displayMessage')
+ widget['displayMessage']();
+ expect(spy).toBeCalled();
+ });
+
+});
diff --git a/templates/widget/widget.tsx b/templates/widget/widget.tsx
index bbc8242..6e6e8eb 100644
--- a/templates/widget/widget.tsx
+++ b/templates/widget/widget.tsx
@@ -1,5 +1,5 @@
import * as React from 'react';
-import { injectable, postConstruct, inject } from 'inversify';
+import { injectable, postConstruct, inject } from '@theia/core/shared/inversify';
import { AlertMessage } from '@theia/core/lib/browser/widgets/alert-message';
import { ReactWidget } from '@theia/core/lib/browser/widgets/react-widget';
import { MessageService } from '@theia/core';
@@ -23,7 +23,7 @@ export class <%= params.extensionPrefix %>Widget extends ReactWidget {
this.update();
}
- protected render(): React.ReactNode {
+ render(): React.ReactElement {
const header = `This is a sample widget which simply calls the messageService
in order to display an info message to end users.`;
return