sprae 5.2.0 → 6.0.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.
@@ -6,16 +6,6 @@ import sprae from '../src/index.js'
6
6
  import h from 'hyperf'
7
7
 
8
8
 
9
- Object.defineProperty(DocumentFragment.prototype, 'outerHTML', {
10
- get() {
11
- let s = ''
12
- this.childNodes.forEach(n => {
13
- s += n.nodeType === 3 ? n.textContent : n.outerHTML != null ? n.outerHTML : ''
14
- })
15
- return s
16
- }
17
- })
18
-
19
9
  test.skip('autoinit', async () => {
20
10
  is(window.x.innerHTML, '1')
21
11
  })
@@ -447,10 +437,10 @@ test('each: loop within condition', async () => {
447
437
 
448
438
  const params = sprae(el, { a: 1 })
449
439
 
450
- is(el.innerHTML, '<x><y>1</y></x>')
440
+ is(el.innerHTML, '<x><y>0</y></x>')
451
441
  params.a = 2
452
442
  await tick()
453
- is(el.innerHTML, '<x><y>-1</y><y>-2</y></x>')
443
+ is(el.innerHTML, '<x><y>0</y><y>-1</y></x>')
454
444
  params.a = 0
455
445
  await tick()
456
446
  is(el.innerHTML, '')
@@ -481,7 +471,7 @@ test('each: next items have own "this", not single one', async () => {
481
471
  let el = h`<div><x :each="x in 3" :data-x="x" :x="log.push(x, this.dataset.x)"></x></div>`
482
472
  let log = []
483
473
  let state = sprae(el, {log})
484
- is(state.log, [1,'1',2,'2',3,'3'])
474
+ is(state.log, [0,'0',1,'1',2,'2'])
485
475
  })
486
476
 
487
477
  test('each: unkeyed', async () => {
@@ -520,7 +510,7 @@ test('each: keyed', async () => {
520
510
  test('each: wrapped source', async () => {
521
511
  let el = h`<div><x :each="i in (x || 2)" :text="i"></x></div>`
522
512
  sprae(el, {x:0})
523
- is(el.innerHTML, `<x>1</x><x>2</x>`)
513
+ is(el.innerHTML, `<x>0</x><x>1</x>`)
524
514
  })
525
515
 
526
516
  test('each: unmounted elements remove listeners', async () => {
@@ -564,316 +554,10 @@ test('each: key-based caching is in-sync with direct elements', () => {
564
554
  is(el.outerHTML, el2.outerHTML)
565
555
  })
566
556
 
567
- test('on: base', async () => {
568
- let el = h`<div :on="{click(e){log.push('click')}, x}"></div>`
569
- let log = []
570
- let params = sprae(el, {x(){log.push('x')}, log})
571
-
572
- is(el.outerHTML, `<div></div>`);
573
- el.dispatchEvent(new window.Event('click'));
574
- is(log, ['click'])
575
- el.dispatchEvent(new window.Event('x'));
576
- is(log, ['click','x'])
577
-
578
- params.x = function(){log.push('xx')}
579
- await tick()
580
- el.dispatchEvent(new window.Event('x'));
581
- is(log, ['click','x','xx']);
582
-
583
- console.log('make null')
584
- params.x = null;
585
- await tick()
586
- el.dispatchEvent(new window.Event('x'));
587
- is(log, ['click','x','xx']);
588
- })
589
-
590
- test('onevt: this context', e => {
591
- let el = h`<div :onx="function(){log.push(this)}"></div>`
592
- let state = sprae(el, {log: []})
593
- el.dispatchEvent(new window.Event('x'));
594
- is(state.log, [el])
595
- })
596
-
597
- test('on: this in chains refers to el', () => {
598
- let el = h`<div :ona..onb="function(e){x=this; log.push(1); return () => log.push(2)}"></div>`
599
- let state = sprae(el, {log:[], x:null})
600
- el.dispatchEvent(new window.Event('a'));
601
- is(state.log, [1])
602
- })
603
-
604
- test('on: multiple events', e => {
605
- let el = h`<div :onscroll:onclick:onx="e=>log.push(e.type)"></div>`
606
- let state = sprae(el, {log:[]})
607
-
608
- el.dispatchEvent(new window.Event('click'));
609
- is(state.log, ['click'])
610
- el.dispatchEvent(new window.Event('scroll'));
611
- is(state.log, ['click','scroll'])
612
- el.dispatchEvent(new window.Event('x'));
613
- is(state.log, ['click','scroll','x'])
614
- })
615
-
616
- test('on: in-out events', e => {
617
- // let el = document.createElement('x');
618
- // el.setAttribute(':onmousedown..onmouseup', 'e=>(log.push(e.type),e=>log.push(e.type))')
619
- let el = h`<x :onmousedown..onmouseup="(e) => { x=this; log.push(e.type); return e=>log.push(e.type); }"></x>`
620
-
621
- let state = sprae(el, {log:[],x:null})
622
- el.dispatchEvent(new window.Event('mousedown'));
623
- is(state.x, el);
624
- is(state.log, ['mousedown'])
625
- el.dispatchEvent(new window.Event('mouseup'));
626
- is(state.log, ['mousedown','mouseup'])
627
- })
628
-
629
- test('on: in-out side-effects', e => {
630
- let log = []
631
-
632
- // 1. skip in event and do directly out
633
- let el = h`<x :onin..onout="io"></x>`
634
- sprae(el, { io(e) {
635
- log.push(e.type)
636
- return (e) => (log.push(e.type), [1,2,3])
637
- } })
638
-
639
- el.dispatchEvent(new window.Event('out'));
640
- is(log, [])
641
-
642
- // 2. Some nonsensical return is fine
643
- el.dispatchEvent(new window.Event('in'));
644
- is(log, ['in'])
645
- el.dispatchEvent(new window.Event('out'));
646
- is(log, ['in','out'], 'out triggers right')
647
- el.dispatchEvent(new window.Event('out'));
648
- is(log, ['in','out'])
649
- el.dispatchEvent(new window.Event('in'));
650
- is(log, ['in','out','in'])
651
- el.dispatchEvent(new window.Event('in'));
652
- is(log, ['in','out','in', 'in'])
653
- el.dispatchEvent(new window.Event('out'));
654
- is(log, ['in','out','in','in','out','out'])
655
- el.dispatchEvent(new window.Event('out'));
656
- is(log, ['in','out','in','in','out','out'])
657
- })
658
-
659
- test('on: chain of events', e => {
660
- let el = h`<div :onmousedown..onmousemove..onmouseup="e=>(log.push(e.type),e=>(log.push(e.type),e=>log.push(e.type)))"></div>`
661
- let state = sprae(el, {log:[]})
662
-
663
- el.dispatchEvent(new window.Event('mousedown'));
664
- is(state.log, ['mousedown'])
665
- el.dispatchEvent(new window.Event('mousemove'));
666
- is(state.log, ['mousedown','mousemove'])
667
- el.dispatchEvent(new window.Event('mouseup'));
668
- is(state.log, ['mousedown','mousemove','mouseup'])
669
- el.dispatchEvent(new window.Event('mouseup'));
670
- is(state.log, ['mousedown','mousemove','mouseup'])
671
- el.dispatchEvent(new window.Event('mousedown'));
672
- is(state.log, ['mousedown','mousemove','mouseup','mousedown'])
673
- })
674
-
675
- test('on: parallel chains', e => {
676
- let el = h`<div :onx..ony..onz="e=>('x',log.push(e.type),e=>('y',log.push(e.type),e=>('z',log.push(e.type))))"></div>`
677
- let state = sprae(el, {log:[]})
678
-
679
- console.log('emit x')
680
- el.dispatchEvent(new window.Event('x'));
681
- is(state.log, ['x'])
682
- console.log('emit x')
683
- el.dispatchEvent(new window.Event('x'));
684
- is(state.log, ['x','x'])
685
- console.log('emit y')
686
- el.dispatchEvent(new window.Event('y'));
687
- is(state.log, ['x','x','y','y'])
688
- console.log('emit y')
689
- el.dispatchEvent(new window.Event('y'));
690
- is(state.log, ['x','x','y','y'])
691
- console.log('emit z')
692
- el.dispatchEvent(new window.Event('z'));
693
- console.log('emit y')
694
- el.dispatchEvent(new window.Event('y'));
695
- is(state.log, ['x','x','y','y','z','z'])
696
- el.dispatchEvent(new window.Event('z'));
697
- is(state.log, ['x','x','y','y','z','z']);
698
- el.dispatchEvent(new window.Event('x'));
699
- is(state.log, ['x','x','y','y','z','z','x']);
700
- })
701
-
702
- test('on: state changes between chain of events', async e => {
703
- let el = h`<x :on="{'x..y':fn}"></x>`
704
- let log = []
705
- let state = sprae(el, {log, fn: () => (log.push('x1'), ()=>log.push('y1'))})
706
- console.log('emit x')
707
- el.dispatchEvent(new window.Event('x'));
708
- is(log, ['x1'])
709
- console.log('update fn')
710
- state.fn = () => (log.push('x2'), () => log.push('y2'))
711
- await tick()
712
- is(log, ['x1'])
713
- // console.log('xx')
714
- // NOTE: state update registers new chain listener before finishing prev chain
715
- // el.dispatchEvent(new window.Event('x'));
716
- // el.dispatchEvent(new window.Event('x'));
717
- // is(log, [1])
718
- console.log('emit y, y')
719
- el.dispatchEvent(new window.Event('y'));
720
- el.dispatchEvent(new window.Event('y'));
721
- is(log, ['x1', 'y1'])
722
- console.log('emit x')
723
- el.dispatchEvent(new window.Event('x'));
724
- is(log, ['x1','y1','x2'])
725
- console.log('emit y, y')
726
- el.dispatchEvent(new window.Event('y'));
727
- el.dispatchEvent(new window.Event('y'));
728
- is(log, ['x1','y1','x2','y2'])
729
- })
730
-
731
- test('on: once', e => {
732
- // NOTE: if callback updates it's still rebound
733
- let el = h`<x :onx.once="(e=>x&&log.push(this))" ></x>`
734
- let log = []
735
- let state = sprae(el, {log, x:1})
736
- el.dispatchEvent(new window.Event('x'));
737
- is(log, [el])
738
- el.dispatchEvent(new window.Event('x'));
739
- is(log, [el])
740
- state.x = 2
741
- el.dispatchEvent(new window.Event('x'));
742
- el.dispatchEvent(new window.Event('x'));
743
- is(log, [el])
744
- })
745
-
746
- test('on: capture, stop, prevent', e => {
747
- let el = h`<x :onx.capture="e=>log.push(1)"><y :onx="e=>log.push(2)"></y></x>`
748
- let state = sprae(el, {log:[]})
749
- el.firstChild.dispatchEvent(new window.Event('x', {bubbles:true}));
750
- is(state.log, [1,2])
751
-
752
- let el2 = h`<x :onx="e=>log.push(1)"><y :onx.stop="e=>log.push(2)"></y></x>`
753
- let state2 = sprae(el2, {log:[]})
754
- el2.firstChild.dispatchEvent(new window.Event('x', {bubbles:true}));
755
- is(state2.log, [2])
756
- })
757
-
758
- test('on: window, self', e => {
759
- let el = h`<x :onx.self="e=>log.push(1)"><y :onx.window="e=>log.push(2)"></y></x>`
760
- let state = sprae(el, {log:[]})
761
- el.firstChild.dispatchEvent(new window.Event('x', {bubbles:true}));
762
- is(state.log, [])
763
- el.dispatchEvent(new window.Event('x', {bubbles:true}));
764
- is(state.log, [1])
765
- window.dispatchEvent(new window.Event('x', {bubbles:true}));
766
- is(state.log, [1,2])
767
- })
768
-
769
- test('on: keys', e => {
770
- let el = h`<x :onkeydown.enter="e=>log.push(1)"></x>`
771
- let state = {log:[]}
772
- sprae(el, state)
773
- el.dispatchEvent(new window.KeyboardEvent('keydown', { key: '' }));
774
- is(state.log,[])
775
- el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'Enter' }));
776
- el.dispatchEvent(new window.KeyboardEvent('keydown', { key: '' }));
777
- is(state.log,[1])
778
- el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'Enter' }));
779
- is(state.log,[1,1])
780
- })
781
-
782
- test('on: key combinations', e => {
783
- let el = h`<x :onkeydown.ctrl-enter="e=>log.push(1)"></x>`
784
- let state = {log:[]}
785
- sprae(el, state)
786
- el.dispatchEvent(new window.KeyboardEvent('keydown', { key: '' }));
787
- is(state.log,[])
788
- el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'Enter' }));
789
- el.dispatchEvent(new window.KeyboardEvent('keydown', { key: '' }));
790
- is(state.log,[])
791
- el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'Enter', ctrlKey: true }));
792
- el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'Enter' }));
793
- is(state.log,[1])
794
- el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'Enter' }));
795
- el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'Enter', ctrlKey: true }));
796
- is(state.log,[1,1])
797
- let el2 = h`<x :onkeydown.ctrl-alt-enter="e=>log.push(1)"></x>`
798
- })
799
-
800
- test('on: keys with prevent', e => {
801
- let el = h`<y :onkeydown="e=>log.push(e.key)"><x :ref="x" :onkeydown.enter.stop></x></y>`
802
- let state = sprae(el, {log:[]})
803
- state.x.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'x', bubbles: true }));
804
- console.log('enter')
805
- state.x.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'Enter', bubbles: true }));
806
- is(state.log,['x'])
807
- })
808
-
809
- test('on: debounce', async e => {
810
- let el = h`<x :onkeydown.debounce-1="e=>log.push(e.key)"></x>`
811
- let state = sprae(el, {log:[]})
812
- el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'x', bubbles: true }));
813
- is(state.log, [])
814
- await time(2)
815
- is(state.log, ['x'])
816
- })
817
-
818
- test('on: debounce 0', async e => {
819
- let el = h`<x :onkeydown.debounce-0="e=>log.push(e.key)"></x>`
820
- let state = sprae(el, {log:[]})
821
- el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'x', bubbles: true }));
822
- is(state.log, [])
823
- await time(2)
824
- is(state.log, ['x'])
825
- })
826
-
827
- test('on: throttle', async e => {
828
- let el = h`<x :onkeydown.throttle-10="e=>log.push(e.key)"></x>`
829
- let state = sprae(el, {log:[]})
830
- el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'x', bubbles: true }));
831
- el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'x', bubbles: true }));
832
- is(state.log, ['x'])
833
- await time(5)
834
- el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'x', bubbles: true }));
835
- is(state.log, ['x'])
836
- await time(10)
837
- is(state.log, ['x', 'x'])
838
- await time(10)
839
- is(state.log, ['x', 'x'])
840
- el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'x', bubbles: true }));
841
- is(state.log, ['x', 'x', 'x'])
842
- })
843
-
844
- test('on: toggle', async e => {
845
- let el = h`<x :onx.toggle="e=>(log.push(1),e=>log.push(2))"></x>`
846
- let state = sprae(el, {log:[]})
847
- el.dispatchEvent(new window.KeyboardEvent('x'));
848
- is(state.log, [1])
849
- el.dispatchEvent(new window.KeyboardEvent('x'));
850
- is(state.log, [1,2])
851
- el.dispatchEvent(new window.KeyboardEvent('x'));
852
- is(state.log, [1,2,1])
853
- el.dispatchEvent(new window.KeyboardEvent('x'));
854
- is(state.log, [1,2,1,2])
855
- })
856
-
857
- test.skip('on: nexttick', async e => {
858
- let el = h`<x :onkeydown.nexttick="e=>log.push(e.key)"></x>`
859
- let state = sprae(el, {log:[]})
860
- el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'x', bubbles: true }));
861
- el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'x', bubbles: true }));
862
- is(state.log, [])
863
- await time()
864
- is(state.log, ['x', 'x'])
865
- })
866
-
867
- test('on: modifiers chain', async e => {
868
- let el = h`<x :onkeydown.letter..onkeyup.letter="e=>(log.push(e.key),(e)=>log.push(e.key))"></x>`
869
- let state = sprae(el, {log:[]})
870
- el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'x', bubbles: true }));
871
- el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'Enter', bubbles: true }));
872
- is(state.log,['x'])
873
- el.dispatchEvent(new window.KeyboardEvent('keyup', { key: 'Enter', bubbles: true }));
874
- is(state.log,['x'])
875
- el.dispatchEvent(new window.KeyboardEvent('keyup', { key: 'x', bubbles: true }));
876
- is(state.log,['x', 'x'])
557
+ test('each: with :with', () => {
558
+ let el = h`<ul><li :each="i in 3" :with="{x:i}" :text="x"></li></ul>`
559
+ sprae(el)
560
+ is(el.outerHTML, `<ul><li>0</li><li>1</li><li>2</li></ul>`)
877
561
  })
