src/Oro/Bundle/UIBundle/Tests/JS/app/models/sync-machine-proxy-cacheSpec.js   F
last analyzed

Complexity

Total Complexity 101
Complexity/F 2.1

Size

Lines of Code 231
Function Count 48

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 0
wmc 101
nc 1
mnd 0
bc 48
fnc 48
dl 0
loc 231
rs 3.12
bpm 1
cpm 2.1041
noi 7
c 0
b 0
f 0

How to fix   Complexity   

Complexity

Complex classes like src/Oro/Bundle/UIBundle/Tests/JS/app/models/sync-machine-proxy-cacheSpec.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
define(function(require) {
2
    'use strict';
3
4
    var _ = require('underscore');
5
    var Backbone = require('backbone');
6
    var SyncMachineProxyCache = require('oroui/js/app/models/sync-machine-proxy-cache');
7
    var exposure = require('requirejs-exposure').disclose('oroui/js/app/models/sync-machine-proxy-cache');
8
9
    describe('oroui/js/app/models/sync-machine-proxy-cache', function() {
10
        var instance;
11
        var storedData;
12
        var storageMock;
13
        var errorHandlerMock;
14
        var storageKey;
15
        var expireTime;
16
17
        beforeEach(function() {
18
            instance = _.extend(Object.create(Backbone.Events), SyncMachineProxyCache);
19
            instance.SYNC_MACHINE_PROXY_CACHE_STORAGE_KEY = storageKey = 'test';
20
            instance.SYNC_MACHINE_PROXY_CACHE_EXPIRE_TIME = expireTime = 1000;
21
            instance.set = jasmine.createSpy('set');
0 ignored issues
show
Bug introduced by
The variable jasmine seems to be never declared. If this is a global, consider adding a /** global: jasmine */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
22
            instance.fetch = function() {
23
                return {then: jasmine.createSpy('then')};
0 ignored issues
show
Bug introduced by
The variable jasmine seems to be never declared. If this is a global, consider adding a /** global: jasmine */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
24
            };
25
            spyOn(instance, 'fetch').and.callThrough();
26
            spyOn(instance, 'once').and.callThrough();
27
            spyOn(instance, 'trigger').and.callThrough();
28
29
            storedData = {};
30
            storageMock = {
31
                getItem: function(key) {
32
                    return storedData[key];
33
                },
34
                setItem: function(key, value) {
35
                    storedData[key] = value;
36
                }
37
            };
38
            spyOn(storageMock, 'getItem').and.callThrough();
39
            spyOn(storageMock, 'setItem').and.callThrough();
40
            exposure.substitute('persistentStorage').by(storageMock);
41
42
            errorHandlerMock = jasmine.createSpyObj('errorHandler', ['showErrorInConsole']);
0 ignored issues
show
Bug introduced by
The variable jasmine seems to be never declared. If this is a global, consider adding a /** global: jasmine */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
43
            exposure.substitute('errorHandler').by(errorHandlerMock);
44
        });
45
46
        afterEach(function() {
47
            storedData = {};
48
            exposure.recover('persistentStorage');
49
            exposure.recover('errorHandler');
50
        });
51
52
        describe('improperly implemented SyncMachineProxyCache', function() {
53
            it('missing SYNC_MACHINE_PROXY_CACHE_STORAGE_KEY property', function() {
54
                delete instance.SYNC_MACHINE_PROXY_CACHE_STORAGE_KEY;
55
                instance.ensureSync();
56
                expect(errorHandlerMock.showErrorInConsole).toHaveBeenCalledWith(jasmine.any(Error));
0 ignored issues
show
Bug introduced by
The variable jasmine seems to be never declared. If this is a global, consider adding a /** global: jasmine */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
57
                expect(storageMock.getItem).not.toHaveBeenCalled();
58
            });
59
60
            it('missing SYNC_MACHINE_PROXY_CACHE_EXPIRE_TIME property', function() {
61
                delete instance.SYNC_MACHINE_PROXY_CACHE_EXPIRE_TIME;
62
                instance.ensureSync();
63
                expect(errorHandlerMock.showErrorInConsole).toHaveBeenCalledWith(jasmine.any(Error));
0 ignored issues
show
Bug introduced by
The variable jasmine seems to be never declared. If this is a global, consider adding a /** global: jasmine */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
64
                expect(storageMock.getItem).not.toHaveBeenCalled();
65
            });
66
        });
67
68
        describe('only unsynced instance reads from cache', function() {
69
            var cases = [
70
                [SyncMachineProxyCache.SYNCING],
71
                [SyncMachineProxyCache.SYNCED],
72
                [SyncMachineProxyCache.STATE_CHANGE]
73
            ];
74
75
            cases.forEach(function(testCase) {
76
                it(testCase[0] + ' instance does not read from cache', function() {
77
                    instance._syncState = testCase[0];
78
                    instance.ensureSync();
79
                    expect(storageMock.getItem).not.toHaveBeenCalled();
80
                });
81
            });
82
        });
83
84
        describe('empty cache', function() {
85
            beforeEach(function() {
86
                instance.ensureSync();
87
            });
88
89
            it('attempt to read from empty cache', function() {
90
                expect(storageMock.getItem).toHaveBeenCalled();
91
            });
92
93
            it('no data set into instance from cache', function() {
94
                expect(instance.set).not.toHaveBeenCalled();
95
            });
96
97
            describe('handle load of remote data', function() {
98
                beforeEach(function(done) {
99
                    // simulate data sync action
100
                    setTimeout(function() {
101
                        instance.trigger('sync', instance, {foo: 'bar'});
102
                        done();
103
                    });
104
                });
105
106
                it('set sync data to cache as JSON string with proper key', function() {
107
                    expect(storageMock.setItem).toHaveBeenCalledWith(storageKey, jasmine.any(String));
0 ignored issues
show
Bug introduced by
The variable jasmine seems to be never declared. If this is a global, consider adding a /** global: jasmine */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
108
                });
109
110
                it('cached JSON string is well formatted and corresponds to sync data', function() {
111
                    var data;
112
113
                    expect(function() {
114
                        data = JSON.parse(storageMock.setItem.calls.mostRecent().args[1]);
115
                    }).not.toThrowError();
116
117
                    expect(data).toEqual({
118
                        time: jasmine.any(Number),
0 ignored issues
show
Bug introduced by
The variable jasmine seems to be never declared. If this is a global, consider adding a /** global: jasmine */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
119
                        data: {foo: 'bar'}
120
                    });
121
                });
122
123
                it('no event triggered about stale data in use', function() {
124
                    expect(instance.trigger.calls.mostRecent().args)
125
                        .not.toEqual(['proxy-cache:stale-data-in-use', instance]);
126
                });
127
            });
128
        });
129
130
        describe('malformed data in cache', function() {
131
            beforeEach(function() {
132
                storedData[storageKey] = 'qee';
133
                instance.ensureSync();
134
            });
135
136
            it('attempt to read from malformed data from cache', function() {
137
                expect(storageMock.getItem).toHaveBeenCalled();
138
            });
139
140
            it('no data set into instance from cache', function() {
141
                expect(instance.set).not.toHaveBeenCalled();
142
            });
143
        });
144
145
        describe('expired data in cache', function() {
146
            beforeEach(function() {
147
                storedData[storageKey] = JSON.stringify({
148
                    time: Date.now() - expireTime * 2,
149
                    data: {foo: 'bar'}
150
                });
151
                instance.ensureSync();
152
            });
153
154
            it('attempt to read from expired data from cache', function() {
155
                expect(storageMock.getItem).toHaveBeenCalled();
156
            });
157
158
            it('no data set into instance from cache', function() {
159
                expect(instance.set).not.toHaveBeenCalled();
160
            });
161
        });
162
163
        describe('data in cache', function() {
164
            var cacheTimeMark;
165
            beforeEach(function() {
166
                cacheTimeMark = Date.now();
167
                storedData[storageKey] = JSON.stringify({
168
                    time: cacheTimeMark,
169
                    data: {foo: 'bar'}
170
                });
171
                instance.ensureSync();
172
            });
173
174
            it('data from cache is set into instance', function() {
175
                expect(instance.set).toHaveBeenCalledWith({foo: 'bar'}, {parse: true});
176
            });
177
178
            describe('handle load of same remote data', function() {
179
                beforeEach(function(done) {
180
                    // simulate data sync action
181
                    setTimeout(function() {
182
                        instance.trigger('sync', instance, {foo: 'bar'});
183
                        done();
184
                    }, 1);
185
                });
186
187
                it('time mark of data  is updated in cache', function() {
188
                    var data = JSON.parse(storedData[storageKey]);
189
                    expect(data.time).toBeGreaterThan(cacheTimeMark);
190
                });
191
192
                it('no event triggered about stale data in use', function() {
193
                    expect(instance.trigger.calls.mostRecent().args)
194
                        .not.toEqual(['proxy-cache:stale-data-in-use', instance]);
195
                });
196
            });
197
198
            describe('handle load of changed remote data', function() {
199
                beforeEach(function(done) {
200
                    // simulate data sync action
201
                    setTimeout(function() {
202
                        instance.trigger('change'); // simulate change event of model
203
                        instance.trigger('sync', instance, {foo: 'diff'});
204
                        done();
205
                    });
206
                });
207
208
                it('triggered event about stale data in use', function() {
209
                    expect(instance.trigger.calls.mostRecent().args)
210
                        .toEqual(['proxy-cache:stale-data-in-use', instance]);
211
                });
212
            });
213
214
            describe('handle load of updated remote data', function() {
215
                beforeEach(function(done) {
216
                    // simulate data sync action
217
                    setTimeout(function() {
218
                        instance.trigger('update'); // simulate update event of collection
219
                        instance.trigger('sync', instance, [{foo: 'diff'}]);
220
                        done();
221
                    });
222
                });
223
224
                it('triggered event about stale data in use', function() {
225
                    expect(instance.trigger.calls.mostRecent().args)
226
                        .toEqual(['proxy-cache:stale-data-in-use', instance]);
227
                });
228
            });
229
        });
230
    });
231
});
232