unpoly-rails 0.37.0 → 0.50.0

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.

Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +127 -25
  3. data/LICENSE +1 -1
  4. data/README_RAILS.md +4 -2
  5. data/Rakefile +6 -1
  6. data/dist/unpoly.js +3192 -2198
  7. data/dist/unpoly.min.js +4 -3
  8. data/lib/assets/javascripts/unpoly/browser.coffee +51 -63
  9. data/lib/assets/javascripts/unpoly/bus.coffee +58 -33
  10. data/lib/assets/javascripts/unpoly/classes/cache.coffee +117 -0
  11. data/lib/assets/javascripts/unpoly/{dom → classes}/extract_cascade.coffee +3 -3
  12. data/lib/assets/javascripts/unpoly/{dom → classes}/extract_plan.coffee +1 -1
  13. data/lib/assets/javascripts/unpoly/classes/field_observer.coffee +57 -0
  14. data/lib/assets/javascripts/unpoly/classes/follow_variant.coffee +52 -0
  15. data/lib/assets/javascripts/unpoly/classes/motion_tracker.coffee +95 -0
  16. data/lib/assets/javascripts/unpoly/classes/record.coffee +16 -0
  17. data/lib/assets/javascripts/unpoly/classes/request.coffee +228 -0
  18. data/lib/assets/javascripts/unpoly/classes/response.coffee +138 -0
  19. data/lib/assets/javascripts/unpoly/dom.coffee +151 -142
  20. data/lib/assets/javascripts/unpoly/feedback.coffee +67 -38
  21. data/lib/assets/javascripts/unpoly/form.coffee +156 -139
  22. data/lib/assets/javascripts/unpoly/history.coffee +22 -19
  23. data/lib/assets/javascripts/unpoly/layout.coffee +108 -90
  24. data/lib/assets/javascripts/unpoly/link.coffee +159 -158
  25. data/lib/assets/javascripts/unpoly/log.coffee +5 -5
  26. data/lib/assets/javascripts/unpoly/modal.coffee +93 -81
  27. data/lib/assets/javascripts/unpoly/motion.coffee +291 -250
  28. data/lib/assets/javascripts/unpoly/popup.coffee +67 -53
  29. data/lib/assets/javascripts/unpoly/protocol.coffee +67 -16
  30. data/lib/assets/javascripts/unpoly/proxy.coffee +282 -211
  31. data/lib/assets/javascripts/unpoly/rails.coffee +3 -14
  32. data/lib/assets/javascripts/unpoly/syntax.coffee +54 -49
  33. data/lib/assets/javascripts/unpoly/tooltip.coffee +18 -25
  34. data/lib/assets/javascripts/unpoly/util.coffee +236 -477
  35. data/lib/assets/javascripts/unpoly.coffee +1 -1
  36. data/lib/unpoly/rails/inspector.rb +67 -22
  37. data/lib/unpoly/rails/version.rb +1 -1
  38. data/package.json +1 -1
  39. data/spec_app/Gemfile.lock +13 -13
  40. data/spec_app/app/assets/javascripts/integration_test.coffee +1 -0
  41. data/spec_app/app/assets/javascripts/jasmine_specs.coffee +1 -1
  42. data/spec_app/app/assets/stylesheets/jasmine_specs.sass +10 -0
  43. data/spec_app/app/controllers/binding_test_controller.rb +19 -2
  44. data/spec_app/app/controllers/method_test_controller.rb +16 -0
  45. data/spec_app/app/views/layouts/jasmine_rails/spec_runner.html.erb +20 -0
  46. data/spec_app/app/views/method_test/form_target.erb +17 -0
  47. data/spec_app/app/views/method_test/page1.erb +11 -0
  48. data/spec_app/app/views/method_test/page2.erb +6 -0
  49. data/spec_app/app/views/pages/start.erb +33 -19
  50. data/spec_app/config/initializers/assets.rb +5 -0
  51. data/spec_app/config/routes.rb +3 -0
  52. data/spec_app/spec/controllers/binding_test_controller_spec.rb +82 -27
  53. data/spec_app/spec/javascripts/helpers/agent_detector.coffee +17 -0
  54. data/spec_app/spec/javascripts/helpers/async_sequence.js.coffee +102 -0
  55. data/spec_app/spec/javascripts/helpers/last_request.js.coffee +1 -1
  56. data/spec_app/spec/javascripts/helpers/mock_ajax.js.coffee +5 -2
  57. data/spec_app/spec/javascripts/helpers/promise_state.js +18 -0
  58. data/spec_app/spec/javascripts/helpers/protect_jasmine_runner.coffee +9 -0
  59. data/spec_app/spec/javascripts/helpers/reset_history.js.coffee +22 -0
  60. data/spec_app/spec/javascripts/helpers/reset_up.js.coffee +11 -3
  61. data/spec_app/spec/javascripts/helpers/show_lib_versions.coffee +10 -0
  62. data/spec_app/spec/javascripts/helpers/to_be_error.coffee +5 -0
  63. data/spec_app/spec/javascripts/helpers/to_match_url.coffee +13 -0
  64. data/spec_app/spec/javascripts/helpers/trigger.js.coffee +13 -6
  65. data/spec_app/spec/javascripts/up/browser_spec.js.coffee +92 -33
  66. data/spec_app/spec/javascripts/up/bus_spec.js.coffee +64 -15
  67. data/spec_app/spec/javascripts/up/classes/.keep +0 -0
  68. data/spec_app/spec/javascripts/up/classes/cache_spec.js.coffee +1 -0
  69. data/spec_app/spec/javascripts/up/dom_spec.js.coffee +759 -551
  70. data/spec_app/spec/javascripts/up/feedback_spec.js.coffee +155 -82
  71. data/spec_app/spec/javascripts/up/form_spec.js.coffee +490 -349
  72. data/spec_app/spec/javascripts/up/history_spec.js.coffee +226 -179
  73. data/spec_app/spec/javascripts/up/layout_spec.js.coffee +253 -185
  74. data/spec_app/spec/javascripts/up/link_spec.js.coffee +416 -270
  75. data/spec_app/spec/javascripts/up/modal_spec.js.coffee +459 -330
  76. data/spec_app/spec/javascripts/up/motion_spec.js.coffee +198 -153
  77. data/spec_app/spec/javascripts/up/namespace_spec.js.coffee +9 -0
  78. data/spec_app/spec/javascripts/up/popup_spec.js.coffee +240 -175
  79. data/spec_app/spec/javascripts/up/protocol_spec.js.coffee +38 -0
  80. data/spec_app/spec/javascripts/up/proxy_spec.js.coffee +777 -303
  81. data/spec_app/spec/javascripts/up/rails_spec.js.coffee +24 -8
  82. data/spec_app/spec/javascripts/up/syntax_spec.js.coffee +40 -23
  83. data/spec_app/spec/javascripts/up/tooltip_spec.js.coffee +80 -66
  84. data/spec_app/spec/javascripts/up/util_spec.js.coffee +227 -201
  85. data/spec_app/vendor/asset-libs/es6-promise-4.1.6/es6-promise.auto.js +1159 -0
  86. metadata +30 -7
  87. data/spec_app/spec/javascripts/helpers/reset_path.js.coffee +0 -7
  88. data/spec_app/spec/javascripts/helpers/to_equal_url.coffee +0 -11
