Skip to content

Commit 54cf5c5

Browse files
Add tests of MethodModelingViewProvider viewLoaded
1 parent 659da6c commit 54cf5c5

4 files changed

Lines changed: 221 additions & 3 deletions

File tree

extensions/ql-vscode/src/model-editor/modeling-store.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ interface InternalDbModelingState {
2222
modelEvaluationRun: ModelEvaluationRun | undefined;
2323
}
2424

25-
interface DbModelingState {
25+
export interface DbModelingState {
2626
readonly databaseItem: DatabaseItem;
2727
readonly methods: readonly Method[];
2828
readonly hideModeledMethods: boolean;
@@ -36,7 +36,7 @@ interface DbModelingState {
3636
readonly modelEvaluationRun: ModelEvaluationRun | undefined;
3737
}
3838

39-
interface SelectedMethodDetails {
39+
export interface SelectedMethodDetails {
4040
readonly databaseItem: DatabaseItem;
4141
readonly method: Method;
4242
readonly usage: Usage | undefined;

extensions/ql-vscode/test/__mocks__/model-editor/modelingEventsMock.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { ModelingEvents } from "../../../src/model-editor/modeling-events";
33

44
export function createMockModelingEvents({
55
onActiveDbChanged = jest.fn(),
6+
onDbOpened = jest.fn(),
67
onDbClosed = jest.fn(),
78
onSelectedMethodChanged = jest.fn(),
89
onMethodsChanged = jest.fn(),
@@ -16,6 +17,7 @@ export function createMockModelingEvents({
1617
onModelEvaluationRunChanged = jest.fn(),
1718
}: {
1819
onActiveDbChanged?: ModelingEvents["onActiveDbChanged"];
20+
onDbOpened?: ModelingEvents["onDbOpened"];
1921
onDbClosed?: ModelingEvents["onDbClosed"];
2022
onSelectedMethodChanged?: ModelingEvents["onSelectedMethodChanged"];
2123
onMethodsChanged?: ModelingEvents["onMethodsChanged"];
@@ -30,6 +32,7 @@ export function createMockModelingEvents({
3032
} = {}): ModelingEvents {
3133
return mockedObject<ModelingEvents>({
3234
onActiveDbChanged,
35+
onDbOpened,
3336
onDbClosed,
3437
onSelectedMethodChanged,
3538
onMethodsChanged,

extensions/ql-vscode/test/__mocks__/model-editor/modelingStoreMock.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,20 @@ import type { ModelingStore } from "../../../src/model-editor/modeling-store";
33

44
export function createMockModelingStore({
55
initializeStateForDb = jest.fn(),
6-
getStateForActiveDb = jest.fn(),
6+
getStateForActiveDb = jest.fn().mockReturnValue(undefined),
7+
getSelectedMethodDetails = jest.fn().mockReturnValue(undefined),
78
getModelEvaluationRun = jest.fn(),
89
updateModelEvaluationRun = jest.fn(),
910
}: {
1011
initializeStateForDb?: ModelingStore["initializeStateForDb"];
1112
getStateForActiveDb?: ModelingStore["getStateForActiveDb"];
13+
getSelectedMethodDetails?: ModelingStore["getSelectedMethodDetails"];
1214
getModelEvaluationRun?: ModelingStore["getModelEvaluationRun"];
1315
updateModelEvaluationRun?: ModelingStore["updateModelEvaluationRun"];
1416
} = {}): ModelingStore {
1517
return mockedObject<ModelingStore>({
1618
initializeStateForDb,
19+
getSelectedMethodDetails,
1720
getStateForActiveDb,
1821
getModelEvaluationRun,
1922
updateModelEvaluationRun,
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
import type {
2+
Uri,
3+
Webview,
4+
WebviewView,
5+
WebviewViewResolveContext,
6+
} from "vscode";
7+
import { CancellationTokenSource, EventEmitter } from "vscode";
8+
import type { ModelConfigListener } from "../../../../../src/config";
9+
import { MethodModelingViewProvider } from "../../../../../src/model-editor/method-modeling/method-modeling-view-provider";
10+
import { createMockApp } from "../../../../__mocks__/appMock";
11+
import { createMockModelingEvents } from "../../../../__mocks__/model-editor/modelingEventsMock";
12+
import { createMockModelingStore } from "../../../../__mocks__/model-editor/modelingStoreMock";
13+
import { mockedObject } from "../../../../mocked-object";
14+
import type { FromMethodModelingMessage } from "../../../../../src/common/interface-types";
15+
import { DisposableObject } from "../../../../../src/common/disposable-object";
16+
import type { ModelingEvents } from "../../../../../src/model-editor/modeling-events";
17+
import type {
18+
DbModelingState,
19+
SelectedMethodDetails,
20+
} from "../../../../../src/model-editor/modeling-store";
21+
import { mockDatabaseItem } from "../../../utils/mocking.helpers";
22+
import {
23+
createMethod,
24+
createUsage,
25+
} from "../../../../factories/model-editor/method-factories";
26+
27+
describe("method modeling view provider", () => {
28+
// Modeling store
29+
let getStateForActiveDb: jest.Mock<DbModelingState | undefined, []>;
30+
let getSelectedMethodDetails: jest.Mock<
31+
SelectedMethodDetails | undefined,
32+
[]
33+
>;
34+
35+
// Modeling events
36+
let selectedMethodChangedEventEmitter: ModelingEvents["onSelectedMethodChangedEventEmitter"];
37+
let dbOpenedEventEmitter: ModelingEvents["onDbOpenedEventEmitter"];
38+
39+
// View provider
40+
let viewProvider: MethodModelingViewProvider;
41+
let onDidReceiveMessage: (msg: FromMethodModelingMessage) => Promise<void>;
42+
let postMessage: (message: unknown) => Promise<boolean>;
43+
44+
beforeEach(async () => {
45+
const app = createMockApp({});
46+
47+
getStateForActiveDb = jest.fn().mockReturnValue(undefined);
48+
getSelectedMethodDetails = jest.fn().mockReturnValue(undefined);
49+
const modelingStore = createMockModelingStore({
50+
getStateForActiveDb,
51+
getSelectedMethodDetails,
52+
});
53+
54+
selectedMethodChangedEventEmitter = new EventEmitter();
55+
dbOpenedEventEmitter = new EventEmitter();
56+
const modelingEvents = createMockModelingEvents({
57+
onSelectedMethodChanged: selectedMethodChangedEventEmitter.event,
58+
onDbOpened: dbOpenedEventEmitter.event,
59+
});
60+
61+
const modelConfigListener = mockedObject<ModelConfigListener>({
62+
showTypeModels: true,
63+
onDidChangeConfiguration: jest.fn(),
64+
});
65+
66+
viewProvider = new MethodModelingViewProvider(
67+
app,
68+
modelingStore,
69+
modelingEvents,
70+
modelConfigListener,
71+
);
72+
73+
postMessage = jest.fn().mockResolvedValue(true);
74+
const webview: Webview = {
75+
options: {},
76+
html: "",
77+
onDidReceiveMessage: (listener) => {
78+
onDidReceiveMessage = listener;
79+
return new DisposableObject();
80+
},
81+
postMessage,
82+
asWebviewUri: (uri: Uri) => uri,
83+
cspSource: "",
84+
};
85+
86+
const webviewView = mockedObject<WebviewView>({
87+
webview,
88+
onDidDispose: jest.fn(),
89+
});
90+
91+
viewProvider.resolveWebviewView(
92+
webviewView,
93+
mockedObject<WebviewViewResolveContext>({}),
94+
new CancellationTokenSource().token,
95+
);
96+
97+
expect(onDidReceiveMessage).toBeDefined();
98+
});
99+
100+
it("should load webview when no active DB", async () => {
101+
await onDidReceiveMessage({
102+
t: "viewLoaded",
103+
viewName: MethodModelingViewProvider.viewType,
104+
});
105+
106+
expect(postMessage).toHaveBeenCalledTimes(1);
107+
expect(postMessage).toHaveBeenCalledWith({
108+
t: "setMethodModelingPanelViewState",
109+
viewState: {
110+
language: undefined,
111+
modelConfig: {
112+
showTypeModels: true,
113+
},
114+
},
115+
});
116+
});
117+
118+
it("should load webview when active DB but no selected method", async () => {
119+
const dbModelingState = mockedObject<DbModelingState>({
120+
databaseItem: mockDatabaseItem({
121+
language: "java",
122+
}),
123+
});
124+
getStateForActiveDb.mockReturnValue(dbModelingState);
125+
126+
await onDidReceiveMessage({
127+
t: "viewLoaded",
128+
viewName: MethodModelingViewProvider.viewType,
129+
});
130+
131+
expect(postMessage).toHaveBeenCalledTimes(3);
132+
expect(postMessage).toHaveBeenNthCalledWith(1, {
133+
t: "setMethodModelingPanelViewState",
134+
viewState: {
135+
language: undefined,
136+
modelConfig: {
137+
showTypeModels: true,
138+
},
139+
},
140+
});
141+
expect(postMessage).toHaveBeenNthCalledWith(2, {
142+
t: "setInModelingMode",
143+
inModelingMode: true,
144+
});
145+
expect(postMessage).toHaveBeenNthCalledWith(3, {
146+
t: "setMethodModelingPanelViewState",
147+
viewState: {
148+
language: "java",
149+
modelConfig: {
150+
showTypeModels: true,
151+
},
152+
},
153+
});
154+
});
155+
156+
it("should load webview when active DB and a selected method", async () => {
157+
const dbModelingState = mockedObject<DbModelingState>({
158+
databaseItem: mockDatabaseItem({
159+
language: "java",
160+
}),
161+
});
162+
getStateForActiveDb.mockReturnValue(dbModelingState);
163+
164+
const selectedMethodDetails: SelectedMethodDetails = {
165+
databaseItem: dbModelingState.databaseItem,
166+
method: createMethod(),
167+
usage: createUsage(),
168+
modeledMethods: [],
169+
isModified: false,
170+
isInProgress: false,
171+
processedByAutoModel: false,
172+
};
173+
getSelectedMethodDetails.mockReturnValue(selectedMethodDetails);
174+
175+
await onDidReceiveMessage({
176+
t: "viewLoaded",
177+
viewName: MethodModelingViewProvider.viewType,
178+
});
179+
180+
expect(postMessage).toHaveBeenCalledTimes(4);
181+
expect(postMessage).toHaveBeenNthCalledWith(1, {
182+
t: "setMethodModelingPanelViewState",
183+
viewState: {
184+
language: undefined,
185+
modelConfig: {
186+
showTypeModels: true,
187+
},
188+
},
189+
});
190+
expect(postMessage).toHaveBeenNthCalledWith(2, {
191+
t: "setInModelingMode",
192+
inModelingMode: true,
193+
});
194+
expect(postMessage).toHaveBeenNthCalledWith(3, {
195+
t: "setMethodModelingPanelViewState",
196+
viewState: {
197+
language: "java",
198+
modelConfig: {
199+
showTypeModels: true,
200+
},
201+
},
202+
});
203+
expect(postMessage).toHaveBeenNthCalledWith(4, {
204+
t: "setSelectedMethod",
205+
method: selectedMethodDetails.method,
206+
modeledMethods: selectedMethodDetails.modeledMethods,
207+
isModified: selectedMethodDetails.isModified,
208+
isInProgress: selectedMethodDetails.isInProgress,
209+
processedByAutoModel: selectedMethodDetails.processedByAutoModel,
210+
});
211+
});
212+
});

0 commit comments

Comments
 (0)