Merge remote-tracking branch 'refs/remotes/origin/master' into wl-electron-37

This commit is contained in:
Wliu
2016-04-29 18:43:48 -04:00
43 changed files with 485 additions and 1021 deletions

View File

@@ -28,8 +28,10 @@ describe "AtomEnvironment", ->
atom.setSize(originalSize.width, originalSize.height)
it 'sets the size of the window, and can retrieve the size just set', ->
atom.setSize(100, 400)
expect(atom.getSize()).toEqual width: 100, height: 400
newWidth = originalSize.width + 12
newHeight = originalSize.height + 23
atom.setSize(newWidth, newHeight)
expect(atom.getSize()).toEqual width: newWidth, height: newHeight
describe ".isReleasedVersion()", ->
it "returns false if the version is a SHA and true otherwise", ->

View File

@@ -5,6 +5,12 @@
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[branch "master"]
remote = origin
merge = refs/heads/master
[remote "origin"]
url = git@github.com:atom/some-repo-i-guess.git
fetch = +refs/heads/*:refs/remotes/origin/*
[submodule "jstips"]
url = https://github.com/loverajoel/jstips
[submodule "You-Dont-Need-jQuery"]

View File

@@ -0,0 +1 @@
d2b0ad9cbc6f6c4372e8956e5cc5af771b2342e5

View File

@@ -3,7 +3,6 @@
import fs from 'fs-plus'
import path from 'path'
import temp from 'temp'
import Git from 'nodegit'
import {it, beforeEach, afterEach} from './async-spec-helpers'
@@ -47,7 +46,7 @@ describe('GitRepositoryAsync', () => {
let threw = false
try {
await repo.repoPromise
await repo.getRepo()
} catch (e) {
threw = true
}
@@ -56,6 +55,14 @@ describe('GitRepositoryAsync', () => {
})
})
describe('openedPath', () => {
it('is the path passed to .open', () => {
const workingDirPath = copyRepository()
repo = GitRepositoryAsync.open(workingDirPath)
expect(repo.openedPath).toBe(workingDirPath)
})
})
describe('.getRepo()', () => {
beforeEach(() => {
const workingDirectory = copySubmoduleRepository()
@@ -64,19 +71,19 @@ describe('GitRepositoryAsync', () => {
})
it('returns the repository when not given a path', async () => {
const nodeGitRepo1 = await repo.repoPromise
const nodeGitRepo1 = await repo.getRepo()
const nodeGitRepo2 = await repo.getRepo()
expect(nodeGitRepo1.workdir()).toBe(nodeGitRepo2.workdir())
})
it('returns the repository when given a non-submodule path', async () => {
const nodeGitRepo1 = await repo.repoPromise
const nodeGitRepo1 = await repo.getRepo()
const nodeGitRepo2 = await repo.getRepo('README')
expect(nodeGitRepo1.workdir()).toBe(nodeGitRepo2.workdir())
})
it('returns the submodule repository when given a submodule path', async () => {
const nodeGitRepo1 = await repo.repoPromise
const nodeGitRepo1 = await repo.getRepo()
const nodeGitRepo2 = await repo.getRepo('jstips')
expect(nodeGitRepo1.workdir()).not.toBe(nodeGitRepo2.workdir())
@@ -103,7 +110,7 @@ describe('GitRepositoryAsync', () => {
it('returns the repository path for a repository path', async () => {
repo = openFixture('master.git')
const repoPath = await repo.getPath()
expect(repoPath).toBe(path.join(__dirname, 'fixtures', 'git', 'master.git'))
expect(repoPath).toEqualPath(path.join(__dirname, 'fixtures', 'git', 'master.git'))
})
})
@@ -303,7 +310,7 @@ describe('GitRepositoryAsync', () => {
await repo.getPathStatus(filePath)
expect(statusHandler.callCount).toBe(1)
const status = Git.Status.STATUS.WT_MODIFIED
const status = GitRepositoryAsync.Git.Status.STATUS.WT_MODIFIED
expect(statusHandler.argsForCall[0][0]).toEqual({path: filePath, pathStatus: status})
fs.writeFileSync(filePath, 'abc')
@@ -878,4 +885,34 @@ describe('GitRepositoryAsync', () => {
})
})
})
describe('.getOriginURL()', () => {
beforeEach(() => {
const workingDirectory = copyRepository('repo-with-submodules')
repo = GitRepositoryAsync.open(workingDirectory)
})
it('returns the origin URL', async () => {
const url = await repo.getOriginURL()
expect(url).toBe('git@github.com:atom/some-repo-i-guess.git')
})
})
describe('.getUpstreamBranch()', () => {
it('returns null when there is no upstream branch', async () => {
const workingDirectory = copyRepository()
repo = GitRepositoryAsync.open(workingDirectory)
const upstream = await repo.getUpstreamBranch()
expect(upstream).toBe(null)
})
it('returns the upstream branch', async () => {
const workingDirectory = copyRepository('repo-with-submodules')
repo = GitRepositoryAsync.open(workingDirectory)
const upstream = await repo.getUpstreamBranch()
expect(upstream).toBe('refs/remotes/origin/master')
})
})
})

View File

@@ -33,7 +33,7 @@ describe "GitRepository", ->
waitsForPromise ->
repo.async.getPath().then(onSuccess)
runs ->
expect(onSuccess.mostRecentCall.args[0]).toBe(repoPath)
expect(onSuccess.mostRecentCall.args[0]).toEqualPath(repoPath)
describe "new GitRepository(path)", ->
it "throws an exception when no repository is found", ->
@@ -289,6 +289,16 @@ describe "GitRepository", ->
expect(repo.isStatusModified(status)).toBe true
expect(repo.isStatusNew(status)).toBe false
it 'caches statuses that were looked up synchronously', ->
originalContent = 'undefined'
fs.writeFileSync(modifiedPath, 'making this path modified')
repo.getPathStatus('file.txt')
fs.writeFileSync(modifiedPath, originalContent)
waitsForPromise -> repo.refreshStatus()
runs ->
expect(repo.isStatusModified(repo.getCachedPathStatus(modifiedPath))).toBeFalsy()
describe "buffer events", ->
[editor] = []

View File

@@ -526,7 +526,7 @@ describe "Project", ->
expect(atom.project.getDirectories()[1].contains(inputPath)).toBe true
expect(atom.project.relativizePath(inputPath)).toEqual [
atom.project.getPaths()[1],
'somewhere/something.txt'
path.join('somewhere', 'something.txt')
]
describe ".contains(path)", ->

View File

@@ -1,66 +0,0 @@
/** @babel */
import ResourcePool from '../src/resource-pool'
import {it} from './async-spec-helpers'
describe('ResourcePool', () => {
let queue
beforeEach(() => {
queue = new ResourcePool([{}])
})
describe('.enqueue', () => {
it('calls the enqueued function', async () => {
let called = false
await queue.enqueue(() => {
called = true
return Promise.resolve()
})
expect(called).toBe(true)
})
it('forwards values from the inner promise', async () => {
const result = await queue.enqueue(() => Promise.resolve(42))
expect(result).toBe(42)
})
it('forwards errors from the inner promise', async () => {
let threw = false
try {
await queue.enqueue(() => Promise.reject(new Error('down with the sickness')))
} catch (e) {
threw = true
}
expect(threw).toBe(true)
})
it('continues to dequeue work after a promise has been rejected', async () => {
try {
await queue.enqueue(() => Promise.reject(new Error('down with the sickness')))
} catch (e) {}
const result = await queue.enqueue(() => Promise.resolve(42))
expect(result).toBe(42)
})
it('queues up work', async () => {
let resolve = null
queue.enqueue(() => {
return new Promise((resolve_, reject) => {
resolve = resolve_
})
})
expect(queue.getQueueDepth()).toBe(0)
queue.enqueue(() => new Promise((resolve, reject) => {}))
expect(queue.getQueueDepth()).toBe(1)
resolve()
waitsFor(() => queue.getQueueDepth() === 0)
})
})
})

