     clientY = gutterClientRect.top + positionOffset.top - editor.getScrollTop()
     {clientX, clientY}
 
+  lineAndLineNumberHaveClass = (screenRow, klass) ->
+    lineHasClass(screenRow, klass) and lineNumberHasClass(screenRow, klass)
+
   lineNumberHasClass = (screenRow, klass) ->
     component.lineNumberNodeForScreenRow(screenRow).classList.contains(klass)
 

          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()

        runSetImmediateCallbacks()
        foldedLineNode = component.lineNodeForScreenRow(4)
        expect(foldedLineNode.querySelector('.fold-marker')).toBeFalsy()

  describe "gutter rendering", ->
    [gutter] = []
