Upgrade CodeMirror from version 5 to 6. #7097

This commit is contained in:
Aditya Toshniwal
2024-02-21 11:15:25 +05:30
committed by GitHub
parent 721290b1e9
commit d3ede3151a
53 changed files with 1565 additions and 1611 deletions

View File

@@ -168,20 +168,20 @@ describe('SchemaView', ()=>{
it('no changes', async ()=>{
await user.click(ctrl.container.querySelector('button[data-test="SQL"]'));
expect(ctrl.container.querySelector('[data-testid="SQL"] textarea')).toHaveValue('-- No updates.');
expect(ctrl.container.querySelector('[data-testid="SQL"] .cm-content')).toHaveTextContent('-- No updates.');
});
it('data invalid', async ()=>{
await user.clear(ctrl.container.querySelector('[name="field2"]'));
await user.type(ctrl.container.querySelector('[name="field2"]'), '2');
await user.click(ctrl.container.querySelector('button[data-test="SQL"]'));
expect(ctrl.container.querySelector('[data-testid="SQL"] textarea')).toHaveValue('-- Definition incomplete.');
expect(ctrl.container.querySelector('[data-testid="SQL"] .cm-content')).toHaveTextContent('-- Definition incomplete.');
});
it('valid data', async ()=>{
await simulateValidData();
await user.click(ctrl.container.querySelector('button[data-test="SQL"]'));
expect(ctrl.container.querySelector('[data-testid="SQL"] textarea')).toHaveValue('select 1;');
expect(ctrl.container.querySelector('[data-testid="SQL"] .cm-content')).toHaveTextContent('select 1;');
});
});

View File

@@ -1,39 +0,0 @@
const getSearchCursorRet = {
_from: 3,
_to: 14,
find: function(_rev) {
if(_rev){
this._from = 1;
this._to = 10;
} else {
this._from = 3;
this._to = 14;
}
return true;
},
from: function() {return this._from;},
to: function() {return this._to;},
replace: jest.fn(),
};
const fromTextAreaRet = {
'getValue':()=>'',
'setValue': jest.fn(),
'refresh': jest.fn(),
'setOption': jest.fn(),
'removeKeyMap': jest.fn(),
'addKeyMap': jest.fn(),
'getSelection': () => '',
'getSearchCursor': jest.fn(()=>getSearchCursorRet),
'getCursor': jest.fn(),
'removeOverlay': jest.fn(),
'addOverlay': jest.fn(),
'setSelection': jest.fn(),
'scrollIntoView': jest.fn(),
'getWrapperElement': ()=>document.createElement('div'),
'on': jest.fn(),
'off': jest.fn(),
'toTextArea': jest.fn(),
};
module.exports = {
fromTextArea: jest.fn(()=>fromTextAreaRet)
};

View File