@@ -10,7 +10,7 @@ describe 'up.motion', ->
10
10
  $element = affix('.element').text('content')
11
11
  up.animate($element, 'fade-in', duration: 200, easing: 'linear')
12
12
 
13
- u.setTimer 0, ->
13
+ u.setTimer 5, ->
14
14
  expect(u.opacity($element)).toBeAround(0.0, 0.25)
15
15
  u.setTimer 100, ->
16
16
  expect(u.opacity($element)).toBeAround(0.5, 0.25)
@@ -18,7 +18,7 @@ describe 'up.motion', ->
18
18
  expect(u.opacity($element)).toBeAround(1.0, 0.25)
19
19
  done()
20
20
 
21
- it 'returns a promise that is resolved when the animation completed', (done) ->
21
+ it 'returns a promise that is fulfilled when the animation has completed', (done) ->
22
22
  $element = affix('.element').text('content')
23
23
  resolveSpy = jasmine.createSpy('resolve')
24
24
 
@@ -31,11 +31,11 @@ describe 'up.motion', ->
31
31
  expect(resolveSpy).toHaveBeenCalled()
32
32
  done()
33
33
 
34
- it 'cancels an existing animation on the element by instantly jumping to the last frame', ->
34
+ it 'cancels an existing animation on the element by instantly jumping to the last frame', asyncSpec (next) ->
35
35
  $element = affix('.element').text('content')
