Merge branch 'master' into ns-fix-softwrap

Conflicts:
	src/row-map.coffee
This commit is contained in:
Nathan Sobo
2014-02-14 08:36:58 -07:00
117 changed files with 2967 additions and 2470 deletions

View File

@@ -1,35 +1,49 @@
{View, $, $$} = require '../src/space-pen-extensions'
path = require 'path'
_ = require 'underscore-plus'
{convertStackTrace} = require 'coffeestack'
{View, $, $$} = require '../src/space-pen-extensions'
sourceMaps = {}
formatStackTrace = (stackTrace) ->
formatStackTrace = (message='', stackTrace) ->
return stackTrace unless stackTrace
jasminePath = require.resolve('../vendor/jasmine')
jasminePattern = new RegExp("\\(#{_.escapeRegExp(jasminePath)}:\\d+:\\d+\\)\\s*$")
jasminePattern = /^\s*at\s+.*\(?.*\/jasmine(-[^\/]*)?\.js:\d+:\d+\)?\s*$/
firstJasmineLinePattern = /^\s*at \/.*\/jasmine(-[^\/]*)?\.js:\d+:\d+\)?\s*$/
convertedLines = []
for line in stackTrace.split('\n')
convertedLines.push(line) unless jasminePattern.test(line)
break if firstJasmineLinePattern.test(line)
convertStackTrace(convertedLines.join('\n'), sourceMaps)
stackTrace = convertStackTrace(convertedLines.join('\n'), sourceMaps)
lines = stackTrace.split('\n')
# Remove first line of stack when it is the same as the error message
errorMatch = lines[0]?.match(/^Error: (.*)/)
lines.shift() if message.trim() is errorMatch?[1]?.trim()
# Remove prefix of lines matching: at [object Object].<anonymous> (path:1:2)
for line, index in lines
prefixMatch = line.match(/at \[object Object\]\.<anonymous> \(([^\)]+)\)/)
lines[index] = "at #{prefixMatch[1]}" if prefixMatch
lines = lines.map (line) -> line.trim()
lines.join('\n')
module.exports =
class AtomReporter extends View
@content: ->
@div id: 'HTMLReporter', class: 'jasmine_reporter', =>
@div outlet: 'specPopup', class: "spec-popup"
@div class: 'spec-reporter', =>
@div outlet: "suites"
@div outlet: 'coreArea', =>
@div outlet: 'coreHeader', class: 'symbolHeader'
@ul outlet: 'coreSummary', class: 'symbolSummary list-unstyled'
@div outlet: 'bundledArea', =>
@div outlet: 'bundledHeader', class: 'symbolHeader'
@ul outlet: 'bundledSummary', class: 'symbolSummary list-unstyled'
@div outlet: 'userArea', =>
@div outlet: 'userHeader', class: 'symbolHeader'
@ul outlet: 'userSummary', class: 'symbolSummary list-unstyled'
@div outlet: "status", class: 'status', =>
@div outlet: 'coreArea', class: 'symbol-area', =>
@div outlet: 'coreHeader', class: 'symbol-header'
@ul outlet: 'coreSummary', class: 'symbol-summary list-unstyled'
@div outlet: 'bundledArea', class: 'symbol-area', =>
@div outlet: 'bundledHeader', class: 'symbol-header'
@ul outlet: 'bundledSummary', class: 'symbol-summary list-unstyled'
@div outlet: 'userArea', class: 'symbol-area', =>
@div outlet: 'userHeader', class: 'symbol-header'
@ul outlet: 'userSummary', class: 'symbol-summary list-unstyled'
@div outlet: "status", class: 'status alert alert-info', =>
@div outlet: "time", class: 'time'
@div outlet: "specCount", class: 'spec-count'
@div outlet: "message", class: 'message'
@@ -46,7 +60,7 @@ class AtomReporter extends View
reportRunnerStarting: (runner) ->
@handleEvents()
@startedAt = new Date()
@startedAt = Date.now()
specs = runner.specs()
@totalSpecCount = specs.length
@addSpecs(specs)
@@ -54,57 +68,29 @@ class AtomReporter extends View
reportRunnerResults: (runner) ->
@updateSpecCounts()
if @failedCount == 0
@message.text "Success!"
@status.addClass('alert-success').removeClass('alert-info') if @failedCount is 0
if @failedCount is 1
@message.text "#{@failedCount} failure"
else
@message.text "Game Over"
@message.text "#{@failedCount} failures"
reportSuiteResults: (suite) ->
reportSpecResults: (spec) ->
@completeSpecCount++
spec.endedAt = new Date().getTime()
spec.endedAt = Date.now()
@specComplete(spec)
@updateStatusView(spec)
reportSpecStarting: (spec) ->
@specStarted(spec)
specFilter: (spec) ->
globalFocusPriority = jasmine.getEnv().focusPriority
parent = spec.parentSuite ? spec.suite
if !globalFocusPriority
true
else if spec.focusPriority >= globalFocusPriority
true
else if not parent
false
else
@specFilter(parent)
handleEvents: ->
$(document).on "mouseover", ".spec-summary", ({currentTarget}) =>
element = $(currentTarget)
description = element.data("description")
return unless description
clearTimeout @timeoutId if @timeoutId?
@specPopup.show()
spec = _.find(window.timedSpecs, ({fullName}) -> description is fullName)
description = "#{description} #{spec.time}ms" if spec
@specPopup.text description
{left, top} = element.offset()
left += 20
top += 20
@specPopup.offset({left, top})
@timeoutId = setTimeout((=> @specPopup.hide()), 3000)
$(document).on "click", ".spec-toggle", ({currentTarget}) =>
element = $(currentTarget)
specFailures = element.parent().find('.spec-failures')
specFailures.toggle()
if specFailures.is(":visible") then element.text "\uf03d" else element.html "\uf03f"
element.toggleClass('folded')
false
updateSpecCounts: ->
@@ -116,7 +102,7 @@ class AtomReporter extends View
updateStatusView: (spec) ->
if @failedCount > 0
@status.addClass('failed') unless @status.hasClass('failed')
@status.addClass('alert-danger').removeClass('alert-info')
@updateSpecCounts()
@@ -124,7 +110,7 @@ class AtomReporter extends View
rootSuite = rootSuite.parentSuite while rootSuite.parentSuite
@message.text rootSuite.description
time = "#{Math.round((spec.endedAt - @startedAt.getTime()) / 10)}"
time = "#{Math.round((spec.endedAt - @startedAt) / 10)}"
time = "0#{time}" if time.length < 3
@time[0].textContent = "#{time[0...-2]}.#{time[-2..]}s"
@@ -146,15 +132,22 @@ class AtomReporter extends View
@userSummary.append symbol
if coreSpecs > 0
@coreHeader.text("Core Specs (#{coreSpecs}):")
@coreHeader.text("Core Specs (#{coreSpecs})")
else
@coreArea.hide()
if bundledPackageSpecs > 0
@bundledHeader.text("Bundled Package Specs (#{bundledPackageSpecs}):")
@bundledHeader.text("Bundled Package Specs (#{bundledPackageSpecs})")
else
@bundledArea.hide()
if userPackageSpecs > 0
@userHeader.text("User Package Specs (#{userPackageSpecs}):")
if coreSpecs is 0 and bundledPackageSpecs is 0
# Package specs being run, show a more descriptive label
{specDirectory} = specs[0]
packageFolderName = path.basename(path.dirname(specDirectory))
packageName = _.undasherize(_.uncamelcase(packageFolderName))
@userHeader.text("#{packageName} Specs")
else
@userHeader.text("User Package Specs (#{userPackageSpecs})")
else
@userArea.hide()
@@ -164,7 +157,7 @@ class AtomReporter extends View
specComplete: (spec) ->
specSummaryElement = $("#spec-summary-#{spec.id}")
specSummaryElement.removeClass('pending')
specSummaryElement.data("description", spec.getFullName())
specSummaryElement.setTooltip(title: spec.getFullName(), container: '.spec-reporter')
results = spec.results()
if results.skipped
@@ -185,11 +178,9 @@ class SuiteResultView extends View
@div class: 'suite', =>
@div outlet: 'description', class: 'description'
suite: null
initialize: (@suite) ->
@attr('id', "suite-view-#{@suite.id}")
@description.html @suite.description
@description.text(@suite.description)
attach: ->
(@parentSuiteView() or $('.results')).append this
@@ -206,20 +197,22 @@ class SuiteResultView extends View
class SpecResultView extends View
@content: ->
@div class: 'spec', =>
@div "\uf03d", class: 'spec-toggle'
@div class: 'spec-toggle'
@div outlet: 'description', class: 'description'
@div outlet: 'specFailures', class: 'spec-failures'
spec: null
initialize: (@spec) ->
@addClass("spec-view-#{@spec.id}")
@description.html @spec.description
description = @spec.description
description = "it #{description}" if description.indexOf('it ') isnt 0
@description.text(description)
for result in @spec.results().getItems() when not result.passed()
stackTrace = formatStackTrace(result.trace.stack)
stackTrace = formatStackTrace(result.message, result.trace.stack)
@specFailures.append $$ ->
@div result.message, class: 'resultMessage fail'
@div stackTrace, class: 'stackTrace' if stackTrace
@div result.message, class: 'result-message fail'
@pre stackTrace, class: 'stack-trace padded' if stackTrace
attach: ->
@parentSuiteView().append this

View File

