Merge branch 'notebook/dev' into main

This commit is contained in:
rebornix 2021-06-08 14:18:30 -07:00
commit bffe6fdf12
11 changed files with 251 additions and 373 deletions

View file

@ -21,6 +21,7 @@ suite('Notebook Editor', function () {
};
const disposables: vscode.Disposable[] = [];
const testDisposables: vscode.Disposable[] = [];
suiteTeardown(async function () {
utils.assertNoRpc();
@ -38,6 +39,10 @@ suite('Notebook Editor', function () {
disposables.push(vscode.workspace.registerNotebookSerializer('notebook.nbdtest', contentSerializer));
});
teardown(async function () {
utils.disposeAll(testDisposables);
testDisposables.length = 0;
});
test('showNotebookDocment', async function () {
@ -74,4 +79,48 @@ suite('Notebook Editor', function () {
assert.ok(await openedEditor);
assert.strictEqual(editor.document.uri.toString(), resource.toString());
});
test('Active/Visible Editor', async function () {
const firstEditorOpen = utils.asPromise(vscode.window.onDidChangeActiveNotebookEditor);
const resource = await utils.createRandomFile(undefined, undefined, '.nbdtest');
const firstEditor = await vscode.window.showNotebookDocument(resource);
await firstEditorOpen;
assert.strictEqual(vscode.window.activeNotebookEditor, firstEditor);
assert.strictEqual(vscode.window.visibleNotebookEditors.includes(firstEditor), true);
const secondEditor = await vscode.window.showNotebookDocument(resource, { viewColumn: vscode.ViewColumn.Beside });
assert.strictEqual(secondEditor === vscode.window.activeNotebookEditor, true);
assert.notStrictEqual(firstEditor, secondEditor);
assert.strictEqual(vscode.window.visibleNotebookEditors.includes(secondEditor), true);
assert.strictEqual(vscode.window.visibleNotebookEditors.includes(firstEditor), true);
assert.strictEqual(vscode.window.visibleNotebookEditors.length, 2);
});
test('Notebook Editor Event - onDidChangeVisibleNotebookEditors on open/close', async function () {
const openedEditor = utils.asPromise(vscode.window.onDidChangeVisibleNotebookEditors);
const resource = await utils.createRandomFile(undefined, undefined, '.nbdtest');
await vscode.window.showNotebookDocument(resource);
assert.ok(await openedEditor);
const firstEditorClose = utils.asPromise(vscode.window.onDidChangeVisibleNotebookEditors);
await utils.closeAllEditors();
await firstEditorClose;
});
test('Notebook Editor Event - onDidChangeVisibleNotebookEditors on two editor groups', async function () {
const resource = await utils.createRandomFile(undefined, undefined, '.nbdtest');
let count = 0;
testDisposables.push(vscode.window.onDidChangeVisibleNotebookEditors(() => {
count = vscode.window.visibleNotebookEditors.length;
}));
await vscode.window.showNotebookDocument(resource, { viewColumn: vscode.ViewColumn.Active });
assert.strictEqual(count, 1);
await vscode.window.showNotebookDocument(resource, { viewColumn: vscode.ViewColumn.Beside });
assert.strictEqual(count, 2);
await utils.closeAllEditors();
assert.strictEqual(count, 0);
});
});

View file

@ -56,18 +56,13 @@ class Kernel {
}
protected async _runCell(cell: vscode.NotebookCell) {
// create a single output with exec order 1 and output is plain/text
// of either the cell itself or (iff empty) the cell's document's uri
const task = this.controller.createNotebookCellExecution(cell);
task.start();
task.executionOrder = 1;
if (cell.notebook.uri.path.endsWith('customRenderer.vsctestnb')) {
await task.replaceOutput([new vscode.NotebookCellOutput([
vscode.NotebookCellOutputItem.text('test', 'text/custom')
])]);
return;
}
await task.replaceOutput([new vscode.NotebookCellOutput([
vscode.NotebookCellOutputItem.text('my output', 'text/plain')
vscode.NotebookCellOutputItem.text(cell.document.getText() || cell.document.uri.toString(), 'text/plain')
])]);
task.end(true);
}
@ -161,40 +156,12 @@ suite('Notebook API tests', function () {
suiteDisposables.push(vscode.workspace.registerNotebookContentProvider('notebookCoreTest', apiTestContentProvider));
});
let kernel1: Kernel;
let kernel2: Kernel;
let defaultKernel: Kernel;
setup(async function () {
kernel1 = new Kernel('mainKernel', 'Notebook Primary Test Kernel');
const listener = vscode.workspace.onDidOpenNotebookDocument(async notebook => {
if (notebook.notebookType === kernel1.controller.notebookType) {
await vscode.commands.executeCommand('notebook.selectKernel', {
extension: 'vscode.vscode-api-tests',
id: kernel1.controller.id
});
}
});
kernel2 = new class extends Kernel {
constructor() {
super('secondaryKernel', 'Notebook Secondary Test Kernel');
this.controller.supportsExecutionOrder = false;
}
override async _runCell(cell: vscode.NotebookCell) {
const task = this.controller.createNotebookCellExecution(cell);
task.start();
await task.replaceOutput([new vscode.NotebookCellOutput([
vscode.NotebookCellOutputItem.text('my second output', 'text/plain')
])]);
task.end(true);
}
};
testDisposables.push(kernel1.controller, listener, kernel2.controller);
// there should be ONE default kernel in this suite
defaultKernel = new Kernel('mainKernel', 'Notebook Default Kernel');
testDisposables.push(defaultKernel.controller);
await saveAllFilesAndCloseAll();
});
@ -204,35 +171,6 @@ suite('Notebook API tests', function () {
await saveAllFilesAndCloseAll();
});
test('editor onDidChangeVisibleNotebookEditors-event', async function () {
const resource = await createRandomNotebookFile();
const firstEditorOpen = asPromise(vscode.window.onDidChangeVisibleNotebookEditors);
await vscode.window.showNotebookDocument(resource);
await firstEditorOpen;
const firstEditorClose = asPromise(vscode.window.onDidChangeVisibleNotebookEditors);
await closeAllEditors();
await firstEditorClose;
});
test('editor onDidChangeVisibleNotebookEditors-event 2', async function () {
const resource = await createRandomNotebookFile();
let count = 0;
const disposables: vscode.Disposable[] = [];
disposables.push(vscode.window.onDidChangeVisibleNotebookEditors(() => {
count = vscode.window.visibleNotebookEditors.length;
}));
await vscode.window.showNotebookDocument(resource, { viewColumn: vscode.ViewColumn.Active });
assert.strictEqual(count, 1);
await vscode.window.showNotebookDocument(resource, { viewColumn: vscode.ViewColumn.Beside });
assert.strictEqual(count, 2);
await closeAllEditors();
assert.strictEqual(count, 0);
});
test('correct cell selection on undo/redo of cell creation', async function () {
const notebook = await openRandomNotebookDocument();
await vscode.window.showNotebookDocument(notebook);
@ -252,23 +190,21 @@ suite('Notebook API tests', function () {
assert.strictEqual(selectionRedo[0].end, 2);
});
test('editor editing event 2', async function () {
// const notebook = await openRandomNotebookDocument();
// await vscode.window.showNotebookDocument(notebook);
const resource = await createRandomNotebookFile();
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
test('editor editing event', async function () {
const notebook = await openRandomNotebookDocument();
const editor = await vscode.window.showNotebookDocument(notebook);
const cellsChangeEvent = asPromise<vscode.NotebookCellsChangeEvent>(vscode.notebooks.onDidChangeNotebookCells);
await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
const cellChangeEventRet = await cellsChangeEvent;
assert.strictEqual(cellChangeEventRet.document, vscode.window.activeNotebookEditor?.document);
assert.strictEqual(cellChangeEventRet.document, editor.document);
assert.strictEqual(cellChangeEventRet.changes.length, 1);
assert.deepStrictEqual(cellChangeEventRet.changes[0], {
start: 1,
deletedCount: 0,
deletedItems: [],
items: [
vscode.window.activeNotebookEditor!.document.cellAt(1)
editor.document.cellAt(1)
]
});
@ -280,8 +216,8 @@ suite('Notebook API tests', function () {
await vscode.commands.executeCommand('notebook.cell.execute');
const cellOutputsAddedRet = await cellOutputChange;
assert.deepStrictEqual(cellOutputsAddedRet, {
document: vscode.window.activeNotebookEditor!.document,
cells: [vscode.window.activeNotebookEditor!.document.cellAt(0)]
document: editor.document,
cells: [editor.document.cellAt(0)]
});
assert.strictEqual(cellOutputsAddedRet.cells[0].outputs.length, 1);
@ -289,8 +225,8 @@ suite('Notebook API tests', function () {
await vscode.commands.executeCommand('notebook.cell.clearOutputs');
const cellOutputsCleardRet = await cellOutputClear;
assert.deepStrictEqual(cellOutputsCleardRet, {
document: vscode.window.activeNotebookEditor!.document,
cells: [vscode.window.activeNotebookEditor!.document.cellAt(0)]
document: editor.document,
cells: [editor.document.cellAt(0)]
});
assert.strictEqual(cellOutputsAddedRet.cells[0].outputs.length, 0);
@ -304,111 +240,45 @@ suite('Notebook API tests', function () {
// });
});
test('editor move cell event', async function () {
const resource = await createRandomNotebookFile();
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
// const notebook = await openRandomNotebookDocument();
// await vscode.window.showNotebookDocument(notebook);
await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove');
await vscode.commands.executeCommand('notebook.focusTop');
const activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 0);
const moveChange = asPromise(vscode.notebooks.onDidChangeNotebookCells);
await vscode.commands.executeCommand('notebook.cell.moveDown');
await moveChange;
await saveAllEditors();
await closeAllEditors();
// await vscode.window.showNotebookDocument(notebook);
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
const firstEditor = vscode.window.activeNotebookEditor;
assert.strictEqual(firstEditor?.document.cellCount, 2);
});
test('notebook editor active/visible', async function () {
const resource = await createRandomNotebookFile();
const firstEditor = await vscode.window.showNotebookDocument(resource, { viewColumn: vscode.ViewColumn.Active });
assert.strictEqual(firstEditor === vscode.window.activeNotebookEditor, true);
assert.strictEqual(vscode.window.visibleNotebookEditors.includes(firstEditor), true);
const secondEditor = await vscode.window.showNotebookDocument(resource, { viewColumn: vscode.ViewColumn.Beside });
assert.strictEqual(secondEditor === vscode.window.activeNotebookEditor, true);
assert.notStrictEqual(firstEditor, secondEditor);
assert.strictEqual(vscode.window.visibleNotebookEditors.includes(secondEditor), true);
assert.strictEqual(vscode.window.visibleNotebookEditors.includes(firstEditor), true);
assert.strictEqual(vscode.window.visibleNotebookEditors.length, 2);
const untitledEditorChange = asPromise(vscode.window.onDidChangeActiveNotebookEditor);
await vscode.commands.executeCommand('workbench.action.files.newUntitledFile');
await untitledEditorChange;
assert.strictEqual(firstEditor && vscode.window.visibleNotebookEditors.indexOf(firstEditor) >= 0, true);
assert.notStrictEqual(firstEditor, vscode.window.activeNotebookEditor);
assert.strictEqual(secondEditor && vscode.window.visibleNotebookEditors.indexOf(secondEditor) < 0, true);
assert.notStrictEqual(secondEditor, vscode.window.activeNotebookEditor);
assert.strictEqual(vscode.window.visibleNotebookEditors.length, 1);
const activeEditorClose = asPromise(vscode.window.onDidChangeActiveNotebookEditor);
await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
await activeEditorClose;
assert.strictEqual(secondEditor, vscode.window.activeNotebookEditor);
assert.strictEqual(vscode.window.visibleNotebookEditors.length, 2);
assert.strictEqual(secondEditor && vscode.window.visibleNotebookEditors.indexOf(secondEditor) >= 0, true);
});
test('notebook active editor change', async function () {
const firstEditorOpen = asPromise(vscode.window.onDidChangeActiveNotebookEditor);
const notebook = await openRandomNotebookDocument();
await vscode.window.showNotebookDocument(notebook);
await firstEditorOpen;
const firstEditorDeactivate = asPromise(vscode.window.onDidChangeActiveNotebookEditor);
await vscode.commands.executeCommand('workbench.action.splitEditor');
await firstEditorDeactivate;
});
test('edit API batch edits', async function () {
const resource = await createRandomNotebookFile();
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
const notebook = await openRandomNotebookDocument();
const editor = await vscode.window.showNotebookDocument(notebook);
const cellsChangeEvent = asPromise<vscode.NotebookCellsChangeEvent>(vscode.notebooks.onDidChangeNotebookCells);
const cellMetadataChangeEvent = asPromise<vscode.NotebookCellMetadataChangeEvent>(vscode.notebooks.onDidChangeCellMetadata);
const version = vscode.window.activeNotebookEditor!.document.version;
await vscode.window.activeNotebookEditor!.edit(editBuilder => {
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;
assert.strictEqual(version + 1, vscode.window.activeNotebookEditor!.document.version);
assert.strictEqual(version + 1, editor.document.version);
});
test('edit API batch edits undo/redo', async function () {
const notebook = await openRandomNotebookDocument();
await vscode.window.showNotebookDocument(notebook);
const editor = await vscode.window.showNotebookDocument(notebook);
const cellsChangeEvent = asPromise<vscode.NotebookCellsChangeEvent>(vscode.notebooks.onDidChangeNotebookCells);
const cellMetadataChangeEvent = asPromise<vscode.NotebookCellMetadataChangeEvent>(vscode.notebooks.onDidChangeCellMetadata);
const version = vscode.window.activeNotebookEditor!.document.version;
await vscode.window.activeNotebookEditor!.edit(editBuilder => {
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;
assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellCount, 3);
assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellAt(0)?.metadata.inputCollapsed, false);
assert.strictEqual(version + 1, vscode.window.activeNotebookEditor!.document.version);
assert.strictEqual(editor.document.cellCount, 3);
assert.strictEqual(editor.document.cellAt(0)?.metadata.inputCollapsed, false);
assert.strictEqual(version + 1, editor.document.version);
await vscode.commands.executeCommand('undo');
assert.strictEqual(version + 2, vscode.window.activeNotebookEditor!.document.version);
assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellAt(0)?.metadata.inputCollapsed, undefined);
assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellCount, 2);
assert.strictEqual(version + 2, editor.document.version);
assert.strictEqual(editor.document.cellAt(0)?.metadata.inputCollapsed, undefined);
assert.strictEqual(editor.document.cellCount, 2);
});
test('#98841, initialzation should not emit cell change events.', async function () {
@ -422,76 +292,61 @@ suite('Notebook API tests', function () {
await vscode.window.showNotebookDocument(notebook);
assert.strictEqual(count, 0);
});
// });
// suite('notebook workflow', () => {
test('notebook open', async function () {
const notebook = await openRandomNotebookDocument();
await vscode.window.showNotebookDocument(notebook);
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), 'test');
assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.languageId, 'typescript');
const editor = await vscode.window.showNotebookDocument(notebook);
assert.strictEqual(vscode.window.activeNotebookEditor === editor, true, 'notebook first');
assert.strictEqual(getFocusedCell(editor)?.document.getText(), 'test');
assert.strictEqual(getFocusedCell(editor)?.document.languageId, 'typescript');
const secondCell = vscode.window.activeNotebookEditor!.document.cellAt(1);
assert.strictEqual(secondCell!.outputs.length, 1);
assert.deepStrictEqual(secondCell!.outputs[0].metadata, { testOutputMetadata: true, ['text/plain']: { testOutputItemMetadata: true } });
assert.strictEqual(secondCell!.outputs[0].items.length, 1);
assert.strictEqual(secondCell!.outputs[0].items[0].mime, 'text/plain');
assert.strictEqual(new TextDecoder().decode(secondCell!.outputs[0].items[0].data), 'Hello World');
assert.strictEqual(secondCell!.executionSummary?.executionOrder, 5);
assert.strictEqual(secondCell!.executionSummary?.success, true);
await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), '');
await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove');
const activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
assert.notStrictEqual(getFocusedCell(vscode.window.activeNotebookEditor), undefined);
assert.strictEqual(activeCell!.document.getText(), '');
assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellCount, 4);
assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 1);
await vscode.commands.executeCommand('workbench.action.files.save');
await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
const secondCell = editor.document.cellAt(1);
assert.strictEqual(secondCell.outputs.length, 1);
assert.deepStrictEqual(secondCell.outputs[0].metadata, { testOutputMetadata: true, ['text/plain']: { testOutputItemMetadata: true } });
assert.strictEqual(secondCell.outputs[0].items.length, 1);
assert.strictEqual(secondCell.outputs[0].items[0].mime, 'text/plain');
assert.strictEqual(new TextDecoder().decode(secondCell.outputs[0].items[0].data), 'Hello World');
assert.strictEqual(secondCell.executionSummary?.executionOrder, 5);
assert.strictEqual(secondCell.executionSummary?.success, true);
});
test('notebook cell actions', async function () {
const notebook = await openRandomNotebookDocument();
await vscode.window.showNotebookDocument(notebook);
const editor = await vscode.window.showNotebookDocument(notebook);
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), 'test');
assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.languageId, 'typescript');
assert.strictEqual(vscode.window.activeNotebookEditor === editor, true, 'notebook first');
assert.strictEqual(getFocusedCell(editor)?.document.getText(), 'test');
assert.strictEqual(getFocusedCell(editor)?.document.languageId, 'typescript');
// ---- insert cell below and focus ---- //
await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), '');
assert.strictEqual(getFocusedCell(editor)?.document.getText(), '');
// ---- insert cell above and focus ---- //
await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove');
let activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
assert.notStrictEqual(getFocusedCell(vscode.window.activeNotebookEditor), undefined);
let activeCell = getFocusedCell(editor);
assert.notStrictEqual(getFocusedCell(editor), undefined);
assert.strictEqual(activeCell!.document.getText(), '');
assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellCount, 4);
assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 1);
assert.strictEqual(editor.document.cellCount, 4);
assert.strictEqual(editor.document.getCells().indexOf(activeCell!), 1);
// ---- focus bottom ---- //
await vscode.commands.executeCommand('notebook.focusBottom');
activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 3);
activeCell = getFocusedCell(editor);
assert.strictEqual(editor.document.getCells().indexOf(activeCell!), 3);
// ---- focus top and then copy down ---- //
await vscode.commands.executeCommand('notebook.focusTop');
activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 0);
activeCell = getFocusedCell(editor);
assert.strictEqual(editor.document.getCells().indexOf(activeCell!), 0);
await vscode.commands.executeCommand('notebook.cell.copyDown');
activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 1);
activeCell = getFocusedCell(editor);
assert.strictEqual(editor.document.getCells().indexOf(activeCell!), 1);
assert.strictEqual(activeCell?.document.getText(), 'test');
{
const focusedCell = getFocusedCell(vscode.window.activeNotebookEditor);
const focusedCell = getFocusedCell(editor);
assert.strictEqual(focusedCell !== undefined, true);
// delete focused cell
const edit = new vscode.WorkspaceEdit();
@ -499,45 +354,44 @@ suite('Notebook API tests', function () {
await vscode.workspace.applyEdit(edit);
}
activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 1);
activeCell = getFocusedCell(editor);
assert.strictEqual(editor.document.getCells().indexOf(activeCell!), 1);
assert.strictEqual(activeCell?.document.getText(), '');
// ---- focus top and then copy up ---- //
await vscode.commands.executeCommand('notebook.focusTop');
await vscode.commands.executeCommand('notebook.cell.copyUp');
assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellCount, 5);
assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellAt(0).document.getText(), 'test');
assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellAt(1).document.getText(), 'test');
assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellAt(2).document.getText(), '');
assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellAt(3).document.getText(), '');
activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 0);
assert.strictEqual(editor.document.cellCount, 5);
assert.strictEqual(editor.document.cellAt(0).document.getText(), 'test');
assert.strictEqual(editor.document.cellAt(1).document.getText(), 'test');
assert.strictEqual(editor.document.cellAt(2).document.getText(), '');
assert.strictEqual(editor.document.cellAt(3).document.getText(), '');
activeCell = getFocusedCell(editor);
assert.strictEqual(editor.document.getCells().indexOf(activeCell!), 0);
// ---- move up and down ---- //
await vscode.commands.executeCommand('notebook.cell.moveDown');
assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(getFocusedCell(vscode.window.activeNotebookEditor)!), 1,
`first move down, active cell ${getFocusedCell(vscode.window.activeNotebookEditor)!.document.uri.toString()}, ${getFocusedCell(vscode.window.activeNotebookEditor)!.document.getText()}`);
assert.strictEqual(editor.document.getCells().indexOf(getFocusedCell(editor)!), 1,
`first move down, active cell ${getFocusedCell(editor)!.document.uri.toString()}, ${getFocusedCell(editor)!.document.getText()}`);
await vscode.commands.executeCommand('workbench.action.files.save');
await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
});
test('move cells will not recreate cells in ExtHost', async function () {
test('editor move command - event and move cells will not recreate cells in ExtHost (#98126)', async function () {
const notebook = await openRandomNotebookDocument();
await vscode.window.showNotebookDocument(notebook);
await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove');
await vscode.commands.executeCommand('notebook.focusTop');
const editor = await vscode.window.showNotebookDocument(notebook);
const activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 0);
await vscode.commands.executeCommand('notebook.cell.moveDown');
const activeCell = getFocusedCell(editor);
assert.strictEqual(activeCell?.index, 0);
const moveChange = asPromise(vscode.notebooks.onDidChangeNotebookCells);
await vscode.commands.executeCommand('notebook.cell.moveDown');
assert.ok(await moveChange);
const newActiveCell = getFocusedCell(vscode.window.activeNotebookEditor);
const newActiveCell = getFocusedCell(editor);
assert.strictEqual(newActiveCell?.index, 1);
assert.deepStrictEqual(activeCell, newActiveCell);
});
@ -674,18 +528,35 @@ suite('Notebook API tests', function () {
const cell = editor.document.cellAt(0);
const alternativeKernel = new class extends Kernel {
constructor() {
super('secondaryKernel', 'Notebook Secondary Test Kernel');
this.controller.supportsExecutionOrder = false;
}
override async _runCell(cell: vscode.NotebookCell) {
const task = this.controller.createNotebookCellExecution(cell);
task.start();
await task.replaceOutput([new vscode.NotebookCellOutput([
vscode.NotebookCellOutputItem.text('my second output', 'text/plain')
])]);
task.end(true);
}
};
testDisposables.push(alternativeKernel.controller);
await withEvent<vscode.NotebookCellOutputsChangeEvent>(vscode.notebooks.onDidChangeCellOutputs, async (event) => {
await assertKernel(kernel1, notebook);
await assertKernel(defaultKernel, notebook);
await vscode.commands.executeCommand('notebook.cell.execute');
await event;
assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked
assert.strictEqual(cell.outputs[0].items.length, 1);
assert.strictEqual(cell.outputs[0].items[0].mime, 'text/plain');
assert.deepStrictEqual(new TextDecoder().decode(cell.outputs[0].items[0].data), 'my output');
assert.deepStrictEqual(new TextDecoder().decode(cell.outputs[0].items[0].data), cell.document.getText());
});
await withEvent<vscode.NotebookCellOutputsChangeEvent>(vscode.notebooks.onDidChangeCellOutputs, async (event) => {
await assertKernel(kernel2, notebook);
await assertKernel(alternativeKernel, notebook);
await vscode.commands.executeCommand('notebook.cell.execute');
await event;
assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked
@ -1134,74 +1005,44 @@ suite('Notebook API tests', function () {
assert.strictEqual(cell.executionSummary?.timing?.endTime, 20);
});
});
suite('statusbar', () => {
const emitter = new vscode.EventEmitter<vscode.NotebookCell>();
const onDidCallProvide = emitter.event;
const suiteDisposables: vscode.Disposable[] = [];
suiteTeardown(async function () {
assertNoRpc();
suite('statusbar', () => {
const emitter = new vscode.EventEmitter<vscode.NotebookCell>();
const onDidCallProvide = emitter.event;
suiteSetup(() => {
vscode.notebooks.registerNotebookCellStatusBarItemProvider('notebookCoreTest', {
async provideCellStatusBarItems(cell: vscode.NotebookCell, _token: vscode.CancellationToken): Promise<vscode.NotebookCellStatusBarItem[]> {
emitter.fire(cell);
return [];
}
});
});
await revertAllDirty();
await closeAllEditors();
test('provideCellStatusBarItems called on metadata change', async function () {
const provideCalled = asPromise(onDidCallProvide);
const resource = await createRandomNotebookFile();
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
await provideCalled;
const edit = new vscode.WorkspaceEdit();
edit.replaceNotebookCellMetadata(resource, 0, { inputCollapsed: true });
vscode.workspace.applyEdit(edit);
await provideCalled;
});
disposeAll(suiteDisposables);
suiteDisposables.length = 0;
});
// });
suiteSetup(() => {
suiteDisposables.push(vscode.notebooks.registerNotebookCellStatusBarItemProvider('notebookCoreTest', {
async provideCellStatusBarItems(cell: vscode.NotebookCell, _token: vscode.CancellationToken): Promise<vscode.NotebookCellStatusBarItem[]> {
emitter.fire(cell);
return [];
}
}));
// suite('webview', () => {
// for web, `asWebUri` gets `https`?
// test('asWebviewUri', async function () {
// if (vscode.env.uiKind === vscode.UIKind.Web) {
// return;
// }
suiteDisposables.push(vscode.workspace.registerNotebookContentProvider('notebookCoreTest', apiTestContentProvider));
});
// const resource = await createRandomNotebookFile();
// await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
// assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
// const uri = vscode.window.activeNotebookEditor!.asWebviewUri(vscode.Uri.file('./hello.png'));
// assert.strictEqual(uri.scheme, 'vscode-webview-resource');
// await closeAllEditors();
// });
test('provideCellStatusBarItems called on metadata change', async function () {
const provideCalled = asPromise(onDidCallProvide);
const resource = await createRandomNotebookFile();
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
await provideCalled;
// 404 on web
// test('custom renderer message', async function () {
// if (vscode.env.uiKind === vscode.UIKind.Web) {
// return;
// }
// const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './customRenderer.vsctestnb'));
// await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
// const editor = vscode.window.activeNotebookEditor;
// const promise = new Promise(resolve => {
// const messageEmitter = editor?.onDidReceiveMessage(e => {
// if (e.type === 'custom_renderer_initialize') {
// resolve();
// messageEmitter?.dispose();
// }
// });
// });
// await vscode.commands.executeCommand('notebook.cell.execute');
// await promise;
// await closeAllEditors();
// });
const edit = new vscode.WorkspaceEdit();
edit.replaceNotebookCellMetadata(resource, 0, { inputCollapsed: true });
vscode.workspace.applyEdit(edit);
await provideCalled;
});
});
suite('Notebook API tests (metadata)', function () {

View file

@ -1874,14 +1874,18 @@ registerAction2(class NotebookConfigureLayoutAction extends Action2 {
group: 'notebookLayout',
when: ContextKeyExpr.and(
NOTEBOOK_IS_ACTIVE_EDITOR,
ContextKeyExpr.notEquals('config.notebook.globalToolbar', true)
ContextKeyExpr.notEquals('config.notebook.globalToolbar', true),
ContextKeyExpr.equals('config.notebook.experimental.openGettingStarted', true)
),
order: 0
},
{
id: MenuId.NotebookToolbar,
group: 'notebookLayout',
when: ContextKeyExpr.equals('config.notebook.globalToolbar', true),
when: ContextKeyExpr.and(
ContextKeyExpr.equals('config.notebook.globalToolbar', true),
ContextKeyExpr.equals('config.notebook.experimental.openGettingStarted', true)
),
order: 0
}
]

View file

@ -65,7 +65,7 @@ class NotebookViewportContribution extends Disposable implements INotebookEditor
if (pickedMimeTypeRenderer.rendererId === BUILTIN_RENDERER_ID) {
const renderer = this._notebookEditor.getOutputRenderer().getContribution(pickedMimeTypeRenderer.mimeType);
if (renderer?.getType() === RenderOutputType.Html) {
const renderResult = renderer.render(output, output.model.outputs.filter(op => op.mime === pickedMimeTypeRenderer.mimeType), DOM.$(''), this._notebookEditor.viewModel.uri) as IInsetRenderOutput;
const renderResult = renderer.render(output, output.model.outputs.filter(op => op.mime === pickedMimeTypeRenderer.mimeType)[0], DOM.$(''), this._notebookEditor.viewModel.uri) as IInsetRenderOutput;
this._notebookEditor.createOutput(viewCell, renderResult, 0);
}
return;

View file

@ -764,7 +764,7 @@ export interface IOutputTransformContribution {
* This call is allowed to have side effects, such as placing output
* directly into the container element.
*/
render(output: ICellOutputViewModel, items: IOutputItemDto[], container: HTMLElement, notebookUri: URI): IRenderOutput;
render(output: ICellOutputViewModel, item: IOutputItemDto, container: HTMLElement, notebookUri: URI): IRenderOutput;
}
export interface CellFindMatch {

View file

@ -68,6 +68,6 @@ export class OutputRenderer {
return this._renderMessage(container, localize('empty', "Cell has no output"));
}
return renderer.render(viewModel, [first], container, notebookUri);
return renderer.render(viewModel, first, container, notebookUri);
}
}

View file

@ -39,13 +39,11 @@ class JavaScriptRendererContrib extends Disposable implements IOutputRendererCon
super();
}
render(output: ICellOutputViewModel, items: IOutputItemDto[], container: HTMLElement, notebookUri: URI): IRenderOutput {
let scriptVal = '';
items.forEach(item => {
const str = getStringValue(item);
scriptVal += `<script type="application/javascript">${str}</script>`;
render(output: ICellOutputViewModel, item: IOutputItemDto, container: HTMLElement, notebookUri: URI): IRenderOutput {
const str = getStringValue(item);
const scriptVal = `<script type="application/javascript">${str}</script>`;
});
return {
type: RenderOutputType.Html,
source: output,
@ -72,8 +70,8 @@ class CodeRendererContrib extends Disposable implements IOutputRendererContribut
super();
}
render(output: ICellOutputViewModel, items: IOutputItemDto[], container: HTMLElement): IRenderOutput {
const value = items.map(getStringValue).join('');
render(output: ICellOutputViewModel, item: IOutputItemDto, container: HTMLElement): IRenderOutput {
const value = getStringValue(item);
return this._render(output, container, value, 'javascript');
}
@ -106,8 +104,8 @@ class JSONRendererContrib extends CodeRendererContrib {
return ['application/json'];
}
override render(output: ICellOutputViewModel, items: IOutputItemDto[], container: HTMLElement): IRenderOutput {
const str = items.map(getStringValue).join('');
override render(output: ICellOutputViewModel, item: IOutputItemDto, container: HTMLElement): IRenderOutput {
const str = getStringValue(item);
return this._render(output, container, str, 'jsonc');
}
}
@ -130,15 +128,13 @@ class StreamRendererContrib extends Disposable implements IOutputRendererContrib
super();
}
render(output: ICellOutputViewModel, items: IOutputItemDto[], container: HTMLElement, notebookUri: URI): IRenderOutput {
render(output: ICellOutputViewModel, item: IOutputItemDto, container: HTMLElement, notebookUri: URI): IRenderOutput {
const linkDetector = this.instantiationService.createInstance(LinkDetector);
items.forEach(item => {
const text = getStringValue(item);
const contentNode = DOM.$('span.output-stream');
truncatedArrayOfString(notebookUri!, output.cellViewModel, contentNode, [text], linkDetector, this.openerService, this.themeService);
container.appendChild(contentNode);
});
const text = getStringValue(item);
const contentNode = DOM.$('span.output-stream');
truncatedArrayOfString(notebookUri, output.cellViewModel, contentNode, [text], linkDetector, this.openerService, this.themeService);
container.appendChild(contentNode);
return { type: RenderOutputType.Mainframe };
}
@ -153,8 +149,8 @@ class StderrRendererContrib extends StreamRendererContrib {
return ['application/vnd.code.notebook.stderr', 'application/x.notebook.stderr'];
}
override render(output: ICellOutputViewModel, items: IOutputItemDto[], container: HTMLElement, notebookUri: URI): IRenderOutput {
const result = super.render(output, items, container, notebookUri);
override render(output: ICellOutputViewModel, item: IOutputItemDto, container: HTMLElement, notebookUri: URI): IRenderOutput {
const result = super.render(output, item, container, notebookUri);
container.classList.add('error');
return result;
}
@ -181,35 +177,34 @@ class JSErrorRendererContrib implements IOutputRendererContribution {
return ['application/vnd.code.notebook.error'];
}
render(_output: ICellOutputViewModel, items: IOutputItemDto[], container: HTMLElement, _notebookUri: URI): IRenderOutput {
render(_output: ICellOutputViewModel, item: IOutputItemDto, container: HTMLElement, _notebookUri: URI): IRenderOutput {
const linkDetector = this._instantiationService.createInstance(LinkDetector);
type ErrorLike = Partial<Error>;
for (let item of items) {
let err: ErrorLike;
try {
err = <ErrorLike>JSON.parse(getStringValue(item));
} catch (e) {
this._logService.warn('INVALID output item (failed to parse)', e);
continue;
}
const header = document.createElement('div');
const headerMessage = err.name && err.message ? `${err.name}: ${err.message}` : err.name || err.message;
if (headerMessage) {
header.innerText = headerMessage;
container.appendChild(header);
}
const stack = document.createElement('pre');
stack.classList.add('traceback');
if (err.stack) {
stack.appendChild(handleANSIOutput(err.stack, linkDetector, this._themeService, undefined));
}
container.appendChild(stack);
container.classList.add('error');
let err: ErrorLike;
try {
err = <ErrorLike>JSON.parse(getStringValue(item));
} catch (e) {
this._logService.warn('INVALID output item (failed to parse)', e);
return { type: RenderOutputType.Mainframe };
}
const header = document.createElement('div');
const headerMessage = err.name && err.message ? `${err.name}: ${err.message}` : err.name || err.message;
if (headerMessage) {
header.innerText = headerMessage;
container.appendChild(header);
}
const stack = document.createElement('pre');
stack.classList.add('traceback');
if (err.stack) {
stack.appendChild(handleANSIOutput(err.stack, linkDetector, this._themeService, undefined));
}
container.appendChild(stack);
container.classList.add('error');
return { type: RenderOutputType.Mainframe };
}
}
@ -232,12 +227,12 @@ class PlainTextRendererContrib extends Disposable implements IOutputRendererCont
super();
}
render(output: ICellOutputViewModel, items: IOutputItemDto[], container: HTMLElement, notebookUri: URI): IRenderOutput {
render(output: ICellOutputViewModel, item: IOutputItemDto, container: HTMLElement, notebookUri: URI): IRenderOutput {
const linkDetector = this.instantiationService.createInstance(LinkDetector);
const str = items.map(getStringValue);
const str = getStringValue(item);
const contentNode = DOM.$('.output-plaintext');
truncatedArrayOfString(notebookUri!, output.cellViewModel, contentNode, str, linkDetector, this.openerService, this.themeService);
truncatedArrayOfString(notebookUri, output.cellViewModel, contentNode, [str], linkDetector, this.openerService, this.themeService);
container.appendChild(contentNode);
return { type: RenderOutputType.Mainframe, supportAppend: true };
@ -259,8 +254,8 @@ class HTMLRendererContrib extends Disposable implements IOutputRendererContribut
super();
}
render(output: ICellOutputViewModel, items: IOutputItemDto[], container: HTMLElement, notebookUri: URI): IRenderOutput {
const str = items.map(getStringValue).join('');
render(output: ICellOutputViewModel, item: IOutputItemDto, container: HTMLElement, notebookUri: URI): IRenderOutput {
const str = getStringValue(item);
return {
type: RenderOutputType.Html,
source: output,
@ -285,16 +280,14 @@ class MdRendererContrib extends Disposable implements IOutputRendererContributio
super();
}
render(output: ICellOutputViewModel, items: IOutputItemDto[], container: HTMLElement, notebookUri: URI): IRenderOutput {
render(output: ICellOutputViewModel, item: IOutputItemDto, container: HTMLElement, notebookUri: URI): IRenderOutput {
const disposable = new DisposableStore();
for (let item of items) {
const str = getStringValue(item);
const mdOutput = document.createElement('div');
const mdRenderer = this.instantiationService.createInstance(MarkdownRenderer, { baseUrl: dirname(notebookUri) });
mdOutput.appendChild(mdRenderer.render({ value: str, isTrusted: true, supportThemeIcons: true }, undefined, { gfm: true }).element);
container.appendChild(mdOutput);
disposable.add(mdRenderer);
}
const str = getStringValue(item);
const mdOutput = document.createElement('div');
const mdRenderer = this.instantiationService.createInstance(MarkdownRenderer, { baseUrl: dirname(notebookUri) });
mdOutput.appendChild(mdRenderer.render({ value: str, isTrusted: true, supportThemeIcons: true }, undefined, { gfm: true }).element);
container.appendChild(mdOutput);
disposable.add(mdRenderer);
return { type: RenderOutputType.Mainframe, disposable };
}
}
@ -314,23 +307,21 @@ class ImgRendererContrib extends Disposable implements IOutputRendererContributi
super();
}
render(output: ICellOutputViewModel, items: IOutputItemDto[], container: HTMLElement, notebookUri: URI): IRenderOutput {
render(output: ICellOutputViewModel, item: IOutputItemDto, container: HTMLElement, notebookUri: URI): IRenderOutput {
const disposable = new DisposableStore();
for (let item of items) {
const bytes = new Uint8Array(item.valueBytes);
const blob = new Blob([bytes], { type: item.mime });
const src = URL.createObjectURL(blob);
disposable.add(toDisposable(() => URL.revokeObjectURL(src)));
const bytes = new Uint8Array(item.valueBytes);
const blob = new Blob([bytes], { type: item.mime });
const src = URL.createObjectURL(blob);
disposable.add(toDisposable(() => URL.revokeObjectURL(src)));
const image = document.createElement('img');
image.src = src;
const display = document.createElement('div');
display.classList.add('display');
display.appendChild(image);
container.appendChild(display);
const image = document.createElement('img');
image.src = src;
const display = document.createElement('div');
display.classList.add('display');
display.appendChild(image);
container.appendChild(display);
}
return { type: RenderOutputType.Mainframe, disposable };
}
}

View file

@ -8,7 +8,7 @@ import { Emitter, Event } from 'vs/base/common/event';
import { Disposable, dispose, IDisposable } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
import { INotebookTextModel, NotebookCellOutputsSplice, NotebookDocumentMetadata, NotebookCellMetadata, ICellEditOperation, CellEditType, CellUri, notebookDocumentMetadataDefaults, diff, NotebookCellsChangeType, ICellDto2, TransientOptions, NotebookTextModelChangedEvent, NotebookRawContentEvent, IOutputDto, ICellOutput, IOutputItemDto, ISelectionState, NullablePartialNotebookCellMetadata, NotebookCellInternalMetadata, NullablePartialNotebookCellInternalMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { INotebookTextModel, NotebookCellOutputsSplice, NotebookDocumentMetadata, NotebookCellMetadata, ICellEditOperation, CellEditType, CellUri, diff, NotebookCellsChangeType, ICellDto2, TransientOptions, NotebookTextModelChangedEvent, NotebookRawContentEvent, IOutputDto, ICellOutput, IOutputItemDto, ISelectionState, NullablePartialNotebookCellMetadata, NotebookCellInternalMetadata, NullablePartialNotebookCellInternalMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { IUndoRedoService, UndoRedoElementType, IUndoRedoElement, IResourceUndoRedoElement, UndoRedoGroup, IWorkspaceUndoRedoElement } from 'vs/platform/undoRedo/common/undoRedo';
import { MoveCellEdit, SpliceCellsEdit, CellMetadataEdit } from 'vs/workbench/contrib/notebook/common/model/cellEdit';
import { ISequence, LcsDiff } from 'vs/base/common/diff/diff';
@ -197,7 +197,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
private _cellListeners: Map<number, IDisposable> = new Map();
private _cells: NotebookCellTextModel[] = [];
metadata: NotebookDocumentMetadata = notebookDocumentMetadataDefaults;
metadata: NotebookDocumentMetadata = {};
transientOptions: TransientOptions = { transientCellMetadata: {}, transientDocumentMetadata: {}, transientOutputs: false };
private _versionId = 0;

View file

@ -60,14 +60,7 @@ export enum NotebookRunState {
Idle = 2
}
export const notebookDocumentMetadataDefaults: Required<NotebookDocumentMetadata> = {
custom: {},
};
export interface NotebookDocumentMetadata {
custom?: { [key: string]: unknown; };
[key: string]: unknown;
}
export type NotebookDocumentMetadata = Record<string, unknown>;
// Aligns with the vscode.d.ts version
export enum NotebookCellExecutionState {

View file

@ -20,7 +20,7 @@ import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/v
import { NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
import { ViewContext } from 'vs/workbench/contrib/notebook/browser/viewModel/viewContext';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
import { CellKind, diff, notebookDocumentMetadataDefaults } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CellKind, diff } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { NotebookOptions } from 'vs/workbench/contrib/notebook/common/notebookOptions';
import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange';
import { NotebookEditorTestModel, setupInstantiationService, withTestNotebook } from 'vs/workbench/contrib/notebook/test/testNotebookEditor';
@ -37,7 +37,7 @@ suite('NotebookViewModel', () => {
instantiationService.stub(IThemeService, new TestThemeService());
test('ctor', function () {
const notebook = new NotebookTextModel('notebook', URI.parse('test'), [], notebookDocumentMetadataDefaults, { transientCellMetadata: {}, transientDocumentMetadata: {}, transientOutputs: false }, undoRedoService, modelService, modeService);
const notebook = new NotebookTextModel('notebook', URI.parse('test'), [], {}, { transientCellMetadata: {}, transientDocumentMetadata: {}, transientOutputs: false }, undoRedoService, modelService, modeService);
const model = new NotebookEditorTestModel(notebook);
const viewContext = new ViewContext(new NotebookOptions(instantiationService.get(IConfigurationService)), new NotebookEventDispatcher());
const viewModel = new NotebookViewModel('notebook', model.notebook, viewContext, null, instantiationService, bulkEditService, undoRedoService, textModelService);

View file

@ -21,7 +21,7 @@ import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/v
import { CellViewModel, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
import { CellKind, CellUri, INotebookDiffEditorModel, INotebookEditorModel, IOutputDto, IResolvedNotebookEditorModel, NotebookCellMetadata, notebookDocumentMetadataDefaults } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CellKind, CellUri, INotebookDiffEditorModel, INotebookEditorModel, IOutputDto, IResolvedNotebookEditorModel, NotebookCellMetadata, } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange';
import { TextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService';
import { IModelService } from 'vs/editor/common/services/modelService';
@ -176,7 +176,7 @@ function _createTestNotebookEditor(instantiationService: TestInstantiationServic
outputs: cell[3] ?? [],
metadata: cell[4]
};
}), notebookDocumentMetadataDefaults, { transientCellMetadata: {}, transientDocumentMetadata: {}, transientOutputs: false });
}), {}, { transientCellMetadata: {}, transientDocumentMetadata: {}, transientOutputs: false });
const model = new NotebookEditorTestModel(notebook);
const viewContext = new ViewContext(new NotebookOptions(instantiationService.get(IConfigurationService)), new NotebookEventDispatcher());