test: add test case for device model manager (#923)

- add example of mocking class from other module
- add test case for "create interface/capability model"
- add test case for UI interaction
This commit is contained in:
Eric Chen 2020-02-21 17:03:29 +08:00 коммит произвёл GitHub
Родитель 27e419c0a4
Коммит d5d02d60be
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
6 изменённых файлов: 198 добавлений и 13 удалений

Просмотреть файл

@ -1,16 +1,60 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
const OutputChannel = {
appendLine: jest.fn(),
show: jest.fn(),
dispose: jest.fn()
};
const ExtensionContext = {
asAbsolutePath: jest.fn()
};
const Uri = {
fsPath: "defaultPath",
file: jest.fn()
};
const WorkspaceFolder = {
uri: Uri
};
const QuickPickOptions = {};
const QuickPickItem = {};
const OpenDialogOptions = {};
const window = {
createOutputChannel: jest.fn(() => OutputChannel)
createOutputChannel: jest.fn(() => OutputChannel),
showQuickPick: jest.fn(items => items[0]),
showOpenDialog: jest.fn(),
showTextDocument: jest.fn(),
showInformationMessage: jest.fn(),
showWarningMessage: jest.fn(),
showErrorMessage: jest.fn()
};
const commands = {
executeCommand: jest.fn()
};
const workspace = {
workspaceFolders: undefined
};
const vscode = {
OutputChannel,
ExtensionContext,
Uri,
WorkspaceFolder,
QuickPickOptions,
QuickPickItem,
OpenDialogOptions,
window,
OutputChannel
commands,
workspace
};
module.exports = vscode;

Просмотреть файл

@ -1,5 +1,5 @@
module.exports = {
moduleFileExtensions: ["js", "ts"],
moduleFileExtensions: ["ts", "js"],
transform: {
"\\.ts$": "ts-jest"
},

Просмотреть файл

@ -93,6 +93,7 @@ function initCommand(
context.subscriptions.push(vscode.commands.registerCommand(command, callback));
}
// DigitalTwin extension part
function initIntelliSense(context: vscode.ExtensionContext): void {
// init DigitalTwin graph
IntelliSenseUtility.initGraph(context);
@ -195,7 +196,7 @@ function initDigitalTwinCommand(
)
);
}
// DigitalTwin extension part
function initDigitalTwin(context: vscode.ExtensionContext, outputChannel: vscode.OutputChannel): void {
const colorizedChannel = new ColorizedChannel(Constants.CHANNEL_NAME);
context.subscriptions.push(colorizedChannel);

Просмотреть файл

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { ColorizedChannel } from "../../src/DigitalTwin/pnp/src/common/colorizedChannel";
import { Constants } from "../../src/DigitalTwin/pnp/src/common/constants";
@ -9,7 +12,7 @@ describe("Colorized channel", () => {
const message = "mock";
afterEach(() => {
vscode.OutputChannel.appendLine.mockReset();
vscode.OutputChannel.appendLine.mockClear();
});
test("format success message", () => {
@ -22,41 +25,41 @@ describe("Colorized channel", () => {
test("print operation start", () => {
channel.start(operation);
expect(vscode.OutputChannel.appendLine).toBeCalledWith("[Start] Test");
expect(vscode.OutputChannel.appendLine).toHaveBeenCalledWith("[Start] Test");
});
test("print operation successfully end", () => {
channel.end(operation, Constants.DEVICE_MODEL_COMPONENT);
expect(vscode.OutputChannel.appendLine).toBeCalledWith("[Done][Device Model] Test successfully");
expect(vscode.OutputChannel.appendLine).toHaveBeenCalledWith("[Done][Device Model] Test successfully");
});
test("print info message", () => {
channel.info(operation);
expect(vscode.OutputChannel.appendLine).toBeCalledWith("Test");
expect(vscode.OutputChannel.appendLine).toHaveBeenCalledWith("Test");
});
test("print warn message", () => {
channel.warn(operation);
expect(vscode.OutputChannel.appendLine).toBeCalledWith("[Warn] Test");
expect(vscode.OutputChannel.appendLine).toHaveBeenCalledWith("[Warn] Test");
});
test("print error message", () => {
channel.error(message);
expect(vscode.OutputChannel.appendLine).toBeCalledWith("[Error] mock");
expect(vscode.OutputChannel.appendLine).toHaveBeenCalledWith("[Error] mock");
});
test("print operation fail to end", () => {
channel.error(operation, Constants.MODEL_REPOSITORY_COMPONENT, new Error(message));
expect(vscode.OutputChannel.appendLine).toBeCalledWith("[Error][Model Repository] Fail to test. Error: mock");
expect(vscode.OutputChannel.appendLine).toHaveBeenCalledWith("[Error][Model Repository] Fail to test. Error: mock");
});
test("show channel", () => {
channel.show();
expect(vscode.OutputChannel.show).toBeCalled();
expect(vscode.OutputChannel.show).toHaveBeenCalled();
});
test("dispose channel", () => {
channel.dispose();
expect(vscode.OutputChannel.dispose).toBeCalled();
expect(vscode.OutputChannel.dispose).toHaveBeenCalled();
});
});

Просмотреть файл

@ -0,0 +1,45 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import * as path from "path";
import { ColorizedChannel } from "../../src/DigitalTwin/pnp/src/common/colorizedChannel";
import { Constants } from "../../src/DigitalTwin/pnp/src/common/constants";
import { ProcessError } from "../../src/DigitalTwin/pnp/src/common/processError";
import { Utility } from "../../src/DigitalTwin/pnp/src/common/utility";
import { DeviceModelManager, ModelType } from "../../src/DigitalTwin/pnp/src/deviceModel/deviceModelManager";
import { UI } from "../../src/DigitalTwin/pnp/src/view/ui";
const vscode = require("../../__mocks__/vscode");
jest.mock("../../src/DigitalTwin/pnp/src/common/colorizedChannel");
jest.mock("../../src/DigitalTwin/pnp/src/common/utility");
jest.mock("../../src/DigitalTwin/pnp/src/view/ui");
describe("Device model manager", () => {
const context = vscode.ExtensionContext;
const channel = new ColorizedChannel(Constants.CHANNEL_NAME);
const manager = new DeviceModelManager(context, channel);
UI.selectRootFolder = jest.fn().mockResolvedValue("root");
UI.inputModelName = jest.fn().mockResolvedValue("test");
test("create interface successfully", async () => {
await manager.createModel(ModelType.Interface);
expect(UI.openAndShowTextDocument).toHaveBeenCalledWith(path.join("root", "test.interface.json"));
});
test("create interface with error", async () => {
Utility.createFileFromTemplate = jest.fn().mockRejectedValueOnce(new Error());
await expect(manager.createModel(ModelType.Interface)).rejects.toThrow(ProcessError);
});
test("create capability model successfully", async () => {
await manager.createModel(ModelType.CapabilityModel);
expect(UI.openAndShowTextDocument).toHaveBeenCalledWith(path.join("root", "test.capabilitymodel.json"));
});
test("create capability model with error", async () => {
Utility.createFileFromTemplate = jest.fn().mockRejectedValueOnce(new Error());
await expect(manager.createModel(ModelType.CapabilityModel)).rejects.toThrow(ProcessError);
});
});

Просмотреть файл

@ -0,0 +1,92 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { UI, MessageType } from "../../src/DigitalTwin/pnp/src/view/ui";
import { UIConstants } from "../../src/DigitalTwin/pnp/src/view/uiConstants";
import { Constants } from "../../src/DigitalTwin/pnp/src/common/constants";
import { UserCancelledError } from "../../src/DigitalTwin/pnp/src/common/userCancelledError";
const vscode = require("../../__mocks__/vscode");
describe("UI", () => {
const label = "label";
const defaultPath = "defaultPath";
const secondPath = "secondPath";
const browseQuickPickItem = {
label: UIConstants.BROWSE_LABEL,
description: Constants.EMPTY_STRING
};
const quickPickOptions = {
placeHolder: label,
ignoreFocusOut: true
};
const secondUri = {
fsPath: secondPath
};
afterEach(() => {
vscode.workspace.workspaceFolders = undefined;
});
test("open and show text document", async () => {
await UI.openAndShowTextDocument(defaultPath);
expect(vscode.commands.executeCommand).toHaveBeenCalled();
expect(vscode.window.showTextDocument).toHaveBeenCalled();
});
test("show noticifation with info/warn/error", () => {
UI.showNotification(MessageType.Info, label);
expect(vscode.window.showInformationMessage).toHaveBeenCalled();
UI.showNotification(MessageType.Warn, label);
expect(vscode.window.showWarningMessage).toHaveBeenCalled();
UI.showNotification(MessageType.Error, label);
expect(vscode.window.showErrorMessage).toHaveBeenCalled();
});
test("select root folder when only one folder is opened", async () => {
vscode.workspace.workspaceFolders = [vscode.WorkspaceFolder];
const folder: string = await UI.selectRootFolder(label);
expect(folder).toBe("defaultPath");
});
test("select root folder when no folder is opened", async () => {
vscode.window.showOpenDialog = jest.fn().mockResolvedValueOnce([secondUri]);
const folder: string = await UI.selectRootFolder(label);
expect(vscode.window.showQuickPick).toHaveBeenCalledWith([browseQuickPickItem], quickPickOptions);
expect(vscode.window.showOpenDialog).toHaveBeenCalledWith({
openLabel: label,
canSelectFiles: false,
canSelectFolders: true,
canSelectMany: false
});
expect(folder).toBe("secondPath");
});
test("select root folder when multiple folders are opened", async () => {
vscode.workspace.workspaceFolders = [vscode.WorkspaceFolder, { uri: secondUri }];
const folder: string = await UI.selectRootFolder(label);
expect(vscode.window.showQuickPick).toHaveBeenCalledWith(
[
{
label: defaultPath,
description: defaultPath
},
{
label: secondPath,
description: secondPath
},
browseQuickPickItem
],
quickPickOptions
);
expect(folder).toBe("defaultPath");
});
test("show quick pick with cancellation", async () => {
await expect(UI.showQuickPick(label, [])).rejects.toThrow(UserCancelledError);
});
test("show open dialog with cancellation", async () => {
await expect(UI.showOpenDialog(label)).rejects.toThrow(UserCancelledError);
});
});