1// Copyright (c) Jupyter Development Team.
2// Distributed under the terms of the Modified BSD License.
3
4import {
5  deepCopy
6} from '../../../src/common/util';
7
8import * as util from '../../../src/diff/util';
9
10import {
11  opPatch, opAdd, opAddRange, opRemoveRange
12} from '../../../src/diff/diffentries';
13
14describe('diff', () => {
15
16  describe('util', () => {
17
18    describe('getSubDiffByKey', () => {
19
20      it('should return null for an empty diff', () => {
21        let diff = util.getSubDiffByKey([], 'not_present');
22        expect(diff).toBe(null);
23      });
24
25      it('should return null for a null diff', () => {
26        let diff = util.getSubDiffByKey(null, 'not_present');
27        expect(diff).toBe(null);
28      });
29
30      it('should return null for a missing key', () => {
31        let subdiff = [opAdd('foo', 11)];
32        let diff = [opPatch('a', subdiff)];
33        let value = util.getSubDiffByKey(diff, 'b');
34        expect(value).toBe(null);
35      });
36
37      it('should return a sub-diff for valid key', () => {
38        let subdiff = [opAdd('foo', 11)];
39        let diff = [opPatch('a', subdiff)];
40        let value = util.getSubDiffByKey(diff, 'a');
41        expect(value).toBe(subdiff);
42      });
43
44      it('should return null for a key to a non-patch op', () => {
45        let subdiff = [opAdd('foo', 11)];
46        let diff = [opPatch('a', subdiff), opAdd('b', subdiff)];
47        let value = util.getSubDiffByKey(diff, 'b');
48        expect(value).toBe(null);
49      });
50
51    });
52
53
54    describe('flattenStringDiff', () => {
55
56      it('should work for an empty diff', () => {
57        let diff = util.flattenStringDiff('test', []);
58        expect(diff).toEqual([]);
59      });
60
61      it('should work for an empty diff on array of lines', () => {
62        let diff = util.flattenStringDiff(['test'], []);
63        expect(diff).toEqual([]);
64      });
65
66      it('should work for a valid line addition', () => {
67        let source = ['test\n', 'foo\n', 'bar\n'];
68        let sourceDiff = [
69          opAddRange(1, ['wee\n'])
70        ]
71        let diff = util.flattenStringDiff(source, sourceDiff);
72        let expected = [opAddRange(source[0].length, 'wee\n')];
73        expect(util.stripSource(diff)).toEqual(expected);
74      });
75
76      it('should work for a valid line addition', () => {
77        let source = ['test\n', 'foo\n', 'bar\n'];
78        let sourceDiff = [
79          opAddRange(1, ['wee\n'])
80        ]
81        let diff = util.flattenStringDiff(source, sourceDiff);
82        let expected = [opAddRange(source[0].length, 'wee\n')];
83        expect(util.stripSource(diff)).toEqual(expected);
84      });
85
86      it('should be robust against different line endings', () => {
87        let sourceA = 'test\nfoo\n\nbar\n';
88        let sourceB = sourceA.replace(/\n/gm, '\r\n');
89        let sourceC = sourceA.replace(/\n/gm, '\r');
90        let sourceDiffA = [
91          opAddRange(3, ['wee\n']),
92          opAddRange(3, ['ooh\n'])
93        ]
94        let sourceDiffB = deepCopy(sourceDiffA);
95        (sourceDiffB[0].valuelist as string[])[0] = sourceDiffA[0].valuelist[0].replace(/\n/gm, '\r\n');
96        (sourceDiffB[1].valuelist as string[])[0] = sourceDiffA[1].valuelist[0].replace(/\n/gm, '\r\n');
97        let sourceDiffC = deepCopy(sourceDiffA);
98        (sourceDiffC[0].valuelist as string[])[0] = sourceDiffA[0].valuelist[0].replace(/\n/gm, '\r');
99        (sourceDiffC[1].valuelist as string[])[0] = sourceDiffA[1].valuelist[0].replace(/\n/gm, '\r');
100
101        let diff = util.flattenStringDiff(sourceA, sourceDiffA);
102        let expected = [
103          opAddRange('test\nfoo\n\n'.length, 'wee\n'),
104          opAddRange('test\nfoo\n\n'.length, 'ooh\n')
105          ];
106        expect(util.stripSource(diff)).toEqual(expected);
107
108        diff = util.flattenStringDiff(sourceB, sourceDiffB);
109        expected = [
110          opAddRange('test\r\nfoo\r\n\r\n'.length, 'wee\r\n'),
111          opAddRange('test\r\nfoo\r\n\r\n'.length, 'ooh\r\n')
112          ];
113        expect(util.stripSource(diff)).toEqual(expected);
114
115        diff = util.flattenStringDiff(sourceC, sourceDiffC);
116        expected = [
117          opAddRange('test\rfoo\r\r'.length, 'wee\r'),
118          opAddRange('test\rfoo\r\r'.length, 'ooh\r')
119          ];
120        expect(util.stripSource(diff)).toEqual(expected);
121      });
122
123      it('should work for a valid line deletion', () => {
124        let source = ['test\n', 'foo\n', 'bar\n'];
125        let sourceDiff = [
126          opRemoveRange(1, 1)
127        ]
128        let diff = util.flattenStringDiff(source, sourceDiff);
129        let expected = [opRemoveRange(source[0].length, 'wee\n'.length)];
130        expect(util.stripSource(diff)).toEqual(expected);
131      });
132
133    });
134
135  });
136
137});
138