mirror of
https://github.com/atom/atom.git
synced 2026-04-28 03:01:47 -04:00
Merge branch 'master' into mb-optimize-marker-observation
Conflicts: src/text-editor-component.coffee src/text-editor-presenter.coffee
This commit is contained in:
@@ -805,7 +805,6 @@ describe "Config", ->
|
||||
atom.config.loadUserConfig()
|
||||
expect(atom.config.get("foo.bar")).toBe "baz"
|
||||
|
||||
|
||||
describe ".observeUserConfig()", ->
|
||||
updatedHandler = null
|
||||
|
||||
@@ -1381,6 +1380,16 @@ describe "Config", ->
|
||||
expect(atom.config.set('foo.bar.aString', nope: 'nope')).toBe false
|
||||
expect(atom.config.get('foo.bar.aString')).toBe 'ok'
|
||||
|
||||
describe 'when the schema has a "maximumLength" key', ->
|
||||
it "trims the string to be no longer than the specified maximum", ->
|
||||
schema =
|
||||
type: 'string'
|
||||
default: 'ok'
|
||||
maximumLength: 3
|
||||
atom.config.setSchema('foo.bar.aString', schema)
|
||||
atom.config.set('foo.bar.aString', 'abcdefg')
|
||||
expect(atom.config.get('foo.bar.aString')).toBe 'abc'
|
||||
|
||||
describe 'when the value has an "object" type', ->
|
||||
beforeEach ->
|
||||
schema =
|
||||
|
||||
@@ -31,6 +31,12 @@ describe "DefaultDirectoryProvider", ->
|
||||
directory = provider.directoryForURISync(file)
|
||||
expect(directory.getPath()).toEqual tmp
|
||||
|
||||
it "creates a Directory with a path as a uri when passed a uri", ->
|
||||
provider = new DefaultDirectoryProvider()
|
||||
uri = 'remote://server:6792/path/to/a/dir'
|
||||
directory = provider.directoryForURISync(uri)
|
||||
expect(directory.getPath()).toEqual uri
|
||||
|
||||
describe ".directoryForURI(uri)", ->
|
||||
it "returns a Promise that resolves to a Directory with a path that matches the uri", ->
|
||||
provider = new DefaultDirectoryProvider()
|
||||
|
||||
@@ -227,3 +227,13 @@ describe "Starting Atom", ->
|
||||
[tempDirPath]
|
||||
[otherTempDirPath]
|
||||
].sort()
|
||||
|
||||
describe "opening a remote directory", ->
|
||||
it "opens the parent directory and creates an empty text editor", ->
|
||||
remoteDirectory = 'remote://server:3437/some/directory/path'
|
||||
runAtom [remoteDirectory], {ATOM_HOME: atomHome}, (client) ->
|
||||
client
|
||||
.waitForWindowCount(1, 1000)
|
||||
.waitForExist("atom-workspace", 5000)
|
||||
.treeViewRootDirectories()
|
||||
.then ({value}) -> expect(value).toEqual([remoteDirectory])
|
||||
|
||||
@@ -57,3 +57,16 @@ describe "Task", ->
|
||||
expect(deprecations.length).toBe 1
|
||||
expect(deprecations[0].getStacks()[0][1].fileName).toBe handlerPath
|
||||
jasmine.restoreDeprecationsSnapshot()
|
||||
|
||||
it "adds data listeners to standard out and error to report output", ->
|
||||
task = new Task(require.resolve('./fixtures/task-spec-handler'))
|
||||
{stdout, stderr} = task.childProcess
|
||||
|
||||
task.start()
|
||||
task.start()
|
||||
expect(stdout.listeners('data').length).toBe 1
|
||||
expect(stderr.listeners('data').length).toBe 1
|
||||
|
||||
task.terminate()
|
||||
expect(stdout.listeners('data').length).toBe 0
|
||||
expect(stderr.listeners('data').length).toBe 0
|
||||
|
||||
@@ -7,10 +7,10 @@ nbsp = String.fromCharCode(160)
|
||||
|
||||
describe "TextEditorComponent", ->
|
||||
[contentNode, editor, wrapperView, wrapperNode, component, componentNode, verticalScrollbarNode, horizontalScrollbarNode] = []
|
||||
[lineHeightInPixels, charWidth, nextAnimationFrame, noAnimationFrame, lineOverdrawMargin] = []
|
||||
[lineHeightInPixels, charWidth, nextAnimationFrame, noAnimationFrame, tileSize] = []
|
||||
|
||||
beforeEach ->
|
||||
lineOverdrawMargin = 2
|
||||
tileSize = 3
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-javascript')
|
||||
@@ -34,7 +34,7 @@ describe "TextEditorComponent", ->
|
||||
contentNode = document.querySelector('#jasmine-content')
|
||||
contentNode.style.width = '1000px'
|
||||
|
||||
wrapperView = new TextEditorView(editor, {lineOverdrawMargin})
|
||||
wrapperView = new TextEditorView(editor, {tileSize})
|
||||
wrapperView.attachToDom()
|
||||
wrapperNode = wrapperView.element
|
||||
wrapperNode.setUpdatedSynchronously(false)
|
||||
@@ -68,48 +68,111 @@ describe "TextEditorComponent", ->
|
||||
expect(nextAnimationFrame).not.toThrow()
|
||||
|
||||
describe "line rendering", ->
|
||||
it "renders the currently-visible lines plus the overdraw margin", ->
|
||||
wrapperNode.style.height = 4.5 * lineHeightInPixels + 'px'
|
||||
expectTileContainsRow = (tileNode, screenRow, {top}) ->
|
||||
lineNode = tileNode.querySelector("[data-screen-row='#{screenRow}']")
|
||||
tokenizedLine = editor.tokenizedLineForScreenRow(screenRow)
|
||||
|
||||
expect(lineNode.offsetTop).toBe(top)
|
||||
if tokenizedLine.text is ""
|
||||
expect(lineNode.innerHTML).toBe(" ")
|
||||
else
|
||||
expect(lineNode.textContent).toBe(tokenizedLine.text)
|
||||
|
||||
it "renders the currently-visible lines in a tiled fashion", ->
|
||||
wrapperNode.style.height = 6.5 * lineHeightInPixels + 'px'
|
||||
tileHeight = tileSize * lineHeightInPixels
|
||||
component.measureDimensions()
|
||||
nextAnimationFrame()
|
||||
|
||||
linesNode = componentNode.querySelector('.lines')
|
||||
expect(linesNode.style['-webkit-transform']).toBe "translate3d(0px, 0px, 0px)"
|
||||
expect(componentNode.querySelectorAll('.line').length).toBe 6 + 2 # no margin above
|
||||
expect(component.lineNodeForScreenRow(0).textContent).toBe editor.tokenizedLineForScreenRow(0).text
|
||||
expect(component.lineNodeForScreenRow(0).offsetTop).toBe 0
|
||||
expect(component.lineNodeForScreenRow(5).textContent).toBe editor.tokenizedLineForScreenRow(5).text
|
||||
expect(component.lineNodeForScreenRow(5).offsetTop).toBe 5 * lineHeightInPixels
|
||||
tilesNodes = componentNode.querySelectorAll(".tile")
|
||||
|
||||
verticalScrollbarNode.scrollTop = 4.5 * lineHeightInPixels
|
||||
expect(tilesNodes.length).toBe(3)
|
||||
|
||||
expect(tilesNodes[0].style['-webkit-transform']).toBe "translate3d(0px, 0px, 0px)"
|
||||
expect(tilesNodes[0].children.length).toBe(tileSize)
|
||||
expectTileContainsRow(tilesNodes[0], 0, top: 0 * lineHeightInPixels)
|
||||
expectTileContainsRow(tilesNodes[0], 1, top: 1 * lineHeightInPixels)
|
||||
expectTileContainsRow(tilesNodes[0], 2, top: 2 * lineHeightInPixels)
|
||||
|
||||
expect(tilesNodes[1].style['-webkit-transform']).toBe "translate3d(0px, #{1 * tileHeight}px, 0px)"
|
||||
expect(tilesNodes[1].children.length).toBe(tileSize)
|
||||
expectTileContainsRow(tilesNodes[1], 3, top: 0 * lineHeightInPixels)
|
||||
expectTileContainsRow(tilesNodes[1], 4, top: 1 * lineHeightInPixels)
|
||||
expectTileContainsRow(tilesNodes[1], 5, top: 2 * lineHeightInPixels)
|
||||
|
||||
expect(tilesNodes[2].style['-webkit-transform']).toBe "translate3d(0px, #{2 * tileHeight}px, 0px)"
|
||||
expect(tilesNodes[2].children.length).toBe(tileSize)
|
||||
expectTileContainsRow(tilesNodes[2], 6, top: 0 * lineHeightInPixels)
|
||||
expectTileContainsRow(tilesNodes[2], 7, top: 1 * lineHeightInPixels)
|
||||
expectTileContainsRow(tilesNodes[2], 8, top: 2 * lineHeightInPixels)
|
||||
|
||||
expect(component.lineNodeForScreenRow(9)).toBeUndefined()
|
||||
|
||||
verticalScrollbarNode.scrollTop = tileSize * lineHeightInPixels + 5
|
||||
verticalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
|
||||
nextAnimationFrame()
|
||||
|
||||
expect(linesNode.style['-webkit-transform']).toBe "translate3d(0px, #{-4.5 * lineHeightInPixels}px, 0px)"
|
||||
expect(componentNode.querySelectorAll('.line').length).toBe 6 + 4 # margin above and below
|
||||
expect(component.lineNodeForScreenRow(2).offsetTop).toBe 2 * lineHeightInPixels
|
||||
expect(component.lineNodeForScreenRow(2).textContent).toBe editor.tokenizedLineForScreenRow(2).text
|
||||
expect(component.lineNodeForScreenRow(9).offsetTop).toBe 9 * lineHeightInPixels
|
||||
expect(component.lineNodeForScreenRow(9).textContent).toBe editor.tokenizedLineForScreenRow(9).text
|
||||
tilesNodes = componentNode.querySelectorAll(".tile")
|
||||
|
||||
it "updates the top position of subsequent lines when lines are inserted or removed", ->
|
||||
expect(component.lineNodeForScreenRow(2)).toBeUndefined()
|
||||
expect(tilesNodes.length).toBe(3)
|
||||
|
||||
expect(tilesNodes[0].style['-webkit-transform']).toBe "translate3d(0px, -5px, 0px)"
|
||||
expect(tilesNodes[0].children.length).toBe(tileSize)
|
||||
expectTileContainsRow(tilesNodes[0], 3, top: 0 * lineHeightInPixels)
|
||||
expectTileContainsRow(tilesNodes[0], 4, top: 1 * lineHeightInPixels)
|
||||
expectTileContainsRow(tilesNodes[0], 5, top: 2 * lineHeightInPixels)
|
||||
|
||||
expect(tilesNodes[1].style['-webkit-transform']).toBe "translate3d(0px, #{1 * tileHeight - 5}px, 0px)"
|
||||
expect(tilesNodes[1].children.length).toBe(tileSize)
|
||||
expectTileContainsRow(tilesNodes[1], 6, top: 0 * lineHeightInPixels)
|
||||
expectTileContainsRow(tilesNodes[1], 7, top: 1 * lineHeightInPixels)
|
||||
expectTileContainsRow(tilesNodes[1], 8, top: 2 * lineHeightInPixels)
|
||||
|
||||
expect(tilesNodes[2].style['-webkit-transform']).toBe "translate3d(0px, #{2 * tileHeight - 5}px, 0px)"
|
||||
expect(tilesNodes[2].children.length).toBe(tileSize)
|
||||
expectTileContainsRow(tilesNodes[2], 9, top: 0 * lineHeightInPixels)
|
||||
expectTileContainsRow(tilesNodes[2], 10, top: 1 * lineHeightInPixels)
|
||||
expectTileContainsRow(tilesNodes[2], 11, top: 2 * lineHeightInPixels)
|
||||
|
||||
it "updates the top position of subsequent tiles when lines are inserted or removed", ->
|
||||
wrapperNode.style.height = 6.5 * lineHeightInPixels + 'px'
|
||||
tileHeight = tileSize * lineHeightInPixels
|
||||
component.measureDimensions()
|
||||
editor.getBuffer().deleteRows(0, 1)
|
||||
nextAnimationFrame()
|
||||
|
||||
lineNodes = componentNode.querySelectorAll('.line')
|
||||
expect(component.lineNodeForScreenRow(0).offsetTop).toBe 0
|
||||
expect(component.lineNodeForScreenRow(1).offsetTop).toBe 1 * lineHeightInPixels
|
||||
expect(component.lineNodeForScreenRow(2).offsetTop).toBe 2 * lineHeightInPixels
|
||||
tilesNodes = componentNode.querySelectorAll(".tile")
|
||||
|
||||
expect(tilesNodes[0].style['-webkit-transform']).toBe "translate3d(0px, 0px, 0px)"
|
||||
expectTileContainsRow(tilesNodes[0], 0, top: 0 * lineHeightInPixels)
|
||||
expectTileContainsRow(tilesNodes[0], 1, top: 1 * lineHeightInPixels)
|
||||
expectTileContainsRow(tilesNodes[0], 2, top: 2 * lineHeightInPixels)
|
||||
|
||||
expect(tilesNodes[1].style['-webkit-transform']).toBe "translate3d(0px, #{1 * tileHeight}px, 0px)"
|
||||
expectTileContainsRow(tilesNodes[1], 3, top: 0 * lineHeightInPixels)
|
||||
expectTileContainsRow(tilesNodes[1], 4, top: 1 * lineHeightInPixels)
|
||||
expectTileContainsRow(tilesNodes[1], 5, top: 2 * lineHeightInPixels)
|
||||
|
||||
editor.getBuffer().insert([0, 0], '\n\n')
|
||||
nextAnimationFrame()
|
||||
|
||||
lineNodes = componentNode.querySelectorAll('.line')
|
||||
expect(component.lineNodeForScreenRow(0).offsetTop).toBe 0 * lineHeightInPixels
|
||||
expect(component.lineNodeForScreenRow(1).offsetTop).toBe 1 * lineHeightInPixels
|
||||
expect(component.lineNodeForScreenRow(2).offsetTop).toBe 2 * lineHeightInPixels
|
||||
expect(component.lineNodeForScreenRow(3).offsetTop).toBe 3 * lineHeightInPixels
|
||||
expect(component.lineNodeForScreenRow(4).offsetTop).toBe 4 * lineHeightInPixels
|
||||
tilesNodes = componentNode.querySelectorAll(".tile")
|
||||
|
||||
expect(tilesNodes[0].style['-webkit-transform']).toBe "translate3d(0px, 0px, 0px)"
|
||||
expectTileContainsRow(tilesNodes[0], 0, top: 0 * lineHeightInPixels)
|
||||
expectTileContainsRow(tilesNodes[0], 1, top: 1 * lineHeightInPixels)
|
||||
expectTileContainsRow(tilesNodes[0], 2, top: 2 * lineHeightInPixels)
|
||||
|
||||
expect(tilesNodes[1].style['-webkit-transform']).toBe "translate3d(0px, #{1 * tileHeight}px, 0px)"
|
||||
expectTileContainsRow(tilesNodes[1], 3, top: 0 * lineHeightInPixels)
|
||||
expectTileContainsRow(tilesNodes[1], 4, top: 1 * lineHeightInPixels)
|
||||
expectTileContainsRow(tilesNodes[1], 5, top: 2 * lineHeightInPixels)
|
||||
|
||||
expect(tilesNodes[2].style['-webkit-transform']).toBe "translate3d(0px, #{2 * tileHeight}px, 0px)"
|
||||
expectTileContainsRow(tilesNodes[2], 6, top: 0 * lineHeightInPixels)
|
||||
expectTileContainsRow(tilesNodes[2], 7, top: 1 * lineHeightInPixels)
|
||||
expectTileContainsRow(tilesNodes[2], 8, top: 2 * lineHeightInPixels)
|
||||
|
||||
it "updates the lines when lines are inserted or removed above the rendered row range", ->
|
||||
wrapperNode.style.height = 4.5 * lineHeightInPixels + 'px'
|
||||
@@ -483,7 +546,7 @@ describe "TextEditorComponent", ->
|
||||
component.measureDimensions()
|
||||
nextAnimationFrame()
|
||||
|
||||
expect(componentNode.querySelectorAll('.line-number').length).toBe 6 + 2 + 1 # line overdraw margin below + dummy line number
|
||||
expect(componentNode.querySelectorAll('.line-number').length).toBe 6 + 1 # visible line-numbers + dummy line number
|
||||
expect(component.lineNumberNodeForScreenRow(0).textContent).toBe "#{nbsp}1"
|
||||
expect(component.lineNumberNodeForScreenRow(5).textContent).toBe "#{nbsp}6"
|
||||
|
||||
@@ -491,7 +554,7 @@ describe "TextEditorComponent", ->
|
||||
verticalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
|
||||
nextAnimationFrame()
|
||||
|
||||
expect(componentNode.querySelectorAll('.line-number').length).toBe 6 + 4 + 1 # line overdraw margin above/below + dummy line number
|
||||
expect(componentNode.querySelectorAll('.line-number').length).toBe 6 + 1 # visible line-numbers + dummy line number
|
||||
|
||||
expect(component.lineNumberNodeForScreenRow(2).textContent).toBe "#{nbsp}3"
|
||||
expect(component.lineNumberNodeForScreenRow(2).offsetTop).toBe 2 * lineHeightInPixels
|
||||
@@ -527,7 +590,7 @@ describe "TextEditorComponent", ->
|
||||
component.measureDimensions()
|
||||
nextAnimationFrame()
|
||||
|
||||
expect(componentNode.querySelectorAll('.line-number').length).toBe 6 + lineOverdrawMargin + 1 # 1 dummy line componentNode
|
||||
expect(componentNode.querySelectorAll('.line-number').length).toBe 6 + 1 # 1 dummy line
|
||||
expect(component.lineNumberNodeForScreenRow(0).textContent).toBe "#{nbsp}1"
|
||||
expect(component.lineNumberNodeForScreenRow(1).textContent).toBe "#{nbsp}•"
|
||||
expect(component.lineNumberNodeForScreenRow(2).textContent).toBe "#{nbsp}2"
|
||||
@@ -725,13 +788,13 @@ describe "TextEditorComponent", ->
|
||||
|
||||
cursorNodes = componentNode.querySelectorAll('.cursor')
|
||||
expect(cursorNodes.length).toBe 2
|
||||
expect(cursorNodes[0].style['-webkit-transform']).toBe "translate(#{10 * charWidth}px, #{4 * lineHeightInPixels}px)"
|
||||
expect(cursorNodes[1].style['-webkit-transform']).toBe "translate(#{11 * charWidth}px, #{8 * lineHeightInPixels}px)"
|
||||
expect(cursorNodes[0].style['-webkit-transform']).toBe "translate(#{10 * charWidth - horizontalScrollbarNode.scrollLeft}px, #{4 * lineHeightInPixels - verticalScrollbarNode.scrollTop}px)"
|
||||
expect(cursorNodes[1].style['-webkit-transform']).toBe "translate(#{11 * charWidth - horizontalScrollbarNode.scrollLeft}px, #{8 * lineHeightInPixels - verticalScrollbarNode.scrollTop}px)"
|
||||
|
||||
editor.onDidChangeCursorPosition cursorMovedListener = jasmine.createSpy('cursorMovedListener')
|
||||
cursor3.setScreenPosition([4, 11], autoscroll: false)
|
||||
nextAnimationFrame()
|
||||
expect(cursorNodes[0].style['-webkit-transform']).toBe "translate(#{11 * charWidth}px, #{4 * lineHeightInPixels}px)"
|
||||
expect(cursorNodes[0].style['-webkit-transform']).toBe "translate(#{11 * charWidth - horizontalScrollbarNode.scrollLeft}px, #{4 * lineHeightInPixels - verticalScrollbarNode.scrollTop}px)"
|
||||
expect(cursorMovedListener).toHaveBeenCalled()
|
||||
|
||||
cursor3.destroy()
|
||||
@@ -739,7 +802,7 @@ describe "TextEditorComponent", ->
|
||||
cursorNodes = componentNode.querySelectorAll('.cursor')
|
||||
|
||||
expect(cursorNodes.length).toBe 1
|
||||
expect(cursorNodes[0].style['-webkit-transform']).toBe "translate(#{11 * charWidth}px, #{8 * lineHeightInPixels}px)"
|
||||
expect(cursorNodes[0].style['-webkit-transform']).toBe "translate(#{11 * charWidth - horizontalScrollbarNode.scrollLeft}px, #{8 * lineHeightInPixels - verticalScrollbarNode.scrollTop}px)"
|
||||
|
||||
it "accounts for character widths when positioning cursors", ->
|
||||
atom.config.set('editor.fontFamily', 'sans-serif')
|
||||
@@ -1001,7 +1064,7 @@ describe "TextEditorComponent", ->
|
||||
nextAnimationFrame()
|
||||
|
||||
# Scroll decorations into view
|
||||
verticalScrollbarNode.scrollTop = 2.5 * lineHeightInPixels
|
||||
verticalScrollbarNode.scrollTop = 4.5 * lineHeightInPixels
|
||||
verticalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
|
||||
nextAnimationFrame()
|
||||
expect(lineAndLineNumberHaveClass(9, 'b')).toBe true
|
||||
@@ -1147,15 +1210,16 @@ describe "TextEditorComponent", ->
|
||||
# Nothing when outside the rendered row range
|
||||
expect(regions.length).toBe 0
|
||||
|
||||
verticalScrollbarNode.scrollTop = 4.5 * lineHeightInPixels
|
||||
verticalScrollbarNode.scrollTop = 6 * lineHeightInPixels
|
||||
verticalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
|
||||
nextAnimationFrame()
|
||||
expect(component.presenter.endRow).toBeGreaterThan(8)
|
||||
|
||||
regions = componentNode.querySelectorAll('.some-highlight .region')
|
||||
|
||||
expect(regions.length).toBe 1
|
||||
regionRect = regions[0].style
|
||||
expect(regionRect.top).toBe 9 * lineHeightInPixels + 'px'
|
||||
expect(regionRect.top).toBe (9 * lineHeightInPixels - verticalScrollbarNode.scrollTop) + 'px'
|
||||
expect(regionRect.height).toBe 1 * lineHeightInPixels + 'px'
|
||||
expect(regionRect.left).toBe 2 * charWidth + 'px'
|
||||
expect(regionRect.width).toBe 2 * charWidth + 'px'
|
||||
@@ -1920,13 +1984,23 @@ describe "TextEditorComponent", ->
|
||||
component.measureDimensions()
|
||||
nextAnimationFrame()
|
||||
|
||||
linesNode = componentNode.querySelector('.lines')
|
||||
expect(linesNode.style['-webkit-transform']).toBe "translate3d(0px, 0px, 0px)"
|
||||
tilesNodes = componentNode.querySelectorAll(".tile")
|
||||
|
||||
top = 0
|
||||
for tileNode in tilesNodes
|
||||
expect(tileNode.style['-webkit-transform']).toBe "translate3d(0px, #{top}px, 0px)"
|
||||
top += tileNode.offsetHeight
|
||||
|
||||
expect(horizontalScrollbarNode.scrollLeft).toBe 0
|
||||
|
||||
editor.setScrollLeft(100)
|
||||
nextAnimationFrame()
|
||||
expect(linesNode.style['-webkit-transform']).toBe "translate3d(-100px, 0px, 0px)"
|
||||
|
||||
top = 0
|
||||
for tileNode in tilesNodes
|
||||
expect(tileNode.style['-webkit-transform']).toBe "translate3d(-100px, #{top}px, 0px)"
|
||||
top += tileNode.offsetHeight
|
||||
|
||||
expect(horizontalScrollbarNode.scrollLeft).toBe 100
|
||||
|
||||
it "updates the scrollLeft of the model when the scrollLeft of the horizontal scrollbar changes", ->
|
||||
@@ -2387,7 +2461,7 @@ describe "TextEditorComponent", ->
|
||||
hiddenParent.style.display = 'none'
|
||||
contentNode.appendChild(hiddenParent)
|
||||
|
||||
wrapperView = new TextEditorView(editor, {lineOverdrawMargin})
|
||||
wrapperView = new TextEditorView(editor, {tileSize})
|
||||
wrapperNode = wrapperView.element
|
||||
wrapperView.appendTo(hiddenParent)
|
||||
|
||||
@@ -2508,7 +2582,7 @@ describe "TextEditorComponent", ->
|
||||
|
||||
advanceClock(atom.views.documentPollingInterval)
|
||||
nextAnimationFrame()
|
||||
expect(componentNode.querySelectorAll('.line')).toHaveLength(4 + lineOverdrawMargin + 1)
|
||||
expect(componentNode.querySelectorAll('.line')).toHaveLength(6)
|
||||
|
||||
gutterWidth = componentNode.querySelector('.gutter').offsetWidth
|
||||
componentNode.style.width = gutterWidth + 14 * charWidth + editor.getVerticalScrollbarWidth() + 'px'
|
||||
|
||||
@@ -39,7 +39,6 @@ describe "TextEditorPresenter", ->
|
||||
verticalScrollbarWidth: 10
|
||||
scrollTop: 0
|
||||
scrollLeft: 0
|
||||
lineOverdrawMargin: 0
|
||||
|
||||
new TextEditorPresenter(params)
|
||||
|
||||
@@ -657,160 +656,125 @@ describe "TextEditorPresenter", ->
|
||||
expectStateUpdate presenter, -> editor.setPlaceholderText("new-placeholder-text")
|
||||
expect(presenter.getState().content.placeholderText).toBe "new-placeholder-text"
|
||||
|
||||
describe ".lines", ->
|
||||
lineStateForScreenRow = (presenter, screenRow) ->
|
||||
presenter.getState().content.lines[presenter.model.tokenizedLineForScreenRow(screenRow).id]
|
||||
describe ".tiles", ->
|
||||
lineStateForScreenRow = (presenter, row) ->
|
||||
lineId = presenter.model.tokenizedLineForScreenRow(row).id
|
||||
tileRow = presenter.tileForRow(row)
|
||||
presenter.getState().content.tiles[tileRow]?.lines[lineId]
|
||||
|
||||
it "contains states for lines that are visible on screen, plus and minus the overdraw margin", ->
|
||||
presenter = buildPresenter(explicitHeight: 15, scrollTop: 50, lineHeight: 10, lineOverdrawMargin: 1)
|
||||
it "contains states for tiles that are visible on screen", ->
|
||||
presenter = buildPresenter(explicitHeight: 6, scrollTop: 0, lineHeight: 1, tileSize: 2)
|
||||
|
||||
expect(lineStateForScreenRow(presenter, 3)).toBeUndefined()
|
||||
|
||||
line4 = editor.tokenizedLineForScreenRow(4)
|
||||
expectValues lineStateForScreenRow(presenter, 4), {
|
||||
screenRow: 4
|
||||
text: line4.text
|
||||
tags: line4.tags
|
||||
specialTokens: line4.specialTokens
|
||||
firstNonWhitespaceIndex: line4.firstNonWhitespaceIndex
|
||||
firstTrailingWhitespaceIndex: line4.firstTrailingWhitespaceIndex
|
||||
invisibles: line4.invisibles
|
||||
top: 10 * 4
|
||||
expectValues presenter.getState().content.tiles[0], {
|
||||
top: 0
|
||||
}
|
||||
expectValues presenter.getState().content.tiles[2], {
|
||||
top: 2
|
||||
}
|
||||
expectValues presenter.getState().content.tiles[4], {
|
||||
top: 4
|
||||
}
|
||||
expectValues presenter.getState().content.tiles[6], {
|
||||
top: 6
|
||||
}
|
||||
|
||||
line5 = editor.tokenizedLineForScreenRow(5)
|
||||
expectValues lineStateForScreenRow(presenter, 5), {
|
||||
screenRow: 5
|
||||
text: line5.text
|
||||
tags: line5.tags
|
||||
specialTokens: line5.specialTokens
|
||||
firstNonWhitespaceIndex: line5.firstNonWhitespaceIndex
|
||||
firstTrailingWhitespaceIndex: line5.firstTrailingWhitespaceIndex
|
||||
invisibles: line5.invisibles
|
||||
top: 10 * 5
|
||||
expect(presenter.getState().content.tiles[8]).toBeUndefined()
|
||||
|
||||
expectStateUpdate presenter, -> presenter.setScrollTop(3)
|
||||
|
||||
expect(presenter.getState().content.tiles[0]).toBeUndefined()
|
||||
|
||||
expectValues presenter.getState().content.tiles[2], {
|
||||
top: -1
|
||||
}
|
||||
expectValues presenter.getState().content.tiles[4], {
|
||||
top: 1
|
||||
}
|
||||
expectValues presenter.getState().content.tiles[6], {
|
||||
top: 3
|
||||
}
|
||||
expectValues presenter.getState().content.tiles[8], {
|
||||
top: 5
|
||||
}
|
||||
expectValues presenter.getState().content.tiles[10], {
|
||||
top: 7
|
||||
}
|
||||
|
||||
line6 = editor.tokenizedLineForScreenRow(6)
|
||||
expectValues lineStateForScreenRow(presenter, 6), {
|
||||
screenRow: 6
|
||||
text: line6.text
|
||||
tags: line6.tags
|
||||
specialTokens: line6.specialTokens
|
||||
firstNonWhitespaceIndex: line6.firstNonWhitespaceIndex
|
||||
firstTrailingWhitespaceIndex: line6.firstTrailingWhitespaceIndex
|
||||
invisibles: line6.invisibles
|
||||
top: 10 * 6
|
||||
}
|
||||
expect(presenter.getState().content.tiles[12]).toBeUndefined()
|
||||
|
||||
line7 = editor.tokenizedLineForScreenRow(7)
|
||||
expectValues lineStateForScreenRow(presenter, 7), {
|
||||
screenRow: 7
|
||||
text: line7.text
|
||||
tags: line7.tags
|
||||
specialTokens: line7.specialTokens
|
||||
firstNonWhitespaceIndex: line7.firstNonWhitespaceIndex
|
||||
firstTrailingWhitespaceIndex: line7.firstTrailingWhitespaceIndex
|
||||
invisibles: line7.invisibles
|
||||
top: 10 * 7
|
||||
}
|
||||
|
||||
line8 = editor.tokenizedLineForScreenRow(8)
|
||||
expectValues lineStateForScreenRow(presenter, 8), {
|
||||
screenRow: 8
|
||||
text: line8.text
|
||||
tags: line8.tags
|
||||
specialTokens: line8.specialTokens
|
||||
firstNonWhitespaceIndex: line8.firstNonWhitespaceIndex
|
||||
firstTrailingWhitespaceIndex: line8.firstTrailingWhitespaceIndex
|
||||
invisibles: line8.invisibles
|
||||
top: 10 * 8
|
||||
}
|
||||
|
||||
expect(lineStateForScreenRow(presenter, 9)).toBeUndefined()
|
||||
|
||||
it "does not overdraw above the first row", ->
|
||||
presenter = buildPresenter(explicitHeight: 15, scrollTop: 10, lineHeight: 10, lineOverdrawMargin: 2)
|
||||
expect(lineStateForScreenRow(presenter, 0)).toBeDefined()
|
||||
expect(lineStateForScreenRow(presenter, 1)).toBeDefined()
|
||||
expect(lineStateForScreenRow(presenter, 2)).toBeDefined()
|
||||
expect(lineStateForScreenRow(presenter, 3)).toBeDefined()
|
||||
expect(lineStateForScreenRow(presenter, 4)).toBeDefined()
|
||||
expect(lineStateForScreenRow(presenter, 5)).toBeDefined()
|
||||
expect(lineStateForScreenRow(presenter, 6)).toBeUndefined()
|
||||
|
||||
it "does not overdraw below the last row", ->
|
||||
presenter = buildPresenter(explicitHeight: 25, scrollTop: 105, lineHeight: 10, lineOverdrawMargin: 2)
|
||||
expect(lineStateForScreenRow(presenter, 7)).toBeUndefined()
|
||||
expect(lineStateForScreenRow(presenter, 8)).toBeDefined()
|
||||
expect(lineStateForScreenRow(presenter, 9)).toBeDefined()
|
||||
expect(lineStateForScreenRow(presenter, 10)).toBeDefined()
|
||||
expect(lineStateForScreenRow(presenter, 11)).toBeDefined()
|
||||
expect(lineStateForScreenRow(presenter, 12)).toBeDefined()
|
||||
|
||||
it "includes state for all lines if no external ::explicitHeight is assigned", ->
|
||||
presenter = buildPresenter(explicitHeight: null)
|
||||
expect(lineStateForScreenRow(presenter, 0)).toBeDefined()
|
||||
expect(lineStateForScreenRow(presenter, 12)).toBeDefined()
|
||||
it "includes state for all tiles if no external ::explicitHeight is assigned", ->
|
||||
presenter = buildPresenter(explicitHeight: null, tileSize: 2)
|
||||
expect(presenter.getState().content.tiles[0]).toBeDefined()
|
||||
expect(presenter.getState().content.tiles[12]).toBeDefined()
|
||||
|
||||
it "is empty until all of the required measurements are assigned", ->
|
||||
presenter = buildPresenter(explicitHeight: null, lineHeight: null, scrollTop: null)
|
||||
expect(presenter.getState().content.lines).toEqual({})
|
||||
expect(presenter.getState().content.tiles).toEqual({})
|
||||
|
||||
presenter.setExplicitHeight(25)
|
||||
expect(presenter.getState().content.lines).toEqual({})
|
||||
expect(presenter.getState().content.tiles).toEqual({})
|
||||
|
||||
presenter.setLineHeight(10)
|
||||
expect(presenter.getState().content.lines).toEqual({})
|
||||
expect(presenter.getState().content.tiles).toEqual({})
|
||||
|
||||
presenter.setScrollTop(0)
|
||||
expect(presenter.getState().content.lines).not.toEqual({})
|
||||
expect(presenter.getState().content.tiles).not.toEqual({})
|
||||
|
||||
it "updates when ::scrollTop changes", ->
|
||||
presenter = buildPresenter(explicitHeight: 25, scrollTop: 0, lineHeight: 10, lineOverdrawMargin: 1)
|
||||
presenter = buildPresenter(explicitHeight: 6, scrollTop: 0, lineHeight: 1, tileSize: 2)
|
||||
|
||||
expect(lineStateForScreenRow(presenter, 0)).toBeDefined()
|
||||
expect(lineStateForScreenRow(presenter, 4)).toBeDefined()
|
||||
expect(lineStateForScreenRow(presenter, 5)).toBeUndefined()
|
||||
expect(presenter.getState().content.tiles[0]).toBeDefined()
|
||||
expect(presenter.getState().content.tiles[2]).toBeDefined()
|
||||
expect(presenter.getState().content.tiles[4]).toBeDefined()
|
||||
expect(presenter.getState().content.tiles[6]).toBeDefined()
|
||||
expect(presenter.getState().content.tiles[8]).toBeUndefined()
|
||||
|
||||
expectStateUpdate presenter, -> presenter.setScrollTop(25)
|
||||
expectStateUpdate presenter, -> presenter.setScrollTop(2)
|
||||
|
||||
expect(lineStateForScreenRow(presenter, 0)).toBeUndefined()
|
||||
expect(lineStateForScreenRow(presenter, 1)).toBeDefined()
|
||||
expect(lineStateForScreenRow(presenter, 6)).toBeDefined()
|
||||
expect(lineStateForScreenRow(presenter, 7)).toBeUndefined()
|
||||
expect(presenter.getState().content.tiles[0]).toBeUndefined()
|
||||
expect(presenter.getState().content.tiles[2]).toBeDefined()
|
||||
expect(presenter.getState().content.tiles[4]).toBeDefined()
|
||||
expect(presenter.getState().content.tiles[6]).toBeDefined()
|
||||
expect(presenter.getState().content.tiles[8]).toBeDefined()
|
||||
expect(presenter.getState().content.tiles[10]).toBeUndefined()
|
||||
|
||||
it "updates when ::explicitHeight changes", ->
|
||||
presenter = buildPresenter(explicitHeight: 15, scrollTop: 15, lineHeight: 10, lineOverdrawMargin: 1)
|
||||
presenter = buildPresenter(explicitHeight: 6, scrollTop: 0, lineHeight: 1, tileSize: 2)
|
||||
|
||||
line5 = editor.tokenizedLineForScreenRow(5)
|
||||
expect(presenter.getState().content.tiles[0]).toBeDefined()
|
||||
expect(presenter.getState().content.tiles[2]).toBeDefined()
|
||||
expect(presenter.getState().content.tiles[4]).toBeDefined()
|
||||
expect(presenter.getState().content.tiles[6]).toBeDefined()
|
||||
expect(presenter.getState().content.tiles[8]).toBeUndefined()
|
||||
|
||||
expect(lineStateForScreenRow(presenter, 4)).toBeDefined()
|
||||
expect(lineStateForScreenRow(presenter, 5)).toBeUndefined()
|
||||
expectStateUpdate presenter, -> presenter.setExplicitHeight(8)
|
||||
|
||||
expectStateUpdate presenter, -> presenter.setExplicitHeight(35)
|
||||
expect(presenter.getState().content.tiles[0]).toBeDefined()
|
||||
expect(presenter.getState().content.tiles[2]).toBeDefined()
|
||||
expect(presenter.getState().content.tiles[4]).toBeDefined()
|
||||
expect(presenter.getState().content.tiles[6]).toBeDefined()
|
||||
expect(presenter.getState().content.tiles[8]).toBeDefined()
|
||||
expect(presenter.getState().content.tiles[10]).toBeUndefined()
|
||||
|
||||
expect(lineStateForScreenRow(presenter, 5)).toBeDefined()
|
||||
expect(lineStateForScreenRow(presenter, 6)).toBeDefined()
|
||||
expect(lineStateForScreenRow(presenter, 7)).toBeUndefined()
|
||||
|
||||
it "updates when ::lineHeight changes", ->
|
||||
presenter = buildPresenter(explicitHeight: 15, scrollTop: 10, lineHeight: 10, lineOverdrawMargin: 0)
|
||||
presenter = buildPresenter(explicitHeight: 6, scrollTop: 0, lineHeight: 1, tileSize: 2)
|
||||
|
||||
expect(lineStateForScreenRow(presenter, 0)).toBeUndefined()
|
||||
expect(lineStateForScreenRow(presenter, 1)).toBeDefined()
|
||||
expect(lineStateForScreenRow(presenter, 2)).toBeDefined()
|
||||
expect(lineStateForScreenRow(presenter, 4)).toBeUndefined()
|
||||
expect(presenter.getState().content.tiles[0]).toBeDefined()
|
||||
expect(presenter.getState().content.tiles[2]).toBeDefined()
|
||||
expect(presenter.getState().content.tiles[4]).toBeDefined()
|
||||
expect(presenter.getState().content.tiles[6]).toBeDefined()
|
||||
expect(presenter.getState().content.tiles[8]).toBeUndefined()
|
||||
|
||||
expectStateUpdate presenter, -> presenter.setLineHeight(5)
|
||||
expectStateUpdate presenter, -> presenter.setLineHeight(2)
|
||||
|
||||
expect(lineStateForScreenRow(presenter, 0)).toBeUndefined()
|
||||
expect(lineStateForScreenRow(presenter, 1)).toBeUndefined()
|
||||
expect(lineStateForScreenRow(presenter, 2)).toBeDefined()
|
||||
expect(lineStateForScreenRow(presenter, 5)).toBeDefined()
|
||||
expect(lineStateForScreenRow(presenter, 6)).toBeUndefined()
|
||||
expect(presenter.getState().content.tiles[0]).toBeDefined()
|
||||
expect(presenter.getState().content.tiles[2]).toBeDefined()
|
||||
expect(presenter.getState().content.tiles[4]).toBeDefined()
|
||||
expect(presenter.getState().content.tiles[6]).toBeUndefined()
|
||||
|
||||
it "updates when the editor's content changes", ->
|
||||
presenter = buildPresenter(explicitHeight: 25, scrollTop: 10, lineHeight: 10)
|
||||
presenter = buildPresenter(explicitHeight: 25, scrollTop: 10, lineHeight: 10, tileSize: 2)
|
||||
|
||||
expectStateUpdate presenter, -> buffer.insert([2, 0], "hello\nworld\n")
|
||||
|
||||
@@ -832,53 +796,125 @@ describe "TextEditorPresenter", ->
|
||||
tags: line3.tags
|
||||
}
|
||||
|
||||
it "does not remove out-of-view lines corresponding to ::mouseWheelScreenRow until ::stoppedScrollingDelay elapses", ->
|
||||
presenter = buildPresenter(explicitHeight: 25, scrollTop: 0, lineHeight: 10, lineOverdrawMargin: 1, stoppedScrollingDelay: 200)
|
||||
it "does not remove out-of-view tiles corresponding to ::mouseWheelScreenRow until ::stoppedScrollingDelay elapses", ->
|
||||
presenter = buildPresenter(explicitHeight: 6, scrollTop: 0, lineHeight: 1, tileSize: 2, stoppedScrollingDelay: 200)
|
||||
|
||||
expect(lineStateForScreenRow(presenter, 0)).toBeDefined()
|
||||
expect(lineStateForScreenRow(presenter, 4)).toBeDefined()
|
||||
expect(lineStateForScreenRow(presenter, 5)).toBeUndefined()
|
||||
expect(presenter.getState().content.tiles[0]).toBeDefined()
|
||||
expect(presenter.getState().content.tiles[6]).toBeDefined()
|
||||
expect(presenter.getState().content.tiles[8]).toBeUndefined()
|
||||
|
||||
presenter.setMouseWheelScreenRow(0)
|
||||
expectStateUpdate presenter, -> presenter.setScrollTop(35)
|
||||
expectStateUpdate presenter, -> presenter.setScrollTop(4)
|
||||
|
||||
expect(lineStateForScreenRow(presenter, 0)).toBeDefined()
|
||||
expect(lineStateForScreenRow(presenter, 1)).toBeUndefined()
|
||||
expect(lineStateForScreenRow(presenter, 7)).toBeDefined()
|
||||
expect(lineStateForScreenRow(presenter, 8)).toBeUndefined()
|
||||
expect(presenter.getState().content.tiles[0]).toBeDefined()
|
||||
expect(presenter.getState().content.tiles[2]).toBeUndefined()
|
||||
expect(presenter.getState().content.tiles[4]).toBeDefined()
|
||||
expect(presenter.getState().content.tiles[12]).toBeUndefined()
|
||||
|
||||
expectStateUpdate presenter, -> advanceClock(200)
|
||||
|
||||
expect(lineStateForScreenRow(presenter, 0)).toBeUndefined()
|
||||
expect(lineStateForScreenRow(presenter, 1)).toBeUndefined()
|
||||
expect(lineStateForScreenRow(presenter, 2)).toBeDefined()
|
||||
expect(lineStateForScreenRow(presenter, 7)).toBeDefined()
|
||||
expect(lineStateForScreenRow(presenter, 8)).toBeUndefined()
|
||||
expect(presenter.getState().content.tiles[0]).toBeUndefined()
|
||||
expect(presenter.getState().content.tiles[2]).toBeUndefined()
|
||||
expect(presenter.getState().content.tiles[4]).toBeDefined()
|
||||
expect(presenter.getState().content.tiles[12]).toBeUndefined()
|
||||
|
||||
|
||||
# should clear ::mouseWheelScreenRow after stoppedScrollingDelay elapses even if we don't scroll first
|
||||
presenter.setMouseWheelScreenRow(2)
|
||||
presenter.setMouseWheelScreenRow(4)
|
||||
advanceClock(200)
|
||||
expectStateUpdate presenter, -> presenter.setScrollTop(45)
|
||||
expect(lineStateForScreenRow(presenter, 2)).toBeUndefined()
|
||||
expectStateUpdate presenter, -> presenter.setScrollTop(6)
|
||||
expect(presenter.getState().content.tiles[4]).toBeUndefined()
|
||||
|
||||
it "does not preserve on-screen lines even if they correspond to ::mouseWheelScreenRow", ->
|
||||
presenter = buildPresenter(explicitHeight: 25, scrollTop: 0, lineHeight: 10, lineOverdrawMargin: 1, stoppedScrollingDelay: 200)
|
||||
oldLine3 = editor.tokenizedLineForScreenRow(6)
|
||||
it "does not preserve deleted on-screen tiles even if they correspond to ::mouseWheelScreenRow", ->
|
||||
presenter = buildPresenter(explicitHeight: 6, scrollTop: 0, lineHeight: 1, tileSize: 2, stoppedScrollingDelay: 200)
|
||||
|
||||
presenter.setMouseWheelScreenRow(3)
|
||||
presenter.setMouseWheelScreenRow(2)
|
||||
|
||||
expectStateUpdate presenter, -> editor.getBuffer().insert([3, Infinity], 'xyz')
|
||||
newLine3 = editor.tokenizedLineForScreenRow(3)
|
||||
expectStateUpdate presenter, -> editor.setText("")
|
||||
|
||||
expect(presenter.getState().content.lines[oldLine3.id]).toBeUndefined()
|
||||
expect(presenter.getState().content.lines[newLine3.id]).toBeDefined()
|
||||
expect(presenter.getState().content.tiles[2]).toBeUndefined()
|
||||
expect(presenter.getState().content.tiles[0]).toBeDefined()
|
||||
|
||||
it "does not attempt to preserve lines corresponding to ::mouseWheelScreenRow if they have been deleted", ->
|
||||
presenter = buildPresenter(explicitHeight: 25, scrollTop: 0, lineHeight: 10, lineOverdrawMargin: 1, stoppedScrollingDelay: 200)
|
||||
presenter.setMouseWheelScreenRow(10)
|
||||
editor.setText('')
|
||||
describe "[tileId].lines[lineId]", -> # line state objects
|
||||
it "includes the state for visible lines in a tile", ->
|
||||
presenter = buildPresenter(explicitHeight: 3, scrollTop: 4, lineHeight: 1, tileSize: 3, stoppedScrollingDelay: 200)
|
||||
|
||||
expect(lineStateForScreenRow(presenter, 2)).toBeUndefined()
|
||||
|
||||
line3 = editor.tokenizedLineForScreenRow(3)
|
||||
expectValues lineStateForScreenRow(presenter, 3), {
|
||||
screenRow: 3
|
||||
text: line3.text
|
||||
tags: line3.tags
|
||||
specialTokens: line3.specialTokens
|
||||
firstNonWhitespaceIndex: line3.firstNonWhitespaceIndex
|
||||
firstTrailingWhitespaceIndex: line3.firstTrailingWhitespaceIndex
|
||||
invisibles: line3.invisibles
|
||||
top: 0
|
||||
}
|
||||
|
||||
line4 = editor.tokenizedLineForScreenRow(4)
|
||||
expectValues lineStateForScreenRow(presenter, 4), {
|
||||
screenRow: 4
|
||||
text: line4.text
|
||||
tags: line4.tags
|
||||
specialTokens: line4.specialTokens
|
||||
firstNonWhitespaceIndex: line4.firstNonWhitespaceIndex
|
||||
firstTrailingWhitespaceIndex: line4.firstTrailingWhitespaceIndex
|
||||
invisibles: line4.invisibles
|
||||
top: 1
|
||||
}
|
||||
|
||||
line5 = editor.tokenizedLineForScreenRow(5)
|
||||
expectValues lineStateForScreenRow(presenter, 5), {
|
||||
screenRow: 5
|
||||
text: line5.text
|
||||
tags: line5.tags
|
||||
specialTokens: line5.specialTokens
|
||||
firstNonWhitespaceIndex: line5.firstNonWhitespaceIndex
|
||||
firstTrailingWhitespaceIndex: line5.firstTrailingWhitespaceIndex
|
||||
invisibles: line5.invisibles
|
||||
top: 2
|
||||
}
|
||||
|
||||
line6 = editor.tokenizedLineForScreenRow(6)
|
||||
expectValues lineStateForScreenRow(presenter, 6), {
|
||||
screenRow: 6
|
||||
text: line6.text
|
||||
tags: line6.tags
|
||||
specialTokens: line6.specialTokens
|
||||
firstNonWhitespaceIndex: line6.firstNonWhitespaceIndex
|
||||
firstTrailingWhitespaceIndex: line6.firstTrailingWhitespaceIndex
|
||||
invisibles: line6.invisibles
|
||||
top: 0
|
||||
}
|
||||
|
||||
line7 = editor.tokenizedLineForScreenRow(7)
|
||||
expectValues lineStateForScreenRow(presenter, 7), {
|
||||
screenRow: 7
|
||||
text: line7.text
|
||||
tags: line7.tags
|
||||
specialTokens: line7.specialTokens
|
||||
firstNonWhitespaceIndex: line7.firstNonWhitespaceIndex
|
||||
firstTrailingWhitespaceIndex: line7.firstTrailingWhitespaceIndex
|
||||
invisibles: line7.invisibles
|
||||
top: 1
|
||||
}
|
||||
|
||||
line8 = editor.tokenizedLineForScreenRow(8)
|
||||
expectValues lineStateForScreenRow(presenter, 8), {
|
||||
screenRow: 8
|
||||
text: line8.text
|
||||
tags: line8.tags
|
||||
specialTokens: line8.specialTokens
|
||||
firstNonWhitespaceIndex: line8.firstNonWhitespaceIndex
|
||||
firstTrailingWhitespaceIndex: line8.firstTrailingWhitespaceIndex
|
||||
invisibles: line8.invisibles
|
||||
top: 2
|
||||
}
|
||||
|
||||
expect(lineStateForScreenRow(presenter, 9)).toBeUndefined()
|
||||
|
||||
describe "[lineId]", -> # line state objects
|
||||
it "includes the .endOfLineInvisibles if the editor.showInvisibles config option is true", ->
|
||||
editor.setText("hello\nworld\r\n")
|
||||
presenter = buildPresenter(explicitHeight: 25, scrollTop: 0, lineHeight: 10)
|
||||
@@ -1031,9 +1067,9 @@ describe "TextEditorPresenter", ->
|
||||
presenter = buildPresenter(explicitHeight: 30, scrollTop: 20)
|
||||
|
||||
expect(stateForCursor(presenter, 0)).toBeUndefined()
|
||||
expect(stateForCursor(presenter, 1)).toEqual {top: 2 * 10, left: 4 * 10, width: 10, height: 10}
|
||||
expect(stateForCursor(presenter, 1)).toEqual {top: 0, left: 4 * 10, width: 10, height: 10}
|
||||
expect(stateForCursor(presenter, 2)).toBeUndefined()
|
||||
expect(stateForCursor(presenter, 3)).toEqual {top: 5 * 10, left: 12 * 10, width: 10, height: 10}
|
||||
expect(stateForCursor(presenter, 3)).toEqual {top: 5 * 10 - 20, left: 12 * 10, width: 10, height: 10}
|
||||
expect(stateForCursor(presenter, 4)).toBeUndefined()
|
||||
|
||||
it "is empty until all of the required measurements are assigned", ->
|
||||
@@ -1069,8 +1105,21 @@ describe "TextEditorPresenter", ->
|
||||
expect(stateForCursor(presenter, 0)).toBeUndefined()
|
||||
expect(stateForCursor(presenter, 1)).toBeUndefined()
|
||||
expect(stateForCursor(presenter, 2)).toBeUndefined()
|
||||
expect(stateForCursor(presenter, 3)).toEqual {top: 5 * 10, left: 12 * 10, width: 10, height: 10}
|
||||
expect(stateForCursor(presenter, 4)).toEqual {top: 8 * 10, left: 4 * 10, width: 10, height: 10}
|
||||
expect(stateForCursor(presenter, 3)).toEqual {top: 0, left: 12 * 10, width: 10, height: 10}
|
||||
expect(stateForCursor(presenter, 4)).toEqual {top: 8 * 10 - 50, left: 4 * 10, width: 10, height: 10}
|
||||
|
||||
it "updates when ::scrollTop changes after the model was changed", ->
|
||||
editor.setCursorBufferPosition([8, 22])
|
||||
presenter = buildPresenter(explicitHeight: 50, scrollTop: 10 * 8)
|
||||
|
||||
expect(stateForCursor(presenter, 0)).toEqual {top: 0, left: 10 * 22, width: 10, height: 10}
|
||||
|
||||
expectStateUpdate presenter, ->
|
||||
editor.getBuffer().deleteRow(12)
|
||||
editor.getBuffer().deleteRow(11)
|
||||
editor.getBuffer().deleteRow(10)
|
||||
|
||||
expect(stateForCursor(presenter, 0)).toEqual {top: 20, left: 10 * 22, width: 10, height: 10}
|
||||
|
||||
it "updates when ::explicitHeight changes", ->
|
||||
editor.setSelectedBufferRanges([
|
||||
@@ -1084,9 +1133,9 @@ describe "TextEditorPresenter", ->
|
||||
|
||||
expectStateUpdate presenter, -> presenter.setExplicitHeight(30)
|
||||
expect(stateForCursor(presenter, 0)).toBeUndefined()
|
||||
expect(stateForCursor(presenter, 1)).toEqual {top: 2 * 10, left: 4 * 10, width: 10, height: 10}
|
||||
expect(stateForCursor(presenter, 1)).toEqual {top: 0, left: 4 * 10, width: 10, height: 10}
|
||||
expect(stateForCursor(presenter, 2)).toBeUndefined()
|
||||
expect(stateForCursor(presenter, 3)).toEqual {top: 5 * 10, left: 12 * 10, width: 10, height: 10}
|
||||
expect(stateForCursor(presenter, 3)).toEqual {top: 5 * 10 - 20, left: 12 * 10, width: 10, height: 10}
|
||||
expect(stateForCursor(presenter, 4)).toBeUndefined()
|
||||
|
||||
it "updates when ::lineHeight changes", ->
|
||||
@@ -1103,15 +1152,15 @@ describe "TextEditorPresenter", ->
|
||||
expect(stateForCursor(presenter, 0)).toBeUndefined()
|
||||
expect(stateForCursor(presenter, 1)).toBeUndefined()
|
||||
expect(stateForCursor(presenter, 2)).toBeUndefined()
|
||||
expect(stateForCursor(presenter, 3)).toEqual {top: 5 * 5, left: 12 * 10, width: 10, height: 5}
|
||||
expect(stateForCursor(presenter, 4)).toEqual {top: 8 * 5, left: 4 * 10, width: 10, height: 5}
|
||||
expect(stateForCursor(presenter, 3)).toEqual {top: 5, left: 12 * 10, width: 10, height: 5}
|
||||
expect(stateForCursor(presenter, 4)).toEqual {top: 8 * 5 - 20, left: 4 * 10, width: 10, height: 5}
|
||||
|
||||
it "updates when ::baseCharacterWidth changes", ->
|
||||
editor.setCursorBufferPosition([2, 4])
|
||||
presenter = buildPresenter(explicitHeight: 20, scrollTop: 20)
|
||||
|
||||
expectStateUpdate presenter, -> presenter.setBaseCharacterWidth(20)
|
||||
expect(stateForCursor(presenter, 0)).toEqual {top: 2 * 10, left: 4 * 20, width: 20, height: 10}
|
||||
expect(stateForCursor(presenter, 0)).toEqual {top: 0, left: 4 * 20, width: 20, height: 10}
|
||||
|
||||
it "updates when scoped character widths change", ->
|
||||
waitsForPromise ->
|
||||
@@ -1137,11 +1186,11 @@ describe "TextEditorPresenter", ->
|
||||
# moving into view
|
||||
expect(stateForCursor(presenter, 0)).toBeUndefined()
|
||||
editor.getCursors()[0].setBufferPosition([2, 4])
|
||||
expect(stateForCursor(presenter, 0)).toEqual {top: 2 * 10, left: 4 * 10, width: 10, height: 10}
|
||||
expect(stateForCursor(presenter, 0)).toEqual {top: 0, left: 4 * 10, width: 10, height: 10}
|
||||
|
||||
# showing
|
||||
expectStateUpdate presenter, -> editor.getSelections()[1].clear()
|
||||
expect(stateForCursor(presenter, 1)).toEqual {top: 3 * 10, left: 5 * 10, width: 10, height: 10}
|
||||
expect(stateForCursor(presenter, 1)).toEqual {top: 5, left: 5 * 10, width: 10, height: 10}
|
||||
|
||||
# hiding
|
||||
expectStateUpdate presenter, -> editor.getSelections()[1].setBufferRange([[3, 4], [3, 5]])
|
||||
@@ -1153,11 +1202,11 @@ describe "TextEditorPresenter", ->
|
||||
|
||||
# adding
|
||||
expectStateUpdate presenter, -> editor.addCursorAtBufferPosition([4, 4])
|
||||
expect(stateForCursor(presenter, 2)).toEqual {top: 4 * 10, left: 4 * 10, width: 10, height: 10}
|
||||
expect(stateForCursor(presenter, 2)).toEqual {top: 5, left: 4 * 10, width: 10, height: 10}
|
||||
|
||||
# moving added cursor
|
||||
expectStateUpdate presenter, -> editor.getCursors()[2].setBufferPosition([4, 6])
|
||||
expect(stateForCursor(presenter, 2)).toEqual {top: 4 * 10, left: 6 * 10, width: 10, height: 10}
|
||||
expect(stateForCursor(presenter, 2)).toEqual {top: 5, left: 6 * 10, width: 10, height: 10}
|
||||
|
||||
# destroying
|
||||
destroyedCursor = editor.getCursors()[2]
|
||||
@@ -1275,39 +1324,39 @@ describe "TextEditorPresenter", ->
|
||||
expectValues stateForHighlight(presenter, highlight2), {
|
||||
class: 'b'
|
||||
regions: [
|
||||
{top: 2 * 10, left: 0 * 10, width: 6 * 10, height: 1 * 10}
|
||||
{top: 2 * 10 - 20, left: 0 * 10, width: 6 * 10, height: 1 * 10}
|
||||
]
|
||||
}
|
||||
|
||||
expectValues stateForHighlight(presenter, highlight3), {
|
||||
class: 'c'
|
||||
regions: [
|
||||
{top: 2 * 10, left: 0 * 10, right: 0, height: 1 * 10}
|
||||
{top: 3 * 10, left: 0 * 10, width: 6 * 10, height: 1 * 10}
|
||||
{top: 2 * 10 - 20, left: 0 * 10, right: 0, height: 1 * 10}
|
||||
{top: 3 * 10 - 20, left: 0 * 10, width: 6 * 10, height: 1 * 10}
|
||||
]
|
||||
}
|
||||
|
||||
expectValues stateForHighlight(presenter, highlight4), {
|
||||
class: 'd'
|
||||
regions: [
|
||||
{top: 2 * 10, left: 6 * 10, right: 0, height: 1 * 10}
|
||||
{top: 3 * 10, left: 0, right: 0, height: 1 * 10}
|
||||
{top: 4 * 10, left: 0, width: 6 * 10, height: 1 * 10}
|
||||
{top: 2 * 10 - 20, left: 6 * 10, right: 0, height: 1 * 10}
|
||||
{top: 3 * 10 - 20, left: 0, right: 0, height: 1 * 10}
|
||||
{top: 4 * 10 - 20, left: 0, width: 6 * 10, height: 1 * 10}
|
||||
]
|
||||
}
|
||||
|
||||
expectValues stateForHighlight(presenter, highlight5), {
|
||||
class: 'e'
|
||||
regions: [
|
||||
{top: 3 * 10, left: 6 * 10, right: 0, height: 1 * 10}
|
||||
{top: 4 * 10, left: 0 * 10, right: 0, height: 2 * 10}
|
||||
{top: 3 * 10 - 20, left: 6 * 10, right: 0, height: 1 * 10}
|
||||
{top: 4 * 10 - 20, left: 0 * 10, right: 0, height: 2 * 10}
|
||||
]
|
||||
}
|
||||
|
||||
expectValues stateForHighlight(presenter, highlight6), {
|
||||
class: 'f'
|
||||
regions: [
|
||||
{top: 5 * 10, left: 6 * 10, right: 0, height: 1 * 10}
|
||||
{top: 5 * 10 - 20, left: 6 * 10, right: 0, height: 1 * 10}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1913,20 +1962,18 @@ describe "TextEditorPresenter", ->
|
||||
|
||||
getLineNumberGutterState(presenter).content.lineNumbers[key]
|
||||
|
||||
it "contains states for line numbers that are visible on screen, plus and minus the overdraw margin", ->
|
||||
it "contains states for line numbers that are visible on screen", ->
|
||||
editor.foldBufferRow(4)
|
||||
editor.setSoftWrapped(true)
|
||||
editor.setEditorWidthInChars(50)
|
||||
presenter = buildPresenter(explicitHeight: 25, scrollTop: 30, lineHeight: 10, lineOverdrawMargin: 1)
|
||||
presenter = buildPresenter(explicitHeight: 25, scrollTop: 30, lineHeight: 10)
|
||||
|
||||
expect(lineNumberStateForScreenRow(presenter, 1)).toBeUndefined()
|
||||
expectValues lineNumberStateForScreenRow(presenter, 2), {screenRow: 2, bufferRow: 2, softWrapped: false, top: 2 * 10}
|
||||
expect(lineNumberStateForScreenRow(presenter, 2)).toBeUndefined()
|
||||
expectValues lineNumberStateForScreenRow(presenter, 3), {screenRow: 3, bufferRow: 3, softWrapped: false, top: 3 * 10}
|
||||
expectValues lineNumberStateForScreenRow(presenter, 4), {screenRow: 4, bufferRow: 3, softWrapped: true, top: 4 * 10}
|
||||
expectValues lineNumberStateForScreenRow(presenter, 5), {screenRow: 5, bufferRow: 4, softWrapped: false, top: 5 * 10}
|
||||
expectValues lineNumberStateForScreenRow(presenter, 6), {screenRow: 6, bufferRow: 7, softWrapped: false, top: 6 * 10}
|
||||
expectValues lineNumberStateForScreenRow(presenter, 7), {screenRow: 7, bufferRow: 8, softWrapped: false, top: 7 * 10}
|
||||
expect(lineNumberStateForScreenRow(presenter, 8)).toBeUndefined()
|
||||
expect(lineNumberStateForScreenRow(presenter, 7)).toBeUndefined()
|
||||
|
||||
it "includes states for all line numbers if no ::explicitHeight is assigned", ->
|
||||
presenter = buildPresenter(explicitHeight: null)
|
||||
@@ -1937,43 +1984,43 @@ describe "TextEditorPresenter", ->
|
||||
editor.foldBufferRow(4)
|
||||
editor.setSoftWrapped(true)
|
||||
editor.setEditorWidthInChars(50)
|
||||
presenter = buildPresenter(explicitHeight: 25, scrollTop: 30, lineOverdrawMargin: 1)
|
||||
presenter = buildPresenter(explicitHeight: 25, scrollTop: 30)
|
||||
|
||||
expect(lineNumberStateForScreenRow(presenter, 1)).toBeUndefined()
|
||||
expectValues lineNumberStateForScreenRow(presenter, 2), {bufferRow: 2}
|
||||
expectValues lineNumberStateForScreenRow(presenter, 7), {bufferRow: 8}
|
||||
expect(lineNumberStateForScreenRow(presenter, 8)).toBeUndefined()
|
||||
expect(lineNumberStateForScreenRow(presenter, 2)).toBeUndefined()
|
||||
expectValues lineNumberStateForScreenRow(presenter, 3), {bufferRow: 3}
|
||||
expectValues lineNumberStateForScreenRow(presenter, 6), {bufferRow: 7}
|
||||
expect(lineNumberStateForScreenRow(presenter, 7)).toBeUndefined()
|
||||
|
||||
expectStateUpdate presenter, -> presenter.setScrollTop(20)
|
||||
|
||||
expect(lineNumberStateForScreenRow(presenter, 0)).toBeUndefined()
|
||||
expectValues lineNumberStateForScreenRow(presenter, 1), {bufferRow: 1}
|
||||
expectValues lineNumberStateForScreenRow(presenter, 6), {bufferRow: 7}
|
||||
expect(lineNumberStateForScreenRow(presenter, 7)).toBeUndefined()
|
||||
expect(lineNumberStateForScreenRow(presenter, 1)).toBeUndefined()
|
||||
expectValues lineNumberStateForScreenRow(presenter, 2), {bufferRow: 2}
|
||||
expectValues lineNumberStateForScreenRow(presenter, 5), {bufferRow: 4}
|
||||
expect(lineNumberStateForScreenRow(presenter, 6)).toBeUndefined()
|
||||
|
||||
it "updates when ::explicitHeight changes", ->
|
||||
editor.foldBufferRow(4)
|
||||
editor.setSoftWrapped(true)
|
||||
editor.setEditorWidthInChars(50)
|
||||
presenter = buildPresenter(explicitHeight: 25, scrollTop: 30, lineOverdrawMargin: 1)
|
||||
presenter = buildPresenter(explicitHeight: 25, scrollTop: 30)
|
||||
|
||||
expect(lineNumberStateForScreenRow(presenter, 1)).toBeUndefined()
|
||||
expectValues lineNumberStateForScreenRow(presenter, 2), {bufferRow: 2}
|
||||
expectValues lineNumberStateForScreenRow(presenter, 7), {bufferRow: 8}
|
||||
expect(lineNumberStateForScreenRow(presenter, 8)).toBeUndefined()
|
||||
expectValues lineNumberStateForScreenRow(presenter, 3), {bufferRow: 3}
|
||||
expectValues lineNumberStateForScreenRow(presenter, 6), {bufferRow: 7}
|
||||
expect(lineNumberStateForScreenRow(presenter, 7)).toBeUndefined()
|
||||
|
||||
expectStateUpdate presenter, -> presenter.setExplicitHeight(35)
|
||||
|
||||
expect(lineNumberStateForScreenRow(presenter, 0)).toBeUndefined()
|
||||
expectValues lineNumberStateForScreenRow(presenter, 2), {bufferRow: 2}
|
||||
expectValues lineNumberStateForScreenRow(presenter, 8), {bufferRow: 8}
|
||||
expect(lineNumberStateForScreenRow(presenter, 9)).toBeUndefined()
|
||||
expectValues lineNumberStateForScreenRow(presenter, 3), {bufferRow: 3}
|
||||
expectValues lineNumberStateForScreenRow(presenter, 7), {bufferRow: 8}
|
||||
expect(lineNumberStateForScreenRow(presenter, 8)).toBeUndefined()
|
||||
|
||||
it "updates when ::lineHeight changes", ->
|
||||
editor.foldBufferRow(4)
|
||||
editor.setSoftWrapped(true)
|
||||
editor.setEditorWidthInChars(50)
|
||||
presenter = buildPresenter(explicitHeight: 25, scrollTop: 0, lineOverdrawMargin: 0)
|
||||
presenter = buildPresenter(explicitHeight: 25, scrollTop: 0)
|
||||
|
||||
expectValues lineNumberStateForScreenRow(presenter, 0), {bufferRow: 0}
|
||||
expectValues lineNumberStateForScreenRow(presenter, 3), {bufferRow: 3}
|
||||
@@ -1989,7 +2036,7 @@ describe "TextEditorPresenter", ->
|
||||
editor.foldBufferRow(4)
|
||||
editor.setSoftWrapped(true)
|
||||
editor.setEditorWidthInChars(50)
|
||||
presenter = buildPresenter(explicitHeight: 35, scrollTop: 30, lineOverdrawMargin: 0)
|
||||
presenter = buildPresenter(explicitHeight: 35, scrollTop: 30)
|
||||
|
||||
expect(lineNumberStateForScreenRow(presenter, 2)).toBeUndefined()
|
||||
expectValues lineNumberStateForScreenRow(presenter, 3), {bufferRow: 3}
|
||||
@@ -2011,26 +2058,26 @@ describe "TextEditorPresenter", ->
|
||||
expect(lineNumberStateForScreenRow(presenter, 8)).toBeUndefined()
|
||||
|
||||
it "does not remove out-of-view line numbers corresponding to ::mouseWheelScreenRow until ::stoppedScrollingDelay elapses", ->
|
||||
presenter = buildPresenter(explicitHeight: 25, lineOverdrawMargin: 1, stoppedScrollingDelay: 200)
|
||||
presenter = buildPresenter(explicitHeight: 25, stoppedScrollingDelay: 200)
|
||||
|
||||
expect(lineNumberStateForScreenRow(presenter, 0)).toBeDefined()
|
||||
expect(lineNumberStateForScreenRow(presenter, 4)).toBeDefined()
|
||||
expect(lineNumberStateForScreenRow(presenter, 5)).toBeUndefined()
|
||||
expect(lineNumberStateForScreenRow(presenter, 3)).toBeDefined()
|
||||
expect(lineNumberStateForScreenRow(presenter, 4)).toBeUndefined()
|
||||
|
||||
presenter.setMouseWheelScreenRow(0)
|
||||
expectStateUpdate presenter, -> presenter.setScrollTop(35)
|
||||
|
||||
expect(lineNumberStateForScreenRow(presenter, 0)).toBeDefined()
|
||||
expect(lineNumberStateForScreenRow(presenter, 1)).toBeUndefined()
|
||||
expect(lineNumberStateForScreenRow(presenter, 7)).toBeDefined()
|
||||
expect(lineNumberStateForScreenRow(presenter, 8)).toBeUndefined()
|
||||
expect(lineNumberStateForScreenRow(presenter, 6)).toBeDefined()
|
||||
expect(lineNumberStateForScreenRow(presenter, 7)).toBeUndefined()
|
||||
|
||||
expectStateUpdate presenter, -> advanceClock(200)
|
||||
|
||||
expect(lineNumberStateForScreenRow(presenter, 0)).toBeUndefined()
|
||||
expect(lineNumberStateForScreenRow(presenter, 1)).toBeUndefined()
|
||||
expect(lineNumberStateForScreenRow(presenter, 7)).toBeDefined()
|
||||
expect(lineNumberStateForScreenRow(presenter, 8)).toBeUndefined()
|
||||
expect(lineNumberStateForScreenRow(presenter, 6)).toBeDefined()
|
||||
expect(lineNumberStateForScreenRow(presenter, 7)).toBeUndefined()
|
||||
|
||||
it "correctly handles the first screen line being soft-wrapped", ->
|
||||
editor.setSoftWrapped(true)
|
||||
@@ -2213,12 +2260,11 @@ describe "TextEditorPresenter", ->
|
||||
scrollTop = 0
|
||||
lineHeight = 10
|
||||
explicitHeight = lineHeight * 10
|
||||
lineOverdrawMargin = 1
|
||||
|
||||
beforeEach ->
|
||||
# At the beginning of each test, decoration1 and decoration2 are in visible range,
|
||||
# but not decoration3.
|
||||
presenter = buildPresenter({explicitHeight, scrollTop, lineHeight, lineOverdrawMargin})
|
||||
presenter = buildPresenter({explicitHeight, scrollTop, lineHeight})
|
||||
gutter = editor.addGutter({name: 'test-gutter', visible: true})
|
||||
decorationItem = document.createElement('div')
|
||||
decorationItem.class = 'decoration-item'
|
||||
@@ -2589,7 +2635,7 @@ describe "TextEditorPresenter", ->
|
||||
editor.setEditorWidthInChars(80)
|
||||
presenterParams =
|
||||
model: editor
|
||||
lineOverdrawMargin: 1
|
||||
|
||||
presenter = new TextEditorPresenter(presenterParams)
|
||||
statements = []
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
fs = require 'fs-plus'
|
||||
path = require 'path'
|
||||
temp = require 'temp'
|
||||
clipboard = require '../src/safe-clipboard'
|
||||
TextEditor = require '../src/text-editor'
|
||||
|
||||
@@ -19,6 +22,17 @@ describe "TextEditor", ->
|
||||
atom.packages.activatePackage('language-javascript')
|
||||
|
||||
describe "when the editor is deserialized", ->
|
||||
it "returns undefined when the path cannot be read", ->
|
||||
pathToOpen = path.join(temp.mkdirSync(), 'file.txt')
|
||||
editor1 = null
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.open(pathToOpen).then (o) -> editor1 = o
|
||||
|
||||
runs ->
|
||||
fs.mkdirSync(pathToOpen)
|
||||
expect(editor1.testSerialization()).toBeUndefined()
|
||||
|
||||
it "restores selections and folds based on markers in the buffer", ->
|
||||
editor.setSelectedBufferRange([[1, 2], [3, 4]])
|
||||
editor.addSelectionForBufferRange([[5, 6], [7, 5]], reversed: true)
|
||||
|
||||
@@ -293,3 +293,14 @@ describe "Window", ->
|
||||
pathToOpen = __dirname
|
||||
atom.getCurrentWindow().send 'message', 'open-locations', [{pathToOpen}]
|
||||
expect(atom.workspace.open.callCount).toBe 0
|
||||
|
||||
describe "when the opened path is a uri", ->
|
||||
it "adds it to the project's paths as is", ->
|
||||
pathToOpen = 'remote://server:7644/some/dir/path'
|
||||
atom.getCurrentWindow().send 'message', 'open-locations', [{pathToOpen}]
|
||||
|
||||
waitsFor ->
|
||||
atom.project.getPaths().length is 1
|
||||
|
||||
runs ->
|
||||
expect(atom.project.getPaths()[0]).toBe pathToOpen
|
||||
|
||||
Reference in New Issue
Block a user