addons/isl/src/stackEdit/__tests__/fileStackState.test.tsblame
View source
b69ab311/**
b69ab312 * Copyright (c) Meta Platforms, Inc. and affiliates.
b69ab313 *
b69ab314 * This source code is licensed under the MIT license found in the
b69ab315 * LICENSE file in the root directory of this source tree.
b69ab316 */
b69ab317
b69ab318import type {FileRev} from '../fileStackState';
b69ab319
b69ab3110import {FileStackState, Source} from '../fileStackState';
b69ab3111
b69ab3112describe('FileStackState', () => {
b69ab3113 const commonContents = ['b\nc\nd\n', 'a\nb\nc\nd\n', 'a\nb\nc\nd\ne\n', 'a\nc\nd\ne\n'];
b69ab3114 const revLength = commonContents.length as FileRev;
b69ab3115
b69ab3116 it('converts between formats', () => {
b69ab3117 const stack = new FileStackState(commonContents);
b69ab3118 const formats = [
b69ab3119 (s: FileStackState) =>
b69ab3120 new FileStackState(Source({type: 'plain', value: s.convertToPlainText(), revLength})),
b69ab3121 (s: FileStackState) =>
b69ab3122 new FileStackState(Source({type: 'linelog', value: s.convertToLineLog(), revLength})),
b69ab3123 (s: FileStackState) =>
b69ab3124 new FileStackState(Source({type: 'flatten', value: s.convertToFlattenLines(), revLength})),
b69ab3125 ];
b69ab3126 formats.forEach(fromFormat => {
b69ab3127 const fromState = fromFormat(stack);
b69ab3128 formats.forEach(toFormat => {
b69ab3129 const toState = toFormat(fromState);
b69ab3130 expect(toState.revs()).toStrictEqual([...commonContents.keys()]);
b69ab3131 expect(toState.revs().map(rev => toState.getRev(rev))).toStrictEqual(commonContents);
b69ab3132 });
b69ab3133 });
b69ab3134 });
b69ab3135
b69ab3136 // Some features are thin wrappers around linelog. Their tests overlap
b69ab3137 // with linelog tests. We prefer corner cases to be tested at the
b69ab3138 // bottom layer. If you'd like to add more corner cases, consider
b69ab3139 // adding them in linelog.test.ts.
b69ab3140
b69ab3141 it('analyses dependency', () => {
b69ab3142 const stack = new FileStackState(['b\n', 'a\nb\n', 'a\nb\nc\n']);
b69ab3143 expect(stack.calculateDepMap()).toStrictEqual(
b69ab3144 new Map([
b69ab3145 [1, new Set([0])],
b69ab3146 [2, new Set([0])],
b69ab3147 ]),
b69ab3148 );
b69ab3149 });
b69ab3150
b69ab3151 it('supports blame', () => {
b69ab3152 const stack = new FileStackState(commonContents);
b69ab3153 expect(stack.blame(0 as FileRev)).toStrictEqual([0, 0, 0]);
b69ab3154 expect(stack.blame(2 as FileRev)).toStrictEqual([1, 0, 0, 0, 2]);
b69ab3155 });
b69ab3156
b69ab3157 it('supports editing text without affecting the stack', () => {
b69ab3158 const stack = new FileStackState(commonContents).editText(0 as FileRev, 'b\nC\nD\n', false);
b69ab3159 expect(stack.getRev(0 as FileRev)).toBe('b\nC\nD\n');
b69ab3160 expect(stack.getRev(1 as FileRev)).toBe('a\nb\nc\nd\n');
b69ab3161 });
b69ab3162
b69ab3163 it('supports editing text and updating the stack', () => {
b69ab3164 const stack = new FileStackState(commonContents).editText(0 as FileRev, 'b\nC\nD\n', true);
b69ab3165 expect(stack.getRev(0 as FileRev)).toBe('b\nC\nD\n');
b69ab3166 expect(stack.getRev(1 as FileRev)).toBe('a\nb\nC\nD\n');
b69ab3167 });
b69ab3168
b69ab3169 it('supports editing chunk at the given rev', () => {
b69ab3170 // Edit rev 1 from rev 0's line ranges.
b69ab3171 const stack = new FileStackState(commonContents).editChunk(0 as FileRev, 1, 3, 1 as FileRev, [
b69ab3172 'C\n',
b69ab3173 'D\n',
b69ab3174 ]);
b69ab3175 // rev 0 is not changed.
b69ab3176 expect(stack.getRev(0 as FileRev)).toBe('b\nc\nd\n');
b69ab3177 // rev 1 is edited.
b69ab3178 expect(stack.getRev(1 as FileRev)).toBe('a\nb\nC\nD\n');
b69ab3179 });
b69ab3180
b69ab3181 it('supports remapping revs', () => {
b69ab3182 const stack = new FileStackState(['a\n', 'a\nb\n', 'z\na\nb\n']).remapRevs(
b69ab3183 new Map([
b69ab3184 [1 as FileRev, 2 as FileRev],
b69ab3185 [2 as FileRev, 1 as FileRev],
b69ab3186 ]),
b69ab3187 );
b69ab3188 expect(stack.getRev(1 as FileRev)).toBe('z\na\n');
b69ab3189 expect(stack.getRev(2 as FileRev)).toBe('z\na\nb\n');
b69ab3190 });
b69ab3191
b69ab3192 it('supports moving lines between revs', () => {
b69ab3193 let stack = new FileStackState(commonContents);
b69ab3194 // Move +a from rev 1 to rev 2 (->).
b69ab3195 stack = stack.moveLines(1 as FileRev, 0, 1, [], [1 as FileRev]);
b69ab3196 expect(stack.getRev(1 as FileRev)).toBe('b\nc\nd\n');
b69ab3197 // Move -b from rev 3 (present in rev 2) to rev 2 (present in rev 1) (<-).
b69ab3198 stack = stack.moveLines(2 as FileRev, 1, 2, [], [2 as FileRev]);
b69ab3199 expect(stack.getRev(2 as FileRev)).toBe('a\nc\nd\ne\n');
b69ab31100 // Move +e from rev 2 to rev 1 (<-).
b69ab31101 stack = stack.moveLines(2 as FileRev, 3, 4, [1 as FileRev], []);
b69ab31102 expect(stack.getRev(1 as FileRev)).toBe('b\nc\nd\ne\n');
b69ab31103 expect(stack.convertToPlainText().toArray()).toStrictEqual([
b69ab31104 'b\nc\nd\n',
b69ab31105 'b\nc\nd\ne\n',
b69ab31106 'a\nc\nd\ne\n',
b69ab31107 'a\nc\nd\ne\n',
b69ab31108 ]);
b69ab31109 });
b69ab31110
b69ab31111 it('supports appending text', () => {
b69ab31112 let stack = new FileStackState([]);
b69ab31113 expect(stack.source.revLength).toBe(0);
b69ab31114 stack = stack.editText(0 as FileRev, 'a', false);
b69ab31115 expect(stack.source.revLength).toBe(1);
b69ab31116 stack = stack.editText(1 as FileRev, 'b', false);
b69ab31117 expect(stack.source.revLength).toBe(2);
b69ab31118 stack = stack.editText(2 as FileRev, 'c', true);
b69ab31119 expect(stack.source.revLength).toBe(3);
b69ab31120 expect(stack.getRev(2 as FileRev)).toBe('c');
b69ab31121 });
b69ab31122});