unpoly-rails 0.23.0 → 0.24.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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +68 -0
  3. data/dist/unpoly-bootstrap3.js +1 -1
  4. data/dist/unpoly-bootstrap3.min.js +1 -1
  5. data/dist/unpoly.css +18 -8
  6. data/dist/unpoly.js +498 -265
  7. data/dist/unpoly.min.css +1 -1
  8. data/dist/unpoly.min.js +3 -3
  9. data/lib/assets/javascripts/unpoly-bootstrap3/modal-ext.js.coffee +5 -2
  10. data/lib/assets/javascripts/unpoly/flow.js.coffee +3 -1
  11. data/lib/assets/javascripts/unpoly/form.js.coffee +3 -6
  12. data/lib/assets/javascripts/unpoly/layout.js.coffee +1 -1
  13. data/lib/assets/javascripts/unpoly/link.js.coffee +4 -2
  14. data/lib/assets/javascripts/unpoly/log.js.coffee +2 -2
  15. data/lib/assets/javascripts/unpoly/modal.js.coffee +125 -36
  16. data/lib/assets/javascripts/unpoly/motion.js.coffee +75 -37
  17. data/lib/assets/javascripts/unpoly/navigation.js.coffee +38 -26
  18. data/lib/assets/javascripts/unpoly/proxy.js.coffee +77 -52
  19. data/lib/assets/javascripts/unpoly/syntax.js.coffee +1 -0
  20. data/lib/assets/javascripts/unpoly/tooltip.js.coffee +2 -0
  21. data/lib/assets/javascripts/unpoly/util.js.coffee +138 -46
  22. data/lib/assets/stylesheets/unpoly/link.css.sass +1 -1
  23. data/lib/assets/stylesheets/unpoly/modal.css.sass +28 -15
  24. data/lib/unpoly/rails/version.rb +1 -1
  25. data/spec_app/Gemfile.lock +7 -7
  26. data/spec_app/spec/javascripts/helpers/reset_up.js.coffee +2 -0
  27. data/spec_app/spec/javascripts/helpers/to_contain.js.coffee +5 -0
  28. data/spec_app/spec/javascripts/up/flow_spec.js.coffee +2 -2
  29. data/spec_app/spec/javascripts/up/history_spec.js.coffee +6 -4
  30. data/spec_app/spec/javascripts/up/link_spec.js.coffee +114 -5
  31. data/spec_app/spec/javascripts/up/modal_spec.js.coffee +28 -18
  32. data/spec_app/spec/javascripts/up/motion_spec.js.coffee +112 -7
  33. data/spec_app/spec/javascripts/up/navigation_spec.js.coffee +157 -121
  34. data/spec_app/spec/javascripts/up/popup_spec.js.coffee +1 -1
  35. data/spec_app/spec/javascripts/up/proxy_spec.js.coffee +42 -3
  36. data/spec_app/spec/javascripts/up/syntax_spec.js.coffee +1 -2
  37. data/spec_app/spec/javascripts/up/util_spec.js.coffee +26 -1
  38. data/spec_app/vendor/assets/bower_components/jquery/.bower.json +1 -1
  39. metadata +3 -3
  40. data/spec_app/spec/javascripts/helpers/set_timer.js.coffee +0 -3
@@ -1,4 +1,6 @@
1
1
  describe 'up.motion', ->
2
+
3
+ u = up.util
2
4
 
3
5
  describe 'Javascript functions', ->
4
6
 
@@ -11,11 +13,11 @@ describe 'up.motion', ->
11
13
  opacity = -> Number($element.css('opacity'))
12
14
  up.animate($element, 'fade-in', duration: 200, easing: 'linear')
13
15
 
14
- @setTimer 0, ->
16
+ u.setTimer 0, ->
15
17
  expect(opacity()).toBeAround(0.0, 0.25)
16
- @setTimer 100, ->
18
+ u.setTimer 100, ->
17
19
  expect(opacity()).toBeAround(0.5, 0.25)
18
- @setTimer 200, ->
20
+ u.setTimer 200, ->
19
21
  expect(opacity()).toBeAround(1.0, 0.25)
20
22
  done()
21
23
 
@@ -42,6 +44,109 @@ describe 'up.motion', ->
42
44
  up.animate($element, { 'font-size': '40px' }, duration: 10000, easing: 'linear')
43
45
  expect($element.css('font-size')).toEqual('40px')
