import EventEmitter from "events" import { createSpy } from "expect" export class Range { constructor(...args) { this._args = args } } const ACE_STUBS = [ "setKeyboardHandler", "focus", "resize", "destroy", "setTheme", "setFontSize", "setHighlightActiveLine", "setReadOnly", "setShowPrintMargin", ] const SESSION_STUBS = [ "setMode", "setUseWrapMode", "setAnnotations" ] export class Session extends EventEmitter { constructor() { super() this.$markerId = 0 this._markers = [] SESSION_STUBS.forEach(stub => { this[stub] = createSpy() }) this.selection = new EventEmitter() this.selection.toJSON = createSpy().andReturn({fake: true}) this.selection.fromJSON = createSpy().andReturn({fake: true}) } addMarker = createSpy().andCall((marker) => { this._markers.push({...marker, id: this.$markerId++ }) }) getMarkers = createSpy().andCall(() => { return this._markers }) removeMarker = createSpy().andCall((markerId) => { this._markers = this._markers.filter(a => a.id !== markerId) }) } export default class Ace extends EventEmitter { constructor() { super() this.session = new Session() this.$options = {} this._undoStack = [""] this._undoPointer = 0 // It starts with nothing.. ACE_STUBS.forEach(stub => { this[stub] = createSpy() }) this.renderer = { setShowGutter: createSpy(), setScrollMargin: createSpy() } } edit = createSpy().andReturn(this) acequire = createSpy().andCall((module) => { if(module == "ace/range") { return { Range } } }) getSession = createSpy().andCall(() => { return this.session }) setOption = createSpy().andCall((option, val) => { this.$options[option] = val }) setOptions = createSpy().andCall((options) => { this.$options = {...this.$options, ...options} }) getOption = createSpy().andCall((optionName) => { return this.$options[optionName] }) setValue = createSpy().andCall((val, addToUndo=true) => { if(addToUndo) { // Wipe out line of redos this._undoStack = this._undoStack.slice(0, this._undoPointer + 1) // Add new value this._undoStack.push(val) this._undoPointer++ } this._value = val this.emit("change") // Remove this.emit("change") // Insert }) getValue = createSpy().andCall(() => { return this._value || "" }) // User API, which closer matches what we want to test ( ie: implementation can improve ) userTypes = createSpy().andCall((val) => { this.setValue(this.getValue() + val) }) userSees = createSpy().andCall(() => { return this.getValue() }) userUndo = createSpy().andCall(() => { this._undoPointer = this._undoPointer > 0 ? this._undoPointer - 1 : 0 this.setValue(this._undoStack[this._undoPointer], false) }) userRedo = createSpy().andCall(() => { const max = this._undoStack.length - 1 // const oriPointer = this._undoPointer this._undoPointer = this._undoPointer < max ? this._undoPointer + 1 : max this.setValue(this._undoStack[this._undoPointer], false) }) }