unpoly-rails 0.53.1 → 0.53.2

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.

@@ -4,6 +4,6 @@ module Unpoly
4
4
  # The current version of the unpoly-rails gem.
5
5
  # This version number is also used for releases of the Unpoly
6
6
  # frontend code.
7
- VERSION = '0.53.1'
7
+ VERSION = '0.53.2'
8
8
  end
9
9
  end
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unpoly",
3
- "version": "0.53.1",
3
+ "version": "0.53.2",
4
4
  "description": "Unobtrusive JavaScript framework",
5
5
  "main": "dist/unpoly.js",
6
6
  "files": [
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- unpoly-rails (0.53.0)
4
+ unpoly-rails (0.53.1)
5
5
  rails (>= 3)
6
6
 
7
7
  GEM
@@ -7,7 +7,7 @@ module FormTest
7
7
  end
8
8
 
9
9
  def create
10
- render 'form_test/submission_result'
10
+ render 'form_test/submission_result', status: 500
11
11
  end
12
12
 
13
13
  end
@@ -1,8 +1,13 @@
1
+ <script>
2
+ up.motion.config.duration = 2000
3
+ up.layout.config.duration = 2000
4
+ </script>
5
+
1
6
  <div class="long-page" style="height: 2000px; background-color: rgba(0, 0, 255, 0.3)">
2
7
 
3
8
  <h2>Long page 1</h2>
4
9
 
5
- <ul>
10
+ <ul style="margin-top: 200px">
6
11
  <li><a up-target=".long-page" href="long2" up-reveal="true" up-transition="false" >Go to long page 2 (with reveal, without animation)</a></li>
7
12
  <li><a up-target=".long-page" href="long2" up-reveal="true" up-transition="cross-fade">Go to long page 2 (with reveal, with animation) </a></li>
8
13
  <li><a up-target=".long-page" href="long2" up-reveal="false" up-transition="false" >Go to long page 2 (without reveal, without animation)</a></li>
@@ -1,8 +1,13 @@
1
+ <script>
2
+ up.motion.config.duration = 2000
3
+ up.layout.config.duration = 2000
4
+ </script>
5
+
1
6
  <div class="long-page" style="height: 2000px; background-color: rgba(255, 0, 0, 0.3)">
2
7
 
3
8
  <h2>Long page 2</h2>
4
9
 
5
- <ul>
10
+ <ul style="margin-top: 200px">
6
11
  <li><a up-target=".long-page" href="long1" up-reveal="true" up-transition="false" >Go to long page 1 (with reveal, without animation)</a></li>
7
12
  <li><a up-target=".long-page" href="long1" up-reveal="true" up-transition="cross-fade">Go to long page 1 (with reveal, with animation) </a></li>
8
13
  <li><a up-target=".long-page" href="long1" up-reveal="false" up-transition="false" >Go to long page 1 (without reveal, without animation)</a></li>
@@ -0,0 +1,36 @@
1
+ UNHANDLED_REJECTIONS = []
2
+
3
+ beforeAll ->
4
+ window.addEventListener 'unhandledrejection', (event) ->
5
+ UNHANDLED_REJECTIONS.push(event)
6
+
7
+ beforeEach ->
8
+ UNHANDLED_REJECTIONS = []
9
+
10
+ jasmine.addMatchers
11
+ toHaveUnhandledRejections: (util, customEqualityTesters) ->
12
+ compare: (actual) ->
13
+ # It doesn't really matter what's in actual.
14
+ # A good way to call this is e.g. `expect(window).not.toHaveUnhandledRejections()
15
+ pass: UNHANDLED_REJECTIONS.length > 0
16
+
17
+ #UnhandledRejectionTracker = do ->
18
+ #
19
+ #
20
+ #
21
+ #
22
+ #
23
+ ##beforeEach (done) ->
24
+ ## @unhandledRejections = []
25
+ ## @trackUnhandledRejections = (event) =>
26
+ ## @unhandledRejections.push(event)
27
+ ## window.addEventListener('unhandledrejection', @trackUnhandledRejections)
28
+ ## done()
29
+ ##
30
+ ##afterEach (done) ->
31
+ ## hadUnhandledRejections = @unhandledRejections.length > 0
32
+ ## @unhandledRejections = []
33
+ ## if hadUnhandledRejections
34
+ ## done.fail('There were rejected promises without a rejection handler')
35
+ ## else
36
+ ## done()
@@ -7,11 +7,26 @@
7
7
  event = createMouseEvent('mouseover', options)
8
8
  dispatch($element, event)
9
9
 
10
+ mouseenter = (element, options) ->
11
+ $element = $(element)
12
+ event = createMouseEvent('mouseenter', options)
13
+ dispatch($element, event)
14
+
10
15
  mousedown = (element, options) ->
11
16
  $element = $(element)
12
17
  event = createMouseEvent('mousedown', options)
13
18
  dispatch($element, event)
14
19
 
20
+ mouseout = (element, options) ->
21
+ $element = $(element)
22
+ event = createMouseEvent('mouseout', options)
23
+ dispatch($element, event)
24
+
25
+ mouseleave = (element, options) ->
26
+ $element = $(element)
27
+ event = createMouseEvent('mouseleave', options)
28
+ dispatch($element, event)
29
+
15
30
  mouseup = (element, options) ->
16
31
  $element = $(element)
17
32
  event = createMouseEvent('mouseup', options)
@@ -34,6 +49,16 @@
34
49
  mouseup($element, options)
35
50
  click($element, options)
36
51
 
52
+ hoverSequence = (element, options) ->
53
+ $element = $(element)
54
+ mouseover($element, options)
55
+ mouseenter($element, options)
56
+
57
+ unhoverSequence = (element, options) ->
58
+ $element = $(element)
59
+ mouseout($element, options)
60
+ mouseleave($element, options)
61
+
37
62
  # Can't use the new MouseEvent constructor in IE11 because computer.
38
63
  # http://www.codeproject.com/Tips/893254/JavaScript-Triggering-Event-Manually-in-Internet-E
39
64
  createMouseEvent = (type, options) ->
@@ -77,10 +102,15 @@
77
102
  this.dispatchEvent(event)
78
103
 
79
104
  mouseover: mouseover
105
+ mouseenter: mouseenter
80
106
  mousedown: mousedown
81
107
  mouseup: mouseup
108
+ mouseout: mouseout
109
+ mouseleave: mouseleave
82
110
  click: click
83
111
  clickSequence: clickSequence
112
+ hoverSequence: hoverSequence
113
+ unhoverSequence: unhoverSequence
84
114
  createMouseEvent: createMouseEvent
85
115
 
86
116
  )()
