Merge branch 'master' into wl-electron-35

This commit is contained in:
Cheng Zhao
2015-12-11 09:32:32 +08:00
59 changed files with 1080 additions and 554 deletions

View File

@@ -81,6 +81,27 @@ describe 'CompileCache', ->
waits(1)
runs ->
error = new Error("Oops again")
console.log error.stack
expect(error.stack).toContain('compile-cache-spec.coffee')
expect(Array.isArray(error.getRawStack())).toBe true
it 'does not infinitely loop when the original prepareStackTrace value is reassigned', ->
originalPrepareStackTrace = Error.prepareStackTrace
Error.prepareStackTrace = -> 'a-stack-trace'
Error.prepareStackTrace = originalPrepareStackTrace
error = new Error('Oops')
expect(error.stack).toContain('compile-cache-spec.coffee')
expect(Array.isArray(error.getRawStack())).toBe true
it 'does not infinitely loop when the assigned prepareStackTrace calls the original prepareStackTrace', ->
originalPrepareStackTrace = Error.prepareStackTrace
Error.prepareStackTrace = (error, stack) ->
error.foo = 'bar'
originalPrepareStackTrace(error, stack)
error = new Error('Oops')
expect(error.stack).toContain('compile-cache-spec.coffee')
expect(error.foo).toBe('bar')
expect(Array.isArray(error.getRawStack())).toBe true

View File

@@ -679,6 +679,26 @@ describe "Config", ->
writtenConfig = CSON.writeFileSync.argsForCall[0][1]
expect(writtenConfig).toEqual '*': atom.config.settings
it 'writes properties in alphabetical order', ->
atom.config.set('foo', 1)
atom.config.set('bar', 2)
atom.config.set('baz.foo', 3)
atom.config.set('baz.bar', 4)
CSON.writeFileSync.reset()
atom.config.save()
expect(CSON.writeFileSync.argsForCall[0][0]).toBe atom.config.configFilePath
writtenConfig = CSON.writeFileSync.argsForCall[0][1]
expect(writtenConfig).toEqual '*': atom.config.settings
expectedKeys = ['bar', 'baz', 'foo']
foundKeys = (key for key of writtenConfig['*'] when key in expectedKeys)
expect(foundKeys).toEqual expectedKeys
expectedKeys = ['bar', 'foo']
foundKeys = (key for key of writtenConfig['*']['baz'] when key in expectedKeys)
expect(foundKeys).toEqual expectedKeys
describe "when ~/.atom/config.json doesn't exist", ->
it "writes any non-default properties to ~/.atom/config.cson", ->
atom.config.set("a.b.c", 1)

View File

@@ -2,13 +2,9 @@
module.exports =
class FakeLinesYardstick
constructor: (@model, @presenter) ->
constructor: (@model) ->
@characterWidthsByScope = {}
prepareScreenRowsForMeasurement: ->
@presenter.getPreMeasurementState()
@screenRows = new Set(@presenter.getScreenRows())
getScopedCharacterWidth: (scopeNames, char) ->
@getScopedCharacterWidths(scopeNames)[char]
@@ -35,8 +31,6 @@ class FakeLinesYardstick
left = 0
column = 0
return {top, left: 0} unless @screenRows.has(screenPosition.row)
iterator = @model.tokenizedLineForScreenRow(targetRow).getTokenIterator()
while iterator.next()
characterWidths = @getScopedCharacterWidths(iterator.getScopes())
@@ -59,18 +53,3 @@ class FakeLinesYardstick
column += charLength
{top, left}
pixelRectForScreenRange: (screenRange) ->
lineHeight = @model.getLineHeightInPixels()
if screenRange.end.row > screenRange.start.row
top = @pixelPositionForScreenPosition(screenRange.start).top
left = 0
height = (screenRange.end.row - screenRange.start.row + 1) * lineHeight
width = @presenter.getScrollWidth()
else
{top, left} = @pixelPositionForScreenPosition(screenRange.start, false)
height = lineHeight
width = @pixelPositionForScreenPosition(screenRange.end, false).left - left
{top, left, width, height}

View File

@@ -0,0 +1,6 @@
module.exports = function (state) {
return {
wasDeserializedBy: 'Deserializer1',
state: state
}
}

View File

@@ -0,0 +1,6 @@
module.exports = function (state) {
return {
wasDeserializedBy: 'Deserializer2',
state: state
}
}

View File

