Start porting TextEditorComponent spec

This commit is contained in:
Antonio Scandurra
2015-06-12 13:12:50 +02:00
parent 605f584d2e
commit 7ac0cdcbf5
5 changed files with 102 additions and 49 deletions

View File

@@ -5,9 +5,9 @@ TextEditorView = require '../src/text-editor-view'
TextEditorComponent = require '../src/text-editor-component'
nbsp = String.fromCharCode(160)
describe "TextEditorComponent", ->
fdescribe "TextEditorComponent", ->
[contentNode, editor, wrapperView, wrapperNode, component, componentNode, verticalScrollbarNode, horizontalScrollbarNode] = []
[lineHeightInPixels, charWidth, nextAnimationFrame, noAnimationFrame, tileSize] = []
[lineHeightInPixels, charWidth, nextAnimationFrame, noAnimationFrame, tileSize, tileHeightInPixels] = []
beforeEach ->
tileSize = 3
@@ -45,6 +45,7 @@ describe "TextEditorComponent", ->
component.setFontSize(20)
lineHeightInPixels = editor.getLineHeightInPixels()
tileHeightInPixels = tileSize * lineHeightInPixels
charWidth = editor.getDefaultCharWidth()
componentNode = component.getDomNode()
verticalScrollbarNode = componentNode.querySelector('.vertical-scrollbar')
@@ -80,11 +81,10 @@ describe "TextEditorComponent", ->
it "renders the currently-visible lines in a tiled fashion", ->
wrapperNode.style.height = 6.5 * lineHeightInPixels + 'px'
tileHeight = tileSize * lineHeightInPixels
component.measureDimensions()
nextAnimationFrame()
tilesNodes = componentNode.querySelectorAll(".tile")
tilesNodes = componentNode.querySelector(".lines").querySelectorAll(".tile")
expect(tilesNodes.length).toBe(3)
@@ -94,13 +94,13 @@ describe "TextEditorComponent", ->
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].style['-webkit-transform']).toBe "translate3d(0px, #{1 * tileHeightInPixels}px, 0px)"
expect(tilesNodes[1].querySelectorAll(".line").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].style['-webkit-transform']).toBe "translate3d(0px, #{2 * tileHeightInPixels}px, 0px)"
expect(tilesNodes[2].querySelectorAll(".line").length).toBe(tileSize)
expectTileContainsRow(tilesNodes[2], 6, top: 0 * lineHeightInPixels)
expectTileContainsRow(tilesNodes[2], 7, top: 1 * lineHeightInPixels)
@@ -112,24 +112,24 @@ describe "TextEditorComponent", ->
verticalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
nextAnimationFrame()
tilesNodes = componentNode.querySelectorAll(".tile")
tilesNodes = componentNode.querySelector(".lines").querySelectorAll(".tile")
expect(component.lineNodeForScreenRow(2)).toBeUndefined()
expect(tilesNodes.length).toBe(3)
expect(tilesNodes[0].style['-webkit-transform']).toBe "translate3d(0px, -5px, 0px)"
expect(tilesNodes[0].style['-webkit-transform']).toBe "translate3d(0px, #{0 * tileHeightInPixels - 5}px, 0px)"
expect(tilesNodes[0].querySelectorAll(".line").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].style['-webkit-transform']).toBe "translate3d(0px, #{1 * tileHeightInPixels - 5}px, 0px)"
expect(tilesNodes[1].querySelectorAll(".line").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].style['-webkit-transform']).toBe "translate3d(0px, #{2 * tileHeightInPixels - 5}px, 0px)"
expect(tilesNodes[2].querySelectorAll(".line").length).toBe(tileSize)
expectTileContainsRow(tilesNodes[2], 9, top: 0 * lineHeightInPixels)
expectTileContainsRow(tilesNodes[2], 10, top: 1 * lineHeightInPixels)
@@ -137,19 +137,18 @@ describe "TextEditorComponent", ->
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()
tilesNodes = componentNode.querySelectorAll(".tile")
tilesNodes = componentNode.querySelector(".lines").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)"
expect(tilesNodes[1].style['-webkit-transform']).toBe "translate3d(0px, #{1 * tileHeightInPixels}px, 0px)"
expectTileContainsRow(tilesNodes[1], 3, top: 0 * lineHeightInPixels)
expectTileContainsRow(tilesNodes[1], 4, top: 1 * lineHeightInPixels)
expectTileContainsRow(tilesNodes[1], 5, top: 2 * lineHeightInPixels)
@@ -157,19 +156,19 @@ describe "TextEditorComponent", ->
editor.getBuffer().insert([0, 0], '\n\n')
nextAnimationFrame()
tilesNodes = componentNode.querySelectorAll(".tile")
tilesNodes = componentNode.querySelector(".lines").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)"
expect(tilesNodes[1].style['-webkit-transform']).toBe "translate3d(0px, #{1 * tileHeightInPixels}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)"
expect(tilesNodes[2].style['-webkit-transform']).toBe "translate3d(0px, #{2 * tileHeightInPixels}px, 0px)"
expectTileContainsRow(tilesNodes[2], 6, top: 0 * lineHeightInPixels)
expectTileContainsRow(tilesNodes[2], 7, top: 1 * lineHeightInPixels)
expectTileContainsRow(tilesNodes[2], 8, top: 2 * lineHeightInPixels)
@@ -543,47 +542,90 @@ describe "TextEditorComponent", ->
expect(foldedLineNode.querySelector('.fold-marker')).toBeFalsy()
describe "gutter rendering", ->
it "renders the currently-visible line numbers", ->
expectTileContainsRow = (tileNode, screenRow, {top, text}) ->
lineNode = tileNode.querySelector("[data-screen-row='#{screenRow}']")
expect(lineNode.offsetTop).toBe(top)
expect(lineNode.textContent).toBe(text)
it "renders the currently-visible line numbers in a tiled fashion", ->
wrapperNode.style.height = 4.5 * lineHeightInPixels + 'px'
component.measureDimensions()
nextAnimationFrame()
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"
tilesNodes = componentNode.querySelector(".line-numbers").querySelectorAll(".tile")
verticalScrollbarNode.scrollTop = 2.5 * lineHeightInPixels
expect(tilesNodes.length).toBe(3)
expect(tilesNodes[0].style['-webkit-transform']).toBe "translate3d(0px, 0px, 0px)"
expect(tilesNodes[0].querySelectorAll('.line-number').length).toBe 3
expectTileContainsRow(tilesNodes[0], 0, top: lineHeightInPixels * 0, text: "#{nbsp}1")
expectTileContainsRow(tilesNodes[0], 1, top: lineHeightInPixels * 1, text: "#{nbsp}2")
expectTileContainsRow(tilesNodes[0], 2, top: lineHeightInPixels * 2, text: "#{nbsp}3")
expect(tilesNodes[1].style['-webkit-transform']).toBe "translate3d(0px, #{1 * tileHeightInPixels}px, 0px)"
expect(tilesNodes[1].querySelectorAll('.line-number').length).toBe 3
expectTileContainsRow(tilesNodes[1], 3, top: lineHeightInPixels * 0, text: "#{nbsp}4")
expectTileContainsRow(tilesNodes[1], 4, top: lineHeightInPixels * 1, text: "#{nbsp}5")
expectTileContainsRow(tilesNodes[1], 5, top: lineHeightInPixels * 2, text: "#{nbsp}6")
expect(tilesNodes[2].style['-webkit-transform']).toBe "translate3d(0px, #{2 * tileHeightInPixels}px, 0px)"
expect(tilesNodes[2].querySelectorAll('.line-number').length).toBe 3
expectTileContainsRow(tilesNodes[2], 6, top: lineHeightInPixels * 0, text: "#{nbsp}7")
expectTileContainsRow(tilesNodes[2], 7, top: lineHeightInPixels * 1, text: "#{nbsp}8")
expectTileContainsRow(tilesNodes[2], 8, top: lineHeightInPixels * 2, text: "#{nbsp}9")
verticalScrollbarNode.scrollTop = tileSize * lineHeightInPixels + 5
verticalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
nextAnimationFrame()
expect(componentNode.querySelectorAll('.line-number').length).toBe 6 + 1 # visible line-numbers + dummy line number
tilesNodes = componentNode.querySelector(".line-numbers").querySelectorAll(".tile")
expect(component.lineNumberNodeForScreenRow(2).textContent).toBe "#{nbsp}3"
expect(component.lineNumberNodeForScreenRow(2).offsetTop).toBe 2 * lineHeightInPixels
expect(component.lineNumberNodeForScreenRow(7).textContent).toBe "#{nbsp}8"
expect(component.lineNumberNodeForScreenRow(7).offsetTop).toBe 7 * lineHeightInPixels
expect(component.lineNumberNodeForScreenRow(2)).toBeUndefined()
expect(tilesNodes.length).toBe(3)
expect(tilesNodes[0].style['-webkit-transform']).toBe "translate3d(0px, #{0 * tileHeightInPixels - 5}px, 0px)"
expect(tilesNodes[0].querySelectorAll(".line-number").length).toBe(tileSize)
expectTileContainsRow(tilesNodes[0], 3, top: lineHeightInPixels * 0, text: "#{nbsp}4")
expectTileContainsRow(tilesNodes[0], 4, top: lineHeightInPixels * 1, text: "#{nbsp}5")
expectTileContainsRow(tilesNodes[0], 5, top: lineHeightInPixels * 2, text: "#{nbsp}6")
expect(tilesNodes[1].style['-webkit-transform']).toBe "translate3d(0px, #{1 * tileHeightInPixels - 5}px, 0px)"
expect(tilesNodes[1].querySelectorAll(".line-number").length).toBe(tileSize)
expectTileContainsRow(tilesNodes[1], 6, top: 0 * lineHeightInPixels, text: "#{nbsp}7")
expectTileContainsRow(tilesNodes[1], 7, top: 1 * lineHeightInPixels, text: "#{nbsp}8")
expectTileContainsRow(tilesNodes[1], 8, top: 2 * lineHeightInPixels, text: "#{nbsp}9")
expect(tilesNodes[2].style['-webkit-transform']).toBe "translate3d(0px, #{2 * tileHeightInPixels - 5}px, 0px)"
expect(tilesNodes[2].querySelectorAll(".line-number").length).toBe(tileSize)
expectTileContainsRow(tilesNodes[2], 9, top: 0 * lineHeightInPixels, text: "10")
expectTileContainsRow(tilesNodes[2], 10, top: 1 * lineHeightInPixels, text: "11")
expectTileContainsRow(tilesNodes[2], 11, top: 2 * lineHeightInPixels, text: "12")
it "updates the translation of subsequent line numbers when lines are inserted or removed", ->
editor.getBuffer().insert([0, 0], '\n\n')
nextAnimationFrame()
lineNumberNodes = componentNode.querySelectorAll('.line-number')
expect(component.lineNumberNodeForScreenRow(0).offsetTop).toBe 0
expect(component.lineNumberNodeForScreenRow(0).offsetTop).toBe 0 * lineHeightInPixels
expect(component.lineNumberNodeForScreenRow(1).offsetTop).toBe 1 * lineHeightInPixels
expect(component.lineNumberNodeForScreenRow(2).offsetTop).toBe 2 * lineHeightInPixels
expect(component.lineNumberNodeForScreenRow(3).offsetTop).toBe 3 * lineHeightInPixels
expect(component.lineNumberNodeForScreenRow(4).offsetTop).toBe 4 * lineHeightInPixels
expect(component.lineNumberNodeForScreenRow(3).offsetTop).toBe 0 * lineHeightInPixels
expect(component.lineNumberNodeForScreenRow(4).offsetTop).toBe 1 * lineHeightInPixels
expect(component.lineNumberNodeForScreenRow(5).offsetTop).toBe 2 * lineHeightInPixels
editor.getBuffer().insert([0, 0], '\n\n')
nextAnimationFrame()
expect(component.lineNumberNodeForScreenRow(0).offsetTop).toBe 0
expect(component.lineNumberNodeForScreenRow(0).offsetTop).toBe 0 * lineHeightInPixels
expect(component.lineNumberNodeForScreenRow(1).offsetTop).toBe 1 * lineHeightInPixels
expect(component.lineNumberNodeForScreenRow(2).offsetTop).toBe 2 * lineHeightInPixels
expect(component.lineNumberNodeForScreenRow(3).offsetTop).toBe 3 * lineHeightInPixels
expect(component.lineNumberNodeForScreenRow(4).offsetTop).toBe 4 * lineHeightInPixels
expect(component.lineNumberNodeForScreenRow(5).offsetTop).toBe 5 * lineHeightInPixels
expect(component.lineNumberNodeForScreenRow(6).offsetTop).toBe 6 * lineHeightInPixels
expect(component.lineNumberNodeForScreenRow(3).offsetTop).toBe 0 * lineHeightInPixels
expect(component.lineNumberNodeForScreenRow(4).offsetTop).toBe 1 * lineHeightInPixels
expect(component.lineNumberNodeForScreenRow(5).offsetTop).toBe 2 * lineHeightInPixels
expect(component.lineNumberNodeForScreenRow(6).offsetTop).toBe 0 * lineHeightInPixels
expect(component.lineNumberNodeForScreenRow(7).offsetTop).toBe 1 * lineHeightInPixels
expect(component.lineNumberNodeForScreenRow(8).offsetTop).toBe 2 * lineHeightInPixels
it "renders • characters for soft-wrapped lines", ->
editor.setSoftWrapped(true)
@@ -592,13 +634,16 @@ describe "TextEditorComponent", ->
component.measureDimensions()
nextAnimationFrame()
expect(componentNode.querySelectorAll('.line-number').length).toBe 6 + 1 # 1 dummy line
expect(componentNode.querySelectorAll('.line-number').length).toBe 9 + 1 # 3 line-numbers tiles + 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"
expect(component.lineNumberNodeForScreenRow(3).textContent).toBe "#{nbsp}"
expect(component.lineNumberNodeForScreenRow(4).textContent).toBe "#{nbsp}3"
expect(component.lineNumberNodeForScreenRow(5).textContent).toBe "#{nbsp}"
expect(component.lineNumberNodeForScreenRow(6).textContent).toBe "#{nbsp}4"
expect(component.lineNumberNodeForScreenRow(7).textContent).toBe "#{nbsp}"
expect(component.lineNumberNodeForScreenRow(8).textContent).toBe "#{nbsp}"
it "pads line numbers to be right-justified based on the maximum number of line number digits", ->
editor.getBuffer().setText([1..10].join('\n'))
@@ -959,7 +1004,7 @@ describe "TextEditorComponent", ->
it "renders 2 regions for 2-line selections", ->
editor.setSelectedScreenRange([[1, 6], [2, 10]])
nextAnimationFrame()
tileNode = componentNode.querySelectorAll(".tile")[0]
tileNode = componentNode.querySelector(".lines").querySelectorAll(".tile")[0]
regions = tileNode.querySelectorAll('.selection .region')
expect(regions.length).toBe 2
@@ -980,7 +1025,7 @@ describe "TextEditorComponent", ->
nextAnimationFrame()
# Tile 0
tileNode = componentNode.querySelectorAll(".tile")[0]
tileNode = componentNode.querySelector(".lines").querySelectorAll(".tile")[0]
regions = tileNode.querySelectorAll('.selection .region')
expect(regions.length).toBe(3)
@@ -1003,7 +1048,7 @@ describe "TextEditorComponent", ->
expect(region3Rect.right).toBe tileNode.getBoundingClientRect().right
# Tile 3
tileNode = componentNode.querySelectorAll(".tile")[1]
tileNode = componentNode.querySelector(".lines").querySelectorAll(".tile")[1]
regions = tileNode.querySelectorAll('.selection .region')
expect(regions.length).toBe(3)
@@ -2015,7 +2060,7 @@ describe "TextEditorComponent", ->
component.measureDimensions()
nextAnimationFrame()
tilesNodes = componentNode.querySelectorAll(".tile")
tilesNodes = componentNode.querySelector(".lines").querySelectorAll(".tile")
top = 0
for tileNode in tilesNodes

