mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-10-27 11:42:41 +03:00
337 lines
11 KiB
JavaScript
337 lines
11 KiB
JavaScript
const PaneContainer = require('../src/pane-container');
|
|
|
|
describe('PaneElement', function() {
|
|
let [paneElement, container, containerElement, pane] = [];
|
|
|
|
beforeEach(function() {
|
|
spyOn(atom.applicationDelegate, 'open');
|
|
|
|
container = new PaneContainer({
|
|
location: 'center',
|
|
config: atom.config,
|
|
confirm: atom.confirm.bind(atom),
|
|
viewRegistry: atom.views,
|
|
applicationDelegate: atom.applicationDelegate
|
|
});
|
|
containerElement = container.getElement();
|
|
pane = container.getActivePane();
|
|
paneElement = pane.getElement();
|
|
});
|
|
|
|
describe("when the pane's active status changes", () =>
|
|
it('adds or removes the .active class as appropriate', function() {
|
|
const pane2 = pane.splitRight();
|
|
expect(pane2.isActive()).toBe(true);
|
|
|
|
expect(paneElement.className).not.toMatch(/active/);
|
|
pane.activate();
|
|
expect(paneElement.className).toMatch(/active/);
|
|
pane2.activate();
|
|
expect(paneElement.className).not.toMatch(/active/);
|
|
}));
|
|
|
|
describe('when the active item changes', function() {
|
|
it('hides all item elements except the active one', function() {
|
|
const item1 = document.createElement('div');
|
|
const item2 = document.createElement('div');
|
|
const item3 = document.createElement('div');
|
|
pane.addItem(item1);
|
|
pane.addItem(item2);
|
|
pane.addItem(item3);
|
|
|
|
expect(pane.getActiveItem()).toBe(item1);
|
|
expect(item1.parentElement).toBeDefined();
|
|
expect(item1.style.display).toBe('');
|
|
expect(item2.parentElement).toBeNull();
|
|
expect(item3.parentElement).toBeNull();
|
|
|
|
pane.activateItem(item2);
|
|
expect(item2.parentElement).toBeDefined();
|
|
expect(item1.style.display).toBe('none');
|
|
expect(item2.style.display).toBe('');
|
|
expect(item3.parentElement).toBeNull();
|
|
|
|
pane.activateItem(item3);
|
|
expect(item3.parentElement).toBeDefined();
|
|
expect(item1.style.display).toBe('none');
|
|
expect(item2.style.display).toBe('none');
|
|
expect(item3.style.display).toBe('');
|
|
});
|
|
|
|
it('transfers focus to the new item if the previous item was focused', function() {
|
|
const item1 = document.createElement('div');
|
|
item1.tabIndex = -1;
|
|
const item2 = document.createElement('div');
|
|
item2.tabIndex = -1;
|
|
pane.addItem(item1);
|
|
pane.addItem(item2);
|
|
jasmine.attachToDOM(paneElement);
|
|
paneElement.focus();
|
|
|
|
expect(document.activeElement).toBe(item1);
|
|
pane.activateItem(item2);
|
|
expect(document.activeElement).toBe(item2);
|
|
});
|
|
|
|
describe('if the active item is a model object', () =>
|
|
it('retrieves the associated view from atom.views and appends it to the itemViews div', function() {
|
|
class TestModel {}
|
|
|
|
atom.views.addViewProvider(TestModel, function(model) {
|
|
const view = document.createElement('div');
|
|
view.model = model;
|
|
return view;
|
|
});
|
|
|
|
const item1 = new TestModel();
|
|
const item2 = new TestModel();
|
|
pane.addItem(item1);
|
|
pane.addItem(item2);
|
|
|
|
expect(paneElement.itemViews.children[0].model).toBe(item1);
|
|
expect(paneElement.itemViews.children[0].style.display).toBe('');
|
|
pane.activateItem(item2);
|
|
expect(paneElement.itemViews.children[1].model).toBe(item2);
|
|
expect(paneElement.itemViews.children[0].style.display).toBe('none');
|
|
expect(paneElement.itemViews.children[1].style.display).toBe('');
|
|
}));
|
|
|
|
describe('when the new active implements .getPath()', function() {
|
|
it('adds the file path and file name as a data attribute on the pane', function() {
|
|
const item1 = document.createElement('div');
|
|
item1.getPath = () => '/foo/bar.txt';
|
|
const item2 = document.createElement('div');
|
|
pane.addItem(item1);
|
|
pane.addItem(item2);
|
|
|
|
expect(paneElement.dataset.activeItemPath).toBe('/foo/bar.txt');
|
|
expect(paneElement.dataset.activeItemName).toBe('bar.txt');
|
|
|
|
pane.activateItem(item2);
|
|
|
|
expect(paneElement.dataset.activeItemPath).toBeUndefined();
|
|
expect(paneElement.dataset.activeItemName).toBeUndefined();
|
|
|
|
pane.activateItem(item1);
|
|
expect(paneElement.dataset.activeItemPath).toBe('/foo/bar.txt');
|
|
expect(paneElement.dataset.activeItemName).toBe('bar.txt');
|
|
|
|
pane.destroyItems();
|
|
expect(paneElement.dataset.activeItemPath).toBeUndefined();
|
|
expect(paneElement.dataset.activeItemName).toBeUndefined();
|
|
});
|
|
|
|
describe('when the path of the item changes', function() {
|
|
let [item1, item2] = [];
|
|
|
|
beforeEach(function() {
|
|
item1 = document.createElement('div');
|
|
item1.path = '/foo/bar.txt';
|
|
item1.changePathCallbacks = [];
|
|
item1.setPath = function(path) {
|
|
this.path = path;
|
|
for (let callback of Array.from(this.changePathCallbacks)) {
|
|
callback();
|
|
}
|
|
};
|
|
item1.getPath = function() {
|
|
return this.path;
|
|
};
|
|
item1.onDidChangePath = function(callback) {
|
|
this.changePathCallbacks.push(callback);
|
|
return {
|
|
dispose: () => {
|
|
this.changePathCallbacks = this.changePathCallbacks.filter(
|
|
f => f !== callback
|
|
);
|
|
}
|
|
};
|
|
};
|
|
|
|
item2 = document.createElement('div');
|
|
|
|
pane.addItem(item1);
|
|
pane.addItem(item2);
|
|
});
|
|
|
|
it('changes the file path and file name data attributes on the pane if the active item path is changed', function() {
|
|
expect(paneElement.dataset.activeItemPath).toBe('/foo/bar.txt');
|
|
expect(paneElement.dataset.activeItemName).toBe('bar.txt');
|
|
|
|
item1.setPath('/foo/bar1.txt');
|
|
|
|
expect(paneElement.dataset.activeItemPath).toBe('/foo/bar1.txt');
|
|
expect(paneElement.dataset.activeItemName).toBe('bar1.txt');
|
|
|
|
pane.activateItem(item2);
|
|
|
|
expect(paneElement.dataset.activeItemPath).toBeUndefined();
|
|
expect(paneElement.dataset.activeItemName).toBeUndefined();
|
|
|
|
item1.setPath('/foo/bar2.txt');
|
|
|
|
expect(paneElement.dataset.activeItemPath).toBeUndefined();
|
|
expect(paneElement.dataset.activeItemName).toBeUndefined();
|
|
|
|
pane.activateItem(item1);
|
|
|
|
expect(paneElement.dataset.activeItemPath).toBe('/foo/bar2.txt');
|
|
expect(paneElement.dataset.activeItemName).toBe('bar2.txt');
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('when an item is removed from the pane', function() {
|
|
describe('when the destroyed item is an element', () =>
|
|
it('removes the item from the itemViews div', function() {
|
|
const item1 = document.createElement('div');
|
|
const item2 = document.createElement('div');
|
|
pane.addItem(item1);
|
|
pane.addItem(item2);
|
|
paneElement = pane.getElement();
|
|
|
|
expect(item1.parentElement).toBe(paneElement.itemViews);
|
|
pane.destroyItem(item1);
|
|
expect(item1.parentElement).toBeNull();
|
|
expect(item2.parentElement).toBe(paneElement.itemViews);
|
|
pane.destroyItem(item2);
|
|
expect(item2.parentElement).toBeNull();
|
|
}));
|
|
|
|
describe('when the destroyed item is a model', () =>
|
|
it("removes the model's associated view", function() {
|
|
class TestModel {}
|
|
|
|
atom.views.addViewProvider(TestModel, function(model) {
|
|
const view = document.createElement('div');
|
|
model.element = view;
|
|
view.model = model;
|
|
return view;
|
|
});
|
|
|
|
const item1 = new TestModel();
|
|
const item2 = new TestModel();
|
|
pane.addItem(item1);
|
|
pane.addItem(item2);
|
|
|
|
expect(item1.element.parentElement).toBe(paneElement.itemViews);
|
|
pane.destroyItem(item1);
|
|
expect(item1.element.parentElement).toBeNull();
|
|
expect(item2.element.parentElement).toBe(paneElement.itemViews);
|
|
pane.destroyItem(item2);
|
|
expect(item2.element.parentElement).toBeNull();
|
|
}));
|
|
});
|
|
|
|
describe('when the pane element is focused', function() {
|
|
it('transfers focus to the active view', function() {
|
|
const item = document.createElement('div');
|
|
item.tabIndex = -1;
|
|
pane.activateItem(item);
|
|
jasmine.attachToDOM(paneElement);
|
|
|
|
expect(document.activeElement).toBe(document.body);
|
|
paneElement.focus();
|
|
expect(document.activeElement).toBe(item);
|
|
|
|
document.body.focus();
|
|
pane.activate();
|
|
expect(document.activeElement).toBe(item);
|
|
});
|
|
|
|
it('makes the pane active', function() {
|
|
pane.splitRight();
|
|
expect(pane.isActive()).toBe(false);
|
|
|
|
jasmine.attachToDOM(paneElement);
|
|
paneElement.focus();
|
|
|
|
expect(pane.isActive()).toBe(true);
|
|
});
|
|
|
|
it('does not re-activate the pane when focus changes within the pane', function() {
|
|
const item = document.createElement('div');
|
|
const itemChild = document.createElement('div');
|
|
item.tabIndex = -1;
|
|
itemChild.tabIndex = -1;
|
|
item.appendChild(itemChild);
|
|
jasmine.attachToDOM(paneElement);
|
|
|
|
pane.activateItem(item);
|
|
pane.activate();
|
|
|
|
let activationCount = 0;
|
|
pane.onDidActivate(() => activationCount++);
|
|
|
|
itemChild.focus();
|
|
expect(activationCount).toBe(0);
|
|
});
|
|
});
|
|
|
|
describe('when the pane element is attached', () =>
|
|
it('focuses the pane element if isFocused() returns true on its model', function() {
|
|
pane.focus();
|
|
jasmine.attachToDOM(paneElement);
|
|
expect(document.activeElement).toBe(paneElement);
|
|
}));
|
|
|
|
describe('drag and drop', function() {
|
|
const buildDragEvent = function(type, files) {
|
|
const dataTransfer = {
|
|
files,
|
|
data: {},
|
|
setData(key, value) {
|
|
this.data[key] = value;
|
|
},
|
|
getData(key) {
|
|
return this.data[key];
|
|
}
|
|
};
|
|
|
|
const event = new CustomEvent('drop');
|
|
event.dataTransfer = dataTransfer;
|
|
return event;
|
|
};
|
|
|
|
describe('when a file is dragged to the pane', () =>
|
|
it('opens it', function() {
|
|
const event = buildDragEvent('drop', [
|
|
{ path: '/fake1' },
|
|
{ path: '/fake2' }
|
|
]);
|
|
paneElement.dispatchEvent(event);
|
|
expect(atom.applicationDelegate.open.callCount).toBe(1);
|
|
expect(atom.applicationDelegate.open.argsForCall[0][0]).toEqual({
|
|
pathsToOpen: ['/fake1', '/fake2'],
|
|
here: true
|
|
});
|
|
}));
|
|
|
|
describe('when a non-file is dragged to the pane', () =>
|
|
it('does nothing', function() {
|
|
const event = buildDragEvent('drop', []);
|
|
paneElement.dispatchEvent(event);
|
|
expect(atom.applicationDelegate.open).not.toHaveBeenCalled();
|
|
}));
|
|
});
|
|
|
|
describe('resize', () =>
|
|
it("shrinks independently of its contents' width", function() {
|
|
jasmine.attachToDOM(containerElement);
|
|
const item = document.createElement('div');
|
|
item.style.width = '2000px';
|
|
item.style.height = '30px';
|
|
paneElement.insertBefore(item, paneElement.children[0]);
|
|
|
|
paneElement.style.flexGrow = 0.1;
|
|
expect(paneElement.getBoundingClientRect().width).toBeGreaterThan(0);
|
|
expect(paneElement.getBoundingClientRect().width).toBeLessThan(
|
|
item.getBoundingClientRect().width
|
|
);
|
|
|
|
paneElement.style.flexGrow = 0;
|
|
expect(paneElement.getBoundingClientRect().width).toBe(0);
|
|
}));
|
|
});
|