Merge branch 'master' into dh-async-repo

This commit is contained in:
joshaber
2015-11-17 11:39:22 -08:00
36 changed files with 609 additions and 176 deletions

View File

@@ -20,10 +20,45 @@ describe "CommandInstaller on #darwin", ->
spyOn(CommandInstaller::, 'getResourcesDirectory').andReturn(resourcesPath)
spyOn(CommandInstaller::, 'getInstallDirectory').andReturn(installationPath)
it "shows an error dialog when installing commands interactively fails", ->
appDelegate = jasmine.createSpyObj("appDelegate", ["confirm"])
installer = new CommandInstaller("2.0.2", appDelegate)
spyOn(installer, "installAtomCommand").andCallFake (__, callback) -> callback(new Error("an error"))
installer.installShellCommandsInteractively()
expect(appDelegate.confirm).toHaveBeenCalledWith({
message: "Failed to install shell commands"
detailedMessage: "an error"
})
appDelegate.confirm.reset()
installer.installAtomCommand.andCallFake (__, callback) -> callback()
spyOn(installer, "installApmCommand").andCallFake (__, callback) -> callback(new Error("another error"))
installer.installShellCommandsInteractively()
expect(appDelegate.confirm).toHaveBeenCalledWith({
message: "Failed to install shell commands"
detailedMessage: "another error"
})
it "shows a success dialog when installing commands interactively succeeds", ->
appDelegate = jasmine.createSpyObj("appDelegate", ["confirm"])
installer = new CommandInstaller("2.0.2", appDelegate)
spyOn(installer, "installAtomCommand").andCallFake (__, callback) -> callback()
spyOn(installer, "installApmCommand").andCallFake (__, callback) -> callback()
installer.installShellCommandsInteractively()
expect(appDelegate.confirm).toHaveBeenCalledWith({
message: "Commands installed."
detailedMessage: "The shell commands `atom` and `apm` are installed."
})
describe "when using a stable version of atom", ->
beforeEach ->
confirm = ->
installer = new CommandInstaller("2.0.2", confirm)
installer = new CommandInstaller("2.0.2")
it "symlinks the atom command as 'atom'", ->
installedAtomPath = path.join(installationPath, 'atom')

View File

@@ -589,6 +589,59 @@ describe "Config", ->
atom.config.transact ->
expect(changeSpy).not.toHaveBeenCalled()
describe ".transactAsync(callback)", ->
changeSpy = null
beforeEach ->
changeSpy = jasmine.createSpy('onDidChange callback')
atom.config.onDidChange("foo.bar.baz", changeSpy)
it "allows only one change event for the duration of the given promise if it gets resolved", ->
promiseResult = null
transactionPromise = atom.config.transactAsync ->
atom.config.set("foo.bar.baz", 1)
atom.config.set("foo.bar.baz", 2)
atom.config.set("foo.bar.baz", 3)
Promise.resolve("a result")
waitsForPromise -> transactionPromise.then (r) -> promiseResult = r
runs ->
expect(promiseResult).toBe("a result")
expect(changeSpy.callCount).toBe(1)
expect(changeSpy.argsForCall[0][0]).toEqual(newValue: 3, oldValue: undefined)
it "allows only one change event for the duration of the given promise if it gets rejected", ->
promiseError = null
transactionPromise = atom.config.transactAsync ->
atom.config.set("foo.bar.baz", 1)
atom.config.set("foo.bar.baz", 2)
atom.config.set("foo.bar.baz", 3)
Promise.reject("an error")
waitsForPromise -> transactionPromise.catch (e) -> promiseError = e
runs ->
expect(promiseError).toBe("an error")
expect(changeSpy.callCount).toBe(1)
expect(changeSpy.argsForCall[0][0]).toEqual(newValue: 3, oldValue: undefined)
it "allows only one change event even when the given callback throws", ->
error = new Error("Oops!")
promiseError = null
transactionPromise = atom.config.transactAsync ->
atom.config.set("foo.bar.baz", 1)
atom.config.set("foo.bar.baz", 2)
atom.config.set("foo.bar.baz", 3)
throw error
waitsForPromise -> transactionPromise.catch (e) -> promiseError = e
runs ->
expect(promiseError).toBe(error)
expect(changeSpy.callCount).toBe(1)
expect(changeSpy.argsForCall[0][0]).toEqual(newValue: 3, oldValue: undefined)
describe ".getSources()", ->
it "returns an array of all of the config's source names", ->
expect(atom.config.getSources()).toEqual([])

