notebook.test.ts 59.8 KB
Newer Older
R
rebornix 已提交
1 2 3 4 5 6 7 8
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import 'mocha';
import * as assert from 'assert';
import * as vscode from 'vscode';
9
import { createRandomFile, asPromise, disposeAll, closeAllEditors, revertAllDirty, saveAllEditors, assertNoRpc } from '../utils';
10
import { TextDecoder } from 'util';
R
rebornix 已提交
11

R
Rob Lourens 已提交
12 13 14 15
async function createRandomNotebookFile() {
	return createRandomFile('', undefined, '.vsctestnb');
}

16 17 18
async function openRandomNotebookDocument() {
	const uri = await createRandomNotebookFile();
	return vscode.notebook.openNotebookDocument(uri);
19 20
}

21 22
async function saveAllFilesAndCloseAll() {
	await saveAllEditors();
R
rebornix 已提交
23
	await closeAllEditors();
24 25
}

R
rebornix 已提交
26
async function withEvent<T>(event: vscode.Event<T>, callback: (e: Promise<T>) => Promise<void>) {
27
	const e = asPromise<T>(event);
R
rebornix 已提交
28 29 30
	await callback(e);
}

31

32
class Kernel {
33

34 35
	readonly controller: vscode.NotebookController;

36 37
	readonly associatedNotebooks = new Set<string>();

38 39 40 41 42
	constructor(id: string, label: string) {
		this.controller = vscode.notebook.createNotebookController(id, 'notebookCoreTest', label);
		this.controller.executeHandler = this._execute.bind(this);
		this.controller.hasExecutionOrder = true;
		this.controller.supportedLanguages = ['typescript', 'javascript'];
43 44 45 46 47 48 49
		this.controller.onDidChangeNotebookAssociation(e => {
			if (e.selected) {
				this.associatedNotebooks.add(e.notebook.uri.toString());
			} else {
				this.associatedNotebooks.delete(e.notebook.uri.toString());
			}
		});
R
Rob Lourens 已提交
50 51
	}

52 53
	protected async _execute(cells: vscode.NotebookCell[]): Promise<void> {
		for (let cell of cells) {
J
Johannes Rieken 已提交
54
			await this._runCell(cell);
R
Rob Lourens 已提交
55
		}
56
	}
R
Rob Lourens 已提交
57

J
Johannes Rieken 已提交
58
	protected async _runCell(cell: vscode.NotebookCell) {
59
		const task = this.controller.createNotebookCellExecution(cell);
R
Rob Lourens 已提交
60 61
		task.start();
		task.executionOrder = 1;
62
		if (cell.notebook.uri.path.endsWith('customRenderer.vsctestnb')) {
R
Rob Lourens 已提交
63
			await task.replaceOutput([new vscode.NotebookCellOutput([
64
				vscode.NotebookCellOutputItem.text('test', 'text/custom', undefined)
65
			])]);
R
Rob Lourens 已提交
66
			return;
67 68
		}

R
Rob Lourens 已提交
69
		await task.replaceOutput([new vscode.NotebookCellOutput([
70
			vscode.NotebookCellOutputItem.text('my output', 'text/plain', undefined)
71
		])]);
R
Rob Lourens 已提交
72 73
		task.end({ success: true });
	}
74
}
R
Rob Lourens 已提交
75

76

R
rebornix 已提交
77 78 79 80
function getFocusedCell(editor?: vscode.NotebookEditor) {
	return editor ? editor.document.cellAt(editor.selections[0].start) : undefined;
}

81
async function assertKernel(kernel: Kernel, notebook: vscode.NotebookDocument): Promise<void> {
82 83
	const success = await vscode.commands.executeCommand('notebook.selectKernel', {
		extension: 'vscode.vscode-api-tests',
84
		id: kernel.controller.id
85
	});
86 87
	assert.ok(success, `expected selected kernel to be ${kernel.controller.id}`);
	assert.ok(kernel.associatedNotebooks.has(notebook.uri.toString()));
88 89
}