44
46
 
47
+ describe 'up.motion.finish', ->
48
+
49
+ describe 'when called with an element or selector', ->
50
+
51
+ it 'cancels an existing animation on the given element by instantly jumping to the last frame', ->
52
+ $element = affix('.element').text('content')
53
+ up.animate($element, { 'font-size': '40px', 'opacity': '0.33' }, duration: 10000)
54
+ up.motion.finish($element)
55
+ expect($element.css('font-size')).toEqual('40px')
56
+ expect($element.css('opacity')).toEqual('0.33')
57
+
58
+ it 'cancels animations on children of the given element', ->
59
+ $parent = affix('.element')
60
+ $child = $parent.affix('.child')
61
+ up.animate($child, { 'font-size': '40px' }, duration: 10000)
62
+ up.motion.finish($parent)
63
+ expect($child.css('font-size')).toEqual('40px')
64
+
65
+ it 'does not cancel animations on other elements', ->
66
+ $element1 = affix('.element1').text('content1')
67
+ $element2 = affix('.element2').text('content2')
68
+ up.animate($element1, 'fade-in', duration: 10000)
69
+ up.animate($element2, 'fade-in', duration: 10000)
70
+ up.motion.finish($element1)
71
+ expect(Number($element1.css('opacity'))).toEqual(1)
72
+ expect(Number($element2.css('opacity'))).toEqual(0, 0.1)
73
+
74
+ it 'restores existing transitions on the element', ->
75
+ $element = affix('.element').text('content')
76
+ $element.css('transition': 'font-size 3s ease')
77
+ oldTransition = $element.css('transition')
78
+ expect(oldTransition).toContain('font-size') # be paranoid
79
+ up.animate($element, 'fade-in', duration: 10000)
80
+ up.motion.finish($element)
81
+ expect(Number($element.css('opacity'))).toEqual(1)
82
+ currentTransition = $element.css('transition')
83
+ expect(currentTransition).toEqual(oldTransition)
84
+ expect(currentTransition).toContain('font-size')
85
+ expect(currentTransition).not.toContain('opacity')
86
+ expect(currentTransition).not.toContain('none')
87
+ expect(currentTransition).not.toContain('all')
88
+
89
+ it 'cancels an existing transition on the element by instantly jumping to the last frame', ->
90
+ $old = affix('.old').text('old content')
91
+ $new = affix('.new').text('new content')
92
+
93
+ up.morph($old, $new, 'cross-fade', duration: 2000)
94
+ expect($('.up-ghost').length).toBe(2)
95
+
96
+ up.motion.finish($old)
97
+
98
+ expect($('.up-ghost').length).toBe(0)
99
+ expect($old.css('display')).toEqual('none')
100
+ expect($new.css('display')).toEqual('block')
101
+
102
+ it 'can be called on either element involved in a transition', ->
103
+ $old = affix('.old').text('old content')
104
+ $new = affix('.new').text('new content')
105
+
106
+ up.morph($old, $new, 'cross-fade', duration: 2000)
107
+ expect($('.up-ghost').length).toBe(2)
108
+
109
+ up.motion.finish($new)
110
+
111
+ expect($('.up-ghost').length).toBe(0)
112
+ expect($old.css('display')).toEqual('none')
113
+ expect($new.css('display')).toEqual('block')
114
+
115
+
116
+ it 'cancels transitions on children of the given element', ->
117
+ $parent = affix('.parent')
118
+ $old = $parent.affix('.old').text('old content')
119
+ $new = $parent.affix('.new').text('new content')
120
+
121
+ up.morph($old, $new, 'cross-fade', duration: 2000)
122
+ expect($('.up-ghost').length).toBe(2)
123
+
124
+ up.motion.finish($parent)
125
+
126
+ expect($('.up-ghost').length).toBe(0)
127
+ expect($old.css('display')).toEqual('none')
128
+ expect($new.css('display')).toEqual('block')
129
+
130
+ describe 'when called without arguments', ->
131
+
132
+ it 'cancels all animations on the screen', ->
133
+ $element1 = affix('.element1').text('content1')
134
+ $element2 = affix('.element2').text('content2')
135
+
136
+ up.animate($element1, 'fade-in', duration: 3000)
137
+ up.animate($element2, 'fade-in', duration: 3000)
138
+
139
+ opacity = ($element) -> Number($element.css('opacity'))
140
+
141
+ expect(opacity($element1)).toBeAround(0.0, 0.1)
142
+ expect(opacity($element2)).toBeAround(0.0, 0.1)
143
+
144
+ up.motion.finish()
145
+
146
+ $element1 = $('.element1')
147
+ $element2 = $('.element2')
148
+ expect(opacity($element1)).toBe(1.0)
149
+ expect(opacity($element2)).toBe(1.0)
45
150
 
