Path: blob/main/src/vs/workbench/contrib/chat/test/browser/chatEditingModifiedNotebookEntry.test.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import assert from 'assert';6import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../base/test/common/utils.js';7import { adjustCellDiffAndOriginalModelBasedOnCellAddDelete, adjustCellDiffAndOriginalModelBasedOnCellMovements, adjustCellDiffForKeepingADeletedCell, adjustCellDiffForKeepingAnInsertedCell, adjustCellDiffForRevertingADeletedCell, adjustCellDiffForRevertingAnInsertedCell } from '../../browser/chatEditing/notebook/helpers.js';8import { ICellDiffInfo } from '../../browser/chatEditing/notebook/notebookCellChanges.js';9import { nullDocumentDiff } from '../../../../../editor/common/diff/documentDiffProvider.js';10import { ObservablePromise, observableValue } from '../../../../../base/common/observable.js';11import { CellEditType, CellKind, ICell, ICellEditOperation, NotebookCellsChangeType } from '../../../notebook/common/notebookCommon.js';12import { ITextModel } from '../../../../../editor/common/model.js';13import { URI } from '../../../../../base/common/uri.js';14import { hash } from '../../../../../base/common/hash.js';15import { generateUuid } from '../../../../../base/common/uuid.js';1617suite('ChatEditingModifiedNotebookEntry', function () {18suite('Keep Inserted Cell', function () {1920const keep = () => Promise.resolve(true);21const undo = () => Promise.resolve(true);22const diff = observableValue('cell1', nullDocumentDiff);23const appliedEdits: ICellEditOperation[] = [];24setup(() => {25appliedEdits.length = 0;26});27ensureNoDisposablesAreLeakedInTestSuite();28function createModifiedModel(id: string): ObservablePromise<ITextModel> {29return `Modified:${id}` as any;3031}32function createOriginalModel(id: string): ObservablePromise<ITextModel> {33return `Original:${id}` as any;3435}36function applyEdits(edits: ICellEditOperation[]): boolean {37appliedEdits.push(...edits);38return true;39}4041function createModifiedCellDiffInfo(modifiedCellIndex: number, originalCellIndex: number): ICellDiffInfo {42return {43diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel(`InsertedOriginal:${originalCellIndex}`), originalCellIndex,44modifiedCellIndex, modifiedModel: createModifiedModel(`InsertedModified:${modifiedCellIndex}`),45};46}47test('Keep first inserted', async function () {48const cellsDiffInfo: ICellDiffInfo[] = [49{50diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,51modifiedCellIndex: 0, modifiedModel: createModifiedModel('New0'),52},53{54diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,55modifiedCellIndex: 1, modifiedModel: createModifiedModel('0'),56},57];5859const result = adjustCellDiffForKeepingAnInsertedCell(0,60cellsDiffInfo, {} as any,61applyEdits, createModifiedCellDiffInfo);6263assert.deepStrictEqual(appliedEdits, [64{ editType: CellEditType.Replace, index: 0, cells: [{}], count: 0 },65]);66assert.deepStrictEqual(result, [67{68diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel(`InsertedOriginal:0`), originalCellIndex: 0,69modifiedCellIndex: 0, modifiedModel: createModifiedModel(`InsertedModified:0`),70},71{72diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 1,73modifiedCellIndex: 1, modifiedModel: createModifiedModel('0'),74},75]);76});77test('Keep first inserted with multiple cells', async function () {78const cellsDiffInfo: ICellDiffInfo[] = [79{80diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,81modifiedCellIndex: 0, modifiedModel: createModifiedModel('New0'),82},83{84diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,85modifiedCellIndex: 1, modifiedModel: createModifiedModel('0'),86},87{88diff, keep, undo, type: 'delete', originalModel: createOriginalModel('1'), originalCellIndex: 1,89modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),90},91{92diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,93modifiedCellIndex: 2, modifiedModel: createModifiedModel('1'),94},95{96diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('2'), originalCellIndex: 2,97modifiedCellIndex: 3, modifiedModel: createModifiedModel('2'),98},99];100101const result = adjustCellDiffForKeepingAnInsertedCell(0,102cellsDiffInfo, {} as any,103applyEdits, createModifiedCellDiffInfo);104105assert.deepStrictEqual(appliedEdits, [106{ editType: CellEditType.Replace, index: 0, cells: [{}], count: 0 },107]);108assert.deepStrictEqual(result, [109{110diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('InsertedOriginal:0'), originalCellIndex: 0,111modifiedCellIndex: 0, modifiedModel: createModifiedModel('InsertedModified:0'),112},113{114diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 1,115modifiedCellIndex: 1, modifiedModel: createModifiedModel('0'),116},117{118diff, keep, undo, type: 'delete', originalModel: createOriginalModel('1'), originalCellIndex: 2,119modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),120},121{122diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,123modifiedCellIndex: 2, modifiedModel: createModifiedModel('1'),124},125{126diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('2'), originalCellIndex: 3,127modifiedCellIndex: 3, modifiedModel: createModifiedModel('2'),128},129]);130});131test('Keep second inserted with multiple cells', async function () {132const cellsDiffInfo: ICellDiffInfo[] = [133{134diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,135modifiedCellIndex: 0, modifiedModel: createModifiedModel('New0'),136},137{138diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,139modifiedCellIndex: 1, modifiedModel: createModifiedModel('0'),140},141{142diff, keep, undo, type: 'delete', originalModel: createOriginalModel('1'), originalCellIndex: 1,143modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),144},145{146diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,147modifiedCellIndex: 2, modifiedModel: createModifiedModel('1'),148},149{150diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('2'), originalCellIndex: 2,151modifiedCellIndex: 3, modifiedModel: createModifiedModel('2'),152},153];154155const result = adjustCellDiffForKeepingAnInsertedCell(2,156cellsDiffInfo, {} as any,157applyEdits, createModifiedCellDiffInfo);158159assert.deepStrictEqual(appliedEdits, [160{ editType: CellEditType.Replace, index: 2, cells: [{}], count: 0 },161]);162assert.deepStrictEqual(result, [163{164diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,165modifiedCellIndex: 0, modifiedModel: createModifiedModel('New0'),166},167{168diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,169modifiedCellIndex: 1, modifiedModel: createModifiedModel('0'),170},171{172diff, keep, undo, type: 'delete', originalModel: createOriginalModel('1'), originalCellIndex: 1,173modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),174},175{176diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('InsertedOriginal:2'), originalCellIndex: 2,177modifiedCellIndex: 2, modifiedModel: createModifiedModel('InsertedModified:2'),178},179{180diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('2'), originalCellIndex: 3,181modifiedCellIndex: 3, modifiedModel: createModifiedModel('2'),182},183]);184});185});186187suite('Revert Inserted Cell', function () {188189const keep = () => Promise.resolve(true);190const undo = () => Promise.resolve(true);191const diff = observableValue('cell1', nullDocumentDiff);192const appliedEdits: ICellEditOperation[] = [];193setup(() => {194appliedEdits.length = 0;195});196ensureNoDisposablesAreLeakedInTestSuite();197function createModifiedModel(id: string): ObservablePromise<ITextModel> {198return `Modified:${id}` as any;199200}201function createOriginalModel(id: string): ObservablePromise<ITextModel> {202return `Original:${id}` as any;203204}205function applyEdits(edits: ICellEditOperation[]): boolean {206appliedEdits.push(...edits);207return true;208}209210test('Delete first inserted', async function () {211const cellsDiffInfo: ICellDiffInfo[] = [212{213diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,214modifiedCellIndex: 0, modifiedModel: createModifiedModel('New0'),215},216{217diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,218modifiedCellIndex: 1, modifiedModel: createModifiedModel('0'),219},220];221222const result = adjustCellDiffForRevertingAnInsertedCell(0,223cellsDiffInfo,224applyEdits);225226assert.deepStrictEqual(appliedEdits, [227{ editType: CellEditType.Replace, index: 0, cells: [], count: 1 },228]);229assert.deepStrictEqual(result, [230{231diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,232modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),233},234]);235});236test('Delete first inserted with multiple cells', async function () {237const cellsDiffInfo: ICellDiffInfo[] = [238{239diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,240modifiedCellIndex: 0, modifiedModel: createModifiedModel('New0'),241},242{243diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,244modifiedCellIndex: 1, modifiedModel: createModifiedModel('0'),245},246{247diff, keep, undo, type: 'delete', originalModel: createOriginalModel('1'), originalCellIndex: 1,248modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),249},250{251diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,252modifiedCellIndex: 2, modifiedModel: createModifiedModel('1'),253},254{255diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('2'), originalCellIndex: 2,256modifiedCellIndex: 3, modifiedModel: createModifiedModel('2'),257},258];259260const result = adjustCellDiffForRevertingAnInsertedCell(0,261cellsDiffInfo,262applyEdits);263264assert.deepStrictEqual(appliedEdits, [265{ editType: CellEditType.Replace, index: 0, cells: [], count: 1 },266]);267assert.deepStrictEqual(result, [268{269diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,270modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),271},272{273diff, keep, undo, type: 'delete', originalModel: createOriginalModel('1'), originalCellIndex: 1,274modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),275},276{277diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,278modifiedCellIndex: 1, modifiedModel: createModifiedModel('1'),279},280{281diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('2'), originalCellIndex: 2,282modifiedCellIndex: 2, modifiedModel: createModifiedModel('2'),283},284]);285});286test('Delete second inserted with multiple cells', async function () {287const cellsDiffInfo: ICellDiffInfo[] = [288{289diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,290modifiedCellIndex: 0, modifiedModel: createModifiedModel('New0'),291},292{293diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,294modifiedCellIndex: 1, modifiedModel: createModifiedModel('0'),295},296{297diff, keep, undo, type: 'delete', originalModel: createOriginalModel('1'), originalCellIndex: 1,298modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),299},300{301diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,302modifiedCellIndex: 2, modifiedModel: createModifiedModel('1'),303},304{305diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('2'), originalCellIndex: 2,306modifiedCellIndex: 3, modifiedModel: createModifiedModel('2'),307},308];309310const result = adjustCellDiffForRevertingAnInsertedCell(2,311cellsDiffInfo,312applyEdits);313314assert.deepStrictEqual(appliedEdits, [315{ editType: CellEditType.Replace, index: 2, cells: [], count: 1 },316]);317assert.deepStrictEqual(result, [318{319diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,320modifiedCellIndex: 0, modifiedModel: createModifiedModel('New0'),321},322{323diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,324modifiedCellIndex: 1, modifiedModel: createModifiedModel('0'),325},326{327diff, keep, undo, type: 'delete', originalModel: createOriginalModel('1'), originalCellIndex: 1,328modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),329},330{331diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('2'), originalCellIndex: 2,332modifiedCellIndex: 2, modifiedModel: createModifiedModel('2'),333},334]);335});336test('Delete second inserted with multiple cells (subsequent inserts)', async function () {337const cellsDiffInfo: ICellDiffInfo[] = [338{339diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,340modifiedCellIndex: 0, modifiedModel: createModifiedModel('New0'),341},342{343diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,344modifiedCellIndex: 1, modifiedModel: createModifiedModel('0'),345},346{347diff, keep, undo, type: 'delete', originalModel: createOriginalModel('1'), originalCellIndex: 1,348modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),349},350{351diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,352modifiedCellIndex: 2, modifiedModel: createModifiedModel('1'),353},354{355diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,356modifiedCellIndex: 3, modifiedModel: createModifiedModel('3'),357},358{359diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('2'), originalCellIndex: 2,360modifiedCellIndex: 4, modifiedModel: createModifiedModel('4'),361},362];363364const result = adjustCellDiffForRevertingAnInsertedCell(2,365cellsDiffInfo,366applyEdits);367368assert.deepStrictEqual(appliedEdits, [369{ editType: CellEditType.Replace, index: 2, cells: [], count: 1 },370]);371assert.deepStrictEqual(result, [372{373diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,374modifiedCellIndex: 0, modifiedModel: createModifiedModel('New0'),375},376{377diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,378modifiedCellIndex: 1, modifiedModel: createModifiedModel('0'),379},380{381diff, keep, undo, type: 'delete', originalModel: createOriginalModel('1'), originalCellIndex: 1,382modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),383},384{385diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,386modifiedCellIndex: 2, modifiedModel: createModifiedModel('3'),387},388{389diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('2'), originalCellIndex: 2,390modifiedCellIndex: 3, modifiedModel: createModifiedModel('4'),391},392]);393});394});395396suite('Keep Deleted Cell', function () {397398const keep = () => Promise.resolve(true);399const undo = () => Promise.resolve(true);400const diff = observableValue('cell1', nullDocumentDiff);401const appliedEdits: ICellEditOperation[] = [];402setup(() => {403appliedEdits.length = 0;404});405ensureNoDisposablesAreLeakedInTestSuite();406function createModifiedModel(id: string): ObservablePromise<ITextModel> {407return `Modified:${id}` as any;408409}410function createOriginalModel(id: string): ObservablePromise<ITextModel> {411return `Original:${id}` as any;412413}414function applyEdits(edits: ICellEditOperation[]): boolean {415appliedEdits.push(...edits);416return true;417}418419test('Keep first deleted cell', async function () {420const cellsDiffInfo: ICellDiffInfo[] = [421{422diff, keep, undo, type: 'delete', originalModel: createOriginalModel('0'), originalCellIndex: 0,423modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),424},425{426diff, keep, undo, type: 'delete', originalModel: createOriginalModel('1'), originalCellIndex: 1,427modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),428},429{430diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,431modifiedCellIndex: 0, modifiedModel: createModifiedModel('New0'),432},433{434diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('2'), originalCellIndex: 2,435modifiedCellIndex: 1, modifiedModel: createModifiedModel('0'),436},437];438439const result = adjustCellDiffForKeepingADeletedCell(0,440cellsDiffInfo,441applyEdits);442443assert.deepStrictEqual(appliedEdits, [444{ editType: CellEditType.Replace, index: 0, cells: [], count: 1 },445]);446assert.deepStrictEqual(result, [447{448diff, keep, undo, type: 'delete', originalModel: createOriginalModel('1'), originalCellIndex: 0,449modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),450},451{452diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,453modifiedCellIndex: 0, modifiedModel: createModifiedModel('New0'),454},455{456diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('2'), originalCellIndex: 1,457modifiedCellIndex: 1, modifiedModel: createModifiedModel('0'),458},459]);460});461test('Keep second deleted cell', async function () {462const cellsDiffInfo: ICellDiffInfo[] = [463{464diff, keep, undo, type: 'delete', originalModel: createOriginalModel('0'), originalCellIndex: 0,465modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),466},467{468diff, keep, undo, type: 'delete', originalModel: createOriginalModel('1'), originalCellIndex: 1,469modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),470},471{472diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,473modifiedCellIndex: 0, modifiedModel: createModifiedModel('New0'),474},475{476diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('2'), originalCellIndex: 2,477modifiedCellIndex: 1, modifiedModel: createModifiedModel('0'),478},479];480481const result = adjustCellDiffForKeepingADeletedCell(1,482cellsDiffInfo,483applyEdits);484485assert.deepStrictEqual(appliedEdits, [486{ editType: CellEditType.Replace, index: 1, cells: [], count: 1 },487]);488assert.deepStrictEqual(result, [489{490diff, keep, undo, type: 'delete', originalModel: createOriginalModel('0'), originalCellIndex: 0,491modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),492},493{494diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,495modifiedCellIndex: 0, modifiedModel: createModifiedModel('New0'),496},497{498diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('2'), originalCellIndex: 1,499modifiedCellIndex: 1, modifiedModel: createModifiedModel('0'),500},501]);502});503504test('Keep first deleted with multiple cells', async function () {505const cellsDiffInfo: ICellDiffInfo[] = [506{507diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,508modifiedCellIndex: 0, modifiedModel: createModifiedModel('New0'),509},510{511diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,512modifiedCellIndex: 1, modifiedModel: createModifiedModel('0'),513},514{515diff, keep, undo, type: 'delete', originalModel: createOriginalModel('1'), originalCellIndex: 1,516modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),517},518{519diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,520modifiedCellIndex: 2, modifiedModel: createModifiedModel('1'),521},522{523diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('2'), originalCellIndex: 2,524modifiedCellIndex: 3, modifiedModel: createModifiedModel('2'),525},526];527528const result = adjustCellDiffForKeepingADeletedCell(1,529cellsDiffInfo,530applyEdits);531532assert.deepStrictEqual(appliedEdits, [533{ editType: CellEditType.Replace, index: 1, cells: [], count: 1 },534]);535assert.deepStrictEqual(result, [536{537diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,538modifiedCellIndex: 0, modifiedModel: createModifiedModel('New0'),539},540{541diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,542modifiedCellIndex: 1, modifiedModel: createModifiedModel('0'),543},544{545diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,546modifiedCellIndex: 2, modifiedModel: createModifiedModel('1'),547},548{549diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('2'), originalCellIndex: 1,550modifiedCellIndex: 3, modifiedModel: createModifiedModel('2'),551},552]);553});554});555556suite('Revert Deleted Cell', function () {557558const keep = () => Promise.resolve(true);559const undo = () => Promise.resolve(true);560const diff = observableValue('cell1', nullDocumentDiff);561const appliedEdits: ICellEditOperation[] = [];562setup(() => {563appliedEdits.length = 0;564});565ensureNoDisposablesAreLeakedInTestSuite();566function createModifiedModel(id: string): ObservablePromise<ITextModel> {567return `Modified:${id}` as any;568569}570function createOriginalModel(id: string): ObservablePromise<ITextModel> {571return `Original:${id}` as any;572573}574function applyEdits(edits: ICellEditOperation[]): boolean {575appliedEdits.push(...edits);576return true;577}578function createModifiedCellDiffInfo(modifiedCellIndex: number, originalCellIndex: number): ICellDiffInfo {579return {580diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel(`InsertedOriginal:${originalCellIndex}`), originalCellIndex,581modifiedCellIndex, modifiedModel: createModifiedModel(`InsertedModified:${modifiedCellIndex}`),582};583}584585test('Revert first deleted cell', async function () {586const cellsDiffInfo: ICellDiffInfo[] = [587{588diff, keep, undo, type: 'delete', originalModel: createOriginalModel('0'), originalCellIndex: 0,589modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),590},591{592diff, keep, undo, type: 'delete', originalModel: createOriginalModel('1'), originalCellIndex: 1,593modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),594},595{596diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,597modifiedCellIndex: 0, modifiedModel: createModifiedModel('New0'),598},599{600diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('2'), originalCellIndex: 2,601modifiedCellIndex: 1, modifiedModel: createModifiedModel('0'),602},603];604605const result = adjustCellDiffForRevertingADeletedCell(0,606cellsDiffInfo,607{} as any,608applyEdits,609createModifiedCellDiffInfo);610611assert.deepStrictEqual(appliedEdits, [612{ editType: CellEditType.Replace, index: 0, cells: [{}], count: 0 },613]);614assert.deepStrictEqual(result, [615{616diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('InsertedOriginal:0'), originalCellIndex: 0,617modifiedCellIndex: 0, modifiedModel: createModifiedModel('InsertedModified:0'),618},619{620diff, keep, undo, type: 'delete', originalModel: createOriginalModel('1'), originalCellIndex: 1,621modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),622},623{624diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,625modifiedCellIndex: 1, modifiedModel: createModifiedModel('New0'),626},627{628diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('2'), originalCellIndex: 2,629modifiedCellIndex: 2, modifiedModel: createModifiedModel('0'),630},631]);632});633test('Revert second deleted cell', async function () {634const cellsDiffInfo: ICellDiffInfo[] = [635{636diff, keep, undo, type: 'delete', originalModel: createOriginalModel('0'), originalCellIndex: 0,637modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),638},639{640diff, keep, undo, type: 'delete', originalModel: createOriginalModel('1'), originalCellIndex: 1,641modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),642},643{644diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,645modifiedCellIndex: 0, modifiedModel: createModifiedModel('New0'),646},647{648diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('2'), originalCellIndex: 2,649modifiedCellIndex: 1, modifiedModel: createModifiedModel('0'),650},651];652653const result = adjustCellDiffForRevertingADeletedCell(1,654cellsDiffInfo,655{} as any,656applyEdits,657createModifiedCellDiffInfo);658659assert.deepStrictEqual(appliedEdits, [660{ editType: CellEditType.Replace, index: 0, cells: [{}], count: 0 },661]);662assert.deepStrictEqual(result, [663{664diff, keep, undo, type: 'delete', originalModel: createOriginalModel('0'), originalCellIndex: 0,665modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),666},667{668diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('InsertedOriginal:1'), originalCellIndex: 1,669modifiedCellIndex: 0, modifiedModel: createModifiedModel('InsertedModified:0'),670},671{672diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,673modifiedCellIndex: 1, modifiedModel: createModifiedModel('New0'),674},675{676diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('2'), originalCellIndex: 2,677modifiedCellIndex: 2, modifiedModel: createModifiedModel('0'),678},679]);680});681682test('Revert first deleted with multiple cells', async function () {683const cellsDiffInfo: ICellDiffInfo[] = [684{685diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,686modifiedCellIndex: 0, modifiedModel: createModifiedModel('New0'),687},688{689diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,690modifiedCellIndex: 1, modifiedModel: createModifiedModel('New1'),691},692{693diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,694modifiedCellIndex: 2, modifiedModel: createModifiedModel('0'),695},696{697diff, keep, undo, type: 'delete', originalModel: createOriginalModel('1'), originalCellIndex: 1,698modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),699},700{701diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,702modifiedCellIndex: 3, modifiedModel: createModifiedModel('1'),703},704{705diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('2'), originalCellIndex: 2,706modifiedCellIndex: 4, modifiedModel: createModifiedModel('2'),707},708];709710const result = adjustCellDiffForRevertingADeletedCell(1,711cellsDiffInfo,712{} as any,713applyEdits,714createModifiedCellDiffInfo);715716assert.deepStrictEqual(appliedEdits, [717{ editType: CellEditType.Replace, index: 3, cells: [{}], count: 0 },718]);719assert.deepStrictEqual(result, [720{721diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,722modifiedCellIndex: 0, modifiedModel: createModifiedModel('New0'),723},724{725diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,726modifiedCellIndex: 1, modifiedModel: createModifiedModel('New1'),727},728{729diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,730modifiedCellIndex: 2, modifiedModel: createModifiedModel('0'),731},732{733diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('InsertedOriginal:1'), originalCellIndex: 1,734modifiedCellIndex: 3, modifiedModel: createModifiedModel('InsertedModified:3'),735},736{737diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,738modifiedCellIndex: 4, modifiedModel: createModifiedModel('1'),739},740{741diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('2'), originalCellIndex: 2,742modifiedCellIndex: 5, modifiedModel: createModifiedModel('2'),743},744]);745});746});747748suite('Cell Addition', function () {749750const keep = () => Promise.resolve(true);751const undo = () => Promise.resolve(true);752const diff = observableValue('cell1', nullDocumentDiff);753const appliedEdits: ICellEditOperation[] = [];754setup(() => {755appliedEdits.length = 0;756});757ensureNoDisposablesAreLeakedInTestSuite();758function createModifiedModel(id: string): ObservablePromise<ITextModel> {759return `Modified:${id}` as any;760761}762function createOriginalModel(id: string): ObservablePromise<ITextModel> {763return `Original:${id}` as any;764765}766function applyEdits(edits: ICellEditOperation[]): boolean {767appliedEdits.push(...edits);768return true;769}770771function createICell(cellKind: CellKind, source: string): ICell {772const handle = hash(generateUuid());773return {774uri: URI.parse(`file:///path/${handle}`),775handle,776cellKind,777language: cellKind === CellKind.Markup ? 'markdown' : 'python',778outputs: [],779metadata: {},780getHashValue: () => {781return hash(`${handle}=>${cellKind}=>${source}`);782},783getValue: () => {784return source;785},786internalMetadata: {},787} as any;788}789function createModifiedCellDiffInfo(modifiedCellIndex: number, originalCellIndex: number): ICellDiffInfo {790return {791diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel(`InsertedOriginal:${originalCellIndex}`), originalCellIndex,792modifiedCellIndex, modifiedModel: createModifiedModel(`InsertedModified:${modifiedCellIndex}`),793};794}795test('Insert a new cell into an unchanged notebook', async function () {796const cellsDiffInfo: ICellDiffInfo[] = [797{798diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,799modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),800},801{802diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 1,803modifiedCellIndex: 1, modifiedModel: createModifiedModel('1'),804},805];806807const cell = createICell(CellKind.Code, 'print("Hello World")');808const result = adjustCellDiffAndOriginalModelBasedOnCellAddDelete([0, 0, [cell]],809cellsDiffInfo, 3, 2, applyEdits, createModifiedCellDiffInfo);810assert.deepStrictEqual(appliedEdits, [811{812editType: CellEditType.Replace,813index: 0,814cells: [{815cellKind: CellKind.Code,816language: 'python',817outputs: [],818mime: undefined,819metadata: {},820internalMetadata: {},821source: cell.getValue(),822}], count: 0823}824]);825assert.deepStrictEqual(result, [826{827diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel(`InsertedOriginal:0`), originalCellIndex: 0,828modifiedCellIndex: 0, modifiedModel: createModifiedModel(`InsertedModified:0`),829},830{831diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 1,832modifiedCellIndex: 1, modifiedModel: createModifiedModel('0'),833},834{835diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 2,836modifiedCellIndex: 2, modifiedModel: createModifiedModel('1'),837},838]);839});840test('Insert a new cell into a notebook with 3 cells deleted', async function () {841const cellsDiffInfo: ICellDiffInfo[] = [842{843diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,844modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),845},846{847diff, keep, undo, type: 'delete', originalModel: createOriginalModel('1'), originalCellIndex: 1,848modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),849},850{851diff, keep, undo, type: 'delete', originalModel: createOriginalModel('2'), originalCellIndex: 2,852modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),853},854{855diff, keep, undo, type: 'delete', originalModel: createOriginalModel('3'), originalCellIndex: 3,856modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),857},858{859diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,860modifiedCellIndex: 1, modifiedModel: createModifiedModel('New1'),861},862{863diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('4'), originalCellIndex: 4,864modifiedCellIndex: 2, modifiedModel: createModifiedModel('4'),865},866{867diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('5'), originalCellIndex: 5,868modifiedCellIndex: 3, modifiedModel: createModifiedModel('5'),869},870{871diff, keep, undo, type: 'modified', originalModel: createOriginalModel('6'), originalCellIndex: 6,872modifiedCellIndex: 4, modifiedModel: createModifiedModel('6'),873},874];875const cell = createICell(CellKind.Code, 'print("Hello World")');876const result = adjustCellDiffAndOriginalModelBasedOnCellAddDelete([2, 0, [cell]],877cellsDiffInfo, 6, 7, applyEdits, createModifiedCellDiffInfo);878879assert.deepStrictEqual(appliedEdits, [880{881editType: CellEditType.Replace,882index: 4,883cells: [{884cellKind: CellKind.Code,885language: 'python',886outputs: [],887mime: undefined,888metadata: {},889internalMetadata: {},890source: cell.getValue(),891}], count: 0892}893]);894895assert.deepStrictEqual(result, [896{897diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,898modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),899},900{901diff, keep, undo, type: 'delete', originalModel: createOriginalModel('1'), originalCellIndex: 1,902modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),903},904{905diff, keep, undo, type: 'delete', originalModel: createOriginalModel('2'), originalCellIndex: 2,906modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),907},908{909diff, keep, undo, type: 'delete', originalModel: createOriginalModel('3'), originalCellIndex: 3,910modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),911},912{913diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,914modifiedCellIndex: 1, modifiedModel: createModifiedModel('New1'),915},916{917diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('InsertedOriginal:4'), originalCellIndex: 4,918modifiedCellIndex: 2, modifiedModel: createModifiedModel('InsertedModified:2'),919},920{921diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('4'), originalCellIndex: 5,922modifiedCellIndex: 3, modifiedModel: createModifiedModel('4'),923},924{925diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('5'), originalCellIndex: 6,926modifiedCellIndex: 4, modifiedModel: createModifiedModel('5'),927},928{929diff, keep, undo, type: 'modified', originalModel: createOriginalModel('6'), originalCellIndex: 7,930modifiedCellIndex: 5, modifiedModel: createModifiedModel('6'),931},932]);933});934test('Insert 2 new cells into an notebook with 3 cells deleted', async function () {935const cellsDiffInfo: ICellDiffInfo[] = [936{937diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,938modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),939},940{941diff, keep, undo, type: 'delete', originalModel: createOriginalModel('2'), originalCellIndex: 1,942modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),943},944{945diff, keep, undo, type: 'delete', originalModel: createOriginalModel('3'), originalCellIndex: 2,946modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),947},948{949diff, keep, undo, type: 'delete', originalModel: createOriginalModel('4'), originalCellIndex: 3,950modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),951},952{953diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,954modifiedCellIndex: 1, modifiedModel: createModifiedModel('New1'),955},956{957diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('5'), originalCellIndex: 4,958modifiedCellIndex: 2, modifiedModel: createModifiedModel('5'),959},960{961diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 5,962modifiedCellIndex: 3, modifiedModel: createModifiedModel('1'),963},964];965const cell1 = createICell(CellKind.Code, 'print("Hello World")');966const cell2 = createICell(CellKind.Code, 'print("Foo Bar")');967const result = adjustCellDiffAndOriginalModelBasedOnCellAddDelete([2, 0, [cell1, cell2]],968cellsDiffInfo, 4, 6, applyEdits, createModifiedCellDiffInfo);969970assert.deepStrictEqual(appliedEdits, [971{972editType: CellEditType.Replace,973index: 4,974cells: [{975cellKind: CellKind.Code,976language: 'python',977outputs: [],978mime: undefined,979metadata: {},980internalMetadata: {},981source: cell1.getValue(),982}, {983cellKind: CellKind.Code,984language: 'python',985outputs: [],986mime: undefined,987metadata: {},988internalMetadata: {},989source: cell2.getValue(),990}], count: 0991}992]);993994assert.deepStrictEqual(result, [995{996diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,997modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),998},999{1000diff, keep, undo, type: 'delete', originalModel: createOriginalModel('2'), originalCellIndex: 1,1001modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1002},1003{1004diff, keep, undo, type: 'delete', originalModel: createOriginalModel('3'), originalCellIndex: 2,1005modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1006},1007{1008diff, keep, undo, type: 'delete', originalModel: createOriginalModel('4'), originalCellIndex: 3,1009modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1010},1011{1012diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1013modifiedCellIndex: 1, modifiedModel: createModifiedModel('New1'),1014},1015{1016diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel(`InsertedOriginal:4`), originalCellIndex: 4,1017modifiedCellIndex: 2, modifiedModel: createModifiedModel(`InsertedModified:2`),1018},1019{1020diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel(`InsertedOriginal:5`), originalCellIndex: 5,1021modifiedCellIndex: 3, modifiedModel: createModifiedModel(`InsertedModified:3`),1022},1023{1024diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('5'), originalCellIndex: 6,1025modifiedCellIndex: 4, modifiedModel: createModifiedModel('5'),1026},1027{1028diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 7,1029modifiedCellIndex: 5, modifiedModel: createModifiedModel('1'),1030},1031]);1032});1033test('Delete a cell from an unchanged notebook', async function () {1034const cellsDiffInfo: ICellDiffInfo[] = [1035{1036diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,1037modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),1038},1039{1040diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 1,1041modifiedCellIndex: 1, modifiedModel: createModifiedModel('1'),1042},1043];10441045const result = adjustCellDiffAndOriginalModelBasedOnCellAddDelete([0, 1, []],1046cellsDiffInfo, 2, 2, applyEdits, createModifiedCellDiffInfo);10471048assert.deepStrictEqual(appliedEdits, [1049{1050editType: CellEditType.Replace,1051index: 0,1052cells: [], count: 11053}1054]);10551056assert.deepStrictEqual(result, [1057{1058diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 0,1059modifiedCellIndex: 0, modifiedModel: createModifiedModel('1'),1060},1061]);1062});1063test('Delete last cell from an unchanged notebook', async function () {1064const cellsDiffInfo: ICellDiffInfo[] = [1065{1066diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,1067modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),1068},1069{1070diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 1,1071modifiedCellIndex: 1, modifiedModel: createModifiedModel('1'),1072},1073];10741075const result = adjustCellDiffAndOriginalModelBasedOnCellAddDelete([1, 1, []],1076cellsDiffInfo, 2, 2, applyEdits, createModifiedCellDiffInfo);1077assert.deepStrictEqual(appliedEdits, [1078{1079editType: CellEditType.Replace,1080index: 1,1081cells: [], count: 11082}1083]);10841085assert.deepStrictEqual(result, [1086{1087diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,1088modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),1089},1090]);1091});1092test('Delete the first cell, then insert a new cell at the top', async function () {1093const cellsDiffInfo: ICellDiffInfo[] = [1094{1095diff, keep, undo, type: 'delete', originalModel: createOriginalModel('0'), originalCellIndex: 0,1096modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1097},1098{1099diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 1,1100modifiedCellIndex: 0, modifiedModel: createModifiedModel('1'),1101},1102];11031104const cell1 = createICell(CellKind.Code, 'print("Hello World")');1105const result = adjustCellDiffAndOriginalModelBasedOnCellAddDelete([0, 0, [cell1]],1106cellsDiffInfo, 2, 2, applyEdits, createModifiedCellDiffInfo);11071108assert.deepStrictEqual(appliedEdits, [1109{1110editType: CellEditType.Replace,1111index: 1,1112cells: [{1113cellKind: CellKind.Code,1114language: 'python',1115outputs: [],1116mime: undefined,1117metadata: {},1118internalMetadata: {},1119source: cell1.getValue(),1120}], count: 01121}1122]);11231124assert.deepStrictEqual(result, [1125{1126diff, keep, undo, type: 'delete', originalModel: createOriginalModel('0'), originalCellIndex: 0,1127modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1128},1129{1130diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('InsertedOriginal:1'), originalCellIndex: 1,1131modifiedCellIndex: 0, modifiedModel: createModifiedModel('InsertedModified:0'),1132},1133{1134diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 2,1135modifiedCellIndex: 1, modifiedModel: createModifiedModel('1'),1136},1137]);1138});1139test('Delete a new cell from a notebook with 3 cells deleted', async function () {1140const cellsDiffInfo: ICellDiffInfo[] = [1141{1142diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,1143modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),1144},1145{1146diff, keep, undo, type: 'delete', originalModel: createOriginalModel('2'), originalCellIndex: 1,1147modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1148},1149{1150diff, keep, undo, type: 'delete', originalModel: createOriginalModel('3'), originalCellIndex: 2,1151modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1152},1153{1154diff, keep, undo, type: 'delete', originalModel: createOriginalModel('4'), originalCellIndex: 3,1155modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1156},1157{1158diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1159modifiedCellIndex: 1, modifiedModel: createModifiedModel('New1'),1160},1161{1162diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('5'), originalCellIndex: 4,1163modifiedCellIndex: 2, modifiedModel: createModifiedModel('5'),1164},1165{1166diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 5,1167modifiedCellIndex: 3, modifiedModel: createModifiedModel('1'),1168},1169];11701171const result = adjustCellDiffAndOriginalModelBasedOnCellAddDelete([1, 1, [1172// createICell(CellKind.Code, 'print("Hello World")')1173]],1174cellsDiffInfo, 4, 6, applyEdits, createModifiedCellDiffInfo);11751176assert.deepStrictEqual(appliedEdits, [1177]);11781179assert.deepStrictEqual(result, [1180{1181diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,1182modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),1183},1184{1185diff, keep, undo, type: 'delete', originalModel: createOriginalModel('2'), originalCellIndex: 1,1186modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1187},1188{1189diff, keep, undo, type: 'delete', originalModel: createOriginalModel('3'), originalCellIndex: 2,1190modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1191},1192{1193diff, keep, undo, type: 'delete', originalModel: createOriginalModel('4'), originalCellIndex: 3,1194modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1195},1196{1197diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('5'), originalCellIndex: 4,1198modifiedCellIndex: 1, modifiedModel: createModifiedModel('5'),1199},1200{1201diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 5,1202modifiedCellIndex: 2, modifiedModel: createModifiedModel('1'),1203},1204]);1205});1206test('Delete 2 cells from a notebook with 3 cells deleted', async function () {1207const cellsDiffInfo: ICellDiffInfo[] = [1208{1209diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,1210modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),1211},1212{1213diff, keep, undo, type: 'delete', originalModel: createOriginalModel('2'), originalCellIndex: 1,1214modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1215},1216{1217diff, keep, undo, type: 'delete', originalModel: createOriginalModel('3'), originalCellIndex: 2,1218modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1219},1220{1221diff, keep, undo, type: 'delete', originalModel: createOriginalModel('4'), originalCellIndex: 3,1222modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1223},1224{1225diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1226modifiedCellIndex: 1, modifiedModel: createModifiedModel('New1'),1227},1228{1229diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('5'), originalCellIndex: 4,1230modifiedCellIndex: 2, modifiedModel: createModifiedModel('5'),1231},1232{1233diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 5,1234modifiedCellIndex: 3, modifiedModel: createModifiedModel('1'),1235},1236];12371238const result = adjustCellDiffAndOriginalModelBasedOnCellAddDelete([1, 2, [1239]],1240cellsDiffInfo, 4, 6, applyEdits, createModifiedCellDiffInfo);12411242assert.deepStrictEqual(appliedEdits, [1243{1244editType: CellEditType.Replace,1245index: 4,1246cells: [], count: 11247}1248]);12491250assert.deepStrictEqual(result, [1251{1252diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,1253modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),1254},1255{1256diff, keep, undo, type: 'delete', originalModel: createOriginalModel('2'), originalCellIndex: 1,1257modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1258},1259{1260diff, keep, undo, type: 'delete', originalModel: createOriginalModel('3'), originalCellIndex: 2,1261modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1262},1263{1264diff, keep, undo, type: 'delete', originalModel: createOriginalModel('4'), originalCellIndex: 3,1265modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1266},1267{1268diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 4,1269modifiedCellIndex: 1, modifiedModel: createModifiedModel('1'),1270},1271]);1272});1273test('Delete 3 cells from a notebook with 3 cells deleted', async function () {1274const cellsDiffInfo: ICellDiffInfo[] = [1275{1276diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,1277modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),1278},1279{1280diff, keep, undo, type: 'modified', originalModel: createOriginalModel('1'), originalCellIndex: 1,1281modifiedCellIndex: 1, modifiedModel: createModifiedModel('1'),1282},1283{1284diff, keep, undo, type: 'delete', originalModel: createOriginalModel('2'), originalCellIndex: 2,1285modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1286},1287{1288diff, keep, undo, type: 'delete', originalModel: createOriginalModel('3'), originalCellIndex: 3,1289modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1290},1291{1292diff, keep, undo, type: 'delete', originalModel: createOriginalModel('4'), originalCellIndex: 4,1293modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1294},1295{1296diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1297modifiedCellIndex: 2, modifiedModel: createModifiedModel('New1'),1298},1299{1300diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('5'), originalCellIndex: 5,1301modifiedCellIndex: 3, modifiedModel: createModifiedModel('5'),1302},1303{1304diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('6'), originalCellIndex: 6,1305modifiedCellIndex: 4, modifiedModel: createModifiedModel('6'),1306},1307];13081309const result = adjustCellDiffAndOriginalModelBasedOnCellAddDelete([1, 3, [1310]],1311cellsDiffInfo, 5, 7, applyEdits, createModifiedCellDiffInfo);13121313assert.deepStrictEqual(appliedEdits, [1314{1315editType: CellEditType.Replace,1316index: 1,1317cells: [], count: 11318},1319{1320editType: CellEditType.Replace,1321index: 5,1322cells: [], count: 11323}1324]);13251326assert.deepStrictEqual(result, [1327{1328diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,1329modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),1330},1331{1332diff, keep, undo, type: 'delete', originalModel: createOriginalModel('2'), originalCellIndex: 1,1333modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1334},1335{1336diff, keep, undo, type: 'delete', originalModel: createOriginalModel('3'), originalCellIndex: 2,1337modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1338},1339{1340diff, keep, undo, type: 'delete', originalModel: createOriginalModel('4'), originalCellIndex: 3,1341modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1342},1343{1344diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('6'), originalCellIndex: 4,1345modifiedCellIndex: 1, modifiedModel: createModifiedModel('6'),1346},1347]);1348});13491350test('Insert 1 cell at the bottom via chat, then user creats a new cell just below that', async function () {1351const cellsDiffInfo: ICellDiffInfo[] = [1352{1353diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,1354modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),1355},1356{1357diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1358modifiedCellIndex: 1, modifiedModel: createModifiedModel('New1'),1359},1360];1361const cell1 = createICell(CellKind.Code, 'print("Hello World")');1362const result = adjustCellDiffAndOriginalModelBasedOnCellAddDelete([2, 0, [cell1]],1363cellsDiffInfo, 3, 1, applyEdits, createModifiedCellDiffInfo);13641365assert.deepStrictEqual(appliedEdits, [1366{1367editType: CellEditType.Replace,1368index: 1,1369cells: [{1370cellKind: CellKind.Code,1371language: 'python',1372outputs: [],1373mime: undefined,1374metadata: {},1375internalMetadata: {},1376source: cell1.getValue(),1377}], count: 01378}1379]);13801381assert.deepStrictEqual(result, [1382{1383diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,1384modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),1385},1386{1387diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1388modifiedCellIndex: 1, modifiedModel: createModifiedModel('New1'),1389},1390{1391diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('InsertedOriginal:1'), originalCellIndex: 1,1392modifiedCellIndex: 2, modifiedModel: createModifiedModel('InsertedModified:2'),1393},1394]);1395});1396test('Insert 1 cell at the bottom via chat, then user creats anew cells above the previous new cell', async function () {1397const cellsDiffInfo: ICellDiffInfo[] = [1398{1399diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,1400modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),1401},1402{1403diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 1,1404modifiedCellIndex: 1, modifiedModel: createModifiedModel('1'),1405},1406{1407diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1408modifiedCellIndex: 2, modifiedModel: createModifiedModel('New1'),1409},1410];1411const cell1 = createICell(CellKind.Code, 'print("Hello World")');1412const result = adjustCellDiffAndOriginalModelBasedOnCellAddDelete([2, 0, [cell1]],1413cellsDiffInfo, 3, 2, applyEdits, createModifiedCellDiffInfo);14141415assert.deepStrictEqual(appliedEdits, [1416{1417editType: CellEditType.Replace,1418index: 2,1419cells: [{1420cellKind: CellKind.Code,1421language: 'python',1422outputs: [],1423mime: undefined,1424metadata: {},1425internalMetadata: {},1426source: cell1.getValue(),1427}], count: 01428}1429]);14301431assert.deepStrictEqual(result, [1432{1433diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,1434modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),1435},1436{1437diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 1,1438modifiedCellIndex: 1, modifiedModel: createModifiedModel('1'),1439},1440{1441diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('InsertedOriginal:2'), originalCellIndex: 2,1442modifiedCellIndex: 2, modifiedModel: createModifiedModel('InsertedModified:2'),1443},1444{1445diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1446modifiedCellIndex: 3, modifiedModel: createModifiedModel('New1'),1447},1448]);1449});1450test('Insert 1 cell at the bottom via chat, then user inserts a new cells below the previous new cell', async function () {1451const cellsDiffInfo: ICellDiffInfo[] = [1452{1453diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,1454modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),1455},1456{1457diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 1,1458modifiedCellIndex: 1, modifiedModel: createModifiedModel('1'),1459},1460{1461diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1462modifiedCellIndex: 2, modifiedModel: createModifiedModel('New1'),1463},1464];1465const cell1 = createICell(CellKind.Code, 'print("Hello World")');1466const result = adjustCellDiffAndOriginalModelBasedOnCellAddDelete([3, 0, [cell1]],1467cellsDiffInfo, 3, 2, applyEdits, createModifiedCellDiffInfo);14681469assert.deepStrictEqual(appliedEdits, [1470{1471editType: CellEditType.Replace,1472index: 2,1473cells: [{1474cellKind: CellKind.Code,1475language: 'python',1476outputs: [],1477mime: undefined,1478metadata: {},1479internalMetadata: {},1480source: cell1.getValue(),1481}], count: 01482}1483]);14841485assert.deepStrictEqual(result, [1486{1487diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,1488modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),1489},1490{1491diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 1,1492modifiedCellIndex: 1, modifiedModel: createModifiedModel('1'),1493},1494{1495diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1496modifiedCellIndex: 2, modifiedModel: createModifiedModel('New1'),1497},1498{1499diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('InsertedOriginal:2'), originalCellIndex: 2,1500modifiedCellIndex: 3, modifiedModel: createModifiedModel('InsertedModified:3'),1501},1502]);1503});1504});15051506suite('Cell Movements', function () {15071508const keep = () => Promise.resolve(true);1509const undo = () => Promise.resolve(true);1510const diff = observableValue('cell1', nullDocumentDiff);15111512ensureNoDisposablesAreLeakedInTestSuite();1513function createModifiedModel(id: string): ObservablePromise<ITextModel> {1514return `Modified:${id}` as any;15151516}1517function createOriginalModel(id: string): ObservablePromise<ITextModel> {1518return `Original:${id}` as any;15191520}1521test('Swap first two inserted cells in a previously empty notebook', async function () {1522const cellsDiffInfo: ICellDiffInfo[] = [1523{1524diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1525modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),1526},1527{1528diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1529modifiedCellIndex: 1, modifiedModel: createModifiedModel('1'),1530}1531];1532const result = adjustCellDiffAndOriginalModelBasedOnCellMovements({1533cells: [], kind: NotebookCellsChangeType.Move,1534index: 0, length: 1, newIdx: 11535}, cellsDiffInfo);15361537assert.ok(result);1538assert.strictEqual(result[1].length, 0);1539assert.deepStrictEqual(result[0], [1540{1541diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1542modifiedCellIndex: 0, modifiedModel: createModifiedModel('1'),1543},1544{1545diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1546modifiedCellIndex: 1, modifiedModel: createModifiedModel('0'),1547},1548]);1549});1550test('Swap first two inserted cells in a notebook that had 2 cells', async function () {1551const cellsDiffInfo: ICellDiffInfo[] = [1552{1553diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1554modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),1555},1556{1557diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1558modifiedCellIndex: 1, modifiedModel: createModifiedModel('1'),1559},1560{1561diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,1562modifiedCellIndex: 2, modifiedModel: createModifiedModel('2'),1563},1564{1565diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 1,1566modifiedCellIndex: 3, modifiedModel: createModifiedModel('3'),1567}1568];1569const result = adjustCellDiffAndOriginalModelBasedOnCellMovements({1570cells: [], kind: NotebookCellsChangeType.Move,1571index: 0, length: 1, newIdx: 11572}, cellsDiffInfo);15731574assert.ok(result);1575assert.strictEqual(result[1].length, 0);1576assert.deepStrictEqual(result[0], [1577{1578diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1579modifiedCellIndex: 0, modifiedModel: createModifiedModel('1'),1580},1581{1582diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1583modifiedCellIndex: 1, modifiedModel: createModifiedModel('0'),1584},1585{1586diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,1587modifiedCellIndex: 2, modifiedModel: createModifiedModel('2'),1588},1589{1590diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 1,1591modifiedCellIndex: 3, modifiedModel: createModifiedModel('3'),1592}1593]);1594});1595test('Move first inserted cell to the very bottom of notebook that had 2 cells', async function () {1596const cellsDiffInfo: ICellDiffInfo[] = [1597{1598diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1599modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),1600},1601{1602diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1603modifiedCellIndex: 1, modifiedModel: createModifiedModel('1'),1604},1605{1606diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,1607modifiedCellIndex: 2, modifiedModel: createModifiedModel('2'),1608},1609{1610diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 1,1611modifiedCellIndex: 3, modifiedModel: createModifiedModel('3'),1612}1613];1614const result = adjustCellDiffAndOriginalModelBasedOnCellMovements({1615cells: [], kind: NotebookCellsChangeType.Move,1616index: 0, length: 1, newIdx: 31617}, cellsDiffInfo);16181619assert.ok(result);1620assert.strictEqual(result[1].length, 0);1621assert.deepStrictEqual(result[0], [1622{1623diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1624modifiedCellIndex: 0, modifiedModel: createModifiedModel('1'),1625},1626{1627diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,1628modifiedCellIndex: 1, modifiedModel: createModifiedModel('2'),1629},1630{1631diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 1,1632modifiedCellIndex: 2, modifiedModel: createModifiedModel('3'),1633},1634{1635diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1636modifiedCellIndex: 3, modifiedModel: createModifiedModel('0'),1637},1638]);1639});1640test('Move last cell to top of notebook after 2 cells were inserted', async function () {1641const cellsDiffInfo: ICellDiffInfo[] = [1642{1643diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1644modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),1645},1646{1647diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1648modifiedCellIndex: 1, modifiedModel: createModifiedModel('1'),1649},1650{1651diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,1652modifiedCellIndex: 2, modifiedModel: createModifiedModel('2'),1653},1654{1655diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 1,1656modifiedCellIndex: 3, modifiedModel: createModifiedModel('3'),1657}1658];1659const result = adjustCellDiffAndOriginalModelBasedOnCellMovements({1660cells: [], kind: NotebookCellsChangeType.Move,1661index: 3, length: 1, newIdx: 01662}, cellsDiffInfo);16631664assert.ok(result);1665assert.deepStrictEqual(result[1], [1666{1667editType: CellEditType.Move,1668index: 1,1669length: 1,1670newIdx: 01671}1672]);1673assert.deepStrictEqual(result[0], [1674{1675diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 0,1676modifiedCellIndex: 0, modifiedModel: createModifiedModel('3'),1677},1678{1679diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1680modifiedCellIndex: 1, modifiedModel: createModifiedModel('0'),1681},1682{1683diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1684modifiedCellIndex: 2, modifiedModel: createModifiedModel('1'),1685},1686{1687diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 1,1688modifiedCellIndex: 3, modifiedModel: createModifiedModel('2'),1689},1690]);1691});16921693test('Move second inserted cell to the very bottom of notebook that had 2 cells', async function () {1694const cellsDiffInfo: ICellDiffInfo[] = [1695{1696diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1697modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),1698},1699{1700diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1701modifiedCellIndex: 1, modifiedModel: createModifiedModel('1'),1702},1703{1704diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,1705modifiedCellIndex: 2, modifiedModel: createModifiedModel('2'),1706},1707{1708diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 1,1709modifiedCellIndex: 3, modifiedModel: createModifiedModel('3'),1710}1711];1712const result = adjustCellDiffAndOriginalModelBasedOnCellMovements({1713cells: [], kind: NotebookCellsChangeType.Move,1714index: 1, length: 1, newIdx: 31715}, cellsDiffInfo);17161717assert.ok(result);1718assert.strictEqual(result[1].length, 0);1719assert.deepStrictEqual(result[0], [1720{1721diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1722modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),1723},1724{1725diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,1726modifiedCellIndex: 1, modifiedModel: createModifiedModel('2'),1727},1728{1729diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 1,1730modifiedCellIndex: 2, modifiedModel: createModifiedModel('3'),1731},1732{1733diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1734modifiedCellIndex: 3, modifiedModel: createModifiedModel('1'),1735},1736]);1737});1738test('Move second inserted cell to the second last position of notebook that had 2 cells', async function () {1739const cellsDiffInfo: ICellDiffInfo[] = [1740{1741diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1742modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),1743},1744{1745diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1746modifiedCellIndex: 1, modifiedModel: createModifiedModel('1'),1747},1748{1749diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,1750modifiedCellIndex: 2, modifiedModel: createModifiedModel('2'),1751},1752{1753diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 1,1754modifiedCellIndex: 3, modifiedModel: createModifiedModel('3'),1755}1756];1757const result = adjustCellDiffAndOriginalModelBasedOnCellMovements({1758cells: [], kind: NotebookCellsChangeType.Move,1759index: 1, length: 1, newIdx: 21760}, cellsDiffInfo);17611762assert.ok(result);1763assert.strictEqual(result[1].length, 0);1764assert.deepStrictEqual(result[0], [1765{1766diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1767modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),1768},1769{1770diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,1771modifiedCellIndex: 1, modifiedModel: createModifiedModel('2'),1772},1773{1774diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1775modifiedCellIndex: 2, modifiedModel: createModifiedModel('1'),1776},1777{1778diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 1,1779modifiedCellIndex: 3, modifiedModel: createModifiedModel('3'),1780}1781]);1782});1783test('Move first cell to the last position of notebook that had 3 cells deleted from the middle', async function () {1784const cellsDiffInfo: ICellDiffInfo[] = [1785{1786diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,1787modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),1788},1789{1790diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 1,1791modifiedCellIndex: 1, modifiedModel: createModifiedModel('1'),1792},1793{1794diff, keep, undo, type: 'delete', originalModel: createOriginalModel('2'), originalCellIndex: 2,1795modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1796},1797{1798diff, keep, undo, type: 'delete', originalModel: createOriginalModel('3'), originalCellIndex: 3,1799modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1800},1801{1802diff, keep, undo, type: 'delete', originalModel: createOriginalModel('4'), originalCellIndex: 4,1803modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1804},1805{1806diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('5'), originalCellIndex: 5,1807modifiedCellIndex: 2, modifiedModel: createModifiedModel('2'),1808},1809];1810const result = adjustCellDiffAndOriginalModelBasedOnCellMovements({1811cells: [], kind: NotebookCellsChangeType.Move,1812index: 0, length: 1, newIdx: 21813}, cellsDiffInfo);18141815assert.ok(result);1816assert.deepStrictEqual(result[1], [1817{1818editType: CellEditType.Move,1819index: 0,1820length: 1,1821newIdx: 51822}1823]);1824assert.deepStrictEqual(result[0], [1825{1826diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 0,1827modifiedCellIndex: 0, modifiedModel: createModifiedModel('1'),1828},1829{1830diff, keep, undo, type: 'delete', originalModel: createOriginalModel('2'), originalCellIndex: 1,1831modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1832},1833{1834diff, keep, undo, type: 'delete', originalModel: createOriginalModel('3'), originalCellIndex: 2,1835modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1836},1837{1838diff, keep, undo, type: 'delete', originalModel: createOriginalModel('4'), originalCellIndex: 3,1839modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1840},1841{1842diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('5'), originalCellIndex: 4,1843modifiedCellIndex: 1, modifiedModel: createModifiedModel('2'),1844},1845{1846diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 5,1847modifiedCellIndex: 2, modifiedModel: createModifiedModel('0'),1848},1849]);1850});1851test('Move second cell to the last position of notebook that had 3 cells deleted from the middle', async function () {1852const cellsDiffInfo: ICellDiffInfo[] = [1853{1854diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,1855modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),1856},1857{1858diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 1,1859modifiedCellIndex: 1, modifiedModel: createModifiedModel('1'),1860},1861{1862diff, keep, undo, type: 'delete', originalModel: createOriginalModel('2'), originalCellIndex: 2,1863modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1864},1865{1866diff, keep, undo, type: 'delete', originalModel: createOriginalModel('3'), originalCellIndex: 3,1867modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1868},1869{1870diff, keep, undo, type: 'delete', originalModel: createOriginalModel('4'), originalCellIndex: 4,1871modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1872},1873{1874diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('5'), originalCellIndex: 5,1875modifiedCellIndex: 2, modifiedModel: createModifiedModel('2'),1876},1877];1878const result = adjustCellDiffAndOriginalModelBasedOnCellMovements({1879cells: [], kind: NotebookCellsChangeType.Move,1880index: 1, length: 1, newIdx: 21881}, cellsDiffInfo);18821883assert.ok(result);1884assert.deepStrictEqual(result[1], [1885{1886editType: CellEditType.Move,1887index: 1,1888length: 1,1889newIdx: 51890}1891]);1892assert.deepStrictEqual(result[0], [1893{1894diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,1895modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),1896},1897{1898diff, keep, undo, type: 'delete', originalModel: createOriginalModel('2'), originalCellIndex: 1,1899modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1900},1901{1902diff, keep, undo, type: 'delete', originalModel: createOriginalModel('3'), originalCellIndex: 2,1903modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1904},1905{1906diff, keep, undo, type: 'delete', originalModel: createOriginalModel('4'), originalCellIndex: 3,1907modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1908},1909{1910diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('5'), originalCellIndex: 4,1911modifiedCellIndex: 1, modifiedModel: createModifiedModel('2'),1912},1913{1914diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 5,1915modifiedCellIndex: 2, modifiedModel: createModifiedModel('1'),1916},1917]);1918});19191920test('Move second cell to the last position of notebook that had 3 cells deleted from middle and 1 inserted in the middle', async function () {1921const cellsDiffInfo: ICellDiffInfo[] = [1922{1923diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,1924modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),1925},1926{1927diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 1,1928modifiedCellIndex: 1, modifiedModel: createModifiedModel('1'),1929},1930{1931diff, keep, undo, type: 'delete', originalModel: createOriginalModel('2'), originalCellIndex: 2,1932modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1933},1934{1935diff, keep, undo, type: 'delete', originalModel: createOriginalModel('3'), originalCellIndex: 3,1936modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1937},1938{1939diff, keep, undo, type: 'delete', originalModel: createOriginalModel('4'), originalCellIndex: 4,1940modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1941},1942{1943diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1944modifiedCellIndex: 2, modifiedModel: createModifiedModel('New1'),1945},1946{1947diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('5'), originalCellIndex: 5,1948modifiedCellIndex: 3, modifiedModel: createModifiedModel('5'),1949},1950];1951const result = adjustCellDiffAndOriginalModelBasedOnCellMovements({1952cells: [], kind: NotebookCellsChangeType.Move,1953index: 1, length: 1, newIdx: 31954}, cellsDiffInfo);19551956assert.ok(result);1957assert.deepStrictEqual(result[1], [1958{1959editType: CellEditType.Move,1960index: 1,1961length: 1,1962newIdx: 51963}1964]);1965assert.deepStrictEqual(result[0], [1966{1967diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,1968modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),1969},1970{1971diff, keep, undo, type: 'delete', originalModel: createOriginalModel('2'), originalCellIndex: 1,1972modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1973},1974{1975diff, keep, undo, type: 'delete', originalModel: createOriginalModel('3'), originalCellIndex: 2,1976modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1977},1978{1979diff, keep, undo, type: 'delete', originalModel: createOriginalModel('4'), originalCellIndex: 3,1980modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),1981},1982{1983diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,1984modifiedCellIndex: 1, modifiedModel: createModifiedModel('New1'),1985},1986{1987diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('5'), originalCellIndex: 4,1988modifiedCellIndex: 2, modifiedModel: createModifiedModel('5'),1989},1990{1991diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 5,1992modifiedCellIndex: 3, modifiedModel: createModifiedModel('1'),1993},1994]);1995});1996test('Move last cell to the second position of notebook that had 3 cells deleted from middle and 1 inserted in the middle', async function () {1997const cellsDiffInfo: ICellDiffInfo[] = [1998{1999diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,2000modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),2001},2002{2003diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 1,2004modifiedCellIndex: 1, modifiedModel: createModifiedModel('1'),2005},2006{2007diff, keep, undo, type: 'delete', originalModel: createOriginalModel('2'), originalCellIndex: 2,2008modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),2009},2010{2011diff, keep, undo, type: 'delete', originalModel: createOriginalModel('3'), originalCellIndex: 3,2012modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),2013},2014{2015diff, keep, undo, type: 'delete', originalModel: createOriginalModel('4'), originalCellIndex: 4,2016modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),2017},2018{2019diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,2020modifiedCellIndex: 2, modifiedModel: createModifiedModel('New1'),2021},2022{2023diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('5'), originalCellIndex: 5,2024modifiedCellIndex: 3, modifiedModel: createModifiedModel('5'),2025},2026];2027const result = adjustCellDiffAndOriginalModelBasedOnCellMovements({2028cells: [], kind: NotebookCellsChangeType.Move,2029index: 3, length: 1, newIdx: 12030}, cellsDiffInfo);20312032assert.ok(result);2033assert.deepStrictEqual(result[1], [2034{2035editType: CellEditType.Move,2036index: 5,2037length: 1,2038newIdx: 12039}2040]);2041assert.deepStrictEqual(result[0], [2042{2043diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('0'), originalCellIndex: 0,2044modifiedCellIndex: 0, modifiedModel: createModifiedModel('0'),2045},2046{2047diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('5'), originalCellIndex: 1,2048modifiedCellIndex: 1, modifiedModel: createModifiedModel('5'),2049},2050{2051diff, keep, undo, type: 'unchanged', originalModel: createOriginalModel('1'), originalCellIndex: 2,2052modifiedCellIndex: 2, modifiedModel: createModifiedModel('1'),2053},2054{2055diff, keep, undo, type: 'delete', originalModel: createOriginalModel('2'), originalCellIndex: 3,2056modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),2057},2058{2059diff, keep, undo, type: 'delete', originalModel: createOriginalModel('3'), originalCellIndex: 4,2060modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),2061},2062{2063diff, keep, undo, type: 'delete', originalModel: createOriginalModel('4'), originalCellIndex: 5,2064modifiedCellIndex: undefined, modifiedModel: createModifiedModel('null'),2065},2066{2067diff, keep, undo, type: 'insert', originalModel: createOriginalModel('null'), originalCellIndex: undefined,2068modifiedCellIndex: 3, modifiedModel: createModifiedModel('New1'),2069},2070]);2071});2072});20732074});207520762077