           runSetImmediateCallbacks()
           expect(lineNumberHasClass(1, 'folded')).toBe false
 
-    describe "when gutter decorations are attached to markers", ->
-      {marker, decoration} = {}
-      beforeEach ->
-        marker = editor.displayBuffer.markBufferRange([[2, 13], [3, 15]], invalidate: 'inside')
-        decoration = {type: 'gutter', class: 'someclass'}
-        editor.addDecorationForMarker(marker, decoration)
-        runSetImmediateCallbacks()
-
-      it "does not render off-screen lines with line number classes until they are with in the rendered row range", ->
-        node.style.height = 4.5 * lineHeightInPixels + 'px'
-        component.measureScrollView()
-        runSetImmediateCallbacks()
-        expect(component.lineNumberNodeForScreenRow(9)).not.toBeDefined()
-
-        marker = editor.displayBuffer.markBufferRange([[9, 0], [9, 0]], invalidate: 'inside')
-        editor.addDecorationForMarker(marker, type: 'gutter', class: 'fancy-class')
-        editor.addDecorationForMarker(marker, type: 'someother-type', class: 'nope-class')
-
-        verticalScrollbarNode.scrollTop = 2.5 * lineHeightInPixels
-        verticalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
-        runSetImmediateCallbacks()
-
-        expect(lineNumberHasClass(9, 'fancy-class')).toBe true
-        expect(lineNumberHasClass(9, 'nope-class')).toBe false
-
-      it "renders classes on correct screen lines when the user folds a block of code", ->
-        marker = editor.displayBuffer.markBufferRange([[9, 0], [9, 0]], invalidate: 'inside')
-        editor.addDecorationForMarker(marker, decoration)
-        runSetImmediateCallbacks()
-        expect(lineNumberForBufferRowHasClass(9, 'someclass')).toBe true
-
-        editor.foldBufferRow(5)
-        runSetImmediateCallbacks() # TODO: Removing this runSetImmediateCallbacks causes the spec to fail because of flaws in decoration updating
-        editor.removeDecorationForMarker(marker, decoration)
-        runSetImmediateCallbacks()
-        expect(lineNumberForBufferRowHasClass(9, 'someclass')).toBe false
-
-      it "only renders 'onlyHead' decorations on lines containing the marker's head", ->
-        editor.addDecorationForMarker(marker, type: 'gutter', class: 'only-head', onlyHead: true)
-        runSetImmediateCallbacks()
-        expect(lineNumberHasClass(1, 'only-head')).toBe false
-        expect(lineNumberHasClass(2, 'only-head')).toBe false
-        expect(lineNumberHasClass(3, 'only-head')).toBe true
-        expect(lineNumberHasClass(4, 'only-head')).toBe false
-
-      it "only renders 'onlyEmpty' decorations on lines for which the marker is empty", ->
-        editor.addDecorationForMarker(marker, type: 'gutter', class: 'only-empty', onlyEmpty: true)
-        runSetImmediateCallbacks()
-        expect(lineNumberHasClass(2, 'only-empty')).toBe false
-        expect(lineNumberHasClass(3, 'only-empty')).toBe false
-
-        marker.clearTail()
-        runSetImmediateCallbacks()
-        expect(lineNumberHasClass(2, 'only-empty')).toBe false
-        expect(lineNumberHasClass(3, 'only-empty')).toBe true
-
-      it "only renders 'onlyNonEmpty' decorations on lines for which the marker is non-empty", ->
-        editor.addDecorationForMarker(marker, type: 'gutter', class: 'only-non-empty', onlyNonEmpty: true)
-        runSetImmediateCallbacks()
-        expect(lineNumberHasClass(2, 'only-non-empty')).toBe true
-        expect(lineNumberHasClass(3, 'only-non-empty')).toBe true
-
-        marker.clearTail()
-        runSetImmediateCallbacks()
-        expect(lineNumberHasClass(2, 'only-non-empty')).toBe false
-        expect(lineNumberHasClass(3, 'only-non-empty')).toBe false
-
-      it "updates line number classes when the marker moves", ->
-        expect(lineNumberHasClass(1, 'someclass')).toBe false
-        expect(lineNumberHasClass(2, 'someclass')).toBe true
-        expect(lineNumberHasClass(3, 'someclass')).toBe true
-        expect(lineNumberHasClass(4, 'someclass')).toBe false
-
-        editor.getBuffer().insert([0, 0], '\n')
-        runSetImmediateCallbacks()
-        expect(lineNumberHasClass(2, 'someclass')).toBe false
-        expect(lineNumberHasClass(3, 'someclass')).toBe true
-        expect(lineNumberHasClass(4, 'someclass')).toBe true
-        expect(lineNumberHasClass(5, 'someclass')).toBe false
-
-        editor.getBuffer().deleteRows(0, 1)
-        runSetImmediateCallbacks()
-        expect(lineNumberHasClass(0, 'someclass')).toBe false
-        expect(lineNumberHasClass(1, 'someclass')).toBe true
-        expect(lineNumberHasClass(2, 'someclass')).toBe true
-        expect(lineNumberHasClass(3, 'someclass')).toBe false
-
-      it "removes line number classes when a decoration's marker is invalidated", ->
-        editor.getBuffer().insert([3, 2], 'n')
-        runSetImmediateCallbacks()
-        expect(marker.isValid()).toBe false
-        expect(lineNumberHasClass(1, 'someclass')).toBe false
-        expect(lineNumberHasClass(2, 'someclass')).toBe false
-        expect(lineNumberHasClass(3, 'someclass')).toBe false
-        expect(lineNumberHasClass(4, 'someclass')).toBe false
-
-        editor.getBuffer().undo()
-        runSetImmediateCallbacks()
-        expect(marker.isValid()).toBe true
-        expect(lineNumberHasClass(1, 'someclass')).toBe false
-        expect(lineNumberHasClass(2, 'someclass')).toBe true
-        expect(lineNumberHasClass(3, 'someclass')).toBe true
-        expect(lineNumberHasClass(4, 'someclass')).toBe false
-
-      it "removes the classes and unsubscribes from the marker when decoration is removed", ->
-        editor.removeDecorationForMarker(marker, decoration)
-        runSetImmediateCallbacks()
-        expect(lineNumberHasClass(1, 'someclass')).toBe false
-        expect(lineNumberHasClass(2, 'someclass')).toBe false
-        expect(lineNumberHasClass(3, 'someclass')).toBe false
-        expect(lineNumberHasClass(4, 'someclass')).toBe false
-
-        editor.getBuffer().insert([0, 0], '\n')
-        runSetImmediateCallbacks()
-        expect(lineNumberHasClass(2, 'someclass')).toBe false
-        expect(lineNumberHasClass(3, 'someclass')).toBe false
-
-      it "removes the line number classes when the decoration's marker is destroyed", ->
-        marker.destroy()
-        runSetImmediateCallbacks()
-        expect(lineNumberHasClass(1, 'someclass')).toBe false
-        expect(lineNumberHasClass(2, 'someclass')).toBe false
-        expect(lineNumberHasClass(3, 'someclass')).toBe false
-        expect(lineNumberHasClass(4, 'someclass')).toBe false
-
-      describe "when soft wrapping is enabled", ->
-        beforeEach ->
-          editor.setText "a line that wraps, ok"
-          editor.setSoftWrap(true)
-          node.style.width = 16 * charWidth + 'px'
-          component.measureScrollView()
-          runSetImmediateCallbacks()
-
-        it "applies decoration only to the first row when marker range does not wrap", ->
-          marker = editor.displayBuffer.markBufferRange([[0, 0], [0, 0]])
-          editor.addDecorationForMarker(marker, type: 'gutter', class: 'someclass')
-          runSetImmediateCallbacks()
-          expect(lineNumberHasClass(0, 'someclass')).toBe true
-          expect(lineNumberHasClass(1, 'someclass')).toBe false
-
-        it "applies decoration to both rows when marker wraps", ->
-          marker = editor.displayBuffer.markBufferRange([[0, 0], [0, Infinity]])
-          editor.addDecorationForMarker(marker, type: 'gutter', class: 'someclass')
-          runSetImmediateCallbacks()
-          expect(lineNumberHasClass(0, 'someclass')).toBe true
-          expect(lineNumberHasClass(1, 'someclass')).toBe true
-
   describe "cursor rendering", ->
     it "renders the currently visible cursors, translated relative to the scroll position", ->
       cursor1 = editor.getCursor()

    clientY = gutterClientRect.top + positionOffset.top - editor.getScrollTop()
    {clientX, clientY}

  lineNumberHasClass = (screenRow, klass) ->
    component.lineNumberNodeForScreenRow(screenRow).classList.contains(klass)


      selectionNode = node.querySelector('.region')
      expect(selectionNode.offsetTop).toBe editor.getLineHeightInPixels()
      expect(selectionNode.offsetLeft).toBe editor.pixelPositionForScreenPosition([1, 6]).left

  describe "line decoration rendering", ->
    [marker, decoration] = []

    beforeEach ->
      marker = editor.displayBuffer.markBufferRange([[2, 13], [3, 15]], invalidate: 'inside')
      decoration = {type: ['gutter', 'line'], class: 'a'}
      editor.addDecorationForMarker(marker, decoration)
      runSetImmediateCallbacks()

    it "applies line decoration classes to lines and line numbers", ->
      expect(lineAndLineNumberHaveClass(2, 'a')).toBe true
      expect(lineAndLineNumberHaveClass(3, 'a')).toBe true

      # Shrink editor vertically
      node.style.height = 4.5 * lineHeightInPixels + 'px'
      component.measureScrollView()
      runSetImmediateCallbacks()

      # Add decorations that are out of range
      marker2 = editor.displayBuffer.markBufferRange([[9, 0], [9, 0]])
      editor.addDecorationForMarker(marker2, type: ['gutter', 'line'], class: 'b')

      # Scroll decorations into view
      verticalScrollbarNode.scrollTop = 2.5 * lineHeightInPixels
      verticalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
      runSetImmediateCallbacks()
      expect(lineAndLineNumberHaveClass(9, 'b')).toBe true

      # Fold a line to move the decorations
      editor.foldBufferRow(5)
      runSetImmediateCallbacks()
      expect(lineAndLineNumberHaveClass(9, 'b')).toBe false
      expect(lineAndLineNumberHaveClass(6, 'b')).toBe true

    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")
      editor.setSoftWrap(true)
      node.style.width = 16 * charWidth + 'px'
      component.measureScrollView()
      runSetImmediateCallbacks()

      marker.destroy()
      marker = editor.markBufferRange([[0, 0], [0, 2]])
      editor.addDecorationForMarker(marker, type: ['gutter', 'line'], class: 'b')
      runSetImmediateCallbacks()
      expect(lineNumberHasClass(0, 'b')).toBe true
      expect(lineNumberHasClass(1, 'b')).toBe false

      marker.setBufferRange([[0, 0], [0, Infinity]])
      runSetImmediateCallbacks()
      expect(lineNumberHasClass(0, 'b')).toBe true
      expect(lineNumberHasClass(1, 'b')).toBe true

    it "updates decorations when markers move", ->
      expect(lineAndLineNumberHaveClass(1, 'a')).toBe false
      expect(lineAndLineNumberHaveClass(2, 'a')).toBe true
      expect(lineAndLineNumberHaveClass(3, 'a')).toBe true
      expect(lineAndLineNumberHaveClass(4, 'a')).toBe false

      editor.getBuffer().insert([0, 0], '\n')
      runSetImmediateCallbacks()
      expect(lineAndLineNumberHaveClass(2, 'a')).toBe false
      expect(lineAndLineNumberHaveClass(3, 'a')).toBe true
      expect(lineAndLineNumberHaveClass(4, 'a')).toBe true
      expect(lineAndLineNumberHaveClass(5, 'a')).toBe false

      marker.setBufferRange([[4, 4], [6, 4]])
      runSetImmediateCallbacks()
      expect(lineAndLineNumberHaveClass(2, 'a')).toBe false
      expect(lineAndLineNumberHaveClass(3, 'a')).toBe false
      expect(lineAndLineNumberHaveClass(4, 'a')).toBe true
      expect(lineAndLineNumberHaveClass(5, 'a')).toBe true
      expect(lineAndLineNumberHaveClass(6, 'a')).toBe true
      expect(lineAndLineNumberHaveClass(7, 'a')).toBe false

    it "remove decoration classes and unsubscribes from markers decorations are removed", ->
      expect(marker.getSubscriptionCount('changed'))
      editor.removeDecorationForMarker(marker, decoration)
      runSetImmediateCallbacks()
      expect(lineNumberHasClass(1, 'a')).toBe false
      expect(lineNumberHasClass(2, 'a')).toBe false
      expect(lineNumberHasClass(3, 'a')).toBe false
      expect(lineNumberHasClass(4, 'a')).toBe false
      expect(marker.getSubscriptionCount('changed')).toBe 0

    it "removes decorations when their marker is invalidated", ->
      editor.getBuffer().insert([3, 2], 'n')
      runSetImmediateCallbacks()
      expect(marker.isValid()).toBe false
      expect(lineAndLineNumberHaveClass(1, 'a')).toBe false
      expect(lineAndLineNumberHaveClass(2, 'a')).toBe false
      expect(lineAndLineNumberHaveClass(3, 'a')).toBe false
      expect(lineAndLineNumberHaveClass(4, 'a')).toBe false

      editor.undo()
      runSetImmediateCallbacks()
      expect(marker.isValid()).toBe true
      expect(lineAndLineNumberHaveClass(1, 'a')).toBe false
      expect(lineAndLineNumberHaveClass(2, 'a')).toBe true
      expect(lineAndLineNumberHaveClass(3, 'a')).toBe true
      expect(lineAndLineNumberHaveClass(4, 'a')).toBe false

    it "removes decorations when their marker is destroyed", ->
      marker.destroy()
      runSetImmediateCallbacks()
      expect(lineNumberHasClass(1, 'a')).toBe false
      expect(lineNumberHasClass(2, 'a')).toBe false
      expect(lineNumberHasClass(3, 'a')).toBe false
      expect(lineNumberHasClass(4, 'a')).toBe false

    describe "when the decoration's 'onlyHead' property is true", ->
      it "only applies the decoration's class to lines containing the marker's head", ->
        editor.addDecorationForMarker(marker, type: ['gutter', 'line'], class: 'only-head', onlyHead: true)
        runSetImmediateCallbacks()
        expect(lineAndLineNumberHaveClass(1, 'only-head')).toBe false
        expect(lineAndLineNumberHaveClass(2, 'only-head')).toBe false
        expect(lineAndLineNumberHaveClass(3, 'only-head')).toBe true
        expect(lineAndLineNumberHaveClass(4, 'only-head')).toBe false

    describe "when the decoration's 'onlyEmpty' property is true", ->
      it "only applies the decoration when its marker is empty", ->
        editor.addDecorationForMarker(marker, type: ['gutter', 'line'], class: 'only-empty', onlyEmpty: true)
        runSetImmediateCallbacks()
        expect(lineAndLineNumberHaveClass(2, 'only-empty')).toBe false
        expect(lineAndLineNumberHaveClass(3, 'only-empty')).toBe false

        marker.clearTail()
        runSetImmediateCallbacks()
        expect(lineAndLineNumberHaveClass(2, 'only-empty')).toBe false
        expect(lineAndLineNumberHaveClass(3, 'only-empty')).toBe true

    describe "when the decoration's 'onlyNonEmpty' property is true", ->
      it "only applies the decoration when its marker is non-empty", ->
        editor.addDecorationForMarker(marker, type: ['gutter', 'line'], class: 'only-non-empty', onlyNonEmpty: true)
        runSetImmediateCallbacks()
        expect(lineAndLineNumberHaveClass(2, 'only-non-empty')).toBe true
        expect(lineAndLineNumberHaveClass(3, 'only-non-empty')).toBe true

        marker.clearTail()
        runSetImmediateCallbacks()
        expect(lineAndLineNumberHaveClass(2, 'only-non-empty')).toBe false
        expect(lineAndLineNumberHaveClass(3, 'only-non-empty')).toBe false

  describe "highlight decoration rendering", ->
    [marker, decoration, scrollViewClientLeft] = []
