From 22e2adcf0dee17cc53f54c946f7b669f2923d12c Mon Sep 17 00:00:00 2001 From: Stanislav Lvovsky Date: Wed, 25 Nov 2020 12:43:20 +0200 Subject: [PATCH 01/12] fix: circular structure error --- backend/package.json | 16 ++++++++-------- backend/src/code-snippet.ts | 3 ++- backend/src/contributors.ts | 8 ++++---- backend/src/panels/CodeSnippetPanel.ts | 8 ++++---- backend/tests/code-snippet.spec.ts | 2 +- frontend/package.json | 4 ++-- 6 files changed, 21 insertions(+), 20 deletions(-) diff --git a/backend/package.json b/backend/package.json index 9ca99df..a32d4ee 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,7 +1,7 @@ { "name": "code-snippet", - "version": "0.0.22", - "displayName": "Code Snippet", + "version": "0.0.23", + "displayName": "Code Snippet", "publisher": "SAPOSS", "author": { "name": "SAP SE" @@ -116,13 +116,13 @@ "lint:fix": "eslint . --ext .ts,.tsx --cache --fix" }, "dependencies": { - "@sap-devx/webview-rpc": "^0.2.2", + "@sap-devx/webview-rpc": "0.2.3", "@vscode-logging/logger": "1.1.0", - "datauri": "^2.0.0", - "fs-extra": "^8.1.0", - "lodash": "^4.17.15", - "strip-ansi": "^6.0.0", - "ws": "^7.2.5", + "datauri": "3.0.0", + "fs-extra": "9.0.1", + "lodash": "4.17.20", + "strip-ansi": "6.0.0", + "ws": "7.4.0", "yeoman-environment": "2.10.3" }, "devDependencies": { diff --git a/backend/src/code-snippet.ts b/backend/src/code-snippet.ts index e95be55..57eff38 100644 --- a/backend/src/code-snippet.ts +++ b/backend/src/code-snippet.ts @@ -50,7 +50,8 @@ export class CodeSnippet { } private async getState() { - return this.uiOptions; + const state = _.omit(this.uiOptions, ["snippet", "contributorInfo.context"]); + return state; } public registerCustomQuestionEventHandler(questionType: string, methodName: string, handler: Function): void { diff --git a/backend/src/contributors.ts b/backend/src/contributors.ts index 6c5ae0a..87ff512 100644 --- a/backend/src/contributors.ts +++ b/backend/src/contributors.ts @@ -2,15 +2,15 @@ import * as vscode from 'vscode'; import * as _ from 'lodash'; export class Contributors { - public static async getSnippet(contributerInfo: any) { - const contributorId = _.get(contributerInfo, "contributorId"); + public static async getSnippet(contributorInfo: any) { + const contributorId = _.get(contributorInfo, "contributorId"); const extension = Contributors.getContributorExtension(contributorId); if (extension) { try { const api = await this.getApiPromise(extension as vscode.Extension); - const snippetContext = _.get(contributerInfo, "context"); + const snippetContext = _.get(contributorInfo, "context"); const snippets = api.getCodeSnippets(snippetContext); - const snippetName = _.get(contributerInfo, "snippetName"); + const snippetName = _.get(contributorInfo, "snippetName"); return snippets.get(snippetName); } catch (error) { const errorMessage = _.get(error, "stack", _.get(error, "message", error)); diff --git a/backend/src/panels/CodeSnippetPanel.ts b/backend/src/panels/CodeSnippetPanel.ts index 4709ba3..6589dc9 100644 --- a/backend/src/panels/CodeSnippetPanel.ts +++ b/backend/src/panels/CodeSnippetPanel.ts @@ -24,9 +24,9 @@ export class CodeSnippetPanel extends AbstractWebviewPanel { public setWebviewPanel(webViewPanel: vscode.WebviewPanel, uiOptions?: any) { super.setWebviewPanel(webViewPanel, uiOptions); - - const contributerInfo = _.get(uiOptions, "contributerInfo", uiOptions); - Contributors.getSnippet(contributerInfo).then(snippet => { + const contributorInfo = _.get(uiOptions, "contributorInfo", uiOptions); + + Contributors.getSnippet(contributorInfo).then(snippet => { if (_.isNil(snippet)) { this.webViewPanel.dispose(); return vscode.window.showErrorMessage("Can not find snippet."); @@ -40,7 +40,7 @@ export class CodeSnippetPanel extends AbstractWebviewPanel { vscodeEvents, this.outputChannel, this.logger, - { messages: this.messages, snippet, contributerInfo}); + { messages: this.messages, snippet, contributorInfo}); this.codeSnippet.registerCustomQuestionEventHandler("file-browser", "getFilePath", this.showOpenFileDialog.bind(this)); this.codeSnippet.registerCustomQuestionEventHandler("folder-browser", "getPath", this.showOpenFolderDialog.bind(this)); diff --git a/backend/tests/code-snippet.spec.ts b/backend/tests/code-snippet.spec.ts index 9d74568..f89cb14 100644 --- a/backend/tests/code-snippet.spec.ts +++ b/backend/tests/code-snippet.spec.ts @@ -147,7 +147,7 @@ describe('codeSnippet unit test', () => { it("getState", async () => { const state = await codeSnippet["getState"](); - expect(state).to.deep.equal(uiOptions); + expect(state.messages).to.be.not.empty; }); describe("receiveIsWebviewReady", () => { diff --git a/frontend/package.json b/frontend/package.json index 6c6fdc2..fd05dbf 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -26,11 +26,11 @@ "material-design-icons-iconfont": "6.1.0", "vue": "2.6.12", "vue-loading-overlay": "3.3.0", - "vuetify": "2.3.10" + "vuetify": "2.3.10", + "@sap-devx/webview-rpc": "0.2.2" }, "devDependencies": { "@babel/preset-env": "7.11.5", - "@sap-devx/webview-rpc": "0.2.3", "@vue/cli-plugin-babel": "4.5.4", "@vue/cli-plugin-eslint": "4.5.4", "@vue/cli-plugin-unit-jest": "4.5.4", From a73087e1cc8bc3507965a7db3255d28faa16a6e9 Mon Sep 17 00:00:00 2001 From: Stanislav Lvovsky Date: Wed, 25 Nov 2020 14:05:27 +0200 Subject: [PATCH 02/12] fix: leave context --- backend/src/code-snippet.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/code-snippet.ts b/backend/src/code-snippet.ts index 57eff38..b05b187 100644 --- a/backend/src/code-snippet.ts +++ b/backend/src/code-snippet.ts @@ -50,7 +50,7 @@ export class CodeSnippet { } private async getState() { - const state = _.omit(this.uiOptions, ["snippet", "contributorInfo.context"]); + const state = _.omit(this.uiOptions, ["snippet"]); return state; } From 88915366056d08fa3d9382f456ba6f9cba382bbb Mon Sep 17 00:00:00 2001 From: Stanislav Lvovsky Date: Wed, 25 Nov 2020 14:06:19 +0200 Subject: [PATCH 03/12] fix: bump version --- frontend/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/package.json b/frontend/package.json index fd05dbf..97fff92 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -27,7 +27,7 @@ "vue": "2.6.12", "vue-loading-overlay": "3.3.0", "vuetify": "2.3.10", - "@sap-devx/webview-rpc": "0.2.2" + "@sap-devx/webview-rpc": "0.2.3" }, "devDependencies": { "@babel/preset-env": "7.11.5", From fd8f2b3d39553db061275f572f616d2c76093076 Mon Sep 17 00:00:00 2001 From: Stanislav Lvovsky Date: Wed, 25 Nov 2020 18:16:41 +0200 Subject: [PATCH 04/12] fix: close snippet tab on stringify error --- backend/.nycrc.json | 4 ++-- backend/package.json | 1 + backend/src/code-snippet.ts | 13 +++++++++++-- backend/src/contributors.ts | 4 ++-- backend/src/extension.ts | 4 ++-- backend/src/panels/CodeSnippetPanel.ts | 14 ++++++++++---- 6 files changed, 28 insertions(+), 12 deletions(-) diff --git a/backend/.nycrc.json b/backend/.nycrc.json index 44cdd24..9672f95 100644 --- a/backend/.nycrc.json +++ b/backend/.nycrc.json @@ -9,7 +9,7 @@ "report-dir": "./reports/coverage", "check-coverage": true, "branches": 98, - "lines": 99, + "lines": 98, "functions": 97, - "statements": 99 + "statements": 98 } diff --git a/backend/package.json b/backend/package.json index a32d4ee..9baf7e4 100644 --- a/backend/package.json +++ b/backend/package.json @@ -126,6 +126,7 @@ "yeoman-environment": "2.10.3" }, "devDependencies": { + "flatted": "3.1.0", "@types/chai": "^4.2.9", "@types/fs-extra": "^8.1.0", "@types/inquirer": "^6.5.0", diff --git a/backend/src/code-snippet.ts b/backend/src/code-snippet.ts index 57eff38..0ff2d45 100644 --- a/backend/src/code-snippet.ts +++ b/backend/src/code-snippet.ts @@ -1,5 +1,4 @@ import * as _ from "lodash"; -import * as Environment from "yeoman-environment"; import * as inquirer from "inquirer"; import { AppLog } from "./app-log"; import { AppEvents } from "./app-events"; @@ -8,6 +7,7 @@ import Generator = require("yeoman-generator"); import { IChildLogger } from "@vscode-logging/logger"; import TerminalAdapter = require("yeoman-environment/lib/adapter"); + export class CodeSnippet { private static funcReplacer(key: any, value: any) { @@ -50,7 +50,16 @@ export class CodeSnippet { } private async getState() { - const state = _.omit(this.uiOptions, ["snippet", "contributorInfo.context"]); + let state = _.omit(this.uiOptions, ["snippet"]); + try { + // valiation for rpc + JSON.stringify(state); + } catch (error) { + // only stateError and contributorInfo will be saved + state = _.omit(state, ["contributorInfo.context"]); + _.set(state, "stateError", true); + } + return state; } diff --git a/backend/src/contributors.ts b/backend/src/contributors.ts index 87ff512..4168699 100644 --- a/backend/src/contributors.ts +++ b/backend/src/contributors.ts @@ -20,8 +20,8 @@ export class Contributors { } } - private static getApiPromise(extension: vscode.Extension) { - return (extension.isActive ? extension.exports : extension.activate()); + private static getApiPromise(extension: vscode.Extension): Thenable { + return (extension.isActive ? Promise.resolve(extension.exports) : extension.activate()); } private static getContributorExtension(contributorId: string) { diff --git a/backend/src/extension.ts b/backend/src/extension.ts index 84cace0..948fd9b 100644 --- a/backend/src/extension.ts +++ b/backend/src/extension.ts @@ -29,8 +29,8 @@ function registerAndSubscribeCommand(cId: string, cAction: any) { function registerWebviewPanelSerializer(abstractPanel: AbstractWebviewPanel) { vscode.window.registerWebviewPanelSerializer(abstractPanel.viewType, { - async deserializeWebviewPanel(webviewPanel: vscode.WebviewPanel, state?: any) { - abstractPanel.setWebviewPanel(webviewPanel, state); + async deserializeWebviewPanel(webViewPanel: vscode.WebviewPanel, state?: any) { + abstractPanel.setWebviewPanel(webViewPanel, state); } }); } diff --git a/backend/src/panels/CodeSnippetPanel.ts b/backend/src/panels/CodeSnippetPanel.ts index 6589dc9..119dc0b 100644 --- a/backend/src/panels/CodeSnippetPanel.ts +++ b/backend/src/panels/CodeSnippetPanel.ts @@ -23,15 +23,21 @@ export class CodeSnippetPanel extends AbstractWebviewPanel { } public setWebviewPanel(webViewPanel: vscode.WebviewPanel, uiOptions?: any) { - super.setWebviewPanel(webViewPanel, uiOptions); const contributorInfo = _.get(uiOptions, "contributorInfo", uiOptions); - + + if (_.get(uiOptions, "stateError")) { + console.error(`ERROR: '${contributorInfo.contributorId}' snippet state was not saved. Serialization issue.`); //TODO: use logger.error + return webViewPanel.dispose(); + } + Contributors.getSnippet(contributorInfo).then(snippet => { if (_.isNil(snippet)) { - this.webViewPanel.dispose(); - return vscode.window.showErrorMessage("Can not find snippet."); + console.error(`ERROR: '${contributorInfo.contributorId}' snippet was not found`); //TODO: use logger.error + return this.webViewPanel.dispose(); } + super.setWebviewPanel(webViewPanel, uiOptions); + this.messages = _.assign({}, backendMessages, snippet.getMessages()); const rpc = new RpcExtension(this.webViewPanel.webview); this.outputChannel = new OutputChannelLog(this.messages.channelName); From 47ba87c230d50f5a3bcd9584f869e74eeed9d08f Mon Sep 17 00:00:00 2001 From: Stanislav Lvovsky Date: Wed, 25 Nov 2020 18:30:16 +0200 Subject: [PATCH 05/12] fix: add test --- backend/.nycrc.json | 4 ++-- backend/tests/code-snippet.spec.ts | 16 ++++++++++++---- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/backend/.nycrc.json b/backend/.nycrc.json index 9672f95..44cdd24 100644 --- a/backend/.nycrc.json +++ b/backend/.nycrc.json @@ -9,7 +9,7 @@ "report-dir": "./reports/coverage", "check-coverage": true, "branches": 98, - "lines": 98, + "lines": 99, "functions": 97, - "statements": 98 + "statements": 99 } diff --git a/backend/tests/code-snippet.spec.ts b/backend/tests/code-snippet.spec.ts index f89cb14..ae766b7 100644 --- a/backend/tests/code-snippet.spec.ts +++ b/backend/tests/code-snippet.spec.ts @@ -145,11 +145,19 @@ describe('codeSnippet unit test', () => { } }); - it("getState", async () => { - const state = await codeSnippet["getState"](); - expect(state.messages).to.be.not.empty; - }); + describe("getState", () => { + it("valid uiOptions", async () => { + const state = await codeSnippet["getState"](); + expect(state.messages).to.be.not.empty; + }); + it("invalid uiOptions", async () => { + codeSnippet["uiOptions"].test = codeSnippet["uiOptions"] + const state = await codeSnippet["getState"](); + expect(state.stateError).to.be.true; + }); + }); + describe("receiveIsWebviewReady", () => { it("flow is successfull", async () => { rpcMock.expects("invoke").withArgs("showPrompt").resolves( From e1603b65aa4d073764db6d928916616aa7cf00ee Mon Sep 17 00:00:00 2001 From: Stanislav Lvovsky Date: Wed, 25 Nov 2020 20:31:06 +0200 Subject: [PATCH 06/12] fix: add logger error messages --- backend/package.json | 5 +++-- backend/src/contributors.ts | 4 ++-- backend/src/extension.ts | 2 +- backend/src/panels/AbstractWebviewPanel.ts | 4 ++-- backend/src/panels/CodeSnippetPanel.ts | 4 ++-- backend/tests/contributors.spec.ts | 2 ++ backend/tests/extension.spec.ts | 3 +-- 7 files changed, 13 insertions(+), 11 deletions(-) diff --git a/backend/package.json b/backend/package.json index 9baf7e4..b5e7385 100644 --- a/backend/package.json +++ b/backend/package.json @@ -117,13 +117,14 @@ }, "dependencies": { "@sap-devx/webview-rpc": "0.2.3", - "@vscode-logging/logger": "1.1.0", + "@vscode-logging/logger": "1.2.1", "datauri": "3.0.0", "fs-extra": "9.0.1", "lodash": "4.17.20", "strip-ansi": "6.0.0", "ws": "7.4.0", - "yeoman-environment": "2.10.3" + "yeoman-environment": "2.10.3", + "@sap/swa-for-sapbas-vsx": "1.1.5" }, "devDependencies": { "flatted": "3.1.0", diff --git a/backend/src/contributors.ts b/backend/src/contributors.ts index 4168699..696ad77 100644 --- a/backend/src/contributors.ts +++ b/backend/src/contributors.ts @@ -1,6 +1,7 @@ import * as vscode from 'vscode'; import * as _ from 'lodash'; + export class Contributors { public static async getSnippet(contributorInfo: any) { const contributorId = _.get(contributorInfo, "contributorId"); @@ -14,8 +15,7 @@ export class Contributors { return snippets.get(snippetName); } catch (error) { const errorMessage = _.get(error, "stack", _.get(error, "message", error)); - console.error(errorMessage); - // TODO: Add Logger.error + console.error(`Could not get '${contributorId}' snippet`, errorMessage); //TODO: use logger.error } } } diff --git a/backend/src/extension.ts b/backend/src/extension.ts index 948fd9b..03dadd5 100644 --- a/backend/src/extension.ts +++ b/backend/src/extension.ts @@ -29,7 +29,7 @@ function registerAndSubscribeCommand(cId: string, cAction: any) { function registerWebviewPanelSerializer(abstractPanel: AbstractWebviewPanel) { vscode.window.registerWebviewPanelSerializer(abstractPanel.viewType, { - async deserializeWebviewPanel(webViewPanel: vscode.WebviewPanel, state?: any) { + async deserializeWebviewPanel(webViewPanel: vscode.WebviewPanel, state?: any) { abstractPanel.setWebviewPanel(webViewPanel, state); } }); diff --git a/backend/src/panels/AbstractWebviewPanel.ts b/backend/src/panels/AbstractWebviewPanel.ts index a523a87..1b81b69 100644 --- a/backend/src/panels/AbstractWebviewPanel.ts +++ b/backend/src/panels/AbstractWebviewPanel.ts @@ -3,7 +3,7 @@ import * as path from 'path'; import * as _ from 'lodash'; import * as fsextra from 'fs-extra'; import { IChildLogger } from '@vscode-logging/logger'; -import { getLogger } from '../logger/logger-wrapper'; +import { getClassLogger } from '../logger/logger-wrapper'; export abstract class AbstractWebviewPanel { @@ -24,7 +24,7 @@ export abstract class AbstractWebviewPanel { this.extensionPath = context.extensionPath; this.mediaPath = path.join(context.extensionPath, "dist", "media"); this.htmlFileName = "index.html"; - this.logger = getLogger(); + this.logger = getClassLogger("AbstractWebviewPanel"); this.disposables = []; } diff --git a/backend/src/panels/CodeSnippetPanel.ts b/backend/src/panels/CodeSnippetPanel.ts index 119dc0b..ff453e0 100644 --- a/backend/src/panels/CodeSnippetPanel.ts +++ b/backend/src/panels/CodeSnippetPanel.ts @@ -26,13 +26,13 @@ export class CodeSnippetPanel extends AbstractWebviewPanel { const contributorInfo = _.get(uiOptions, "contributorInfo", uiOptions); if (_.get(uiOptions, "stateError")) { - console.error(`ERROR: '${contributorInfo.contributorId}' snippet state was not saved. Serialization issue.`); //TODO: use logger.error + this.logger.error(`'${contributorInfo.contributorId}' snippet state could not be saved. JSON.stringify issue.`); return webViewPanel.dispose(); } Contributors.getSnippet(contributorInfo).then(snippet => { if (_.isNil(snippet)) { - console.error(`ERROR: '${contributorInfo.contributorId}' snippet was not found`); //TODO: use logger.error + this.logger.error(`'${contributorInfo.contributorId}' snippet could not be found.`); return this.webViewPanel.dispose(); } diff --git a/backend/tests/contributors.spec.ts b/backend/tests/contributors.spec.ts index ad82724..de1e3ef 100644 --- a/backend/tests/contributors.spec.ts +++ b/backend/tests/contributors.spec.ts @@ -9,6 +9,7 @@ _.set(testVscode, "extensions.all", []); mockVscode(testVscode, "src/contributors.ts"); import { Contributors } from "../src/contributors"; + describe('Contributors unit test', () => { describe('getSnippet', () => { function createCodeSnippetQuestions(): any[] { @@ -118,6 +119,7 @@ describe('Contributors unit test', () => { "contributorId": extensionId, "snippetName": snippetName }; + const res = await Contributors.getSnippet(uiOptions); expect(res).to.be.undefined; }); diff --git a/backend/tests/extension.spec.ts b/backend/tests/extension.spec.ts index d273fd3..e123e21 100644 --- a/backend/tests/extension.spec.ts +++ b/backend/tests/extension.spec.ts @@ -3,7 +3,6 @@ import { expect } from "chai"; import * as sinon from "sinon"; import * as _ from "lodash"; import { mockVscode } from "./mockUtil"; -import { Contributors } from "../src/contributors"; const oRegisteredCommands = {}; const testVscode = { @@ -59,7 +58,7 @@ describe('extension unit test', () => { describe('activate', () => { it("commands registration", () => { loggerWrapperMock.expects("createExtensionLoggerAndSubscribeToLogSettingsChanges"); - loggerWrapperMock.expects("getLogger").once(); + loggerWrapperMock.expects("getClassLogger"); extension.activate(testContext); expect(_.size(_.keys(oRegisteredCommands))).to.be.equal(2); expect( _.get(oRegisteredCommands, "loadCodeSnippet")).to.be.not.undefined; From 9c875852addc9c033c5329745f10abe04d9dfbf7 Mon Sep 17 00:00:00 2001 From: Stanislav Lvovsky Date: Wed, 25 Nov 2020 20:33:20 +0200 Subject: [PATCH 07/12] fix: remove unused dependencies --- backend/package.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/backend/package.json b/backend/package.json index b5e7385..54bd966 100644 --- a/backend/package.json +++ b/backend/package.json @@ -123,11 +123,9 @@ "lodash": "4.17.20", "strip-ansi": "6.0.0", "ws": "7.4.0", - "yeoman-environment": "2.10.3", - "@sap/swa-for-sapbas-vsx": "1.1.5" + "yeoman-environment": "2.10.3" }, "devDependencies": { - "flatted": "3.1.0", "@types/chai": "^4.2.9", "@types/fs-extra": "^8.1.0", "@types/inquirer": "^6.5.0", From 27813613a6c52e6cef8337e055eeef8fa7f21660 Mon Sep 17 00:00:00 2001 From: Stanislav Lvovsky Date: Thu, 26 Nov 2020 08:35:51 +0200 Subject: [PATCH 08/12] fix: add more test + use logger --- backend/package.json | 16 +++--- backend/src/code-snippet.ts | 2 - backend/src/contributors.ts | 24 ++++++--- backend/src/panels/CodeSnippetPanel.ts | 6 ++- backend/tests/contributors.spec.ts | 72 ++++++++++++++++++++++---- backend/tests/extension.spec.ts | 2 +- 6 files changed, 91 insertions(+), 31 deletions(-) diff --git a/backend/package.json b/backend/package.json index 54bd966..8fcf66a 100644 --- a/backend/package.json +++ b/backend/package.json @@ -126,13 +126,13 @@ "yeoman-environment": "2.10.3" }, "devDependencies": { - "@types/chai": "^4.2.9", - "@types/fs-extra": "^8.1.0", + "@types/chai": "^4.2.14", + "@types/fs-extra": "^9.0.4", "@types/inquirer": "^6.5.0", - "@types/lodash": "^4.14.150", - "@types/mocha": "^5.2.7", + "@types/lodash": "^4.14.165", + "@types/mocha": "^7.0.0", "@types/node": "^10.17.21", - "@types/sinon": "^7.5.0", + "@types/sinon": "^9.0.9", "@types/ws": "^6.0.3", "@types/yeoman-environment": "2.10.2", "@typescript-eslint/parser": "^2.30.0", @@ -143,9 +143,9 @@ "typescript": "^3.9.7", "chai": "^4.2.0", "copy-webpack-plugin": "^5.0.5", - "mocha": "^6.2.2", - "nyc": "^14.1.1", - "sinon": "^7.5.0", + "mocha": "^7.0.0", + "nyc": "^15.1.0", + "sinon": "^9.2.1", "ts-loader": "^6.2.1", "ts-node": "^8.9.1", "string-replace-loader": "^2.1.1", diff --git a/backend/src/code-snippet.ts b/backend/src/code-snippet.ts index 0ff2d45..d2bc867 100644 --- a/backend/src/code-snippet.ts +++ b/backend/src/code-snippet.ts @@ -24,7 +24,6 @@ export class CodeSnippet { private currentQuestions: TerminalAdapter.Questions; private snippetName: string; private readonly customQuestionEventHandlers: Map>; - private errorThrown = false; constructor(rpc: IRpc, appEvents: AppEvents, outputChannel: AppLog, logger: IChildLogger, uiOptions: any) { this.rpc = rpc; @@ -175,7 +174,6 @@ export class CodeSnippet { } private async onFailure(snippetrName: string, error: any) { - this.errorThrown = true; const messagePrefix = `${snippetrName} snippet failed.`; const errorMessage: string = await this.logError(error, messagePrefix); this.appEvents.doSnippeDone(false, errorMessage); diff --git a/backend/src/contributors.ts b/backend/src/contributors.ts index 696ad77..100284b 100644 --- a/backend/src/contributors.ts +++ b/backend/src/contributors.ts @@ -1,11 +1,19 @@ import * as vscode from 'vscode'; import * as _ from 'lodash'; +import { IChildLogger } from '@vscode-logging/logger'; +import { getClassLogger } from './logger/logger-wrapper'; export class Contributors { - public static async getSnippet(contributorInfo: any) { + private logger: IChildLogger; + + constructor() { + this.logger = getClassLogger("Contributors"); + } + + public async getSnippet(contributorInfo: any) { const contributorId = _.get(contributorInfo, "contributorId"); - const extension = Contributors.getContributorExtension(contributorId); + const extension = this.getContributorExtension(contributorId); if (extension) { try { const api = await this.getApiPromise(extension as vscode.Extension); @@ -15,27 +23,29 @@ export class Contributors { return snippets.get(snippetName); } catch (error) { const errorMessage = _.get(error, "stack", _.get(error, "message", error)); - console.error(`Could not get '${contributorId}' snippet`, errorMessage); //TODO: use logger.error + this.logger.error(`Could not get '${contributorId}' snippet`, errorMessage); } } } - private static getApiPromise(extension: vscode.Extension): Thenable { + private getApiPromise(extension: vscode.Extension): Thenable { return (extension.isActive ? Promise.resolve(extension.exports) : extension.activate()); } - private static getContributorExtension(contributorId: string) { + private getContributorExtension(contributorId: string) { return _.find(vscode.extensions.all, (extension: vscode.Extension) => { const extensionDependencies: string[] = _.get(extension, "packageJSON.extensionDependencies"); if (_.includes(extensionDependencies, "saposs.code-snippet")) { - if (contributorId === Contributors.getExtensionId(extension)) { + if (contributorId === this.getExtensionId(extension)) { return extension; } } + + this.logger.warn(`Extension '${contributorId}' could not be found.`) }); } - private static getExtensionId(extension: vscode.Extension) { + private getExtensionId(extension: vscode.Extension) { const extensionName: string = _.get(extension, "packageJSON.name"); const extensionPublisher: string = _.get(extension, "packageJSON.publisher"); return `${extensionPublisher}.${extensionName}`; diff --git a/backend/src/panels/CodeSnippetPanel.ts b/backend/src/panels/CodeSnippetPanel.ts index ff453e0..b6d727b 100644 --- a/backend/src/panels/CodeSnippetPanel.ts +++ b/backend/src/panels/CodeSnippetPanel.ts @@ -15,7 +15,6 @@ import { Contributors } from "../contributors"; export class CodeSnippetPanel extends AbstractWebviewPanel { public static CODE_SNIPPET = "Code Snippet"; - private static channel: vscode.OutputChannel; public toggleOutput() { @@ -26,11 +25,12 @@ export class CodeSnippetPanel extends AbstractWebviewPanel { const contributorInfo = _.get(uiOptions, "contributorInfo", uiOptions); if (_.get(uiOptions, "stateError")) { + this.logger.error("test"); this.logger.error(`'${contributorInfo.contributorId}' snippet state could not be saved. JSON.stringify issue.`); return webViewPanel.dispose(); } - Contributors.getSnippet(contributorInfo).then(snippet => { + this.contributors.getSnippet(contributorInfo).then(snippet => { if (_.isNil(snippet)) { this.logger.error(`'${contributorInfo.contributorId}' snippet could not be found.`); return this.webViewPanel.dispose(); @@ -65,12 +65,14 @@ export class CodeSnippetPanel extends AbstractWebviewPanel { private codeSnippet: CodeSnippet; private messages: any; private outputChannel: AppLog; + private contributors: Contributors; public constructor(context: vscode.ExtensionContext) { super(context); this.viewType = "codeSnippet"; this.viewTitle = CodeSnippetPanel.CODE_SNIPPET; this.focusedKey = "codeSnippet.Focused"; + this.contributors = new Contributors(); } private async showOpenFileDialog(currentPath: string): Promise { diff --git a/backend/tests/contributors.spec.ts b/backend/tests/contributors.spec.ts index de1e3ef..43eadbe 100644 --- a/backend/tests/contributors.spec.ts +++ b/backend/tests/contributors.spec.ts @@ -1,6 +1,7 @@ import * as mocha from 'mocha'; import { expect } from 'chai'; import * as _ from 'lodash'; +import * as sinon from "sinon"; import { mockVscode } from './mockUtil'; const testVscode = {}; @@ -8,9 +9,33 @@ _.set(testVscode, "extensions.all", []); mockVscode(testVscode, "src/contributors.ts"); import { Contributors } from "../src/contributors"; +import * as loggerWrapper from "../src/logger/logger-wrapper"; describe('Contributors unit test', () => { + let sandbox: any; + let loggerWrapperMock: any; + const logger = { + error: () => "", + warn: () => "" + }; + + before(() => { + sandbox = sinon.createSandbox(); + }); + + after(() => { + sandbox.restore(); + }); + + beforeEach(() => { + loggerWrapperMock = sandbox.mock(loggerWrapper); + }); + + afterEach(() => { + loggerWrapperMock.verify(); + }); + describe('getSnippet', () => { function createCodeSnippetQuestions(): any[] { const questions: any[] = [{ @@ -78,10 +103,11 @@ describe('Contributors unit test', () => { } }; const extensionId = "BLABLA3.vscode-snippet-contrib"; - + it("receives no contributorId and no snippetName ---> returns undefined snippet", async () => { - const uiOptions = {}; - const snippet = await Contributors.getSnippet(uiOptions); + loggerWrapperMock.expects("getClassLogger").returns(logger); + const contributors = new Contributors(); + const snippet = await contributors.getSnippet({}); expect(snippet).to.be.undefined; }); @@ -92,7 +118,10 @@ describe('Contributors unit test', () => { "contributorId": extensionId, "snippetName": snippetName }; - const snippet = await Contributors.getSnippet(uiOptions); + + loggerWrapperMock.expects("getClassLogger").returns(logger); + const contributors = new Contributors(); + const snippet = await contributors.getSnippet(uiOptions); expect(snippet.getMessages()).to.deep.equal(messageValue); }); @@ -104,7 +133,10 @@ describe('Contributors unit test', () => { "contributorId": extensionId, "snippetName": snippetName }; - const snippet = await Contributors.getSnippet(uiOptions); + + loggerWrapperMock.expects("getClassLogger").returns(logger); + const contributors = new Contributors(); + const snippet = await contributors.getSnippet(uiOptions); expect(snippet.getMessages()).to.deep.equal(messageValue); }); @@ -119,12 +151,17 @@ describe('Contributors unit test', () => { "contributorId": extensionId, "snippetName": snippetName }; - - const res = await Contributors.getSnippet(uiOptions); + + loggerWrapperMock.expects("getClassLogger").returns(logger); + const errorSpy = sinon.spy(logger, "error"); + const contributors = new Contributors(); + const res = await contributors.getSnippet(uiOptions); expect(res).to.be.undefined; + expect(errorSpy.calledOnce).to.be.true; + errorSpy.restore(); }); - it("no contributer extension not found", async () => { + it("contributer extension not found", async () => { api.packageJSON = { name: "vscode-snippet-contrib", publisher: "BLABLA3", @@ -136,11 +173,17 @@ describe('Contributors unit test', () => { "contributorId": extensionId, "snippetName": snippetName }; - const res = await Contributors.getSnippet(uiOptions); + + loggerWrapperMock.expects("getClassLogger").returns(logger); + const contributors = new Contributors(); + const warnSpy = sinon.spy(logger, "warn"); + const res = await contributors.getSnippet(uiOptions); expect(res).to.be.undefined; + expect(warnSpy.calledOnce).to.be.true; + warnSpy.restore(); }); - it("no contributer extension not found by contributorId", async () => { + it("contributer extension not found by contributorId", async () => { api.packageJSON = { name: "vscode-snippet-contrib", publisher: "BLABLA3", @@ -152,8 +195,15 @@ describe('Contributors unit test', () => { "contributorId": extensionId + "-other", "snippetName": snippetName }; - const res = await Contributors.getSnippet(uiOptions); + + loggerWrapperMock.expects("getClassLogger").returns(logger); + const warnSpy = sinon.spy(logger, "warn"); + const contributors = new Contributors(); + const res = await contributors.getSnippet(uiOptions); expect(res).to.be.undefined; + const warnMessage = `Extension '${uiOptions.contributorId}' could not be found.`; + expect(warnSpy.calledOnce).to.be.true; + warnSpy.restore(); }); }); }); diff --git a/backend/tests/extension.spec.ts b/backend/tests/extension.spec.ts index e123e21..3289c34 100644 --- a/backend/tests/extension.spec.ts +++ b/backend/tests/extension.spec.ts @@ -58,7 +58,7 @@ describe('extension unit test', () => { describe('activate', () => { it("commands registration", () => { loggerWrapperMock.expects("createExtensionLoggerAndSubscribeToLogSettingsChanges"); - loggerWrapperMock.expects("getClassLogger"); + loggerWrapperMock.expects("getClassLogger").twice(); extension.activate(testContext); expect(_.size(_.keys(oRegisteredCommands))).to.be.equal(2); expect( _.get(oRegisteredCommands, "loadCodeSnippet")).to.be.not.undefined; From edfc275ebd2c4a6d1a01b17dc82bd214f998a7e7 Mon Sep 17 00:00:00 2001 From: Stanislav Lvovsky Date: Thu, 26 Nov 2020 08:38:28 +0200 Subject: [PATCH 09/12] fix: lint errors --- backend/src/contributors.ts | 4 ++-- backend/src/panels/CodeSnippetPanel.ts | 2 +- backend/tests/code-snippet.spec.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/src/contributors.ts b/backend/src/contributors.ts index 100284b..ebdaaf1 100644 --- a/backend/src/contributors.ts +++ b/backend/src/contributors.ts @@ -5,7 +5,7 @@ import { getClassLogger } from './logger/logger-wrapper'; export class Contributors { - private logger: IChildLogger; + private readonly logger: IChildLogger; constructor() { this.logger = getClassLogger("Contributors"); @@ -41,7 +41,7 @@ export class Contributors { } } - this.logger.warn(`Extension '${contributorId}' could not be found.`) + this.logger.warn(`Extension '${contributorId}' could not be found.`); }); } diff --git a/backend/src/panels/CodeSnippetPanel.ts b/backend/src/panels/CodeSnippetPanel.ts index b6d727b..a250ca6 100644 --- a/backend/src/panels/CodeSnippetPanel.ts +++ b/backend/src/panels/CodeSnippetPanel.ts @@ -65,7 +65,7 @@ export class CodeSnippetPanel extends AbstractWebviewPanel { private codeSnippet: CodeSnippet; private messages: any; private outputChannel: AppLog; - private contributors: Contributors; + private readonly contributors: Contributors; public constructor(context: vscode.ExtensionContext) { super(context); diff --git a/backend/tests/code-snippet.spec.ts b/backend/tests/code-snippet.spec.ts index ae766b7..770ca78 100644 --- a/backend/tests/code-snippet.spec.ts +++ b/backend/tests/code-snippet.spec.ts @@ -152,7 +152,7 @@ describe('codeSnippet unit test', () => { }); it("invalid uiOptions", async () => { - codeSnippet["uiOptions"].test = codeSnippet["uiOptions"] + codeSnippet["uiOptions"].test = codeSnippet["uiOptions"]; const state = await codeSnippet["getState"](); expect(state.stateError).to.be.true; }); From 31ec1d4346ab9763604c0c1a9bc1d8dfc324aa4e Mon Sep 17 00:00:00 2001 From: Stanislav Lvovsky Date: Thu, 26 Nov 2020 08:40:27 +0200 Subject: [PATCH 10/12] fix: improve comment --- backend/src/code-snippet.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/code-snippet.ts b/backend/src/code-snippet.ts index d2bc867..da94afe 100644 --- a/backend/src/code-snippet.ts +++ b/backend/src/code-snippet.ts @@ -54,7 +54,7 @@ export class CodeSnippet { // valiation for rpc JSON.stringify(state); } catch (error) { - // only stateError and contributorInfo will be saved + // save stateError and remove contributorInfo.context state = _.omit(state, ["contributorInfo.context"]); _.set(state, "stateError", true); } From 906f9adbee14f9ed78444cf7e2aa328cfc3a7268 Mon Sep 17 00:00:00 2001 From: Stanislav Lvovsky Date: Thu, 26 Nov 2020 09:21:09 +0200 Subject: [PATCH 11/12] fix: improve tests --- backend/.nycrc.json | 43 +++++++++----- backend/mocha.opts | 4 -- backend/package.json | 2 +- backend/tests/code-snippet.spec.ts | 92 ++++++++++++++++-------------- 4 files changed, 79 insertions(+), 62 deletions(-) delete mode 100644 backend/mocha.opts diff --git a/backend/.nycrc.json b/backend/.nycrc.json index 44cdd24..92fba09 100644 --- a/backend/.nycrc.json +++ b/backend/.nycrc.json @@ -1,15 +1,30 @@ { - "require": ["ts-node/register/transpile-only"], - "include": ["src/**/*.ts"], - "exclude": ["src/logger/*.ts", "src/panels/*.ts", "src/webSocketServer/*.ts", "src/output-channel-log.ts", "src/youi-adapter.ts"], - "reporter": ["lcov", "text"], - "extension": [".ts"], - "all": true, - "temp-dir": "./reports/.nyc_output", - "report-dir": "./reports/coverage", - "check-coverage": true, - "branches": 98, - "lines": 99, - "functions": 97, - "statements": 99 - } + "require": [ + "ts-node/register/transpile-only" + ], + "include": [ + "src/**/*.ts" + ], + "exclude": [ + "src/logger/*.ts", + "src/panels/*.ts", + "src/webSocketServer/*.ts", + "src/output-channel-log.ts", + "src/youi-adapter.ts" + ], + "reporter": [ + "lcov", + "text" + ], + "extension": [ + ".ts" + ], + "all": true, + "temp-dir": "./reports/.nyc_output", + "report-dir": "./reports/coverage", + "check-coverage": true, + "branches": 98, + "lines": 99, + "functions": 97, + "statements": 99 +} diff --git a/backend/mocha.opts b/backend/mocha.opts deleted file mode 100644 index bdab613..0000000 --- a/backend/mocha.opts +++ /dev/null @@ -1,4 +0,0 @@ ---require ts-node/register/transpile-only ---require source-map-support/register ---recursive "tests/**/*.spec.ts" ---timeout 80000 \ No newline at end of file diff --git a/backend/package.json b/backend/package.json index 8fcf66a..c209a08 100644 --- a/backend/package.json +++ b/backend/package.json @@ -110,7 +110,7 @@ "compile": "tsc -p ./", "watch": "tsc -watch -p ./", "package": "npm run webpack && vsce package .", - "test": "nyc mocha -p tsconfig.json --opts ./mocha.opts", + "test": "nyc mocha -p tsconfig.json --recursive tests/**/*.spec.ts", "ws:run": "node ./out/src/webSocketServer/index.js", "lint": "eslint . --ext .ts,.tsx --cache", "lint:fix": "eslint . --ext .ts,.tsx --cache --fix" diff --git a/backend/tests/code-snippet.spec.ts b/backend/tests/code-snippet.spec.ts index 770ca78..e9c2c53 100644 --- a/backend/tests/code-snippet.spec.ts +++ b/backend/tests/code-snippet.spec.ts @@ -4,7 +4,7 @@ const datauri = require("datauri"); // eslint-disable-line @typescript-eslint/no import * as fsextra from "fs-extra"; import { expect } from "chai"; import * as _ from "lodash"; -import {CodeSnippet} from "../src/code-snippet"; +import { CodeSnippet } from "../src/code-snippet"; import { AppLog } from "../src/app-log"; import { AppEvents } from '../src/app-events'; import { IMethod, IPromiseCallbacks, IRpc } from "@sap-devx/webview-rpc/out.ext/rpc-common"; @@ -31,30 +31,30 @@ describe('codeSnippet unit test', () => { } } class TestRpc implements IRpc { - public timeout: number; + public timeout: number; public promiseCallbacks: Map; public methods: Map; public sendRequest(): void { return; - } + } public sendResponse(): void { return; - } + } public setResponseTimeout(): void { return; } public registerMethod(): void { return; - } + } public unregisterMethod(): void { return; - } + } public listLocalMethods(): string[] { return []; } public handleResponse(): void { return; - } + } public listRemoteMethods(): Promise { return Promise.resolve([]); } @@ -68,31 +68,31 @@ describe('codeSnippet unit test', () => { class TestOutputChannel implements AppLog { public log(): void { return; - } + } public writeln(): void { return; - } + } public create(): void { return; - } + } public force(): void { return; - } + } public conflict(): void { return; - } + } public identical(): void { return; - } + } public skip(): void { return; - } + } public showOutput(): boolean { return false; - } + } } - const testLogger = { debug: () => "", error: () => "", fatal: () => "", warn: () => "", info: () => "", trace: () => "", getChildLogger: () => ({} as IChildLogger)}; + const testLogger = { debug: () => "", error: () => "", fatal: () => "", warn: () => "", info: () => "", trace: () => "", getChildLogger: () => ({} as IChildLogger) }; const snippet: any = { getMessages() { @@ -109,7 +109,7 @@ describe('codeSnippet unit test', () => { const rpc = new TestRpc(); const outputChannel = new TestOutputChannel(); const appEvents = new TestEvents(); - const uiOptions = {messages: {title: "snippet title"}, snippet: snippet}; + const uiOptions = { messages: { title: "snippet title" }, snippet: snippet }; const codeSnippet: CodeSnippet = new CodeSnippet(rpc, appEvents, outputChannel, testLogger, uiOptions); before(() => { @@ -157,13 +157,13 @@ describe('codeSnippet unit test', () => { expect(state.stateError).to.be.true; }); }); - + describe("receiveIsWebviewReady", () => { it("flow is successfull", async () => { rpcMock.expects("invoke").withArgs("showPrompt").resolves( - {actionName: "actionName"}, - {actionTemplate: "OData action"}, - {actionType: "Create entity"}); + { actionName: "actionName" }, + { actionTemplate: "OData action" }, + { actionType: "Create entity" }); appEventsMock.expects("doApply"); await codeSnippet["receiveIsWebviewReady"](); }); @@ -217,9 +217,9 @@ describe('codeSnippet unit test', () => { describe("answersUtils", () => { it("setDefaults", () => { const questions = [ - {name: "q1", default: "a"}, - {name: "q2", default: () => { return "b";}}, - {name: "q3"} + { name: "q1", default: "a" }, + { name: "q2", default: () => { return "b"; } }, + { name: "q3" } ]; const answers = { q1: "x", @@ -252,9 +252,9 @@ describe('codeSnippet unit test', () => { }; }; const codeSnippetInstance: CodeSnippet = new CodeSnippet(rpc, appEvents, outputChannel, testLogger, {}); - const questions = [{name: "q1"}]; + const questions = [{ name: "q1" }]; const response = await codeSnippetInstance.showPrompt(questions); - expect (response.firstName).to.equal(firstName); + expect(response.firstName).to.equal(firstName); }); }); @@ -288,7 +288,7 @@ describe('codeSnippet unit test', () => { }; const questions = [ { - name:"q1", + name: "q1", guiType: "questionType" } ]; @@ -311,25 +311,29 @@ describe('codeSnippet unit test', () => { }; const codeSnippetInstance: CodeSnippet = new CodeSnippet(rpc, appEvents, outputChannel, testLogger, {}); codeSnippetInstance.registerCustomQuestionEventHandler("questionType", "testEvent", testEventFunction); - codeSnippetInstance["currentQuestions"] = [{name:"question1", guiType: "questionType"}]; + codeSnippetInstance["currentQuestions"] = [{ name: "question1", guiType: "questionType" }]; const response = await codeSnippetInstance["evaluateMethod"](null, "question1", "testEvent"); expect(response).to.be.true; }); it("question method is called", async () => { const codeSnippetInstance: CodeSnippet = new CodeSnippet(rpc, appEvents, outputChannel, testLogger, {}); - codeSnippetInstance["currentQuestions"] = [{name:"question1", method1:()=>{ - return true; - }}]; + codeSnippetInstance["currentQuestions"] = [{ + name: "question1", method1: () => { + return true; + } + }]; const response = await codeSnippetInstance["evaluateMethod"](null, "question1", "method1"); expect(response).to.be.true; }); it("no relevant question", async () => { const codeSnippetInstance: CodeSnippet = new CodeSnippet(rpc, appEvents, outputChannel, testLogger, {}); - codeSnippetInstance["currentQuestions"] = [{name:"question1", method1:()=>{ - return true; - }}]; + codeSnippetInstance["currentQuestions"] = [{ + name: "question1", method1: () => { + return true; + } + }]; const response = await codeSnippetInstance["evaluateMethod"](null, "question2", "method2"); expect(response).to.be.undefined; }); @@ -344,12 +348,14 @@ describe('codeSnippet unit test', () => { const codeSnippetInstance: CodeSnippet = new CodeSnippet(rpc, appEvents, outputChannel, testLogger, {}); codeSnippetInstance["gen"] = Object.create({}); codeSnippetInstance["gen"].options = {}; - codeSnippetInstance["currentQuestions"] = [{name:"question1", method1:()=>{ - throw new Error("Error"); - }}]; + codeSnippetInstance["currentQuestions"] = [{ + name: "question1", method1: () => { + throw new Error("Error"); + } + }]; try { await codeSnippetInstance["evaluateMethod"](null, "question1", "method1"); - } catch(e) { + } catch (e) { expect(e.toString()).to.contain("method1"); } }); @@ -361,7 +367,7 @@ describe('codeSnippet unit test', () => { let codeSnippetInstance: CodeSnippet; beforeEach(() => { - codeSnippetInstance = new CodeSnippet(rpc, appEvents, outputChannel, testLogger, {messages: {title: title}}); + codeSnippetInstance = new CodeSnippet(rpc, appEvents, outputChannel, testLogger, { messages: { title: title } }); codeSnippetInstanceMock = sandbox.mock(codeSnippetInstance); }); @@ -396,10 +402,10 @@ describe('codeSnippet unit test', () => { onFailureSpy.restore(); }); }); - + describe("createCodeSnippetWorkspaceEdit", () => { it("snippet has getWorkspaceEdit ---> call getWorkspaceEdit", async () => { - const myCodeSnippet = new CodeSnippet(rpc, appEvents, outputChannel, testLogger, {snippet: snippet}); + const myCodeSnippet = new CodeSnippet(rpc, appEvents, outputChannel, testLogger, { snippet: snippet }); const we = await myCodeSnippet["createCodeSnippetWorkspaceEdit"]({}); expect(we).to.be.equal("getWorkspaceEdit"); }); @@ -413,7 +419,7 @@ describe('codeSnippet unit test', () => { describe("createCodeSnippetQuestions", () => { it("snippet has getQuestions ---> call getQuestions", async () => { - const myCodeSnippet = new CodeSnippet(rpc, appEvents, outputChannel, testLogger, {snippet: snippet}); + const myCodeSnippet = new CodeSnippet(rpc, appEvents, outputChannel, testLogger, { snippet: snippet }); const we = await myCodeSnippet["createCodeSnippetQuestions"](); expect(we).to.be.equal("createCodeSnippetQuestions"); }); @@ -429,7 +435,7 @@ describe('codeSnippet unit test', () => { codeSnippetInstance.registerCustomQuestionEventHandler("questionType", "testEvent1", testEventFunction); expect(codeSnippetInstance["customQuestionEventHandlers"].size).to.be.equal(1); - codeSnippetInstance.registerCustomQuestionEventHandler("questionType", "testEvent2", testEventFunction); + codeSnippetInstance.registerCustomQuestionEventHandler("questionType", "testEvent2", testEventFunction); expect(codeSnippetInstance["customQuestionEventHandlers"].size).to.be.equal(1); }); From 748d1cd64c6360c1d4e3c8d92b52f74109d5a2bc Mon Sep 17 00:00:00 2001 From: Stanislav Lvovsky Date: Thu, 26 Nov 2020 09:37:30 +0200 Subject: [PATCH 12/12] fix: add test --- backend/tests/code-snippet.spec.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/backend/tests/code-snippet.spec.ts b/backend/tests/code-snippet.spec.ts index e9c2c53..8804764 100644 --- a/backend/tests/code-snippet.spec.ts +++ b/backend/tests/code-snippet.spec.ts @@ -423,6 +423,12 @@ describe('codeSnippet unit test', () => { const we = await myCodeSnippet["createCodeSnippetQuestions"](); expect(we).to.be.equal("createCodeSnippetQuestions"); }); + + it("no snippet provided ---> call getQuestions", async () => { + const myCodeSnippet = new CodeSnippet(rpc, appEvents, outputChannel, testLogger, { snippet: null }); + const we = await myCodeSnippet["createCodeSnippetQuestions"](); + expect(we).to.be.empty; + }); }); describe("registerCustomQuestionEventHandler", () => {