Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add containerapps-albumapi-go test project & cases #707

Merged
merged 71 commits into from
Jun 28, 2024
Merged
Show file tree
Hide file tree
Changes from 69 commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
1461d47
Refactor ingress tests to use test workspace
MicroFish91 May 24, 2024
50cc37f
Update package.json
MicroFish91 May 24, 2024
dc53932
Fix prepublish
MicroFish91 May 24, 2024
f235e50
Update testProjects folder name
MicroFish91 May 24, 2024
7aa9d80
Use blank pretest script
MicroFish91 Jun 13, 2024
c93618e
Update tools deps
MicroFish91 Jun 13, 2024
da2544b
SharedResourcesNameStep
MicroFish91 Jun 13, 2024
d889656
EnvironmentVariablesListStep
MicroFish91 Jun 13, 2024
b6a1ebb
settingUtils
MicroFish91 Jun 13, 2024
d86efde
Use path lib for TarFileStep
MicroFish91 Jun 13, 2024
2a5a692
Update getRootWorkspaceFolder
MicroFish91 Jun 13, 2024
0f21b64
Revert
MicroFish91 Jun 13, 2024
51592b3
Update comment
MicroFish91 Jun 13, 2024
c06d1b2
Update SharedResourcesNameStep
MicroFish91 Jun 13, 2024
38c457c
Monorepo test scaffold
MicroFish91 Jun 13, 2024
a819e8c
Add method for cleaning workspace folder settings
MicroFish91 Jun 13, 2024
9831624
Add delete resource groups functionality
MicroFish91 Jun 13, 2024
5918519
Add test workspace fields
MicroFish91 Jun 13, 2024
5d52072
Revert scripts
MicroFish91 Jun 13, 2024
a92417e
Add monorepo-basic test project
MicroFish91 Jun 13, 2024
4609473
Add resource groups to delete
MicroFish91 Jun 13, 2024
0beb67f
Merge with main
MicroFish91 Jun 14, 2024
2636f2e
Fix test workspace paths
MicroFish91 Jun 14, 2024
af1d275
Use different port numbers
MicroFish91 Jun 14, 2024
7df2569
Timeout test
MicroFish91 Jun 14, 2024
ecb2787
Test with delete rg
MicroFish91 Jun 14, 2024
92e7f69
Update skip logic
MicroFish91 Jun 14, 2024
34acb22
Test rg activation
MicroFish91 Jun 14, 2024
2622bf2
Test log statements
MicroFish91 Jun 14, 2024
feb3530
Test upgrade arm package
MicroFish91 Jun 14, 2024
1311350
Your guess is as good as mine
MicroFish91 Jun 14, 2024
e0858c2
Add timeout
MicroFish91 Jun 14, 2024
a2ccc28
Add timeout
MicroFish91 Jun 14, 2024
f2dd372
Clean up delete logic and increase timeout
MicroFish91 Jun 14, 2024
2f92f2b
Uset set instead of a list
MicroFish91 Jun 14, 2024
de7ce3d
Merge with main
MicroFish91 Jun 14, 2024
495d00b
Merge branch 'mwf/nightly-test-prep' of https://github.com/microsoft/…
MicroFish91 Jun 14, 2024
0b2a1de
Update arm dep
MicroFish91 Jun 14, 2024
48ab51e
Merge branch 'mwf/nightly-test-prep' of https://github.com/microsoft/…
MicroFish91 Jun 14, 2024
6039db4
Update timeouts
MicroFish91 Jun 14, 2024
04b73ff
Add monorepo test project
MicroFish91 Jun 14, 2024
f1cd5ee
Update readme title
MicroFish91 Jun 14, 2024
39c507e
Merge with parent pr
MicroFish91 Jun 14, 2024
973d4a0
Update timeouts
MicroFish91 Jun 14, 2024
eae6a78
Merge branch 'main' of https://github.com/microsoft/vscode-azureconta…
MicroFish91 Jun 14, 2024
5439abc
Merge branch 'mwfe/ingress-test-workspace' of https://github.com/micr…
MicroFish91 Jun 14, 2024
c8fb59b
Update ports
MicroFish91 Jun 14, 2024
73dae15
Merge branch 'mwf/add-monorepo-test-project' of https://github.com/mi…
MicroFish91 Jun 14, 2024
d1bf0cf
Add albumapi-js repo
MicroFish91 Jun 17, 2024
9c4a757
Update ms learn test cases
MicroFish91 Jun 17, 2024
27943e6
Update names of things
MicroFish91 Jun 17, 2024
c93349b
Misc changes
MicroFish91 Jun 17, 2024
98b174e
Merge branch 'mwf/monorepo-tests' of https://github.com/microsoft/vsc…
MicroFish91 Jun 17, 2024
3ec35fe
Add shared subscription context
MicroFish91 Jun 21, 2024
1267652
Merge branch 'mwf/monorepo-tests' of https://github.com/microsoft/vsc…
MicroFish91 Jun 21, 2024
6f60ff4
Merge branch 'main' of https://github.com/microsoft/vscode-azureconta…
MicroFish91 Jun 25, 2024
9c87453
Alternate registry naming solution
MicroFish91 Jun 26, 2024
88a008f
Rename test scenarios
MicroFish91 Jun 26, 2024
c46d62c
Use a more generic interface comment
MicroFish91 Jun 26, 2024
15f98e3
Simplify generateRelatedName
MicroFish91 Jun 26, 2024
f866395
Merge branch 'mwf/nightly-test-prep' of https://github.com/microsoft/…
MicroFish91 Jun 26, 2024
7554a8f
Merge branch 'mwf/add-monorepo-test-project' of https://github.com/mi…
MicroFish91 Jun 26, 2024
072819b
allSettled
MicroFish91 Jun 26, 2024
9ce2b85
Merge with main
MicroFish91 Jun 26, 2024
27fe579
Merge branch 'mwf/monorepo-tests' of https://github.com/microsoft/vsc…
MicroFish91 Jun 26, 2024
4194a58
Add go test repo
MicroFish91 Jun 26, 2024
603479b
Update readme link
MicroFish91 Jun 26, 2024
1bc9164
Merge branch 'mwf/albumapi-js-test' of https://github.com/microsoft/v…
MicroFish91 Jun 26, 2024
f543a34
Golang test cases
MicroFish91 Jun 26, 2024
8ba3c38
Trick for package-lock merge
MicroFish91 Jun 28, 2024
b7b8aec
Merge with main
MicroFish91 Jun 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
"MOCHA_timeout": "0", // Disable time-outs
"DEBUGTELEMETRY": "v",
"NODE_DEBUG": "",
"ENABLE_LONG_RUNNING_TESTS": ""
"AzCode_UseAzureFederatedCredentials": ""
}
},
{
Expand All @@ -115,7 +115,7 @@
"DEBUGTELEMETRY": "v",
"NODE_DEBUG": "",
"DEBUG_WEBPACK": "1",
"ENABLE_LONG_RUNNING_TESTS": ""
"AzCode_UseAzureFederatedCredentials": ""
}
},
{
Expand Down
11 changes: 10 additions & 1 deletion extension.bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,22 @@
// At runtime the tests live in dist/tests and will therefore pick up the main webpack bundle at dist/extension.bundle.js.
export * from '@microsoft/vscode-azext-utils';
// Export activate/deactivate for main.js
export * from './src/commands/deployWorkspaceProject/deployWorkspaceProject';
export * from './src/commands/deployWorkspaceProject/getDeployWorkspaceProjectResults';
export * from './src/commands/deployWorkspaceProject/internal/DeployWorkspaceProjectInternalContext';
export * from './src/commands/deployWorkspaceProject/settings/DeployWorkspaceProjectSettingsV1';
export * from './src/commands/deployWorkspaceProject/settings/DeployWorkspaceProjectSettingsV2';
export * from './src/commands/deployWorkspaceProject/settings/dwpSettingUtilsV1';
export * from './src/commands/deployWorkspaceProject/settings/dwpSettingUtilsV2';
export * from './src/commands/IContainerAppContext';
export * from './src/commands/ingress/editTargetPort/getDefaultPort';
export * from './src/commands/ingress/IngressContext';
export * from './src/commands/ingress/IngressPromptStep';
export * from './src/commands/ingress/editTargetPort/getDefaultPort';
export * from './src/commands/ingress/tryGetDockerfileExposePorts';
export { activate, deactivate } from './src/extension';
export * from './src/extensionVariables';
export * from './src/utils/azureClients';
export * from './src/utils/settingUtils';
export * from './src/utils/validateUtils';

// NOTE: The auto-fix action "source.organizeImports" does weird things with this file, but there doesn't seem to be a way to disable it on a per-file basis so we'll just let it happen
14 changes: 8 additions & 6 deletions test/global.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@
* Licensed under the MIT License. See LICENSE.md in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { registerAzureUtilsExtensionVariables } from '@microsoft/vscode-azext-azureutils';
import { TestOutputChannel, TestUserInput } from '@microsoft/vscode-azext-dev';
import * as assert from 'assert';
import * as vscode from 'vscode';
import { ext, registerOnActionStartHandler } from '../extension.bundle';
import { ext, registerOnActionStartHandler, registerUIExtensionVariables } from '../extension.bundle';

export let longRunningTestsEnabled: boolean;
export const longRunningTestsEnabled: boolean = !/^(false|0)?$/i.test(process.env.AzCode_UseAzureFederatedCredentials || '');

// Runs before all tests
suiteSetup(async function (this: Mocha.Context): Promise<void> {
this.timeout(1 * 60 * 1000);
this.timeout(2 * 60 * 1000);

const extension = vscode.extensions.getExtension('ms-azuretools.vscode-azurecontainerapps');
if (!extension) {
Expand All @@ -21,11 +22,12 @@ suiteSetup(async function (this: Mocha.Context): Promise<void> {
await extension.activate();
}

ext.outputChannel = new TestOutputChannel();
registerUIExtensionVariables(ext);
registerAzureUtilsExtensionVariables(ext);

registerOnActionStartHandler(context => {
// Use `TestUserInput` by default so we get an error if an unexpected call to `context.ui` occurs, rather than timing out
context.ui = new TestUserInput(vscode);
});

ext.outputChannel = new TestOutputChannel();
longRunningTestsEnabled = !/^(false|0)?$/i.test(process.env.AzCode_UseAzureFederatedCredentials || '');
});
71 changes: 71 additions & 0 deletions test/nightly/deployWorkspaceProject/deployWorkspaceProject.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE.md in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { parseAzureResourceGroupId } from '@microsoft/vscode-azext-azureutils';
import { runWithTestActionContext } from '@microsoft/vscode-azext-dev';
import * as assert from 'assert';
import * as path from 'path';
import { workspace, type Uri, type WorkspaceFolder } from 'vscode';
import { AzExtFsExtra, deployWorkspaceProject, dwpSettingUtilsV2, settingUtils, type DeploymentConfigurationSettings, type DeployWorkspaceProjectResults } from '../../../extension.bundle';
import { longRunningTestsEnabled } from '../../global.test';
import { assertStringPropsMatch, getWorkspaceFolderUri } from '../../testUtils';
import { resourceGroupsToDelete } from '../global.nightly.test';
import { dwpTestScenarios } from './dwpTestScenarios';

suite('deployWorkspaceProject', function (this: Mocha.Suite) {
this.timeout(15 * 60 * 1000);

suiteSetup(function (this: Mocha.Context) {
if (!longRunningTestsEnabled) {
this.skip();
}
});

for (const scenario of dwpTestScenarios) {
suite(scenario.label, function () {
const workspaceFolderUri: Uri = getWorkspaceFolderUri(scenario.folderName);
const rootFolder: WorkspaceFolder | undefined = workspace.getWorkspaceFolder(workspaceFolderUri);
assert.ok(rootFolder, 'Could not retrieve root workspace folder.');

suiteSetup(getMethodCleanWorkspaceFolderSettings(rootFolder));
suiteTeardown(getMethodCleanWorkspaceFolderSettings(rootFolder));

for (const testCase of scenario.testCases) {
test(testCase.label, async function () {
await runWithTestActionContext('deployWorkspaceProject', async context => {
await context.ui.runWithInputs(testCase.inputs, async () => {
const results: DeployWorkspaceProjectResults = await deployWorkspaceProject(context);
if (results.resourceGroupId) {
const resourceGroupName: string = parseAzureResourceGroupId(results.resourceGroupId).resourceGroup;
resourceGroupsToDelete.add(resourceGroupName);
}

assertStringPropsMatch(results as Partial<Record<string, string>>, testCase.expectedResults as Record<string, string | RegExp>, 'DeployWorkspaceProject results mismatch.');

const deploymentConfigurationsV2: DeploymentConfigurationSettings[] = await dwpSettingUtilsV2.getWorkspaceDeploymentConfigurations(rootFolder) ?? [];
for (const [i, expectedDeploymentConfiguration] of (testCase.expectedVSCodeSettings?.deploymentConfigurations ?? []).entries()) {
const deploymentConfiguration: DeploymentConfigurationSettings = deploymentConfigurationsV2[i] ?? {};
assertStringPropsMatch(deploymentConfiguration as Partial<Record<string, string>>, expectedDeploymentConfiguration, 'DeployWorkspaceProject ".vscode" saved settings mismatch.');
}

await testCase.postTestAssertion?.(context, results, 'DeployWorkspaceProject resource settings mismatch.');
});
});
});
}
});
}
});

function getMethodCleanWorkspaceFolderSettings(rootFolder: WorkspaceFolder) {
return async function cleanWorkspaceFolderSettings(): Promise<void> {
const settingsPath: string = settingUtils.getDefaultRootWorkspaceSettingsPath(rootFolder);
const vscodeFolderPath: string = path.dirname(settingsPath);
if (await AzExtFsExtra.pathExists(vscodeFolderPath)) {
await AzExtFsExtra.deleteResource(vscodeFolderPath, { recursive: true });
}
}
}

33 changes: 33 additions & 0 deletions test/nightly/deployWorkspaceProject/dwpTestScenarios.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE.md in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { generateAlbumApiGolangTestCases } from "./testCases/albumApiGolangTestCases";
import { generateAlbumApiJavaScriptTestCases } from "./testCases/albumApiJavaScriptTestCases";
import { type DeployWorkspaceProjectTestCase } from "./testCases/DeployWorkspaceProjectTestCase";
import { generateMonoRepoBasicTestCases } from "./testCases/monoRepoBasicTestCases";

interface DeployWorkspaceProjectTestScenario {
label: string;
folderName: string;
testCases: DeployWorkspaceProjectTestCase[];
}

export const dwpTestScenarios: DeployWorkspaceProjectTestScenario[] = [
{
label: 'albumapi-go',
folderName: 'albumapi-go',
testCases: generateAlbumApiGolangTestCases()
},
{
label: 'albumapi-js',
folderName: 'albumapi-js',
testCases: generateAlbumApiJavaScriptTestCases()
},
{
label: 'monorepo',
folderName: 'monorepo-basic',
testCases: generateMonoRepoBasicTestCases()
},
];
41 changes: 41 additions & 0 deletions test/nightly/deployWorkspaceProject/dwpTestUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE.md in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { type ContainerApp, type EnvironmentVar } from "@azure/arm-appcontainers";
import { parseAzureResourceId } from "@microsoft/vscode-azext-azureutils";
import { nonNullProp, type IActionContext } from "@microsoft/vscode-azext-utils";
import * as assert from "assert";
import { createContainerAppsAPIClient, type DeployWorkspaceProjectResults } from "../../../extension.bundle";
import { type StringOrRegExpProps } from "../../typeUtils";
import { subscriptionContext } from "../global.nightly.test";
import { type PostTestAssertion } from "./testCases/DeployWorkspaceProjectTestCase";

export namespace dwpTestUtils {
export function generateExpectedResults(sharedResourceName: string, acrResourceName: string, appResourceName: string): StringOrRegExpProps<DeployWorkspaceProjectResults> {
return {
containerAppId: new RegExp(`\/resourceGroups\/${sharedResourceName}\/providers\/Microsoft\.App\/containerApps\/${appResourceName}`, 'i'),
imageName: new RegExp(appResourceName, 'i'),
logAnalyticsWorkspaceId: new RegExp(`\/resourceGroups\/${sharedResourceName}\/providers\/Microsoft\.OperationalInsights\/workspaces\/${sharedResourceName}`, 'i'),
managedEnvironmentId: new RegExp(`\/resourceGroups\/${sharedResourceName}\/providers\/Microsoft\.App\/managedEnvironments\/${sharedResourceName}`, 'i'),
registryId: new RegExp(`\/resourceGroups\/${sharedResourceName}\/providers\/Microsoft\.ContainerRegistry\/registries\/${acrResourceName}.{6}`, 'i'),
registryLoginServer: new RegExp(`${acrResourceName}.{6}\.azurecr\.io`, 'i'),
registryPassword: new RegExp('.*'),
registryUsername: new RegExp(`${acrResourceName}.{6}`, 'i'),
resourceGroupId: new RegExp(`\/resourceGroups\/${sharedResourceName}`, 'i')
};
}

export function generatePostTestAssertion(expectedContainerAppSettings: { targetPort: number | undefined, env: EnvironmentVar[] | undefined }): PostTestAssertion {
return async function postTestAssertion(context: IActionContext, resources: DeployWorkspaceProjectResults, errMsg?: string): Promise<void> {
const parsedId = parseAzureResourceId(nonNullProp(resources, 'containerAppId'));
const client = await createContainerAppsAPIClient(Object.assign(context, subscriptionContext));
const containerApp: ContainerApp = await client.containerApps.get(parsedId.resourceGroup, parsedId.resourceName);

assert.strictEqual(containerApp.configuration?.ingress?.targetPort, expectedContainerAppSettings.targetPort, errMsg ? errMsg + ' (container app target port)' : undefined);
assert.strictEqual(containerApp.template?.containers?.[0].image, `${resources.registryLoginServer}/${resources.imageName}`, errMsg ? errMsg + ' (container image name)' : undefined);
assert.deepStrictEqual(containerApp.template?.containers?.[0].env, expectedContainerAppSettings.env, errMsg ? errMsg + ' (container environment variables)' : undefined);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE.md in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { type DeploymentConfigurationSettings, type DeployWorkspaceProjectResults, type IActionContext } from "../../../../extension.bundle";
import { type StringOrRegExpProps } from "../../../typeUtils";

export interface DeployWorkspaceProjectTestCase {
/**
* Label to display when executing the test
*/
label: string;
/**
* The list of inputs that will be passed to the test UI
*/
inputs: (string | RegExp)[];
/**
* The expected results that should be returned after executing the command
*/
expectedResults?: StringOrRegExpProps<DeployWorkspaceProjectResults>;
/**
* The expected `.vscode` settings that should be present in the workspace folder root after executing the command
*/
expectedVSCodeSettings?: VSCodeSettings;
/**
* A post test callback that can be added for further verifying any of the created resources before final suite teardown
*/
postTestAssertion?: PostTestAssertion;
}

export type PostTestAssertion = (context: IActionContext, results: DeployWorkspaceProjectResults, errMsg?: string) => void | Promise<void>;

export interface VSCodeSettings {
deploymentConfigurations?: StringOrRegExpProps<DeploymentConfigurationSettings>[];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE.md in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { randomUtils } from "@microsoft/vscode-azext-utils";
import * as path from "path";
import { type DeploymentConfigurationSettings } from "../../../../extension.bundle";
import { type StringOrRegExpProps } from "../../../typeUtils";
import { dwpTestUtils } from "../dwpTestUtils";
import { type DeployWorkspaceProjectTestCase } from "./DeployWorkspaceProjectTestCase";

export function generateAlbumApiGolangTestCases(): DeployWorkspaceProjectTestCase[] {
const folderName: string = 'albumapi-go';
const appResourceName: string = 'album-api';
const sharedResourceName: string = appResourceName + randomUtils.getRandomHexString(4);
const acrResourceName: string = sharedResourceName.replace(/[^a-zA-Z0-9]+/g, '');

return [
{
label: 'Deploy App',
inputs: [
new RegExp(folderName, 'i'),
new RegExp('Create new container apps environment', 'i'),
'Continue',
sharedResourceName,
appResourceName,
`.${path.sep}src`,
'East US',
'Save'
],
expectedResults: dwpTestUtils.generateExpectedResults(sharedResourceName, acrResourceName, appResourceName),
expectedVSCodeSettings: {
deploymentConfigurations: [
generateExpectedDeploymentConfiguration(sharedResourceName, acrResourceName, appResourceName)
]
},
postTestAssertion: dwpTestUtils.generatePostTestAssertion({ targetPort: 8080, env: undefined })
},
{
label: 'Re-deploy App',
inputs: [
new RegExp(folderName, 'i'),
appResourceName,
'Continue'
],
expectedResults: dwpTestUtils.generateExpectedResults(sharedResourceName, acrResourceName, appResourceName),
expectedVSCodeSettings: {
deploymentConfigurations: [
generateExpectedDeploymentConfiguration(sharedResourceName, acrResourceName, appResourceName)
]
},
postTestAssertion: dwpTestUtils.generatePostTestAssertion({ targetPort: 8080, env: undefined })
}
];
}

function generateExpectedDeploymentConfiguration(sharedResourceName: string, acrResourceName: string, appResourceName: string): StringOrRegExpProps<DeploymentConfigurationSettings> {
return {
label: appResourceName,
type: 'AcrDockerBuildRequest',
dockerfilePath: path.join('src', 'Dockerfile'),
srcPath: 'src',
envPath: '',
resourceGroup: sharedResourceName,
containerApp: appResourceName,
containerRegistry: new RegExp(`${acrResourceName}.{6}`, 'i'),
};
}
Loading
Loading