/**
* @jest-environment jsdom
*/
import createEditor from './createEditor';
import Setting from '@joplin/lib/models/Setting';
import { forceParsing } from '@codemirror/language';
import loadLangauges from './testUtil/loadLanguages';
import { expect, describe, it } from '@jest/globals';
import createEditorSettings from './testUtil/createEditorSettings';
describe('createEditor', () => {
beforeAll(() => {
jest.useFakeTimers();
});
// This checks for a regression -- occasionally, when updating packages,
// syntax highlighting in the CodeMirror editor stops working. This is usually
// fixed by
// 1. removing all `@codemirror/` and `@lezer/` dependencies from yarn.lock,
// 2. upgrading all CodeMirror packages to the latest versions in package.json, and
// 3. re-running `yarn install`.
//
// See https://github.com/laurent22/joplin/issues/7253
it('should give headings a different style', async () => {
const headerLineText = '# Testing...';
const initialText = `${headerLineText}\nThis is a test.`;
const editorSettings = createEditorSettings(Setting.THEME_LIGHT);
await loadLangauges();
const editor = createEditor(document.body, {
initialText,
settings: editorSettings,
onEvent: _event => {},
onLogMessage: _message => {},
});
// Force the generation of the syntax tree now.
forceParsing(editor.editor);
const headerLine = document.body.querySelector('.cm-headerLine')!;
expect(headerLine.textContent).toBe(headerLineText);
// CodeMirror nests the tag that styles the header within .cm-headerLine:
//
const headerLineContent = document.body.querySelectorAll('.cm-headerLine > span');
expect(headerLineContent.length).toBeGreaterThanOrEqual(1);
for (const part of headerLineContent) {
const style = getComputedStyle(part);
expect(style.fontSize).toBe('1.6em');
}
// Cleanup
editor.remove();
});
it('should support loading plugins', async () => {
const initialText = '# Test\nThis is a test.';
const editorSettings = createEditorSettings(Setting.THEME_LIGHT);
const editor = createEditor(document.body, {
initialText,
settings: editorSettings,
onEvent: _event => {},
onLogMessage: _message => {},
});
const getContentScriptJs = jest.fn(async () => {
return `
exports.default = context => {
context.postMessage(context.pluginId);
};
`;
});
const postMessageHandler = jest.fn();
const testPlugin1 = {
pluginId: 'a.plugin.id',
contentScriptId: 'a.plugin.id.contentScript',
contentScriptJs: getContentScriptJs,
postMessageHandler,
};
const testPlugin2 = {
pluginId: 'another.plugin.id',
contentScriptId: 'another.plugin.id.contentScript',
contentScriptJs: getContentScriptJs,
postMessageHandler,
};
// Should be able to load a plugin
await editor.setPlugins([
testPlugin1,
]);
// Allow plugins to load
await jest.runAllTimersAsync();
// Because plugin loading is done by adding script elements to the document,
// we test for the presence of these script elements, rather than waiting for
// them to run.
expect(document.querySelectorAll('#joplin-plugin-scripts-container')).toHaveLength(1);
// Only one script should be present.
const scriptContainer = document.querySelector('#joplin-plugin-scripts-container');
expect(scriptContainer.querySelectorAll('script')).toHaveLength(1);
// Adding another plugin should add another script element
await editor.setPlugins([
testPlugin2, testPlugin1,
]);
await jest.runAllTimersAsync();
// There should now be script elements for each plugin
expect(scriptContainer.querySelectorAll('script')).toHaveLength(2);
// Removing the editor should remove the script container
editor.remove();
expect(document.querySelectorAll('#joplin-plugin-scripts-container')).toHaveLength(0);
});
});