Skip to content

Commit

Permalink
add some integration tests for notebook editing, #105283
Browse files Browse the repository at this point in the history
  • Loading branch information
jrieken committed Aug 28, 2020
1 parent dd3e9ee commit a3f414c
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 17 deletions.
103 changes: 95 additions & 8 deletions extensions/vscode-notebook-tests/src/notebook.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,11 @@ async function saveFileAndCloseAll(resource: vscode.Uri) {
await documentClosed;
}

async function saveAllFilesAndCloseAll(resource: vscode.Uri) {
async function saveAllFilesAndCloseAll(resource: vscode.Uri | undefined) {
const documentClosed = new Promise((resolve, _reject) => {
if (!resource) {
return resolve();
}
const d = vscode.notebook.onDidCloseNotebookDocument(e => {
if (e.uri.toString() === resource.toString()) {
d.dispose();
Expand Down Expand Up @@ -393,23 +396,107 @@ suite('Notebook API tests', () => {
await saveFileAndCloseAll(resource);
});

test('edit API', async function () {
test('edit API (replaceCells)', async function () {
assertInitalState();
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
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);
editBuilder.replaceCells(1, 0, [{ cellKind: vscode.CellKind.Code, language: 'javascript', source: 'test 2', outputs: [], metadata: 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]);
assert.strictEqual(cellChangeEventRet.document === vscode.notebook.activeNotebookEditor?.document, true);
assert.strictEqual(cellChangeEventRet.document.isDirty, true);
assert.strictEqual(cellChangeEventRet.changes.length, 1);
assert.strictEqual(cellChangeEventRet.changes[0].start, 1);
assert.strictEqual(cellChangeEventRet.changes[0].deletedCount, 0);
assert.strictEqual(cellChangeEventRet.changes[0].items[0] === vscode.notebook.activeNotebookEditor!.document.cells[1], true);

await saveAllFilesAndCloseAll(resource);
});

test('edit API (replaceOutput)', async function () {
// no output events yet...
this.skip();

assertInitalState();
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');

await vscode.notebook.activeNotebookEditor!.edit(editBuilder => {
editBuilder.replaceOutput(0, [{ outputKind: vscode.CellOutputKind.Rich, data: { foo: 'bar' } }]);
});

const document = vscode.notebook.activeNotebookEditor?.document!;
assert.strictEqual(document.isDirty, false);
assert.strictEqual(document.cells.length, 1);
assert.strictEqual(document.cells[0].outputs.length, 1);
assert.strictEqual(document.cells[0].outputs[0].outputKind, vscode.CellOutputKind.Rich);

await saveAllFilesAndCloseAll(undefined);
});

test('edit API (replaceOutput, event)', async function () {
// no output events yet...
this.skip();

assertInitalState();
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');

const outputChangeEvent = getEventOncePromise<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs);
await vscode.notebook.activeNotebookEditor!.edit(editBuilder => {
editBuilder.replaceOutput(0, [{ outputKind: vscode.CellOutputKind.Rich, data: { foo: 'bar' } }]);
});

const value = await outputChangeEvent;
assert.strictEqual(value.document === vscode.notebook.activeNotebookEditor?.document, true);
assert.strictEqual(value.cells.length, 1);
assert.strictEqual(value.cells[0].outputs.length, 1);
assert.strictEqual(value.cells[0].outputs[0].outputKind, vscode.CellOutputKind.Rich);

await saveAllFilesAndCloseAll(undefined);
});

test('edit API (replaceMetadata)', async function () {

assertInitalState();
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');

await vscode.notebook.activeNotebookEditor!.edit(editBuilder => {
editBuilder.replaceMetadata(0, { inputCollapsed: true, executionOrder: 17 });
});

const document = vscode.notebook.activeNotebookEditor?.document!;
assert.strictEqual(document.cells.length, 1);
assert.strictEqual(document.cells[0].metadata.executionOrder, 17);
assert.strictEqual(document.cells[0].metadata.inputCollapsed, true);

assert.strictEqual(document.isDirty, true);
await saveFileAndCloseAll(resource);
});

test('edit API (replaceMetadata, event)', async function () {

assertInitalState();
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');

const event = getEventOncePromise<vscode.NotebookCellMetadataChangeEvent>(vscode.notebook.onDidChangeCellMetadata);

await vscode.notebook.activeNotebookEditor!.edit(editBuilder => {
editBuilder.replaceMetadata(0, { inputCollapsed: true, executionOrder: 17 });
});

const data = await event;
assert.strictEqual(data.document, vscode.notebook.activeNotebookEditor?.document);
assert.strictEqual(data.cell.metadata.executionOrder, 17);
assert.strictEqual(data.cell.metadata.inputCollapsed, true);

assert.strictEqual(data.document.isDirty, true);
await saveFileAndCloseAll(resource);
});

Expand Down
2 changes: 1 addition & 1 deletion src/vs/workbench/api/browser/mainThreadNotebook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
const disposableStore = new DisposableStore();
const textModel = this._notebookService.getNotebookTextModel(doc);
disposableStore.add(textModel!.onDidModelChangeProxy(e => {
this._proxy.$acceptModelChanged(textModel!.uri, e);
this._proxy.$acceptModelChanged(textModel!.uri, e, textModel!.isDirty);
this._proxy.$acceptEditorPropertiesChanged(doc, { selections: { selections: textModel!.selections }, metadata: null });
}));
disposableStore.add(textModel!.onDidSelectionChange(e => {
Expand Down
2 changes: 1 addition & 1 deletion src/vs/workbench/api/common/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1668,7 +1668,7 @@ export interface ExtHostNotebookShape {
$acceptDisplayOrder(displayOrder: INotebookDisplayOrder): void;
$acceptNotebookActiveKernelChange(event: { uri: UriComponents, providerHandle: number | undefined, kernelId: string | undefined }): void;
$onDidReceiveMessage(editorId: string, rendererId: string | undefined, message: unknown): void;
$acceptModelChanged(uriComponents: UriComponents, event: NotebookCellsChangedEvent): void;
$acceptModelChanged(uriComponents: UriComponents, event: NotebookCellsChangedEvent, isDirty: boolean): void;
$acceptModelSaved(uriComponents: UriComponents): void;
$acceptEditorPropertiesChanged(uriComponents: UriComponents, data: INotebookEditorPropertiesChangeData): void;
$acceptDocumentAndEditorsDelta(delta: INotebookDocumentsAndEditorsDelta): void;
Expand Down
14 changes: 7 additions & 7 deletions src/vs/workbench/api/common/extHostNotebook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ export class ExtHostNotebookDocument extends Disposable {
private _metadataChangeListener: IDisposable;
private _displayOrder: string[] = [];
private _versionId = 0;
private _isDirty: boolean = false;
private _backupCounter = 1;
private _backup?: vscode.NotebookDocumentBackup;
private _disposed = false;
Expand Down Expand Up @@ -274,7 +275,7 @@ export class ExtHostNotebookDocument extends Disposable {
get version() { return that._versionId; },
get fileName() { return that.uri.fsPath; },
get viewType() { return that._viewType; },
get isDirty() { return false; },
get isDirty() { return that._isDirty; },
get isUntitled() { return that.uri.scheme === Schemas.untitled; },
get cells(): ReadonlyArray<vscode.NotebookCell> { return that._cells.map(cell => cell.cell); },
get languages() { return that._languages; },
Expand Down Expand Up @@ -311,8 +312,9 @@ export class ExtHostNotebookDocument extends Disposable {
this._backup = undefined;
}

acceptModelChanged(event: NotebookCellsChangedEvent): void {
acceptModelChanged(event: NotebookCellsChangedEvent, isDirty: boolean): void {
this._versionId = event.versionId;
this._isDirty = isDirty;
if (event.kind === NotebookCellsChangeType.Initialize) {
this._spliceNotebookCells(event.changes, true);
} if (event.kind === NotebookCellsChangeType.ModelChange) {
Expand Down Expand Up @@ -1255,12 +1257,10 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
this._webviewComm.get(editorId)?.onDidReceiveMessage(forRendererType, message);
}

$acceptModelChanged(uriComponents: UriComponents, event: NotebookCellsChangedEvent): void {

$acceptModelChanged(uriComponents: UriComponents, event: NotebookCellsChangedEvent, isDirty: boolean): void {
const document = this._documents.get(URI.revive(uriComponents));

if (document) {
document.acceptModelChanged(event);
document.acceptModelChanged(event, isDirty);
}
}

Expand Down Expand Up @@ -1401,7 +1401,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
0,
modelData.cells
]]
});
}, false);

// add cell document as vscode.TextDocument
addedCellDocuments.push(...modelData.cells.map(cell => ExtHostCell.asModelAddData(document.notebookDocument, cell)));
Expand Down

0 comments on commit a3f414c

Please sign in to comment.