notebook.test.ts 59.4 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
	constructor(id: string, label: string) {
J
Johannes Rieken 已提交
39
		this.controller = vscode.notebooks.createNotebookController(id, 'notebookCoreTest', label);
40
		this.controller.executeHandler = this._execute.bind(this);
J
Johannes Rieken 已提交
41
		this.controller.supportsExecutionOrder = true;
42
		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')
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')
71
		])]);
72
		task.end(true);
R
Rob Lourens 已提交
73
	}
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: {},
112 113 114 115 116
						cells: []
					};
				}

				const dto: vscode.NotebookData = {
117
					metadata: { custom: { testMetadata: false } },
118 119
					cells: [
						{
120 121
							value: 'test',
							languageId: 'typescript',
122
							kind: vscode.NotebookCellKind.Code,
123
							outputs: [],
124
							metadata: { custom: { testCellMetadata: 123 } },
125
							executionSummary: { timing: { 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')
134
								],
135 136 137 138
									{
										testOutputMetadata: true,
										['text/plain']: { testOutputItemMetadata: true }
									})
139
							],
140
							executionSummary: { executionOrder: 5, success: true },
141
							metadata: { custom: { testCellMetadata: 456 } }
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
						}
					]
				};
				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 已提交
160
	});
161

162 163 164
	let kernel1: Kernel;
	let kernel2: Kernel;

165
	setup(async function () {
166

167
		kernel1 = new Kernel('mainKernel', 'Notebook Primary Test Kernel');
168

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


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

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

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

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

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

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

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

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

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

229
		const firstEditorClose = asPromise(vscode.window.onDidChangeVisibleNotebookEditors);
R
rebornix 已提交
230
		await closeAllEditors();
231 232 233
		await firstEditorClose;
	});

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

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

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

R
rebornix 已提交
248
		await closeAllEditors();
J
Johannes Rieken 已提交
249
		assert.strictEqual(count, 0);
250 251
	});