878
562
 
879
563
  test('with: inline', async () => {
@@ -923,7 +607,7 @@ test.skip('with: reactive transparency', () => {
923
607
  is(el.innerHTML, `<y>13</y>`)
924
608
  })
925
609
  test('with: writes to state', async () => {
926
- let a = h`<x :with="{a:1}"><y :on="{x(){a++}}" :text="a"></y></x>`
610
+ let a = h`<x :with="{a:1}"><y :onx="e=>a++" :text="a"></y></x>`
927
611
  sprae(a)
928
612
  is(a.innerHTML, `<y>1</y>`)
929
613
  a.firstChild.dispatchEvent(new window.Event('x'))
package/test/events.js ADDED
@@ -0,0 +1,138 @@
1
+ // import { signal } from 'usignal/sync'
2
+ import test, {is, any, throws} from 'tst'
3
+ import {tick, time} from 'wait-please'
4
+ import sprae from '../src/index.js'
5
+ import h from 'hyperf'
6
+
7
+
8
+ test('events: this context', e => {
9
+ let el = h`<div @x="log.push(this)"></div>`
10
+ let state = sprae(el, {log: []})
11
+ el.dispatchEvent(new window.Event('x'));
12
+ is(state.log, [el])
13
+ })
14
+
15
+ test('events: multiple events', e => {
16
+ let el = h`<div @scroll@click@x="log.push(event.type)"></div>`
17
+ let state = sprae(el, {log:[]})
18
+
19
+ el.dispatchEvent(new window.Event('click'));
20
+ is(state.log, ['click'])
21
+ el.dispatchEvent(new window.Event('scroll'));
22
+ is(state.log, ['click','scroll'])
23
+ el.dispatchEvent(new window.Event('x'));
24
+ is(state.log, ['click','scroll','x'])
25
+ })
26
+
27
+ test('events: once', e => {
28
+ // NOTE: if callback updates it's still rebound
29
+ let el = h`<x @x.once="(x&&log.push(this))" ></x>`
30
+ let log = []
31
+ let state = sprae(el, {log, x:1})
32
+ el.dispatchEvent(new window.Event('x'));
33
+ is(log, [el])
34
+ el.dispatchEvent(new window.Event('x'));
35
+ is(log, [el])
36
+ state.x = 2
37
+ el.dispatchEvent(new window.Event('x'));
38
+ el.dispatchEvent(new window.Event('x'));
39
+ is(log, [el])
40
+ })
41
+
42
+ test('events: capture, stop, prevent', e => {
43
+ let el = h`<x @x.capture="log.push(1)"><y @x="log.push(2)"></y></x>`
44
+ let state = sprae(el, {log:[]})
45
+ el.firstChild.dispatchEvent(new window.Event('x', {bubbles:true}));
46
+ is(state.log, [1,2])
47
+
48
+ let el2 = h`<x @x="log.push(1)"><y @x.stop="log.push(2)"></y></x>`
49
+ let state2 = sprae(el2, {log:[]})
50
+ el2.firstChild.dispatchEvent(new window.Event('x', {bubbles:true}));
51
+ is(state2.log, [2])
52
+ })
53
+
54
+ test('events: window, self', e => {
55
+ let el = h`<x @x.self="log.push(1)"><y @x.window="log.push(2)"></y></x>`
56
+ let state = sprae(el, {log:[]})
57
+ el.firstChild.dispatchEvent(new window.Event('x', {bubbles:true}));
58
+ is(state.log, [])
59
+ el.dispatchEvent(new window.Event('x', {bubbles:true}));
60
+ is(state.log, [1])
61
+ window.dispatchEvent(new window.Event('x', {bubbles:true}));
62
+ is(state.log, [1,2])
63
+ })
64
+
65
+ test('events: keys', e => {
66
+ let el = h`<x @keydown.enter="log.push(1)"></x>`
67
+ let state = {log:[]}
68
+ sprae(el, state)
69
+ el.dispatchEvent(new window.KeyboardEvent('keydown', { key: '' }));
70
+ is(state.log,[])
71
+ el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'Enter' }));
72
+ el.dispatchEvent(new window.KeyboardEvent('keydown', { key: '' }));
73
+ is(state.log,[1])
74
+ el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'Enter' }));
75
+ is(state.log,[1,1])
76
+ })
77
+
78
+ test('events: key combinations', e => {
79
+ let el = h`<x @keydown.ctrl-enter="log.push(1)"></x>`
80
+ let state = {log:[]}
81
+ sprae(el, state)
82
+ el.dispatchEvent(new window.KeyboardEvent('keydown', { key: '' }));
83
+ is(state.log,[])
84
+ el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'Enter' }));
85
+ el.dispatchEvent(new window.KeyboardEvent('keydown', { key: '' }));
86
+ is(state.log,[])
87
+ el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'Enter', ctrlKey: true }));
88
+ el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'Enter' }));
89
+ is(state.log,[1])
90
+ el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'Enter' }));
91
+ el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'Enter', ctrlKey: true }));
92
+ is(state.log,[1,1])
93
+ let el2 = h`<x @keydown.ctrl-alt-enter="log.push(1)"></x>`
94
+ })
95
+
96
+ test('events: keys with prevent', e => {
97
+ let el = h`<y @keydown="log.push(event.key)"><x :ref="x" @keydown.enter.stop></x></y>`
98
+ let state = sprae(el, {log:[]})
99
+ state.x.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'x', bubbles: true }));
100
+ console.log('enter')
101
+ state.x.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'Enter', bubbles: true }));
102
+ is(state.log,['x'])
103
+ })
104
+
105
+ test('events: debounce', async e => {
106
+ let el = h`<x @keydown.debounce-1="log.push(event.key)"></x>`
107
+ let state = sprae(el, {log:[]})
108
+ el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'x', bubbles: true }));
109
+ is(state.log, [])
110
+ await time(2)
111
+ is(state.log, ['x'])
112
+ })
113
+
114
+ test('events: debounce 0', async e => {
115
+ let el = h`<x @keydown.debounce-0="log.push(event.key)"></x>`
116
+ let state = sprae(el, {log:[]})
117
+ el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'x', bubbles: true }));
118
+ is(state.log, [])
119
+ await time(2)
120
+ is(state.log, ['x'])
121
+ })
122
+
123
+ test('events: throttle', async e => {
124
+ let el = h`<x @keydown.throttle-10="log.push(event.key)"></x>`
125
+ let state = sprae(el, {log:[]})
126
+ el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'x', bubbles: true }));
127
+ el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'x', bubbles: true }));
128
+ is(state.log, ['x'])
129
+ await time(5)
130
+ el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'x', bubbles: true }));
131
+ is(state.log, ['x'])
132
+ await time(10)
133
+ is(state.log, ['x', 'x'])
134
+ await time(10)
135
+ is(state.log, ['x', 'x'])
136
+ el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'x', bubbles: true }));
137
+ is(state.log, ['x', 'x', 'x'])
138
+ })
package/test/test.js CHANGED
@@ -1,2 +1,13 @@
1
1
  import './state.js'
2
- import './dom.js'
2
+ import './attrs.js'
3
+ import './events.js'
4
+
5
+ Object.defineProperty(DocumentFragment.prototype, 'outerHTML', {
6
+ get() {
7
+ let s = ''
8
+ this.childNodes.forEach(n => {
9
+ s += n.nodeType === 3 ? n.textContent : n.outerHTML != null ? n.outerHTML : ''
10
+ })
11
+ return s
12
+ }
13
+ })
package/todo.md CHANGED
@@ -50,4 +50,5 @@
50
50
  * [x] Autorun
51
51
  * [x] There's some bug with prostogreen not triggering effect. (caused by special array.length case)
52
52
  * [x] Getters must become evaluable
53
- * [ ] `:with="{likes:[], like(){ /* likes should not be undefined here */ }}"`
53
+ * [ ] `:with="{likes:[], like(){ /* likes should not be undefined here */ }}"`
54
+ * [ ] `<li :each="item in items" :with="{collapsed:true}"><button :onclick='e=>collapsed=false'></li>`