focalboard/webapp/src/undoManager.test.ts
Miguel de la Cruz d22fe7fbc0
Modify undo manager to return a value and use it on undo (#1616)
* Modify undo manager to return a value and use it on undo

* Storing the last redo value internally to correctly run undo

* Fix types

* Improve test ensuring redo didn't add original block

Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
2021-10-21 18:50:19 +02:00

179 lines
5.5 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import undoManager from './undomanager'
test('Basic undo/redo', async () => {
expect(undoManager.canUndo).toBe(false)
expect(undoManager.canRedo).toBe(false)
expect(undoManager.currentCheckpoint).toBe(0)
const values: string[] = []
await undoManager.perform(
async () => {
values.push('a')
},
async () => {
values.pop()
},
'test',
)
expect(undoManager.canUndo).toBe(true)
expect(undoManager.canRedo).toBe(false)
expect(undoManager.currentCheckpoint).toBeGreaterThan(0)
expect(values).toEqual(['a'])
expect(undoManager.undoDescription).toBe('test')
expect(undoManager.redoDescription).toBe(undefined)
await undoManager.undo()
expect(undoManager.canUndo).toBe(false)
expect(undoManager.canRedo).toBe(true)
expect(values).toEqual([])
expect(undoManager.undoDescription).toBe(undefined)
expect(undoManager.redoDescription).toBe('test')
await undoManager.redo()
expect(undoManager.canUndo).toBe(true)
expect(undoManager.canRedo).toBe(false)
expect(values).toEqual(['a'])
await undoManager.clear()
expect(undoManager.canUndo).toBe(false)
expect(undoManager.canRedo).toBe(false)
expect(undoManager.currentCheckpoint).toBe(0)
expect(undoManager.undoDescription).toBe(undefined)
expect(undoManager.redoDescription).toBe(undefined)
})
test('Basic undo/redo response dependant', async () => {
expect(undoManager.canUndo).toBe(false)
expect(undoManager.canRedo).toBe(false)
expect(undoManager.currentCheckpoint).toBe(0)
const blockIds = [2, 1]
const blocks: Record<string, any> = {}
const newBlock = await undoManager.perform(
async () => {
const responseId = blockIds.pop() // every time we run the action a new ID is obtained
const block: Record<string, any> = {id: responseId, title: 'Sample'}
blocks[block.id] = block
return block
},
async (block: Record<string, any>) => {
delete blocks[block.id]
},
'test',
)
// should insert the block and return the new block for its use
expect(undoManager.canUndo).toBe(true)
expect(undoManager.canRedo).toBe(false)
expect(blocks).toHaveProperty('1')
expect(blocks[1]).toEqual(newBlock)
// should correctly remove the block based on the info gathered in
// the redo function
await undoManager.undo()
expect(undoManager.canUndo).toBe(false)
expect(undoManager.canRedo).toBe(true)
expect(blocks).not.toHaveProperty('1')
// when redoing, as the function has side effects the new id will
// be different
await undoManager.redo()
expect(undoManager.canUndo).toBe(true)
expect(undoManager.canRedo).toBe(false)
expect(blocks).not.toHaveProperty('1')
expect(blocks).toHaveProperty('2')
expect(blocks[2].id).toEqual(2)
// when undoing, the undo manager has saved the new id internally
// and it removes the right block
await undoManager.undo()
expect(undoManager.canUndo).toBe(false)
expect(undoManager.canRedo).toBe(true)
expect(blocks).not.toHaveProperty('2')
await undoManager.clear()
})
test('Grouped undo/redo', async () => {
expect(undoManager.canUndo).toBe(false)
expect(undoManager.canRedo).toBe(false)
const values: string[] = []
const groupId = 'the group id'
await undoManager.perform(
async () => {
values.push('a')
},
async () => {
values.pop()
},
'insert a',
)
expect(undoManager.canUndo).toBe(true)
expect(undoManager.canRedo).toBe(false)
expect(values).toEqual(['a'])
expect(undoManager.undoDescription).toBe('insert a')
expect(undoManager.redoDescription).toBe(undefined)
await undoManager.perform(
async () => {
values.push('b')
},
async () => {
values.pop()
},
'insert b',
groupId,
)
expect(undoManager.canUndo).toBe(true)
expect(undoManager.canRedo).toBe(false)
expect(values).toEqual(['a', 'b'])
expect(undoManager.undoDescription).toBe('insert b')
expect(undoManager.redoDescription).toBe(undefined)
await undoManager.perform(
async () => {
values.push('c')
},
async () => {
values.pop()
},
'insert c',
groupId,
)
expect(undoManager.canUndo).toBe(true)
expect(undoManager.canRedo).toBe(false)
expect(values).toEqual(['a', 'b', 'c'])
expect(undoManager.undoDescription).toBe('insert c')
expect(undoManager.redoDescription).toBe(undefined)
await undoManager.undo()
expect(undoManager.canUndo).toBe(true)
expect(undoManager.canRedo).toBe(true)
expect(values).toEqual(['a'])
expect(undoManager.undoDescription).toBe('insert a')
expect(undoManager.redoDescription).toBe('insert b')
await undoManager.redo()
expect(undoManager.canUndo).toBe(true)
expect(undoManager.canRedo).toBe(false)
expect(values).toEqual(['a', 'b', 'c'])
expect(undoManager.undoDescription).toBe('insert c')
expect(undoManager.redoDescription).toBe(undefined)
await undoManager.clear()
expect(undoManager.canUndo).toBe(false)
expect(undoManager.canRedo).toBe(false)
expect(undoManager.undoDescription).toBe(undefined)
expect(undoManager.redoDescription).toBe(undefined)
})