View File

@@ -142,9 +142,13 @@ describe "the `grammars` global", ->
expect(atom.grammars.selectGrammar('Rakefile', '').scopeName).toBe 'source.coffee'
expect(atom.grammars.selectGrammar('Cakefile', '').scopeName).toBe 'source.ruby'
it "favors grammars with matching first-line-regexps even if custom file types match the file", ->
it "favors user-defined file types over grammars with matching first-line-regexps", ->
atom.config.set('core.customFileTypes', 'source.ruby': ['bootstrap'])
expect(atom.grammars.selectGrammar('bootstrap', '#!/usr/bin/env node').scopeName).toBe 'source.js'
expect(atom.grammars.selectGrammar('bootstrap', '#!/usr/bin/env node').scopeName).toBe 'source.ruby'
describe "when there is a grammar with a first line pattern, the file type of the file is known, but from a different grammar", ->
it "favors file type over the matching pattern", ->
expect(atom.grammars.selectGrammar('foo.rb', '#!/usr/bin/env node').scopeName).toBe 'source.ruby'
describe ".removeGrammar(grammar)", ->
it "removes the grammar, so it won't be returned by selectGrammar", ->

View File

@@ -4,7 +4,7 @@
return unless process.env.ATOM_INTEGRATION_TESTS_ENABLED
# Integration tests require a fast machine and, for now, we cannot afford to
# run them on Travis.
return if process.env.TRAVIS
return if process.env.CI
fs = require "fs-plus"
path = require "path"

View File

@@ -284,6 +284,7 @@ describe "PackageManager", ->
expect(Package.prototype.requireMainModule.callCount).toBe 0
atom.packages.triggerActivationHook('language-fictitious:grammar-used')
atom.packages.triggerDeferredActivationHooks()
waitsForPromise ->
promise
@@ -433,6 +434,13 @@ describe "PackageManager", ->
runs ->
expect(atom.keymaps.findKeyBindings(keystrokes: 'ctrl-z', target: element1)).toHaveLength 0
describe "when setting core.packagesWithKeymapsDisabled", ->
it "ignores package names in the array that aren't loaded", ->
atom.packages.observePackagesWithKeymapsDisabled()
expect(-> atom.config.set("core.packagesWithKeymapsDisabled", ["package-does-not-exist"])).not.toThrow()
expect(-> atom.config.set("core.packagesWithKeymapsDisabled", [])).not.toThrow()
describe "when the package's keymaps are disabled and re-enabled after it is activated", ->
it "removes and re-adds the keymaps", ->
element1 = createTestElement('test-1')

View File

@@ -168,6 +168,15 @@ describe "Pane", ->
pane.activateNextItem()
expect(pane.getActiveItem()).toBe item1
describe "::activateLastItem()", ->
it "sets the active item to the last item", ->
pane = new Pane(paneParams(items: [new Item("A"), new Item("B"), new Item("C")]))
[item1, item2, item3] = pane.getItems()
expect(pane.getActiveItem()).toBe item1
pane.activateLastItem()
expect(pane.getActiveItem()).toBe item3
describe "::moveItemRight() and ::moveItemLeft()", ->
it "moves the active item to the right and left, without looping around at either end", ->
pane = new Pane(paneParams(items: [new Item("A"), new Item("B"), new Item("C")]))

View File

