Merge branch 'master' into dh-async-repo

This commit is contained in:
joshaber
2015-11-10 15:23:54 -05:00
25 changed files with 5948 additions and 4470 deletions

View File

@@ -0,0 +1,28 @@
exports.beforeEach = (fn) ->
global.beforeEach ->
result = fn()
if result instanceof Promise
waitsForPromise(-> result)
exports.afterEach = (fn) ->
global.afterEach ->
result = fn()
if result instanceof Promise
waitsForPromise(-> result)
['it', 'fit', 'ffit', 'fffit'].forEach (name) ->
exports[name] = (description, fn) ->
global[name] description, ->
result = fn()
if result instanceof Promise
waitsForPromise(-> result)
waitsForPromise = (fn) ->
promise = fn()
waitsFor 'spec promise to resolve', 30000, (done) ->
promise.then(
done,
(error) ->
jasmine.getEnv().currentSpec.fail(error)
done()
)

View File

@@ -243,23 +243,6 @@ describe "AtomEnvironment", ->
atomEnvironment.destroy()
describe "::destroy()", ->
it "unsubscribes from all buffers", ->
atomEnvironment = new AtomEnvironment({applicationDelegate: atom.applicationDelegate, window, document})
waitsForPromise ->
atomEnvironment.workspace.open("sample.js")
runs ->
buffer = atomEnvironment.workspace.getActivePaneItem().buffer
pane = atomEnvironment.workspace.getActivePane()
pane.splitRight(copyActiveItem: true)
expect(atomEnvironment.workspace.getTextEditors().length).toBe 2
atomEnvironment.destroy()
expect(buffer.getSubscriptionCount()).toBe 0
describe "::openLocations(locations) (called via IPC from browser process)", ->
beforeEach ->
spyOn(atom.workspace, 'open')

View File

@@ -418,11 +418,11 @@ describe "DisplayBuffer", ->
describe "when creating a fold where one already exists", ->
it "returns existing fold and does't create new fold", ->
fold = displayBuffer.createFold(0, 10)
expect(displayBuffer.findMarkers(class: 'fold').length).toBe 1
expect(displayBuffer.foldsMarkerLayer.getMarkers().length).toBe 1
newFold = displayBuffer.createFold(0, 10)
expect(newFold).toBe fold
expect(displayBuffer.findMarkers(class: 'fold').length).toBe 1
expect(displayBuffer.foldsMarkerLayer.getMarkers().length).toBe 1
describe "when a fold is created inside an existing folded region", ->
it "creates/destroys the fold, but does not trigger change event", ->
@@ -829,7 +829,6 @@ describe "DisplayBuffer", ->
it "unsubscribes all display buffer markers from their underlying buffer marker (regression)", ->
marker = displayBuffer.markBufferPosition([12, 2])
displayBuffer.destroy()
expect(marker.bufferMarker.getSubscriptionCount()).toBe 0
expect( -> buffer.insert([12, 2], '\n')).not.toThrow()
describe "markers", ->
@@ -879,7 +878,7 @@ describe "DisplayBuffer", ->
[markerChangedHandler, marker] = []
beforeEach ->
marker = displayBuffer.markScreenRange([[5, 4], [5, 10]], maintainHistory: true)
marker = displayBuffer.addMarkerLayer(maintainHistory: true).markScreenRange([[5, 4], [5, 10]])
marker.onDidChange markerChangedHandler = jasmine.createSpy("markerChangedHandler")
it "triggers the 'changed' event whenever the markers head's screen position changes in the buffer or on screen", ->
@@ -1016,7 +1015,7 @@ describe "DisplayBuffer", ->
expect(markerChangedHandler).not.toHaveBeenCalled()
it "updates markers before emitting buffer change events, but does not notify their observers until the change event", ->
marker2 = displayBuffer.markBufferRange([[8, 1], [8, 1]], maintainHistory: true)
marker2 = displayBuffer.addMarkerLayer(maintainHistory: true).markBufferRange([[8, 1], [8, 1]])
marker2.onDidChange marker2ChangedHandler = jasmine.createSpy("marker2ChangedHandler")
displayBuffer.onDidChange changeHandler = jasmine.createSpy("changeHandler").andCallFake -> onDisplayBufferChange()
@@ -1237,11 +1236,6 @@ describe "DisplayBuffer", ->
decoration.destroy()
expect(displayBuffer.decorationForId(decoration.id)).not.toBeDefined()
it "does not leak disposables", ->
disposablesSize = displayBuffer.disposables.disposables.size
decoration.destroy()
expect(displayBuffer.disposables.disposables.size).toBe(disposablesSize - 1)
describe "when a decoration is updated via Decoration::update()", ->
it "emits an 'updated' event containing the new and old params", ->
decoration.onDidChangeProperties updatedSpy = jasmine.createSpy()
@@ -1249,7 +1243,7 @@ describe "DisplayBuffer", ->
{oldProperties, newProperties} = updatedSpy.mostRecentCall.args[0]
expect(oldProperties).toEqual decorationProperties
expect(newProperties).toEqual type: 'line-number', gutterName: 'line-number', class: 'two', id: decoration.id
expect(newProperties).toEqual {type: 'line-number', gutterName: 'line-number', class: 'two'}
describe "::getDecorations(properties)", ->
it "returns decorations matching the given optional properties", ->

View File

