notebook.test.ts 48.4 KB
Newer Older
R
rebornix 已提交
1 2 3 4 5 6 7 8 9 10
/*---------------------------------------------------------------------------------------------
 *  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';
import { join } from 'path';

R
rebornix 已提交
11 12 13 14 15 16 17 18
export function timeoutAsync(n: number): Promise<void> {
	return new Promise(resolve => {
		setTimeout(() => {
			resolve();
		}, n);
	});
}

19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
export function once<T>(event: vscode.Event<T>): vscode.Event<T> {
	return (listener: any, thisArgs = null, disposables?: any) => {
		// we need this, in case the event fires during the listener call
		let didFire = false;
		let result: vscode.Disposable;
		result = event(e => {
			if (didFire) {
				return;
			} else if (result) {
				result.dispose();
			} else {
				didFire = true;
			}

			return listener.call(thisArgs, e);
		}, null, disposables);

		if (didFire) {
			result.dispose();
		}

		return result;
	};
}
R
rebornix 已提交
43

44 45 46
async function getEventOncePromise<T>(event: vscode.Event<T>): Promise<T> {
	return new Promise<T>((resolve, _reject) => {
		once(event)((result: T) => resolve(result));
R
rebornix 已提交
47 48 49
	});
}

50 51 52 53 54 55 56 57 58
// Since `workbench.action.splitEditor` command does await properly
// Notebook editor/document events are not guaranteed to be sent to the ext host when promise resolves
// The workaround here is waiting for the first visible notebook editor change event.
async function splitEditor() {
	const once = getEventOncePromise(vscode.notebook.onDidChangeVisibleNotebookEditors);
	await vscode.commands.executeCommand('workbench.action.splitEditor');
	await once;
}

59 60 61 62 63 64 65 66 67 68 69 70 71 72
async function saveFileAndCloseAll(resource: vscode.Uri) {
	const documentClosed = new Promise((resolve, _reject) => {
		const d = vscode.notebook.onDidCloseNotebookDocument(e => {
			if (e.uri.toString() === resource.toString()) {
				d.dispose();
				resolve();
			}
		});
	});
	await vscode.commands.executeCommand('workbench.action.files.save');
	await vscode.commands.executeCommand('workbench.action.closeAllEditors');
	await documentClosed;
}

R
rebornix 已提交
73
suite('Notebook API tests', () => {
R
rebornix 已提交
74 75 76 77 78 79 80 81 82 83 84 85
	// test.only('crash', async function () {
	// 	for (let i = 0; i < 200; i++) {
	// 		let resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
	// 		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
	// 		await vscode.commands.executeCommand('workbench.action.revertAndCloseActiveEditor');

	// 		resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './empty.vsctestnb'));
	// 		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
	// 		await vscode.commands.executeCommand('workbench.action.revertAndCloseActiveEditor');
	// 	}
	// });

R
rebornix 已提交
86 87 88 89 90 91 92 93 94 95 96 97 98
	// test.only('crash', async function () {
	// 	for (let i = 0; i < 200; i++) {
	// 		let resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
	// 		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
	// 		await vscode.commands.executeCommand('workbench.action.files.save');
	// 		await vscode.commands.executeCommand('workbench.action.closeAllEditors');
	// 		resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './empty.vsctestnb'));
	// 		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
	// 		await vscode.commands.executeCommand('workbench.action.files.save');
	// 		await vscode.commands.executeCommand('workbench.action.closeAllEditors');
	// 	}
	// });

99
	test('document open/close event', async function () {
R
rebornix 已提交
100
		const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
101 102 103 104 105 106 107 108 109 110
		const firstDocumentOpen = getEventOncePromise(vscode.notebook.onDidOpenNotebookDocument);
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
		await firstDocumentOpen;

		const firstDocumentClose = getEventOncePromise(vscode.notebook.onDidCloseNotebookDocument);
		await vscode.commands.executeCommand('workbench.action.closeAllEditors');
		await firstDocumentClose;
	});

	test('shared document in notebook editors', async function () {
R
rebornix 已提交
111
		const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
112 113 114 115 116 117 118 119 120 121 122
		let counter = 0;
		const disposables: vscode.Disposable[] = [];
		disposables.push(vscode.notebook.onDidOpenNotebookDocument(() => {
			counter++;
		}));
		disposables.push(vscode.notebook.onDidCloseNotebookDocument(() => {
			counter--;
		}));
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
		assert.equal(counter, 1);

123
		await splitEditor();
124 125 126 127 128 129 130 131
		assert.equal(counter, 1);
		await vscode.commands.executeCommand('workbench.action.closeAllEditors');
		assert.equal(counter, 0);

		disposables.forEach(d => d.dispose());
	});

	test('editor open/close event', async function () {
R
rebornix 已提交
132
		const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
133 134 135 136 137 138 139 140 141
		const firstEditorOpen = getEventOncePromise(vscode.notebook.onDidChangeVisibleNotebookEditors);
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
		await firstEditorOpen;

		const firstEditorClose = getEventOncePromise(vscode.notebook.onDidChangeVisibleNotebookEditors);
		await vscode.commands.executeCommand('workbench.action.closeAllEditors');
		await firstEditorClose;
	});

142
	test('editor open/close event 2', async function () {
R
rebornix 已提交
143
		const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
144 145 146 147 148 149 150 151 152
		let count = 0;
		const disposables: vscode.Disposable[] = [];
		disposables.push(vscode.notebook.onDidChangeVisibleNotebookEditors(() => {
			count = vscode.notebook.visibleNotebookEditors.length;
		}));

		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
		assert.equal(count, 1);

R
rebornix 已提交
153
		await splitEditor();
154 155 156 157 158 159
		assert.equal(count, 2);

		await vscode.commands.executeCommand('workbench.action.closeAllEditors');
		assert.equal(count, 0);
	});

R
rebornix 已提交
160
	test('editor editing event 2', async function () {
R
rebornix 已提交
161
		const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
162 163 164 165 166 167 168 169 170 171
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');

		const cellsChangeEvent = getEventOncePromise<vscode.NotebookCellsChangeEvent>(vscode.notebook.onDidChangeNotebookCells);
		await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
		const cellChangeEventRet = await cellsChangeEvent;
		assert.equal(cellChangeEventRet.document, vscode.notebook.activeNotebookEditor?.document);
		assert.equal(cellChangeEventRet.changes.length, 1);
		assert.deepEqual(cellChangeEventRet.changes[0], {
			start: 1,
			deletedCount: 0,
R
:guard:  
rebornix 已提交
172
			deletedItems: [],
173 174 175 176 177
			items: [
				vscode.notebook.activeNotebookEditor!.document.cells[1]
			]
		});

R
:guard:  
rebornix 已提交
178 179
		const secondCell = vscode.notebook.activeNotebookEditor!.document.cells[1];

R
rebornix 已提交
180
		const moveCellEvent = getEventOncePromise<vscode.NotebookCellsChangeEvent>(vscode.notebook.onDidChangeNotebookCells);
181 182 183 184
		await vscode.commands.executeCommand('notebook.cell.moveUp');
		const moveCellEventRet = await moveCellEvent;
		assert.deepEqual(moveCellEventRet, {
			document: vscode.notebook.activeNotebookEditor!.document,
185 186 187 188
			changes: [
				{
					start: 1,
					deletedCount: 1,
R
:guard:  
rebornix 已提交
189
					deletedItems: [secondCell],
190 191 192 193 194
					items: []
				},
				{
					start: 0,
					deletedCount: 0,
R
:guard:  
rebornix 已提交
195
					deletedItems: [],
196 197 198
					items: [vscode.notebook.activeNotebookEditor?.document.cells[0]]
				}
			]
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
		});

		const cellOutputChange = getEventOncePromise<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs);
		await vscode.commands.executeCommand('notebook.cell.execute');
		const cellOutputsAddedRet = await cellOutputChange;
		assert.deepEqual(cellOutputsAddedRet, {
			document: vscode.notebook.activeNotebookEditor!.document,
			cells: [vscode.notebook.activeNotebookEditor!.document.cells[0]]
		});
		assert.equal(cellOutputsAddedRet.cells[0].outputs.length, 1);

		const cellOutputClear = getEventOncePromise<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs);
		await vscode.commands.executeCommand('notebook.cell.clearOutputs');
		const cellOutputsCleardRet = await cellOutputClear;
		assert.deepEqual(cellOutputsCleardRet, {
			document: vscode.notebook.activeNotebookEditor!.document,
			cells: [vscode.notebook.activeNotebookEditor!.document.cells[0]]
		});
		assert.equal(cellOutputsAddedRet.cells[0].outputs.length, 0);

		// const cellChangeLanguage = getEventOncePromise<vscode.NotebookCellLanguageChangeEvent>(vscode.notebook.onDidChangeCellLanguage);
		// await vscode.commands.executeCommand('notebook.cell.changeToMarkdown');
		// const cellChangeLanguageRet = await cellChangeLanguage;
		// assert.deepEqual(cellChangeLanguageRet, {
		// 	document: vscode.notebook.activeNotebookEditor!.document,
		// 	cells: vscode.notebook.activeNotebookEditor!.document.cells[0],
		// 	language: 'markdown'
		// });

		await vscode.commands.executeCommand('workbench.action.files.save');
		await vscode.commands.executeCommand('workbench.action.closeAllEditors');
	});
R
rebornix 已提交
231

232
	test('editor move cell event', async function () {
R
rebornix 已提交
233
		const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
		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');

		const activeCell = vscode.notebook.activeNotebookEditor!.selection;
		assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.indexOf(activeCell!), 0);
		const moveChange = getEventOncePromise(vscode.notebook.onDidChangeNotebookCells);
		await vscode.commands.executeCommand('notebook.cell.moveDown');
		const ret = await moveChange;
		assert.deepEqual(ret, {
			document: vscode.notebook.activeNotebookEditor?.document,
			changes: [
				{
					start: 0,
					deletedCount: 1,
R
:guard:  
rebornix 已提交
250
					deletedItems: [activeCell],
251 252 253 254 255
					items: []
				},
				{
					start: 1,
					deletedCount: 0,
R
:guard:  
rebornix 已提交
256
					deletedItems: [],
257 258 259 260
					items: [activeCell]
				}
			]
		});
261 262 263

		await vscode.commands.executeCommand('workbench.action.files.save');
		await vscode.commands.executeCommand('workbench.action.closeAllEditors');
264 265 266 267 268 269 270

		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
		const firstEditor = vscode.notebook.activeNotebookEditor;
		assert.equal(firstEditor?.document.cells.length, 1);

		await vscode.commands.executeCommand('workbench.action.files.save');
		await vscode.commands.executeCommand('workbench.action.closeAllEditors');
271 272
	});

273
	test('notebook editor active/visible', async function () {
R
rebornix 已提交
274
		const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
R
rebornix 已提交
275 276 277
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
		const firstEditor = vscode.notebook.activeNotebookEditor;
		assert.equal(firstEditor?.active, true);
R
rebornix 已提交
278
		assert.equal(firstEditor?.visible, true);
R
rebornix 已提交
279

280
		await splitEditor();
R
rebornix 已提交
281 282
		const secondEditor = vscode.notebook.activeNotebookEditor;
		assert.equal(secondEditor?.active, true);
R
rebornix 已提交
283
		assert.equal(secondEditor?.visible, true);
R
rebornix 已提交
284 285
		assert.equal(firstEditor?.active, false);

R
rebornix 已提交
286 287
		assert.equal(vscode.notebook.visibleNotebookEditors.length, 2);

288
		const untitledEditorChange = getEventOncePromise(vscode.notebook.onDidChangeActiveNotebookEditor);
R
rebornix 已提交
289
		await vscode.commands.executeCommand('workbench.action.files.newUntitledFile');
290
		await untitledEditorChange;
R
rebornix 已提交
291 292 293 294 295 296
		assert.equal(firstEditor?.visible, true);
		assert.equal(firstEditor?.active, false);
		assert.equal(secondEditor?.visible, false);
		assert.equal(secondEditor?.active, false);
		assert.equal(vscode.notebook.visibleNotebookEditors.length, 1);

297
		const activeEditorClose = getEventOncePromise(vscode.notebook.onDidChangeActiveNotebookEditor);
R
rebornix 已提交
298
		await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
299
		await activeEditorClose;
R
rebornix 已提交
300 301 302 303
		assert.equal(secondEditor?.active, true);
		assert.equal(secondEditor?.visible, true);
		assert.equal(vscode.notebook.visibleNotebookEditors.length, 2);

R
rebornix 已提交
304 305 306
		await vscode.commands.executeCommand('workbench.action.files.save');
		await vscode.commands.executeCommand('workbench.action.closeAllEditors');
	});
R
rebornix 已提交
307 308

	test('notebook active editor change', async function () {
R
rebornix 已提交
309
		const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
R
rebornix 已提交
310 311 312 313 314 315 316 317
		const firstEditorOpen = getEventOncePromise(vscode.notebook.onDidChangeActiveNotebookEditor);
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
		await firstEditorOpen;

		const firstEditorDeactivate = getEventOncePromise(vscode.notebook.onDidChangeActiveNotebookEditor);
		await vscode.commands.executeCommand('workbench.action.splitEditor');
		await firstEditorDeactivate;

318
		await vscode.commands.executeCommand('workbench.action.files.save');
R
rebornix 已提交
319 320
		await vscode.commands.executeCommand('workbench.action.closeAllEditors');
	});
321 322

	test('edit API', async function () {
R
rebornix 已提交
323
		const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');

		const cellsChangeEvent = getEventOncePromise<vscode.NotebookCellsChangeEvent>(vscode.notebook.onDidChangeNotebookCells);
		await vscode.notebook.activeNotebookEditor!.edit(editBuilder => {
			editBuilder.insert(1, 'test 2', 'javascript', vscode.CellKind.Code, [], undefined);
		});

		const cellChangeEventRet = await cellsChangeEvent;
		assert.equal(cellChangeEventRet.document, vscode.notebook.activeNotebookEditor?.document);
		assert.equal(cellChangeEventRet.changes.length, 1);
		assert.deepEqual(cellChangeEventRet.changes[0].start, 1);
		assert.deepEqual(cellChangeEventRet.changes[0].deletedCount, 0);
		assert.equal(cellChangeEventRet.changes[0].items[0], vscode.notebook.activeNotebookEditor!.document.cells[1]);

		await vscode.commands.executeCommand('workbench.action.files.save');
339
		await vscode.commands.executeCommand('workbench.action.closeAllEditors');
340
	});
341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357

	test('initialzation should not emit cell change events.', async function () {
		const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));

		let count = 0;
		const disposables: vscode.Disposable[] = [];
		disposables.push(vscode.notebook.onDidChangeNotebookCells(() => {
			count++;
		}));

		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
		assert.equal(count, 0);

		disposables.forEach(d => d.dispose());
		await vscode.commands.executeCommand('workbench.action.files.save');
		await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
	});
358 359
});

R
rebornix 已提交
360 361
suite('notebook workflow', () => {
	test('notebook open', async function () {
R
rebornix 已提交
362
		const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
R
rebornix 已提交
363
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
R
rebornix 已提交
364
		assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true, 'notebook first');
J
Johannes Rieken 已提交
365
		assert.equal(vscode.notebook.activeNotebookEditor!.selection?.document.getText(), 'test');
R
rebornix 已提交
366 367
		assert.equal(vscode.notebook.activeNotebookEditor!.selection?.language, 'typescript');

R
Rob Lourens 已提交
368
		await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
J
Johannes Rieken 已提交
369
		assert.equal(vscode.notebook.activeNotebookEditor!.selection?.document.getText(), '');
R
rebornix 已提交
370

R
Rob Lourens 已提交
371
		await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove');
R
rebornix 已提交
372 373
		const activeCell = vscode.notebook.activeNotebookEditor!.selection;
		assert.notEqual(vscode.notebook.activeNotebookEditor!.selection, undefined);
J
Johannes Rieken 已提交
374
		assert.equal(activeCell!.document.getText(), '');
R
rebornix 已提交
375 376 377 378 379 380 381 382
		assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.length, 3);
		assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.indexOf(activeCell!), 1);

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

	test('notebook cell actions', async function () {
R
rebornix 已提交
383
		const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
R
rebornix 已提交
384
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
R
rebornix 已提交
385
		assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true, 'notebook first');
J
Johannes Rieken 已提交
386
		assert.equal(vscode.notebook.activeNotebookEditor!.selection?.document.getText(), 'test');
R
rebornix 已提交
387 388 389
		assert.equal(vscode.notebook.activeNotebookEditor!.selection?.language, 'typescript');

		// ---- insert cell below and focus ---- //
R
Rob Lourens 已提交
390
		await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
J
Johannes Rieken 已提交
391
		assert.equal(vscode.notebook.activeNotebookEditor!.selection?.document.getText(), '');
R
rebornix 已提交
392 393

		// ---- insert cell above and focus ---- //
R
Rob Lourens 已提交
394
		await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove');
R
rebornix 已提交
395 396
		let activeCell = vscode.notebook.activeNotebookEditor!.selection;
		assert.notEqual(vscode.notebook.activeNotebookEditor!.selection, undefined);
J
Johannes Rieken 已提交
397
		assert.equal(activeCell!.document.getText(), '');
R
rebornix 已提交
398 399 400 401
		assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.length, 3);
		assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.indexOf(activeCell!), 1);

		// ---- focus bottom ---- //
R
Rob Lourens 已提交
402
		await vscode.commands.executeCommand('notebook.focusBottom');
R
rebornix 已提交
403 404 405 406
		activeCell = vscode.notebook.activeNotebookEditor!.selection;
		assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.indexOf(activeCell!), 2);

		// ---- focus top and then copy down ---- //
R
Rob Lourens 已提交
407
		await vscode.commands.executeCommand('notebook.focusTop');
R
rebornix 已提交
408 409 410
		activeCell = vscode.notebook.activeNotebookEditor!.selection;
		assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.indexOf(activeCell!), 0);

R
Rob Lourens 已提交
411
		await vscode.commands.executeCommand('notebook.cell.copyDown');
R
rebornix 已提交
412 413
		activeCell = vscode.notebook.activeNotebookEditor!.selection;
		assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.indexOf(activeCell!), 1);
J
Johannes Rieken 已提交
414
		assert.equal(activeCell?.document.getText(), 'test');
R
rebornix 已提交
415

R
Rob Lourens 已提交
416
		await vscode.commands.executeCommand('notebook.cell.delete');
R
rebornix 已提交
417 418
		activeCell = vscode.notebook.activeNotebookEditor!.selection;
		assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.indexOf(activeCell!), 1);
J
Johannes Rieken 已提交
419
		assert.equal(activeCell?.document.getText(), '');
R
rebornix 已提交
420 421

		// ---- focus top and then copy up ---- //
R
Rob Lourens 已提交
422 423
		await vscode.commands.executeCommand('notebook.focusTop');
		await vscode.commands.executeCommand('notebook.cell.copyUp');
R
rebornix 已提交
424
		assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.length, 4);
J
Johannes Rieken 已提交
425 426 427 428
		assert.equal(vscode.notebook.activeNotebookEditor!.document.cells[0].document.getText(), 'test');
		assert.equal(vscode.notebook.activeNotebookEditor!.document.cells[1].document.getText(), 'test');
		assert.equal(vscode.notebook.activeNotebookEditor!.document.cells[2].document.getText(), '');
		assert.equal(vscode.notebook.activeNotebookEditor!.document.cells[3].document.getText(), '');
R
rebornix 已提交
429 430 431 432 433 434
		activeCell = vscode.notebook.activeNotebookEditor!.selection;
		assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.indexOf(activeCell!), 0);


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

R
Rob Lourens 已提交
435
		await vscode.commands.executeCommand('notebook.cell.moveDown');
436
		assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.indexOf(vscode.notebook.activeNotebookEditor!.selection!), 1,
J
Johannes Rieken 已提交
437
			`first move down, active cell ${vscode.notebook.activeNotebookEditor!.selection!.uri.toString()}, ${vscode.notebook.activeNotebookEditor!.selection!.document.getText()}`);
438

R
rebornix 已提交
439 440 441 442
		// await vscode.commands.executeCommand('notebook.cell.moveDown');
		// activeCell = vscode.notebook.activeNotebookEditor!.selection;

		// assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.indexOf(activeCell!), 2,
J
Johannes Rieken 已提交
443 444 445 446 447
		// 	`second move down, active cell ${vscode.notebook.activeNotebookEditor!.selection!.uri.toString()}, ${vscode.notebook.activeNotebookEditor!.selection!.document.getText()}`);
		// assert.equal(vscode.notebook.activeNotebookEditor!.document.cells[0].document.getText(), 'test');
		// assert.equal(vscode.notebook.activeNotebookEditor!.document.cells[1].document.getText(), '');
		// assert.equal(vscode.notebook.activeNotebookEditor!.document.cells[2].document.getText(), 'test');
		// assert.equal(vscode.notebook.activeNotebookEditor!.document.cells[3].document.getText(), '');
R
rebornix 已提交
448 449 450

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

451
		await vscode.commands.executeCommand('workbench.action.files.save');
R
rebornix 已提交
452 453
		await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
	});
R
Rob Lourens 已提交
454

R
rebornix 已提交
455
	test('notebook join cells', async function () {
R
rebornix 已提交
456 457 458 459 460 461 462 463
		const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
		assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true, 'notebook first');
		assert.equal(vscode.notebook.activeNotebookEditor!.selection?.document.getText(), 'test');
		assert.equal(vscode.notebook.activeNotebookEditor!.selection?.language, 'typescript');

		await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
		assert.equal(vscode.notebook.activeNotebookEditor!.selection?.document.getText(), '');
R
rebornix 已提交
464 465 466
		const edit = new vscode.WorkspaceEdit();
		edit.insert(vscode.notebook.activeNotebookEditor!.selection!.uri, new vscode.Position(0, 0), 'var abc = 0;');
		await vscode.workspace.applyEdit(edit);
R
rebornix 已提交
467 468 469 470 471

		const cellsChangeEvent = getEventOncePromise<vscode.NotebookCellsChangeEvent>(vscode.notebook.onDidChangeNotebookCells);
		await vscode.commands.executeCommand('notebook.cell.joinAbove');
		await cellsChangeEvent;

R
rebornix 已提交
472
		assert.deepEqual(vscode.notebook.activeNotebookEditor!.selection?.document.getText().split(/\r\n|\r|\n/), ['test', 'var abc = 0;']);
R
rebornix 已提交
473 474 475 476 477

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

478
	test('move cells will not recreate cells in ExtHost', async function () {
R
rebornix 已提交
479
		const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
480 481 482 483 484 485 486 487 488 489 490 491
		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');

		const activeCell = vscode.notebook.activeNotebookEditor!.selection;
		assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.indexOf(activeCell!), 0);
		await vscode.commands.executeCommand('notebook.cell.moveDown');
		await vscode.commands.executeCommand('notebook.cell.moveDown');

		const newActiveCell = vscode.notebook.activeNotebookEditor!.selection;
		assert.deepEqual(activeCell, newActiveCell);
R
rebornix 已提交
492 493 494
		await vscode.commands.executeCommand('workbench.action.files.saveAll');
		await vscode.commands.executeCommand('workbench.action.closeAllEditors');

495 496
		// TODO@rebornix, there are still some events order issue.
		// assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.indexOf(newActiveCell!), 2);
497 498
	});

R
Rob Lourens 已提交
499
	// test.only('document metadata is respected', async function () {
R
rebornix 已提交
500
	// 	const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
R
Rob Lourens 已提交
501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523
	// 	await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');

	// 	assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true, 'notebook first');
	// 	const editor = vscode.notebook.activeNotebookEditor!;

	// 	assert.equal(editor.document.cells.length, 1);
	// 	editor.document.metadata.editable = false;
	// 	await editor.edit(builder => builder.delete(0));
	// 	assert.equal(editor.document.cells.length, 1, 'should not delete cell'); // Not editable, no effect
	// 	await editor.edit(builder => builder.insert(0, 'test', 'python', vscode.CellKind.Code, [], undefined));
	// 	assert.equal(editor.document.cells.length, 1, 'should not insert cell'); // Not editable, no effect

	// 	editor.document.metadata.editable = true;
	// 	await editor.edit(builder => builder.delete(0));
	// 	assert.equal(editor.document.cells.length, 0, 'should delete cell'); // Editable, it worked
	// 	await editor.edit(builder => builder.insert(0, 'test', 'python', vscode.CellKind.Code, [], undefined));
	// 	assert.equal(editor.document.cells.length, 1, 'should insert cell'); // Editable, it worked

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

	test('cell runnable metadata is respected', async () => {
R
rebornix 已提交
524
		const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
R
Rob Lourens 已提交
525 526 527 528 529 530 531 532 533 534 535 536 537 538 539
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
		assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true, 'notebook first');
		const editor = vscode.notebook.activeNotebookEditor!;

		await vscode.commands.executeCommand('notebook.focusTop');
		const cell = editor.document.cells[0];
		assert.equal(cell.outputs.length, 0);
		cell.metadata.runnable = false;
		await vscode.commands.executeCommand('notebook.cell.execute');
		assert.equal(cell.outputs.length, 0, 'should not execute'); // not runnable, didn't work

		cell.metadata.runnable = true;
		await vscode.commands.executeCommand('notebook.cell.execute');
		assert.equal(cell.outputs.length, 1, 'should execute'); // runnable, it worked

540
		await vscode.commands.executeCommand('workbench.action.files.save');
R
Rob Lourens 已提交
541 542 543 544
		await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
	});

	test('document runnable metadata is respected', async () => {
R
rebornix 已提交
545
		const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
R
Rob Lourens 已提交
546 547 548 549 550 551 552 553 554 555 556 557 558 559
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
		assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true, 'notebook first');
		const editor = vscode.notebook.activeNotebookEditor!;

		const cell = editor.document.cells[0];
		assert.equal(cell.outputs.length, 0);
		editor.document.metadata.runnable = false;
		await vscode.commands.executeCommand('notebook.execute');
		assert.equal(cell.outputs.length, 0, 'should not execute'); // not runnable, didn't work

		editor.document.metadata.runnable = true;
		await vscode.commands.executeCommand('notebook.execute');
		assert.equal(cell.outputs.length, 1, 'should execute'); // runnable, it worked

560
		await vscode.commands.executeCommand('workbench.action.files.save');
R
Rob Lourens 已提交
561 562
		await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
	});
R
rebornix 已提交
563
});
R
rebornix 已提交
564 565 566

suite('notebook dirty state', () => {
	test('notebook open', async function () {
R
rebornix 已提交
567
		const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
R
rebornix 已提交
568 569
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
		assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true, 'notebook first');
J
Johannes Rieken 已提交
570
		assert.equal(vscode.notebook.activeNotebookEditor!.selection?.document.getText(), 'test');
R
rebornix 已提交
571 572 573
		assert.equal(vscode.notebook.activeNotebookEditor!.selection?.language, 'typescript');

		await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
J
Johannes Rieken 已提交
574
		assert.equal(vscode.notebook.activeNotebookEditor!.selection?.document.getText(), '');
R
rebornix 已提交
575 576 577 578

		await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove');
		const activeCell = vscode.notebook.activeNotebookEditor!.selection;
		assert.notEqual(vscode.notebook.activeNotebookEditor!.selection, undefined);
J
Johannes Rieken 已提交
579
		assert.equal(activeCell!.document.getText(), '');
R
rebornix 已提交
580 581 582
		assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.length, 3);
		assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.indexOf(activeCell!), 1);

R
rebornix 已提交
583 584 585
		const edit = new vscode.WorkspaceEdit();
		edit.insert(activeCell!.uri, new vscode.Position(0, 0), 'var abc = 0;');
		await vscode.workspace.applyEdit(edit);
R
rebornix 已提交
586 587 588
		assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true);
		assert.equal(vscode.notebook.activeNotebookEditor?.selection !== undefined, true);
		assert.deepEqual(vscode.notebook.activeNotebookEditor?.document.cells[1], vscode.notebook.activeNotebookEditor?.selection);
J
Johannes Rieken 已提交
589
		assert.equal(vscode.notebook.activeNotebookEditor?.selection?.document.getText(), 'var abc = 0;');
R
rebornix 已提交
590

591
		await saveFileAndCloseAll(resource);
R
rebornix 已提交
592 593 594 595
	});
});

suite('notebook undo redo', () => {
596
	test('notebook open', async function () {
R
rebornix 已提交
597
		const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
R
rebornix 已提交
598 599
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
		assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true, 'notebook first');
J
Johannes Rieken 已提交
600
		assert.equal(vscode.notebook.activeNotebookEditor!.selection?.document.getText(), 'test');
R
rebornix 已提交
601 602 603
		assert.equal(vscode.notebook.activeNotebookEditor!.selection?.language, 'typescript');

		await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
J
Johannes Rieken 已提交
604
		assert.equal(vscode.notebook.activeNotebookEditor!.selection?.document.getText(), '');
R
rebornix 已提交
605 606 607 608

		await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove');
		const activeCell = vscode.notebook.activeNotebookEditor!.selection;
		assert.notEqual(vscode.notebook.activeNotebookEditor!.selection, undefined);
J
Johannes Rieken 已提交
609
		assert.equal(activeCell!.document.getText(), '');
R
rebornix 已提交
610 611 612 613 614
		assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.length, 3);
		assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.indexOf(activeCell!), 1);


		// modify the second cell, delete it
R
rebornix 已提交
615 616 617
		const edit = new vscode.WorkspaceEdit();
		edit.insert(vscode.notebook.activeNotebookEditor!.selection!.uri, new vscode.Position(0, 0), 'var abc = 0;');
		await vscode.workspace.applyEdit(edit);
R
rebornix 已提交
618 619 620 621 622 623 624 625 626
		await vscode.commands.executeCommand('notebook.cell.delete');
		assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.length, 2);
		assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.indexOf(vscode.notebook.activeNotebookEditor!.selection!), 1);


		// undo should bring back the deleted cell, and revert to previous content and selection
		await vscode.commands.executeCommand('notebook.undo');
		assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.length, 3);
		assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.indexOf(vscode.notebook.activeNotebookEditor!.selection!), 1);
J
Johannes Rieken 已提交
627
		assert.equal(vscode.notebook.activeNotebookEditor?.selection?.document.getText(), 'var abc = 0;');
R
rebornix 已提交
628 629 630 631 632

		// redo
		// await vscode.commands.executeCommand('notebook.redo');
		// assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.length, 2);
		// assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.indexOf(vscode.notebook.activeNotebookEditor!.selection!), 1);
J
Johannes Rieken 已提交
633
		// assert.equal(vscode.notebook.activeNotebookEditor?.selection?.document.getText(), 'test');
R
rebornix 已提交
634

635
		await saveFileAndCloseAll(resource);
R
rebornix 已提交
636
	});
637

R
rebornix 已提交
638
	test.skip('execute and then undo redo', async function () {
639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696
		const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');

		const cellsChangeEvent = getEventOncePromise<vscode.NotebookCellsChangeEvent>(vscode.notebook.onDidChangeNotebookCells);
		await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
		const cellChangeEventRet = await cellsChangeEvent;
		assert.equal(cellChangeEventRet.document, vscode.notebook.activeNotebookEditor?.document);
		assert.equal(cellChangeEventRet.changes.length, 1);
		assert.deepEqual(cellChangeEventRet.changes[0], {
			start: 1,
			deletedCount: 0,
			deletedItems: [],
			items: [
				vscode.notebook.activeNotebookEditor!.document.cells[1]
			]
		});

		const secondCell = vscode.notebook.activeNotebookEditor!.document.cells[1];

		const moveCellEvent = getEventOncePromise<vscode.NotebookCellsChangeEvent>(vscode.notebook.onDidChangeNotebookCells);
		await vscode.commands.executeCommand('notebook.cell.moveUp');
		const moveCellEventRet = await moveCellEvent;
		assert.deepEqual(moveCellEventRet, {
			document: vscode.notebook.activeNotebookEditor!.document,
			changes: [
				{
					start: 1,
					deletedCount: 1,
					deletedItems: [secondCell],
					items: []
				},
				{
					start: 0,
					deletedCount: 0,
					deletedItems: [],
					items: [vscode.notebook.activeNotebookEditor?.document.cells[0]]
				}
			]
		});

		const cellOutputChange = getEventOncePromise<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs);
		await vscode.commands.executeCommand('notebook.cell.execute');
		const cellOutputsAddedRet = await cellOutputChange;
		assert.deepEqual(cellOutputsAddedRet, {
			document: vscode.notebook.activeNotebookEditor!.document,
			cells: [vscode.notebook.activeNotebookEditor!.document.cells[0]]
		});
		assert.equal(cellOutputsAddedRet.cells[0].outputs.length, 1);

		const cellOutputClear = getEventOncePromise<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs);
		await vscode.commands.executeCommand('notebook.undo');
		const cellOutputsCleardRet = await cellOutputClear;
		assert.deepEqual(cellOutputsCleardRet, {
			document: vscode.notebook.activeNotebookEditor!.document,
			cells: [vscode.notebook.activeNotebookEditor!.document.cells[0]]
		});
		assert.equal(cellOutputsAddedRet.cells[0].outputs.length, 0);

697
		await saveFileAndCloseAll(resource);
698 699
	});

R
rebornix 已提交
700
});
701 702

suite('notebook working copy', () => {
R
rebornix 已提交
703 704 705 706 707
	// test('notebook revert on close', async function () {
	// 	const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
	// 	await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
	// 	await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
	// 	assert.equal(vscode.notebook.activeNotebookEditor!.selection?.document.getText(), '');
708

R
rebornix 已提交
709 710
	// 	await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove');
	// 	await vscode.commands.executeCommand('default:type', { text: 'var abc = 0;' });
711

R
rebornix 已提交
712 713 714 715 716 717 718
	// 	// close active editor from command will revert the file
	// 	await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
	// 	await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
	// 	assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true);
	// 	assert.equal(vscode.notebook.activeNotebookEditor?.selection !== undefined, true);
	// 	assert.deepEqual(vscode.notebook.activeNotebookEditor?.document.cells[0], vscode.notebook.activeNotebookEditor?.selection);
	// 	assert.equal(vscode.notebook.activeNotebookEditor?.selection?.document.getText(), 'test');
719

R
rebornix 已提交
720 721 722
	// 	await vscode.commands.executeCommand('workbench.action.files.save');
	// 	await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
	// });
723

R
rebornix 已提交
724 725 726 727 728
	// test('notebook revert', async function () {
	// 	const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
	// 	await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
	// 	await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
	// 	assert.equal(vscode.notebook.activeNotebookEditor!.selection?.document.getText(), '');
729

R
rebornix 已提交
730 731 732
	// 	await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove');
	// 	await vscode.commands.executeCommand('default:type', { text: 'var abc = 0;' });
	// 	await vscode.commands.executeCommand('workbench.action.files.revert');
733

R
rebornix 已提交
734 735 736 737 738
	// 	assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true);
	// 	assert.equal(vscode.notebook.activeNotebookEditor?.selection !== undefined, true);
	// 	assert.deepEqual(vscode.notebook.activeNotebookEditor?.document.cells[0], vscode.notebook.activeNotebookEditor?.selection);
	// 	assert.deepEqual(vscode.notebook.activeNotebookEditor?.document.cells.length, 1);
	// 	assert.equal(vscode.notebook.activeNotebookEditor?.selection?.document.getText(), 'test');
739

R
rebornix 已提交
740 741 742
	// 	await vscode.commands.executeCommand('workbench.action.files.saveAll');
	// 	await vscode.commands.executeCommand('workbench.action.closeAllEditors');
	// });
743 744

	test('multiple tabs: dirty + clean', async function () {
R
rebornix 已提交
745
		const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
746 747
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
		await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
J
Johannes Rieken 已提交
748
		assert.equal(vscode.notebook.activeNotebookEditor!.selection?.document.getText(), '');
749 750

		await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove');
R
rebornix 已提交
751 752 753
		const edit = new vscode.WorkspaceEdit();
		edit.insert(vscode.notebook.activeNotebookEditor!.selection!.uri, new vscode.Position(0, 0), 'var abc = 0;');
		await vscode.workspace.applyEdit(edit);
754

R
rebornix 已提交
755
		const secondResource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './second.vsctestnb'));
756 757 758 759 760 761 762 763
		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
		assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true);
		assert.equal(vscode.notebook.activeNotebookEditor?.selection !== undefined, true);
		assert.deepEqual(vscode.notebook.activeNotebookEditor?.document.cells[1], vscode.notebook.activeNotebookEditor?.selection);
		assert.deepEqual(vscode.notebook.activeNotebookEditor?.document.cells.length, 3);
J
Johannes Rieken 已提交
764
		assert.equal(vscode.notebook.activeNotebookEditor?.selection?.document.getText(), 'var abc = 0;');
765

766
		await saveFileAndCloseAll(resource);
767 768 769
	});

	test('multiple tabs: two dirty tabs and switching', async function () {
R
rebornix 已提交
770
		const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
771 772
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
		await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
J
Johannes Rieken 已提交
773
		assert.equal(vscode.notebook.activeNotebookEditor!.selection?.document.getText(), '');
774 775

		await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove');
R
rebornix 已提交
776 777 778
		const edit = new vscode.WorkspaceEdit();
		edit.insert(vscode.notebook.activeNotebookEditor!.selection!.uri, new vscode.Position(0, 0), 'var abc = 0;');
		await vscode.workspace.applyEdit(edit);
779

R
rebornix 已提交
780
		const secondResource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './second.vsctestnb'));
781 782
		await vscode.commands.executeCommand('vscode.openWith', secondResource, 'notebookCoreTest');
		await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
J
Johannes Rieken 已提交
783
		assert.equal(vscode.notebook.activeNotebookEditor!.selection?.document.getText(), '');
784 785 786 787 788 789 790

		// switch to the first editor
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
		assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true);
		assert.equal(vscode.notebook.activeNotebookEditor?.selection !== undefined, true);
		assert.deepEqual(vscode.notebook.activeNotebookEditor?.document.cells[1], vscode.notebook.activeNotebookEditor?.selection);
		assert.deepEqual(vscode.notebook.activeNotebookEditor?.document.cells.length, 3);
J
Johannes Rieken 已提交
791
		assert.equal(vscode.notebook.activeNotebookEditor?.selection?.document.getText(), 'var abc = 0;');
792 793 794 795 796 797 798

		// switch to the second editor
		await vscode.commands.executeCommand('vscode.openWith', secondResource, 'notebookCoreTest');
		assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true);
		assert.equal(vscode.notebook.activeNotebookEditor?.selection !== undefined, true);
		assert.deepEqual(vscode.notebook.activeNotebookEditor?.document.cells[1], vscode.notebook.activeNotebookEditor?.selection);
		assert.deepEqual(vscode.notebook.activeNotebookEditor?.document.cells.length, 2);
J
Johannes Rieken 已提交
799
		assert.equal(vscode.notebook.activeNotebookEditor?.selection?.document.getText(), '');
800

801 802 803 804 805 806
		await vscode.commands.executeCommand('workbench.action.files.saveAll');
		await vscode.commands.executeCommand('workbench.action.closeAllEditors');
	});

	test('multiple tabs: different editors with same document', async function () {

R
rebornix 已提交
807
		const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
808 809 810
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
		const firstNotebookEditor = vscode.notebook.activeNotebookEditor;
		assert.equal(firstNotebookEditor !== undefined, true, 'notebook first');
J
Johannes Rieken 已提交
811
		assert.equal(firstNotebookEditor!.selection?.document.getText(), 'test');
812 813
		assert.equal(firstNotebookEditor!.selection?.language, 'typescript');

814
		await splitEditor();
815 816
		const secondNotebookEditor = vscode.notebook.activeNotebookEditor;
		assert.equal(secondNotebookEditor !== undefined, true, 'notebook first');
J
Johannes Rieken 已提交
817
		assert.equal(secondNotebookEditor!.selection?.document.getText(), 'test');
818 819 820 821
		assert.equal(secondNotebookEditor!.selection?.language, 'typescript');

		assert.notEqual(firstNotebookEditor, secondNotebookEditor);
		assert.equal(firstNotebookEditor?.document, secondNotebookEditor?.document, 'split notebook editors share the same document');
R
rebornix 已提交
822
		assert.notEqual(firstNotebookEditor?.asWebviewUri(vscode.Uri.file('./hello.png')), secondNotebookEditor?.asWebviewUri(vscode.Uri.file('./hello.png')));
823

824 825 826
		await vscode.commands.executeCommand('workbench.action.files.saveAll');
		await vscode.commands.executeCommand('workbench.action.closeAllEditors');
	});
827
});
828

R
rebornix 已提交
829 830
suite('metadata', () => {
	test('custom metadata should be supported', async function () {
R
rebornix 已提交
831
		const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
R
rebornix 已提交
832 833
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
		assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true, 'notebook first');
834
		assert.equal(vscode.notebook.activeNotebookEditor!.document.metadata.custom!['testMetadata'] as boolean, false);
R
rebornix 已提交
835
		assert.equal(vscode.notebook.activeNotebookEditor!.selection?.metadata.custom!['testCellMetadata'] as number, 123);
R
rebornix 已提交
836
		assert.equal(vscode.notebook.activeNotebookEditor!.selection?.language, 'typescript');
837

838
		await saveFileAndCloseAll(resource);
R
rebornix 已提交
839
	});
840

841

R
rebornix 已提交
842 843
	// TODO@rebornix skip as it crashes the process all the time
	test.skip('custom metadata should be supported', async function () {
R
rebornix 已提交
844
		const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
845 846 847 848 849 850
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
		assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true, 'notebook first');
		assert.equal(vscode.notebook.activeNotebookEditor!.document.metadata.custom!['testMetadata'] as boolean, false);
		assert.equal(vscode.notebook.activeNotebookEditor!.selection?.metadata.custom!['testCellMetadata'] as number, 123);
		assert.equal(vscode.notebook.activeNotebookEditor!.selection?.language, 'typescript');

851 852 853 854 855
		// TODO see #101462
		// await vscode.commands.executeCommand('notebook.cell.copyDown');
		// const activeCell = vscode.notebook.activeNotebookEditor!.selection;
		// assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.indexOf(activeCell!), 1);
		// assert.equal(activeCell?.metadata.custom!['testCellMetadata'] as number, 123);
856

857
		await saveFileAndCloseAll(resource);
R
rebornix 已提交
858
	});
R
rebornix 已提交
859 860
});

861 862
suite('regression', () => {
	test('microsoft/vscode-github-issue-notebooks#26. Insert template cell in the new empty document', async function () {
R
rebornix 已提交
863
		const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './empty.vsctestnb'));
864 865
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
		assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true, 'notebook first');
J
Johannes Rieken 已提交
866
		assert.equal(vscode.notebook.activeNotebookEditor!.selection?.document.getText(), '');
867
		assert.equal(vscode.notebook.activeNotebookEditor!.selection?.language, 'typescript');
868
		await saveFileAndCloseAll(resource);
869
	});
870 871

	test('#97830, #97764. Support switch to other editor types', async function () {
R
rebornix 已提交
872
		const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './empty.vsctestnb'));
873 874
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
		await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
R
rebornix 已提交
875 876 877
		const edit = new vscode.WorkspaceEdit();
		edit.insert(vscode.notebook.activeNotebookEditor!.selection!.uri, new vscode.Position(0, 0), 'var abc = 0;');
		await vscode.workspace.applyEdit(edit);
878 879

		assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true, 'notebook first');
J
Johannes Rieken 已提交
880
		assert.equal(vscode.notebook.activeNotebookEditor!.selection?.document.getText(), 'var abc = 0;');
881 882 883 884 885 886 887
		assert.equal(vscode.notebook.activeNotebookEditor!.selection?.language, 'typescript');

		await vscode.commands.executeCommand('vscode.openWith', resource, 'default');
		assert.equal(vscode.window.activeTextEditor?.document.uri.path, resource.path);

		await vscode.commands.executeCommand('workbench.action.closeAllEditors');
	});
888 889 890

	// open text editor, pin, and then open a notebook
	test('#96105 - dirty editors', async function () {
R
rebornix 已提交
891
		const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './empty.vsctestnb'));
892
		await vscode.commands.executeCommand('vscode.openWith', resource, 'default');
R
rebornix 已提交
893
		const edit = new vscode.WorkspaceEdit();
R
rebornix 已提交
894
		edit.insert(resource, new vscode.Position(0, 0), 'var abc = 0;');
R
rebornix 已提交
895
		await vscode.workspace.applyEdit(edit);
896 897 898 899 900 901 902 903 904

		// now it's dirty, open the resource with notebook editor should open a new one
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
		assert.notEqual(vscode.notebook.activeNotebookEditor, undefined, 'notebook first');
		assert.notEqual(vscode.window.activeTextEditor, undefined);

		await vscode.commands.executeCommand('workbench.action.closeAllEditors');
	});

R
rebornix 已提交
905
	test('#102411 - untitled notebook creation failed', async function () {
J
Johannes Rieken 已提交
906
		await vscode.commands.executeCommand('workbench.action.files.newUntitledFile', { viewType: 'notebookCoreTest' });
R
rebornix 已提交
907
		assert.notEqual(vscode.notebook.activeNotebookEditor, undefined, 'untitled notebook editor is not undefined');
908 909

		await vscode.commands.executeCommand('workbench.action.closeAllEditors');
R
rebornix 已提交
910
	});
R
rebornix 已提交
911 912 913 914 915 916 917 918 919 920 921 922 923 924

	test('#102423 - copy/paste shares the same text buffer', async function () {
		const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
		await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');

		let activeCell = vscode.notebook.activeNotebookEditor!.selection;
		assert.equal(activeCell?.document.getText(), 'test');

		await vscode.commands.executeCommand('notebook.cell.copyDown');
		await vscode.commands.executeCommand('notebook.cell.edit');
		activeCell = vscode.notebook.activeNotebookEditor!.selection;
		assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.indexOf(activeCell!), 1);
		assert.equal(activeCell?.document.getText(), 'test');

R
rebornix 已提交
925 926 927
		const edit = new vscode.WorkspaceEdit();
		edit.insert(vscode.notebook.activeNotebookEditor!.selection!.uri, new vscode.Position(0, 0), 'var abc = 0;');
		await vscode.workspace.applyEdit(edit);
R
rebornix 已提交
928 929

		assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.length, 2);
J
Johannes Rieken 已提交
930
		assert.notEqual(vscode.notebook.activeNotebookEditor!.document.cells[0].document.getText(), vscode.notebook.activeNotebookEditor!.document.cells[1].document.getText());
931 932

		await vscode.commands.executeCommand('workbench.action.closeAllEditors');
R
rebornix 已提交
933
	});
934
});
R
rebornix 已提交
935

R
rebornix 已提交
936
suite('webview', () => {
R
rebornix 已提交
937
	// for web, `asWebUri` gets `https`?
938 939 940 941
	// test('asWebviewUri', async function () {
	// 	if (vscode.env.uiKind === vscode.UIKind.Web) {
	// 		return;
	// 	}
R
rebornix 已提交
942

943 944 945 946
	// 	const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
	// 	await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
	// 	assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true, 'notebook first');
	// 	const uri = vscode.notebook.activeNotebookEditor!.asWebviewUri(vscode.Uri.file('./hello.png'));
947
	// 	assert.equal(uri.scheme, 'vscode-webview-resource');
948 949
	// 	await vscode.commands.executeCommand('workbench.action.closeAllEditors');
	// });
R
rebornix 已提交
950

R
rebornix 已提交
951 952

	// 404 on web
953 954 955 956
	// test('custom renderer message', async function () {
	// 	if (vscode.env.uiKind === vscode.UIKind.Web) {
	// 		return;
	// 	}
R
rebornix 已提交
957

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

961 962 963 964 965 966 967 968 969 970 971 972 973 974
	// 	const editor = vscode.notebook.activeNotebookEditor;
	// 	const promise = new Promise(resolve => {
	// 		const messageEmitter = editor?.onDidReceiveMessage(e => {
	// 			if (e.type === 'custom_renderer_initialize') {
	// 				resolve();
	// 				messageEmitter?.dispose();
	// 			}
	// 		});
	// 	});

	// 	await vscode.commands.executeCommand('notebook.cell.execute');
	// 	await promise;
	// 	await vscode.commands.executeCommand('workbench.action.closeAllEditors');
	// });
R
rebornix 已提交
975
});