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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +127 -25
- data/LICENSE +1 -1
- data/README_RAILS.md +4 -2
- data/Rakefile +6 -1
- data/dist/unpoly.js +3192 -2198
- data/dist/unpoly.min.js +4 -3
- data/lib/assets/javascripts/unpoly/browser.coffee +51 -63
- data/lib/assets/javascripts/unpoly/bus.coffee +58 -33
- data/lib/assets/javascripts/unpoly/classes/cache.coffee +117 -0
- data/lib/assets/javascripts/unpoly/{dom → classes}/extract_cascade.coffee +3 -3
- data/lib/assets/javascripts/unpoly/{dom → classes}/extract_plan.coffee +1 -1
- data/lib/assets/javascripts/unpoly/classes/field_observer.coffee +57 -0
- data/lib/assets/javascripts/unpoly/classes/follow_variant.coffee +52 -0
- data/lib/assets/javascripts/unpoly/classes/motion_tracker.coffee +95 -0
- data/lib/assets/javascripts/unpoly/classes/record.coffee +16 -0
- data/lib/assets/javascripts/unpoly/classes/request.coffee +228 -0
- data/lib/assets/javascripts/unpoly/classes/response.coffee +138 -0
- data/lib/assets/javascripts/unpoly/dom.coffee +151 -142
- data/lib/assets/javascripts/unpoly/feedback.coffee +67 -38
- data/lib/assets/javascripts/unpoly/form.coffee +156 -139
- data/lib/assets/javascripts/unpoly/history.coffee +22 -19
- data/lib/assets/javascripts/unpoly/layout.coffee +108 -90
- data/lib/assets/javascripts/unpoly/link.coffee +159 -158
- data/lib/assets/javascripts/unpoly/log.coffee +5 -5
- data/lib/assets/javascripts/unpoly/modal.coffee +93 -81
- data/lib/assets/javascripts/unpoly/motion.coffee +291 -250
- data/lib/assets/javascripts/unpoly/popup.coffee +67 -53
- data/lib/assets/javascripts/unpoly/protocol.coffee +67 -16
- data/lib/assets/javascripts/unpoly/proxy.coffee +282 -211
- data/lib/assets/javascripts/unpoly/rails.coffee +3 -14
- data/lib/assets/javascripts/unpoly/syntax.coffee +54 -49
- data/lib/assets/javascripts/unpoly/tooltip.coffee +18 -25
- data/lib/assets/javascripts/unpoly/util.coffee +236 -477
- data/lib/assets/javascripts/unpoly.coffee +1 -1
- data/lib/unpoly/rails/inspector.rb +67 -22
- data/lib/unpoly/rails/version.rb +1 -1
- data/package.json +1 -1
- data/spec_app/Gemfile.lock +13 -13
- data/spec_app/app/assets/javascripts/integration_test.coffee +1 -0
- data/spec_app/app/assets/javascripts/jasmine_specs.coffee +1 -1
- data/spec_app/app/assets/stylesheets/jasmine_specs.sass +10 -0
- data/spec_app/app/controllers/binding_test_controller.rb +19 -2
- data/spec_app/app/controllers/method_test_controller.rb +16 -0
- data/spec_app/app/views/layouts/jasmine_rails/spec_runner.html.erb +20 -0
- data/spec_app/app/views/method_test/form_target.erb +17 -0
- data/spec_app/app/views/method_test/page1.erb +11 -0
- data/spec_app/app/views/method_test/page2.erb +6 -0
- data/spec_app/app/views/pages/start.erb +33 -19
- data/spec_app/config/initializers/assets.rb +5 -0
- data/spec_app/config/routes.rb +3 -0
- data/spec_app/spec/controllers/binding_test_controller_spec.rb +82 -27
- data/spec_app/spec/javascripts/helpers/agent_detector.coffee +17 -0
- data/spec_app/spec/javascripts/helpers/async_sequence.js.coffee +102 -0
- data/spec_app/spec/javascripts/helpers/last_request.js.coffee +1 -1
- data/spec_app/spec/javascripts/helpers/mock_ajax.js.coffee +5 -2
- data/spec_app/spec/javascripts/helpers/promise_state.js +18 -0
- data/spec_app/spec/javascripts/helpers/protect_jasmine_runner.coffee +9 -0
- data/spec_app/spec/javascripts/helpers/reset_history.js.coffee +22 -0
- data/spec_app/spec/javascripts/helpers/reset_up.js.coffee +11 -3
- data/spec_app/spec/javascripts/helpers/show_lib_versions.coffee +10 -0
- data/spec_app/spec/javascripts/helpers/to_be_error.coffee +5 -0
- data/spec_app/spec/javascripts/helpers/to_match_url.coffee +13 -0
- data/spec_app/spec/javascripts/helpers/trigger.js.coffee +13 -6
- data/spec_app/spec/javascripts/up/browser_spec.js.coffee +92 -33
- data/spec_app/spec/javascripts/up/bus_spec.js.coffee +64 -15
- data/spec_app/spec/javascripts/up/classes/.keep +0 -0
- data/spec_app/spec/javascripts/up/classes/cache_spec.js.coffee +1 -0
- data/spec_app/spec/javascripts/up/dom_spec.js.coffee +759 -551
- data/spec_app/spec/javascripts/up/feedback_spec.js.coffee +155 -82
- data/spec_app/spec/javascripts/up/form_spec.js.coffee +490 -349
- data/spec_app/spec/javascripts/up/history_spec.js.coffee +226 -179
- data/spec_app/spec/javascripts/up/layout_spec.js.coffee +253 -185
- data/spec_app/spec/javascripts/up/link_spec.js.coffee +416 -270
- data/spec_app/spec/javascripts/up/modal_spec.js.coffee +459 -330
- data/spec_app/spec/javascripts/up/motion_spec.js.coffee +198 -153
- data/spec_app/spec/javascripts/up/namespace_spec.js.coffee +9 -0
- data/spec_app/spec/javascripts/up/popup_spec.js.coffee +240 -175
- data/spec_app/spec/javascripts/up/protocol_spec.js.coffee +38 -0
- data/spec_app/spec/javascripts/up/proxy_spec.js.coffee +777 -303
- data/spec_app/spec/javascripts/up/rails_spec.js.coffee +24 -8
- data/spec_app/spec/javascripts/up/syntax_spec.js.coffee +40 -23
- data/spec_app/spec/javascripts/up/tooltip_spec.js.coffee +80 -66
- data/spec_app/spec/javascripts/up/util_spec.js.coffee +227 -201
- data/spec_app/vendor/asset-libs/es6-promise-4.1.6/es6-promise.auto.js +1159 -0
- metadata +30 -7
- data/spec_app/spec/javascripts/helpers/reset_path.js.coffee +0 -7
- data/spec_app/spec/javascripts/helpers/to_equal_url.coffee +0 -11
@@ -26,7 +26,7 @@ describe 'up.util', ->
|
|
26
26
|
done()
|
27
27
|
|
28
28
|
it "delays resolution of the proxy's .promise if the inner function returns a promise", (done) ->
|
29
|
-
funDeferred =
|
29
|
+
funDeferred = u.newDeferred()
|
30
30
|
fun = -> funDeferred
|
31
31
|
proxy = up.util.previewable(fun)
|
32
32
|
callback = jasmine.createSpy('promise callback')
|
@@ -34,31 +34,31 @@ describe 'up.util', ->
|
|
34
34
|
proxy()
|
35
35
|
u.nextFrame ->
|
36
36
|
expect(callback).not.toHaveBeenCalled()
|
37
|
-
funDeferred.resolve()
|
37
|
+
funDeferred.resolve('return value')
|
38
38
|
u.nextFrame ->
|
39
|
-
expect(callback).
|
39
|
+
expect(callback).toHaveBeenCalledWith('return value')
|
40
40
|
done()
|
41
41
|
|
42
42
|
describe 'up.util.DivertibleChain', ->
|
43
43
|
|
44
44
|
it "instantiates a task queue whose (2..n)th tasks can be changed by calling '.asap'", (done) ->
|
45
45
|
chain = new up.util.DivertibleChain()
|
46
|
-
|
46
|
+
|
47
47
|
timer1Spy = jasmine.createSpy('timer1 has been called')
|
48
48
|
timer1 = ->
|
49
49
|
timer1Spy()
|
50
50
|
u.promiseTimer(50)
|
51
|
-
|
51
|
+
|
52
52
|
timer2Spy = jasmine.createSpy('timer2 has been called')
|
53
53
|
timer2 = ->
|
54
54
|
timer2Spy()
|
55
55
|
u.promiseTimer(50)
|
56
|
-
|
56
|
+
|
57
57
|
timer3Spy = jasmine.createSpy('timer3 has been called')
|
58
58
|
timer3 = ->
|
59
59
|
timer3Spy()
|
60
60
|
u.promiseTimer(50)
|
61
|
-
|
61
|
+
|
62
62
|
timer4Spy = jasmine.createSpy('timer4 has been called')
|
63
63
|
timer4 = ->
|
64
64
|
timer4Spy()
|
@@ -184,15 +184,6 @@ describe 'up.util', ->
|
|
184
184
|
expect(element.querySelector("title")).toBeMissing()
|
185
185
|
expect(element.querySelector("h1").textContent).toEqual('Full story')
|
186
186
|
|
187
|
-
describe 'up.util.cssAnimate', ->
|
188
|
-
|
189
|
-
it 'returns a deferred that eventually resolves if called with a duration of 0 (bugfix)', (done) ->
|
190
|
-
$element = affix('.element')
|
191
|
-
promise = up.util.cssAnimate($element, { 'font-size': '90px' }, { duration: 0 })
|
192
|
-
promise.then ->
|
193
|
-
expect('done').toEqual('done') # need an expectation of Jasmine will complain
|
194
|
-
done()
|
195
|
-
|
196
187
|
describe 'up.util.isFixed', ->
|
197
188
|
|
198
189
|
it 'returns true if the given element or one of its ancestors has a "fixed" CSS position', ->
|
@@ -212,28 +203,26 @@ describe 'up.util', ->
|
|
212
203
|
|
213
204
|
describe 'up.util.setTimer', ->
|
214
205
|
|
215
|
-
it 'calls the given function after waiting the given milliseconds', ->
|
216
|
-
jasmine.clock().install()
|
217
|
-
jasmine.clock().mockDate()
|
206
|
+
it 'calls the given function after waiting the given milliseconds', (done) ->
|
218
207
|
callback = jasmine.createSpy()
|
219
|
-
|
220
|
-
expect(callback).
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
208
|
+
expectNotCalled = -> expect(callback).not.toHaveBeenCalled()
|
209
|
+
expectCalled = -> expect(callback).toHaveBeenCalled()
|
210
|
+
|
211
|
+
up.util.setTimer(100, callback)
|
212
|
+
|
213
|
+
expectNotCalled()
|
214
|
+
setTimeout(expectNotCalled, 50)
|
215
|
+
setTimeout(expectCalled, 50 + 75)
|
216
|
+
setTimeout(done, 50 + 75)
|
225
217
|
|
226
218
|
describe 'if the delay is zero', ->
|
227
219
|
|
228
|
-
it 'calls the given function in the
|
220
|
+
it 'calls the given function in the next execution frame', ->
|
229
221
|
callback = jasmine.createSpy()
|
230
222
|
up.util.setTimer(0, callback)
|
231
|
-
expect(callback).toHaveBeenCalled()
|
223
|
+
expect(callback).not.toHaveBeenCalled()
|
232
224
|
|
233
|
-
|
234
|
-
callback = -> 'function return value'
|
235
|
-
timerReturnValue = up.util.setTimer(0, callback)
|
236
|
-
expect(timerReturnValue).toBeUndefined()
|
225
|
+
setTimeout((-> expect(callback).toHaveBeenCalled()), 0)
|
237
226
|
|
238
227
|
# describe 'up.util.argNames', ->
|
239
228
|
#
|
@@ -361,28 +350,28 @@ describe 'up.util', ->
|
|
361
350
|
expect(count).toBe(3)
|
362
351
|
|
363
352
|
describe 'up.util.isBlank', ->
|
364
|
-
|
353
|
+
|
365
354
|
it 'returns false for false', ->
|
366
355
|
expect(up.util.isBlank(false)).toBe(false)
|
367
|
-
|
356
|
+
|
368
357
|
it 'returns false for true', ->
|
369
358
|
expect(up.util.isBlank(true)).toBe(false)
|
370
|
-
|
359
|
+
|
371
360
|
it 'returns true for null', ->
|
372
361
|
expect(up.util.isBlank(null)).toBe(true)
|
373
|
-
|
362
|
+
|
374
363
|
it 'returns true for undefined', ->
|
375
364
|
expect(up.util.isBlank(undefined)).toBe(true)
|
376
|
-
|
365
|
+
|
377
366
|
it 'returns true for an empty String', ->
|
378
367
|
expect(up.util.isBlank('')).toBe(true)
|
379
|
-
|
368
|
+
|
380
369
|
it 'returns false for a String with at least one character', ->
|
381
370
|
expect(up.util.isBlank('string')).toBe(false)
|
382
|
-
|
371
|
+
|
383
372
|
it 'returns true for an empty array', ->
|
384
373
|
expect(up.util.isBlank([])).toBe(true)
|
385
|
-
|
374
|
+
|
386
375
|
it 'returns false for an array with at least one element', ->
|
387
376
|
expect(up.util.isBlank(['element'])).toBe(false)
|
388
377
|
|
@@ -412,6 +401,9 @@ describe 'up.util', ->
|
|
412
401
|
it 'does not strip a trailing slash by default', ->
|
413
402
|
expect(up.util.normalizeUrl('/foo/')).toEqual("http://#{location.hostname}:#{location.port}/foo/")
|
414
403
|
|
404
|
+
it 'normalizes redundant segments', ->
|
405
|
+
expect(up.util.normalizeUrl('/foo/../foo')).toBe("http://#{location.hostname}:#{location.port}/foo")
|
406
|
+
|
415
407
|
describe 'up.util.detect', ->
|
416
408
|
|
417
409
|
it 'finds the first element in the given array that matches the given tester', ->
|
@@ -509,97 +501,19 @@ describe 'up.util', ->
|
|
509
501
|
string = up.util.requestDataAsQuery({ 'my+key': 'my+value' })
|
510
502
|
expect(string).toEqual('my%2Bkey=my%2Bvalue')
|
511
503
|
|
512
|
-
describe 'up.util.unresolvableDeferred', ->
|
513
|
-
|
514
|
-
it 'returns a different object every time (to prevent memory leaks)', ->
|
515
|
-
one = up.util.unresolvableDeferred()
|
516
|
-
two = up.util.unresolvableDeferred()
|
517
|
-
expect(one).not.toBe(two)
|
518
|
-
|
519
504
|
describe 'up.util.unresolvablePromise', ->
|
520
|
-
|
505
|
+
|
506
|
+
it 'return a pending promise', (done) ->
|
507
|
+
promise = up.util.unresolvablePromise()
|
508
|
+
promiseState(promise).then (result) ->
|
509
|
+
expect(result.state).toEqual('pending')
|
510
|
+
done()
|
511
|
+
|
521
512
|
it 'returns a different object every time (to prevent memory leaks)', ->
|
522
513
|
one = up.util.unresolvablePromise()
|
523
514
|
two = up.util.unresolvablePromise()
|
524
515
|
expect(one).not.toBe(two)
|
525
516
|
|
526
|
-
describe 'up.util.resolvableWhen', ->
|
527
|
-
|
528
|
-
it 'returns a promise that is resolved when all the given deferreds are resolved', ->
|
529
|
-
one = jasmine.createSpy()
|
530
|
-
two = jasmine.createSpy()
|
531
|
-
both = jasmine.createSpy()
|
532
|
-
oneDeferred = $.Deferred()
|
533
|
-
oneDeferred.then(one)
|
534
|
-
twoDeferred = $.Deferred()
|
535
|
-
twoDeferred.then(two)
|
536
|
-
|
537
|
-
bothDeferred = up.util.resolvableWhen(oneDeferred, twoDeferred)
|
538
|
-
bothDeferred.then(both)
|
539
|
-
|
540
|
-
expect(one).not.toHaveBeenCalled()
|
541
|
-
expect(two).not.toHaveBeenCalled()
|
542
|
-
expect(both).not.toHaveBeenCalled()
|
543
|
-
|
544
|
-
oneDeferred.resolve()
|
545
|
-
expect(one).toHaveBeenCalled()
|
546
|
-
expect(two).not.toHaveBeenCalled()
|
547
|
-
expect(both).not.toHaveBeenCalled()
|
548
|
-
|
549
|
-
twoDeferred.resolve()
|
550
|
-
expect(one).toHaveBeenCalled()
|
551
|
-
expect(two).toHaveBeenCalled()
|
552
|
-
expect(both).toHaveBeenCalled()
|
553
|
-
|
554
|
-
it 'returns a promise with a .resolve method that resolves the given deferreds', ->
|
555
|
-
one = jasmine.createSpy()
|
556
|
-
two = jasmine.createSpy()
|
557
|
-
both = jasmine.createSpy()
|
558
|
-
oneDeferred = $.Deferred()
|
559
|
-
oneDeferred.then(one)
|
560
|
-
twoDeferred = $.Deferred()
|
561
|
-
twoDeferred.then(two)
|
562
|
-
|
563
|
-
bothDeferred = up.util.resolvableWhen(oneDeferred, twoDeferred)
|
564
|
-
bothDeferred.then(both)
|
565
|
-
|
566
|
-
expect(one).not.toHaveBeenCalled()
|
567
|
-
expect(two).not.toHaveBeenCalled()
|
568
|
-
expect(both).not.toHaveBeenCalled()
|
569
|
-
|
570
|
-
bothDeferred.resolve()
|
571
|
-
expect(one).toHaveBeenCalled()
|
572
|
-
expect(two).toHaveBeenCalled()
|
573
|
-
expect(both).toHaveBeenCalled()
|
574
|
-
|
575
|
-
it 'does not resolve the given deferreds more than once', ->
|
576
|
-
oneDeferred = $.Deferred()
|
577
|
-
spyOn(oneDeferred, 'resolve')
|
578
|
-
bothDeferred = up.util.resolvableWhen(oneDeferred)
|
579
|
-
|
580
|
-
bothDeferred.resolve()
|
581
|
-
bothDeferred.resolve()
|
582
|
-
|
583
|
-
expect(oneDeferred.resolve.calls.count()).toEqual(1)
|
584
|
-
|
585
|
-
describe 'bugfix against troublesome jQuery optimization if only one deferred is given', ->
|
586
|
-
|
587
|
-
it 'does not simply return the given deferred', ->
|
588
|
-
oneDeferred = $.Deferred()
|
589
|
-
whenDeferred = up.util.resolvableWhen(oneDeferred)
|
590
|
-
# This is what $.when returns if only passed a single argument
|
591
|
-
expect(whenDeferred).not.toBe(oneDeferred.promise())
|
592
|
-
# Cover eventual implementations
|
593
|
-
expect(whenDeferred).not.toBe(oneDeferred)
|
594
|
-
expect(whenDeferred.promise()).not.toBe(oneDeferred.promise())
|
595
|
-
expect(whenDeferred.promise()).not.toBe(oneDeferred)
|
596
|
-
|
597
|
-
it 'does not create an infinite loop if the given deferred is nested twice and the first nesting is resolved', ->
|
598
|
-
oneDeferred = $.Deferred()
|
599
|
-
firstNesting = up.util.resolvableWhen(oneDeferred)
|
600
|
-
secondNesting = up.util.resolvableWhen(firstNesting)
|
601
|
-
expect(-> firstNesting.resolve()).not.toThrowError()
|
602
|
-
|
603
517
|
describe 'up.util.requestDataAsArray', ->
|
604
518
|
|
605
519
|
it 'normalized null to an empty array', ->
|
@@ -678,112 +592,224 @@ describe 'up.util', ->
|
|
678
592
|
{ name: 'my=key', value: 'my=value' },
|
679
593
|
])
|
680
594
|
|
681
|
-
|
595
|
+
describe 'up.util.flatten', ->
|
596
|
+
|
597
|
+
it 'flattens the given array', ->
|
598
|
+
array = [1, [2, 3], 4]
|
599
|
+
expect(u.flatten(array)).toEqual([1, 2, 3, 4])
|
600
|
+
|
601
|
+
it 'only flattens one level deep for performance reasons', ->
|
602
|
+
array = [1, [2, [3,4]], 5]
|
603
|
+
expect(u.flatten(array)).toEqual([1, 2, [3, 4], 5])
|
604
|
+
|
605
|
+
describe 'up.util.renameKey', ->
|
606
|
+
|
607
|
+
it 'renames a key in the given property', ->
|
608
|
+
object = { a: 'a value', b: 'b value'}
|
609
|
+
u.renameKey(object, 'a', 'c')
|
610
|
+
expect(object.a).toBeUndefined()
|
611
|
+
expect(object.b).toBe('b value')
|
612
|
+
expect(object.c).toBe('a value')
|
613
|
+
|
614
|
+
describe 'up.util.selectInSubtree', ->
|
615
|
+
|
616
|
+
it 'finds the selector in ancestors and descendants of the given element', ->
|
617
|
+
$grandMother = affix('.grand-mother.match')
|
618
|
+
$mother = $grandMother.affix('.mother')
|
619
|
+
$element = $mother.affix('.element')
|
620
|
+
$child = $element.affix('.child.match')
|
621
|
+
$grandChild = $child.affix('.grand-child.match')
|
622
|
+
|
623
|
+
$matches = up.util.selectInSubtree($element, '.match')
|
624
|
+
$expected = $child.add($grandChild)
|
625
|
+
expect($matches).toEqual $expected
|
626
|
+
|
627
|
+
it 'finds the element itself if it matches the selector', ->
|
628
|
+
$element = affix('.element.match')
|
629
|
+
$matches = up.util.selectInSubtree($element, '.match')
|
630
|
+
expect($matches).toEqual $element
|
631
|
+
|
632
|
+
describe 'when given a jQuery collection with multiple elements', ->
|
633
|
+
|
634
|
+
it 'searches in a all subtrees of the given elements', ->
|
635
|
+
$a_grandMother = affix('.grand-mother.match')
|
636
|
+
$a_mother = $a_grandMother.affix('.mother')
|
637
|
+
$a_element = $a_mother.affix('.element')
|
638
|
+
$a_child = $a_element.affix('.child.match')
|
639
|
+
$a_grandChild = $a_child.affix('.grand-child.match')
|
640
|
+
|
641
|
+
$b_grandMother = affix('.grand-mother.match')
|
642
|
+
$b_mother = $b_grandMother.affix('.mother')
|
643
|
+
$b_element = $b_mother.affix('.element')
|
644
|
+
$b_child = $b_element.affix('.child.match')
|
645
|
+
$b_grandChild = $b_child.affix('.grand-child.match')
|
646
|
+
|
647
|
+
$matches = up.util.selectInSubtree($a_element.add($b_element), '.match')
|
648
|
+
expect($matches).toEqual $a_child.add($a_grandChild).add($b_child).add($b_grandChild)
|
649
|
+
|
650
|
+
|
651
|
+
describe 'up.util.selectInDynasty', ->
|
652
|
+
|
653
|
+
it 'finds the selector in both ancestors and descendants of the given element', ->
|
654
|
+
$grandMother = affix('.grand-mother.match')
|
655
|
+
$mother = $grandMother.affix('.mother')
|
656
|
+
$element = $mother.affix('.element')
|
657
|
+
$child = $element.affix('.child.match')
|
658
|
+
$grandChild = $child.affix('.grand-child.match')
|
659
|
+
|
660
|
+
$matches = up.util.selectInDynasty($element, '.match')
|
661
|
+
$expected = $grandMother.add($child).add($grandChild)
|
662
|
+
expect($matches).toEqual $expected
|
663
|
+
|
664
|
+
it 'finds the element itself if it matches the selector', ->
|
665
|
+
$element = affix('.element.match')
|
666
|
+
$matches = up.util.selectInDynasty($element, '.match')
|
667
|
+
expect($matches).toEqual $element
|
668
|
+
|
669
|
+
describe 'up.util.isCrossDomain', ->
|
670
|
+
|
671
|
+
it 'returns false for an absolute path', ->
|
672
|
+
expect(up.util.isCrossDomain('/foo')).toBe(false)
|
673
|
+
|
674
|
+
it 'returns false for an relative path', ->
|
675
|
+
expect(up.util.isCrossDomain('foo')).toBe(false)
|
676
|
+
|
677
|
+
it 'returns false for a fully qualified URL with the same protocol and hostname as the current location', ->
|
678
|
+
fullUrl = "#{location.protocol}//#{location.host}/foo"
|
679
|
+
expect(up.util.isCrossDomain(fullUrl)).toBe(false)
|
680
|
+
|
681
|
+
it 'returns true for a fully qualified URL with a different protocol than the current location', ->
|
682
|
+
fullUrl = "otherprotocol://#{location.host}/foo"
|
683
|
+
expect(up.util.isCrossDomain(fullUrl)).toBe(true)
|
684
|
+
|
685
|
+
it 'returns false for a fully qualified URL with a different hostname than the current location', ->
|
686
|
+
fullUrl = "#{location.protocol}//other-host.tld/foo"
|
687
|
+
expect(up.util.isCrossDomain(fullUrl)).toBe(true)
|
688
|
+
|
689
|
+
describe 'up.util.isOptions', ->
|
690
|
+
|
691
|
+
it 'returns true for an Object instance', ->
|
692
|
+
expect(up.util.isOptions(new Object())).toBe(true)
|
693
|
+
|
694
|
+
it 'returns true for an object literal', ->
|
695
|
+
expect(up.util.isOptions({ foo: 'bar'})).toBe(true)
|
696
|
+
|
697
|
+
it 'returns false for undefined', ->
|
698
|
+
expect(up.util.isOptions(undefined)).toBe(false)
|
699
|
+
|
700
|
+
it 'returns false for null', ->
|
701
|
+
expect(up.util.isOptions(null)).toBe(false)
|
702
|
+
|
703
|
+
it 'returns false for a function (which is technically an object)', ->
|
704
|
+
fn = -> 'foo'
|
705
|
+
fn.key = 'value'
|
706
|
+
expect(up.util.isOptions(fn)).toBe(false)
|
707
|
+
|
708
|
+
it 'returns false for an array', ->
|
709
|
+
expect(up.util.isOptions(['foo'])).toBe(false)
|
710
|
+
|
711
|
+
it 'returns false for a jQuery collection', ->
|
712
|
+
expect(up.util.isOptions($('body'))).toBe(false)
|
713
|
+
|
714
|
+
it 'returns false for a promise', ->
|
715
|
+
expect(up.util.isOptions(Promise.resolve())).toBe(false)
|
716
|
+
|
717
|
+
it 'returns false for a FormData object', ->
|
718
|
+
expect(up.util.isOptions(new FormData())).toBe(false)
|
719
|
+
|
720
|
+
describe 'up.util.isObject', ->
|
721
|
+
|
722
|
+
it 'returns true for an Object instance', ->
|
723
|
+
expect(up.util.isObject(new Object())).toBe(true)
|
682
724
|
|
683
|
-
|
684
|
-
|
685
|
-
expect(u.flatten(array)).toEqual([1, 2, 3, 4])
|
725
|
+
it 'returns true for an object literal', ->
|
726
|
+
expect(up.util.isObject({ foo: 'bar'})).toBe(true)
|
686
727
|
|
687
|
-
|
688
|
-
|
689
|
-
expect(u.flatten(array)).toEqual([1, 2, [3, 4], 5])
|
728
|
+
it 'returns false for undefined', ->
|
729
|
+
expect(up.util.isObject(undefined)).toBe(false)
|
690
730
|
|
691
|
-
|
731
|
+
it 'returns false for null', ->
|
732
|
+
expect(up.util.isObject(null)).toBe(false)
|
692
733
|
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
expect(object.b).toBe('b value')
|
698
|
-
expect(object.c).toBe('a value')
|
734
|
+
it 'returns true for a function (which is technically an object)', ->
|
735
|
+
fn = -> 'foo'
|
736
|
+
fn.key = 'value'
|
737
|
+
expect(up.util.isObject(fn)).toBe(true)
|
699
738
|
|
700
|
-
|
739
|
+
it 'returns true for an array', ->
|
740
|
+
expect(up.util.isObject(['foo'])).toBe(true)
|
701
741
|
|
702
|
-
|
703
|
-
|
704
|
-
$child1 = $container.affix('div.match')
|
705
|
-
$child2 = $container.affix('div')
|
706
|
-
$child2Child1 = $child2.affix('div.match')
|
707
|
-
matches = u.findWithSelf($container, '.match')
|
708
|
-
expect(matches).toEqual [$child1.get(0), $child2Child1.get(0)]
|
742
|
+
it 'returns true for a jQuery collection', ->
|
743
|
+
expect(up.util.isObject($('body'))).toBe(true)
|
709
744
|
|
710
|
-
|
711
|
-
|
712
|
-
$child1 = $container.affix('div')
|
713
|
-
$child1Child1 = $child1.affix('div.match')
|
714
|
-
matches = u.findWithSelf($container, '.match')
|
715
|
-
expect(matches).toEqual [$container.get(0), $child1Child1.get(0)]
|
745
|
+
it 'returns true for a promise', ->
|
746
|
+
expect(up.util.isObject(Promise.resolve())).toBe(true)
|
716
747
|
|
717
|
-
|
718
|
-
|
719
|
-
$child1 = $container.affix('div')
|
720
|
-
$child2 = $container.affix('div.match')
|
721
|
-
$child2Child1 = $child2.affix('div.match')
|
722
|
-
matches = u.findWithSelf($container, '.match')
|
723
|
-
expect(matches).toEqual [$container.get(0), $child2.get(0), $child2Child1.get(0)]
|
748
|
+
it 'returns true for a FormData object', ->
|
749
|
+
expect(up.util.isObject(new FormData())).toBe(true)
|
724
750
|
|
725
|
-
|
751
|
+
describe 'up.util.memoize', ->
|
726
752
|
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
753
|
+
it 'returns a function that calls the memoized function', ->
|
754
|
+
fun = (a, b) -> a + b
|
755
|
+
memoized = u.memoize(fun)
|
756
|
+
expect(memoized(2, 3)).toEqual(5)
|
731
757
|
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
758
|
+
it 'returns the cached return value of the first call when called again', ->
|
759
|
+
spy = jasmine.createSpy().and.returnValue(5)
|
760
|
+
memoized = u.memoize(spy)
|
761
|
+
expect(memoized(2, 3)).toEqual(5)
|
762
|
+
expect(memoized(2, 3)).toEqual(5)
|
763
|
+
expect(spy.calls.count()).toEqual(1)
|
738
764
|
|
739
|
-
|
765
|
+
['assign', 'assignPolyfill'].forEach (assignVariant) ->
|
740
766
|
|
741
|
-
|
767
|
+
describe "up.util.#{assignVariant}", ->
|
742
768
|
|
743
|
-
|
769
|
+
assign = up.util[assignVariant]
|
744
770
|
|
745
|
-
|
746
|
-
|
747
|
-
|
771
|
+
it 'copies the second object into the first object', ->
|
772
|
+
target = { a: 1 }
|
773
|
+
source = { b: 2, c: 3 }
|
748
774
|
|
749
|
-
|
775
|
+
assign(target, source)
|
750
776
|
|
751
|
-
|
777
|
+
expect(target).toEqual { a: 1, b: 2, c: 3 }
|
752
778
|
|
753
|
-
|
754
|
-
|
779
|
+
# Source is unchanged
|
780
|
+
expect(source).toEqual { b: 2, c: 3 }
|
755
781
|
|
756
|
-
|
757
|
-
|
758
|
-
|
782
|
+
it 'copies null property values', ->
|
783
|
+
target = { a: 1, b: 2 }
|
784
|
+
source = { b: null }
|
759
785
|
|
760
|
-
|
786
|
+
assign(target, source)
|
761
787
|
|
762
|
-
|
788
|
+
expect(target).toEqual { a: 1, b: null }
|
763
789
|
|
764
|
-
|
765
|
-
|
766
|
-
|
790
|
+
it 'copies undefined property values', ->
|
791
|
+
target = { a: 1, b: 2 }
|
792
|
+
source = { b: undefined }
|
767
793
|
|
768
|
-
|
794
|
+
assign(target, source)
|
769
795
|
|
770
|
-
|
796
|
+
expect(target).toEqual { a: 1, b: undefined }
|
771
797
|
|
772
|
-
|
773
|
-
|
774
|
-
|
798
|
+
it 'returns the first object', ->
|
799
|
+
target = { a: 1 }
|
800
|
+
source = { b: 2 }
|
775
801
|
|
776
|
-
|
802
|
+
result = assign(target, source)
|
777
803
|
|
778
|
-
|
804
|
+
expect(result).toBe(target)
|
779
805
|
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
806
|
+
it 'takes multiple sources to copy from', ->
|
807
|
+
target = { a: 1 }
|
808
|
+
source1 = { b: 2, c: 3 }
|
809
|
+
source2 = { d: 4, e: 5 }
|
784
810
|
|
785
|
-
|
811
|
+
assign(target, source1, source2)
|
786
812
|
|
787
|
-
|
813
|
+
expect(target).toEqual { a: 1, b: 2, c: 3, d: 4, e: 5 }
|
788
814
|
|
789
815
|
|