pulsar/spec/dock-spec.js
2018-03-06 15:45:29 -08:00

360 lines
13 KiB
JavaScript

/** @babel */
const Grim = require('grim')
import {it, fit, ffit, fffit, beforeEach, afterEach} from './async-spec-helpers'
import etch from 'etch'
const getNextUpdatePromise = () => etch.getScheduler().nextUpdatePromise
describe('Dock', () => {
describe('when a dock is activated', () => {
it('opens the dock and activates its active pane', () => {
jasmine.attachToDOM(atom.workspace.getElement())
const dock = atom.workspace.getLeftDock()
const didChangeVisibleSpy = jasmine.createSpy()
dock.onDidChangeVisible(didChangeVisibleSpy)
expect(dock.isVisible()).toBe(false)
expect(document.activeElement).toBe(atom.workspace.getCenter().getActivePane().getElement())
dock.activate()
expect(dock.isVisible()).toBe(true)
expect(document.activeElement).toBe(dock.getActivePane().getElement())
expect(didChangeVisibleSpy).toHaveBeenCalledWith(true)
})
})
describe('when a dock is hidden', () => {
it('transfers focus back to the active center pane if the dock had focus', () => {
jasmine.attachToDOM(atom.workspace.getElement())
const dock = atom.workspace.getLeftDock()
const didChangeVisibleSpy = jasmine.createSpy()
dock.onDidChangeVisible(didChangeVisibleSpy)
dock.activate()
expect(document.activeElement).toBe(dock.getActivePane().getElement())
expect(didChangeVisibleSpy.mostRecentCall.args[0]).toBe(true)
dock.hide()
expect(document.activeElement).toBe(atom.workspace.getCenter().getActivePane().getElement())
expect(didChangeVisibleSpy.mostRecentCall.args[0]).toBe(false)
dock.activate()
expect(document.activeElement).toBe(dock.getActivePane().getElement())
expect(didChangeVisibleSpy.mostRecentCall.args[0]).toBe(true)
dock.toggle()
expect(document.activeElement).toBe(atom.workspace.getCenter().getActivePane().getElement())
expect(didChangeVisibleSpy.mostRecentCall.args[0]).toBe(false)
// Don't change focus if the dock was not focused in the first place
const modalElement = document.createElement('div')
modalElement.setAttribute('tabindex', -1)
atom.workspace.addModalPanel({item: modalElement})
modalElement.focus()
expect(document.activeElement).toBe(modalElement)
dock.show()
expect(document.activeElement).toBe(modalElement)
expect(didChangeVisibleSpy.mostRecentCall.args[0]).toBe(true)
dock.hide()
expect(document.activeElement).toBe(modalElement)
expect(didChangeVisibleSpy.mostRecentCall.args[0]).toBe(false)
})
})
describe('when a pane in a dock is activated', () => {
it('opens the dock', async () => {
const item = {
element: document.createElement('div'),
getDefaultLocation() { return 'left' }
}
await atom.workspace.open(item, {activatePane: false})
expect(atom.workspace.getLeftDock().isVisible()).toBe(false)
atom.workspace.getLeftDock().getPanes()[0].activate()
expect(atom.workspace.getLeftDock().isVisible()).toBe(true)
})
})
describe('activating the next pane', () => {
describe('when the dock has more than one pane', () => {
it('activates the next pane', () => {
const dock = atom.workspace.getLeftDock()
const pane1 = dock.getPanes()[0]
const pane2 = pane1.splitRight()
const pane3 = pane2.splitRight()
pane2.activate()
expect(pane1.isActive()).toBe(false)
expect(pane2.isActive()).toBe(true)
expect(pane3.isActive()).toBe(false)
dock.activateNextPane()
expect(pane1.isActive()).toBe(false)
expect(pane2.isActive()).toBe(false)
expect(pane3.isActive()).toBe(true)
})
})
describe('when the dock has only one pane', () => {
it('leaves the current pane active', () => {
const dock = atom.workspace.getLeftDock()
expect(dock.getPanes().length).toBe(1)
const pane = dock.getPanes()[0]
expect(pane.isActive()).toBe(true)
dock.activateNextPane()
expect(pane.isActive()).toBe(true)
})
})
})
describe('activating the previous pane', () => {
describe('when the dock has more than one pane', () => {
it('activates the previous pane', () => {
const dock = atom.workspace.getLeftDock()
const pane1 = dock.getPanes()[0]
const pane2 = pane1.splitRight()
const pane3 = pane2.splitRight()
pane2.activate()
expect(pane1.isActive()).toBe(false)
expect(pane2.isActive()).toBe(true)
expect(pane3.isActive()).toBe(false)
dock.activatePreviousPane()
expect(pane1.isActive()).toBe(true)
expect(pane2.isActive()).toBe(false)
expect(pane3.isActive()).toBe(false)
})
})
describe('when the dock has only one pane', () => {
it('leaves the current pane active', () => {
const dock = atom.workspace.getLeftDock()
expect(dock.getPanes().length).toBe(1)
const pane = dock.getPanes()[0]
expect(pane.isActive()).toBe(true)
dock.activatePreviousPane()
expect(pane.isActive()).toBe(true)
})
})
})
describe('when the dock resize handle is double-clicked', () => {
describe('when the dock is open', () => {
it('resizes a vertically-oriented dock to the current item\'s preferred width', async () => {
jasmine.attachToDOM(atom.workspace.getElement())
const item = {
element: document.createElement('div'),
getDefaultLocation() { return 'left' },
getPreferredWidth() { return 142 },
getPreferredHeight() { return 122 }
}
await atom.workspace.open(item)
const dock = atom.workspace.getLeftDock()
const dockElement = dock.getElement()
dock.setState({size: 300})
await getNextUpdatePromise()
expect(dockElement.offsetWidth).toBe(300)
dockElement.querySelector('.atom-dock-resize-handle').dispatchEvent(new MouseEvent('mousedown', {detail: 2}))
await getNextUpdatePromise()
expect(dockElement.offsetWidth).toBe(item.getPreferredWidth())
})
it('resizes a horizontally-oriented dock to the current item\'s preferred width', async () => {
jasmine.attachToDOM(atom.workspace.getElement())
const item = {
element: document.createElement('div'),
getDefaultLocation() { return 'bottom' },
getPreferredWidth() { return 122 },
getPreferredHeight() { return 142 }
}
await atom.workspace.open(item)
const dock = atom.workspace.getBottomDock()
const dockElement = dock.getElement()
dock.setState({size: 300})
await getNextUpdatePromise()
expect(dockElement.offsetHeight).toBe(300)
dockElement.querySelector('.atom-dock-resize-handle').dispatchEvent(new MouseEvent('mousedown', {detail: 2}))
await getNextUpdatePromise()
expect(dockElement.offsetHeight).toBe(item.getPreferredHeight())
})
})
describe('when the dock is closed', () => {
it('does nothing', async () => {
jasmine.attachToDOM(atom.workspace.getElement())
const item = {
element: document.createElement('div'),
getDefaultLocation() { return 'bottom' },
getPreferredWidth() { return 122 },
getPreferredHeight() { return 142 }
}
await atom.workspace.open(item, {activatePane: false})
const dockElement = atom.workspace.getBottomDock().getElement()
dockElement.querySelector('.atom-dock-resize-handle').dispatchEvent(new MouseEvent('mousedown', {detail: 2}))
expect(dockElement.offsetHeight).toBe(0)
expect(dockElement.querySelector('.atom-dock-inner').offsetHeight).toBe(0)
// The content should be masked away.
expect(dockElement.querySelector('.atom-dock-mask').offsetHeight).toBe(0)
})
})
})
describe('when you add an item to an empty dock', () => {
describe('when the item has a preferred size', () => {
it('is takes the preferred size of the item', async () => {
jasmine.attachToDOM(atom.workspace.getElement())
const createItem = preferredWidth => ({
element: document.createElement('div'),
getDefaultLocation() { return 'left' },
getPreferredWidth() { return preferredWidth }
})
const dock = atom.workspace.getLeftDock()
const dockElement = dock.getElement()
expect(dock.getPaneItems()).toHaveLength(0)
const item1 = createItem(111)
await atom.workspace.open(item1)
// It should update the width every time we go from 0 -> 1 items, not just the first.
expect(dock.isVisible()).toBe(true)
expect(dockElement.offsetWidth).toBe(111)
dock.destroyActivePane()
expect(dock.getPaneItems()).toHaveLength(0)
expect(dock.isVisible()).toBe(false)
const item2 = createItem(222)
await atom.workspace.open(item2)
expect(dock.isVisible()).toBe(true)
expect(dockElement.offsetWidth).toBe(222)
// Adding a second shouldn't change the size.
const item3 = createItem(333)
await atom.workspace.open(item3)
expect(dockElement.offsetWidth).toBe(222)
})
})
describe('when the item has no preferred size', () => {
it('is still has an explicit size', async () => {
jasmine.attachToDOM(atom.workspace.getElement())
const item = {
element: document.createElement('div'),
getDefaultLocation() { return 'left' }
}
const dock = atom.workspace.getLeftDock()
expect(dock.getPaneItems()).toHaveLength(0)
expect(dock.state.size).toBe(null)
await atom.workspace.open(item)
expect(dock.state.size).not.toBe(null)
})
})
})
describe('a deserialized dock', () => {
it('restores the serialized size', async () => {
jasmine.attachToDOM(atom.workspace.getElement())
const item = {
element: document.createElement('div'),
getDefaultLocation() { return 'left' },
getPreferredWidth() { return 122 },
serialize: () => ({deserializer: 'DockTestItem'})
}
const itemDeserializer = atom.deserializers.add({
name: 'DockTestItem',
deserialize: () => item
})
const dock = atom.workspace.getLeftDock()
const dockElement = dock.getElement()
await atom.workspace.open(item)
dock.setState({size: 150})
expect(dockElement.offsetWidth).toBe(150)
const serialized = dock.serialize()
dock.setState({size: 122})
expect(dockElement.offsetWidth).toBe(122)
dock.destroyActivePane()
dock.deserialize(serialized, atom.deserializers)
expect(dockElement.offsetWidth).toBe(150)
})
it("isn't visible if it has no items", async () => {
jasmine.attachToDOM(atom.workspace.getElement())
const item = {
element: document.createElement('div'),
getDefaultLocation() { return 'left' },
getPreferredWidth() { return 122 }
}
const dock = atom.workspace.getLeftDock()
await atom.workspace.open(item)
expect(dock.isVisible()).toBe(true)
const serialized = dock.serialize()
dock.deserialize(serialized, atom.deserializers)
expect(dock.getPaneItems()).toHaveLength(0)
expect(dock.isVisible()).toBe(false)
})
})
describe('drag handling', () => {
it('expands docks to match the preferred size of the dragged item', async () => {
jasmine.attachToDOM(atom.workspace.getElement())
const element = document.createElement('div')
element.setAttribute('is', 'tabs-tab')
element.item = {
element,
getDefaultLocation() { return 'left' },
getPreferredWidth() { return 144 }
}
const dragEvent = new DragEvent('dragstart')
Object.defineProperty(dragEvent, 'target', {value: element})
atom.workspace.getElement().handleDragStart(dragEvent)
await getNextUpdatePromise()
expect(atom.workspace.getLeftDock().refs.wrapperElement.offsetWidth).toBe(144)
})
it('does nothing when text nodes are dragged', () => {
jasmine.attachToDOM(atom.workspace.getElement())
const textNode = document.createTextNode('hello')
const dragEvent = new DragEvent('dragstart')
Object.defineProperty(dragEvent, 'target', {value: textNode})
expect(() => atom.workspace.getElement().handleDragStart(dragEvent)).not.toThrow()
})
})
describe('::getActiveTextEditor()', () => {
it('is deprecated', () => {
spyOn(Grim, 'deprecate')
atom.workspace.getLeftDock().getActiveTextEditor()
expect(Grim.deprecate.callCount).toBe(1)
})
})
})