Skip to content

Commit

Permalink
Add tests vscode
Browse files Browse the repository at this point in the history
  • Loading branch information
koenekelschot committed Apr 18, 2020
1 parent c7cfa96 commit c610373
Show file tree
Hide file tree
Showing 7 changed files with 305 additions and 1,130 deletions.
1,169 changes: 87 additions & 1,082 deletions package-lock.json

Large diffs are not rendered by default.

19 changes: 3 additions & 16 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,42 +13,29 @@
"vscode/publish": "npm run vscode/pre-publish && cd dist/vscode && vsce package --out ../../releases/vscode",
"test": "jest --coverage"
},
"babel": {
"plugins": [
"@babel/plugin-proposal-class-properties"
],
"presets": [
"@babel/preset-env",
"@babel/preset-typescript"
]
},
"jest": {
"testRegex": "/test/.*\\.test\\.(js|jsx|ts)$",
"transform": {
"^.+\\.(js|jsx|ts)$": "babel-jest"
}
"testMatch": null,
"preset": "ts-jest"
},
"dependencies": {
"js-yaml": "^3.5.5",
"jsonschema": "1.2.6"
},
"devDependencies": {
"@babel/plugin-proposal-class-properties": "7.8.3",
"@babel/preset-env": "7.9.5",
"@babel/preset-typescript": "7.9.0",
"@types/chrome": "0.0.100",
"@types/jest": "25.2.1",
"@types/js-yaml": "^3.5.5",
"@types/node": "^12.11.7",
"@types/vscode": "^1.43.0",
"@typescript-eslint/parser": "^2.18.0",
"@typescript-eslint/eslint-plugin": "^2.18.0",
"babel-jest": "25.2.6",
"clean-webpack-plugin": "^3.0.0",
"copy-webpack-plugin": "^5.1.1",
"eslint": "^6.8.0",
"jest": "25.2.7",
"ts-loader": "^6.2.1",
"ts-jest": "25.3.1",
"typescript": "^3.7.5",
"vsce": "1.74.0",
"webpack": "~4.42.0",
Expand Down
11 changes: 4 additions & 7 deletions src/parser.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IMonitorValidator, MonitorValidator } from "./monitorValidator";
import { IMonitorValidator } from "./monitorValidator";
import { sanitize } from "./sanitizer";
import { toYaml } from "./converter";

Expand All @@ -9,13 +9,10 @@ export interface IParser {
}

