unpoly-rails 0.27.3 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of unpoly-rails might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +22 -1
- data/dist/unpoly.css +29 -21
- data/dist/unpoly.js +291 -134
- data/dist/unpoly.min.css +1 -1
- data/dist/unpoly.min.js +3 -3
- data/lib/assets/javascripts/unpoly.js.coffee +1 -0
- data/lib/assets/javascripts/unpoly/browser.js.coffee +22 -5
- data/lib/assets/javascripts/unpoly/bus.js.coffee +1 -1
- data/lib/assets/javascripts/unpoly/flow.js.coffee +9 -6
- data/lib/assets/javascripts/unpoly/form.js.coffee +46 -49
- data/lib/assets/javascripts/unpoly/history.js.coffee +2 -2
- data/lib/assets/javascripts/unpoly/layout.js.coffee +3 -3
- data/lib/assets/javascripts/unpoly/modal.js.coffee +30 -2
- data/lib/assets/javascripts/unpoly/motion.js.coffee +6 -6
- data/lib/assets/javascripts/unpoly/navigation.js.coffee +1 -1
- data/lib/assets/javascripts/unpoly/popup.js.coffee +2 -2
- data/lib/assets/javascripts/unpoly/proxy.js.coffee +5 -9
- data/lib/assets/javascripts/unpoly/syntax.js.coffee +10 -6
- data/lib/assets/javascripts/unpoly/toast.js.coffee +66 -0
- data/lib/assets/javascripts/unpoly/tooltip.js.coffee +1 -1
- data/lib/assets/javascripts/unpoly/util.js.coffee +47 -21
- data/lib/assets/stylesheets/unpoly/toast.css.sass +33 -0
- data/lib/unpoly/rails/version.rb +1 -1
- data/spec_app/Gemfile.lock +1 -1
- data/spec_app/app/assets/javascripts/integration_test.coffee +1 -0
- data/spec_app/app/assets/stylesheets/integration_test.sass +14 -0
- data/spec_app/app/controllers/application_controller.rb +8 -0
- data/spec_app/app/controllers/error_test_controller.rb +5 -0
- data/spec_app/app/views/error_test/trigger.erb +72 -0
- data/spec_app/app/views/error_test/unexpected_response.erb +3 -0
- data/spec_app/app/views/pages/start.erb +4 -0
- data/spec_app/config/routes.rb +2 -0
- data/spec_app/spec/javascripts/helpers/last_request.js.coffee +1 -1
- data/spec_app/spec/javascripts/up/browser_spec.js.coffee +62 -0
- data/spec_app/spec/javascripts/up/form_spec.js.coffee +116 -3
- data/spec_app/spec/javascripts/up/link_spec.js.coffee +2 -2
- data/spec_app/spec/javascripts/up/modal_spec.js.coffee +88 -4
- data/spec_app/spec/javascripts/up/syntax_spec.js.coffee +27 -1
- data/spec_app/spec/javascripts/up/util_spec.js.coffee +12 -0
- metadata +8 -3
- data/lib/assets/stylesheets/unpoly/error.css.sass +0 -21
@@ -0,0 +1,72 @@
|
|
1
|
+
<div class="example">
|
2
|
+
|
3
|
+
<h2>Link to unexpected response</h2>
|
4
|
+
|
5
|
+
<p>
|
6
|
+
<a href="/error_test/unexpected_response" up-target=".link-target">Link</a>
|
7
|
+
</p>
|
8
|
+
|
9
|
+
<div class="area link-target">
|
10
|
+
.link-target
|
11
|
+
</div>
|
12
|
+
|
13
|
+
</div>
|
14
|
+
|
15
|
+
<div class="example">
|
16
|
+
|
17
|
+
<h2>Form to unexpected response</h2>
|
18
|
+
|
19
|
+
<%= form_tag "/error_test/unexpected_response", 'up-target' => '.form-target' do %>
|
20
|
+
|
21
|
+
<p>
|
22
|
+
<input type="text" name="param" value="param-value">
|
23
|
+
</p>
|
24
|
+
|
25
|
+
<p>
|
26
|
+
<button type="submit">Submit</button>
|
27
|
+
</p>
|
28
|
+
|
29
|
+
<% end %>
|
30
|
+
|
31
|
+
<div class="area form-target">
|
32
|
+
.form-target
|
33
|
+
</div>
|
34
|
+
|
35
|
+
</div>
|
36
|
+
|
37
|
+
<script>
|
38
|
+
|
39
|
+
if (false) {
|
40
|
+
|
41
|
+
var html = '<!DOCTYPE html>\
|
42
|
+
<html>\
|
43
|
+
<head>\
|
44
|
+
<title>Integration test - Unpoly</title>\
|
45
|
+
<link rel="stylesheet" media="all" href="/assets/integration_test-6697c9a85c007956bf460adc74ba46bc.css" />\
|
46
|
+
<meta name="csrf-param" content="authenticity_token" />\
|
47
|
+
<meta name="csrf-token" content="CYCqVYIr0wbjErWnupydWZiO8WMqRn+z4BlHN4g4o3T3UN4hW2sDfQXFT3/ygZt41m0jo/YEl6syohm8b8DsYw==" />\
|
48
|
+
</head>\
|
49
|
+
<body>\
|
50
|
+
<div class="page">\
|
51
|
+
<div class="unexpected-response">\
|
52
|
+
unexpected response\
|
53
|
+
</div>\
|
54
|
+
\
|
55
|
+
</div>\
|
56
|
+
</body>\
|
57
|
+
</html>';
|
58
|
+
|
59
|
+
var selector = '.linx-target';
|
60
|
+
|
61
|
+
up.fail(['Could not find selector %s in response %s', selector, html], {
|
62
|
+
inspect: {
|
63
|
+
label: 'Open response',
|
64
|
+
callback: function () {
|
65
|
+
alert("callback")
|
66
|
+
}
|
67
|
+
}
|
68
|
+
});
|
69
|
+
|
70
|
+
}
|
71
|
+
|
72
|
+
</script>
|
data/spec_app/config/routes.rb
CHANGED
@@ -5,6 +5,8 @@ Rails.application.routes.draw do
|
|
5
5
|
|
6
6
|
get 'binding_test/:action', controller: 'binding_test'
|
7
7
|
get 'css_test/:action', controller: 'css_test'
|
8
|
+
get 'error_test/:action', controller: 'error_test'
|
9
|
+
post 'error_test/:action', controller: 'error_test'
|
8
10
|
|
9
11
|
namespace :form_test do
|
10
12
|
resource :basic, only: [:new, :create]
|
@@ -0,0 +1,62 @@
|
|
1
|
+
describe 'up.browser', ->
|
2
|
+
|
3
|
+
u = up.util
|
4
|
+
|
5
|
+
describe 'Javascript functions', ->
|
6
|
+
|
7
|
+
describe 'up.browser.loadPage', ->
|
8
|
+
|
9
|
+
afterEach ->
|
10
|
+
# We're preventing the form to be submitted during tests,
|
11
|
+
# so we need to remove it manually after each example.
|
12
|
+
$('form.up-page-loader').remove()
|
13
|
+
|
14
|
+
describe 'for GET requests', ->
|
15
|
+
|
16
|
+
it 'sets location.href to the given URL', ->
|
17
|
+
hrefSetter = up.browser.knife.mock('setLocationHref')
|
18
|
+
up.browser.loadPage('/foo')
|
19
|
+
expect(hrefSetter).toHaveBeenCalledWith('/foo')
|
20
|
+
|
21
|
+
it 'encodes { data } params into the URL', ->
|
22
|
+
hrefSetter = up.browser.knife.mock('setLocationHref')
|
23
|
+
up.browser.loadPage('/foo', data: { param1: 'param1 value', param2: 'param2 value' })
|
24
|
+
expect(hrefSetter).toHaveBeenCalledWith('/foo?param1=param1%20value¶m2=param2%20value')
|
25
|
+
|
26
|
+
describe 'for POST requests', ->
|
27
|
+
|
28
|
+
it 'creates a form, adds all { data } params a hidden fields and submits the form', ->
|
29
|
+
submitForm = up.browser.knife.mock('submitForm')
|
30
|
+
up.browser.loadPage('/foo', method: 'post', data: { param1: 'param1 value', param2: 'param2 value' })
|
31
|
+
expect(submitForm).toHaveBeenCalled()
|
32
|
+
$form = $('form.up-page-loader')
|
33
|
+
expect($form).toExist()
|
34
|
+
expect($form.attr('action')).toEqual('/foo')
|
35
|
+
expect($form.attr('method')).toEqual('post')
|
36
|
+
expect($form.find('input[name="param1"][value="param1 value"]')).toExist()
|
37
|
+
expect($form.find('input[name="param2"][value="param2 value"]')).toExist()
|
38
|
+
|
39
|
+
it 'submits the Rails CSRF token as another hidden field', ->
|
40
|
+
submitForm = up.browser.knife.mock('submitForm')
|
41
|
+
spyOn(up.rails, 'csrfField').and.returnValue
|
42
|
+
name: 'authenticity-param-name',
|
43
|
+
value: 'authenticity-token'
|
44
|
+
up.browser.loadPage('/foo', method: 'post')
|
45
|
+
expect(submitForm).toHaveBeenCalled()
|
46
|
+
$form = $('form.up-page-loader')
|
47
|
+
$tokenInput = $form.find('input[name="authenticity-param-name"]')
|
48
|
+
expect($tokenInput).toExist()
|
49
|
+
expect($tokenInput.val()).toEqual('authenticity-token')
|
50
|
+
|
51
|
+
u.each ['PUT', 'PATCH', 'DELETE'], (method) ->
|
52
|
+
|
53
|
+
describe "for #{method} requests", ->
|
54
|
+
|
55
|
+
it "uses a POST form and sends the actual method as a { _method } param", ->
|
56
|
+
submitForm = up.browser.knife.mock('submitForm')
|
57
|
+
up.browser.loadPage('/foo', method: method)
|
58
|
+
expect(submitForm).toHaveBeenCalled()
|
59
|
+
$form = $('form.up-page-loader')
|
60
|
+
expect($form).toExist()
|
61
|
+
expect($form.attr('method')).toEqual('post')
|
62
|
+
expect($form.find('input[name="_method"]').val()).toEqual(method.toLowerCase())
|
@@ -6,6 +6,9 @@ describe 'up.form', ->
|
|
6
6
|
|
7
7
|
describe 'up.observe', ->
|
8
8
|
|
9
|
+
beforeEach ->
|
10
|
+
up.form.config.observeDelay = 0
|
11
|
+
|
9
12
|
changeEvents = if up.browser.canInputEvent()
|
10
13
|
# Actually we only need `input`, but we want to notice
|
11
14
|
# if another script manually triggers `change` on the element.
|
@@ -16,9 +19,9 @@ describe 'up.form', ->
|
|
16
19
|
# on the element.
|
17
20
|
['input', 'change', 'keypress', 'paste', 'cut', 'click', 'propertychange']
|
18
21
|
|
19
|
-
|
22
|
+
describe 'when the first argument is a form field', ->
|
20
23
|
|
21
|
-
|
24
|
+
u.each changeEvents, (eventName) ->
|
22
25
|
|
23
26
|
it "runs the callback when the input receives a '#{eventName}' event and the value changed", (done) ->
|
24
27
|
$input = affix('input[value="old-value"]')
|
@@ -58,7 +61,107 @@ describe 'up.form', ->
|
|
58
61
|
$input.trigger(eventName)
|
59
62
|
expect(callback.calls.count()).toEqual(2)
|
60
63
|
|
61
|
-
describe 'when the first argument is a
|
64
|
+
describe 'when the first argument is a checkbox', ->
|
65
|
+
|
66
|
+
it 'runs the callback when the checkbox changes its checked state', (done) ->
|
67
|
+
$form = affix('form')
|
68
|
+
$checkbox = $form.affix('input[type="checkbox"]')
|
69
|
+
callback = jasmine.createSpy('change callback')
|
70
|
+
up.observe($checkbox, callback)
|
71
|
+
expect($checkbox.is(':checked')).toBe(false)
|
72
|
+
$checkbox.get(0).click()
|
73
|
+
u.nextFrame ->
|
74
|
+
expect($checkbox.is(':checked')).toBe(true)
|
75
|
+
expect(callback.calls.count()).toEqual(1)
|
76
|
+
$checkbox.get(0).click()
|
77
|
+
u.nextFrame ->
|
78
|
+
expect($checkbox.is(':checked')).toBe(false)
|
79
|
+
expect(callback.calls.count()).toEqual(2)
|
80
|
+
done()
|
81
|
+
|
82
|
+
it 'runs the callback when the checkbox is toggled by clicking its label', (done) ->
|
83
|
+
$form = affix('form')
|
84
|
+
$checkbox = $form.affix('input#tick[type="checkbox"]')
|
85
|
+
$label = $form.affix('label[for="tick"]').text('tick label')
|
86
|
+
callback = jasmine.createSpy('change callback')
|
87
|
+
up.observe($checkbox, callback)
|
88
|
+
expect($checkbox.is(':checked')).toBe(false)
|
89
|
+
$label.get(0).click()
|
90
|
+
u.nextFrame ->
|
91
|
+
expect($checkbox.is(':checked')).toBe(true)
|
92
|
+
expect(callback.calls.count()).toEqual(1)
|
93
|
+
$label.get(0).click()
|
94
|
+
u.nextFrame ->
|
95
|
+
expect($checkbox.is(':checked')).toBe(false)
|
96
|
+
expect(callback.calls.count()).toEqual(2)
|
97
|
+
done()
|
98
|
+
|
99
|
+
describe 'when the first argument is a radio button group', ->
|
100
|
+
|
101
|
+
it 'runs the callback when the group changes its selection', (done) ->
|
102
|
+
$form = affix('form')
|
103
|
+
$radio1 = $form.affix('input[type="radio"][name="group"][value="1"]')
|
104
|
+
$radio2 = $form.affix('input[type="radio"][name="group"][value="2"]')
|
105
|
+
$group = $radio1.add($radio2)
|
106
|
+
callback = jasmine.createSpy('change callback')
|
107
|
+
up.observe($group, callback)
|
108
|
+
expect($radio1.is(':checked')).toBe(false)
|
109
|
+
$radio1.get(0).click()
|
110
|
+
u.nextFrame ->
|
111
|
+
expect($radio1.is(':checked')).toBe(true)
|
112
|
+
expect(callback.calls.count()).toEqual(1)
|
113
|
+
$radio2.get(0).click()
|
114
|
+
u.nextFrame ->
|
115
|
+
expect($radio1.is(':checked')).toBe(false)
|
116
|
+
expect(callback.calls.count()).toEqual(2)
|
117
|
+
done()
|
118
|
+
|
119
|
+
it "runs the callbacks when a radio button is selected or deselected by clicking a label in the group", (done) ->
|
120
|
+
$form = affix('form')
|
121
|
+
$radio1 = $form.affix('input#radio1[type="radio"][name="group"][value="1"]')
|
122
|
+
$radio1Label = $form.affix('label[for="radio1"]').text('label 1')
|
123
|
+
$radio2 = $form.affix('input#radio2[type="radio"][name="group"][value="2"]')
|
124
|
+
$radio2Label = $form.affix('label[for="radio2"]').text('label 2')
|
125
|
+
$group = $radio1.add($radio2)
|
126
|
+
callback = jasmine.createSpy('change callback')
|
127
|
+
up.observe($group, callback)
|
128
|
+
expect($radio1.is(':checked')).toBe(false)
|
129
|
+
$radio1Label.get(0).click()
|
130
|
+
u.nextFrame ->
|
131
|
+
expect($radio1.is(':checked')).toBe(true)
|
132
|
+
expect(callback.calls.count()).toEqual(1)
|
133
|
+
$radio2Label.get(0).click()
|
134
|
+
u.nextFrame ->
|
135
|
+
expect($radio1.is(':checked')).toBe(false)
|
136
|
+
expect(callback.calls.count()).toEqual(2)
|
137
|
+
done()
|
138
|
+
|
139
|
+
it "takes the group's initial selected value into account", (done) ->
|
140
|
+
$form = affix('form')
|
141
|
+
$radio1 = $form.affix('input[type="radio"][name="group"][value="1"][checked="checked"]')
|
142
|
+
$radio2 = $form.affix('input[type="radio"][name="group"][value="2"]')
|
143
|
+
$group = $radio1.add($radio2)
|
144
|
+
callback = jasmine.createSpy('change callback')
|
145
|
+
up.observe($group, callback)
|
146
|
+
expect($radio1.is(':checked')).toBe(true)
|
147
|
+
expect($radio2.is(':checked')).toBe(false)
|
148
|
+
$radio1.get(0).click()
|
149
|
+
u.nextFrame ->
|
150
|
+
# Since the radio button was already checked, the click doesn't do anything
|
151
|
+
expect($radio1.is(':checked')).toBe(true)
|
152
|
+
expect($radio2.is(':checked')).toBe(false)
|
153
|
+
# Since the radio button was already checked, clicking it again won't trigger the callback
|
154
|
+
expect(callback.calls.count()).toEqual(0)
|
155
|
+
$radio2.get(0).click()
|
156
|
+
u.nextFrame ->
|
157
|
+
expect($radio1.is(':checked')).toBe(false)
|
158
|
+
expect($radio2.is(':checked')).toBe(true)
|
159
|
+
expect(callback.calls.count()).toEqual(1)
|
160
|
+
done()
|
161
|
+
|
162
|
+
describe 'when the first argument is a form', ->
|
163
|
+
|
164
|
+
u.each changeEvents, (eventName) ->
|
62
165
|
|
63
166
|
it "runs the callback when any of the form's inputs receives a '#{eventName}' event and the value changed", (done) ->
|
64
167
|
$form = affix('form')
|
@@ -82,6 +185,16 @@ describe 'up.form', ->
|
|
82
185
|
expect(callback).not.toHaveBeenCalled()
|
83
186
|
done()
|
84
187
|
|
188
|
+
# it 'runs the callback only once when a radio button group changes its selection', ->
|
189
|
+
# $form = affix('form')
|
190
|
+
# $radio1 = $form.affix('input[type="radio"][name="group"][value="1"][checked="checked"]')
|
191
|
+
# $radio2 = $form.affix('input[type="radio"][name="group"][value="2"]')
|
192
|
+
# callback = jasmine.createSpy('change callback')
|
193
|
+
# up.observe($form, callback)
|
194
|
+
# $radio2.get(0).click()
|
195
|
+
# u.nextFrame ->
|
196
|
+
# expect(callback.calls.count()).toEqual(1)
|
197
|
+
|
85
198
|
describe 'up.submit', ->
|
86
199
|
|
87
200
|
describeCapability 'canPushState', ->
|
@@ -395,7 +395,7 @@ describe 'up.link', ->
|
|
395
395
|
|
396
396
|
it 'morphs between the old and new target element', (done) ->
|
397
397
|
affix('.target.old')
|
398
|
-
$link = affix('a[href="/path"][up-target=".target"][up-transition="cross-fade"][up-duration="
|
398
|
+
$link = affix('a[href="/path"][up-target=".target"][up-transition="cross-fade"][up-duration="500"][up-easing="linear"]')
|
399
399
|
$link.click()
|
400
400
|
@respondWith '<div class="target new">new text</div>'
|
401
401
|
|
@@ -405,7 +405,7 @@ describe 'up.link', ->
|
|
405
405
|
expect($newGhost).toExist()
|
406
406
|
expect(u.opacity($oldGhost)).toBeAround(1, 0.15)
|
407
407
|
expect(u.opacity($newGhost)).toBeAround(0, 0.15)
|
408
|
-
u.setTimer
|
408
|
+
u.setTimer 250, ->
|
409
409
|
expect(u.opacity($oldGhost)).toBeAround(0.5, 0.15)
|
410
410
|
expect(u.opacity($newGhost)).toBeAround(0.5, 0.15)
|
411
411
|
done()
|
@@ -318,13 +318,24 @@ describe 'up.modal', ->
|
|
318
318
|
|
319
319
|
describe 'up.modal.close', ->
|
320
320
|
|
321
|
-
it 'closes a currently open modal'
|
321
|
+
it 'closes a currently open modal', (done) ->
|
322
|
+
up.modal.extract('.modal', '<div class="modal">Modal content</div>')
|
322
323
|
|
323
|
-
|
324
|
+
modalContent = $('.modal')
|
325
|
+
expect(modalContent).toBeInDOM()
|
324
326
|
|
325
|
-
|
327
|
+
up.modal.close().then ->
|
328
|
+
expect(modalContent).not.toBeInDOM()
|
329
|
+
done()
|
326
330
|
|
327
|
-
it '
|
331
|
+
it 'does nothing if no modal is open', (done) ->
|
332
|
+
wasClosed = false
|
333
|
+
up.on 'up:modal:close', ->
|
334
|
+
wasClosed = true
|
335
|
+
|
336
|
+
up.modal.close().then ->
|
337
|
+
expect(wasClosed).toBe(false)
|
338
|
+
done()
|
328
339
|
|
329
340
|
describe 'unobtrusive behavior', ->
|
330
341
|
|
@@ -443,6 +454,79 @@ describe 'up.modal', ->
|
|
443
454
|
expect(wasClosed).toBe(false)
|
444
455
|
expect(wasDefaultPrevented).toBe(false)
|
445
456
|
|
457
|
+
describe 'template behavior', ->
|
458
|
+
|
459
|
+
it 'closes the modal on close icon click', (done) ->
|
460
|
+
wasClosed = false
|
461
|
+
up.modal.extract('.modal', '<div class="modal">Modal content</div>', animation: false)
|
462
|
+
|
463
|
+
closeIcon = $('.up-modal-close')
|
464
|
+
up.on 'up:modal:close', ->
|
465
|
+
wasClosed = true
|
466
|
+
|
467
|
+
closeIcon.click()
|
468
|
+
u.nextFrame ->
|
469
|
+
expect(wasClosed).toBe(true)
|
470
|
+
done()
|
471
|
+
|
472
|
+
it 'closes the modal on backdrop click', (done) ->
|
473
|
+
wasClosed = false
|
474
|
+
up.modal.extract('.modal', '<div class="modal">Modal content</div>', animation: false)
|
475
|
+
|
476
|
+
backdrop = $('.up-modal-backdrop')
|
477
|
+
up.on 'up:modal:close', ->
|
478
|
+
wasClosed = true
|
479
|
+
|
480
|
+
backdrop.click()
|
481
|
+
u.nextFrame ->
|
482
|
+
expect(wasClosed).toBe(true)
|
483
|
+
done()
|
484
|
+
|
485
|
+
it 'closes the modal when the user presses the escape key', (done) ->
|
486
|
+
wasClosed = false
|
487
|
+
up.modal.extract('.modal', '<div class="modal">Modal content</div>', animation: false)
|
488
|
+
up.on 'up:modal:close', ->
|
489
|
+
wasClosed = true
|
490
|
+
|
491
|
+
escapeEvent = $.Event('keydown', keyCode: 27)
|
492
|
+
$('body').trigger(escapeEvent)
|
493
|
+
u.nextFrame ->
|
494
|
+
expect(wasClosed).toBe(true)
|
495
|
+
done()
|
496
|
+
|
497
|
+
describe 'when opened with { closable: false }', ->
|
498
|
+
|
499
|
+
it 'does not render a close icon', ->
|
500
|
+
up.modal.extract('.modal', '<div class="modal">Modal content</div>', animation: false, closable: false)
|
501
|
+
|
502
|
+
modal = $('.up-modal')
|
503
|
+
expect(modal).not.toContainElement('.up-modal-close')
|
504
|
+
|
505
|
+
it 'does not close the modal on backdrop click', (done) ->
|
506
|
+
wasClosed = false
|
507
|
+
up.modal.extract('.modal', '<div class="modal">Modal content</div>', animation: false, closable: false)
|
508
|
+
|
509
|
+
backdrop = $('.up-modal-backdrop')
|
510
|
+
up.on 'up:modal:close', ->
|
511
|
+
wasClosed = true
|
512
|
+
|
513
|
+
backdrop.click()
|
514
|
+
u.nextFrame ->
|
515
|
+
expect(wasClosed).toBe(false)
|
516
|
+
done()
|
517
|
+
|
518
|
+
it 'does not close the modal when the user presses the escape key', (done) ->
|
519
|
+
wasClosed = false
|
520
|
+
up.modal.extract('.modal', '<div class="modal">Modal content</div>', animation: false, closable: false)
|
521
|
+
up.on 'up:modal:close', ->
|
522
|
+
wasClosed = true
|
523
|
+
|
524
|
+
escapeEvent = $.Event('keydown', keyCode: 27)
|
525
|
+
$('body').trigger(escapeEvent)
|
526
|
+
u.nextFrame ->
|
527
|
+
expect(wasClosed).toBe(false)
|
528
|
+
done()
|
529
|
+
|
446
530
|
describe 'when replacing content', ->
|
447
531
|
|
448
532
|
beforeEach ->
|