pulsar/spec/project-spec.coffee

367 lines
14 KiB
CoffeeScript
Raw Normal View History

2013-09-18 05:58:41 +04:00
Project = require '../src/project'
{_, fs} = require 'atom-api'
path = require 'path'
2013-09-18 05:58:41 +04:00
BufferedProcess = require '../src/buffered-process'
describe "Project", ->
beforeEach ->
2013-02-28 03:20:33 +04:00
project.setPath(project.resolve('dir'))
describe "serialization", ->
deserializedProject = null
afterEach ->
deserializedProject?.destroy()
it "destroys unretained buffers and does not include them in the serialized state", ->
project.bufferForPath('a')
expect(project.getBuffers().length).toBe 1
deserializedProject = deserialize(project.serialize())
expect(deserializedProject.getBuffers().length).toBe 0
expect(project.getBuffers().length).toBe 0
2013-02-28 03:20:43 +04:00
describe "when an edit session is destroyed", ->
it "removes edit session and calls destroy on buffer (if buffer is not referenced by other edit sessions)", ->
editSession = project.open("a")
anotherEditSession = project.open("a")
expect(project.editSessions.length).toBe 2
expect(editSession.buffer).toBe anotherEditSession.buffer
editSession.destroy()
expect(project.editSessions.length).toBe 1
anotherEditSession.destroy()
expect(project.editSessions.length).toBe 0
describe "when an edit session is saved and the project has no path", ->
it "sets the project's path to the saved file's parent directory", ->
project.setPath(undefined)
expect(project.getPath()).toBeUndefined()
editSession = project.open()
editSession.saveAs('/tmp/atom-test-save-sets-project-path')
expect(project.getPath()).toBe '/tmp'
2013-09-18 05:58:41 +04:00
fs.remove('/tmp/atom-test-save-sets-project-path')
describe "when an edit session is deserialized", ->
it "emits an 'edit-session-created' event and stores the edit session", ->
handler = jasmine.createSpy('editSessionCreatedHandler')
project.on 'edit-session-created', handler
editSession1 = project.open("a")
expect(handler.callCount).toBe 1
expect(project.getEditSessions().length).toBe 1
expect(project.getEditSessions()[0]).toBe editSession1
editSession2 = deserialize(editSession1.serialize())
expect(handler.callCount).toBe 2
expect(project.getEditSessions().length).toBe 2
expect(project.getEditSessions()[0]).toBe editSession1
expect(project.getEditSessions()[1]).toBe editSession2
describe ".open(path)", ->
[fooOpener, barOpener, absolutePath, newBufferHandler, newEditSessionHandler] = []
beforeEach ->
absolutePath = require.resolve('./fixtures/dir/a')
newBufferHandler = jasmine.createSpy('newBufferHandler')
project.on 'buffer-created', newBufferHandler
newEditSessionHandler = jasmine.createSpy('newEditSessionHandler')
project.on 'edit-session-created', newEditSessionHandler
fooOpener = (pathToOpen, options) -> { foo: pathToOpen, options } if pathToOpen?.match(/\.foo/)
barOpener = (pathToOpen) -> { bar: pathToOpen } if pathToOpen?.match(/^bar:\/\//)
project.registerOpener(fooOpener)
project.registerOpener(barOpener)
afterEach ->
project.unregisterOpener(fooOpener)
project.unregisterOpener(barOpener)
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 'edit-session-created' events", ->
editSession = project.open(absolutePath)
expect(editSession.buffer.getPath()).toBe absolutePath
expect(newBufferHandler).toHaveBeenCalledWith editSession.buffer
expect(newEditSessionHandler).toHaveBeenCalledWith editSession
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 'edit-session-created' events", ->
editSession = project.open('a')
expect(editSession.buffer.getPath()).toBe absolutePath
expect(newBufferHandler).toHaveBeenCalledWith editSession.buffer
expect(newEditSessionHandler).toHaveBeenCalledWith editSession
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 'edit-session-created' event", ->
editSession = project.open(absolutePath)
newBufferHandler.reset()
expect(project.open(absolutePath).buffer).toBe editSession.buffer
expect(project.open('a').buffer).toBe editSession.buffer
expect(newBufferHandler).not.toHaveBeenCalled()
expect(newEditSessionHandler).toHaveBeenCalledWith editSession
describe "when not passed a path", ->
it "returns a new edit session and emits 'buffer-created' and 'edit-session-created' events", ->
editSession = project.open()
expect(editSession.buffer.getPath()).toBeUndefined()
expect(newBufferHandler).toHaveBeenCalledWith(editSession.buffer)
expect(newEditSessionHandler).toHaveBeenCalledWith editSession
describe "when passed a path that matches a custom opener", ->
it "returns the resource returned by the custom opener", ->
pathToOpen = project.resolve('a.foo')
expect(project.open(pathToOpen, hey: "there")).toEqual { foo: pathToOpen, options: {hey: "there"} }
expect(project.open("bar://baz")).toEqual { bar: "bar://baz" }
describe ".bufferForPath(path)", ->
describe "when opening a previously opened path", ->
it "does not create a new buffer", ->
buffer = project.bufferForPath("a").retain()
expect(project.bufferForPath("a")).toBe buffer
alternativeBuffer = project.bufferForPath("b").retain().release()
expect(alternativeBuffer).not.toBe buffer
buffer.release()
it "creates a new buffer if the previous buffer was destroyed", ->
buffer = project.bufferForPath("a").retain().release()
expect(project.bufferForPath("a").retain().release()).not.toBe buffer
describe ".resolve(uri)", ->
describe "when passed an absolute or relative path", ->
it "returns an absolute path based on the project's root", ->
absolutePath = require.resolve('./fixtures/dir/a')
expect(project.resolve('a')).toBe absolutePath
expect(project.resolve(absolutePath + '/../a')).toBe absolutePath
expect(project.resolve('a/../a')).toBe absolutePath
describe "when passed a uri with a scheme", ->
it "does not modify uris that begin with a scheme", ->
expect(project.resolve('http://zombo.com')).toBe 'http://zombo.com'
describe ".setPath(path)", ->
describe "when path is a file", ->
it "sets its path to the files parent directory and updates the root directory", ->
project.setPath(require.resolve('./fixtures/dir/a'))
expect(project.getPath()).toEqual path.dirname(require.resolve('./fixtures/dir/a'))
expect(project.getRootDirectory().path).toEqual path.dirname(require.resolve('./fixtures/dir/a'))
describe "when path is a directory", ->
it "sets its path to the directory and updates the root directory", ->
2013-09-18 05:58:41 +04:00
directory = fs.absolute(path.join(__dirname, 'fixtures', 'dir', 'a-dir'))
project.setPath(directory)
expect(project.getPath()).toEqual directory
expect(project.getRootDirectory().path).toEqual directory
describe "when path is null", ->
it "sets its path and root directory to null", ->
project.setPath(null)
expect(project.getPath()?).toBeFalsy()
expect(project.getRootDirectory()?).toBeFalsy()
describe ".getFilePaths()", ->
it "returns file paths using a promise", ->
2012-12-13 00:26:39 +04:00
paths = null
waitsForPromise ->
project.getFilePaths().done (foundPaths) -> paths = foundPaths
runs ->
expect(paths.length).toBeGreaterThan 0
it "ignores files that return true from atom.ignorePath(path)", ->
spyOn(project, 'isPathIgnored').andCallFake (filePath) -> path.basename(filePath).match /a$/
2012-12-13 00:26:39 +04:00
paths = null
waitsForPromise ->
project.getFilePaths().done (foundPaths) -> paths = foundPaths
runs ->
expect(paths).not.toContain(project.resolve('a'))
expect(paths).toContain(project.resolve('b'))
describe "when config.core.hideGitIgnoredFiles is true", ->
it "ignores files that are present in .gitignore if the project is a git repo", ->
config.set "core.hideGitIgnoredFiles", true
project.setPath(path.join(__dirname, 'fixtures', 'git', 'working-dir'))
paths = null
waitsForPromise ->
project.getFilePaths().done (foundPaths) -> paths = foundPaths
2012-12-13 00:26:39 +04:00
runs ->
expect(paths).not.toContain('ignored.txt')
describe "ignored file name", ->
ignoredFile = null
beforeEach ->
ignoredFile = path.join(__dirname, 'fixtures', 'dir', 'ignored.txt')
2013-09-18 05:58:41 +04:00
fs.writeSync(ignoredFile, "")
afterEach ->
2013-09-18 05:58:41 +04:00
fs.remove(ignoredFile)
it "ignores ignored.txt file", ->
paths = null
config.pushAtKeyPath("core.ignoredNames", "ignored.txt")
waitsForPromise ->
project.getFilePaths().done (foundPaths) -> paths = foundPaths
runs ->
expect(paths).not.toContain('ignored.txt')
2012-11-09 23:35:45 +04:00
describe "ignored folder name", ->
ignoredFile = null
beforeEach ->
ignoredFile = path.join(__dirname, 'fixtures', 'dir', 'ignored', 'ignored.txt')
2013-09-18 05:58:41 +04:00
fs.writeSync(ignoredFile, "")
afterEach ->
2013-09-18 05:58:41 +04:00
fs.remove(ignoredFile)
it "ignores ignored folder", ->
paths = null
config.get("core.ignoredNames").push("ignored.txt")
config.set("core.ignoredNames", config.get("core.ignoredNames"))
waitsForPromise ->
project.getFilePaths().done (foundPaths) -> paths = foundPaths
runs ->
expect(paths).not.toContain('ignored/ignored.txt')
describe ".scan(options, callback)", ->
describe "when called with a regex", ->
it "calls the callback with all regex matches in all files in the project", ->
matches = []
waitsForPromise ->
project.scan /(a)+/, (match) -> matches.push(match)
runs ->
expect(matches[0]).toEqual
path: project.resolve('a')
match: 'aaa'
range: [[0, 0], [0, 3]]
expect(matches[1]).toEqual
path: project.resolve('a')
match: 'aa'
range: [[1, 3], [1, 5]]
it "works with with escaped literals (like $ and ^)", ->
matches = []
waitsForPromise ->
project.scan /\$\w+/, (match) -> matches.push(match)
runs ->
expect(matches.length).toBe 1
expect(matches[0]).toEqual
path: project.resolve('a')
2012-11-06 00:16:08 +04:00
match: '$bill'
range: [[2, 6], [2, 11]]
it "works on evil filenames", ->
project.setPath(path.join(__dirname, 'fixtures', 'evil-files'))
paths = []
matches = []
waitsForPromise ->
project.scan /evil/, (result) ->
paths.push(result.path)
matches.push(result.match)
runs ->
expect(paths.length).toBe 5
matches.forEach (match) -> expect(match).toEqual 'evil'
expect(paths[0]).toMatch /a_file_with_utf8.txt$/
expect(paths[1]).toMatch /file with spaces.txt$/
expect(paths[2]).toMatch /goddam\nnewlines$/m
expect(paths[3]).toMatch /quote".txt$/m
expect(path.basename(paths[4])).toBe "utfa\u0306.md"
it "ignores case if the regex includes the `i` flag", ->
matches = []
waitsForPromise ->
project.scan /DOLLAR/i, (match) -> matches.push(match)
runs ->
expect(matches).toHaveLength 1
it "handles breaks in the search subprocess's output following the filename", ->
spyOn(BufferedProcess.prototype, 'bufferStream')
iterator = jasmine.createSpy('iterator')
project.scan /a+/, iterator
stdout = BufferedProcess.prototype.bufferStream.argsForCall[0][1]
stdout ":#{path.join(__dirname, 'fixtures', 'dir', 'a')}\n"
stdout "1;0 3:aaa bbb\n2;3 2:cc aa cc\n"
expect(iterator.argsForCall[0][0]).toEqual
path: project.resolve('a')
match: 'aaa'
range: [[0, 0], [0, 3]]
expect(iterator.argsForCall[1][0]).toEqual
path: project.resolve('a')
match: 'aa'
range: [[1, 3], [1, 5]]
2013-01-09 03:24:14 +04:00
describe "when the core.excludeVcsIgnoredPaths config is truthy", ->
[projectPath, ignoredPath] = []
beforeEach ->
projectPath = path.join(__dirname, 'fixtures', 'git', 'working-dir')
ignoredPath = path.join(projectPath, 'ignored.txt')
2013-09-18 05:58:41 +04:00
fs.writeSync(ignoredPath, 'this match should not be included')
afterEach ->
2013-09-18 05:58:41 +04:00
fs.remove(ignoredPath) if fs.exists(ignoredPath)
it "excludes ignored files", ->
project.setPath(projectPath)
config.set('core.excludeVcsIgnoredPaths', true)
paths = []
matches = []
waitsForPromise ->
project.scan /match/, (result) ->
paths.push(result.path)
matches.push(result.match)
runs ->
expect(paths.length).toBe 0
expect(matches.length).toBe 0
2013-04-12 22:47:11 +04:00
it "includes files and folders that begin with a '.'", ->
projectPath = '/tmp/atom-tests/folder-with-dot-file'
filePath = path.join(projectPath, '.text')
2013-09-18 05:58:41 +04:00
fs.writeSync(filePath, 'match this')
2013-04-12 22:47:11 +04:00
project.setPath(projectPath)
paths = []
matches = []
waitsForPromise ->
project.scan /match this/, (result) ->
paths.push(result.path)
matches.push(result.match)
2013-04-12 22:47:11 +04:00
runs ->
expect(paths.length).toBe 1
expect(paths[0]).toBe filePath
expect(matches.length).toBe 1
it "excludes values in core.ignoredNames", ->
projectPath = '/tmp/atom-tests/folder-with-dot-git/.git'
filePath = path.join(projectPath, 'test.txt')
2013-09-18 05:58:41 +04:00
fs.writeSync(filePath, 'match this')
project.setPath(projectPath)
paths = []
matches = []
waitsForPromise ->
project.scan /match/, (result) ->
paths.push(result.path)
matches.push(result.match)
runs ->
expect(paths.length).toBe 0
expect(matches.length).toBe 0