36
36
  up.animate($element, { 'font-size': '40px' }, duration: 10000, easing: 'linear')
37
- up.animate($element, { 'fade-in' }, duration: 100, easing: 'linear')
38
- expect($element.css('font-size')).toEqual('40px')
37
+ next => up.animate($element, { 'fade-in' }, duration: 100, easing: 'linear')
38
+ next => expect($element.css('font-size')).toEqual('40px')
39
39
 
40
40
  describe 'with animations disabled globally', ->
41
41
 
@@ -47,128 +47,155 @@ describe 'up.motion', ->
47
47
  callback = jasmine.createSpy('animation done callback')
48
48
  animateDone = up.animate($element, { 'font-size': '40px' }, duration: 10000, easing: 'linear')
49
49
  animateDone.then(callback)
50
- expect($element.css('font-size')).toEqual('40px')
51
- u.nextFrame ->
50
+
51
+ u.setTimer 5, =>
52
+ expect($element.css('font-size')).toEqual('40px')
52
53
  expect(callback).toHaveBeenCalled()
53
54
  done()
54
55
 
55
- [false, null, undefined, 'none', up.motion.none()].forEach (noneAnimation) ->
56
+ [false, null, undefined, 'none', '', {}].forEach (noneAnimation) ->
56
57
 
57
58
  describe "when called with a `#{noneAnimation}` animation", ->
58
59
 
59
- it "doesn't animate and resolves instantly", (done) ->
60
+ it "doesn't animate and resolves instantly", asyncSpec (next) ->
60
61
  $element = affix('.element').text('content')
61
62
  callback = jasmine.createSpy('animation done callback')
62
63
  animateDone = up.animate($element, noneAnimation, duration: 10000, easing: 'linear')
63
64
  animateDone.then(callback)
64
- u.nextFrame ->
65
- expect(callback).toHaveBeenCalled()
66
- done()
65
+ next => expect(callback).toHaveBeenCalled()
67
66
 
68
67
  describe 'up.motion.finish', ->
69
68
 
70
69
  describe 'when called with an element or selector', ->
71
70
 
72
- it 'cancels an existing animation on the given element by instantly jumping to the last frame', ->
71
+ it 'cancels an existing animation on the given element by instantly jumping to the last frame', asyncSpec (next) ->
73
72
  $element = affix('.element').text('content')
74
- up.animate($element, { 'font-size': '40px', 'opacity': '0.33' }, duration: 10000)
75
- up.motion.finish($element)
76
- expect($element.css('font-size')).toEqual('40px')
77
- expect($element.css('opacity')).toEqual('0.33')
73
+ up.animate($element, { 'font-size': '40px', 'opacity': '0.5' }, duration: 30000)
74
+
75
+ next =>
76
+ up.motion.finish($element)
78
77
 
79
- it 'cancels animations on children of the given element', ->
78
+ next =>
79
+ expect($element.css('font-size')).toEqual('40px')
80
+ expect(parseFloat($element.css('opacity'))).toBeAround(0.5, 0.01) # Safari sometimes has rounding errors
81
+
82
+ it 'cancels animations on children of the given element', asyncSpec (next) ->
80
83
  $parent = affix('.element')
81
84
  $child = $parent.affix('.child')