D
Oops  
Don Jayamanne 已提交
90
suite('Notebook API tests', function () {
91

R
Rob Lourens 已提交
92 93
	const testDisposables: vscode.Disposable[] = [];
	const suiteDisposables: vscode.Disposable[] = [];
94 95

	suiteTeardown(async function () {
96 97 98

		assertNoRpc();

99
		await revertAllDirty();
100
		await closeAllEditors();
101

R
Rob Lourens 已提交
102 103
		disposeAll(suiteDisposables);
		suiteDisposables.length = 0;
104 105 106
	});

	suiteSetup(function () {
R
Rob Lourens 已提交
107
		suiteDisposables.push(vscode.notebook.registerNotebookContentProvider('notebookCoreTest', {
108 109
			openNotebook: async (resource: vscode.Uri): Promise<vscode.NotebookData> => {
				if (/.*empty\-.*\.vsctestnb$/.test(resource.path)) {
110
					return {
111
						metadata: new vscode.NotebookDocumentMetadata(),
112 113 114 115 116
						cells: []
					};
				}

				const dto: vscode.NotebookData = {
117
					metadata: new vscode.NotebookDocumentMetadata().with({ custom: { testMetadata: false } }),
118 119
					cells: [
						{
120 121
							value: 'test',
							languageId: 'typescript',
122
							kind: vscode.NotebookCellKind.Code,
123
							outputs: [],
124
							metadata: new vscode.NotebookCellMetadata().with({ custom: { testCellMetadata: 123 } }),
125
							executionSummary: { startTime: 10, endTime: 20 }
126 127
						},
						{
128 129
							value: 'test2',
							languageId: 'typescript',
130
							kind: vscode.NotebookCellKind.Code,
131 132
							outputs: [
								new vscode.NotebookCellOutput([
133
									vscode.NotebookCellOutputItem.text('Hello World', 'text/plain', { testOutputItemMetadata: true })
134 135 136
								],
									{ testOutputMetadata: true })
							],
137
							executionSummary: { executionOrder: 5, success: true },
138
							metadata: new vscode.NotebookCellMetadata().with({ custom: { testCellMetadata: 456 } })
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
						}
					]
				};
				return dto;
			},
			saveNotebook: async (_document: vscode.NotebookDocument, _cancellation: vscode.CancellationToken) => {
				return;
			},
			saveNotebookAs: async (_targetResource: vscode.Uri, _document: vscode.NotebookDocument, _cancellation: vscode.CancellationToken) => {
				return;
			},
			backupNotebook: async (_document: vscode.NotebookDocument, _context: vscode.NotebookDocumentBackupContext, _cancellation: vscode.CancellationToken) => {
				return {
					id: '1',
					delete: () => { }
				};
			}
		}));
R
Rob Lourens 已提交
157
	});
158

159 160 161
	let kernel1: Kernel;
	let kernel2: Kernel;

162
	setup(async function () {
163

164
		kernel1 = new Kernel('mainKernel', 'Notebook Primary Test Kernel');
165

J
Johannes Rieken 已提交
166 167 168 169 170 171 172 173 174 175
		const listener = vscode.notebook.onDidOpenNotebookDocument(async notebook => {
			if (notebook.viewType === kernel1.controller.viewType) {
				await vscode.commands.executeCommand('notebook.selectKernel', {
					extension: 'vscode.vscode-api-tests',
					id: kernel1.controller.id
				});
			}
		});


176
		kernel2 = new class extends Kernel {
177 178 179 180
			constructor() {
				super('secondaryKernel', 'Notebook Secondary Test Kernel');
				this.controller.hasExecutionOrder = false;
			}
J
Johannes Rieken 已提交
181 182

			override async _runCell(cell: vscode.NotebookCell) {
183
				const task = this.controller.createNotebookCellExecution(cell);
J
Johannes Rieken 已提交
184 185
				task.start();
				await task.replaceOutput([new vscode.NotebookCellOutput([
186
					vscode.NotebookCellOutputItem.text('my second output', 'text/plain', undefined)
J
Johannes Rieken 已提交
187 188 189
				])]);
				task.end({ success: true });
			}
190 191
		};

J
Johannes Rieken 已提交
192
		testDisposables.push(kernel1.controller, listener, kernel2.controller);
193
		await saveAllFilesAndCloseAll();
R
Rob Lourens 已提交
194 195
	});

196
	teardown(async function () {
R
Rob Lourens 已提交
197 198
		disposeAll(testDisposables);
		testDisposables.length = 0;
199
		await saveAllFilesAndCloseAll();
200 201
	});

D
Oops  
Don Jayamanne 已提交
202
	test('shared document in notebook editors', async function () {
203
		let counter = 0;
204
		testDisposables.push(vscode.notebook.onDidOpenNotebookDocument(() => {
205 206
			counter++;
		}));
207 208

		const notebook = await openRandomNotebookDocument();
J
Johannes Rieken 已提交
209
		assert.strictEqual(counter, 1);
210

211
		await vscode.window.showNotebookDocument(notebook, { viewColumn: vscode.ViewColumn.Active });
J
Johannes Rieken 已提交
212
		assert.strictEqual(counter, 1);
213
		assert.strictEqual(vscode.window.visibleNotebookEditors.length, 1);
214

215 216 217
		await vscode.window.showNotebookDocument(notebook, { viewColumn: vscode.ViewColumn.Beside });
		assert.strictEqual(counter, 1);
		assert.strictEqual(vscode.window.visibleNotebookEditors.length, 2);
218 219
	});

220
	test('editor onDidChangeVisibleNotebookEditors-event', async function () {
R
Rob Lourens 已提交
221
		const resource = await createRandomNotebookFile();
222
		const firstEditorOpen = asPromise(vscode.window.onDidChangeVisibleNotebookEditors);
223
		await vscode.window.showNotebookDocument(resource);
224 225
		await firstEditorOpen;

226
		const firstEditorClose = asPromise(vscode.window.onDidChangeVisibleNotebookEditors);
R
rebornix 已提交
227
		await closeAllEditors();
228 229 230
		await firstEditorClose;
	});

231
	test('editor onDidChangeVisibleNotebookEditors-event 2', async function () {
R
Rob Lourens 已提交
232
		const resource = await createRandomNotebookFile();
233 234
		let count = 0;
		const disposables: vscode.Disposable[] = [];
R
rebornix 已提交
235 236
		disposables.push(vscode.window.onDidChangeVisibleNotebookEditors(() => {
			count = vscode.window.visibleNotebookEditors.length;
237 238
		}));

239
		await vscode.window.showNotebookDocument(resource, { viewColumn: vscode.ViewColumn.Active });
J
Johannes Rieken 已提交
240
		assert.strictEqual(count, 1);
241

242
		await vscode.window.showNotebookDocument(resource, { viewColumn: vscode.ViewColumn.Beside });
J
Johannes Rieken 已提交
243
		assert.strictEqual(count, 2);
244

R
rebornix 已提交
245
		await closeAllEditors();
J
Johannes Rieken 已提交
246
		assert.strictEqual(count, 0);
247 248
	});

249
	test('correct cell selection on undo/redo of cell creation', async function () {
R
Rob Lourens 已提交
250
		const resource = await createRandomNotebookFile();
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
		await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
		await vscode.commands.executeCommand('undo');
		const selectionUndo = [...vscode.window.activeNotebookEditor!.selections];
		await vscode.commands.executeCommand('redo');
		const selectionRedo = vscode.window.activeNotebookEditor!.selections;

		// On undo, the selected cell must be the upper cell, ie the first one
		assert.strictEqual(selectionUndo.length, 1);
		assert.strictEqual(selectionUndo[0].start, 0);
		assert.strictEqual(selectionUndo[0].end, 1);
		// On redo, the selected cell must be the new cell, ie the second one
		assert.strictEqual(selectionRedo.length, 1);
		assert.strictEqual(selectionRedo[0].start, 1);
		assert.strictEqual(selectionRedo[0].end, 2);
	});

D
Oops  
Don Jayamanne 已提交
268
	test('editor editing event 2', async function () {
R
Rob Lourens 已提交
269
		const resource = await createRandomNotebookFile();
270 271
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');

272
		const cellsChangeEvent = asPromise<vscode.NotebookCellsChangeEvent>(vscode.notebook.onDidChangeNotebookCells);
273 274
		await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
		const cellChangeEventRet = await cellsChangeEvent;
J
Johannes Rieken 已提交
275 276 277
		assert.strictEqual(cellChangeEventRet.document, vscode.window.activeNotebookEditor?.document);
		assert.strictEqual(cellChangeEventRet.changes.length, 1);
		assert.deepStrictEqual(cellChangeEventRet.changes[0], {
278 279
			start: 1,
			deletedCount: 0,
R
:guard:  
rebornix 已提交
280
			deletedItems: [],
281
			items: [
282
				vscode.window.activeNotebookEditor!.document.cellAt(1)
283 284 285
			]
		});

286
		const moveCellEvent = asPromise<vscode.NotebookCellsChangeEvent>(vscode.notebook.onDidChangeNotebookCells);
287
		await vscode.commands.executeCommand('notebook.cell.moveUp');
R
rebornix 已提交
288
		await moveCellEvent;
289

290
		const cellOutputChange = asPromise<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs);
291 292
		await vscode.commands.executeCommand('notebook.cell.execute');
		const cellOutputsAddedRet = await cellOutputChange;
J
Johannes Rieken 已提交
293
		assert.deepStrictEqual(cellOutputsAddedRet, {
R
rebornix 已提交
294
			document: vscode.window.activeNotebookEditor!.document,
295
			cells: [vscode.window.activeNotebookEditor!.document.cellAt(0)]
296
		});
R
rebornix 已提交
297
		assert.strictEqual(cellOutputsAddedRet.cells[0].outputs.length, 1);
298

299
		const cellOutputClear = asPromise<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs);
300 301
		await vscode.commands.executeCommand('notebook.cell.clearOutputs');
		const cellOutputsCleardRet = await cellOutputClear;
J
Johannes Rieken 已提交
302
		assert.deepStrictEqual(cellOutputsCleardRet, {
R
rebornix 已提交
303
			document: vscode.window.activeNotebookEditor!.document,
304
			cells: [vscode.window.activeNotebookEditor!.document.cellAt(0)]
305
		});
R
rebornix 已提交
306
		assert.strictEqual(cellOutputsAddedRet.cells[0].outputs.length, 0);
307 308 309 310

		// const cellChangeLanguage = getEventOncePromise<vscode.NotebookCellLanguageChangeEvent>(vscode.notebook.onDidChangeCellLanguage);
		// await vscode.commands.executeCommand('notebook.cell.changeToMarkdown');
		// const cellChangeLanguageRet = await cellChangeLanguage;
J
Johannes Rieken 已提交
311
		// assert.deepStrictEqual(cellChangeLanguageRet, {
R
rebornix 已提交
312
		// 	document: vscode.window.activeNotebookEditor!.document,
313
		// 	cells: vscode.window.activeNotebookEditor!.document.cellAt(0),
314 315 316
		// 	language: 'markdown'
		// });
	});
R
rebornix 已提交
317

D
Oops  
Don Jayamanne 已提交
318
	test('editor move cell event', async function () {
R
Rob Lourens 已提交
319
		const resource = await createRandomNotebookFile();
320 321 322 323 324
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
		await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
		await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove');
		await vscode.commands.executeCommand('notebook.focusTop');

R
rebornix 已提交
325
		const activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
326
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 0);
327
		const moveChange = asPromise(vscode.notebook.onDidChangeNotebookCells);
328
		await vscode.commands.executeCommand('notebook.cell.moveDown');
R
rebornix 已提交
329
		await moveChange;
R
rebornix 已提交
330 331
		await saveAllEditors();
		await closeAllEditors();
332 333

		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
R
rebornix 已提交
334
		const firstEditor = vscode.window.activeNotebookEditor;
335
		assert.strictEqual(firstEditor?.document.cellCount, 2);
336 337
	});

