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
@@ -49,6 +49,21 @@ describe 'up.feedback', ->
49
49
  $link = up.hello(affix('a[href="#"]'))
50
50
  expect($link).not.toHaveClass('up-current')
51
51
 
52
+ it 'does not highlight links with unsafe methods', ->
53
+ spyOn(up.browser, 'url').and.returnValue('/foo')
54
+ $defaultLink = up.hello(affix('a[href="/foo"]'))
55
+ $getLink = up.hello(affix('a[href="/foo"][up-method="get"]'))
56
+ $putLink = up.hello(affix('a[href="/foo"][up-method="put"]'))
57
+ $patchLink = up.hello(affix('a[href="/foo"][up-method="patch"]'))
58
+ $postLink = up.hello(affix('a[href="/foo"][up-method="post"]'))
59
+ $deleteLink = up.hello(affix('a[href="/foo"][up-method="delete"]'))
60
+ expect($defaultLink).toHaveClass('up-current')
61
+ expect($getLink).toHaveClass('up-current')
62
+ expect($putLink).not.toHaveClass('up-current')
63
+ expect($patchLink).not.toHaveClass('up-current')
64
+ expect($postLink).not.toHaveClass('up-current')
65
+ expect($deleteLink).not.toHaveClass('up-current')
66
+
52
67
  it 'marks URL prefixes as .up-current if an up-alias value ends in *', ->
53
68
  spyOn(up.browser, 'url').and.returnValue('/foo/123')
54
69
  $currentLink = up.hello(affix('a[href="/x"][up-alias="/aaa /foo/* /bbb"]'))
@@ -64,117 +79,175 @@ describe 'up.feedback', ->
64
79
 
65
80
  describeCapability 'canPushState', ->
66
81
 
67
- it 'marks a link as .up-current if it links to the current URL, but is missing a trailing slash', ->
68
- $link = affix('a[href="/foo"][up-target=".main"]')
69
- affix('.main')
70
- Trigger.clickSequence($link)
71
- @respondWith
72
- responseHeaders: { 'X-Up-Location': '/foo/' }
73
- responseText: '<div class="main">new-text</div>'
74
- expect($link).toHaveClass('up-current')
82
+ describe 'updating .up-current marks wen the URL changes', ->
75
83
 