46
151
  describe 'up.morph', ->
47
152
 
@@ -119,19 +224,19 @@ describe 'up.motion', ->
119
224
 
120
225
  opacity = ($element) -> Number($element.css('opacity'))
121
226
 
122
- @setTimer 0, ->
227
+ u.setTimer 0, ->
123
228
  expect(opacity($newGhost)).toBeAround(0.0, 0.25)
124
229
  expect(opacity($oldGhost)).toBeAround(1.0, 0.25)
125
230
 
126
- @setTimer 80, ->
231
+ u.setTimer 80, ->
127
232
  expect(opacity($newGhost)).toBeAround(0.4, 0.25)
128
233
  expect(opacity($oldGhost)).toBeAround(0.6, 0.25)
129
234
 
130
- @setTimer 140, ->
235
+ u.setTimer 140, ->
131
236
  expect(opacity($newGhost)).toBeAround(0.7, 0.25)
132
237
  expect(opacity($oldGhost)).toBeAround(0.3, 0.25)
133
238
 
134
- @setTimer 250, ->
239
+ u.setTimer 250, ->
135
240
  # Once our two ghosts have rendered their visual effect,
136
241
  # we remove them from the DOM.
137
242
  expect($newGhost).not.toBeInDOM()
@@ -1,132 +1,168 @@
1
1
  describe 'up.navigation', ->
2
-
2
+
3
+ u = up.util
4
+
5
+ beforeEach ->
6
+ up.modal.config.openAnimation = 'none'
7
+ up.modal.config.closeAnimation = 'none'
8
+
3
9
  describe 'unobtrusive behavior', ->
4
10
 
