123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343 |
- // Copyright (c) Jupyter Development Team.
- import 'jest';
- import { simulate } from 'simulate-event';
- import { PromiseDelegate } from '@lumino/coreutils';
- import { Widget } from '@lumino/widgets';
- import { Context } from '@jupyterlab/docregistry';
- import { CodeCell, MarkdownCell } from '@jupyterlab/cells';
- import {
- INotebookModel,
- NotebookActions,
- NotebookPanel,
- ToolbarItems
- } from '../src';
- import {
- initNotebookContext,
- signalToPromise,
- sleep,
- framePromise,
- acceptDialog
- } from '@jupyterlab/testutils';
- import { JupyterServer } from '@jupyterlab/testutils/lib/start_jupyter_server';
- import * as utils from './utils';
- const JUPYTER_CELL_MIME = 'application/vnd.jupyter.cells';
- const server = new JupyterServer();
- beforeAll(async () => {
- jest.setTimeout(20000);
- await server.start();
- });
- afterAll(async () => {
- await server.shutdown();
- });
- describe('@jupyterlab/notebook', () => {
- describe('ToolbarItems', () => {
- describe('noKernel', () => {
- let context: Context<INotebookModel>;
- let panel: NotebookPanel;
- beforeEach(async () => {
- context = await initNotebookContext();
- panel = utils.createNotebookPanel(context);
- context.model.fromJSON(utils.DEFAULT_CONTENT);
- });
- afterEach(() => {
- panel.dispose();
- context.dispose();
- });
- describe('#createSaveButton()', () => {
- it('should save when clicked', async () => {
- const button = ToolbarItems.createSaveButton(panel);
- Widget.attach(button, document.body);
- const promise = signalToPromise(context.fileChanged);
- await framePromise();
- simulate(button.node.firstChild as HTMLElement, 'mousedown');
- await promise;
- button.dispose();
- });
- it("should add an inline svg node with the 'save' icon", async () => {
- const button = ToolbarItems.createSaveButton(panel);
- Widget.attach(button, document.body);
- await framePromise();
- expect(
- button.node.querySelector("[data-icon$='save']")
- ).toBeDefined();
- });
- });
- describe('#createInsertButton()', () => {
- it('should insert below when clicked', async () => {
- const button = ToolbarItems.createInsertButton(panel);
- Widget.attach(button, document.body);
- await framePromise();
- simulate(button.node.firstChild as HTMLElement, 'mousedown');
- expect(panel.content.activeCellIndex).toBe(1);
- expect(panel.content.activeCell).toBeInstanceOf(CodeCell);
- button.dispose();
- });
- it("should add an inline svg node with the 'add' icon", async () => {
- const button = ToolbarItems.createInsertButton(panel);
- Widget.attach(button, document.body);
- await framePromise();
- expect(button.node.querySelector("[data-icon$='add']")).toBeDefined();
- button.dispose();
- });
- });
- describe('#createCutButton()', () => {
- it('should cut when clicked', async () => {
- const button = ToolbarItems.createCutButton(panel);
- const count = panel.content.widgets.length;
- Widget.attach(button, document.body);
- await framePromise();
- simulate(button.node.firstChild as HTMLElement, 'mousedown');
- expect(panel.content.widgets.length).toBe(count - 1);
- expect(utils.clipboard.hasData(JUPYTER_CELL_MIME)).toBe(true);
- button.dispose();
- });
- it("should add an inline svg node with the 'cut' icon", async () => {
- const button = ToolbarItems.createCutButton(panel);
- Widget.attach(button, document.body);
- await framePromise();
- expect(button.node.querySelector("[data-icon$='cut']")).toBeDefined();
- button.dispose();
- });
- });
- describe('#createCopyButton()', () => {
- it('should copy when clicked', async () => {
- const button = ToolbarItems.createCopyButton(panel);
- const count = panel.content.widgets.length;
- Widget.attach(button, document.body);
- await framePromise();
- simulate(button.node.firstChild as HTMLElement, 'mousedown');
- expect(panel.content.widgets.length).toBe(count);
- expect(utils.clipboard.hasData(JUPYTER_CELL_MIME)).toBe(true);
- button.dispose();
- });
- it("should add an inline svg node with the 'copy' icon", async () => {
- const button = ToolbarItems.createCopyButton(panel);
- Widget.attach(button, document.body);
- await framePromise();
- expect(
- button.node.querySelector("[data-icon$='copy']")
- ).toBeDefined();
- button.dispose();
- });
- });
- describe('#createPasteButton()', () => {
- it('should paste when clicked', async () => {
- const button = ToolbarItems.createPasteButton(panel);
- const count = panel.content.widgets.length;
- Widget.attach(button, document.body);
- await framePromise();
- NotebookActions.copy(panel.content);
- simulate(button.node.firstChild as HTMLElement, 'mousedown');
- await sleep();
- expect(panel.content.widgets.length).toBe(count + 1);
- button.dispose();
- });
- it("should add an inline svg node with the 'paste' icon", async () => {
- const button = ToolbarItems.createPasteButton(panel);
- Widget.attach(button, document.body);
- await framePromise();
- expect(
- button.node.querySelector("[data-icon$='paste']")
- ).toBeDefined();
- button.dispose();
- });
- });
- describe('#createCellTypeItem()', () => {
- it('should track the cell type of the current cell', async () => {
- const item = ToolbarItems.createCellTypeItem(panel);
- Widget.attach(item, document.body);
- await framePromise();
- const node = item.node.getElementsByTagName(
- 'select'
- )[0] as HTMLSelectElement;
- expect(node.value).toBe('code');
- panel.content.activeCellIndex++;
- await framePromise();
- expect(node.value).toBe('markdown');
- item.dispose();
- });
- it("should display `'-'` if multiple cell types are selected", async () => {
- const item = ToolbarItems.createCellTypeItem(panel);
- Widget.attach(item, document.body);
- await framePromise();
- const node = item.node.getElementsByTagName(
- 'select'
- )[0] as HTMLSelectElement;
- expect(node.value).toBe('code');
- panel.content.select(panel.content.widgets[1]);
- await framePromise();
- expect(node.value).toBe('-');
- item.dispose();
- });
- it('should display the active cell type if multiple cells of the same type are selected', async () => {
- const item = ToolbarItems.createCellTypeItem(panel);
- Widget.attach(item, document.body);
- await framePromise();
- const node = item.node.getElementsByTagName(
- 'select'
- )[0] as HTMLSelectElement;
- expect(node.value).toBe('code');
- const cell = panel.model!.contentFactory.createCodeCell({});
- panel.model!.cells.insert(1, cell);
- panel.content.select(panel.content.widgets[1]);
- await framePromise();
- expect(node.value).toBe('code');
- item.dispose();
- });
- });
- describe('#getDefaultItems()', () => {
- it('should return the default items of the panel toolbar', () => {
- const names = ToolbarItems.getDefaultItems(panel).map(item => {
- const name = item.name;
- item.widget.dispose();
- return name;
- });
- expect(names).toEqual([
- 'save',
- 'insert',
- 'cut',
- 'copy',
- 'paste',
- 'run',
- 'interrupt',
- 'restart',
- 'restart-and-run',
- 'cellType',
- 'spacer',
- 'kernelName',
- 'kernelStatus'
- ]);
- });
- });
- });
- describe('kernelRequired', () => {
- let context: Context<INotebookModel>;
- let panel: NotebookPanel;
- beforeEach(async function() {
- context = await initNotebookContext({ startKernel: true });
- panel = utils.createNotebookPanel(context);
- context.model.fromJSON(utils.DEFAULT_CONTENT);
- });
- afterEach(async () => {
- await context.sessionContext.shutdown();
- panel.dispose();
- context.dispose();
- });
- describe('#createRunButton()', () => {
- it('should run and advance when clicked', async () => {
- const button = ToolbarItems.createRunButton(panel);
- const widget = panel.content;
- // Clear and select the first two cells.
- const codeCell = widget.widgets[0] as CodeCell;
- codeCell.model.outputs.clear();
- widget.select(codeCell);
- const mdCell = widget.widgets[1] as MarkdownCell;
- mdCell.rendered = false;
- widget.select(mdCell);
- 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(mdCell.rendered).toBe(true);
- expect(widget.activeCellIndex).toBe(2);
- button.dispose();
- p.resolve(0);
- }
- });
- await framePromise();
- simulate(button.node.firstChild as HTMLElement, 'mousedown');
- await p.promise;
- });
- it("should add an inline svg node with the 'run' icon", async () => {
- const button = ToolbarItems.createRunButton(panel);
- Widget.attach(button, document.body);
- await framePromise();
- expect(button.node.querySelector("[data-icon$='run']")).toBeDefined();
- });
- });
- 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).toBe(
- 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;
- });
- 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']")
- ).toBeDefined();
- });
- });
- });
- });
- });
|