@@ -25,27 +25,34 @@ describe "TextEditorPresenter", ->
editor.destroy()
buffer.destroy()
buildPresenter = (params={}) ->
buildPresenterWithoutMeasurements = (params={}) ->
_.defaults params,
model: editor
explicitHeight: 130
contentFrameWidth: 500
windowWidth: 500
windowHeight: 130
boundingClientRect: {left: 0, top: 0, width: 500, height: 130}
gutterWidth: 0
lineHeight: 10
baseCharacterWidth: 10
horizontalScrollbarHeight: 10
verticalScrollbarWidth: 10
scrollTop: 0
scrollLeft: 0
config: atom.config
contentFrameWidth: 500
presenter = new TextEditorPresenter(params)
presenter.setLinesYardstick(new FakeLinesYardstick(editor, presenter))
presenter
buildPresenter = (params={}) ->
presenter = buildPresenterWithoutMeasurements(params)
presenter.setScrollTop(params.scrollTop) if params.scrollTop?
presenter.setScrollLeft(params.scrollLeft) if params.scrollLeft?
presenter.setExplicitHeight(params.explicitHeight ? 130)
presenter.setWindowSize(params.windowWidth ? 500, params.windowHeight ? 130)
presenter.setBoundingClientRect(params.boundingClientRect ? {
left: 0
top: 0
width: 500
height: 130
})
presenter.setGutterWidth(params.gutterWidth ? 0)
presenter.setLineHeight(params.lineHeight ? 10)
presenter.setBaseCharacterWidth(params.baseCharacterWidth ? 10)
presenter.setHorizontalScrollbarHeight(params.horizontalScrollbarHeight ? 10)
presenter.setVerticalScrollbarWidth(params.verticalScrollbarWidth ? 10)
presenter
expectValues = (actual, expected) ->
for key, value of expected
expect(actual[key]).toEqual value
@@ -167,16 +174,14 @@ describe "TextEditorPresenter", ->
expect(stateFn(presenter).tiles[12]).toBeDefined()
it "is empty until all of the required measurements are assigned", ->
presenter = buildPresenter(explicitHeight: null, lineHeight: null, scrollTop: null)
presenter = buildPresenterWithoutMeasurements()
expect(stateFn(presenter).tiles).toEqual({})
presenter.setExplicitHeight(25)
expect(stateFn(presenter).tiles).toEqual({})
# Sets scroll row from model's logical position
presenter.setLineHeight(10)
expect(stateFn(presenter).tiles).toEqual({})
presenter.setScrollTop(0)
expect(stateFn(presenter).tiles).not.toEqual({})
it "updates when ::scrollTop changes", ->
@@ -619,6 +624,8 @@ describe "TextEditorPresenter", ->
describe ".scrollingVertically", ->
it "is true for ::stoppedScrollingDelay milliseconds following a changes to ::scrollTop", ->
presenter = buildPresenter(scrollTop: 10, stoppedScrollingDelay: 200, explicitHeight: 100)
expect(presenter.getState().content.scrollingVertically).toBe true
advanceClock(300)
expect(presenter.getState().content.scrollingVertically).toBe false
expectStateUpdate presenter, -> presenter.setScrollTop(0)
expect(presenter.getState().content.scrollingVertically).toBe true
@@ -761,7 +768,8 @@ describe "TextEditorPresenter", ->
expect(presenter.getState().content.scrollTop).toBe(10)
it "corresponds to the passed logical coordinates when building the presenter", ->
presenter = buildPresenter(scrollRow: 4, lineHeight: 10, explicitHeight: 20)
editor.setFirstVisibleScreenRow(4)
presenter = buildPresenter(lineHeight: 10, explicitHeight: 20)
expect(presenter.getState().content.scrollTop).toBe(40)
it "tracks the value of ::scrollTop", ->
@@ -775,11 +783,11 @@ describe "TextEditorPresenter", ->
expectStateUpdate presenter, -> presenter.setScrollTop(50)
presenter.getState() # commits scroll position
expect(editor.getScrollRow()).toBe(5)
expect(editor.getFirstVisibleScreenRow()).toBe 5
expectStateUpdate presenter, -> presenter.setScrollTop(57)
presenter.getState() # commits scroll position
expect(editor.getScrollRow()).toBe(6)
expect(editor.getFirstVisibleScreenRow()).toBe 6
it "reassigns the scrollTop if it exceeds the max possible value after lines are removed", ->
presenter = buildPresenter(scrollTop: 80, lineHeight: 10, explicitHeight: 50, horizontalScrollbarHeight: 0)
@@ -888,7 +896,8 @@ describe "TextEditorPresenter", ->
expect(presenter.getState().content.scrollLeft).toBe(50)
it "corresponds to the passed logical coordinates when building the presenter", ->
presenter = buildPresenter(scrollColumn: 3, lineHeight: 10, baseCharacterWidth: 10, verticalScrollbarWidth: 10, contentFrameWidth: 500)
editor.setFirstVisibleScreenColumn(3)
presenter = buildPresenter(lineHeight: 10, baseCharacterWidth: 10, verticalScrollbarWidth: 10, contentFrameWidth: 500)
expect(presenter.getState().content.scrollLeft).toBe(30)
it "tracks the value of ::scrollLeft", ->
@@ -902,11 +911,11 @@ describe "TextEditorPresenter", ->
expectStateUpdate presenter, -> presenter.setScrollLeft(50)
presenter.getState() # commits scroll position
expect(editor.getScrollColumn()).toBe(5)
expect(editor.getFirstVisibleScreenColumn()).toBe 5
expectStateUpdate presenter, -> presenter.setScrollLeft(57)
presenter.getState() # commits scroll position
expect(editor.getScrollColumn()).toBe(6)
expect(editor.getFirstVisibleScreenColumn()).toBe 6
it "is always rounded to the nearest integer", ->
presenter = buildPresenter(scrollLeft: 10, lineHeight: 10, baseCharacterWidth: 10, verticalScrollbarWidth: 10, contentFrameWidth: 500)
@@ -1006,20 +1015,25 @@ describe "TextEditorPresenter", ->
describe ".backgroundColor", ->
it "is assigned to ::backgroundColor unless the editor is mini", ->
presenter = buildPresenter(backgroundColor: 'rgba(255, 0, 0, 0)')
presenter = buildPresenter()
presenter.setBackgroundColor('rgba(255, 0, 0, 0)')
expect(presenter.getState().content.backgroundColor).toBe 'rgba(255, 0, 0, 0)'
editor.setMini(true)
presenter = buildPresenter(backgroundColor: 'rgba(255, 0, 0, 0)')
presenter = buildPresenter()
presenter.setBackgroundColor('rgba(255, 0, 0, 0)')
expect(presenter.getState().content.backgroundColor).toBeNull()
it "updates when ::backgroundColor changes", ->
presenter = buildPresenter(backgroundColor: 'rgba(255, 0, 0, 0)')
presenter = buildPresenter()
presenter.setBackgroundColor('rgba(255, 0, 0, 0)')
expect(presenter.getState().content.backgroundColor).toBe 'rgba(255, 0, 0, 0)'
expectStateUpdate presenter, -> presenter.setBackgroundColor('rgba(0, 0, 255, 0)')
expect(presenter.getState().content.backgroundColor).toBe 'rgba(0, 0, 255, 0)'
it "updates when ::mini changes", ->
presenter = buildPresenter(backgroundColor: 'rgba(255, 0, 0, 0)')
presenter = buildPresenter()
presenter.setBackgroundColor('rgba(255, 0, 0, 0)')
expect(presenter.getState().content.backgroundColor).toBe 'rgba(255, 0, 0, 0)'
expectStateUpdate presenter, -> editor.setMini(true)
expect(presenter.getState().content.backgroundColor).toBeNull()
@@ -1047,6 +1061,7 @@ describe "TextEditorPresenter", ->
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)
presenter.setExplicitHeight(3)
expect(lineStateForScreenRow(presenter, 2)).toBeUndefined()
@@ -1320,7 +1335,7 @@ describe "TextEditorPresenter", ->
expect(stateForCursor(presenter, 4)).toBeUndefined()
it "is empty until all of the required measurements are assigned", ->
presenter = buildPresenter(explicitHeight: null, lineHeight: null, scrollTop: null, baseCharacterWidth: null, horizontalScrollbarHeight: null)
presenter = buildPresenterWithoutMeasurements()
expect(presenter.getState().content.cursors).toEqual({})
presenter.setExplicitHeight(25)
@@ -1335,6 +1350,15 @@ describe "TextEditorPresenter", ->
presenter.setBaseCharacterWidth(8)
expect(presenter.getState().content.cursors).toEqual({})
presenter.setBoundingClientRect(top: 0, left: 0, width: 500, height: 130)
expect(presenter.getState().content.cursors).toEqual({})
presenter.setWindowSize(500, 130)
expect(presenter.getState().content.cursors).toEqual({})
presenter.setVerticalScrollbarWidth(10)
expect(presenter.getState().content.cursors).toEqual({})
presenter.setHorizontalScrollbarHeight(10)
expect(presenter.getState().content.cursors).not.toEqual({})
@@ -1466,7 +1490,8 @@ describe "TextEditorPresenter", ->
it "alternates between true and false twice per ::cursorBlinkPeriod when the editor is focused", ->
cursorBlinkPeriod = 100
cursorBlinkResumeDelay = 200
presenter = buildPresenter({cursorBlinkPeriod, cursorBlinkResumeDelay, focused: true})
presenter = buildPresenter({cursorBlinkPeriod, cursorBlinkResumeDelay})
presenter.setFocused(true)
expect(presenter.getState().content.cursorsVisible).toBe true
expectStateUpdate presenter, -> advanceClock(cursorBlinkPeriod / 2)
@@ -1493,7 +1518,8 @@ describe "TextEditorPresenter", ->
it "stops alternating for ::cursorBlinkResumeDelay when a cursor moves or a cursor is added", ->
cursorBlinkPeriod = 100
cursorBlinkResumeDelay = 200
presenter = buildPresenter({cursorBlinkPeriod, cursorBlinkResumeDelay, focused: true})
presenter = buildPresenter({cursorBlinkPeriod, cursorBlinkResumeDelay})
presenter.setFocused(true)
expect(presenter.getState().content.cursorsVisible).toBe true
expectStateUpdate presenter, -> advanceClock(cursorBlinkPeriod / 2)
@@ -1643,7 +1669,7 @@ describe "TextEditorPresenter", ->
[[0, 2], [2, 4]],
])
presenter = buildPresenter(explicitHeight: null, lineHeight: null, scrollTop: null, baseCharacterWidth: null, tileSize: 2)
presenter = buildPresenterWithoutMeasurements(tileSize: 2)
for tileId, tileState of presenter.getState().content.tiles
expect(tileState.highlights).toEqual({})
@@ -1970,7 +1996,7 @@ describe "TextEditorPresenter", ->
marker = editor.markBufferRange([[2, 13], [4, 14]], invalidate: 'touch')
decoration = editor.decorateMarker(marker, {type: 'overlay', position: 'tail', item})
presenter = buildPresenter(baseCharacterWidth: null, lineHeight: null, windowWidth: null, windowHeight: null, boundingClientRect: null)
presenter = buildPresenterWithoutMeasurements()
expect(presenter.getState().content.overlays).toEqual({})
presenter.setBaseCharacterWidth(10)
@@ -1982,6 +2008,12 @@ describe "TextEditorPresenter", ->
presenter.setWindowSize(500, 100)
expect(presenter.getState().content.overlays).toEqual({})
presenter.setVerticalScrollbarWidth(10)
expect(presenter.getState().content.overlays).toEqual({})
presenter.setHorizontalScrollbarHeight(10)
expect(presenter.getState().content.overlays).toEqual({})
presenter.setBoundingClientRect({top: 0, left: 0, height: 100, width: 500})
expect(presenter.getState().content.overlays).not.toEqual({})
@@ -2168,7 +2200,8 @@ describe "TextEditorPresenter", ->
expect(editor.getRowsPerPage()).toBe(20)
it "tracks the computed content height if ::autoHeight is true so the editor auto-expands vertically", ->
presenter = buildPresenter(explicitHeight: null, autoHeight: true)
presenter = buildPresenter(explicitHeight: null)
presenter.setAutoHeight(true)
expect(presenter.getState().height).toBe editor.getScreenLineCount() * 10
expectStateUpdate presenter, -> presenter.setAutoHeight(false)
@@ -2185,7 +2218,9 @@ describe "TextEditorPresenter", ->
describe ".focused", ->
it "tracks the value of ::focused", ->
presenter = buildPresenter(focused: false)
presenter = buildPresenter()
presenter.setFocused(false)
expect(presenter.getState().focused).toBe false
expectStateUpdate presenter, -> presenter.setFocused(true)
expect(presenter.getState().focused).toBe true
@@ -2882,7 +2917,9 @@ describe "TextEditorPresenter", ->
describe ".backgroundColor", ->
it "is assigned to ::gutterBackgroundColor if present, and to ::backgroundColor otherwise", ->
presenter = buildPresenter(backgroundColor: "rgba(255, 0, 0, 0)", gutterBackgroundColor: "rgba(0, 255, 0, 0)")
presenter = buildPresenter()
presenter.setBackgroundColor("rgba(255, 0, 0, 0)")
presenter.setGutterBackgroundColor("rgba(0, 255, 0, 0)")
expect(getStylesForGutterWithName(presenter, 'line-number').backgroundColor).toBe "rgba(0, 255, 0, 0)"
expect(getStylesForGutterWithName(presenter, 'test-gutter').backgroundColor).toBe "rgba(0, 255, 0, 0)"