252
	test('correct cell selection on undo/redo of cell creation', async function () {
R
Rob Lourens 已提交
253
		const resource = await createRandomNotebookFile();
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
		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 已提交
271
	test('editor editing event 2', async function () {
R
Rob Lourens 已提交
272
		const resource = await createRandomNotebookFile();
273 274
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');

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

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

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

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

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

D
Oops  
Don Jayamanne 已提交
321
	test('editor move cell event', async function () {
R
Rob Lourens 已提交
322
		const resource = await createRandomNotebookFile();
323 324 325 326 327
		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 已提交
328
		const activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
329
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 0);
330
		const moveChange = asPromise(vscode.notebook.onDidChangeNotebookCells);
331
		await vscode.commands.executeCommand('notebook.cell.moveDown');
R
rebornix 已提交
332
		await moveChange;
R
rebornix 已提交
333 334
		await saveAllEditors();
		await closeAllEditors();
335 336

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

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

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

355
		const untitledEditorChange = asPromise(vscode.window.onDidChangeActiveNotebookEditor);
R
rebornix 已提交
356
		await vscode.commands.executeCommand('workbench.action.files.newUntitledFile');
357
		await untitledEditorChange;
R
rebornix 已提交
358
		assert.strictEqual(firstEditor && vscode.window.visibleNotebookEditors.indexOf(firstEditor) >= 0, true);
R
rebornix 已提交
359 360 361
		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 已提交
362
		assert.strictEqual(vscode.window.visibleNotebookEditors.length, 1);
R
rebornix 已提交
363

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

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

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

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

R
rebornix 已提交
387
		await vscode.window.activeNotebookEditor!.edit(editBuilder => {
388
			editBuilder.replaceCellMetadata(0, { inputCollapsed: true });
389 390
		});

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

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

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

402
		const event = asPromise<vscode.NotebookCellMetadataChangeEvent>(vscode.notebook.onDidChangeCellMetadata);
403

R
rebornix 已提交
404
		await vscode.window.activeNotebookEditor!.edit(editBuilder => {
405
			editBuilder.replaceCellMetadata(0, { inputCollapsed: true });
406 407 408
		});

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

412
		assert.strictEqual(data.document.isDirty, true);
413
	});
414

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

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

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

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

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

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

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

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

		testDisposables.push(vscode.notebook.onDidChangeNotebookCells(() => {
461 462 463 464
			count++;
		}));

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

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

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

478
		const secondCell = vscode.window.activeNotebookEditor!.document.cellAt(1);
479
		assert.strictEqual(secondCell!.outputs.length, 1);
480
		assert.deepStrictEqual(secondCell!.outputs[0].metadata, { testOutputMetadata: true, ['text/plain']: { testOutputItemMetadata: true } });
481 482 483 484
		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');
485 486
		assert.strictEqual(secondCell!.executionSummary?.executionOrder, 5);
		assert.strictEqual(secondCell!.executionSummary?.success, true);
487

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

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

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

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

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

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

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

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

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

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

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


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

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

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

562
		// assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 2,
R
rebornix 已提交
563
		// 	`second move down, active cell ${getFocusedCell(vscode.window.activeNotebookEditor)!.uri.toString()}, ${getFocusedCell(vscode.window.activeNotebookEditor)!.document.getText()}`);
564 565 566 567
		// 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 已提交
568 569 570

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

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

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

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

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

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

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

D
Oops  
Don Jayamanne 已提交
598
	test('move cells will not recreate cells in ExtHost', async function () {
R
Rob Lourens 已提交
599
		const resource = await createRandomNotebookFile();
600 601 602 603 604
		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 已提交
605
		const activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
606
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 0);
607 608 609
		await vscode.commands.executeCommand('notebook.cell.moveDown');
		await vscode.commands.executeCommand('notebook.cell.moveDown');

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

614
	// test('document runnable based on kernel count', async () => {
R
Rob Lourens 已提交
615
	// 	const resource = await createRandomNotebookFile();
616 617 618
	// 	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 已提交
619

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

623 624 625
	// 	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 已提交
626

627
	// 	currentKernelProvider.setHasKernels(true);
628

629 630 631 632 633
	// 	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 已提交
634

635 636
	// 	await saveAllFilesAndCloseAll(undefined);
	// });
R
rebornix 已提交
637

R
rebornix 已提交
638 639 640

	// 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 已提交
641
		const resource = await createRandomNotebookFile();
R
rebornix 已提交
642
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
J
Johannes Rieken 已提交
643
		assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
R
rebornix 已提交
644
		const editor = vscode.window.activeNotebookEditor!;
645
		const cell = editor.document.cellAt(0);
R
rebornix 已提交
646 647

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

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

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

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

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

		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 已提交
676
			assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked
J
Johannes Rieken 已提交
677
			assert.strictEqual(vscode.window.activeNotebookEditor?.document.uri.fsPath, secondResource.fsPath);
R
rebornix 已提交
678
		});
R
rebornix 已提交
679
	});
R
rebornix 已提交
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 706 707

	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 已提交
708
		await saveAllFilesAndCloseAll();
R
rebornix 已提交
709
	});
R
rebornix 已提交
710

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

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

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

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

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

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

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

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

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

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

770 771 772 773 774 775
		const cancelableKernel = new class extends Kernel {

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

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

				}
R
Rob Lourens 已提交
788 789 790
			}
		};

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

		await withEvent<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs, async (event) => {
796
			await assertKernel(cancelableKernel, notebook);
797
			assert.ok(editor === vscode.window.activeNotebookEditor);
R
Rob Lourens 已提交
798 799 800 801
			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
802 803 804
			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 已提交
805 806
		});

807
		cancelableKernel.controller.dispose();
R
Rob Lourens 已提交
808 809
	});

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

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

818
			private _task: vscode.NotebookCellExecution | undefined;
R
Rob Lourens 已提交
819

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

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

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

		await withEvent<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs, async (event) => {
838
			await assertKernel(interruptableKernel, notebook);
839
			assert.ok(editor === vscode.window.activeNotebookEditor);
R
Rob Lourens 已提交
840 841 842 843
			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
844 845 846
			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 已提交
847 848
		});

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

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

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

			eventCount++;
		});

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

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

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

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