@@ -1 +0,0 @@
undefined

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -62,6 +62,13 @@ describe "TextEditorPresenter", ->
expectNoStateUpdate = (presenter, fn) -> expectStateUpdatedToBe(false, presenter, fn)
waitsForStateToUpdate = (presenter, fn) ->
waitsFor "presenter state to update", 1000, (done) ->
fn?()
disposable = presenter.onDidUpdateState ->
disposable.dispose()
process.nextTick(done)
tiledContentContract = (stateFn) ->
it "contains states for tiles that are visible on screen", ->
presenter = buildPresenter(explicitHeight: 6, scrollTop: 0, lineHeight: 1, tileSize: 2)
@@ -1147,55 +1154,62 @@ describe "TextEditorPresenter", ->
describe ".decorationClasses", ->
it "adds decoration classes to the relevant line state objects, both initially and when decorations change", ->
marker1 = editor.markBufferRange([[4, 0], [6, 2]], invalidate: 'touch', maintainHistory: true)
marker1 = editor.addMarkerLayer(maintainHistory: true).markBufferRange([[4, 0], [6, 2]], invalidate: 'touch')
decoration1 = editor.decorateMarker(marker1, type: 'line', class: 'a')
presenter = buildPresenter()
marker2 = editor.markBufferRange([[4, 0], [6, 2]], invalidate: 'touch', maintainHistory: true)
marker2 = editor.addMarkerLayer(maintainHistory: true).markBufferRange([[4, 0], [6, 2]], invalidate: 'touch')
decoration2 = editor.decorateMarker(marker2, type: 'line', class: 'b')
expect(lineStateForScreenRow(presenter, 3).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 4).decorationClasses).toEqual ['a', 'b']
expect(lineStateForScreenRow(presenter, 5).decorationClasses).toEqual ['a', 'b']
expect(lineStateForScreenRow(presenter, 6).decorationClasses).toEqual ['a', 'b']
expect(lineStateForScreenRow(presenter, 7).decorationClasses).toBeNull()
waitsForStateToUpdate presenter
runs ->
expect(lineStateForScreenRow(presenter, 3).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 4).decorationClasses).toEqual ['a', 'b']
expect(lineStateForScreenRow(presenter, 5).decorationClasses).toEqual ['a', 'b']
expect(lineStateForScreenRow(presenter, 6).decorationClasses).toEqual ['a', 'b']
expect(lineStateForScreenRow(presenter, 7).decorationClasses).toBeNull()
expectStateUpdate presenter, -> editor.getBuffer().insert([5, 0], 'x')
expect(marker1.isValid()).toBe false
expect(lineStateForScreenRow(presenter, 4).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 5).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 6).decorationClasses).toBeNull()
waitsForStateToUpdate presenter, -> editor.getBuffer().insert([5, 0], 'x')
runs ->
expect(marker1.isValid()).toBe false
expect(lineStateForScreenRow(presenter, 4).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 5).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 6).decorationClasses).toBeNull()
expectStateUpdate presenter, -> editor.undo()
expect(lineStateForScreenRow(presenter, 3).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 4).decorationClasses).toEqual ['a', 'b']
expect(lineStateForScreenRow(presenter, 5).decorationClasses).toEqual ['a', 'b']
expect(lineStateForScreenRow(presenter, 6).decorationClasses).toEqual ['a', 'b']
expect(lineStateForScreenRow(presenter, 7).decorationClasses).toBeNull()
waitsForStateToUpdate presenter, -> editor.undo()
runs ->
expect(lineStateForScreenRow(presenter, 3).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 4).decorationClasses).toEqual ['a', 'b']
expect(lineStateForScreenRow(presenter, 5).decorationClasses).toEqual ['a', 'b']
expect(lineStateForScreenRow(presenter, 6).decorationClasses).toEqual ['a', 'b']
expect(lineStateForScreenRow(presenter, 7).decorationClasses).toBeNull()
expectStateUpdate presenter, -> marker1.setBufferRange([[2, 0], [4, 2]])
expect(lineStateForScreenRow(presenter, 1).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 2).decorationClasses).toEqual ['a']
expect(lineStateForScreenRow(presenter, 3).decorationClasses).toEqual ['a']
expect(lineStateForScreenRow(presenter, 4).decorationClasses).toEqual ['a', 'b']
expect(lineStateForScreenRow(presenter, 5).decorationClasses).toEqual ['b']
expect(lineStateForScreenRow(presenter, 6).decorationClasses).toEqual ['b']
expect(lineStateForScreenRow(presenter, 7).decorationClasses).toBeNull()
waitsForStateToUpdate presenter, -> marker1.setBufferRange([[2, 0], [4, 2]])
runs ->
expect(lineStateForScreenRow(presenter, 1).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 2).decorationClasses).toEqual ['a']
expect(lineStateForScreenRow(presenter, 3).decorationClasses).toEqual ['a']
expect(lineStateForScreenRow(presenter, 4).decorationClasses).toEqual ['a', 'b']
expect(lineStateForScreenRow(presenter, 5).decorationClasses).toEqual ['b']
expect(lineStateForScreenRow(presenter, 6).decorationClasses).toEqual ['b']
expect(lineStateForScreenRow(presenter, 7).decorationClasses).toBeNull()
expectStateUpdate presenter, -> decoration1.destroy()
expect(lineStateForScreenRow(presenter, 2).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 3).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 4).decorationClasses).toEqual ['b']
expect(lineStateForScreenRow(presenter, 5).decorationClasses).toEqual ['b']
expect(lineStateForScreenRow(presenter, 6).decorationClasses).toEqual ['b']
expect(lineStateForScreenRow(presenter, 7).decorationClasses).toBeNull()
waitsForStateToUpdate presenter, -> decoration1.destroy()
runs ->
expect(lineStateForScreenRow(presenter, 2).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 3).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 4).decorationClasses).toEqual ['b']
expect(lineStateForScreenRow(presenter, 5).decorationClasses).toEqual ['b']
expect(lineStateForScreenRow(presenter, 6).decorationClasses).toEqual ['b']
expect(lineStateForScreenRow(presenter, 7).decorationClasses).toBeNull()
expectStateUpdate presenter, -> marker2.destroy()
expect(lineStateForScreenRow(presenter, 2).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 3).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 4).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 5).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 6).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 7).decorationClasses).toBeNull()
waitsForStateToUpdate presenter, -> marker2.destroy()
runs ->
expect(lineStateForScreenRow(presenter, 2).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 3).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 4).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 5).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 6).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 7).decorationClasses).toBeNull()
it "honors the 'onlyEmpty' option on line decorations", ->
presenter = buildPresenter()
@@ -1206,11 +1220,12 @@ describe "TextEditorPresenter", ->
expect(lineStateForScreenRow(presenter, 5).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 6).decorationClasses).toBeNull()
expectStateUpdate presenter, -> marker.clearTail()
waitsForStateToUpdate presenter, -> marker.clearTail()
expect(lineStateForScreenRow(presenter, 4).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 5).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 6).decorationClasses).toEqual ['a']
runs ->
expect(lineStateForScreenRow(presenter, 4).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 5).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 6).decorationClasses).toEqual ['a']
it "honors the 'onlyNonEmpty' option on line decorations", ->
presenter = buildPresenter()
@@ -1221,40 +1236,49 @@ describe "TextEditorPresenter", ->
expect(lineStateForScreenRow(presenter, 5).decorationClasses).toEqual ['a']
expect(lineStateForScreenRow(presenter, 6).decorationClasses).toEqual ['a']
expectStateUpdate presenter, -> marker.clearTail()
waitsForStateToUpdate presenter, -> marker.clearTail()
expect(lineStateForScreenRow(presenter, 6).decorationClasses).toBeNull()
runs ->
expect(lineStateForScreenRow(presenter, 6).decorationClasses).toBeNull()
it "honors the 'onlyHead' option on line decorations", ->
presenter = buildPresenter()
marker = editor.markBufferRange([[4, 0], [6, 2]])
decoration = editor.decorateMarker(marker, type: 'line', class: 'a', onlyHead: true)
waitsForStateToUpdate presenter, ->
marker = editor.markBufferRange([[4, 0], [6, 2]])
editor.decorateMarker(marker, type: 'line', class: 'a', onlyHead: true)
expect(lineStateForScreenRow(presenter, 4).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 5).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 6).decorationClasses).toEqual ['a']
runs ->
expect(lineStateForScreenRow(presenter, 4).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 5).decorationClasses).toBeNull()
expect(lineStateForScreenRow(presenter, 6).decorationClasses).toEqual ['a']
it "does not decorate the last line of a non-empty line decoration range if it ends at column 0", ->
presenter = buildPresenter()
marker = editor.markBufferRange([[4, 0], [6, 0]])
decoration = editor.decorateMarker(marker, type: 'line', class: 'a')
waitsForStateToUpdate presenter, ->
marker = editor.markBufferRange([[4, 0], [6, 0]])
editor.decorateMarker(marker, type: 'line', class: 'a')
expect(lineStateForScreenRow(presenter, 4).decorationClasses).toEqual ['a']
expect(lineStateForScreenRow(presenter, 5).decorationClasses).toEqual ['a']
expect(lineStateForScreenRow(presenter, 6).decorationClasses).toBeNull()
runs ->
expect(lineStateForScreenRow(presenter, 4).decorationClasses).toEqual ['a']
expect(lineStateForScreenRow(presenter, 5).decorationClasses).toEqual ['a']
expect(lineStateForScreenRow(presenter, 6).decorationClasses).toBeNull()
it "does not apply line decorations to mini editors", ->
editor.setMini(true)
presenter = buildPresenter(explicitHeight: 10)
marker = editor.markBufferRange([[0, 0], [0, 0]])
decoration = editor.decorateMarker(marker, type: 'line', class: 'a')
expect(lineStateForScreenRow(presenter, 0).decorationClasses).toBeNull()
expectStateUpdate presenter, -> editor.setMini(false)
expect(lineStateForScreenRow(presenter, 0).decorationClasses).toEqual ['cursor-line', 'a']
waitsForStateToUpdate presenter, ->
marker = editor.markBufferRange([[0, 0], [0, 0]])
decoration = editor.decorateMarker(marker, type: 'line', class: 'a')
expectStateUpdate presenter, -> editor.setMini(true)
expect(lineStateForScreenRow(presenter, 0).decorationClasses).toBeNull()
runs ->
expect(lineStateForScreenRow(presenter, 0).decorationClasses).toBeNull()
expectStateUpdate presenter, -> editor.setMini(false)
expect(lineStateForScreenRow(presenter, 0).decorationClasses).toEqual ['cursor-line', 'a']
expectStateUpdate presenter, -> editor.setMini(true)
expect(lineStateForScreenRow(presenter, 0).decorationClasses).toBeNull()
it "only applies decorations to screen rows that are spanned by their marker when lines are soft-wrapped", ->
editor.setText("a line that wraps, ok")
@@ -1268,9 +1292,12 @@ describe "TextEditorPresenter", ->
expect(lineStateForScreenRow(presenter, 0).decorationClasses).toContain 'a'
expect(lineStateForScreenRow(presenter, 1).decorationClasses).toBeNull()
marker.setBufferRange([[0, 0], [0, Infinity]])
expect(lineStateForScreenRow(presenter, 0).decorationClasses).toContain 'a'
expect(lineStateForScreenRow(presenter, 1).decorationClasses).toContain 'a'
waitsForStateToUpdate presenter, ->
marker.setBufferRange([[0, 0], [0, Infinity]])
runs ->
expect(lineStateForScreenRow(presenter, 0).decorationClasses).toContain 'a'
expect(lineStateForScreenRow(presenter, 1).decorationClasses).toContain 'a'
describe ".cursors", ->
stateForCursor = (presenter, cursorIndex) ->
@@ -1740,41 +1767,51 @@ describe "TextEditorPresenter", ->
expectUndefinedStateForSelection(presenter, 1)
# moving into view
expectStateUpdate presenter, -> editor.getSelections()[1].setBufferRange([[2, 4], [2, 6]], autoscroll: false)
expectValues stateForSelectionInTile(presenter, 1, 2), {
regions: [{top: 0, left: 4 * 10, width: 2 * 10, height: 10}]
}
waitsForStateToUpdate presenter, -> editor.getSelections()[1].setBufferRange([[2, 4], [2, 6]], autoscroll: false)
runs ->
expectValues stateForSelectionInTile(presenter, 1, 2), {
regions: [{top: 0, left: 4 * 10, width: 2 * 10, height: 10}]
}
# becoming empty
expectStateUpdate presenter, -> editor.getSelections()[1].clear(autoscroll: false)
expectUndefinedStateForSelection(presenter, 1)
waitsForStateToUpdate presenter, -> editor.getSelections()[1].clear(autoscroll: false)
runs ->
expectUndefinedStateForSelection(presenter, 1)
# becoming non-empty
expectStateUpdate presenter, -> editor.getSelections()[1].setBufferRange([[2, 4], [2, 6]], autoscroll: false)
expectValues stateForSelectionInTile(presenter, 1, 2), {
regions: [{top: 0, left: 4 * 10, width: 2 * 10, height: 10}]
}
waitsForStateToUpdate presenter, -> editor.getSelections()[1].setBufferRange([[2, 4], [2, 6]], autoscroll: false)
runs ->
expectValues stateForSelectionInTile(presenter, 1, 2), {
regions: [{top: 0, left: 4 * 10, width: 2 * 10, height: 10}]
}
# moving out of view
expectStateUpdate presenter, -> editor.getSelections()[1].setBufferRange([[3, 4], [3, 6]], autoscroll: false)
expectUndefinedStateForSelection(presenter, 1)
waitsForStateToUpdate presenter, -> editor.getSelections()[1].setBufferRange([[3, 4], [3, 6]], autoscroll: false)
runs ->
expectUndefinedStateForSelection(presenter, 1)
# adding
expectStateUpdate presenter, -> editor.addSelectionForBufferRange([[1, 4], [1, 6]], autoscroll: false)
expectValues stateForSelectionInTile(presenter, 2, 0), {
regions: [{top: 10, left: 4 * 10, width: 2 * 10, height: 10}]
}
waitsForStateToUpdate presenter, -> editor.addSelectionForBufferRange([[1, 4], [1, 6]], autoscroll: false)
runs ->
expectValues stateForSelectionInTile(presenter, 2, 0), {
regions: [{top: 10, left: 4 * 10, width: 2 * 10, height: 10}]
}
# moving added selection
expectStateUpdate presenter, -> editor.getSelections()[2].setBufferRange([[1, 4], [1, 8]], autoscroll: false)
expectValues stateForSelectionInTile(presenter, 2, 0), {
regions: [{top: 10, left: 4 * 10, width: 4 * 10, height: 10}]
}
waitsForStateToUpdate presenter, -> editor.getSelections()[2].setBufferRange([[1, 4], [1, 8]], autoscroll: false)
# destroying
destroyedSelection = editor.getSelections()[2]
expectStateUpdate presenter, -> destroyedSelection.destroy()
expectUndefinedStateForHighlight(presenter, destroyedSelection.decoration)
destroyedSelection = null
runs ->
expectValues stateForSelectionInTile(presenter, 2, 0), {
regions: [{top: 10, left: 4 * 10, width: 4 * 10, height: 10}]
}
# destroying
destroyedSelection = editor.getSelections()[2]
waitsForStateToUpdate presenter, -> destroyedSelection.destroy()
runs ->
expectUndefinedStateForHighlight(presenter, destroyedSelection.decoration)
it "updates when highlight decorations' properties are updated", ->
marker = editor.markBufferPosition([2, 2])
@@ -1784,44 +1821,45 @@ describe "TextEditorPresenter", ->
expectUndefinedStateForHighlight(presenter, highlight)
expectStateUpdate presenter, ->
waitsForStateToUpdate presenter, ->
marker.setBufferRange([[2, 2], [2, 4]])
highlight.setProperties(class: 'b', type: 'highlight')
expectValues stateForHighlightInTile(presenter, highlight, 2), {class: 'b'}
runs ->
expectValues stateForHighlightInTile(presenter, highlight, 2), {class: 'b'}
it "increments the .flashCount and sets the .flashClass and .flashDuration when the highlight model flashes", ->
presenter = buildPresenter(explicitHeight: 30, scrollTop: 20, tileSize: 2)
marker = editor.markBufferPosition([2, 2])
highlight = editor.decorateMarker(marker, type: 'highlight', class: 'a')
expectStateUpdate presenter, ->
waitsForStateToUpdate presenter, ->
marker.setBufferRange([[2, 2], [5, 2]])
highlight.flash('b', 500)
runs ->
expectValues stateForHighlightInTile(presenter, highlight, 2), {
flashClass: 'b'
flashDuration: 500
flashCount: 1
}
expectValues stateForHighlightInTile(presenter, highlight, 4), {
flashClass: 'b'
flashDuration: 500
flashCount: 1
}
expectValues stateForHighlightInTile(presenter, highlight, 2), {
flashClass: 'b'
flashDuration: 500
flashCount: 1
}
expectValues stateForHighlightInTile(presenter, highlight, 4), {
flashClass: 'b'
flashDuration: 500
flashCount: 1
}
expectStateUpdate presenter, -> highlight.flash('c', 600)
expectValues stateForHighlightInTile(presenter, highlight, 2), {
flashClass: 'c'
flashDuration: 600
flashCount: 2
}
expectValues stateForHighlightInTile(presenter, highlight, 4), {
flashClass: 'c'
flashDuration: 600
flashCount: 2
}
waitsForStateToUpdate presenter, -> highlight.flash('c', 600)
runs ->
expectValues stateForHighlightInTile(presenter, highlight, 2), {
flashClass: 'c'
flashDuration: 600
flashCount: 2
}
expectValues stateForHighlightInTile(presenter, highlight, 4), {
flashClass: 'c'
flashDuration: 600
flashCount: 2
}
describe ".overlays", ->
[item] = []
@@ -1829,7 +1867,7 @@ describe "TextEditorPresenter", ->
presenter.getState().content.overlays[decoration.id]
it "contains state for overlay decorations both initially and when their markers move", ->
marker = editor.markBufferPosition([2, 13], invalidate: 'touch', maintainHistory: true)
marker = editor.addMarkerLayer(maintainHistory: true).markBufferPosition([2, 13], invalidate: 'touch')
decoration = editor.decorateMarker(marker, {type: 'overlay', item})
presenter = buildPresenter(explicitHeight: 30, scrollTop: 20)
@@ -1840,40 +1878,47 @@ describe "TextEditorPresenter", ->
}
# Change range
expectStateUpdate presenter, -> marker.setBufferRange([[2, 13], [4, 6]])
expectValues stateForOverlay(presenter, decoration), {
item: item
pixelPosition: {top: 5 * 10 - presenter.state.content.scrollTop, left: 6 * 10}
}
waitsForStateToUpdate presenter, -> marker.setBufferRange([[2, 13], [4, 6]])
runs ->
expectValues stateForOverlay(presenter, decoration), {
item: item
pixelPosition: {top: 5 * 10 - presenter.state.content.scrollTop, left: 6 * 10}
}
# Valid -> invalid
expectStateUpdate presenter, -> editor.getBuffer().insert([2, 14], 'x')
expect(stateForOverlay(presenter, decoration)).toBeUndefined()
# Valid -> invalid
waitsForStateToUpdate presenter, -> editor.getBuffer().insert([2, 14], 'x')
runs ->
expect(stateForOverlay(presenter, decoration)).toBeUndefined()
# Invalid -> valid
expectStateUpdate presenter, -> editor.undo()
expectValues stateForOverlay(presenter, decoration), {
item: item
pixelPosition: {top: 5 * 10 - presenter.state.content.scrollTop, left: 6 * 10}
}
# Invalid -> valid
waitsForStateToUpdate presenter, -> editor.undo()
runs ->
expectValues stateForOverlay(presenter, decoration), {
item: item
pixelPosition: {top: 5 * 10 - presenter.state.content.scrollTop, left: 6 * 10}
}
# Reverse direction
expectStateUpdate presenter, -> marker.setBufferRange([[2, 13], [4, 6]], reversed: true)
expectValues stateForOverlay(presenter, decoration), {
item: item
pixelPosition: {top: 3 * 10 - presenter.state.content.scrollTop, left: 13 * 10}
}
waitsForStateToUpdate presenter, -> marker.setBufferRange([[2, 13], [4, 6]], reversed: true)
runs ->
expectValues stateForOverlay(presenter, decoration), {
item: item
pixelPosition: {top: 3 * 10 - presenter.state.content.scrollTop, left: 13 * 10}
}
# Destroy
decoration.destroy()
expect(stateForOverlay(presenter, decoration)).toBeUndefined()
waitsForStateToUpdate presenter, -> decoration.destroy()
runs ->
expect(stateForOverlay(presenter, decoration)).toBeUndefined()
# Add
decoration2 = editor.decorateMarker(marker, {type: 'overlay', item})
expectValues stateForOverlay(presenter, decoration2), {
item: item
pixelPosition: {top: 3 * 10 - presenter.state.content.scrollTop, left: 13 * 10}
}
decoration2 = null
waitsForStateToUpdate presenter, -> decoration2 = editor.decorateMarker(marker, {type: 'overlay', item})
runs ->
expectValues stateForOverlay(presenter, decoration2), {
item: item
pixelPosition: {top: 3 * 10 - presenter.state.content.scrollTop, left: 13 * 10}
}
it "updates when character widths changes", ->
scrollTop = 20
@@ -2308,11 +2353,11 @@ describe "TextEditorPresenter", ->
describe ".decorationClasses", ->
it "adds decoration classes to the relevant line number state objects, both initially and when decorations change", ->
marker1 = editor.markBufferRange([[4, 0], [6, 2]], invalidate: 'touch', maintainHistory: true)
marker1 = editor.addMarkerLayer(maintainHistory: true).markBufferRange([[4, 0], [6, 2]], invalidate: 'touch')
decoration1 = editor.decorateMarker(marker1, type: 'line-number', class: 'a')
presenter = buildPresenter()
marker2 = editor.markBufferRange([[4, 0], [6, 2]], invalidate: 'touch', maintainHistory: true)
marker2 = editor.addMarkerLayer(maintainHistory: true).markBufferRange([[4, 0], [6, 2]], invalidate: 'touch')
decoration2 = editor.decorateMarker(marker2, type: 'line-number', class: 'b')
presenter = buildPresenter()
expect(lineNumberStateForScreenRow(presenter, 3).decorationClasses).toBeNull()
expect(lineNumberStateForScreenRow(presenter, 4).decorationClasses).toEqual ['a', 'b']
@@ -2320,85 +2365,92 @@ describe "TextEditorPresenter", ->
expect(lineNumberStateForScreenRow(presenter, 6).decorationClasses).toEqual ['a', 'b']
expect(lineNumberStateForScreenRow(presenter, 7).decorationClasses).toBeNull()
expectStateUpdate presenter, -> editor.getBuffer().insert([5, 0], 'x')
expect(marker1.isValid()).toBe false
expect(lineNumberStateForScreenRow(presenter, 4).decorationClasses).toBeNull()
expect(lineNumberStateForScreenRow(presenter, 5).decorationClasses).toBeNull()
expect(lineNumberStateForScreenRow(presenter, 6).decorationClasses).toBeNull()
waitsForStateToUpdate presenter, -> editor.getBuffer().insert([5, 0], 'x')
runs ->
expect(marker1.isValid()).toBe false
expect(lineNumberStateForScreenRow(presenter, 4).decorationClasses).toBeNull()
expect(lineNumberStateForScreenRow(presenter, 5).decorationClasses).toBeNull()
expect(lineNumberStateForScreenRow(presenter, 6).decorationClasses).toBeNull()
expectStateUpdate presenter, -> editor.undo()
expect(lineNumberStateForScreenRow(presenter, 3).decorationClasses).toBeNull()
expect(lineNumberStateForScreenRow(presenter, 4).decorationClasses).toEqual ['a', 'b']
expect(lineNumberStateForScreenRow(presenter, 5).decorationClasses).toEqual ['a', 'b']
expect(lineNumberStateForScreenRow(presenter, 6).decorationClasses).toEqual ['a', 'b']
expect(lineNumberStateForScreenRow(presenter, 7).decorationClasses).toBeNull()
waitsForStateToUpdate presenter, -> editor.undo()
runs ->
expect(lineNumberStateForScreenRow(presenter, 3).decorationClasses).toBeNull()
expect(lineNumberStateForScreenRow(presenter, 4).decorationClasses).toEqual ['a', 'b']
expect(lineNumberStateForScreenRow(presenter, 5).decorationClasses).toEqual ['a', 'b']
expect(lineNumberStateForScreenRow(presenter, 6).decorationClasses).toEqual ['a', 'b']
expect(lineNumberStateForScreenRow(presenter, 7).decorationClasses).toBeNull()
expectStateUpdate presenter, -> marker1.setBufferRange([[2, 0], [4, 2]])
expect(lineNumberStateForScreenRow(presenter, 1).decorationClasses).toBeNull()
expect(lineNumberStateForScreenRow(presenter, 2).decorationClasses).toEqual ['a']
expect(lineNumberStateForScreenRow(presenter, 3).decorationClasses).toEqual ['a']
expect(lineNumberStateForScreenRow(presenter, 4).decorationClasses).toEqual ['a', 'b']
expect(lineNumberStateForScreenRow(presenter, 5).decorationClasses).toEqual ['b']
expect(lineNumberStateForScreenRow(presenter, 6).decorationClasses).toEqual ['b']
expect(lineNumberStateForScreenRow(presenter, 7).decorationClasses).toBeNull()
waitsForStateToUpdate presenter, -> marker1.setBufferRange([[2, 0], [4, 2]])
runs ->
expect(lineNumberStateForScreenRow(presenter, 1).decorationClasses).toBeNull()
expect(lineNumberStateForScreenRow(presenter, 2).decorationClasses).toEqual ['a']
expect(lineNumberStateForScreenRow(presenter, 3).decorationClasses).toEqual ['a']
expect(lineNumberStateForScreenRow(presenter, 4).decorationClasses).toEqual ['a', 'b']
expect(lineNumberStateForScreenRow(presenter, 5).decorationClasses).toEqual ['b']
expect(lineNumberStateForScreenRow(presenter, 6).decorationClasses).toEqual ['b']
expect(lineNumberStateForScreenRow(presenter, 7).decorationClasses).toBeNull()
expectStateUpdate presenter, -> decoration1.destroy()
expect(lineNumberStateForScreenRow(presenter, 2).decorationClasses).toBeNull()
expect(lineNumberStateForScreenRow(presenter, 3).decorationClasses).toBeNull()
expect(lineNumberStateForScreenRow(presenter, 4).decorationClasses).toEqual ['b']
expect(lineNumberStateForScreenRow(presenter, 5).decorationClasses).toEqual ['b']
expect(lineNumberStateForScreenRow(presenter, 6).decorationClasses).toEqual ['b']
expect(lineNumberStateForScreenRow(presenter, 7).decorationClasses).toBeNull()
waitsForStateToUpdate presenter, -> decoration1.destroy()
runs ->
expect(lineNumberStateForScreenRow(presenter, 2).decorationClasses).toBeNull()
expect(lineNumberStateForScreenRow(presenter, 3).decorationClasses).toBeNull()
expect(lineNumberStateForScreenRow(presenter, 4).decorationClasses).toEqual ['b']
expect(lineNumberStateForScreenRow(presenter, 5).decorationClasses).toEqual ['b']
expect(lineNumberStateForScreenRow(presenter, 6).decorationClasses).toEqual ['b']
expect(lineNumberStateForScreenRow(presenter, 7).decorationClasses).toBeNull()
expectStateUpdate presenter, -> marker2.destroy()
expect(lineNumberStateForScreenRow(presenter, 2).decorationClasses).toBeNull()
expect(lineNumberStateForScreenRow(presenter, 3).decorationClasses).toBeNull()
expect(lineNumberStateForScreenRow(presenter, 4).decorationClasses).toBeNull()
expect(lineNumberStateForScreenRow(presenter, 5).decorationClasses).toBeNull()
expect(lineNumberStateForScreenRow(presenter, 6).decorationClasses).toBeNull()
expect(lineNumberStateForScreenRow(presenter, 7).decorationClasses).toBeNull()
waitsForStateToUpdate presenter, -> marker2.destroy()
runs ->
expect(lineNumberStateForScreenRow(presenter, 2).decorationClasses).toBeNull()
expect(lineNumberStateForScreenRow(presenter, 3).decorationClasses).toBeNull()
expect(lineNumberStateForScreenRow(presenter, 4).decorationClasses).toBeNull()
expect(lineNumberStateForScreenRow(presenter, 5).decorationClasses).toBeNull()
expect(lineNumberStateForScreenRow(presenter, 6).decorationClasses).toBeNull()
expect(lineNumberStateForScreenRow(presenter, 7).decorationClasses).toBeNull()
it "honors the 'onlyEmpty' option on line-number decorations", ->
presenter = buildPresenter()
marker = editor.markBufferRange([[4, 0], [6, 1]])
decoration = editor.decorateMarker(marker, type: 'line-number', class: 'a', onlyEmpty: true)
presenter = buildPresenter()
expect(lineNumberStateForScreenRow(presenter, 4).decorationClasses).toBeNull()
expect(lineNumberStateForScreenRow(presenter, 5).decorationClasses).toBeNull()
expect(lineNumberStateForScreenRow(presenter, 6).decorationClasses).toBeNull()
expectStateUpdate presenter, -> marker.clearTail()
waitsForStateToUpdate presenter, -> marker.clearTail()
expect(lineNumberStateForScreenRow(presenter, 4).decorationClasses).toBeNull()
expect(lineNumberStateForScreenRow(presenter, 5).decorationClasses).toBeNull()
expect(lineNumberStateForScreenRow(presenter, 6).decorationClasses).toEqual ['a']
runs ->
expect(lineNumberStateForScreenRow(presenter, 4).decorationClasses).toBeNull()
expect(lineNumberStateForScreenRow(presenter, 5).decorationClasses).toBeNull()
expect(lineNumberStateForScreenRow(presenter, 6).decorationClasses).toEqual ['a']
it "honors the 'onlyNonEmpty' option on line-number decorations", ->
presenter = buildPresenter()
marker = editor.markBufferRange([[4, 0], [6, 2]])
decoration = editor.decorateMarker(marker, type: 'line-number', class: 'a', onlyNonEmpty: true)
presenter = buildPresenter()
expect(lineNumberStateForScreenRow(presenter, 4).decorationClasses).toEqual ['a']
expect(lineNumberStateForScreenRow(presenter, 5).decorationClasses).toEqual ['a']
expect(lineNumberStateForScreenRow(presenter, 6).decorationClasses).toEqual ['a']
expectStateUpdate presenter, -> marker.clearTail()
waitsForStateToUpdate presenter, -> marker.clearTail()
expect(lineNumberStateForScreenRow(presenter, 6).decorationClasses).toBeNull()
runs ->
expect(lineNumberStateForScreenRow(presenter, 6).decorationClasses).toBeNull()
it "honors the 'onlyHead' option on line-number decorations", ->
presenter = buildPresenter()
marker = editor.markBufferRange([[4, 0], [6, 2]])
decoration = editor.decorateMarker(marker, type: 'line-number', class: 'a', onlyHead: true)
presenter = buildPresenter()
expect(lineNumberStateForScreenRow(presenter, 4).decorationClasses).toBeNull()
expect(lineNumberStateForScreenRow(presenter, 5).decorationClasses).toBeNull()
expect(lineNumberStateForScreenRow(presenter, 6).decorationClasses).toEqual ['a']
it "does not decorate the last line of a non-empty line-number decoration range if it ends at column 0", ->
presenter = buildPresenter()
marker = editor.markBufferRange([[4, 0], [6, 0]])
decoration = editor.decorateMarker(marker, type: 'line-number', class: 'a')
presenter = buildPresenter()
expect(lineNumberStateForScreenRow(presenter, 4).decorationClasses).toEqual ['a']
expect(lineNumberStateForScreenRow(presenter, 5).decorationClasses).toEqual ['a']
@@ -2430,9 +2482,10 @@ describe "TextEditorPresenter", ->
expect(lineNumberStateForScreenRow(presenter, 0).decorationClasses).toContain 'a'
expect(lineNumberStateForScreenRow(presenter, 1).decorationClasses).toBeNull()
marker.setBufferRange([[0, 0], [0, Infinity]])
expect(lineNumberStateForScreenRow(presenter, 0).decorationClasses).toContain 'a'
expect(lineNumberStateForScreenRow(presenter, 1).decorationClasses).toContain 'a'
waitsForStateToUpdate presenter, -> marker.setBufferRange([[0, 0], [0, Infinity]])
runs ->
expect(lineNumberStateForScreenRow(presenter, 0).decorationClasses).toContain 'a'
expect(lineNumberStateForScreenRow(presenter, 1).decorationClasses).toContain 'a'
describe ".foldable", ->
it "marks line numbers at the start of a foldable region as foldable", ->
@@ -2565,14 +2618,15 @@ describe "TextEditorPresenter", ->
it "updates when a decoration's marker is modified", ->
# This update will move decoration1 out of view.
expectStateUpdate presenter, ->
waitsForStateToUpdate presenter, ->
newRange = new Range([13, 0], [14, 0])
marker1.setBufferRange(newRange)
decorationState = getContentForGutterWithName(presenter, 'test-gutter')
expect(decorationState[decoration1.id]).toBeUndefined()
expect(decorationState[decoration2.id].top).toBeDefined()
expect(decorationState[decoration3.id]).toBeUndefined()
runs ->
decorationState = getContentForGutterWithName(presenter, 'test-gutter')
expect(decorationState[decoration1.id]).toBeUndefined()
expect(decorationState[decoration2.id].top).toBeDefined()
expect(decorationState[decoration3.id]).toBeUndefined()
describe "when a decoration's properties are modified", ->
it "updates the item applied to the decoration, if the decoration item is changed", ->
@@ -2584,12 +2638,14 @@ describe "TextEditorPresenter", ->
gutterName: 'test-gutter'
class: 'test-class'
item: newItem
expectStateUpdate presenter, -> decoration1.setProperties(newDecorationParams)
decorationState = getContentForGutterWithName(presenter, 'test-gutter')
expect(decorationState[decoration1.id].item).toBe newItem
expect(decorationState[decoration2.id].item).toBe decorationItem
expect(decorationState[decoration3.id]).toBeUndefined()
waitsForStateToUpdate presenter, -> decoration1.setProperties(newDecorationParams)
runs ->
decorationState = getContentForGutterWithName(presenter, 'test-gutter')
expect(decorationState[decoration1.id].item).toBe newItem
expect(decorationState[decoration2.id].item).toBe decorationItem
expect(decorationState[decoration3.id]).toBeUndefined()
it "updates the class applied to the decoration, if the decoration class is changed", ->
# This changes the decoration item. The visibility of the decoration should not be affected.
@@ -2598,12 +2654,13 @@ describe "TextEditorPresenter", ->
gutterName: 'test-gutter'
class: 'new-test-class'
item: decorationItem
expectStateUpdate presenter, -> decoration1.setProperties(newDecorationParams)
waitsForStateToUpdate presenter, -> decoration1.setProperties(newDecorationParams)
decorationState = getContentForGutterWithName(presenter, 'test-gutter')
expect(decorationState[decoration1.id].class).toBe 'new-test-class'
expect(decorationState[decoration2.id].class).toBe 'test-class'
expect(decorationState[decoration3.id]).toBeUndefined()
runs ->
decorationState = getContentForGutterWithName(presenter, 'test-gutter')
expect(decorationState[decoration1.id].class).toBe 'new-test-class'
expect(decorationState[decoration2.id].class).toBe 'test-class'
expect(decorationState[decoration3.id]).toBeUndefined()
it "updates the type of the decoration, if the decoration type is changed", ->
# This changes the type of the decoration. This should remove the decoration from the gutter.
@@ -2612,12 +2669,13 @@ describe "TextEditorPresenter", ->
gutterName: 'test-gutter' # This is an invalid/meaningless option here, but it shouldn't matter.
class: 'test-class'
item: decorationItem
expectStateUpdate presenter, -> decoration1.setProperties(newDecorationParams)
waitsForStateToUpdate presenter, -> decoration1.setProperties(newDecorationParams)
decorationState = getContentForGutterWithName(presenter, 'test-gutter')
expect(decorationState[decoration1.id]).toBeUndefined()
expect(decorationState[decoration2.id].top).toBeDefined()
expect(decorationState[decoration3.id]).toBeUndefined()
runs ->
decorationState = getContentForGutterWithName(presenter, 'test-gutter')
expect(decorationState[decoration1.id]).toBeUndefined()
expect(decorationState[decoration2.id].top).toBeDefined()
expect(decorationState[decoration3.id]).toBeUndefined()
it "updates the gutter the decoration targets, if the decoration gutterName is changed", ->
# This changes which gutter this decoration applies to. Since this gutter does not exist,
@@ -2627,24 +2685,25 @@ describe "TextEditorPresenter", ->
gutterName: 'test-gutter-2'
class: 'new-test-class'
item: decorationItem
expectStateUpdate presenter, -> decoration1.setProperties(newDecorationParams)
waitsForStateToUpdate presenter, -> decoration1.setProperties(newDecorationParams)
decorationState = getContentForGutterWithName(presenter, 'test-gutter')
expect(decorationState[decoration1.id]).toBeUndefined()
expect(decorationState[decoration2.id].top).toBeDefined()
expect(decorationState[decoration3.id]).toBeUndefined()
runs ->
decorationState = getContentForGutterWithName(presenter, 'test-gutter')
expect(decorationState[decoration1.id]).toBeUndefined()
expect(decorationState[decoration2.id].top).toBeDefined()
expect(decorationState[decoration3.id]).toBeUndefined()
# After adding the targeted gutter, the decoration will appear in the state for that gutter,
# since it should be visible.
expectStateUpdate presenter, -> editor.addGutter({name: 'test-gutter-2'})
newGutterDecorationState = getContentForGutterWithName(presenter, 'test-gutter-2')
expect(newGutterDecorationState[decoration1.id].top).toBeDefined()
expect(newGutterDecorationState[decoration2.id]).toBeUndefined()
expect(newGutterDecorationState[decoration3.id]).toBeUndefined()
oldGutterDecorationState = getContentForGutterWithName(presenter, 'test-gutter')
expect(oldGutterDecorationState[decoration1.id]).toBeUndefined()
expect(oldGutterDecorationState[decoration2.id].top).toBeDefined()
expect(oldGutterDecorationState[decoration3.id]).toBeUndefined()
# After adding the targeted gutter, the decoration will appear in the state for that gutter,
# since it should be visible.
expectStateUpdate presenter, -> editor.addGutter({name: 'test-gutter-2'})
newGutterDecorationState = getContentForGutterWithName(presenter, 'test-gutter-2')
expect(newGutterDecorationState[decoration1.id].top).toBeDefined()
expect(newGutterDecorationState[decoration2.id]).toBeUndefined()
expect(newGutterDecorationState[decoration3.id]).toBeUndefined()
oldGutterDecorationState = getContentForGutterWithName(presenter, 'test-gutter')
expect(oldGutterDecorationState[decoration1.id]).toBeUndefined()
expect(oldGutterDecorationState[decoration2.id].top).toBeDefined()
expect(oldGutterDecorationState[decoration3.id]).toBeUndefined()
it "updates when the editor's mini state changes, and is cleared when the editor is mini", ->
expectStateUpdate presenter, -> editor.setMini(true)
@@ -2679,13 +2738,17 @@ describe "TextEditorPresenter", ->
class: 'test-class'
marker4 = editor.markBufferRange([[0, 0], [1, 0]])
decoration4 = editor.decorateMarker(marker4, decorationParams)
expectStateUpdate presenter, -> editor.addGutter({name: 'test-gutter-2'})
decorationState = getContentForGutterWithName(presenter, 'test-gutter-2')
expect(decorationState[decoration1.id]).toBeUndefined()
expect(decorationState[decoration2.id]).toBeUndefined()
expect(decorationState[decoration3.id]).toBeUndefined()
expect(decorationState[decoration4.id].top).toBeDefined()
waitsForStateToUpdate presenter
runs ->
expectStateUpdate presenter, -> editor.addGutter({name: 'test-gutter-2'})
decorationState = getContentForGutterWithName(presenter, 'test-gutter-2')
expect(decorationState[decoration1.id]).toBeUndefined()
expect(decorationState[decoration2.id]).toBeUndefined()
expect(decorationState[decoration3.id]).toBeUndefined()
expect(decorationState[decoration4.id].top).toBeDefined()
it "updates when editor lines are folded", ->
oldDimensionsForDecoration1 =