@@ -9,41 +9,54 @@
import React from 'react';
import {default as OrigCodeMirror} from 'bundled_codemirror';
import { withTheme } from '../fake_theme';
import pgWindow from 'sources/window';
import CodeMirror from 'sources/components/CodeMirror';
import { FindDialog } from '../../../pgadmin/static/js/components/CodeMirror';
import CodeMirror from 'sources/components/ReactCodeMirror';
import FindDialog from 'sources/components/ReactCodeMirror/FindDialog';
import CustomEditorView from 'sources/components/ReactCodeMirror/CustomEditorView';
import fakePgAdmin from '../fake_pgadmin';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { render, screen, fireEvent } from '@testing-library/react';
import * as CMSearch from '@codemirror/search';
jest.mock('sources/components/ReactCodeMirror/CustomEditorView');
jest.mock('@codemirror/search', () => ({
...(jest.requireActual('@codemirror/search')),
SearchQuery: jest.fn().mockImplementation(() => {
return {
eq: jest.fn(),
};
}),
openSearchPanel: jest.fn(),
closeSearchPanel: jest.fn(),
replaceNext: jest.fn(),
}));
describe('CodeMirror', ()=>{
const ThemedCM = withTheme(CodeMirror);
let cmInstance, options={
lineNumbers: true,
mode: 'text/x-pgsql',
},
cmObj = OrigCodeMirror.fromTextArea();
let cmInstance, editor;
const cmRerender = (props)=>{
cmInstance.rerender(
<ThemedCM
value={'Init text'}
options={options}
className="testClass"
currEditor={(obj) => {
editor = obj;
}}
{...props}
/>
);
};
beforeEach(()=>{
pgWindow.pgAdmin = fakePgAdmin;
// jest.spyOn(OrigCodeMirror, 'fromTextArea').mockReturnValue(cmObj);
cmInstance = render(
<ThemedCM
value={'Init text'}
options={options}
className="testClass"
currEditor={(obj) => {
editor = obj;
}}
/>);
});
@@ -52,17 +65,23 @@ describe('CodeMirror', ()=>{
});
it('init', async ()=>{
/* textarea ref passed to fromTextArea */
expect(OrigCodeMirror.fromTextArea).toHaveBeenCalledWith(cmInstance.container.querySelector('textarea'), expect.objectContaining(options));
await waitFor(() => expect(cmObj.setValue).toHaveBeenCalledWith('Init text'));
expect(CustomEditorView).toHaveBeenCalledTimes(1);
expect(editor.setValue).toHaveBeenCalledWith('Init text');
});
it('change value', ()=>{
editor.state = {
doc: [],
};
editor.setValue.mockClear();
jest.spyOn(editor, 'getValue').mockReturnValue('Init text');
cmRerender({value: 'the new text'});
expect(cmObj.setValue).toHaveBeenCalledWith('the new text');
expect(editor.setValue).toHaveBeenCalledWith('the new text');
editor.setValue.mockClear();
jest.spyOn(editor, 'getValue').mockReturnValue('the new text');
cmRerender({value: null});
expect(cmObj.setValue).toHaveBeenCalledWith('');
expect(editor.setValue).toHaveBeenCalledWith('');
});
@@ -73,7 +92,7 @@ describe('CodeMirror', ()=>{
const ctrlMount = (props)=>{
ctrl = render(
<ThemedFindDialog
editor={cmObj}
editor={editor}
show={true}
onClose={onClose}
{...props}
@@ -84,29 +103,27 @@ describe('CodeMirror', ()=>{
it('init', ()=>{
ctrlMount({});
cmObj.removeOverlay.mockClear();
cmObj.addOverlay.mockClear();
CMSearch.SearchQuery.mockClear();
const input = ctrl.container.querySelector('input');
fireEvent.change(input, {
target: {value: '\n\r\tA'},
});
expect(cmObj.removeOverlay).toHaveBeenCalled();
expect(cmObj.addOverlay).toHaveBeenCalled();
expect(cmObj.setSelection).toHaveBeenCalledWith(3, 14);
expect(cmObj.scrollIntoView).toHaveBeenCalled();
expect(CMSearch.SearchQuery).toHaveBeenCalledWith(expect.objectContaining({
search: expect.stringContaining('A')
}));
});
it('escape', ()=>{
ctrlMount({});
cmObj.removeOverlay.mockClear();
CMSearch.closeSearchPanel.mockClear();
fireEvent.keyDown(ctrl.container.querySelector('input'), {
key: 'Escape',
});
expect(cmObj.removeOverlay).toHaveBeenCalled();
expect(CMSearch.closeSearchPanel).toHaveBeenCalled();
});
it('toggle match case', ()=>{
@@ -132,7 +149,8 @@ describe('CodeMirror', ()=>{
it('replace', async ()=>{
ctrlMount({replace: true});
cmObj.getSearchCursor().replace.mockClear();
CMSearch.SearchQuery.mockClear();
fireEvent.change(ctrl.container.querySelectorAll('input')[0], {
target: {value: 'A'},
});
@@ -142,9 +160,13 @@ describe('CodeMirror', ()=>{
fireEvent.keyPress(ctrl.container.querySelectorAll('input')[1], {
key: 'Enter', shiftKey: true, code: 13, charCode: 13
});
await waitFor(()=>{
expect(cmObj.getSearchCursor().replace).toHaveBeenCalled();
});
expect(CMSearch.SearchQuery).toHaveBeenCalledWith(expect.objectContaining({
search: 'A',
replace: 'B'
}));
expect(CMSearch.replaceNext).toHaveBeenCalled();
});
});
});

View File

@@ -50,6 +50,20 @@ global.afterEach(() => {
window.HTMLElement.prototype.scrollIntoView = function() {};
// required for Codemirror 6 to run in jsdom
document.createRange = () => {
const range = new Range();
range.getBoundingClientRect = jest.fn();
range.getClientRects = jest.fn(() => ({
item: () => null,
length: 0,
}));
return range;
};
jest.setTimeout(15000); // 1 second