提交 a3f414cf 编写于 作者: J Johannes Rieken

add some integration tests for notebook editing, https://github.com/microsoft/vscode/issues/105283

上级 dd3e9ee0
......@@ -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();
......@@ -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);
});
......
......@@ -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 => {
......
......@@ -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;
......
......@@ -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;
......@@ -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; },
......@@ -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) {
......@@ -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);
}
}
......@@ -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)));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册