react-ace
Version:
A react component for Ace Editor
570 lines (489 loc) • 17.7 kB
JavaScript
import { expect } from "chai";
import * as React from "react";
import * as sinon from "sinon";
import * as Enzyme from "enzyme";
import SplitEditor from "../../src/split";
import Adapter from "enzyme-adapter-react-16";
const mount = Enzyme.mount;
Enzyme.configure({ adapter: new Adapter() });
describe("Split Component", () => {
// Required for the document.getElementById used by Ace can work in the test environment
const domElement = document.getElementById("app");
const mountOptions = {
attachTo: domElement
};
describe("General", () => {
it("should render without problems with defaults properties", () => {
const wrapper = mount(<SplitEditor />, mountOptions);
expect(wrapper).to.exist;
});
it("should get the ace library from the onBeforeLoad callback", () => {
const beforeLoadCallback = sinon.spy();
mount(<SplitEditor onBeforeLoad={beforeLoadCallback} />, mountOptions);
expect(beforeLoadCallback.callCount).to.equal(1);
});
it("should trigger console warn if editorOption is called", () => {
const stub = sinon.stub(console, "warn");
const wrapper = mount(
<SplitEditor enableBasicAutocompletion={true} />,
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();
});
it("should set the editor props to the Ace element", () => {
const editorProperties = {
react: "setFromReact",
test: "setFromTest"
};
const wrapper = mount(
<SplitEditor editorProps={editorProperties} />,
mountOptions
);
const editor = wrapper.instance().splitEditor;
expect(editor.react).to.equal(editorProperties.react);
expect(editor.test).to.equal(editorProperties.test);
});
it("should update the orientation on componentDidUpdate", () => {
let orientation = "below";
const wrapper = mount(
<SplitEditor orientation={orientation} splits={2} />,
mountOptions
);
// Read set value
let editor = wrapper.instance().split;
expect(editor.getOrientation()).to.equal(editor.BELOW);
// Now trigger the componentDidUpdate
orientation = "beside";
wrapper.setProps({ orientation });
editor = wrapper.instance().split;
expect(editor.getOrientation()).to.equal(editor.BESIDE);
});
it("should update the orientation on componentDidUpdate", () => {
const wrapper = mount(<SplitEditor splits={2} />, mountOptions);
// Read set value
let editor = wrapper.instance().split;
expect(editor.getSplits()).to.equal(2);
// Now trigger the componentDidUpdate
wrapper.setProps({ splits: 4 });
editor = wrapper.instance().split;
expect(editor.getSplits()).to.equal(4);
});
it("should set the command for the Ace element", () => {
const commandsMock = [
{
name: "myReactAceTest",
bindKey: { win: "Ctrl-M", mac: "Command-M" },
exec: () => {},
readOnly: true
},
{
name: "myTestCommand",
bindKey: { win: "Ctrl-W", mac: "Command-W" },
exec: () => {},
readOnly: true
}
];
const wrapper = mount(
<SplitEditor commands={commandsMock} />,
mountOptions
);
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]
);
});
it("should change the command binding for the Ace element", () => {
const commandsMock = [
{
bindKey: { win: "ctrl-d", mac: "command-d" },
name: "selectMoreAfter",
exec: "selectMoreAfter"
}
];
const wrapper = mount(
<SplitEditor commands={commandsMock} />,
mountOptions
);
const editor = wrapper.instance().splitEditor;
const expected = [editor.commands.commands.removeline, "selectMoreAfter"];
expect(editor.commands.commandKeyBinding["ctrl-d"]).to.deep.equal(
expected
);
});
it("should get the editor from the onLoad callback", () => {
const loadCallback = sinon.spy();
const wrapper = mount(
<SplitEditor onLoad={loadCallback} />,
mountOptions
);
// Get the editor
const editor = wrapper.instance().split;
expect(loadCallback.callCount).to.equal(1);
expect(loadCallback.getCall(0).args[0]).to.deep.equal(editor);
});
it("should trigger the focus on mount", () => {
const onFocusCallback = sinon.spy();
mount(
<SplitEditor focus={true} onFocus={onFocusCallback} />,
mountOptions
);
// Read the focus
expect(onFocusCallback.callCount).to.equal(1);
});
it("should set editor to null on componentWillUnmount", () => {
const wrapper = mount(<SplitEditor />, 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;
});
});
describe("Events", () => {
it("should call the onChange method callback", () => {
const onChangeCallback = sinon.spy();
const wrapper = mount(
<SplitEditor onChange={onChangeCallback} />,
mountOptions
);
// Check is not previously called
expect(onChangeCallback.callCount).to.equal(0);
// 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");
});
it("should call the onCopy method", () => {
const onCopyCallback = sinon.spy();
const wrapper = mount(
<SplitEditor onCopy={onCopyCallback} />,
mountOptions
);
// Check is not previously called
expect(onCopyCallback.callCount).to.equal(0);
// Trigger the copy event
const expectText = "React Ace Test";
wrapper.instance().onCopy(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(
<SplitEditor onPaste={onPasteCallback} />,
mountOptions
);
// Check is not previously called
expect(onPasteCallback.callCount).to.equal(0);
// 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);
});
it("should call the onFocus method callback", () => {
const onFocusCallback = sinon.spy();
const wrapper = mount(
<SplitEditor onFocus={onFocusCallback} />,
mountOptions
);
// Check is not previously called
expect(onFocusCallback.callCount).to.equal(0);
// Trigger the focus event
wrapper.instance().split.focus();
expect(onFocusCallback.callCount).to.equal(1);
});
it("should call the onSelectionChange method callback", () => {
const onSelectionChangeCallback = sinon.spy();
const wrapper = mount(
<SplitEditor
onSelectionChange={onSelectionChangeCallback}
value="some value"
/>,
mountOptions
);
// Check is not previously called
expect(onSelectionChangeCallback.callCount).to.equal(0);
// Trigger the focus event
wrapper
.instance()
.splitEditor.getSession()
.selection.selectAll();
expect(onSelectionChangeCallback.callCount).to.equal(1);
});
it("should call the onCursorChange method callback", () => {
const onCursorChangeCallback = sinon.spy();
const wrapper = mount(
<SplitEditor value="a" onCursorChange={onCursorChangeCallback} />,
mountOptions
);
// The changeCursor event is called when the initial value is set
expect(onCursorChangeCallback.callCount).to.equal(1);
// Trigger the changeCursor event
wrapper
.instance()
.splitEditor.getSession()
.selection.moveCursorTo(0, 0);
expect(onCursorChangeCallback.callCount).to.equal(2);
});
it("should call the onBlur method callback", () => {
const onBlurCallback = sinon.spy();
const wrapper = mount(
<SplitEditor onBlur={onBlurCallback} />,
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);
});
it("should not trigger a component error to call the events without setting the props", () => {
const wrapper = mount(<SplitEditor />, 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(<SplitEditor setOptions={options} />, mountOptions);
// Read set value
const editor = wrapper.instance().splitEditor;
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(<SplitEditor minLines={1} />, mountOptions);
// Read set value
const editor = wrapper.instance().splitEditor;
expect(editor.getOption("minLines")).to.equal(1);
wrapper.setProps({ minLines: 2 });
expect(editor.getOption("minLines")).to.equal(2);
});
it("should update the mode on componentDidUpdate", () => {
const wrapper = mount(<SplitEditor mode="javascript" />, mountOptions);
// Read set value
const oldMode = wrapper.first("SplitEditor").props();
wrapper.setProps({ mode: "elixir" });
const newMode = wrapper.first("SplitEditor").props();
expect(oldMode).to.not.deep.equal(newMode);
});
it("should update many props on componentDidUpdate", () => {
const wrapper = mount(
<SplitEditor
theme="github"
keyboardHandler="vim"
fontSize={14}
wrapEnabled={true}
showPrintMargin={true}
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);
});
it("should update the className on componentDidUpdate", () => {
const className = "old-class";
const wrapper = mount(
<SplitEditor className={className} />,
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 anotherStartValue = "another start value";
const wrapper = mount(
<SplitEditor value={[startValue, anotherStartValue]} />,
mountOptions
);
// 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);
// 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);
});
it("should set up the markers", () => {
const markers = [
[
{
startRow: 3,
type: "text",
className: "test-marker"
}
]
];
const wrapper = mount(<SplitEditor markers={markers} />, mountOptions);
// Read the markers
const editor = wrapper.instance().splitEditor;
expect(editor.getSession().getMarkers()["3"].clazz).to.equal(
"test-marker"
);
expect(editor.getSession().getMarkers()["3"].type).to.equal("text");
});
it("should update the markers", () => {
const oldMarkers = [
[
{
startRow: 4,
type: "text",
className: "test-marker-old"
},
{
startRow: 7,
type: "foo",
className: "test-marker-old",
inFront: true
}
]
];
const markers = [
[
{
startRow: 3,
type: "text",
className: "test-marker-new",
inFront: true
},
{
startRow: 5,
type: "text",
className: "test-marker-new"
}
]
];
const wrapper = mount(<SplitEditor markers={oldMarkers} />, mountOptions);
// Read the markers
const editor = wrapper.instance().splitEditor;
expect(editor.getSession().getMarkers()["3"].clazz).to.equal(
"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(
"test-marker-new"
);
expect(editorB.getSession().getMarkers()["6"].type).to.equal("text");
});
it("should update the markers", () => {
const oldMarkers = [
[
{
startRow: 4,
type: "text",
className: "test-marker-old"
},
{
startRow: 7,
type: "foo",
className: "test-marker-old",
inFront: true
}
]
];
const markers = [[]];
const wrapper = mount(<SplitEditor markers={oldMarkers} />, mountOptions);
// Read the markers
const editor = wrapper.instance().splitEditor;
expect(editor.getSession().getMarkers()["3"].clazz).to.equal(
"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({});
});
it("should add annotations", () => {
const annotations = [
{
row: 3, // must be 0 based
column: 4, // must be 0 based
text: "error.message", // text to show in tooltip
type: "error"
}
];
const wrapper = mount(<SplitEditor />, 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([]);
});
it("should trigger the focus on componentDidUpdate", () => {
const onFocusCallback = sinon.spy();
const wrapper = mount(
<SplitEditor onFocus={onFocusCallback} />,
mountOptions
);
// Read the focus
expect(onFocusCallback.callCount).to.equal(0);
// Now trigger the componentDidUpdate
wrapper.setProps({ focus: true });
expect(onFocusCallback.callCount).to.equal(1);
});
});
});