default-toolbar.spec.ts 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. // Copyright (c) Jupyter Development Team.
  2. // Distributed under the terms of the Modified BSD License.
  3. import expect = require('expect.js');
  4. import {
  5. toArray
  6. } from '@phosphor/algorithm';
  7. import {
  8. PromiseDelegate
  9. } from '@phosphor/coreutils';
  10. import {
  11. Widget
  12. } from '@phosphor/widgets';
  13. import {
  14. Context
  15. } from '@jupyterlab/docregistry';
  16. import {
  17. CodeCell, MarkdownCell
  18. } from '@jupyterlab/cells';
  19. import {
  20. NotebookActions
  21. } from '@jupyterlab/notebook';
  22. import {
  23. ToolbarItems
  24. } from '@jupyterlab/notebook';
  25. import {
  26. INotebookModel
  27. } from '@jupyterlab/notebook';
  28. import {
  29. NotebookPanel
  30. } from '@jupyterlab/notebook';
  31. import {
  32. createNotebookContext, moment
  33. } from '../../utils';
  34. import {
  35. DEFAULT_CONTENT, clipboard, createNotebookPanel
  36. } from '../../notebook-utils';
  37. const JUPYTER_CELL_MIME = 'application/vnd.jupyter.cells';
  38. describe('@jupyterlab/notebook', () => {
  39. describe('ToolbarItems', () => {
  40. let context: Context<INotebookModel>;
  41. let panel: NotebookPanel;
  42. beforeEach(async () => {
  43. context = await createNotebookContext();
  44. await context.initialize(true);
  45. panel = createNotebookPanel(context);
  46. context.model.fromJSON(DEFAULT_CONTENT);
  47. });
  48. afterEach(async () => {
  49. await context.session.shutdown();
  50. context.dispose();
  51. panel.dispose();
  52. });
  53. describe('#createSaveButton()', () => {
  54. it('should save when clicked', (done) => {
  55. let button = ToolbarItems.createSaveButton(panel);
  56. Widget.attach(button, document.body);
  57. context.fileChanged.connect(() => {
  58. button.dispose();
  59. done();
  60. });
  61. button.node.click();
  62. });
  63. it('should have the `\'jp-SaveIcon\'` class', () => {
  64. let button = ToolbarItems.createSaveButton(panel);
  65. expect(button.hasClass('jp-SaveIcon')).to.be(true);
  66. });
  67. });
  68. describe('#createInsertButton()', () => {
  69. it('should insert below when clicked', () => {
  70. let button = ToolbarItems.createInsertButton(panel);
  71. Widget.attach(button, document.body);
  72. button.node.click();
  73. expect(panel.content.activeCellIndex).to.be(1);
  74. expect(panel.content.activeCell).to.be.a(CodeCell);
  75. button.dispose();
  76. });
  77. it('should have the `\'jp-AddIcon\'` class', () => {
  78. let button = ToolbarItems.createInsertButton(panel);
  79. expect(button.hasClass('jp-AddIcon')).to.be(true);
  80. });
  81. });
  82. describe('#createCutButton()', () => {
  83. it('should cut when clicked', () => {
  84. let button = ToolbarItems.createCutButton(panel);
  85. let count = panel.content.widgets.length;
  86. Widget.attach(button, document.body);
  87. button.node.click();
  88. expect(panel.content.widgets.length).to.be(count - 1);
  89. expect(clipboard.hasData(JUPYTER_CELL_MIME)).to.be(true);
  90. button.dispose();
  91. });
  92. it('should have the `\'jp-CutIcon\'` class', () => {
  93. let button = ToolbarItems.createCutButton(panel);
  94. expect(button.hasClass('jp-CutIcon')).to.be(true);
  95. });
  96. });
  97. describe('#createCopyButton()', () => {
  98. it('should copy when clicked', () => {
  99. let button = ToolbarItems.createCopyButton(panel);
  100. let count = panel.content.widgets.length;
  101. Widget.attach(button, document.body);
  102. button.node.click();
  103. expect(panel.content.widgets.length).to.be(count);
  104. expect(clipboard.hasData(JUPYTER_CELL_MIME)).to.be(true);
  105. button.dispose();
  106. });
  107. it('should have the `\'jp-CopyIcon\'` class', () => {
  108. let button = ToolbarItems.createCopyButton(panel);
  109. expect(button.hasClass('jp-CopyIcon')).to.be(true);
  110. });
  111. });
  112. describe('#createPasteButton()', () => {
  113. it('should paste when clicked', async () => {
  114. let button = ToolbarItems.createPasteButton(panel);
  115. let count = panel.content.widgets.length;
  116. Widget.attach(button, document.body);
  117. NotebookActions.copy(panel.content);
  118. button.node.click();
  119. await moment();
  120. expect(panel.content.widgets.length).to.be(count + 1);
  121. button.dispose();
  122. });
  123. it('should have the `\'jp-PasteIcon\'` class', () => {
  124. let button = ToolbarItems.createPasteButton(panel);
  125. expect(button.hasClass('jp-PasteIcon')).to.be(true);
  126. });
  127. });
  128. describe('#createRunButton()', () => {
  129. it('should run and advance when clicked', async () => {
  130. let button = ToolbarItems.createRunButton(panel);
  131. let widget = panel.content;
  132. // Clear and select the first two cells.
  133. const codeCell = widget.widgets[0] as CodeCell;
  134. codeCell.model.outputs.clear();
  135. widget.select(codeCell);
  136. const mdCell = widget.widgets[1] as MarkdownCell;
  137. mdCell.rendered = false;
  138. widget.select(mdCell);
  139. Widget.attach(button, document.body);
  140. await context.ready;
  141. await context.session.ready;
  142. await context.session.kernel.ready;
  143. const p = new PromiseDelegate();
  144. context.session.statusChanged.connect((sender, status) => {
  145. // Find the right status idle message
  146. if (status === 'idle' && codeCell.model.outputs.length > 0) {
  147. expect(mdCell.rendered).to.be(true);
  148. expect(widget.activeCellIndex).to.equal(2);
  149. button.dispose();
  150. p.resolve(0);
  151. }
  152. });
  153. button.node.click();
  154. await p.promise;
  155. });
  156. it('should have the `\'jp-RunIcon\'` class', () => {
  157. let button = ToolbarItems.createRunButton(panel);
  158. expect(button.hasClass('jp-RunIcon')).to.be(true);
  159. });
  160. });
  161. describe('#createCellTypeItem()', () => {
  162. it('should track the cell type of the current cell', () => {
  163. let item = ToolbarItems.createCellTypeItem(panel);
  164. let node = item.node.getElementsByTagName('select')[0] as HTMLSelectElement;
  165. expect(node.value).to.be('code');
  166. panel.content.activeCellIndex++;
  167. expect(node.value).to.be('markdown');
  168. });
  169. it('should display `\'-\'` if multiple cell types are selected', () => {
  170. let item = ToolbarItems.createCellTypeItem(panel);
  171. let node = item.node.getElementsByTagName('select')[0] as HTMLSelectElement;
  172. expect(node.value).to.be('code');
  173. panel.content.select(panel.content.widgets[1]);
  174. expect(node.value).to.be('-');
  175. });
  176. it('should display the active cell type if multiple cells of the same type are selected', () => {
  177. let item = ToolbarItems.createCellTypeItem(panel);
  178. let node = item.node.getElementsByTagName('select')[0] as HTMLSelectElement;
  179. expect(node.value).to.be('code');
  180. let cell = panel.model.contentFactory.createCodeCell({});
  181. panel.model.cells.insert(1, cell);
  182. panel.content.select(panel.content.widgets[1]);
  183. expect(node.value).to.be('code');
  184. });
  185. });
  186. describe('#populateDefaults()', () => {
  187. it('should add the default items to the panel toolbar', () => {
  188. ToolbarItems.populateDefaults(panel);
  189. expect(toArray(panel.toolbar.names())).to.eql(['save', 'insert', 'cut',
  190. 'copy', 'paste', 'run', 'interrupt', 'restart', 'cellType',
  191. 'spacer', 'kernelName', 'kernelStatus']);
  192. });
  193. });
  194. });
  195. });