diff --git a/packages/vscode-extension/src/extension.ts b/packages/vscode-extension/src/extension.ts index 983741a57c..0f7b3be645 100644 --- a/packages/vscode-extension/src/extension.ts +++ b/packages/vscode-extension/src/extension.ts @@ -133,6 +133,12 @@ import { showError } from "./error/common"; import { TreeViewCommand } from "./treeview/treeViewCommand"; import { signOutM365, signOutAzure } from "./utils/accountUtils"; import { cmpAccountsHandler, createAccountHandler } from "./handlers/accountHandlers"; +import { + buildPackageHandler, + publishInDeveloperPortalHandler, + updatePreviewManifest, + validateManifestHandler, +} from "./handlers/manifestHandlers"; export async function activate(context: vscode.ExtensionContext) { process.env[FeatureFlags.ChatParticipant] = ( @@ -547,12 +553,7 @@ function registerTreeViewCommandsInLifecycle(context: vscode.ExtensionContext) { registerInCommandController(context, CommandKeys.Provision, provisionHandler, "provision"); // Zip Teams metadata package - registerInCommandController( - context, - "fx-extension.build", - handlers.buildPackageHandler, - "buildPackage" - ); + registerInCommandController(context, "fx-extension.build", buildPackageHandler, "buildPackage"); // Deploy to the cloud registerInCommandController(context, CommandKeys.Deploy, deployHandler, "deploy"); @@ -564,7 +565,7 @@ function registerTreeViewCommandsInLifecycle(context: vscode.ExtensionContext) { registerInCommandController( context, "fx-extension.publishInDeveloperPortal", - handlers.publishInDeveloperPortalHandler, + publishInDeveloperPortalHandler, "publishInDeveloperPortal" ); @@ -596,13 +597,13 @@ function registerTeamsFxCommands(context: vscode.ExtensionContext) { const updateManifestCmd = vscode.commands.registerCommand( "fx-extension.updatePreviewFile", - (...args) => Correlator.run(handlers.updatePreviewManifest, args) + (...args) => Correlator.run(updatePreviewManifest, args) ); context.subscriptions.push(updateManifestCmd); const validateManifestCmd = vscode.commands.registerCommand( "fx-extension.validateManifest", - (...args) => Correlator.run(handlers.validateManifestHandler, args) + (...args) => Correlator.run(validateManifestHandler, args) ); context.subscriptions.push(validateManifestCmd); diff --git a/packages/vscode-extension/src/handlers.ts b/packages/vscode-extension/src/handlers.ts index e0457b6806..b9957a91ca 100644 --- a/packages/vscode-extension/src/handlers.ts +++ b/packages/vscode-extension/src/handlers.ts @@ -173,16 +173,6 @@ export async function treeViewPreviewHandler(...args: any[]): Promise> { - ExtTelemetry.sendTelemetryEvent( - TelemetryEvent.ValidateManifestStart, - getTriggerFromProperty(args) - ); - - const inputs = getSystemInputs(); - return await runCommand(Stage.validateApplication, inputs); -} - /** * Ask user to select environment, local is included */ @@ -208,118 +198,6 @@ export async function askTargetEnvironment(): Promise> { } } -export async function buildPackageHandler(...args: unknown[]): Promise> { - ExtTelemetry.sendTelemetryEvent(TelemetryEvent.BuildStart, getTriggerFromProperty(args)); - return await runCommand(Stage.createAppPackage); -} - -let lastAppPackageFile: string | undefined; - -export async function publishInDeveloperPortalHandler( - ...args: unknown[] -): Promise> { - ExtTelemetry.sendTelemetryEvent( - TelemetryEvent.PublishInDeveloperPortalStart, - getTriggerFromProperty(args) - ); - const workspacePath = workspaceUri?.fsPath; - const zipDefaultFolder: string | undefined = path.join( - workspacePath!, - BuildFolderName, - AppPackageFolderName - ); - - let files: string[] = []; - if (await fs.pathExists(zipDefaultFolder)) { - files = await fs.readdir(zipDefaultFolder); - files = files - .filter((file) => path.extname(file).toLowerCase() === ".zip") - .map((file) => { - return path.join(zipDefaultFolder, file); - }); - } - while (true) { - const selectFileConfig: SelectFileConfig = { - name: "appPackagePath", - title: localize("teamstoolkit.publishInDevPortal.selectFile.title"), - placeholder: localize("teamstoolkit.publishInDevPortal.selectFile.placeholder"), - filters: { - "Zip files": ["zip"], - }, - }; - if (lastAppPackageFile && fs.existsSync(lastAppPackageFile)) { - selectFileConfig.default = lastAppPackageFile; - } else { - selectFileConfig.possibleFiles = files.map((file) => { - const appPackageFilename = path.basename(file); - const appPackageFilepath = path.dirname(file); - return { - id: file, - label: `$(file) ${appPackageFilename}`, - description: appPackageFilepath, - }; - }); - } - const selectFileResult = await VS_CODE_UI.selectFile(selectFileConfig); - if (selectFileResult.isErr()) { - ExtTelemetry.sendTelemetryErrorEvent( - TelemetryEvent.PublishInDeveloperPortal, - selectFileResult.error, - getTriggerFromProperty(args) - ); - return ok(null); - } - if ( - (lastAppPackageFile && selectFileResult.value.result === lastAppPackageFile) || - (!lastAppPackageFile && files.indexOf(selectFileResult.value.result!) !== -1) - ) { - // user selected file in options - lastAppPackageFile = selectFileResult.value.result; - break; - } - // final confirmation - lastAppPackageFile = selectFileResult.value.result!; - const appPackageFilename = path.basename(lastAppPackageFile); - const appPackageFilepath = path.dirname(lastAppPackageFile); - const confirmOption: SingleSelectConfig = { - options: [ - { - id: "yes", - label: `$(file) ${appPackageFilename}`, - description: appPackageFilepath, - }, - ], - name: "confirm", - title: localize("teamstoolkit.publishInDevPortal.selectFile.title"), - placeholder: localize("teamstoolkit.publishInDevPortal.confirmFile.placeholder"), - step: 2, - }; - const confirm = await VS_CODE_UI.selectOption(confirmOption); - if (confirm.isErr()) { - ExtTelemetry.sendTelemetryErrorEvent( - TelemetryEvent.PublishInDeveloperPortal, - confirm.error, - getTriggerFromProperty(args) - ); - return ok(null); - } - if (confirm.value.type === "success") { - break; - } - } - const inputs = getSystemInputs(); - inputs["appPackagePath"] = lastAppPackageFile; - const res = await runCommand(Stage.publishInDeveloperPortal, inputs); - if (res.isErr()) { - ExtTelemetry.sendTelemetryErrorEvent( - TelemetryEvent.PublishInDeveloperPortal, - res.error, - getTriggerFromProperty(args) - ); - } - return res; -} - export function openFolderHandler(...args: unknown[]): Promise> { const scheme = "file://"; ExtTelemetry.sendTelemetryEvent(TelemetryEvent.OpenFolder, { @@ -1255,45 +1133,6 @@ export async function openConfigStateFile(args: any[]): Promise { }); } -export async function updatePreviewManifest(args: any[]): Promise { - ExtTelemetry.sendTelemetryEvent( - TelemetryEvent.UpdatePreviewManifestStart, - getTriggerFromProperty(args && args.length > 1 ? [args[1]] : undefined) - ); - let env: string | undefined; - if (args && args.length > 0) { - const filePath = args[0].fsPath as string; - if (!filePath.endsWith("manifest.template.json")) { - const envReg = /manifest\.(\w+)\.json$/; - const result = envReg.exec(filePath); - if (result && result.length >= 2) { - env = result[1]; - } - } - } - - const inputs = getSystemInputs(); - const result = await runCommand(Stage.deployTeams, inputs); - - if (!args || args.length === 0) { - const workspacePath = workspaceUri?.fsPath; - const inputs = getSystemInputs(); - inputs.ignoreEnvInfo = true; - const env = await core.getSelectedEnv(inputs); - if (env.isErr()) { - ExtTelemetry.sendTelemetryErrorEvent(TelemetryEvent.UpdatePreviewManifest, env.error); - return err(env.error); - } - const manifestPath = `${ - workspacePath as string - }/${AppPackageFolderName}/${BuildFolderName}/manifest.${env.value as string}.json`; - void workspace.openTextDocument(manifestPath).then((document) => { - void window.showTextDocument(document); - }); - } - return result; -} - export async function copilotPluginAddAPIHandler(args: any[]) { // Telemetries are handled in runCommand() const inputs = getSystemInputs(); diff --git a/packages/vscode-extension/test/extension/handlers.test.ts b/packages/vscode-extension/test/extension/handlers.test.ts index 0a002c0fb5..b760a20cf0 100644 --- a/packages/vscode-extension/test/extension/handlers.test.ts +++ b/packages/vscode-extension/test/extension/handlers.test.ts @@ -41,7 +41,7 @@ import * as vscode from "vscode"; import { AzureAccountManager } from "../../src/commonlib/azureLogin"; import { signedIn, signedOut } from "../../src/commonlib/common/constant"; import VsCodeLogInstance, { VsCodeLogProvider } from "../../src/commonlib/log"; -import M365TokenInstance, { M365Login } from "../../src/commonlib/m365Login"; +import M365TokenInstance from "../../src/commonlib/m365Login"; import { DeveloperPortalHomeLink, GlobalKey } from "../../src/constants"; import { PanelType } from "../../src/controls/PanelType"; import { WebviewPanel } from "../../src/controls/webviewPanel"; @@ -102,37 +102,6 @@ describe("handlers", () => { sandbox.restore(); }); - it("buildPackageHandler()", async () => { - sandbox.stub(globalVariables, "core").value(new MockCore()); - sandbox.stub(globalVariables.core, "createAppPackage").resolves(err(new UserCancelError())); - sandbox.stub(ExtTelemetry, "sendTelemetryEvent"); - const sendTelemetryErrorEvent = sandbox.stub(ExtTelemetry, "sendTelemetryErrorEvent"); - - await handlers.buildPackageHandler(); - - // should show error for invalid project - sinon.assert.calledOnce(sendTelemetryErrorEvent); - }); - - it("validateManifestHandler() - app package", async () => { - sandbox.stub(globalVariables, "core").value(new MockCore()); - sandbox.stub(ExtTelemetry, "sendTelemetryEvent"); - sandbox.stub(ExtTelemetry, "sendTelemetryErrorEvent"); - sandbox.stub(localizeUtils, "localize").returns(""); - sandbox.stub(projectSettingsHelper, "isValidProject").returns(true); - sandbox.stub(systemEnvUtils, "getSystemInputs").returns({} as Inputs); - const validateApplication = sandbox.spy(globalVariables.core, "validateApplication"); - - sandbox.stub(vsc_ui, "VS_CODE_UI").value({ - selectOption: () => { - return Promise.resolve(ok({ type: "success", result: "validateAgainstPackage" })); - }, - }); - - await handlers.validateManifestHandler(); - sinon.assert.calledOnce(validateApplication); - }); - it("API ME: copilotPluginAddAPIHandler()", async () => { sandbox.stub(globalVariables, "core").value(new MockCore()); const addAPIHanlder = sandbox.spy(globalVariables.core, "copilotPluginAddAPI"); @@ -1282,80 +1251,6 @@ describe("handlers", () => { }); }); - describe("publishInDeveloperPortalHandler", async () => { - const sandbox = sinon.createSandbox(); - - beforeEach(() => { - sandbox.stub(globalVariables, "workspaceUri").value(vscode.Uri.file("path")); - }); - - afterEach(() => { - sandbox.restore(); - }); - - it("publish in developer portal - success", async () => { - sandbox.stub(globalVariables, "core").value(new MockCore()); - sandbox.stub(vsc_ui, "VS_CODE_UI").value(new VsCodeUI({})); - sandbox - .stub(vsc_ui.VS_CODE_UI, "selectFile") - .resolves(ok({ type: "success", result: "test.zip" })); - const publish = sandbox.spy(globalVariables.core, "publishInDeveloperPortal"); - sandbox - .stub(vsc_ui.VS_CODE_UI, "selectOption") - .resolves(ok({ type: "success", result: "test.zip" })); - sandbox.stub(ExtTelemetry, "sendTelemetryEvent"); - sandbox.stub(ExtTelemetry, "sendTelemetryErrorEvent"); - sandbox.stub(vscode.commands, "executeCommand"); - sandbox.stub(fs, "pathExists").resolves(true); - sandbox.stub(fs, "readdir").resolves(["test.zip", "test.json"] as any); - - const res = await handlers.publishInDeveloperPortalHandler(); - if (res.isErr()) { - console.log(res.error); - } - chai.assert.isTrue(publish.calledOnce); - chai.assert.isTrue(res.isOk()); - }); - - it("publish in developer portal - cancelled", async () => { - sandbox.stub(globalVariables, "core").value(new MockCore()); - sandbox.stub(vsc_ui, "VS_CODE_UI").value(new VsCodeUI({})); - sandbox - .stub(vsc_ui.VS_CODE_UI, "selectFile") - .resolves(ok({ type: "success", result: "test2.zip" })); - const publish = sandbox.spy(globalVariables.core, "publishInDeveloperPortal"); - sandbox.stub(vsc_ui.VS_CODE_UI, "selectOption").resolves(err(new UserCancelError("VSC"))); - sandbox.stub(ExtTelemetry, "sendTelemetryEvent"); - sandbox.stub(ExtTelemetry, "sendTelemetryErrorEvent"); - sandbox.stub(vscode.commands, "executeCommand"); - sandbox.stub(fs, "pathExists").resolves(true); - sandbox.stub(fs, "readdir").resolves(["test.zip", "test.json"] as any); - - const res = await handlers.publishInDeveloperPortalHandler(); - if (res.isErr()) { - console.log(res.error); - } - chai.assert.isTrue(publish.notCalled); - chai.assert.isTrue(res.isOk()); - }); - - it("select file error", async () => { - sandbox.stub(globalVariables, "core").value(new MockCore()); - sandbox.stub(vsc_ui, "VS_CODE_UI").value(new VsCodeUI({})); - sandbox.stub(vsc_ui.VS_CODE_UI, "selectFile").resolves(err(new UserCancelError("VSC"))); - const publish = sandbox.spy(globalVariables.core, "publishInDeveloperPortal"); - sandbox.stub(ExtTelemetry, "sendTelemetryEvent"); - sandbox.stub(ExtTelemetry, "sendTelemetryErrorEvent"); - sandbox.stub(vscode.commands, "executeCommand"); - sandbox.stub(fs, "pathExists").resolves(true); - sandbox.stub(fs, "readdir").resolves(["test.zip", "test.json"] as any); - - const res = await handlers.publishInDeveloperPortalHandler(); - chai.assert.isTrue(res.isOk()); - chai.assert.isFalse(publish.calledOnce); - }); - }); - describe("openAppManagement", async () => { const sandbox = sinon.createSandbox(); @@ -1742,26 +1637,6 @@ describe("handlers", () => { chai.assert.equal(actualPath, path.delimiter); }); }); - - describe("others", function () { - const sandbox = sinon.createSandbox(); - afterEach(() => { - sandbox.restore(); - }); - - it("updatePreviewManifest", async () => { - sandbox.stub(globalVariables, "core").value(new MockCore()); - sandbox.stub(ExtTelemetry, "sendTelemetryEvent"); - sandbox.stub(ExtTelemetry, "sendTelemetryErrorEvent"); - const openTextDocumentStub = sandbox - .stub(vscode.workspace, "openTextDocument") - .returns(Promise.resolve("" as any)); - - await handlers.updatePreviewManifest([]); - - chai.assert.isTrue(openTextDocumentStub.calledOnce); - }); - }); }); describe("openPreviewAadFile", () => {