5
- it 'marks a link as .up-current if it links to the current URL', ->
6
- spyOn(up.browser, 'url').and.returnValue('/foo')
7
- $currentLink = up.hello(affix('a[href="/foo"]'))
8
- $otherLink = up.hello(affix('a[href="/bar"]'))
9
- expect($currentLink).toHaveClass('up-current')
10
- expect($otherLink).not.toHaveClass('up-current')
11
-
12
- it 'marks any link as .up-current if its up-href attribute matches the current URL', ->
13
- spyOn(up.browser, 'url').and.returnValue('/foo')
14
- $currentLink = up.hello(affix('span[up-href="/foo"]'))
15
- $otherLink = up.hello(affix('span[up-href="/bar"]'))
16
- expect($currentLink).toHaveClass('up-current')
17
- expect($otherLink).not.toHaveClass('up-current')
18
-
19
- it 'marks any link as .up-current if any of its space-separated up-alias values matches the current URL', ->
20
- spyOn(up.browser, 'url').and.returnValue('/foo')
21
- $currentLink = up.hello(affix('span[up-alias="/aaa /foo /bbb"]'))
22
- $otherLink = up.hello(affix('span[up-alias="/bar"]'))
23
- expect($currentLink).toHaveClass('up-current')
24
- expect($otherLink).not.toHaveClass('up-current')
25
-
26
- it 'does not throw if the current location does not match an up-alias wildcard (bugfix)', ->
27
- inserter = -> up.hello(affix('a[up-alias="/qqqq*"]'))
28
- expect(inserter).not.toThrow()
29
-
30
- it 'does not highlight a link to "#" (commonly used for JS-only buttons)', ->
31
- $link = up.hello(affix('a[href="#"]'))
32
- expect($link).not.toHaveClass('up-current')
33
-
34
- it 'marks URL prefixes as .up-current if an up-alias value ends in *', ->
35
- spyOn(up.browser, 'url').and.returnValue('/foo/123')
36
- $currentLink = up.hello(affix('span[up-alias="/aaa /foo/* /bbb"]'))
37
- $otherLink = up.hello(affix('span[up-alias="/bar"]'))
38
- expect($currentLink).toHaveClass('up-current')
39
- expect($otherLink).not.toHaveClass('up-current')
40
-
41
- it 'allows to configure a custom "current" class, but always also sets .up-current', ->
42
- up.navigation.config.currentClasses = ['highlight']
43
- spyOn(up.browser, 'url').and.returnValue('/foo')
44
- $currentLink = up.hello(affix('a[href="/foo"]'))
45
- expect($currentLink).toHaveClass('highlight up-current')
46
-
47
- describeCapability 'canPushState', ->
48
-
49
- it 'marks a link as .up-current if it links to the current URL, but is missing a trailing slash', ->
50
- $link = affix('a[href="/foo"][up-target=".main"]')
51
- affix('.main')
52
- $link.click()
53
- @respondWith
54
- responseHeaders: { 'X-Up-Location': '/foo/' }
55
- responseText: '<div class="main">new-text</div>'
56
- expect($link).toHaveClass('up-current')
57
-
58
- it 'marks a link as .up-current if it links to the current URL, but has an extra trailing slash', ->
59
- $link = affix('a[href="/foo/"][up-target=".main"]')
60
- affix('.main')
61
- $link.click()
62
- @respondWith
63
- responseHeaders: { 'X-Up-Location': '/foo' }
64
- responseText: '<div class="main">new-text</div>'
65
- expect($link).toHaveClass('up-current')
66
-
67
- it 'marks a link as .up-current if it links to an URL currently shown either within or below the modal', (done) ->
68
- up.history.replace('/foo')
69
- $backgroundLink = affix('a[href="/foo"]')
70
- $modalLink = affix('a[href="/bar"][up-modal=".main"]')
71
- $unrelatedLink = affix('a[href="/baz]')
72
-
73
- Trigger.click($modalLink)
74
- @respondWith('<div class="main">new-text</div>')
75
- expect($backgroundLink).toHaveClass('up-current')
76
- expect($modalLink).toHaveClass('up-current')
77
- expect($unrelatedLink).not.toHaveClass('up-current')
78
-
79
- up.modal.close().then ->
11
+ describe '.up-current', ->
12
+
13
+ it 'marks a link as .up-current if it links to the current URL', ->
14
+ spyOn(up.browser, 'url').and.returnValue('/foo')
15
+ $currentLink = up.hello(affix('a[href="/foo"]'))
16
+ $otherLink = up.hello(affix('a[href="/bar"]'))
17
+ expect($currentLink).toHaveClass('up-current')
18
+ expect($otherLink).not.toHaveClass('up-current')
19
+
20
+ it 'marks any link as .up-current if its up-href attribute matches the current URL', ->
21
+ spyOn(up.browser, 'url').and.returnValue('/foo')
22
+ $currentLink = up.hello(affix('span[up-href="/foo"]'))
23
+ $otherLink = up.hello(affix('span[up-href="/bar"]'))
24
+ expect($currentLink).toHaveClass('up-current')
25
+ expect($otherLink).not.toHaveClass('up-current')
26
+
27
+ it 'marks any link as .up-current if any of its space-separated up-alias values matches the current URL', ->
28
+ spyOn(up.browser, 'url').and.returnValue('/foo')
29
+ $currentLink = up.hello(affix('a[href="/x"][up-alias="/aaa /foo /bbb"]'))
30
+ $otherLink = up.hello(affix('a[href="/y"][up-alias="/bar"]'))
31
+ expect($currentLink).toHaveClass('up-current')
32
+ expect($otherLink).not.toHaveClass('up-current')
33
+
34
+ it 'does not throw if the current location does not match an up-alias wildcard (bugfix)', ->
35
+ inserter = -> up.hello(affix('a[up-alias="/qqqq*"]'))
36
+ expect(inserter).not.toThrow()
37
+
38
+ it 'does not highlight a link to "#" (commonly used for JS-only buttons)', ->
39
+ $link = up.hello(affix('a[href="#"]'))
40
+ expect($link).not.toHaveClass('up-current')
41
+
42
+ it 'marks URL prefixes as .up-current if an up-alias value ends in *', ->
43
+ spyOn(up.browser, 'url').and.returnValue('/foo/123')
44
+ $currentLink = up.hello(affix('a[href="/x"][up-alias="/aaa /foo/* /bbb"]'))
45
+ $otherLink = up.hello(affix('a[href="/y"][up-alias="/bar"]'))
46
+ expect($currentLink).toHaveClass('up-current')
47
+ expect($otherLink).not.toHaveClass('up-current')
48
+
49
+ it 'allows to configure a custom "current" class, but always also sets .up-current', ->
50
+ up.navigation.config.currentClasses = ['highlight']
51
+ spyOn(up.browser, 'url').and.returnValue('/foo')
52
+ $currentLink = up.hello(affix('a[href="/foo"]'))
53
+ expect($currentLink).toHaveClass('highlight up-current')
54
+
55
+ describeCapability 'canPushState', ->
56
+
57
+ it 'marks a link as .up-current if it links to the current URL, but is missing a trailing slash', ->
58
+ $link = affix('a[href="/foo"][up-target=".main"]')
59
+ affix('.main')
60
+ $link.click()
61
+ @respondWith
62
+ responseHeaders: { 'X-Up-Location': '/foo/' }
63
+ responseText: '<div class="main">new-text</div>'
64
+ expect($link).toHaveClass('up-current')
65
+
66
+ it 'marks a link as .up-current if it links to the current URL, but has an extra trailing slash', ->
67
+ $link = affix('a[href="/foo/"][up-target=".main"]')
68
+ affix('.main')
69
+ $link.click()
70
+ @respondWith
71
+ responseHeaders: { 'X-Up-Location': '/foo' }
72
+ responseText: '<div class="main">new-text</div>'
73
+ expect($link).toHaveClass('up-current')
74
+
75
+ it 'marks a link as .up-current if it links to an URL currently shown either within or below the modal', (done) ->
76
+ up.history.replace('/foo')
77
+ $backgroundLink = affix('a[href="/foo"]')
78
+ $modalLink = affix('a[href="/bar"][up-modal=".main"]')
79
+ $unrelatedLink = affix('a[href="/baz]')
80
+
81
+ Trigger.click($modalLink)
82
+ @respondWith('<div class="main">new-text</div>')
80
83
  expect($backgroundLink).toHaveClass('up-current')