76
- it 'marks a link as .up-current if it links to the current URL, but has an extra trailing slash', ->
77
- $link = affix('a[href="/foo/"][up-target=".main"]')
78
- affix('.main')
79
- Trigger.clickSequence($link)
80
- @respondWith
81
- responseHeaders: { 'X-Up-Location': '/foo' }
82
- responseText: '<div class="main">new-text</div>'
83
- expect($link).toHaveClass('up-current')
84
-
85
- it 'marks a link as .up-current if it links to an URL currently shown either within or below the modal', (done) ->
86
- up.history.replace('/foo')
87
- $backgroundLink = affix('a[href="/foo"]')
88
- $modalLink = affix('a[href="/bar"][up-modal=".main"]')
89
- $unrelatedLink = affix('a[href="/baz]')
90
-
91
- Trigger.click($modalLink)
92
- @respondWith('<div class="main">new-text</div>')
93
- expect($backgroundLink).toHaveClass('up-current')
94
- expect($modalLink).toHaveClass('up-current')
95
- expect($unrelatedLink).not.toHaveClass('up-current')
96
-
97
- up.modal.close().then ->
98
- expect($backgroundLink).toHaveClass('up-current')
99
- expect($modalLink).not.toHaveClass('up-current')
100
- expect($unrelatedLink).not.toHaveClass('up-current')
101
- done()
102
-
103
- it 'marks a link as .up-current if it links to the URL currently either within or below the popup', (done) ->
104
- up.history.replace('/foo')
105
- $backgroundLink = affix('a[href="/foo"]')
106
- $popupLink = affix('a[href="/bar"][up-popup=".main"]')
107
- $unrelatedLink = affix('a[href="/baz]')
108
-
109
- Trigger.clickSequence($popupLink)
110
- @respondWith('<div class="main">new-text</div>')
111
- expect($backgroundLink).toHaveClass('up-current')
112
- expect($popupLink).toHaveClass('up-current')
113
- expect($unrelatedLink).not.toHaveClass('up-current')
114
-
115
- up.popup.close().then ->
116
- expect($backgroundLink).toHaveClass('up-current')
117
- expect($popupLink).not.toHaveClass('up-current')
118
- expect($unrelatedLink).not.toHaveClass('up-current')
119
- done()
120
-
121
- it 'changes .up-current marks as the URL changes'
84
+ beforeEach ->
85
+ up.history.config.enabled = true
86
+
87
+ it 'marks a link as .up-current if it links to the current URL, but is missing a trailing slash', asyncSpec (next) ->
88
+ $link = affix('a[href="/foo"][up-target=".main"]')
89
+ affix('.main')
90
+ Trigger.clickSequence($link)
91
+
92
+ next =>
93
+ @respondWith
94
+ responseHeaders: { 'X-Up-Location': '/foo/' }
95
+ responseText: '<div class="main">new-text</div>'
96
+
97
+ next =>
98
+ expect($link).toHaveClass('up-current')
99
+
100
+ it 'marks a link as .up-current if it links to the current URL, but has an extra trailing slash', asyncSpec (next) ->
101
+ $link = affix('a[href="/foo/"][up-target=".main"]')
102
+ affix('.main')
103
+ Trigger.clickSequence($link)
104
+
105
+ next =>
106
+ @respondWith
107
+ responseHeaders: { 'X-Up-Location': '/foo' }
108
+ responseText: '<div class="main">new-text</div>'
109
+
110
+ next =>
111
+ expect($link).toHaveClass('up-current')
112
+
113
+ it 'marks a link as .up-current if it links to an URL currently shown either within or below the modal', asyncSpec (next) ->
114
+ up.history.replace('/foo')
115
+
116
+ $backgroundLink = affix('a[href="/foo"]')
117
+ $modalLink = affix('a[href="/bar"][up-modal=".main"]')
118
+ $unrelatedLink = affix('a[href="/baz]')
119
+
120
+ Trigger.clickSequence($modalLink)
121
+
122
+ next =>
123
+ @respondWith('<div class="main">new-text</div>')
124
+
125
+ next =>
126
+ expect($backgroundLink).toHaveClass('up-current')
127
+ expect($modalLink).toHaveClass('up-current')
128
+ expect($unrelatedLink).not.toHaveClass('up-current')
129
+ next.await up.modal.close()
130
+
131
+ next =>
132
+ expect($backgroundLink).toHaveClass('up-current')
133
+ expect($modalLink).not.toHaveClass('up-current')
134
+ expect($unrelatedLink).not.toHaveClass('up-current')
135
+
136
+ it 'marks a link as .up-current if it links to the URL currently either within or below the popup', asyncSpec (next) ->
137
+ up.history.replace('/foo')
138
+
139
+ $backgroundLink = affix('a[href="/foo"]')
140
+ $popupLink = affix('a[href="/bar"][up-popup=".main"]')
141
+ $unrelatedLink = affix('a[href="/baz]')
142
+
143
+ next =>
144
+ Trigger.clickSequence($popupLink)
145
+
146
+ next =>
147
+ @respondWith('<div class="main">new-text</div>')
148
+
149
+ next =>
150
+ expect($backgroundLink).toHaveClass('up-current')
151
+ expect($popupLink).toHaveClass('up-current')
152
+ expect($unrelatedLink).not.toHaveClass('up-current')
153
+
154
+ next.await up.popup.close()
155
+
156
+ next =>
157
+ expect($backgroundLink).toHaveClass('up-current')
158
+ expect($popupLink).not.toHaveClass('up-current')
159
+ expect($unrelatedLink).not.toHaveClass('up-current')
122
160
 
123
161
  describe '.up-active', ->
124
162
 
125
163
  describeCapability 'canPushState', ->
126
164
 
127
- it 'marks clicked links as .up-active until the request finishes', ->
165
+ it 'marks clicked links as .up-active until the request finishes', asyncSpec (next) ->
128
166
  $link = affix('a[href="/foo"][up-target=".main"]')
129
167
  affix('.main')
130
168
  Trigger.clickSequence($link)
131
- expect($link).toHaveClass('up-active')
132
- @respondWith('<div class="main">new-text</div>')
133
- expect($link).not.toHaveClass('up-active')
134
169
 
135
- it 'marks links with [up-instant] on mousedown as .up-active until the request finishes', ->
170
+ next =>
171
+ expect($link).toHaveClass('up-active')
172
+ @respondWith('<div class="main">new-text</div>')
173
+
174
+ next =>
175
+ expect($link).not.toHaveClass('up-active')
176
+
177
+ it 'does not mark a link as .up-active while it is preloading', asyncSpec (next) ->
178
+ $link = affix('a[href="/foo"][up-target=".main"]')
179
+ affix('.main')
180
+
181
+ up.proxy.preload($link)
182
+
183
+ next =>
184
+ expect(jasmine.Ajax.requests.count()).toEqual(1)
185
+ expect($link).not.toHaveClass('up-active')
186
+
187
+ it 'marks links with [up-instant] on mousedown as .up-active until the request finishes', asyncSpec (next) ->
136
188
  $link = affix('a[href="/foo"][up-instant][up-target=".main"]')
