From b462957eb266dda560d9ba9625fc6bb52e08cfaf Mon Sep 17 00:00:00 2001 From: Huajie Zhang Date: Wed, 26 Jun 2024 13:09:51 +0800 Subject: [PATCH] refactor: seperate scaffold from tdp (#11910) * refactor: seperate scaffold from tdp * test: ut --- packages/vscode-extension/src/extension.ts | 3 +- packages/vscode-extension/src/handlers.ts | 99 ---------- .../src/handlers/lifecycleHandlers.ts | 122 +++++++++++- .../test/extension/handlers.test.ts | 161 ---------------- .../test/handlers/lifecycleHandlers.test.ts | 176 +++++++++++++++++- 5 files changed, 296 insertions(+), 265 deletions(-) diff --git a/packages/vscode-extension/src/extension.ts b/packages/vscode-extension/src/extension.ts index d2285d2a04..b2603b300e 100644 --- a/packages/vscode-extension/src/extension.ts +++ b/packages/vscode-extension/src/extension.ts @@ -87,6 +87,7 @@ import { deployHandler, provisionHandler, publishHandler, + scaffoldFromDeveloperPortalHandler, } from "./handlers/lifecycleHandlers"; import * as officeDevHandlers from "./handlers/officeDevHandlers"; import { @@ -422,7 +423,7 @@ function registerInternalCommands(context: vscode.ExtensionContext) { registerInCommandController( context, "fx-extension.openFromTdp", - handlers.scaffoldFromDeveloperPortalHandler, + scaffoldFromDeveloperPortalHandler, "openFromTdp" ); diff --git a/packages/vscode-extension/src/handlers.ts b/packages/vscode-extension/src/handlers.ts index c7003e4918..3de3aa5622 100644 --- a/packages/vscode-extension/src/handlers.ts +++ b/packages/vscode-extension/src/handlers.ts @@ -713,102 +713,3 @@ export async function selectSubscriptionCallback(args?: any[]): Promise> { - if (!args || args.length < 1) { - // should never happen - return ok(null); - } - - const appId = args[0]; - const properties: { [p: string]: string } = { - teamsAppId: appId, - }; - - ExtTelemetry.sendTelemetryEvent(TelemetryEvent.HandleUrlFromDeveloperProtalStart, properties); - const loginHint = args.length < 2 ? undefined : args[1]; - const progressBar = VS_CODE_UI.createProgressBar( - localize("teamstoolkit.devPortalIntegration.checkM365Account.progressTitle"), - 1 - ); - - await progressBar.start(); - let token = undefined; - try { - const tokenRes = await M365TokenInstance.signInWhenInitiatedFromTdp( - { scopes: AppStudioScopes }, - loginHint - ); - if (tokenRes.isErr()) { - if ((tokenRes.error as any).displayMessage) { - void vscode.window.showErrorMessage((tokenRes.error as any).displayMessage); - } else { - void vscode.window.showErrorMessage( - localize("teamstoolkit.devPortalIntegration.generalError.message") - ); - } - ExtTelemetry.sendTelemetryErrorEvent( - TelemetryEvent.HandleUrlFromDeveloperProtal, - tokenRes.error, - properties - ); - await progressBar.end(false); - return err(tokenRes.error); - } - token = tokenRes.value; - - // set region - const AuthSvcTokenRes = await M365TokenInstance.getAccessToken({ scopes: AuthSvcScopes }); - if (AuthSvcTokenRes.isOk()) { - await teamsDevPortalClient.setRegionEndpointByToken(AuthSvcTokenRes.value); - } - - await progressBar.end(true); - } catch (e) { - void vscode.window.showErrorMessage( - localize("teamstoolkit.devPortalIntegration.generalError.message") - ); - await progressBar.end(false); - const error = assembleError(e); - ExtTelemetry.sendTelemetryErrorEvent( - TelemetryEvent.HandleUrlFromDeveloperProtal, - error, - properties - ); - return err(error); - } - - let appDefinition; - try { - appDefinition = await teamsDevPortalClient.getApp(token, appId); - } catch (error: any) { - ExtTelemetry.sendTelemetryErrorEvent( - TelemetryEvent.HandleUrlFromDeveloperProtal, - error, - properties - ); - void vscode.window.showErrorMessage( - localize("teamstoolkit.devPortalIntegration.getTeamsAppError.message") - ); - return err(error); - } - - const res = await createNewProjectHandler({ teamsAppFromTdp: appDefinition }); - - if (res.isErr()) { - ExtTelemetry.sendTelemetryErrorEvent( - TelemetryEvent.HandleUrlFromDeveloperProtal, - res.error, - properties - ); - return err(res.error); - } - - ExtTelemetry.sendTelemetryEvent(TelemetryEvent.HandleUrlFromDeveloperProtal, properties); - return ok(null); -} diff --git a/packages/vscode-extension/src/handlers/lifecycleHandlers.ts b/packages/vscode-extension/src/handlers/lifecycleHandlers.ts index 6e2cd9f0af..f52cebdc0e 100644 --- a/packages/vscode-extension/src/handlers/lifecycleHandlers.ts +++ b/packages/vscode-extension/src/handlers/lifecycleHandlers.ts @@ -1,11 +1,30 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { CreateProjectResult, err, FxError, Inputs, Result, Stage } from "@microsoft/teamsfx-api"; -import { isUserCancelError, isValidOfficeAddInProject } from "@microsoft/teamsfx-core"; +import { + CreateProjectResult, + err, + FxError, + Inputs, + ok, + Result, + Stage, +} from "@microsoft/teamsfx-api"; +import { + AppStudioScopes, + assembleError, + AuthSvcScopes, + isUserCancelError, + isValidOfficeAddInProject, + teamsDevPortalClient, +} from "@microsoft/teamsfx-core"; +import * as vscode from "vscode"; import { Uri } from "vscode"; +import M365TokenInstance from "../commonlib/m365Login"; +import { VS_CODE_UI } from "../qm/vsc_ui"; import { ExtTelemetry } from "../telemetry/extTelemetry"; import { TelemetryEvent, TelemetryTriggerFrom } from "../telemetry/extTelemetryEvents"; import envTreeProviderInstance from "../treeview/environmentTreeViewProvider"; +import { localize } from "../utils/localizeUtils"; import { getSystemInputs } from "../utils/systemEnvUtils"; import { getTriggerFromProperty } from "../utils/telemetryUtils"; import { openFolder, openOfficeDevFolder } from "../utils/workspaceUtils"; @@ -75,3 +94,102 @@ export async function addWebpartHandler(...args: unknown[]) { ExtTelemetry.sendTelemetryEvent(TelemetryEvent.AddWebpartStart, getTriggerFromProperty(args)); return await runCommand(Stage.addWebpart); } + +/** + * scaffold based on app id from Developer Portal + */ +export async function scaffoldFromDeveloperPortalHandler( + ...args: any[] +): Promise> { + if (!args || args.length < 1) { + // should never happen + return ok(null); + } + + const appId = args[0]; + const properties: { [p: string]: string } = { + teamsAppId: appId, + }; + + ExtTelemetry.sendTelemetryEvent(TelemetryEvent.HandleUrlFromDeveloperProtalStart, properties); + const loginHint = args.length < 2 ? undefined : args[1]; + const progressBar = VS_CODE_UI.createProgressBar( + localize("teamstoolkit.devPortalIntegration.checkM365Account.progressTitle"), + 1 + ); + + await progressBar.start(); + let token = undefined; + try { + const tokenRes = await M365TokenInstance.signInWhenInitiatedFromTdp( + { scopes: AppStudioScopes }, + loginHint + ); + if (tokenRes.isErr()) { + if ((tokenRes.error as any).displayMessage) { + void vscode.window.showErrorMessage((tokenRes.error as any).displayMessage); + } else { + void vscode.window.showErrorMessage( + localize("teamstoolkit.devPortalIntegration.generalError.message") + ); + } + ExtTelemetry.sendTelemetryErrorEvent( + TelemetryEvent.HandleUrlFromDeveloperProtal, + tokenRes.error, + properties + ); + await progressBar.end(false); + return err(tokenRes.error); + } + token = tokenRes.value; + + // set region + const AuthSvcTokenRes = await M365TokenInstance.getAccessToken({ scopes: AuthSvcScopes }); + if (AuthSvcTokenRes.isOk()) { + await teamsDevPortalClient.setRegionEndpointByToken(AuthSvcTokenRes.value); + } + + await progressBar.end(true); + } catch (e) { + void vscode.window.showErrorMessage( + localize("teamstoolkit.devPortalIntegration.generalError.message") + ); + await progressBar.end(false); + const error = assembleError(e); + ExtTelemetry.sendTelemetryErrorEvent( + TelemetryEvent.HandleUrlFromDeveloperProtal, + error, + properties + ); + return err(error); + } + + let appDefinition; + try { + appDefinition = await teamsDevPortalClient.getApp(token, appId); + } catch (error: any) { + ExtTelemetry.sendTelemetryErrorEvent( + TelemetryEvent.HandleUrlFromDeveloperProtal, + error, + properties + ); + void vscode.window.showErrorMessage( + localize("teamstoolkit.devPortalIntegration.getTeamsAppError.message") + ); + return err(error); + } + + const res = await createNewProjectHandler({ teamsAppFromTdp: appDefinition }); + + if (res.isErr()) { + ExtTelemetry.sendTelemetryErrorEvent( + TelemetryEvent.HandleUrlFromDeveloperProtal, + res.error, + properties + ); + return err(res.error); + } + + ExtTelemetry.sendTelemetryEvent(TelemetryEvent.HandleUrlFromDeveloperProtal, properties); + return ok(null); +} diff --git a/packages/vscode-extension/test/extension/handlers.test.ts b/packages/vscode-extension/test/extension/handlers.test.ts index be25e2bb7a..369330dbef 100644 --- a/packages/vscode-extension/test/extension/handlers.test.ts +++ b/packages/vscode-extension/test/extension/handlers.test.ts @@ -590,167 +590,6 @@ describe("handlers", () => { }); }); - describe("scaffoldFromDeveloperPortalHandler", async () => { - const sandbox = sinon.createSandbox(); - - beforeEach(() => { - sandbox.stub(ExtTelemetry, "sendTelemetryEvent").resolves(); - sandbox.stub(ExtTelemetry, "sendTelemetryErrorEvent").resolves(); - sandbox.stub(globalVariables, "checkIsSPFx").returns(false); - }); - - afterEach(() => { - sandbox.restore(); - }); - - it("missing args", async () => { - const progressHandler = new ProgressHandler("title", 1); - sandbox.stub(vsc_ui, "VS_CODE_UI").value(new VsCodeUI({})); - const createProgressBar = sandbox - .stub(vsc_ui.VS_CODE_UI, "createProgressBar") - .returns(progressHandler); - - const res = await handlers.scaffoldFromDeveloperPortalHandler(); - - chai.assert.equal(res.isOk(), true); - chai.assert.equal(createProgressBar.notCalled, true); - }); - - it("incorrect number of args", async () => { - const progressHandler = new ProgressHandler("title", 1); - sandbox.stub(vsc_ui, "VS_CODE_UI").value(new VsCodeUI({})); - const createProgressBar = sandbox - .stub(vsc_ui.VS_CODE_UI, "createProgressBar") - .returns(progressHandler); - - const res = await handlers.scaffoldFromDeveloperPortalHandler(); - - chai.assert.equal(res.isOk(), true); - chai.assert.equal(createProgressBar.notCalled, true); - }); - - it("general error when signing in M365", async () => { - sandbox.stub(vsc_ui, "VS_CODE_UI").value(new VsCodeUI({})); - const progressHandler = new ProgressHandler("title", 1); - const startProgress = sandbox.stub(progressHandler, "start").resolves(); - const endProgress = sandbox.stub(progressHandler, "end").resolves(); - sandbox.stub(M365TokenInstance, "signInWhenInitiatedFromTdp").throws("error1"); - const createProgressBar = sandbox - .stub(vsc_ui.VS_CODE_UI, "createProgressBar") - .returns(progressHandler); - const showErrorMessage = sandbox.stub(vscode.window, "showErrorMessage"); - - const res = await handlers.scaffoldFromDeveloperPortalHandler(["appId"]); - chai.assert.isTrue(res.isErr()); - chai.assert.isTrue(createProgressBar.calledOnce); - chai.assert.isTrue(startProgress.calledOnce); - chai.assert.isTrue(endProgress.calledOnceWithExactly(false)); - chai.assert.isTrue(showErrorMessage.calledOnce); - if (res.isErr()) { - chai.assert.isTrue(res.error instanceof UnhandledError); - } - }); - - it("error when signing M365", async () => { - sandbox.stub(vsc_ui, "VS_CODE_UI").value(new VsCodeUI({})); - const progressHandler = new ProgressHandler("title", 1); - const startProgress = sandbox.stub(progressHandler, "start").resolves(); - const endProgress = sandbox.stub(progressHandler, "end").resolves(); - sandbox - .stub(M365TokenInstance, "signInWhenInitiatedFromTdp") - .resolves(err(new UserError("source", "name", "message", "displayMessage"))); - const createProgressBar = sandbox - .stub(vsc_ui.VS_CODE_UI, "createProgressBar") - .returns(progressHandler); - const showErrorMessage = sandbox.stub(vscode.window, "showErrorMessage"); - - const res = await handlers.scaffoldFromDeveloperPortalHandler(["appId"]); - - chai.assert.equal(res.isErr(), true); - chai.assert.equal(createProgressBar.calledOnce, true); - chai.assert.equal(startProgress.calledOnce, true); - chai.assert.equal(endProgress.calledOnceWithExactly(false), true); - chai.assert.equal(showErrorMessage.calledOnce, true); - }); - - it("error when signing in M365 but missing display message", async () => { - sandbox.stub(vsc_ui, "VS_CODE_UI").value(new VsCodeUI({})); - const progressHandler = new ProgressHandler("title", 1); - const startProgress = sandbox.stub(progressHandler, "start").resolves(); - const endProgress = sandbox.stub(progressHandler, "end").resolves(); - sandbox - .stub(M365TokenInstance, "signInWhenInitiatedFromTdp") - .resolves(err(new UserError("source", "name", "", ""))); - const createProgressBar = sandbox - .stub(vsc_ui.VS_CODE_UI, "createProgressBar") - .returns(progressHandler); - const showErrorMessage = sandbox.stub(vscode.window, "showErrorMessage"); - - const res = await handlers.scaffoldFromDeveloperPortalHandler(["appId"]); - - chai.assert.equal(res.isErr(), true); - chai.assert.equal(createProgressBar.calledOnce, true); - chai.assert.equal(startProgress.calledOnce, true); - chai.assert.equal(endProgress.calledOnceWithExactly(false), true); - chai.assert.equal(showErrorMessage.calledOnce, true); - }); - - it("failed to get teams app", async () => { - sandbox.stub(vsc_ui, "VS_CODE_UI").value(new VsCodeUI({})); - const progressHandler = new ProgressHandler("title", 1); - const startProgress = sandbox.stub(progressHandler, "start").resolves(); - const endProgress = sandbox.stub(progressHandler, "end").resolves(); - sandbox.stub(M365TokenInstance, "signInWhenInitiatedFromTdp").resolves(ok("token")); - sandbox - .stub(M365TokenInstance, "getAccessToken") - .resolves(err(new SystemError("source", "name", "", ""))); - const createProgressBar = sandbox - .stub(vsc_ui.VS_CODE_UI, "createProgressBar") - .returns(progressHandler); - sandbox.stub(globalVariables, "core").value(new MockCore()); - sandbox.stub(vscode.commands, "executeCommand"); - sandbox.stub(globalState, "globalStateUpdate"); - const getApp = sandbox.stub(teamsDevPortalClient, "getApp").throws("error"); - - const res = await handlers.scaffoldFromDeveloperPortalHandler(["appId"]); - - chai.assert.isTrue(res.isErr()); - chai.assert.isTrue(getApp.calledOnce); - chai.assert.isTrue(createProgressBar.calledOnce); - chai.assert.isTrue(startProgress.calledOnce); - chai.assert.isTrue(endProgress.calledOnceWithExactly(true)); - }); - - it("happy path", async () => { - sandbox.stub(vsc_ui, "VS_CODE_UI").value(new VsCodeUI({})); - const progressHandler = new ProgressHandler("title", 1); - const startProgress = sandbox.stub(progressHandler, "start").resolves(); - const endProgress = sandbox.stub(progressHandler, "end").resolves(); - sandbox.stub(M365TokenInstance, "signInWhenInitiatedFromTdp").resolves(ok("token")); - sandbox.stub(M365TokenInstance, "getAccessToken").resolves(ok("authSvcToken")); - sandbox.stub(teamsDevPortalClient, "setRegionEndpointByToken").resolves(); - const createProgressBar = sandbox - .stub(vsc_ui.VS_CODE_UI, "createProgressBar") - .returns(progressHandler); - sandbox.stub(globalVariables, "core").value(new MockCore()); - const createProject = sandbox.spy(globalVariables.core, "createProject"); - sandbox.stub(vscode.commands, "executeCommand"); - sandbox.stub(globalState, "globalStateUpdate"); - const appDefinition: AppDefinition = { - teamsAppId: "mock-id", - }; - sandbox.stub(teamsDevPortalClient, "getApp").resolves(appDefinition); - - const res = await handlers.scaffoldFromDeveloperPortalHandler("appId", "testuser"); - - chai.assert.equal(createProject.args[0][0].teamsAppFromTdp.teamsAppId, "mock-id"); - chai.assert.isTrue(res.isOk()); - chai.assert.isTrue(createProgressBar.calledOnce); - chai.assert.isTrue(startProgress.calledOnce); - chai.assert.isTrue(endProgress.calledOnceWithExactly(true)); - }); - }); - describe("openAppManagement", async () => { const sandbox = sinon.createSandbox(); diff --git a/packages/vscode-extension/test/handlers/lifecycleHandlers.test.ts b/packages/vscode-extension/test/handlers/lifecycleHandlers.test.ts index 8b93781444..6ba2c82a1a 100644 --- a/packages/vscode-extension/test/handlers/lifecycleHandlers.test.ts +++ b/packages/vscode-extension/test/handlers/lifecycleHandlers.test.ts @@ -1,8 +1,16 @@ -import { err, ok, Platform } from "@microsoft/teamsfx-api"; -import { UserCancelError } from "@microsoft/teamsfx-core"; +import { err, ok, Platform, SystemError, UserError } from "@microsoft/teamsfx-api"; +import { + AppDefinition, + teamsDevPortalClient, + UnhandledError, + UserCancelError, +} from "@microsoft/teamsfx-core"; import * as projectSettingsHelper from "@microsoft/teamsfx-core/build/common/projectSettingsHelper"; +import { ProgressHandler } from "@microsoft/vscode-ui"; import { assert } from "chai"; import * as sinon from "sinon"; +import * as vscode from "vscode"; +import * as globalVariables from "../../src/globalVariables"; import * as copilotHandler from "../../src/handlers/copilotChatHandlers"; import { addWebpartHandler, @@ -10,14 +18,19 @@ import { deployHandler, provisionHandler, publishHandler, + scaffoldFromDeveloperPortalHandler, } from "../../src/handlers/lifecycleHandlers"; import * as shared from "../../src/handlers/sharedOpts"; import { processResult } from "../../src/handlers/sharedOpts"; +import * as vsc_ui from "../../src/qm/vsc_ui"; import { ExtTelemetry } from "../../src/telemetry/extTelemetry"; import { TelemetryEvent } from "../../src/telemetry/extTelemetryEvents"; import envTreeProviderInstance from "../../src/treeview/environmentTreeViewProvider"; import * as telemetryUtils from "../../src/utils/telemetryUtils"; import * as workspaceUtils from "../../src/utils/workspaceUtils"; +import M365TokenInstance from "../../src/commonlib/m365Login"; +import { MockCore } from "../mocks/mockCore"; +import * as globalState from "@microsoft/teamsfx-core/build/common/globalState"; describe("Lifecycle handlers", () => { const sandbox = sinon.createSandbox(); @@ -156,4 +169,163 @@ describe("Lifecycle handlers", () => { assert.isTrue(res.isOk()); }); }); + + describe("scaffoldFromDeveloperPortalHandler", async () => { + const sandbox = sinon.createSandbox(); + + beforeEach(() => { + sandbox.stub(globalVariables, "checkIsSPFx").returns(false); + }); + + afterEach(() => { + sandbox.restore(); + }); + + it("missing args", async () => { + const progressHandler = new ProgressHandler("title", 1); + sandbox.stub(vsc_ui, "VS_CODE_UI").value(new vsc_ui.VsCodeUI({})); + const createProgressBar = sandbox + .stub(vsc_ui.VS_CODE_UI, "createProgressBar") + .returns(progressHandler); + + const res = await scaffoldFromDeveloperPortalHandler(); + + assert.equal(res.isOk(), true); + assert.equal(createProgressBar.notCalled, true); + }); + + it("incorrect number of args", async () => { + const progressHandler = new ProgressHandler("title", 1); + sandbox.stub(vsc_ui, "VS_CODE_UI").value(new vsc_ui.VsCodeUI({})); + const createProgressBar = sandbox + .stub(vsc_ui.VS_CODE_UI, "createProgressBar") + .returns(progressHandler); + + const res = await scaffoldFromDeveloperPortalHandler(); + + assert.equal(res.isOk(), true); + assert.equal(createProgressBar.notCalled, true); + }); + + it("general error when signing in M365", async () => { + sandbox.stub(vsc_ui, "VS_CODE_UI").value(new vsc_ui.VsCodeUI({})); + const progressHandler = new ProgressHandler("title", 1); + const startProgress = sandbox.stub(progressHandler, "start").resolves(); + const endProgress = sandbox.stub(progressHandler, "end").resolves(); + sandbox.stub(M365TokenInstance, "signInWhenInitiatedFromTdp").throws("error1"); + const createProgressBar = sandbox + .stub(vsc_ui.VS_CODE_UI, "createProgressBar") + .returns(progressHandler); + const showErrorMessage = sandbox.stub(vscode.window, "showErrorMessage"); + + const res = await scaffoldFromDeveloperPortalHandler(["appId"]); + assert.isTrue(res.isErr()); + assert.isTrue(createProgressBar.calledOnce); + assert.isTrue(startProgress.calledOnce); + assert.isTrue(endProgress.calledOnceWithExactly(false)); + assert.isTrue(showErrorMessage.calledOnce); + if (res.isErr()) { + assert.isTrue(res.error instanceof UnhandledError); + } + }); + + it("error when signing M365", async () => { + sandbox.stub(vsc_ui, "VS_CODE_UI").value(new vsc_ui.VsCodeUI({})); + const progressHandler = new ProgressHandler("title", 1); + const startProgress = sandbox.stub(progressHandler, "start").resolves(); + const endProgress = sandbox.stub(progressHandler, "end").resolves(); + sandbox + .stub(M365TokenInstance, "signInWhenInitiatedFromTdp") + .resolves(err(new UserError("source", "name", "message", "displayMessage"))); + const createProgressBar = sandbox + .stub(vsc_ui.VS_CODE_UI, "createProgressBar") + .returns(progressHandler); + const showErrorMessage = sandbox.stub(vscode.window, "showErrorMessage"); + + const res = await scaffoldFromDeveloperPortalHandler(["appId"]); + + assert.equal(res.isErr(), true); + assert.equal(createProgressBar.calledOnce, true); + assert.equal(startProgress.calledOnce, true); + assert.equal(endProgress.calledOnceWithExactly(false), true); + assert.equal(showErrorMessage.calledOnce, true); + }); + + it("error when signing in M365 but missing display message", async () => { + sandbox.stub(vsc_ui, "VS_CODE_UI").value(new vsc_ui.VsCodeUI({})); + const progressHandler = new ProgressHandler("title", 1); + const startProgress = sandbox.stub(progressHandler, "start").resolves(); + const endProgress = sandbox.stub(progressHandler, "end").resolves(); + sandbox + .stub(M365TokenInstance, "signInWhenInitiatedFromTdp") + .resolves(err(new UserError("source", "name", "", ""))); + const createProgressBar = sandbox + .stub(vsc_ui.VS_CODE_UI, "createProgressBar") + .returns(progressHandler); + const showErrorMessage = sandbox.stub(vscode.window, "showErrorMessage"); + + const res = await scaffoldFromDeveloperPortalHandler(["appId"]); + + assert.equal(res.isErr(), true); + assert.equal(createProgressBar.calledOnce, true); + assert.equal(startProgress.calledOnce, true); + assert.equal(endProgress.calledOnceWithExactly(false), true); + assert.equal(showErrorMessage.calledOnce, true); + }); + + it("failed to get teams app", async () => { + sandbox.stub(vsc_ui, "VS_CODE_UI").value(new vsc_ui.VsCodeUI({})); + const progressHandler = new ProgressHandler("title", 1); + const startProgress = sandbox.stub(progressHandler, "start").resolves(); + const endProgress = sandbox.stub(progressHandler, "end").resolves(); + sandbox.stub(M365TokenInstance, "signInWhenInitiatedFromTdp").resolves(ok("token")); + sandbox + .stub(M365TokenInstance, "getAccessToken") + .resolves(err(new SystemError("source", "name", "", ""))); + const createProgressBar = sandbox + .stub(vsc_ui.VS_CODE_UI, "createProgressBar") + .returns(progressHandler); + sandbox.stub(globalVariables, "core").value(new MockCore()); + sandbox.stub(vscode.commands, "executeCommand"); + sandbox.stub(globalState, "globalStateUpdate"); + const getApp = sandbox.stub(teamsDevPortalClient, "getApp").throws("error"); + + const res = await scaffoldFromDeveloperPortalHandler(["appId"]); + + assert.isTrue(res.isErr()); + assert.isTrue(getApp.calledOnce); + assert.isTrue(createProgressBar.calledOnce); + assert.isTrue(startProgress.calledOnce); + assert.isTrue(endProgress.calledOnceWithExactly(true)); + }); + + it("happy path", async () => { + sandbox.stub(vsc_ui, "VS_CODE_UI").value(new vsc_ui.VsCodeUI({})); + const progressHandler = new ProgressHandler("title", 1); + const startProgress = sandbox.stub(progressHandler, "start").resolves(); + const endProgress = sandbox.stub(progressHandler, "end").resolves(); + sandbox.stub(M365TokenInstance, "signInWhenInitiatedFromTdp").resolves(ok("token")); + sandbox.stub(M365TokenInstance, "getAccessToken").resolves(ok("authSvcToken")); + sandbox.stub(teamsDevPortalClient, "setRegionEndpointByToken").resolves(); + const createProgressBar = sandbox + .stub(vsc_ui.VS_CODE_UI, "createProgressBar") + .returns(progressHandler); + sandbox.stub(globalVariables, "core").value(new MockCore()); + const createProject = sandbox.spy(globalVariables.core, "createProject"); + sandbox.stub(vscode.commands, "executeCommand"); + sandbox.stub(globalState, "globalStateUpdate"); + const appDefinition: AppDefinition = { + teamsAppId: "mock-id", + }; + sandbox.stub(teamsDevPortalClient, "getApp").resolves(appDefinition); + + const res = await scaffoldFromDeveloperPortalHandler("appId", "testuser"); + + assert.equal(createProject.args[0][0].teamsAppFromTdp.teamsAppId, "mock-id"); + assert.isTrue(res.isOk()); + assert.isTrue(createProgressBar.calledOnce); + assert.isTrue(startProgress.calledOnce); + assert.isTrue(endProgress.calledOnceWithExactly(true)); + }); + }); });