Merge pull request #3444 from github/robertbrignull/start-modeling-test

Add tests of MethodModelingViewProvider.viewLoaded
This commit is contained in:
Robert
2024-03-11 11:18:56 +00:00
committed by GitHub
5 changed files with 216 additions and 14 deletions

View File

@@ -1,9 +1,4 @@
import type {
CancellationToken,
WebviewView,
WebviewViewProvider,
WebviewViewResolveContext,
} from "vscode";
import type { WebviewView, WebviewViewProvider } from "vscode";
import { Uri } from "vscode";
import type { WebviewKind, WebviewMessage } from "./webview-html";
import { getHtmlForWebview } from "./webview-html";
@@ -28,11 +23,7 @@ export abstract class AbstractWebviewViewProvider<
* This is called when a view first becomes visible. This may happen when the view is
* first loaded or when the user hides and then shows a view again.
*/
public resolveWebviewView(
webviewView: WebviewView,
_context: WebviewViewResolveContext,
_token: CancellationToken,
) {
public resolveWebviewView(webviewView: WebviewView) {
webviewView.webview.options = {
enableScripts: true,
localResourceRoots: [Uri.file(this.app.extensionPath)],

View File

@@ -22,7 +22,7 @@ interface InternalDbModelingState {
modelEvaluationRun: ModelEvaluationRun | undefined;
}
interface DbModelingState {
export interface DbModelingState {
readonly databaseItem: DatabaseItem;
readonly methods: readonly Method[];
readonly hideModeledMethods: boolean;
@@ -36,7 +36,7 @@ interface DbModelingState {
readonly modelEvaluationRun: ModelEvaluationRun | undefined;
}
interface SelectedMethodDetails {
export interface SelectedMethodDetails {
readonly databaseItem: DatabaseItem;
readonly method: Method;
readonly usage: Usage | undefined;

View File

@@ -3,6 +3,7 @@ import type { ModelingEvents } from "../../../src/model-editor/modeling-events";
export function createMockModelingEvents({
onActiveDbChanged = jest.fn(),
onDbOpened = jest.fn(),
onDbClosed = jest.fn(),
onSelectedMethodChanged = jest.fn(),
onMethodsChanged = jest.fn(),
@@ -16,6 +17,7 @@ export function createMockModelingEvents({
onModelEvaluationRunChanged = jest.fn(),
}: {
onActiveDbChanged?: ModelingEvents["onActiveDbChanged"];
onDbOpened?: ModelingEvents["onDbOpened"];
onDbClosed?: ModelingEvents["onDbClosed"];
onSelectedMethodChanged?: ModelingEvents["onSelectedMethodChanged"];
onMethodsChanged?: ModelingEvents["onMethodsChanged"];
@@ -30,6 +32,7 @@ export function createMockModelingEvents({
} = {}): ModelingEvents {
return mockedObject<ModelingEvents>({
onActiveDbChanged,
onDbOpened,
onDbClosed,
onSelectedMethodChanged,
onMethodsChanged,

View File

@@ -3,17 +3,20 @@ import type { ModelingStore } from "../../../src/model-editor/modeling-store";
export function createMockModelingStore({
initializeStateForDb = jest.fn(),
getStateForActiveDb = jest.fn(),
getStateForActiveDb = jest.fn().mockReturnValue(undefined),
getSelectedMethodDetails = jest.fn().mockReturnValue(undefined),
getModelEvaluationRun = jest.fn(),
updateModelEvaluationRun = jest.fn(),
}: {
initializeStateForDb?: ModelingStore["initializeStateForDb"];
getStateForActiveDb?: ModelingStore["getStateForActiveDb"];
getSelectedMethodDetails?: ModelingStore["getSelectedMethodDetails"];
getModelEvaluationRun?: ModelingStore["getModelEvaluationRun"];
updateModelEvaluationRun?: ModelingStore["updateModelEvaluationRun"];
} = {}): ModelingStore {
return mockedObject<ModelingStore>({
initializeStateForDb,
getSelectedMethodDetails,
getStateForActiveDb,
getModelEvaluationRun,
updateModelEvaluationRun,

View File

@@ -0,0 +1,205 @@
import type { Uri, Webview, WebviewView } from "vscode";
import { EventEmitter } from "vscode";
import type { ModelConfigListener } from "../../../../../src/config";
import { MethodModelingViewProvider } from "../../../../../src/model-editor/method-modeling/method-modeling-view-provider";
import { createMockApp } from "../../../../__mocks__/appMock";
import { createMockModelingEvents } from "../../../../__mocks__/model-editor/modelingEventsMock";
import { createMockModelingStore } from "../../../../__mocks__/model-editor/modelingStoreMock";
import { mockedObject } from "../../../../mocked-object";
import type { FromMethodModelingMessage } from "../../../../../src/common/interface-types";
import { DisposableObject } from "../../../../../src/common/disposable-object";
import type { ModelingEvents } from "../../../../../src/model-editor/modeling-events";
import type {
DbModelingState,
ModelingStore,
SelectedMethodDetails,
} from "../../../../../src/model-editor/modeling-store";
import { mockDatabaseItem } from "../../../utils/mocking.helpers";
import {
createMethod,
createUsage,
} from "../../../../factories/model-editor/method-factories";
describe("method modeling view provider", () => {
// Modeling store
let getStateForActiveDb: jest.MockedFunction<
ModelingStore["getStateForActiveDb"]
>;
let getSelectedMethodDetails: jest.MockedFunction<
ModelingStore["getSelectedMethodDetails"]
>;
// Modeling events
let selectedMethodChangedEventEmitter: ModelingEvents["onSelectedMethodChangedEventEmitter"];
let dbOpenedEventEmitter: ModelingEvents["onDbOpenedEventEmitter"];
// View provider
let viewProvider: MethodModelingViewProvider;
let onDidReceiveMessage: (msg: FromMethodModelingMessage) => Promise<void>;
let postMessage: (message: unknown) => Promise<boolean>;
beforeEach(async () => {
const app = createMockApp({});
getStateForActiveDb = jest.fn().mockReturnValue(undefined);
getSelectedMethodDetails = jest.fn().mockReturnValue(undefined);
const modelingStore = createMockModelingStore({
getStateForActiveDb,
getSelectedMethodDetails,
});
selectedMethodChangedEventEmitter = new EventEmitter();
dbOpenedEventEmitter = new EventEmitter();
const modelingEvents = createMockModelingEvents({
onSelectedMethodChanged: selectedMethodChangedEventEmitter.event,
onDbOpened: dbOpenedEventEmitter.event,
});
const modelConfigListener = mockedObject<ModelConfigListener>({
showTypeModels: true,
onDidChangeConfiguration: jest.fn(),
});
viewProvider = new MethodModelingViewProvider(
app,
modelingStore,
modelingEvents,
modelConfigListener,
);
postMessage = jest.fn().mockResolvedValue(true);
const webview: Webview = {
options: {},
html: "",
onDidReceiveMessage: (listener) => {
onDidReceiveMessage = listener;
return new DisposableObject();
},
postMessage,
asWebviewUri: (uri: Uri) => uri,
cspSource: "",
};
const webviewView = mockedObject<WebviewView>({
webview,
onDidDispose: jest.fn(),
});
viewProvider.resolveWebviewView(webviewView);
expect(onDidReceiveMessage).toBeDefined();
});
it("should load webview when no active DB", async () => {
await onDidReceiveMessage({
t: "viewLoaded",
viewName: MethodModelingViewProvider.viewType,
});
expect(postMessage).toHaveBeenCalledTimes(1);
expect(postMessage).toHaveBeenCalledWith({
t: "setMethodModelingPanelViewState",
viewState: {
language: undefined,
modelConfig: {
showTypeModels: true,
},
},
});
});
it("should load webview when active DB but no selected method", async () => {
const dbModelingState = mockedObject<DbModelingState>({
databaseItem: mockDatabaseItem({
language: "java",
}),
});
getStateForActiveDb.mockReturnValue(dbModelingState);
await onDidReceiveMessage({
t: "viewLoaded",
viewName: MethodModelingViewProvider.viewType,
});
expect(postMessage).toHaveBeenCalledTimes(3);
expect(postMessage).toHaveBeenNthCalledWith(1, {
t: "setMethodModelingPanelViewState",
viewState: {
language: undefined,
modelConfig: {
showTypeModels: true,
},
},
});
expect(postMessage).toHaveBeenNthCalledWith(2, {
t: "setInModelingMode",
inModelingMode: true,
});
expect(postMessage).toHaveBeenNthCalledWith(3, {
t: "setMethodModelingPanelViewState",
viewState: {
language: "java",
modelConfig: {
showTypeModels: true,
},
},
});
});
it("should load webview when active DB and a selected method", async () => {
const dbModelingState = mockedObject<DbModelingState>({
databaseItem: mockDatabaseItem({
language: "java",
}),
});
getStateForActiveDb.mockReturnValue(dbModelingState);
const selectedMethodDetails: SelectedMethodDetails = {
databaseItem: dbModelingState.databaseItem,
method: createMethod(),
usage: createUsage(),
modeledMethods: [],
isModified: false,
isInProgress: false,
processedByAutoModel: false,
};
getSelectedMethodDetails.mockReturnValue(selectedMethodDetails);
await onDidReceiveMessage({
t: "viewLoaded",
viewName: MethodModelingViewProvider.viewType,
});
expect(postMessage).toHaveBeenCalledTimes(4);
expect(postMessage).toHaveBeenNthCalledWith(1, {
t: "setMethodModelingPanelViewState",
viewState: {
language: undefined,
modelConfig: {
showTypeModels: true,
},
},
});
expect(postMessage).toHaveBeenNthCalledWith(2, {
t: "setInModelingMode",
inModelingMode: true,
});
expect(postMessage).toHaveBeenNthCalledWith(3, {
t: "setMethodModelingPanelViewState",
viewState: {
language: "java",
modelConfig: {
showTypeModels: true,
},
},
});
expect(postMessage).toHaveBeenNthCalledWith(4, {
t: "setSelectedMethod",
method: selectedMethodDetails.method,
modeledMethods: selectedMethodDetails.modeledMethods,
isModified: selectedMethodDetails.isModified,
isInProgress: selectedMethodDetails.isInProgress,
processedByAutoModel: selectedMethodDetails.processedByAutoModel,
});
});
});