View File

@@ -4589,7 +4589,10 @@ describe "TextEditor", ->
expect(buffer.getLineCount()).toBe(count - 1)
describe "when the line being deleted preceeds a fold, and the command is undone", ->
it "restores the line and preserves the fold", ->
# TODO: This seemed to have only been passing due to an accident in the text
# buffer implementation. Once we moved selections to a different layer it
# broke. We need to revisit our representation of folds and then reenable it.
xit "restores the line and preserves the fold", ->
editor.setCursorBufferPosition([4])
editor.foldCurrentRow()
expect(editor.isFoldedAtScreenRow(4)).toBeTruthy()
@@ -5057,11 +5060,12 @@ describe "TextEditor", ->
expect(coffeeEditor.lineTextForBufferRow(2)).toBe ""
describe ".destroy()", ->
it "destroys all markers associated with the edit session", ->
editor.foldAll()
expect(buffer.getMarkerCount()).toBeGreaterThan 0
it "destroys marker layers associated with the text editor", ->
selectionsMarkerLayerId = editor.selectionsMarkerLayer.id
foldsMarkerLayerId = editor.displayBuffer.foldsMarkerLayer.id
editor.destroy()
expect(buffer.getMarkerCount()).toBe 0
expect(buffer.getMarkerLayer(selectionsMarkerLayerId)).toBeUndefined()
expect(buffer.getMarkerLayer(foldsMarkerLayerId)).toBeUndefined()
it "notifies ::onDidDestroy observers when the editor is destroyed", ->
destroyObserverCalled = false
@@ -5500,101 +5504,189 @@ describe "TextEditor", ->
it "does not allow a custom gutter with the 'line-number' name.", ->
expect(editor.addGutter.bind(editor, {name: 'line-number'})).toThrow()
describe '::decorateMarker', ->
[marker] = []
describe '::decorateMarker', ->
[marker] = []
beforeEach ->
marker = editor.markBufferRange([[1, 0], [1, 0]])
beforeEach ->
marker = editor.markBufferRange([[1, 0], [1, 0]])
it 'reflects an added decoration when one of its custom gutters is decorated.', ->
gutter = editor.addGutter {'name': 'custom-gutter'}
decoration = gutter.decorateMarker marker, {class: 'custom-class'}
gutterDecorations = editor.getDecorations
type: 'gutter'
gutterName: 'custom-gutter'
class: 'custom-class'
expect(gutterDecorations.length).toBe 1
expect(gutterDecorations[0]).toBe decoration
it 'reflects an added decoration when one of its custom gutters is decorated.', ->
gutter = editor.addGutter {'name': 'custom-gutter'}
decoration = gutter.decorateMarker marker, {class: 'custom-class'}
gutterDecorations = editor.getDecorations
type: 'gutter'
gutterName: 'custom-gutter'
class: 'custom-class'
expect(gutterDecorations.length).toBe 1
expect(gutterDecorations[0]).toBe decoration
it 'reflects an added decoration when its line-number gutter is decorated.', ->
decoration = editor.gutterWithName('line-number').decorateMarker marker, {class: 'test-class'}
gutterDecorations = editor.getDecorations
type: 'line-number'
gutterName: 'line-number'
class: 'test-class'
expect(gutterDecorations.length).toBe 1
expect(gutterDecorations[0]).toBe decoration
it 'reflects an added decoration when its line-number gutter is decorated.', ->
decoration = editor.gutterWithName('line-number').decorateMarker marker, {class: 'test-class'}
gutterDecorations = editor.getDecorations
type: 'line-number'
gutterName: 'line-number'
class: 'test-class'
expect(gutterDecorations.length).toBe 1
expect(gutterDecorations[0]).toBe decoration
describe '::observeGutters', ->
[payloads, callback] = []
describe '::observeGutters', ->
[payloads, callback] = []
beforeEach ->
payloads = []
callback = (payload) ->
payloads.push(payload)
beforeEach ->
payloads = []
callback = (payload) ->
payloads.push(payload)
it 'calls the callback immediately with each existing gutter, and with each added gutter after that.', ->
lineNumberGutter = editor.gutterWithName('line-number')
editor.observeGutters(callback)
expect(payloads).toEqual [lineNumberGutter]
gutter1 = editor.addGutter({name: 'test-gutter-1'})
expect(payloads).toEqual [lineNumberGutter, gutter1]
gutter2 = editor.addGutter({name: 'test-gutter-2'})
expect(payloads).toEqual [lineNumberGutter, gutter1, gutter2]
it 'calls the callback immediately with each existing gutter, and with each added gutter after that.', ->
lineNumberGutter = editor.gutterWithName('line-number')
editor.observeGutters(callback)
expect(payloads).toEqual [lineNumberGutter]
gutter1 = editor.addGutter({name: 'test-gutter-1'})
expect(payloads).toEqual [lineNumberGutter, gutter1]
gutter2 = editor.addGutter({name: 'test-gutter-2'})
expect(payloads).toEqual [lineNumberGutter, gutter1, gutter2]
it 'does not call the callback when a gutter is removed.', ->
gutter = editor.addGutter({name: 'test-gutter'})
editor.observeGutters(callback)
payloads = []
gutter.destroy()
expect(payloads).toEqual []
it 'does not call the callback when a gutter is removed.', ->
gutter = editor.addGutter({name: 'test-gutter'})
editor.observeGutters(callback)
payloads = []
gutter.destroy()
expect(payloads).toEqual []
it 'does not call the callback after the subscription has been disposed.', ->
subscription = editor.observeGutters(callback)
payloads = []
subscription.dispose()
editor.addGutter({name: 'test-gutter'})
expect(payloads).toEqual []
it 'does not call the callback after the subscription has been disposed.', ->
subscription = editor.observeGutters(callback)
payloads = []
subscription.dispose()
editor.addGutter({name: 'test-gutter'})
expect(payloads).toEqual []
describe '::onDidAddGutter', ->
[payloads, callback] = []
describe '::onDidAddGutter', ->
[payloads, callback] = []
beforeEach ->
payloads = []
callback = (payload) ->
payloads.push(payload)
beforeEach ->
payloads = []
callback = (payload) ->
payloads.push(payload)
it 'calls the callback with each newly-added gutter, but not with existing gutters.', ->
editor.onDidAddGutter(callback)
expect(payloads).toEqual []
gutter = editor.addGutter({name: 'test-gutter'})
expect(payloads).toEqual [gutter]
it 'calls the callback with each newly-added gutter, but not with existing gutters.', ->
editor.onDidAddGutter(callback)
expect(payloads).toEqual []
gutter = editor.addGutter({name: 'test-gutter'})
expect(payloads).toEqual [gutter]
it 'does not call the callback after the subscription has been disposed.', ->
subscription = editor.onDidAddGutter(callback)
payloads = []
subscription.dispose()
editor.addGutter({name: 'test-gutter'})
expect(payloads).toEqual []
it 'does not call the callback after the subscription has been disposed.', ->
subscription = editor.onDidAddGutter(callback)
payloads = []
subscription.dispose()
editor.addGutter({name: 'test-gutter'})
expect(payloads).toEqual []
describe '::onDidRemoveGutter', ->
[payloads, callback] = []
describe '::onDidRemoveGutter', ->
[payloads, callback] = []
beforeEach ->
payloads = []
callback = (payload) ->
payloads.push(payload)
beforeEach ->
payloads = []
callback = (payload) ->
payloads.push(payload)
it 'calls the callback when a gutter is removed.', ->
gutter = editor.addGutter({name: 'test-gutter'})
editor.onDidRemoveGutter(callback)
expect(payloads).toEqual []
gutter.destroy()
expect(payloads).toEqual ['test-gutter']
it 'calls the callback when a gutter is removed.', ->
gutter = editor.addGutter({name: 'test-gutter'})
editor.onDidRemoveGutter(callback)
expect(payloads).toEqual []
gutter.destroy()
expect(payloads).toEqual ['test-gutter']
it 'does not call the callback after the subscription has been disposed.', ->
gutter = editor.addGutter({name: 'test-gutter'})
subscription = editor.onDidRemoveGutter(callback)
subscription.dispose()
gutter.destroy()
expect(payloads).toEqual []
it 'does not call the callback after the subscription has been disposed.', ->
gutter = editor.addGutter({name: 'test-gutter'})
subscription = editor.onDidRemoveGutter(callback)
subscription.dispose()
gutter.destroy()
expect(payloads).toEqual []
describe "decorations", ->
describe "::decorateMarker", ->
it "includes the decoration in the object returned from ::decorationsStateForScreenRowRange", ->
marker = editor.markBufferRange([[2, 4], [6, 8]])
decoration = editor.decorateMarker(marker, type: 'highlight', class: 'foo')
expect(editor.decorationsStateForScreenRowRange(0, 5)[decoration.id]).toEqual {
properties: {type: 'highlight', class: 'foo'}
screenRange: marker.getScreenRange(),
rangeIsReversed: false
}
describe "::decorateMarkerLayer", ->
it "based on the markers in the layer, includes multiple decoration objects with the same properties and different ranges in the object returned from ::decorationsStateForScreenRowRange", ->
layer1 = editor.getBuffer().addMarkerLayer()
marker1 = layer1.markRange([[2, 4], [6, 8]])
marker2 = layer1.markRange([[11, 0], [11, 12]])
layer2 = editor.getBuffer().addMarkerLayer()
marker3 = layer2.markRange([[8, 0], [9, 0]])
layer1Decoration1 = editor.decorateMarkerLayer(layer1, type: 'highlight', class: 'foo')
layer1Decoration2 = editor.decorateMarkerLayer(layer1, type: 'highlight', class: 'bar')
layer2Decoration = editor.decorateMarkerLayer(layer2, type: 'highlight', class: 'baz')
decorationState = editor.decorationsStateForScreenRowRange(0, 13)
expect(decorationState["#{layer1Decoration1.id}-#{marker1.id}"]).toEqual {
properties: {type: 'highlight', class: 'foo'},
screenRange: marker1.getRange(),
rangeIsReversed: false
}
expect(decorationState["#{layer1Decoration1.id}-#{marker2.id}"]).toEqual {
properties: {type: 'highlight', class: 'foo'},
screenRange: marker2.getRange(),
rangeIsReversed: false
}
expect(decorationState["#{layer1Decoration2.id}-#{marker1.id}"]).toEqual {
properties: {type: 'highlight', class: 'bar'},
screenRange: marker1.getRange(),
rangeIsReversed: false
}
expect(decorationState["#{layer1Decoration2.id}-#{marker2.id}"]).toEqual {
properties: {type: 'highlight', class: 'bar'},
screenRange: marker2.getRange(),
rangeIsReversed: false
}
expect(decorationState["#{layer2Decoration.id}-#{marker3.id}"]).toEqual {
properties: {type: 'highlight', class: 'baz'},
screenRange: marker3.getRange(),
rangeIsReversed: false
}
layer1Decoration1.destroy()
decorationState = editor.decorationsStateForScreenRowRange(0, 12)
expect(decorationState["#{layer1Decoration1.id}-#{marker1.id}"]).toBeUndefined()
expect(decorationState["#{layer1Decoration1.id}-#{marker2.id}"]).toBeUndefined()
expect(decorationState["#{layer1Decoration2.id}-#{marker1.id}"]).toEqual {
properties: {type: 'highlight', class: 'bar'},
screenRange: marker1.getRange(),
rangeIsReversed: false
}
expect(decorationState["#{layer1Decoration2.id}-#{marker2.id}"]).toEqual {
properties: {type: 'highlight', class: 'bar'},
screenRange: marker2.getRange(),
rangeIsReversed: false
}
expect(decorationState["#{layer2Decoration.id}-#{marker3.id}"]).toEqual {
properties: {type: 'highlight', class: 'baz'},
screenRange: marker3.getRange(),
rangeIsReversed: false
}
layer1Decoration2.setPropertiesForMarker(marker1, {type: 'highlight', class: 'quux'})
decorationState = editor.decorationsStateForScreenRowRange(0, 12)
expect(decorationState["#{layer1Decoration2.id}-#{marker1.id}"]).toEqual {
properties: {type: 'highlight', class: 'quux'},
screenRange: marker1.getRange(),
rangeIsReversed: false
}
layer1Decoration2.setPropertiesForMarker(marker1, null)
decorationState = editor.decorationsStateForScreenRowRange(0, 12)
expect(decorationState["#{layer1Decoration2.id}-#{marker1.id}"]).toEqual {
properties: {type: 'highlight', class: 'bar'},
screenRange: marker1.getRange(),
rangeIsReversed: false
}

View File

@@ -209,3 +209,21 @@ describe "ViewRegistry", ->
window.dispatchEvent(new UIEvent('resize'))
expect(events).toEqual ['poll 1', 'poll 2']
describe "::getNextUpdatePromise()", ->
it "returns a promise that resolves at the end of the next update cycle", ->
updateCalled = false
readCalled = false
pollCalled = false
waitsFor 'getNextUpdatePromise to resolve', (done) ->
registry.getNextUpdatePromise().then ->
expect(updateCalled).toBe true
expect(readCalled).toBe true
expect(pollCalled).toBe true
done()
registry.updateDocument -> updateCalled = true
registry.readDocument -> readCalled = true
registry.pollDocument -> pollCalled = true
registry.pollAfterNextUpdate()