@@ -0,0 +1,3 @@
module.exports = {
activate: function() {}
}

View File

@@ -0,0 +1,9 @@
{
"name": "package-with-deserializers",
"version": "1.0.0",
"main": "./index",
"deserializers": {
"Deserializer1": "./deserializer-1.js",
"Deserializer2": "./deserializer-2.js"
}
}

View File

@@ -0,0 +1,5 @@
atom.deserializers.add('MyDeserializer', function (state) {
return {state: state, a: 'b'}
})
exports.activate = function () {}

View File

@@ -0,0 +1,5 @@
{
"name": "package-with-eval-time-api-calls",
"version": "1.2.3",
"main": "./index"
}

View File

@@ -0,0 +1,13 @@
{
"name": "package-with-json-config-schema",
"configSchema": {
"a": {
"type": "number",
"default": 5
},
"b": {
"type": "string",
"default": "five"
}
}
}

View File

@@ -1 +1,2 @@
'main': 'main-module.coffee'
'version': '2.3.4'

View File

@@ -0,0 +1,3 @@
module.exports = function (state) {
return {state: state}
}

View File

@@ -0,0 +1,3 @@
module.exports = {
activate: function() {}
}

View File

@@ -0,0 +1,12 @@
{
"name": "package-with-view-providers",
"main": "./index",
"version": "1.0.0",
"deserializers": {
"DeserializerFromPackageWithViewProviders": "./deserializer"
},
"viewProviders": [
"./view-provider-1",
"./view-provider-2"
]
}

View File

@@ -0,0 +1,9 @@
'use strict'
module.exports = function (model) {
if (model.worksWithViewProvider1) {
let element = document.createElement('div')
element.dataset['createdBy'] = 'view-provider-1'
return element
}
}

View File

@@ -0,0 +1,9 @@
'use strict'
module.exports = function (model) {
if (model.worksWithViewProvider2) {
let element = document.createElement('div')
element.dataset['createdBy'] = 'view-provider-2'
return element
}
}

View File