View File

@@ -91,3 +91,13 @@ describe "Selection", ->
expect(buffer.lineForRow(0)).toBe " "
expect(buffer.lineForRow(1)).toBe " "
expect(buffer.lineForRow(2)).toBe ""
it "auto-indents if only a newline is inserted", ->
selection.setBufferRange [[2, 0], [3, 0]]
selection.insertText("\n", autoIndent: true)
expect(buffer.lineForRow(2)).toBe " "
it "auto-indents if only a carriage return + newline is inserted", ->
selection.setBufferRange [[2, 0], [3, 0]]
selection.insertText("\r\n", autoIndent: true)
expect(buffer.lineForRow(2)).toBe " "

View File

@@ -172,8 +172,8 @@ jasmine.useRealClock = ->
addCustomMatchers = (spec) ->
spec.addMatchers
toBeInstanceOf: (expected) ->
notText = if @isNot then " not" else ""
this.message = => "Expected #{jasmine.pp(@actual)} to#{notText} be instance of #{expected.name} class"
beOrNotBe = if @isNot then "not be" else "be"
this.message = => "Expected #{jasmine.pp(@actual)} to #{beOrNotBe} instance of #{expected.name} class"
@actual instanceof expected
toHaveLength: (expected) ->
@@ -181,32 +181,38 @@ addCustomMatchers = (spec) ->
this.message = => "Expected object #{@actual} has no length method"
false
else
notText = if @isNot then " not" else ""
this.message = => "Expected object with length #{@actual.length} to#{notText} have length #{expected}"
haveOrNotHave = if @isNot then "not have" else "have"
this.message = => "Expected object with length #{@actual.length} to #{haveOrNotHave} length #{expected}"
@actual.length is expected
toExistOnDisk: (expected) ->
notText = this.isNot and " not" or ""
@message = -> return "Expected path '" + @actual + "'" + notText + " to exist."
toOrNotTo = this.isNot and "not to" or "to"
@message = -> return "Expected path '#{@actual}' #{toOrNotTo} exist."
fs.existsSync(@actual)
toHaveFocus: ->
notText = this.isNot and " not" or ""
toOrNotTo = this.isNot and "not to" or "to"
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."
@message = -> return "Expected element '#{@actual}' or its descendants #{toOrNotTo} have focus."
element = @actual
element = element.get(0) if element.jquery
element is document.activeElement or element.contains(document.activeElement)
toShow: ->
notText = if @isNot then " not" else ""
toOrNotTo = this.isNot and "not to" or "to"
element = @actual
element = element.get(0) if element.jquery
@message = -> return "Expected element '#{element}' or its descendants#{notText} to show."
@message = -> return "Expected element '#{element}' or its descendants #{toOrNotTo} show."
element.style.display in ['block', 'inline-block', 'static', 'fixed']
toEqualPath: (expected) ->
actualPath = path.normalize(@actual)
expectedPath = path.normalize(expected)
@message = -> return "Expected path '#{actualPath}' to be equal to '#{expectedPath}'."
actualPath is expectedPath
window.waitsForPromise = (args...) ->
label = null
if args.length > 1

