From b1faab40de0d69a67cbf799038fac8584b32f9bd Mon Sep 17 00:00:00 2001 From: Johannes Date: Tue, 29 Mar 2022 11:58:54 +0200 Subject: [PATCH] adopt tests to new notebook change event --- extensions/ipynb/package.json | 13 ++- extensions/ipynb/src/cellIdService.ts | 14 +-- extensions/ipynb/tsconfig.json | 1 + extensions/vscode-api-tests/package.json | 1 + .../notebook.document.test.ts | 24 ++-- .../src/singlefolder-tests/notebook.test.ts | 105 ++++++++++-------- 6 files changed, 85 insertions(+), 73 deletions(-) diff --git a/extensions/ipynb/package.json b/extensions/ipynb/package.json index e6951a58a49..414bedf2c52 100644 --- a/extensions/ipynb/package.json +++ b/extensions/ipynb/package.json @@ -10,7 +10,8 @@ }, "enabledApiProposals": [ "notebookEditor", - "notebookEditorEdit" + "notebookEditorEdit", + "notebookDocumentEvents" ], "activationEvents": [ "*" @@ -31,9 +32,9 @@ "commands": [ { "command": "ipynb.newUntitledIpynb", - "title": "New Jupyter Notebook", + "title": "New Jupyter Notebook", "shortTitle": "Jupyter Notebook", - "category": "Create" + "category": "Create" }, { "command": "ipynb.openIpynbInNotebookEditor", @@ -60,9 +61,9 @@ } ], "commandPalette": [ - { - "command": "ipynb.newUntitledIpynb" - }, + { + "command": "ipynb.newUntitledIpynb" + }, { "command": "ipynb.openIpynbInNotebookEditor", "when": "false" diff --git a/extensions/ipynb/src/cellIdService.ts b/extensions/ipynb/src/cellIdService.ts index afcad72e9e7..082d25add97 100644 --- a/extensions/ipynb/src/cellIdService.ts +++ b/extensions/ipynb/src/cellIdService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ExtensionContext, NotebookCellsChangeEvent, NotebookDocument, notebooks, workspace, WorkspaceEdit } from 'vscode'; +import { ExtensionContext, NotebookDocument, NotebookDocumentChangeEvent, workspace, WorkspaceEdit } from 'vscode'; import { v4 as uuid } from 'uuid'; import { getCellMetadata } from './serializers'; import { CellMetadata } from './common'; @@ -15,21 +15,21 @@ import * as nbformat from '@jupyterlab/nbformat'; * Details of the spec can be found here https://jupyter.org/enhancement-proposals/62-cell-id/cell-id.html# */ export function ensureAllNewCellsHaveCellIds(context: ExtensionContext) { - notebooks.onDidChangeNotebookCells(onDidChangeNotebookCells, undefined, context.subscriptions); + workspace.onDidChangeNotebookDocument(onDidChangeNotebookCells, undefined, context.subscriptions); } -function onDidChangeNotebookCells(e: NotebookCellsChangeEvent) { - const nbMetadata = getNotebookMetadata(e.document); +function onDidChangeNotebookCells(e: NotebookDocumentChangeEvent) { + const nbMetadata = getNotebookMetadata(e.notebook); if (!isCellIdRequired(nbMetadata)) { return; } - e.changes.forEach(change => { - change.items.forEach(cell => { + e.contentChanges.forEach(change => { + change.addedCells.forEach(cell => { const cellMetadata = getCellMetadata(cell); if (cellMetadata?.id) { return; } - const id = generateCellId(e.document); + const id = generateCellId(e.notebook); const edit = new WorkspaceEdit(); // Don't edit the metadata directly, always get a clone (prevents accidental singletons and directly editing the objects). const updatedMetadata: CellMetadata = { ...JSON.parse(JSON.stringify(cellMetadata || {})) }; diff --git a/extensions/ipynb/tsconfig.json b/extensions/ipynb/tsconfig.json index 2032bf87b0d..b437665bd92 100644 --- a/extensions/ipynb/tsconfig.json +++ b/extensions/ipynb/tsconfig.json @@ -11,5 +11,6 @@ "../../src/vscode-dts/vscode.d.ts", "../../src/vscode-dts/vscode.proposed.notebookEditor.d.ts", "../../src/vscode-dts/vscode.proposed.notebookEditorEdit.d.ts", + "../../src/vscode-dts/vscode.proposed.notebookDocumentEvents.d.ts", ] } diff --git a/extensions/vscode-api-tests/package.json b/extensions/vscode-api-tests/package.json index abe4aff2dc3..95d995e36d2 100644 --- a/extensions/vscode-api-tests/package.json +++ b/extensions/vscode-api-tests/package.json @@ -23,6 +23,7 @@ "notebookControllerKind", "notebookDebugOptions", "notebookDeprecated", + "notebookDocumentEvents", "notebookEditor", "notebookEditorDecorationType", "notebookEditorEdit", diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/notebook.document.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/notebook.document.test.ts index 9ca93564824..951ac132c5c 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/notebook.document.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/notebook.document.test.ts @@ -261,7 +261,7 @@ suite.skip('Notebook Document', function () { value: 'new_code' }]); - const event = utils.asPromise(vscode.notebooks.onDidChangeNotebookCells); + const event = utils.asPromise(vscode.workspace.onDidChangeNotebookDocument); const success = await vscode.workspace.applyEdit(edit); assert.strictEqual(success, true); @@ -274,13 +274,13 @@ suite.skip('Notebook Document', function () { assert.strictEqual(document.cellAt(1).document.getText(), 'new_code'); // check event data - assert.strictEqual(data.document === document, true); - assert.strictEqual(data.changes.length, 1); - assert.strictEqual(data.changes[0].deletedCount, 0); - assert.strictEqual(data.changes[0].deletedItems.length, 0); - assert.strictEqual(data.changes[0].items.length, 2); - assert.strictEqual(data.changes[0].items[0], document.cellAt(0)); - assert.strictEqual(data.changes[0].items[1], document.cellAt(1)); + assert.strictEqual(data.notebook === document, true); + assert.strictEqual(data.contentChanges.length, 1); + assert.strictEqual(data.contentChanges[0].range.isEmpty, true); + assert.strictEqual(data.contentChanges[0].removedCells.length, 0); + assert.strictEqual(data.contentChanges[0].addedCells.length, 2); + assert.strictEqual(data.contentChanges[0].addedCells[0], document.cellAt(0)); + assert.strictEqual(data.contentChanges[0].addedCells[1], document.cellAt(1)); }); test('workspace edit API (replaceMetadata)', async function () { @@ -299,7 +299,7 @@ suite.skip('Notebook Document', function () { const document = await vscode.workspace.openNotebookDocument(uri); const edit = new vscode.WorkspaceEdit(); - const event = utils.asPromise(vscode.notebooks.onDidChangeCellMetadata); + const event = utils.asPromise(vscode.workspace.onDidChangeNotebookDocument); edit.replaceNotebookCellMetadata(document.uri, 0, { inputCollapsed: true }); const success = await vscode.workspace.applyEdit(edit); @@ -310,8 +310,10 @@ suite.skip('Notebook Document', function () { assert.strictEqual(document.cellAt(0).metadata.inputCollapsed, true); // check event data - assert.strictEqual(data.document === document, true); - assert.strictEqual(data.cell.index, 0); + assert.strictEqual(data.notebook === document, true); + assert.strictEqual(data.contentChanges.length, 0); + assert.strictEqual(data.cellChanges.length, 1); + assert.strictEqual(data.cellChanges[0].cell.index, 0); }); test('document save API', async function () { diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts index 2e3a32cd9ce..74c3bf0ccbb 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts @@ -194,41 +194,52 @@ const apiTestContentProvider: vscode.NotebookContentProvider = { const notebook = await openRandomNotebookDocument(); const editor = await vscode.window.showNotebookDocument(notebook); - const cellsChangeEvent = asPromise(vscode.notebooks.onDidChangeNotebookCells); + const cellsChangeEvent = asPromise(vscode.workspace.onDidChangeNotebookDocument); await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow'); const cellChangeEventRet = await cellsChangeEvent; - assert.strictEqual(cellChangeEventRet.document, editor.document); - assert.strictEqual(cellChangeEventRet.changes.length, 1); - assert.deepStrictEqual(cellChangeEventRet.changes[0], { - start: 1, - deletedCount: 0, - deletedItems: [], - items: [ - editor.document.cellAt(1) - ] + assert.strictEqual(cellChangeEventRet.notebook, editor.document); + assert.strictEqual(cellChangeEventRet.contentChanges.length, 1); + assert.deepStrictEqual(cellChangeEventRet.contentChanges[0], { + range: new vscode.NotebookRange(1, 1), + removedCells: [], + addedCells: [editor.document.cellAt(1)] }); - const moveCellEvent = asPromise(vscode.notebooks.onDidChangeNotebookCells); + const moveCellEvent = asPromise(vscode.workspace.onDidChangeNotebookDocument); await vscode.commands.executeCommand('notebook.cell.moveUp'); await moveCellEvent; - const cellOutputChange = asPromise(vscode.notebooks.onDidChangeCellOutputs); + const cellOutputChange = asPromise(vscode.workspace.onDidChangeNotebookDocument); await vscode.commands.executeCommand('notebook.cell.execute'); const cellOutputsAddedRet = await cellOutputChange; - assert.deepStrictEqual(cellOutputsAddedRet, { - document: editor.document, - cells: [editor.document.cellAt(0)] - }); - assert.strictEqual(cellOutputsAddedRet.cells[0].outputs.length, 1); - const cellOutputClear = asPromise(vscode.notebooks.onDidChangeCellOutputs); + assert.strictEqual(cellOutputsAddedRet.notebook.uri.toString(), editor.document.uri.toString()); + assert.strictEqual(cellOutputsAddedRet.metadata, undefined); + assert.strictEqual(cellOutputsAddedRet.contentChanges.length, 0); + assert.strictEqual(cellOutputsAddedRet.cellChanges.length, 1); + assert.deepStrictEqual(cellOutputsAddedRet.cellChanges[0].cell, editor.document.cellAt(0)); + assert.deepStrictEqual(cellOutputsAddedRet.cellChanges[0].executionSummary, { executionOrder: undefined, success: undefined, timing: undefined }); // TODO@jrieken should this be undefined instead all empty? + assert.strictEqual(cellOutputsAddedRet.cellChanges[0].document, undefined); + assert.strictEqual(cellOutputsAddedRet.cellChanges[0].metadata, undefined); + assert.strictEqual(cellOutputsAddedRet.cellChanges[0].outputs, undefined); + assert.strictEqual(cellOutputsAddedRet.cellChanges[0].cell.outputs.length, 1); + + const cellOutputClear = asPromise(vscode.workspace.onDidChangeNotebookDocument); await vscode.commands.executeCommand('notebook.cell.clearOutputs'); const cellOutputsCleardRet = await cellOutputClear; - assert.deepStrictEqual(cellOutputsCleardRet, { - document: editor.document, - cells: [editor.document.cellAt(0)] + assert.deepStrictEqual(cellOutputsCleardRet, { + notebook: editor.document, + metadata: undefined, + contentChanges: [], + cellChanges: [{ + cell: editor.document.cellAt(0), + document: undefined, + executionSummary: undefined, + metadata: undefined, + outputs: editor.document.cellAt(0).outputs + }], }); - assert.strictEqual(cellOutputsAddedRet.cells[0].outputs.length, 0); + assert.strictEqual(cellOutputsCleardRet.cellChanges[0].cell.outputs.length, 0); // const cellChangeLanguage = getEventOncePromise(vscode.notebooks.onDidChangeCellLanguage); // await vscode.commands.executeCommand('notebook.cell.changeToMarkdown'); @@ -244,16 +255,14 @@ const apiTestContentProvider: vscode.NotebookContentProvider = { const notebook = await openRandomNotebookDocument(); const editor = await vscode.window.showNotebookDocument(notebook); - const cellsChangeEvent = asPromise(vscode.notebooks.onDidChangeNotebookCells); - const cellMetadataChangeEvent = asPromise(vscode.notebooks.onDidChangeCellMetadata); + const notebookChangeEvent = asPromise(vscode.workspace.onDidChangeNotebookDocument); const version = editor.document.version; await editor.edit(editBuilder => { editBuilder.replaceCells(1, 0, [{ kind: vscode.NotebookCellKind.Code, languageId: 'javascript', value: 'test 2', outputs: [], metadata: undefined }]); editBuilder.replaceCellMetadata(0, { inputCollapsed: false }); }); - await cellsChangeEvent; - await cellMetadataChangeEvent; + await notebookChangeEvent; assert.strictEqual(version + 1, editor.document.version); }); @@ -261,16 +270,14 @@ const apiTestContentProvider: vscode.NotebookContentProvider = { const notebook = await openRandomNotebookDocument(); const editor = await vscode.window.showNotebookDocument(notebook); - const cellsChangeEvent = asPromise(vscode.notebooks.onDidChangeNotebookCells); - const cellMetadataChangeEvent = asPromise(vscode.notebooks.onDidChangeCellMetadata); + const notebookChangeEvent = asPromise(vscode.workspace.onDidChangeNotebookDocument); const version = editor.document.version; await editor.edit(editBuilder => { editBuilder.replaceCells(1, 0, [{ kind: vscode.NotebookCellKind.Code, languageId: 'javascript', value: 'test 2', outputs: [], metadata: undefined }]); editBuilder.replaceCellMetadata(0, { inputCollapsed: false }); }); - await cellsChangeEvent; - await cellMetadataChangeEvent; + await notebookChangeEvent; assert.strictEqual(editor.document.cellCount, 3); assert.strictEqual(editor.document.cellAt(0)?.metadata.inputCollapsed, false); assert.strictEqual(version + 1, editor.document.version); @@ -285,7 +292,7 @@ const apiTestContentProvider: vscode.NotebookContentProvider = { test.skip('#98841, initialzation should not emit cell change events.', async function () { let count = 0; - testDisposables.push(vscode.notebooks.onDidChangeNotebookCells(() => { + testDisposables.push(vscode.workspace.onDidChangeNotebookDocument(() => { count++; })); @@ -387,9 +394,9 @@ const apiTestContentProvider: vscode.NotebookContentProvider = { const activeCell = getFocusedCell(editor); assert.strictEqual(activeCell?.index, 0); - const moveChange = asPromise(vscode.notebooks.onDidChangeNotebookCells); + const notebookChangeEvent = asPromise(vscode.workspace.onDidChangeNotebookDocument); await vscode.commands.executeCommand('notebook.cell.moveDown'); - assert.ok(await moveChange); + assert.ok(await notebookChangeEvent); const newActiveCell = getFocusedCell(editor); assert.strictEqual(newActiveCell?.index, 1); @@ -440,13 +447,13 @@ const apiTestContentProvider: vscode.NotebookContentProvider = { const editor = vscode.window.activeNotebookEditor!; const cell = editor.document.cellAt(0); - await withEvent(vscode.notebooks.onDidChangeCellOutputs, async (event) => { + await withEvent(vscode.workspace.onDidChangeNotebookDocument, async (event) => { await vscode.commands.executeCommand('notebook.execute'); await event; assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked }); - await withEvent(vscode.notebooks.onDidChangeCellOutputs, async event => { + await withEvent(vscode.workspace.onDidChangeNotebookDocument, async event => { await vscode.commands.executeCommand('notebook.cell.clearOutputs'); await event; assert.strictEqual(cell.outputs.length, 0, 'should clear'); @@ -455,7 +462,7 @@ const apiTestContentProvider: vscode.NotebookContentProvider = { const secondResource = await createRandomNotebookFile(); await vscode.commands.executeCommand('vscode.openWith', secondResource, 'notebookCoreTest'); - await withEvent(vscode.notebooks.onDidChangeCellOutputs, async (event) => { + await withEvent(vscode.workspace.onDidChangeNotebookDocument, async (event) => { await vscode.commands.executeCommand('notebook.cell.execute', { start: 0, end: 1 }, resource); await event; assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked @@ -473,13 +480,13 @@ const apiTestContentProvider: vscode.NotebookContentProvider = { let secondCellExecuted = false; let resolve: () => void; const p = new Promise(r => resolve = r); - const listener = vscode.notebooks.onDidChangeCellOutputs(e => { - e.cells.forEach(cell => { - if (cell.index === 0) { + const listener = vscode.workspace.onDidChangeNotebookDocument(e => { + e.cellChanges.forEach(change => { + if (change.cell.index === 0) { firstCellExecuted = true; } - if (cell.index === 1) { + if (change.cell.index === 1) { secondCellExecuted = true; } }); @@ -501,13 +508,13 @@ const apiTestContentProvider: vscode.NotebookContentProvider = { const editor = vscode.window.activeNotebookEditor!; const cell = editor.document.cellAt(0); - await withEvent(vscode.notebooks.onDidChangeCellOutputs, async (event) => { + await withEvent(vscode.workspace.onDidChangeNotebookDocument, async (event) => { await vscode.commands.executeCommand('notebook.execute'); await event; assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked }); - const clearChangeEvent = asPromise(vscode.notebooks.onDidChangeCellOutputs); + const clearChangeEvent = asPromise(vscode.workspace.onDidChangeNotebookDocument); await vscode.commands.executeCommand('notebook.cell.clearOutputs'); await clearChangeEvent; assert.strictEqual(cell.outputs.length, 0, 'should clear'); @@ -515,7 +522,7 @@ const apiTestContentProvider: vscode.NotebookContentProvider = { const secondResource = await createRandomNotebookFile(); await vscode.commands.executeCommand('vscode.openWith', secondResource, 'notebookCoreTest'); - await withEvent(vscode.notebooks.onDidChangeCellOutputs, async (event) => { + await withEvent(vscode.workspace.onDidChangeNotebookDocument, async (event) => { await vscode.commands.executeCommand('notebook.execute', resource); await event; assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked @@ -547,7 +554,7 @@ const apiTestContentProvider: vscode.NotebookContentProvider = { }; testDisposables.push(alternativeKernel.controller); - await withEvent(vscode.notebooks.onDidChangeCellOutputs, async (event) => { + await withEvent(vscode.workspace.onDidChangeNotebookDocument, async (event) => { await assertKernel(defaultKernel, notebook); await vscode.commands.executeCommand('notebook.cell.execute'); await event; @@ -557,7 +564,7 @@ const apiTestContentProvider: vscode.NotebookContentProvider = { assert.deepStrictEqual(new TextDecoder().decode(cell.outputs[0].items[0].data), cell.document.getText()); }); - await withEvent(vscode.notebooks.onDidChangeCellOutputs, async (event) => { + await withEvent(vscode.workspace.onDidChangeNotebookDocument, async (event) => { await assertKernel(alternativeKernel, notebook); await vscode.commands.executeCommand('notebook.cell.execute'); await event; @@ -798,16 +805,16 @@ const apiTestContentProvider: vscode.NotebookContentProvider = { const notebook = await vscode.workspace.openNotebookDocument(resource); const editor = await vscode.window.showNotebookDocument(notebook); - const cellsChangeEvent = asPromise(vscode.notebooks.onDidChangeNotebookCells); + const cellsChangeEvent = asPromise(vscode.workspace.onDidChangeNotebookDocument); await editor.edit(editBuilder => { editBuilder.replaceCells(1, 0, [{ kind: vscode.NotebookCellKind.Code, languageId: 'javascript', value: 'test 2', outputs: [], metadata: undefined }]); }); const cellChangeEventRet = await cellsChangeEvent; - assert.strictEqual(cellChangeEventRet.document === notebook, true); - assert.strictEqual(cellChangeEventRet.document.isDirty, true); + assert.strictEqual(cellChangeEventRet.notebook === notebook, true); + assert.strictEqual(cellChangeEventRet.notebook.isDirty, true); - const saveEvent = asPromise(vscode.notebooks.onDidSaveNotebookDocument); + const saveEvent = asPromise(vscode.workspace.onDidSaveNotebookDocument); await notebook.save();