Browse Source

Add restart kernel and run all to default toolbar items

To achieve a more faithful about duplicating the jupyter notebook
toolbar.

Add tests while we are at it.

Related: #7935
Ryan Tam 5 years ago
parent
commit
63d9fced35

+ 30 - 1
packages/notebook/src/default-toolbar.tsx

@@ -13,7 +13,9 @@ import {
   addToolbarButtonClass,
   ReactWidget,
   ToolbarButton,
-  ISessionContextDialogs
+  ISessionContextDialogs,
+  ISessionContext,
+  sessionContextDialogs
 } from '@jupyterlab/apputils';
 import { DocumentRegistry } from '@jupyterlab/docregistry';
 import * as nbformat from '@jupyterlab/nbformat';
@@ -21,6 +23,7 @@ import {
   addIcon,
   copyIcon,
   cutIcon,
+  fastForwardIcon,
   HTMLSelect,
   pasteIcon,
   runIcon,
@@ -150,6 +153,28 @@ export namespace ToolbarItems {
       tooltip: 'Run the selected cells and advance'
     });
   }
+  /**
+   * Create a restart run all toolbar item
+   */
+  export function createRestartRunAllButton(
+    panel: NotebookPanel,
+    dialogs?: ISessionContext.IDialogs
+  ): Widget {
+    return new ToolbarButton({
+      icon: fastForwardIcon,
+      onClick: () => {
+        void (dialogs ?? sessionContextDialogs)
+          .restart(panel.sessionContext)
+          .then(restarted => {
+            if (restarted) {
+              void NotebookActions.runAll(panel.content, panel.sessionContext);
+            }
+            return restarted;
+          });
+      },
+      tooltip: 'Restart the kernel, then re-run the whole notebook'
+    });
+  }
 
   /**
    * Create a cell type switcher item.
@@ -191,6 +216,10 @@ export namespace ToolbarItems {
           sessionDialogs
         )
       },
+      {
+        name: 'restart-and-run',
+        widget: createRestartRunAllButton(panel, sessionDialogs)
+      },
       { name: 'cellType', widget: createCellTypeItem(panel) },
       { name: 'spacer', widget: Toolbar.createSpacerItem() },
       {

+ 46 - 1
tests/test-notebook/src/default-toolbar.spec.ts

@@ -25,7 +25,8 @@ import {
   signalToPromise,
   sleep,
   NBTestUtils,
-  framePromise
+  framePromise,
+  acceptDialog
 } from '@jupyterlab/testutils';
 
 const JUPYTER_CELL_MIME = 'application/vnd.jupyter.cells';
@@ -216,6 +217,7 @@ describe('@jupyterlab/notebook', () => {
             'run',
             'interrupt',
             'restart',
+            'restart-and-run',
             'cellType',
             'spacer',
             'kernelName',
@@ -279,6 +281,49 @@ describe('@jupyterlab/notebook', () => {
           expect(button.node.querySelector("[data-icon$='run']")).to.exist;
         });
       });
+
+      describe('#createRestartRunAllButton()', () => {
+        it('should restart and run all when clicked', async () => {
+          const button = ToolbarItems.createRestartRunAllButton(panel);
+          const widget = panel.content;
+
+          // Clear the first two cells.
+          const codeCell = widget.widgets[0] as CodeCell;
+          codeCell.model.outputs.clear();
+          const mdCell = widget.widgets[1] as MarkdownCell;
+          mdCell.rendered = false;
+
+          Widget.attach(button, document.body);
+          const p = new PromiseDelegate();
+          context.sessionContext.statusChanged.connect((sender, status) => {
+            // Find the right status idle message
+            if (status === 'idle' && codeCell.model.outputs.length > 0) {
+              expect(
+                widget.widgets
+                  .filter(cell => cell.model.type === 'markdown')
+                  .every(cell => (cell as MarkdownCell).rendered)
+              );
+              expect(widget.activeCellIndex).to.equal(
+                widget.widgets.filter(cell => cell.model.type === 'code').length
+              );
+              button.dispose();
+              p.resolve(0);
+            }
+          });
+          await framePromise();
+          simulate(button.node.firstChild as HTMLElement, 'mousedown');
+          await acceptDialog();
+          await p.promise;
+        }).timeout(30000); // Allow for slower CI
+
+        it("should add an inline svg node with the 'fast-forward' icon", async () => {
+          const button = ToolbarItems.createRestartRunAllButton(panel);
+          Widget.attach(button, document.body);
+          await framePromise();
+          expect(button.node.querySelector("[data-icon$='fast-forward']")).to
+            .exist;
+        });
+      });
     });
   });
 });