Skip to content

Commit fd57133

Browse files
authored
Merge pull request #2103 from github/koesie10/mock-more-objects
Remove more instances of `as unknown as`
2 parents f39bbd3 + 65e652b commit fd57133

File tree

10 files changed

+106
-50
lines changed

10 files changed

+106
-50
lines changed

extensions/ql-vscode/test/vscode-tests/cli-integration/variant-analysis/variant-analysis-manager.test.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ import { DbManager } from "../../../../src/databases/db-manager";
5959
import { App } from "../../../../src/common/app";
6060
import { ExtensionApp } from "../../../../src/common/vscode/vscode-app";
6161
import { DbConfigStore } from "../../../../src/databases/config/db-config-store";
62+
import { mockedObject } from "../../utils/mocking.helpers";
6263

6364
// up to 3 minutes per test
6465
jest.setTimeout(3 * 60 * 1000);
@@ -992,10 +993,10 @@ describe("Variant Analysis Manager", () => {
992993

993994
showTextDocumentSpy = jest
994995
.spyOn(window, "showTextDocument")
995-
.mockResolvedValue(undefined as unknown as TextEditor);
996+
.mockResolvedValue(mockedObject<TextEditor>({}));
996997
openTextDocumentSpy = jest
997998
.spyOn(workspace, "openTextDocument")
998-
.mockResolvedValue(undefined as unknown as TextDocument);
999+
.mockResolvedValue(mockedObject<TextDocument>({}));
9991000
});
10001001