@@ -940,7 +940,7 @@ describe 'up.dom', ->
940
940
 
941
941
  next =>
942
942
  expect(@revealedHTML).toEqual ['<div id="three">three</div>']
943
- expect(@revealOptions).toEqual { top: true }
943
+ expect(@revealOptions).toEqual jasmine.objectContaining(top: true)
944
944
 
945
945
  it "reveals the entire element if it has no child with the ID of that #hash", asyncSpec (next) ->
946
946
  up.replace('.middle', '/path#four', reveal: true)
@@ -355,6 +355,8 @@ describe 'up.form', ->
355
355
  expect('.before').not.toHaveText('old-before')
356
356
  expect('.after').not.toHaveText('old-after')
357
357
 
358
+ expect(window).toHaveUnhandledRejections()
359
+
358
360
  it 'respects X-Up-Method and X-Up-Location response headers so the server can show that it redirected to a GET URL', asyncSpec (next) ->
359
361
  up.submit(@$form)
360
362
 
@@ -529,7 +531,70 @@ describe 'up.form', ->
529
531
 
530
532
  describe 'form[up-target]', ->
531
533
 
532
- it 'rigs the form to use up.submit instead of a standard submit'
534
+ it 'submits the form with AJAX and replaces the [up-target] selector', asyncSpec (next) ->
535
+ up.history.config.enabled = true
536
+
537
+ affix('.response').text('old text')
538
+
539
+ $form = affix('form[action="/form-target"][method="put"][up-target=".response"]')
540
+ $form.append('<input name="field1" value="value1">')
541
+ $form.append('<input name="field2" value="value2">')
542
+ $submitButton = $form.affix('input[type="submit"][name="submit-button"][value="submit-button-value"]')
543
+ up.hello($form)
544
+
545
+ Trigger.clickSequence($submitButton)
546
+
547
+ next =>
548
+ params = @lastRequest().data()
549
+ expect(params['field1']).toEqual(['value1'])
550
+ expect(params['field2']).toEqual(['value2'])
551
+
552
+ next =>
553
+ @respondWith """
554
+ <div class="response">
555
+ new text
556
+ </div>
557
+ """
558
+
559
+ next =>
560
+ expect('.response').toHaveText('new text')
561
+
562
+ describe 'when the server responds with an error code', ->
563
+
564
+ it 'replaces the form instead of the [up-target] selector', asyncSpec (next) ->
565
+ up.history.config.enabled = true
566
+
567
+ affix('.response').text('old text')
568
+
569
+ $form = affix('form.test-form[action="/form-target"][method="put"][up-target=".response"]')
570
+ $form.append('<input name="field1" value="value1">')
571
+ $form.append('<input name="field2" value="value2">')
572
+ $submitButton = $form.affix('input[type="submit"][name="submit-button"][value="submit-button-value"]')
573
+ up.hello($form)
574
+
575
+ Trigger.clickSequence($submitButton)
576
+
577
+ next =>
578
+ params = @lastRequest().data()
579
+ expect(params['field1']).toEqual(['value1'])
580
+ expect(params['field2']).toEqual(['value2'])
581
+
582
+ next =>
583
+ @respondWith
584
+ status: 500
585
+ responseText: """
586
+ <form class="test-form">
587
+ validation errors
588
+ </form>
589
+ """
590
+
591
+ next =>
592
+ expect('.response').toHaveText('old text')
593
+ expect('form.test-form').toHaveText('validation errors')
594
+
595
+ # Since there isn't anyone who could handle the rejection inside
596
+ # the event handler, our handler mutes the rejection.
597
+ expect(window).not.toHaveUnhandledRejections()
533
598
 