137
189
  affix('.main')
138
190
  Trigger.mousedown($link)
139
- expect($link).toHaveClass('up-active')
140
- @respondWith('<div class="main">new-text</div>')
141
- expect($link).not.toHaveClass('up-active')
142
191
 
143
- it 'prefers to mark an enclosing [up-expand] click area', ->
192
+ next => expect($link).toHaveClass('up-active')
193
+ next => @respondWith('<div class="main">new-text</div>')
194
+ next => expect($link).not.toHaveClass('up-active')
195
+
196
+ it 'prefers to mark an enclosing [up-expand] click area', asyncSpec (next) ->
144
197
  $area = affix('div[up-expand] a[href="/foo"][up-target=".main"]')
145
198
  up.hello($area)
146
199
  $link = $area.find('a')
147
200
  affix('.main')
148
201
  Trigger.clickSequence($link)
149
- expect($link).not.toHaveClass('up-active')
150
- expect($area).toHaveClass('up-active')
151
- @respondWith('<div class="main">new-text</div>')
152
- expect($area).not.toHaveClass('up-active')
153
202
 
154
- it 'marks clicked modal openers as .up-active while the modal is loading', (done) ->
203
+ next =>
204
+ expect($link).not.toHaveClass('up-active')
205
+ expect($area).toHaveClass('up-active')
206
+ next =>
207
+ @respondWith('<div class="main">new-text</div>')
208
+ next =>
209
+ expect($area).not.toHaveClass('up-active')
210
+
211
+ it 'marks clicked modal openers as .up-active while the modal is loading', asyncSpec (next) ->
155
212
  $link = affix('a[href="/foo"][up-modal=".main"]')
156
213
  affix('.main')
157
214
  Trigger.clickSequence($link)
158
- expect($link).toHaveClass('up-active')
159
- u.nextFrame =>
160
- @respondWith('<div class="main">new-text</div>')
161
- expect($link).not.toHaveClass('up-active')
162
- done()
163
215
 
164
- it 'removes .up-active from a clicked modal opener if the target is already preloaded (bugfix)', ->
216
+ next => expect($link).toHaveClass('up-active')
217
+ next => @respondWith('<div class="main">new-text</div>')
218
+ next => expect($link).not.toHaveClass('up-active')
219
+
220
+ it 'removes .up-active from a clicked modal opener if the target is already preloaded (bugfix)', asyncSpec (next) ->
165
221
  $link = affix('a[href="/foo"][up-modal=".main"]')
166
222
  up.proxy.preload($link)
167
- @respondWith('<div class="main">new-text</div>')
168
- Trigger.clickSequence($link)
169
- expect('.up-modal .main').toHaveText('new-text')
170
- expect($link).not.toHaveClass('up-active')
171
223
 
172
- it 'removes .up-active from a clicked link if the target is already preloaded (bugfix)', ->
224
+ next => @respondWith('<div class="main">new-text</div>')
225
+ next => Trigger.clickSequence($link)
226
+ next =>
227
+ expect('.up-modal .main').toHaveText('new-text')
228
+ expect($link).not.toHaveClass('up-active')
229
+
230
+ it 'removes .up-active from a clicked link if the target is already preloaded (bugfix)', asyncSpec (next) ->
173
231
  $link = affix('a[href="/foo"][up-target=".main"]')
174
232
  affix('.main')
175
233
  up.proxy.preload($link)
176
- @respondWith('<div class="main">new-text</div>')
234
+
235
+ next => @respondWith('<div class="main">new-text</div>')
236
+ next => Trigger.clickSequence($link)
237
+ next =>
238
+ expect('.main').toHaveText('new-text')
239
+ expect($link).not.toHaveClass('up-active')
240
+
241
+ it 'removes .up-active from a clicked link if the request fails (bugfix)', asyncSpec (next) ->
242
+ $link = affix('a[href="/foo"][up-target=".main"]')
243
+ affix('.main')
177
244
  Trigger.clickSequence($link)
178
- expect('.main').toHaveText('new-text')
179
- expect($link).not.toHaveClass('up-active')
180
245
 
246
+ next =>
247
+ expect($link).toHaveClass('up-active')
248
+ @respondWith
249
+ responseText: '<div class="main">failed</div>'
250
+ status: 400
251
+
252
+ next =>
253
+ expect($link).not.toHaveClass('up-active')