82
85
  up.animate($child, { 'font-size': '40px' }, duration: 10000)
83
- up.motion.finish($parent)
84
- expect($child.css('font-size')).toEqual('40px')
85
86
 
86
- it 'does not cancel animations on other elements', ->
87
+ next =>
88
+ up.motion.finish($parent)
89
+
90
+ next =>
91
+ expect($child.css('font-size')).toEqual('40px')
92
+
93
+ it 'does not cancel animations on other elements', asyncSpec (next) ->
87
94
  $element1 = affix('.element1').text('content1')
88
95
  $element2 = affix('.element2').text('content2')
89
96
  up.animate($element1, 'fade-in', duration: 10000)
90
97
  up.animate($element2, 'fade-in', duration: 10000)
91
- up.motion.finish($element1)
92
- expect(Number($element1.css('opacity'))).toEqual(1)
93
- expect(Number($element2.css('opacity'))).toEqual(0, 0.1)
94
98
 
95
- it 'restores existing transitions on the element', ->
99
+ next =>
100
+ up.motion.finish($element1)
101
+
102
+ next =>
103
+ expect(Number($element1.css('opacity'))).toEqual(1)
104
+ expect(Number($element2.css('opacity'))).toBeAround(0, 0.1)
105
+
106
+ it 'restores existing transitions on the element', asyncSpec (next) ->
96
107
  $element = affix('.element').text('content')
97
108
  $element.css('transition': 'font-size 3s ease')
98
109
  oldTransitionProperty = $element.css('transition-property')
99
110
  expect(oldTransitionProperty).toBeDefined()
100
111
  expect(oldTransitionProperty).toContain('font-size') # be paranoid
101
112
  up.animate($element, 'fade-in', duration: 10000)
102
- up.motion.finish($element)
103
- expect(u.opacity($element)).toEqual(1)
104
- currentTransitionProperty = $element.css('transition-property')
105
- expect(currentTransitionProperty).toEqual(oldTransitionProperty)
106
- expect(currentTransitionProperty).toContain('font-size')
107
- expect(currentTransitionProperty).not.toContain('opacity')
108
-
109
- it 'cancels an existing transition on the element by instantly jumping to the last frame', ->
113
+
114
+ next =>
115
+ up.motion.finish($element)
116
+
117
+ next =>
118
+ expect(u.opacity($element)).toEqual(1)
119
+ currentTransitionProperty = $element.css('transition-property')
120
+ expect(currentTransitionProperty).toEqual(oldTransitionProperty)
121
+ expect(currentTransitionProperty).toContain('font-size')
122
+ expect(currentTransitionProperty).not.toContain('opacity')
123
+
124
+ it 'cancels an existing transition on the element by instantly jumping to the last frame', asyncSpec (next) ->
110
125
  $old = affix('.old').text('old content')
111
126
  $new = affix('.new').text('new content')
112
127
 
113
128
  up.morph($old, $new, 'cross-fade', duration: 2000)
114
- expect($('.up-ghost').length).toBe(2)
115
129
 
116
- up.motion.finish($old)
130
+ next =>
131
+ expect($('.up-ghost').length).toBe(2)
117
132
 
118
- expect($('.up-ghost').length).toBe(0)
119
- expect($old.css('display')).toEqual('none')
120
- expect($new.css('display')).toEqual('block')
133
+ next.await =>
134
+ up.motion.finish($old)
135
+
136
+ next.after 100, =>
137
+ expect($('.up-ghost').length).toBe(0)
138
+ expect($old.css('display')).toEqual('none')
139
+ expect($new.css('display')).toEqual('block')
121
140
 
122
- it 'can be called on either element involved in a transition', ->
141
+ it 'can be called on either element involved in a transition', asyncSpec (next) ->
123
142
  $old = affix('.old').text('old content')
124
143
  $new = affix('.new').text('new content')
125
144
 
126
145
  up.morph($old, $new, 'cross-fade', duration: 2000)
127
- expect($('.up-ghost').length).toBe(2)
128
146
 