D
Oops  
Don Jayamanne 已提交
338
	test('notebook editor active/visible', async function () {
R
Rob Lourens 已提交
339
		const resource = await createRandomNotebookFile();
340 341 342 343 344 345
		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);
R
rebornix 已提交
346

R
rebornix 已提交
347
		assert.notStrictEqual(firstEditor, secondEditor);
348 349
		assert.strictEqual(vscode.window.visibleNotebookEditors.includes(secondEditor), true);
		assert.strictEqual(vscode.window.visibleNotebookEditors.includes(firstEditor), true);
J
Johannes Rieken 已提交
350
		assert.strictEqual(vscode.window.visibleNotebookEditors.length, 2);
R
rebornix 已提交
351

352
		const untitledEditorChange = asPromise(vscode.window.onDidChangeActiveNotebookEditor);
R
rebornix 已提交
353
		await vscode.commands.executeCommand('workbench.action.files.newUntitledFile');
354
		await untitledEditorChange;
R
rebornix 已提交
355
		assert.strictEqual(firstEditor && vscode.window.visibleNotebookEditors.indexOf(firstEditor) >= 0, true);
R
rebornix 已提交
356 357 358
		assert.notStrictEqual(firstEditor, vscode.window.activeNotebookEditor);
		assert.strictEqual(secondEditor && vscode.window.visibleNotebookEditors.indexOf(secondEditor) < 0, true);
		assert.notStrictEqual(secondEditor, vscode.window.activeNotebookEditor);
J
Johannes Rieken 已提交
359
		assert.strictEqual(vscode.window.visibleNotebookEditors.length, 1);
R
rebornix 已提交
360

361
		const activeEditorClose = asPromise(vscode.window.onDidChangeActiveNotebookEditor);
R
rebornix 已提交
362
		await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
363
		await activeEditorClose;
R
rebornix 已提交
364
		assert.strictEqual(secondEditor, vscode.window.activeNotebookEditor);
J
Johannes Rieken 已提交
365
		assert.strictEqual(vscode.window.visibleNotebookEditors.length, 2);
R
rebornix 已提交
366
		assert.strictEqual(secondEditor && vscode.window.visibleNotebookEditors.indexOf(secondEditor) >= 0, true);
R
rebornix 已提交
367
	});
R
rebornix 已提交
368

D
Oops  
Don Jayamanne 已提交
369
	test('notebook active editor change', async function () {
R
Rob Lourens 已提交
370
		const resource = await createRandomNotebookFile();
371
		const firstEditorOpen = asPromise(vscode.window.onDidChangeActiveNotebookEditor);
R
rebornix 已提交
372 373 374
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
		await firstEditorOpen;

375
		const firstEditorDeactivate = asPromise(vscode.window.onDidChangeActiveNotebookEditor);
R
rebornix 已提交
376 377 378
		await vscode.commands.executeCommand('workbench.action.splitEditor');
		await firstEditorDeactivate;
	});
379

D
Oops  
Don Jayamanne 已提交
380
	test('edit API (replaceMetadata)', async function () {
R
Rob Lourens 已提交
381
		const resource = await createRandomNotebookFile();
382 383
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');

R
rebornix 已提交
384
		await vscode.window.activeNotebookEditor!.edit(editBuilder => {
R
Rob Lourens 已提交
385
			editBuilder.replaceCellMetadata(0, new vscode.NotebookCellMetadata().with({ inputCollapsed: true }));
386 387
		});

R
rebornix 已提交
388
		const document = vscode.window.activeNotebookEditor?.document!;
389 390
		assert.strictEqual(document.cellCount, 2);
		assert.strictEqual(document.cellAt(0).metadata.inputCollapsed, true);
391 392 393 394

		assert.strictEqual(document.isDirty, true);
	});

D
Oops  
Don Jayamanne 已提交
395
	test('edit API (replaceMetadata, event)', async function () {
R
Rob Lourens 已提交
396
		const resource = await createRandomNotebookFile();
397 398
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');

399
		const event = asPromise<vscode.NotebookCellMetadataChangeEvent>(vscode.notebook.onDidChangeCellMetadata);
400

R
rebornix 已提交
401
		await vscode.window.activeNotebookEditor!.edit(editBuilder => {
R
Rob Lourens 已提交
402
			editBuilder.replaceCellMetadata(0, new vscode.NotebookCellMetadata().with({ inputCollapsed: true }));
403 404 405
		});

		const data = await event;
R
rebornix 已提交
406
		assert.strictEqual(data.document, vscode.window.activeNotebookEditor?.document);
407
		assert.strictEqual(data.cell.metadata.inputCollapsed, true);
408

409
		assert.strictEqual(data.document.isDirty, true);
410
	});
411

D
Oops  
Don Jayamanne 已提交
412
	test('edit API batch edits', async function () {
R
Rob Lourens 已提交
413
		const resource = await createRandomNotebookFile();
R
rebornix 已提交
414 415
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');

416 417
		const cellsChangeEvent = asPromise<vscode.NotebookCellsChangeEvent>(vscode.notebook.onDidChangeNotebookCells);
		const cellMetadataChangeEvent = asPromise<vscode.NotebookCellMetadataChangeEvent>(vscode.notebook.onDidChangeCellMetadata);
R
rebornix 已提交
418 419
		const version = vscode.window.activeNotebookEditor!.document.version;
		await vscode.window.activeNotebookEditor!.edit(editBuilder => {
420
			editBuilder.replaceCells(1, 0, [{ kind: vscode.NotebookCellKind.Code, languageId: 'javascript', value: 'test 2', outputs: [], metadata: undefined }]);
R
rebornix 已提交
421
			editBuilder.replaceCellMetadata(0, new vscode.NotebookCellMetadata().with({ inputCollapsed: false }));
R
rebornix 已提交
422 423 424 425
		});

		await cellsChangeEvent;
		await cellMetadataChangeEvent;
R
rebornix 已提交
426
		assert.strictEqual(version + 1, vscode.window.activeNotebookEditor!.document.version);
R
rebornix 已提交
427 428
	});

D
Oops  
Don Jayamanne 已提交
429
	test('edit API batch edits undo/redo', async function () {
R
Rob Lourens 已提交
430
		const resource = await createRandomNotebookFile();
R
rebornix 已提交
431 432
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');

433 434
		const cellsChangeEvent = asPromise<vscode.NotebookCellsChangeEvent>(vscode.notebook.onDidChangeNotebookCells);
		const cellMetadataChangeEvent = asPromise<vscode.NotebookCellMetadataChangeEvent>(vscode.notebook.onDidChangeCellMetadata);
R
rebornix 已提交
435 436
		const version = vscode.window.activeNotebookEditor!.document.version;
		await vscode.window.activeNotebookEditor!.edit(editBuilder => {
437
			editBuilder.replaceCells(1, 0, [{ kind: vscode.NotebookCellKind.Code, languageId: 'javascript', value: 'test 2', outputs: [], metadata: undefined }]);
R
rebornix 已提交
438
			editBuilder.replaceCellMetadata(0, new vscode.NotebookCellMetadata().with({ inputCollapsed: false }));
R
rebornix 已提交
439 440 441 442
		});

		await cellsChangeEvent;
		await cellMetadataChangeEvent;
443
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellCount, 3);
444
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellAt(0)?.metadata.inputCollapsed, false);
R
rebornix 已提交
445
		assert.strictEqual(version + 1, vscode.window.activeNotebookEditor!.document.version);
R
rebornix 已提交
446 447

		await vscode.commands.executeCommand('undo');
R
rebornix 已提交
448
		assert.strictEqual(version + 2, vscode.window.activeNotebookEditor!.document.version);
449
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellAt(0)?.metadata.inputCollapsed, undefined);
450
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellCount, 2);
R
rebornix 已提交
451 452
	});

D
Oops  
Don Jayamanne 已提交
453
	test('initialzation should not emit cell change events.', async function () {
R
Rob Lourens 已提交
454
		const resource = await createRandomNotebookFile();
455
		let count = 0;
456 457

		testDisposables.push(vscode.notebook.onDidChangeNotebookCells(() => {
458 459 460 461
			count++;
		}));

		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
J
Johannes Rieken 已提交
462
		assert.strictEqual(count, 0);
463
	});
464 465 466
	// });

	// suite('notebook workflow', () => {
467

D
Oops  
Don Jayamanne 已提交
468
	test('notebook open', async function () {
R
Rob Lourens 已提交
469
		const resource = await createRandomNotebookFile();
R
rebornix 已提交
470
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
J
Johannes Rieken 已提交
471
		assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
R
rebornix 已提交
472 473
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), 'test');
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.languageId, 'typescript');
R
rebornix 已提交
474

475
		const secondCell = vscode.window.activeNotebookEditor!.document.cellAt(1);
476 477
		assert.strictEqual(secondCell!.outputs.length, 1);
		assert.deepStrictEqual(secondCell!.outputs[0].metadata, { testOutputMetadata: true });
478 479 480 481 482
		assert.strictEqual((<any>secondCell!.outputs[0]).outputs.length, 1); //todo@jrieken will FAIL once the backwards compatibility is gone
		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.deepStrictEqual(secondCell!.outputs[0].items[0].metadata, { testOutputItemMetadata: true });
483 484
		assert.strictEqual(secondCell!.executionSummary?.executionOrder, 5);
		assert.strictEqual(secondCell!.executionSummary?.success, true);
485

R
Rob Lourens 已提交
486
		await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
R
rebornix 已提交
487
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), '');
R
rebornix 已提交
488

R
Rob Lourens 已提交
489
		await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove');