export class Parser implements IParser {
private indentSize: number = 2;
private onValidationErrors: ((errors: string[]) => void) | undefined;
private validator: IMonitorValidator;
protected indentSize: number = 2;
protected onValidationErrors: ((errors: string[]) => void) | undefined;

public constructor(validator: IMonitorValidator) {
this.validator = validator;
};
public constructor(private readonly validator: IMonitorValidator) { };

public setIndentSize(indentSize: number): void {
this.indentSize = indentSize;
Expand Down
39 changes: 21 additions & 18 deletions src/vscode/extension.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,34 @@
import { commands, env, ExtensionContext, Range, TextEditor, window } from 'vscode';
import { commands, env, ExtensionContext, Range, TextEditor, window, TextEditorOptions, TextEdit, TextEditorEdit } from 'vscode';
import { IParser, Parser } from "../parser";
import { MonitorValidator } from '../monitorValidator';

let parser: IParser;
export const ValidationErrorMessage = "Copied data is not a valid monitor";
export const ConversionErrorMessage = "Could not convert monitor data to YAML";

export function activate(context: ExtensionContext) {
parser = new Parser(new MonitorValidator());
export function activate(context: ExtensionContext, parser: IParser = new Parser(new MonitorValidator())): void {
parser.setOnValidationErrors((errors: string[]) => {
errors.forEach(err => console.error(err));
window.showErrorMessage("Copied data is not a valid monitor");
window.showErrorMessage(ValidationErrorMessage);
});

let pasteCommand = commands.registerTextEditorCommand("pasteDatadogAsYAML", editor =>
pasteDatadogAsYAML(editor)
);

const registerCallback = (editor: TextEditor) => pasteDatadogAsYAML(editor, parser);
const pasteCommand = commands.registerTextEditorCommand(pasteDatadogAsYAML.name, registerCallback);
context.subscriptions.push(pasteCommand);
}

export function deactivate() {}
};

export async function pasteDatadogAsYAML(editor: TextEditor) {
export function deactivate(context: ExtensionContext): void {
context.subscriptions.forEach(subscription => subscription.dispose());
};

export async function pasteDatadogAsYAML(editor: TextEditor, parser: IParser): Promise<void> {
if (editor.document.languageId !== 'yaml') {
return;
}

configureIndentSize(parser, editor.options);

try {
const indentSize = editor.options.insertSpaces ? editor.options.tabSize as number : 2;
const clipboardContent = await env.clipboard.readText();

parser.setIndentSize(indentSize);
const converted = parser.parse(clipboardContent);

if (converted) {
Expand All @@ -44,6 +42,11 @@ export async function pasteDatadogAsYAML(editor: TextEditor) {
}
} catch (e) {
console.error(e);
window.showErrorMessage("Could not convert monitor data to YAML");
window.showErrorMessage(ConversionErrorMessage);
}
}
};

function configureIndentSize(parser: IParser, options: TextEditorOptions) {
const indentSize = options.insertSpaces ? options.tabSize as number : 2;
parser.setIndentSize(indentSize);
};
10 changes: 5 additions & 5 deletions test/parser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ jest.mock("../src/sanitizer");
(sanitize as jest.Mock).mockImplementation((input) => input);

let parser: Parser;
let validatorMock: MonitorValidatorMock;
let validatorMock: MockMonitorValidator;
let validationErrors: string[];
let validationCallback = (errors: string[]) => validationErrors = errors;

describe('parse', () => {

beforeEach(() => {
validatorMock = new MonitorValidatorMock();
validatorMock = new MockMonitorValidator();
validatorMock.isValid = true;
validationErrors = [];
parser = new Parser(validatorMock);
Expand Down Expand Up @@ -75,7 +75,7 @@ describe('parse', () => {

describe('setIndentSize', () => {
it('should set the indent size', () => {
validatorMock = new MonitorValidatorMock();
validatorMock = new MockMonitorValidator();
validatorMock.isValid = true;
parser = new Parser(validatorMock);

Expand All @@ -88,7 +88,7 @@ describe('setIndentSize', () => {

describe('setOnValidationErrors', () => {
it ('should set the onValidationErrors callback', () => {
validatorMock = new MonitorValidatorMock();
validatorMock = new MockMonitorValidator();
validatorMock.isValid = false;
parser = new Parser(validatorMock);

Expand All @@ -101,7 +101,7 @@ describe('setOnValidationErrors', () => {
});
});

class MonitorValidatorMock implements IMonitorValidator {
class MockMonitorValidator implements IMonitorValidator {
private validated = false;

public get hasValidated(): boolean {
Expand Down
183 changes: 183 additions & 0 deletions test/vscode/extension.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
import { ExtensionContext, commands, Disposable, env, TextEditor, window } from 'vscode';
import { activate, pasteDatadogAsYAML, deactivate, ConversionErrorMessage, ValidationErrorMessage } from '../../src/vscode/extension';
import { Parser } from '../../src/parser';
import { MonitorValidator } from '../../src/monitorValidator';

jest.mock('vscode', () => {
return {
commands: {
registerTextEditorCommand: jest.fn()
},
env: {
clipboard: {
readText: jest.fn().mockImplementation(() => { return "clipboard data"; })
}
},
window: {
showErrorMessage: jest.fn()
}
}
}, {virtual: true});

let mockContext: ExtensionContext;
let mockEditor: TextEditor;
let parser: MockParser;

beforeEach(() => {
mockContext = {
subscriptions: Array<Disposable>()
} as ExtensionContext;
mockEditor = ({
document: {
languageId: "yaml"
},
options: {
insertSpaces: false
},
edit: jest.fn()
} as unknown) as TextEditor;
parser = new MockParser();

jest.clearAllMocks();
jest.spyOn(console, 'error').mockImplementation(() => {});
});

describe('activate', () => {
it('should register the text editor command', () => {
activate(mockContext);

expect(commands.registerTextEditorCommand).toHaveBeenCalledWith(pasteDatadogAsYAML.name, expect.anything());
expect(mockContext.subscriptions.length).toBe(1);
});

it('should call setOnValidationErrors on parser', () => {
activate(mockContext, parser);

expect(parser.onValidationErrorsSet).toBe(true);
});
});

describe('deactivate', () => {
it('should dispose subscriptions', () => {
const disposable = { dispose: jest.fn() };
mockContext.subscriptions.push(disposable);

deactivate(mockContext);

expect(disposable.dispose).toHaveBeenCalled();
});
});

describe('pasteDatadogAsYAML', () => {
it('should do nothing when editor language is not yaml', async () => {
const editor = {
document: {
languageId: "not-yaml"
}
} as TextEditor;

await pasteDatadogAsYAML(editor, parser);

expect(parser.indentSizeSet).toBe(false);
expect(env.clipboard.readText).not.toHaveBeenCalled();
expect(parser.parsedJson).toBeNull();
});

describe('set indent size', () => {
it('should set the indent size when configured', async () => {
const editor = {
document: {
languageId: "yaml"
},
options: {
insertSpaces: true,
tabSize: 6
}
} as TextEditor;
await pasteDatadogAsYAML(editor, parser);

expect(parser.indentSizeSet).toBe(true);
});

it('should set a default indent size when not configured', async () => {
await pasteDatadogAsYAML(mockEditor, parser);

expect(parser.indentSizeSet).toBe(true);
});
});

it('should read the clipboard contents', async () => {
await pasteDatadogAsYAML(mockEditor, parser);

expect(env.clipboard.readText).toHaveBeenCalled();
});

it('should parse the clipboard contents', async () => {
await pasteDatadogAsYAML(mockEditor, parser);

expect(parser.parsedJson).not.toBeNull();
});

describe('valid monitor data', () => {
it('should paste yaml', async () => {
parser.isValid = true;

await pasteDatadogAsYAML(mockEditor, parser);

expect(mockEditor.edit).toHaveBeenCalled();
});
});

describe('invalid monitor data', () => {
it('should show message when input is not JSON', async () => {
(env.clipboard.readText as jest.Mock).mockImplementationOnce(() => {
return "not json";
});

await pasteDatadogAsYAML(mockEditor, parser);

expect(window.showErrorMessage).toBeCalledWith(ConversionErrorMessage);
});

it('should show message when input is not a valid monitor', async () => {
(env.clipboard.readText as jest.Mock).mockImplementationOnce(() => {
return "{}";
});

activate(mockContext, parser);
await pasteDatadogAsYAML(mockEditor, parser);

expect(window.showErrorMessage).toBeCalledWith(ValidationErrorMessage);
});
});
});

class MockParser extends Parser {
private parsed: string | null = null;
public isValid: boolean = false;

public get indentSizeSet(): boolean {
return this.indentSize !== 0;
}

public get onValidationErrorsSet(): boolean {
return this.onValidationErrors !== undefined;
}

public get parsedJson(): string | null {
return this.parsed;
}

public constructor() {
super(new MonitorValidator());
this.indentSize = 0;
}

public parse(json: string): string | null {
this.parsed = json;
if (this.isValid) {
return json;
}
return super.parse(json);
}
}
4 changes: 2 additions & 2 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"es6"
],
"sourceMap": true,
"rootDir": "src",
"rootDir": ".",
"strict": true,
"esModuleInterop": true,
"noImplicitReturns": true,
Expand All @@ -19,6 +19,6 @@
},
"exclude": [
"node_modules",
".vscode-test"
"test"
]
}

0 comments on commit c610373

Please sign in to comment.