10011002
afterEach(() => {
@@ -1005,8 +1006,8 @@ describe("Variant Analysis Manager", () => {
10051006
it("opens the query text", async () => {
10061007
await variantAnalysisManager.openQueryText(variantAnalysis.id);
10071008

1008-
expect(showTextDocumentSpy).toHaveBeenCalledTimes(1);
10091009
expect(openTextDocumentSpy).toHaveBeenCalledTimes(1);
1010+
expect(showTextDocumentSpy).toHaveBeenCalledTimes(1);
10101011

10111012
const uri: Uri = openTextDocumentSpy.mock.calls[0][0] as Uri;
10121013
expect(uri.scheme).toEqual("codeql-variant-analysis");
@@ -1040,10 +1041,10 @@ describe("Variant Analysis Manager", () => {
10401041

10411042
showTextDocumentSpy = jest
10421043
.spyOn(window, "showTextDocument")
1043-
.mockResolvedValue(undefined as unknown as TextEditor);
1044+
.mockResolvedValue(mockedObject<TextEditor>({}));
10441045
openTextDocumentSpy = jest
10451046
.spyOn(workspace, "openTextDocument")
1046-
.mockResolvedValue(undefined as unknown as TextDocument);
1047+
.mockResolvedValue(mockedObject<TextDocument>({}));
10471048
});
10481049

10491050
afterEach(() => {

extensions/ql-vscode/test/vscode-tests/minimal-workspace/local-databases.test.ts

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ describe("local databases", () => {
4848
>;
4949

5050
let dir: tmp.DirResult;
51+
let extensionContextStoragePath: string;
5152

5253
beforeEach(() => {
5354
dir = tmp.dirSync();
@@ -65,16 +66,24 @@ describe("local databases", () => {
6566
.spyOn(helpers, "showBinaryChoiceDialog")
6667
.mockResolvedValue(true);
6768

68-
extensionContext = {
69-
workspaceState: {
70-
update: updateSpy,
71-
get: () => [],
69+
extensionContextStoragePath = dir.name;
70+
71+
extensionContext = mockedObject<ExtensionContext>(
72+
{
73+
workspaceState: {
74+
update: updateSpy,
75+
get: () => [],
76+
},
7277
},
73-
// pretend like databases added in the temp dir are controlled by the extension
74-
// so that they are deleted upon removal
75-
storagePath: dir.name,
76-
storageUri: Uri.parse(dir.name),
77-
} as unknown as ExtensionContext;
78+
{
79+
dynamicProperties: {
80+
// pretend like databases added in the temp dir are controlled by the extension
81+
// so that they are deleted upon removal
82+
storagePath: () => extensionContextStoragePath,
83+
storageUri: () => Uri.parse(extensionContextStoragePath),
84+
},
85+
},
86+
);
7887

7988
databaseManager = new DatabaseManager(
8089
extensionContext,
@@ -267,6 +276,7 @@ describe("local databases", () => {
267276

268277
// pretend that the database location is not controlled by the extension
269278
(databaseManager as any).ctx.storagePath = "hucairz";
279+
extensionContextStoragePath = "hucairz";
270280

271281
await databaseManager.removeDatabaseItem(
272282
{} as ProgressCallback,

extensions/ql-vscode/test/vscode-tests/minimal-workspace/qltest-discovery.test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { DirectoryResult } from "tmp-promise";
77
import * as tmp from "tmp-promise";
88

99
import "../../matchers/toEqualPath";
10+
import { mockedObject } from "../utils/mocking.helpers";
1011

1112
describe("qltest-discovery", () => {
1213
describe("discoverTests", () => {
@@ -34,10 +35,10 @@ describe("qltest-discovery", () => {
3435
iFile = join(hDir, "i.ql");
3536

3637
qlTestDiscover = new QLTestDiscovery(
37-
{
38+
mockedObject<WorkspaceFolder>({
3839
uri: baseUri,
3940
name: "My tests",
40-
} as unknown as WorkspaceFolder,
41+
}),
4142
{
4243
resolveTests() {
4344
return [dFile, eFile, iFile];

extensions/ql-vscode/test/vscode-tests/no-workspace/query-history/history-item-label-provider.test.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ describe("HistoryItemLabelProvider", () => {
2222
beforeEach(() => {
2323
config = {
2424
format: "xxx %q xxx",
25-
} as unknown as QueryHistoryConfig;
25+
ttlInMillis: 0,
26+
onDidChangeConfiguration: jest.fn(),
27+
};
2628
labelProvider = new HistoryItemLabelProvider(config);
2729
});
2830

extensions/ql-vscode/test/vscode-tests/no-workspace/query-history/history-tree-data-provider.test.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@ import { join } from "path";
22
import * as vscode from "vscode";
33

44
import { extLogger } from "../../../../src/common";
5-
import {
6-
QueryHistoryConfig,
7-
QueryHistoryConfigListener,
8-
} from "../../../../src/config";
5+
import { QueryHistoryConfigListener } from "../../../../src/config";
96
import { LocalQueryInfo } from "../../../../src/query-results";
107
import { DatabaseManager } from "../../../../src/local-databases";
118
import { tmpDir } from "../../../../src/helpers";
@@ -121,8 +118,10 @@ describe("HistoryTreeDataProvider", () => {
121118
]);
122119

123120
labelProvider = new HistoryItemLabelProvider({
124-
/**/
125-
} as QueryHistoryConfig);
121+
format: "",
122+
ttlInMillis: 0,
123+
onDidChangeConfiguration: jest.fn(),
124+
});
126125
historyTreeDataProvider = new HistoryTreeDataProvider(labelProvider);
127126
});
128127

@@ -432,7 +431,11 @@ describe("HistoryTreeDataProvider", () => {
432431
extensionPath: vscode.Uri.file("/x/y/z").fsPath,
433432
} as vscode.ExtensionContext,
434433
configListener,
435-
new HistoryItemLabelProvider({} as QueryHistoryConfig),
434+
new HistoryItemLabelProvider({
435+
format: "",
436+
ttlInMillis: 0,
437+
onDidChangeConfiguration: jest.fn(),
438+
}),
436439
doCompareCallback,
437440
);
438441
(qhm.treeDataProvider as any).history = [...allHistory];

extensions/ql-vscode/test/vscode-tests/no-workspace/query-history/query-history-manager.test.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@ import * as vscode from "vscode";
33

44
import { extLogger } from "../../../../src/common";
55
import { QueryHistoryManager } from "../../../../src/query-history/query-history-manager";
6-
import {
7-
QueryHistoryConfig,
8-
QueryHistoryConfigListener,
9-
} from "../../../../src/config";
6+
import { QueryHistoryConfigListener } from "../../../../src/config";
107
import { LocalQueryInfo } from "../../../../src/query-results";
118
import { DatabaseManager } from "../../../../src/local-databases";
129
import { tmpDir } from "../../../../src/helpers";
@@ -28,6 +25,7 @@ import { VariantAnalysisStatus } from "../../../../src/variant-analysis/shared/v
2825
import { QuickPickItem, TextEditor } from "vscode";
2926
import { WebviewReveal } from "../../../../src/interface-utils";
3027
import * as helpers from "../../../../src/helpers";
28+
import { mockedObject } from "../../utils/mocking.helpers";
3129

3230
describe("QueryHistoryManager", () => {
3331
const mockExtensionLocation = join(tmpDir.name, "mock-extension-location");
@@ -58,7 +56,7 @@ describe("QueryHistoryManager", () => {
5856
beforeEach(() => {
5957
showTextDocumentSpy = jest
6058
.spyOn(vscode.window, "showTextDocument")
61-
.mockResolvedValue(undefined as unknown as TextEditor);
59+
.mockResolvedValue(mockedObject<TextEditor>({}));
6260
showInformationMessageSpy = jest
6361
.spyOn(vscode.window, "showInformationMessage")
6462
.mockResolvedValue(undefined);
@@ -1158,7 +1156,11 @@ describe("QueryHistoryManager", () => {
11581156
extensionPath: vscode.Uri.file("/x/y/z").fsPath,
11591157
} as vscode.ExtensionContext,
11601158
configListener,
1161-
new HistoryItemLabelProvider({} as QueryHistoryConfig),
1159+
new HistoryItemLabelProvider({
1160+
format: "",
1161+
ttlInMillis: 0,
1162+
onDidChangeConfiguration: jest.fn(),
1163+
}),
11621164
doCompareCallback,
11631165
);
11641166
(qhm.treeDataProvider as any).history = [...allHistory];

extensions/ql-vscode/test/vscode-tests/no-workspace/query-history/query-history-scrubber.test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
THREE_HOURS_IN_MS,
1313
TWO_HOURS_IN_MS,
1414
} from "../../../../src/pure/time";
15+
import { mockedObject } from "../../utils/mocking.helpers";
1516

1617
describe("query history scrubber", () => {
1718
const now = Date.now();
@@ -181,11 +182,11 @@ describe("query history scrubber", () => {
181182
TWO_HOURS_IN_MS,
182183
LESS_THAN_ONE_DAY,
183184
dir,
184-
{
185+
mockedObject<QueryHistoryManager>({
185186
removeDeletedQueries: () => {
186187
return Promise.resolve();
187188
},
188-
} as QueryHistoryManager,
189+
}),
189190
mockCtx,
190191
{
191192
increment: () => runCount++,

extensions/ql-vscode/test/vscode-tests/no-workspace/query-history/variant-analysis-history.test.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {
99
import { join } from "path";
1010

1111
import { commands, ExtensionContext, Uri } from "vscode";
12-
import { QueryHistoryConfig } from "../../../../src/config";
1312
import { DatabaseManager } from "../../../../src/local-databases";
1413
import { tmpDir, walkDirectory } from "../../../../src/helpers";
1514
import { DisposableBucket } from "../../disposable-bucket";
@@ -20,6 +19,7 @@ import { EvalLogViewer } from "../../../../src/eval-log-viewer";
2019
import { QueryRunner } from "../../../../src/queryRunner";
2120
import { VariantAnalysisManager } from "../../../../src/variant-analysis/variant-analysis-manager";
2221
import { QueryHistoryManager } from "../../../../src/query-history/query-history-manager";
22+
import { mockedObject } from "../../utils/mocking.helpers";
2323

2424
// set a higher timeout since recursive delete may take a while, expecially on Windows.
2525
jest.setTimeout(120000);
@@ -75,14 +75,21 @@ describe("Variant Analyses and QueryHistoryManager", () => {
7575
variantAnalysisManagerStub,
7676
{} as EvalLogViewer,
7777
STORAGE_DIR,
78-
{
78+
mockedObject<ExtensionContext>({
7979
globalStorageUri: Uri.file(STORAGE_DIR),
80+
storageUri: undefined,
8081
extensionPath: EXTENSION_PATH,
81-
} as ExtensionContext,
82+
}),
8283
{
84+
format: "",
85+
ttlInMillis: 0,
8386
onDidChangeConfiguration: () => new DisposableBucket(),
84-
} as unknown as QueryHistoryConfig,
85-
new HistoryItemLabelProvider({} as QueryHistoryConfig),
87+
},
88+
new HistoryItemLabelProvider({
89+
format: "",
90+
ttlInMillis: 0,
91+
onDidChangeConfiguration: jest.fn(),
92+
}),
8693
asyncNoop,
8794
);
8895
disposables.push(qhm);

extensions/ql-vscode/test/vscode-tests/no-workspace/test-adapter.test.ts

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -59,18 +59,20 @@ describe("test-adapter", () => {
5959
setCurrentDatabaseItemSpy.mockResolvedValue(undefined);
6060
resolveQlpacksSpy.mockResolvedValue({});
6161
resolveTestsSpy.mockResolvedValue([]);
62-
fakeDatabaseManager = {
63-
openDatabase: openDatabaseSpy,
64-
removeDatabaseItem: removeDatabaseItemSpy,
65-
renameDatabaseItem: renameDatabaseItemSpy,
66-
setCurrentDatabaseItem: setCurrentDatabaseItemSpy,
67-
} as unknown as DatabaseManager;
68-
Object.defineProperty(fakeDatabaseManager, "currentDatabaseItem", {
69-
get: () => currentDatabaseItem,
70-
});
71-
Object.defineProperty(fakeDatabaseManager, "databaseItems", {
72-
get: () => databaseItems,
73-
});
62+
fakeDatabaseManager = mockedObject<DatabaseManager>(
63+
{
64+
openDatabase: openDatabaseSpy,
65+
removeDatabaseItem: removeDatabaseItemSpy,
66+
renameDatabaseItem: renameDatabaseItemSpy,
67+
setCurrentDatabaseItem: setCurrentDatabaseItemSpy,
68+
},
69+
{
70+
dynamicProperties: {
71+
currentDatabaseItem: () => currentDatabaseItem,
72+
databaseItems: () => databaseItems,
73+
},
74+
},
75+
);
7476

7577
jest.spyOn(preTestDatabaseItem, "isAffectedByTest").mockResolvedValue(true);
7678

extensions/ql-vscode/test/vscode-tests/utils/mocking.helpers.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,39 @@ export type DeepPartial<T> = T extends object
44
}
55
: T;
66

7-
export function mockedObject<T extends object>(props: DeepPartial<T>): T {
7+
export type DynamicProperties<T extends object> = {
8+
[P in keyof T]?: () => T[P];
9+
};
10+
11+
type MockedObjectOptions<T extends object> = {
12+
/**
13+
* Properties for which the given method should be called when accessed.
14+
* The method should return the value to be returned when the property is accessed.
15+
* Methods which are explicitly defined in `methods` will take precedence over
16+
* dynamic properties.
17+
*/
18+
dynamicProperties?: DynamicProperties<T>;
19+
};
20+
21+
export function mockedObject<T extends object>(
22+
props: DeepPartial<T>,
23+
{ dynamicProperties }: MockedObjectOptions<T> = {},
24+
): T {
825
return new Proxy<T>({} as unknown as T, {
926
get: (_target, prop) => {
1027
if (prop in props) {
1128
return (props as any)[prop];
1229
}
30+
if (dynamicProperties && prop in dynamicProperties) {
31+
return (dynamicProperties as any)[prop]();
32+
}
33+
34+
// The `then` method is accessed by `Promise.resolve` to check if the object is a thenable.
35+
// We don't want to throw an error when this happens.
36+
if (prop === "then") {
37+
return undefined;
38+
}
39+
1340
throw new Error(`Method ${String(prop)} not mocked`);
1441
},
1542
});

0 commit comments

Comments
 (0)