@@ -1,6 +1,7 @@
{$, $$, fs, WorkspaceView} = require 'atom'
Exec = require('child_process').exec
path = require 'path'
AtomPackage = require '../src/atom-package'
ThemeManager = require '../src/theme-manager'
describe "the `atom` global", ->
@@ -9,35 +10,28 @@ describe "the `atom` global", ->
describe "package lifecycle methods", ->
describe ".loadPackage(name)", ->
describe "when the package has deferred deserializers", ->
it "requires the package's main module if one of its deferred deserializers is referenced", ->
pack = atom.packages.loadPackage('package-with-activation-events')
spyOn(pack, 'activateStylesheets').andCallThrough()
expect(pack.mainModule).toBeNull()
object = atom.deserializers.deserialize({deserializer: 'Foo', data: 5})
expect(pack.mainModule).toBeDefined()
expect(object.constructor.name).toBe 'Foo'
expect(object.data).toBe 5
expect(pack.activateStylesheets).toHaveBeenCalled()
it "continues if the package has an invalid package.json", ->
spyOn(console, 'warn')
atom.config.set("core.disabledPackages", [])
expect(-> atom.packages.loadPackage("package-with-broken-package-json")).not.toThrow()
it "continues if the package has an invalid package.json", ->
spyOn(console, 'warn')
atom.config.set("core.disabledPackages", [])
expect(-> atom.packages.loadPackage("package-with-broken-package-json")).not.toThrow()
it "continues if the package has an invalid keymap", ->
atom.config.set("core.disabledPackages", [])
expect(-> atom.packages.loadPackage("package-with-broken-keymap")).not.toThrow()
it "continues if the package has an invalid keymap", ->
atom.config.set("core.disabledPackages", [])
expect(-> atom.packages.loadPackage("package-with-broken-keymap")).not.toThrow()
describe ".unloadPackage(name)", ->
describe "when the package is active", ->
it "throws an error", ->
pack = atom.packages.activatePackage('package-with-main')
expect(atom.packages.isPackageLoaded(pack.name)).toBeTruthy()
expect(atom.packages.isPackageActive(pack.name)).toBeTruthy()
expect( -> atom.packages.unloadPackage(pack.name)).toThrow()
expect(atom.packages.isPackageLoaded(pack.name)).toBeTruthy()
expect(atom.packages.isPackageActive(pack.name)).toBeTruthy()
pack = null
waitsForPromise ->
atom.packages.activatePackage('package-with-main').then (p) -> pack = p
runs ->
expect(atom.packages.isPackageLoaded(pack.name)).toBeTruthy()
expect(atom.packages.isPackageActive(pack.name)).toBeTruthy()
expect( -> atom.packages.unloadPackage(pack.name)).toThrow()
expect(atom.packages.isPackageLoaded(pack.name)).toBeTruthy()
expect(atom.packages.isPackageActive(pack.name)).toBeTruthy()
describe "when the package is not loaded", ->
it "throws an error", ->
@@ -54,22 +48,42 @@ describe "the `atom` global", ->
describe ".activatePackage(id)", ->
describe "atom packages", ->
describe "when called multiple times", ->
it "it only calls activate on the package once", ->
spyOn(AtomPackage.prototype, 'activateNow').andCallThrough()
atom.packages.activatePackage('package-with-index')
atom.packages.activatePackage('package-with-index')
waitsForPromise ->
atom.packages.activatePackage('package-with-index')
runs ->
expect(AtomPackage.prototype.activateNow.callCount).toBe 1
describe "when the package has a main module", ->
describe "when the metadata specifies a main module path˜", ->
it "requires the module at the specified path", ->
mainModule = require('./fixtures/packages/package-with-main/main-module')
spyOn(mainModule, 'activate')
pack = atom.packages.activatePackage('package-with-main')
expect(mainModule.activate).toHaveBeenCalled()
expect(pack.mainModule).toBe mainModule
pack = null
waitsForPromise ->
atom.packages.activatePackage('package-with-main').then (p) -> pack = p
runs ->
expect(mainModule.activate).toHaveBeenCalled()
expect(pack.mainModule).toBe mainModule
describe "when the metadata does not specify a main module", ->
it "requires index.coffee", ->
indexModule = require('./fixtures/packages/package-with-index/index')
spyOn(indexModule, 'activate')
pack = atom.packages.activatePackage('package-with-index')
expect(indexModule.activate).toHaveBeenCalled()
expect(pack.mainModule).toBe indexModule
pack = null
waitsForPromise ->
atom.packages.activatePackage('package-with-index').then (p) -> pack = p
runs ->
expect(indexModule.activate).toHaveBeenCalled()
expect(pack.mainModule).toBe indexModule
it "assigns config defaults from the module", ->
expect(atom.config.get('package-with-config-defaults.numbers.one')).toBeUndefined()
@@ -78,20 +92,22 @@ describe "the `atom` global", ->
expect(atom.config.get('package-with-config-defaults.numbers.two')).toBe 2
describe "when the package metadata includes activation events", ->
[mainModule, pack] = []
[mainModule, promise] = []
beforeEach ->
mainModule = require './fixtures/packages/package-with-activation-events/index'
spyOn(mainModule, 'activate').andCallThrough()
AtomPackage = require '../src/atom-package'
spyOn(AtomPackage.prototype, 'requireMainModule').andCallThrough()
pack = atom.packages.activatePackage('package-with-activation-events')
promise = atom.packages.activatePackage('package-with-activation-events')
it "defers requiring/activating the main module until an activation event bubbles to the root view", ->
expect(pack.requireMainModule).not.toHaveBeenCalled()
expect(mainModule.activate).not.toHaveBeenCalled()
expect(promise.isFulfilled()).not.toBeTruthy()
atom.workspaceView.trigger 'activation-event'
expect(mainModule.activate).toHaveBeenCalled()
waitsForPromise ->
promise
it "triggers the activation event on all handlers registered during activation", ->
atom.workspaceView.openSync()
@@ -116,13 +132,17 @@ describe "the `atom` global", ->
expect(console.warn).not.toHaveBeenCalled()
it "passes the activate method the package's previously serialized state if it exists", ->
pack = atom.packages.activatePackage("package-with-serialization")
expect(pack.mainModule.someNumber).not.toBe 77
pack.mainModule.someNumber = 77
atom.packages.deactivatePackage("package-with-serialization")
spyOn(pack.mainModule, 'activate').andCallThrough()
atom.packages.activatePackage("package-with-serialization")
expect(pack.mainModule.activate).toHaveBeenCalledWith({someNumber: 77})
pack = null
waitsForPromise ->
atom.packages.activatePackage("package-with-serialization").then (p) -> pack = p
runs ->
expect(pack.mainModule.someNumber).not.toBe 77
pack.mainModule.someNumber = 77
atom.packages.deactivatePackage("package-with-serialization")
spyOn(pack.mainModule, 'activate').andCallThrough()
atom.packages.activatePackage("package-with-serialization")
expect(pack.mainModule.activate).toHaveBeenCalledWith({someNumber: 77})
it "logs warning instead of throwing an exception if the package fails to load", ->
atom.config.set("core.disabledPackages", [])
@@ -245,29 +265,38 @@ describe "the `atom` global", ->
describe "scoped-property loading", ->
it "loads the scoped properties", ->
atom.packages.activatePackage("package-with-scoped-properties")
expect(atom.syntax.getProperty ['.source.omg'], 'editor.increaseIndentPattern').toBe '^a'
waitsForPromise ->
atom.packages.activatePackage("package-with-scoped-properties")
runs ->
expect(atom.syntax.getProperty ['.source.omg'], 'editor.increaseIndentPattern').toBe '^a'
describe "textmate packages", ->
it "loads the package's grammars", ->
expect(atom.syntax.selectGrammar("file.rb").name).toBe "Null Grammar"
atom.packages.activatePackage('language-ruby', sync: true)
expect(atom.syntax.selectGrammar("file.rb").name).toBe "Ruby"
waitsForPromise ->
atom.packages.activatePackage('language-ruby')
runs ->
expect(atom.syntax.selectGrammar("file.rb").name).toBe "Ruby"
it "translates the package's scoped properties to Atom terms", ->
expect(atom.syntax.getProperty(['.source.ruby'], 'editor.commentStart')).toBeUndefined()
atom.packages.activatePackage('language-ruby', sync: true)
expect(atom.syntax.getProperty(['.source.ruby'], 'editor.commentStart')).toBe '# '
waitsForPromise ->
atom.packages.activatePackage('language-ruby')
runs ->
expect(atom.syntax.getProperty(['.source.ruby'], 'editor.commentStart')).toBe '# '
describe "when the package has no grammars but does have preferences", ->
it "loads the package's preferences as scoped properties", ->
jasmine.unspy(window, 'setTimeout')
spyOn(atom.syntax, 'addProperties').andCallThrough()
atom.packages.activatePackage('package-with-preferences-tmbundle')
waitsFor ->
atom.syntax.addProperties.callCount > 0
waitsForPromise ->
atom.packages.activatePackage('package-with-preferences-tmbundle')
runs ->
expect(atom.syntax.getProperty(['.source.pref'], 'editor.increaseIndentPattern')).toBe '^abc$'
@@ -275,80 +304,118 @@ describe "the `atom` global", ->
describe ".deactivatePackage(id)", ->
describe "atom packages", ->
it "calls `deactivate` on the package's main module if activate was successful", ->
pack = atom.packages.activatePackage("package-with-deactivate")
expect(atom.packages.isPackageActive("package-with-deactivate")).toBeTruthy()
spyOn(pack.mainModule, 'deactivate').andCallThrough()
pack = null
waitsForPromise ->
atom.packages.activatePackage("package-with-deactivate").then (p) -> pack = p
atom.packages.deactivatePackage("package-with-deactivate")
expect(pack.mainModule.deactivate).toHaveBeenCalled()
expect(atom.packages.isPackageActive("package-with-module")).toBeFalsy()
runs ->
expect(atom.packages.isPackageActive("package-with-deactivate")).toBeTruthy()
spyOn(pack.mainModule, 'deactivate').andCallThrough()
spyOn(console, 'warn')
badPack = atom.packages.activatePackage("package-that-throws-on-activate")
expect(atom.packages.isPackageActive("package-that-throws-on-activate")).toBeTruthy()
spyOn(badPack.mainModule, 'deactivate').andCallThrough()
atom.packages.deactivatePackage("package-with-deactivate")
expect(pack.mainModule.deactivate).toHaveBeenCalled()
expect(atom.packages.isPackageActive("package-with-module")).toBeFalsy()
atom.packages.deactivatePackage("package-that-throws-on-activate")
expect(badPack.mainModule.deactivate).not.toHaveBeenCalled()
expect(atom.packages.isPackageActive("package-that-throws-on-activate")).toBeFalsy()
spyOn(console, 'warn')
badPack = null
waitsForPromise ->
atom.packages.activatePackage("package-that-throws-on-activate").then (p) -> badPack = p
runs ->
expect(atom.packages.isPackageActive("package-that-throws-on-activate")).toBeTruthy()
spyOn(badPack.mainModule, 'deactivate').andCallThrough()
atom.packages.deactivatePackage("package-that-throws-on-activate")
expect(badPack.mainModule.deactivate).not.toHaveBeenCalled()
expect(atom.packages.isPackageActive("package-that-throws-on-activate")).toBeFalsy()
it "does not serialize packages that have not been activated called on their main module", ->
spyOn(console, 'warn')
badPack = atom.packages.activatePackage("package-that-throws-on-activate")
spyOn(badPack.mainModule, 'serialize').andCallThrough()
badPack = null
waitsForPromise ->
atom.packages.activatePackage("package-that-throws-on-activate").then (p) -> badPack = p
atom.packages.deactivatePackage("package-that-throws-on-activate")
expect(badPack.mainModule.serialize).not.toHaveBeenCalled()
runs ->
spyOn(badPack.mainModule, 'serialize').andCallThrough()
atom.packages.deactivatePackage("package-that-throws-on-activate")
expect(badPack.mainModule.serialize).not.toHaveBeenCalled()
it "absorbs exceptions that are thrown by the package module's serialize methods", ->
spyOn(console, 'error')
atom.packages.activatePackage('package-with-serialize-error', immediate: true)
atom.packages.activatePackage('package-with-serialization', immediate: true)
atom.packages.deactivatePackages()
expect(atom.packages.packageStates['package-with-serialize-error']).toBeUndefined()
expect(atom.packages.packageStates['package-with-serialization']).toEqual someNumber: 1
expect(console.error).toHaveBeenCalled()
waitsForPromise ->
atom.packages.activatePackage('package-with-serialize-error')
waitsForPromise ->
atom.packages.activatePackage('package-with-serialization')
runs ->
atom.packages.deactivatePackages()
expect(atom.packages.packageStates['package-with-serialize-error']).toBeUndefined()
expect(atom.packages.packageStates['package-with-serialization']).toEqual someNumber: 1
expect(console.error).toHaveBeenCalled()
it "removes the package's grammars", ->
atom.packages.activatePackage('package-with-grammars')
atom.packages.deactivatePackage('package-with-grammars')
expect(atom.syntax.selectGrammar('a.alot').name).toBe 'Null Grammar'
expect(atom.syntax.selectGrammar('a.alittle').name).toBe 'Null Grammar'
waitsForPromise ->
atom.packages.activatePackage('package-with-grammars')
runs ->
atom.packages.deactivatePackage('package-with-grammars')
expect(atom.syntax.selectGrammar('a.alot').name).toBe 'Null Grammar'
expect(atom.syntax.selectGrammar('a.alittle').name).toBe 'Null Grammar'
it "removes the package's keymaps", ->
atom.packages.activatePackage('package-with-keymaps')
atom.packages.deactivatePackage('package-with-keymaps')
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', $$ -> @div class: 'test-1')).toHaveLength 0
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', $$ -> @div class: 'test-2')).toHaveLength 0
waitsForPromise ->
atom.packages.activatePackage('package-with-keymaps')
runs ->
atom.packages.deactivatePackage('package-with-keymaps')
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', $$ -> @div class: 'test-1')).toHaveLength 0
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', $$ -> @div class: 'test-2')).toHaveLength 0
it "removes the package's stylesheets", ->
atom.packages.activatePackage('package-with-stylesheets')
atom.packages.deactivatePackage('package-with-stylesheets')
one = require.resolve("./fixtures/packages/package-with-stylesheets-manifest/stylesheets/1.css")
two = require.resolve("./fixtures/packages/package-with-stylesheets-manifest/stylesheets/2.less")
three = require.resolve("./fixtures/packages/package-with-stylesheets-manifest/stylesheets/3.css")
expect(atom.themes.stylesheetElementForId(one)).not.toExist()
expect(atom.themes.stylesheetElementForId(two)).not.toExist()
expect(atom.themes.stylesheetElementForId(three)).not.toExist()
waitsForPromise ->
atom.packages.activatePackage('package-with-stylesheets')
runs ->
atom.packages.deactivatePackage('package-with-stylesheets')
one = require.resolve("./fixtures/packages/package-with-stylesheets-manifest/stylesheets/1.css")
two = require.resolve("./fixtures/packages/package-with-stylesheets-manifest/stylesheets/2.less")
three = require.resolve("./fixtures/packages/package-with-stylesheets-manifest/stylesheets/3.css")
expect(atom.themes.stylesheetElementForId(one)).not.toExist()
expect(atom.themes.stylesheetElementForId(two)).not.toExist()
expect(atom.themes.stylesheetElementForId(three)).not.toExist()
it "removes the package's scoped-properties", ->
atom.packages.activatePackage("package-with-scoped-properties")
expect(atom.syntax.getProperty ['.source.omg'], 'editor.increaseIndentPattern').toBe '^a'
atom.packages.deactivatePackage("package-with-scoped-properties")
expect(atom.syntax.getProperty ['.source.omg'], 'editor.increaseIndentPattern').toBeUndefined()
waitsForPromise ->
atom.packages.activatePackage("package-with-scoped-properties")
runs ->
expect(atom.syntax.getProperty ['.source.omg'], 'editor.increaseIndentPattern').toBe '^a'
atom.packages.deactivatePackage("package-with-scoped-properties")
expect(atom.syntax.getProperty ['.source.omg'], 'editor.increaseIndentPattern').toBeUndefined()
describe "textmate packages", ->
it "removes the package's grammars", ->
expect(atom.syntax.selectGrammar("file.rb").name).toBe "Null Grammar"
atom.packages.activatePackage('language-ruby', sync: true)
expect(atom.syntax.selectGrammar("file.rb").name).toBe "Ruby"
atom.packages.deactivatePackage('language-ruby')
expect(atom.syntax.selectGrammar("file.rb").name).toBe "Null Grammar"
waitsForPromise ->
atom.packages.activatePackage('language-ruby')
runs ->
expect(atom.syntax.selectGrammar("file.rb").name).toBe "Ruby"
atom.packages.deactivatePackage('language-ruby')
expect(atom.syntax.selectGrammar("file.rb").name).toBe "Null Grammar"
it "removes the package's scoped properties", ->
atom.packages.activatePackage('language-ruby', sync: true)
atom.packages.deactivatePackage('language-ruby')
expect(atom.syntax.getProperty(['.source.ruby'], 'editor.commentStart')).toBeUndefined()
waitsForPromise ->
atom.packages.activatePackage('language-ruby')
runs ->
atom.packages.deactivatePackage('language-ruby')
expect(atom.syntax.getProperty(['.source.ruby'], 'editor.commentStart')).toBeUndefined()
describe ".activate()", ->
packageActivator = null
@@ -382,7 +449,7 @@ describe "the `atom` global", ->
themes = themeActivator.mostRecentCall.args[0]
expect(['theme']).toContain(theme.getType()) for theme in themes
describe ".en/disablePackage()", ->
describe ".enablePackage() and disablePackage()", ->
describe "with packages", ->
it ".enablePackage() enables a disabled package", ->
packageName = 'package-with-main'
@@ -391,28 +458,36 @@ describe "the `atom` global", ->
expect(atom.config.get('core.disabledPackages')).toContain packageName
pack = atom.packages.enablePackage(packageName)
loadedPackages = atom.packages.getLoadedPackages()
activatedPackages = atom.packages.getActivePackages()
expect(loadedPackages).toContain(pack)
expect(activatedPackages).toContain(pack)
expect(atom.config.get('core.disabledPackages')).not.toContain packageName
activatedPackages = null
waitsFor ->
activatedPackages = atom.packages.getActivePackages()
activatedPackages.length > 0
runs ->
expect(loadedPackages).toContain(pack)
expect(activatedPackages).toContain(pack)
expect(atom.config.get('core.disabledPackages')).not.toContain packageName
it ".disablePackage() disables an enabled package", ->
packageName = 'package-with-main'
atom.packages.activatePackage(packageName)
atom.packages.observeDisabledPackages()
expect(atom.config.get('core.disabledPackages')).not.toContain packageName
waitsForPromise ->
atom.packages.activatePackage(packageName)
pack = atom.packages.disablePackage(packageName)
runs ->
atom.packages.observeDisabledPackages()
expect(atom.config.get('core.disabledPackages')).not.toContain packageName
activatedPackages = atom.packages.getActivePackages()
expect(activatedPackages).not.toContain(pack)
expect(atom.config.get('core.disabledPackages')).toContain packageName
pack = atom.packages.disablePackage(packageName)
activatedPackages = atom.packages.getActivePackages()
expect(activatedPackages).not.toContain(pack)
expect(atom.config.get('core.disabledPackages')).toContain packageName
describe "with themes", ->
beforeEach ->
atom.themes.activateThemes()
waitsForPromise ->
atom.themes.activateThemes()
afterEach ->
atom.themes.deactivateThemes()
@@ -426,18 +501,24 @@ describe "the `atom` global", ->
# enabling of theme
pack = atom.packages.enablePackage(packageName)
activatedPackages = atom.packages.getActivePackages()
expect(activatedPackages).toContain(pack)
expect(atom.config.get('core.themes')).toContain packageName
expect(atom.config.get('core.disabledPackages')).not.toContain packageName
# disabling of theme
pack = atom.packages.disablePackage(packageName)
activatedPackages = atom.packages.getActivePackages()
expect(activatedPackages).not.toContain(pack)
expect(atom.config.get('core.themes')).not.toContain packageName
expect(atom.config.get('core.themes')).not.toContain packageName
expect(atom.config.get('core.disabledPackages')).not.toContain packageName
activatedPackages = null
waitsFor ->
activatedPackages = atom.packages.getActivePackages()
activatedPackages.length > 0
runs ->
expect(activatedPackages).toContain(pack)
expect(atom.config.get('core.themes')).toContain packageName
expect(atom.config.get('core.disabledPackages')).not.toContain packageName
# disabling of theme
pack = atom.packages.disablePackage(packageName)
activatedPackages = atom.packages.getActivePackages()
expect(activatedPackages).not.toContain(pack)
expect(atom.config.get('core.themes')).not.toContain packageName
expect(atom.config.get('core.themes')).not.toContain packageName
expect(atom.config.get('core.disabledPackages')).not.toContain packageName
describe ".isReleasedVersion()", ->
it "returns false if the version is a SHA and true otherwise", ->