129
- up.motion.finish($new)
147
+ next =>
148
+ expect($('.up-ghost').length).toBe(2)
130
149
 
131
- expect($('.up-ghost').length).toBe(0)
132
- expect($old.css('display')).toEqual('none')
133
- expect($new.css('display')).toEqual('block')
150
+ up.motion.finish($new)
134
151
 
152
+ next =>
153
+ expect($('.up-ghost').length).toBe(0)
154
+ expect($old.css('display')).toEqual('none')
155
+ expect($new.css('display')).toEqual('block')
135
156
 
136
- it 'cancels transitions on children of the given element', ->
157
+
158
+ it 'cancels transitions on children of the given element', asyncSpec (next) ->
137
159
  $parent = affix('.parent')
138
160
  $old = $parent.affix('.old').text('old content')
139
161
  $new = $parent.affix('.new').text('new content')
140
162
 
141
163
  up.morph($old, $new, 'cross-fade', duration: 2000)
142
- expect($('.up-ghost').length).toBe(2)
143
164
 
144
- up.motion.finish($parent)
165
+ next =>
166
+ expect($('.up-ghost').length).toBe(2)
145
167
 
146
- expect($('.up-ghost').length).toBe(0)
147
- expect($old.css('display')).toEqual('none')
148
- expect($new.css('display')).toEqual('block')
168
+ up.motion.finish($parent)
169
+
170
+ next =>
171
+ expect($('.up-ghost').length).toBe(0)
172
+ expect($old.css('display')).toEqual('none')
173
+ expect($new.css('display')).toEqual('block')
149
174
 
150
175
  describe 'when called without arguments', ->
151
176
 
152
- it 'cancels all animations on the screen', ->
177
+ it 'cancels all animations on the screen', asyncSpec (next) ->
153
178
  $element1 = affix('.element1').text('content1')
154
179
  $element2 = affix('.element2').text('content2')
155
180
 
156
181
  up.animate($element1, 'fade-in', duration: 3000)
157
182
  up.animate($element2, 'fade-in', duration: 3000)
158
183
 
159
- expect(u.opacity($element1)).toBeAround(0.0, 0.1)
160
- expect(u.opacity($element2)).toBeAround(0.0, 0.1)
184
+ next =>
185
+ expect(u.opacity($element1)).toBeAround(0.0, 0.1)
186
+ expect(u.opacity($element2)).toBeAround(0.0, 0.1)
161
187
 
162
- up.motion.finish()
188
+ up.motion.finish()
163
189
 
164
- $element1 = $('.element1')
165
- $element2 = $('.element2')
166
- expect(u.opacity($element1)).toBe(1.0)
167
- expect(u.opacity($element2)).toBe(1.0)
190
+ next =>
191
+ $element1 = $('.element1')
192
+ $element2 = $('.element2')
193
+ expect(u.opacity($element1)).toBe(1.0)
194
+ expect(u.opacity($element2)).toBe(1.0)
168
195
 
169
196
  describe 'up.morph', ->
170
197
 
171
- it 'transitions between two element by animating two copies while keeping the originals in the background', (done) ->
198
+ it 'transitions between two element by animating two copies while keeping the originals in the background', asyncSpec (next) ->
172
199
 
173
200
  $old = affix('.old').text('old content').css(
174
201
  position: 'absolute'
@@ -186,75 +213,75 @@ describe 'up.motion', ->
186
213
  )
187
214
  up.morph($old, $new, 'cross-fade', duration: 200, easing: 'linear')
188
215
 