View File

@@ -4022,15 +4022,33 @@ describe('TextEditorComponent', function () {
})
})
describe('when changing the font', async function () {
it('measures the default char, the korean char, the double width char and the half width char widths', async function () {
expect(editor.getDefaultCharWidth()).toBeCloseTo(12, 0)
describe('when decreasing the fontSize', async function () {
it('decreases the widths of the korean char, the double width char and the half width char', async function () {
originalDefaultCharWidth = editor.getDefaultCharWidth()
koreanDefaultCharWidth = editor.getKoreanCharWidth()
doubleWidthDefaultCharWidth = editor.getDoubleWidthCharWidth()
halfWidthDefaultCharWidth = editor.getHalfWidthCharWidth()
component.setFontSize(10)
await nextViewUpdatePromise()
expect(editor.getDefaultCharWidth()).toBeCloseTo(6, 0)
expect(editor.getKoreanCharWidth()).toBeCloseTo(9, 0)
expect(editor.getDoubleWidthCharWidth()).toBe(10)
expect(editor.getHalfWidthCharWidth()).toBe(5)
expect(editor.getDefaultCharWidth()).toBeLessThan(originalDefaultCharWidth)
expect(editor.getKoreanCharWidth()).toBeLessThan(koreanDefaultCharWidth)
expect(editor.getDoubleWidthCharWidth()).toBeLessThan(doubleWidthDefaultCharWidth)
expect(editor.getHalfWidthCharWidth()).toBeLessThan(halfWidthDefaultCharWidth)
})
})
describe('when increasing the fontSize', function() {
it('increases the widths of the korean char, the double width char and the half width char', async function () {
originalDefaultCharWidth = editor.getDefaultCharWidth()
koreanDefaultCharWidth = editor.getKoreanCharWidth()
doubleWidthDefaultCharWidth = editor.getDoubleWidthCharWidth()
halfWidthDefaultCharWidth = editor.getHalfWidthCharWidth()
component.setFontSize(25)
await nextViewUpdatePromise()
expect(editor.getDefaultCharWidth()).toBeGreaterThan(originalDefaultCharWidth)
expect(editor.getKoreanCharWidth()).toBeGreaterThan(koreanDefaultCharWidth)
expect(editor.getDoubleWidthCharWidth()).toBeGreaterThan(doubleWidthDefaultCharWidth)
expect(editor.getHalfWidthCharWidth()).toBeGreaterThan(halfWidthDefaultCharWidth)
})
})

View File

@@ -182,17 +182,19 @@ describe "TextEditor", ->
expect(editor1.getLongTitle()).toBe "readme \u2014 sample-theme-1"
expect(editor2.getLongTitle()).toBe "readme \u2014 sample-theme-2"
it "returns '<filename> — <parent-directories>' when opened files have identical file and dir names", ->
it "returns '<filename> — <parent-directories>' when opened files have identical file names in subdirectories", ->
editor1 = null
editor2 = null
path1 = path.join('sample-theme-1', 'src', 'js')
path2 = path.join('sample-theme-2', 'src', 'js')
waitsForPromise ->
atom.workspace.open(path.join('sample-theme-1', 'src', 'js', 'main.js')).then (o) ->
atom.workspace.open(path.join(path1, 'main.js')).then (o) ->
editor1 = o
atom.workspace.open(path.join('sample-theme-2', 'src', 'js', 'main.js')).then (o) ->
atom.workspace.open(path.join(path2, 'main.js')).then (o) ->
editor2 = o
runs ->
expect(editor1.getLongTitle()).toBe "main.js \u2014 sample-theme-1/src/js"
expect(editor2.getLongTitle()).toBe "main.js \u2014 sample-theme-2/src/js"
expect(editor1.getLongTitle()).toBe "main.js \u2014 #{path1}"
expect(editor2.getLongTitle()).toBe "main.js \u2014 #{path2}"
it "returns '<filename> — <parent-directories>' when opened files have identical file and same parent dir name", ->
editor1 = null
@@ -204,7 +206,7 @@ describe "TextEditor", ->
editor2 = o
runs ->
expect(editor1.getLongTitle()).toBe "main.js \u2014 js"
expect(editor2.getLongTitle()).toBe "main.js \u2014 js/plugin"
expect(editor2.getLongTitle()).toBe "main.js \u2014 " + path.join('js', 'plugin')
it "notifies ::onDidChangeTitle observers when the underlying buffer path changes", ->
observed = []
@@ -1187,14 +1189,10 @@ describe "TextEditor", ->
cursor2 = editor.addCursorAtBufferPosition([1, 4])
expect(cursor2.marker).toBe cursor1.marker
describe '.logCursorScope()', ->
beforeEach ->
spyOn(atom.notifications, 'addInfo')
it 'opens a notification', ->
editor.logCursorScope()
expect(atom.notifications.addInfo).toHaveBeenCalled()
describe '.getCursorScope()', ->
it 'returns the current scope', ->
descriptor = editor.getCursorScope()
expect(descriptor.scopes).toContain('source.js')
describe "selection", ->
selection = null
@@ -5729,28 +5727,6 @@ describe "TextEditor", ->
expect(handler).toHaveBeenCalledWith 'OK'
expect(editor.getPlaceholderText()).toBe 'OK'
describe ".checkoutHeadRevision()", ->
it "reverts to the version of its file checked into the project repository", ->
atom.config.set("editor.confirmCheckoutHeadRevision", false)
editor.setCursorBufferPosition([0, 0])
editor.insertText("---\n")
expect(editor.lineTextForBufferRow(0)).toBe "---"
waitsForPromise ->
editor.checkoutHeadRevision()
runs ->
expect(editor.lineTextForBufferRow(0)).toBe "var quicksort = function () {"
describe "when there's no repository for the editor's file", ->
it "doesn't do anything", ->
editor = atom.workspace.buildTextEditor()
editor.setText("stuff")
editor.checkoutHeadRevision()
waitsForPromise -> editor.checkoutHeadRevision()
describe 'gutters', ->
describe 'the TextEditor constructor', ->
it 'creates a line-number gutter', ->

View File

@@ -175,7 +175,7 @@ describe "atom.themes", ->
expect(styleElementAddedHandler).toHaveBeenCalled()
element = document.querySelector('head style[source-path*="css.css"]')
expect(element.getAttribute('source-path')).toBe atom.themes.stringToId(cssPath)
expect(element.getAttribute('source-path')).toEqualPath atom.themes.stringToId(cssPath)
expect(element.textContent).toBe fs.readFileSync(cssPath, 'utf8')
# doesn't append twice
@@ -194,7 +194,7 @@ describe "atom.themes", ->
expect(document.querySelectorAll('head style').length).toBe lengthBefore + 1
element = document.querySelector('head style[source-path*="sample.less"]')
expect(element.getAttribute('source-path')).toBe atom.themes.stringToId(lessPath)
expect(element.getAttribute('source-path')).toEqualPath atom.themes.stringToId(lessPath)
expect(element.textContent).toBe """
#header {
color: #4d926f;
@@ -213,9 +213,9 @@ describe "atom.themes", ->
it "supports requiring css and less stylesheets without an explicit extension", ->
atom.themes.requireStylesheet path.join(__dirname, 'fixtures', 'css')
expect(document.querySelector('head style[source-path*="css.css"]').getAttribute('source-path')).toBe atom.themes.stringToId(atom.project.getDirectories()[0]?.resolve('css.css'))
expect(document.querySelector('head style[source-path*="css.css"]').getAttribute('source-path')).toEqualPath atom.themes.stringToId(atom.project.getDirectories()[0]?.resolve('css.css'))
atom.themes.requireStylesheet path.join(__dirname, 'fixtures', 'sample')
expect(document.querySelector('head style[source-path*="sample.less"]').getAttribute('source-path')).toBe atom.themes.stringToId(atom.project.getDirectories()[0]?.resolve('sample.less'))
expect(document.querySelector('head style[source-path*="sample.less"]').getAttribute('source-path')).toEqualPath atom.themes.stringToId(atom.project.getDirectories()[0]?.resolve('sample.less'))
document.querySelector('head style[source-path*="css.css"]').remove()
document.querySelector('head style[source-path*="sample.less"]').remove()

View File

@@ -445,13 +445,12 @@ describe "TokenizedBuffer", ->
expect(screenLine0.text).toBe "# Econ 101#{tabAsSpaces}"
{tokens} = screenLine0
expect(tokens.length).toBe 4
expect(tokens.length).toBe 3
expect(tokens[0].value).toBe "#"
expect(tokens[1].value).toBe " Econ 101"
expect(tokens[2].value).toBe tabAsSpaces
expect(tokens[2].scopes).toEqual tokens[1].scopes
expect(tokens[2].isAtomic).toBeTruthy()
expect(tokens[3].value).toBe ""
expect(tokenizedBuffer.tokenizedLineForRow(2).text).toBe "#{tabAsSpaces} buy()#{tabAsSpaces}while supply > demand"

View File

@@ -80,7 +80,8 @@ describe "Workspace", ->
expect(untitledEditor.getText()).toBe("An untitled editor.")
expect(atom.workspace.getActiveTextEditor().getPath()).toBe editor3.getPath()
expect(document.title).toMatch ///^#{path.basename(editor3.getLongTitle())}\ \u2014\ #{atom.project.getPaths()[0]}///
pathEscaped = escapeStringRegex(atom.project.getPaths()[0])
expect(document.title).toMatch ///^#{path.basename(editor3.getLongTitle())}\ \u2014\ #{pathEscaped}///
describe "where there are no open panes or editors", ->
it "constructs the view with no open editors", ->
@@ -833,25 +834,29 @@ 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).toMatch ///^#{item.getTitle()}\ \u2014\ #{atom.project.getPaths()[0]}///
pathEscaped = escapeStringRegex(atom.project.getPaths()[0])
expect(document.title).toMatch ///^#{item.getTitle()}\ \u2014\ #{pathEscaped}///
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).toMatch ///^#{editor.getTitle()}\ \u2014\ #{atom.project.getPaths()[0]}///
pathEscaped = escapeStringRegex(atom.project.getPaths()[0])
expect(document.title).toMatch ///^#{editor.getTitle()}\ \u2014\ #{pathEscaped}///
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).toMatch ///^#{item.getTitle()}\ \u2014\ #{atom.project.getPaths()[0]}///
pathEscaped = escapeStringRegex(atom.project.getPaths()[0])
expect(document.title).toMatch ///^#{item.getTitle()}\ \u2014\ #{pathEscaped}///
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).toMatch ///^#{atom.project.getPaths()[0]}///
pathEscaped = escapeStringRegex(atom.project.getPaths()[0])
expect(document.title).toMatch ///^#{pathEscaped}///
describe "when an inactive pane's item changes", ->
it "does not update the title", ->
@@ -875,7 +880,8 @@ describe "Workspace", ->
})
workspace2.deserialize(atom.workspace.serialize(), atom.deserializers)
item = workspace2.getActivePaneItem()
expect(document.title).toMatch ///^#{item.getLongTitle()}\ \u2014\ #{atom.project.getPaths()[0]}///
pathEscaped = escapeStringRegex(atom.project.getPaths()[0])
expect(document.title).toMatch ///^#{item.getLongTitle()}\ \u2014\ #{pathEscaped}///
workspace2.destroy()
describe "document edited status", ->
@@ -1610,3 +1616,48 @@ describe "Workspace", ->
runs ->
expect(pane.getPendingItem()).toBeFalsy()
describe "grammar activation", ->
beforeEach ->
waitsForPromise ->
atom.packages.activatePackage('language-javascript')
it "notifies the workspace of which grammar is used", ->
editor = null
grammarUsed = jasmine.createSpy()
atom.workspace.handleGrammarUsed = grammarUsed
waitsForPromise -> atom.workspace.open('sample-with-comments.js').then (o) -> editor = o
waitsFor -> grammarUsed.callCount is 1
runs ->
expect(grammarUsed.argsForCall[0][0].name).toBe 'JavaScript'
describe ".checkoutHeadRevision()", ->
editor = null
beforeEach ->
atom.config.set("editor.confirmCheckoutHeadRevision", false)
waitsForPromise -> atom.workspace.open('sample-with-comments.js').then (o) -> editor = o
it "reverts to the version of its file checked into the project repository", ->
editor.setCursorBufferPosition([0, 0])
editor.insertText("---\n")
expect(editor.lineTextForBufferRow(0)).toBe "---"
waitsForPromise ->
atom.workspace.checkoutHeadRevision(editor)
runs ->
expect(editor.lineTextForBufferRow(0)).toBe ""
describe "when there's no repository for the editor's file", ->
it "doesn't do anything", ->
editor = atom.workspace.buildTextEditor()
editor.setText("stuff")
atom.workspace.checkoutHeadRevision(editor)
waitsForPromise -> atom.workspace.checkoutHeadRevision(editor)
escapeStringRegex = (str) ->
str.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&')