View File

@@ -0,0 +1,12 @@
describe "Clipboard", ->
describe "write(text, metadata) and read()", ->
it "writes and reads text to/from the native clipboard", ->
expect(atom.clipboard.read()).toBe 'initial clipboard content'
atom.clipboard.write('next')
expect(atom.clipboard.read()).toBe 'next'
it "returns metadata if the item on the native clipboard matches the last written item", ->
atom.clipboard.write('next', {meta: 'data'})
expect(atom.clipboard.read()).toBe 'next'
expect(atom.clipboard.readWithMetadata().text).toBe 'next'
expect(atom.clipboard.readWithMetadata().metadata).toEqual {meta: 'data'}

View File

@@ -20,7 +20,7 @@ describe "install(commandPath, callback)", ->
installDone = false
installError = null
installer.install commandFilePath, (error) ->
installer.install commandFilePath, false, (error) ->
installDone = true
installError = error

View File

@@ -63,6 +63,19 @@ describe "Config", ->
atom.config.toggle('foo.a')
expect(atom.config.get('foo.a')).toBe false
describe ".restoreDefault(keyPath)", ->
it "sets the value of the key path to its default", ->
atom.config.setDefaults('a', b: 3)
atom.config.set('a.b', 4)
expect(atom.config.get('a.b')).toBe 4
atom.config.restoreDefault('a.b')
expect(atom.config.get('a.b')).toBe 3
atom.config.set('a.c', 5)
expect(atom.config.get('a.c')).toBe 5
atom.config.restoreDefault('a.c')
expect(atom.config.get('a.c')).toBeUndefined()
describe ".pushAtKeyPath(keyPath, value)", ->
it "pushes the given value to the array at the key path and updates observers", ->
atom.config.set("foo.bar.baz", ["a"])
@@ -220,6 +233,8 @@ describe "Config", ->
expect(fs.existsSync(path.join(atom.config.configDirPath, 'packages'))).toBeTruthy()
expect(fs.isFileSync(path.join(atom.config.configDirPath, 'snippets.cson'))).toBeTruthy()
expect(fs.isFileSync(path.join(atom.config.configDirPath, 'config.cson'))).toBeTruthy()
expect(fs.isFileSync(path.join(atom.config.configDirPath, 'init.coffee'))).toBeTruthy()
expect(fs.isFileSync(path.join(atom.config.configDirPath, 'styles.css'))).toBeTruthy()
describe ".loadUserConfig()", ->
beforeEach ->

View File

@@ -5,12 +5,15 @@ describe "DisplayBuffer", ->
[displayBuffer, buffer, changeHandler, tabLength] = []
beforeEach ->
tabLength = 2
atom.packages.activatePackage('language-javascript', sync: true)
buffer = atom.project.bufferForPathSync('sample.js')
displayBuffer = new DisplayBuffer({buffer, tabLength})
changeHandler = jasmine.createSpy 'changeHandler'
displayBuffer.on 'changed', changeHandler
waitsForPromise ->
atom.packages.activatePackage('language-javascript')
afterEach ->
displayBuffer.destroy()
buffer.release()

View File

