panel-container-element-spec.js 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. 'use strict';
  2. const Panel = require('../src/panel');
  3. const PanelContainer = require('../src/panel-container');
  4. describe('PanelContainerElement', () => {
  5. let jasmineContent, element, container;
  6. class TestPanelContainerItem {}
  7. class TestPanelContainerItemElement_ extends HTMLElement {
  8. connectedCallback() {
  9. this.classList.add('test-root');
  10. }
  11. initialize(model) {
  12. this.model = model;
  13. return this;
  14. }
  15. focus() {}
  16. }
  17. window.customElements.define(
  18. 'atom-test-container-item-element',
  19. TestPanelContainerItemElement_
  20. );
  21. const TestPanelContainerItemElement = document.createElement(
  22. 'atom-test-container-item-element'
  23. );
  24. beforeEach(() => {
  25. jasmineContent = document.body.querySelector('#jasmine-content');
  26. atom.views.addViewProvider(TestPanelContainerItem, model =>
  27. TestPanelContainerItemElement.initialize(model)
  28. );
  29. container = new PanelContainer({
  30. viewRegistry: atom.views,
  31. location: 'left'
  32. });
  33. element = container.getElement();
  34. jasmineContent.appendChild(element);
  35. });
  36. it('has a location class with value from the model', () => {
  37. expect(element).toHaveClass('left');
  38. });
  39. it('removes the element when the container is destroyed', () => {
  40. expect(element.parentNode).toBe(jasmineContent);
  41. container.destroy();
  42. expect(element.parentNode).not.toBe(jasmineContent);
  43. });
  44. describe('adding and removing panels', () => {
  45. it('allows panels to be inserted at any position', () => {
  46. const panel1 = new Panel(
  47. { item: new TestPanelContainerItem(), priority: 10 },
  48. atom.views
  49. );
  50. const panel2 = new Panel(
  51. { item: new TestPanelContainerItem(), priority: 5 },
  52. atom.views
  53. );
  54. const panel3 = new Panel(
  55. { item: new TestPanelContainerItem(), priority: 8 },
  56. atom.views
  57. );
  58. container.addPanel(panel1);
  59. container.addPanel(panel2);
  60. container.addPanel(panel3);
  61. expect(element.childNodes[2]).toBe(panel1.getElement());
  62. expect(element.childNodes[1]).toBe(panel3.getElement());
  63. expect(element.childNodes[0]).toBe(panel2.getElement());
  64. });
  65. describe('when the container is at the left location', () =>
  66. it('adds atom-panel elements when a new panel is added to the container; removes them when the panels are destroyed', () => {
  67. expect(element.childNodes.length).toBe(0);
  68. const panel1 = new Panel(
  69. { item: new TestPanelContainerItem() },
  70. atom.views
  71. );
  72. container.addPanel(panel1);
  73. expect(element.childNodes.length).toBe(1);
  74. expect(element.childNodes[0]).toHaveClass('left');
  75. expect(element.childNodes[0]).toHaveClass('tool-panel'); // legacy selector support
  76. expect(element.childNodes[0]).toHaveClass('panel-left'); // legacy selector support
  77. expect(element.childNodes[0].tagName).toBe('ATOM-PANEL');
  78. const panel2 = new Panel(
  79. { item: new TestPanelContainerItem() },
  80. atom.views
  81. );
  82. container.addPanel(panel2);
  83. expect(element.childNodes.length).toBe(2);
  84. expect(panel1.getElement().style.display).not.toBe('none');
  85. expect(panel2.getElement().style.display).not.toBe('none');
  86. panel1.destroy();
  87. expect(element.childNodes.length).toBe(1);
  88. panel2.destroy();
  89. expect(element.childNodes.length).toBe(0);
  90. }));
  91. describe('when the container is at the bottom location', () => {
  92. beforeEach(() => {
  93. container = new PanelContainer({
  94. viewRegistry: atom.views,
  95. location: 'bottom'
  96. });
  97. element = container.getElement();
  98. jasmineContent.appendChild(element);
  99. });
  100. it('adds atom-panel elements when a new panel is added to the container; removes them when the panels are destroyed', () => {
  101. expect(element.childNodes.length).toBe(0);
  102. const panel1 = new Panel(
  103. { item: new TestPanelContainerItem(), className: 'one' },
  104. atom.views
  105. );
  106. container.addPanel(panel1);
  107. expect(element.childNodes.length).toBe(1);
  108. expect(element.childNodes[0]).toHaveClass('bottom');
  109. expect(element.childNodes[0]).toHaveClass('tool-panel'); // legacy selector support
  110. expect(element.childNodes[0]).toHaveClass('panel-bottom'); // legacy selector support
  111. expect(element.childNodes[0].tagName).toBe('ATOM-PANEL');
  112. expect(panel1.getElement()).toHaveClass('one');
  113. const panel2 = new Panel(
  114. { item: new TestPanelContainerItem(), className: 'two' },
  115. atom.views
  116. );
  117. container.addPanel(panel2);
  118. expect(element.childNodes.length).toBe(2);
  119. expect(panel2.getElement()).toHaveClass('two');
  120. panel1.destroy();
  121. expect(element.childNodes.length).toBe(1);
  122. panel2.destroy();
  123. expect(element.childNodes.length).toBe(0);
  124. });
  125. });
  126. });
  127. describe('when the container is modal', () => {
  128. beforeEach(() => {
  129. container = new PanelContainer({
  130. viewRegistry: atom.views,
  131. location: 'modal'
  132. });
  133. element = container.getElement();
  134. jasmineContent.appendChild(element);
  135. });
  136. it('allows only one panel to be visible at a time', () => {
  137. const panel1 = new Panel(
  138. { item: new TestPanelContainerItem() },
  139. atom.views
  140. );
  141. container.addPanel(panel1);
  142. expect(panel1.getElement().style.display).not.toBe('none');
  143. const panel2 = new Panel(
  144. { item: new TestPanelContainerItem() },
  145. atom.views
  146. );
  147. container.addPanel(panel2);
  148. expect(panel1.getElement().style.display).toBe('none');
  149. expect(panel2.getElement().style.display).not.toBe('none');
  150. panel1.show();
  151. expect(panel1.getElement().style.display).not.toBe('none');
  152. expect(panel2.getElement().style.display).toBe('none');
  153. });
  154. it("adds the 'modal' class to panels", () => {
  155. const panel1 = new Panel(
  156. { item: new TestPanelContainerItem() },
  157. atom.views
  158. );
  159. container.addPanel(panel1);
  160. expect(panel1.getElement()).toHaveClass('modal');
  161. // legacy selector support
  162. expect(panel1.getElement()).not.toHaveClass('tool-panel');
  163. expect(panel1.getElement()).toHaveClass('overlay');
  164. expect(panel1.getElement()).toHaveClass('from-top');
  165. });
  166. describe('autoFocus', () => {
  167. function createPanel(autoFocus = true) {
  168. const panel = new Panel(
  169. {
  170. item: new TestPanelContainerItem(),
  171. autoFocus: autoFocus,
  172. visible: false
  173. },
  174. atom.views
  175. );
  176. container.addPanel(panel);
  177. return panel;
  178. }
  179. it('focuses the first tabbable item if available', () => {
  180. const panel = createPanel();
  181. const panelEl = panel.getElement();
  182. const inputEl = document.createElement('input');
  183. panelEl.appendChild(inputEl);
  184. expect(document.activeElement).not.toBe(inputEl);
  185. panel.show();
  186. expect(document.activeElement).toBe(inputEl);
  187. panel.destroy();
  188. });
  189. it('focuses the autoFocus element if available', () => {
  190. const inputEl1 = document.createElement('input');
  191. const inputEl2 = document.createElement('input');
  192. const panel = createPanel(inputEl2);
  193. const panelEl = panel.getElement();
  194. panelEl.appendChild(inputEl1);
  195. panelEl.appendChild(inputEl2);
  196. expect(document.activeElement).not.toBe(inputEl2);
  197. panel.show();
  198. expect(document.activeElement).toBe(inputEl2);
  199. panel.destroy();
  200. });
  201. it('focuses the entire panel item when no tabbable item is available and the panel is focusable', () => {
  202. const panel = createPanel();
  203. const panelEl = panel.getElement();
  204. spyOn(panelEl, 'focus');
  205. panel.show();
  206. expect(panelEl.focus).toHaveBeenCalled();
  207. panel.destroy()
  208. });
  209. it('returns focus to the original activeElement', () => {
  210. const panel = createPanel();
  211. const previousActiveElement = document.activeElement;
  212. const panelEl = panel.getElement();
  213. panelEl.appendChild(document.createElement('input'));
  214. panel.show();
  215. panel.hide();
  216. waitsFor(() => document.activeElement === previousActiveElement);
  217. runs(() => {
  218. expect(document.activeElement).toBe(previousActiveElement);
  219. });
  220. });
  221. });
  222. });
  223. });