Skip to content

Commit 00145bb

Browse files
committed
Add some basic integration tests for MRVA
This adds some basic integration tests for MRVA using the GitHub mock API server. It only does basic assertions and still needs to stub some things because it is quite hard to properly test things since VSCode does not expose an API to e.g. answer quick pick pop-ups. I'm not sure how useful these integration tests will actually be in practice, but they do at least ensure that we are able to successfully submit a variant analysis.
1 parent 3812e3d commit 00145bb

File tree

1 file changed

+142
-0
lines changed

1 file changed

+142
-0
lines changed
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
import * as path from 'path';
2+
3+
import * as sinon from 'sinon';
4+
5+
import { commands, extensions, TextDocument, window, workspace } from 'vscode';
6+
import { setupServer } from 'msw/node';
7+
import * as Octokit from '@octokit/rest';
8+
import { retry } from '@octokit/plugin-retry';
9+
10+
import { CodeQLExtensionInterface } from '../../../extension';
11+
import { createRequestHandlers } from '../../../mocks/request-handlers';
12+
import * as config from '../../../config';
13+
import { Credentials } from '../../../authentication';
14+
15+
const server = setupServer();
16+
17+
before(() => server.listen());
18+
19+
afterEach(() => server.resetHandlers());
20+
21+
after(() => server.close());
22+
23+
async function loadScenario(scenarioName: string) {
24+
const handlers = await createRequestHandlers(path.join(__dirname, '../../../../src/mocks/scenarios', scenarioName));
25+
26+
server.use(...handlers);
27+
}
28+
29+
async function showQlDocument(name: string): Promise<TextDocument> {
30+
const folderPath = workspace.workspaceFolders![0].uri.fsPath;
31+
const documentPath = path.resolve(folderPath, name);
32+
const document = await workspace.openTextDocument(documentPath);
33+
await window.showTextDocument(document!);
34+
return document;
35+
}
36+
37+
describe('Variant Analysis Integration', function() {
38+
this.timeout(10_000);
39+
40+
let sandbox: sinon.SinonSandbox;
41+
let quickPickSpy: sinon.SinonStub;
42+
let inputBoxSpy: sinon.SinonStub;
43+
let executeCommandSpy: sinon.SinonStub;
44+
let showErrorMessageSpy: sinon.SinonStub;
45+
46+
beforeEach(async () => {
47+
sandbox = sinon.createSandbox();
48+
49+
sandbox.stub(config, 'isCanary').returns(true);
50+
sandbox.stub(config, 'isVariantAnalysisLiveResultsEnabled').returns(true);
51+
52+
const mockCredentials = {
53+
getOctokit: () => Promise.resolve(new Octokit.Octokit({ retry })),
54+
} as unknown as Credentials;
55+
sandbox.stub(Credentials, 'initialize').resolves(mockCredentials);
56+
57+
await config.setRemoteControllerRepo('github/vscode-codeql');
58+
59+
quickPickSpy = sandbox.stub(window, 'showQuickPick').resolves(undefined);
60+
inputBoxSpy = sandbox.stub(window, 'showInputBox').resolves(undefined);
61+
62+
executeCommandSpy = sandbox.stub(commands, 'executeCommand').callThrough();
63+
showErrorMessageSpy = sandbox.stub(window, 'showErrorMessage').resolves(undefined);
64+
65+
try {
66+
await extensions.getExtension<CodeQLExtensionInterface | Record<string, never>>('GitHub.vscode-codeql')!.activate();
67+
} catch (e) {
68+
fail(e as Error);
69+
}
70+
});
71+
72+
afterEach(() => {
73+
sandbox.restore();
74+
});
75+
76+
describe('Successful scenario', () => {
77+
beforeEach(async () => {
78+
await loadScenario('problem-query-success');
79+
});
80+
81+
it('opens the variant analysis view', async () => {
82+
await showQlDocument('query.ql');
83+
84+
// Select a repository list
85+
quickPickSpy.onFirstCall().resolves({
86+
useCustomRepo: true,
87+
});
88+
// Enter a GitHub repository
89+
inputBoxSpy.onFirstCall().resolves('github/codeql');
90+
// Select target language for your query
91+
quickPickSpy.onSecondCall().resolves('javascript');
92+
93+
await commands.executeCommand('codeQL.runVariantAnalysis');
94+
95+
sinon.assert.calledWith(executeCommandSpy, 'codeQL.openVariantAnalysisView', 146);
96+
});
97+
});
98+
99+
describe('Missing controller repo', () => {
100+
beforeEach(async () => {
101+
await loadScenario('missing-controller-repo');
102+
});
103+
104+
it('shows the error message', async () => {
105+
await showQlDocument('query.ql');
106+
107+
// Select a repository list
108+
quickPickSpy.onFirstCall().resolves({
109+
useCustomRepo: true,
110+
});
111+
// Enter a GitHub repository
112+
inputBoxSpy.onFirstCall().resolves('github/codeql');
113+
114+
await commands.executeCommand('codeQL.runVariantAnalysis');
115+
116+
sinon.assert.calledWith(showErrorMessageSpy, sinon.match('Controller repository "github/vscode-codeql" not found'), sinon.match.string);
117+
});
118+
});
119+
120+
describe('Submission failure', () => {
121+
beforeEach(async () => {
122+
await loadScenario('submission-failure');
123+
});
124+
125+
it('shows the error message', async () => {
126+
await showQlDocument('query.ql');
127+
128+
// Select a repository list
129+
quickPickSpy.onFirstCall().resolves({
130+
useCustomRepo: true,
131+
});
132+
// Enter a GitHub repository
133+
inputBoxSpy.onFirstCall().resolves('github/codeql');
134+
// Select target language for your query
135+
quickPickSpy.onSecondCall().resolves('javascript');
136+
137+
await commands.executeCommand('codeQL.runVariantAnalysis');
138+
139+
sinon.assert.calledWith(showErrorMessageSpy, sinon.match('No repositories could be queried.'), sinon.match.string);
140+
});
141+
});
142+
});

0 commit comments

Comments
 (0)