modularity-rails 0.11.1 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/demo/spec/javascripts/data/ajax_loader_spec.coffee +136 -0
- data/demo/spec/javascripts/{tools → data}/cache_spec.coffee +19 -2
- data/demo/spec/javascripts/data/indexed_cache_spec.coffee +51 -0
- data/demo/spec/javascripts/data/persistence_manager_spec.coffee +276 -0
- data/demo/spec/javascripts/tools/object_tools_spec.coffee +27 -0
- data/lib/modularity-rails/version.rb +1 -1
- data/vendor/assets/javascripts/modularity/{tools → data}/ajax_loader.coffee +10 -3
- data/vendor/assets/javascripts/modularity/{tools → data}/cache.coffee +8 -2
- data/vendor/assets/javascripts/modularity/data/indexed_cache.coffee +26 -0
- data/vendor/assets/javascripts/modularity/data/persistence_manager.coffee +131 -0
- data/vendor/assets/javascripts/modularity/tools/object_tools.coffee +15 -0
- metadata +22 -16
- data/demo/spec/javascripts/tools/ajax_loader_spec.coffee +0 -79
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
#= require spec_helper
|
|
2
|
+
#= require modularity/data/ajax_loader
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
describe 'ajax_loader', ->
|
|
6
|
+
|
|
7
|
+
ajax_loader = spy = spy_get = null
|
|
8
|
+
beforeEach ->
|
|
9
|
+
spy = sinon.spy()
|
|
10
|
+
spy_get = sinon.spy jQuery, 'get'
|
|
11
|
+
|
|
12
|
+
afterEach ->
|
|
13
|
+
spy_get.restore()
|
|
14
|
+
|
|
15
|
+
describe 'constructor', ->
|
|
16
|
+
it "stores the 'cache' settings", ->
|
|
17
|
+
loader = new modularity.AjaxLoader {caching: yes}
|
|
18
|
+
loader.caching.should.be.true
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
describe 'get', ->
|
|
22
|
+
url = "/users/4"
|
|
23
|
+
|
|
24
|
+
describe 'with caching enabled', ->
|
|
25
|
+
|
|
26
|
+
beforeEach ->
|
|
27
|
+
ajax_loader = new modularity.AjaxLoader {caching: yes}
|
|
28
|
+
|
|
29
|
+
describe 'first time request', ->
|
|
30
|
+
|
|
31
|
+
beforeEach ->
|
|
32
|
+
ajax_loader.get url, spy
|
|
33
|
+
|
|
34
|
+
it 'makes an ajax request', ->
|
|
35
|
+
jQuery.get.should.have.been.called
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
it 'saves the callback for later', ->
|
|
39
|
+
ajax_loader.cache.get(url).should.have.length 1
|
|
40
|
+
ajax_loader.cache.get(url)[0].should.equal spy
|
|
41
|
+
|
|
42
|
+
it 'returns without calling the callback', ->
|
|
43
|
+
spy.should.not.have.been.called
|
|
44
|
+
|
|
45
|
+
describe 'the request is already in progress', ->
|
|
46
|
+
|
|
47
|
+
beforeEach ->
|
|
48
|
+
ajax_loader.cache.cache[url] = [spy]
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
it 'adds the callback to the callback array', ->
|
|
52
|
+
ajax_loader.cache.get(url).should.have.length 1
|
|
53
|
+
ajax_loader.cache.get(url)[0].should.equal spy
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
it 'returns without calling the callback', ->
|
|
57
|
+
spy.should.not.have.been.called
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
it 'does not make another ajax request', ->
|
|
61
|
+
jQuery.get.should.not.have.been.called
|
|
62
|
+
|
|
63
|
+
describe 'ajax request successful', ->
|
|
64
|
+
|
|
65
|
+
beforeEach ->
|
|
66
|
+
jquery_callback = null
|
|
67
|
+
jQuery.get = (url, callback) -> jquery_callback = callback
|
|
68
|
+
ajax_loader.get url, spy
|
|
69
|
+
jquery_callback('result')
|
|
70
|
+
|
|
71
|
+
it 'calls the given callbacks with the server data', ->
|
|
72
|
+
spy.should.have.been.calledWith 'result'
|
|
73
|
+
|
|
74
|
+
it 'replaces the cache callbacks with returned data', ->
|
|
75
|
+
ajax_loader.cache.get(url).should.equal 'result'
|
|
76
|
+
|
|
77
|
+
describe 'the data has already been loaded', ->
|
|
78
|
+
|
|
79
|
+
it 'calls the callback with the cached data', ->
|
|
80
|
+
ajax_loader.cache.add url, "my data"
|
|
81
|
+
|
|
82
|
+
ajax_loader.get(url, spy)
|
|
83
|
+
|
|
84
|
+
spy.should.have.been.called
|
|
85
|
+
spy.should.have.been.calledWith "my data"
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
describe 'with caching disabled', ->
|
|
89
|
+
|
|
90
|
+
beforeEach ->
|
|
91
|
+
ajax_loader = new modularity.AjaxLoader {caching: no}
|
|
92
|
+
|
|
93
|
+
describe 'first time request', ->
|
|
94
|
+
|
|
95
|
+
beforeEach ->
|
|
96
|
+
ajax_loader.get url, spy
|
|
97
|
+
|
|
98
|
+
it 'makes an ajax request', ->
|
|
99
|
+
jQuery.get.should.have.been.called
|
|
100
|
+
|
|
101
|
+
it 'saves the callback for later', ->
|
|
102
|
+
ajax_loader.cache.get(url).should.have.length 1
|
|
103
|
+
ajax_loader.cache.get(url)[0].should.equal spy
|
|
104
|
+
|
|
105
|
+
it 'returns without calling the callback', ->
|
|
106
|
+
spy.should.not.have.been.called
|
|
107
|
+
|
|
108
|
+
describe 'the request is already in progress', ->
|
|
109
|
+
|
|
110
|
+
beforeEach ->
|
|
111
|
+
ajax_loader.cache.cache[url] = [spy]
|
|
112
|
+
|
|
113
|
+
it 'adds the callback to the callback array', ->
|
|
114
|
+
ajax_loader.cache.get(url).should.have.length 1
|
|
115
|
+
ajax_loader.cache.get(url)[0].should.equal spy
|
|
116
|
+
|
|
117
|
+
it 'returns without calling the callback', ->
|
|
118
|
+
spy.should.not.have.been.called
|
|
119
|
+
|
|
120
|
+
it 'does not make another ajax request', ->
|
|
121
|
+
jQuery.get.should.not.have.been.called
|
|
122
|
+
|
|
123
|
+
describe 'ajax request successful', ->
|
|
124
|
+
|
|
125
|
+
beforeEach ->
|
|
126
|
+
jquery_callback = null
|
|
127
|
+
jQuery.get = (url, callback) -> jquery_callback = callback
|
|
128
|
+
ajax_loader.get url, spy
|
|
129
|
+
jquery_callback('result')
|
|
130
|
+
|
|
131
|
+
it 'calls the given callbacks with the server data', ->
|
|
132
|
+
spy.should.have.been.calledWith 'result'
|
|
133
|
+
|
|
134
|
+
it 'replaces the cache callbacks with returned data', ->
|
|
135
|
+
expect(ajax_loader.cache.get(url)).to.be.undefined
|
|
136
|
+
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#= require spec_helper
|
|
2
|
-
#= require modularity/
|
|
2
|
+
#= require modularity/data/cache
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
describe 'Cache', ->
|
|
@@ -18,7 +18,7 @@ describe 'Cache', ->
|
|
|
18
18
|
describe 'add', ->
|
|
19
19
|
|
|
20
20
|
it 'stores the given data in the cache', ->
|
|
21
|
-
cache.add
|
|
21
|
+
cache.add 'foo', 'bar'
|
|
22
22
|
cache.cache.should.eql({'foo': 'bar'})
|
|
23
23
|
|
|
24
24
|
it 'overwrites existing entries', ->
|
|
@@ -27,6 +27,23 @@ describe 'Cache', ->
|
|
|
27
27
|
(cache.cache['foo']).should.be.equal('new')
|
|
28
28
|
|
|
29
29
|
|
|
30
|
+
describe 'remove', ->
|
|
31
|
+
|
|
32
|
+
it 'removes the entry with the given key from the chache', ->
|
|
33
|
+
cache.add 'foo', 'bar'
|
|
34
|
+
cache.remove 'foo'
|
|
35
|
+
expect(cache.get('foo')).to.be.undefined
|
|
36
|
+
cache.length().should.equal 0
|
|
37
|
+
|
|
38
|
+
it 'only removes the given data and leaves the rest of the cache alone', ->
|
|
39
|
+
cache.add 1, 'one'
|
|
40
|
+
cache.add 2, 'two'
|
|
41
|
+
cache.remove 1
|
|
42
|
+
expect(cache.get(1)).to.be.undefined
|
|
43
|
+
expect(cache.get(2)).to.equal 'two'
|
|
44
|
+
cache.length().should.equal 1
|
|
45
|
+
|
|
46
|
+
|
|
30
47
|
describe 'get', ->
|
|
31
48
|
|
|
32
49
|
it "returns undefined if the entry doesn't exist", ->
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#= require spec_helper
|
|
2
|
+
#= require modularity/data/indexed_cache
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
describe 'IndexedCache', ->
|
|
6
|
+
|
|
7
|
+
indexed_cache = null
|
|
8
|
+
entry_1 = {id: 1, value: 'one'}
|
|
9
|
+
entry_2 = {id: 2, value: 'two'}
|
|
10
|
+
beforeEach ->
|
|
11
|
+
indexed_cache = new modularity.IndexedCache 'id'
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
describe 'constructor', ->
|
|
15
|
+
|
|
16
|
+
it 'stores the given key attribute', ->
|
|
17
|
+
indexed_cache.key.should == 'id'
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
describe 'add', ->
|
|
21
|
+
|
|
22
|
+
beforeEach ->
|
|
23
|
+
indexed_cache.add entry_1
|
|
24
|
+
|
|
25
|
+
it 'adds the given element', ->
|
|
26
|
+
indexed_cache.cache.length().should.equal 1
|
|
27
|
+
indexed_cache.cache.cache[1].should.eql entry_1
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
describe 'add_all', ->
|
|
31
|
+
it 'adds all the given elements', ->
|
|
32
|
+
indexed_cache.add_all [entry_1, entry_2]
|
|
33
|
+
indexed_cache.length().should.equal 2
|
|
34
|
+
indexed_cache.cache.cache[1].should.eql entry_1
|
|
35
|
+
indexed_cache.cache.cache[2].should.eql entry_2
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
describe 'remove', ->
|
|
39
|
+
it 'removes the given object from the server', ->
|
|
40
|
+
indexed_cache.add entry_1
|
|
41
|
+
indexed_cache.remove entry_1
|
|
42
|
+
indexed_cache.length().should.equal 0
|
|
43
|
+
|
|
44
|
+
describe 'get', ->
|
|
45
|
+
it 'returns the element indexed by the given key', ->
|
|
46
|
+
indexed_cache.add entry_1
|
|
47
|
+
indexed_cache.get(1).should.eql entry_1
|
|
48
|
+
|
|
49
|
+
it "returns undefined if the element doesn't exist", ->
|
|
50
|
+
expect(indexed_cache.get(2)).to.be.undefined
|
|
51
|
+
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
#= require spec_helper
|
|
2
|
+
#= require modularity/data/persistence_manager
|
|
3
|
+
#= require jquery
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
describe 'PersistenceManager', ->
|
|
7
|
+
|
|
8
|
+
# Global variables for testing.
|
|
9
|
+
persistence_manager = null
|
|
10
|
+
entry_1 = {id: 1, value: 'one'}
|
|
11
|
+
entry_2 = {id: 2, value: 'two'}
|
|
12
|
+
|
|
13
|
+
beforeEach ->
|
|
14
|
+
persistence_manager = new modularity.PersistenceManager {url: '/users'}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
describe 'constructor', ->
|
|
18
|
+
|
|
19
|
+
it 'initializes an empty server data cache', ->
|
|
20
|
+
persistence_manager.server_data.length().should.equal 0
|
|
21
|
+
|
|
22
|
+
it 'initializes an empty client data cache', ->
|
|
23
|
+
persistence_manager.client_data.length().should.eql 0
|
|
24
|
+
|
|
25
|
+
it 'stores the given base url', ->
|
|
26
|
+
persistence_manager.base_url.should.equal '/users'
|
|
27
|
+
|
|
28
|
+
it 'stores the given index key', ->
|
|
29
|
+
persistence_manager = new modularity.PersistenceManager {key: 'my_key', url: '/users'}
|
|
30
|
+
persistence_manager.key.should.equal 'my_key'
|
|
31
|
+
|
|
32
|
+
it "uses 'id' as the default if no key is given", ->
|
|
33
|
+
persistence_manager.key.should.equal 'id'
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
describe 'clone', ->
|
|
37
|
+
|
|
38
|
+
clone = null
|
|
39
|
+
beforeEach ->
|
|
40
|
+
clone = persistence_manager.clone entry_1
|
|
41
|
+
|
|
42
|
+
it 'returns an object that has the same properties as the given object', ->
|
|
43
|
+
clone.id.should.equal 1
|
|
44
|
+
clone.value.should.equal 'one'
|
|
45
|
+
|
|
46
|
+
it 'returns an object that can be changed independently from the given object', ->
|
|
47
|
+
clone.id = 2
|
|
48
|
+
clone.value = 'two'
|
|
49
|
+
entry_1.id.should == 1
|
|
50
|
+
entry_1.value.should == 'one'
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
describe 'create', ->
|
|
54
|
+
new_obj = {value: 'foo'}
|
|
55
|
+
|
|
56
|
+
beforeEach ->
|
|
57
|
+
sinon.stub(jQuery, 'ajax').yieldsTo('success', entry_2)
|
|
58
|
+
|
|
59
|
+
afterEach ->
|
|
60
|
+
jQuery.ajax.restore()
|
|
61
|
+
|
|
62
|
+
it 'makes an ajax POST request to the CREATE url on the server', ->
|
|
63
|
+
persistence_manager.create new_obj, ->
|
|
64
|
+
jQuery.ajax.should.have.been.calledOnce
|
|
65
|
+
args = jQuery.ajax.args[0][0]
|
|
66
|
+
args.url.should.equal '/users.json'
|
|
67
|
+
args.type.should.equal 'POST'
|
|
68
|
+
|
|
69
|
+
it 'sends the object as payload', ->
|
|
70
|
+
persistence_manager.create new_obj, ->
|
|
71
|
+
args = jQuery.ajax.args[0][0]
|
|
72
|
+
args.data.should.equal new_obj
|
|
73
|
+
|
|
74
|
+
it "doesn't updates the server cache immediately because the object doesn't have an id", ->
|
|
75
|
+
persistence_manager.create new_obj, ->
|
|
76
|
+
expect(persistence_manager.server_data.get(1)).to.be.undefined
|
|
77
|
+
|
|
78
|
+
it 'updates the server cache with the server data when the call returns', (done) ->
|
|
79
|
+
persistence_manager.create {value: 'bar'}, (server_obj) ->
|
|
80
|
+
persistence_manager.server_data.get(server_obj.id).should.equal entry_2
|
|
81
|
+
done()
|
|
82
|
+
|
|
83
|
+
it 'calls the given callback when done', (done) ->
|
|
84
|
+
persistence_manager.create new_obj, ->
|
|
85
|
+
done()
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
describe 'delete', ->
|
|
89
|
+
|
|
90
|
+
beforeEach ->
|
|
91
|
+
sinon.stub(jQuery, 'ajax').yieldsTo('success')
|
|
92
|
+
|
|
93
|
+
afterEach ->
|
|
94
|
+
jQuery.ajax.restore()
|
|
95
|
+
|
|
96
|
+
it 'makes an ajax DELETE request to the item url on the server', ->
|
|
97
|
+
persistence_manager.delete entry_1
|
|
98
|
+
jQuery.ajax.should.have.been.calledOnce
|
|
99
|
+
args = jQuery.ajax.args[0][0]
|
|
100
|
+
args.url.should.equal '/users/1.json'
|
|
101
|
+
args.type.should.equal 'DELETE'
|
|
102
|
+
|
|
103
|
+
it 'removes the object from the client and server cache', ->
|
|
104
|
+
persistence_manager.server_data.add entry_1
|
|
105
|
+
persistence_manager.client_data.add entry_1
|
|
106
|
+
persistence_manager.delete entry_1
|
|
107
|
+
persistence_manager.server_data.length().should.equal 0
|
|
108
|
+
persistence_manager.client_data.length().should.equal 0
|
|
109
|
+
|
|
110
|
+
it 'calls the given callback when done', (done) ->
|
|
111
|
+
persistence_manager.delete entry_1, ->
|
|
112
|
+
done()
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
describe 'entry_url', ->
|
|
116
|
+
|
|
117
|
+
it 'returns the url to access a single entry', ->
|
|
118
|
+
persistence_manager.entry_url(entry_1).should.equal '/users/1.json'
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
describe 'load_all', ->
|
|
122
|
+
|
|
123
|
+
loading_done_callback = null
|
|
124
|
+
beforeEach ->
|
|
125
|
+
sinon.stub(jQuery, 'ajax').yieldsTo('success', [entry_1, entry_2])
|
|
126
|
+
loading_done_callback = sinon.spy()
|
|
127
|
+
persistence_manager.load_all loading_done_callback, {'q': 'foo'},
|
|
128
|
+
|
|
129
|
+
afterEach ->
|
|
130
|
+
jQuery.ajax.restore()
|
|
131
|
+
|
|
132
|
+
it 'makes a request to the INDEX action of the server', ->
|
|
133
|
+
jQuery.ajax.should.have.been.calledOnce
|
|
134
|
+
jQuery.ajax.args[0][0].url.should.equal '/users.json'
|
|
135
|
+
|
|
136
|
+
it 'provides the given data as parameters to the request', ->
|
|
137
|
+
jQuery.ajax.args[0][0].data.should.eql {'q': 'foo'}
|
|
138
|
+
|
|
139
|
+
it 'fills the server cache with the response data', ->
|
|
140
|
+
persistence_manager.server_data.length().should.eql 2
|
|
141
|
+
persistence_manager.server_data.get(1).should.eql entry_1
|
|
142
|
+
persistence_manager.server_data.get(2).should.eql entry_2
|
|
143
|
+
|
|
144
|
+
it 'calls the given callback method when the data is available', ->
|
|
145
|
+
loading_done_callback.should.have.been.calledOnce
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
describe 'load', ->
|
|
149
|
+
|
|
150
|
+
describe 'entry exists in client data cache', ->
|
|
151
|
+
it 'returns the entry from the @client_data cache if it exists there', (done) ->
|
|
152
|
+
persistence_manager.client_data.add entry_1
|
|
153
|
+
persistence_manager.load 1, (entry) ->
|
|
154
|
+
entry.should.equal entry_1
|
|
155
|
+
done()
|
|
156
|
+
|
|
157
|
+
describe 'entry exists in server data cache', ->
|
|
158
|
+
|
|
159
|
+
beforeEach ->
|
|
160
|
+
persistence_manager.server_data.add entry_1
|
|
161
|
+
|
|
162
|
+
it 'adds the entry to the client data cache', (done) ->
|
|
163
|
+
persistence_manager.load 1, ->
|
|
164
|
+
persistence_manager.client_data.length().should.equal 1
|
|
165
|
+
persistence_manager.client_data.get(1).should.eql entry_1
|
|
166
|
+
done()
|
|
167
|
+
|
|
168
|
+
it 'returns the entry from the client data cache', (done) ->
|
|
169
|
+
persistence_manager.load 1, (entry) ->
|
|
170
|
+
client_cache_entry = persistence_manager.client_data.get 1
|
|
171
|
+
entry.should.equal client_cache_entry
|
|
172
|
+
done()
|
|
173
|
+
|
|
174
|
+
it 'returns a different hash than the server data, so that the user can make changes to it', (done) ->
|
|
175
|
+
persistence_manager.load 1, (entry) ->
|
|
176
|
+
server_cache_entry = persistence_manager.server_data.get 1
|
|
177
|
+
|
|
178
|
+
entry.should.not.equal server_cache_entry
|
|
179
|
+
done()
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
describe "entry doesn't exist on the client at all", ->
|
|
183
|
+
|
|
184
|
+
beforeEach ->
|
|
185
|
+
sinon.stub(jQuery, 'ajax').yieldsTo('success', entry_1)
|
|
186
|
+
|
|
187
|
+
afterEach ->
|
|
188
|
+
jQuery.ajax.restore()
|
|
189
|
+
|
|
190
|
+
it "retrieves the entry from the server", (done) ->
|
|
191
|
+
persistence_manager.load 1, ->
|
|
192
|
+
jQuery.ajax.should.have.been.calledOnce
|
|
193
|
+
done()
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
it 'stores the entry in the server cache', (done) ->
|
|
197
|
+
persistence_manager.load 1, ->
|
|
198
|
+
persistence_manager.server_data.length().should.equal 1
|
|
199
|
+
persistence_manager.server_data.get(1).should.equal entry_1
|
|
200
|
+
done()
|
|
201
|
+
|
|
202
|
+
it 'stores a replica of the entry in the client cache', (done) ->
|
|
203
|
+
persistence_manager.load 1, ->
|
|
204
|
+
persistence_manager.client_data.get(1).should.not.equal entry_1
|
|
205
|
+
persistence_manager.client_data.get(1).should.eql entry_1
|
|
206
|
+
done()
|
|
207
|
+
|
|
208
|
+
it 'returns the client replica', (done) ->
|
|
209
|
+
persistence_manager.load 1, (entry) ->
|
|
210
|
+
persistence_manager.client_data.get(1).should.equal entry
|
|
211
|
+
persistence_manager.server_data.get(1).should.not.equal entry
|
|
212
|
+
done()
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
describe 'save', ->
|
|
216
|
+
|
|
217
|
+
describe 'for unsaved objects', ->
|
|
218
|
+
it "calls the 'create' action", ->
|
|
219
|
+
sinon.stub persistence_manager, 'create'
|
|
220
|
+
persistence_manager.save {value: 'foo'}, ->
|
|
221
|
+
persistence_manager.create.should.have.been.calledOnce
|
|
222
|
+
|
|
223
|
+
describe 'for objects from the server', ->
|
|
224
|
+
it "calls the 'update' action", ->
|
|
225
|
+
sinon.stub persistence_manager, 'update'
|
|
226
|
+
persistence_manager.save entry_1, ->
|
|
227
|
+
persistence_manager.update.should.have.been.calledOnce
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
describe 'update', ->
|
|
231
|
+
|
|
232
|
+
beforeEach ->
|
|
233
|
+
sinon.stub(jQuery, 'ajax').yieldsTo('success', entry_2)
|
|
234
|
+
server_entry = {id: 1, title: 'server title', desc: 'server desc'}
|
|
235
|
+
persistence_manager.server_data.add server_entry
|
|
236
|
+
|
|
237
|
+
afterEach ->
|
|
238
|
+
jQuery.ajax.restore()
|
|
239
|
+
|
|
240
|
+
it 'makes an ajax PUT request to the UPDATE url on the server', ->
|
|
241
|
+
persistence_manager.update entry_1, ->
|
|
242
|
+
jQuery.ajax.should.have.been.calledOnce
|
|
243
|
+
args = jQuery.ajax.args[0][0]
|
|
244
|
+
args.url.should.equal '/users/1.json'
|
|
245
|
+
args.type.should.equal 'PUT'
|
|
246
|
+
|
|
247
|
+
it 'sends only updated colums of the object as payload', (done) ->
|
|
248
|
+
persistence_manager.load 1, (client_entry) ->
|
|
249
|
+
client_entry.title = 'client title'
|
|
250
|
+
|
|
251
|
+
persistence_manager.update client_entry
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
args = jQuery.ajax.args[0][0]
|
|
255
|
+
args.data.should.eql {id: 1, title: 'client title'}
|
|
256
|
+
done()
|
|
257
|
+
|
|
258
|
+
it "doesn't perform the call if nothing is changed", (done) ->
|
|
259
|
+
persistence_manager.load 1, (client_entry) ->
|
|
260
|
+
persistence_manager.update client_entry
|
|
261
|
+
jQuery.ajax.should.not.have.been.called
|
|
262
|
+
done()
|
|
263
|
+
|
|
264
|
+
it 'updates the server cache immediately with the given object', ->
|
|
265
|
+
persistence_manager.update entry_1, ->
|
|
266
|
+
persistence_manager.server_data.get(1).should.equal entry_1
|
|
267
|
+
|
|
268
|
+
it 'updates the server cache with the server object when done', (done) ->
|
|
269
|
+
persistence_manager.update entry_1, (server_obj) ->
|
|
270
|
+
persistence_manager.server_data.get(2).should.equal entry_2
|
|
271
|
+
done()
|
|
272
|
+
|
|
273
|
+
it 'calls the given callback when done', (done) ->
|
|
274
|
+
persistence_manager.update entry_1, ->
|
|
275
|
+
done()
|
|
276
|
+
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#= require spec_helper
|
|
2
|
+
#= require modularity/tools/object_tools
|
|
3
|
+
|
|
4
|
+
describe 'object_tools', ->
|
|
5
|
+
|
|
6
|
+
describe 'object_diff', ->
|
|
7
|
+
obj_1 = {title: 'title 1', value: 'value 1'}
|
|
8
|
+
obj_2 = {title: 'title 2', value: 'value 1'}
|
|
9
|
+
obj_1b = {title: 'title 1', value: 'value 1'}
|
|
10
|
+
|
|
11
|
+
it 'returns a new object that contains only the changed attributes', ->
|
|
12
|
+
modularity.object_diff(obj_1, obj_2).should.eql {title: 'title 2'}
|
|
13
|
+
|
|
14
|
+
it 'returns an empty object if the two objects are equal', ->
|
|
15
|
+
modularity.object_diff(obj_1, obj_1b).should.eql {}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
describe 'object_length', ->
|
|
19
|
+
|
|
20
|
+
it 'returns the number of attributes of the given object', ->
|
|
21
|
+
obj_1 = {1: 'one'}
|
|
22
|
+
obj_2 = {1: 'one', 2: 'two'}
|
|
23
|
+
obj_3 = {1: 'one', 2: 'two', 3: 'three'}
|
|
24
|
+
modularity.object_length({}).should.equal 0
|
|
25
|
+
modularity.object_length(obj_1).should.equal 1
|
|
26
|
+
modularity.object_length(obj_2).should.equal 2
|
|
27
|
+
modularity.object_length(obj_3).should.equal 3
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#= require modularity/
|
|
1
|
+
#= require modularity/data/cache
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
# A generic ajax loader for parallel GET requests.
|
|
@@ -10,9 +10,13 @@
|
|
|
10
10
|
# any new content on the same URL will not be visible!
|
|
11
11
|
class window.modularity.AjaxLoader
|
|
12
12
|
|
|
13
|
-
constructor: ->
|
|
13
|
+
constructor: (params = {}) ->
|
|
14
14
|
@cache = new modularity.Cache()
|
|
15
15
|
|
|
16
|
+
# Whether to perform caching of data.
|
|
17
|
+
# Default: no.
|
|
18
|
+
@caching = params.caching
|
|
19
|
+
|
|
16
20
|
|
|
17
21
|
get: (url, callback) ->
|
|
18
22
|
cached_value = @cache.get url
|
|
@@ -22,7 +26,10 @@ class window.modularity.AjaxLoader
|
|
|
22
26
|
@cache.add url, [callback]
|
|
23
27
|
return jQuery.get url, (data) =>
|
|
24
28
|
cb(data) for cb in @cache.get(url)
|
|
25
|
-
@
|
|
29
|
+
if @caching
|
|
30
|
+
@cache.add url, data
|
|
31
|
+
else
|
|
32
|
+
@cache.remove url
|
|
26
33
|
|
|
27
34
|
# Request while the GET call is still pending -->
|
|
28
35
|
# add the given callback to the list of waiting callbacks.
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
#= require modularity/tools/object_tools
|
|
2
|
+
|
|
1
3
|
# A generic cache.
|
|
2
4
|
# Stores key-value pairs.
|
|
3
5
|
class window.modularity.Cache
|
|
@@ -34,8 +36,12 @@ class window.modularity.Cache
|
|
|
34
36
|
|
|
35
37
|
# Returns the number of cached objects.
|
|
36
38
|
length: () ->
|
|
37
|
-
|
|
38
|
-
|
|
39
|
+
modularity.object_length @cache
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# Removes the entry with the given key.
|
|
43
|
+
remove: (key) =>
|
|
44
|
+
delete @cache[key]
|
|
39
45
|
|
|
40
46
|
|
|
41
47
|
# Replaces the cache with the given data.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#= require modularity/data/cache
|
|
2
|
+
|
|
3
|
+
# Provides fast and convenient retrieval of hash objects
|
|
4
|
+
# by indexing them on a given key column.
|
|
5
|
+
class modularity.IndexedCache
|
|
6
|
+
|
|
7
|
+
constructor: (@key) ->
|
|
8
|
+
@cache = new modularity.Cache
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
add: (entry) ->
|
|
12
|
+
@cache.add entry[@key], entry
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
add_all: (entries) ->
|
|
16
|
+
@add(entry) for entry in entries
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
remove: (entry) ->
|
|
20
|
+
@cache.remove entry[@key]
|
|
21
|
+
|
|
22
|
+
get: (key) ->
|
|
23
|
+
@cache.get key
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
length: => @cache.length()
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
#= require modularity/data/indexed_cache
|
|
2
|
+
#= require modularity/tools/object_tools
|
|
3
|
+
|
|
4
|
+
# Provides persistence services for data models.
|
|
5
|
+
class modularity.PersistenceManager
|
|
6
|
+
|
|
7
|
+
constructor: (params) ->
|
|
8
|
+
|
|
9
|
+
# Copy of the data as it is on the server.
|
|
10
|
+
@server_data = new modularity.IndexedCache 'id'
|
|
11
|
+
|
|
12
|
+
# Copy of the data as it is on the client.
|
|
13
|
+
@client_data = new modularity.IndexedCache 'id'
|
|
14
|
+
|
|
15
|
+
# The base url on the server. Expected to be a fully RESTful API.
|
|
16
|
+
@base_url = params.url
|
|
17
|
+
|
|
18
|
+
@key = params.key or 'id'
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# Returns a deep replica of the given object.
|
|
22
|
+
clone: (obj) ->
|
|
23
|
+
result = {}
|
|
24
|
+
result[key] = value for own key, value of obj
|
|
25
|
+
result
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# Returns the URL to access the collection of objects.
|
|
29
|
+
collection_url: ->
|
|
30
|
+
"#{@base_url}.json"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
# Creates the given object on the server.
|
|
34
|
+
create: (obj, callback) ->
|
|
35
|
+
jQuery.ajax {
|
|
36
|
+
url: @collection_url()
|
|
37
|
+
type: 'POST'
|
|
38
|
+
data: obj
|
|
39
|
+
success: (server_obj) =>
|
|
40
|
+
@server_data.add server_obj
|
|
41
|
+
callback server_obj
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
delete: (obj, callback) ->
|
|
46
|
+
@client_data.remove obj
|
|
47
|
+
@server_data.remove obj
|
|
48
|
+
jQuery.ajax {
|
|
49
|
+
url: @entry_url(obj)
|
|
50
|
+
type: 'DELETE'
|
|
51
|
+
success: ->
|
|
52
|
+
callback() if callback?
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
# Returns the url to access a single entry.
|
|
57
|
+
entry_url: (entry) ->
|
|
58
|
+
"#{@base_url}/#{entry[@key]}.json"
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
# Returns the entry with the given key.
|
|
62
|
+
load: (key, callback) ->
|
|
63
|
+
|
|
64
|
+
# Try to use client_data cache.
|
|
65
|
+
client_obj = @client_data.get key
|
|
66
|
+
return callback(client_obj) if client_obj
|
|
67
|
+
|
|
68
|
+
# No data in client cache --> try to use server cache.
|
|
69
|
+
server_obj = @server_data.get key
|
|
70
|
+
if server_obj
|
|
71
|
+
client_obj = @clone server_obj
|
|
72
|
+
@client_data.add client_obj
|
|
73
|
+
return callback client_obj
|
|
74
|
+
|
|
75
|
+
# No data on client at all --> load data from server.
|
|
76
|
+
jQuery.ajax {
|
|
77
|
+
url: "#{@base_url}/#{key}"
|
|
78
|
+
cache: no
|
|
79
|
+
success: (server_entry) =>
|
|
80
|
+
@server_data.add server_entry
|
|
81
|
+
client_entry = @clone server_entry
|
|
82
|
+
@client_data.add client_entry
|
|
83
|
+
callback client_entry
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
# Loads all objects from the server.
|
|
88
|
+
# Provides the given params as parameters to the GET request.
|
|
89
|
+
load_all: (callback, params) ->
|
|
90
|
+
jQuery.ajax {
|
|
91
|
+
url: @collection_url()
|
|
92
|
+
cache: no
|
|
93
|
+
data: params
|
|
94
|
+
success: (data) =>
|
|
95
|
+
@server_data.add_all data
|
|
96
|
+
callback()
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
# Saves the given object.
|
|
101
|
+
# Does the right thing (create or update) dependent on
|
|
102
|
+
# whether the object already has a key parameter.
|
|
103
|
+
save: (obj, callback) ->
|
|
104
|
+
if obj[@key]?
|
|
105
|
+
@update obj, callback
|
|
106
|
+
else
|
|
107
|
+
@create obj, callback
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
update: (obj, callback) ->
|
|
111
|
+
|
|
112
|
+
# Create a new hash, containing only the changed attributes between obj and it's replica in @server_data.
|
|
113
|
+
diff_obj = modularity.object_diff @server_data.get(obj[@key]), obj
|
|
114
|
+
return if modularity.object_length(diff_obj) == 0
|
|
115
|
+
|
|
116
|
+
# Add key attribute.
|
|
117
|
+
diff_obj[@key] = obj[@key]
|
|
118
|
+
|
|
119
|
+
# Update server_data version.
|
|
120
|
+
@server_data.add obj
|
|
121
|
+
|
|
122
|
+
# Send to server
|
|
123
|
+
jQuery.ajax {
|
|
124
|
+
url: @entry_url(obj)
|
|
125
|
+
type: 'PUT'
|
|
126
|
+
data: diff_obj
|
|
127
|
+
success: (server_obj) =>
|
|
128
|
+
@server_data.add server_obj
|
|
129
|
+
callback server_obj if callback
|
|
130
|
+
}
|
|
131
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Returns an object that contains only the attributes
|
|
2
|
+
# that are different between obj_1 and obj_2.
|
|
3
|
+
# Only looks for changed attributes, not missing attributes.
|
|
4
|
+
modularity.object_diff = (obj_1, obj_2) ->
|
|
5
|
+
result = {}
|
|
6
|
+
for own key, value_2 of obj_2
|
|
7
|
+
do (key, value_2) ->
|
|
8
|
+
value_1 = obj_1[key]
|
|
9
|
+
result[key] = value_2 if value_1 != value_2
|
|
10
|
+
result
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
modularity.object_length = (obj) ->
|
|
14
|
+
# NOTE(KG): This doesn't work in IE8.
|
|
15
|
+
Object.keys(obj).length
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: modularity-rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.12.0
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -9,11 +9,11 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2012-05-
|
|
12
|
+
date: 2012-05-19 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: rails
|
|
16
|
-
requirement: &
|
|
16
|
+
requirement: &70234292434960 !ruby/object:Gem::Requirement
|
|
17
17
|
none: false
|
|
18
18
|
requirements:
|
|
19
19
|
- - ! '>='
|
|
@@ -21,10 +21,10 @@ dependencies:
|
|
|
21
21
|
version: 3.1.0
|
|
22
22
|
type: :runtime
|
|
23
23
|
prerelease: false
|
|
24
|
-
version_requirements: *
|
|
24
|
+
version_requirements: *70234292434960
|
|
25
25
|
- !ruby/object:Gem::Dependency
|
|
26
26
|
name: capybara-webkit
|
|
27
|
-
requirement: &
|
|
27
|
+
requirement: &70234292434440 !ruby/object:Gem::Requirement
|
|
28
28
|
none: false
|
|
29
29
|
requirements:
|
|
30
30
|
- - ! '>='
|
|
@@ -32,10 +32,10 @@ dependencies:
|
|
|
32
32
|
version: '0'
|
|
33
33
|
type: :development
|
|
34
34
|
prerelease: false
|
|
35
|
-
version_requirements: *
|
|
35
|
+
version_requirements: *70234292434440
|
|
36
36
|
- !ruby/object:Gem::Dependency
|
|
37
37
|
name: evergreen
|
|
38
|
-
requirement: &
|
|
38
|
+
requirement: &70234292433920 !ruby/object:Gem::Requirement
|
|
39
39
|
none: false
|
|
40
40
|
requirements:
|
|
41
41
|
- - ! '>='
|
|
@@ -43,10 +43,10 @@ dependencies:
|
|
|
43
43
|
version: '0'
|
|
44
44
|
type: :development
|
|
45
45
|
prerelease: false
|
|
46
|
-
version_requirements: *
|
|
46
|
+
version_requirements: *70234292433920
|
|
47
47
|
- !ruby/object:Gem::Dependency
|
|
48
48
|
name: rb-fsevent
|
|
49
|
-
requirement: &
|
|
49
|
+
requirement: &70234292433260 !ruby/object:Gem::Requirement
|
|
50
50
|
none: false
|
|
51
51
|
requirements:
|
|
52
52
|
- - ! '>='
|
|
@@ -54,10 +54,10 @@ dependencies:
|
|
|
54
54
|
version: '0'
|
|
55
55
|
type: :development
|
|
56
56
|
prerelease: false
|
|
57
|
-
version_requirements: *
|
|
57
|
+
version_requirements: *70234292433260
|
|
58
58
|
- !ruby/object:Gem::Dependency
|
|
59
59
|
name: guard-livereload
|
|
60
|
-
requirement: &
|
|
60
|
+
requirement: &70234292432580 !ruby/object:Gem::Requirement
|
|
61
61
|
none: false
|
|
62
62
|
requirements:
|
|
63
63
|
- - ! '>='
|
|
@@ -65,7 +65,7 @@ dependencies:
|
|
|
65
65
|
version: '0'
|
|
66
66
|
type: :development
|
|
67
67
|
prerelease: false
|
|
68
|
-
version_requirements: *
|
|
68
|
+
version_requirements: *70234292432580
|
|
69
69
|
description: Description of ModularityRails.
|
|
70
70
|
email:
|
|
71
71
|
- kevin.goslar@gmail.com
|
|
@@ -121,6 +121,10 @@ files:
|
|
|
121
121
|
- demo/public/index.html
|
|
122
122
|
- demo/public/robots.txt
|
|
123
123
|
- demo/script/rails
|
|
124
|
+
- demo/spec/javascripts/data/ajax_loader_spec.coffee
|
|
125
|
+
- demo/spec/javascripts/data/cache_spec.coffee
|
|
126
|
+
- demo/spec/javascripts/data/indexed_cache_spec.coffee
|
|
127
|
+
- demo/spec/javascripts/data/persistence_manager_spec.coffee
|
|
124
128
|
- demo/spec/javascripts/konacha_config.coffee
|
|
125
129
|
- demo/spec/javascripts/mixins/closable_spec.coffee
|
|
126
130
|
- demo/spec/javascripts/modularity_spec.coffee
|
|
@@ -134,9 +138,8 @@ files:
|
|
|
134
138
|
- demo/spec/javascripts/templates/button.jst.ejs
|
|
135
139
|
- demo/spec/javascripts/templates/closable.jst.ejs
|
|
136
140
|
- demo/spec/javascripts/templates/modularity.jst.ejs
|
|
137
|
-
- demo/spec/javascripts/tools/ajax_loader_spec.coffee
|
|
138
141
|
- demo/spec/javascripts/tools/array_tools_spec.coffee
|
|
139
|
-
- demo/spec/javascripts/tools/
|
|
142
|
+
- demo/spec/javascripts/tools/object_tools_spec.coffee
|
|
140
143
|
- demo/vendor/assets/javascripts/.gitkeep
|
|
141
144
|
- demo/vendor/assets/stylesheets/.gitkeep
|
|
142
145
|
- demo/vendor/plugins/.gitkeep
|
|
@@ -146,14 +149,17 @@ files:
|
|
|
146
149
|
- modularity-rails.gemspec
|
|
147
150
|
- run_tests
|
|
148
151
|
- vendor/assets/javascripts/modularity.js.coffee
|
|
152
|
+
- vendor/assets/javascripts/modularity/data/ajax_loader.coffee
|
|
153
|
+
- vendor/assets/javascripts/modularity/data/cache.coffee
|
|
154
|
+
- vendor/assets/javascripts/modularity/data/indexed_cache.coffee
|
|
155
|
+
- vendor/assets/javascripts/modularity/data/persistence_manager.coffee
|
|
149
156
|
- vendor/assets/javascripts/modularity/mixins/clickable.coffee
|
|
150
157
|
- vendor/assets/javascripts/modularity/mixins/closable.coffee
|
|
151
158
|
- vendor/assets/javascripts/modularity/modules/autogrow_textarea.coffee
|
|
152
159
|
- vendor/assets/javascripts/modularity/modules/button.coffee
|
|
153
160
|
- vendor/assets/javascripts/modularity/modules/counter_button.coffee
|
|
154
|
-
- vendor/assets/javascripts/modularity/tools/ajax_loader.coffee
|
|
155
161
|
- vendor/assets/javascripts/modularity/tools/array_tools.coffee
|
|
156
|
-
- vendor/assets/javascripts/modularity/tools/
|
|
162
|
+
- vendor/assets/javascripts/modularity/tools/object_tools.coffee
|
|
157
163
|
homepage: http://github.com/kevgo/modularity-rails
|
|
158
164
|
licenses: []
|
|
159
165
|
post_install_message:
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
#= require spec_helper
|
|
2
|
-
#= require modularity/tools/ajax_loader
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
describe 'ajax_loader', ->
|
|
6
|
-
|
|
7
|
-
ajax_loader = spy = spy_get = null
|
|
8
|
-
beforeEach ->
|
|
9
|
-
ajax_loader = new modularity.AjaxLoader()
|
|
10
|
-
spy = sinon.spy()
|
|
11
|
-
spy_get = sinon.spy jQuery, 'get'
|
|
12
|
-
|
|
13
|
-
afterEach ->
|
|
14
|
-
spy_get.restore()
|
|
15
|
-
|
|
16
|
-
describe 'get', ->
|
|
17
|
-
|
|
18
|
-
url = "/users/4"
|
|
19
|
-
|
|
20
|
-
describe 'the data has already been loaded', ->
|
|
21
|
-
|
|
22
|
-
it 'calls the callback with the cached data', ->
|
|
23
|
-
ajax_loader.cache.add url, "my data"
|
|
24
|
-
|
|
25
|
-
ajax_loader.get(url, spy)
|
|
26
|
-
|
|
27
|
-
spy.should.have.been.called
|
|
28
|
-
spy.should.have.been.calledWith "my data"
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
describe 'the request is already in progress', ->
|
|
32
|
-
|
|
33
|
-
beforeEach ->
|
|
34
|
-
ajax_loader.cache.cache[url] = [spy]
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
it 'adds the callback to the callback array', ->
|
|
38
|
-
ajax_loader.cache.get(url).should.have.length 1
|
|
39
|
-
ajax_loader.cache.get(url)[0].should.equal spy
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
it 'returns without calling the callback', ->
|
|
43
|
-
spy.should.not.have.been.called
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
it 'does not make another ajax request', ->
|
|
47
|
-
jQuery.get.should.not.have.been.called
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
describe 'first time request', ->
|
|
51
|
-
|
|
52
|
-
beforeEach ->
|
|
53
|
-
ajax_loader.get url, spy
|
|
54
|
-
|
|
55
|
-
it 'makes an ajax request', ->
|
|
56
|
-
jQuery.get.should.have.been.called
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
it 'saves the callback for later', ->
|
|
60
|
-
ajax_loader.cache.get(url).should.have.length 1
|
|
61
|
-
ajax_loader.cache.get(url)[0].should.equal spy
|
|
62
|
-
|
|
63
|
-
it 'returns without calling the callback', ->
|
|
64
|
-
spy.should.not.have.been.called
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
describe 'ajax request successful', ->
|
|
68
|
-
|
|
69
|
-
beforeEach ->
|
|
70
|
-
jquery_callback = null
|
|
71
|
-
jQuery.get = (url, callback) -> jquery_callback = callback
|
|
72
|
-
ajax_loader.get url, spy
|
|
73
|
-
jquery_callback('result')
|
|
74
|
-
|
|
75
|
-
it 'calls the given callbacks', ->
|
|
76
|
-
spy.should.have.been.calledWith 'result'
|
|
77
|
-
|
|
78
|
-
it 'replaces the cache callbacks with returned data', ->
|
|
79
|
-
ajax_loader.cache.get(url).should.equal 'result'
|