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