       expect(gutterNode.offsetWidth).toBe initialGutterWidth
 
     fdescribe "when decorations are used", ->
+      {lineHasClass, gutter} = {}
+      beforeEach ->
+        gutter = component.refs.gutter
+        lineHasClass = (screenRow, klass) ->
+          component.lineNumberNodeForScreenRow(screenRow).classList.contains(klass)
+
       it "renders the gutter-class decorations", ->
         node.style.height = 4.5 * lineHeightInPixels + 'px'
         component.measureScrollView()

        verticalScrollbarNode.scrollTop = 2.5 * lineHeightInPixels
        verticalScrollbarNode.dispatchEvent(new UIEvent('scroll'))

        expect(component.lineNumberNodeForScreenRow(9).classList.contains('fancy-class')).toBeTruthy()
        expect(component.lineNumberNodeForScreenRow(9).classList.contains('nope-class')).toBeFalsy()

      it "handles updates to gutter-class decorations", ->
        gutter = component.refs.gutter

        editor.addDecorationForBufferRow(2, {type: 'gutter-class', class: 'fancy-class'})
        editor.addDecorationForBufferRow(2, {type: 'someother-type', class: 'nope-class'})

        advanceClock(gutter.decorationRenderDelay)

        expect(component.lineNumberNodeForScreenRow(2).classList.contains('fancy-class')).toBeTruthy()
        expect(component.lineNumberNodeForScreenRow(2).classList.contains('nope-class')).toBeFalsy()

        editor.removeDecorationForBufferRow(2, {type: 'gutter-class', class: 'fancy-class'})
        editor.removeDecorationForBufferRow(2, {type: 'someother-type', class: 'nope-class'})

        advanceClock(gutter.decorationRenderDelay)

        expect(component.lineNumberNodeForScreenRow(2).classList.contains('fancy-class')).toBeFalsy()
        expect(component.lineNumberNodeForScreenRow(2).classList.contains('nope-class')).toBeFalsy()

      it "handles softWrap decorations", ->
        gutter = component.refs.gutter
        editor.addDecorationForBufferRow(1, {type: 'gutter-class', class: 'no-wrap'})
        editor.addDecorationForBufferRow(1, {type: 'gutter-class', class: 'wrap-me', softWrap: true})


        node.style.width = 30 * charWidth + 'px'
        component.measureScrollView()

        expect(lineHasClass(2, 'no-wrap')).toBeTruthy()
        expect(lineHasClass(2, 'wrap-me')).toBeTruthy()
        expect(lineHasClass(3, 'no-wrap')).toBeFalsy()
        expect(lineHasClass(3, 'wrap-me')).toBeTruthy()

        # should remove the wrapped decorations
        editor.removeDecorationForBufferRow(1, {type: 'gutter-class', class: 'no-wrap'})
        editor.removeDecorationForBufferRow(1, {type: 'gutter-class', class: 'wrap-me'})
        advanceClock(gutter.decorationRenderDelay)

        expect(lineHasClass(2, 'no-wrap')).toBeFalsy()
        expect(lineHasClass(2, 'wrap-me')).toBeFalsy()
        expect(lineHasClass(3, 'no-wrap')).toBeFalsy()
        expect(lineHasClass(3, 'wrap-me')).toBeFalsy()

        # should add them back when the nodes are not recreated
        editor.addDecorationForBufferRow(1, {type: 'gutter-class', class: 'no-wrap'})
        editor.addDecorationForBufferRow(1, {type: 'gutter-class', class: 'wrap-me', softWrap: true})
        advanceClock(gutter.decorationRenderDelay)

        expect(lineHasClass(2, 'no-wrap')).toBeTruthy()
        expect(lineHasClass(2, 'wrap-me')).toBeTruthy()
        expect(lineHasClass(3, 'no-wrap')).toBeFalsy()
        expect(lineHasClass(3, 'wrap-me')).toBeTruthy()

      describe "when markers are used", ->
        {marker, decoration} = {}
        beforeEach ->
          marker = editor.displayBuffer.markBufferRange([[2, 13], [3, 15]], class: 'my-marker', invalidate: 'inside')
          decoration = {type: 'gutter-class', class: 'someclass'}
          editor.addDecorationForMarker(marker, decoration)
          advanceClock(gutter.decorationRenderDelay)

        it "tracks the marker's movements", ->
          expect(lineHasClass(1, 'someclass')).toBeFalsy()
          expect(lineHasClass(2, 'someclass')).toBeTruthy()
          expect(lineHasClass(3, 'someclass')).toBeTruthy()
          expect(lineHasClass(4, 'someclass')).toBeFalsy()

          editor.getBuffer().insert([0, 0], '\n')
          advanceClock(gutter.decorationRenderDelay)

          expect(lineHasClass(2, 'someclass')).toBeFalsy()
          expect(lineHasClass(3, 'someclass')).toBeTruthy()
          expect(lineHasClass(4, 'someclass')).toBeTruthy()
          expect(lineHasClass(5, 'someclass')).toBeFalsy()

          editor.getBuffer().deleteRows(0, 1)
          advanceClock(gutter.decorationRenderDelay)

          expect(lineHasClass(0, 'someclass')).toBeFalsy()
          expect(lineHasClass(1, 'someclass')).toBeTruthy()
          expect(lineHasClass(2, 'someclass')).toBeTruthy()
          expect(lineHasClass(3, 'someclass')).toBeFalsy()

        it "removes the classes when marker is invalidated", ->
          t = editor.getBuffer().getText()
          # invalidate this thing
          editor.getBuffer().insert([3, 2], 'n')
          advanceClock(gutter.decorationRenderDelay)

          expect(marker.isValid()).toBeFalsy()
          expect(lineHasClass(1, 'someclass')).toBeFalsy()
          expect(lineHasClass(2, 'someclass')).toBeFalsy()
          expect(lineHasClass(3, 'someclass')).toBeFalsy()
          expect(lineHasClass(4, 'someclass')).toBeFalsy()

          # Back to valid
          editor.getBuffer().undo()
          advanceClock(gutter.decorationRenderDelay)

          expect(marker.isValid()).toBeTruthy()
          expect(lineHasClass(1, 'someclass')).toBeFalsy()
          expect(lineHasClass(2, 'someclass')).toBeTruthy()
          expect(lineHasClass(3, 'someclass')).toBeTruthy()
          expect(lineHasClass(4, 'someclass')).toBeFalsy()

        it "removes the classes and unsubscribes from the marker when decoration is removed", ->
          editor.removeDecorationForMarker(marker, decoration)
          advanceClock(gutter.decorationRenderDelay)

          expect(lineHasClass(1, 'someclass')).toBeFalsy()
          expect(lineHasClass(2, 'someclass')).toBeFalsy()
          expect(lineHasClass(3, 'someclass')).toBeFalsy()
          expect(lineHasClass(4, 'someclass')).toBeFalsy()

          editor.getBuffer().insert([0, 0], '\n')
          advanceClock(gutter.decorationRenderDelay)
          expect(lineHasClass(2, 'someclass')).toBeFalsy()
          expect(lineHasClass(3, 'someclass')).toBeFalsy()

        it "removes the decoration when the marker is destroyed", ->
          marker.destroy()
          advanceClock(gutter.decorationRenderDelay)

          expect(lineHasClass(1, 'someclass')).toBeFalsy()
          expect(lineHasClass(2, 'someclass')).toBeFalsy()
          expect(lineHasClass(3, 'someclass')).toBeFalsy()
          expect(lineHasClass(4, 'someclass')).toBeFalsy()

  describe "cursor rendering", ->
    it "renders the currently visible cursors, translated relative to the scroll position", ->
