| b69ab31 | | | 1 | /** |
| b69ab31 | | | 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. |
| b69ab31 | | | 3 | * |
| b69ab31 | | | 4 | * This source code is licensed under the MIT license found in the |
| b69ab31 | | | 5 | * LICENSE file in the root directory of this source tree. |
| b69ab31 | | | 6 | */ |
| b69ab31 | | | 7 | |
| b69ab31 | | | 8 | import type {FileRev} from '../fileStackState'; |
| b69ab31 | | | 9 | |
| b69ab31 | | | 10 | import {FileStackState, Source} from '../fileStackState'; |
| b69ab31 | | | 11 | |
| b69ab31 | | | 12 | describe('FileStackState', () => { |
| b69ab31 | | | 13 | const commonContents = ['b\nc\nd\n', 'a\nb\nc\nd\n', 'a\nb\nc\nd\ne\n', 'a\nc\nd\ne\n']; |
| b69ab31 | | | 14 | const revLength = commonContents.length as FileRev; |
| b69ab31 | | | 15 | |
| b69ab31 | | | 16 | it('converts between formats', () => { |
| b69ab31 | | | 17 | const stack = new FileStackState(commonContents); |
| b69ab31 | | | 18 | const formats = [ |
| b69ab31 | | | 19 | (s: FileStackState) => |
| b69ab31 | | | 20 | new FileStackState(Source({type: 'plain', value: s.convertToPlainText(), revLength})), |
| b69ab31 | | | 21 | (s: FileStackState) => |
| b69ab31 | | | 22 | new FileStackState(Source({type: 'linelog', value: s.convertToLineLog(), revLength})), |
| b69ab31 | | | 23 | (s: FileStackState) => |
| b69ab31 | | | 24 | new FileStackState(Source({type: 'flatten', value: s.convertToFlattenLines(), revLength})), |
| b69ab31 | | | 25 | ]; |
| b69ab31 | | | 26 | formats.forEach(fromFormat => { |
| b69ab31 | | | 27 | const fromState = fromFormat(stack); |
| b69ab31 | | | 28 | formats.forEach(toFormat => { |
| b69ab31 | | | 29 | const toState = toFormat(fromState); |
| b69ab31 | | | 30 | expect(toState.revs()).toStrictEqual([...commonContents.keys()]); |
| b69ab31 | | | 31 | expect(toState.revs().map(rev => toState.getRev(rev))).toStrictEqual(commonContents); |
| b69ab31 | | | 32 | }); |
| b69ab31 | | | 33 | }); |
| b69ab31 | | | 34 | }); |
| b69ab31 | | | 35 | |
| b69ab31 | | | 36 | // Some features are thin wrappers around linelog. Their tests overlap |
| b69ab31 | | | 37 | // with linelog tests. We prefer corner cases to be tested at the |
| b69ab31 | | | 38 | // bottom layer. If you'd like to add more corner cases, consider |
| b69ab31 | | | 39 | // adding them in linelog.test.ts. |
| b69ab31 | | | 40 | |
| b69ab31 | | | 41 | it('analyses dependency', () => { |
| b69ab31 | | | 42 | const stack = new FileStackState(['b\n', 'a\nb\n', 'a\nb\nc\n']); |
| b69ab31 | | | 43 | expect(stack.calculateDepMap()).toStrictEqual( |
| b69ab31 | | | 44 | new Map([ |
| b69ab31 | | | 45 | [1, new Set([0])], |
| b69ab31 | | | 46 | [2, new Set([0])], |
| b69ab31 | | | 47 | ]), |
| b69ab31 | | | 48 | ); |
| b69ab31 | | | 49 | }); |
| b69ab31 | | | 50 | |
| b69ab31 | | | 51 | it('supports blame', () => { |
| b69ab31 | | | 52 | const stack = new FileStackState(commonContents); |
| b69ab31 | | | 53 | expect(stack.blame(0 as FileRev)).toStrictEqual([0, 0, 0]); |
| b69ab31 | | | 54 | expect(stack.blame(2 as FileRev)).toStrictEqual([1, 0, 0, 0, 2]); |
| b69ab31 | | | 55 | }); |
| b69ab31 | | | 56 | |
| b69ab31 | | | 57 | it('supports editing text without affecting the stack', () => { |
| b69ab31 | | | 58 | const stack = new FileStackState(commonContents).editText(0 as FileRev, 'b\nC\nD\n', false); |
| b69ab31 | | | 59 | expect(stack.getRev(0 as FileRev)).toBe('b\nC\nD\n'); |
| b69ab31 | | | 60 | expect(stack.getRev(1 as FileRev)).toBe('a\nb\nc\nd\n'); |
| b69ab31 | | | 61 | }); |
| b69ab31 | | | 62 | |
| b69ab31 | | | 63 | it('supports editing text and updating the stack', () => { |
| b69ab31 | | | 64 | const stack = new FileStackState(commonContents).editText(0 as FileRev, 'b\nC\nD\n', true); |
| b69ab31 | | | 65 | expect(stack.getRev(0 as FileRev)).toBe('b\nC\nD\n'); |
| b69ab31 | | | 66 | expect(stack.getRev(1 as FileRev)).toBe('a\nb\nC\nD\n'); |
| b69ab31 | | | 67 | }); |
| b69ab31 | | | 68 | |
| b69ab31 | | | 69 | it('supports editing chunk at the given rev', () => { |
| b69ab31 | | | 70 | // Edit rev 1 from rev 0's line ranges. |
| b69ab31 | | | 71 | const stack = new FileStackState(commonContents).editChunk(0 as FileRev, 1, 3, 1 as FileRev, [ |
| b69ab31 | | | 72 | 'C\n', |
| b69ab31 | | | 73 | 'D\n', |
| b69ab31 | | | 74 | ]); |
| b69ab31 | | | 75 | // rev 0 is not changed. |
| b69ab31 | | | 76 | expect(stack.getRev(0 as FileRev)).toBe('b\nc\nd\n'); |
| b69ab31 | | | 77 | // rev 1 is edited. |
| b69ab31 | | | 78 | expect(stack.getRev(1 as FileRev)).toBe('a\nb\nC\nD\n'); |
| b69ab31 | | | 79 | }); |
| b69ab31 | | | 80 | |
| b69ab31 | | | 81 | it('supports remapping revs', () => { |
| b69ab31 | | | 82 | const stack = new FileStackState(['a\n', 'a\nb\n', 'z\na\nb\n']).remapRevs( |
| b69ab31 | | | 83 | new Map([ |
| b69ab31 | | | 84 | [1 as FileRev, 2 as FileRev], |
| b69ab31 | | | 85 | [2 as FileRev, 1 as FileRev], |
| b69ab31 | | | 86 | ]), |
| b69ab31 | | | 87 | ); |
| b69ab31 | | | 88 | expect(stack.getRev(1 as FileRev)).toBe('z\na\n'); |
| b69ab31 | | | 89 | expect(stack.getRev(2 as FileRev)).toBe('z\na\nb\n'); |
| b69ab31 | | | 90 | }); |
| b69ab31 | | | 91 | |
| b69ab31 | | | 92 | it('supports moving lines between revs', () => { |
| b69ab31 | | | 93 | let stack = new FileStackState(commonContents); |
| b69ab31 | | | 94 | // Move +a from rev 1 to rev 2 (->). |
| b69ab31 | | | 95 | stack = stack.moveLines(1 as FileRev, 0, 1, [], [1 as FileRev]); |
| b69ab31 | | | 96 | expect(stack.getRev(1 as FileRev)).toBe('b\nc\nd\n'); |
| b69ab31 | | | 97 | // Move -b from rev 3 (present in rev 2) to rev 2 (present in rev 1) (<-). |
| b69ab31 | | | 98 | stack = stack.moveLines(2 as FileRev, 1, 2, [], [2 as FileRev]); |
| b69ab31 | | | 99 | expect(stack.getRev(2 as FileRev)).toBe('a\nc\nd\ne\n'); |
| b69ab31 | | | 100 | // Move +e from rev 2 to rev 1 (<-). |
| b69ab31 | | | 101 | stack = stack.moveLines(2 as FileRev, 3, 4, [1 as FileRev], []); |
| b69ab31 | | | 102 | expect(stack.getRev(1 as FileRev)).toBe('b\nc\nd\ne\n'); |
| b69ab31 | | | 103 | expect(stack.convertToPlainText().toArray()).toStrictEqual([ |
| b69ab31 | | | 104 | 'b\nc\nd\n', |
| b69ab31 | | | 105 | 'b\nc\nd\ne\n', |
| b69ab31 | | | 106 | 'a\nc\nd\ne\n', |
| b69ab31 | | | 107 | 'a\nc\nd\ne\n', |
| b69ab31 | | | 108 | ]); |
| b69ab31 | | | 109 | }); |
| b69ab31 | | | 110 | |
| b69ab31 | | | 111 | it('supports appending text', () => { |
| b69ab31 | | | 112 | let stack = new FileStackState([]); |
| b69ab31 | | | 113 | expect(stack.source.revLength).toBe(0); |
| b69ab31 | | | 114 | stack = stack.editText(0 as FileRev, 'a', false); |
| b69ab31 | | | 115 | expect(stack.source.revLength).toBe(1); |
| b69ab31 | | | 116 | stack = stack.editText(1 as FileRev, 'b', false); |
| b69ab31 | | | 117 | expect(stack.source.revLength).toBe(2); |
| b69ab31 | | | 118 | stack = stack.editText(2 as FileRev, 'c', true); |
| b69ab31 | | | 119 | expect(stack.source.revLength).toBe(3); |
| b69ab31 | | | 120 | expect(stack.getRev(2 as FileRev)).toBe('c'); |
| b69ab31 | | | 121 | }); |
| b69ab31 | | | 122 | }); |