@@ -16,11 +16,13 @@ describe "Editor", ->
describe "with default options", ->
beforeEach ->
atom.packages.activatePackage('language-javascript', sync: true)
editor = atom.project.openSync('sample.js', autoIndent: false)
buffer = editor.buffer
lineLengths = buffer.getLines().map (line) -> line.length
waitsForPromise ->
atom.packages.activatePackage('language-javascript')
describe "when the editor is deserialized", ->
it "restores selections and folds based on markers in the buffer", ->
editor.setSelectedBufferRange([[1, 2], [3, 4]])
@@ -1856,12 +1858,12 @@ describe "Editor", ->
expect(editor.getCursorBufferPosition()).toEqual [0, 2]
expect(editor.getCursorScreenPosition()).toEqual [0, editor.getTabLength() * 2]
describe "pasteboard operations", ->
describe "clipboard operations", ->
beforeEach ->
editor.setSelectedBufferRanges([[[0, 4], [0, 13]], [[1, 6], [1, 10]]])
describe ".cutSelectedText()", ->
it "removes the selected text from the buffer and places it on the pasteboard", ->
it "removes the selected text from the buffer and places it on the clipboard", ->
editor.cutSelectedText()
expect(buffer.lineForRow(0)).toBe "var = function () {"
expect(buffer.lineForRow(1)).toBe " var = function(items) {"
@@ -1885,7 +1887,7 @@ describe "Editor", ->
editor.cutToEndOfLine()
expect(buffer.lineForRow(2)).toBe ' if (items.length'
expect(buffer.lineForRow(3)).toBe ' var pivot = item'
expect(atom.pasteboard.read()[0]).toBe ' <= 1) return items;\ns.shift(), current, left = [], right = [];'
expect(atom.clipboard.read()).toBe ' <= 1) return items;\ns.shift(), current, left = [], right = [];'
describe "when text is selected", ->
it "only cuts the selected text, not to the end of the line", ->
@@ -1895,7 +1897,7 @@ describe "Editor", ->
expect(buffer.lineForRow(2)).toBe ' if (items.lengthurn items;'
expect(buffer.lineForRow(3)).toBe ' var pivot = item'
expect(atom.pasteboard.read()[0]).toBe ' <= 1) ret\ns.shift(), current, left = [], right = [];'
expect(atom.clipboard.read()).toBe ' <= 1) ret\ns.shift(), current, left = [], right = [];'
describe ".copySelectedText()", ->
it "copies selected text onto the clipboard", ->
@@ -1906,7 +1908,7 @@ describe "Editor", ->
describe ".pasteText()", ->
it "pastes text into the buffer", ->
atom.pasteboard.write('first')
atom.clipboard.write('first')
editor.pasteText()
expect(editor.buffer.lineForRow(0)).toBe "var first = function () {"
expect(buffer.lineForRow(1)).toBe " var first = function(items) {"
@@ -2733,19 +2735,26 @@ describe "Editor", ->
describe "when the editor's grammar has an injection selector", ->
beforeEach ->
atom.packages.activatePackage('language-text', sync: true)
atom.packages.activatePackage('language-javascript', sync: true)
waitsForPromise ->
atom.packages.activatePackage('language-text')
waitsForPromise ->
atom.packages.activatePackage('language-javascript')
it "includes the grammar's patterns when the selector matches the current scope in other grammars", ->
atom.packages.activatePackage('language-hyperlink', sync: true)
grammar = atom.syntax.selectGrammar("text.js")
{tokens} = grammar.tokenizeLine("var i; // http://github.com")
waitsForPromise ->
atom.packages.activatePackage('language-hyperlink')
expect(tokens[0].value).toBe "var"
expect(tokens[0].scopes).toEqual ["source.js", "storage.modifier.js"]
runs ->
grammar = atom.syntax.selectGrammar("text.js")
{tokens} = grammar.tokenizeLine("var i; // http://github.com")
expect(tokens[6].value).toBe "http://github.com"
expect(tokens[6].scopes).toEqual ["source.js", "comment.line.double-slash.js", "markup.underline.link.http.hyperlink"]
expect(tokens[0].value).toBe "var"
expect(tokens[0].scopes).toEqual ["source.js", "storage.modifier.js"]
expect(tokens[6].value).toBe "http://github.com"
expect(tokens[6].scopes).toEqual ["source.js", "comment.line.double-slash.js", "markup.underline.link.http.hyperlink"]
describe "when the grammar is added", ->
it "retokenizes existing buffers that contain tokens that match the injection selector", ->
@@ -2756,11 +2765,13 @@ describe "Editor", ->
expect(tokens[1].value).toBe " http://github.com"
expect(tokens[1].scopes).toEqual ["source.js", "comment.line.double-slash.js"]
atom.packages.activatePackage('language-hyperlink', sync: true)
waitsForPromise ->
atom.packages.activatePackage('language-hyperlink')
{tokens} = editor.lineForScreenRow(0)
expect(tokens[2].value).toBe "http://github.com"
expect(tokens[2].scopes).toEqual ["source.js", "comment.line.double-slash.js", "markup.underline.link.http.hyperlink"]
runs ->
{tokens} = editor.lineForScreenRow(0)
expect(tokens[2].value).toBe "http://github.com"
expect(tokens[2].scopes).toEqual ["source.js", "comment.line.double-slash.js", "markup.underline.link.http.hyperlink"]
describe "when the grammar is updated", ->
it "retokenizes existing buffers that contain tokens that match the injection selector", ->
@@ -2771,14 +2782,17 @@ describe "Editor", ->
expect(tokens[1].value).toBe " SELECT * FROM OCTOCATS"
expect(tokens[1].scopes).toEqual ["source.js", "comment.line.double-slash.js"]
atom.packages.activatePackage('package-with-injection-selector', sync: true)
atom.packages.activatePackage('package-with-injection-selector')
{tokens} = editor.lineForScreenRow(0)
expect(tokens[1].value).toBe " SELECT * FROM OCTOCATS"
expect(tokens[1].scopes).toEqual ["source.js", "comment.line.double-slash.js"]
atom.packages.activatePackage('language-sql', sync: true)
waitsForPromise ->
atom.packages.activatePackage('language-sql')
{tokens} = editor.lineForScreenRow(0)
expect(tokens[2].value).toBe "SELECT"
expect(tokens[2].scopes).toEqual ["source.js", "comment.line.double-slash.js", "keyword.other.DML.sql"]
runs ->
{tokens} = editor.lineForScreenRow(0)
expect(tokens[2].value).toBe "SELECT"
expect(tokens[2].scopes).toEqual ["source.js", "comment.line.double-slash.js", "keyword.other.DML.sql"]

View File

@@ -10,8 +10,6 @@ describe "EditorView", ->
[buffer, editorView, editor, cachedLineHeight, cachedCharWidth] = []
beforeEach ->
atom.packages.activatePackage('language-text', sync: true)
atom.packages.activatePackage('language-javascript', sync: true)
editor = atom.project.openSync('sample.js')
buffer = editor.buffer
editorView = new EditorView(editor)
@@ -26,6 +24,12 @@ describe "EditorView", ->
@width(getCharWidth() * widthInChars) if widthInChars
$('#jasmine-content').append(this)
waitsForPromise ->
atom.packages.activatePackage('language-text', sync: true)
waitsForPromise ->
atom.packages.activatePackage('language-javascript', sync: true)
getLineHeight = ->
return cachedLineHeight if cachedLineHeight?
calcDimensions()
@@ -2515,9 +2519,9 @@ describe "EditorView", ->
expect(edited).toBe false
describe "when editor:copy-path is triggered", ->
it "copies the absolute path to the editor view's file to the pasteboard", ->
it "copies the absolute path to the editor view's file to the clipboard", ->
editorView.trigger 'editor:copy-path'
expect(atom.pasteboard.read()[0]).toBe editor.getPath()
expect(atom.clipboard.read()).toBe editor.getPath()
describe "when editor:move-line-up is triggered", ->
describe "when there is no selection", ->
@@ -2532,6 +2536,52 @@ describe "EditorView", ->
editorView.trigger 'editor:move-line-up'
expect(editor.getCursorBufferPosition()).toEqual [0,2]
describe "when the line above is folded", ->
it "moves the line around the fold", ->
editor.foldBufferRow(1)
editor.setCursorBufferPosition([10, 0])
editorView.trigger 'editor:move-line-up'
expect(editor.getCursorBufferPosition()).toEqual [1, 0]
expect(buffer.lineForRow(1)).toBe ''
expect(buffer.lineForRow(2)).toBe ' var sort = function(items) {'
expect(editor.isFoldedAtBufferRow(1)).toBe false
expect(editor.isFoldedAtBufferRow(2)).toBe true
describe "when the line being moved is folded", ->
it "moves the fold around the fold above it", ->
editor.setCursorBufferPosition([0, 0])
editor.insertText """
var a = function() {
b = 3;
};
"""
editor.foldBufferRow(0)
editor.foldBufferRow(3)
editor.setCursorBufferPosition([3, 0])
editorView.trigger 'editor:move-line-up'
expect(editor.getCursorBufferPosition()).toEqual [0, 0]
expect(buffer.lineForRow(0)).toBe 'var quicksort = function () {'
expect(buffer.lineForRow(13)).toBe 'var a = function() {'
editor.logScreenLines()
expect(editor.isFoldedAtBufferRow(0)).toBe true
expect(editor.isFoldedAtBufferRow(13)).toBe true
describe "when the line above is empty and the line above that is folded", ->
it "moves the line to the empty line", ->
editor.foldBufferRow(2)
editor.setCursorBufferPosition([11, 0])
editorView.trigger 'editor:move-line-up'
expect(editor.getCursorBufferPosition()).toEqual [10, 0]
expect(buffer.lineForRow(9)).toBe ' };'
expect(buffer.lineForRow(10)).toBe ' return sort(Array.apply(this, arguments));'
expect(buffer.lineForRow(11)).toBe ''
expect(editor.isFoldedAtBufferRow(2)).toBe true
expect(editor.isFoldedAtBufferRow(10)).toBe false
describe "where there is a selection", ->
describe "when the selection falls inside the line", ->
it "maintains the selection", ->
@@ -2631,6 +2681,54 @@ describe "EditorView", ->
editorView.trigger 'editor:move-line-down'
expect(editor.getCursorBufferPosition()).toEqual [1, 2]
describe "when the line below is folded", ->
it "moves the line around the fold", ->
editor.setCursorBufferPosition([0, 0])
editor.foldBufferRow(1)
editorView.trigger 'editor:move-line-down'
expect(editor.getCursorBufferPosition()).toEqual [9, 0]
expect(buffer.lineForRow(0)).toBe ' var sort = function(items) {'
expect(buffer.lineForRow(9)).toBe 'var quicksort = function () {'
expect(editor.isFoldedAtBufferRow(0)).toBe true
expect(editor.isFoldedAtBufferRow(9)).toBe false
describe "when the line being moved is folded", ->
it "moves the fold around the fold below it", ->
editor.setCursorBufferPosition([0, 0])
editor.insertText """
var a = function() {
b = 3;
};
"""
editor.foldBufferRow(0)
editor.foldBufferRow(3)
editor.setCursorBufferPosition([0, 0])
editorView.trigger 'editor:move-line-down'
expect(editor.getCursorBufferPosition()).toEqual [13, 0]
expect(buffer.lineForRow(0)).toBe 'var quicksort = function () {'
expect(buffer.lineForRow(13)).toBe 'var a = function() {'
expect(editor.isFoldedAtBufferRow(0)).toBe true
expect(editor.isFoldedAtBufferRow(13)).toBe true
describe "when the line below is empty and the line below that is folded", ->
it "moves the line to the empty line", ->
editor.setCursorBufferPosition([0, Infinity])
editor.insertText('\n')
editor.setCursorBufferPosition([0, 0])
editor.foldBufferRow(2)
editorView.trigger 'editor:move-line-down'
expect(editor.getCursorBufferPosition()).toEqual [1, 0]
expect(buffer.lineForRow(0)).toBe ''
expect(buffer.lineForRow(1)).toBe 'var quicksort = function () {'
expect(buffer.lineForRow(2)).toBe ' var sort = function(items) {'
expect(editor.isFoldedAtBufferRow(0)).toBe false
expect(editor.isFoldedAtBufferRow(1)).toBe false
expect(editor.isFoldedAtBufferRow(2)).toBe true
describe "when the cursor is on the last line", ->
it "does not move the line", ->
editor.moveCursorToBottom()

View File

@@ -1,2 +1 @@
'activationEvents': ['activation-event']
'deferredDeserializers': ['Foo']

View File

