summaryrefslogtreecommitdiff
path: root/spec/frontend/editor/source_editor_extension_base_spec.js
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/editor/source_editor_extension_base_spec.js')
-rw-r--r--spec/frontend/editor/source_editor_extension_base_spec.js161
1 files changed, 53 insertions, 108 deletions
diff --git a/spec/frontend/editor/source_editor_extension_base_spec.js b/spec/frontend/editor/source_editor_extension_base_spec.js
index a0fb1178b3b..6606557fd1f 100644
--- a/spec/frontend/editor/source_editor_extension_base_spec.js
+++ b/spec/frontend/editor/source_editor_extension_base_spec.js
@@ -2,40 +2,25 @@ import { Range } from 'monaco-editor';
import { useFakeRequestAnimationFrame } from 'helpers/fake_request_animation_frame';
import setWindowLocation from 'helpers/set_window_location_helper';
import {
- ERROR_INSTANCE_REQUIRED_FOR_EXTENSION,
EDITOR_TYPE_CODE,
EDITOR_TYPE_DIFF,
+ EXTENSION_BASE_LINE_LINK_ANCHOR_CLASS,
+ EXTENSION_BASE_LINE_NUMBERS_CLASS,
} from '~/editor/constants';
import { SourceEditorExtension } from '~/editor/extensions/source_editor_extension_base';
-
-jest.mock('~/helpers/startup_css_helper', () => {
- return {
- waitForCSSLoaded: jest.fn().mockImplementation((cb) => {
- // We have to artificially put the callback's execution
- // to the end of the current call stack to be able to
- // test that the callback is called after waitForCSSLoaded.
- // setTimeout with 0 delay does exactly that.
- // Otherwise we might end up with false positive results
- setTimeout(() => {
- cb.apply();
- }, 0);
- }),
- };
-});
+import EditorInstance from '~/editor/source_editor_instance';
describe('The basis for an Source Editor extension', () => {
const defaultLine = 3;
- let ext;
let event;
- const defaultOptions = { foo: 'bar' };
const findLine = (num) => {
- return document.querySelector(`.line-numbers:nth-child(${num})`);
+ return document.querySelector(`.${EXTENSION_BASE_LINE_NUMBERS_CLASS}:nth-child(${num})`);
};
const generateLines = () => {
let res = '';
for (let line = 1, lines = 5; line <= lines; line += 1) {
- res += `<div class="line-numbers">${line}</div>`;
+ res += `<div class="${EXTENSION_BASE_LINE_NUMBERS_CLASS}">${line}</div>`;
}
return res;
};
@@ -49,6 +34,9 @@ describe('The basis for an Source Editor extension', () => {
},
};
};
+ const createInstance = (baseInstance = {}) => {
+ return new EditorInstance(baseInstance);
+ };
beforeEach(() => {
setFixtures(generateLines());
@@ -59,95 +47,47 @@ describe('The basis for an Source Editor extension', () => {
jest.clearAllMocks();
});
- describe('constructor', () => {
- it('resets the layout in waitForCSSLoaded callback', async () => {
- const instance = {
- layout: jest.fn(),
- };
- ext = new SourceEditorExtension({ instance });
- expect(instance.layout).not.toHaveBeenCalled();
-
- // We're waiting for the waitForCSSLoaded mock to kick in
- await jest.runOnlyPendingTimers();
+ describe('onUse callback', () => {
+ it('initializes the line highlighting', () => {
+ const instance = createInstance();
+ const spy = jest.spyOn(SourceEditorExtension, 'highlightLines');
- expect(instance.layout).toHaveBeenCalled();
+ instance.use({ definition: SourceEditorExtension });
+ expect(spy).toHaveBeenCalled();
});
it.each`
- description | instance | options
- ${'accepts configuration options and instance'} | ${{}} | ${defaultOptions}
- ${'leaves instance intact if no options are passed'} | ${{}} | ${undefined}
- ${'does not fail if both instance and the options are omitted'} | ${undefined} | ${undefined}
- ${'throws if only options are passed'} | ${undefined} | ${defaultOptions}
- `('$description', ({ instance, options } = {}) => {
- SourceEditorExtension.deferRerender = jest.fn();
- const originalInstance = { ...instance };
-
- if (instance) {
- if (options) {
- Object.entries(options).forEach((prop) => {
- expect(instance[prop]).toBeUndefined();
- });
- // Both instance and options are passed
- ext = new SourceEditorExtension({ instance, ...options });
- Object.entries(options).forEach(([prop, value]) => {
- expect(ext[prop]).toBeUndefined();
- expect(instance[prop]).toBe(value);
- });
+ description | instanceType | shouldBeCalled
+ ${'Sets up'} | ${EDITOR_TYPE_CODE} | ${true}
+ ${'Does not set up'} | ${EDITOR_TYPE_DIFF} | ${false}
+ `(
+ '$description the line linking for $instanceType instance',
+ ({ instanceType, shouldBeCalled }) => {
+ const instance = createInstance({
+ getEditorType: jest.fn().mockReturnValue(instanceType),
+ onMouseMove: jest.fn(),
+ onMouseDown: jest.fn(),
+ });
+ const spy = jest.spyOn(SourceEditorExtension, 'setupLineLinking');
+
+ instance.use({ definition: SourceEditorExtension });
+ if (shouldBeCalled) {
+ expect(spy).toHaveBeenCalledWith(instance);
} else {
- ext = new SourceEditorExtension({ instance });
- expect(instance).toEqual(originalInstance);
+ expect(spy).not.toHaveBeenCalled();
}
- } else if (options) {
- // Options are passed without instance
- expect(() => {
- ext = new SourceEditorExtension({ ...options });
- }).toThrow(ERROR_INSTANCE_REQUIRED_FOR_EXTENSION);
- } else {
- // Neither options nor instance are passed
- expect(() => {
- ext = new SourceEditorExtension();
- }).not.toThrow();
- }
- });
-
- it('initializes the line highlighting', () => {
- SourceEditorExtension.deferRerender = jest.fn();
- const spy = jest.spyOn(SourceEditorExtension, 'highlightLines');
- ext = new SourceEditorExtension({ instance: {} });
- expect(spy).toHaveBeenCalled();
- });
-
- it('sets up the line linking for code instance', () => {
- SourceEditorExtension.deferRerender = jest.fn();
- const spy = jest.spyOn(SourceEditorExtension, 'setupLineLinking');
- const instance = {
- getEditorType: jest.fn().mockReturnValue(EDITOR_TYPE_CODE),
- onMouseMove: jest.fn(),
- onMouseDown: jest.fn(),
- };
- ext = new SourceEditorExtension({ instance });
- expect(spy).toHaveBeenCalledWith(instance);
- });
-
- it('does not set up the line linking for diff instance', () => {
- SourceEditorExtension.deferRerender = jest.fn();
- const spy = jest.spyOn(SourceEditorExtension, 'setupLineLinking');
- const instance = {
- getEditorType: jest.fn().mockReturnValue(EDITOR_TYPE_DIFF),
- };
- ext = new SourceEditorExtension({ instance });
- expect(spy).not.toHaveBeenCalled();
- });
+ },
+ );
});
describe('highlightLines', () => {
const revealSpy = jest.fn();
const decorationsSpy = jest.fn();
- const instance = {
+ const instance = createInstance({
revealLineInCenter: revealSpy,
deltaDecorations: decorationsSpy,
- };
+ });
+ instance.use({ definition: SourceEditorExtension });
const defaultDecorationOptions = {
isWholeLine: true,
className: 'active-line-text',
@@ -175,7 +115,7 @@ describe('The basis for an Source Editor extension', () => {
${'uses bounds if both hash and bounds exist'} | ${'#L7-42'} | ${[3, 5]} | ${true} | ${[3, 1, 5, 1]}
`('$desc', ({ hash, bounds, shouldReveal, expectedRange } = {}) => {
window.location.hash = hash;
- SourceEditorExtension.highlightLines(instance, bounds);
+ instance.highlightLines(bounds);
if (!shouldReveal) {
expect(revealSpy).not.toHaveBeenCalled();
expect(decorationsSpy).not.toHaveBeenCalled();
@@ -193,11 +133,11 @@ describe('The basis for an Source Editor extension', () => {
}
});
- it('stores the line decorations on the instance', () => {
+ it('stores the line decorations on the instance', () => {
decorationsSpy.mockReturnValue('foo');
window.location.hash = '#L10';
expect(instance.lineDecorations).toBeUndefined();
- SourceEditorExtension.highlightLines(instance);
+ instance.highlightLines();
expect(instance.lineDecorations).toBe('foo');
});
@@ -215,7 +155,7 @@ describe('The basis for an Source Editor extension', () => {
},
];
instance.lineDecorations = oldLineDecorations;
- SourceEditorExtension.highlightLines(instance, [7, 10]);
+ instance.highlightLines([7, 10]);
expect(decorationsSpy).toHaveBeenCalledWith(oldLineDecorations, newLineDecorations);
});
});
@@ -228,13 +168,18 @@ describe('The basis for an Source Editor extension', () => {
options: { isWholeLine: true, className: 'active-line-text' },
},
];
- const instance = {
- deltaDecorations: decorationsSpy,
- lineDecorations,
- };
+ let instance;
+
+ beforeEach(() => {
+ instance = createInstance({
+ deltaDecorations: decorationsSpy,
+ lineDecorations,
+ });
+ instance.use({ definition: SourceEditorExtension });
+ });
it('removes all existing decorations', () => {
- SourceEditorExtension.removeHighlights(instance);
+ instance.removeHighlights();
expect(decorationsSpy).toHaveBeenCalledWith(lineDecorations, []);
});
});
@@ -261,9 +206,9 @@ describe('The basis for an Source Editor extension', () => {
});
it.each`
- desc | eventTrigger | shouldRemove
- ${'does not remove the line decorations if the event is triggered on a wrong node'} | ${null} | ${false}
- ${'removes existing line decorations when clicking a line number'} | ${'.link-anchor'} | ${true}
+ desc | eventTrigger | shouldRemove
+ ${'does not remove the line decorations if the event is triggered on a wrong node'} | ${null} | ${false}
+ ${'removes existing line decorations when clicking a line number'} | ${`.${EXTENSION_BASE_LINE_LINK_ANCHOR_CLASS}`} | ${true}
`('$desc', ({ eventTrigger, shouldRemove } = {}) => {
event = generateEventMock({ el: eventTrigger ? document.querySelector(eventTrigger) : null });
instance.onMouseDown.mockImplementation((fn) => {