189
- # The actual animation will be performed on Ghosts since
190
- # two element usually cannot exist in the DOM at the same time
191
- # without undesired visual effects
192
- $oldGhost = $('.old.up-ghost')
193
- $newGhost = $('.new.up-ghost')
194
- expect($oldGhost).toExist()
195
- expect($newGhost).toExist()
196
-
197
- $oldBounds = $oldGhost.parent('.up-bounds')
198
- $newBounds = $newGhost.parent('.up-bounds')
199
- expect($oldBounds).toExist()
200
- expect($newBounds).toExist()
201
-
202
- # Ghosts should be inserted before (not after) the element
203
- # or the browser scroll position will be too low after the
204
- # transition ends.
205
- expect($oldGhost.parent().next()).toEqual($old)
206
- expect($newGhost.parent().next()).toEqual($new)
207
-
208
- # The old element is removed from the layout flow.
209
- # It will be removed from the DOM after the animation has ended.
210
- expect($old.css('display')).toEqual('none')
211
-
212
- # The new element is invisible due to an opacity of zero,
213
- # but takes up the space in the layout flow.
214
- expect($new.css(['display', 'opacity'])).toEqual(
215
- display: 'block',
216
- opacity: '0'
217
- )
216
+ next =>
217
+ # The actual animation will be performed on Ghosts since
218
+ # two element usually cannot exist in the DOM at the same time
219
+ # without undesired visual effects
220
+ @$oldGhost = $('.old.up-ghost')
221
+ @$newGhost = $('.new.up-ghost')
222
+ expect(@$oldGhost).toExist()
223
+ expect(@$newGhost).toExist()
224
+
225
+ $oldBounds = @$oldGhost.parent('.up-bounds')
226
+ $newBounds = @$newGhost.parent('.up-bounds')
227
+ expect($oldBounds).toExist()
228
+ expect($newBounds).toExist()
229
+
230
+ # Ghosts should be inserted before (not after) the element
231
+ # or the browser scroll position will be too low after the
232
+ # transition ends.
233
+ expect(@$oldGhost.parent().next()).toEqual($old)
234
+ expect(@$newGhost.parent().next()).toEqual($new)
235
+
236
+ # The old element is removed from the layout flow.
237
+ # It will be removed from the DOM after the animation has ended.
238
+ expect($old.css('display')).toEqual('none')
218
239
 
219
- # We **must not** use `visibility: hidden` to hide the new
220
- # element. This would delay browser painting until the element is
221
- # shown again, causing a flicker while the browser is painting.
222
- expect($new.css('visibility')).not.toEqual('hidden')
240
+ # The new element is invisible due to an opacity of zero,
241
+ # but takes up the space in the layout flow.
242
+ expect($new.css(['display', 'opacity'])).toEqual(
243
+ display: 'block',
244
+ opacity: '0'
245
+ )
223
246
 
224
- # Ghosts will hover over $old and $new using absolute positioning,
225
- # matching the coordinates of the original elements.
226
- expect($oldBounds.css(['position', 'top', 'left', 'width', 'height'])).toEqual(
227
- position: 'absolute'
228
- top: '10px'
229
- left: '11px',
230
- width: '12px',
231
- height: '13px'
232
- )
233
- expect($newBounds.css(['position', 'top', 'left', 'width', 'height'])).toEqual(
234
- position: 'absolute'
235
- top: '20px'
236
- left: '21px',
237
- width: '22px',
238
- height: '23px'
239
- )
247
+ # We **must not** use `visibility: hidden` to hide the new
248
+ # element. This would delay browser painting until the element is
249
+ # shown again, causing a flicker while the browser is painting.
250
+ expect($new.css('visibility')).not.toEqual('hidden')
251
+
252
+ # Ghosts will hover over $old and $new using absolute positioning,
253
+ # matching the coordinates of the original elements.
254
+ expect($oldBounds.css(['position', 'top', 'left', 'width', 'height'])).toEqual(
255
+ position: 'absolute'
256
+ top: '10px'
257
+ left: '11px',
258
+ width: '12px',
259
+ height: '13px'
260
+ )
261
+ expect($newBounds.css(['position', 'top', 'left', 'width', 'height'])).toEqual(
262
+ position: 'absolute'
263
+ top: '20px'
264
+ left: '21px',
265
+ width: '22px',
266
+ height: '23px'
267
+ )
240
268
 