@@ -1,5 +1 @@
# This package loads async, otherwise it would log errors when it
# is automatically serialized when workspaceView is deactivatated
'main': 'index.coffee'
'activationEvents': ['activation-event']

View File

@@ -1,3 +1,3 @@
{
"theme": true
"theme": "ui"
}

View File

@@ -1,3 +1,3 @@
{
"theme": true
"theme": "ui"
}

View File

@@ -1,3 +1,3 @@
{
"theme": true
"theme": "ui"
}

View File

@@ -1,4 +1,4 @@
{
"theme": true,
"theme": "ui",
"stylesheets": ["first.css", "second.less", "last.css"]
}

View File

@@ -1,4 +1,4 @@
{
"theme": true,
"theme": "ui",
"stylesheets": ["editor.less"]
}

View File

@@ -21,10 +21,6 @@ module.exports.runSpecSuite = (specSuite, logFile, logErrors=true) ->
print: (str) ->
log(str)
onComplete: (runner) ->
log('\n')
timeReporter.logLongestSuites 10, (line) -> log("#{line}\n")
log('\n')
timeReporter.logLongestSpecs 10, (line) -> log("#{line}\n")
fs.closeSync(logStream) if logStream?
atom.exit(runner.results().failedCount > 0 ? 1 : 0)
else

View File

@@ -6,10 +6,12 @@ describe "LanguageMode", ->
describe "javascript", ->
beforeEach ->
atom.packages.activatePackage('language-javascript', sync: true)
editor = atom.project.openSync('sample.js', autoIndent: false)
{buffer, languageMode} = editor
waitsForPromise ->
atom.packages.activatePackage('language-javascript')
describe ".minIndentLevelForRowRange(startRow, endRow)", ->
it "returns the minimum indent level for the given row range", ->
expect(languageMode.minIndentLevelForRowRange(4, 7)).toBe 2
@@ -100,10 +102,12 @@ describe "LanguageMode", ->
describe "coffeescript", ->
beforeEach ->
atom.packages.activatePackage('language-coffee-script', sync: true)
editor = atom.project.openSync('coffee.coffee', autoIndent: false)
{buffer, languageMode} = editor
waitsForPromise ->
atom.packages.activatePackage('language-coffee-script')
describe ".toggleLineCommentsForBufferRows(start, end)", ->
it "comments/uncomments lines in the given range", ->
languageMode.toggleLineCommentsForBufferRows(4, 6)
@@ -147,10 +151,12 @@ describe "LanguageMode", ->
describe "css", ->
beforeEach ->
atom.packages.activatePackage('language-css', sync: true)
editor = atom.project.openSync('css.css', autoIndent: false)
{buffer, languageMode} = editor
waitsForPromise ->
atom.packages.activatePackage('language-css')
describe ".toggleLineCommentsForBufferRows(start, end)", ->
it "comments/uncomments lines in the given range", ->
languageMode.toggleLineCommentsForBufferRows(0, 1)
@@ -188,11 +194,15 @@ describe "LanguageMode", ->
describe "less", ->
beforeEach ->
atom.packages.activatePackage('language-less', sync: true)
atom.packages.activatePackage('language-css', sync: true)
editor = atom.project.openSync('sample.less', autoIndent: false)
{buffer, languageMode} = editor
waitsForPromise ->
atom.packages.activatePackage('language-less')
waitsForPromise ->
atom.packages.activatePackage('language-css')
describe "when commenting lines", ->
it "only uses the `commentEnd` pattern if it comes from the same grammar as the `commentStart`", ->
languageMode.toggleLineCommentsForBufferRows(0, 0)
@@ -200,10 +210,12 @@ describe "LanguageMode", ->
describe "folding", ->
beforeEach ->
atom.packages.activatePackage('language-javascript', sync: true)
editor = atom.project.openSync('sample.js', autoIndent: false)
{buffer, languageMode} = editor
waitsForPromise ->
atom.packages.activatePackage('language-javascript')
it "maintains cursor buffer position when a folding/unfolding", ->
editor.setCursorBufferPosition([5,5])
languageMode.foldAll()
@@ -298,10 +310,12 @@ describe "LanguageMode", ->
describe "folding with comments", ->
beforeEach ->
atom.packages.activatePackage('language-javascript', sync: true)
editor = atom.project.openSync('sample-with-comments.js', autoIndent: false)
{buffer, languageMode} = editor
waitsForPromise ->
atom.packages.activatePackage('language-javascript')
describe ".unfoldAll()", ->
it "unfolds every folded line", ->
initialScreenLineCount = editor.getScreenLineCount()
@@ -362,10 +376,12 @@ describe "LanguageMode", ->
describe "css", ->
beforeEach ->
atom.packages.activatePackage('language-source', sync: true)
atom.packages.activatePackage('language-css', sync: true)
editor = atom.project.openSync('css.css', autoIndent: true)
waitsForPromise ->
atom.packages.activatePackage('language-source')
atom.packages.activatePackage('language-css')
describe "suggestedIndentForBufferRow", ->
it "does not return negative values (regression)", ->
editor.setText('.test {\npadding: 0;\n}')

View File

@@ -27,32 +27,6 @@ describe "PaneContainerView", ->
afterEach ->
atom.deserializers.remove(TestView)
describe ".focusNextPane()", ->
it "focuses the pane following the focused pane or the first pane if no pane has focus", ->
container.attachToDom()
container.focusNextPane()
expect(pane1.activeItem).toMatchSelector ':focus'
container.focusNextPane()
expect(pane2.activeItem).toMatchSelector ':focus'
container.focusNextPane()
expect(pane3.activeItem).toMatchSelector ':focus'
container.focusNextPane()
expect(pane1.activeItem).toMatchSelector ':focus'
describe ".focusPreviousPane()", ->
it "focuses the pane preceding the focused pane or the last pane if no pane has focus", ->
container.attachToDom()
container.getPanes()[0].focus() # activate first pane
container.focusPreviousPane()
expect(pane3.activeItem).toMatchSelector ':focus'
container.focusPreviousPane()
expect(pane2.activeItem).toMatchSelector ':focus'
container.focusPreviousPane()
expect(pane1.activeItem).toMatchSelector ':focus'
container.focusPreviousPane()
expect(pane3.activeItem).toMatchSelector ':focus'
describe ".getActivePane()", ->
it "returns the most-recently focused pane", ->
focusStealer = $$ -> @div tabindex: -1, "focus stealer"
@@ -265,3 +239,115 @@ describe "PaneContainerView", ->
pane1.remove()
pane2.remove()
expect(activeItemChangedHandler).not.toHaveBeenCalled()
describe ".focusNextPane()", ->
it "focuses the pane following the focused pane or the first pane if no pane has focus", ->
container.attachToDom()
container.focusNextPane()
expect(pane1.activeItem).toMatchSelector ':focus'
container.focusNextPane()
expect(pane2.activeItem).toMatchSelector ':focus'
container.focusNextPane()
expect(pane3.activeItem).toMatchSelector ':focus'
container.focusNextPane()
expect(pane1.activeItem).toMatchSelector ':focus'
describe ".focusPreviousPane()", ->
it "focuses the pane preceding the focused pane or the last pane if no pane has focus", ->
container.attachToDom()
container.getPanes()[0].focus() # activate first pane
container.focusPreviousPane()
expect(pane3.activeItem).toMatchSelector ':focus'
container.focusPreviousPane()
expect(pane2.activeItem).toMatchSelector ':focus'
container.focusPreviousPane()
expect(pane1.activeItem).toMatchSelector ':focus'
container.focusPreviousPane()
expect(pane3.activeItem).toMatchSelector ':focus'
describe "changing focus directionally between panes", ->
[pane1, pane2, pane3, pane4, pane5, pane6, pane7, pane8, pane9] = []
beforeEach ->
# Set up a grid of 9 panes, in the following arrangement, where the
# numbers correspond to the variable names below.
#
# -------
# |1|2|3|
# -------
# |4|5|6|
# -------
# |7|8|9|
# -------
container = new PaneContainerView
pane1 = container.getRoot()
pane1.activateItem(new TestView('1'))
pane4 = pane1.splitDown(new TestView('4'))
pane7 = pane4.splitDown(new TestView('7'))
pane2 = pane1.splitRight(new TestView('2'))
pane3 = pane2.splitRight(new TestView('3'))
pane5 = pane4.splitRight(new TestView('5'))
pane6 = pane5.splitRight(new TestView('6'))
pane8 = pane7.splitRight(new TestView('8'))
pane9 = pane8.splitRight(new TestView('9'))
container.height(400)
container.width(400)
container.attachToDom()
describe ".focusPaneAbove()", ->
describe "when there are multiple rows above the focused pane", ->
it "focuses up to the adjacent row", ->
pane8.focus()
container.focusPaneAbove()
expect(pane5.activeItem).toMatchSelector ':focus'
describe "when there are no rows above the focused pane", ->
it "keeps the current pane focused", ->
pane2.focus()
container.focusPaneAbove()
expect(pane2.activeItem).toMatchSelector ':focus'
describe ".focusPaneBelow()", ->
describe "when there are multiple rows below the focused pane", ->
it "focuses down to the adjacent row", ->
pane2.focus()
container.focusPaneBelow()
expect(pane5.activeItem).toMatchSelector ':focus'
describe "when there are no rows below the focused pane", ->
it "keeps the current pane focused", ->
pane8.focus()
container.focusPaneBelow()
expect(pane8.activeItem).toMatchSelector ':focus'
describe ".focusPaneOnLeft()", ->
describe "when there are multiple columns to the left of the focused pane", ->
it "focuses left to the adjacent column", ->
pane6.focus()
container.focusPaneOnLeft()
expect(pane5.activeItem).toMatchSelector ':focus'
describe "when there are no columns to the left of the focused pane", ->
it "keeps the current pane focused", ->
pane4.focus()
container.focusPaneOnLeft()
expect(pane4.activeItem).toMatchSelector ':focus'
describe ".focusPaneOnRight()", ->
describe "when there are multiple columns to the right of the focused pane", ->
it "focuses right to the adjacent column", ->
pane4.focus()
container.focusPaneOnRight()
expect(pane5.activeItem).toMatchSelector ':focus'
describe "when there are no columns to the right of the focused pane", ->
it "keeps the current pane focused", ->
pane6.focus()
container.focusPaneOnRight()
expect(pane6.activeItem).toMatchSelector ':focus'

View File

@@ -1,10 +0,0 @@
describe "Pasteboard", ->
describe "write(text, metadata) and read()", ->
it "writes and reads text to/from the native pasteboard", ->
expect(atom.pasteboard.read()).toEqual ['initial pasteboard content']
atom.pasteboard.write('next')
expect(atom.pasteboard.read()[0]).toBe 'next'
it "returns metadata if the item on the native pasteboard matches the last written item", ->
atom.pasteboard.write('next', {meta: 'data'})
expect(atom.pasteboard.read()).toEqual ['next', {meta: 'data'}]

View File

