Skip to content

Commit

Permalink
Add some tests for the deploy pane
Browse files Browse the repository at this point in the history
  • Loading branch information
anthony-c-martin committed Jan 23, 2025
1 parent 3c802a3 commit 54df4c3
Show file tree
Hide file tree
Showing 18 changed files with 2,298 additions and 459 deletions.
12 changes: 11 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,16 @@
"request": "launch",
"script": "${file}",
"cwd": "${cwd}"
}
},
{
"name": "Deploy Pane Tests",
"type": "node",
"request": "launch",
"runtimeExecutable": "npm",
"runtimeArgs": [
"test"
],
"cwd": "${workspaceFolder}/src/vscode-bicep-ui/apps/deploy-pane"
},
]
}
13 changes: 12 additions & 1 deletion .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,20 @@
"cwd": "${workspaceFolder}/src/vscode-bicep"
},
"dependsOn": [
"Build Language Server for VSIX"
"Build Language Server for VSIX",
"Build VSCode UI"
]
},
{
"label": "Build VSCode UI",
"command": "npm",
"args": ["run", "build", "--loglevel", "silent"],
"type": "shell",
"problemMatcher": "$tsc-watch",
"options": {
"cwd": "${workspaceFolder}/src/vscode-bicep-ui"
}
},
{
"label": "Build WASM for Playground",
"command": "npm",
Expand Down
13 changes: 11 additions & 2 deletions src/vscode-bicep-ui/apps/deploy-pane/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,32 @@
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview",
"test": "vitest",
"lint": "eslint . --report-unused-disable-directives --max-warnings 0",
"lint:fix": "eslint . --fix"
},
"devDependencies": {
"@rollup/plugin-node-resolve": "^16.0.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.2.0",
"@testing-library/user-event": "^14.6.0",
"@types/react": "^18.3.5",
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react": "^4.3.4",
"@vitest/coverage-v8": "^3.0.2",
"@vscode-elements/webview-playground": "^1.3.0",
"vite": "^5.4.5",
"vite-plugin-ejs": "^1.7.0"
"element-internals-polyfill": "^1.3.12",
"jsdom": "^26.0.0",
"typescript": "^5.7.3",
"vite": "^5.4.8",
"vitest": "^3.0.2"
},
"dependencies": {
"@azure/arm-resources": "^5.2.0",
"@azure/identity": "^4.5.0",
"@microsoft/vscode-azext-utils": "^2.5.12",
"@vscode-bicep-ui/components": "^0.0.0",
"@vscode-elements/elements": "^1.11.0",
"@vscode-elements/react-elements": "^0.8.0",
"react": "^18.3.1",
"react-dom": "^18.3.1"
Expand Down
158 changes: 158 additions & 0 deletions src/vscode-bicep-ui/apps/deploy-pane/src/__tests__/App.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { beforeEach, describe, expect, it, vi } from 'vitest'
import { render, waitFor, fireEvent, screen, act } from '@testing-library/react'
import { App } from '../components/App'
import { vscode } from '../vscode'
import { createDeploymentDataMessage, createGetAccessTokenMessage, createGetAccessTokenResultMessage, createGetDeploymentScopeMessage, createGetDeploymentScopeResultMessage, createGetStateMessage, createGetStateResultMessage, createReadyMessage, type VscodeMessage } from '../messages';
import { fileUri, getDeploymentOperations, getDeployResponse, getValidateResponse, getWhatIfResponse, parametersJson, scope, templateJson } from './mockData';

const mockClient = {
deployments: {
beginCreateOrUpdateAtScope: vi.fn(async () => {
return {
isDone: vi.fn(() => true),
getResult: vi.fn(getDeployResponse),
};
}),
beginValidateAtScopeAndWait: vi.fn(async () => getValidateResponse()),
beginWhatIfAndWait: vi.fn(async () => getWhatIfResponse()),
},
deploymentOperations: {
listAtScope: vi.fn(getDeploymentOperations),
}
}

beforeEach(() => {
vi.mock('@azure/arm-resources', async (importOriginal) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const mod: any = await importOriginal();
return {
...mod,
ResourceManagementClient: vi.fn(() => mockClient),
};
})
vi.mock('../components/hooks/time', () => ({
getDate: () => '1737601964200',
}));
});

describe('App', () => {
it('renders the loading spinner before initialization', async () => {
const { container } = render(<App />);
expect(container).toMatchSnapshot();
});

it('renders the App component with deployment state', async () => {
const { container } = render(<App />);

await initialize();

expect(container).toMatchSnapshot();
});

it('runs a deployment', async () => {
const { container } = render(<App />);

const scope = await initialize();

const deployButton = screen.getByText('Deploy');
fireEvent.click(deployButton);

await act(async () => {
await waitFor(() => expect(vscode.postMessage).toBeCalledWith(createGetAccessTokenMessage(scope)));
sendMessage(getAccessTokenResultMessage());
})

expect(container).toMatchSnapshot();
});

it('validates a deployment', async () => {
const { container } = render(<App />);

const scope = await initialize();

const validateButton = screen.getByText('Validate');
fireEvent.click(validateButton);

await act(async () => {
await waitFor(() => expect(vscode.postMessage).toBeCalledWith(createGetAccessTokenMessage(scope)));
sendMessage(getAccessTokenResultMessage());
})

expect(container).toMatchSnapshot();
});

it('what-ifs a deployment', async () => {
const { container } = render(<App />);

const scope = await initialize();

const whatIfButton = screen.getByText('What-If');
fireEvent.click(whatIfButton);

await act(async () => {
await waitFor(() => expect(vscode.postMessage).toBeCalledWith(createGetAccessTokenMessage(scope)));
sendMessage(getAccessTokenResultMessage());
})

expect(container).toMatchSnapshot();
});

it('supports the scope picker', async () => {
const { container } = render(<App />);

const scope = await initialize();

const changeScopeButton = screen.getByText('Change Scope');
fireEvent.click(changeScopeButton);

await act(async () => {
await waitFor(() => expect(vscode.postMessage).toBeCalledWith(createGetDeploymentScopeMessage("resourceGroup")));
sendMessage(createGetDeploymentScopeResultMessage(scope));
})

expect(container).toMatchSnapshot();
});
})

async function initialize() {
const stateResult = getStateResultMessage();
await act(async () => {
await waitFor(() => expect(vscode.postMessage).toBeCalledWith(createReadyMessage()));
sendMessage(getDeploymentDataMessage());

await waitFor(() => expect(vscode.postMessage).toBeCalledWith(createGetStateMessage()));
sendMessage(stateResult);
})

return stateResult.state.scope;
}

function sendMessage(message: VscodeMessage) {
fireEvent(
window,
new MessageEvent<VscodeMessage>("message", { data: message }));
}

function getDeploymentDataMessage() {
return createDeploymentDataMessage(
fileUri,
false,
templateJson,
parametersJson);
}

function getStateResultMessage() {
return createGetStateResultMessage({
scope: scope,
});
}

function getAccessTokenResultMessage() {
return createGetAccessTokenResultMessage({
expiresOnTimestamp: 1737601964200,
token: 'mockAccessToken'
});
}
Loading

0 comments on commit 54df4c3

Please sign in to comment.