View File

@@ -163,14 +163,8 @@ describe "TextEditor", ->
expect(editor.getTitle()).toBe 'untitled'
describe ".getLongTitle()", ->
it "appends the name of the containing directory to the basename of the file", ->
expect(editor.getLongTitle()).toBe 'sample.js - fixtures'
buffer.setPath(undefined)
expect(editor.getLongTitle()).toBe 'untitled'
describe ".getUniqueTitle()", ->
it "returns file name when there is no opened file with identical name", ->
expect(editor.getUniqueTitle()).toBe 'sample.js'
expect(editor.getLongTitle()).toBe 'sample.js'
buffer.setPath(undefined)
expect(editor.getLongTitle()).toBe 'untitled'
@@ -183,8 +177,8 @@ describe "TextEditor", ->
atom.workspace.open(path.join('sample-theme-2', 'readme')).then (o) ->
editor2 = o
runs ->
expect(editor1.getUniqueTitle()).toBe 'sample-theme-1/readme'
expect(editor2.getUniqueTitle()).toBe 'sample-theme-2/readme'
expect(editor1.getLongTitle()).toBe 'sample-theme-1/readme'
expect(editor2.getLongTitle()).toBe 'sample-theme-2/readme'
it "or returns <parent-directory>/.../<filename> when opened files has identical file names", ->
editor1 = null
@@ -195,8 +189,8 @@ describe "TextEditor", ->
atom.workspace.open(path.join('sample-theme-2', 'src', 'js', 'main.js')).then (o) ->
editor2 = o
runs ->
expect(editor1.getUniqueTitle()).toBe 'sample-theme-1/.../main.js'
expect(editor2.getUniqueTitle()).toBe 'sample-theme-2/.../main.js'
expect(editor1.getLongTitle()).toBe 'sample-theme-1/.../main.js'
expect(editor2.getLongTitle()).toBe 'sample-theme-2/.../main.js'
it "notifies ::onDidChangeTitle observers when the underlying buffer path changes", ->
@@ -5444,6 +5438,73 @@ describe "TextEditor", ->
editor.selectPageUp()
expect(editor.getSelectedBufferRanges()).toEqual [[[0, 0], [12, 2]]]
describe "::setFirstVisibleScreenRow() and ::getFirstVisibleScreenRow()", ->
beforeEach ->
line = Array(9).join('0123456789')
editor.setText([1..100].map(-> line).join('\n'))
expect(editor.getLineCount()).toBe 100
expect(editor.lineTextForBufferRow(0).length).toBe 80
describe "when the editor doesn't have a height and lineHeightInPixels", ->
it "does not affect the editor's visible row range", ->
expect(editor.getVisibleRowRange()).toBeNull()
editor.setFirstVisibleScreenRow(1)
expect(editor.getFirstVisibleScreenRow()).toEqual 1
editor.setFirstVisibleScreenRow(3)
expect(editor.getFirstVisibleScreenRow()).toEqual 3
expect(editor.getVisibleRowRange()).toBeNull()
expect(editor.getLastVisibleScreenRow()).toBeNull()
describe "when the editor has a height and lineHeightInPixels", ->
beforeEach ->
atom.config.set('editor.scrollPastEnd', true)
editor.setHeight(100, true)
editor.setLineHeightInPixels(10)
it "updates the editor's visible row range", ->
editor.setFirstVisibleScreenRow(2)
expect(editor.getFirstVisibleScreenRow()).toEqual 2
expect(editor.getLastVisibleScreenRow()).toBe 12
expect(editor.getVisibleRowRange()).toEqual [2, 12]
it "notifies ::onDidChangeFirstVisibleScreenRow observers", ->
changeCount = 0
editor.onDidChangeFirstVisibleScreenRow -> changeCount++
editor.setFirstVisibleScreenRow(2)
expect(changeCount).toBe 1
editor.setFirstVisibleScreenRow(2)
expect(changeCount).toBe 1
editor.setFirstVisibleScreenRow(3)
expect(changeCount).toBe 2
it "ensures that the top row is less than the buffer's line count", ->
editor.setFirstVisibleScreenRow(102)
expect(editor.getFirstVisibleScreenRow()).toEqual 99
expect(editor.getVisibleRowRange()).toEqual [99, 99]
it "ensures that the left column is less than the length of the longest screen line", ->
editor.setFirstVisibleScreenRow(10)
expect(editor.getFirstVisibleScreenRow()).toEqual 10
editor.setText("\n\n\n")
editor.setFirstVisibleScreenRow(10)
expect(editor.getFirstVisibleScreenRow()).toEqual 3
describe "when the 'editor.scrollPastEnd' option is set to false", ->
it "ensures that the bottom row is less than the buffer's line count", ->
atom.config.set('editor.scrollPastEnd', false)
editor.setFirstVisibleScreenRow(95)
expect(editor.getFirstVisibleScreenRow()).toEqual 89
expect(editor.getVisibleRowRange()).toEqual [89, 99]
describe '.get/setPlaceholderText()', ->
it 'can be created with placeholderText', ->
newEditor = atom.workspace.buildTextEditor(