@@ -72,7 +72,7 @@ describe "Project", ->
expect(atom.project.getEditors()[1]).toBe editor2
describe ".openSync(path)", ->
[fooOpener, barOpener, absolutePath, newBufferHandler, newEditorHandler] = []
[absolutePath, newBufferHandler, newEditorHandler] = []
beforeEach ->
absolutePath = require.resolve('./fixtures/dir/a')
newBufferHandler = jasmine.createSpy('newBufferHandler')
@@ -80,129 +80,92 @@ describe "Project", ->
newEditorHandler = jasmine.createSpy('newEditorHandler')
atom.project.on 'editor-created', newEditorHandler
fooOpener = (pathToOpen, options) -> { foo: pathToOpen, options } if pathToOpen?.match(/\.foo/)
barOpener = (pathToOpen) -> { bar: pathToOpen } if pathToOpen?.match(/^bar:\/\//)
atom.project.registerOpener(fooOpener)
atom.project.registerOpener(barOpener)
describe "when given an absolute path that hasn't been opened previously", ->
it "returns a new edit session for the given path and emits 'buffer-created' and 'editor-created' events", ->
editor = atom.project.openSync(absolutePath)
expect(editor.buffer.getPath()).toBe absolutePath
expect(newBufferHandler).toHaveBeenCalledWith editor.buffer
expect(newEditorHandler).toHaveBeenCalledWith editor
afterEach ->
atom.project.unregisterOpener(fooOpener)
atom.project.unregisterOpener(barOpener)
describe "when given a relative path that hasn't been opened previously", ->
it "returns a new edit session for the given path (relative to the project root) and emits 'buffer-created' and 'editor-created' events", ->
editor = atom.project.openSync('a')
expect(editor.buffer.getPath()).toBe absolutePath
expect(newBufferHandler).toHaveBeenCalledWith editor.buffer
expect(newEditorHandler).toHaveBeenCalledWith editor
describe "when passed a path that doesn't match a custom opener", ->
describe "when given an absolute path that hasn't been opened previously", ->
it "returns a new edit session for the given path and emits 'buffer-created' and 'editor-created' events", ->
editor = atom.project.openSync(absolutePath)
describe "when passed the path to a buffer that has already been opened", ->
it "returns a new edit session containing previously opened buffer and emits a 'editor-created' event", ->
editor = atom.project.openSync(absolutePath)
newBufferHandler.reset()
expect(atom.project.openSync(absolutePath).buffer).toBe editor.buffer
expect(atom.project.openSync('a').buffer).toBe editor.buffer
expect(newBufferHandler).not.toHaveBeenCalled()
expect(newEditorHandler).toHaveBeenCalledWith editor
describe "when not passed a path", ->
it "returns a new edit session and emits 'buffer-created' and 'editor-created' events", ->
editor = atom.project.openSync()
expect(editor.buffer.getPath()).toBeUndefined()
expect(newBufferHandler).toHaveBeenCalledWith(editor.buffer)
expect(newEditorHandler).toHaveBeenCalledWith editor
describe ".open(path)", ->
[absolutePath, newBufferHandler, newEditorHandler] = []
beforeEach ->
absolutePath = require.resolve('./fixtures/dir/a')
newBufferHandler = jasmine.createSpy('newBufferHandler')
atom.project.on 'buffer-created', newBufferHandler
newEditorHandler = jasmine.createSpy('newEditorHandler')
atom.project.on 'editor-created', newEditorHandler
describe "when given an absolute path that isn't currently open", ->
it "returns a new edit session for the given path and emits 'buffer-created' and 'editor-created' events", ->
editor = null
waitsForPromise ->
atom.project.open(absolutePath).then (o) -> editor = o
runs ->
expect(editor.buffer.getPath()).toBe absolutePath
expect(newBufferHandler).toHaveBeenCalledWith editor.buffer
expect(newEditorHandler).toHaveBeenCalledWith editor
describe "when given a relative path that hasn't been opened previously", ->
it "returns a new edit session for the given path (relative to the project root) and emits 'buffer-created' and 'editor-created' events", ->
editor = atom.project.openSync('a')
describe "when given a relative path that isn't currently opened", ->
it "returns a new edit session for the given path (relative to the project root) and emits 'buffer-created' and 'editor-created' events", ->
editor = null
waitsForPromise ->
atom.project.open(absolutePath).then (o) -> editor = o
runs ->
expect(editor.buffer.getPath()).toBe absolutePath
expect(newBufferHandler).toHaveBeenCalledWith editor.buffer
expect(newEditorHandler).toHaveBeenCalledWith editor
describe "when passed the path to a buffer that has already been opened", ->
it "returns a new edit session containing previously opened buffer and emits a 'editor-created' event", ->
editor = atom.project.openSync(absolutePath)
describe "when passed the path to a buffer that is currently opened", ->
it "returns a new edit session containing currently opened buffer and emits a 'editor-created' event", ->
editor = null
waitsForPromise ->
atom.project.open(absolutePath).then (o) -> editor = o
runs ->
newBufferHandler.reset()
expect(atom.project.openSync(absolutePath).buffer).toBe editor.buffer
expect(atom.project.openSync('a').buffer).toBe editor.buffer
expect(newBufferHandler).not.toHaveBeenCalled()
expect(newEditorHandler).toHaveBeenCalledWith editor
describe "when not passed a path", ->
it "returns a new edit session and emits 'buffer-created' and 'editor-created' events", ->
editor = atom.project.openSync()
describe "when not passed a path", ->
it "returns a new edit session and emits 'buffer-created' and 'editor-created' events", ->
editor = null
waitsForPromise ->
atom.project.open().then (o) -> editor = o
runs ->
expect(editor.buffer.getPath()).toBeUndefined()
expect(newBufferHandler).toHaveBeenCalledWith(editor.buffer)
expect(newEditorHandler).toHaveBeenCalledWith editor
describe "when passed a path that matches a custom opener", ->
it "returns the resource returned by the custom opener", ->
pathToOpen = atom.project.resolve('a.foo')
expect(atom.project.openSync(pathToOpen, hey: "there")).toEqual { foo: pathToOpen, options: {hey: "there"} }
expect(atom.project.openSync("bar://baz")).toEqual { bar: "bar://baz" }
describe ".open(path)", ->
[fooOpener, barOpener, absolutePath, newBufferHandler, newEditorHandler] = []
beforeEach ->
absolutePath = require.resolve('./fixtures/dir/a')
newBufferHandler = jasmine.createSpy('newBufferHandler')
atom.project.on 'buffer-created', newBufferHandler
newEditorHandler = jasmine.createSpy('newEditorHandler')
atom.project.on 'editor-created', newEditorHandler
fooOpener = (pathToOpen, options) -> { foo: pathToOpen, options } if pathToOpen?.match(/\.foo/)
barOpener = (pathToOpen) -> { bar: pathToOpen } if pathToOpen?.match(/^bar:\/\//)
atom.project.registerOpener(fooOpener)
atom.project.registerOpener(barOpener)
afterEach ->
atom.project.unregisterOpener(fooOpener)
atom.project.unregisterOpener(barOpener)
describe "when passed a path that doesn't match a custom opener", ->
describe "when given an absolute path that isn't currently open", ->
it "returns a new edit session for the given path and emits 'buffer-created' and 'editor-created' events", ->
editor = null
waitsForPromise ->
atom.project.open(absolutePath).then (o) -> editor = o
runs ->
expect(editor.buffer.getPath()).toBe absolutePath
expect(newBufferHandler).toHaveBeenCalledWith editor.buffer
expect(newEditorHandler).toHaveBeenCalledWith editor
describe "when given a relative path that isn't currently opened", ->
it "returns a new edit session for the given path (relative to the project root) and emits 'buffer-created' and 'editor-created' events", ->
editor = null
waitsForPromise ->
atom.project.open(absolutePath).then (o) -> editor = o
runs ->
expect(editor.buffer.getPath()).toBe absolutePath
expect(newBufferHandler).toHaveBeenCalledWith editor.buffer
expect(newEditorHandler).toHaveBeenCalledWith editor
describe "when passed the path to a buffer that is currently opened", ->
it "returns a new edit session containing currently opened buffer and emits a 'editor-created' event", ->
editor = null
waitsForPromise ->
atom.project.open(absolutePath).then (o) -> editor = o
runs ->
newBufferHandler.reset()
expect(atom.project.openSync(absolutePath).buffer).toBe editor.buffer
expect(atom.project.openSync('a').buffer).toBe editor.buffer
expect(newBufferHandler).not.toHaveBeenCalled()
expect(newEditorHandler).toHaveBeenCalledWith editor
describe "when not passed a path", ->
it "returns a new edit session and emits 'buffer-created' and 'editor-created' events", ->
editor = null
waitsForPromise ->
atom.project.open().then (o) -> editor = o
runs ->
expect(editor.buffer.getPath()).toBeUndefined()
expect(newBufferHandler).toHaveBeenCalledWith(editor.buffer)
expect(newEditorHandler).toHaveBeenCalledWith editor
describe "when passed a path that matches a custom opener", ->
it "returns the resource returned by the custom opener", ->
waitsForPromise ->
pathToOpen = atom.project.resolve('a.foo')
atom.project.open(pathToOpen, hey: "there").then (item) ->
expect(item).toEqual { foo: pathToOpen, options: {hey: "there"} }
waitsForPromise ->
atom.project.open("bar://baz").then (item) ->
expect(item).toEqual { bar: "bar://baz" }
it "returns number of read bytes as progress indicator", ->
filePath = atom.project.resolve 'a'
totalBytes = 0

View File

@@ -11,35 +11,6 @@ describe "SpacePen extensions", ->
parent = $$ -> @div()
parent.append(view)
describe "View.observeConfig(keyPath, callback)", ->
observeHandler = null
beforeEach ->
observeHandler = jasmine.createSpy("observeHandler")
view.observeConfig "foo.bar", observeHandler
expect(view.hasParent()).toBeTruthy()
it "observes the keyPath and cancels the subscription when `.unobserveConfig()` is called", ->
expect(observeHandler).toHaveBeenCalledWith(undefined)
observeHandler.reset()
atom.config.set("foo.bar", "hello")
expect(observeHandler).toHaveBeenCalledWith("hello", previous: undefined)
observeHandler.reset()
view.unobserveConfig()
atom.config.set("foo.bar", "goodbye")
expect(observeHandler).not.toHaveBeenCalled()
it "unobserves when the view is removed", ->
observeHandler.reset()
parent.remove()
atom.config.set("foo.bar", "hello")
expect(observeHandler).not.toHaveBeenCalled()
describe "View.subscribe(eventEmitter, eventName, callback)", ->
[emitter, eventHandler] = []

View File

@@ -95,9 +95,9 @@ beforeEach ->
TokenizedBuffer.prototype.chunkSize = Infinity
spyOn(TokenizedBuffer.prototype, "tokenizeInBackground").andCallFake -> @tokenizeNextChunk()
pasteboardContent = 'initial pasteboard content'
spyOn(clipboard, 'writeText').andCallFake (text) -> pasteboardContent = text
spyOn(clipboard, 'readText').andCallFake -> pasteboardContent
clipboardContent = 'initial clipboard content'
spyOn(clipboard, 'writeText').andCallFake (text) -> clipboardContent = text
spyOn(clipboard, 'readText').andCallFake -> clipboardContent
addCustomMatchers(this)
@@ -159,6 +159,16 @@ addCustomMatchers = (spec) ->
@message = -> return "Expected path '" + @actual + "'" + notText + " to exist."
fs.existsSync(@actual)
toHaveFocus: ->
notText = this.isNot and " not" or ""
if not document.hasFocus()
console.error "Specs will fail because the Dev Tools have focus. To fix this close the Dev Tools or click the spec runner."
@message = -> return "Expected element '" + @actual + "' or its descendants" + notText + " to have focus."
element = @actual
element = element.get(0) if element.jquery
element.webkitMatchesSelector(":focus") or element.querySelector(":focus")
window.keyIdentifierForKey = (key) ->
if key.length > 1 # named key
key

View File

@@ -4,10 +4,18 @@ temp = require 'temp'
describe "the `syntax` global", ->
beforeEach ->
atom.packages.activatePackage('language-text', sync: true)
atom.packages.activatePackage('language-javascript', sync: true)
atom.packages.activatePackage('language-coffee-script', sync: true)
atom.packages.activatePackage('language-ruby', sync: true)
waitsForPromise ->
atom.packages.activatePackage('language-text')
waitsForPromise ->
atom.packages.activatePackage('language-javascript')
waitsForPromise ->
atom.packages.activatePackage('language-coffee-script')
waitsForPromise ->
atom.packages.activatePackage('language-ruby')
describe "serialization", ->
it "remembers grammar overrides by path", ->
@@ -20,29 +28,33 @@ describe "the `syntax` global", ->
describe ".selectGrammar(filePath)", ->
it "can use the filePath to load the correct grammar based on the grammar's filetype", ->
atom.packages.activatePackage('language-git', sync: true)
waitsForPromise ->
atom.packages.activatePackage('language-git')
expect(atom.syntax.selectGrammar("file.js").name).toBe "JavaScript" # based on extension (.js)
expect(atom.syntax.selectGrammar(path.join(temp.dir, '.git', 'config')).name).toBe "Git Config" # based on end of the path (.git/config)
expect(atom.syntax.selectGrammar("Rakefile").name).toBe "Ruby" # based on the file's basename (Rakefile)
expect(atom.syntax.selectGrammar("curb").name).toBe "Null Grammar"
expect(atom.syntax.selectGrammar("/hu.git/config").name).toBe "Null Grammar"
runs ->
expect(atom.syntax.selectGrammar("file.js").name).toBe "JavaScript" # based on extension (.js)
expect(atom.syntax.selectGrammar(path.join(temp.dir, '.git', 'config')).name).toBe "Git Config" # based on end of the path (.git/config)
expect(atom.syntax.selectGrammar("Rakefile").name).toBe "Ruby" # based on the file's basename (Rakefile)
expect(atom.syntax.selectGrammar("curb").name).toBe "Null Grammar"
expect(atom.syntax.selectGrammar("/hu.git/config").name).toBe "Null Grammar"
it "uses the filePath's shebang line if the grammar cannot be determined by the extension or basename", ->
filePath = require.resolve("./fixtures/shebang")
expect(atom.syntax.selectGrammar(filePath).name).toBe "Ruby"
it "uses the number of newlines in the first line regex to determine the number of lines to test against", ->
atom.packages.activatePackage('language-property-list', sync: true)
waitsForPromise ->
atom.packages.activatePackage('language-property-list')
fileContent = "first-line\n<html>"
expect(atom.syntax.selectGrammar("dummy.coffee", fileContent).name).toBe "CoffeeScript"
runs ->
fileContent = "first-line\n<html>"
expect(atom.syntax.selectGrammar("dummy.coffee", fileContent).name).toBe "CoffeeScript"
fileContent = '<?xml version="1.0" encoding="UTF-8"?>'
expect(atom.syntax.selectGrammar("grammar.tmLanguage", fileContent).name).toBe "Null Grammar"
fileContent = '<?xml version="1.0" encoding="UTF-8"?>'
expect(atom.syntax.selectGrammar("grammar.tmLanguage", fileContent).name).toBe "Null Grammar"
fileContent += '\n<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">'
expect(atom.syntax.selectGrammar("grammar.tmLanguage", fileContent).name).toBe "Property List (XML)"
fileContent += '\n<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">'
expect(atom.syntax.selectGrammar("grammar.tmLanguage", fileContent).name).toBe "Property List (XML)"
it "doesn't read the file when the file contents are specified", ->
filePath = require.resolve("./fixtures/shebang")

View File

@@ -571,6 +571,23 @@ describe 'TextBuffer', ->
saveBuffer.reload()
expect(events).toEqual ['will-reload', 'reloaded']
it "no longer reports being in conflict", ->
saveBuffer.setText('a')
saveBuffer.save()
saveBuffer.setText('ab')
fs.writeFileSync(saveBuffer.getPath(), 'c')
conflictHandler = jasmine.createSpy('conflictHandler')
saveBuffer.on 'contents-conflicted', conflictHandler
waitsFor ->
conflictHandler.callCount > 0
runs ->
expect(saveBuffer.isInConflict()).toBe true
saveBuffer.save()
expect(saveBuffer.isInConflict()).toBe false
describe "when the buffer has no path", ->
it "throws an exception", ->
saveBuffer = atom.project.bufferForPathSync(null)

View File

@@ -26,11 +26,14 @@ describe "ThemeManager", ->
expect(themes.length).toBeGreaterThan(2)
it 'getActiveThemes get all the active themes', ->
themeManager.activateThemes()
names = atom.config.get('core.themes')
expect(names.length).toBeGreaterThan(0)
themes = themeManager.getActiveThemes()
expect(themes).toHaveLength(names.length)
waitsForPromise ->
themeManager.activateThemes()
runs ->
names = atom.config.get('core.themes')
expect(names.length).toBeGreaterThan(0)
themes = themeManager.getActiveThemes()
expect(themes).toHaveLength(names.length)
describe "getImportPaths()", ->
it "returns the theme directories before the themes are loaded", ->
@@ -51,29 +54,58 @@ describe "ThemeManager", ->
it "add/removes stylesheets to reflect the new config value", ->
themeManager.on 'reloaded', reloadHandler = jasmine.createSpy()
spyOn(themeManager, 'getUserStylesheetPath').andCallFake -> null
themeManager.activateThemes()
atom.config.set('core.themes', [])
expect($('style.theme').length).toBe 0
expect(reloadHandler).toHaveBeenCalled()
waitsForPromise ->
themeManager.activateThemes()
atom.config.set('core.themes', ['atom-dark-syntax'])
expect($('style.theme').length).toBe 1
expect($('style.theme:eq(0)').attr('id')).toMatch /atom-dark-syntax/
runs ->
reloadHandler.reset()
atom.config.set('core.themes', [])
atom.config.set('core.themes', ['atom-light-syntax', 'atom-dark-syntax'])
expect($('style.theme').length).toBe 2
expect($('style.theme:eq(0)').attr('id')).toMatch /atom-dark-syntax/
expect($('style.theme:eq(1)').attr('id')).toMatch /atom-light-syntax/
waitsFor ->
reloadHandler.callCount == 1
atom.config.set('core.themes', [])
expect($('style.theme').length).toBe 0
runs ->
reloadHandler.reset()
expect($('style.theme')).toHaveLength 0
atom.config.set('core.themes', ['atom-dark-syntax'])
# atom-dark-ui has an directory path, the syntax one doesn't
atom.config.set('core.themes', ['theme-with-index-less', 'atom-dark-ui'])
importPaths = themeManager.getImportPaths()
expect(importPaths.length).toBe 1
expect(importPaths[0]).toContain 'atom-dark-ui'
waitsFor ->
reloadHandler.callCount == 1
runs ->
reloadHandler.reset()
expect($('style.theme')).toHaveLength 1
expect($('style.theme:eq(0)').attr('id')).toMatch /atom-dark-syntax/
atom.config.set('core.themes', ['atom-light-syntax', 'atom-dark-syntax'])
waitsFor ->
reloadHandler.callCount == 1
runs ->
reloadHandler.reset()
expect($('style.theme')).toHaveLength 2
expect($('style.theme:eq(0)').attr('id')).toMatch /atom-dark-syntax/
expect($('style.theme:eq(1)').attr('id')).toMatch /atom-light-syntax/
atom.config.set('core.themes', [])
waitsFor ->
reloadHandler.callCount == 1
runs ->
reloadHandler.reset()
expect($('style.theme')).toHaveLength 0
# atom-dark-ui has an directory path, the syntax one doesn't
atom.config.set('core.themes', ['theme-with-index-less', 'atom-dark-ui'])
waitsFor ->
reloadHandler.callCount == 1
runs ->
expect($('style.theme')).toHaveLength 2
importPaths = themeManager.getImportPaths()
expect(importPaths.length).toBe 1
expect(importPaths[0]).toContain 'atom-dark-ui'
describe "when a theme fails to load", ->
it "logs a warning", ->
@@ -145,18 +177,25 @@ describe "ThemeManager", ->
atom.workspaceView = new WorkspaceView
atom.workspaceView.append $$ -> @div class: 'editor'
atom.workspaceView.attachToDom()
themeManager.activateThemes()
waitsForPromise ->
themeManager.activateThemes()
it "loads the correct values from the theme's ui-variables file", ->
themeManager.on 'reloaded', reloadHandler = jasmine.createSpy()
atom.config.set('core.themes', ['theme-with-ui-variables'])
# an override loaded in the base css
expect(atom.workspaceView.css("background-color")).toBe "rgb(0, 0, 255)"
waitsFor ->
reloadHandler.callCount > 0
# from within the theme itself
expect($(".editor").css("padding-top")).toBe "150px"
expect($(".editor").css("padding-right")).toBe "150px"
expect($(".editor").css("padding-bottom")).toBe "150px"
runs ->
# an override loaded in the base css
expect(atom.workspaceView.css("background-color")).toBe "rgb(0, 0, 255)"
# from within the theme itself
expect($(".editor").css("padding-top")).toBe "150px"
expect($(".editor").css("padding-right")).toBe "150px"
expect($(".editor").css("padding-bottom")).toBe "150px"
describe "when the user stylesheet changes", ->
it "reloads it", ->
@@ -164,12 +203,14 @@ describe "ThemeManager", ->
fs.writeFileSync(userStylesheetPath, 'body {border-style: dotted !important;}')
spyOn(themeManager, 'getUserStylesheetPath').andReturn userStylesheetPath
themeManager.activateThemes()
expect($(document.body).css('border-style')).toBe 'dotted'
spyOn(themeManager, 'loadUserStylesheet').andCallThrough()
waitsForPromise ->
themeManager.activateThemes()
fs.writeFileSync(userStylesheetPath, 'body {border-style: dashed}')
runs ->
expect($(document.body).css('border-style')).toBe 'dotted'
spyOn(themeManager, 'loadUserStylesheet').andCallThrough()
fs.writeFileSync(userStylesheetPath, 'body {border-style: dashed}')
waitsFor ->
themeManager.loadUserStylesheet.callCount is 1

View File

@@ -5,11 +5,13 @@ describe "TokenizedBuffer", ->
[tokenizedBuffer, buffer, changeHandler] = []
beforeEach ->
atom.packages.activatePackage('language-javascript', sync: true)
# enable async tokenization
TokenizedBuffer.prototype.chunkSize = 5
jasmine.unspy(TokenizedBuffer.prototype, 'tokenizeInBackground')
waitsForPromise ->
atom.packages.activatePackage('language-javascript')
startTokenizing = (tokenizedBuffer) ->
tokenizedBuffer.setVisible(true)
@@ -311,10 +313,13 @@ describe "TokenizedBuffer", ->
describe "when the buffer contains hard-tabs", ->
beforeEach ->
atom.packages.activatePackage('language-coffee-script', sync: true)
buffer = atom.project.bufferForPathSync('sample-with-tabs.coffee')
tokenizedBuffer = new TokenizedBuffer({buffer})
startTokenizing(tokenizedBuffer)
waitsForPromise ->
atom.packages.activatePackage('language-coffee-script')
runs ->
buffer = atom.project.bufferForPathSync('sample-with-tabs.coffee')
tokenizedBuffer = new TokenizedBuffer({buffer})
startTokenizing(tokenizedBuffer)
afterEach ->
tokenizedBuffer.destroy()
@@ -341,14 +346,17 @@ describe "TokenizedBuffer", ->
describe "when the buffer contains surrogate pairs", ->
beforeEach ->
atom.packages.activatePackage('language-javascript', sync: true)
buffer = atom.project.bufferForPathSync 'sample-with-pairs.js'
buffer.setText """
'abc\uD835\uDF97def'
//\uD835\uDF97xyz
"""
tokenizedBuffer = new TokenizedBuffer({buffer})
fullyTokenize(tokenizedBuffer)
waitsForPromise ->
atom.packages.activatePackage('language-javascript')
runs ->
buffer = atom.project.bufferForPathSync 'sample-with-pairs.js'
buffer.setText """
'abc\uD835\uDF97def'
//\uD835\uDF97xyz
"""
tokenizedBuffer = new TokenizedBuffer({buffer})
fullyTokenize(tokenizedBuffer)
afterEach ->
tokenizedBuffer.destroy()
@@ -379,22 +387,30 @@ describe "TokenizedBuffer", ->
describe "when the grammar is updated because a grammar it includes is activated", ->
it "retokenizes the buffer", ->
atom.packages.activatePackage('language-ruby-on-rails', sync: true)
atom.packages.activatePackage('language-ruby', sync: true)
buffer = atom.project.bufferForPathSync()
buffer.setText "<div class='name'><%= User.find(2).full_name %></div>"
tokenizedBuffer = new TokenizedBuffer({buffer})
tokenizedBuffer.setGrammar(atom.syntax.selectGrammar('test.erb'))
fullyTokenize(tokenizedBuffer)
waitsForPromise ->
atom.packages.activatePackage('language-ruby-on-rails')
{tokens} = tokenizedBuffer.lineForScreenRow(0)
expect(tokens[0]).toEqual value: "<div class='name'>", scopes: ["text.html.ruby"]
waitsForPromise ->
atom.packages.activatePackage('language-ruby')
atom.packages.activatePackage('language-html', sync: true)
fullyTokenize(tokenizedBuffer)
{tokens} = tokenizedBuffer.lineForScreenRow(0)
expect(tokens[0]).toEqual value: '<', scopes: ["text.html.ruby","meta.tag.block.any.html","punctuation.definition.tag.begin.html"]
runs ->
buffer = atom.project.bufferForPathSync()
buffer.setText "<div class='name'><%= User.find(2).full_name %></div>"
tokenizedBuffer = new TokenizedBuffer({buffer})
tokenizedBuffer.setGrammar(atom.syntax.selectGrammar('test.erb'))
fullyTokenize(tokenizedBuffer)
{tokens} = tokenizedBuffer.lineForScreenRow(0)
expect(tokens[0]).toEqual value: "<div class='name'>", scopes: ["text.html.ruby"]
waitsForPromise ->
atom.packages.activatePackage('language-html')
runs ->
fullyTokenize(tokenizedBuffer)
{tokens} = tokenizedBuffer.lineForScreenRow(0)
expect(tokens[0]).toEqual value: '<', scopes: ["text.html.ruby","meta.tag.block.any.html","punctuation.definition.tag.begin.html"]
describe ".tokenForPosition(position)", ->
afterEach ->

View File

@@ -7,49 +7,141 @@ describe "Workspace", ->
atom.project.setPath(atom.project.resolve('dir'))
workspace = new Workspace
describe "::open(uri)", ->
describe "::open(uri, options)", ->
beforeEach ->
spyOn(workspace.activePane, 'activate')
describe "when called without a uri", ->
it "adds and activates an empty editor on the active pane", ->
editor = null
waitsForPromise ->
workspace.open().then (o) -> editor = o
runs ->
expect(editor.getPath()).toBeUndefined()
expect(workspace.activePane.items).toEqual [editor]
expect(workspace.activePaneItem).toBe editor
expect(workspace.activePane.activate).toHaveBeenCalled()
describe "when called with a uri", ->
describe "when the active pane already has an editor for the given uri", ->
it "activates the existing editor on the active pane", ->
editor1 = workspace.openSync('a')
editor2 = workspace.openSync('b')
spyOn(workspace.activePane, 'activate').andCallThrough()
describe "when the 'searchAllPanes' option is false (default)", ->
describe "when called without a uri", ->
it "adds and activates an empty editor on the active pane", ->
editor = null
waitsForPromise ->
workspace.open('a').then (o) -> editor = o
workspace.open().then (o) -> editor = o
runs ->
expect(editor).toBe editor1
expect(workspace.activePaneItem).toBe editor
expect(workspace.activePane.activate).toHaveBeenCalled()
describe "when the active pane does not have an editor for the given uri", ->
it "adds and activates a new editor for the given path on the active pane", ->
editor = null
waitsForPromise ->
workspace.open('a').then (o) -> editor = o
runs ->
expect(editor.getUri()).toBe 'a'
expect(workspace.activePaneItem).toBe editor
expect(editor.getPath()).toBeUndefined()
expect(workspace.activePane.items).toEqual [editor]
expect(workspace.activePaneItem).toBe editor
expect(workspace.activePane.activate).toHaveBeenCalled()
describe "when called with a uri", ->
describe "when the active pane already has an editor for the given uri", ->
it "activates the existing editor on the active pane", ->
editor1 = workspace.openSync('a')
editor2 = workspace.openSync('b')
editor = null
waitsForPromise ->
workspace.open('a').then (o) -> editor = o
runs ->
expect(editor).toBe editor1
expect(workspace.activePaneItem).toBe editor
expect(workspace.activePane.activate).toHaveBeenCalled()
describe "when the active pane does not have an editor for the given uri", ->
it "adds and activates a new editor for the given path on the active pane", ->
editor = null
waitsForPromise ->
workspace.open('a').then (o) -> editor = o
runs ->
expect(editor.getUri()).toBe 'a'
expect(workspace.activePaneItem).toBe editor
expect(workspace.activePane.items).toEqual [editor]
expect(workspace.activePane.activate).toHaveBeenCalled()
describe "when the 'searchAllPanes' option is true", ->
describe "when an editor for the given uri is already open on an inactive pane", ->
it "activates the existing editor on the inactive pane, then activates that pane", ->
editor1 = workspace.openSync('a')
pane1 = workspace.activePane
pane2 = workspace.activePane.splitRight()
editor2 = workspace.openSync('b')
expect(workspace.activePaneItem).toBe editor2
waitsForPromise ->
workspace.open('a', searchAllPanes: true)
runs ->
expect(workspace.activePane).toBe pane1
expect(workspace.activePaneItem).toBe editor1
describe "when no editor for the given uri is open in any pane", ->
it "opens an editor for the given uri in the active pane", ->
editor = null
waitsForPromise ->
workspace.open('a', searchAllPanes: true).then (o) -> editor = o
runs ->
expect(workspace.activePaneItem).toBe editor
describe "when the 'split' option is set", ->
describe "when the 'split' option is 'left'", ->
it "opens the editor in the leftmost pane of the current pane axis", ->
pane1 = workspace.activePane
pane2 = pane1.splitRight()
expect(workspace.activePane).toBe pane2
editor = null
waitsForPromise ->
workspace.open('a', split: 'left').then (o) -> editor = o
runs ->
expect(workspace.activePane).toBe pane1
expect(pane1.items).toEqual [editor]
expect(pane2.items).toEqual []
# Focus right pane and reopen the file on the left
waitsForPromise ->
pane2.focus()
workspace.open('a', split: 'left').then (o) -> editor = o
runs ->
expect(workspace.activePane).toBe pane1
expect(pane1.items).toEqual [editor]
expect(pane2.items).toEqual []
describe "when the 'split' option is 'right'", ->
it "opens the editor in the rightmost pane of the current pane axis", ->
editor = null
pane1 = workspace.activePane
pane2 = null
waitsForPromise ->
workspace.open('a', split: 'right').then (o) -> editor = o
runs ->
pane2 = workspace.getPanes().filter((p) -> p != pane1)[0]
expect(workspace.activePane).toBe pane2
expect(pane1.items).toEqual []
expect(pane2.items).toEqual [editor]
# Focus right pane and reopen the file on the right
waitsForPromise ->
pane1.focus()
workspace.open('a', split: 'right').then (o) -> editor = o
runs ->
expect(workspace.activePane).toBe pane2
expect(pane1.items).toEqual []
expect(pane2.items).toEqual [editor]
describe "when passed a path that matches a custom opener", ->
it "returns the resource returned by the custom opener", ->
fooOpener = (pathToOpen, options) -> { foo: pathToOpen, options } if pathToOpen?.match(/\.foo/)
barOpener = (pathToOpen) -> { bar: pathToOpen } if pathToOpen?.match(/^bar:\/\//)
workspace.registerOpener(fooOpener)
workspace.registerOpener(barOpener)
waitsForPromise ->
pathToOpen = atom.project.resolve('a.foo')
workspace.open(pathToOpen, hey: "there").then (item) ->
expect(item).toEqual { foo: pathToOpen, options: {hey: "there"} }
waitsForPromise ->
workspace.open("bar://baz").then (item) ->
expect(item).toEqual { bar: "bar://baz" }
describe "::openSync(uri, options)", ->
[activePane, initialItemCount] = []
@@ -92,61 +184,6 @@ describe "Workspace", ->
workspace.openSync('b', activatePane: false)
expect(activePane.activate).not.toHaveBeenCalled()
describe "::openSingletonSync(uri, options)", ->
describe "when an editor for the given uri is already open on the active pane", ->
it "activates the existing editor", ->
editor1 = workspace.openSync('a')
editor2 = workspace.openSync('b')
expect(workspace.activePaneItem).toBe editor2
workspace.openSingletonSync('a')
expect(workspace.activePaneItem).toBe editor1
describe "when an editor for the given uri is already open on an inactive pane", ->
it "activates the existing editor on the inactive pane, then activates that pane", ->
editor1 = workspace.openSync('a')
pane1 = workspace.activePane
pane2 = workspace.activePane.splitRight()
editor2 = workspace.openSync('b')
expect(workspace.activePaneItem).toBe editor2
workspace.openSingletonSync('a')
expect(workspace.activePane).toBe pane1
expect(workspace.activePaneItem).toBe editor1
describe "when no editor for the given uri is open in any pane", ->
it "opens an editor for the given uri in the active pane", ->
editor1 = workspace.openSingletonSync('a')
expect(workspace.activePaneItem).toBe editor1
describe "when the 'split' option is 'left'", ->
it "opens the editor in the leftmost pane of the current pane axis", ->
pane1 = workspace.activePane
pane2 = pane1.splitRight()
expect(workspace.activePane).toBe pane2
editor1 = workspace.openSingletonSync('a', split: 'left')
expect(workspace.activePane).toBe pane1
expect(pane1.items).toEqual [editor1]
expect(pane2.items).toEqual []
describe "when the 'split' option is 'right'", ->
describe "when the active pane is in a horizontal pane axis", ->
it "activates the editor on the rightmost pane of the current pane axis", ->
pane1 = workspace.activePane
pane2 = pane1.splitRight()
pane1.activate()
editor1 = workspace.openSingletonSync('a', split: 'right')
expect(workspace.activePane).toBe pane2
expect(pane2.items).toEqual [editor1]
expect(pane1.items).toEqual []
describe "when the active pane is not in a horizontal pane axis", ->
it "splits the current pane to the right, then activates the editor on the right pane", ->
pane1 = workspace.activePane
editor1 = workspace.openSingletonSync('a', split: 'right')
pane2 = workspace.activePane
expect(workspace.paneContainer.root.children).toEqual [pane1, pane2]
expect(pane2.items).toEqual [editor1]
expect(pane1.items).toEqual []
describe "::reopenItemSync()", ->
it "opens the uri associated with the last closed pane that isn't currently open", ->
pane = workspace.activePane