Skip to content

Commit

Permalink
fix: fast clicking on next button leads to ui steps problem (#589)
Browse files Browse the repository at this point in the history
* chore: fix formatting

* chore: update test

* chore: fix formatting

* chore: improve logic

* chore: fix formatting

* chore: fix formatting
  • Loading branch information
slavik-lvovsky authored May 20, 2021
1 parent 0619053 commit 9ea48b6
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 135 deletions.
134 changes: 29 additions & 105 deletions packages/frontend/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,27 +23,14 @@

<v-row class="main-row ma-0 pa-0">
<v-col class="left-col ma-0 pa-0" cols="3">
<Navigation
v-if="prompts.length"
:promptIndex="promptIndex"
:prompts="prompts"
@onGotoStep="gotoStep"
/>
<Navigation v-if="prompts.length" :promptIndex="promptIndex" :prompts="prompts" @onGotoStep="gotoStep" />
</v-col>
<v-col cols="9" class="right-col">
<v-row class="prompts-col">
<v-col>
<Done
v-if="isDone"
:doneStatus="doneStatus"
:doneMessage="doneMessage"
:donePath="donePath"
/>
<Done v-if="isDone" :doneStatus="doneStatus" :doneMessage="doneMessage" :donePath="donePath" />

<PromptInfo
v-if="currentPrompt && !isDone"
:currentPrompt="currentPrompt"
/>
<PromptInfo v-if="currentPrompt && !isDone" :currentPrompt="currentPrompt" />
<v-slide-x-transition>
<Form
ref="form"
Expand Down Expand Up @@ -75,32 +62,16 @@
>
<v-icon left>mdi-chevron-left</v-icon>{{ backButtonText }}
</v-btn>
<v-btn
id="next"
:disabled="!stepValidated"
@click="next"
style="min-width: 90px"
>
<v-btn id="next" :disabled="!stepValidated" @click="next" style="min-width: 90px">
{{ nextButtonText }}
<v-icon right v-if="nextButtonText !== `Finish`"
>mdi-chevron-right</v-icon
>
<v-icon right v-if="nextButtonText !== `Finish`">mdi-chevron-right</v-icon>
</v-btn>
</div>
<div class="prompt-message" v-if="toShowPromptMessage">
<img
style="vertical-align: middle; padding-left: 12px"
:src="promptMessageIcon"
alt=""
/>
<v-tooltip
right
:disabled="promptMessageToDisplay.length < this.messageMaxLength"
>
<img style="vertical-align: middle; padding-left: 12px" :src="promptMessageIcon" alt="" />
<v-tooltip right :disabled="promptMessageToDisplay.length < this.messageMaxLength">
<template v-slot:activator="{ on }">
<span :class="promptMessageClass" v-on="on">{{
showPrompt
}}</span>
<span :class="promptMessageClass" v-on="on">{{ showPrompt }}</span>
</template>
<span>{{ promptMessageToDisplay }}</span>
</v-tooltip>
Expand All @@ -112,11 +83,7 @@

<!-- TODO Handle scroll of above content when console is visible. low priority because it is for localhost console only -->
<v-card :class="consoleClass" v-show="showConsole">
<v-footer
absolute
class="font-weight-medium"
style="max-height: 300px; overflow-y: auto"
>
<v-footer absolute class="font-weight-medium" style="max-height: 300px; overflow-y: auto">
<v-col class cols="12">
<div id="logArea" placeholder="No log entry">{{ logText }}</div>
</v-col>
Expand Down Expand Up @@ -206,8 +173,7 @@ export default {
},
nextButtonText() {
if (
(!this.selectGeneratorPromptExists() &&
this.promptIndex === _.size(this.promptsInfoToDisplay) - 1) ||
(!this.selectGeneratorPromptExists() && this.promptIndex === _.size(this.promptsInfoToDisplay) - 1) ||
(this.selectGeneratorPromptExists() &&
this.promptIndex > 0 &&
this.promptIndex === _.size(this.promptsInfoToDisplay)) ||
Expand All @@ -221,15 +187,11 @@ export default {
},
isLoadingColor() {
return (
getComputedStyle(document.documentElement).getPropertyValue(
"--vscode-progressBar-background"
) || "#0e70c0"
getComputedStyle(document.documentElement).getPropertyValue("--vscode-progressBar-background") || "#0e70c0"
);
},
headerTitle() {
const titleSuffix = _.isEmpty(this.generatorPrettyName)
? ""
: ` - ${this.generatorPrettyName}`;
const titleSuffix = _.isEmpty(this.generatorPrettyName) ? "" : ` - ${this.generatorPrettyName}`;
return `${_.get(this.messages, "yeoman_ui_title")}${titleSuffix}`;
},
currentPrompt() {
Expand Down Expand Up @@ -269,9 +231,7 @@ export default {
showPromptMessage(message, type, image) {
this.promptMessageToDisplay = message;
this.showPrompt =
message.length < this.messageMaxLength
? message
: message.substr(0, this.messageMaxLength) + "...";
message.length < this.messageMaxLength ? message : message.substr(0, this.messageMaxLength) + "...";
this.toShowPromptMessage = true;
this.promptMessageIcon = image;
Expand All @@ -287,8 +247,7 @@ export default {
this.expectedShowBusyIndicator =
_.isEmpty(this.prompts) ||
(this.currentPrompt &&
(this.currentPrompt.status === PENDING ||
this.currentPrompt.status === EVALUATING) &&
(this.currentPrompt.status === PENDING || this.currentPrompt.status === EVALUATING) &&
!this.isDone);
if (this.expectedShowBusyIndicator) {
setTimeout(() => {
Expand Down Expand Up @@ -333,23 +292,16 @@ export default {
}
},
getInProgressStepName() {
return this.isWriting
? _.get(this.messages, "step_is_generating")
: _.get(this.messages, "step_is_pending");
return this.isWriting ? _.get(this.messages, "step_is_generating") : _.get(this.messages, "step_is_pending");
},
next() {
if (!this.stepValidated || this.resolve === null) {
if (this.resolve === null) {
return;
}
this.stepValidated = false;
this.toShowPromptMessage = false;
try {
this.resolve(this.currentPrompt.answers);
} catch (error) {
this.rpc.invoke("logError", [error]);
this.reject(error);
}
this.resolve(this.currentPrompt.answers);
if (this.promptIndex >= _.size(this.prompts) - 1) {
const prompt = {
Expand All @@ -365,23 +317,14 @@ export default {
this.prompts[this.promptIndex].active = true;
},
onAnswered(answers, issues) {
if (
_.get(this.currentPrompt, "status") === PENDING ||
(_.isEmpty(answers) &&
_.isEmpty(_.get(this.currentPrompt, "questions")))
) {
this.stepValidated = false;
} else {
this.stepValidated = issues === undefined;
}
const currentPrompt = this.currentPrompt;
if (currentPrompt) {
this.stepValidated =
currentPrompt.status === PENDING || _.isEmpty(currentPrompt.questions) ? false : _.isNil(issues);
currentPrompt.answers = answers;
if (currentPrompt.answers.generator) {
this.isToolsSuiteTypeGen = this.isToolsSuiteType(
currentPrompt.answers.generator
);
this.isToolsSuiteTypeGen = this.isToolsSuiteType(currentPrompt.answers.generator);
}
if (currentPrompt.status === EVALUATING) {
currentPrompt.status = undefined;
Expand All @@ -397,10 +340,7 @@ export default {
const choices = _.compact(_.get(generatorQuestion, "choices"));
if (choices) {
const isToolsSuiteGen = _.find(choices, (choice) => {
return (
_.get(choice, "isToolsSuiteType") === true &&
_.get(choice, "value") === genName
);
return _.get(choice, "isToolsSuiteType") === true && _.get(choice, "value") === genName;
});
return _.isEmpty(isToolsSuiteGen) === false;
}
Expand Down Expand Up @@ -476,11 +416,7 @@ export default {
}
try {
return await that.rpc.invoke("evaluateMethod", [
args,
question.name,
prop,
]);
return await that.rpc.invoke("evaluateMethod", [args, question.name, prop]);
} catch (e) {
that.showBusyIndicator = false;
throw e;
Expand Down Expand Up @@ -520,8 +456,7 @@ export default {
}
if (this.nextButtonText === "Finish" && this.isToolsSuiteTypeGen) {
const message =
"The generated project will not open in a new workspace.";
const message = "The generated project will not open in a new workspace.";
const image =
"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+DQo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHdpZHRoPSIxNyIgaGVpZ2h0PSIxNyIgdmlld0JveD0iMCAwIDE3IDE3Ij4NCiAgPGRlZnM+DQogICAgPGNsaXBQYXRoIGlkPSJjbGlwLWluZm9fdmNvZGUiPg0KICAgICAgPHJlY3Qgd2lkdGg9IjE3IiBoZWlnaHQ9IjE3Ii8+DQogICAgPC9jbGlwUGF0aD4NCiAgPC9kZWZzPg0KICA8ZyBpZD0iaW5mb192Y29kZSIgY2xpcC1wYXRoPSJ1cmwoI2NsaXAtaW5mb192Y29kZSkiPg0KICAgIDxnIGlkPSJHcm91cF8zNTQ0IiBkYXRhLW5hbWU9Ikdyb3VwIDM1NDQiPg0KICAgICAgPGcgaWQ9Ikdyb3VwXzM1NDMiIGRhdGEtbmFtZT0iR3JvdXAgMzU0MyI+DQogICAgICAgIDxnIGlkPSJHcm91cF8zNTQyIiBkYXRhLW5hbWU9Ikdyb3VwIDM1NDIiPg0KICAgICAgICAgIDxnIGlkPSJFbGxpcHNlXzU0IiBkYXRhLW5hbWU9IkVsbGlwc2UgNTQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzZmYmFmNyIgc3Ryb2tlLXdpZHRoPSIxLjUiPg0KICAgICAgICAgICAgPGNpcmNsZSBjeD0iOC41IiBjeT0iOC41IiByPSI4LjUiIHN0cm9rZT0ibm9uZSIvPg0KICAgICAgICAgICAgPGNpcmNsZSBjeD0iOC41IiBjeT0iOC41IiByPSI3Ljc1IiBmaWxsPSJub25lIi8+DQogICAgICAgICAgPC9nPg0KICAgICAgICAgIDxwYXRoIGlkPSJQYXRoXzE2NDAiIGRhdGEtbmFtZT0iUGF0aCAxNjQwIiBkPSJNMTg1Mi41LTI3NzkuNzMxdjQuNTA2IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMTg0NCAyNzg3Ljc1KSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNmZiYWY3IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS13aWR0aD0iMS41Ii8+DQogICAgICAgICAgPHBhdGggaWQ9IlBhdGhfMTY0MSIgZGF0YS1uYW1lPSJQYXRoIDE2NDEiIGQ9Ik0xODUyLjUtMjc3NC43MzFoMCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTE4NDQgMjc4MCkiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzZmYmFmNyIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2Utd2lkdGg9IjIiLz4NCiAgICAgICAgPC9nPg0KICAgICAgPC9nPg0KICAgIDwvZz4NCiAgPC9nPg0KPC9zdmc+DQo=";
this.showPromptMessage(message, Severity.information, image);
Expand All @@ -544,19 +479,11 @@ export default {
let promptDescription = "";
let promptName = "";
if (name === "select_generator") {
promptDescription = _.get(
this.messages,
"select_generator_description"
);
promptDescription = _.get(this.messages, "select_generator_description");
promptName = _.get(this.messages, "select_generator_name");
} else {
const promptIndex = this.selectGeneratorPromptExists()
? this.promptIndex - 1
: this.promptIndex;
const promptToDisplay = _.get(
this.promptsInfoToDisplay,
`[${promptIndex}]`
);
const promptIndex = this.selectGeneratorPromptExists() ? this.promptIndex - 1 : this.promptIndex;
const promptToDisplay = _.get(this.promptsInfoToDisplay, `[${promptIndex}]`);
promptDescription = _.get(promptToDisplay, "description", "");
promptName = _.get(promptToDisplay, "name", name);
}
Expand Down Expand Up @@ -644,8 +571,7 @@ export default {
async setMessagesAndSaveState() {
const uiOptions = await this.rpc.invoke("getState");
this.messages = _.get(uiOptions, "messages");
this.isGeneric =
_.get(this.messages, "panel_title") === "Template Wizard";
this.isGeneric = _.get(this.messages, "panel_title") === "Template Wizard";
const vscodeApi = this.getVsCodeApi();
if (vscodeApi) {
vscodeApi.setState(uiOptions);
Expand Down Expand Up @@ -674,9 +600,7 @@ export default {
this.registerPlugin(TilesPlugin);
this.registerPlugin(LabelPlugin);
this.isInVsCode()
? (this.consoleClass = "consoleClassHidden")
: (this.consoleClass = "consoleClassVisible");
this.isInVsCode() ? (this.consoleClass = "consoleClassHidden") : (this.consoleClass = "consoleClassVisible");
},
reload() {
const dataObj = initialState();
Expand Down
40 changes: 10 additions & 30 deletions packages/frontend/test/App.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ describe("App.vue", () => {

it("createPrompt - method", () => {
wrapper = initComponent(App, {}, true);
wrapper.vm.prompts = [
{ questions: [{ name: "generator", type: "list", guiType: "tiles" }] },
];
wrapper.vm.prompts = [{ questions: [{ name: "generator", type: "list", guiType: "tiles" }] }];
expect(wrapper.vm.createPrompt().name).toBe();
expect(wrapper.vm.createPrompt([]).name).toBe();
expect(wrapper.vm.createPrompt([], "name").name).toBe("name");
Expand Down Expand Up @@ -167,9 +165,7 @@ describe("App.vue", () => {
it("no generators", () => {
wrapper = initComponent(App, {}, true);
wrapper.vm.promptIndex = 0;
wrapper.vm.prompts = [
{ name: "Select Generator", questions: [{ choices: [] }] },
];
wrapper.vm.prompts = [{ name: "Select Generator", questions: [{ choices: [] }] }];
wrapper.vm.$data.messages = { select_generator_name: "Select Generator" };
expect(wrapper.vm.isNoGenerators).toBeTruthy();
});
Expand All @@ -190,19 +186,15 @@ describe("App.vue", () => {
it("generators exist question.name != 'generator'", () => {
wrapper = initComponent(App, {}, true);
wrapper.vm.promptIndex = 0;
wrapper.vm.prompts = [
{ name: "Select Generator", questions: [{}, { choices: [{}] }] },
];
wrapper.vm.prompts = [{ name: "Select Generator", questions: [{}, { choices: [{}] }] }];
wrapper.vm.$data.messages = { select_generator_name: "Select Generator" };
expect(wrapper.vm.isNoGenerators).toBeTruthy();
});

it("prompt name != generators", () => {
wrapper = initComponent(App, {}, true);
wrapper.vm.promptIndex = 0;
wrapper.vm.prompts = [
{ name: "Prompt Name", questions: [{ choices: [{}] }] },
];
wrapper.vm.prompts = [{ name: "Prompt Name", questions: [{ choices: [{}] }] }];
wrapper.vm.$data.messages = { select_generator_name: "Select Generator" };
expect(wrapper.vm.isNoGenerators).toBeFalsy();
});
Expand Down Expand Up @@ -302,9 +294,7 @@ describe("App.vue", () => {
wrapper.vm.promptIndex = 1;
wrapper.vm.rpc = {
invoke: jest.fn().mockImplementation((methodName, question) => {
return new Promise((resolve) =>
setTimeout(() => resolve(question[1]), 1500)
);
return new Promise((resolve) => setTimeout(() => resolve(question[1]), 1500));
}),
};

Expand Down Expand Up @@ -523,21 +513,14 @@ describe("App.vue", () => {
const event = {
target: {
getAttribute: jest.fn().mockImplementation((key) => {
return key === "command"
? "vscode.open"
: key === "params"
? ["param"]
: "";
return key === "command" ? "vscode.open" : key === "params" ? ["param"] : "";
}),
},
};
const invokeSpy = jest.spyOn(wrapper.vm.rpc, "invoke");
wrapper.vm.executeCommand(event);

expect(invokeSpy).toHaveBeenCalledWith("executeCommand", [
"vscode.open",
["param"],
]);
expect(invokeSpy).toHaveBeenCalledWith("executeCommand", ["vscode.open", ["param"]]);

invokeSpy.mockRestore();
});
Expand Down Expand Up @@ -581,7 +564,7 @@ describe("App.vue", () => {
resolveSpy.mockRestore();
});

it("resolve method throws an exception", () => {
it.skip("resolve method throws an exception", () => {
wrapper = initComponent(App, {});

wrapper.vm.resolve = () => {
Expand All @@ -593,8 +576,7 @@ describe("App.vue", () => {
wrapper.vm.stepValidated = true;
wrapper.vm.prompts = [{}, {}];
wrapper.vm.rpc = {
invoke: () =>
new Promise((resolve) => setTimeout(() => resolve(), 300)),
invoke: () => new Promise((resolve) => setTimeout(() => resolve(), 300)),
};

wrapper.vm.next();
Expand Down Expand Up @@ -918,9 +900,7 @@ describe("App.vue", () => {
wrapper.vm.promptIndex = 1;
wrapper.vm.$data.generatorPrettyName = "testGeneratorPrettyName";
wrapper.vm.$data.messages = { yeoman_ui_title: "yeoman_ui_title" };
expect(wrapper.vm.headerTitle).toEqual(
"yeoman_ui_title - testGeneratorPrettyName"
);
expect(wrapper.vm.headerTitle).toEqual("yeoman_ui_title - testGeneratorPrettyName");
});
});

Expand Down

0 comments on commit 9ea48b6

Please sign in to comment.