241
- u.setTimer 0, ->
242
- expect(u.opacity($newGhost)).toBeAround(0.0, 0.25)
243
- expect(u.opacity($oldGhost)).toBeAround(1.0, 0.25)
269
+ expect(u.opacity(@$newGhost)).toBeAround(0.0, 0.25)
270
+ expect(u.opacity(@$oldGhost)).toBeAround(1.0, 0.25)
244
271
 
245
- u.setTimer 80, ->
246
- expect(u.opacity($newGhost)).toBeAround(0.4, 0.25)
247
- expect(u.opacity($oldGhost)).toBeAround(0.6, 0.25)
272
+ next.after 80, =>
273
+ expect(u.opacity(@$newGhost)).toBeAround(0.4, 0.25)
274
+ expect(u.opacity(@$oldGhost)).toBeAround(0.6, 0.25)
248
275
 
249
- u.setTimer 140, ->
250
- expect(u.opacity($newGhost)).toBeAround(0.7, 0.25)
251
- expect(u.opacity($oldGhost)).toBeAround(0.3, 0.25)
276
+ next.after 60, =>
277
+ expect(u.opacity(@$newGhost)).toBeAround(0.7, 0.25)
278
+ expect(u.opacity(@$oldGhost)).toBeAround(0.3, 0.25)
252
279
 
253
- u.setTimer 250, ->
280
+ next.after 110, =>
254
281
  # Once our two ghosts have rendered their visual effect,
255
282
  # we remove them from the DOM.
256
- expect($newGhost).not.toBeInDOM()
257
- expect($oldGhost).not.toBeInDOM()
283
+ expect(@$newGhost).not.toBeInDOM()
284
+ expect(@$oldGhost).not.toBeInDOM()
258
285
 
259
286
  # The old element is still in the DOM, but hidden.
260
287
  # Morphing does *not* remove the target element.
@@ -264,26 +291,28 @@ describe 'up.motion', ->
264
291
  visibility: 'visible'
265
292
  )
266
293
 
267
- done()
268
-
269
- it 'cancels an existing transition on the element by instantly jumping to the last frame', ->
294
+ it 'cancels an existing transition on the element by instantly jumping to the last frame', asyncSpec (next) ->
270
295
  $old = affix('.old').text('old content')
271
296
  $new = affix('.new').text('new content')
272
297
 
273
298
  up.morph($old, $new, 'cross-fade', duration: 200)
274
- $ghost1 = $('.old.up-ghost')
275
- expect($ghost1).toHaveLength(1)
276
299
 
277
- up.morph($old, $new, 'cross-fade', duration: 200)
278
- $ghost2 = $('.old.up-ghost')
279
- # Check that we didn't create additional ghosts
280
- expect($ghost2).toHaveLength(1)
281
- # Check that it's a different ghosts
282
- expect($ghost2).not.toEqual($ghost1)
300
+ next =>
301
+ @$ghost1 = $('.old.up-ghost')
302
+ expect(@$ghost1).toHaveLength(1)
303
+
304
+ up.morph($old, $new, 'cross-fade', duration: 200)
305
+
306
+ next =>
307
+ @$ghost2 = $('.old.up-ghost')
308
+ # Check that we didn't create additional ghosts
309
+ expect(@$ghost2).toHaveLength(1)
310
+ # Check that it's a different ghosts
311
+ expect(@$ghost2).not.toEqual(@$ghost1)
283
312
 
284
313
  describe 'with { reveal: true } option', ->
285
314
 
286
- it 'reveals the new element while making the old element within the same viewport appear as if it would keep its scroll position', ->
315
+ it 'reveals the new element while making the old element within the same viewport appear as if it would keep its scroll position', asyncSpec (next) ->
287
316
  $container = affix('.container[up-viewport]').css
288
317
  'width': '200px'
289
318
  'height': '200px'
@@ -294,39 +323,59 @@ describe 'up.motion', ->
294
323
  $old = affix('.old').appendTo($container).css(height: '600px')
295
324
  $container.scrollTop(300)
296
325
 
