From 9e93c71864466e4cdb4a837b72334dca4ad58708 Mon Sep 17 00:00:00 2001 From: James Hrisho Date: Sat, 23 Mar 2024 22:49:47 -0400 Subject: [PATCH] Fix tests and reinstate running them --- jest.config.ts | 3 +- package.json | 6 +- src/split.tsx | 11 +- tests/src/ace.spec.tsx | 1279 +++++++++++++++++++++++--------------- tests/src/split.spec.tsx | 693 ++++++++++++++------- 5 files changed, 1266 insertions(+), 726 deletions(-) diff --git a/jest.config.ts b/jest.config.ts index de4dbde5..ea3193ae 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -2,7 +2,8 @@ import type {Config} from 'jest'; const config: Config = { testEnvironment: "jsdom", - coverageReporters: ["html", "text", "lcov"] + coverageReporters: ["html", "text", "lcov"], + reporters: ["default", "summary"], }; export default config; \ No newline at end of file diff --git a/package.json b/package.json index 52984695..d0e10dc5 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "lib/index.js", "types": "lib/index.d.ts", "scripts": { - "prettier": "prettier --write \"src/**\" \"example/*.js\"", + "prettier": "prettier --write \"src/**\" \"example/*.js\" \"tests/**\"", "clean": "rimraf lib dist", "lint": "echo 'foo'", "build:lib": "tsc", @@ -18,8 +18,8 @@ "preversion": "npm run clean && npm run check", "version": "npm run build", "prepublishOnly": "npm run clean && npm run build", - "test": "echo 'jest'", - "coverage": "nyc npm run test", + "test": "jest", + "coverage": "jest --coverage", "prepare": "npm run build:lib" }, "author": "James Hrisho", diff --git a/src/split.tsx b/src/split.tsx index 2d4f9b34..47eb3951 100644 --- a/src/split.tsx +++ b/src/split.tsx @@ -6,13 +6,13 @@ import { } from "./editorOptions"; const ace = getAceInstance(); import { Ace, Range } from "ace-builds"; -import Editor = Ace.Editor; import { Split } from "ace-builds/src-noconflict/ext-split"; import * as PropTypes from "prop-types"; import * as React from "react"; const isEqual = require("lodash.isequal"); const get = require("lodash.get"); import { + IAceEditor, IAceOptions, IAnnotation, ICommand, @@ -20,7 +20,7 @@ import { IMarker } from "./types"; -interface IAceEditorClass extends Editor { +interface IAceEditorClass extends IAceEditor { [index: string]: any; $options?: any; } @@ -75,10 +75,7 @@ export interface ISplitEditorProps { markers?: IMarker[][]; } -export default class SplitComponent extends React.Component< - ISplitEditorProps, - undefined -> { +export default class SplitComponent extends React.Component { [index: string]: any; public static propTypes: PropTypes.ValidationMap = { @@ -209,7 +206,7 @@ export default class SplitComponent extends React.Component< splits } = this.props; - this.editor = ace.edit(this.refEditor); + this.editor = ace.edit(this.refEditor) as IAceEditor; if (this.isInShadow(this.refEditor)) { this.editor.renderer.attachToShadowRoot(); } diff --git a/tests/src/ace.spec.tsx b/tests/src/ace.spec.tsx index b324e930..d3339849 100644 --- a/tests/src/ace.spec.tsx +++ b/tests/src/ace.spec.tsx @@ -1,7 +1,7 @@ import AceEditor from "../../src/ace"; -import {jest, expect} from '@jest/globals'; -import { render as mount, screen} from '@testing-library/react' -import React from 'react'; +import { jest, expect } from "@jest/globals"; +import { render as mount, screen } from "@testing-library/react"; +import React from "react"; import { IAceEditor, IMarker } from "../../src/types"; describe("Ace Component", () => { // Required for the document.getElementById used by Ace can work in the test environment @@ -13,24 +13,18 @@ describe("Ace Component", () => { it("should trigger console warn if editorOption is called", () => { jest.spyOn(console, "warn"); - mount( - , - + mount(); + expect(console.warn).toBeCalledWith( + "ReactAce: editor option enableBasicAutocompletion was activated but not found. Did you need to import a related tool or did you possibly mispell the option?" ); - expect(console.warn).toBeCalledWith( - "ReactAce: editor option enableBasicAutocompletion was activated but not found. Did you need to import a related tool or did you possibly mispell the option?" - ) }); it("should render without problems with defaults properties, defaultValue and keyboardHandler", () => { - mount( - , - ); - expect(screen.findAllByText("hi james")).toBeTruthy(); + mount(); + expect(screen.findAllByText("hi james")).toBeTruthy(); }); it("should render editor options not default values", () => { - mount( { tabSize: 2 }} ref={node => { - editor = node?.editor + editor = node?.editor; }} /> ); @@ -50,15 +44,14 @@ describe("Ace Component", () => { const beforeLoadCallback = jest.fn(); mount(); - expect(beforeLoadCallback).toBeCalledTimes(1) + expect(beforeLoadCallback).toBeCalledTimes(1); }); it("should get the editor from the onLoad callback", () => { - const loadCallback = jest.fn() + const loadCallback = jest.fn(); mount(); - - expect(loadCallback).toBeCalledTimes(1) + expect(loadCallback).toBeCalledTimes(1); }); it("should set the editor props to the Ace element", () => { @@ -67,14 +60,14 @@ describe("Ace Component", () => { test: "setFromTest" }; mount( - { - editor = node?.editor - }} />, - + { + editor = node?.editor; + }} + /> ); - expect(editor?.react).toEqual(editorProperties.react); expect(editor?.test).toEqual(editorProperties.test); }); @@ -95,17 +88,16 @@ describe("Ace Component", () => { } ]; mount( - { - editor = node?.editor - }} /> + { + editor = node?.editor; + }} + /> ); - expect(editor?.commands.commands.myReactAceTest).toEqual( - commandsMock[0] - ); - expect(editor?.commands.commands.myTestCommand).toEqual( - commandsMock[1] - ); + expect(editor?.commands.commands.myReactAceTest).toEqual(commandsMock[0]); + expect(editor?.commands.commands.myTestCommand).toEqual(commandsMock[1]); }); // it("should change the command binding for the Ace element", () => { @@ -131,22 +123,31 @@ describe("Ace Component", () => { it("should set up the placeholder text with no value set", () => { const placeholder = "Placeholder Text Here"; const wrapper = mount( - { - editor = node?.editor - }}/>, + { + editor = node?.editor; + }} + /> ); // Read the markers - expect(editor?.renderer.placeholderNode).toBeTruthy() - expect(editor?.renderer.placeholderNode?.textContent).toEqual(placeholder); + expect(editor?.renderer.placeholderNode).toBeTruthy(); + expect(editor?.renderer.placeholderNode?.textContent).toEqual( + placeholder + ); }); it("should not set up the placeholder text with value set", () => { const placeholder = "Placeholder Text Here"; const wrapper = mount( - { - editor = node?.editor - }} value="Code here" />, + { + editor = node?.editor; + }} + value="Code here" + /> ); // Read the markers @@ -164,9 +165,14 @@ describe("Ace Component", () => { className: "test-marker" } ]; - mount( { - editor = node?.editor - }} />); + mount( + { + editor = node?.editor; + }} + /> + ); // Read the markers expect(editor?.getSession().getMarkers()["3"].clazz).toEqual( @@ -202,18 +208,28 @@ describe("Ace Component", () => { className: "test-marker-new" } ]; - const wrapper = mount( { - editor = node?.editor - }} />); + const wrapper = mount( + { + editor = node?.editor; + }} + /> + ); // Read the markers expect(editor?.getSession().getMarkers()["3"].clazz).toEqual( "test-marker-old" ); expect(editor?.getSession().getMarkers()["3"].type).toEqual("text"); - wrapper.rerender( {editor = node?.editor - }}>) + wrapper.rerender( + { + editor = node?.editor; + }} + > + ); expect(editor?.getSession().getMarkers()["6"].clazz).toEqual( "test-marker-new" @@ -236,10 +252,14 @@ describe("Ace Component", () => { } ]; const markers = []; - const wrapper = mount( {editor = node?.editor - }} - />); + const wrapper = mount( + { + editor = node?.editor; + }} + /> + ); // Read the markers expect(Object.keys(editor?.getSession().getMarkers()!)).toEqual([ @@ -251,8 +271,14 @@ describe("Ace Component", () => { "test-marker-old" ); expect(editor?.getSession().getMarkers()["3"].type).toEqual("text"); - wrapper.rerender( {editor = node?.editor} }>); - + wrapper.rerender( + { + editor = node?.editor; + }} + > + ); expect(Object.keys(editor?.getSession().getMarkers()!)).toEqual([ "1", @@ -269,7 +295,13 @@ describe("Ace Component", () => { } ]; const wrapper = mount( - {editor = node?.editor} }/> + { + editor = node?.editor; + }} + /> ); const bgMarkers = editor?.getSession().getMarkers(false)!; @@ -277,7 +309,15 @@ describe("Ace Component", () => { expect(bgMarkers["1"]).toHaveProperty("clazz", "ace_active-line"); expect(bgMarkers["2"]).toHaveProperty("clazz", "ace_selected-word"); - wrapper.rerender( {editor = node?.editor} }/>); + wrapper.rerender( + { + editor = node?.editor; + }} + /> + ); const bgMarkersNew = editor?.getSession().getMarkers(false)!; expect(Object.keys(bgMarkersNew)).toEqual(["1", "2", "3"]); expect(bgMarkersNew["1"]).toHaveProperty("clazz", "ace_active-line"); @@ -294,457 +334,688 @@ describe("Ace Component", () => { type: "error" } ]; - const wrapper = mount( {editor = node?.editor} }/>); - wrapper.rerender( {editor = node?.editor} } annotations={ annotations } />); + const wrapper = mount( + { + editor = node?.editor; + }} + /> + ); + wrapper.rerender( + { + editor = node?.editor; + }} + annotations={annotations} + /> + ); expect(editor?.getSession().getAnnotations()).toEqual(annotations); - wrapper.rerender( {editor = node?.editor} } annotations={ undefined } />) + wrapper.rerender( + { + editor = node?.editor; + }} + annotations={undefined} + /> + ); expect(editor?.getSession().getAnnotations()).toEqual([]); }); - // it("should add annotations with changing editor value", () => { - // // See https://github.com/securingsincity/react-ace/issues/300 - // const annotations = [ - // { row: 0, column: 0, text: "error.message", type: "error" } - // ]; - // const initialText = `Initial - // text`; - // const modifiedText = `Modified - // text`; - // const wrapper = mount( - // , - // mountOptions - // ); - // const editor = wrapper.instance().editor; - // wrapper.setProps({ - // annotations: annotations, - // value: modifiedText - // }); - // expect(editor.renderer.$gutterLayer.$annotations).to.have.length(1); - // expect(editor.renderer.$gutterLayer.$annotations[0]).toHaveProperty( - // "className" - // ); - // }); - - // it("should keep annotations with changing editor value", () => { - // // See https://github.com/securingsincity/react-ace/issues/300 - // const annotations = [ - // { row: 0, column: 0, text: "error.message", type: "error" } - // ]; - // const initialText = `Initial - // text`; - // const modifiedText = `Modified - // text`; - // const wrapper = mount( - // , - // mountOptions - // ); - // const editor = wrapper.instance().editor; - // wrapper.setProps({ - // value: modifiedText - // }); - // expect(editor.renderer.$gutterLayer.$annotations).to.have.length(1); - // expect(editor.renderer.$gutterLayer.$annotations[0]).toHaveProperty( - // "className" - // ); - // }); - - // it("should set editor to null on componentWillUnmount", () => { - // const wrapper = mount(, mountOptions); - // expect(wrapper.getElement().editor).to.not.equal(null); - - // // Check the editor is null after the Unmount - // wrapper.unmount(); - // expect(wrapper.get(0)).to.not.exist; - // }); - // }); + it("should add annotations with changing editor value", () => { + // See https://github.com/securingsincity/react-ace/issues/300 + const annotations = [ + { row: 0, column: 0, text: "error.message", type: "error" } + ]; + const initialText = `Initial + text`; + const modifiedText = `Modified + text`; + const wrapper = mount( + { + editor = node?.editor; + }} + /> + ); + wrapper.rerender( + { + editor = node?.editor; + }} + /> + ); + expect(editor?.session.getAnnotations()).toHaveLength(1); + expect(editor?.session.getAnnotations()[0]).toEqual(annotations[0]); + }); + + it("should keep annotations with changing editor value", () => { + // See https://github.com/securingsincity/react-ace/issues/300 + const annotations = [ + { row: 0, column: 0, text: "error.message", type: "error" } + ]; + const initialText = `Initial + text`; + const modifiedText = `Modified + text`; + const wrapper = mount( + { + editor = node?.editor; + }} + /> + ); + wrapper.rerender( + { + editor = node?.editor; + }} + /> + ); + expect(editor?.session.getAnnotations()).toHaveLength(1); + expect(editor?.session.getAnnotations()[0]).toEqual(annotations[0]); + }); + + it("should set editor to null on componentWillUnmount", () => { + const wrapper = mount(); + // Check the editor is null after the Unmount + wrapper.unmount(); + expect(wrapper.container.innerHTML).toBe(""); + }); + }); // //inspired from https://github.com/goodtimeaj/debounce-function/blob/master/test/unit/debounce-function.js - // describe("Debounce function", () => { - // it("function arg should be called when after timeout", done => { - // const wrapper = mount(, mountOptions); - // var flag = false; - // var func = wrapper.instance().debounce(function () { - // flag = true; - // }, 100); - // func(); - // expect(flag).to.be.false; - // setTimeout(function () { - // expect(flag).to.be.true; - // done(); - // }, 150); - // }); - - // it("timer should be reset on successive call", done => { - // const wrapper = mount(, mountOptions); - - // var flag = false; - // var func = wrapper.instance().debounce(function () { - // flag = true; - // }, 100); - // func(); - // expect(flag).to.be.false; - // setTimeout(function () { - // expect(flag).to.be.false; - // func(); - // }, 50); - // setTimeout(function () { - // expect(flag).to.be.false; - // }, 120); - // setTimeout(function () { - // expect(flag).to.be.true; - // done(); - // }, 160); - // }); - - // it("function should be called only once per period", done => { - // const wrapper = mount(, mountOptions); - - // var flag1 = false; - // var flag2 = false; - // var func = wrapper.instance().debounce(function () { - // if (flag1) { - // flag2 = true; - // } - // flag1 = true; - // }, 100); - - // func(); - // expect(flag1).to.be.false; - // expect(flag2).to.be.false; - // setTimeout(function () { - // expect(flag1).to.be.false; - // expect(flag2).to.be.false; - // func(); - // setTimeout(function () { - // expect(flag1).to.be.true; - // expect(flag2).to.be.false; - // func(); - // setTimeout(function () { - // expect(flag1).to.be.true; - // expect(flag2).to.be.false; - // done(); - // }, 90); - // }, 110); - // }, 50); - // }); - // it("should keep initial value after undo event", () => { - // const onInput = () => { - // const editor = wrapper.instance().editor; - // editor.undo(); - // expect(editor.getValue()).to.equal("foobar"); - // }; - - // const wrapper = mount( - // , - // mountOptions - // ); - // }); - // }); - - // describe("Events", () => { - // it("should call the onChange method callback", () => { - // const onChangeCallback = sinon.spy(); - // const wrapper = mount( - // , - // mountOptions - // ); - - // // Check is not previously called - // expect(onChangeCallback.callCount).to.equal(0); - - // // Trigger the change event - // const expectText = "React Ace Test"; - // wrapper.instance().editor.setValue(expectText, 1); - - // expect(onChangeCallback.callCount).to.equal(1); - // expect(onChangeCallback.getCall(0).args[0]).to.equal(expectText); - // expect(onChangeCallback.getCall(0).args[1].action).to.eq("insert"); - // }); - - // it("should limit call to onChange (debounce)", done => { - // const period = 100; - // const onChangeCallback = sinon.spy(); - // const wrapper = mount( - // , - // mountOptions - // ); - - // // Check is not previously called - // expect(onChangeCallback.callCount).to.equal(0); - - // // Trigger the change event - // const expectText = "React Ace Test"; - // const expectText2 = "React Ace Test2"; - // wrapper.instance().editor.setValue(expectText, 1); - // wrapper.instance().editor.setValue(expectText2, 1); - - // expect(onChangeCallback.callCount).to.equal(0); - - // setTimeout(function () { - // expect(onChangeCallback.callCount).to.equal(1); - // expect(onChangeCallback.getCall(0).args[0]).to.equal(expectText2); - // expect(onChangeCallback.getCall(0).args[1].action).to.eq("insert"); - // onChangeCallback.resetHistory(); - // wrapper.instance().editor.setValue(expectText2, 1); - // wrapper.instance().editor.setValue(expectText, 1); - // expect(onChangeCallback.callCount).to.equal(0); - // setTimeout(function () { - // expect(onChangeCallback.callCount).to.equal(1); - // expect(onChangeCallback.getCall(0).args[0]).to.equal(expectText); - // expect(onChangeCallback.getCall(0).args[1].action).to.eq("insert"); - // done(); - // }, 100); - // }, 100); - // }); - - // it("should call the onCopy method", () => { - // const onCopyCallback = sinon.spy(); - // const wrapper = mount( - // , - // mountOptions - // ); - - // // Check is not previously called - // expect(onCopyCallback.callCount).to.equal(0); - - // // Trigger the copy event - // const expectText = "React Ace Test"; - // wrapper.instance().onCopy({ text: expectText }); - - // expect(onCopyCallback.callCount).to.equal(1); - // expect(onCopyCallback.getCall(0).args[0]).to.equal(expectText); - // }); - - // it("should call the onPaste method", () => { - // const onPasteCallback = sinon.spy(); - // const wrapper = mount( - // , - // mountOptions - // ); - - // // Check is not previously called - // expect(onPasteCallback.callCount).to.equal(0); - - // // Trigger the Paste event - // const expectText = "React Ace Test"; - // wrapper.instance().onPaste({ text: expectText }); - - // expect(onPasteCallback.callCount).to.equal(1); - // expect(onPasteCallback.getCall(0).args[0]).to.equal(expectText); - // }); - - // it.skip("should call the onFocus method callback", () => { - // const onFocusCallback = sinon.spy(); - // const wrapper = mount( - // , - // mountOptions - // ); - - // // Check is not previously called - // expect(onFocusCallback.callCount).to.equal(0); - - // // Trigger the focus event - // wrapper.instance().editor.focus(); - - // expect(onFocusCallback.callCount).to.equal(1); - // expect(onFocusCallback.args.length).to.equal(1); - // }); - - // it("should call the onSelectionChange method callback", done => { - // let onSelectionChange = function () {}; - // const value = ` - // function main(value) { - // console.log('hi james') - // return value; - // } - // `; - // const wrapper = mount(, mountOptions); - - // onSelectionChange = function (selection) { - // const content = wrapper - // .instance() - // .editor.session.getTextRange(selection.getRange()); - // expect(content).to.equal(value); - // done(); - // }; - // wrapper.setProps({ onSelectionChange }); - // wrapper.instance().editor.getSession().selection.selectAll(); - // }); - - // it("should call the onCursorChange method callback", done => { - // let onCursorChange = function () {}; - // const value = ` - // function main(value) { - // console.log('hi james') - // return value; - // } - // `; - - // const wrapper = mount(, mountOptions); - // onCursorChange = function (selection) { - // expect(selection.getCursor()).toEqual({ row: 0, column: 0 }); - // done(); - // }; - // wrapper.setProps({ onCursorChange }); - // expect( - // wrapper.instance().editor.getSession().selection.getCursor() - // ).toEqual({ row: 5, column: 6 }); - // wrapper.instance().editor.getSession().selection.moveCursorTo(0, 0); - // }); - - // it("should call the onBlur method callback", () => { - // const onBlurCallback = sinon.spy(); - // const wrapper = mount( - // , - // mountOptions - // ); - - // // Check is not previously called - // expect(onBlurCallback.callCount).to.equal(0); - - // // Trigger the blur event - // wrapper.instance().onBlur(); - - // expect(onBlurCallback.callCount).to.equal(1); - // expect(onBlurCallback.args.length).to.equal(1); - // }); - - // it("should not trigger a component error to call the events without setting the props", () => { - // const wrapper = mount(, mountOptions); - - // // Check the if statement is checking if the property is set. - // wrapper.instance().onChange(); - // wrapper.instance().onCopy("copy"); - // wrapper.instance().onPaste("paste"); - // wrapper.instance().onFocus(); - // wrapper.instance().onBlur(); - // }); - // }); - - // describe("ComponentDidUpdate", () => { - // it("should update the editorOptions on componentDidUpdate", () => { - // const options = { - // printMargin: 80 - // }; - // const wrapper = mount(, mountOptions); - - // // Read set value - // const editor = wrapper.instance().editor; - // expect(editor.getOption("printMargin")).to.equal(options.printMargin); - - // // Now trigger the componentDidUpdate - // const newOptions = { - // printMargin: 200, - // animatedScroll: true - // }; - // wrapper.setProps({ setOptions: newOptions }); - // expect(editor.getOption("printMargin")).to.equal(newOptions.printMargin); - // expect(editor.getOption("animatedScroll")).to.equal( - // newOptions.animatedScroll - // ); - // }); - - // it("should update the editorOptions on componentDidUpdate", () => { - // const wrapper = mount(, mountOptions); - - // // Read set value - // const editor = wrapper.instance().editor; - // expect(editor.getOption("minLines")).to.equal(1); - - // wrapper.setProps({ minLines: 2 }); - // expect(editor.getOption("minLines")).to.equal(2); - // }); - - // describe("mode prop", () => { - // it("should update the mode on componentDidUpdate", () => { - // const wrapper = mount(, mountOptions); - - // // Read set value - // const oldMode = wrapper.first("AceEditor").props(); - - // wrapper.setProps({ mode: "elixir" }); - // const newMode = wrapper.first("AceEditor").props(); - // expect(oldMode).to.not.deep.equal(newMode); - // }); - - // it("should accept an object mode", () => { - // const wrapper = mount(, mountOptions); - // const session = wrapper.instance().editor.getSession(); - // const sessionSpy = sinon.spy(session, "setMode"); - - // const mode = { - // path: "ace/mode/javascript" - // }; - // wrapper.setProps({ mode: mode }); - // expect(sessionSpy.withArgs(mode).callCount).to.equal(1); - // }); - // }); - - // it("should update many props on componentDidUpdate", () => { - // const wrapper = mount( - // , - // mountOptions - // ); - - // // Read set value - // const oldMode = wrapper.first("AceEditor").props(); - - // wrapper.setProps({ - // theme: "solarized", - // keyboardHandler: "emacs", - // fontSize: 18, - // wrapEnabled: false, - // showPrintMargin: false, - // showGutter: true, - // height: "120px", - // width: "220px" - // }); - // const newMode = wrapper.first("AceEditor").props(); - // expect(oldMode).to.not.deep.equal(newMode); - // }); - - // it("should update the className on componentDidUpdate", () => { - // const className = "old-class"; - // const wrapper = mount(, mountOptions); - - // // Read set value - // let editor = wrapper.instance().refEditor; - // expect(editor.className).to.equal( - // " ace_editor ace_hidpi ace-tm old-class" - // ); - - // // Now trigger the componentDidUpdate - // const newClassName = "new-class"; - // wrapper.setProps({ className: newClassName }); - // editor = wrapper.instance().refEditor; - // expect(editor.className).to.equal( - // " new-class ace_editor ace_hidpi ace-tm" - // ); - // }); - - // it("should update the value on componentDidUpdate", () => { - // const startValue = "start value"; - // const wrapper = mount(, mountOptions); - - // // Read set value - // let editor = wrapper.instance().editor; - // expect(editor.getValue()).to.equal(startValue); - - // // Now trigger the componentDidUpdate - // const newValue = "updated value"; - // wrapper.setProps({ value: newValue }); - // editor = wrapper.instance().editor; - // expect(editor.getValue()).to.equal(newValue); - // }); + describe("Debounce function", () => { + it("function arg should be called when after timeout", done => { + let instance; + const wrapper = mount( + { + instance = node; + }} + /> + ); + var flag = false; + var func = instance.debounce(function () { + flag = true; + }, 100); + func(); + expect(flag).toBeFalsy(); + setTimeout(function () { + expect(flag).toBeTruthy; + done(); + }, 150); + }); + + it("timer should be reset on successive call", done => { + let instance; + const wrapper = mount( + { + instance = node; + }} + /> + ); + + var flag = false; + var func = instance.debounce(function () { + flag = true; + }, 100); + func(); + expect(flag).toBeFalsy(); + setTimeout(function () { + expect(flag).toBeFalsy(); + func(); + }, 50); + setTimeout(function () { + expect(flag).toBeFalsy(); + }, 120); + setTimeout(function () { + expect(flag).toBeTruthy(); + done(); + }, 160); + }); + + it("function should be called only once per period", done => { + let instance; + const wrapper = mount( + { + instance = node; + }} + /> + ); + + var flag1 = false; + var flag2 = false; + var func = instance.debounce(function () { + if (flag1) { + flag2 = true; + } + flag1 = true; + }, 100); + + func(); + expect(flag1).toBeFalsy(); + expect(flag2).toBeFalsy(); + setTimeout(function () { + expect(flag1).toBeFalsy(); + expect(flag2).toBeFalsy(); + func(); + setTimeout(function () { + expect(flag1).toBeTruthy(); + expect(flag2).toBeFalsy(); + func(); + setTimeout(function () { + expect(flag1).toBeTruthy(); + expect(flag2).toBeFalsy(); + done(); + }, 90); + }, 110); + }, 50); + }); + it("should keep initial value after undo event", () => { + let instance; + const onInput = () => { + const editor = instance.editor; + editor.undo(); + expect(editor.getValue()).toEqual("foobar"); + }; + + const wrapper = mount( + { + instance = node; + }} + /> + ); + }); + }); + + describe("Events", () => { + it("should call the onChange method callback", () => { + const onChangeCallback = jest.fn(); + const wrapper = mount( + { + editor = node?.editor; + }} + /> + ); + + // Check is not previously called + expect(onChangeCallback).toBeCalledTimes(0); + + // Trigger the change event + const expectText = "React Ace Test"; + editor?.setValue(expectText, 1); + + expect(onChangeCallback).toHaveBeenCalledWith(expectText, { + id: 1, + action: "insert", + lines: ["React Ace Test"], + start: { row: 0, column: 0 }, + end: { row: 0, column: 14 } + }); + }); + + it("should limit call to onChange (debounce)", done => { + const period = 100; + const onChangeCallback = jest.fn(); + let instance; + const wrapper = mount( + { + instance = node; + }} + /> + ); + + // Check is not previously called + expect(onChangeCallback).toBeCalledTimes(0); + + // Trigger the change event + const expectText = "React Ace Test"; + const expectText2 = "React Ace Test2"; + instance.editor.setValue(expectText, 1); + instance.editor.setValue(expectText2, 1); + + expect(onChangeCallback).toBeCalledTimes(0); + + setTimeout(function () { + expect(onChangeCallback).toHaveBeenCalledWith(expectText2, { + action: "insert", + lines: ["React Ace Test2"], + start: { row: 0, column: 0 }, + end: { row: 0, column: 15 } + }); + + onChangeCallback.mockReset(); + instance.editor.setValue(expectText2, 1); + instance.editor.setValue(expectText, 1); + expect(onChangeCallback).toBeCalledTimes(0); + setTimeout(function () { + expect(onChangeCallback).toBeCalledTimes(1); + expect(onChangeCallback).toHaveBeenCalledWith(expectText, { + action: "insert", + lines: ["React Ace Test"], + start: { row: 0, column: 0 }, + end: { row: 0, column: 14 } + }); + + done(); + }, 100); + }, 100); + }); + + it("should call the onCopy method", () => { + let instance; + const onCopyCallback = jest.fn(); + const wrapper = mount( + { + instance = node; + }} + /> + ); + + // Check is not previously called + expect(onCopyCallback).toBeCalledTimes(0); + + // Trigger the copy event + const expectText = "React Ace Test"; + instance.onCopy({ text: expectText }); + + expect(onCopyCallback).toBeCalledWith(expectText); + }); + + it("should call the onPaste method", () => { + let instance; + const onPasteCallback = jest.fn(); + const wrapper = mount( + { + instance = node; + }} + /> + ); + + // Check is not previously called + expect(onPasteCallback).toBeCalledTimes(0); + + // Trigger the Paste event + const expectText = "React Ace Test"; + instance.onPaste({ text: expectText }); + + expect(onPasteCallback).toBeCalledWith(expectText); + }); + + it("should call the onFocus method callback", () => { + const onFocusCallback = jest.fn(); + let instance; + const wrapper = mount( + { + instance = node; + }} + /> + ); + + // Check is not previously called + expect(onFocusCallback).toBeCalledTimes(0); + + // Trigger the focus event + instance.editor.focus(); + + expect(onFocusCallback).toBeCalledTimes(1); + }); + + it("should call the onSelectionChange method callback", done => { + let onSelectionChange = function (selection) {}; + const value = ` + function main(value) { + console.log('hi james') + return value; + } + `; + let instance; + const wrapper = mount( + { + instance = node; + }} + /> + ); + + onSelectionChange = function (selection) { + const content = instance.editor.session.getTextRange( + selection.getRange() + ); + expect(content).toEqual(value); + done(); + }; + wrapper.rerender( + { + instance = node; + }} + onSelectionChange={onSelectionChange} + /> + ); + instance.editor.getSession().selection.selectAll(); + }); + + it("should call the onCursorChange method callback", done => { + let onCursorChange = function (selection) {}; + const value = ` + function main(value) { + console.log('hi james') + return value; + } + `; + let instance; + const wrapper = mount( + { + instance = node; + }} + /> + ); + onCursorChange = function (selection) { + expect(selection.getCursor()).toEqual({ row: 0, column: 0 }); + done(); + }; + wrapper.rerender( + { + instance = node; + }} + onCursorChange={onCursorChange} + /> + ); + + expect(instance.editor.getSession().selection.getCursor()).toEqual({ + row: 5, + column: 6 + }); + instance.editor.getSession().selection.moveCursorTo(0, 0); + }); + + it("should call the onBlur method callback", () => { + const onBlurCallback = jest.fn(); + let instance; + const wrapper = mount( + { + instance = node; + }} + /> + ); + + // Check is not previously called + expect(onBlurCallback).toBeCalledTimes(0); + + // Trigger the blur event + instance.onBlur(); + + expect(onBlurCallback).toBeCalledTimes(1); + }); + + it("should not trigger a component error to call the events without setting the props", () => { + let instance; + const wrapper = mount( + { + instance = node; + }} + /> + ); + + // Check the if statement is checking if the property is set. + instance.onChange(); + instance.onCopy("copy"); + instance.onPaste("paste"); + instance.onFocus(); + instance.onBlur(); + }); + }); + describe("ComponentDidUpdate", () => { + let instance: AceEditor | null; + it("should update the editorOptions on componentDidUpdate", () => { + const options = { + printMargin: 80 + }; + const wrapper = mount( + { + instance = node; + }} + /> + ); + + // Read set value + const editor = instance?.editor; + expect(editor?.getOption("printMargin")).toEqual(options.printMargin); + + // Now trigger the componentDidUpdate + const newOptions = { + printMargin: 200, + animatedScroll: true + }; + wrapper.rerender( + { + instance = node; + }} + /> + ); + + expect(editor?.getOption("printMargin")).toEqual(newOptions.printMargin); + expect(editor?.getOption("animatedScroll")).toEqual( + newOptions.animatedScroll + ); + }); + + it("should update the editorOptions on componentDidUpdate", () => { + const wrapper = mount( + { + instance = node; + }} + /> + ); + + // Read set value + const editor = instance?.editor; + expect(editor?.getOption("minLines")).toEqual(1); + + wrapper.rerender( + { + instance = node; + }} + /> + ); + + expect(editor?.getOption("minLines")).toEqual(2); + }); + + describe("mode prop", () => { + it("should update the mode on componentDidUpdate", () => { + const wrapper = mount( + { + instance = node; + }} + /> + ); + + // Read set value + const oldMode = instance?.props.mode; + let newInstance; + wrapper.rerender( + { + newInstance = node; + }} + /> + ); + const newMode = newInstance?.props.mode; + expect(oldMode).not.toEqual(newMode); + }); + + it("should accept an object mode", () => { + const wrapper = mount( + { + instance = node; + }} + /> + ); + const session = instance?.editor.getSession(); + const sessionSpy = jest.spyOn(session!, "setMode"); + + const mode = { + path: "ace/mode/javascript" + }; + wrapper.rerender( + { + instance = node; + }} + /> + ); + expect(sessionSpy).toBeCalledTimes(1); + }); + }); + + it("should update many props on componentDidUpdate", () => { + const wrapper = mount( + { + instance = node; + }} + /> + ); + const oldMode = instance?.props; + let newInstance; + // Read set value + wrapper.rerender( + { + newInstance = node; + }} + /> + ); + expect(oldMode).not.toEqual(newInstance?.props); + }); + + it("should update the className on componentDidUpdate", () => { + const className = "old-class"; + const wrapper = mount( + { + instance = node; + }} + /> + ); + + // Read set value + let editor = instance?.refEditor; + expect(editor?.className).toEqual( + " ace_editor ace_hidpi ace-tm old-class" + ); + + // Now trigger the componentDidUpdate + const newClassName = "new-class"; + wrapper.rerender( + { + instance = node; + }} + /> + ); + + editor = instance?.refEditor; + expect(editor?.className).toEqual( + " new-class ace_editor ace_hidpi ace-tm" + ); + }); + + it("should update the value on componentDidUpdate", () => { + const startValue = "start value"; + const wrapper = mount( + { + instance = node; + }} + /> + ); + + // Read set value + let editor = instance?.editor; + expect(editor?.getValue()).toEqual(startValue); + + // Now trigger the componentDidUpdate + const newValue = "updated value"; + wrapper.rerender( + { + instance = node; + }} + /> + ); + + editor = instance?.editor; + expect(editor?.getValue()).toEqual(newValue); + }); }); }); diff --git a/tests/src/split.spec.tsx b/tests/src/split.spec.tsx index 1473dc3e..7ff0a80e 100644 --- a/tests/src/split.spec.tsx +++ b/tests/src/split.spec.tsx @@ -1,40 +1,51 @@ -import {expect} from '@jest/globals'; -import * as sinon from "sinon"; import SplitEditor from "../../src/split"; -import {RenderOptions, render as mount} from '@testing-library/react' -import React from 'react'; +import { jest, expect } from "@jest/globals"; +import { render as mount, screen } from "@testing-library/react"; +import React from "react"; +import { IAceEditor, IMarker } from "../../src/types"; describe("Split Component", () => { // Required for the document.getElementById used by Ace can work in the test environment - const domElement = document.getElementById("app"); - const mountOptions: RenderOptions = { - container: domElement - }; describe("General", () => { + let instance: SplitEditor | null = null; it("should render without problems with defaults properties", () => { - const wrapper = mount(, mountOptions); - expect(wrapper).to.exist; + const wrapper = mount( + { + instance = node!; + }} + splits={2} + /> + ); }); it("should get the ace library from the onBeforeLoad callback", () => { - const beforeLoadCallback = sinon.spy(); - mount(, mountOptions); + const beforeLoadCallback = jest.fn(); + mount( + { + instance = node!; + }} + splits={2} + onBeforeLoad={beforeLoadCallback} + /> + ); - expect(beforeLoadCallback.callCount).to.equal(1); + expect(beforeLoadCallback).toBeCalledTimes(1); }); it("should trigger console warn if editorOption is called", () => { - const stub = sinon.stub(console, "warn"); + jest.resetModules(); + jest.spyOn(console, "warn"); const wrapper = mount( - , - mountOptions - ); - expect(wrapper).to.exist; - expect( - console.warn.calledWith( - "ReaceAce: editor option enableBasicAutocompletion was activated but not found. Did you need to import a related tool or did you possibly mispell the option?" - ) - ).to.be.true; - stub.restore(); + { + instance = node!; + }} + splits={2} + enableBasicAutocompletion={true} + /> + ); + expect(console.warn).toBeCalled(); }); it("should set the editor props to the Ace element", () => { @@ -43,45 +54,82 @@ describe("Split Component", () => { test: "setFromTest" }; const wrapper = mount( - , - mountOptions + { + instance = node!; + }} + splits={2} + editorProps={editorProperties} + /> ); - const editor = wrapper.instance().splitEditor; + const editor = instance!.splitEditor; - expect(editor.react).to.equal(editorProperties.react); - expect(editor.test).to.equal(editorProperties.test); + expect(editor.react).toEqual(editorProperties.react); + expect(editor.test).toEqual(editorProperties.test); }); it("should update the orientation on componentDidUpdate", () => { let orientation = "below"; const wrapper = mount( - , - mountOptions + { + instance = node!; + }} + splits={2} + orientation={orientation} + /> ); // Read set value - let editor = wrapper.instance().split; - expect(editor.getOrientation()).to.equal(editor.BELOW); + let editor = instance!.split; + expect(editor.getOrientation()).toEqual(editor.BELOW); // Now trigger the componentDidUpdate orientation = "beside"; - wrapper.setProps({ orientation }); - editor = wrapper.instance().split; - expect(editor.getOrientation()).to.equal(editor.BESIDE); + wrapper.rerender( + { + instance = node!; + }} + splits={2} + orientation={orientation} + /> + ); + editor = instance!.split; + expect(editor.getOrientation()).toEqual(editor.BESIDE); }); it("should update the orientation on componentDidUpdate", () => { - const wrapper = mount(, mountOptions); + const wrapper = mount( + { + instance = node!; + }} + splits={2} + ref={node => { + instance = node!; + }} + splits={2} + /> + ); // Read set value - let editor = wrapper.instance().split; - expect(editor.getSplits()).to.equal(2); + let editor = instance!.split; + expect(editor.getSplits()).toEqual(2); // Now trigger the componentDidUpdate - wrapper.setProps({ splits: 4 }); - editor = wrapper.instance().split; - expect(editor.getSplits()).to.equal(4); + wrapper.rerender( + { + instance = node!; + }} + splits={4} + /> + ); + + editor = instance!.split; + expect(editor.getSplits()).toEqual(4); }); it("should set the command for the Ace element", () => { @@ -100,17 +148,18 @@ describe("Split Component", () => { } ]; const wrapper = mount( - , - mountOptions + { + instance = node!; + }} + splits={2} + commands={commandsMock} + /> ); - const editor = wrapper.instance().splitEditor; - expect(editor.commands.commands.myReactAceTest).to.deep.equal( - commandsMock[0] - ); - expect(editor.commands.commands.myTestCommand).to.deep.equal( - commandsMock[1] - ); + const editor = instance!.splitEditor; + expect(editor.commands.commands.myReactAceTest).toEqual(commandsMock[0]); + expect(editor.commands.commands.myTestCommand).toEqual(commandsMock[1]); }); it("should change the command binding for the Ace element", () => { @@ -122,237 +171,349 @@ describe("Split Component", () => { } ]; const wrapper = mount( - , - mountOptions + { + instance = node!; + }} + splits={2} + commands={commandsMock} + /> ); - const editor = wrapper.instance().splitEditor; + const editor = instance!.splitEditor; const expected = [editor.commands.commands.removeline, "selectMoreAfter"]; - expect(editor.commands.commandKeyBinding["ctrl-d"]).to.deep.equal( - expected - ); + expect(editor.commands.commandKeyBinding["ctrl-d"]).toEqual(expected); }); it("should get the editor from the onLoad callback", () => { - const loadCallback = sinon.spy(); + const loadCallback = jest.fn(); const wrapper = mount( - , - mountOptions + { + instance = node!; + }} + splits={2} + onLoad={loadCallback} + /> ); // Get the editor - const editor = wrapper.instance().split; + const editor = instance!.split; - expect(loadCallback.callCount).to.equal(1); - expect(loadCallback.getCall(0).args[0]).to.deep.equal(editor); + expect(loadCallback).toBeCalledWith(editor); }); it.skip("should trigger the focus on mount", () => { - const onFocusCallback = sinon.spy(); + const onFocusCallback = jest.fn(); mount( - , - mountOptions + { + instance = node!; + }} + splits={2} + focus={true} + onFocus={onFocusCallback} + /> ); // Read the focus - expect(onFocusCallback.callCount).to.equal(1); + expect(onFocusCallback).toBeCalledTimes(1); }); it("should set editor to null on componentWillUnmount", () => { - const wrapper = mount(, mountOptions); - expect(wrapper.getElement().editor).to.not.equal(null); + const wrapper = mount( + { + instance = node!; + }} + splits={2} + /> + ); + // expect(wrapper.getElement().editor).to.not.equal(null); // Check the editor is null after the Unmount wrapper.unmount(); - expect(wrapper.get(0)).to.not.exist; + // expect(wrapper.get(0)).to.not.exist; }); }); describe("Events", () => { + let instance; it("should call the onChange method callback", () => { - const onChangeCallback = sinon.spy(); + const onChangeCallback = jest.fn(); const wrapper = mount( - , - mountOptions + { + instance = node!; + }} + splits={2} + onChange={onChangeCallback} + /> ); // Check is not previously called - expect(onChangeCallback.callCount).to.equal(0); + expect(onChangeCallback).not.toBeCalled(); // Trigger the change event const expectText = "React Ace Test"; - wrapper.instance().splitEditor.setValue(expectText, 1); - - expect(onChangeCallback.callCount).to.equal(1); - expect(onChangeCallback.getCall(0).args[0]).to.deep.equal([ - expectText, - "" - ]); - expect(onChangeCallback.getCall(0).args[1].action).to.eq("insert"); + instance!.splitEditor.setValue(expectText, 1); + + expect(onChangeCallback).toBeCalledWith([expectText, ""], { + action: "insert", + end: { column: 14, row: 0 }, + id: 1, + lines: ["React Ace Test"], + start: { column: 0, row: 0 } + }); }); - it("should call the onCopy method", () => { - const onCopyCallback = sinon.spy(); + const onCopyCallback = jest.fn(); const wrapper = mount( - , - mountOptions + { + instance = node!; + }} + splits={2} + onCopy={onCopyCallback} + /> ); // Check is not previously called - expect(onCopyCallback.callCount).to.equal(0); + expect(onCopyCallback).not.toBeCalled(); // Trigger the copy event const expectText = "React Ace Test"; - wrapper.instance().onCopy(expectText); + instance!.onCopy(expectText); - expect(onCopyCallback.callCount).to.equal(1); - expect(onCopyCallback.getCall(0).args[0]).to.equal(expectText); + expect(onCopyCallback).toBeCalledWith(expectText); }); it("should call the onPaste method", () => { - const onPasteCallback = sinon.spy(); + const onPasteCallback = jest.fn(); const wrapper = mount( - , - mountOptions + { + instance = node!; + }} + splits={2} + onPaste={onPasteCallback} + /> ); // Check is not previously called - expect(onPasteCallback.callCount).to.equal(0); + expect(onPasteCallback).not.toBeCalled(); // Trigger the Paste event const expectText = "React Ace Test"; - wrapper.instance().onPaste(expectText); - - expect(onPasteCallback.callCount).to.equal(1); - expect(onPasteCallback.getCall(0).args[0]).to.equal(expectText); + instance!.onPaste(expectText); + expect(onPasteCallback).toBeCalledWith(expectText); }); it.skip("should call the onFocus method callback", () => { - const onFocusCallback = sinon.spy(); + const onFocusCallback = jest.fn(); const wrapper = mount( - , - mountOptions + { + instance = node!; + }} + splits={2} + onFocus={onFocusCallback} + /> ); // Check is not previously called - expect(onFocusCallback.callCount).to.equal(0); + expect(onFocusCallback).not.toBeCalled(); // Trigger the focus event - wrapper.instance().split.focus(); + instance!.split.focus(); - expect(onFocusCallback.callCount).to.equal(1); + expect(onFocusCallback).toBeCalledTimes(1); }); it("should call the onSelectionChange method callback", () => { - const onSelectionChangeCallback = sinon.spy(); + const onSelectionChangeCallback = jest.fn(); const wrapper = mount( { + instance = node!; + }} + splits={2} onSelectionChange={onSelectionChangeCallback} - value="some value" - />, - mountOptions + value={["some value", "another value"]} + /> ); // Check is not previously called - expect(onSelectionChangeCallback.callCount).to.equal(0); + expect(onSelectionChangeCallback).not.toBeCalled(); // Trigger the focus event - wrapper.instance().splitEditor.getSession().selection.selectAll(); + instance!.splitEditor.getSession().selection.selectAll(); - expect(onSelectionChangeCallback.callCount).to.equal(1); + expect(onSelectionChangeCallback).toBeCalledTimes(1); }); it("should call the onCursorChange method callback", () => { - const onCursorChangeCallback = sinon.spy(); + const onCursorChangeCallback = jest.fn(); const wrapper = mount( - , - mountOptions + { + instance = node!; + }} + splits={2} + value={["a"]} + onCursorChange={onCursorChangeCallback} + /> ); // The changeCursor event is called when the initial value is set - expect(onCursorChangeCallback.callCount).to.equal(1); + expect(onCursorChangeCallback).toBeCalledTimes(1); // Trigger the changeCursor event - wrapper.instance().splitEditor.getSession().selection.moveCursorTo(0, 0); + instance!.splitEditor.getSession().selection.moveCursorTo(0, 0); - expect(onCursorChangeCallback.callCount).to.equal(2); + expect(onCursorChangeCallback).toBeCalledTimes(2); }); it("should call the onBlur method callback", () => { - const onBlurCallback = sinon.spy(); + const onBlurCallback = jest.fn(); const wrapper = mount( - , - mountOptions + { + instance = node!; + }} + splits={2} + onBlur={onBlurCallback} + /> ); // Check is not previously called - expect(onBlurCallback.callCount).to.equal(0); + expect(onBlurCallback).not.toBeCalled(); // Trigger the blur event - wrapper.instance().onBlur(); + instance!.onBlur(); - expect(onBlurCallback.callCount).to.equal(1); + expect(onBlurCallback).toBeCalledTimes(1); }); it("should not trigger a component error to call the events without setting the props", () => { - const wrapper = mount(, mountOptions); + const wrapper = mount( + { + instance = node!; + }} + splits={2} + /> + ); // Check the if statement is checking if the property is set. - wrapper.instance().onChange(); - wrapper.instance().onCopy("copy"); - wrapper.instance().onPaste("paste"); - wrapper.instance().onFocus(); - wrapper.instance().onBlur(); + instance!.onChange(); + instance!.onCopy("copy"); + instance!.onPaste("paste"); + instance!.onFocus(); + instance!.onBlur(); }); }); describe("ComponentDidUpdate", () => { + let instance; it("should update the editorOptions on componentDidUpdate", () => { const options = { printMargin: 80 }; - const wrapper = mount(, mountOptions); + const wrapper = mount( + { + instance = node!; + }} + splits={2} + setOptions={options} + /> + ); // Read set value - const editor = wrapper.instance().splitEditor; - expect(editor.getOption("printMargin")).to.equal(options.printMargin); + const editor = instance!.splitEditor; + expect(editor.getOption("printMargin")).toEqual(options.printMargin); // Now trigger the componentDidUpdate const newOptions = { printMargin: 200, animatedScroll: true }; - wrapper.setProps({ setOptions: newOptions }); - expect(editor.getOption("printMargin")).to.equal(newOptions.printMargin); - expect(editor.getOption("animatedScroll")).to.equal( + wrapper.rerender( + { + instance = node!; + }} + splits={2} + setOptions={newOptions} + /> + ); + expect(editor.getOption("printMargin")).toEqual(newOptions.printMargin); + expect(editor.getOption("animatedScroll")).toEqual( newOptions.animatedScroll ); }); it("should update the editorOptions on componentDidUpdate", () => { - const wrapper = mount(, mountOptions); + const wrapper = mount( + { + instance = node!; + }} + splits={2} + minLines={1} + /> + ); // Read set value - const editor = wrapper.instance().splitEditor; - expect(editor.getOption("minLines")).to.equal(1); + const editor = instance!.splitEditor; + expect(editor.getOption("minLines")).toEqual(1); + wrapper.rerender( + { + instance = node!; + }} + splits={2} + minLines={2} + /> + ); - wrapper.setProps({ minLines: 2 }); - expect(editor.getOption("minLines")).to.equal(2); + expect(editor.getOption("minLines")).toEqual(2); }); it("should update the mode on componentDidUpdate", () => { - const wrapper = mount(, mountOptions); - + const wrapper = mount( + { + instance = node!; + }} + splits={2} + mode="javascript" + /> + ); + const oldMode = instance?.props.mode; // Read set value - const oldMode = wrapper.first("SplitEditor").props(); + let newInstance; - wrapper.setProps({ mode: "elixir" }); - const newMode = wrapper.first("SplitEditor").props(); - expect(oldMode).to.not.deep.equal(newMode); + wrapper.rerender( + { + newInstance = node; + }} + /> + ); + const newMode = newInstance.props.mode; + expect(oldMode).not.toEqual(newMode); }); it("should update many props on componentDidUpdate", () => { const wrapper = mount( { + instance = node!; + }} + splits={2} theme="github" keyboardHandler="vim" fontSize={14} @@ -361,45 +522,63 @@ describe("Split Component", () => { showGutter={false} height="100px" width="200px" - />, - mountOptions + /> ); // Read set value - const oldMode = wrapper.first("SplitEditor").props(); - - wrapper.setProps({ - theme: "solarized", - keyboardHandler: "emacs", - fontSize: 18, - wrapEnabled: false, - showPrintMargin: false, - showGutter: true, - height: "120px", - width: "220px" - }); - const newMode = wrapper.first("SplitEditor").props(); - expect(oldMode).to.not.deep.equal(newMode); + const oldMode = instance.props; + let newInstance; + wrapper.rerender( + { + newInstance = node; + }} + /> + ); + expect(oldMode).not.toEqual(newInstance?.props); }); it("should update the className on componentDidUpdate", () => { const className = "old-class"; const wrapper = mount( - , - mountOptions + { + instance = node!; + }} + splits={2} + className={className} + /> ); // Read set value - let editor = wrapper.instance().refEditor; - expect(editor.className).to.equal( + let editor = instance!.refEditor; + expect(editor.className).toEqual( " ace_editor ace_hidpi ace-tm old-class" ); // Now trigger the componentDidUpdate const newClassName = "new-class"; - wrapper.setProps({ className: newClassName }); - editor = wrapper.instance().refEditor; - expect(editor.className).to.equal( + wrapper.rerender( + { + instance = node!; + }} + splits={2} + className={newClassName} + /> + ); + + editor = instance!.refEditor; + expect(editor.className).toEqual( " new-class ace_editor ace_hidpi ace-tm" ); }); @@ -408,24 +587,38 @@ describe("Split Component", () => { const startValue = "start value"; const anotherStartValue = "another start value"; const wrapper = mount( - , - mountOptions + { + instance = node!; + }} + splits={2} + value={[startValue, anotherStartValue]} + /> ); // Read set value - let editor = wrapper.instance().split.getEditor(0); - let editor2 = wrapper.instance().split.getEditor(1); - expect(editor.getValue()).to.equal(startValue); - expect(editor2.getValue()).to.equal(anotherStartValue); + let editor = instance!.split.getEditor(0); + let editor2 = instance!.split.getEditor(1); + expect(editor.getValue()).toEqual(startValue); + expect(editor2.getValue()).toEqual(anotherStartValue); // Now trigger the componentDidUpdate const newValue = "updated value"; const anotherNewValue = "another updated value"; - wrapper.setProps({ value: [newValue, anotherNewValue] }); - editor = wrapper.instance().splitEditor; - editor2 = wrapper.instance().split.getEditor(1); - expect(editor.getValue()).to.equal(newValue); - expect(editor2.getValue()).to.equal(anotherNewValue); + wrapper.rerender( + { + instance = node!; + }} + splits={2} + value={[newValue, anotherNewValue]} + /> + ); + + editor = instance!.splitEditor; + editor2 = instance!.split.getEditor(1); + expect(editor.getValue()).toEqual(newValue); + expect(editor2.getValue()).toEqual(anotherNewValue); }); it("should set up the markers", () => { const markers = [ @@ -437,14 +630,22 @@ describe("Split Component", () => { } ] ]; - const wrapper = mount(, mountOptions); + const wrapper = mount( + { + instance = node!; + }} + splits={2} + markers={markers as any} + /> + ); // Read the markers - const editor = wrapper.instance().splitEditor; - expect(editor.getSession().getMarkers()["3"].clazz).to.equal( + const editor = instance!.splitEditor; + expect(editor.getSession().getMarkers()["3"].clazz).toEqual( "test-marker" ); - expect(editor.getSession().getMarkers()["3"].type).to.equal("text"); + expect(editor.getSession().getMarkers()["3"].type).toEqual("text"); }); it("should update the markers", () => { @@ -478,20 +679,36 @@ describe("Split Component", () => { } ] ]; - const wrapper = mount(, mountOptions); + const wrapper = mount( + { + instance = node!; + }} + splits={2} + markers={oldMarkers as any} + /> + ); // Read the markers - const editor = wrapper.instance().splitEditor; - expect(editor.getSession().getMarkers()["3"].clazz).to.equal( + const editor = instance!.splitEditor; + expect(editor.getSession().getMarkers()["3"].clazz).toEqual( "test-marker-old" ); - expect(editor.getSession().getMarkers()["3"].type).to.equal("text"); - wrapper.setProps({ markers: markers }); - const editorB = wrapper.instance().splitEditor; - expect(editorB.getSession().getMarkers()["6"].clazz).to.equal( + expect(editor.getSession().getMarkers()["3"].type).toEqual("text"); + wrapper.rerender( + { + instance = node!; + }} + splits={2} + markers={markers as any} + /> + ); + const editorB = instance!.splitEditor; + expect(editorB.getSession().getMarkers()["6"].clazz).toEqual( "test-marker-new" ); - expect(editorB.getSession().getMarkers()["6"].type).to.equal("text"); + expect(editorB.getSession().getMarkers()["6"].type).toEqual("text"); }); it("should update the markers", () => { @@ -511,17 +728,33 @@ describe("Split Component", () => { ] ]; const markers = [[]]; - const wrapper = mount(, mountOptions); + const wrapper = mount( + { + instance = node!; + }} + splits={2} + markers={oldMarkers as any} + /> + ); // Read the markers - const editor = wrapper.instance().splitEditor; - expect(editor.getSession().getMarkers()["3"].clazz).to.equal( + const editor = instance!.splitEditor; + expect(editor.getSession().getMarkers()["3"].clazz).toEqual( "test-marker-old" ); - expect(editor.getSession().getMarkers()["3"].type).to.equal("text"); - wrapper.setProps({ markers: markers }); - const editorB = wrapper.instance().splitEditor; - expect(editorB.getSession().getMarkers()).to.deep.equal({}); + expect(editor.getSession().getMarkers()["3"].type).toEqual("text"); + wrapper.rerender( + { + instance = node!; + }} + splits={2} + markers={markers} + /> + ); + const editorB = instance!.splitEditor; + expect(editorB.getSession().getMarkers()).toEqual({}); }); it("should add annotations", () => { @@ -533,27 +766,65 @@ describe("Split Component", () => { type: "error" } ]; - const wrapper = mount(, mountOptions); - const editor = wrapper.instance().splitEditor; - wrapper.setProps({ annotations: [annotations] }); - expect(editor.getSession().getAnnotations()).to.deep.equal(annotations); - wrapper.setProps({ annotations: null }); - expect(editor.getSession().getAnnotations()).to.deep.equal([]); + const wrapper = mount( + { + instance = node!; + }} + splits={2} + /> + ); + const editor = instance!.splitEditor; + wrapper.rerender( + { + instance = node!; + }} + splits={2} + annotations={annotations as any} + /> + ); + + expect(editor.getSession().getAnnotations()).toEqual(annotations[0]); + wrapper.rerender( + { + instance = node!; + }} + splits={2} + annotations={[]} + /> + ); + expect(editor.getSession().getAnnotations()).toEqual([]); }); it.skip("should trigger the focus on componentDidUpdate", () => { - const onFocusCallback = sinon.spy(); + const onFocusCallback = jest.fn(); const wrapper = mount( - , - mountOptions + { + instance = node!; + }} + splits={2} + onFocus={onFocusCallback} + /> ); // Read the focus - expect(onFocusCallback.callCount).to.equal(0); + expect(onFocusCallback).not.toBeCalled(); // Now trigger the componentDidUpdate - wrapper.setProps({ focus: true }); - expect(onFocusCallback.callCount).to.equal(1); + wrapper.rerender( + { + instance = node!; + }} + splits={2} + focus={true} + onFocus={onFocusCallback} + /> + ); + expect(onFocusCallback).toBeCalledTimes(1); }); }); });