joosy 1.2.0.beta.1 → 1.2.0.beta.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +17 -11
- data/bower.json +1 -1
- data/build/joosy.js +2 -2
- data/build/joosy/resources.js +1 -1
- data/package.json +1 -1
- data/source/joosy/module.coffee +2 -29
- data/source/joosy/modules/resources/cacher.coffee +2 -2
- data/source/joosy/modules/resources/function.coffee +41 -0
- data/source/joosy/modules/resources/identity_map.coffee +4 -3
- data/source/joosy/modules/resources/model.coffee +10 -6
- data/source/joosy/resources/array.coffee +9 -8
- data/source/joosy/resources/hash.coffee +21 -19
- data/source/joosy/resources/rest.coffee +21 -82
- data/source/joosy/resources/scalar.coffee +13 -14
- data/source/joosy/router.coffee +4 -2
- data/spec/helpers/matchers.coffee +16 -2
- data/spec/joosy/core/helpers/view_spec.coffee +2 -2
- data/spec/joosy/core/router_spec.coffee +99 -98
- data/spec/joosy/core/templaters/jst_spec.coffee +2 -2
- data/spec/joosy/form/form_spec.coffee +1 -1
- data/spec/joosy/resources/array_spec.coffee +4 -8
- data/spec/joosy/resources/hash_spec.coffee +15 -15
- data/spec/joosy/resources/modules/cacher_spec.coffee +2 -2
- data/spec/joosy/resources/modules/function_spec.coffee +32 -0
- data/spec/joosy/resources/modules/identity_map_spec.coffee +3 -3
- data/spec/joosy/resources/modules/model_spec.coffee +40 -29
- data/spec/joosy/resources/rest_spec.coffee +9 -9
- data/spec/joosy/resources/scalar_spec.coffee +9 -14
- metadata +5 -4
@@ -1,32 +1,31 @@
|
|
1
|
-
class Joosy.Resources.Scalar extends Joosy.
|
1
|
+
class Joosy.Resources.Scalar extends Joosy.Module
|
2
2
|
|
3
3
|
@include Joosy.Modules.Events
|
4
4
|
@include Joosy.Modules.Filters
|
5
5
|
|
6
6
|
@registerPlainFilters 'beforeLoad'
|
7
7
|
|
8
|
+
@build: ->
|
9
|
+
new @ arguments...
|
10
|
+
|
11
|
+
__call: ->
|
12
|
+
if arguments.length > 0
|
13
|
+
@set arguments[0]
|
14
|
+
else
|
15
|
+
@get()
|
16
|
+
|
8
17
|
constructor: (value) ->
|
9
|
-
|
10
|
-
@load value
|
18
|
+
@load value
|
11
19
|
|
12
20
|
load: (value) ->
|
13
21
|
@value = @__applyBeforeLoads(value)
|
14
22
|
@trigger 'changed'
|
15
23
|
@value
|
16
24
|
|
17
|
-
|
18
|
-
new @constructor @value
|
19
|
-
|
20
|
-
__call: ->
|
21
|
-
if arguments.length > 0
|
22
|
-
@__set arguments[0]
|
23
|
-
else
|
24
|
-
@__get()
|
25
|
-
|
26
|
-
__get: ->
|
25
|
+
get: ->
|
27
26
|
@value
|
28
27
|
|
29
|
-
|
28
|
+
set: (@value) ->
|
30
29
|
@trigger 'changed'
|
31
30
|
|
32
31
|
valueOf: ->
|
data/source/joosy/router.coffee
CHANGED
@@ -290,10 +290,12 @@ class Joosy.Router extends Joosy.Module
|
|
290
290
|
@["#{as}Path"] = helper
|
291
291
|
|
292
292
|
@["#{as}Url"] = (options) ->
|
293
|
+
origin = "#{location.protocol}//#{location.host}"
|
294
|
+
|
293
295
|
if Joosy.Router.config.html5
|
294
|
-
"#{
|
296
|
+
"#{origin}#{helper(options)}"
|
295
297
|
else
|
296
|
-
"#{
|
298
|
+
"#{origin}#{location.pathname}#{helper(options)}"
|
297
299
|
|
298
300
|
@__grabParams: (query, route=null, match=[]) ->
|
299
301
|
params = {}
|
@@ -30,7 +30,8 @@ beforeEach ->
|
|
30
30
|
return true
|
31
31
|
|
32
32
|
toEqualHTML: (string) ->
|
33
|
-
html = @actual.replace(/>\s+</g, '><')
|
33
|
+
html = @actual.replace(/>\s+</g, '><').toLowerCase().replace(/\"/g, '')
|
34
|
+
string = string.toLowerCase().replace(/\"/g, '')
|
34
35
|
@message = -> "Expected '#{html}' to equal '#{string}'"
|
35
36
|
|
36
37
|
html == string
|
@@ -44,23 +45,36 @@ beforeEach ->
|
|
44
45
|
# tag.toBeTag 'div', 'foo', class: 'foo', id: /\S+/
|
45
46
|
#
|
46
47
|
toBeTag: (tagName, content, attrs) ->
|
48
|
+
reason = ''
|
47
49
|
@message = =>
|
48
50
|
actual = $('<div>').append(@actual).html()
|
49
|
-
"Expected '#{actual}' to be a tag #{tagName} with attributes #{JSON.stringify attrs} and content '#{content}'"
|
51
|
+
"Expected '#{actual}' to be a tag #{tagName} with attributes #{JSON.stringify attrs} and content '#{content}': #{reason}"
|
50
52
|
|
51
53
|
tag = $ @actual
|
52
54
|
|
53
55
|
# Is it alone?
|
54
56
|
flag = tag.length == 1
|
57
|
+
if !flag
|
58
|
+
reason = 'not alone'
|
59
|
+
return false
|
55
60
|
|
56
61
|
# Tag name matches?
|
57
62
|
flag &&= tag[0].nodeName == tagName.toUpperCase()
|
63
|
+
if !flag
|
64
|
+
reason = 'tag name mismatch'
|
65
|
+
return false
|
58
66
|
|
59
67
|
# Content matches?
|
60
68
|
flag &&= tag.html() == content if content != false
|
69
|
+
if !flag
|
70
|
+
reason = 'content mismatch'
|
71
|
+
return false
|
61
72
|
|
62
73
|
# Same number of attributes?
|
63
74
|
flag &&= tag[0].attributes.length == Object.keys(attrs).length
|
75
|
+
if !flag
|
76
|
+
reason = 'attributes count mismatch'
|
77
|
+
return false
|
64
78
|
|
65
79
|
# Attributes match?
|
66
80
|
for name, val of attrs
|
@@ -5,10 +5,10 @@ describe "Joosy.Helpers.View", ->
|
|
5
5
|
|
6
6
|
it "renders tag with string content", ->
|
7
7
|
tag = h.contentTag 'div', 'content', {id: 'id'}
|
8
|
-
expect(tag).
|
8
|
+
expect(tag).toBeTag 'div', 'content', id: 'id'
|
9
9
|
|
10
10
|
it "renders tag with lambda content", ->
|
11
11
|
tag = h.contentTag 'div', {id: 'id'}, ->
|
12
12
|
h.contentTag 'div', 'content', {id: 'id2'}
|
13
13
|
|
14
|
-
expect(tag).
|
14
|
+
expect(tag.toLowerCase()).toEqualHTML '<div id="id"><div id="id2">content</div></div>'
|
@@ -190,127 +190,128 @@ describe "Joosy.Router", ->
|
|
190
190
|
expect(Joosy.Helpers.Routes.sectionPagePath(id: 1)).toEqual '#section/page/1'
|
191
191
|
expect(Joosy.Helpers.Routes.sectionPageUrl(id: 1)).toEqual "http://#{location.host}#{pathname}#section/page/1"
|
192
192
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
afterEach ->
|
199
|
-
Joosy.Router.reset()
|
200
|
-
history.pushState {}, '', pathname
|
201
|
-
waits 0
|
193
|
+
if history.pushState?
|
194
|
+
describe 'html5 based', ->
|
195
|
+
beforeEach ->
|
196
|
+
Joosy.Router.setup {html5: true}, @spies.responder, false
|
197
|
+
Joosy.Router.map @map
|
202
198
|
|
203
|
-
|
204
|
-
runs -> Joosy.Router.navigate '/page'
|
205
|
-
waits 0
|
206
|
-
runs ->
|
199
|
+
afterEach ->
|
207
200
|
Joosy.Router.reset()
|
208
|
-
|
209
|
-
|
210
|
-
runs ->
|
211
|
-
expect(@spies.responder.callCount).toEqual 1
|
212
|
-
|
213
|
-
it 'boots pages', ->
|
214
|
-
runs -> Joosy.Router.navigate '/page'
|
215
|
-
waits 0
|
216
|
-
runs ->
|
217
|
-
expect(@spies.responder.callCount).toEqual 1
|
218
|
-
expect(@spies.responder.args[0][0]).toEqual @Page
|
219
|
-
|
220
|
-
it 'runs lamdas', ->
|
221
|
-
runs -> Joosy.Router.navigate '/base'
|
222
|
-
waits 0
|
223
|
-
runs ->
|
224
|
-
expect(@spies.responder.callCount).toEqual 1
|
225
|
-
expect(@spies.responder.args[0][0]).toEqual @spies.base
|
226
|
-
|
227
|
-
it 'responds namespaced routes', ->
|
228
|
-
runs -> Joosy.Router.navigate '/section/page/1'
|
229
|
-
waits 0
|
230
|
-
runs ->
|
231
|
-
expect(@spies.responder.callCount).toEqual 1
|
232
|
-
expect(@spies.responder.args[0][0]).toEqual @spies.section
|
233
|
-
|
234
|
-
it 'parses query parametrs', ->
|
235
|
-
runs -> Joosy.Router.navigate '/?test=test&foo=bar'
|
236
|
-
waits 0
|
237
|
-
runs ->
|
238
|
-
expect(@spies.responder.callCount).toEqual 1
|
239
|
-
expect(@spies.responder.args[0][0]).toEqual @spies.root
|
240
|
-
expect(@spies.responder.args[0][1]).toEqual {test: 'test', foo: 'bar'}
|
241
|
-
|
242
|
-
it 'parses route placeholders', ->
|
243
|
-
runs -> Joosy.Router.navigate '/section/page/1'
|
244
|
-
waits 0
|
245
|
-
runs ->
|
246
|
-
expect(@spies.responder.callCount).toEqual 1
|
247
|
-
expect(@spies.responder.args[0][0]).toEqual @spies.section
|
248
|
-
expect(@spies.responder.args[0][1]).toEqual {id: '1'}
|
249
|
-
|
250
|
-
it 'ignores restricted routes', ->
|
251
|
-
Joosy.Router.restrict /^base/
|
201
|
+
history.pushState {}, '', pathname
|
202
|
+
waits 0
|
252
203
|
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
204
|
+
it 'resets', ->
|
205
|
+
runs -> Joosy.Router.navigate '/page'
|
206
|
+
waits 0
|
207
|
+
runs ->
|
208
|
+
Joosy.Router.reset()
|
209
|
+
Joosy.Router.navigate '/'
|
210
|
+
waits 0
|
211
|
+
runs ->
|
212
|
+
expect(@spies.responder.callCount).toEqual 1
|
257
213
|
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
214
|
+
it 'boots pages', ->
|
215
|
+
runs -> Joosy.Router.navigate '/page'
|
216
|
+
waits 0
|
217
|
+
runs ->
|
218
|
+
expect(@spies.responder.callCount).toEqual 1
|
219
|
+
expect(@spies.responder.args[0][0]).toEqual @Page
|
264
220
|
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
221
|
+
it 'runs lamdas', ->
|
222
|
+
runs -> Joosy.Router.navigate '/base'
|
223
|
+
waits 0
|
224
|
+
runs ->
|
225
|
+
expect(@spies.responder.callCount).toEqual 1
|
226
|
+
expect(@spies.responder.args[0][0]).toEqual @spies.base
|
271
227
|
|
272
|
-
|
273
|
-
|
274
|
-
|
228
|
+
it 'responds namespaced routes', ->
|
229
|
+
runs -> Joosy.Router.navigate '/section/page/1'
|
230
|
+
waits 0
|
231
|
+
runs ->
|
232
|
+
expect(@spies.responder.callCount).toEqual 1
|
233
|
+
expect(@spies.responder.args[0][0]).toEqual @spies.section
|
275
234
|
|
276
|
-
|
277
|
-
|
278
|
-
|
235
|
+
it 'parses query parametrs', ->
|
236
|
+
runs -> Joosy.Router.navigate '/?test=test&foo=bar'
|
237
|
+
waits 0
|
238
|
+
runs ->
|
239
|
+
expect(@spies.responder.callCount).toEqual 1
|
240
|
+
expect(@spies.responder.args[0][0]).toEqual @spies.root
|
241
|
+
expect(@spies.responder.args[0][1]).toEqual {test: 'test', foo: 'bar'}
|
279
242
|
|
280
|
-
|
281
|
-
|
282
|
-
describe "#{name} prefix", ->
|
283
|
-
afterEach ->
|
284
|
-
Joosy.Router.reset()
|
285
|
-
location.hash = ''
|
286
|
-
history.pushState {}, '', pathname
|
243
|
+
it 'parses route placeholders', ->
|
244
|
+
runs -> Joosy.Router.navigate '/section/page/1'
|
287
245
|
waits 0
|
246
|
+
runs ->
|
247
|
+
expect(@spies.responder.callCount).toEqual 1
|
248
|
+
expect(@spies.responder.args[0][0]).toEqual @spies.section
|
249
|
+
expect(@spies.responder.args[0][1]).toEqual {id: '1'}
|
288
250
|
|
289
|
-
|
290
|
-
Joosy.Router.
|
291
|
-
Joosy.Router.map @map
|
251
|
+
it 'ignores restricted routes', ->
|
252
|
+
Joosy.Router.restrict /^base/
|
292
253
|
|
293
|
-
it "is considered in path without prefix", ->
|
294
254
|
runs -> Joosy.Router.navigate '/base'
|
295
255
|
waits 0
|
296
256
|
runs ->
|
297
|
-
expect(@spies.responder.callCount).toEqual
|
298
|
-
expect(@spies.responder.args[0][0]).toEqual @spies.base
|
257
|
+
expect(@spies.responder.callCount).toEqual 0
|
299
258
|
|
300
|
-
it
|
301
|
-
runs -> Joosy.Router.navigate '/
|
259
|
+
it 'defaults to wildcard route', ->
|
260
|
+
runs -> Joosy.Router.navigate '/trololo'
|
302
261
|
waits 0
|
303
262
|
runs ->
|
304
263
|
expect(@spies.responder.callCount).toEqual 1
|
305
|
-
expect(@spies.responder.args[0][0]).toEqual @spies.
|
264
|
+
expect(@spies.responder.args[0][0]).toEqual @spies.wildcard
|
306
265
|
|
307
|
-
it
|
308
|
-
runs -> Joosy.Router.navigate '/
|
266
|
+
it 'navigates', ->
|
267
|
+
runs -> Joosy.Router.navigate '/base'
|
309
268
|
waits 0
|
310
269
|
runs ->
|
270
|
+
location.pathname == '/base'
|
311
271
|
expect(@spies.responder.callCount).toEqual 1
|
312
|
-
expect(@spies.responder.args[0][0]).toEqual @spies.root
|
313
272
|
|
273
|
+
it 'defines plain helper', ->
|
274
|
+
expect(Joosy.Helpers.Routes.rootPath()).toEqual '/'
|
275
|
+
expect(Joosy.Helpers.Routes.rootUrl()).toEqual "http://#{location.host}/"
|
276
|
+
|
277
|
+
it 'defines namespaced parameterized helpers', ->
|
278
|
+
expect(Joosy.Helpers.Routes.sectionPagePath(id: 1)).toEqual '/section/page/1'
|
279
|
+
expect(Joosy.Helpers.Routes.sectionPageUrl(id: 1)).toEqual "http://#{location.host}/section/page/1"
|
280
|
+
|
281
|
+
for name, val of { html5: true, hash: false }
|
282
|
+
do (name, val) ->
|
283
|
+
if name != 'html5' || history.pushState
|
284
|
+
describe "#{name} prefix", ->
|
285
|
+
afterEach ->
|
286
|
+
Joosy.Router.reset()
|
287
|
+
location.hash = ''
|
288
|
+
history.pushState?({}, '', pathname)
|
289
|
+
waits 0
|
290
|
+
|
291
|
+
beforeEach ->
|
292
|
+
Joosy.Router.setup {html5: val, prefix: 'admin', hashSuffix: 'admin'}, @spies.responder, false
|
293
|
+
Joosy.Router.map @map
|
294
|
+
|
295
|
+
it "is considered in path without prefix", ->
|
296
|
+
runs -> Joosy.Router.navigate '/base'
|
297
|
+
waits 0
|
298
|
+
runs ->
|
299
|
+
expect(@spies.responder.callCount).toEqual 1
|
300
|
+
expect(@spies.responder.args[0][0]).toEqual @spies.base
|
301
|
+
|
302
|
+
it "is considered in path with prefix", ->
|
303
|
+
runs -> Joosy.Router.navigate '/admin/base'
|
304
|
+
waits 0
|
305
|
+
runs ->
|
306
|
+
expect(@spies.responder.callCount).toEqual 1
|
307
|
+
expect(@spies.responder.args[0][0]).toEqual @spies.base
|
308
|
+
|
309
|
+
it "is considered in root path", ->
|
310
|
+
runs -> Joosy.Router.navigate '/admin'
|
311
|
+
waits 0
|
312
|
+
runs ->
|
313
|
+
expect(@spies.responder.callCount).toEqual 1
|
314
|
+
expect(@spies.responder.args[0][0]).toEqual @spies.root
|
314
315
|
|
315
316
|
describe 'linker', ->
|
316
317
|
it 'defines helper', ->
|
@@ -165,7 +165,7 @@ describe "Joosy.Form", ->
|
|
165
165
|
expect(@arrayForm.$fields()[0].value).toEqual 'here'
|
166
166
|
|
167
167
|
it "should break cross-references", ->
|
168
|
-
@resource('single')('trololo', @resource)
|
168
|
+
@resource.get('single').get('trololo', @resource)
|
169
169
|
@nestedForm.fill @resource
|
170
170
|
# expect(you).toBeAlive(), lol
|
171
171
|
|
@@ -11,14 +11,10 @@ describe 'Joosy.Resources.Array', ->
|
|
11
11
|
expect(@array[1]).toEqual 2
|
12
12
|
expect(@array[2]).toEqual 3
|
13
13
|
|
14
|
-
it '
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
expect(@array.length).toEqual 3
|
19
|
-
expect(@array[0]).toEqual 1
|
20
|
-
expect(@array[1]).toEqual 2
|
21
|
-
expect(@array[2]).toEqual 3
|
14
|
+
it 'modifies', ->
|
15
|
+
@array.push 4
|
16
|
+
@array.push 5
|
17
|
+
expect(@array.length).toEqual 5
|
22
18
|
|
23
19
|
it 'triggers', ->
|
24
20
|
spy = sinon.spy()
|
@@ -2,40 +2,40 @@ describe "Joosy.Resources.Hash", ->
|
|
2
2
|
|
3
3
|
describe 'in general', ->
|
4
4
|
beforeEach ->
|
5
|
-
@hash =
|
5
|
+
@hash = Joosy.Resources.Hash.build({foo: 'bar', bar: {baz: 'yummy!'}})
|
6
6
|
|
7
7
|
it 'wraps', ->
|
8
|
-
expect(typeof(@hash)).toEqual '
|
9
|
-
expect(@hash 'foo').toEqual 'bar'
|
10
|
-
expect(@hash 'bar').toEqual {baz: 'yummy!'}
|
11
|
-
expect(@hash 'bar.baz').toEqual 'yummy!'
|
8
|
+
expect(typeof(@hash)).toEqual 'object'
|
9
|
+
expect(@hash.get 'foo').toEqual 'bar'
|
10
|
+
expect(@hash.get 'bar').toEqual {baz: 'yummy!'}
|
11
|
+
expect(@hash.get 'bar.baz').toEqual 'yummy!'
|
12
12
|
|
13
13
|
it 'sets', ->
|
14
|
-
@hash('bar.baz', 'the ignition')
|
14
|
+
@hash.set('bar.baz', 'the ignition')
|
15
15
|
expect(@hash.data.bar.baz).toEqual 'the ignition'
|
16
|
-
expect(@hash 'bar.baz').toEqual 'the ignition'
|
16
|
+
expect(@hash.get 'bar.baz').toEqual 'the ignition'
|
17
17
|
|
18
18
|
it 'gets', ->
|
19
|
-
expect(@hash 'foo.bar.baz').toBeUndefined()
|
19
|
+
expect(@hash.get 'foo.bar.baz').toBeUndefined()
|
20
20
|
expect(@hash.data.foo.bar).toBeUndefined()
|
21
21
|
|
22
22
|
it 'triggers', ->
|
23
23
|
spy = sinon.spy()
|
24
24
|
@hash.bind 'changed', spy
|
25
25
|
|
26
|
-
@hash 'bar.baz', 'rocking'
|
26
|
+
@hash.set 'bar.baz', 'rocking'
|
27
27
|
expect(spy.callCount)
|
28
28
|
|
29
29
|
describe 'nested hash', ->
|
30
30
|
beforeEach ->
|
31
|
-
@nested =
|
32
|
-
@hash =
|
31
|
+
@nested = Joosy.Resources.Hash.build(trolo: 'lo')
|
32
|
+
@hash = Joosy.Resources.Hash.build({foo: 'bar', bar: @nested})
|
33
33
|
|
34
34
|
it 'gets', ->
|
35
|
-
expect(@hash 'bar.trolo').toEqual 'lo'
|
35
|
+
expect(@hash.get 'bar.trolo').toEqual 'lo'
|
36
36
|
|
37
37
|
it 'sets', ->
|
38
|
-
@hash 'bar.trolo', 'lolo'
|
38
|
+
@hash.set 'bar.trolo', 'lolo'
|
39
39
|
expect(@nested.data.trolo).toEqual 'lolo'
|
40
40
|
|
41
41
|
describe 'filters', ->
|
@@ -45,6 +45,6 @@ describe "Joosy.Resources.Hash", ->
|
|
45
45
|
data.test = true
|
46
46
|
data
|
47
47
|
|
48
|
-
hash =
|
48
|
+
hash = Hash.build(foo: 'bar')
|
49
49
|
expect(hash.data.test).toBeTruthy()
|
50
|
-
expect(hash 'test').toBeTruthy()
|
50
|
+
expect(hash.get 'test').toBeTruthy()
|