1 | var expect = require('chai').expect
|
2 | , diff = require('..');
|
3 |
|
4 | describe('changeset', function () {
|
5 | beforeEach(function (done) {
|
6 | done();
|
7 | });
|
8 |
|
9 | it('should be able to diff two objects and return a changeset',
|
10 | function (done) {
|
11 | var a = {
|
12 | name: 'Eugene',
|
13 | number: 42,
|
14 | tags: ['tag1', 'tag2', 'tag3'],
|
15 | scores: {
|
16 | tetris: 1000,
|
17 | carmageddon: 3,
|
18 | someArray: ['one', 'two', 'three']
|
19 | }
|
20 | };
|
21 |
|
22 | a.self = a;
|
23 | a.scoresAgain = a.scores;
|
24 |
|
25 | var b = {
|
26 | name: 'Susan',
|
27 | number: 43,
|
28 | tags: ['tag1', 'tag4'],
|
29 | scores: {
|
30 | carmageddon: 3,
|
31 | zelda: 3000,
|
32 | someArray: ['one', 'three']
|
33 | },
|
34 | age: 37
|
35 | };
|
36 |
|
37 | b.friend = a;
|
38 | b.self = b;
|
39 |
|
40 | var changes = diff(a, b);
|
41 |
|
42 | expect(changes).to.deep.equal([
|
43 | { type: 'put', key: ['name'], value: 'Susan' },
|
44 | { type: 'put', key: ['number'], value: 43 },
|
45 | { type: 'put', key: ['tags', '1'], value: 'tag4' },
|
46 | { type: 'del', key: ['tags', '2'] },
|
47 | { type: 'put', key: [ 'scores', 'someArray', '1' ], value: 'three' },
|
48 | { type: 'del', key: [ 'scores', 'someArray', '2' ] },
|
49 | { type: 'del', key: ['scores', 'tetris'] },
|
50 | { type: 'put', key: ['scores', 'zelda'], value: 3000 },
|
51 | { type: 'put', key: ['self'], value: b },
|
52 | { type: 'del', key: ['scoresAgain'], },
|
53 | { type: 'put', key: ['age'], value: 37 },
|
54 | { type: 'put', key: ['friend'], value: a }
|
55 | ]);
|
56 |
|
57 | done();
|
58 | });
|
59 |
|
60 | it('should be able to handle basic types', function (done) {
|
61 | var a = 'Eugene';
|
62 | var b = 'Susan';
|
63 |
|
64 | var changes = diff(a, b);
|
65 | expect(changes).to.deep.equal([
|
66 | { type: 'put', key: [], value: 'Susan' }
|
67 | ]);
|
68 |
|
69 | done();
|
70 | });
|
71 |
|
72 | it('should be able to handle nulls', function (done) {
|
73 | var changes;
|
74 |
|
75 | changes = diff(null, 'Susan');
|
76 | expect(changes).to.deep.equal([
|
77 | { type: 'put', key: [], value: 'Susan' }
|
78 | ]);
|
79 |
|
80 | changes = diff('Eugene', null);
|
81 | expect(changes).to.deep.equal([
|
82 | { type: 'put', key: [], value: null }
|
83 | ]);
|
84 |
|
85 | done();
|
86 | });
|
87 |
|
88 | it('should be able to handle undefined', function (done) {
|
89 | var changes;
|
90 |
|
91 | changes = diff(undefined, 'Susan');
|
92 | expect(changes).to.deep.equal([
|
93 | { type: 'put', key: [], value: 'Susan' }
|
94 | ]);
|
95 |
|
96 | changes = diff('Eugene', undefined);
|
97 | expect(changes).to.deep.equal([
|
98 | { type: 'del', key: [] }
|
99 | ]);
|
100 |
|
101 | done();
|
102 | });
|
103 |
|
104 | it('should be able to apply a changeset to an object', function (done) {
|
105 | var a = {
|
106 | name: 'Eugene',
|
107 | number: 42,
|
108 | tags: ['tag1', 'tag2', 'tag3'],
|
109 | scores: {
|
110 | tetris: 1000,
|
111 | carmageddon: 3,
|
112 | someArray: ['one', 'two', 'three']
|
113 | }
|
114 | };
|
115 |
|
116 | a.self = a;
|
117 | a.scoresAgain = a.scores;
|
118 |
|
119 | var b = {
|
120 | name: 'Susan',
|
121 | number: 43,
|
122 | tags: ['tag1', 'tag4'],
|
123 | scores: {
|
124 | carmageddon: 3,
|
125 | zelda: 3000,
|
126 | someArray: ['one', 'three']
|
127 | },
|
128 | age: 37
|
129 | };
|
130 |
|
131 | b.friend = a;
|
132 | b.self = b;
|
133 |
|
134 | var clone = require("udc");
|
135 | var bClone = clone(b);
|
136 |
|
137 | var changes = diff(a, b);
|
138 | var b_ = diff.apply(changes, a);
|
139 | expect(b_.scores.someArray.length).to.equal(b.scores.someArray.length);
|
140 | expect(b_).to.deep.equals(b);
|
141 | expect(b).to.deep.equals(bClone);
|
142 | done();
|
143 | });
|
144 |
|
145 | it('should be able to apply a changeset to a value', function (done) {
|
146 | var a = 'Eugene';
|
147 | var b = 'Susan';
|
148 |
|
149 | var changes = diff(a, b);
|
150 | var b_ = diff.apply(changes, a);
|
151 | expect(b_).to.deep.equals(b);
|
152 | done();
|
153 | });
|
154 |
|
155 | it('should be able to apply a changeset with nulls', function (done) {
|
156 | var changes, b_;
|
157 |
|
158 | changes = diff(null, 'Susan');
|
159 | b_ = diff.apply(changes, null);
|
160 | expect(b_).to.deep.equals('Susan');
|
161 |
|
162 | changes = diff('Eugene', null);
|
163 | b_ = diff.apply(changes, 'Eugene');
|
164 | expect(b_).to.deep.equals(null);
|
165 |
|
166 | done();
|
167 | });
|
168 |
|
169 | it('should be able to apply a changeset with undefined', function (done) {
|
170 | var changes, b_;
|
171 |
|
172 | changes = diff(undefined, 'Susan');
|
173 | b_ = diff.apply(changes, undefined);
|
174 | expect(b_).to.deep.equals('Susan');
|
175 |
|
176 | changes = diff('Eugene', undefined);
|
177 | b_ = diff.apply(changes, 'Eugene');
|
178 | expect(b_).to.deep.equals(null);
|
179 |
|
180 | done();
|
181 | });
|
182 |
|
183 | it('should be able to apply a changeset to an object and modify it',
|
184 | function (done) {
|
185 | var a = {
|
186 | name: 'Eugene',
|
187 | number: 42,
|
188 | tags: ['tag1', 'tag2', 'tag3'],
|
189 | scores: {
|
190 | tetris: 1000,
|
191 | carmageddon: 3,
|
192 | someArray: ['one', 'two', 'three']
|
193 | }
|
194 | };
|
195 |
|
196 | a.self = a;
|
197 | a.scoresAgain = a.scores;
|
198 |
|
199 | var b = {
|
200 | name: 'Susan',
|
201 | number: 43,
|
202 | tags: ['tag1', 'tag4'],
|
203 | scores: {
|
204 | carmageddon: 3,
|
205 | zelda: 3000,
|
206 | someArray: ['one', 'three']
|
207 | },
|
208 | age: 37
|
209 | };
|
210 |
|
211 | b.friend = a;
|
212 | b.self = b;
|
213 |
|
214 | var changes = diff(a, b);
|
215 | var b_ = diff.apply(changes, a, true);
|
216 | expect(b_.scores.someArray.length).to.equal(b.scores.someArray.length);
|
217 | expect(b_).to.deep.equals(b);
|
218 | expect(b_).to.equal(a);
|
219 | done();
|
220 | });
|
221 |
|
222 | it('should be able to self-modify and replace an entire object',
|
223 | function(done) {
|
224 | var data = { name: 'Eugene', number: 43 };
|
225 | var change = [ { type: 'put', key: [], value: 'xxx' } ];
|
226 | var obj = diff.apply(change, data, true);
|
227 | expect(obj).to.equal('xxx');
|
228 | done();
|
229 | });
|
230 |
|
231 | it('should be able to deal with incrementally built arrays', function(done) {
|
232 | var obj = [];
|
233 | var changeset = [
|
234 | { type: 'put', key: [], value: [] },
|
235 | { type: 'put', key: [ 0, 'make' ], value: 'Toyota' },
|
236 | { type: 'put', key: [ 0, 'model' ], value: 'Camry' },
|
237 | { type: 'put', key: [ 1, 'make' ], value: 'Toyota' },
|
238 | { type: 'put', key: [ 1, 'model' ], value: 'Corolla' } ];
|
239 | obj = diff.apply(changeset, obj, true);
|
240 | expect(obj).to.deep.equals([
|
241 | { make: 'Toyota', model: 'Camry' },
|
242 | { make: 'Toyota', model: 'Corolla' }
|
243 | ]);
|
244 | done();
|
245 | });
|
246 |
|
247 | it('should not allow prototype pollution', function(done) {
|
248 | var changeset = [
|
249 | { type: 'put', key: ['__proto__','polluted'], value: 'Yes! Its Polluted'}
|
250 | ];
|
251 | diff.apply(changeset, {}, true);
|
252 | expect({}.polluted).to.not.equal('Yes! Its Polluted');
|
253 | done();
|
254 | })
|
255 | });
|