diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 1138c79f34..beb3cf0d49 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -67,6 +67,7 @@ /packages/tests/src/e2e/scaffold @hund030 @eriolchan @huimiu /packages/tests/src/e2e/multienv @a1exwang @dooriya @qinezh @xiaolang124 @kimizhu /packages/tests/src/e2e/m365 @kimizhu @swatDong @kuojianlu +/packages/tests/src/e2e/m365/ProvisionApiSpecMessageExtension.tests.ts @yuqizhou77 @Alive-Fish /packages/tests/src/e2e/debug @kimizhu @swatDong @kuojianlu /packages/tests/src/e2e/samples @LongOddCode @ayachensiyuan /packages/cli/tests/unit/commonlib @kimizhu @swatDong @kuojianlu @a1exwang @qinezh @XiaofuHuang @xiaolang124 @dooriya diff --git a/packages/tests/src/e2e/m365/ProvisionApiSpecMessageExtension.tests.ts b/packages/tests/src/e2e/m365/ProvisionApiSpecMessageExtension.tests.ts new file mode 100644 index 0000000000..0cbe0a1c1c --- /dev/null +++ b/packages/tests/src/e2e/m365/ProvisionApiSpecMessageExtension.tests.ts @@ -0,0 +1,76 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +/** + * @author Yuqi Zhou + */ + +import { describe } from "mocha"; +import * as chai from "chai"; +import * as path from "path"; + +import { it } from "@microsoft/extra-shot-mocha"; + +import { CliHelper } from "../../commonlib/cliHelper"; +import { Capability } from "../../utils/constants"; +import { + cleanUpLocalProject, + getTestFolder, + getUniqueAppName, + readContextMultiEnvV3, +} from "../commonUtils"; +import { deleteTeamsApp, getTeamsApp } from "../debug/utility"; + +describe("Provision V3 api-based-message-extension api=-spec template", () => { + const testFolder = getTestFolder(); + const appName = getUniqueAppName(); + const projectPath = path.resolve(testFolder, appName); + + afterEach(async function () { + // clean up + const context = await readContextMultiEnvV3(projectPath, "dev"); + if (context?.TEAMS_APP_ID) { + await deleteTeamsApp(context.TEAMS_APP_ID); + } + + await cleanUpLocalProject(projectPath); + }); + + it( + "happy path: scaffold and provision", + { testPlanCaseId: 25285721, author: "yuqzho@microsoft.com" }, + async function () { + const apiSpecPath = path.join(__dirname, "apispec.yml"); + // create + await CliHelper.createProjectWithCapability( + appName, + testFolder, + Capability.M365SearchApp, + undefined, + `--me-architecture api-spec --openapi-spec-location ${apiSpecPath} --api-operation "GET /repairs"` + ); + console.log(`[Successfully] scaffold to ${projectPath}`); + + // provision + + await CliHelper.provisionProject(projectPath, "", "dev", { + ...process.env, + }); + console.log(`[Successfully] provision for ${projectPath}`); + + const context = await readContextMultiEnvV3(projectPath, "dev"); + chai.assert.isDefined(context); + + // validate teams app + chai.assert.isDefined(context.TEAMS_APP_ID); + const teamsApp = await getTeamsApp(context.TEAMS_APP_ID); + chai.assert.equal(teamsApp?.teamsAppId, context.TEAMS_APP_ID); + + // validate m365 + chai.assert.isDefined(context.M365_TITLE_ID); + chai.assert.isNotEmpty(context.M365_TITLE_ID); + chai.assert.isDefined(context.M365_APP_ID); + chai.assert.isNotEmpty(context.M365_APP_ID); + } + ); +}); diff --git a/packages/tests/src/e2e/m365/apispec.yml b/packages/tests/src/e2e/m365/apispec.yml new file mode 100644 index 0000000000..4cb2946876 --- /dev/null +++ b/packages/tests/src/e2e/m365/apispec.yml @@ -0,0 +1,209 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "Repair Service", + "description": "A simple service to manage repairs for various items", + "version": "1.0.0" + }, + "servers": [ + { + "url": "https://test.com/" + } + ], + "paths": { + "/repairs": { + "get": { + "operationId": "listRepairs", + "summary": "List all repairs", + "description": "Returns a list of repairs with their details and images", + "parameters": [ + { + "name": "assignedTo", + "in": "query", + "description": "Filter repairs by who they're assigned to", + "schema": { + "type": "string" + }, + "required": false + } + ], + "responses": { + "200": { + "description": "A successful response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "The unique identifier of the repair" + }, + "title": { + "type": "string", + "description": "The short summary of the repair" + }, + "description": { + "type": "string", + "description": "The detailed description of the repair" + }, + "assignedTo": { + "type": "string", + "description": "The user who is responsible for the repair" + }, + "date": { + "type": "string", + "format": "date-time", + "description": "The date and time when the repair is scheduled or completed" + }, + "image": { + "type": "string", + "format": "uri", + "description": "The URL of the image of the item to be repaired or the repair process" + } + } + } + } + } + } + } + } + }, + "post": { + "operationId": "createRepair", + "summary": "Create a new repair", + "description": "Adds a new repair to the list with the given details and image URL", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "title": { + "type": "string", + "description": "The short summary of the repair" + }, + "description": { + "type": "string", + "description": "The detailed description of the repair" + }, + "assignedTo": { + "type": "string", + "description": "The user who is responsible for the repair" + }, + "date": { + "type": "string", + "format": "date-time", + "description": "The optional date and time when the repair is scheduled or completed" + }, + "image": { + "type": "string", + "format": "uri", + "description": "The URL of the image of the item to be repaired or the repair process" + } + }, + "required": [ + "title", + "description", + "assignedTo" + ] + } + } + } + }, + "responses": { + "201": { + "description": "A successful response indicating that the repair was created" + } + } + }, + "patch": { + "summary": "Update an existing repair", + "description": "Update an existing repair to the list with the new updated details and image URL", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "type": "integer", + "description": "The unique identifier of the repair to update" + }, + "title": { + "type": "string", + "description": "The short summary of the repair" + }, + "description": { + "type": "string", + "description": "The detailed description of the repair" + }, + "assignedTo": { + "type": "string", + "description": "The user who is responsible for the repair" + }, + "date": { + "type": "string", + "format": "date-time", + "description": "The date and time when the repair is scheduled or completed" + }, + "image": { + "type": "string", + "format": "uri", + "description": "The URL of the image of the item to be repaired or the repair process" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Repair updated" + }, + "404": { + "description": "Repair not found" + } + } + }, + "delete": { + "summary": "Delete an existing repair", + "description": "Delete an existing repair from the list using its ID", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "type": "integer", + "description": "The unique identifier of the repair to delete" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Repair deleted" + }, + "404": { + "description": "Repair not found" + } + } + } + } + } +} \ No newline at end of file