View File

@@ -7,8 +7,7 @@ LineNumberGutterComponent = require './line-number-gutter-component'
module.exports =
class GutterContainerComponent
constructor: ({@onLineNumberGutterMouseDown, @editor}) ->
constructor: ({@onLineNumberGutterMouseDown, @editor, @presenter}) ->
# An array of objects of the form: {name: {String}, component: {Object}}
@gutterComponents = []
@gutterComponentsByGutterName = {}
@@ -35,7 +34,7 @@ class GutterContainerComponent
gutterComponent = @gutterComponentsByGutterName[gutter.name]
if not gutterComponent
if gutter.name is 'line-number'
gutterComponent = new LineNumberGutterComponent({onMouseDown: @onLineNumberGutterMouseDown, @editor, gutter})
gutterComponent = new LineNumberGutterComponent({onMouseDown: @onLineNumberGutterMouseDown, @presenter, @editor, gutter})
@lineNumberGutterComponent = gutterComponent
else
gutterComponent = new CustomGutterComponent({gutter})

View File

@@ -9,7 +9,7 @@ module.exports =
class LineNumberGutterComponent extends TiledComponent
dummyLineNumberNode: null
constructor: ({@onMouseDown, @editor, @gutter}) ->
constructor: ({@onMouseDown, @editor, @presenter, @gutter}) ->
@lineNumberNodesById = {}
@visible = true
@@ -74,10 +74,9 @@ class LineNumberGutterComponent extends TiledComponent
@dummyLineNumberNode.innerHTML = DummyLineNumberComponent.buildLineNumberInnerHTML(0, false)
lineNumberNodeForScreenRow: (screenRow) ->
for id, lineNumberState of @oldState.lineNumbers
if lineNumberState.screenRow is screenRow
return @lineNumberNodesById[id]
null
tile = @presenter.tileForRow(screenRow)
@componentsByTileId[tile]?.lineNumberNodeForScreenRow(screenRow)
onMouseDown: (event) =>
{target} = event