534
599
  describe 'submit buttons', ->
535
600
 
@@ -711,12 +776,14 @@ describe 'up.form', ->
711
776
  expect(request.requestHeaders['X-Up-Validate']).toEqual('user')
712
777
  expect(request.requestHeaders['X-Up-Target']).toEqual('.field-group:has(input[name="user"])')
713
778
 
714
- @respondWith """
715
- <div class="field-group has-error">
716
- <div class='error'>Username has already been taken</div>
717
- <input name="user" value="judy" up-validate=".field-group:has(&)">
718
- </div>
719
- """
779
+ @respondWith
780
+ status: 500
781
+ responseText: """
782
+ <div class="field-group has-error">
783
+ <div class='error'>Username has already been taken</div>
784
+ <input name="user" value="judy" up-validate=".field-group:has(&)">
785
+ </div>
786
+ """
720
787
 
721
788
  next =>
722
789
  $group = $('.field-group')
@@ -724,6 +791,10 @@ describe 'up.form', ->
724
791
  expect($group).toHaveClass('has-error')
725
792
  expect($group).toHaveText('Username has already been taken')
726
793
 
794
+ # Since there isn't anyone who could handle the rejection inside
795
+ # the event handler, our handler mutes the rejection.
796
+ expect(window).not.toHaveUnhandledRejections()
797
+
727
798
  it 'does not reveal the updated fragment (bugfix)', asyncSpec (next) ->
728
799
  revealSpy = up.layout.knife.mock('reveal').and.returnValue(Promise.resolve())
729
800
 
@@ -654,6 +654,18 @@ describe 'up.link', ->
654
654
 
655
655
  describeCapability 'canPushState', ->
656
656
 
657
+ it 'requests the [href] with AJAX and replaces the [up-target] selector', asyncSpec (next) ->
658
+ affix('.target')
659
+ $link = affix('a[href="/path"][up-target=".target"]')
660
+ Trigger.clickSequence($link)
661
+
662
+ next =>
663
+ @respondWith('<div class="target">new text</div>')
664
+
665
+ next =>
666
+ expect($('.target')).toHaveText('new text')
667
+
668
+
657
669
  it 'adds a history entry', asyncSpec (next) ->
658
670
  up.history.config.enabled = true
659
671
 
@@ -784,6 +796,11 @@ describe 'up.link', ->
784
796
  expect($('.success-target')).toHaveText('old success text')
785
797
  expect($('.failure-target')).toHaveText('new failure text')
786
798
 
799
+ # Since there isn't anyone who could handle the rejection inside
800
+ # the event handler, our handler mutes the rejection.
801
+ expect(window).not.toHaveUnhandledRejections()
802
+
803
+
787
804
  it 'uses the [up-target] selector for a successful response', asyncSpec (next) ->
788
805
  Trigger.clickSequence(@$link)
789
806
 
@@ -973,25 +973,119 @@ describe 'up.proxy', ->
973
973
 
974
974
  describe '[up-preload]', ->
975
975
 