R
rebornix 已提交
490
		const activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
L
Logan Ramos 已提交
491
		assert.notStrictEqual(getFocusedCell(vscode.window.activeNotebookEditor), undefined);
J
Johannes Rieken 已提交
492
		assert.strictEqual(activeCell!.document.getText(), '');
493 494
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellCount, 4);
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 1);
R
rebornix 已提交
495 496 497 498 499

		await vscode.commands.executeCommand('workbench.action.files.save');
		await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
	});

D
Oops  
Don Jayamanne 已提交
500
	test('notebook cell actions', async function () {
R
Rob Lourens 已提交
501
		const resource = await createRandomNotebookFile();
R
rebornix 已提交
502
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
J
Johannes Rieken 已提交
503
		assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
R
rebornix 已提交
504 505
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), 'test');
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.languageId, 'typescript');
R
rebornix 已提交
506 507

		// ---- insert cell below and focus ---- //
R
Rob Lourens 已提交
508
		await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
R
rebornix 已提交
509
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), '');
R
rebornix 已提交
510 511

		// ---- insert cell above and focus ---- //
R
Rob Lourens 已提交
512
		await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove');
R
rebornix 已提交
513
		let activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
L
Logan Ramos 已提交
514
		assert.notStrictEqual(getFocusedCell(vscode.window.activeNotebookEditor), undefined);
J
Johannes Rieken 已提交
515
		assert.strictEqual(activeCell!.document.getText(), '');
516 517
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellCount, 4);
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 1);
R
rebornix 已提交
518 519

		// ---- focus bottom ---- //
R
Rob Lourens 已提交
520
		await vscode.commands.executeCommand('notebook.focusBottom');
R
rebornix 已提交
521
		activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
522
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 3);
R
rebornix 已提交
523 524

		// ---- focus top and then copy down ---- //
R
Rob Lourens 已提交
525
		await vscode.commands.executeCommand('notebook.focusTop');
R
rebornix 已提交
526
		activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
527
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 0);
R
rebornix 已提交
528

R
Rob Lourens 已提交
529
		await vscode.commands.executeCommand('notebook.cell.copyDown');
R
rebornix 已提交
530
		activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
531
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 1);
J
Johannes Rieken 已提交
532
		assert.strictEqual(activeCell?.document.getText(), 'test');
R
rebornix 已提交
533

R
Rob Lourens 已提交
534
		await vscode.commands.executeCommand('notebook.cell.delete');
R
rebornix 已提交
535
		activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
536
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 1);
J
Johannes Rieken 已提交
537
		assert.strictEqual(activeCell?.document.getText(), '');
R
rebornix 已提交
538 539

		// ---- focus top and then copy up ---- //
R
Rob Lourens 已提交
540 541
		await vscode.commands.executeCommand('notebook.focusTop');
		await vscode.commands.executeCommand('notebook.cell.copyUp');
542 543 544 545 546
		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(), '');
R
rebornix 已提交
547
		activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
548
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 0);
R
rebornix 已提交
549 550 551 552


		// ---- move up and down ---- //

R
Rob Lourens 已提交
553
		await vscode.commands.executeCommand('notebook.cell.moveDown');