@@ -2,7 +2,7 @@ LinesYardstick = require "../src/lines-yardstick"
{toArray} = require 'underscore-plus'
describe "LinesYardstick", ->
[editor, mockPresenter, mockLineNodesProvider, createdLineNodes, linesYardstick, buildLineNode] = []
[editor, mockLineNodesProvider, createdLineNodes, linesYardstick, buildLineNode] = []
beforeEach ->
waitsForPromise ->
@@ -31,22 +31,10 @@ describe "LinesYardstick", ->
createdLineNodes.push(lineNode)
lineNode
mockPresenter =
setScreenRowsToMeasure: (screenRows) -> screenRowsToMeasure = screenRows
clearScreenRowsToMeasure: -> setScreenRowsToMeasure = []
getPreMeasurementState: ->
state = {}
for screenRow in screenRowsToMeasure
tokenizedLine = editor.tokenizedLineForScreenRow(screenRow)
state[tokenizedLine.id] = screenRow
state
mockLineNodesProvider =
updateSync: (state) -> availableScreenRows = state
lineNodeForLineIdAndScreenRow: (lineId, screenRow) ->
return if availableScreenRows[lineId] isnt screenRow
buildLineNode(screenRow)
textNodesForLineIdAndScreenRow: (lineId, screenRow) ->
lineNode = @lineNodeForLineIdAndScreenRow(lineId, screenRow)
iterator = document.createNodeIterator(lineNode, NodeFilter.SHOW_TEXT)
@@ -56,7 +44,7 @@ describe "LinesYardstick", ->
textNodes
editor.setLineHeightInPixels(14)
linesYardstick = new LinesYardstick(editor, mockPresenter, mockLineNodesProvider, atom.grammars)
linesYardstick = new LinesYardstick(editor, mockLineNodesProvider, atom.grammars)
afterEach ->
lineNode.remove() for lineNode in createdLineNodes
@@ -153,18 +141,6 @@ describe "LinesYardstick", ->
expect(linesYardstick.pixelPositionForScreenPosition([0, 36]).left).toBe 237.5
expect(linesYardstick.pixelPositionForScreenPosition([0, 37]).left).toBe 244.09375
it "doesn't measure invisible lines if it is explicitly told so", ->
atom.styles.addStyleSheet """
* {
font-size: 12px;
font-family: monospace;
}
"""
expect(linesYardstick.pixelPositionForScreenPosition([0, 0], true, true)).toEqual({left: 0, top: 0})
expect(linesYardstick.pixelPositionForScreenPosition([0, 1], true, true)).toEqual({left: 0, top: 0})
expect(linesYardstick.pixelPositionForScreenPosition([0, 5], true, true)).toEqual({left: 0, top: 0})
describe "::screenPositionForPixelPosition(pixelPosition)", ->
it "converts pixel positions to screen positions", ->
atom.styles.addStyleSheet """
@@ -197,15 +173,3 @@ describe "LinesYardstick", ->
expect(linesYardstick.screenPositionForPixelPosition(top: Infinity, left: Infinity)).toEqual [12, 2]
expect(linesYardstick.screenPositionForPixelPosition(top: (editor.getLastScreenRow() + 1) * 14, left: 0)).toEqual [12, 2]
expect(linesYardstick.screenPositionForPixelPosition(top: editor.getLastScreenRow() * 14, left: 0)).toEqual [12, 0]
it "doesn't measure invisible lines if it is explicitly told so", ->
atom.styles.addStyleSheet """
* {
font-size: 12px;
font-family: monospace;
}
"""
expect(linesYardstick.screenPositionForPixelPosition({top: 0, left: 13}, true)).toEqual([0, 0])
expect(linesYardstick.screenPositionForPixelPosition({top: 14, left: 20}, true)).toEqual([1, 0])
expect(linesYardstick.screenPositionForPixelPosition({top: 28, left: 100}, true)).toEqual([2, 0])

View File

@@ -1,6 +1,10 @@
path = require 'path'
Package = require '../src/package'
temp = require 'temp'
fs = require 'fs-plus'
{Disposable} = require 'atom'
{buildKeydownEvent} = require '../src/keymap-extensions'
{mockLocalStorage} = require './spec-helper'
describe "PackageManager", ->
workspaceElement = null
@@ -79,6 +83,121 @@ describe "PackageManager", ->
expect(loadedPackage.name).toBe "package-with-main"
it "registers any deserializers specified in the package's package.json", ->
pack = atom.packages.loadPackage("package-with-deserializers")
state1 = {deserializer: 'Deserializer1', a: 'b'}
expect(atom.deserializers.deserialize(state1)).toEqual {
wasDeserializedBy: 'Deserializer1'
state: state1
}
state2 = {deserializer: 'Deserializer2', c: 'd'}
expect(atom.deserializers.deserialize(state2)).toEqual {
wasDeserializedBy: 'Deserializer2'
state: state2
}
expect(pack.mainModule).toBeNull()
describe "when there are view providers specified in the package's package.json", ->
model1 = {worksWithViewProvider1: true}
model2 = {worksWithViewProvider2: true}
afterEach ->
atom.packages.deactivatePackage('package-with-view-providers')
atom.packages.unloadPackage('package-with-view-providers')
it "does not load the view providers immediately", ->
pack = atom.packages.loadPackage("package-with-view-providers")
expect(pack.mainModule).toBeNull()
expect(-> atom.views.getView(model1)).toThrow()
expect(-> atom.views.getView(model2)).toThrow()
it "registers the view providers when the package is activated", ->
pack = atom.packages.loadPackage("package-with-view-providers")
waitsForPromise ->
atom.packages.activatePackage("package-with-view-providers").then ->
element1 = atom.views.getView(model1)
expect(element1 instanceof HTMLDivElement).toBe true
expect(element1.dataset.createdBy).toBe 'view-provider-1'
element2 = atom.views.getView(model2)
expect(element2 instanceof HTMLDivElement).toBe true
expect(element2.dataset.createdBy).toBe 'view-provider-2'
it "registers the view providers when any of the package's deserializers are used", ->
pack = atom.packages.loadPackage("package-with-view-providers")
spyOn(atom.views, 'addViewProvider').andCallThrough()
atom.deserializers.deserialize({
deserializer: 'DeserializerFromPackageWithViewProviders',
a: 'b'
})
expect(atom.views.addViewProvider.callCount).toBe 2
atom.deserializers.deserialize({
deserializer: 'DeserializerFromPackageWithViewProviders',
a: 'b'
})
expect(atom.views.addViewProvider.callCount).toBe 2
element1 = atom.views.getView(model1)
expect(element1 instanceof HTMLDivElement).toBe true
expect(element1.dataset.createdBy).toBe 'view-provider-1'
element2 = atom.views.getView(model2)
expect(element2 instanceof HTMLDivElement).toBe true
expect(element2.dataset.createdBy).toBe 'view-provider-2'
it "registers the config schema in the package's metadata, if present", ->
pack = atom.packages.loadPackage("package-with-json-config-schema")
expect(atom.config.getSchema('package-with-json-config-schema')).toEqual {
type: 'object'
properties: {
a: {type: 'number', default: 5}
b: {type: 'string', default: 'five'}
}
}
expect(pack.mainModule).toBeNull()
atom.packages.unloadPackage('package-with-json-config-schema')
atom.config.clear()
pack = atom.packages.loadPackage("package-with-json-config-schema")
expect(atom.config.getSchema('package-with-json-config-schema')).toEqual {
type: 'object'
properties: {
a: {type: 'number', default: 5}
b: {type: 'string', default: 'five'}
}
}
describe "when a package does not have deserializers, view providers or a config schema in its package.json", ->
beforeEach ->
mockLocalStorage()
it "defers loading the package's main module if the package previously used no Atom APIs when its main module was required", ->
pack1 = atom.packages.loadPackage('package-with-main')
expect(pack1.mainModule).toBeDefined()
atom.packages.unloadPackage('package-with-main')
pack2 = atom.packages.loadPackage('package-with-main')
expect(pack2.mainModule).toBeNull()
it "does not defer loading the package's main module if the package previously used Atom APIs when its main module was required", ->
pack1 = atom.packages.loadPackage('package-with-eval-time-api-calls')
expect(pack1.mainModule).toBeDefined()
atom.packages.unloadPackage('package-with-eval-time-api-calls')
pack2 = atom.packages.loadPackage('package-with-eval-time-api-calls')
expect(pack2.mainModule).not.toBeNull()
describe "::unloadPackage(name)", ->
describe "when the package is active", ->
it "throws an error", ->
@@ -456,6 +575,54 @@ describe "PackageManager", ->
atom.config.set("core.packagesWithKeymapsDisabled", [])
expect(atom.keymaps.findKeyBindings(keystrokes: 'ctrl-z', target: element1)[0].command).toBe 'keymap-1'
describe "when the package is de-activated and re-activated", ->
[element, events, userKeymapPath] = []
beforeEach ->
userKeymapPath = path.join(temp.path(), "user-keymaps.cson")
spyOn(atom.keymaps, "getUserKeymapPath").andReturn(userKeymapPath)
element = createTestElement('test-1')
jasmine.attachToDOM(element)
events = []
element.addEventListener 'user-command', (e) -> events.push(e)
element.addEventListener 'test-1', (e) -> events.push(e)
afterEach ->
element.remove()
# Avoid leaking user keymap subscription
atom.keymaps.watchSubscriptions[userKeymapPath].dispose()
delete atom.keymaps.watchSubscriptions[userKeymapPath]
it "doesn't override user-defined keymaps", ->
fs.writeFileSync userKeymapPath, """
".test-1":
"ctrl-z": "user-command"
"""
atom.keymaps.loadUserKeymap()
waitsForPromise ->
atom.packages.activatePackage("package-with-keymaps")
runs ->
atom.keymaps.handleKeyboardEvent(buildKeydownEvent("z", ctrl: true, target: element))
expect(events.length).toBe(1)
expect(events[0].type).toBe("user-command")
atom.packages.deactivatePackage("package-with-keymaps")
waitsForPromise ->
atom.packages.activatePackage("package-with-keymaps")
runs ->
atom.keymaps.handleKeyboardEvent(buildKeydownEvent("z", ctrl: true, target: element))
expect(events.length).toBe(2)
expect(events[1].type).toBe("user-command")
describe "menu loading", ->
beforeEach ->
atom.contextMenu.definitions = []

View File

@@ -1,6 +1,7 @@
path = require 'path'
Package = require '../src/package'
ThemePackage = require '../src/theme-package'
{mockLocalStorage} = require './spec-helper'
describe "Package", ->
build = (constructor, path) ->
@@ -10,6 +11,7 @@ describe "Package", ->
keymapManager: atom.keymaps, commandRegistry: atom.command,
grammarRegistry: atom.grammars, themeManager: atom.themes,
menuManager: atom.menu, contextMenuManager: atom.contextMenu,
deserializerManager: atom.deserializers, viewRegistry: atom.views,
devMode: false
)
@@ -19,10 +21,7 @@ describe "Package", ->
describe "when the package contains incompatible native modules", ->
beforeEach ->
items = {}
spyOn(global.localStorage, 'setItem').andCallFake (key, item) -> items[key] = item; undefined
spyOn(global.localStorage, 'getItem').andCallFake (key) -> items[key] ? null
spyOn(global.localStorage, 'removeItem').andCallFake (key) -> delete items[key]; undefined
mockLocalStorage()
it "does not activate it", ->
packagePath = atom.project.getDirectories()[0]?.resolve('packages/package-with-incompatible-native-module')
@@ -54,10 +53,7 @@ describe "Package", ->
describe "::rebuild()", ->
beforeEach ->
items = {}
spyOn(global.localStorage, 'setItem').andCallFake (key, item) -> items[key] = item; undefined
spyOn(global.localStorage, 'getItem').andCallFake (key) -> items[key] ? null
spyOn(global.localStorage, 'removeItem').andCallFake (key) -> delete items[key]; undefined
mockLocalStorage()
it "returns a promise resolving to the results of `apm rebuild`", ->
packagePath = atom.project.getDirectories()[0]?.resolve('packages/package-with-index')

View File

@@ -265,3 +265,9 @@ window.advanceClock = (delta=1) ->
true
callback() for callback in callbacks
exports.mockLocalStorage = ->
items = {}
spyOn(global.localStorage, 'setItem').andCallFake (key, item) -> items[key] = item.toString(); undefined
spyOn(global.localStorage, 'getItem').andCallFake (key) -> items[key] ? null
spyOn(global.localStorage, 'removeItem').andCallFake (key) -> delete items[key]; undefined

View File

@@ -484,7 +484,7 @@ describe('TextEditorComponent', function () {
it('displays newlines as their own token outside of the other tokens\' scopeDescriptor', async function () {
editor.setText('let\n')
await nextViewUpdatePromise()
expect(component.lineNodeForScreenRow(0).innerHTML).toBe('<span class="source js"><span class="storage modifier js">let</span></span><span class="invisible-character">' + invisibles.eol + '</span>')
expect(component.lineNodeForScreenRow(0).innerHTML).toBe('<span class="source js"><span class="storage type var js">let</span></span><span class="invisible-character">' + invisibles.eol + '</span>')
})
it('displays trailing carriage returns using a visible, non-empty value', async function () {

File diff suppressed because it is too large Load Diff

View File

@@ -22,17 +22,6 @@ describe "TextEditor", ->
atom.packages.activatePackage('language-javascript')
describe "when the editor is deserialized", ->
it "returns undefined when the path cannot be read", ->
pathToOpen = path.join(temp.mkdirSync(), 'file.txt')
editor1 = null
waitsForPromise ->
atom.workspace.open(pathToOpen).then (o) -> editor1 = o
runs ->
fs.mkdirSync(pathToOpen)
expect(TextEditor.deserialize(editor1.serialize(), atom)).toBeUndefined()
it "restores selections and folds based on markers in the buffer", ->
editor.setSelectedBufferRange([[1, 2], [3, 4]])
editor.addSelectionForBufferRange([[5, 6], [7, 5]], reversed: true)
@@ -762,11 +751,24 @@ describe "TextEditor", ->
editor.moveToBeginningOfWord()
expect(editor.getCursorBufferPosition()).toEqual [10, 0]
it "treats lines with only whitespace as a word (CRLF line ending)", ->
editor.buffer.setText(buffer.getText().replace(/\n/g, "\r\n"))
editor.setCursorBufferPosition([11, 0])
editor.moveToBeginningOfWord()
expect(editor.getCursorBufferPosition()).toEqual [10, 0]
it "works when the current line is blank", ->
editor.setCursorBufferPosition([10, 0])
editor.moveToBeginningOfWord()
expect(editor.getCursorBufferPosition()).toEqual [9, 2]
it "works when the current line is blank (CRLF line ending)", ->
editor.buffer.setText(buffer.getText().replace(/\n/g, "\r\n"))
editor.setCursorBufferPosition([10, 0])
editor.moveToBeginningOfWord()
expect(editor.getCursorBufferPosition()).toEqual [9, 2]
editor.buffer.setText(buffer.getText().replace(/\r\n/g, "\n"))
describe ".moveToPreviousWordBoundary()", ->
it "moves the cursor to the previous word boundary", ->
editor.setCursorBufferPosition [0, 8]
@@ -821,11 +823,23 @@ describe "TextEditor", ->
editor.moveToEndOfWord()
expect(editor.getCursorBufferPosition()).toEqual [10, 0]
it "treats lines with only whitespace as a word (CRLF line ending)", ->
editor.buffer.setText(buffer.getText().replace(/\n/g, "\r\n"))
editor.setCursorBufferPosition([9, 4])
editor.moveToEndOfWord()
expect(editor.getCursorBufferPosition()).toEqual [10, 0]
it "works when the current line is blank", ->
editor.setCursorBufferPosition([10, 0])
editor.moveToEndOfWord()
expect(editor.getCursorBufferPosition()).toEqual [11, 8]
it "works when the current line is blank (CRLF line ending)", ->
editor.buffer.setText(buffer.getText().replace(/\n/g, "\r\n"))
editor.setCursorBufferPosition([10, 0])
editor.moveToEndOfWord()
expect(editor.getCursorBufferPosition()).toEqual [11, 8]
describe ".moveToBeginningOfNextWord()", ->
it "moves the cursor before the first character of the next word", ->
editor.setCursorBufferPosition [0, 6]
@@ -1055,8 +1069,36 @@ describe "TextEditor", ->
editor.moveToBeginningOfNextParagraph()
expect(editor.getCursorBufferPosition()).toEqual [0, 0]
it "moves the cursor before the first line of the next paragraph (CRLF line endings)", ->
editor.setText(editor.getText().replace(/\n/g, '\r\n'))
editor.setCursorBufferPosition [0, 6]
editor.foldBufferRow(4)
editor.moveToBeginningOfNextParagraph()
expect(editor.getCursorBufferPosition()).toEqual [10, 0]
editor.setText("")
editor.setCursorBufferPosition [0, 0]
editor.moveToBeginningOfNextParagraph()
expect(editor.getCursorBufferPosition()).toEqual [0, 0]
describe ".moveToBeginningOfPreviousParagraph()", ->
it "moves the cursor before the first line of the pevious paragraph", ->
it "moves the cursor before the first line of the previous paragraph", ->
editor.setCursorBufferPosition [10, 0]
editor.foldBufferRow(4)
editor.moveToBeginningOfPreviousParagraph()
expect(editor.getCursorBufferPosition()).toEqual [0, 0]
editor.setText("")
editor.setCursorBufferPosition [0, 0]
editor.moveToBeginningOfPreviousParagraph()
expect(editor.getCursorBufferPosition()).toEqual [0, 0]
it "moves the cursor before the first line of the previous paragraph (CRLF line endings)", ->
editor.setText(editor.getText().replace(/\n/g, '\r\n'))
editor.setCursorBufferPosition [10, 0]
editor.foldBufferRow(4)
@@ -5337,7 +5379,7 @@ describe "TextEditor", ->
tokens = atom.grammars.decodeTokens(line, tags)
expect(tokens[0].value).toBe "var"
expect(tokens[0].scopes).toEqual ["source.js", "storage.modifier.js"]
expect(tokens[0].scopes).toEqual ["source.js", "storage.type.var.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"]

View File

@@ -24,6 +24,34 @@ describe "TokenizedBuffer", ->
advanceClock() while tokenizedBuffer.firstInvalidRow()?
changeHandler?.reset()
describe "serialization", ->
describe "when the underlying buffer has a path", ->
it "deserializes it searching among the buffers in the current project", ->
buffer = atom.project.bufferForPathSync('sample.js')
tokenizedBufferA = new TokenizedBuffer({
buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages, assert: atom.assert
})
tokenizedBufferB = TokenizedBuffer.deserialize(
JSON.parse(JSON.stringify(tokenizedBufferA.serialize())),
atom
)
expect(tokenizedBufferB.buffer).toBe(tokenizedBufferA.buffer)
describe "when the underlying buffer has no path", ->
it "deserializes it searching among the buffers in the current project", ->
buffer = atom.project.bufferForPathSync(null)
tokenizedBufferA = new TokenizedBuffer({
buffer, config: atom.config, grammarRegistry: atom.grammars, packageManager: atom.packages, assert: atom.assert
})
tokenizedBufferB = TokenizedBuffer.deserialize(
JSON.parse(JSON.stringify(tokenizedBufferA.serialize())),
atom
)
expect(tokenizedBufferB.buffer).toBe(tokenizedBufferA.buffer)
describe "when the buffer is destroyed", ->
beforeEach ->
buffer = atom.project.bufferForPathSync('sample.js')
@@ -198,7 +226,7 @@ describe "TokenizedBuffer", ->
buffer.setTextInRange([[1, 0], [3, 0]], "foo()")
# previous line 0 remains
expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[0]).toEqual(value: 'var', scopes: ['source.js', 'storage.modifier.js'])
expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[0]).toEqual(value: 'var', scopes: ['source.js', 'storage.type.var.js'])
# previous line 3 should be combined with input to form line 1
expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[0]).toEqual(value: 'foo', scopes: ['source.js', 'meta.function-call.js', 'entity.name.function.js'])
@@ -242,7 +270,7 @@ describe "TokenizedBuffer", ->
buffer.setTextInRange([[1, 0], [2, 0]], "foo()\nbar()\nbaz()\nquux()")
# previous line 0 remains
expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[0]).toEqual( value: 'var', scopes: ['source.js', 'storage.modifier.js'])
expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[0]).toEqual( value: 'var', scopes: ['source.js', 'storage.type.var.js'])
# 3 new lines inserted
expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[0]).toEqual(value: 'foo', scopes: ['source.js', 'meta.function-call.js', 'entity.name.function.js'])
@@ -582,7 +610,7 @@ describe "TokenizedBuffer", ->
fullyTokenize(tokenizedBuffer)
expect(tokenizedBuffer.tokenForPosition([1, 0]).scopes).toEqual ["source.js"]
expect(tokenizedBuffer.tokenForPosition([1, 1]).scopes).toEqual ["source.js"]
expect(tokenizedBuffer.tokenForPosition([1, 2]).scopes).toEqual ["source.js", "storage.modifier.js"]
expect(tokenizedBuffer.tokenForPosition([1, 2]).scopes).toEqual ["source.js", "storage.type.var.js"]
describe ".bufferRangeForScopeAtPosition(selector, position)", ->
beforeEach ->
@@ -599,8 +627,8 @@ describe "TokenizedBuffer", ->
describe "when the selector matches a single token at the position", ->
it "returns the range covered by the token", ->
expect(tokenizedBuffer.bufferRangeForScopeAtPosition('.storage.modifier.js', [0, 1])).toEqual [[0, 0], [0, 3]]
expect(tokenizedBuffer.bufferRangeForScopeAtPosition('.storage.modifier.js', [0, 3])).toEqual [[0, 0], [0, 3]]
expect(tokenizedBuffer.bufferRangeForScopeAtPosition('.storage.type.var.js', [0, 1])).toEqual [[0, 0], [0, 3]]
expect(tokenizedBuffer.bufferRangeForScopeAtPosition('.storage.type.var.js', [0, 3])).toEqual [[0, 0], [0, 3]]
describe "when the selector matches a run of multiple tokens at the position", ->
it "returns the range covered by all contigous tokens (within a single line)", ->

View File

@@ -47,6 +47,21 @@ describe "ViewRegistry", ->
expect(view2 instanceof TestView).toBe true
expect(view2.model).toBe subclassModel
describe "when a view provider is registered generically, and works with the object", ->
it "constructs a view element and assigns the model on it", ->
model = {a: 'b'}
registry.addViewProvider (model) ->
if model.a is 'b'
element = document.createElement('div')
element.className = 'test-element'
element
view = registry.getView({a: 'b'})
expect(view.className).toBe 'test-element'
expect(-> registry.getView({a: 'c'})).toThrow()
describe "when no view provider is registered for the object's constructor", ->
it "throws an exception", ->
expect(-> registry.getView(new Object)).toThrow()

View File

@@ -43,6 +43,9 @@ describe "Workspace", ->
pane3 = pane2.splitRight(copyActiveItem: true)
pane4 = null
waitsForPromise ->
atom.workspace.open(null).then (editor) -> editor.setText("An untitled editor.")
waitsForPromise ->
atom.workspace.open('b').then (editor) ->
pane2.activateItem(editor.copy())
@@ -65,18 +68,19 @@ describe "Workspace", ->
simulateReload()
expect(atom.workspace.getTextEditors().length).toBe 4
[editor1, editor2, editor3, editor4] = atom.workspace.getTextEditors()
expect(atom.workspace.getTextEditors().length).toBe 5
[editor1, editor2, untitledEditor, editor3, editor4] = atom.workspace.getTextEditors()
expect(editor1.getPath()).toBe atom.project.getDirectories()[0]?.resolve('b')
expect(editor2.getPath()).toBe atom.project.getDirectories()[0]?.resolve('../sample.txt')
expect(editor2.getCursorScreenPosition()).toEqual [0, 2]
expect(editor3.getPath()).toBe atom.project.getDirectories()[0]?.resolve('b')
expect(editor4.getPath()).toBe atom.project.getDirectories()[0]?.resolve('../sample.js')
expect(editor4.getCursorScreenPosition()).toEqual [2, 4]
expect(untitledEditor.getPath()).toBeUndefined()
expect(untitledEditor.getText()).toBe("An untitled editor.")
expect(atom.workspace.getActiveTextEditor().getPath()).toBe editor3.getPath()
expect(document.title).toBe "#{path.basename(editor3.getLongTitle())} - #{atom.project.getPaths()[0]} - Atom"
expect(document.title).toMatch ///^#{path.basename(editor3.getLongTitle())}\ \u2014\ #{atom.project.getPaths()[0]}///
describe "where there are no open panes or editors", ->
it "constructs the view with no open editors", ->
@@ -661,7 +665,7 @@ describe "Workspace", ->
describe "::isTextEditor(obj)", ->
it "returns true when the passed object is an instance of `TextEditor`", ->
expect(workspace.isTextEditor(atom.workspace.buildTextEditor())).toBe(true)
expect(workspace.isTextEditor({getText: ->})).toBe(false)
expect(workspace.isTextEditor({getText: -> null})).toBe(false)
expect(workspace.isTextEditor(null)).toBe(false)
expect(workspace.isTextEditor(undefined)).toBe(false)
@@ -732,7 +736,7 @@ describe "Workspace", ->
describe "when the project has no path", ->
it "sets the title to 'untitled'", ->
atom.project.setPaths([])
expect(document.title).toBe 'untitled - Atom'
expect(document.title).toMatch ///^untitled///
describe "when the project has a path", ->
beforeEach ->
@@ -742,25 +746,25 @@ describe "Workspace", ->
describe "when there is an active pane item", ->
it "sets the title to the pane item's title plus the project path", ->
item = atom.workspace.getActivePaneItem()
expect(document.title).toBe "#{item.getTitle()} - #{atom.project.getPaths()[0]} - Atom"
expect(document.title).toMatch ///^#{item.getTitle()}\ \u2014\ #{atom.project.getPaths()[0]}///
describe "when the title of the active pane item changes", ->
it "updates the window title based on the item's new title", ->
editor = atom.workspace.getActivePaneItem()
editor.buffer.setPath(path.join(temp.dir, 'hi'))
expect(document.title).toBe "#{editor.getTitle()} - #{atom.project.getPaths()[0]} - Atom"
expect(document.title).toMatch ///^#{editor.getTitle()}\ \u2014\ #{atom.project.getPaths()[0]}///
describe "when the active pane's item changes", ->
it "updates the title to the new item's title plus the project path", ->
atom.workspace.getActivePane().activateNextItem()
item = atom.workspace.getActivePaneItem()
expect(document.title).toBe "#{item.getTitle()} - #{atom.project.getPaths()[0]} - Atom"
expect(document.title).toMatch ///^#{item.getTitle()}\ \u2014\ #{atom.project.getPaths()[0]}///
describe "when the last pane item is removed", ->
it "updates the title to contain the project's path", ->
atom.workspace.getActivePane().destroy()
expect(atom.workspace.getActivePaneItem()).toBeUndefined()
expect(document.title).toBe "#{atom.project.getPaths()[0]} - Atom"
expect(document.title).toMatch ///^#{atom.project.getPaths()[0]}///
describe "when an inactive pane's item changes", ->
it "does not update the title", ->
@@ -784,7 +788,7 @@ describe "Workspace", ->
})
workspace2.deserialize(atom.workspace.serialize(), atom.deserializers)
item = workspace2.getActivePaneItem()
expect(document.title).toBe "#{item.getLongTitle()} - #{atom.project.getPaths()[0]} - Atom"
expect(document.title).toMatch ///^#{item.getLongTitle()}\ \u2014\ #{atom.project.getPaths()[0]}///
workspace2.destroy()
describe "document edited status", ->