53 |
54 | dispatch(commit())} />
55 | dispatch(rollback())} />
56 | dispatch(reset())} />
57 |
58 |
59 | {actionReports.reverse()}
60 |
61 |
62 | );
63 | }
64 | }
65 |
66 | const styles = StyleSheet.create({
67 | wrap: {
68 | overflowY: 'auto',
69 | width: '100%',
70 | height: '100%',
71 | minWidth: 300,
72 | },
73 | container: {
74 | display : 'flex',
75 | flexDirection: 'row',
76 | flexWrap : 'nowrap',
77 | borderBottom : '1px solid #ddd',
78 | },
79 | actions : {
80 | margin: '10px',
81 | },
82 | });
83 |
--------------------------------------------------------------------------------
/src/utils/diff-state.js:
--------------------------------------------------------------------------------
1 | import deep from 'deep-diff';
2 | import Immutable from 'immutable';
3 |
4 | export default (computedStates, index) => {
5 | if (index !== 0) {
6 | const newState = Immutable.fromJS({
7 | state: computedStates[index].state,
8 | }).toJS().state;
9 |
10 | const oldState = Immutable.fromJS({
11 | state: computedStates[index - 1].state,
12 | }).toJS().state;
13 |
14 | const diff = deep.diff(oldState, newState);
15 |
16 | return diff || [];
17 | }
18 |
19 | return [];
20 | };
21 |
--------------------------------------------------------------------------------
/test/action/index.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-env mocha */
2 |
3 | import { expect } from 'chai';
4 | import React from 'react';
5 | import ReactDOM from 'react-dom';
6 | import ManifestActionComponent from '../../src/action/index';
7 | import TestUtils from 'react-addons-test-utils';
8 |
9 | describe('ManifestActionComponent', () => {
10 | const mockProps = {
11 | action: {
12 | type: 'PERFORM_ACTION',
13 | action: { type: 'ACTION_1' },
14 | },
15 | diff: [],
16 | expanded: true,
17 | };
18 |
19 | const render = props => {
20 | const element = React.createElement(ManifestActionComponent, props);
21 |
22 | return TestUtils.renderIntoDocument(element);
23 | };
24 |
25 | // it('should show actions', () => {
26 | // const rendered = render(mockProps);
27 | //
28 | // expect(
29 | // ReactDOM.findDOMNode(rendered).querySelectorAll('.ACTION_1')
30 | // ).to.have.length(1);
31 | // });
32 |
33 | describe('diff', () => {
34 | it('should show no diff if the data has not changed', () => {
35 | const rendered = render(mockProps);
36 |
37 | expect(
38 | ReactDOM.findDOMNode(rendered).querySelectorAll('.diff')
39 | ).to.have.length(0);
40 | });
41 |
42 | it('should show the correct diff when comparing objects having other properties', () => {
43 | const rendered = render(Object.assign({}, mockProps, {
44 | diff: [{
45 | kind: 'E', path: ['key'], lhs: {}, rhs: {
46 | other: 'property',
47 | another: 13.13,
48 | },
49 | }],
50 | }));
51 |
52 | expect(
53 | ReactDOM.findDOMNode(rendered).querySelectorAll('.diff')[0].textContent.trim()
54 | ).to.eql('key: {} {"other":"property","another":13.13}');
55 | });
56 |
57 | it('should show the correct diff when replacing an object with an empty object', () => {
58 | const rendered = render(Object.assign({}, mockProps, {
59 | diff: [{ kind: 'D', path: ['one'], lhs: 'property' }],
60 | }));
61 |
62 | expect(
63 | ReactDOM.findDOMNode(rendered).querySelectorAll('.diff')[0].textContent.trim()
64 | ).to.eql('one: "property"');
65 | });
66 |
67 | it('should show the correct diff when comparing changes in nested objects', () => {
68 | const rendered = render(Object.assign({}, mockProps, {
69 | diff: [{ kind: 'E', path: ['levelOne', 'levelTwo'], lhs: 'value', rhs: 'another value' }],
70 | }));
71 |
72 | expect(
73 | ReactDOM.findDOMNode(rendered).querySelectorAll('.diff')[0].textContent.trim()
74 | ).to.eql('levelOne.levelTwo: "value" "another value"');
75 | });
76 |
77 | it('should show the correct diff when comparing changes in arrays', () => {
78 | const rendered = render(Object.assign({}, mockProps, {
79 | diff: [
80 | { kind: 'E', path: [0], lhs: 1, rhs: 2 },
81 | { kind: 'E', path: [1], lhs: 2, rhs: 3 },
82 | { kind: 'E', path: [2], lhs: 3, rhs: 4 },
83 | ],
84 | }));
85 |
86 | expect(
87 | ReactDOM.findDOMNode(rendered).querySelectorAll('.diff')[0].textContent.trim()
88 | ).to.eql('0: 1 2 1: 2 3 2: 3 4');
89 | });
90 |
91 | it('should show the correct diff when comparing changes in arrays inside objects', () => {
92 | const rendered = render(Object.assign({}, mockProps, {
93 | diff: [
94 | { kind: 'E', path: ['a', 0], lhs: 1, rhs: 2 },
95 | { kind: 'E', path: ['a', 1], lhs: 2, rhs: 3 },
96 | { kind: 'E', path: ['a', 2], lhs: 3, rhs: 4 },
97 | ],
98 | }));
99 |
100 | expect(
101 | ReactDOM.findDOMNode(rendered).querySelectorAll('.diff')[0].textContent.trim()
102 | ).to.eql('a.0: 1 2 a.1: 2 3 a.2: 3 4');
103 | });
104 |
105 | it('should show the correct diff when item removed from array', () => {
106 | const rendered = render(Object.assign({}, mockProps, {
107 | diff: [
108 | { kind: 'E', path: [0], lhs: 1, rhs: 2 },
109 | { kind: 'E', path: [1], lhs: 2, rhs: 3 },
110 | { kind: 'A', index: 2, item: { kind: 'D', lhs: 3 } },
111 | ],
112 | }));
113 |
114 | expect(
115 | ReactDOM.findDOMNode(rendered).querySelectorAll('.diff')[0].textContent.trim()
116 | ).to.eql('0: 1 2 1: 2 3 2: 3');
117 | });
118 |
119 | it('should show the correct diff when item removed from array inside an object', () => {
120 | const rendered = render(Object.assign({}, mockProps, {
121 | diff: [
122 | { kind: 'E', path: ['a', 0], lhs: 1, rhs: 2 },
123 | { kind: 'E', path: ['a', 1], lhs: 2, rhs: 3 },
124 | { kind: 'A', path: ['a'], index: 2, item: { kind: 'D', lhs: 3 } }],
125 | }));
126 |
127 | expect(
128 | ReactDOM.findDOMNode(rendered).querySelectorAll('.diff')[0].textContent.trim()
129 | ).to.eql('a.0: 1 2 a.1: 2 3 a.2: 3');
130 | });
131 |
132 | it('should diff items added to an array', () => {
133 | const rendered = render(Object.assign({}, mockProps, {
134 | diff: [{ kind: 'A', index: 2, item: { kind: 'N', rhs: 3 } }],
135 | }));
136 |
137 | expect(
138 | ReactDOM.findDOMNode(rendered).querySelectorAll('.diff')[0].textContent.trim()
139 | ).to.eql('2: undefined 3');
140 | });
141 |
142 | it('should diff complex objects', () => {
143 | const rendered = render(Object.assign({}, mockProps, {
144 | diff: [
145 | { kind: 'A', path: ['ids'], index: 0, item: { kind: 'N', rhs: 2 } },
146 | { kind: 'A', path: ['ids'], index: 1, item: { kind: 'N', rhs: 3 } },
147 | { kind: 'E', path: ['turn'], lhs: 0, rhs: 1 },
148 | { kind: 'E', path: ['round'], lhs: 0, rhs: 1 },
149 | ],
150 | }));
151 |
152 | expect(
153 | ReactDOM.findDOMNode(rendered).querySelectorAll('.diff')[0].textContent.trim()
154 | ).to.equal('ids.0: undefined 2 ids.1: undefined 3 turn: 0 1 round: 0 1');
155 | });
156 | });
157 | });
158 |
--------------------------------------------------------------------------------
/test/index.spec.js:
--------------------------------------------------------------------------------
1 | /* eslint-env mocha */
2 |
3 | import { expect } from 'chai';
4 | import React from 'react';
5 | import ReactDOM from 'react-dom';
6 | import ManifestComponent from '../src/index';
7 | import TestUtils from 'react-addons-test-utils';
8 |
9 | describe('ManifestComponent', () => {
10 | it('should show actions', () => {
11 | const element = React.createElement(ManifestComponent, {
12 | computedStates: [{}, {}],
13 | actionsById: {
14 | 0: {
15 | type: 'PERFORM_ACTION',
16 | action: {
17 | type: 'TEST_ACTION_1',
18 | },
19 | },
20 | 1: {
21 | type: 'PERFORM_ACTION',
22 | action: {
23 | type: 'TEST_ACTION_2',
24 | },
25 | },
26 | },
27 | stagedActionIds: [0, 1],
28 | skippedActionIds: [],
29 | dispatch: () => {},
30 | });
31 |
32 | const rendered = TestUtils.renderIntoDocument(element);
33 | expect(
34 | ReactDOM.findDOMNode(rendered).querySelectorAll('.manifest-action-component')
35 | ).to.have.length(2);
36 | });
37 | });
38 |
--------------------------------------------------------------------------------
/test/mocha.opts:
--------------------------------------------------------------------------------
1 | --require test/test-utils/dom.js
2 | --require should
3 | --reporter nyan
4 | --recursive
--------------------------------------------------------------------------------
/test/test-utils/dom.js:
--------------------------------------------------------------------------------
1 | var jsdom = require('jsdom')
2 |
3 | // setup the simplest document possible
4 | var doc = jsdom.jsdom('')
5 |
6 | // get the window object out of the document
7 | var win = doc.defaultView;
8 |
9 | // set globals for mocha that make access to document and window feel
10 | // natural in the test environment
11 | global.document = doc
12 | global.window = win
13 |
14 | // take all properties of the window object and also attach it to the
15 | // mocha global object
16 | propagateToGlobal(win)
17 |
18 | // from mocha-jsdom https://github.com/rstacruz/mocha-jsdom/blob/master/index.js#L80
19 | function propagateToGlobal (window) {
20 | for (let key in window) {
21 | if (!window.hasOwnProperty(key)) continue
22 | if (key in global) continue
23 |
24 | global[key] = window[key]
25 | }
26 | }
--------------------------------------------------------------------------------
/test/utils/diff-state.spec.js:
--------------------------------------------------------------------------------
1 | import { expect } from 'chai';
2 | import diffState from '../../src/utils/diff-state';
3 | import Immutable from 'immutable';
4 |
5 | describe('diffState', () => {
6 | let computedStates = [{}, {}];
7 |
8 | const empty = {};
9 |
10 | describe('Plain JavaScript data', () => {
11 |
12 | describe('A target that has no properties', () => {
13 | computedStates[0].state = empty;
14 |
15 | it('shows no differences when compared to another empty object', () => {
16 | computedStates[1].state = {};
17 |
18 | const diff = diffState(computedStates, 1);
19 |
20 | expect(diff).to.be.an('array');
21 | expect(diff).to.have.length(0);
22 | });
23 | });
24 |
25 | describe('when compared to a different type of keyless object', () => {
26 | const aDate = new Date();
27 |
28 | const comparandTuples = [
29 | ['an array', {
30 | key: []
31 | }],
32 | ['an object', {
33 | key: {}
34 | }],
35 | ['a date', {
36 | key: aDate
37 | }],
38 | ['a null', {
39 | key: null
40 | }]
41 | ];
42 |
43 | comparandTuples.forEach(function(lhsTuple) {
44 | comparandTuples.forEach(function(rhsTuple) {
45 | if (lhsTuple[0] === rhsTuple[0]) {
46 | return;
47 | }
48 |
49 | it('shows differences when comparing ' + lhsTuple[0] + ' to ' + rhsTuple[0], () => {
50 | computedStates[0].state = lhsTuple[1];
51 | computedStates[1].state = rhsTuple[1];
52 |
53 | const diff = diffState(computedStates, 1);
54 |
55 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"key"');
56 |
57 | if (lhsTuple[0] === comparandTuples[0][0]) {
58 | expect(JSON.stringify(diff[0].lhs)).to.eql('[]');
59 | } else if (lhsTuple[0] === comparandTuples[1][0]) {
60 | expect(JSON.stringify(diff[0].lhs)).to.eql('{}');
61 | } else if (lhsTuple[0] === comparandTuples[2][0]) {
62 | expect(JSON.stringify(diff[0].lhs)).to.eql('"' + aDate.toISOString() + '"');
63 | } else if (lhsTuple[0] === comparandTuples[3][0]) {
64 | expect(JSON.stringify(diff[0].lhs)).to.eql('null');
65 | }
66 |
67 | if (rhsTuple[0] === comparandTuples[0][0]) {
68 | expect(JSON.stringify(diff[0].rhs)).to.eql('[]');
69 | } else if (rhsTuple[0] === comparandTuples[1][0]) {
70 | expect(JSON.stringify(diff[0].rhs)).to.eql('{}');
71 | } else if (rhsTuple[0] === comparandTuples[2][0]) {
72 | expect(JSON.stringify(diff[0].rhs)).to.eql('"' + aDate.toISOString() + '"');
73 | } else if (rhsTuple[0] === comparandTuples[3][0]) {
74 | expect(JSON.stringify(diff[0].rhs)).to.eql('null');
75 | }
76 | });
77 | });
78 | });
79 | });
80 |
81 | describe('when compared with an object having other properties', () => {
82 | computedStates[0].state = empty;
83 | computedStates[1].state = {
84 | other: 'property',
85 | another: 13.13
86 | };
87 |
88 | const diff = diffState(computedStates, 1);
89 |
90 | it('the differences are reported', () => {
91 |
92 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"other"');
93 | expect(JSON.stringify(diff[0].lhs)).be.undefined;
94 | expect(JSON.stringify(diff[0].rhs)).eql('"property"');
95 |
96 | expect(JSON.stringify(diff[1].path.join('.'))).to.eql('"another"');
97 | expect(JSON.stringify(diff[1].lhs)).be.undefined;
98 | expect(JSON.stringify(diff[1].rhs)).eql('13.13');
99 | });
100 |
101 | });
102 |
103 | describe('A target that has one property', function() {
104 | const lhs = {
105 | one: 'property'
106 | };
107 |
108 | it('shows no differences when compared to itself', function() {
109 | computedStates[0].state = lhs;
110 | computedStates[1].state = lhs;
111 |
112 | const diff = diffState(computedStates, 1);
113 | expect(diff).to.be.an.array;
114 | expect(diff).to.have.length(0);
115 | });
116 |
117 | it('shows the property as removed when compared to an empty object', function() {
118 | computedStates[0].state = lhs;
119 | computedStates[1].state = empty;
120 |
121 | const diff = diffState(computedStates, 1);
122 |
123 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"one"');
124 | expect(JSON.stringify(diff[0].lhs)).eql('"property"');
125 | expect(JSON.stringify(diff[0].rhs)).be.undefined;
126 | });
127 |
128 | it('shows the property as edited when compared to an object with null', function() {
129 | computedStates[0].state = lhs;
130 | computedStates[1].state = {
131 | one: null
132 | };
133 |
134 | const diff = diffState(computedStates, 1);
135 |
136 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"one"');
137 | expect(JSON.stringify(diff[0].lhs)).eql('"property"');
138 | expect(JSON.stringify(diff[0].rhs)).eql('null');
139 | });
140 |
141 | it('shows the property as edited when compared to an array', function() {
142 | computedStates[0].state = lhs;
143 | computedStates[1].state = ['one'];
144 |
145 | const diff = diffState(computedStates, 1);
146 |
147 | expect(diff[0].path).to.be.undefined;
148 | expect(JSON.stringify(diff[0].lhs)).eql('{"one":"property"}');
149 | expect(JSON.stringify(diff[0].rhs)).eql('["one"]');
150 | });
151 |
152 | });
153 |
154 | describe('A target that has null value', function() {
155 | const lhs = {
156 | key: null
157 | };
158 |
159 | it('shows no differences when compared to itself', function() {
160 | computedStates[0].state = lhs;
161 | computedStates[1].state = lhs;
162 |
163 | const diff = diffState(computedStates, 1);
164 |
165 | expect(diff).to.be.an.array;
166 | expect(diff).to.have.length(0);
167 | });
168 |
169 | it('shows the property as removed when compared to an empty object', function() {
170 | computedStates[0].state = lhs;
171 | computedStates[1].state = empty;
172 |
173 | const diff = diffState(computedStates, 1);
174 |
175 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"key"');
176 | expect(JSON.stringify(diff[0].lhs)).eql('null');
177 | expect(JSON.stringify(diff[0].rhs)).be.undefined;
178 | });
179 |
180 | it('shows the property is changed when compared to an object that has value', function() {
181 | computedStates[0].state = lhs;
182 | computedStates[1].state = {
183 | key: 'value'
184 | };
185 |
186 | const diff = diffState(computedStates, 1);
187 |
188 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"key"');
189 | expect(JSON.stringify(diff[0].lhs)).eql('null');
190 | expect(JSON.stringify(diff[0].rhs)).eql('"value"');
191 | });
192 |
193 | it('shows that an object property is changed when it is set to null', function() {
194 | lhs.key = {
195 | nested: 'value'
196 | };
197 |
198 | computedStates[0].state = lhs;
199 | computedStates[1].state = {
200 | key: null
201 | };
202 |
203 | const diff = diffState(computedStates, 1);
204 |
205 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"key"');
206 | expect(JSON.stringify(diff[0].lhs)).eql('{"nested":"value"}');
207 | expect(JSON.stringify(diff[0].rhs)).eql('null');
208 | });
209 |
210 | });
211 |
212 | describe('A target that has a NaN', function() {
213 | const lhs = {
214 | key: NaN
215 | };
216 |
217 | it('shows the property is changed when compared to another number', function() {
218 | computedStates[0].state = lhs;
219 | computedStates[1].state = {
220 | key: 0
221 | };
222 |
223 | const diff = diffState(computedStates, 1);
224 |
225 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"key"');
226 | expect(JSON.stringify(diff[0].lhs)).eql('null');
227 | expect(JSON.stringify(diff[0].rhs)).eql('0');
228 | });
229 |
230 | it('shows no differences when compared to another NaN', function() {
231 | computedStates[0].state = lhs;
232 | computedStates[1].state = {
233 | key: NaN
234 | };
235 |
236 | const diff = diffState(computedStates, 1);
237 |
238 | expect(diff).to.be.an.array;
239 | expect(diff).to.have.length(0);
240 | });
241 |
242 | });
243 |
244 | describe('A target that has nested values', function() {
245 | const nestedOne = {
246 | noChange: 'same',
247 | levelOne: {
248 | levelTwo: 'value'
249 | }
250 | };
251 | const nestedTwo = {
252 | noChange: 'same',
253 | levelOne: {
254 | levelTwo: 'another value'
255 | }
256 | };
257 |
258 | it('shows no differences when compared to itself', function() {
259 | computedStates[0].state = nestedOne;
260 | computedStates[1].state = nestedOne;
261 |
262 | const diff = diffState(computedStates, 1);
263 |
264 | expect(diff).to.be.an.array;
265 | expect(diff).to.have.length(0);
266 | });
267 |
268 | it('shows the property as removed when compared to an empty object', function() {
269 | computedStates[0].state = nestedOne;
270 | computedStates[1].state = empty;
271 |
272 | const diff = diffState(computedStates, 1);
273 |
274 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"noChange"');
275 | expect(JSON.stringify(diff[0].lhs)).eql('"same"');
276 | expect(JSON.stringify(diff[0].rhs)).to.be.undefined;
277 |
278 | expect(JSON.stringify(diff[1].path.join('.'))).to.eql('"levelOne"');
279 | expect(JSON.stringify(diff[1].lhs)).eql('{"levelTwo":"value"}');
280 | expect(JSON.stringify(diff[1].rhs)).be.undefined;
281 | });
282 |
283 | it('shows the property is changed when compared to an object that has value', function() {
284 | computedStates[0].state = nestedOne;
285 | computedStates[1].state = nestedTwo;
286 |
287 | const diff = diffState(computedStates, 1);
288 |
289 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"levelOne.levelTwo"');
290 | expect(JSON.stringify(diff[0].lhs)).eql('"value"');
291 | expect(JSON.stringify(diff[0].rhs)).eql('"another value"');
292 | });
293 |
294 | it('shows the property as added when compared to an empty object on left', function() {
295 | computedStates[0].state = empty;
296 | computedStates[1].state = nestedOne;
297 |
298 | const diff = diffState(computedStates, 1);
299 |
300 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"noChange"');
301 | expect(JSON.stringify(diff[0].lhs)).be.undefined;
302 | expect(JSON.stringify(diff[0].rhs)).eql('"same"');
303 |
304 | expect(JSON.stringify(diff[1].path.join('.'))).to.eql('"levelOne"');
305 | expect(JSON.stringify(diff[1].lhs)).to.be.undefined;
306 | expect(JSON.stringify(diff[1].rhs)).eql('{"levelTwo":"value"}');
307 | });
308 | });
309 |
310 | describe('Working with arrays', () => {
311 |
312 | it('should diff items changed in an array', () => {
313 | computedStates[0].state = [1, 2, 3];
314 | computedStates[1].state = [2, 3, 4];
315 |
316 | const diff = diffState(computedStates, 1);
317 |
318 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"0"');
319 | expect(JSON.stringify(diff[0].lhs)).to.eql('1');
320 | expect(JSON.stringify(diff[0].rhs)).eql('2');
321 |
322 | expect(JSON.stringify(diff[1].path.join('.'))).to.eql('"1"');
323 | expect(JSON.stringify(diff[1].lhs)).to.eql('2');
324 | expect(JSON.stringify(diff[1].rhs)).eql('3');
325 |
326 | expect(JSON.stringify(diff[2].path.join('.'))).to.eql('"2"');
327 | expect(JSON.stringify(diff[2].lhs)).to.eql('3');
328 | expect(JSON.stringify(diff[2].rhs)).eql('4');
329 | });
330 |
331 | it('should diff items changed in an array inside an object', () => {
332 | computedStates[0].state = {
333 | a: [1, 2, 3]
334 | };
335 | computedStates[1].state = {
336 | a: [2, 3, 4]
337 | };
338 |
339 | const diff = diffState(computedStates, 1);
340 |
341 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"a.0"');
342 | expect(JSON.stringify(diff[0].lhs)).to.eql('1');
343 | expect(JSON.stringify(diff[0].rhs)).eql('2');
344 |
345 | expect(JSON.stringify(diff[1].path.join('.'))).to.eql('"a.1"');
346 | expect(JSON.stringify(diff[1].lhs)).to.eql('2');
347 | expect(JSON.stringify(diff[1].rhs)).eql('3');
348 |
349 | expect(JSON.stringify(diff[2].path.join('.'))).to.eql('"a.2"');
350 | expect(JSON.stringify(diff[2].lhs)).to.eql('3');
351 | expect(JSON.stringify(diff[2].rhs)).eql('4');
352 | });
353 |
354 | it('should diff when item removed from array', () => {
355 | computedStates[0].state = [1, 2, 3];
356 | computedStates[1].state = [2, 3];
357 |
358 | const diff = diffState(computedStates, 1);
359 |
360 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"0"');
361 | expect(JSON.stringify(diff[0].lhs)).to.eql('1');
362 | expect(JSON.stringify(diff[0].rhs)).eql('2');
363 |
364 | expect(JSON.stringify(diff[1].path.join('.'))).to.eql('"1"');
365 | expect(JSON.stringify(diff[1].lhs)).to.eql('2');
366 | expect(JSON.stringify(diff[1].rhs)).eql('3');
367 |
368 | expect(JSON.stringify(diff[2].index)).to.eql('2');
369 | expect(JSON.stringify(diff[2].item.lhs)).to.eql('3');
370 | expect(JSON.stringify(diff[2].item.rhs)).be.undefined;
371 | });
372 |
373 | it('should diff item removed from an array inside an object', () => {
374 | computedStates[0].state = {
375 | a: [1, 2, 3]
376 | };
377 | computedStates[1].state = {
378 | a: [2, 3]
379 | };
380 |
381 | const diff = diffState(computedStates, 1);
382 |
383 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"a.0"');
384 | expect(JSON.stringify(diff[0].lhs)).to.eql('1');
385 | expect(JSON.stringify(diff[0].rhs)).eql('2');
386 |
387 | expect(JSON.stringify(diff[1].path.join('.'))).to.eql('"a.1"');
388 | expect(JSON.stringify(diff[1].lhs)).to.eql('2');
389 | expect(JSON.stringify(diff[1].rhs)).eql('3');
390 |
391 | expect(JSON.stringify(diff[2].path.join('.'))).to.eql('"a"');
392 | expect(JSON.stringify(diff[2].index)).to.eql('2');
393 | expect(JSON.stringify(diff[2].item.lhs)).to.eql('3');
394 | expect(JSON.stringify(diff[2].item.rhs)).be.undefined;
395 | });
396 |
397 | it('should diff items added to an array', () => {
398 | computedStates[0].state = [1, 2];
399 | computedStates[1].state = [1, 2, 3];
400 |
401 | const diff = diffState(computedStates, 1);
402 |
403 | expect(JSON.stringify(diff[0].index)).to.eql('2');
404 | expect(JSON.stringify(diff[0].item.lhs)).to.be.undefined;
405 | expect(JSON.stringify(diff[0].item.rhs)).eql('3');
406 | });
407 |
408 | it('should diff item added to an array inside an object', () => {
409 | computedStates[0].state = {
410 | a: [1, 2]
411 | };
412 | computedStates[1].state = {
413 | a: [2, 3, 4]
414 | };
415 |
416 | const diff = diffState(computedStates, 1);
417 |
418 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"a.0"');
419 | expect(JSON.stringify(diff[0].lhs)).to.eql('1');
420 | expect(JSON.stringify(diff[0].rhs)).eql('2');
421 |
422 | expect(JSON.stringify(diff[1].path.join('.'))).to.eql('"a.1"');
423 | expect(JSON.stringify(diff[1].lhs)).to.eql('2');
424 | expect(JSON.stringify(diff[1].rhs)).eql('3');
425 |
426 | expect(JSON.stringify(diff[2].path.join('.'))).to.eql('"a"');
427 | expect(JSON.stringify(diff[2].index)).to.eql('2');
428 | expect(JSON.stringify(diff[2].item.lhs)).to.be.undefined;
429 | expect(JSON.stringify(diff[2].item.rhs)).to.eql('4');
430 | });
431 | });
432 |
433 | });
434 |
435 | describe('ImmutableJS data', () => {
436 | let computedStates = [{}, {}];
437 |
438 | const empty = Immutable.Map();
439 |
440 | describe('A target that has no properties', () => {
441 | computedStates[0].state = empty;
442 |
443 | it('shows no differences when compared to another empty object', () => {
444 | computedStates[1].state = Immutable.Map();
445 |
446 | const diff = diffState(computedStates, 1);
447 |
448 | expect(diff).to.be.an('array');
449 | expect(diff).to.have.length(0);
450 | });
451 | });
452 |
453 | describe('when compared to a different type of keyless object', () => {
454 | const aDate = new Date();
455 |
456 | const comparandTuples = [
457 | ['an array', {
458 | key: Immutable.fromJS([])
459 | }],
460 | ['an object', {
461 | key: Immutable.fromJS({})
462 | }],
463 | ['a date', {
464 | key: Immutable.fromJS(aDate)
465 | }],
466 | ['a null', {
467 | key: Immutable.fromJS(null)
468 | }],
469 | ['a regexp literal', {
470 | key: Immutable.fromJS(/a/)
471 | }]
472 | ];
473 |
474 | comparandTuples.forEach(function(lhsTuple) {
475 | comparandTuples.forEach(function(rhsTuple) {
476 | if (lhsTuple[0] === rhsTuple[0]) {
477 | return;
478 | }
479 |
480 | it('shows differences when comparing ' + lhsTuple[0] + ' to ' + rhsTuple[0], () => {
481 | computedStates[0].state = lhsTuple[1];
482 | computedStates[1].state = rhsTuple[1];
483 |
484 | const diff = diffState(computedStates, 1);
485 |
486 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"key"');
487 |
488 | if (lhsTuple[0] === comparandTuples[0][0]) {
489 | expect(JSON.stringify(diff[0].lhs)).to.eql('[]');
490 | } else if (lhsTuple[0] === comparandTuples[1][0]) {
491 | expect(JSON.stringify(diff[0].lhs)).to.eql('{}');
492 | } else if (lhsTuple[0] === comparandTuples[2][0]) {
493 | expect(JSON.stringify(diff[0].lhs)).to.eql('"' + aDate.toISOString() + '"');
494 | } else if (lhsTuple[0] === comparandTuples[3][0]) {
495 | expect(JSON.stringify(diff[0].lhs)).to.eql('null');
496 | }
497 |
498 | if (rhsTuple[0] === comparandTuples[0][0]) {
499 | expect(JSON.stringify(diff[0].rhs)).to.eql('[]');
500 | } else if (rhsTuple[0] === comparandTuples[1][0]) {
501 | expect(JSON.stringify(diff[0].rhs)).to.eql('{}');
502 | } else if (rhsTuple[0] === comparandTuples[2][0]) {
503 | expect(JSON.stringify(diff[0].rhs)).to.eql('"' + aDate.toISOString() + '"');
504 | } else if (rhsTuple[0] === comparandTuples[3][0]) {
505 | expect(JSON.stringify(diff[0].rhs)).to.eql('null');
506 | }
507 | });
508 | });
509 | });
510 | });
511 |
512 | describe('when compared with an object having other properties', () => {
513 | computedStates[0].state = empty;
514 | computedStates[1].state = Immutable.fromJS({
515 | other: 'property',
516 | another: 13.13
517 | });
518 |
519 | const diff = diffState(computedStates, 1);
520 |
521 | it('the differences are reported', () => {
522 |
523 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"other"');
524 | expect(JSON.stringify(diff[0].lhs)).be.undefined;
525 | expect(JSON.stringify(diff[0].rhs)).eql('"property"');
526 |
527 | expect(JSON.stringify(diff[1].path.join('.'))).to.eql('"another"');
528 | expect(JSON.stringify(diff[1].lhs)).be.undefined;
529 | expect(JSON.stringify(diff[1].rhs)).eql('13.13');
530 | });
531 |
532 | });
533 |
534 | describe('A target that has one property', function() {
535 | const lhs = Immutable.fromJS({
536 | one: 'property'
537 | });
538 |
539 | it('shows no differences when compared to itself', function() {
540 | computedStates[0].state = lhs;
541 | computedStates[1].state = lhs;
542 |
543 | const diff = diffState(computedStates, 1);
544 | expect(diff).to.be.an.array;
545 | expect(diff).to.have.length(0);
546 | });
547 |
548 | it('shows the property as removed when compared to an empty object', function() {
549 | computedStates[0].state = lhs;
550 | computedStates[1].state = empty;
551 |
552 | const diff = diffState(computedStates, 1);
553 |
554 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"one"');
555 | expect(JSON.stringify(diff[0].lhs)).eql('"property"');
556 | expect(JSON.stringify(diff[0].rhs)).be.undefined;
557 | });
558 |
559 | it('shows the property as edited when compared to an object with null', function() {
560 | computedStates[0].state = lhs;
561 | computedStates[1].state = Immutable.fromJS({
562 | one: null
563 | });
564 |
565 | const diff = diffState(computedStates, 1);
566 |
567 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"one"');
568 | expect(JSON.stringify(diff[0].lhs)).eql('"property"');
569 | expect(JSON.stringify(diff[0].rhs)).eql('null');
570 | });
571 |
572 | it('shows the property as edited when compared to an array', function() {
573 | computedStates[0].state = lhs;
574 | computedStates[1].state = Immutable.fromJS(['one']);
575 |
576 | const diff = diffState(computedStates, 1);
577 |
578 | expect(diff[0].path).to.be.undefined;
579 | expect(JSON.stringify(diff[0].lhs)).eql('{"one":"property"}');
580 | expect(JSON.stringify(diff[0].rhs)).eql('["one"]');
581 | });
582 |
583 | });
584 |
585 | describe('A target that has null value', function() {
586 | const lhs = Immutable.fromJS({
587 | key: null
588 | });
589 |
590 | it('shows no differences when compared to itself', function() {
591 | computedStates[0].state = lhs;
592 | computedStates[1].state = lhs;
593 |
594 | const diff = diffState(computedStates, 1);
595 |
596 | expect(diff).to.be.an.array;
597 | expect(diff).to.have.length(0);
598 | });
599 |
600 | it('shows the property as removed when compared to an empty object', function() {
601 | computedStates[0].state = lhs;
602 | computedStates[1].state = empty;
603 |
604 | const diff = diffState(computedStates, 1);
605 |
606 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"key"');
607 | expect(JSON.stringify(diff[0].lhs)).eql('null');
608 | expect(JSON.stringify(diff[0].rhs)).be.undefined;
609 | });
610 |
611 | it('shows the property is changed when compared to an object that has value', function() {
612 | computedStates[0].state = lhs;
613 | computedStates[1].state = Immutable.fromJS({
614 | key: 'value'
615 | });
616 |
617 | const diff = diffState(computedStates, 1);
618 |
619 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"key"');
620 | expect(JSON.stringify(diff[0].lhs)).eql('null');
621 | expect(JSON.stringify(diff[0].rhs)).eql('"value"');
622 | });
623 |
624 | it('shows that an object property is changed when it is set to null', function() {
625 | computedStates[0].state = lhs.set('key', {
626 | nested: 'value'
627 | });
628 | computedStates[1].state = Immutable.fromJS({
629 | key: null
630 | });
631 |
632 | const diff = diffState(computedStates, 1);
633 |
634 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"key"');
635 | expect(JSON.stringify(diff[0].lhs)).eql('{"nested":"value"}');
636 | expect(JSON.stringify(diff[0].rhs)).eql('null');
637 | });
638 |
639 | });
640 |
641 |
642 | describe('A target that has a NaN', function() {
643 | const lhs = Immutable.fromJS({
644 | key: NaN
645 | });
646 |
647 | it('shows the property is changed when compared to another number', function() {
648 | computedStates[0].state = lhs;
649 | computedStates[1].state = Immutable.fromJS({
650 | key: 0
651 | });
652 |
653 | const diff = diffState(computedStates, 1);
654 |
655 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"key"');
656 | expect(JSON.stringify(diff[0].lhs)).eql('null');
657 | expect(JSON.stringify(diff[0].rhs)).eql('0');
658 | });
659 |
660 | it('shows no differences when compared to another NaN', function() {
661 | computedStates[0].state = lhs;
662 | computedStates[1].state = Immutable.fromJS({
663 | key: NaN
664 | });
665 |
666 | const diff = diffState(computedStates, 1);
667 |
668 | expect(diff).to.be.an.array;
669 | expect(diff).to.have.length(0);
670 | });
671 |
672 | });
673 |
674 | describe('A target that has nested values', function() {
675 | const nestedOne = Immutable.fromJS({
676 | noChange: 'same',
677 | levelOne: {
678 | levelTwo: 'value'
679 | }
680 | });
681 | const nestedTwo = Immutable.fromJS({
682 | noChange: 'same',
683 | levelOne: {
684 | levelTwo: 'another value'
685 | }
686 | });
687 |
688 | it('shows no differences when compared to itself', function() {
689 | computedStates[0].state = nestedOne;
690 | computedStates[1].state = nestedOne;
691 |
692 | const diff = diffState(computedStates, 1);
693 |
694 | expect(diff).to.be.an.array;
695 | expect(diff).to.have.length(0);
696 | });
697 |
698 | it('shows the property as removed when compared to an empty object', function() {
699 | computedStates[0].state = nestedOne;
700 | computedStates[1].state = empty;
701 |
702 | const diff = diffState(computedStates, 1);
703 |
704 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"noChange"');
705 | expect(JSON.stringify(diff[0].lhs)).eql('"same"');
706 | expect(JSON.stringify(diff[0].rhs)).to.be.undefined;
707 |
708 | expect(JSON.stringify(diff[1].path.join('.'))).to.eql('"levelOne"');
709 | expect(JSON.stringify(diff[1].lhs)).eql('{"levelTwo":"value"}');
710 | expect(JSON.stringify(diff[1].rhs)).be.undefined;
711 | });
712 |
713 | it('shows the property is changed when compared to an object that has value', function() {
714 | computedStates[0].state = nestedOne;
715 | computedStates[1].state = nestedTwo;
716 |
717 | const diff = diffState(computedStates, 1);
718 |
719 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"levelOne.levelTwo"');
720 | expect(JSON.stringify(diff[0].lhs)).eql('"value"');
721 | expect(JSON.stringify(diff[0].rhs)).eql('"another value"');
722 | });
723 |
724 | it('shows the property as added when compared to an empty object on left', function() {
725 | computedStates[0].state = empty;
726 | computedStates[1].state = nestedOne;
727 |
728 | const diff = diffState(computedStates, 1);
729 |
730 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"noChange"');
731 | expect(JSON.stringify(diff[0].lhs)).be.undefined;
732 | expect(JSON.stringify(diff[0].rhs)).eql('"same"');
733 |
734 | expect(JSON.stringify(diff[1].path.join('.'))).to.eql('"levelOne"');
735 | expect(JSON.stringify(diff[1].lhs)).to.be.undefined;
736 | expect(JSON.stringify(diff[1].rhs)).eql('{"levelTwo":"value"}');
737 | });
738 | });
739 |
740 | describe('Immutable data in plain objects', function() {
741 |
742 | describe('Single level Immutable objects one level deep in plain object', () => {
743 |
744 | const nestedOne = {
745 | a: Immutable.fromJS({
746 | one: 'something'
747 | })
748 | };
749 |
750 | const nestedTwo = {
751 | a: Immutable.fromJS({
752 | one: 'somethingElse'
753 | })
754 | };
755 |
756 | it('shows the property is changed when compared to an object that has value', () => {
757 | computedStates[0].state = nestedOne;
758 | computedStates[1].state = nestedTwo;
759 |
760 | const diff = diffState(computedStates, 1);
761 |
762 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"a.one"');
763 | expect(JSON.stringify(diff[0].lhs)).eql('"something"');
764 | expect(JSON.stringify(diff[0].rhs)).eql('"somethingElse"');
765 | });
766 | });
767 |
768 | describe('Nested Immutable objects one level deep in plain object', () => {
769 |
770 | const nestedOne = {
771 | a: Immutable.fromJS({
772 | one: {
773 | two: 'something'
774 | }
775 | })
776 | };
777 |
778 | const nestedTwo = {
779 | a: Immutable.fromJS({
780 | one: {
781 | two: 'somethingElse'
782 | }
783 | })
784 | };
785 |
786 | const nestedThree = {
787 | a: Immutable.fromJS({
788 | one: {
789 | two: 'somethingElse'
790 | },
791 | three: {
792 | four: "cheese"
793 | }
794 | })
795 | };
796 |
797 | it('shows the property is changed when compared to an object that has value', () => {
798 | computedStates[0].state = nestedOne;
799 | computedStates[1].state = nestedTwo;
800 |
801 | const diff = diffState(computedStates, 1);
802 |
803 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"a.one.two"');
804 | expect(JSON.stringify(diff[0].lhs)).eql('"something"');
805 | expect(JSON.stringify(diff[0].rhs)).eql('"somethingElse"');
806 | });
807 |
808 | it('shows properties change when compared to an object that has value', () => {
809 | computedStates[0].state = nestedOne;
810 | computedStates[1].state = nestedThree;
811 |
812 | const diff = diffState(computedStates, 1);
813 |
814 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"a.one.two"');
815 | expect(JSON.stringify(diff[0].lhs)).eql('"something"');
816 | expect(JSON.stringify(diff[0].rhs)).eql('"somethingElse"');
817 |
818 | expect(JSON.stringify(diff[1].path.join('.'))).to.eql('"a.three"');
819 | expect(JSON.stringify(diff[1].lhs)).to.be.undefined;
820 | expect(JSON.stringify(diff[1].rhs)).eql('{"four":"cheese"}');
821 | })
822 | });
823 | });
824 |
825 | describe('Working with arrays', () => {
826 |
827 | it('should diff items changed in an array', () => {
828 | computedStates[0].state = Immutable.List([1, 2, 3]);
829 | computedStates[1].state = Immutable.List([2, 3, 4]);
830 |
831 | const diff = diffState(computedStates, 1);
832 |
833 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"0"');
834 | expect(JSON.stringify(diff[0].lhs)).to.eql('1');
835 | expect(JSON.stringify(diff[0].rhs)).eql('2');
836 |
837 | expect(JSON.stringify(diff[1].path.join('.'))).to.eql('"1"');
838 | expect(JSON.stringify(diff[1].lhs)).to.eql('2');
839 | expect(JSON.stringify(diff[1].rhs)).eql('3');
840 |
841 | expect(JSON.stringify(diff[2].path.join('.'))).to.eql('"2"');
842 | expect(JSON.stringify(diff[2].lhs)).to.eql('3');
843 | expect(JSON.stringify(diff[2].rhs)).eql('4');
844 | });
845 |
846 | it('should diff items changed in an array inside an object', () => {
847 | computedStates[0].state = {
848 | a: Immutable.List([1, 2, 3])
849 | };
850 | computedStates[1].state = {
851 | a: Immutable.List([2, 3, 4])
852 | };
853 |
854 | const diff = diffState(computedStates, 1);
855 |
856 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"a.0"');
857 | expect(JSON.stringify(diff[0].lhs)).to.eql('1');
858 | expect(JSON.stringify(diff[0].rhs)).eql('2');
859 |
860 | expect(JSON.stringify(diff[1].path.join('.'))).to.eql('"a.1"');
861 | expect(JSON.stringify(diff[1].lhs)).to.eql('2');
862 | expect(JSON.stringify(diff[1].rhs)).eql('3');
863 |
864 | expect(JSON.stringify(diff[2].path.join('.'))).to.eql('"a.2"');
865 | expect(JSON.stringify(diff[2].lhs)).to.eql('3');
866 | expect(JSON.stringify(diff[2].rhs)).eql('4');
867 | });
868 |
869 | it('should diff items changed in an array inside a map', () => {
870 | computedStates[0].state = Immutable.Map({
871 | a: [1, 2, 3]
872 | });
873 | computedStates[1].state = Immutable.Map({
874 | a: [2, 3, 4]
875 | });
876 |
877 | const diff = diffState(computedStates, 1);
878 |
879 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"a.0"');
880 | expect(JSON.stringify(diff[0].lhs)).to.eql('1');
881 | expect(JSON.stringify(diff[0].rhs)).eql('2');
882 |
883 | expect(JSON.stringify(diff[1].path.join('.'))).to.eql('"a.1"');
884 | expect(JSON.stringify(diff[1].lhs)).to.eql('2');
885 | expect(JSON.stringify(diff[1].rhs)).eql('3');
886 |
887 | expect(JSON.stringify(diff[2].path.join('.'))).to.eql('"a.2"');
888 | expect(JSON.stringify(diff[2].lhs)).to.eql('3');
889 | expect(JSON.stringify(diff[2].rhs)).eql('4');
890 | });
891 |
892 | it('should diff when item removed from array', () => {
893 | computedStates[0].state = Immutable.List([1, 2, 3]);
894 | computedStates[1].state = Immutable.List([2, 3]);
895 |
896 | const diff = diffState(computedStates, 1);
897 |
898 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"0"');
899 | expect(JSON.stringify(diff[0].lhs)).to.eql('1');
900 | expect(JSON.stringify(diff[0].rhs)).eql('2');
901 |
902 | expect(JSON.stringify(diff[1].path.join('.'))).to.eql('"1"');
903 | expect(JSON.stringify(diff[1].lhs)).to.eql('2');
904 | expect(JSON.stringify(diff[1].rhs)).eql('3');
905 |
906 | expect(JSON.stringify(diff[2].index)).to.eql('2');
907 | expect(JSON.stringify(diff[2].item.lhs)).to.eql('3');
908 | expect(JSON.stringify(diff[2].item.rhs)).be.undefined;
909 | });
910 |
911 | it('should diff item removed from an array inside an object', () => {
912 | computedStates[0].state = {
913 | a: Immutable.List([1, 2, 3])
914 | };
915 | computedStates[1].state = {
916 | a: Immutable.List([2, 3])
917 | };
918 |
919 | const diff = diffState(computedStates, 1);
920 |
921 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"a.0"');
922 | expect(JSON.stringify(diff[0].lhs)).to.eql('1');
923 | expect(JSON.stringify(diff[0].rhs)).eql('2');
924 |
925 | expect(JSON.stringify(diff[1].path.join('.'))).to.eql('"a.1"');
926 | expect(JSON.stringify(diff[1].lhs)).to.eql('2');
927 | expect(JSON.stringify(diff[1].rhs)).eql('3');
928 |
929 | expect(JSON.stringify(diff[2].path.join('.'))).to.eql('"a"');
930 | expect(JSON.stringify(diff[2].index)).to.eql('2');
931 | expect(JSON.stringify(diff[2].item.lhs)).to.eql('3');
932 | expect(JSON.stringify(diff[2].item.rhs)).be.undefined;
933 | });
934 |
935 | it('should diff items added to an array', () => {
936 | computedStates[0].state = Immutable.List([1, 2]);
937 | computedStates[1].state = Immutable.List([2, 3, 4]);
938 |
939 | const diff = diffState(computedStates, 1);
940 |
941 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"0"');
942 | expect(JSON.stringify(diff[0].lhs)).to.eql('1');
943 | expect(JSON.stringify(diff[0].rhs)).eql('2');
944 |
945 | expect(JSON.stringify(diff[1].path.join('.'))).to.eql('"1"');
946 | expect(JSON.stringify(diff[1].lhs)).to.eql('2');
947 | expect(JSON.stringify(diff[1].rhs)).eql('3');
948 |
949 | expect(JSON.stringify(diff[2].index)).to.eql('2');
950 | expect(JSON.stringify(diff[2].item.lhs)).to.be.undefined;
951 | expect(JSON.stringify(diff[2].item.rhs)).eql('4');
952 | });
953 |
954 | it('should diff item added to an array inside an object', () => {
955 | computedStates[0].state = {
956 | a: Immutable.List([1, 2])
957 | };
958 | computedStates[1].state = {
959 | a: Immutable.List([2, 3, 4])
960 | };
961 |
962 | const diff = diffState(computedStates, 1);
963 |
964 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"a.0"');
965 | expect(JSON.stringify(diff[0].lhs)).to.eql('1');
966 | expect(JSON.stringify(diff[0].rhs)).eql('2');
967 |
968 | expect(JSON.stringify(diff[1].path.join('.'))).to.eql('"a.1"');
969 | expect(JSON.stringify(diff[1].lhs)).to.eql('2');
970 | expect(JSON.stringify(diff[1].rhs)).eql('3');
971 |
972 | expect(JSON.stringify(diff[2].path.join('.'))).to.eql('"a"');
973 | expect(JSON.stringify(diff[2].index)).to.eql('2');
974 | expect(JSON.stringify(diff[2].item.lhs)).to.be.undefined;
975 | expect(JSON.stringify(diff[2].item.rhs)).to.eql('4');
976 | });
977 |
978 | it('should diff complex object', () => {
979 | computedStates[0].state = Immutable.Map({
980 | ids: [],
981 | turn: 0,
982 | round: 0
983 | });
984 | computedStates[1].state = Immutable.Map({
985 | ids: [2,3],
986 | turn:1,
987 | round: 1
988 | });
989 |
990 | const diff = diffState(computedStates, 1);
991 |
992 | expect(JSON.stringify(diff[0].path.join('.'))).to.eql('"ids"');
993 | expect(JSON.stringify(diff[0].index)).to.eql('0');
994 | expect(JSON.stringify(diff[0].item.lhs)).to.be.undefined;
995 | expect(JSON.stringify(diff[0].item.rhs)).eql('2');
996 |
997 | expect(JSON.stringify(diff[1].path.join('.'))).to.eql('"ids"');
998 | expect(JSON.stringify(diff[1].index)).to.eql('1');
999 | expect(JSON.stringify(diff[1].item.lhs)).to.be.undefined;
1000 | expect(JSON.stringify(diff[1].item.rhs)).eql('3');
1001 |
1002 | expect(JSON.stringify(diff[2].path.join('.'))).to.eql('"turn"');
1003 | expect(JSON.stringify(diff[2].lhs)).to.eql('0');
1004 | expect(JSON.stringify(diff[2].rhs)).to.eql('1');
1005 |
1006 | expect(JSON.stringify(diff[3].path.join('.'))).to.eql('"round"');
1007 | expect(JSON.stringify(diff[3].lhs)).to.eql('0');
1008 | expect(JSON.stringify(diff[3].rhs)).to.eql('1');
1009 | });
1010 | });
1011 | });
1012 | });
--------------------------------------------------------------------------------