View File

@@ -30,12 +30,16 @@ class LineNumbersTileComponent
@domNode.style.display = @newTileState.display
@oldTileState.display = @newTileState.display
if @newState.backgroundColor isnt @oldState.backgroundColor
@domNode.style.backgroundColor = @newState.backgroundColor
@oldState.backgroundColor = @newState.backgroundColor
if @newTileState.height isnt @oldTileState.height
@domNode.style.height = @newTileState.height + 'px'
@oldTileState.height = @newTileState.height
if @newTileState.top isnt @oldTileState.top
@domNode.style['-webkit-transform'] = "translate3d(#{@newTileState.left}px, #{@newTileState.top}px, 0px)"
@domNode.style['-webkit-transform'] = "translate3d(0, #{@newTileState.top}px, 0px)"
@oldTileState.top = @newTileState.top
@oldTileState.left = @newTileState.left
@@ -127,3 +131,9 @@ class LineNumbersTileComponent
className += " " + decorationClasses.join(' ') if decorationClasses?
className += " foldable" if foldable and not softWrapped
className
lineNumberNodeForScreenRow: (screenRow) ->
for id, lineNumberState of @oldTileState.lineNumbers
if lineNumberState.screenRow is screenRow
return @lineNumberNodesById[id]
null

View File

@@ -165,7 +165,7 @@ class TextEditorComponent
@overlayManager?.measureOverlays()
mountGutterContainerComponent: ->
@gutterContainerComponent = new GutterContainerComponent({@editor, @onLineNumberGutterMouseDown})
@gutterContainerComponent = new GutterContainerComponent({@editor, @onLineNumberGutterMouseDown, @presenter})
@domNode.insertBefore(@gutterContainerComponent.getDomNode(), @domNode.firstChild)
becameVisible: ->