R
rebornix 已提交
899 900
		await withEvent(vscode.workspace.onDidChangeTextDocument, async event => {
			const edit = new vscode.WorkspaceEdit();
J
Johannes Rieken 已提交
901
			edit.insert(activeCell!.document.uri, new vscode.Position(0, 0), 'var abc = 0;');
R
rebornix 已提交
902 903
			await vscode.workspace.applyEdit(edit);
			await event;
J
Johannes Rieken 已提交
904
			assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true);
R
rebornix 已提交
905 906
			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 已提交
907
		});
R
rebornix 已提交
908
	});
909
	// });
R
rebornix 已提交
910

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

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

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


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


		// undo should bring back the deleted cell, and revert to previous content and selection
R
rebornix 已提交
940
		await vscode.commands.executeCommand('undo');
941
		assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellCount, 4);
R
rebornix 已提交
942 943
		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 已提交
944 945 946

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

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

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

R
Rob Lourens 已提交
963
		const secondResource = await createRandomNotebookFile();
964 965 966 967
		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 已提交
968
		assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true);
R
rebornix 已提交
969
		assert.deepStrictEqual(vscode.window.activeNotebookEditor?.document.cellAt(1), getFocusedCell(vscode.window.activeNotebookEditor));
970
		assert.deepStrictEqual(vscode.window.activeNotebookEditor?.document.cellCount, 4);
R
rebornix 已提交
971
		assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), 'var abc = 0;');
972 973 974

	});

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

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

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

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

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

1005 1006
	});

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

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

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

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

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

1025
	});
1026

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

R
rebornix 已提交
1035
	});
1036

1037

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

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

R
rebornix 已提交
1053
	});
R
rebornix 已提交
1054

1055

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

1058
		const document = await openRandomNotebookDocument();
1059
		const [cell] = document.getCells();
1060

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

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

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

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

1073
		const document = await openRandomNotebookDocument();
1074
		const [cell] = document.getCells();
1075

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

		// 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 已提交
1081
		await vscode.commands.executeCommand('vscode.open', cell.document.uri);
1082

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

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

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

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

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

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

		// 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 已提交
1115 1116
		assert.notStrictEqual(vscode.window.activeNotebookEditor, undefined, 'notebook first');
		// assert.notStrictEqual(vscode.window.activeTextEditor, undefined);
1117 1118 1119

	});

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

R
rebornix 已提交
1124
		await closeAllEditors();
R
rebornix 已提交
1125
	});
R
rebornix 已提交
1126

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

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

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

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

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

R
rebornix 已提交
1147
		await closeAllEditors();
R
rebornix 已提交
1148
	});
1149

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

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

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

1164 1165 1166 1167 1168 1169
		const saveEvent = asPromise(vscode.notebook.onDidSaveNotebookDocument);

		await notebook.save();

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

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

		let called = false;

1176 1177 1178 1179 1180
		const verifyOutputSyncKernel = new class extends Kernel {

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

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

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

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

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

	});
1219

1220
	test('initialize executionSummary', async () => {
1221 1222 1223

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

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

	});

1231

R
Rob Lourens 已提交
1232 1233 1234 1235
	suite('statusbar', () => {
		const emitter = new vscode.EventEmitter<vscode.NotebookCell>();
		const onDidCallProvide = emitter.event;
		suiteSetup(() => {
1236
			vscode.notebook.registerNotebookCellStatusBarItemProvider('notebookCoreTest', {
R
Rob Lourens 已提交
1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250
				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();
1251
			edit.replaceNotebookCellMetadata(resource, 0, { inputCollapsed: true });
R
Rob Lourens 已提交
1252 1253 1254 1255 1256
			vscode.workspace.applyEdit(edit);
			await provideCalled;
		});
	});

1257
	// });
R
rebornix 已提交
1258

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

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

R
rebornix 已提交
1274 1275

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

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

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