976
- it 'preloads the link destination on mouseover, after a delay'
976
+ it 'preloads the link destination when hovering, after a delay', asyncSpec (next) ->
977
+ up.proxy.config.preloadDelay = 100
978
+
979
+ affix('.target').text('old text')
980
+
981
+ $link = affix('a[href="/foo"][up-target=".target"][up-preload]')
982
+ up.hello($link)
983
+
984
+ Trigger.hoverSequence($link)
985
+
986
+ next.after 50, =>
987
+ # It's still too early
988
+ expect(jasmine.Ajax.requests.count()).toEqual(0)
989
+
990
+ next.after 75, =>
991
+ expect(jasmine.Ajax.requests.count()).toEqual(1)
992
+ expect(@lastRequest().url).toMatchUrl('/foo')
993
+ expect(@lastRequest()).toHaveRequestMethod('GET')
994
+ expect(@lastRequest().requestHeaders['X-Up-Target']).toEqual('.target')
995
+
996
+ @respondWith """
997
+ <div class="target">
998
+ new text
999
+ </div>
1000
+ """
1001
+
1002
+ next =>
1003
+ # We only preloaded, so the target isn't replaced yet.
1004
+ expect('.target').toHaveText('old text')
1005
+
1006
+ Trigger.clickSequence($link)
1007
+
1008
+ next =>
1009
+ # No additional request has been sent since we already preloaded
1010
+ expect(jasmine.Ajax.requests.count()).toEqual(1)
1011
+
1012
+ # The target is replaced instantly
1013
+ expect('.target').toHaveText('new text')
1014
+
1015
+ it 'does not send a request if the user stops hovering before the delay is over', asyncSpec (next) ->
1016
+ up.proxy.config.preloadDelay = 100
1017
+
1018
+ affix('.target').text('old text')
1019
+
1020
+ $link = affix('a[href="/foo"][up-target=".target"][up-preload]')
1021
+ up.hello($link)
1022
+
1023
+ Trigger.hoverSequence($link)
1024
+
1025
+ next.after 40, =>
1026
+ # It's still too early
1027
+ expect(jasmine.Ajax.requests.count()).toEqual(0)
1028
+
1029
+ Trigger.unhoverSequence($link)
1030
+
1031
+ next.after 90, =>
1032
+ expect(jasmine.Ajax.requests.count()).toEqual(0)
1033
+
1034
+ it 'does not cache a failed response', asyncSpec (next) ->
1035
+ up.proxy.config.preloadDelay = 0
1036
+
1037
+ affix('.target').text('old text')
1038
+
1039
+ $link = affix('a[href="/foo"][up-target=".target"][up-preload]')
1040
+ up.hello($link)
1041
+
1042
+ Trigger.hoverSequence($link)
1043
+
1044
+ next.after 2, =>
1045
+ expect(jasmine.Ajax.requests.count()).toEqual(1)
1046
+
1047
+ @respondWith
1048
+ status: 500
1049
+ responseText: """
1050
+ <div class="target">
1051
+ new text
1052
+ </div>
1053
+ """
1054
+
1055
+ next =>
1056
+ # We only preloaded, so the target isn't replaced yet.
1057
+ expect('.target').toHaveText('old text')
1058
+
1059
+ Trigger.click($link)
1060
+
1061
+ next =>
1062
+ # Since the preloading failed, we send another request
1063
+ expect(jasmine.Ajax.requests.count()).toEqual(2)
1064
+
1065
+ # Since there isn't anyone who could handle the rejection inside
1066
+ # the event handler, our handler mutes the rejection.
1067
+ expect(window).not.toHaveUnhandledRejections()
977
1068
 
978
1069
  it 'triggers a separate AJAX request when hovered multiple times and the cache expires between hovers', asyncSpec (next) ->
979
1070
  up.proxy.config.cacheExpiry = 50
980
1071
  up.proxy.config.preloadDelay = 0
1072
+
981
1073
  $element = affix('a[href="/foo"][up-preload]')
982
- Trigger.mouseover($element)
1074
+ up.hello($element)
1075
+
1076
+ Trigger.hoverSequence($element)
983
1077
 
984
1078
  next.after 1, =>
985
1079
  expect(jasmine.Ajax.requests.count()).toEqual(1)
986
1080
 
987
1081
  next.after 1, =>
988
- Trigger.mouseover($element)
1082
+ Trigger.hoverSequence($element)
989
1083
 
990
1084
  next.after 1, =>
991
1085
  expect(jasmine.Ajax.requests.count()).toEqual(1)
992
1086
 
993
1087
  next.after 60, =>
994
- Trigger.mouseover($element)
1088
+ Trigger.hoverSequence($element)
995
1089
 
996
1090
  next.after 1, =>
997
1091
  expect(jasmine.Ajax.requests.count()).toEqual(2)
@@ -1,5 +1,7 @@
1
1
  describe 'up.radio', ->
2
2
 
3
+ u = up.util
4
+
3
5
  describe 'JavaScript functions', ->
4
6
 
5
7
  describe 'unobtrusive behavior', ->