mirror of
https://github.com/atom/atom.git
synced 2026-04-28 03:01:47 -04:00
Merge branch 'master' into wl-electron-35
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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}
|
||||
|
||||
6
spec/fixtures/packages/package-with-deserializers/deserializer-1.js
vendored
Normal file
6
spec/fixtures/packages/package-with-deserializers/deserializer-1.js
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
module.exports = function (state) {
|
||||
return {
|
||||
wasDeserializedBy: 'Deserializer1',
|
||||
state: state
|
||||
}
|
||||
}
|
||||
6
spec/fixtures/packages/package-with-deserializers/deserializer-2.js
vendored
Normal file
6
spec/fixtures/packages/package-with-deserializers/deserializer-2.js
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
module.exports = function (state) {
|
||||
return {
|
||||
wasDeserializedBy: 'Deserializer2',
|
||||
state: state
|
||||
}
|
||||
}
|
||||
3
spec/fixtures/packages/package-with-deserializers/index.js
vendored
Normal file
3
spec/fixtures/packages/package-with-deserializers/index.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
activate: function() {}
|
||||
}
|
||||
9
spec/fixtures/packages/package-with-deserializers/package.json
vendored
Normal file
9
spec/fixtures/packages/package-with-deserializers/package.json
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "package-with-deserializers",
|
||||
"version": "1.0.0",
|
||||
"main": "./index",
|
||||
"deserializers": {
|
||||
"Deserializer1": "./deserializer-1.js",
|
||||
"Deserializer2": "./deserializer-2.js"
|
||||
}
|
||||
}
|
||||
5
spec/fixtures/packages/package-with-eval-time-api-calls/index.js
vendored
Normal file
5
spec/fixtures/packages/package-with-eval-time-api-calls/index.js
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
atom.deserializers.add('MyDeserializer', function (state) {
|
||||
return {state: state, a: 'b'}
|
||||
})
|
||||
|
||||
exports.activate = function () {}
|
||||
5
spec/fixtures/packages/package-with-eval-time-api-calls/package.json
vendored
Normal file
5
spec/fixtures/packages/package-with-eval-time-api-calls/package.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "package-with-eval-time-api-calls",
|
||||
"version": "1.2.3",
|
||||
"main": "./index"
|
||||
}
|
||||
13
spec/fixtures/packages/package-with-json-config-schema/package.json
vendored
Normal file
13
spec/fixtures/packages/package-with-json-config-schema/package.json
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "package-with-json-config-schema",
|
||||
"configSchema": {
|
||||
"a": {
|
||||
"type": "number",
|
||||
"default": 5
|
||||
},
|
||||
"b": {
|
||||
"type": "string",
|
||||
"default": "five"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +1,2 @@
|
||||
'main': 'main-module.coffee'
|
||||
'version': '2.3.4'
|
||||
|
||||
3
spec/fixtures/packages/package-with-view-providers/deserializer.js
vendored
Normal file
3
spec/fixtures/packages/package-with-view-providers/deserializer.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = function (state) {
|
||||
return {state: state}
|
||||
}
|
||||
3
spec/fixtures/packages/package-with-view-providers/index.js
vendored
Normal file
3
spec/fixtures/packages/package-with-view-providers/index.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
activate: function() {}
|
||||
}
|
||||
12
spec/fixtures/packages/package-with-view-providers/package.json
vendored
Normal file
12
spec/fixtures/packages/package-with-view-providers/package.json
vendored
Normal 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"
|
||||
]
|
||||
}
|
||||
9
spec/fixtures/packages/package-with-view-providers/view-provider-1.js
vendored
Normal file
9
spec/fixtures/packages/package-with-view-providers/view-provider-1.js
vendored
Normal 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
|
||||
}
|
||||
}
|
||||
9
spec/fixtures/packages/package-with-view-providers/view-provider-2.js
vendored
Normal file
9
spec/fixtures/packages/package-with-view-providers/view-provider-2.js
vendored
Normal 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
|
||||
}
|
||||
}
|
||||
@@ -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])
|
||||
|
||||
@@ -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 = []
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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"]
|
||||
|
||||
@@ -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)", ->
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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", ->
|
||||
|
||||
Reference in New Issue
Block a user