Skip to content

Commit

Permalink
test: add docker bot sso sample (#11504)
Browse files Browse the repository at this point in the history
* test: add docker sample
---------

Co-authored-by: Ivan_Chen <[email protected]>
  • Loading branch information
ayachensiyuan and Ivan_Chen authored Apr 29, 2024
1 parent 1e362ee commit f43dc91
Show file tree
Hide file tree
Showing 11 changed files with 274 additions and 56 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/ui-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,12 @@ jobs:
run: |
npm run build
- name: Install docker extension
if: contains(matrix.test-case, 'docker')
working-directory: packages/tests
run: |
npx extest install-from-marketplace --storage .test-resources --extensions_dir .test-resources --type stable ms-azuretools.vscode-docker
- name: Install vsix(unix)
if: matrix.os != 'windows-latest'
working-directory: packages/tests
Expand Down
1 change: 1 addition & 0 deletions packages/tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ CI_ENABLED=true
- (**Required**) Run `npx extest get-chromedriver --storage .test-resources --type stable --code_version 1.88.1` to download chromedriver
- (**Required**) Download TeamsFx vsix file to this project root folder. You can download it from the [artifacts of TeamsFx CD action](https://github.com/OfficeDev/TeamsFx/actions/workflows/cd.yml). Remember to unzip.
- (**Required**) Run `npx extest install-vsix --storage .test-resources --extensions_dir .test-resources --type stable --vsix_file ${{ YOUR VSIX FILE NAME }} ` to install Teams Toolkit
- (**OPTIONAL**) If local test docker cases, Run `npx extest install-from-marketplace --storage .test-resources --extensions_dir .test-resources --type stable ms-azuretools.vscode-docker` to install docker extension.
- (**Required**) Run `npx extest run-tests --storage .test-resources --extensions_dir .test-resources --type stable --code_version 1.88.1 --code_settings ./settings.json ./out/ui-test/**/${{ YOUR TEST CASE }}.test.js` to execute your case
- (**OPTIONAL**) If you want to debug your case via vscode, replace "YOUR TEST CASE" with your case name in .vscode/launch.json and click F5

Expand Down
19 changes: 18 additions & 1 deletion packages/tests/scripts/randomCases.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"node-18": []
},
"macos-latest": {
"node-16": []
"node-16": [],
"node-18": []
}
},
"cases": [
Expand Down Expand Up @@ -171,5 +172,21 @@
"sample-remotedebug-todo-list-sql",
"sample-remotedebug-large-scale-notification"
]
},
{
"os": {
"ubuntu-latest": {
"node-16": [],
"node-18": []
},
"macos-latest": {
"node-16": [],
"node-18": []
}
},
"cases": [
"sample-localdebug-bot-sso-docker",
"sample-remotedebug-bot-sso-docker"
]
}
]
78 changes: 78 additions & 0 deletions packages/tests/src/ui-test/cliHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import path from "path";
import * as chai from "chai";
import { Executor } from "../utils/executor";
import * as os from "os";
import { ChildProcess, ChildProcessWithoutNullStreams } from "child_process";

