$ = require 'jquery' _ = require 'underscore' TreeView = require 'tree-view' RootView = require 'root-view' Directory = require 'directory' Native = require 'native' fs = require 'fs' describe "TreeView", -> [rootView, project, treeView, sampleJs, sampleTxt] = [] beforeEach -> rootView = new RootView(require.resolve('fixtures/tree-view')) project = rootView.project rootView.activateExtension(TreeView) treeView = rootView.find(".tree-view").view() treeView.root = treeView.find('> li:first').view() sampleJs = treeView.find('.file:contains(tree-view.js)') sampleTxt = treeView.find('.file:contains(tree-view.txt)') expect(treeView.root.directory.subscriptionCount()).toBeGreaterThan 0 afterEach -> rootView.deactivate() describe ".initialize(project)", -> it "renders the root of the project and its contents alphabetically with subdirectories first in a collapsed state", -> expect(treeView.root.find('> .header .disclosure-arrow')).toHaveText('▾') expect(treeView.root.find('> .header .name')).toHaveText('tree-view/') rootEntries = treeView.root.find('.entries') subdir0 = rootEntries.find('> li:eq(0)') expect(subdir0.find('.disclosure-arrow')).toHaveText('▸') expect(subdir0.find('.name')).toHaveText('dir1/') expect(subdir0.find('.entries')).not.toExist() subdir2 = rootEntries.find('> li:eq(1)') expect(subdir2.find('.disclosure-arrow')).toHaveText('▸') expect(subdir2.find('.name')).toHaveText('dir2/') expect(subdir2.find('.entries')).not.toExist() expect(rootEntries.find('> .file:contains(tree-view.js)')).toExist() expect(rootEntries.find('> .file:contains(tree-view.txt)')).toExist() it "selects the rootview", -> expect(treeView.selectedEntry()).toEqual treeView.root describe "when the project has no path", -> beforeEach -> rootView.deactivate() rootView = new RootView rootView.activateExtension(TreeView) treeView = rootView.find(".tree-view").view() it "does not create a root node", -> expect(treeView.root).not.toExist() it "serializes without throwing an exception", -> expect(-> treeView.serialize()).not.toThrow() it "creates a root view when the project path is created", -> rootView.open(require.resolve('fixtures/sample.js')) expect(treeView.root.getPath()).toBe require.resolve('fixtures') expect(treeView.root.parent()).toMatchSelector(".tree-view") oldRoot = treeView.root rootView.project.setPath('/tmp') expect(treeView.root).not.toEqual oldRoot expect(oldRoot.hasParent()).toBeFalsy() describe "when the prototypes deactivate method is called", -> it "calls the deactivate on tree view instance", -> spyOn(treeView, "deactivate").andCallThrough() rootView.deactivateExtension(TreeView) expect(treeView.deactivate).toHaveBeenCalled() describe "serialization", -> [newRootView, newTreeView] = [] afterEach -> newRootView?.deactivate() it "restores expanded directories and selected file when deserialized", -> treeView.find('.directory:contains(dir1)').click() sampleJs.click() newRootView = RootView.deserialize(rootView.serialize()) rootView.deactivate() # Deactivates previous TreeView newRootView.activateExtension(TreeView) newTreeView = newRootView.find(".tree-view").view() expect(newTreeView).toExist() expect(newTreeView.selectedEntry()).toMatchSelector(".file:contains(tree-view.js)") expect(newTreeView.find(".directory:contains(dir1)")).toHaveClass("expanded") it "restores the focus state of the tree view", -> rootView.attachToDom() treeView.focus() expect(treeView).toMatchSelector ':focus' newRootView = RootView.deserialize(rootView.serialize()) rootView.deactivate() # Deactivates previous TreeView newRootView.attachToDom() newRootView.activateExtension(TreeView) newTreeView = newRootView.find(".tree-view").view() expect(newTreeView).toMatchSelector ':focus' it "restores the scroll top when toggled", -> rootView.height(5) rootView.attachToDom() expect(treeView).toBeVisible() treeView.focus() treeView.scrollTop(10) expect(treeView.scrollTop()).toBe(10) rootView.trigger 'tree-view:toggle' expect(treeView).toBeHidden() rootView.trigger 'tree-view:toggle' expect(treeView).toBeVisible() expect(treeView.scrollTop()).toBe(10) describe "when tree-view:toggle is triggered on the root view", -> beforeEach -> rootView.attachToDom() describe "when the tree view is visible", -> beforeEach -> expect(treeView).toBeVisible() describe "when the tree view is focused", -> it "hides the tree view", -> treeView.focus() rootView.trigger 'tree-view:toggle' expect(treeView).toBeHidden() describe "when the tree view is not focused", -> it "shifts focus to the tree view", -> rootView.open() # When we call focus below, we want an editor to become focused rootView.focus() rootView.trigger 'tree-view:toggle' expect(treeView).toBeVisible() expect(treeView).toMatchSelector(':focus') describe "when the tree view is hidden", -> it "shows and focuses the tree view", -> treeView.detach() rootView.trigger 'tree-view:toggle' expect(treeView.hasParent()).toBeTruthy() expect(treeView).toMatchSelector(':focus') describe "when tree-view:reveal-current-file is triggered on the root view", -> beforeEach -> treeView.detach() spyOn(treeView, 'focus') describe "if the current file has a path", -> it "shows and focuses the tree view and selects the file", -> rootView.open('dir1/file1') rootView.trigger 'tree-view:reveal-active-file' expect(treeView.hasParent()).toBeTruthy() expect(treeView.focus).toHaveBeenCalled() expect(treeView.selectedEntry().getPath()).toMatch /dir1\/file1$/ describe "if the current file has no path", -> it "shows and focuses the tree view, but does not attempt to select a specific file", -> rootView.open() expect(rootView.getActiveEditSession().getPath()).toBeUndefined() rootView.trigger 'tree-view:reveal-active-file' expect(treeView.hasParent()).toBeTruthy() expect(treeView.focus).toHaveBeenCalled() describe "if there is no editor open", -> it "shows and focuses the tree view, but does not attempt to select a specific file", -> expect(rootView.getActiveEditSession()).toBeUndefined() rootView.trigger 'tree-view:reveal-active-file' expect(treeView.hasParent()).toBeTruthy() expect(treeView.focus).toHaveBeenCalled() describe "when tree-view:unfocus is triggered on the tree view", -> it "surrenders focus to the root view but remains open", -> rootView.open() # When we trigger 'tree-view:unfocus' below, we want an editor to become focused rootView.attachToDom() treeView.focus() expect(treeView).toMatchSelector(':focus') treeView.trigger 'tree-view:unfocus' expect(treeView).toBeVisible() expect(treeView).not.toMatchSelector(':focus') expect(rootView.getActiveEditor().isFocused).toBeTruthy() describe "when a directory's disclosure arrow is clicked", -> it "expands / collapses the associated directory", -> subdir = treeView.root.find('.entries > li:contains(dir1/)').view() expect(subdir.disclosureArrow).toHaveText('▸') expect(subdir.find('.entries')).not.toExist() subdir.disclosureArrow.click() expect(subdir.disclosureArrow).toHaveText('▾') expect(subdir.find('.entries')).toExist() subdir.disclosureArrow.click() expect(subdir.disclosureArrow).toHaveText('▸') expect(subdir.find('.entries')).not.toExist() it "restores the expansion state of descendant directories", -> child = treeView.root.find('.entries > li:contains(dir1/)').view() child.disclosureArrow.click() grandchild = child.find('.entries > li:contains(sub-dir1/)').view() grandchild.disclosureArrow.click() treeView.root.disclosureArrow.click() expect(treeView.root.find('.entries')).not.toExist() treeView.root.disclosureArrow.click() # previously expanded descendants remain expanded expect(treeView.root.find('> .entries > li:contains(dir1/) > .entries > li:contains(sub-dir1/) > .entries').length).toBe 1 # collapsed descendants remain collapsed expect(treeView.root.find('> .entries > li.contains(dir2/) > .entries')).not.toExist() it "when collapsing a directory, removes change subscriptions from the collapsed directory and its descendants", -> child = treeView.root.entries.find('li:contains(dir1/)').view() child.disclosureArrow.click() grandchild = child.entries.find('li:contains(sub-dir1/)').view() grandchild.disclosureArrow.click() expect(treeView.root.directory.subscriptionCount()).toBe 1 expect(child.directory.subscriptionCount()).toBe 1 expect(grandchild.directory.subscriptionCount()).toBe 1 treeView.root.disclosureArrow.click() expect(treeView.root.directory.subscriptionCount()).toBe 0 expect(child.directory.subscriptionCount()).toBe 0 expect(grandchild.directory.subscriptionCount()).toBe 0 describe "when a file is single-clicked", -> it "selects the files and opens it in the active editor, without changing focus", -> expect(rootView.getActiveEditor()).toBeUndefined() sampleJs.trigger clickEvent(originalEvent: { detail: 1 }) expect(sampleJs).toHaveClass 'selected' expect(rootView.getActiveEditor().getPath()).toBe require.resolve('fixtures/tree-view/tree-view.js') expect(rootView.getActiveEditor().isFocused).toBeFalsy() sampleTxt.trigger clickEvent(originalEvent: { detail: 1 }) expect(sampleTxt).toHaveClass 'selected' expect(treeView.find('.selected').length).toBe 1 expect(rootView.getActiveEditor().getPath()).toBe require.resolve('fixtures/tree-view/tree-view.txt') expect(rootView.getActiveEditor().isFocused).toBeFalsy() describe "when a file is double-clicked", -> it "selects the file and opens it in the active editor on the first click, then changes focus to the active editor on the second", -> sampleJs.trigger clickEvent(originalEvent: { detail: 1 }) expect(sampleJs).toHaveClass 'selected' expect(rootView.getActiveEditor().getPath()).toBe require.resolve('fixtures/tree-view/tree-view.js') expect(rootView.getActiveEditor().isFocused).toBeFalsy() sampleJs.trigger clickEvent(originalEvent: { detail: 2 }) expect(rootView.getActiveEditor().isFocused).toBeTruthy() describe "when a directory is single-clicked", -> it "is selected", -> subdir = treeView.root.find('.directory:first').view() subdir.trigger clickEvent(originalEvent: { detail: 1 }) expect(subdir).toHaveClass 'selected' describe "when a directory is double-clicked", -> it "toggles the directory expansion state and does not change the focus to the editor", -> sampleJs.trigger clickEvent(originalEvent: { detail: 1 }) subdir = treeView.root.find('.directory:first').view() subdir.trigger clickEvent(originalEvent: { detail: 1 }) expect(subdir).toHaveClass 'selected' subdir.trigger clickEvent(originalEvent: { detail: 2 }) expect(subdir).toHaveClass 'expanded' expect(rootView.getActiveEditor().isFocused).toBeFalsy() describe "when a new file is opened in the active editor", -> it "is selected in the tree view if the file's entry visible", -> sampleJs.click() rootView.open(require.resolve('fixtures/tree-view/tree-view.txt')) expect(sampleTxt).toHaveClass 'selected' expect(treeView.find('.selected').length).toBe 1 it "selected a file's parent dir if the file's entry is not visible", -> rootView.open(require.resolve('fixtures/tree-view/dir1/sub-dir1/sub-file1')) dirView = treeView.root.find('.directory:contains(dir1)').view() expect(dirView).toHaveClass 'selected' describe "when a different editor becomes active", -> it "selects the file in that is open in that editor", -> sampleJs.click() leftEditor = rootView.getActiveEditor() rightEditor = leftEditor.splitRight() sampleTxt.click() expect(sampleTxt).toHaveClass('selected') leftEditor.focus() expect(sampleJs).toHaveClass('selected') describe "keyboard navigation", -> afterEach -> expect(treeView.find('.selected').length).toBeLessThan 2 describe "move-down", -> describe "when a collapsed directory is selected", -> it "skips to the next directory", -> treeView.root.find('.directory:eq(0)').click() treeView.trigger 'move-down' expect(treeView.root.find('.directory:eq(1)')).toHaveClass 'selected' describe "when an expanded directory is selected", -> it "selects the first entry of the directory", -> subdir = treeView.root.find('.directory:eq(1)').view() subdir.expand() subdir.click() treeView.trigger 'move-down' expect(subdir.entries.find('.entry:first')).toHaveClass 'selected' describe "when the last entry of an expanded directory is selected", -> it "selects the entry after its parent directory", -> subdir1 = treeView.root.find('.directory:eq(1)').view() subdir1.expand() subdir1.entries.find('.entry:last').click() treeView.trigger 'move-down' expect(treeView.root.find('.entries > .entry:eq(2)')).toHaveClass 'selected' describe "when the last directory of another last directory is selected", -> [nested, nested2] = [] beforeEach -> nested = treeView.root.find('.directory:eq(2)').view() expect(nested.find('.header').text()).toContain 'nested/' nested.expand() nested2 = nested.entries.find('.entry:last').view() nested2.click() describe "when the directory is collapsed", -> it "selects the entry after its grandparent directory", -> treeView.trigger 'move-down' expect(nested.next()).toHaveClass 'selected' describe "when the directory is expanded", -> it "selects the entry after its grandparent directory", -> nested2.expand() nested2.find('.file').remove() # kill the .gitkeep file, which has to be there but screws the test treeView.trigger 'move-down' expect(nested.next()).toHaveClass 'selected' describe "when the last entry of the last directory is selected", -> it "does not change the selection", -> lastEntry = treeView.root.find('> .entries .entry:last') lastEntry.click() treeView.trigger 'move-down' expect(lastEntry).toHaveClass 'selected' describe "move-up", -> describe "when there is an expanded directory before the currently selected entry", -> it "selects the last entry in the expanded directory", -> lastDir = treeView.root.find('.directory:last').view() fileAfterDir = lastDir.next().view() lastDir.expand() fileAfterDir.click() treeView.trigger 'move-up' expect(lastDir.find('.entry:last')).toHaveClass 'selected' describe "when there is an entry before the currently selected entry", -> it "selects the previous entry", -> lastEntry = treeView.root.find('.entry:last') lastEntry.click() treeView.trigger 'move-up' expect(lastEntry.prev()).toHaveClass 'selected' describe "when there is no entry before the currently selected entry, but there is a parent directory", -> it "selects the parent directory", -> subdir = treeView.root.find('.directory:first').view() subdir.expand() subdir.find('> .entries > .entry:first').click() treeView.trigger 'move-up' expect(subdir).toHaveClass 'selected' describe "when there is no parent directory or previous entry", -> it "does not change the selection", -> treeView.root.click() treeView.trigger 'move-up' expect(treeView.root).toHaveClass 'selected' describe "movement outside of viewable region", -> it "scrolls the tree view to the selected item", -> treeView.height(100) treeView.attachToDom() $(element).view().expand() for element in treeView.find('.directory') expect(treeView.prop('scrollHeight')).toBeGreaterThan treeView.outerHeight() treeView.moveDown() expect(treeView.scrollTop()).toBe 0 entryCount = treeView.find(".entry").length _.times entryCount, -> treeView.moveDown() expect(treeView.scrollBottom()).toBe treeView.prop('scrollHeight') _.times entryCount, -> treeView.moveUp() expect(treeView.scrollTop()).toBe 0 describe "tree-view:expand-directory", -> describe "when a directory entry is selected", -> it "expands the current directory", -> subdir = treeView.root.find('.directory:first') subdir.click() expect(subdir).not.toHaveClass 'expanded' treeView.trigger 'tree-view:expand-directory' expect(subdir).toHaveClass 'expanded' describe "when a file entry is selected", -> it "does nothing", -> treeView.root.find('.file').click() treeView.trigger 'tree-view:expand-directory' describe "tree-view:collapse-directory", -> subdir = null beforeEach -> subdir = treeView.root.find('> .entries > .directory').eq(0).view() subdir.expand() describe "when an expanded directory is selected", -> it "collapses the selected directory", -> expect(subdir).toHaveClass 'expanded' subdir.click() treeView.trigger 'tree-view:collapse-directory' expect(subdir).not.toHaveClass 'expanded' expect(treeView.root).toHaveClass 'expanded' describe "when a collapsed directory is selected", -> it "collapses and selects the selected directory's parent directory", -> subdir.find('.directory').click() treeView.trigger 'tree-view:collapse-directory' expect(subdir).not.toHaveClass 'expanded' expect(subdir).toHaveClass 'selected' expect(treeView.root).toHaveClass 'expanded' describe "when collapsed root directory is selected", -> it "does not raise an error", -> treeView.root.collapse() treeView.selectEntry(treeView.root) treeView.trigger 'tree-view:collapse-directory' describe "when a file is selected", -> it "collapses and selects the selected file's parent directory", -> subdir.find('.file').click() treeView.trigger 'tree-view:collapse-directory' expect(subdir).not.toHaveClass 'expanded' expect(subdir).toHaveClass 'selected' expect(treeView.root).toHaveClass 'expanded' describe "tree-view:open-selected-entry", -> describe "when a file is selected", -> it "opens the file in the editor and focuses it", -> treeView.root.find('.file:contains(tree-view.js)').click() treeView.root.trigger 'tree-view:open-selected-entry' expect(rootView.getActiveEditor().getPath()).toBe require.resolve('fixtures/tree-view/tree-view.js') expect(rootView.getActiveEditor().isFocused).toBeTruthy() describe "when a directory is selected", -> it "expands or collapses the directory", -> subdir = treeView.root.find('.directory').first() subdir.click() expect(subdir).not.toHaveClass 'expanded' treeView.root.trigger 'tree-view:open-selected-entry' expect(subdir).toHaveClass 'expanded' treeView.root.trigger 'tree-view:open-selected-entry' expect(subdir).not.toHaveClass 'expanded' describe "when nothing is selected", -> it "does nothing", -> treeView.root.trigger 'tree-view:open-selected-entry' expect(rootView.getActiveEditor()).toBeUndefined() describe "file modification", -> [dirView, fileView, rootDirPath, dirPath, filePath] = [] beforeEach -> rootView.deactivate() rootDirPath = "/tmp/atom-tests" fs.remove(rootDirPath) if fs.exists(rootDirPath) dirPath = fs.join(rootDirPath, "test-dir") filePath = fs.join(dirPath, "test-file.txt") fs.makeDirectory(rootDirPath) fs.makeDirectory(dirPath) fs.write(filePath, "doesn't matter") rootView = new RootView(rootDirPath) project = rootView.project rootView.activateExtension(TreeView) treeView = rootView.find(".tree-view").view() dirView = treeView.root.entries.find('.directory:contains(test-dir)').view() dirView.expand() fileView = treeView.find('.file:contains(test-file.txt)').view() afterEach -> fs.remove(rootDirPath) if fs.exists(rootDirPath) describe "tree-view:add", -> addDialog = null beforeEach -> fileView.click() treeView.trigger "tree-view:add" addDialog = rootView.find(".tree-view-dialog").view() describe "when a file is selected", -> it "opens an add dialog with the file's current directory path populated", -> expect(addDialog).toExist() expect(addDialog.prompt.text()).toBeTruthy() expect(project.relativize(dirPath)).toMatch(/[^\/]$/) expect(addDialog.miniEditor.getText()).toBe(project.relativize(dirPath) + "/") expect(addDialog.miniEditor.getCursorBufferPosition().column).toBe addDialog.miniEditor.getText().length expect(addDialog.miniEditor.isFocused).toBeTruthy() describe "when parent directory of the selected file changes", -> it "active file is still shown as selected in the tree view", -> directoryChangeHandler = jasmine.createSpy("directory-change") dirView.on "tree-view:directory-modified", directoryChangeHandler dirView.directory.trigger 'contents-change' expect(directoryChangeHandler).toHaveBeenCalled() expect(treeView.find('.selected').text()).toBe fs.base(filePath) describe "when the path without a trailing '/' is changed and confirmed", -> describe "when no file exists at that location", -> it "add a file, closes the dialog and selects the file in the tree-view", -> newPath = fs.join(dirPath, "new-test-file.txt") addDialog.miniEditor.insertText(fs.base(newPath)) addDialog.trigger 'tree-view:confirm' expect(fs.exists(newPath)).toBeTruthy() expect(fs.isFile(newPath)).toBeTruthy() expect(addDialog.parent()).not.toExist() expect(rootView.getActiveEditor().getPath()).toBe newPath waitsFor "tree view to be updated", -> dirView.entries.find("> .file").length > 1 runs -> expect(treeView.find('.selected').text()).toBe fs.base(newPath) describe "when a file already exists at that location", -> it "shows an error message and does not close the dialog", -> newPath = fs.join(dirPath, "new-test-file.txt") fs.write(newPath, '') addDialog.miniEditor.insertText(fs.base(newPath)) addDialog.trigger 'tree-view:confirm' expect(addDialog.prompt.text()).toContain 'Error' expect(addDialog.prompt.text()).toContain 'already exists' expect(addDialog.prompt).toHaveClass('error') expect(addDialog.hasParent()).toBeTruthy() describe "when the path with a trailing '/' is changed and confirmed", -> describe "when no file or directory exists at the given path", -> it "adds a directory and closes the dialog", -> treeView.attachToDom() newPath = fs.join(dirPath, "new/dir") addDialog.miniEditor.insertText("new/dir/") addDialog.trigger 'tree-view:confirm' expect(fs.exists(newPath)).toBeTruthy() expect(fs.isDirectory(newPath)).toBeTruthy() expect(addDialog.parent()).not.toExist() expect(rootView.getActiveEditor().getPath()).not.toBe newPath expect(treeView).toMatchSelector(':focus') expect(rootView.getActiveEditor().isFocused).toBeFalsy() expect(dirView.find('.directory.selected:contains(new/)').length).toBe(1) it "selects the created directory", -> treeView.attachToDom() newPath = fs.join(dirPath, "new2/") addDialog.miniEditor.insertText("new2/") addDialog.trigger 'tree-view:confirm' expect(fs.exists(newPath)).toBeTruthy() expect(fs.isDirectory(newPath)).toBeTruthy() expect(addDialog.parent()).not.toExist() expect(rootView.getActiveEditor().getPath()).not.toBe newPath expect(treeView).toMatchSelector(':focus') expect(rootView.getActiveEditor().isFocused).toBeFalsy() expect(dirView.find('.directory.selected:contains(new2/)').length).toBe(1) describe "when a file or directory already exists at the given path", -> it "shows an error message and does not close the dialog", -> newPath = fs.join(dirPath, "new-dir") fs.makeDirectory(newPath) addDialog.miniEditor.insertText("new-dir/") addDialog.trigger 'tree-view:confirm' expect(addDialog.prompt.text()).toContain 'Error' expect(addDialog.prompt.text()).toContain 'already exists' expect(addDialog.prompt).toHaveClass('error') expect(addDialog.hasParent()).toBeTruthy() describe "when 'tree-view:cancel' is triggered on the add dialog", -> it "removes the dialog and focuses the tree view", -> treeView.attachToDom() addDialog.trigger 'tree-view:cancel' expect(addDialog.parent()).not.toExist() expect(treeView).toMatchSelector(':focus') describe "when the add dialog's editor loses focus", -> it "removes the dialog and focuses root view", -> rootView.attachToDom() rootView.focus() expect(addDialog.parent()).not.toExist() expect(rootView.getActiveEditor().isFocused).toBeTruthy() describe "when a directory is selected", -> it "opens an add dialog with the directory's path populated", -> addDialog.cancel() dirView.click() treeView.trigger "tree-view:add" addDialog = rootView.find(".tree-view-dialog").view() expect(addDialog).toExist() expect(addDialog.prompt.text()).toBeTruthy() expect(project.relativize(dirPath)).toMatch(/[^\/]$/) expect(addDialog.miniEditor.getText()).toBe(project.relativize(dirPath) + "/") expect(addDialog.miniEditor.getCursorBufferPosition().column).toBe addDialog.miniEditor.getText().length expect(addDialog.miniEditor.isFocused).toBeTruthy() describe "when the root directory is selected", -> it "opens an add dialog with no path populated", -> addDialog.cancel() treeView.root.click() treeView.trigger "tree-view:add" addDialog = rootView.find(".tree-view-dialog").view() expect(addDialog.miniEditor.getText().length).toBe 0 describe "tree-view:move", -> describe "when a file is selected", -> moveDialog = null beforeEach -> fileView.click() treeView.trigger "tree-view:move" moveDialog = rootView.find(".tree-view-dialog").view() it "opens a move dialog with the file's current path (excluding extension) populated", -> extension = fs.extension(filePath) fileNameWithoutExtension = fs.base(filePath, extension) expect(moveDialog).toExist() expect(moveDialog.prompt.text()).toBe "Enter the new path for the file:" expect(moveDialog.miniEditor.getText()).toBe(project.relativize(filePath)) expect(moveDialog.miniEditor.getSelectedText()).toBe fs.base(fileNameWithoutExtension) expect(moveDialog.miniEditor.isFocused).toBeTruthy() describe "when the path is changed and confirmed", -> describe "when all the directories along the new path exist", -> it "moves the file, updates the tree view, and closes the dialog", -> newPath = fs.join(rootDirPath, 'renamed-test-file.txt') moveDialog.miniEditor.setText(newPath) moveDialog.trigger 'tree-view:confirm' expect(fs.exists(newPath)).toBeTruthy() expect(fs.exists(filePath)).toBeFalsy() expect(moveDialog.parent()).not.toExist() waitsFor "tree view to update", -> treeView.root.find('> .entries > .file:contains(renamed-test-file.txt)').length > 0 runs -> dirView = treeView.root.entries.find('.directory:contains(test-dir)').view() dirView.expand() expect(dirView.entries.children().length).toBe 0 describe "when the directories along the new path don't exist", -> it "creates the target directory before moving the file", -> newPath = fs.join(rootDirPath, 'new/directory', 'renamed-test-file.txt') moveDialog.miniEditor.setText(newPath) moveDialog.trigger 'tree-view:confirm' expect(fs.exists(newPath)).toBeTruthy() expect(fs.exists(filePath)).toBeFalsy() waits 50 # TODO: remove this workaround once we fix the race condition in fs events describe "when a file or directory already exists at the target path", -> it "shows an error message and does not close the dialog", -> runs -> fs.write(fs.join(rootDirPath, 'target.txt'), '') newPath = fs.join(rootDirPath, 'target.txt') moveDialog.miniEditor.setText(newPath) moveDialog.trigger 'tree-view:confirm' expect(moveDialog.prompt.text()).toContain 'Error' expect(moveDialog.prompt.text()).toContain 'already exists' expect(moveDialog.prompt).toHaveClass('error') expect(moveDialog.hasParent()).toBeTruthy() describe "when 'tree-view:cancel' is triggered on the move dialog", -> it "removes the dialog and focuses the tree view", -> treeView.attachToDom() moveDialog.trigger 'tree-view:cancel' expect(moveDialog.parent()).not.toExist() expect(treeView).toMatchSelector(':focus') describe "when the move dialog's editor loses focus", -> it "removes the dialog and focuses root view", -> rootView.attachToDom() rootView.focus() expect(moveDialog.parent()).not.toExist() expect(rootView.getActiveEditor().isFocused).toBeTruthy() describe "tree-view:remove", -> it "shows the native alert dialog", -> fileView.click() spyOn(atom, 'confirm') treeView.trigger 'tree-view:remove' expect(atom.confirm).toHaveBeenCalled() describe "file system events", -> temporaryFilePath = null beforeEach -> temporaryFilePath = fs.join(require.resolve('fixtures/tree-view'), 'temporary') if fs.exists(temporaryFilePath) fs.remove(temporaryFilePath) waits(20) afterEach -> fs.remove(temporaryFilePath) if fs.exists(temporaryFilePath) describe "when a file is added or removed in an expanded directory", -> it "updates the directory view to display the directory's new contents", -> entriesCountBefore = null runs -> expect(fs.exists(temporaryFilePath)).toBeFalsy() entriesCountBefore = treeView.root.entries.find('.entry').length fs.write temporaryFilePath, 'hi' waitsFor "directory view contens to refresh", -> treeView.root.entries.find('.entry').length == entriesCountBefore + 1 runs -> expect(treeView.root.entries.find('.entry').length).toBe entriesCountBefore + 1 expect(treeView.root.entries.find('.file:contains(temporary)')).toExist() fs.remove(temporaryFilePath) waitsFor "directory view contens to refresh", -> treeView.root.entries.find('.entry').length == entriesCountBefore