81
- expect($modalLink).not.toHaveClass('up-current')
84
+ expect($modalLink).toHaveClass('up-current')
82
85
  expect($unrelatedLink).not.toHaveClass('up-current')
83
- done()
84
86
 
85
- it 'marks a link as .up-current if it links to the URL currently either within or below the popup', (done) ->
86
- up.history.replace('/foo')
87
- $backgroundLink = affix('a[href="/foo"]')
88
- $popupLink = affix('a[href="/bar"][up-popup=".main"]')
89
- $unrelatedLink = affix('a[href="/baz]')
87
+ up.modal.close().then ->
88
+ expect($backgroundLink).toHaveClass('up-current')
89
+ expect($modalLink).not.toHaveClass('up-current')
90
+ expect($unrelatedLink).not.toHaveClass('up-current')
91
+ done()
90
92
 
91
- $popupLink.click()
92
- @respondWith('<div class="main">new-text</div>')
93
- expect($backgroundLink).toHaveClass('up-current')
94
- expect($popupLink).toHaveClass('up-current')
95
- expect($unrelatedLink).not.toHaveClass('up-current')
93
+ it 'marks a link as .up-current if it links to the URL currently either within or below the popup', (done) ->
94
+ up.history.replace('/foo')
95
+ $backgroundLink = affix('a[href="/foo"]')
96
+ $popupLink = affix('a[href="/bar"][up-popup=".main"]')
97
+ $unrelatedLink = affix('a[href="/baz]')
96
98
 
97
- up.popup.close().then ->
99
+ $popupLink.click()
100
+ @respondWith('<div class="main">new-text</div>')
98
101
  expect($backgroundLink).toHaveClass('up-current')
99
- expect($popupLink).not.toHaveClass('up-current')
102
+ expect($popupLink).toHaveClass('up-current')
100
103
  expect($unrelatedLink).not.toHaveClass('up-current')
