unpoly-rails 0.30.0 → 0.30.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of unpoly-rails might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/lib/assets/javascripts/unpoly/form.js.coffee +22 -41
- data/lib/assets/javascripts/unpoly/util.js.coffee +33 -2
- data/lib/unpoly/rails/version.rb +1 -1
- data/spec_app/Gemfile.lock +12 -10
- data/spec_app/spec/javascripts/helpers/wait_until_dom_ready.js.coffee +0 -1
- data/spec_app/spec/javascripts/up/form_spec.js.coffee +146 -70
- data/spec_app/spec/javascripts/up/util_spec.js.coffee +90 -5
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1e53ab2c1cbdfe09b80e31d76371d5382ad40f70
|
4
|
+
data.tar.gz: 7ba79eb21d2494bf69b3bc222a4b7e89778671a1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5789b11f34c69787dbf6fdd9fe9ed03d6c25c5c76fbf32b7028fcba36a6ecad14072c10d1cf5b4945d7edd104d11e581a302f6ca45b1c15baf4b5aa868c90691
|
7
|
+
data.tar.gz: 3d07d31ce7a01814badad2a7e16fbe4bbf283dc574a6b27818ea9a2ba5a6cff9b9fdcf6a9acfd19b6d505d12f8c84486ea12b7322fae39fa7000cb9af3492c1d
|
data/CHANGELOG.md
CHANGED
@@ -14,6 +14,16 @@ Unreleased
|
|
14
14
|
### Breaking changes
|
15
15
|
|
16
16
|
|
17
|
+
0.30.1
|
18
|
+
------
|
19
|
+
|
20
|
+
### Compatible changes
|
21
|
+
|
22
|
+
- Fix [`up.observe`](/up.observe) not honoring `{ delay }` option
|
23
|
+
- Fix [`[up-observe]`](/up-observe) not honoring `[up-delay]` modifier
|
24
|
+
- Fix many issues with concurrency and slow server responses for [`up.observe`](/up.observe) and [`[up-observe]`](/up-observe)
|
25
|
+
|
26
|
+
|
17
27
|
|
18
28
|
0.30.0
|
19
29
|
------
|
@@ -249,52 +249,35 @@ up.form = (($) ->
|
|
249
249
|
delay = u.option($fields.attr('up-delay'), options.delay, config.observeDelay)
|
250
250
|
delay = parseInt(delay)
|
251
251
|
|
252
|
+
console.debug("Observing with delay %o", delay)
|
253
|
+
|
252
254
|
destructors = u.map $fields, (field) ->
|
253
|
-
observeField($(field),
|
255
|
+
observeField($(field), delay, callback)
|
254
256
|
|
255
257
|
u.sequence(destructors...)
|
256
258
|
|
257
259
|
observeField = ($field, delay, callback) ->
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
if nextCallback
|
270
|
-
returnValue = nextCallback()
|
271
|
-
nextCallback = null
|
272
|
-
returnValue
|
260
|
+
processedValue = u.submittedValue($field)
|
261
|
+
timer = undefined
|
262
|
+
lastCallbackDone = u.resolvedPromise()
|
263
|
+
|
264
|
+
runCallback = (value) ->
|
265
|
+
processedValue = value
|
266
|
+
callbackReturnValue = callback.apply($field.get(0), [value, $field])
|
267
|
+
if u.isPromise(callbackReturnValue)
|
268
|
+
lastCallbackDone = callbackReturnValue
|
269
|
+
else
|
270
|
+
lastCallbackDone = callbackReturnValue
|
273
271
|
|
274
272
|
check = ->
|
275
273
|
value = u.submittedValue($field)
|
276
274
|
# don't run the callback for the check during initialization
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
runAndChain = ->
|
284
|
-
# Only run the callback once the previous callback's
|
285
|
-
# promise resolves.
|
286
|
-
callbackPromise.then ->
|
287
|
-
returnValue = runNextCallback()
|
288
|
-
# If the callback returns a promise, we will remember it
|
289
|
-
# and chain additional callback invocations to it.
|
290
|
-
if u.isPromise(returnValue)
|
291
|
-
callbackPromise = returnValue
|
292
|
-
else
|
293
|
-
callbackPromise = u.resolvedPromise()
|
294
|
-
u.setTimer(delay, runAndChain)
|
295
|
-
|
296
|
-
clearTimer = ->
|
297
|
-
clearTimeout(callbackTimer)
|
275
|
+
if processedValue != value
|
276
|
+
nextCallback = -> runCallback(value)
|
277
|
+
timer?.cancel()
|
278
|
+
timer = u.promiseTimer(delay)
|
279
|
+
# We wait until both the delay has passed and a previous callback is done executing
|
280
|
+
$.when(timer, lastCallbackDone).then(nextCallback)
|
298
281
|
|
299
282
|
# Although (depending on the browser) we only need/receive either input or change,
|
300
283
|
# we always bind to both events in case another script manually triggers it.
|
@@ -307,12 +290,10 @@ up.form = (($) ->
|
|
307
290
|
|
308
291
|
$field.on(changeEvents, check)
|
309
292
|
|
310
|
-
check()
|
311
|
-
|
312
293
|
# return destructor
|
313
294
|
return ->
|
314
295
|
$field.off(changeEvents, check)
|
315
|
-
|
296
|
+
timer?.cancel()
|
316
297
|
|
317
298
|
###*
|
318
299
|
[Observes](/up.observe) a field or form and submits the form when a value changes.
|
@@ -860,7 +841,7 @@ up.form = (($) ->
|
|
860
841
|
but not if the checkbox was changed:
|
861
842
|
|
862
843
|
<form method="GET" action="/search">
|
863
|
-
<input type="search" name="query" autosubmit>
|
844
|
+
<input type="search" name="query" up-autosubmit>
|
864
845
|
<input type="checkbox"> Include archive
|
865
846
|
</form>
|
866
847
|
|
@@ -778,6 +778,7 @@ up.util = (($) ->
|
|
778
778
|
setTimeout(callback, millis)
|
779
779
|
else
|
780
780
|
callback()
|
781
|
+
undefined
|
781
782
|
|
782
783
|
|
783
784
|
###*
|
@@ -1777,14 +1778,21 @@ up.util = (($) ->
|
|
1777
1778
|
The proxy's `.promise` attribute is available even before the function is called
|
1778
1779
|
and will resolve when the inner function's returned promise resolves.
|
1779
1780
|
|
1781
|
+
If the inner function does not return a promise, the proxy's `.promise` attribute
|
1782
|
+
will resolve as soon as the inner function returns.
|
1783
|
+
|
1780
1784
|
@function up.util.previewable
|
1781
1785
|
@internal
|
1782
1786
|
###
|
1783
1787
|
previewable = (fun) ->
|
1784
1788
|
deferred = $.Deferred()
|
1785
1789
|
preview = (args...) ->
|
1786
|
-
fun(args...)
|
1787
|
-
|
1790
|
+
funValue = fun(args...)
|
1791
|
+
if isPromise(funValue)
|
1792
|
+
funValue.then -> deferred.resolve(funValue)
|
1793
|
+
else
|
1794
|
+
deferred.resolve(funValue)
|
1795
|
+
funValue
|
1788
1796
|
preview.promise = deferred.promise()
|
1789
1797
|
preview
|
1790
1798
|
|
@@ -1844,6 +1852,27 @@ up.util = (($) ->
|
|
1844
1852
|
->
|
1845
1853
|
map functions, (f) -> f()
|
1846
1854
|
|
1855
|
+
# ###*
|
1856
|
+
# @function up.util.race
|
1857
|
+
# @internal
|
1858
|
+
# ###
|
1859
|
+
# race = (promises...) ->
|
1860
|
+
# raceDone = $.Deferred()
|
1861
|
+
# each promises, (promise) ->
|
1862
|
+
# promise.then -> raceDone.resolve()
|
1863
|
+
# raceDone.promise()
|
1864
|
+
|
1865
|
+
###*
|
1866
|
+
@function up.util.promiseTimer
|
1867
|
+
@internal
|
1868
|
+
###
|
1869
|
+
promiseTimer = (ms) ->
|
1870
|
+
deferred = $.Deferred()
|
1871
|
+
timeout = setTimer ms, ->
|
1872
|
+
deferred.resolve()
|
1873
|
+
deferred.cancel = -> clearTimeout(timeout)
|
1874
|
+
deferred
|
1875
|
+
|
1847
1876
|
isDetached: isDetached
|
1848
1877
|
requestDataAsArray: requestDataAsArray
|
1849
1878
|
requestDataAsQuery: requestDataAsQuery
|
@@ -1952,6 +1981,8 @@ up.util = (($) ->
|
|
1952
1981
|
DivertibleChain: DivertibleChain
|
1953
1982
|
submittedValue: submittedValue
|
1954
1983
|
sequence: sequence
|
1984
|
+
promiseTimer: promiseTimer
|
1985
|
+
previewable: previewable
|
1955
1986
|
|
1956
1987
|
)($)
|
1957
1988
|
|
data/lib/unpoly/rails/version.rb
CHANGED
data/spec_app/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
|
-
unpoly-rails (0.
|
4
|
+
unpoly-rails (0.30.0)
|
5
5
|
rails (>= 3)
|
6
6
|
|
7
7
|
GEM
|
@@ -82,8 +82,8 @@ GEM
|
|
82
82
|
hpricot (~> 0.8.6)
|
83
83
|
ruby_parser (~> 3.1.1)
|
84
84
|
i18n (0.7.0)
|
85
|
-
jasmine-core (2.
|
86
|
-
jasmine-rails (0.
|
85
|
+
jasmine-core (2.5.2)
|
86
|
+
jasmine-rails (0.14.1)
|
87
87
|
jasmine-core (>= 1.3, < 3.0)
|
88
88
|
phantomjs (>= 1.9)
|
89
89
|
railties (>= 3.2.0)
|
@@ -99,12 +99,14 @@ GEM
|
|
99
99
|
mail (2.6.3)
|
100
100
|
mime-types (>= 1.16, < 3)
|
101
101
|
mime-types (2.99)
|
102
|
-
mini_portile2 (2.
|
103
|
-
minitest (5.
|
104
|
-
multi_json (1.
|
105
|
-
nokogiri (1.6.
|
106
|
-
mini_portile2 (~> 2.
|
107
|
-
|
102
|
+
mini_portile2 (2.1.0)
|
103
|
+
minitest (5.9.1)
|
104
|
+
multi_json (1.12.1)
|
105
|
+
nokogiri (1.6.8)
|
106
|
+
mini_portile2 (~> 2.1.0)
|
107
|
+
pkg-config (~> 1.1.7)
|
108
|
+
phantomjs (2.1.1.0)
|
109
|
+
pkg-config (1.1.7)
|
108
110
|
rack (1.6.4)
|
109
111
|
rack-test (0.6.3)
|
110
112
|
rack (>= 1.0)
|
@@ -132,7 +134,7 @@ GEM
|
|
132
134
|
activesupport (= 4.2.0)
|
133
135
|
rake (>= 0.8.7)
|
134
136
|
thor (>= 0.18.1, < 2.0)
|
135
|
-
rake (11.
|
137
|
+
rake (11.3.0)
|
136
138
|
ref (1.0.5)
|
137
139
|
rspec-core (3.4.1)
|
138
140
|
rspec-support (~> 3.4.0)
|
@@ -3,7 +3,7 @@ describe 'up.form', ->
|
|
3
3
|
u = up.util
|
4
4
|
|
5
5
|
describe 'Javascript functions', ->
|
6
|
-
|
6
|
+
|
7
7
|
describe 'up.observe', ->
|
8
8
|
|
9
9
|
beforeEach ->
|
@@ -23,43 +23,100 @@ describe 'up.form', ->
|
|
23
23
|
|
24
24
|
u.each changeEvents, (eventName) ->
|
25
25
|
|
26
|
-
|
27
|
-
$input = affix('input[value="old-value"]')
|
28
|
-
callback = jasmine.createSpy('change callback')
|
29
|
-
up.observe($input, callback)
|
30
|
-
$input.val('new-value')
|
31
|
-
u.times 2, -> $input.trigger(eventName)
|
32
|
-
u.nextFrame ->
|
33
|
-
expect(callback).toHaveBeenCalledWith('new-value', $input)
|
34
|
-
expect(callback.calls.count()).toEqual(1)
|
35
|
-
done()
|
26
|
+
describe "when the input receives a #{eventName} event", ->
|
36
27
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
28
|
+
it "runs the callback if the value changed", (done) ->
|
29
|
+
$input = affix('input[value="old-value"]')
|
30
|
+
callback = jasmine.createSpy('change callback')
|
31
|
+
up.observe($input, callback)
|
32
|
+
$input.val('new-value')
|
33
|
+
u.times 2, -> $input.trigger(eventName)
|
34
|
+
u.nextFrame ->
|
35
|
+
expect(callback).toHaveBeenCalledWith('new-value', $input)
|
36
|
+
expect(callback.calls.count()).toEqual(1)
|
37
|
+
done()
|
45
38
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
39
|
+
it "does not run the callback if the value didn't change", (done) ->
|
40
|
+
$input = affix('input[value="old-value"]')
|
41
|
+
callback = jasmine.createSpy('change callback')
|
42
|
+
up.observe($input, callback)
|
43
|
+
$input.trigger(eventName)
|
44
|
+
u.nextFrame ->
|
45
|
+
expect(callback).not.toHaveBeenCalled()
|
46
|
+
done()
|
53
47
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
48
|
+
it 'debounces the callback when the { delay } option is given', (done) ->
|
49
|
+
$input = affix('input[value="old-value"]')
|
50
|
+
callback = jasmine.createSpy('change callback')
|
51
|
+
up.observe($input, { delay: 100 }, callback)
|
52
|
+
$input.val('new-value-1')
|
53
|
+
$input.trigger(eventName)
|
54
|
+
u.setTimer 50, ->
|
55
|
+
# 50 ms after change 1: We're still waiting for the 100ms delay to expire
|
56
|
+
expect(callback.calls.count()).toEqual(0)
|
57
|
+
u.setTimer 100, ->
|
58
|
+
# 150 ms after change 1: The 100ms delay has expired
|
59
|
+
expect(callback.calls.count()).toEqual(1)
|
60
|
+
expect(callback.calls.mostRecent().args[0]).toEqual('new-value-1')
|
61
|
+
$input.val('new-value-2')
|
62
|
+
$input.trigger(eventName)
|
63
|
+
u.setTimer 40, ->
|
64
|
+
# 40 ms after change 2: We change again, resetting the delay
|
65
|
+
expect(callback.calls.count()).toEqual(1)
|
66
|
+
$input.val('new-value-3')
|
67
|
+
$input.trigger(eventName)
|
68
|
+
u.setTimer 85, ->
|
69
|
+
# 125 ms after change 2, which was superseded by change 3
|
70
|
+
# 85 ms after change 3
|
71
|
+
expect(callback.calls.count()).toEqual(1)
|
72
|
+
u.setTimer 65, ->
|
73
|
+
# 190 ms after change 2, which was superseded by change 3
|
74
|
+
# 150 ms after change 3
|
75
|
+
expect(callback.calls.count()).toEqual(2)
|
76
|
+
expect(callback.calls.mostRecent().args[0]).toEqual('new-value-3')
|
77
|
+
done()
|
78
|
+
|
79
|
+
it 'delays a callback if a previous async callback is taking long to execute', (done) ->
|
80
|
+
$input = affix('input[value="old-value"]')
|
81
|
+
callbackCount = 0
|
82
|
+
callback = ->
|
83
|
+
callbackCount += 1
|
84
|
+
u.promiseTimer(100)
|
85
|
+
up.observe($input, { delay: 1 }, callback)
|
86
|
+
$input.val('new-value-1')
|
87
|
+
$input.trigger(eventName)
|
88
|
+
u.setTimer 30, ->
|
89
|
+
# Callback has been called and takes 100 ms to complete
|
90
|
+
expect(callbackCount).toEqual(1)
|
91
|
+
$input.val('new-value-2')
|
92
|
+
$input.trigger(eventName)
|
93
|
+
u.setTimer 30, ->
|
94
|
+
# Second callback is triggerd, but waits for first callback to complete
|
95
|
+
expect(callbackCount).toEqual(1)
|
96
|
+
u.setTimer 100, ->
|
97
|
+
expect(callbackCount).toEqual(2)
|
98
|
+
done()
|
99
|
+
|
100
|
+
it 'does not run multiple callbacks if a long-running callback has been blocking multiple subsequent callbacks'
|
101
|
+
|
102
|
+
it "runs a callback in the same frame if the delay is 0", ->
|
103
|
+
console.debug('*** next example')
|
104
|
+
$input = affix('input[value="old-value"]')
|
105
|
+
callback = jasmine.createSpy('change callback')
|
106
|
+
up.observe($input, { delay: 0 }, callback)
|
107
|
+
$input.val('new-value')
|
108
|
+
$input.trigger(eventName)
|
109
|
+
expect(callback.calls.count()).toEqual(1)
|
110
|
+
|
111
|
+
it "runs multiple callbacks in the same frame if the delay is 0", ->
|
112
|
+
$input = affix('input[value="old-value"]')
|
113
|
+
callback = jasmine.createSpy('change callback')
|
114
|
+
up.observe($input, { delay: 0 }, callback)
|
115
|
+
$input.val('new-value')
|
116
|
+
$input.trigger(eventName)
|
117
|
+
$input.val('yet-another-value')
|
118
|
+
$input.trigger(eventName)
|
119
|
+
expect(callback.calls.count()).toEqual(2)
|
63
120
|
|
64
121
|
describe 'when the first argument is a checkbox', ->
|
65
122
|
|
@@ -163,42 +220,44 @@ describe 'up.form', ->
|
|
163
220
|
|
164
221
|
u.each changeEvents, (eventName) ->
|
165
222
|
|
166
|
-
|
167
|
-
$form = affix('form')
|
168
|
-
$input = $form.affix('input[value="old-value"]')
|
169
|
-
callback = jasmine.createSpy('change callback')
|
170
|
-
up.observe($form, callback)
|
171
|
-
$input.val('new-value')
|
172
|
-
u.times 2, -> $input.trigger(eventName)
|
173
|
-
u.nextFrame ->
|
174
|
-
expect(callback).toHaveBeenCalledWith('new-value', $input)
|
175
|
-
expect(callback.calls.count()).toEqual(1)
|
176
|
-
done()
|
223
|
+
describe "when any of the form's inputs receives a #{eventName} event", ->
|
177
224
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
225
|
+
it "runs the callback if the value changed", (done) ->
|
226
|
+
$form = affix('form')
|
227
|
+
$input = $form.affix('input[value="old-value"]')
|
228
|
+
callback = jasmine.createSpy('change callback')
|
229
|
+
up.observe($form, callback)
|
230
|
+
$input.val('new-value')
|
231
|
+
u.times 2, -> $input.trigger(eventName)
|
232
|
+
u.nextFrame ->
|
233
|
+
expect(callback).toHaveBeenCalledWith('new-value', $input)
|
234
|
+
expect(callback.calls.count()).toEqual(1)
|
235
|
+
done()
|
187
236
|
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
237
|
+
it "does not run the callback if the value didn't change", (done) ->
|
238
|
+
$form = affix('form')
|
239
|
+
$input = $form.affix('input[value="old-value"]')
|
240
|
+
callback = jasmine.createSpy('change callback')
|
241
|
+
up.observe($form, callback)
|
242
|
+
$input.trigger(eventName)
|
243
|
+
u.nextFrame ->
|
244
|
+
expect(callback).not.toHaveBeenCalled()
|
245
|
+
done()
|
246
|
+
|
247
|
+
# it 'runs the callback only once when a radio button group changes its selection', ->
|
248
|
+
# $form = affix('form')
|
249
|
+
# $radio1 = $form.affix('input[type="radio"][name="group"][value="1"][checked="checked"]')
|
250
|
+
# $radio2 = $form.affix('input[type="radio"][name="group"][value="2"]')
|
251
|
+
# callback = jasmine.createSpy('change callback')
|
252
|
+
# up.observe($form, callback)
|
253
|
+
# $radio2.get(0).click()
|
254
|
+
# u.nextFrame ->
|
255
|
+
# expect(callback.calls.count()).toEqual(1)
|
197
256
|
|
198
257
|
describe 'up.submit', ->
|
199
258
|
|
200
259
|
describeCapability 'canPushState', ->
|
201
|
-
|
260
|
+
|
202
261
|
beforeEach ->
|
203
262
|
@$form = affix('form[action="/path/to"][method="put"][up-target=".response"]')
|
204
263
|
@$form.append('<input name="field1" value="value1">')
|
@@ -232,11 +291,11 @@ describe 'up.form', ->
|
|
232
291
|
responseText:
|
233
292
|
"""
|
234
293
|
text-before
|
235
|
-
|
294
|
+
|
236
295
|
<form>
|
237
296
|
error-messages
|
238
297
|
</form>
|
239
|
-
|
298
|
+
|
240
299
|
text-after
|
241
300
|
"""
|
242
301
|
expect(up.browser.url()).toEqual(@hrefBeforeExample)
|
@@ -300,12 +359,12 @@ describe 'up.form', ->
|
|
300
359
|
expect(form.submit).toHaveBeenCalled()
|
301
360
|
|
302
361
|
describeFallback 'canPushState', ->
|
303
|
-
|
362
|
+
|
304
363
|
it 'falls back to a vanilla form submission', ->
|
305
364
|
$form = affix('form[action="/path/to"][method="put"][up-target=".response"]')
|
306
365
|
form = $form.get(0)
|
307
366
|
spyOn(form, 'submit')
|
308
|
-
|
367
|
+
|
309
368
|
up.submit($form)
|
310
369
|
expect(form.submit).toHaveBeenCalled()
|
311
370
|
|
@@ -358,7 +417,10 @@ describe 'up.form', ->
|
|
358
417
|
|
359
418
|
describe '[up-observe]', ->
|
360
419
|
|
361
|
-
|
420
|
+
afterEach ->
|
421
|
+
window.observeCallbackSpy = undefined
|
422
|
+
|
423
|
+
it 'runs the Javascript code in the attribute value when a change is observed in the field', (done) ->
|
362
424
|
$form = affix('form')
|
363
425
|
window.observeCallbackSpy = jasmine.createSpy('observe callback')
|
364
426
|
$field = $form.affix('input[val="old-value"][up-observe="window.observeCallbackSpy(value, $field.get(0))"]')
|
@@ -369,6 +431,20 @@ describe 'up.form', ->
|
|
369
431
|
expect(window.observeCallbackSpy).toHaveBeenCalledWith('new-value', $field.get(0))
|
370
432
|
done()
|
371
433
|
|
434
|
+
describe 'with [up-delay] modifier', ->
|
435
|
+
|
436
|
+
it 'debounces the callback', (done) ->
|
437
|
+
$form = affix('form')
|
438
|
+
window.observeCallbackSpy = jasmine.createSpy('observe callback')
|
439
|
+
$field = $form.affix('input[val="old-value"][up-observe="window.observeCallbackSpy()"][up-delay="50"]')
|
440
|
+
up.hello($form)
|
441
|
+
$field.val('new-value')
|
442
|
+
$field.trigger('change')
|
443
|
+
u.nextFrame ->
|
444
|
+
expect(window.observeCallbackSpy).not.toHaveBeenCalled()
|
445
|
+
u.setTimer 80, ->
|
446
|
+
expect(window.observeCallbackSpy).toHaveBeenCalled()
|
447
|
+
done()
|
372
448
|
|
373
449
|
describe 'input[up-validate]', ->
|
374
450
|
|
@@ -1,7 +1,85 @@
|
|
1
1
|
describe 'up.util', ->
|
2
|
-
|
2
|
+
|
3
|
+
u = up.util
|
4
|
+
|
3
5
|
describe 'Javascript functions', ->
|
4
6
|
|
7
|
+
describe 'up.util.previewable', ->
|
8
|
+
|
9
|
+
it 'wraps a function into a proxy function with an additional .promise attribute', ->
|
10
|
+
fun = -> 'return value'
|
11
|
+
proxy = up.util.previewable(fun)
|
12
|
+
expect(u.isFunction(proxy)).toBe(true)
|
13
|
+
expect(u.isPromise(proxy.promise)).toBe(true)
|
14
|
+
expect(proxy()).toEqual('return value')
|
15
|
+
|
16
|
+
it "resolves the proxy's .promise when the inner function returns", (done) ->
|
17
|
+
fun = -> 'return value'
|
18
|
+
proxy = up.util.previewable(fun)
|
19
|
+
callback = jasmine.createSpy('promise callback')
|
20
|
+
proxy.promise.then(callback)
|
21
|
+
u.nextFrame ->
|
22
|
+
expect(callback).not.toHaveBeenCalled()
|
23
|
+
proxy()
|
24
|
+
u.nextFrame ->
|
25
|
+
expect(callback).toHaveBeenCalledWith('return value')
|
26
|
+
done()
|
27
|
+
|
28
|
+
it "delays resolution of the proxy's .promise if the inner function returns a promise", (done) ->
|
29
|
+
funDeferred = $.Deferred()
|
30
|
+
fun = -> funDeferred
|
31
|
+
proxy = up.util.previewable(fun)
|
32
|
+
callback = jasmine.createSpy('promise callback')
|
33
|
+
proxy.promise.then(callback)
|
34
|
+
proxy()
|
35
|
+
u.nextFrame ->
|
36
|
+
expect(callback).not.toHaveBeenCalled()
|
37
|
+
funDeferred.resolve()
|
38
|
+
u.nextFrame ->
|
39
|
+
expect(callback).toHaveBeenCalled()
|
40
|
+
done()
|
41
|
+
|
42
|
+
describe 'up.util.DivertibleChain', ->
|
43
|
+
|
44
|
+
it "instantiates a task queue whose (2..n)th tasks can be changed by calling '.asap'", (done) ->
|
45
|
+
chain = new up.util.DivertibleChain()
|
46
|
+
|
47
|
+
timer1Spy = jasmine.createSpy('timer1 has been called')
|
48
|
+
timer1 = ->
|
49
|
+
timer1Spy()
|
50
|
+
u.promiseTimer(50)
|
51
|
+
|
52
|
+
timer2Spy = jasmine.createSpy('timer2 has been called')
|
53
|
+
timer2 = ->
|
54
|
+
timer2Spy()
|
55
|
+
u.promiseTimer(50)
|
56
|
+
|
57
|
+
timer3Spy = jasmine.createSpy('timer3 has been called')
|
58
|
+
timer3 = ->
|
59
|
+
timer3Spy()
|
60
|
+
u.promiseTimer(50)
|
61
|
+
|
62
|
+
timer4Spy = jasmine.createSpy('timer4 has been called')
|
63
|
+
timer4 = ->
|
64
|
+
timer4Spy()
|
65
|
+
u.promiseTimer(50)
|
66
|
+
|
67
|
+
chain.asap(timer1)
|
68
|
+
u.nextFrame ->
|
69
|
+
expect(timer1Spy).toHaveBeenCalled()
|
70
|
+
chain.asap(timer2)
|
71
|
+
u.nextFrame ->
|
72
|
+
# timer2 is still waiting for timer1 to finish
|
73
|
+
expect(timer2Spy).not.toHaveBeenCalled()
|
74
|
+
# Override the (2..n)th tasks. This unschedules timer2.
|
75
|
+
chain.asap(timer3, timer4)
|
76
|
+
u.setTimer 80, ->
|
77
|
+
expect(timer2Spy).not.toHaveBeenCalled()
|
78
|
+
expect(timer3Spy).toHaveBeenCalled()
|
79
|
+
u.setTimer 70, ->
|
80
|
+
expect(timer4Spy).toHaveBeenCalled()
|
81
|
+
done()
|
82
|
+
|
5
83
|
describe 'up.util.sequence', ->
|
6
84
|
|
7
85
|
it 'combines the given functions into a single function', ->
|
@@ -144,10 +222,17 @@ describe 'up.util', ->
|
|
144
222
|
jasmine.clock().tick(1500)
|
145
223
|
expect(callback).toHaveBeenCalled()
|
146
224
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
225
|
+
describe 'if the delay is zero', ->
|
226
|
+
|
227
|
+
it 'calls the given function in the current execution frame', ->
|
228
|
+
callback = jasmine.createSpy()
|
229
|
+
up.util.setTimer(0, callback)
|
230
|
+
expect(callback).toHaveBeenCalled()
|
231
|
+
|
232
|
+
it "returns undefined so the return value won't be mistaken with a Javascript timer ID", ->
|
233
|
+
callback = -> 'function return value'
|
234
|
+
timerReturnValue = up.util.setTimer(0, callback)
|
235
|
+
expect(timerReturnValue).toBeUndefined()
|
151
236
|
|
152
237
|
# describe 'up.util.argNames', ->
|
153
238
|
#
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unpoly-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.30.
|
4
|
+
version: 0.30.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Henning Koch
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-10-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|