shell.spec.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. // Copyright (c) Jupyter Development Team.
  2. // Distributed under the terms of the Modified BSD License.
  3. import { expect } from 'chai';
  4. import { Message } from '@phosphor/messaging';
  5. import { Widget } from '@phosphor/widgets';
  6. import { simulate } from 'simulate-event';
  7. import { ApplicationShell } from '@jupyterlab/application';
  8. class ContentWidget extends Widget {
  9. activated = false;
  10. onActivateRequest(msg: Message): void {
  11. this.activated = true;
  12. }
  13. }
  14. describe('ApplicationShell', () => {
  15. let shell: ApplicationShell;
  16. beforeEach(() => {
  17. shell = new ApplicationShell();
  18. Widget.attach(shell, document.body);
  19. });
  20. afterEach(() => {
  21. shell.dispose();
  22. });
  23. describe('#constructor()', () => {
  24. it('should create an ApplicationShell instance', () => {
  25. expect(shell).to.be.an.instanceof(ApplicationShell);
  26. });
  27. });
  28. describe('#leftCollapsed', () => {
  29. it('should return whether the left area is collapsed', () => {
  30. let widget = new Widget();
  31. widget.id = 'foo';
  32. shell.addToLeftArea(widget);
  33. expect(shell.leftCollapsed).to.equal(true);
  34. shell.activateById('foo');
  35. expect(shell.leftCollapsed).to.equal(false);
  36. });
  37. });
  38. describe('#rightCollapsed', () => {
  39. it('should return whether the right area is collapsed', () => {
  40. let widget = new Widget();
  41. widget.id = 'foo';
  42. shell.addToRightArea(widget);
  43. expect(shell.rightCollapsed).to.equal(true);
  44. shell.activateById('foo');
  45. expect(shell.rightCollapsed).to.equal(false);
  46. });
  47. });
  48. describe('#currentWidget', () => {
  49. it('should be the current widget in the shell main area', () => {
  50. expect(shell.currentWidget).to.equal(null);
  51. let widget = new Widget();
  52. widget.node.tabIndex = -1;
  53. widget.id = 'foo';
  54. shell.addToMainArea(widget);
  55. expect(shell.currentWidget).to.equal(null);
  56. simulate(widget.node, 'focus');
  57. expect(shell.currentWidget).to.equal(widget);
  58. widget.parent = null;
  59. expect(shell.currentWidget).to.equal(null);
  60. });
  61. });
  62. describe('#isEmpty()', () => {
  63. it('should test whether the main area is empty', () => {
  64. expect(shell.isEmpty('top')).to.equal(true);
  65. let widget = new Widget();
  66. widget.id = 'foo';
  67. shell.addToMainArea(widget);
  68. expect(shell.isEmpty('main')).to.equal(false);
  69. });
  70. it('should test whether the top area is empty', () => {
  71. expect(shell.isEmpty('top')).to.equal(true);
  72. let widget = new Widget();
  73. widget.id = 'foo';
  74. shell.addToTopArea(widget);
  75. expect(shell.isEmpty('top')).to.equal(false);
  76. });
  77. it('should test whether the left area is empty', () => {
  78. expect(shell.isEmpty('left')).to.equal(true);
  79. let widget = new Widget();
  80. widget.id = 'foo';
  81. shell.addToLeftArea(widget);
  82. expect(shell.isEmpty('left')).to.equal(false);
  83. });
  84. it('should test whether the right area is empty', () => {
  85. expect(shell.isEmpty('right')).to.equal(true);
  86. let widget = new Widget();
  87. widget.id = 'foo';
  88. shell.addToRightArea(widget);
  89. expect(shell.isEmpty('right')).to.equal(false);
  90. });
  91. });
  92. describe('#restored', () => {
  93. it('should resolve when the app is restored for the first time', () => {
  94. let state = shell.saveLayout();
  95. shell.restoreLayout(state);
  96. return shell.restored;
  97. });
  98. });
  99. describe('#addToTopArea()', () => {
  100. it('should add a widget to the top area', () => {
  101. let widget = new Widget();
  102. widget.id = 'foo';
  103. shell.addToTopArea(widget);
  104. expect(shell.isEmpty('top')).to.equal(false);
  105. });
  106. it('should be a no-op if the widget has no id', () => {
  107. let widget = new Widget();
  108. shell.addToTopArea(widget);
  109. expect(shell.isEmpty('top')).to.equal(true);
  110. });
  111. it('should accept options', () => {
  112. let widget = new Widget();
  113. widget.id = 'foo';
  114. shell.addToTopArea(widget, { rank: 10 });
  115. expect(shell.isEmpty('top')).to.equal(false);
  116. });
  117. });
  118. describe('#addToLeftArea()', () => {
  119. it('should add a widget to the left area', () => {
  120. let widget = new Widget();
  121. widget.id = 'foo';
  122. shell.addToLeftArea(widget);
  123. expect(shell.isEmpty('left')).to.equal(false);
  124. });
  125. it('should be a no-op if the widget has no id', () => {
  126. let widget = new Widget();
  127. shell.addToLeftArea(widget);
  128. expect(shell.isEmpty('left')).to.equal(true);
  129. });
  130. it('should accept options', () => {
  131. let widget = new Widget();
  132. widget.id = 'foo';
  133. shell.addToLeftArea(widget, { rank: 10 });
  134. expect(shell.isEmpty('left')).to.equal(false);
  135. });
  136. });
  137. describe('#addToRightArea()', () => {
  138. it('should add a widget to the right area', () => {
  139. let widget = new Widget();
  140. widget.id = 'foo';
  141. shell.addToRightArea(widget);
  142. expect(shell.isEmpty('right')).to.equal(false);
  143. });
  144. it('should be a no-op if the widget has no id', () => {
  145. let widget = new Widget();
  146. shell.addToRightArea(widget);
  147. expect(shell.isEmpty('right')).to.equal(true);
  148. });
  149. it('should accept options', () => {
  150. let widget = new Widget();
  151. widget.id = 'foo';
  152. shell.addToRightArea(widget, { rank: 10 });
  153. expect(shell.isEmpty('right')).to.equal(false);
  154. });
  155. });
  156. describe('#addToMainArea()', () => {
  157. it('should add a widget to the main area', () => {
  158. let widget = new Widget();
  159. widget.id = 'foo';
  160. shell.addToMainArea(widget);
  161. expect(shell.isEmpty('main')).to.equal(false);
  162. });
  163. it('should be a no-op if the widget has no id', () => {
  164. let widget = new Widget();
  165. shell.addToMainArea(widget);
  166. expect(shell.isEmpty('main')).to.equal(true);
  167. });
  168. });
  169. describe('#activateById()', () => {
  170. it('should activate a widget in the left area', () => {
  171. let widget = new Widget();
  172. widget.id = 'foo';
  173. shell.addToLeftArea(widget);
  174. expect(widget.isVisible).to.equal(false);
  175. shell.activateById('foo');
  176. expect(widget.isVisible).to.equal(true);
  177. });
  178. it('should be a no-op if the widget is not in the left area', () => {
  179. let widget = new Widget();
  180. widget.id = 'foo';
  181. expect(widget.isVisible).to.equal(false);
  182. shell.activateById('foo');
  183. expect(widget.isVisible).to.equal(false);
  184. });
  185. it('should activate a widget in the right area', () => {
  186. let widget = new Widget();
  187. widget.id = 'foo';
  188. shell.addToRightArea(widget);
  189. expect(widget.isVisible).to.equal(false);
  190. shell.activateById('foo');
  191. expect(widget.isVisible).to.equal(true);
  192. });
  193. it('should be a no-op if the widget is not in the right area', () => {
  194. let widget = new Widget();
  195. widget.id = 'foo';
  196. expect(widget.isVisible).to.equal(false);
  197. shell.activateById('foo');
  198. expect(widget.isVisible).to.equal(false);
  199. });
  200. it('should activate a widget in the main area', done => {
  201. let widget = new ContentWidget();
  202. widget.id = 'foo';
  203. shell.addToMainArea(widget);
  204. shell.activateById('foo');
  205. requestAnimationFrame(() => {
  206. expect(widget.activated).to.equal(true);
  207. done();
  208. });
  209. });
  210. it('should be a no-op if the widget is not in the main area', done => {
  211. let widget = new ContentWidget();
  212. widget.id = 'foo';
  213. shell.activateById('foo');
  214. requestAnimationFrame(() => {
  215. expect(widget.activated).to.equal(false);
  216. done();
  217. });
  218. });
  219. });
  220. describe('#collapseLeft()', () => {
  221. it('should collapse all widgets in the left area', () => {
  222. let widget = new Widget();
  223. widget.id = 'foo';
  224. shell.addToLeftArea(widget);
  225. shell.activateById('foo');
  226. expect(widget.isVisible).to.equal(true);
  227. shell.collapseLeft();
  228. expect(widget.isVisible).to.equal(false);
  229. });
  230. });
  231. describe('#collapseRight()', () => {
  232. it('should collapse all widgets in the right area', () => {
  233. let widget = new Widget();
  234. widget.id = 'foo';
  235. shell.addToRightArea(widget);
  236. shell.activateById('foo');
  237. expect(widget.isVisible).to.equal(true);
  238. shell.collapseRight();
  239. expect(widget.isVisible).to.equal(false);
  240. });
  241. });
  242. describe('#expandLeft()', () => {
  243. it('should expand the most recently used widget', () => {
  244. let widget = new Widget();
  245. widget.id = 'foo';
  246. let widget2 = new Widget();
  247. widget2.id = 'bar';
  248. shell.addToLeftArea(widget, { rank: 10 });
  249. shell.addToLeftArea(widget2, { rank: 1 });
  250. shell.activateById('foo');
  251. shell.collapseLeft();
  252. expect(widget.isVisible).to.equal(false);
  253. shell.expandLeft();
  254. expect(widget.isVisible).to.equal(true);
  255. });
  256. it('should expand the first widget if none have been activated', () => {
  257. let widget = new Widget();
  258. widget.id = 'foo';
  259. let widget2 = new Widget();
  260. widget2.id = 'bar';
  261. shell.addToLeftArea(widget, { rank: 10 });
  262. shell.addToLeftArea(widget2, { rank: 1 });
  263. expect(widget2.isVisible).to.equal(false);
  264. shell.expandLeft();
  265. expect(widget2.isVisible).to.equal(true);
  266. });
  267. });
  268. describe('#expandRight()', () => {
  269. it('should expand the most recently used widget', () => {
  270. let widget = new Widget();
  271. widget.id = 'foo';
  272. let widget2 = new Widget();
  273. widget2.id = 'bar';
  274. shell.addToRightArea(widget, { rank: 10 });
  275. shell.addToRightArea(widget2, { rank: 1 });
  276. shell.activateById('foo');
  277. shell.collapseRight();
  278. expect(widget.isVisible).to.equal(false);
  279. shell.expandRight();
  280. expect(widget.isVisible).to.equal(true);
  281. });
  282. it('should expand the first widget if none have been activated', () => {
  283. let widget = new Widget();
  284. widget.id = 'foo';
  285. let widget2 = new Widget();
  286. widget2.id = 'bar';
  287. shell.addToRightArea(widget, { rank: 10 });
  288. shell.addToRightArea(widget2, { rank: 1 });
  289. expect(widget2.isVisible).to.equal(false);
  290. shell.expandRight();
  291. expect(widget2.isVisible).to.equal(true);
  292. });
  293. });
  294. describe('#closeAll()', () => {
  295. it('should close all of the widgets in the main area', () => {
  296. let foo = new Widget();
  297. foo.id = 'foo';
  298. shell.addToMainArea(foo);
  299. let bar = new Widget();
  300. bar.id = 'bar';
  301. shell.addToMainArea(bar);
  302. shell.closeAll();
  303. expect(foo.parent).to.equal(null);
  304. expect(bar.parent).to.equal(null);
  305. });
  306. });
  307. describe('#saveLayout', () => {
  308. it('should save the layout of the shell', () => {
  309. let foo = new Widget();
  310. foo.id = 'foo';
  311. shell.addToMainArea(foo);
  312. let state = shell.saveLayout();
  313. shell.activateById('foo');
  314. expect(state.mainArea.mode).to.equal('multiple-document');
  315. expect(state.mainArea.currentWidget).to.equal(null);
  316. });
  317. });
  318. describe('#restoreLayout', () => {
  319. it('should restore the layout of the shell', () => {
  320. let state = shell.saveLayout();
  321. shell.mode = 'single-document';
  322. shell.restoreLayout(state);
  323. expect(state.mainArea.mode).to.equal('multiple-document');
  324. });
  325. });
  326. });