R
rebornix 已提交
554 555
		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()}`);
556

R
rebornix 已提交
557
		// await vscode.commands.executeCommand('notebook.cell.moveDown');
R
rebornix 已提交
558
		// activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
R
rebornix 已提交
559

560
		// assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 2,
R
rebornix 已提交
561
		// 	`second move down, active cell ${getFocusedCell(vscode.window.activeNotebookEditor)!.uri.toString()}, ${getFocusedCell(vscode.window.activeNotebookEditor)!.document.getText()}`);
562 563 564 565
		// assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellAt(0).document.getText(), 'test');
		// assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellAt(1).document.getText(), '');
		// assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellAt(2).document.getText(), 'test');
		// assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellAt(3).document.getText(), '');
R
rebornix 已提交
566 567 568

		// ---- ---- //

569
		await vscode.commands.executeCommand('workbench.action.files.save');
R
rebornix 已提交
570 571
		await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
	});
R
Rob Lourens 已提交
572

D
Oops  
Don Jayamanne 已提交
573
	test('notebook join cells', async function () {
R
Rob Lourens 已提交
574
		const resource = await createRandomNotebookFile();
R
rebornix 已提交
575
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
J
Johannes Rieken 已提交
576
		assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
R
rebornix 已提交
577 578
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), 'test');
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.languageId, 'typescript');
R
rebornix 已提交
579 580

		await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
R
rebornix 已提交
581
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), '');
R
rebornix 已提交
582
		const edit = new vscode.WorkspaceEdit();
R
rebornix 已提交
583
		edit.insert(getFocusedCell(vscode.window.activeNotebookEditor)!.document.uri, new vscode.Position(0, 0), 'var abc = 0;');
R
rebornix 已提交
584
		await vscode.workspace.applyEdit(edit);
R
rebornix 已提交
585

586
		const cellsChangeEvent = asPromise<vscode.NotebookCellsChangeEvent>(vscode.notebook.onDidChangeNotebookCells);
R
rebornix 已提交
587 588 589
		await vscode.commands.executeCommand('notebook.cell.joinAbove');
		await cellsChangeEvent;

R
rebornix 已提交
590
		assert.deepStrictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText().split(/\r\n|\r|\n/), ['test', 'var abc = 0;']);
R
rebornix 已提交
591 592 593 594 595

		await vscode.commands.executeCommand('workbench.action.files.save');
		await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
	});

D
Oops  
Don Jayamanne 已提交
596
	test('move cells will not recreate cells in ExtHost', async function () {
R
Rob Lourens 已提交
597
		const resource = await createRandomNotebookFile();
598 599 600 601 602
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
		await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
		await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove');
		await vscode.commands.executeCommand('notebook.focusTop');

R
rebornix 已提交
603
		const activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
604
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 0);
605 606 607
		await vscode.commands.executeCommand('notebook.cell.moveDown');
		await vscode.commands.executeCommand('notebook.cell.moveDown');

R
rebornix 已提交
608
		const newActiveCell = getFocusedCell(vscode.window.activeNotebookEditor);
J
Johannes Rieken 已提交
609
		assert.deepStrictEqual(activeCell, newActiveCell);
610 611
	});

612
	// test('document runnable based on kernel count', async () => {
R
Rob Lourens 已提交
613
	// 	const resource = await createRandomNotebookFile();
614 615 616
	// 	await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
	// 	assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
	// 	const editor = vscode.window.activeNotebookEditor!;
R
Rob Lourens 已提交
617

618 619
	// 	const cell = editor.document.cellAt(0);
	// 	assert.strictEqual(cell.outputs.length, 0);
R
rebornix 已提交
620

621 622 623
	// 	currentKernelProvider.setHasKernels(false);
	// 	await vscode.commands.executeCommand('notebook.execute');
	// 	assert.strictEqual(cell.outputs.length, 0, 'should not execute'); // not runnable, didn't work
R
Rob Lourens 已提交
624

625
	// 	currentKernelProvider.setHasKernels(true);
626

627 628 629 630 631
	// 	await withEvent<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs, async (event) => {
	// 		await vscode.commands.executeCommand('notebook.execute');
	// 		await event;
	// 		assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked
	// 	});
R
Rob Lourens 已提交
632

633 634
	// 	await saveAllFilesAndCloseAll(undefined);
	// });
R
rebornix 已提交
635

R
rebornix 已提交
636 637 638

	// TODO@rebornix this is wrong, `await vscode.commands.executeCommand('notebook.execute');` doesn't wait until the workspace edit is applied
	test.skip('cell execute command takes arguments', async () => {
R
Rob Lourens 已提交
639
		const resource = await createRandomNotebookFile();
R
rebornix 已提交
640
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
J
Johannes Rieken 已提交
641
		assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
R
rebornix 已提交
642
		const editor = vscode.window.activeNotebookEditor!;
643
		const cell = editor.document.cellAt(0);
R
rebornix 已提交
644 645

		await vscode.commands.executeCommand('notebook.execute');
R
rebornix 已提交
646
		assert.strictEqual(cell.outputs.length, 0, 'should not execute'); // not runnable, didn't work
R
rebornix 已提交
647
	});
R
rebornix 已提交
648

D
Oops  
Don Jayamanne 已提交
649
	test('cell execute command takes arguments 2', async () => {
R
Rob Lourens 已提交
650
		const resource = await createRandomNotebookFile();
R
rebornix 已提交
651
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
J
Johannes Rieken 已提交
652
		assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
R
rebornix 已提交
653
		const editor = vscode.window.activeNotebookEditor!;
654
		const cell = editor.document.cellAt(0);
R
rebornix 已提交
655

R
rebornix 已提交
656 657 658
		await withEvent(vscode.notebook.onDidChangeCellOutputs, async (event) => {
			await vscode.commands.executeCommand('notebook.execute');
			await event;
R
rebornix 已提交
659
			assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked
R
rebornix 已提交
660 661 662 663 664
		});

		await withEvent(vscode.notebook.onDidChangeCellOutputs, async event => {
			await vscode.commands.executeCommand('notebook.cell.clearOutputs');
			await event;
R
rebornix 已提交
665
			assert.strictEqual(cell.outputs.length, 0, 'should clear');
R
rebornix 已提交
666
		});
R
rebornix 已提交
667

R
Rob Lourens 已提交
668
		const secondResource = await createRandomNotebookFile();
R
rebornix 已提交
669
		await vscode.commands.executeCommand('vscode.openWith', secondResource, 'notebookCoreTest');
R
rebornix 已提交
670 671 672 673

		await withEvent<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs, async (event) => {
			await vscode.commands.executeCommand('notebook.cell.execute', { start: 0, end: 1 }, resource);
			await event;
R
rebornix 已提交
674
			assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked
J
Johannes Rieken 已提交
675
			assert.strictEqual(vscode.window.activeNotebookEditor?.document.uri.fsPath, secondResource.fsPath);
R
rebornix 已提交
676
		});
R
rebornix 已提交
677
	});
R
rebornix 已提交
678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705

	test('cell execute command takes arguments ICellRange[]', async () => {
		const resource = await createRandomNotebookFile();
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');

		vscode.commands.executeCommand('notebook.cell.execute', { ranges: [{ start: 0, end: 1 }, { start: 1, end: 2 }] });
		let firstCellExecuted = false;
		let secondCellExecuted = false;
		let resolve: () => void;
		const p = new Promise<void>(r => resolve = r);
		const listener = vscode.notebook.onDidChangeCellOutputs(e => {
			e.cells.forEach(cell => {
				if (cell.index === 0) {
					firstCellExecuted = true;
				}

				if (cell.index === 1) {
					secondCellExecuted = true;
				}
			});

			if (firstCellExecuted && secondCellExecuted) {
				resolve();
			}
		});

		await p;
		listener.dispose();
R
rebornix 已提交
706
		await saveAllFilesAndCloseAll();
R
rebornix 已提交
707
	});
R
rebornix 已提交
708

D
Oops  
Don Jayamanne 已提交
709
	test('document execute command takes arguments', async () => {
R
Rob Lourens 已提交
710
		const resource = await createRandomNotebookFile();
R
rebornix 已提交
711
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
J
Johannes Rieken 已提交
712
		assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
R
rebornix 已提交
713
		const editor = vscode.window.activeNotebookEditor!;
714
		const cell = editor.document.cellAt(0);
R
rebornix 已提交
715

R
rebornix 已提交
716 717 718
		await withEvent<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs, async (event) => {
			await vscode.commands.executeCommand('notebook.execute');
			await event;
R
rebornix 已提交
719
			assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked
R
rebornix 已提交
720
		});
R
rebornix 已提交
721

722
		const clearChangeEvent = asPromise<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs);
R
rebornix 已提交
723 724
		await vscode.commands.executeCommand('notebook.cell.clearOutputs');
		await clearChangeEvent;
R
rebornix 已提交
725
		assert.strictEqual(cell.outputs.length, 0, 'should clear');
R
rebornix 已提交
726

R
Rob Lourens 已提交
727
		const secondResource = await createRandomNotebookFile();
R
rebornix 已提交
728
		await vscode.commands.executeCommand('vscode.openWith', secondResource, 'notebookCoreTest');
R
rebornix 已提交
729 730 731 732

		await withEvent<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs, async (event) => {
			await vscode.commands.executeCommand('notebook.execute', resource);
			await event;
R
rebornix 已提交
733
			assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked
J
Johannes Rieken 已提交
734
			assert.strictEqual(vscode.window.activeNotebookEditor?.document.uri.fsPath, secondResource.fsPath);
R
rebornix 已提交
735
		});
R
rebornix 已提交
736 737
	});

738
	test('cell execute and select kernel', async function () {
739 740 741 742
		const notebook = await openRandomNotebookDocument();
		const editor = await vscode.window.showNotebookDocument(notebook);
		assert.strictEqual(vscode.window.activeNotebookEditor === editor, true, 'notebook first');

743
		const cell = editor.document.cellAt(0);
R
rebornix 已提交
744

R
Rob Lourens 已提交
745
		await withEvent<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs, async (event) => {
746
			await assertKernel(kernel1, notebook);
J
Johannes Rieken 已提交
747
			await vscode.commands.executeCommand('notebook.cell.execute');
R
Rob Lourens 已提交
748 749
			await event;
			assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked
750 751 752
			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');
R
Rob Lourens 已提交
753
		});
R
rebornix 已提交
754

R
Rob Lourens 已提交
755
		await withEvent<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs, async (event) => {
756
			await assertKernel(kernel2, notebook);
J
Johannes Rieken 已提交
757
			await vscode.commands.executeCommand('notebook.cell.execute');
R
Rob Lourens 已提交
758 759
			await event;
			assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked
760 761 762
			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 second output');
R
Rob Lourens 已提交
763
		});
R
rebornix 已提交
764
	});
R
Rob Lourens 已提交
765

766
	test('set outputs on cancel', async () => {
R
Rob Lourens 已提交
767

768 769 770 771 772 773
		const cancelableKernel = new class extends Kernel {

			constructor() {
				super('cancelableKernel', 'Notebook Cancelable Test Kernel');
			}

M
Matt Bierner 已提交
774
			override async _execute(cells: vscode.NotebookCell[]) {
775
				for (const cell of cells) {
776
					const task = this.controller.createNotebookCellExecution(cell);
777 778 779
					task.start();
					task.token.onCancellationRequested(async () => {
						await task.replaceOutput([new vscode.NotebookCellOutput([
780
							vscode.NotebookCellOutputItem.text('Canceled', 'text/plain', undefined)
781 782 783 784 785
						])]);
						task.end({});
					});

				}
R
Rob Lourens 已提交
786 787 788
			}
		};

789 790
		const notebook = await openRandomNotebookDocument();
		const editor = await vscode.window.showNotebookDocument(notebook);
791
		const cell = editor.document.cellAt(0);
R
Rob Lourens 已提交
792 793

		await withEvent<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs, async (event) => {
794
			await assertKernel(cancelableKernel, notebook);
795
			assert.ok(editor === vscode.window.activeNotebookEditor);
R
Rob Lourens 已提交
796 797 798 799
			await vscode.commands.executeCommand('notebook.cell.execute');
			await vscode.commands.executeCommand('notebook.cell.cancelExecution');
			await event;
			assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked
800 801 802
			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), 'Canceled');
R
Rob Lourens 已提交
803 804
		});

805
		cancelableKernel.controller.dispose();
R
Rob Lourens 已提交
806 807
	});

808
	test('set outputs on interrupt', async () => {
809
		const interruptableKernel = new class extends Kernel {
R
Rob Lourens 已提交
810

811 812 813 814
			constructor() {
				super('interruptableKernel', 'Notebook Interruptable Test Kernel');
				this.controller.interruptHandler = this.interrupt.bind(this);
			}
R
Rob Lourens 已提交
815

816
			private _task: vscode.NotebookCellExecution | undefined;
R
Rob Lourens 已提交
817

M
Matt Bierner 已提交
818
			override async _execute(cells: vscode.NotebookCell[]) {
819
				this._task = this.controller.createNotebookCellExecution(cells[0]);
R
Rob Lourens 已提交
820 821 822
				this._task.start();
			}

823
			async interrupt() {
R
Rob Lourens 已提交
824
				await this._task!.replaceOutput([new vscode.NotebookCellOutput([
825
					vscode.NotebookCellOutputItem.text('Interrupted', 'text/plain', undefined)
R
Rob Lourens 已提交
826 827 828 829 830
				])]);
				this._task!.end({});
			}
		};

831 832
		const notebook = await openRandomNotebookDocument();
		const editor = await vscode.window.showNotebookDocument(notebook);
833
		const cell = editor.document.cellAt(0);
R
Rob Lourens 已提交
834 835

		await withEvent<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs, async (event) => {
836
			await assertKernel(interruptableKernel, notebook);
837
			assert.ok(editor === vscode.window.activeNotebookEditor);
R
Rob Lourens 已提交
838 839 840 841
			await vscode.commands.executeCommand('notebook.cell.execute');
			await vscode.commands.executeCommand('notebook.cell.cancelExecution');
			await event;
			assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked
842 843 844
			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), 'Interrupted');
R
Rob Lourens 已提交
845 846
		});

847
		interruptableKernel.controller.dispose();
R
Rob Lourens 已提交
848 849 850
	});

	test('onDidChangeCellExecutionState is fired', async () => {
R
Rob Lourens 已提交
851
		const resource = await createRandomNotebookFile();
R
Rob Lourens 已提交
852 853
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
		const editor = vscode.window.activeNotebookEditor!;
854
		const cell = editor.document.cellAt(0);
R
Rob Lourens 已提交
855 856 857 858 859

		vscode.commands.executeCommand('notebook.cell.execute');
		let eventCount = 0;
		let resolve: () => void;
		const p = new Promise<void>(r => resolve = r);
860
		const listener = vscode.notebook.onDidChangeNotebookCellExecutionState(e => {
R
Rob Lourens 已提交
861
			if (eventCount === 0) {
862
				assert.strictEqual(e.state, vscode.NotebookCellExecutionState.Pending, 'should be set to Pending');
R
Rob Lourens 已提交
863
			} else if (eventCount === 1) {
864
				assert.strictEqual(e.state, vscode.NotebookCellExecutionState.Executing, 'should be set to Executing');
R
Rob Lourens 已提交
865 866
				assert.strictEqual(cell.outputs.length, 0, 'no outputs yet: ' + JSON.stringify(cell.outputs[0]));
			} else if (eventCount === 2) {
867
				assert.strictEqual(e.state, vscode.NotebookCellExecutionState.Idle, 'should be set to Idle');
R
Rob Lourens 已提交
868 869 870 871 872 873 874 875 876 877
				assert.strictEqual(cell.outputs.length, 1, 'should have an output');
				resolve();
			}

			eventCount++;
		});

		await p;
		listener.dispose();
	});
R
rebornix 已提交
878

879
	// suite('notebook dirty state', () => {
D
Oops  
Don Jayamanne 已提交
880
	test('notebook open', async function () {
R
Rob Lourens 已提交
881
		const resource = await createRandomNotebookFile();
R
rebornix 已提交
882
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
J
Johannes Rieken 已提交
883
		assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
R
rebornix 已提交
884 885
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), 'test');
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.languageId, 'typescript');
R
rebornix 已提交
886 887

		await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
R
rebornix 已提交
888
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), '');
R
rebornix 已提交
889 890

		await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove');
R
rebornix 已提交
891 892
		const activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
		assert.notStrictEqual(getFocusedCell(vscode.window.activeNotebookEditor), undefined);
J
Johannes Rieken 已提交
893
		assert.strictEqual(activeCell!.document.getText(), '');
894 895
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellCount, 4);
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 1);
R
rebornix 已提交
896

R
rebornix 已提交
897 898
		await withEvent(vscode.workspace.onDidChangeTextDocument, async event => {
			const edit = new vscode.WorkspaceEdit();
J
Johannes Rieken 已提交
899
			edit.insert(activeCell!.document.uri, new vscode.Position(0, 0), 'var abc = 0;');
R
rebornix 已提交
900 901
			await vscode.workspace.applyEdit(edit);
			await event;
J
Johannes Rieken 已提交
902
			assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true);
R
rebornix 已提交
903 904
			assert.deepStrictEqual(vscode.window.activeNotebookEditor?.document.cellAt(1), getFocusedCell(vscode.window.activeNotebookEditor));
			assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), 'var abc = 0;');
R
rebornix 已提交
905
		});
R
rebornix 已提交
906
	});
907
	// });
R
rebornix 已提交
908

909
	// suite('notebook undo redo', () => {
D
Oops  
Don Jayamanne 已提交
910
	test('notebook open', async function () {
R
Rob Lourens 已提交
911
		const resource = await createRandomNotebookFile();
R
rebornix 已提交
912
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
J
Johannes Rieken 已提交
913
		assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
R
rebornix 已提交
914 915
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), 'test');
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.languageId, 'typescript');
R
rebornix 已提交
916 917

		await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
R
rebornix 已提交
918
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), '');
R
rebornix 已提交
919 920

		await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove');
R
rebornix 已提交
921 922
		const activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
		assert.notStrictEqual(getFocusedCell(vscode.window.activeNotebookEditor), undefined);
J
Johannes Rieken 已提交
923
		assert.strictEqual(activeCell!.document.getText(), '');
924 925
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellCount, 4);
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 1);
R
rebornix 已提交
926 927 928


		// modify the second cell, delete it
R
rebornix 已提交
929
		const edit = new vscode.WorkspaceEdit();
R
rebornix 已提交
930
		edit.insert(getFocusedCell(vscode.window.activeNotebookEditor)!.document.uri, new vscode.Position(0, 0), 'var abc = 0;');
R
rebornix 已提交
931
		await vscode.workspace.applyEdit(edit);
R
rebornix 已提交
932
		await vscode.commands.executeCommand('notebook.cell.delete');
933
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellCount, 3);
R
rebornix 已提交
934
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(getFocusedCell(vscode.window.activeNotebookEditor)!), 1);
R
rebornix 已提交
935 936 937


		// undo should bring back the deleted cell, and revert to previous content and selection
R
rebornix 已提交
938
		await vscode.commands.executeCommand('undo');
939
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellCount, 4);
R
rebornix 已提交
940 941
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(getFocusedCell(vscode.window.activeNotebookEditor)!), 1);
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), 'var abc = 0;');
R
rebornix 已提交
942 943 944

		// redo
		// await vscode.commands.executeCommand('notebook.redo');
945
		// assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellCount, 2);
R
rebornix 已提交
946
		// assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(getFocusedCell(vscode.window.activeNotebookEditor)!), 1);
J
Johannes Rieken 已提交
947
		// assert.strictEqual(vscode.window.activeNotebookEditor?.selection?.document.getText(), 'test');
R
rebornix 已提交
948
	});
949

D
Oops  
Don Jayamanne 已提交
950
	test('multiple tabs: dirty + clean', async function () {
R
Rob Lourens 已提交
951
		const resource = await createRandomNotebookFile();
952 953
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
		await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
R
rebornix 已提交
954
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), '');
955 956

		await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove');
R
rebornix 已提交
957
		const edit = new vscode.WorkspaceEdit();
R
rebornix 已提交
958
		edit.insert(getFocusedCell(vscode.window.activeNotebookEditor)!.document.uri, new vscode.Position(0, 0), 'var abc = 0;');
R
rebornix 已提交
959
		await vscode.workspace.applyEdit(edit);
960

R
Rob Lourens 已提交
961
		const secondResource = await createRandomNotebookFile();
962 963 964 965
		await vscode.commands.executeCommand('vscode.openWith', secondResource, 'notebookCoreTest');
		await vscode.commands.executeCommand('workbench.action.closeActiveEditor');

		// make sure that the previous dirty editor is still restored in the extension host and no data loss
J
Johannes Rieken 已提交
966
		assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true);
R
rebornix 已提交
967
		assert.deepStrictEqual(vscode.window.activeNotebookEditor?.document.cellAt(1), getFocusedCell(vscode.window.activeNotebookEditor));
968
		assert.deepStrictEqual(vscode.window.activeNotebookEditor?.document.cellCount, 4);
R
rebornix 已提交
969
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), 'var abc = 0;');
970 971 972

	});

D
Oops  
Don Jayamanne 已提交
973
	test('multiple tabs: two dirty tabs and switching', async function () {
R
Rob Lourens 已提交
974
		const resource = await createRandomNotebookFile();
975 976
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
		await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
R
rebornix 已提交
977
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), '');
978 979

		await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove');
R
rebornix 已提交
980
		const edit = new vscode.WorkspaceEdit();
R
rebornix 已提交
981
		edit.insert(getFocusedCell(vscode.window.activeNotebookEditor)!.document.uri, new vscode.Position(0, 0), 'var abc = 0;');
R
rebornix 已提交
982
		await vscode.workspace.applyEdit(edit);
983

R
Rob Lourens 已提交
984
		const secondResource = await createRandomNotebookFile();
985 986
		await vscode.commands.executeCommand('vscode.openWith', secondResource, 'notebookCoreTest');
		await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
R
rebornix 已提交
987
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), '');
988 989 990

		// switch to the first editor
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
J
Johannes Rieken 已提交
991
		assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true);
R
rebornix 已提交
992
		assert.deepStrictEqual(vscode.window.activeNotebookEditor?.document.cellAt(1), getFocusedCell(vscode.window.activeNotebookEditor));
993
		assert.deepStrictEqual(vscode.window.activeNotebookEditor?.document.cellCount, 4);
R
rebornix 已提交
994
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), 'var abc = 0;');
995 996 997

		// switch to the second editor
		await vscode.commands.executeCommand('vscode.openWith', secondResource, 'notebookCoreTest');
J
Johannes Rieken 已提交
998
		assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true);
R
rebornix 已提交
999
		assert.deepStrictEqual(vscode.window.activeNotebookEditor?.document.cellAt(1), getFocusedCell(vscode.window.activeNotebookEditor));
1000
		assert.deepStrictEqual(vscode.window.activeNotebookEditor?.document.cellCount, 3);
R
rebornix 已提交
1001
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), '');
1002

1003 1004
	});

M
Matt Bierner 已提交
1005
	test('multiple tabs: different editors with same document', async function () {
1006 1007 1008 1009 1010

		const notebook = await openRandomNotebookDocument();
		const firstNotebookEditor = await vscode.window.showNotebookDocument(notebook, { viewColumn: vscode.ViewColumn.One });
		assert.ok(firstNotebookEditor === vscode.window.activeNotebookEditor);

J
Johannes Rieken 已提交
1011
		assert.strictEqual(firstNotebookEditor !== undefined, true, 'notebook first');
R
rebornix 已提交
1012 1013
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor!)?.document.getText(), 'test');
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor!)?.document.languageId, 'typescript');
1014

M
Matt Bierner 已提交
1015
		const secondNotebookEditor = await vscode.window.showNotebookDocument(notebook, { viewColumn: vscode.ViewColumn.Beside });
J
Johannes Rieken 已提交
1016
		assert.strictEqual(secondNotebookEditor !== undefined, true, 'notebook first');
R
rebornix 已提交
1017 1018
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor!)?.document.getText(), 'test');
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor!)?.document.languageId, 'typescript');
1019

L
Logan Ramos 已提交
1020
		assert.notStrictEqual(firstNotebookEditor, secondNotebookEditor);
J
Johannes Rieken 已提交
1021
		assert.strictEqual(firstNotebookEditor?.document, secondNotebookEditor?.document, 'split notebook editors share the same document');
1022

1023
	});
1024

D
Oops  
Don Jayamanne 已提交
1025
	test('custom metadata should be supported', async function () {
R
Rob Lourens 已提交
1026
		const resource = await createRandomNotebookFile();
R
rebornix 已提交
1027
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
J
Johannes Rieken 已提交
1028 1029
		assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.metadata.custom!['testMetadata'] as boolean, false);
R
rebornix 已提交
1030 1031
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.metadata.custom!['testCellMetadata'] as number, 123);
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.languageId, 'typescript');
1032

R
rebornix 已提交
1033
	});
1034

1035

R
rebornix 已提交
1036
	// TODO@rebornix skip as it crashes the process all the time
1037
	test.skip('custom metadata should be supported 2', async function () {
R
Rob Lourens 已提交
1038
		const resource = await createRandomNotebookFile();
1039
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
J
Johannes Rieken 已提交
1040 1041
		assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.metadata.custom!['testMetadata'] as boolean, false);
R
rebornix 已提交
1042 1043
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.metadata.custom!['testCellMetadata'] as number, 123);
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.languageId, 'typescript');
1044

1045 1046
		// TODO see #101462
		// await vscode.commands.executeCommand('notebook.cell.copyDown');
R
rebornix 已提交
1047
		// const activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
1048
		// assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 1);
J
Johannes Rieken 已提交
1049
		// assert.strictEqual(activeCell?.metadata.custom!['testCellMetadata'] as number, 123);
1050

R
rebornix 已提交
1051
	});
R
rebornix 已提交
1052

1053

1054
	test.skip('#106657. Opening a notebook from markers view is broken ', async function () {
1055

1056
		const document = await openRandomNotebookDocument();
1057
		const [cell] = document.getCells();
1058

R
rebornix 已提交
1059
		assert.strictEqual(vscode.window.activeNotebookEditor, undefined);
1060 1061

		// opening a cell-uri opens a notebook editor
1062 1063
		await vscode.window.showTextDocument(cell.document, { viewColumn: vscode.ViewColumn.Active });
		// await vscode.commands.executeCommand('vscode.open', cell.document.uri, vscode.ViewColumn.Active);
1064

R
rebornix 已提交
1065
		assert.strictEqual(!!vscode.window.activeNotebookEditor, true);
1066
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.uri.toString(), document.uri.toString());
1067 1068
	});

1069
	test('Cannot open notebook from cell-uri with vscode.open-command', async function () {
1070

1071
		const document = await openRandomNotebookDocument();
1072
		const [cell] = document.getCells();
1073

1074
		await saveAllFilesAndCloseAll();
R
rebornix 已提交
1075
		assert.strictEqual(vscode.window.activeNotebookEditor, undefined);
1076 1077 1078

		// BUG is that the editor opener (https://github.com/microsoft/vscode/blob/8e7877bdc442f1e83a7fec51920d82b696139129/src/vs/editor/browser/services/openerService.ts#L69)
		// removes the fragment if it matches something numeric. For notebooks that's not wanted...
J
Johannes Rieken 已提交
1079
		await vscode.commands.executeCommand('vscode.open', cell.document.uri);
1080

1081
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.uri.toString(), document.uri.toString());
1082 1083
	});

D
Oops  
Don Jayamanne 已提交
1084
	test('#97830, #97764. Support switch to other editor types', async function () {
R
Rob Lourens 已提交
1085
		const resource = await createRandomNotebookFile();
1086 1087
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
		await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
R
rebornix 已提交
1088
		const edit = new vscode.WorkspaceEdit();
R
rebornix 已提交
1089
		edit.insert(getFocusedCell(vscode.window.activeNotebookEditor)!.document.uri, new vscode.Position(0, 0), 'var abc = 0;');
R
rebornix 已提交
1090
		await vscode.workspace.applyEdit(edit);
1091

J
Johannes Rieken 已提交
1092
		assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
R
rebornix 已提交
1093
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), 'var abc = 0;');
1094 1095

		// no kernel -> no default language
R
rebornix 已提交
1096
		// assert.strictEqual(vscode.window.activeNotebookEditor!.kernel, undefined);
R
rebornix 已提交
1097
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.languageId, 'typescript');
1098 1099

		await vscode.commands.executeCommand('vscode.openWith', resource, 'default');
J
Johannes Rieken 已提交
1100
		assert.strictEqual(vscode.window.activeTextEditor?.document.uri.path, resource.path);
1101
	});
1102 1103

	// open text editor, pin, and then open a notebook
D
Oops  
Don Jayamanne 已提交
1104
	test('#96105 - dirty editors', async function () {
R
Rob Lourens 已提交
1105
		const resource = await createRandomNotebookFile();
1106
		await vscode.commands.executeCommand('vscode.openWith', resource, 'default');
R
rebornix 已提交
1107
		const edit = new vscode.WorkspaceEdit();
R
rebornix 已提交
1108
		edit.insert(resource, new vscode.Position(0, 0), 'var abc = 0;');
R
rebornix 已提交
1109
		await vscode.workspace.applyEdit(edit);
1110 1111 1112

		// now it's dirty, open the resource with notebook editor should open a new one
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
L
Logan Ramos 已提交
1113 1114
		assert.notStrictEqual(vscode.window.activeNotebookEditor, undefined, 'notebook first');
		// assert.notStrictEqual(vscode.window.activeTextEditor, undefined);
1115 1116 1117

	});

D
Oops  
Don Jayamanne 已提交
1118
	test('#102411 - untitled notebook creation failed', async function () {
J
Johannes Rieken 已提交
1119
		await vscode.commands.executeCommand('workbench.action.files.newUntitledFile', { viewType: 'notebookCoreTest' });
L
Logan Ramos 已提交
1120
		assert.notStrictEqual(vscode.window.activeNotebookEditor, undefined, 'untitled notebook editor is not undefined');
1121

R
rebornix 已提交
1122
		await closeAllEditors();
R
rebornix 已提交
1123
	});
R
rebornix 已提交
1124

D
Oops  
Don Jayamanne 已提交
1125
	test('#102423 - copy/paste shares the same text buffer', async function () {
R
Rob Lourens 已提交
1126
		const resource = await createRandomNotebookFile();
R
rebornix 已提交
1127 1128
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');

R
rebornix 已提交
1129
		let activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
J
Johannes Rieken 已提交
1130
		assert.strictEqual(activeCell?.document.getText(), 'test');
R
rebornix 已提交
1131 1132 1133

		await vscode.commands.executeCommand('notebook.cell.copyDown');
		await vscode.commands.executeCommand('notebook.cell.edit');
R
rebornix 已提交
1134
		activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
1135
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 1);
J
Johannes Rieken 已提交
1136
		assert.strictEqual(activeCell?.document.getText(), 'test');
R
rebornix 已提交
1137

R
rebornix 已提交
1138
		const edit = new vscode.WorkspaceEdit();
R
rebornix 已提交
1139
		edit.insert(getFocusedCell(vscode.window.activeNotebookEditor)!.document.uri, new vscode.Position(0, 0), 'var abc = 0;');
R
rebornix 已提交
1140
		await vscode.workspace.applyEdit(edit);
R
rebornix 已提交
1141

1142
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().length, 3);
L
Logan Ramos 已提交
1143
		assert.notStrictEqual(vscode.window.activeNotebookEditor!.document.cellAt(0).document.getText(), vscode.window.activeNotebookEditor!.document.cellAt(1).document.getText());
1144

R
rebornix 已提交
1145
		await closeAllEditors();
R
rebornix 已提交
1146
	});
1147

D
Oops  
Don Jayamanne 已提交
1148
	test('#115855 onDidSaveNotebookDocument', async function () {
R
Rob Lourens 已提交
1149
		const resource = await createRandomNotebookFile();
1150 1151
		const notebook = await vscode.notebook.openNotebookDocument(resource);
		const editor = await vscode.window.showNotebookDocument(notebook);
R
rebornix 已提交
1152 1153

		const cellsChangeEvent = asPromise<vscode.NotebookCellsChangeEvent>(vscode.notebook.onDidChangeNotebookCells);
1154
		await editor.edit(editBuilder => {
1155
			editBuilder.replaceCells(1, 0, [{ kind: vscode.NotebookCellKind.Code, languageId: 'javascript', value: 'test 2', outputs: [], metadata: undefined }]);
R
rebornix 已提交
1156 1157 1158
		});

		const cellChangeEventRet = await cellsChangeEvent;
1159
		assert.strictEqual(cellChangeEventRet.document === notebook, true);
R
rebornix 已提交
1160 1161
		assert.strictEqual(cellChangeEventRet.document.isDirty, true);

1162 1163 1164 1165 1166 1167
		const saveEvent = asPromise(vscode.notebook.onDidSaveNotebookDocument);

		await notebook.save();

		await saveEvent;
		assert.strictEqual(notebook.isDirty, false);
R
rebornix 已提交
1168 1169
	});

1170
	test('Output changes are applied once the promise resolves', async function () {
1171 1172 1173

		let called = false;

1174 1175 1176 1177 1178
		const verifyOutputSyncKernel = new class extends Kernel {

			constructor() {
				super('verifyOutputSyncKernel', '');
			}
R
Rob Lourens 已提交
1179

1180 1181
			override async _execute(cells: vscode.NotebookCell[]) {
				const [cell] = cells;
1182
				const task = this.controller.createNotebookCellExecution(cell);
R
Rob Lourens 已提交
1183 1184
				task.start();
				await task.replaceOutput([new vscode.NotebookCellOutput([
1185
					vscode.NotebookCellOutputItem.text('Some output', 'text/plain', undefined)
R
Rob Lourens 已提交
1186
				])]);
1187
				assert.strictEqual(cell.notebook.cellAt(0).outputs.length, 1);
1188
				assert.deepStrictEqual(new TextDecoder().decode(cell.notebook.cellAt(0).outputs[0].items[0].data), 'Some output');
R
Rob Lourens 已提交
1189
				task.end({});
1190
				called = true;
R
Rob Lourens 已提交
1191 1192 1193
			}
		};

1194 1195 1196
		const notebook = await openRandomNotebookDocument();
		await vscode.window.showNotebookDocument(notebook);
		await assertKernel(verifyOutputSyncKernel, notebook);
R
Rob Lourens 已提交
1197
		await vscode.commands.executeCommand('notebook.cell.execute');
1198
		assert.strictEqual(called, true);
1199
		verifyOutputSyncKernel.controller.dispose();
R
Rob Lourens 已提交
1200 1201
	});

1202
	test('executionSummary', async () => {
R
Rob Lourens 已提交
1203
		const resource = await createRandomNotebookFile();
R
Rob Lourens 已提交
1204 1205
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
		const editor = vscode.window.activeNotebookEditor!;
1206
		const cell = editor.document.cellAt(0);
1207

1208 1209
		assert.strictEqual(cell.executionSummary?.success, undefined);
		assert.strictEqual(cell.executionSummary?.executionOrder, undefined);
R
Rob Lourens 已提交
1210 1211
		await vscode.commands.executeCommand('notebook.cell.execute');
		assert.strictEqual(cell.outputs.length, 1, 'should execute');
1212 1213 1214
		assert.ok(cell.executionSummary);
		assert.strictEqual(cell.executionSummary!.success, true);
		assert.strictEqual(typeof cell.executionSummary!.executionOrder, 'number');
1215 1216

	});
1217

1218
	test('initialize executionSummary', async () => {
1219 1220 1221

		const document = await openRandomNotebookDocument();
		const cell = document.cellAt(0);
R
Rob Lourens 已提交
1222

1223 1224 1225
		assert.strictEqual(cell.executionSummary?.success, undefined);
		assert.strictEqual(cell.executionSummary?.startTime, 10);
		assert.strictEqual(cell.executionSummary?.endTime, 20);
R
Rob Lourens 已提交
1226 1227 1228

	});

1229

R
Rob Lourens 已提交
1230 1231 1232 1233
	suite('statusbar', () => {
		const emitter = new vscode.EventEmitter<vscode.NotebookCell>();
		const onDidCallProvide = emitter.event;
		suiteSetup(() => {
1234
			vscode.notebook.registerNotebookCellStatusBarItemProvider('notebookCoreTest', {
R
Rob Lourens 已提交
1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254
				async provideCellStatusBarItems(cell: vscode.NotebookCell, _token: vscode.CancellationToken): Promise<vscode.NotebookCellStatusBarItem[]> {
					emitter.fire(cell);
					return [];
				}
			});
		});

		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, new vscode.NotebookCellMetadata().with({ inputCollapsed: true }));
			vscode.workspace.applyEdit(edit);
			await provideCalled;
		});
	});

1255
	// });
R
rebornix 已提交
1256

1257
	// suite('webview', () => {
R
rebornix 已提交
1258
	// for web, `asWebUri` gets `https`?
D
Oops  
Don Jayamanne 已提交
1259
	// test('asWebviewUri', async function () {
1260 1261 1262
	// 	if (vscode.env.uiKind === vscode.UIKind.Web) {
	// 		return;
	// 	}
R
rebornix 已提交
1263

R
Rob Lourens 已提交
1264
	// 	const resource = await createRandomNotebookFile();
1265
	// 	await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
J
Johannes Rieken 已提交
1266
	// 	assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
R
rebornix 已提交
1267
	// 	const uri = vscode.window.activeNotebookEditor!.asWebviewUri(vscode.Uri.file('./hello.png'));
J
Johannes Rieken 已提交
1268
	// 	assert.strictEqual(uri.scheme, 'vscode-webview-resource');
R
rebornix 已提交
1269
	// 	await closeAllEditors();
1270
	// });
R
rebornix 已提交
1271

R
rebornix 已提交
1272 1273

	// 404 on web
D
Oops  
Don Jayamanne 已提交
1274
	// test('custom renderer message', async function () {
1275 1276 1277
	// 	if (vscode.env.uiKind === vscode.UIKind.Web) {
	// 		return;
	// 	}
R
rebornix 已提交
1278

1279 1280
	// 	const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './customRenderer.vsctestnb'));
	// 	await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
R
rebornix 已提交
1281

R
rebornix 已提交
1282
	// 	const editor = vscode.window.activeNotebookEditor;
1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293
	// 	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;
R
rebornix 已提交
1294
	// 	await closeAllEditors();
1295
	// });
R
rebornix 已提交
1296
});