From 42d5f7465ae3d971eaa2826b7d8748b96d87da77 Mon Sep 17 00:00:00 2001 From: Yuqi Zhou <86260893+yuqizhou77@users.noreply.github.com> Date: Mon, 17 Jul 2023 10:02:52 +0800 Subject: [PATCH] refactor: spfx package question (#9301) * refactor: spfx question * test: ut1 * test: ut * refactor: spfx * test: ut --- packages/api/review/teamsfx-api.api.md | 6 + packages/api/src/types.ts | 3 + .../spfx/depsChecker/generatorChecker.ts | 7 +- .../component/generator/spfx/spfxGenerator.ts | 14 +- packages/fx-core/src/question/create.ts | 132 ++++++--------- .../component/generator/spfxGenerator.test.ts | 8 +- .../spfx/depsChecker/generatorChecker.test.ts | 29 +--- .../plugins/resource/spfx/unit/utils.test.ts | 65 +------- .../fx-core/tests/question/create.test.ts | 1 - .../tests/question/question.spfx.test.ts | 154 +++++++++--------- 10 files changed, 147 insertions(+), 272 deletions(-) diff --git a/packages/api/review/teamsfx-api.api.md b/packages/api/review/teamsfx-api.api.md index 8985178197..12c6278560 100644 --- a/packages/api/review/teamsfx-api.api.md +++ b/packages/api/review/teamsfx-api.api.md @@ -259,6 +259,10 @@ export interface Inputs extends Record { // (undocumented) existingResources?: string[]; // (undocumented) + globalSpfxPackageVersion?: string; + // (undocumented) + globalYeomanPackageVersion?: string; + // (undocumented) ignoreConfigPersist?: boolean; // (undocumented) ignoreEnvInfo?: boolean; @@ -267,6 +271,8 @@ export interface Inputs extends Record { // (undocumented) isM365?: boolean; // (undocumented) + latestSpfxPackageVersion?: string; + // (undocumented) locale?: string; // (undocumented) openAIPluginManifest?: OpenAIPluginManifest; diff --git a/packages/api/src/types.ts b/packages/api/src/types.ts index bc9e7d1cf0..9329ac46dd 100644 --- a/packages/api/src/types.ts +++ b/packages/api/src/types.ts @@ -85,6 +85,9 @@ export interface Inputs extends Record { inProductDoc?: boolean; // AB test for in product doc feature teamsAppFromTdp?: any; openAIPluginManifest?: OpenAIPluginManifest; + globalYeomanPackageVersion?: string; + globalSpfxPackageVersion?: string; + latestSpfxPackageVersion?: string; } export type InputsWithProjectPath = Inputs & { projectPath: string }; diff --git a/packages/fx-core/src/component/generator/spfx/depsChecker/generatorChecker.ts b/packages/fx-core/src/component/generator/spfx/depsChecker/generatorChecker.ts index a601d0717c..13bbcf92b3 100644 --- a/packages/fx-core/src/component/generator/spfx/depsChecker/generatorChecker.ts +++ b/packages/fx-core/src/component/generator/spfx/depsChecker/generatorChecker.ts @@ -22,7 +22,6 @@ import { DependencyValidateError, NpmInstallError } from "../error"; import { cpUtils } from "../../../../common/deps-checker/util/cpUtils"; import { Constants } from "../utils/constants"; import { getExecCommand, Utils } from "../utils/utils"; -import { PackageSelectOptionsHelper } from "../../../../question/create"; const name = Constants.GeneratorPackageName; const displayName = `${name}@${Constants.LatestVersion}`; @@ -62,12 +61,10 @@ export class GeneratorChecker implements DependencyChecker { return ok(true); } - public async isLatestInstalled(): Promise { + public async isLatestInstalled(loadedLatestVersion: string | undefined): Promise { try { const generatorVersion = await this.queryVersion(); - const latestGeneratorVersion = - PackageSelectOptionsHelper.getLatestSpGeneratorVersion() ?? - (await this.findLatestVersion(5)); + const latestGeneratorVersion = loadedLatestVersion ?? (await this.findLatestVersion(5)); const hasSentinel = await fs.pathExists(this.getSentinelPath()); return !!latestGeneratorVersion && generatorVersion === latestGeneratorVersion && hasSentinel; } catch (error) { diff --git a/packages/fx-core/src/component/generator/spfx/spfxGenerator.ts b/packages/fx-core/src/component/generator/spfx/spfxGenerator.ts index 03d187db1b..c4e1d1ebb7 100644 --- a/packages/fx-core/src/component/generator/spfx/spfxGenerator.ts +++ b/packages/fx-core/src/component/generator/spfx/spfxGenerator.ts @@ -44,9 +44,10 @@ import { } from "./error"; import { Constants, ManifestTemplate } from "./utils/constants"; import { ProgressHelper } from "./utils/progress-helper"; -import { PackageSelectOptionsHelper, SPFxVersionOptionIds } from "../../../question/create"; +import { SPFxVersionOptionIds } from "../../../question/create"; import { TelemetryEvents, TelemetryProperty } from "./utils/telemetryEvents"; import { Utils } from "./utils/utils"; +import semver from "semver"; export class SPFxGenerator { @hooks([ @@ -232,7 +233,9 @@ export class SPFxGenerator { if (shouldInstallLocally) { const latestYoInstalled = await yoChecker.isLatestInstalled(); - const latestGeneratorInstalled = await spGeneratorChecker.isLatestInstalled(); + const latestGeneratorInstalled = await spGeneratorChecker.isLatestInstalled( + inputs.latestSpfxPackageVersion + ); if (!latestYoInstalled || !latestGeneratorInstalled) { await progressHandler?.next( @@ -254,7 +257,12 @@ export class SPFxGenerator { } } } else { - const isLowerVersion = PackageSelectOptionsHelper.isLowerThanRecommendedVersion(); + const isLowerVersion = + !!inputs.globalSpfxPackageVersion && + semver.lte( + inputs.globalSpfxPackageVersion, + Constants.RecommendedLowestSpfxVersion.substring(1) + ); if (isLowerVersion) { context.telemetryReporter.sendTelemetryEvent(TelemetryEvents.UseNotRecommendedVersion); } diff --git a/packages/fx-core/src/question/create.ts b/packages/fx-core/src/question/create.ts index 6e70dd67ea..de64e06919 100644 --- a/packages/fx-core/src/question/create.ts +++ b/packages/fx-core/src/question/create.ts @@ -4,7 +4,6 @@ import { CLIPlatforms, FolderQuestion, - FuncQuestion, IQTreeNode, Inputs, MultiSelectQuestion, @@ -21,7 +20,6 @@ import * as jsonschema from "jsonschema"; import { cloneDeep } from "lodash"; import * as os from "os"; import * as path from "path"; -import semver from "semver"; import { ConstantString } from "../common/constants"; import { isCLIDotNetEnabled, isCopilotPluginEnabled } from "../common/featureFlags"; import { getLocalizedString } from "../common/localizeUtils"; @@ -720,14 +718,56 @@ export function SPFxPackageSelectQuestion(): SingleSelectQuestion { staticOptions: [], placeholder: getLocalizedString("plugins.spfx.questions.packageSelect.placeholder"), dynamicOptions: async (inputs: Inputs): Promise => { - await PackageSelectOptionsHelper.loadOptions(); - return PackageSelectOptionsHelper.getOptions(); + const versions = await Promise.all([ + Utils.findGloballyInstalledVersion(undefined, Constants.GeneratorPackageName, 0, false), + Utils.findLatestVersion(undefined, Constants.GeneratorPackageName, 5), + Utils.findGloballyInstalledVersion(undefined, Constants.YeomanPackageName, 0, false), + ]); + + inputs.globalSpfxPackageVersion = versions[0]; + inputs.latestSpfxPackageVersion = versions[1]; + inputs.globalYeomanPackageVersion = versions[2]; + + return [ + { + id: SPFxVersionOptionIds.installLocally, + + label: + versions[1] !== undefined + ? getLocalizedString( + "plugins.spfx.questions.packageSelect.installLocally.withVersion.label", + "v" + versions[1] + ) + : getLocalizedString( + "plugins.spfx.questions.packageSelect.installLocally.noVersion.label" + ), + }, + { + id: SPFxVersionOptionIds.globalPackage, + label: + versions[0] !== undefined + ? getLocalizedString( + "plugins.spfx.questions.packageSelect.useGlobalPackage.withVersion.label", + "v" + versions[0] + ) + : getLocalizedString( + "plugins.spfx.questions.packageSelect.useGlobalPackage.noVersion.label" + ), + description: getLocalizedString( + "plugins.spfx.questions.packageSelect.useGlobalPackage.detail", + Constants.RecommendedLowestSpfxVersion + ), + }, + ]; }, default: SPFxVersionOptionIds.installLocally, validation: { - validFunc: async (input: string): Promise => { + validFunc: async (input: string, previousInputs?: Inputs): Promise => { if (input === SPFxVersionOptionIds.globalPackage) { - const hasPackagesInstalled = PackageSelectOptionsHelper.checkGlobalPackages(); + const hasPackagesInstalled = + !!previousInputs && + !!previousInputs.globalSpfxPackageVersion && + !!previousInputs.globalYeomanPackageVersion; if (!hasPackagesInstalled) { throw DevEnvironmentSetupError(); } @@ -802,86 +842,6 @@ export enum SPFxVersionOptionIds { globalPackage = "false", } -export class PackageSelectOptionsHelper { - private static options: OptionItem[] = []; - private static globalPackageVersions: (string | undefined)[] = [undefined, undefined]; - private static latestSpGeneratorVersion: string | undefined = undefined; - - public static async loadOptions(): Promise { - const versions = await Promise.all([ - Utils.findGloballyInstalledVersion(undefined, Constants.GeneratorPackageName, 0, false), - Utils.findLatestVersion(undefined, Constants.GeneratorPackageName, 5), - Utils.findGloballyInstalledVersion(undefined, Constants.YeomanPackageName, 0, false), - ]); - - PackageSelectOptionsHelper.globalPackageVersions[0] = versions[0]; - PackageSelectOptionsHelper.globalPackageVersions[1] = versions[2]; - PackageSelectOptionsHelper.latestSpGeneratorVersion = versions[1]; - - PackageSelectOptionsHelper.options = [ - { - id: SPFxVersionOptionIds.installLocally, - - label: - versions[1] !== undefined - ? getLocalizedString( - "plugins.spfx.questions.packageSelect.installLocally.withVersion.label", - "v" + versions[1] - ) - : getLocalizedString( - "plugins.spfx.questions.packageSelect.installLocally.noVersion.label" - ), - }, - { - id: SPFxVersionOptionIds.globalPackage, - label: - versions[0] !== undefined - ? getLocalizedString( - "plugins.spfx.questions.packageSelect.useGlobalPackage.withVersion.label", - "v" + versions[0] - ) - : getLocalizedString( - "plugins.spfx.questions.packageSelect.useGlobalPackage.noVersion.label" - ), - description: getLocalizedString( - "plugins.spfx.questions.packageSelect.useGlobalPackage.detail", - Constants.RecommendedLowestSpfxVersion - ), - }, - ]; - } - - public static getOptions(): OptionItem[] { - return PackageSelectOptionsHelper.options; - } - - public static clear(): void { - PackageSelectOptionsHelper.options = []; - PackageSelectOptionsHelper.globalPackageVersions = [undefined, undefined]; - PackageSelectOptionsHelper.latestSpGeneratorVersion = undefined; - } - - public static checkGlobalPackages(): boolean { - return ( - !!PackageSelectOptionsHelper.globalPackageVersions[0] && - !!PackageSelectOptionsHelper.globalPackageVersions[1] - ); - } - - public static getLatestSpGeneratorVersion(): string | undefined { - return PackageSelectOptionsHelper.latestSpGeneratorVersion; - } - - public static isLowerThanRecommendedVersion(): boolean | undefined { - const installedVersion = PackageSelectOptionsHelper.globalPackageVersions[0]; - if (!installedVersion) { - return undefined; - } - - const recommendedLowestVersion = Constants.RecommendedLowestSpfxVersion.substring(1); // remove "v" - return semver.lte(installedVersion, recommendedLowestVersion); - } -} export function SPFxImportFolderQuestion(hasDefaultFunc = false): FolderQuestion { return { type: "folder", diff --git a/packages/fx-core/tests/component/generator/spfxGenerator.test.ts b/packages/fx-core/tests/component/generator/spfxGenerator.test.ts index b86c167228..be084746a6 100644 --- a/packages/fx-core/tests/component/generator/spfxGenerator.test.ts +++ b/packages/fx-core/tests/component/generator/spfxGenerator.test.ts @@ -19,11 +19,7 @@ import { Utils } from "../../../src/component/generator/spfx/utils/utils"; import { createContextV3 } from "../../../src/component/utils"; import { envUtil } from "../../../src/component/utils/envUtil"; import { setTools } from "../../../src/core/globalVars"; -import { - PackageSelectOptionsHelper, - QuestionNames, - SPFxVersionOptionIds, -} from "../../../src/question"; +import { QuestionNames, SPFxVersionOptionIds } from "../../../src/question"; import { MockTools } from "../../core/utils"; describe("SPFxGenerator", function () { @@ -384,9 +380,9 @@ describe("SPFxGenerator", function () { [QuestionNames.AppName]: "spfxTestApp", [QuestionNames.SPFxInstallPackage]: SPFxVersionOptionIds.globalPackage, [QuestionNames.SPFxSolution]: "new", + globalSpfxPackageVersion: "1.17.0", }; sinon.stub(YoChecker.prototype, "isLatestInstalled").resolves(true); - sinon.stub(PackageSelectOptionsHelper, "isLowerThanRecommendedVersion").resolves(true); sinon.stub(GeneratorChecker.prototype, "isLatestInstalled").resolves(true); sinon.stub(cpUtils, "executeCommand").resolves("succeed"); diff --git a/packages/fx-core/tests/plugins/resource/spfx/depsChecker/generatorChecker.test.ts b/packages/fx-core/tests/plugins/resource/spfx/depsChecker/generatorChecker.test.ts index a2d90d571b..849a580d4e 100644 --- a/packages/fx-core/tests/plugins/resource/spfx/depsChecker/generatorChecker.test.ts +++ b/packages/fx-core/tests/plugins/resource/spfx/depsChecker/generatorChecker.test.ts @@ -12,7 +12,6 @@ import { telemetryHelper } from "../../../../../src/component/generator/spfx/uti import { createContextV3 } from "../../../../../src/component/utils"; import { setTools } from "../../../../../src/core/globalVars"; import { MockTools } from "../../../../core/utils"; -import { PackageSelectOptionsHelper } from "../../../../../src/question/create"; class StubLogger implements LogProvider { async log(logLevel: LogLevel, message: string): Promise { @@ -63,7 +62,6 @@ describe("generator checker", () => { afterEach(() => { restore(); - PackageSelectOptionsHelper.clear(); }); describe("getDependencyInfo", async () => { @@ -161,7 +159,7 @@ describe("generator checker", () => { return "latest"; }); - const result = await checker.isLatestInstalled(); + const result = await checker.isLatestInstalled("latest"); chai.expect(result).is.true; }); @@ -182,28 +180,7 @@ describe("generator checker", () => { return "latest"; }); - const result = await checker.isLatestInstalled(); - chai.expect(result).is.false; - }); - - it("latest not installed", async () => { - const checker = new GeneratorChecker(new StubLogger()); - stub(fs, "pathExists").callsFake(async () => { - console.log("stub pathExists"); - return false; - }); - - stub(GeneratorChecker.prototype, "queryVersion").callsFake(async () => { - console.log("stub queryversion"); - return "lower version"; - }); - - stub(GeneratorChecker.prototype, "findLatestVersion").callsFake(async () => { - console.log("stub findLatestVersion"); - return "latest"; - }); - - const result = await checker.isLatestInstalled(); + const result = await checker.isLatestInstalled(undefined); chai.expect(result).is.false; }); @@ -216,7 +193,7 @@ describe("generator checker", () => { stub(GeneratorChecker.prototype, "queryVersion").throws("error"); - const result = await checker.isLatestInstalled(); + const result = await checker.isLatestInstalled(undefined); chai.expect(result).is.false; }); }); diff --git a/packages/fx-core/tests/plugins/resource/spfx/unit/utils.test.ts b/packages/fx-core/tests/plugins/resource/spfx/unit/utils.test.ts index 28496212ce..6499da24c6 100644 --- a/packages/fx-core/tests/plugins/resource/spfx/unit/utils.test.ts +++ b/packages/fx-core/tests/plugins/resource/spfx/unit/utils.test.ts @@ -1,13 +1,5 @@ /* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */ -import { - FuncValidation, - getValidationFunction, - Inputs, - Platform, - SingleSelectQuestion, - Stage, - TextInputQuestion, -} from "@microsoft/teamsfx-api"; +import { FuncValidation, Inputs, Platform, Stage, TextInputQuestion } from "@microsoft/teamsfx-api"; import * as chai from "chai"; import fs from "fs-extra"; import "mocha"; @@ -18,10 +10,7 @@ import { cpUtils } from "../../../../../src"; import { getLocalizedString } from "../../../../../src/common/localizeUtils"; import { Utils } from "../../../../../src/component/generator/spfx/utils/utils"; import { - PackageSelectOptionsHelper, - SPFxVersionOptionIds, QuestionNames, - SPFxPackageSelectQuestion, SPFxWebpartNameQuestion, appNameQuestion, } from "../../../../../src/question"; @@ -155,48 +144,6 @@ describe("utils", () => { }); }); - describe("SPFxPackageSelectQuestion", async () => { - afterEach(() => { - sinon.restore(); - }); - - it("return undefined if choosing to install locally", async () => { - const func = getValidationFunction( - (SPFxPackageSelectQuestion() as SingleSelectQuestion).validation!, - { platform: Platform.VSCode } - ); - const res = await func(SPFxVersionOptionIds.installLocally); - chai.expect(res).equal(undefined); - }); - - it("return undefined if package exists", async () => { - sinon.stub(PackageSelectOptionsHelper, "checkGlobalPackages").returns(true); - - const func = getValidationFunction( - (SPFxPackageSelectQuestion() as SingleSelectQuestion).validation!, - { platform: Platform.VSCode } - ); - const res = await func(SPFxVersionOptionIds.globalPackage); - chai.expect(res).equal(undefined); - }); - - it("return undefined if package exists", async () => { - sinon.stub(PackageSelectOptionsHelper, "checkGlobalPackages").returns(false); - - const func = getValidationFunction( - (SPFxPackageSelectQuestion() as SingleSelectQuestion).validation!, - { platform: Platform.VSCode } - ); - let error; - try { - await func(SPFxVersionOptionIds.globalPackage); - } catch (e) { - error = e; - } - chai.expect(error.name).equal("DevEnvironmentSetupError"); - }); - }); - it("findLatestVersion: exeute commmand error with undefined logger", async () => { sinon.stub(cpUtils, "executeCommand").throws("run command error"); @@ -224,16 +171,6 @@ describe("utils", () => { chai.expect(res).to.be.undefined; }); - it("dynamicOptions", async () => { - const inputs: Inputs = { - platform: Platform.VSCode, - }; - sinon.stub(PackageSelectOptionsHelper, "loadOptions").resolves(); - sinon.stub(PackageSelectOptionsHelper, "getOptions").resolves([]); - const res = await (SPFxPackageSelectQuestion() as SingleSelectQuestion).dynamicOptions!(inputs); - chai.expect(res.length === 0).to.be.true; - }); - it("Returns solution name as default app name", async () => { const inputs: Inputs = { platform: Platform.VSCode, diff --git a/packages/fx-core/tests/question/create.test.ts b/packages/fx-core/tests/question/create.test.ts index 16bf7870f1..0224d1a461 100644 --- a/packages/fx-core/tests/question/create.test.ts +++ b/packages/fx-core/tests/question/create.test.ts @@ -6,7 +6,6 @@ import { Inputs, LocalFunc, MultiSelectQuestion, - OpenAIPluginManifest, OptionItem, Platform, Question, diff --git a/packages/fx-core/tests/question/question.spfx.test.ts b/packages/fx-core/tests/question/question.spfx.test.ts index 7e77323713..b15be130c1 100644 --- a/packages/fx-core/tests/question/question.spfx.test.ts +++ b/packages/fx-core/tests/question/question.spfx.test.ts @@ -2,16 +2,15 @@ import "mocha"; import * as chai from "chai"; import * as sinon from "sinon"; import { - PackageSelectOptionsHelper, SPFxPackageSelectQuestion, SPFxVersionOptionIds, SPFxWebpartNameQuestion, } from "../../src/question/create"; -import { Utils } from "../../src/component/generator/spfx/utils/utils"; import mockedEnv, { RestoreFn } from "mocked-env"; import { FuncValidation, Inputs, + OptionItem, Platform, SingleSelectQuestion, Stage, @@ -21,79 +20,8 @@ import { import { getLocalizedString } from "../../src/common/localizeUtils"; import * as path from "path"; import fs from "fs-extra"; +import { Utils } from "../../src/component/generator/spfx/utils/utils"; describe("SPFx question-helpers", () => { - describe("PackageSelectOptionsHelper", () => { - const sandbox = sinon.createSandbox(); - - afterEach(async () => { - PackageSelectOptionsHelper.clear(); - sandbox.restore(); - }); - - it("loadOptions and getOptions: not find latest", async () => { - sandbox.stub(Utils, "findGloballyInstalledVersion").resolves(undefined); - sandbox.stub(Utils, "findLatestVersion").resolves(undefined); - - const originalOptions = PackageSelectOptionsHelper.getOptions(); - chai.expect(originalOptions.length).equal(0); - await PackageSelectOptionsHelper.loadOptions(); - const options = PackageSelectOptionsHelper.getOptions(); - const latestVersion = PackageSelectOptionsHelper.getLatestSpGeneratorVersion(); - const isLowerVersion = PackageSelectOptionsHelper.isLowerThanRecommendedVersion(); - - chai.expect(options.length).equal(2); - chai.expect(options[0].label.includes("(")).equal(false); - chai.expect(options[1].label.includes("(")).equal(false); - chai.expect(latestVersion).to.be.undefined; - chai.expect(isLowerVersion).to.be.undefined; - }); - - it("loadOptions and getOptions: find latest", async () => { - sandbox.stub(Utils, "findGloballyInstalledVersion").resolves("1.16.0"); - sandbox.stub(Utils, "findLatestVersion").resolves("1.16.1"); - - await PackageSelectOptionsHelper.loadOptions(); - const options = PackageSelectOptionsHelper.getOptions(); - const latestVersion = PackageSelectOptionsHelper.getLatestSpGeneratorVersion(); - - chai.expect(options.length).equal(2); - chai.expect(options[1].label.includes("v1.16.0")).equal(true); - chai.expect(options[0].label.includes("v1.16.1")).equal(true); - chai.expect(latestVersion).equal("1.16.1"); - }); - - it("check whether pacakges installed: returns true", async () => { - sandbox.stub(Utils, "findGloballyInstalledVersion").resolves("1.13.0"); - sandbox.stub(Utils, "findLatestVersion").resolves("1.16.1"); - - await PackageSelectOptionsHelper.loadOptions(); - const res = PackageSelectOptionsHelper.checkGlobalPackages(); - const isLowerVersion = PackageSelectOptionsHelper.isLowerThanRecommendedVersion(); - - chai.expect(res).equal(true); - chai.expect(isLowerVersion).equal(true); - }); - - it("check whether pacakges installed: returns false", async () => { - sandbox.stub(Utils, "findGloballyInstalledVersion").resolves(undefined); - sandbox.stub(Utils, "findLatestVersion").resolves("1.16.1"); - - await PackageSelectOptionsHelper.loadOptions(); - const res = PackageSelectOptionsHelper.checkGlobalPackages(); - - chai.expect(res).equal(false); - }); - - it("installed beta version", async () => { - sandbox.stub(Utils, "findGloballyInstalledVersion").resolves("1.17.0-beta.3"); - sandbox.stub(Utils, "findLatestVersion").resolves("1.16.1"); - - await PackageSelectOptionsHelper.loadOptions(); - const isLowerVersion = PackageSelectOptionsHelper.isLowerThanRecommendedVersion(); - - chai.expect(isLowerVersion).equal(false); - }); - }); describe("SPFxWebpartNameQuestion", () => { let mockedEnvRestore: RestoreFn; const previousInputs: Inputs = { platform: Platform.VSCode }; @@ -219,9 +147,12 @@ describe("SPFx question-helpers", () => { }); describe("SPFxPackageSelectQuestion", async () => { + const sandbox = sinon.createSandbox(); + afterEach(() => { - sinon.restore(); + sandbox.restore(); }); + it("return undefined if choosing to install locally", async () => { const func = getValidationFunction( (SPFxPackageSelectQuestion() as SingleSelectQuestion).validation!, @@ -232,22 +163,36 @@ describe("SPFx question-helpers", () => { }); it("return undefined if package exists", async () => { - sinon.stub(PackageSelectOptionsHelper, "checkGlobalPackages").returns(true); - const func = getValidationFunction( (SPFxPackageSelectQuestion() as SingleSelectQuestion).validation!, - { platform: Platform.VSCode } + { + platform: Platform.VSCode, + globalSpfxPackageVersion: "1.17.0", + globalYeomanPackageVersion: "1.0.0", + } ); const res = await func(SPFxVersionOptionIds.globalPackage); chai.expect(res).equal(undefined); }); - it("return undefined if package exists", async () => { - sinon.stub(PackageSelectOptionsHelper, "checkGlobalPackages").returns(false); + it("return undefined if missing Yeoman", async () => { + const func = getValidationFunction( + (SPFxPackageSelectQuestion() as SingleSelectQuestion).validation!, + { platform: Platform.VSCode, globalSpfxPackageVersion: "1.17.0" } + ); + let error; + try { + await func(SPFxVersionOptionIds.globalPackage); + } catch (e) { + error = e; + } + chai.expect(error.name).equal("DevEnvironmentSetupError"); + }); + it("return undefined if missing SPFX generator", async () => { const func = getValidationFunction( (SPFxPackageSelectQuestion() as SingleSelectQuestion).validation!, - { platform: Platform.VSCode } + { platform: Platform.VSCode, globalYeomanPackageVersion: "4.3.0" } ); let error; try { @@ -257,5 +202,52 @@ describe("SPFx question-helpers", () => { } chai.expect(error.name).equal("DevEnvironmentSetupError"); }); + + it("throws error if inputs is undefined", async () => { + const question = SPFxPackageSelectQuestion(); + + let error; + try { + await (question.validation! as FuncValidation).validFunc!( + SPFxVersionOptionIds.globalPackage + ); + } catch (e) { + error = e; + } + chai.expect(error.name).equal("DevEnvironmentSetupError"); + }); + + it("returns two options with package versions after loading", async () => { + sandbox.stub(Utils, "findGloballyInstalledVersion").resolves("1.17.0"); + sandbox.stub(Utils, "findLatestVersion").resolves("1.17.4"); + + const question = SPFxPackageSelectQuestion(); + const options = await question.dynamicOptions!({ platform: Platform.VSCode }); + + chai.expect(options.length).equal(2); + chai.expect((options[0] as OptionItem).label.includes("1.17.4")).equal(true); + }); + + it("returns two options without package versions after loading", async () => { + sandbox.stub(Utils, "findGloballyInstalledVersion").resolves(undefined); + sandbox.stub(Utils, "findLatestVersion").resolves(undefined); + + const question = SPFxPackageSelectQuestion(); + const options = await question.dynamicOptions!({ platform: Platform.VSCode }); + + chai.expect(options.length).equal(2); + chai + .expect((options[0] as OptionItem).label) + .equal( + getLocalizedString("plugins.spfx.questions.packageSelect.installLocally.noVersion.label") + ); + chai + .expect((options[1] as OptionItem).label) + .equal( + getLocalizedString( + "plugins.spfx.questions.packageSelect.useGlobalPackage.noVersion.label" + ) + ); + }); }); });