Skip to content

Commit eabcd00

Browse files
Merge pull request #2297 from github/elena/improvements-to-wizard
Refactor `digForDatabaseItem` and `digForDatabaseWithSameLanguage` methods for skeleton wizard
2 parents a48b1f8 + 4c04daa commit eabcd00

File tree

5 files changed

+259
-174
lines changed

5 files changed

+259
-174
lines changed

extensions/ql-vscode/src/local-databases.ts

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -897,31 +897,6 @@ export class DatabaseManager extends DisposableObject {
897897
}
898898
}
899899

900-
public async digForDatabaseItem(
901-
language: string,
902-
databaseNwo: string,
903-
): Promise<DatabaseItem | undefined> {
904-
const dbItems = this.databaseItems || [];
905-
const dbs = dbItems.filter(
906-
(db) => db.language === language && db.name === databaseNwo,
907-
);
908-
if (dbs.length === 0) {
909-
return undefined;
910-
}
911-
return dbs[0];
912-
}
913-
914-
public async digForDatabaseWithSameLanguage(
915-
language: string,
916-
): Promise<DatabaseItem | undefined> {
917-
const dbItems = this.databaseItems || [];
918-
const dbs = dbItems.filter((db) => db.language === language);
919-
if (dbs.length === 0) {
920-
return undefined;
921-
}
922-
return dbs[0];
923-
}
924-
925900
/**
926901
* Returns the index of the workspace folder that corresponds to the source archive of `item`
927902
* if there is one, and -1 otherwise.

extensions/ql-vscode/src/skeleton-query-wizard.ts

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { QueryLanguage } from "./common/query-language";
77
import { askForLanguage, isFolderAlreadyInWorkspace } from "./helpers";
88
import { getErrorMessage } from "./pure/helpers-pure";
99
import { QlPackGenerator } from "./qlpack-generator";
10-
import { DatabaseManager } from "./local-databases";
10+
import { DatabaseItem, DatabaseManager } from "./local-databases";
1111
import * as databaseFetcher from "./databaseFetcher";
1212
import { ProgressCallback, UserCancellationException } from "./progress";
1313

@@ -239,20 +239,20 @@ export class SkeletonQueryWizard {
239239

240240
const databaseNwo = QUERY_LANGUAGE_TO_DATABASE_REPO[this.language];
241241

242-
// Check that we haven't already downloaded a database for this language
243-
const existingDatabaseItem = await this.databaseManager.digForDatabaseItem(
242+
const existingDatabaseItem = await this.findDatabaseItemByNwo(
244243
this.language,
245244
databaseNwo,
245+
this.databaseManager.databaseItems,
246246
);
247247

248248
if (existingDatabaseItem) {
249249
// select the found database
250250
await this.databaseManager.setCurrentDatabaseItem(existingDatabaseItem);
251251
} else {
252-
const sameLanguageDatabaseItem =
253-
await this.databaseManager.digForDatabaseWithSameLanguage(
254-
this.language,
255-
);
252+
const sameLanguageDatabaseItem = await this.findDatabaseItemByLanguage(
253+
this.language,
254+
this.databaseManager.databaseItems,
255+
);
256256

257257
if (sameLanguageDatabaseItem) {
258258
// select the found database
@@ -265,4 +265,31 @@ export class SkeletonQueryWizard {
265265
}
266266
}
267267
}
268+
269+
public async findDatabaseItemByNwo(
270+
language: string,
271+
databaseNwo: string,
272+
databaseItems: readonly DatabaseItem[],
273+
): Promise<DatabaseItem | undefined> {
274+
const dbItems = databaseItems || [];
275+
const dbs = dbItems.filter(
276+
(db) => db.language === language && db.name === databaseNwo,
277+
);
278+
if (dbs.length === 0) {
279+
return undefined;
280+
}
281+
return dbs[0];
282+
}
283+
284+
public async findDatabaseItemByLanguage(
285+
language: string,
286+
databaseItems: readonly DatabaseItem[],
287+
): Promise<DatabaseItem | undefined> {
288+
const dbItems = databaseItems || [];
289+
const dbs = dbItems.filter((db) => db.language === language);
290+
if (dbs.length === 0) {
291+
return undefined;
292+
}
293+
return dbs[0];
294+
}
268295
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { join } from "path";
2+
import { Uri } from "vscode";
3+
import {
4+
DatabaseContents,
5+
DatabaseItemImpl,
6+
FullDatabaseOptions,
7+
} from "../../../src/local-databases";
8+
import { DirResult } from "tmp";
9+
10+
export function mockDbOptions(): FullDatabaseOptions {
11+
return {
12+
dateAdded: 123,
13+
ignoreSourceArchive: false,
14+
language: "",
15+
};
16+
}
17+
18+
export function createMockDB(
19+
dir: DirResult,
20+
dbOptions = mockDbOptions(),
21+
// source archive location must be a real(-ish) location since
22+
// tests will add this to the workspace location
23+
sourceArchiveUri?: Uri,
24+
databaseUri?: Uri,
25+
): DatabaseItemImpl {
26+
sourceArchiveUri = sourceArchiveUri || sourceLocationUri(dir);
27+
databaseUri = databaseUri || dbLocationUri(dir);
28+
29+
return new DatabaseItemImpl(
30+
databaseUri,
31+
{
32+
sourceArchiveUri,
33+
datasetUri: databaseUri,
34+
} as DatabaseContents,
35+
dbOptions,
36+
() => void 0,
37+
);
38+
}
39+
40+
export function sourceLocationUri(dir: DirResult) {
41+
return Uri.file(join(dir.name, "src.zip"));
42+
}
43+
44+
export function dbLocationUri(dir: DirResult) {
45+
return Uri.file(join(dir.name, "db"));
46+
}

extensions/ql-vscode/test/vscode-tests/cli-integration/skeleton-query-wizard.test.ts

Lines changed: 112 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,20 @@ import { createFileSync, ensureDirSync, removeSync } from "fs-extra";
1313
import { join } from "path";
1414
import { CancellationTokenSource } from "vscode-jsonrpc";
1515
import { testCredentialsWithStub } from "../../factories/authentication";
16-
import { DatabaseItem, DatabaseManager } from "../../../src/local-databases";
16+
import {
17+
DatabaseItem,
18+
DatabaseManager,
19+
FullDatabaseOptions,
20+
} from "../../../src/local-databases";
1721
import * as databaseFetcher from "../../../src/databaseFetcher";
22+
import { createMockDB } from "../../factories/databases/databases";
1823

1924
jest.setTimeout(40_000);
2025

2126
describe("SkeletonQueryWizard", () => {
27+
let mockCli: CodeQLCliServer;
2228
let wizard: SkeletonQueryWizard;
29+
let mockDatabaseManager: DatabaseManager;
2330
let dir: tmp.DirResult;
2431
let storagePath: string;
2532
let quickPickSpy: jest.SpiedFunction<typeof window.showQuickPick>;
@@ -42,29 +49,30 @@ describe("SkeletonQueryWizard", () => {
4249
const token = new CancellationTokenSource().token;
4350
const credentials = testCredentialsWithStub();
4451
const chosenLanguage = "ruby";
45-
const mockDatabaseManager = mockedObject<DatabaseManager>({
46-
setCurrentDatabaseItem: jest.fn(),
47-
digForDatabaseItem: jest.fn(),
48-
digForDatabaseWithSameLanguage: jest.fn(),
49-
});
50-
const mockCli = mockedObject<CodeQLCliServer>({
51-
resolveLanguages: jest
52-
.fn()
53-
.mockResolvedValue([
54-
"ruby",
55-
"javascript",
56-
"go",
57-
"java",
58-
"python",
59-
"csharp",
60-
"cpp",
61-
]),
62-
getSupportedLanguages: jest.fn(),
63-
});
6452

6553
jest.spyOn(extLogger, "log").mockResolvedValue(undefined);
6654

6755
beforeEach(async () => {
56+
mockCli = mockedObject<CodeQLCliServer>({
57+
resolveLanguages: jest
58+
.fn()
59+
.mockResolvedValue([
60+
"ruby",
61+
"javascript",
62+
"go",
63+
"java",
64+
"python",
65+
"csharp",
66+
"cpp",
67+
]),
68+
getSupportedLanguages: jest.fn(),
69+
});
70+
71+
mockDatabaseManager = mockedObject<DatabaseManager>({
72+
setCurrentDatabaseItem: jest.fn(),
73+
databaseItems: [] as DatabaseItem[],
74+
});
75+
6876
dir = tmp.dirSync({
6977
prefix: "skeleton_query_wizard_",
7078
unsafeCleanup: true,
@@ -214,6 +222,7 @@ describe("SkeletonQueryWizard", () => {
214222
describe("if database is also already downloaded", () => {
215223
let databaseNwo: string;
216224
let databaseItem: DatabaseItem;
225+
let mockDatabaseManagerWithItems: DatabaseManager;
217226

218227
beforeEach(async () => {
219228
databaseNwo = QUERY_LANGUAGE_TO_DATABASE_REPO[chosenLanguage];
@@ -223,9 +232,19 @@ describe("SkeletonQueryWizard", () => {
223232
language: chosenLanguage,
224233
} as DatabaseItem;
225234

226-
jest
227-
.spyOn(mockDatabaseManager, "digForDatabaseItem")
228-
.mockResolvedValue([databaseItem] as any);
235+
mockDatabaseManagerWithItems = mockedObject<DatabaseManager>({
236+
setCurrentDatabaseItem: jest.fn(),
237+
databaseItems: [databaseItem] as DatabaseItem[],
238+
});
239+
240+
wizard = new SkeletonQueryWizard(
241+
mockCli,
242+
jest.fn(),
243+
credentials,
244+
extLogger,
245+
mockDatabaseManagerWithItems,
246+
token,
247+
);
229248
});
230249

231250
it("should not download a new database for language", async () => {
@@ -237,9 +256,9 @@ describe("SkeletonQueryWizard", () => {
237256
it("should select an existing database", async () => {
238257
await wizard.execute();
239258

240-
expect(mockDatabaseManager.setCurrentDatabaseItem).toHaveBeenCalledWith(
241-
[databaseItem],
242-
);
259+
expect(
260+
mockDatabaseManagerWithItems.setCurrentDatabaseItem,
261+
).toHaveBeenCalledWith(databaseItem);
243262
});
244263

245264
it("should open the new query file", async () => {
@@ -254,12 +273,6 @@ describe("SkeletonQueryWizard", () => {
254273
});
255274

256275
describe("if database is missing", () => {
257-
beforeEach(async () => {
258-
jest
259-
.spyOn(mockDatabaseManager, "digForDatabaseItem")
260-
.mockResolvedValue(undefined);
261-
});
262-
263276
describe("if the user choses to downloaded the suggested database from GitHub", () => {
264277
it("should download a new database for language", async () => {
265278
await wizard.execute();
@@ -335,4 +348,71 @@ describe("SkeletonQueryWizard", () => {
335348
});
336349
});
337350
});
351+
352+
describe("findDatabaseItemByNwo", () => {
353+
describe("when the item exists", () => {
354+
it("should return the database item", async () => {
355+
const mockDbItem = createMockDB(dir);
356+
const mockDbItem2 = createMockDB(dir);
357+
358+
const databaseItem = await wizard.findDatabaseItemByNwo(
359+
mockDbItem.language,
360+
mockDbItem.name,
361+
[mockDbItem, mockDbItem2],
362+
);
363+
364+
expect(databaseItem!.language).toEqual(mockDbItem.language);
365+
expect(databaseItem!.name).toEqual(mockDbItem.name);
366+
});
367+
});
368+
369+
describe("when the item doesn't exist", () => {
370+
it("should return nothing", async () => {
371+
const mockDbItem = createMockDB(dir);
372+
const mockDbItem2 = createMockDB(dir);
373+
374+
const databaseItem = await wizard.findDatabaseItemByNwo(
375+
"ruby",
376+
"mock-nwo",
377+
[mockDbItem, mockDbItem2],
378+
);
379+
380+
expect(databaseItem).toBeUndefined();
381+
});
382+
});
383+
});
384+
385+
describe("findDatabaseItemByLanguage", () => {
386+
describe("when the item exists", () => {
387+
it("should return the database item", async () => {
388+
const mockDbItem = createMockDB(dir, {
389+
language: "ruby",
390+
} as FullDatabaseOptions);
391+
const mockDbItem2 = createMockDB(dir, {
392+
language: "javascript",
393+
} as FullDatabaseOptions);
394+
395+
const databaseItem = await wizard.findDatabaseItemByLanguage("ruby", [
396+
mockDbItem,
397+
mockDbItem2,
398+
]);
399+
400+
expect(databaseItem).toEqual(mockDbItem);
401+
});
402+
});
403+
404+
describe("when the item doesn't exist", () => {
405+
it("should return nothing", async () => {
406+
const mockDbItem = createMockDB(dir);
407+
const mockDbItem2 = createMockDB(dir);
408+
409+
const databaseItem = await wizard.findDatabaseItemByLanguage("ruby", [
410+
mockDbItem,
411+
mockDbItem2,
412+
]);
413+
414+
expect(databaseItem).toBeUndefined();
415+
});
416+
});
417+
});
338418
});

0 commit comments

Comments
 (0)