unpoly-rails 0.52.0 → 0.53.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +52 -2
- data/dist/unpoly.js +204 -55
- data/dist/unpoly.min.js +4 -4
- data/lib/assets/javascripts/unpoly/classes/extract_cascade.coffee +20 -2
- data/lib/assets/javascripts/unpoly/classes/extract_plan.coffee +3 -9
- data/lib/assets/javascripts/unpoly/dom.coffee +14 -5
- data/lib/assets/javascripts/unpoly/form.coffee +23 -5
- data/lib/assets/javascripts/unpoly/layout.coffee +8 -2
- data/lib/assets/javascripts/unpoly/link.coffee +19 -5
- data/lib/assets/javascripts/unpoly/protocol.coffee +12 -6
- data/lib/assets/javascripts/unpoly/radio.coffee +63 -0
- data/lib/assets/javascripts/unpoly/util.coffee +15 -4
- data/lib/assets/javascripts/unpoly.coffee +1 -0
- data/lib/unpoly/rails/version.rb +1 -1
- data/package.json +1 -1
- data/spec_app/Gemfile.lock +1 -1
- data/spec_app/app/controllers/hash_test_controller.rb +5 -0
- data/spec_app/app/views/hash_test/vanilla.erb +13 -0
- data/spec_app/app/views/pages/start.erb +1 -0
- data/spec_app/config/routes.rb +1 -0
- data/spec_app/spec/javascripts/up/dom_spec.js.coffee +1 -1
- data/spec_app/spec/javascripts/up/form_spec.js.coffee +111 -1
- data/spec_app/spec/javascripts/up/link_spec.js.coffee +122 -4
- data/spec_app/spec/javascripts/up/radio_spec.js.coffee +75 -0
- data/spec_app/spec/javascripts/up/util_spec.js.coffee +30 -5
- metadata +6 -2
@@ -336,11 +336,129 @@ describe 'up.link', ->
|
|
336
336
|
next =>
|
337
337
|
expect($viewport.scrollTop()).toEqual(65)
|
338
338
|
|
339
|
-
describe "when the browser is already on the link's destination", ->
|
340
339
|
|
341
|
-
|
340
|
+
describe 'revealing', ->
|
342
341
|
|
343
|
-
it
|
342
|
+
it 'reaveals the target fragment', asyncSpec (next) ->
|
343
|
+
$link = affix('a[href="/action"][up-target=".target"]')
|
344
|
+
$target = affix('.target')
|
345
|
+
|
346
|
+
revealStub = up.layout.knife.mock('reveal')
|
347
|
+
|
348
|
+
up.follow($link)
|
349
|
+
|
350
|
+
next =>
|
351
|
+
@respondWith('<div class="target">new text</div>')
|
352
|
+
|
353
|
+
next =>
|
354
|
+
expect(revealStub).toHaveBeenCalled()
|
355
|
+
expect(revealStub.calls.mostRecent().args[0]).toBeMatchedBy('.target')
|
356
|
+
|
357
|
+
it 'reveals the { failTarget } if the server responds with an error', asyncSpec (next) ->
|
358
|
+
$link = affix('a[href="/action"][up-target=".target"][up-fail-target=".fail-target"]')
|
359
|
+
$target = affix('.target')
|
360
|
+
$failTarget = affix('.fail-target')
|
361
|
+
|
362
|
+
revealStub = up.layout.knife.mock('reveal')
|
363
|
+
|
364
|
+
up.follow($link)
|
365
|
+
|
366
|
+
next =>
|
367
|
+
@respondWith
|
368
|
+
status: 500,
|
369
|
+
responseText: """
|
370
|
+
<div class="fail-target">
|
371
|
+
Errors here
|
372
|
+
</div>
|
373
|
+
"""
|
374
|
+
|
375
|
+
next =>
|
376
|
+
expect(revealStub).toHaveBeenCalled()
|
377
|
+
expect(revealStub.calls.mostRecent().args[0]).toBeMatchedBy('.fail-target')
|
378
|
+
|
379
|
+
|
380
|
+
describe 'with { reveal } option', ->
|
381
|
+
|
382
|
+
it 'allows to reveal a different selector', asyncSpec (next) ->
|
383
|
+
$link = affix('a[href="/action"][up-target=".target"]')
|
384
|
+
$target = affix('.target')
|
385
|
+
$other = affix('.other')
|
386
|
+
|
387
|
+
revealStub = up.layout.knife.mock('reveal')
|
388
|
+
|
389
|
+
up.follow($link, reveal: '.other')
|
390
|
+
|
391
|
+
next =>
|
392
|
+
@respondWith """
|
393
|
+
<div class="target">
|
394
|
+
new text
|
395
|
+
</div>
|
396
|
+
<div class="other">
|
397
|
+
new other
|
398
|
+
</div>
|
399
|
+
"""
|
400
|
+
|
401
|
+
next =>
|
402
|
+
expect(revealStub).toHaveBeenCalled()
|
403
|
+
expect(revealStub.calls.mostRecent().args[0]).toBeMatchedBy('.other')
|
404
|
+
|
405
|
+
it 'still reveals the { failTarget } for a failed submission', asyncSpec (next) ->
|
406
|
+
$link = affix('a[href="/action"][up-target=".target"][up-fail-target=".fail-target"]')
|
407
|
+
$target = affix('.target')
|
408
|
+
$failTarget = affix('.fail-target')
|
409
|
+
$other = affix('.other')
|
410
|
+
|
411
|
+
revealStub = up.layout.knife.mock('reveal')
|
412
|
+
|
413
|
+
up.submit($link, reveal: '.other', failTarget: '.fail-target')
|
414
|
+
|
415
|
+
next =>
|
416
|
+
@respondWith
|
417
|
+
status: 500,
|
418
|
+
responseText: """
|
419
|
+
<div class="fail-target">
|
420
|
+
Errors here
|
421
|
+
</div>
|
422
|
+
"""
|
423
|
+
|
424
|
+
next =>
|
425
|
+
expect(revealStub).toHaveBeenCalled()
|
426
|
+
expect(revealStub.calls.mostRecent().args[0]).toBeMatchedBy('.fail-target')
|
427
|
+
|
428
|
+
describe 'with { failReveal } option', ->
|
429
|
+
|
430
|
+
it 'reveals the given selector when the server responds with an error', asyncSpec (next) ->
|
431
|
+
$link = affix('a[href="/action"][up-target=".target"][up-fail-target=".fail-target"]')
|
432
|
+
$target = affix('.target')
|
433
|
+
$failTarget = affix('.fail-target')
|
434
|
+
$other = affix('.other')
|
435
|
+
$failOther = affix('.fail-other')
|
436
|
+
|
437
|
+
revealStub = up.layout.knife.mock('reveal')
|
438
|
+
|
439
|
+
up.follow($link, reveal: '.other', failReveal: '.fail-other')
|
440
|
+
|
441
|
+
next =>
|
442
|
+
@respondWith
|
443
|
+
status: 500,
|
444
|
+
responseText: """
|
445
|
+
<div class="fail-target">
|
446
|
+
Errors here
|
447
|
+
</div>
|
448
|
+
<div class="fail-other">
|
449
|
+
Fail other here
|
450
|
+
</div>
|
451
|
+
"""
|
452
|
+
|
453
|
+
next =>
|
454
|
+
expect(revealStub).toHaveBeenCalled()
|
455
|
+
expect(revealStub.calls.mostRecent().args[0]).toBeMatchedBy('.fail-other')
|
456
|
+
|
457
|
+
describe "when the browser is already on the link's destination", ->
|
458
|
+
|
459
|
+
it "doesn't make a request and reveals the target container"
|
460
|
+
|
461
|
+
it "doesn't make a request and reveals the target of a #hash in the URL"
|
344
462
|
|
345
463
|
describe 'with { confirm } option', ->
|
346
464
|
|
@@ -609,7 +727,7 @@ describe 'up.link', ->
|
|
609
727
|
expect($('.document .target')).toHaveText('new text from modal link')
|
610
728
|
expect($('.up-modal .target')).toHaveText('old modal text')
|
611
729
|
|
612
|
-
it 'ignores [up-layer] if the server responds with
|
730
|
+
it 'ignores [up-layer] if the server responds with an error', asyncSpec (next) ->
|
613
731
|
affix('.document').affix('.target').text('old document text')
|
614
732
|
up.modal.extract('.target', "<div class='target'>old modal text</div>", sticky: true)
|
615
733
|
|
@@ -0,0 +1,75 @@
|
|
1
|
+
describe 'up.radio', ->
|
2
|
+
|
3
|
+
describe 'JavaScript functions', ->
|
4
|
+
|
5
|
+
describe 'unobtrusive behavior', ->
|
6
|
+
|
7
|
+
describe '[up-hungry]', ->
|
8
|
+
|
9
|
+
it "replaces the element when it is found in a response, even when the element wasn't targeted", asyncSpec (next) ->
|
10
|
+
affix('.hungry[up-hungry]').text('old hungry')
|
11
|
+
affix('.target').text('old target')
|
12
|
+
|
13
|
+
up.replace('.target', '/path')
|
14
|
+
|
15
|
+
next =>
|
16
|
+
@respondWith """
|
17
|
+
<div class="target">
|
18
|
+
new target
|
19
|
+
</div>
|
20
|
+
<div class="between">
|
21
|
+
new between
|
22
|
+
</div>
|
23
|
+
<div class="hungry">
|
24
|
+
new hungry
|
25
|
+
</div>
|
26
|
+
"""
|
27
|
+
|
28
|
+
next =>
|
29
|
+
expect('.target').toHaveText('new target')
|
30
|
+
expect('.hungry').toHaveText('new hungry')
|
31
|
+
|
32
|
+
it "does not impede replacements when the element is not part of a response", asyncSpec (next) ->
|
33
|
+
affix('.hungry[up-hungry]').text('old hungry')
|
34
|
+
affix('.target').text('old target')
|
35
|
+
|
36
|
+
promise = up.replace('.target', '/path')
|
37
|
+
|
38
|
+
next =>
|
39
|
+
@respondWith """
|
40
|
+
<div class="target">
|
41
|
+
new target
|
42
|
+
</div>
|
43
|
+
"""
|
44
|
+
|
45
|
+
next =>
|
46
|
+
expect('.target').toHaveText('new target')
|
47
|
+
expect('.hungry').toHaveText('old hungry')
|
48
|
+
|
49
|
+
promiseState(promise).then (result) ->
|
50
|
+
expect(result.state).toEqual('fulfilled')
|
51
|
+
|
52
|
+
it 'does not replace the element when the server responds with an error', asyncSpec (next) ->
|
53
|
+
affix('.hungry[up-hungry]').text('old hungry')
|
54
|
+
affix('.target').text('old target')
|
55
|
+
|
56
|
+
up.replace('.target', '/path', failTarget: '.target')
|
57
|
+
|
58
|
+
next =>
|
59
|
+
@respondWith
|
60
|
+
status: 500
|
61
|
+
responseText: """
|
62
|
+
<div class="target">
|
63
|
+
new target
|
64
|
+
</div>
|
65
|
+
<div class="between">
|
66
|
+
new between
|
67
|
+
</div>
|
68
|
+
<div class="hungry">
|
69
|
+
new hungry
|
70
|
+
</div>
|
71
|
+
"""
|
72
|
+
|
73
|
+
next =>
|
74
|
+
expect('.target').toHaveText('new target')
|
75
|
+
expect('.hungry').toHaveText('old hungry')
|
@@ -278,24 +278,49 @@ describe 'up.util', ->
|
|
278
278
|
|
279
279
|
it "prefers using the element's 'up-id' attribute to using the element's ID", ->
|
280
280
|
$element = affix('div[up-id=up-id-value]#id-value')
|
281
|
-
expect(up.util.selectorForElement($element)).toBe(
|
281
|
+
expect(up.util.selectorForElement($element)).toBe('[up-id="up-id-value"]')
|
282
282
|
|
283
283
|
it "prefers using the element's ID to using the element's name", ->
|
284
284
|
$element = affix('div#id-value[name=name-value]')
|
285
285
|
expect(up.util.selectorForElement($element)).toBe("#id-value")
|
286
286
|
|
287
|
-
it "
|
288
|
-
$element = affix('div
|
289
|
-
expect(up.util.selectorForElement($element)).toBe(
|
287
|
+
it "selects the ID with an attribute selector if the ID contains a slash", ->
|
288
|
+
$element = affix('div').attr(id: 'foo/bar')
|
289
|
+
expect(up.util.selectorForElement($element)).toBe('[id="foo/bar"]')
|
290
290
|
|
291
|
-
it "
|
291
|
+
it "selects the ID with an attribute selector if the ID contains a space", ->
|
292
|
+
$element = affix('div').attr(id: 'foo bar')
|
293
|
+
expect(up.util.selectorForElement($element)).toBe('[id="foo bar"]')
|
294
|
+
|
295
|
+
it "selects the ID with an attribute selector if the ID contains a dot", ->
|
296
|
+
$element = affix('div').attr(id: 'foo.bar')
|
297
|
+
expect(up.util.selectorForElement($element)).toBe('[id="foo.bar"]')
|
298
|
+
|
299
|
+
it "selects the ID with an attribute selector if the ID contains a quote", ->
|
300
|
+
$element = affix('div').attr(id: 'foo"bar')
|
301
|
+
expect(up.util.selectorForElement($element)).toBe('[id="foo\\"bar"]')
|
302
|
+
|
303
|
+
it "prefers using the element's tagName + [name] to using the element's classes", ->
|
304
|
+
$element = affix('input[name=name-value].class1.class2')
|
305
|
+
expect(up.util.selectorForElement($element)).toBe('input[name="name-value"]')
|
306
|
+
|
307
|
+
it "prefers using the element's classes to using the element's ARIA label", ->
|
292
308
|
$element = affix('div.class1.class2')
|
293
309
|
expect(up.util.selectorForElement($element)).toBe(".class1.class2")
|
294
310
|
|
311
|
+
it "prefers using the element's ARIA label to using the element's tag name", ->
|
312
|
+
$element = affix('div[aria-label="ARIA label value"]')
|
313
|
+
expect(up.util.selectorForElement($element)).toBe('[aria-label="ARIA label value"]')
|
314
|
+
|
295
315
|
it "uses the element's tag name if no better description is available", ->
|
296
316
|
$element = affix('div')
|
297
317
|
expect(up.util.selectorForElement($element)).toBe("div")
|
298
318
|
|
319
|
+
it 'escapes quotes in attribute selector values', ->
|
320
|
+
$element = affix('div')
|
321
|
+
$element.attr('aria-label', 'foo"bar')
|
322
|
+
expect(up.util.selectorForElement($element)).toBe('[aria-label="foo\\"bar"]')
|
323
|
+
|
299
324
|
|
300
325
|
describe 'up.util.castedAttr', ->
|
301
326
|
|
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.
|
4
|
+
version: 0.53.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Henning Koch
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-02-
|
11
|
+
date: 2018-02-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -118,6 +118,7 @@ files:
|
|
118
118
|
- lib/assets/javascripts/unpoly/popup.coffee
|
119
119
|
- lib/assets/javascripts/unpoly/protocol.coffee
|
120
120
|
- lib/assets/javascripts/unpoly/proxy.coffee
|
121
|
+
- lib/assets/javascripts/unpoly/radio.coffee
|
121
122
|
- lib/assets/javascripts/unpoly/rails.coffee
|
122
123
|
- lib/assets/javascripts/unpoly/syntax.coffee
|
123
124
|
- lib/assets/javascripts/unpoly/toast.coffee
|
@@ -164,6 +165,7 @@ files:
|
|
164
165
|
- spec_app/app/controllers/form_test/basics_controller.rb
|
165
166
|
- spec_app/app/controllers/form_test/redirects_controller.rb
|
166
167
|
- spec_app/app/controllers/form_test/uploads_controller.rb
|
168
|
+
- spec_app/app/controllers/hash_test_controller.rb
|
167
169
|
- spec_app/app/controllers/method_test_controller.rb
|
168
170
|
- spec_app/app/controllers/pages_controller.rb
|
169
171
|
- spec_app/app/controllers/replace_test_controller.rb
|
@@ -183,6 +185,7 @@ files:
|
|
183
185
|
- spec_app/app/views/form_test/redirects/target.erb
|
184
186
|
- spec_app/app/views/form_test/submission_result.erb
|
185
187
|
- spec_app/app/views/form_test/uploads/new.erb
|
188
|
+
- spec_app/app/views/hash_test/vanilla.erb
|
186
189
|
- spec_app/app/views/layouts/integration_test.erb
|
187
190
|
- spec_app/app/views/layouts/jasmine_rails/spec_runner.html.erb
|
188
191
|
- spec_app/app/views/method_test/form_target.erb
|
@@ -282,6 +285,7 @@ files:
|
|
282
285
|
- spec_app/spec/javascripts/up/popup_spec.js.coffee
|
283
286
|
- spec_app/spec/javascripts/up/protocol_spec.js.coffee
|
284
287
|
- spec_app/spec/javascripts/up/proxy_spec.js.coffee
|
288
|
+
- spec_app/spec/javascripts/up/radio_spec.js.coffee
|
285
289
|
- spec_app/spec/javascripts/up/rails_spec.js.coffee
|
286
290
|
- spec_app/spec/javascripts/up/syntax_spec.js.coffee
|
287
291
|
- spec_app/spec/javascripts/up/tooltip_spec.js.coffee
|