Skip to content

Commit

Permalink
refactor: spfx package question (#9301)
Browse files Browse the repository at this point in the history
* refactor: spfx question

* test: ut1

* test: ut

* refactor: spfx

* test: ut
  • Loading branch information
yuqizhou77 authored Jul 17, 2023
1 parent 235582c commit 42d5f74
Show file tree
Hide file tree
Showing 10 changed files with 147 additions and 272 deletions.
6 changes: 6 additions & 0 deletions packages/api/review/teamsfx-api.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,10 @@ export interface Inputs extends Record<string, any> {
// (undocumented)
existingResources?: string[];
// (undocumented)
globalSpfxPackageVersion?: string;
// (undocumented)
globalYeomanPackageVersion?: string;
// (undocumented)
ignoreConfigPersist?: boolean;
// (undocumented)
ignoreEnvInfo?: boolean;
Expand All @@ -267,6 +271,8 @@ export interface Inputs extends Record<string, any> {
// (undocumented)
isM365?: boolean;
// (undocumented)
latestSpfxPackageVersion?: string;
// (undocumented)
locale?: string;
// (undocumented)
openAIPluginManifest?: OpenAIPluginManifest;
Expand Down
3 changes: 3 additions & 0 deletions packages/api/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ export interface Inputs extends Record<string, any> {
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 };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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}`;
Expand Down Expand Up @@ -62,12 +61,10 @@ export class GeneratorChecker implements DependencyChecker {
return ok(true);
}

public async isLatestInstalled(): Promise<boolean> {
public async isLatestInstalled(loadedLatestVersion: string | undefined): Promise<boolean> {
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) {
Expand Down
14 changes: 11 additions & 3 deletions packages/fx-core/src/component/generator/spfx/spfxGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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([
Expand Down Expand Up @@ -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(
Expand All @@ -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);
}
Expand Down
132 changes: 46 additions & 86 deletions packages/fx-core/src/question/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import {
CLIPlatforms,
FolderQuestion,
FuncQuestion,
IQTreeNode,
Inputs,
MultiSelectQuestion,
Expand All @@ -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";
Expand Down Expand Up @@ -720,14 +718,56 @@ export function SPFxPackageSelectQuestion(): SingleSelectQuestion {
staticOptions: [],
placeholder: getLocalizedString("plugins.spfx.questions.packageSelect.placeholder"),
dynamicOptions: async (inputs: Inputs): Promise<OptionItem[]> => {
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<string | undefined> => {
validFunc: async (input: string, previousInputs?: Inputs): Promise<string | undefined> => {
if (input === SPFxVersionOptionIds.globalPackage) {
const hasPackagesInstalled = PackageSelectOptionsHelper.checkGlobalPackages();
const hasPackagesInstalled =
!!previousInputs &&
!!previousInputs.globalSpfxPackageVersion &&
!!previousInputs.globalYeomanPackageVersion;
if (!hasPackagesInstalled) {
throw DevEnvironmentSetupError();
}
Expand Down Expand Up @@ -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<void> {
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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 () {
Expand Down Expand Up @@ -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");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<boolean> {
Expand Down Expand Up @@ -63,7 +62,6 @@ describe("generator checker", () => {

afterEach(() => {
restore();
PackageSelectOptionsHelper.clear();
});

describe("getDependencyInfo", async () => {
Expand Down Expand Up @@ -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;
});

Expand All @@ -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, <any>"queryVersion").callsFake(async () => {
console.log("stub queryversion");
return "lower version";
});

stub(GeneratorChecker.prototype, <any>"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;
});

Expand All @@ -216,7 +193,7 @@ describe("generator checker", () => {

stub(GeneratorChecker.prototype, <any>"queryVersion").throws("error");

const result = await checker.isLatestInstalled();
const result = await checker.isLatestInstalled(undefined);
chai.expect(result).is.false;
});
});
Expand Down
Loading

0 comments on commit 42d5f74

Please sign in to comment.