326
+ expect($container.scrollTop()).toEqual(300)
327
+
297
328
  $new = affix('.new').insertBefore($old).css(height: '600px')
298
329
 
299
330
  up.morph($old, $new, 'cross-fade', duration: 50, reveal: true)
300
331
 
301
- $oldGhost = $('.old.up-ghost')
302
- $newGhost = $('.new.up-ghost')
303
-
304
- # Container is scrolled up due to { reveal: true } option.
305
- # Since $old and $new are sitting in the same viewport with a
306
- # single shares scrollbar This will make the ghost for $old jump.
307
- expect($container.scrollTop()).toEqual(0)
332
+ next =>
333
+ $oldGhost = $('.old.up-ghost')
334
+ $newGhost = $('.new.up-ghost')
308
335
 
309
- # See that the ghost for $new is aligned with the top edge
310
- # of the viewport.
311
- expect($newGhost.offset().top).toEqual(0)
336
+ # Container is scrolled up due to { reveal: true } option.
337
+ # Since $old and $new are sitting in the same viewport with a
338
+ # single shared scrollbar, this will make the ghost for $old jump.
339
+ expect($container.scrollTop()).toEqual(0)
312
340
 
313
- # The ghost for $old is shifted upwards to make it looks like it
314
- # was at the scroll position before we revealed $new.
315
- expect($oldGhost.offset().top).toEqual(-300)
341
+ # See that the ghost for $new is aligned with the top edge
342
+ # of the viewport.
343
+ expect($newGhost.offset().top).toEqual(0)
316
344
 
345
+ # The ghost for $old is shifted upwards to make it looks like it
346
+ # was at the scroll position before we revealed $new.
347
+ expect($oldGhost.offset().top).toEqual(-300)
317
348
 
318
349
  describe 'with animations disabled globally', ->
319
350
 
320
351
  beforeEach ->
321
352
  up.motion.config.enabled = false
322
353
 
323
- it "doesn't animate and hides the old element instead", ->
354
+ it "doesn't animate and hides the old element instead", asyncSpec (next) ->
324
355
  $old = affix('.old').text('old content')
325
356
  $new = affix('.new').text('new content')
326
357
  up.morph($old, $new, 'cross-fade', duration: 1000)
327
- expect($old).toBeHidden()
328
- expect($new).toBeVisible()
329
- expect($new.css('opacity')).toEqual('1')
358
+
359
+ next =>
360
+ expect($old).toBeHidden()
361
+ expect($new).toBeVisible()
362
+ expect($new.css('opacity')).toEqual('1')
363
+
364
+
365
+ [false, null, undefined, 'none', 'none/none', '', [], [undefined, null], ['none', 'none'], ['none', {}]].forEach (noneTransition) ->
366
+
367
+ describe "when called with a `#{noneTransition}` transition", ->
368
+
369
+ it "doesn't animate and hides the old element instead", asyncSpec (next) ->
370
+ $old = affix('.old').text('old content')
371
+ $new = affix('.new').text('new content')
372
+ up.morph($old, $new, noneTransition, duration: 1000)
373
+
374
+ next =>
375
+ expect($old).toBeHidden()
376
+ expect($new).toBeVisible()
377
+ expect($new.css('opacity')).toEqual('1')
378
+
330
379
 
331
380
  describe 'up.transition', ->
332
381
 
@@ -336,10 +385,6 @@ describe 'up.motion', ->
336
385
 
337
386
  it 'should have tests'
338
387
 
339
- describe 'up.motion.none', ->
340
-
341
- it 'should have tests'
342
-
343
388
  describe 'up.motion.prependCopy', ->
344
389
 
345
390
  afterEach ->
@@ -0,0 +1,9 @@
1
+ describe 'window.up namespace', ->
2
+
3
+ describe 'renamedModule()', ->
4
+
5
+ it 'prints a warning and forwards the call to the new module', ->
6
+ warnSpy = spyOn(up.log, 'warn')
7
+ value = up.flow
8
+ expect(warnSpy).toHaveBeenCalled()
9
+ expect(value).toBe(up.dom)