101
- done()
102
-
103
- it 'changes .up-current marks as the URL changes'
104
-
105
- it 'marks clicked links as .up-active until the request finishes', ->
106
- $link = affix('a[href="/foo"][up-target=".main"]')
107
- affix('.main')
108
- $link.click()
109
- expect($link).toHaveClass('up-active')
110
- @respondWith('<div class="main">new-text</div>')
111
- expect($link).not.toHaveClass('up-active')
112
- expect($link).toHaveClass('up-current')
113
-
114
- it 'marks links with [up-instant] on mousedown as .up-active until the request finishes', ->
115
- $link = affix('a[href="/foo"][up-instant][up-target=".main"]')
116
- affix('.main')
117
- Trigger.mousedown($link)
118
- expect($link).toHaveClass('up-active')
119
- @respondWith('<div class="main">new-text</div>')
120
- expect($link).not.toHaveClass('up-active')
121
- expect($link).toHaveClass('up-current')
122
-
123
- it 'prefers to mark an enclosing [up-expand] click area', ->
124
- $area = affix('div[up-expand] a[href="/foo"][up-target=".main"]')
125
- up.hello($area)
126
- $link = $area.find('a')
127
- affix('.main')
128
- $link.click()
129
- expect($area).toHaveClass('up-active')
130
- @respondWith('<div class="main">new-text</div>')
131
- expect($area).toHaveClass('up-current')
104
+
105
+ up.popup.close().then ->
106
+ expect($backgroundLink).toHaveClass('up-current')
107
+ expect($popupLink).not.toHaveClass('up-current')
108
+ expect($unrelatedLink).not.toHaveClass('up-current')
109
+ done()
110
+
111
+ it 'changes .up-current marks as the URL changes'
112
+
113
+ describe '.up-active', ->
114
+
115
+ describeCapability 'canPushState', ->
116
+
117
+ it 'marks clicked links as .up-active until the request finishes', ->
118
+ $link = affix('a[href="/foo"][up-target=".main"]')
119
+ affix('.main')
120
+ $link.click()
121
+ expect($link).toHaveClass('up-active')
122
+ @respondWith('<div class="main">new-text</div>')
123
+ expect($link).not.toHaveClass('up-active')
124
+
125
+ it 'marks links with [up-instant] on mousedown as .up-active until the request finishes', ->
126
+ $link = affix('a[href="/foo"][up-instant][up-target=".main"]')
127
+ affix('.main')
128
+ Trigger.mousedown($link)
129
+ expect($link).toHaveClass('up-active')
130
+ @respondWith('<div class="main">new-text</div>')
131
+ expect($link).not.toHaveClass('up-active')
132
+
133
+ it 'prefers to mark an enclosing [up-expand] click area', ->
134
+ $area = affix('div[up-expand] a[href="/foo"][up-target=".main"]')
135
+ up.hello($area)
136
+ $link = $area.find('a')
137
+ affix('.main')
138
+ $link.click()
139
+ expect($link).not.toHaveClass('up-active')
140
+ expect($area).toHaveClass('up-active')
141
+ @respondWith('<div class="main">new-text</div>')
142
+ expect($area).not.toHaveClass('up-active')
143
+
144
+ it 'marks clicked modal openers as .up-active while the modal is loading', ->
145
+ $link = affix('a[href="/foo"][up-modal=".main"]')
146
+ affix('.main')
147
+ $link.click()
148
+ expect($link).toHaveClass('up-active')
149
+ @respondWith('<div class="main">new-text</div>')
150
+ expect($link).not.toHaveClass('up-active')
151
+
152
+ it 'removes .up-active from a clicked modal opener if the target is already preloaded (bugfix)', ->
153
+ $link = affix('a[href="/foo"][up-modal=".main"]')
154
+ up.proxy.preload($link)
155
+ @respondWith('<div class="main">new-text</div>')
156
+ $link.click()
157
+ expect('.up-modal .main').toHaveText('new-text')
158
+ expect($link).not.toHaveClass('up-active')
159
+
160
+ it 'removes .up-active from a clicked link if the target is already preloaded (bugfix)', ->
161
+ $link = affix('a[href="/foo"][up-target=".main"]')
162
+ affix('.main')
163
+ up.proxy.preload($link)
164
+ @respondWith('<div class="main">new-text</div>')
165
+ $link.click()
166
+ expect('.main').toHaveText('new-text')
167
+ expect($link).not.toHaveClass('up-active')
132
168
 
@@ -73,7 +73,7 @@ describe 'up.popup', ->
73
73
 
74
74
  beforeEach ->
75
75
  @$link = affix('a[href="/path"][up-popup=".target"]')
76
- @attachSpy = up.popup.knife.mock('attach')
76
+ @attachSpy = up.popup.knife.mock('attach').and.returnValue(u.resolvedPromise())
77
77
  @defaultSpy = up.link.knife.mock('allowDefault').and.callFake((event) -> event.preventDefault())
78
78
 
79
79
  it 'opens the clicked link in a popup', ->