export class CliHelper {
static async addEnv(
Expand Down Expand Up @@ -615,4 +616,81 @@ export class CliHelper {
}
console.log("[success] debug successfully !!!");
}

static async dockerBuild(
projectPath: string,
folder: string,
path = "./",
processEnv: NodeJS.ProcessEnv = process.env,
delay: number = 3 * 60 * 1000
): Promise<ChildProcessWithoutNullStreams> {
console.log(`[start] docker build ... `);
const timeout = timeoutPromise(delay);
const childProcess = spawnCommand(
"docker",
["build", "-t", folder, path],
{
cwd: projectPath,
env: processEnv ? processEnv : process.env,
},
(data) => {
console.log(data);
},
(error) => {
console.log(error);
if (error.includes("Error:")) {
chai.assert.fail(error);
}
}
);
await Promise.all([timeout, childProcess]);
console.log("[success] docker build successfully !!!");
return childProcess;
}

static async dockerRun(
projectPath: string,
folder: string,
processEnv: NodeJS.ProcessEnv = process.env,
delay: number = 30 * 1000
): Promise<ChildProcessWithoutNullStreams> {
console.log(`[start] docker run ... `);
const timeout = timeoutPromise(delay);
const childProcess = spawnCommand(
"docker",
["run", "-p", "3978:80", "--env-file", ".localConfigs", folder],
{
cwd: projectPath,
env: processEnv ? processEnv : process.env,
},
(data) => {
console.log(data);
},
(error) => {
console.log(error);
if (error.includes("Error:")) {
chai.assert.fail(error);
}
}
);
await Promise.all([timeout, childProcess]);
console.log("[success] docker run successfully !!!");
return childProcess;
}

static async stopAllDocker() {
console.log(`[start] docker stop all ... `);
let cmd = "";
if (os.type() === "Windows_NT") {
cmd = "docker ps -q | ForEach-Object { docker stop $_ }";
} else {
cmd = "docker stop $(docker ps -q)";
}
const { stderr, stdout } = await execAsync(cmd);
if (stderr) {
console.log(stderr);
}
console.log(stdout);
console.log("[success] docker stop all successfully !!!");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

/**
* @author Ivan Chen <[email protected]>
*/

import { Page } from "playwright";
import { TemplateProject, LocalDebugTaskLabel } from "../../utils/constants";
import { validateBot } from "../../utils/playwrightOperation";
import { CaseFactory } from "./sampleCaseFactory";
import { Env } from "../../utils/env";

class BotSSODockerTestCase extends CaseFactory {
override async onValidate(page: Page): Promise<void> {
return await validateBot(page, {
botCommand: "show",
expected: Env.displayName,
});
}
public override async onCliValidate(page: Page): Promise<void> {
return await validateBot(page, {
botCommand: "show",
expected: Env.displayName,
});
}
}

new BotSSODockerTestCase(
TemplateProject.BotSSODocker,
26577671,
"[email protected]",
"local",
[LocalDebugTaskLabel.StartLocalTunnel, LocalDebugTaskLabel.DockerRun]
).test();
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

/**
* @author Ivan Chen <[email protected]>
*/

import { Page } from "playwright";
import { TemplateProject, LocalDebugTaskLabel } from "../../utils/constants";
import { validateBot } from "../../utils/playwrightOperation";
import { CaseFactory } from "./sampleCaseFactory";
import { Env } from "../../utils/env";

class BotSSODockerTestCase extends CaseFactory {
override async onValidate(page: Page): Promise<void> {
return await validateBot(page, {
botCommand: "show",
expected: Env.displayName,
});
}
}

new BotSSODockerTestCase(
TemplateProject.BotSSODocker,
27852471,
"[email protected]",
"dev",
undefined,
{ container: true }
).test();
44 changes: 38 additions & 6 deletions packages/tests/src/ui-test/samples/sampleCaseFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import path from "path";
import { Executor } from "../../utils/executor";
import { ChildProcessWithoutNullStreams } from "child_process";
import { initDebugPort } from "../../utils/commonUtils";
import { CliHelper } from "../cliHelper";

const debugMap: Record<LocalDebugTaskLabel, () => Promise<void>> = {
[LocalDebugTaskLabel.StartFrontend]: async () => {
Expand Down Expand Up @@ -97,6 +98,12 @@ const debugMap: Record<LocalDebugTaskLabel, () => Promise<void>> = {
LocalDebugTaskResult.WebServerSuccess
);
},
[LocalDebugTaskLabel.DockerRun]: async () => {
await waitForTerminal(
LocalDebugTaskLabel.DockerRun,
LocalDebugTaskResult.WebServerSuccess
);
},
};

export abstract class CaseFactory {
Expand All @@ -118,6 +125,8 @@ export abstract class CaseFactory {
debug?: "cli" | "ttk";
botFlag?: boolean;
repoPath?: string;
container?: boolean;
dockerFolder?: string;
};

public constructor(
Expand All @@ -139,6 +148,8 @@ export abstract class CaseFactory {
debug?: "cli" | "ttk";
botFlag?: boolean;
repoPath?: string;
container?: boolean;
dockerFolder?: string;
} = {}
) {
this.sampleName = sampleName;
Expand Down Expand Up @@ -277,6 +288,7 @@ export abstract class CaseFactory {
let azSqlHelper: AzSqlHelper | undefined;
let devtunnelProcess: ChildProcessWithoutNullStreams;
let debugProcess: ChildProcessWithoutNullStreams;
let dockerProcess: ChildProcessWithoutNullStreams;
let successFlag = true;
let envContent = "";
let botFlag = false;
Expand Down Expand Up @@ -363,6 +375,9 @@ export abstract class CaseFactory {
sampledebugContext.appName,
sampledebugContext.projectPath
);
if (options?.container) {
await Executor.login();
}
await sampledebugContext.deployProject(
sampledebugContext.projectPath,
Timeout.botDeploy
Expand Down Expand Up @@ -392,11 +407,23 @@ export abstract class CaseFactory {
"local"
);
expect(provisionSuccess).to.be.true;
const { success: deploySuccess } = await Executor.deploy(
sampledebugContext.projectPath,
"local"
);
expect(deploySuccess).to.be.true;
if (!options.container) {
const { success: deploySuccess } = await Executor.deploy(
sampledebugContext.projectPath,
"local"
);
expect(deploySuccess).to.be.true;
} else {
await CliHelper.dockerBuild(
sampledebugContext.projectPath,
options.dockerFolder || ""
);

dockerProcess = await CliHelper.dockerRun(
sampledebugContext.projectPath,
options.dockerFolder || ""
);
}
const teamsAppId = await sampledebugContext.getTeamsAppId(env);
expect(teamsAppId).to.not.be.empty;

Expand All @@ -421,7 +448,8 @@ export abstract class CaseFactory {
successFlag = false;
expect.fail(errorMsg);
}
}
},
options.container
);
await new Promise((resolve) =>
setTimeout(resolve, 2 * 60 * 1000)
Expand Down Expand Up @@ -458,6 +486,10 @@ export abstract class CaseFactory {
// kill process
await Executor.closeProcess(debugProcess);
if (botFlag) await Executor.closeProcess(devtunnelProcess);
if (dockerProcess) {
await Executor.closeProcess(dockerProcess);
await CliHelper.stopAllDocker();
}
await initDebugPort();
}

Expand Down
4 changes: 4 additions & 0 deletions packages/tests/src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export enum TemplateProject {
RetailDashboard = "Contoso Retail Dashboard",
TabSSOApimProxy = "SSO Enabled Tab via APIM Proxy",
LargeScaleBot = "Large Scale Notification Bot",
BotSSODocker = "Containerized Bot App with SSO Enabled",
}

export enum TemplateProjectFolder {
Expand Down Expand Up @@ -128,6 +129,7 @@ export const sampleProjectMap: Record<TemplateProject, TemplateProjectFolder> =
[TemplateProject.RetailDashboard]: TemplateProjectFolder.RetailDashboard,
[TemplateProject.TabSSOApimProxy]: TemplateProjectFolder.TabSSOApimProxy,
[TemplateProject.LargeScaleBot]: TemplateProjectFolder.LargeScaleBot,
[TemplateProject.BotSSODocker]: TemplateProjectFolder.BotSSODocker,
};

export enum Resource {
Expand Down Expand Up @@ -380,6 +382,7 @@ export enum LocalDebugTaskLabel {
Azurite = "Start Azurite emulator",
Compile = "Compile typescript",
StartWebServer = "Start web server",
DockerRun = "docker-run: debug",
}

export class LocalDebugTaskResult {
Expand All @@ -394,6 +397,7 @@ export class LocalDebugTaskResult {
static readonly Error = "error";
static readonly DebuggerAttached = "Debugger attached";
static readonly WebServerSuccess = "press h to show help";
static readonly DockerRunFinish = "press any key to close it";
}

export enum LocalDebugTaskLabel2 {
Expand Down
12 changes: 10 additions & 2 deletions packages/tests/src/utils/executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,8 @@ export class Executor {
v3 = true,
processEnv: NodeJS.ProcessEnv = process.env,
onData?: (data: string) => void,
onError?: (data: string) => void
onError?: (data: string) => void,
openOnly?: boolean
) {
console.log(`[start] ${env} debug ... `);
const childProcess = spawn(
Expand All @@ -208,7 +209,12 @@ export class Executor {
: v3
? "teamsapp"
: "teamsfx",
["preview", v3 ? "--env" : "", v3 ? `${env}` : `--${env}`],
[
"preview",
v3 ? "--env" : "",
v3 ? `${env}` : `--${env}`,
openOnly ? "--open-only" : "",
],
{
cwd: projectPath,
env: processEnv ? processEnv : process.env,
Expand Down Expand Up @@ -594,6 +600,8 @@ export class Executor {
} catch (error) {
console.log(error);
}
} else {
console.log(childProcess);
}
}
}
Loading

0 comments on commit f43dc91

Please sign in to comment.