Commit 38f794b9 authored by Denys Mishunov's avatar Denys Mishunov

Refactored the spec to be closer to integration

A lot of mocks have been removed
parent fcda2e70
/* eslint-disable max-classes-per-file */ /* eslint-disable max-classes-per-file */
import { editor as monacoEditor, languages as monacoLanguages, Uri } from 'monaco-editor'; import { editor as monacoEditor, languages as monacoLanguages } from 'monaco-editor';
import waitForPromises from 'helpers/wait_for_promises'; import waitForPromises from 'helpers/wait_for_promises';
import { joinPaths } from '~/lib/utils/url_utility';
import EditorLite from '~/editor/editor_lite'; import EditorLite from '~/editor/editor_lite';
import { EditorLiteExtension } from '~/editor/extensions/editor_lite_extension_base'; import { EditorLiteExtension } from '~/editor/extensions/editor_lite_extension_base';
import { DEFAULT_THEME, themes } from '~/ide/lib/themes'; import { DEFAULT_THEME, themes } from '~/ide/lib/themes';
...@@ -8,7 +9,6 @@ import { ...@@ -8,7 +9,6 @@ import {
EDITOR_LITE_INSTANCE_ERROR_NO_EL, EDITOR_LITE_INSTANCE_ERROR_NO_EL,
URI_PREFIX, URI_PREFIX,
EDITOR_READY_EVENT, EDITOR_READY_EVENT,
EDITOR_TYPE_DIFF,
} from '~/editor/constants'; } from '~/editor/constants';
describe('Base editor', () => { describe('Base editor', () => {
...@@ -19,7 +19,7 @@ describe('Base editor', () => { ...@@ -19,7 +19,7 @@ describe('Base editor', () => {
const blobContent = 'Foo Bar'; const blobContent = 'Foo Bar';
const blobPath = 'test.md'; const blobPath = 'test.md';
const blobGlobalId = 'snippet_777'; const blobGlobalId = 'snippet_777';
const fakeModel = { foo: 'bar', dispose: jest.fn(), uri: { path: blobPath } }; const fakeModel = { foo: 'bar', dispose: jest.fn() };
beforeEach(() => { beforeEach(() => {
setFixtures('<div id="editor" data-editor-loading></div>'); setFixtures('<div id="editor" data-editor-loading></div>');
...@@ -36,7 +36,7 @@ describe('Base editor', () => { ...@@ -36,7 +36,7 @@ describe('Base editor', () => {
}); });
}); });
const createUri = (...paths) => Uri.file([URI_PREFIX, ...paths].join('/')); const uriFilePath = joinPaths('/', URI_PREFIX, blobGlobalId, blobPath);
it('initializes Editor with basic properties', () => { it('initializes Editor with basic properties', () => {
expect(editor).toBeDefined(); expect(editor).toBeDefined();
...@@ -52,37 +52,27 @@ describe('Base editor', () => { ...@@ -52,37 +52,27 @@ describe('Base editor', () => {
describe('instance of the Editor Lite', () => { describe('instance of the Editor Lite', () => {
let modelSpy; let modelSpy;
let instanceSpy; let instanceSpy;
let use; const setModel = jest.fn();
let setModel; const dispose = jest.fn();
let getModel; const mockModelReturn = (res = fakeModel) => {
let dispose; modelSpy = jest.spyOn(monacoEditor, 'createModel').mockImplementation(() => res);
let modelsStorage; };
let instanceCreateResponse; const mockDecorateInstance = (decorations) => {
jest.spyOn(EditorLite, 'decorateInstance').mockImplementation((inst) => {
return Object.assign(inst, decorations);
});
};
beforeEach(() => { beforeEach(() => {
setModel = jest.fn(); modelSpy = jest.spyOn(monacoEditor, 'createModel');
getModel = jest.fn();
dispose = jest.fn();
use = jest.fn();
modelsStorage = new Map();
modelSpy = jest.spyOn(monacoEditor, 'createModel').mockImplementation(() => fakeModel);
jest.spyOn(monacoEditor, 'getModel').mockImplementation((uri) => {
return modelsStorage.get(uri.path);
});
instanceCreateResponse = {
setModel,
getModel,
dispose,
use,
onDidDispose: jest.fn(),
};
}); });
describe('instance of the Code Editor', () => { describe('instance of the Code Editor', () => {
beforeEach(() => { beforeEach(() => {
instanceSpy = jest instanceSpy = jest.spyOn(monacoEditor, 'create');
.spyOn(monacoEditor, 'create') mockDecorateInstance({
.mockImplementation(() => instanceCreateResponse); setModel,
});
}); });
it('throws an error if no dom element is supplied', () => { it('throws an error if no dom element is supplied', () => {
...@@ -92,16 +82,19 @@ describe('Base editor', () => { ...@@ -92,16 +82,19 @@ describe('Base editor', () => {
expect(modelSpy).not.toHaveBeenCalled(); expect(modelSpy).not.toHaveBeenCalled();
expect(instanceSpy).not.toHaveBeenCalled(); expect(instanceSpy).not.toHaveBeenCalled();
expect(setModel).not.toHaveBeenCalled(); expect(EditorLite.decorateInstance).not.toHaveBeenCalled();
}); });
it('creates model to be supplied to Monaco editor', () => { it('creates model to be supplied to Monaco editor', () => {
mockModelReturn();
editor.createInstance(defaultArguments); editor.createInstance(defaultArguments);
expect(modelSpy).toHaveBeenCalledWith( expect(modelSpy).toHaveBeenCalledWith(
blobContent, blobContent,
undefined, undefined,
createUri(blobGlobalId, blobPath), expect.objectContaining({
path: uriFilePath,
}),
); );
expect(setModel).toHaveBeenCalledWith(fakeModel); expect(setModel).toHaveBeenCalledWith(fakeModel);
}); });
...@@ -112,17 +105,6 @@ describe('Base editor', () => { ...@@ -112,17 +105,6 @@ describe('Base editor', () => {
expect(setModel).not.toHaveBeenCalled(); expect(setModel).not.toHaveBeenCalled();
}); });
it('does not create a new model if a model for the path already exists', () => {
modelSpy = jest
.spyOn(monacoEditor, 'createModel')
.mockImplementation((content, lang, uri) => modelsStorage.set(uri.path, content));
const a = editor.createInstance(defaultArguments);
const b = editor.createInstance(defaultArguments);
expect(a).toBe(b);
expect(modelSpy).toHaveBeenCalledTimes(1);
});
it('initializes the instance on a supplied DOM node', () => { it('initializes the instance on a supplied DOM node', () => {
editor.createInstance({ el: editorEl }); editor.createInstance({ el: editorEl });
...@@ -130,13 +112,15 @@ describe('Base editor', () => { ...@@ -130,13 +112,15 @@ describe('Base editor', () => {
expect(instanceSpy).toHaveBeenCalledWith(editorEl, expect.anything()); expect(instanceSpy).toHaveBeenCalledWith(editorEl, expect.anything());
}); });
it('with blobGlobalId, creates model with id in uri', () => { it('with blobGlobalId, creates model with the id in uri', () => {
editor.createInstance(defaultArguments); editor.createInstance(defaultArguments);
expect(modelSpy).toHaveBeenCalledWith( expect(modelSpy).toHaveBeenCalledWith(
blobContent, blobContent,
undefined, undefined,
createUri(blobGlobalId, blobPath), expect.objectContaining({
path: uriFilePath,
}),
); );
}); });
...@@ -155,6 +139,9 @@ describe('Base editor', () => { ...@@ -155,6 +139,9 @@ describe('Base editor', () => {
}); });
it('disposes instance when the global editor is disposed', () => { it('disposes instance when the global editor is disposed', () => {
mockDecorateInstance({
dispose,
});
editor.createInstance(defaultArguments); editor.createInstance(defaultArguments);
expect(dispose).not.toHaveBeenCalled(); expect(dispose).not.toHaveBeenCalled();
...@@ -165,14 +152,14 @@ describe('Base editor', () => { ...@@ -165,14 +152,14 @@ describe('Base editor', () => {
}); });
it("removes the disposed instance from the global editor's storage and disposes the associated model", () => { it("removes the disposed instance from the global editor's storage and disposes the associated model", () => {
instanceCreateResponse.getModel = jest.fn().mockReturnValue(fakeModel); mockModelReturn();
instanceCreateResponse.getEditorType = jest.fn().mockReturnValue('code'); const instance = editor.createInstance(defaultArguments);
editor.createInstance(defaultArguments);
expect(editor.instances).toHaveLength(1); expect(editor.instances).toHaveLength(1);
expect(fakeModel.dispose).not.toHaveBeenCalled(); expect(fakeModel.dispose).not.toHaveBeenCalled();
EditorLite.onInstanceDisposal(editor, instanceCreateResponse); instance.dispose();
expect(editor.instances).toHaveLength(0); expect(editor.instances).toHaveLength(0);
expect(fakeModel.dispose).toHaveBeenCalled(); expect(fakeModel.dispose).toHaveBeenCalled();
}); });
...@@ -180,9 +167,10 @@ describe('Base editor', () => { ...@@ -180,9 +167,10 @@ describe('Base editor', () => {
describe('instance of the Diff Editor', () => { describe('instance of the Diff Editor', () => {
beforeEach(() => { beforeEach(() => {
instanceSpy = jest instanceSpy = jest.spyOn(monacoEditor, 'createDiffEditor');
.spyOn(monacoEditor, 'createDiffEditor') mockDecorateInstance({
.mockImplementation(() => instanceCreateResponse); setModel,
});
}); });
it('Diff Editor goes through the normal path of Code Editor just with the flag ON', () => { it('Diff Editor goes through the normal path of Code Editor just with the flag ON', () => {
...@@ -206,33 +194,42 @@ describe('Base editor', () => { ...@@ -206,33 +194,42 @@ describe('Base editor', () => {
it('creates correct model for the Diff Editor', () => { it('creates correct model for the Diff Editor', () => {
editor.createDiffInstance({ ...defaultArguments, blobOriginalContent }); editor.createDiffInstance({ ...defaultArguments, blobOriginalContent });
const uri = createUri(blobGlobalId, blobPath);
expect(modelSpy).toHaveBeenCalledTimes(2); expect(modelSpy).toHaveBeenCalledTimes(2);
expect(modelSpy.mock.calls[0]).toEqual([blobContent, undefined, uri]); expect(modelSpy.mock.calls[0]).toEqual([
blobContent,
undefined,
expect.objectContaining({
path: uriFilePath,
}),
]);
expect(modelSpy.mock.calls[1]).toEqual([blobOriginalContent, 'markdown']); expect(modelSpy.mock.calls[1]).toEqual([blobOriginalContent, 'markdown']);
expect(setModel).toHaveBeenCalledWith({ expect(setModel).toHaveBeenCalledWith(
original: expect.anything(), expect.objectContaining({
modified: fakeModel, original: expect.anything(),
}); modified: expect.anything(),
}),
);
}); });
it('correctly disposes the diff editor model', () => { it('correctly disposes the diff editor model', () => {
const modifiedModel = fakeModel; const modifiedModel = fakeModel;
const originalModel = { ...fakeModel }; const originalModel = { ...fakeModel };
instanceCreateResponse.getModel = jest.fn().mockReturnValue({ mockDecorateInstance({
original: originalModel, getModel: jest.fn().mockReturnValue({
modified: modifiedModel, original: originalModel,
modified: modifiedModel,
}),
}); });
instanceCreateResponse.getEditorType = jest.fn().mockReturnValue(EDITOR_TYPE_DIFF); const instance = editor.createDiffInstance({ ...defaultArguments, blobOriginalContent });
editor.createDiffInstance({ ...defaultArguments, blobOriginalContent });
expect(editor.instances).toHaveLength(1); expect(editor.instances).toHaveLength(1);
expect(originalModel.dispose).not.toHaveBeenCalled(); expect(originalModel.dispose).not.toHaveBeenCalled();
expect(modifiedModel.dispose).not.toHaveBeenCalled(); expect(modifiedModel.dispose).not.toHaveBeenCalled();
EditorLite.onInstanceDisposal(editor, instanceCreateResponse); instance.dispose();
expect(editor.instances).toHaveLength(0); expect(editor.instances).toHaveLength(0);
expect(originalModel.dispose).toHaveBeenCalled(); expect(originalModel.dispose).toHaveBeenCalled();
expect(modifiedModel.dispose).toHaveBeenCalled(); expect(modifiedModel.dispose).toHaveBeenCalled();
...@@ -293,6 +290,18 @@ describe('Base editor', () => { ...@@ -293,6 +290,18 @@ describe('Base editor', () => {
expect(model1).not.toEqual(model2); expect(model1).not.toEqual(model2);
}); });
it('does not create a new model if a model for the path & globalId combo already exists', () => {
const modelSpy = jest.spyOn(monacoEditor, 'createModel');
inst1 = editor.createInstance({ ...inst2Args, blobGlobalId });
inst2 = editor.createInstance({ ...inst2Args, el: editorEl1, blobGlobalId });
const model1 = inst1.getModel();
const model2 = inst2.getModel();
expect(modelSpy).toHaveBeenCalledTimes(1);
expect(model1).toBe(model2);
});
it('shares global editor options among all instances', () => { it('shares global editor options among all instances', () => {
editor = new EditorLite({ editor = new EditorLite({
readOnly: true, readOnly: true,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment