Skip to content

Commit

Permalink
catch question exception (#100)
Browse files Browse the repository at this point in the history
* catch question exception

* Update QuestionTypeSelector.vue

* remove bootstrap

* add test

* fix solution

* write error to log

* toggle log

* version update
  • Loading branch information
slavik-lvovsky authored Jan 15, 2020
1 parent f81ac36 commit 49081a1
Show file tree
Hide file tree
Showing 10 changed files with 93 additions and 84 deletions.
13 changes: 7 additions & 6 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"license": "Apache 2.0",
"description": "Provide rich user experience for Yeoman generators using VSCode extension or the browser",
"repository": "https://github.com/SAP/yeoman-ui",
"version": "0.0.22",
"version": "0.0.23",
"engines": {
"vscode": "^1.38.0"
},
Expand Down Expand Up @@ -50,11 +50,12 @@
"yeoman-environment": "^2.7.0",
"titleize": "^1.0.1",
"humanize-string": "^1.0.2",
"fs-extra": "^8.1.0"
"fs-extra": "^8.1.0",
"chalk": "^3.0.0"
},
"devDependencies": {
"@types/fs-extra": "^8.0.1",
"@types/chai": "^4.2.5",
"@types/fs-extra": "^8.0.1",
"@types/inquirer": "^6.5.0",
"@types/lodash": "^4.14.145",
"@types/mocha": "^5.2.7",
Expand All @@ -63,6 +64,7 @@
"@types/strip-ansi": "^5.2.1",
"@types/ws": "^6.0.3",
"@types/yeoman-environment": "^2.3.2",
"bufferutil": "^4.0.1",
"chai": "^4.2.0",
"copy-webpack-plugin": "^5.0.5",
"mocha": "^6.2.2",
Expand All @@ -74,11 +76,10 @@
"tslint-config-prettier": "^1.18.0",
"tslint-no-unused-expression-chai": "^0.1.4",
"typescript": "^3.7.3",
"utf-8-validate": "^5.0.2",
"vsce": "^1.68.0",
"vscode": "^1.1.28",
"webpack": "^4.41.2",
"webpack-cli": "^3.3.10",
"bufferutil": "^4.0.1",
"utf-8-validate": "^5.0.2"
"webpack-cli": "^3.3.10"
}
}
5 changes: 5 additions & 0 deletions backend/src/yeomanui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export class YeomanUI {
this.rpc.registerMethod({ func: this.runGenerator, thisArg: this });
this.rpc.registerMethod({ func: this.evaluateMethod, thisArg: this });
this.rpc.registerMethod({ func: this.toggleLog, thisArg: this });
this.rpc.registerMethod({ func: this.logMessage, thisArg: this });
this.youiAdapter = new YouiAdapter(logger);
this.youiAdapter.setYeomanUI(this);
this.promptCount = 0;
Expand Down Expand Up @@ -209,6 +210,10 @@ export class YeomanUI {
return this.logger.showLog();
}

public logMessage(message: string): void {
this.logger.log(message);
}

public async showPrompt(questions: Environment.Adapter.Questions<any>): Promise<inquirer.Answers> {
this.currentQuestions = questions;

Expand Down
7 changes: 7 additions & 0 deletions backend/tests/yeomanui.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,13 @@ describe('yeomanui unit test', () => {
expect(res).to.be.false;
});

it("logMessage", () => {
const yeomanUi: YeomanUI = new YeomanUI(rpc, logger);
const res = yeomanUi.logMessage("message");
// tslint:disable-next-line: no-unused-expression
expect(res).to.be.undefined;
});

describe("getEnv", () => {
const yeomanUi: YeomanUI = new YeomanUI(rpc, logger);
const testEnv = yeomanUi["getEnv"]();
Expand Down
4 changes: 1 addition & 3 deletions frontend/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "yeoman-ui-frontend",
"displayName": "Yeoman UI Frontend",
"version": "0.1.9",
"version": "0.2.3",
"publisher": "SAP",
"license": "Apache 2.0",
"description": "Frontend for the yeoman UI framework",
Expand All @@ -15,8 +15,6 @@
"precommit": "lint-staged"
},
"dependencies": {
"bootstrap": "^4.3.1",
"bootstrap-vue": "^2.0.2",
"core-js": "2.6.6",
"jquery": "3.4.1",
"vue-loading-overlay": "^3.2.0",
Expand Down
100 changes: 53 additions & 47 deletions frontend/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -187,57 +187,63 @@ export default {
},
async updateQuestion(question) {
const newAnswers = this.currentPrompt.answers
if (question.when === FUNCTION) {
question.isWhen = await this.rpc.invoke("evaluateMethod", [
[newAnswers],
question.name,
"when"
]);
}
if (question.isWhen === true) {
if (question.filter === FUNCTION) {
question.answer = await this.rpc.invoke("evaluateMethod", [
[question.answer],
question.name,
"filter"
]);
}
if (question._default === FUNCTION) {
question.default = await this.rpc.invoke("evaluateMethod", [
[newAnswers],
question.name,
"default"
]);
if (question.answer === undefined) {
question.answer = question.default;
}
}
if (question._message === FUNCTION) {
question.message = await this.rpc.invoke("evaluateMethod", [
[newAnswers],
question.name,
"message"
]);
}
if (question._choices === FUNCTION) {
question.choices = await this.rpc.invoke("evaluateMethod", [
try {
if (question.when === FUNCTION) {
question.isWhen = await this.rpc.invoke("evaluateMethod", [
[newAnswers],
question.name,
"choices"
"when"
]);
}
if (question.validate === FUNCTION) {
const response = await this.rpc.invoke("evaluateMethod", [
[question.answer, newAnswers],
question.name,
"validate"
]);
question.isValid = _.isString(response) ? false : response;
question.validationMessage = _.isString(response)
? response
: undefined;
if (question.isWhen === true) {
if (question.filter === FUNCTION) {
question.answer = await this.rpc.invoke("evaluateMethod", [
[question.answer],
question.name,
"filter"
]);
}
if (question._default === FUNCTION) {
question.default = await this.rpc.invoke("evaluateMethod", [
[newAnswers],
question.name,
"default"
]);
if (question.answer === undefined) {
question.answer = question.default;
}
}
if (question._message === FUNCTION) {
question.message = await this.rpc.invoke("evaluateMethod", [
[newAnswers],
question.name,
"message"
]);
}
if (question._choices === FUNCTION) {
question.choices = await this.rpc.invoke("evaluateMethod", [
[newAnswers],
question.name,
"choices"
]);
}
if (question.validate === FUNCTION) {
const response = await this.rpc.invoke("evaluateMethod", [
[question.answer, newAnswers],
question.name,
"validate"
]);
question.isValid = _.isString(response) ? false : response;
question.validationMessage = _.isString(response)
? response
: undefined;
}
}
} catch (error) {
const message = `'${question.name}' question update of generator ${this.generatorName} has failed: ${_.get(error, "message", error)}`;
await this.rpc.invoke("logMessage", [message]);
this.rpc.invoke("toggleLog", [{}]);
}
},
next() {
Expand Down Expand Up @@ -330,6 +336,7 @@ export default {
}
this.$set(question, "answer", answer);
this.$set(question, "isValid", true);
this.$set(question, "doNotShow", false);
this.$set(question, "validationMessage", true);
this.$set(question, "isWhen", question.when !== FUNCTION);
Expand Down Expand Up @@ -485,4 +492,3 @@ div.bottom-right-col .progress-buttons-row {
padding-top: 4px;
}
</style>

2 changes: 1 addition & 1 deletion frontend/src/components/QuestionTypeSelector.vue
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,4 @@ export default {
selectGenerator: Function
}
};
</script>
</script>
5 changes: 0 additions & 5 deletions frontend/src/components/QuestionTypes/QuestionInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,6 @@ export default {
},
computed: {
type() {
// mapping between
// https://www.npmjs.com/package/inquirer#question
// and
// https://bootstrap-vue.js.org/docs/components/form-input/
// const questionType = _.get(this.currentQuestion, "type")
const type = this.currentQuestion.type;
return type === "input" ? "text" : type;
}
Expand Down
21 changes: 19 additions & 2 deletions frontend/tests/App.spec.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import {initComponent, destroy} from './Utils'
import App from '../src/App.vue';
import Vue from 'vue'
import BootstrapVue from 'bootstrap-vue'
import Vuetify from 'vuetify'
import { WebSocket } from 'mock-socket'

Vue.use(BootstrapVue)
Vue.use(Vuetify)
global.WebSocket = WebSocket

Expand Down Expand Up @@ -148,6 +146,25 @@ describe('App.vue', () => {
expect(wrapper.vm.prompts[0].questions[0].isValid).toBe(true)
expect(wrapper.vm.prompts[0].questions[0].validationMessage ).toBeUndefined()
})

test('invoke for question that throws error', async () => {
wrapper.vm.rpc = {
invoke: jest.fn().mockRejectedValueOnce("test error").mockResolvedValue()
}
wrapper.vm.prompts = [{
questions: [{
name: 'validateQ', validate: '__Function', answer: 'validateAnswer', isWhen: true, doNotShow: false
}],
answers: {}
}]
wrapper.vm.promptIndex = 0

const invokeSpy = jest.spyOn(wrapper.vm.rpc, 'invoke')
await wrapper.vm.updateQuestionsFromIndex(0)
expect(invokeSpy).toHaveBeenCalledWith('evaluateMethod', [["validateAnswer", {"validateQ": "validateAnswer"}], 'validateQ', 'validate'])
expect(invokeSpy).toHaveBeenCalledWith('logMessage', ["'validateQ' question update of generator has failed: test error"])
expect(invokeSpy).toHaveBeenCalledWith('toggleLog', [{}])
})
})

describe('setQuestionProps - method', () => {
Expand Down
2 changes: 0 additions & 2 deletions frontend/tests/Utils.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { mount, shallowMount } from '@vue/test-utils'
import Vue from 'vue'
import BootstrapVue from 'bootstrap-vue'
import Vuetify from 'vuetify'
Vue.use(Vuetify);
Vue.use(BootstrapVue)

import {
createLocalVue
Expand Down
18 changes: 0 additions & 18 deletions frontend/tests/components/QuestionTypes/GeneratorSelection.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,24 +32,6 @@ describe('GeneratorSelection.vue', () => {
expect(wrapper.vm.getImageUrl({})).toBe("testPublicPath-generator.png")
})
})

describe.skip('emitSelection - method', () => {
beforeEach(() => {
wrapper = initComponent(GeneratorSelection, {
currentQuestion: {
choices: [{imageUrl: 'testImageUrl', name: 'testName'}]
},
selectGenerator: jest.fn()
}, true)
})

test('on click event of vCard', async () => {
wrapper.find('.v-card').trigger('click')
await wrapper.vm.$nextTick()
expect(wrapper.emitted('generatorSelected')).toBeTruthy()
expect(wrapper.vm.$options.propsData.currentQuestion.answer).toBe('testName')
})
})

describe('select - method', () => {
beforeEach(() => {
Expand Down

0 comments on commit 49081a1

Please sign in to comment.