Skip to content

Commit

Permalink
When 'Open in new workspace' and 'Add to workspace' should be shown. (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
ira-gordin-sap authored Oct 7, 2020
1 parent dc1510f commit 1a585e6
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 31 deletions.
2 changes: 1 addition & 1 deletion backend/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "yeoman-ui",
"version": "1.1.28",
"version": "1.1.29",
"displayName": "Application Wizard",
"publisher": "SAPOS",
"author": {
Expand Down
10 changes: 7 additions & 3 deletions backend/src/vscode-youi-events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,14 @@ export class VSCodeYouiEvents implements YouiEvents {
const addToWorkspace = "Add to Workspace";
const openInNewWorkspace: any = "Open in New Workspace";
const items: string[] = [];

const targetFolderUri: vscode.Uri = vscode.Uri.file(targetFolderPath);
let targetFolderUri: vscode.Uri = null;

if (!_.includes(this.genFilter.types, GeneratorType.module)) {
// The correct targetFolderPath is unknown ---> no buttons should be shown
if (!_.isNil(targetFolderPath)) {
// Target folder is visible in workpace ---> addToWorkspace only
// Target folder is not visible in workpace ---> addToWorkspace and openInNewWorkspace

targetFolderUri = vscode.Uri.file(targetFolderPath);
const workspacePath = _.get(vscode, "workspace.workspaceFolders[0].uri.fsPath");
// 1. target workspace folder should not already contain target generator folder
const foundInWorkspace = _.find(vscode.workspace.workspaceFolders, (wsFolder: vscode.WorkspaceFolder) => {
Expand Down
47 changes: 35 additions & 12 deletions backend/src/yeomanui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {IPrompt} from "@sap-devx/yeoman-ui-types";
import { SWA } from "./swa-tracker/swa-tracker-wrapper";
import TerminalAdapter = require("yeoman-environment/lib/adapter");
import { Output } from "./output";
import { resolve } from "path";


export interface IQuestionsPrompt extends IPrompt{
Expand Down Expand Up @@ -54,6 +55,7 @@ export class YeomanUI {
private readonly replayUtils: ReplayUtils;
private readonly customQuestionEventHandlers: Map<string, Map<string, Function>>;
private errorThrown = false;
private outputPath: string;

constructor(rpc: IRpc, youiEvents: YouiEvents, output: Output, logger: IChildLogger, uiOptions: any, outputPath: string = YeomanUI.PROJECTS) {
this.rpc = rpc;
Expand All @@ -62,7 +64,8 @@ export class YeomanUI {
this.replayUtils = new ReplayUtils();
this.youiEvents = youiEvents;
this.logger = logger;
this.output = output;
this.output = output;
this.outputPath = outputPath;
this.rpc.setResponseTimeout(3600000);
this.rpc.registerMethod({ func: this.receiveIsWebviewReady, thisArg: this });
this.rpc.registerMethod({ func: this.runGenerator, thisArg: this });
Expand Down Expand Up @@ -209,7 +212,9 @@ export class YeomanUI {
// (for example: 2.0.5) of "yeoman-generator" do not support it
this.gen.run(error => {;
if (!this.errorThrown && !error) {
this.getChildDirectories(this.gen.destinationRoot()).then(dirsAfter => {
// Without resolve this code worked only for absolute paths without / at the end.
// Generator can put a relative path, path including . and .. and / at the end.
this.getChildDirectories(resolve(this.getCwd(), this.gen.destinationRoot())).then(dirsAfter => {
this.onGeneratorSuccess(generatorName, dirsBefore, dirsAfter);
});
}
Expand Down Expand Up @@ -351,26 +356,40 @@ export class YeomanUI {
return (firstQuestionName ? _.startCase(firstQuestionName) : `Step ${this.promptCount}`);
}

private onGeneratorSuccess(generatorName: string, reourcesBeforeGen?: any, resourcesAfterGen?: any) {
let targetFolderPath: string = _.get(resourcesAfterGen, "targetFolderPath");
if (_.get(reourcesBeforeGen, "targetFolderPath") === targetFolderPath) {
const newDirs: string[] = _.difference(_.get(resourcesAfterGen, "childDirs"), _.get(reourcesBeforeGen, "childDirs"));
private onGeneratorSuccess(generatorName: string, resourcesBeforeGen?: any, resourcesAfterGen?: any) {
let targetFolderPath: string = null;
// All the paths here absolute normilized paths.
const targetFolderPathBeforeGen: string = _.get(resourcesBeforeGen, "targetFolderPath");
const targetFolderPathAfterGen: string = _.get(resourcesAfterGen, "targetFolderPath");
if (targetFolderPathBeforeGen === targetFolderPathAfterGen) {
const newDirs: string[] = _.difference(_.get(resourcesAfterGen, "childDirs"), _.get(resourcesBeforeGen, "childDirs"));
if (_.size(newDirs) === 1) {
targetFolderPath = newDirs[0];
}
}
// One folder added by generator and targetFolderPath/destinationRoot was not changed by generator.
// ---> Fiori project generator flow.
targetFolderPath = newDirs[0];
} //else { //_.size(newDirs) = 0 (0 folders) or _.size(newDirs) > 1 (5 folders)
// We don't know what is the correct targetFolderPath ---> no buttons should be shown.
// No folder added by generator ---> Fiori module generator flow.
// Many folders added by generator --->
// }
} else { //(targetFolderPathBeforeGen !== targetFolderPathAfterGen)
// Generator changed targetFolderPath/destinationRoot.
// ---> FoodQ generator flow.
targetFolderPath = targetFolderPathAfterGen;
}

const message = this.uiOptions.messages.artifact_with_name_generated(generatorName);
this.logger.debug("done running yeomanui! " + message + ` You can find it at ${targetFolderPath}`);
SWA.updateGeneratorEnded(this.generatorName, true, this.logger);
const generatedTemplatePath = targetFolderPath ? targetFolderPath : targetFolderPathBeforeGen;
this.logger.debug("done running yeomanui! " + message + ` You can find it at ${generatedTemplatePath}`);
SWA.updateGeneratorEnded(generatorName, true, this.logger);
this.youiEvents.doGeneratorDone(true, message, targetFolderPath);
}

private async onGeneratorFailure(generatorName: string, error: any) {
this.errorThrown = true;
const messagePrefix = `${generatorName} generator failed`;
const errorMessage: string = await this.logError(error, messagePrefix);
SWA.updateGeneratorEnded(this.generatorName, false, this.logger, errorMessage);
SWA.updateGeneratorEnded(generatorName, false, this.logger, errorMessage);
this.youiEvents.doGeneratorDone(false, errorMessage);
}

Expand Down Expand Up @@ -427,6 +446,10 @@ export class YeomanUI {
getPath: async (path: string) => path,
validate: async (path: string) => {
try {
// Without resolve this code worked only for absolute paths without / at the end.
// The user can put a relative path, path including . and .. and / at the end.
// In this case many project generation failed or opened invalid folders instead of project at the end (after clicking on the button 'Open project in workspace').
path = resolve(this.outputPath, path);
await fsextra.access(path, fsextra.constants.W_OK);
this.setCwd(path);
return true;
Expand Down
20 changes: 9 additions & 11 deletions backend/tests/vscode-youi-events.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,28 +206,26 @@ describe('vscode-youi-events unit test', () => {
return events.doGeneratorDone(true, "success message", "testDestinationRoot");
});

it("on success, no buttons are displayed", () => {
it("on success with the project already opened in the workspace, no buttons are displayed", () => {
eventsMock.expects("doClose");
_.set(vscode, "workspace.workspaceFolders", [{uri: {fsPath: "testDestinationRoot"}}]);
windowMock.expects("showInformationMessage").
withExactArgs(messages.default.artifact_generated).resolves();
return events.doGeneratorDone(true, "success message", "testDestinationRoot");
});

it("on failure", () => {
it("on success with null targetFolderPath, no buttons are displayed", () => {
eventsMock.expects("doClose");
windowMock.expects("showErrorMessage").withExactArgs("error message");
return events.doGeneratorDone(false, "error message");
_.set(vscode, "workspace.workspaceFolders", [{uri: {fsPath: "rootFolderPath"}}]);
windowMock.expects("showInformationMessage").
withExactArgs(messages.default.artifact_generated).resolves();
return events.doGeneratorDone(true, "success message", null);
});

it("generator filter type is module", () => {
const genFilter = GeneratorFilter.create({type: ["module"]});
loggerWrapperMock.expects("getClassLogger");
const testEvents = new VSCodeYouiEvents(undefined, undefined, genFilter, messages.default, undefined);
eventsMock = sandbox.mock(testEvents);
it("on failure", () => {
eventsMock.expects("doClose");
windowMock.expects("showInformationMessage").withExactArgs(messages.default.artifact_generated).resolves();
return testEvents.doGeneratorDone(true, "success message", "testDestinationRoot");
windowMock.expects("showErrorMessage").withExactArgs("error message");
return events.doGeneratorDone(false, "error message");
});
});
});
24 changes: 20 additions & 4 deletions backend/tests/yeomanui.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -669,21 +669,37 @@ describe('yeomanui unit test', () => {
it("onGeneratorSuccess - one dir was created", () => {
const beforeGen = {targetFolderPath: "testDestinationRoot", childDirs: ["dirparh1"]};
const afterGen = {targetFolderPath: "testDestinationRoot", childDirs: ["dirparh1", "dirpath2"]};
swaTrackerWrapperMock.expects("updateGeneratorEnded").withArgs("testGenerator", true);
swaTrackerWrapperMock.expects("updateGeneratorEnded").withArgs("testGenName", true, testLogger);
yeomanUi["onGeneratorSuccess"]("testGenName", beforeGen, afterGen);
expect(doGeneratorDoneSpy.calledWith(true, _.get(yeomanUi, "uiOptions.messages.artifact_with_name_generated")("testGenName"), "dirpath2")).to.be.true;
});

it("onGeneratorSuccess - two dirs were created", () => {
const beforeGen = {targetFolderPath: "testDestinationRoot", childDirs: ["dirparh1"]};
const afterGen = {targetFolderPath: "testDestinationRoot", childDirs: ["dirparh1", "dirpath2", "dirpath3"]};
swaTrackerWrapperMock.expects("updateGeneratorEnded").withArgs("testGenerator", true);
swaTrackerWrapperMock.expects("updateGeneratorEnded").withArgs("testGenName", true, testLogger);
yeomanUi["onGeneratorSuccess"]("testGenName", beforeGen, afterGen);
expect(doGeneratorDoneSpy.calledWith(true, _.get(yeomanUi, "uiOptions.messages.artifact_with_name_generated")("testGenName"), "testDestinationRoot")).to.be.true;
expect(doGeneratorDoneSpy.calledWith(true, _.get(yeomanUi, "uiOptions.messages.artifact_with_name_generated")("testGenName"), null)).to.be.true;
});

it("onGeneratorSuccess - zero dirs were created", () => {
const beforeGen = {targetFolderPath: "testDestinationRoot", childDirs: ["dirparh1"]};
const afterGen = {targetFolderPath: "testDestinationRoot", childDirs: ["dirparh1"]};
swaTrackerWrapperMock.expects("updateGeneratorEnded").withArgs("testGenName", true, testLogger);
yeomanUi["onGeneratorSuccess"]("testGenName", beforeGen, afterGen);
expect(doGeneratorDoneSpy.calledWith(true, _.get(yeomanUi, "uiOptions.messages.artifact_with_name_generated")("testGenName"), null)).to.be.true;
});

it("onGeneratorSuccess - targetFolderPath was changed by generator", () => {
const beforeGen = {targetFolderPath: "testDestinationRoot"};
const afterGen = {targetFolderPath: "testDestinationRoot/generatedProject"};
swaTrackerWrapperMock.expects("updateGeneratorEnded").withArgs("testGenName", true, testLogger);
yeomanUi["onGeneratorSuccess"]("testGenName", beforeGen, afterGen);
expect(doGeneratorDoneSpy.calledWith(true, _.get(yeomanUi, "uiOptions.messages.artifact_with_name_generated")("testGenName"), "testDestinationRoot/generatedProject")).to.be.true;
});

it("onGeneratorFailure", async () => {
swaTrackerWrapperMock.expects("updateGeneratorEnded").withArgs("testGenerator", false);
swaTrackerWrapperMock.expects("updateGeneratorEnded").withArgs("testGenName", false, testLogger);
await yeomanUi["onGeneratorFailure"]("testGenName", "testError");
expect(doGeneratorDoneSpy.calledWith(false, `{"message":"testGenName generator failed - testError"}`)).to.be.true;
});
Expand Down

0 comments on commit 1a585e6

Please sign in to comment.