diff --git a/packages/fx-core/resource/yaml-schema/yaml.schema.json b/packages/fx-core/resource/yaml-schema/yaml.schema.json index 7fc8e669ce..df17cc4a29 100644 --- a/packages/fx-core/resource/yaml-schema/yaml.schema.json +++ b/packages/fx-core/resource/yaml-schema/yaml.schema.json @@ -1277,6 +1277,10 @@ "symlinkDir": { "type": "string", "description": "The path of the symlink target for the folder containing Azure Functions Core Tools binaries." + }, + "releaseType": { + "type": "string", + "description": "The release type of Teams App Test Tool: binary or npm. Default to 'npm'." } } }, diff --git a/packages/fx-core/src/component/driver/devTool/installDriver.ts b/packages/fx-core/src/component/driver/devTool/installDriver.ts index 41650d2a81..5fea07b85b 100644 --- a/packages/fx-core/src/component/driver/devTool/installDriver.ts +++ b/packages/fx-core/src/component/driver/devTool/installDriver.ts @@ -4,10 +4,14 @@ /** * @author Xiaofu Huang */ +import { hooks } from "@feathersjs/hooks/lib"; +import { FxError, Result } from "@microsoft/teamsfx-api"; import * as path from "path"; import semver from "semver"; import { Service } from "typedi"; -import { FxError, Result } from "@microsoft/teamsfx-api"; +import { ErrorContextMW } from "../../../common/globalVars"; +import { getLocalizedString } from "../../../common/localizeUtils"; +import { InvalidActionInputError } from "../../../error/common"; import { DependencyStatus, EmptyLogger, @@ -15,10 +19,14 @@ import { TestToolReleaseType, v3DefaultHelpLink, } from "../../deps-checker"; +import { DotnetChecker } from "../../deps-checker/internal/dotnetChecker"; +import { FuncToolChecker } from "../../deps-checker/internal/funcToolChecker"; +import { TestToolChecker } from "../../deps-checker/internal/testToolChecker"; import { LocalCertificate, LocalCertificateManager } from "../../local/localCertificateManager"; import { wrapRun } from "../../utils/common"; import { DriverContext } from "../interface/commonArgs"; import { ExecutionResult, StepDriver } from "../interface/stepDriver"; +import { addStartAndEndTelemetry } from "../middleware/addStartAndEndTelemetry"; import { WrapDriverContext } from "../util/wrapUtil"; import { Summaries, @@ -29,16 +37,8 @@ import { } from "./constant"; import { DotnetInstallationUserError } from "./error/dotnetInstallationUserError"; import { FuncInstallationUserError } from "./error/funcInstallationUserError"; -import { InstallToolArgs } from "./interfaces/InstallToolArgs"; -import { InvalidActionInputError } from "../../../error/common"; -import { addStartAndEndTelemetry } from "../middleware/addStartAndEndTelemetry"; -import { hooks } from "@feathersjs/hooks/lib"; -import { getLocalizedString } from "../../../common/localizeUtils"; -import { FuncToolChecker } from "../../deps-checker/internal/funcToolChecker"; -import { DotnetChecker } from "../../deps-checker/internal/dotnetChecker"; -import { ErrorContextMW } from "../../../common/globalVars"; -import { TestToolChecker } from "../../deps-checker/internal/testToolChecker"; import { TestToolInstallationUserError } from "./error/testToolInstallationUserError"; +import { InstallToolArgs } from "./interfaces/InstallToolArgs"; const ACTION_NAME = "devTool/install"; const helpLink = "https://aka.ms/teamsfx-actions/devtool-install"; @@ -127,8 +127,9 @@ export class ToolsInstallDriverImpl { if (args.testTool) { await this.resolveTestTool( - // Hardcode to npm release type if running from YAML - TestToolReleaseType.Npm, + args.testTool.releaseType == TestToolReleaseType.Binary + ? TestToolReleaseType.Binary + : TestToolReleaseType.Npm, `${args.testTool.version}`, args.testTool.symlinkDir ); @@ -329,6 +330,13 @@ export class ToolsInstallDriverImpl { if (typeof args.testTool.symlinkDir !== "string") { throw new InvalidActionInputError(ACTION_NAME, ["testTool.symlinkDir"], helpLink); } + if ( + args.testTool.releaseType && + args.testTool.releaseType !== TestToolReleaseType.Binary && + args.testTool.releaseType !== TestToolReleaseType.Npm + ) { + throw new InvalidActionInputError(ACTION_NAME, ["testTool.releaseType"], helpLink); + } } } diff --git a/packages/fx-core/src/component/driver/devTool/interfaces/InstallToolArgs.ts b/packages/fx-core/src/component/driver/devTool/interfaces/InstallToolArgs.ts index 9114337ddf..0a22383ec2 100644 --- a/packages/fx-core/src/component/driver/devTool/interfaces/InstallToolArgs.ts +++ b/packages/fx-core/src/component/driver/devTool/interfaces/InstallToolArgs.ts @@ -35,4 +35,5 @@ interface FuncArgs { interface TestToolArgs { version: string | number; symlinkDir: string; + releaseType?: string; } diff --git a/packages/fx-core/tests/component/driver/devTool/installDriver.test.ts b/packages/fx-core/tests/component/driver/devTool/installDriver.test.ts index d929cf27fe..3c8114b440 100644 --- a/packages/fx-core/tests/component/driver/devTool/installDriver.test.ts +++ b/packages/fx-core/tests/component/driver/devTool/installDriver.test.ts @@ -5,7 +5,7 @@ import { UserError } from "@microsoft/teamsfx-api"; import chai from "chai"; import "mocha"; import * as sinon from "sinon"; -import { DepsType } from "../../../../src/component/deps-checker/depsChecker"; +import { DepsType, TestToolReleaseType } from "../../../../src/component/deps-checker/depsChecker"; import { DotnetChecker } from "../../../../src/component/deps-checker/internal/dotnetChecker"; import { FuncToolChecker } from "../../../../src/component/deps-checker/internal/funcToolChecker"; import { TestToolChecker } from "../../../../src/component/deps-checker/internal/testToolChecker"; @@ -319,7 +319,7 @@ describe("Tools Install Driver test", () => { }); it("Install test tool", async () => { - sandbox.stub(TestToolChecker.prototype, "resolve").resolves({ + const resolveStub = sandbox.stub(TestToolChecker.prototype, "resolve").resolves({ name: "Teams App Test Tool", type: DepsType.TestTool, isInstalled: true, @@ -339,6 +339,14 @@ describe("Tools Install Driver test", () => { if (res.isOk()) { chai.assert.isEmpty(res.value); } + chai.assert.isTrue( + resolveStub.calledWith({ + versionRange: "~0.1.0", + symlinkDir: "./devTools/testTool", + releaseType: TestToolReleaseType.Npm, + projectPath: mockedDriverContext.projectPath, + }) + ); }); // it("Install test tool failed without error", async () => { @@ -398,6 +406,13 @@ describe("Tools Install Driver test", () => { args: { testTool: { version: "~1", symlinkDir: 1 } }, expected: false, }, + { + name: "invalid releaseType", + args: { + testTool: { version: "~1", symlinkDir: "./devTools/testTool", releaseType: "bin" }, + }, + expected: false, + }, ]; for (const c of cases) { it("Install test tool args check " + c.name, async () => { diff --git a/templates/python/custom-copilot-basic/.vscode/launch.json.tpl b/templates/python/custom-copilot-basic/.vscode/launch.json.tpl index 64d89b5e54..368cb1b852 100644 --- a/templates/python/custom-copilot-basic/.vscode/launch.json.tpl +++ b/templates/python/custom-copilot-basic/.vscode/launch.json.tpl @@ -7,7 +7,7 @@ "request": "launch", "url": "https://teams.microsoft.com/l/app/${{TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&${account-hint}", "presentation": { - "group": "1-Teams", + "group": "2-Teams", "order": 4 }, "internalConsoleOptions": "neverOpen" @@ -18,7 +18,7 @@ "request": "launch", "url": "https://teams.microsoft.com/l/app/${{TEAMS_APP_ID}}?installAppPackage=true&webjoin=true&${account-hint}", "presentation": { - "group": "1-Teams", + "group": "2-Teams", "order": 5 }, "internalConsoleOptions": "neverOpen" @@ -29,7 +29,7 @@ "request": "launch", "preLaunchTask": "Start Teams App in Desktop Client (Remote)", "presentation": { - "group": "1-Teams", + "group": "2-Teams", "order": 6 }, "internalConsoleOptions": "neverOpen" @@ -63,18 +63,6 @@ "program": "${workspaceFolder}/src/app.py", "cwd": "${workspaceFolder}/src", "console": "integratedTerminal" - }, - { - "name": "Start Test Tool", - "type": "node", - "request": "launch", - "program": "${workspaceFolder}/devTools/teamsapptester/node_modules/@microsoft/teams-app-test-tool/cli.js", - "args": [ - "start" - ], - "cwd": "${workspaceFolder}", - "console": "integratedTerminal", - "internalConsoleOptions": "neverOpen" {{#CEAEnabled}} }, { @@ -118,7 +106,7 @@ "cascadeTerminateToConfigurations": ["Start Python"], "preLaunchTask": "Start Teams App Locally", "presentation": { - "group": "1-Teams", + "group": "2-Teams", "order": 1 }, "stopAll": true @@ -129,7 +117,7 @@ "cascadeTerminateToConfigurations": ["Start Python"], "preLaunchTask": "Start Teams App Locally", "presentation": { - "group": "1-Teams", + "group": "2-Teams", "order": 2 }, "stopAll": true @@ -139,7 +127,7 @@ "configurations": ["Start Python"], "preLaunchTask": "Start Teams App in Desktop Client", "presentation": { - "group": "1-Teams", + "group": "2-Teams", "order": 3 }, "stopAll": true @@ -148,14 +136,10 @@ "name": "Debug in Test Tool", "configurations": [ "Start Python", - "Start Test Tool" - ], - "cascadeTerminateToConfigurations": [ - "Start Test Tool" ], - "preLaunchTask": "Deploy (Test Tool)", + "preLaunchTask": "Test Tool", "presentation": { - "group": "2-local", + "group": "1-local", "order": 1 }, "stopAll": true diff --git a/templates/python/custom-copilot-basic/.vscode/tasks.json b/templates/python/custom-copilot-basic/.vscode/tasks.json index a964abf89f..883c49873f 100644 --- a/templates/python/custom-copilot-basic/.vscode/tasks.json +++ b/templates/python/custom-copilot-basic/.vscode/tasks.json @@ -4,6 +4,14 @@ { "version": "2.0.0", "tasks": [ + { + "label": "Test Tool", + "dependsOn": ["Validate prerequisites (Test Tool)", "Deploy (Test Tool)", "Start Test Tool"], + "dependsOrder": "sequence", + "presentation": { + "reveal": "never" + }, + }, { // Check all required prerequisites. // See https://aka.ms/teamsfx-tasks/check-prerequisites to know the details and how to customize the args. @@ -12,7 +20,6 @@ "command": "debug-check-prerequisites", "args": { "prerequisites": [ - "nodejs", // Check if Node.js is installed and the version is >= 12. "portOccupancy" // Validate available ports to ensure those debug ones are not occupied. ], "portOccupancy": [ @@ -25,15 +32,37 @@ // Build project. // See https://aka.ms/teamsfx-tasks/deploy to know the details and how to customize the args. "label": "Deploy (Test Tool)", - "dependsOn": [ - "Validate prerequisites (Test Tool)" - ], "type": "teamsfx", "command": "deploy", "args": { "env": "testtool", } }, + { + "label": "Start Test Tool", + "type": "shell", + "command": "${workspaceFolder}/devTools/teamsapptester/teamsapptester.exe", + "args": [ + "start" + ], + "isBackground": true, + "problemMatcher": { + "owner": "custom", + "pattern": { + "regexp": ".*InternalServiceError: (.*)", + "message": 1 + }, + "background": { + "activeOnStart": true, + "beginsPattern": { + "regexp": ".*Teams App Test Tool" + }, + "endsPattern": { + "regexp": ".*started web socket client" + } + }, + } + }, { "label": "Start Teams App Locally", "dependsOn": [ diff --git a/templates/python/custom-copilot-basic/teamsapp.testtool.yml.tpl b/templates/python/custom-copilot-basic/teamsapp.testtool.yml.tpl index bb5d6a35d4..9a7ea88032 100644 --- a/templates/python/custom-copilot-basic/teamsapp.testtool.yml.tpl +++ b/templates/python/custom-copilot-basic/teamsapp.testtool.yml.tpl @@ -10,6 +10,7 @@ deploy: testTool: version: ~0.2.1 symlinkDir: ./devTools/teamsapptester + releaseType: binary # Generate runtime environment variables - uses: file/createOrUpdateEnvironmentFile