Add unit tests for event bubbling in portals (#8509)
These bubble through the portal and up to the parent that rendered the portal.
Sebastian Markbåge committed
Dec 8, 2016 at 13:51 UTC
6c785ed5246997c6d2b6bc1a84177e94f413cb27
2 files changed
+110
scripts/fiber/tests-passing.txt
+2
@@ -524,6 +524,8 @@ src/renderers/dom/fiber/__tests__/ReactDOMFiber-test.js
524
* should update portal context if it changes due to setState
525
* should update portal context if it changes due to re-render
526
* findDOMNode should find dom element after expanding a fragment
527
+* should bubble events from the portal to the parent
528
+* should not onMouseLeave when staying in the portal
529
530
src/renderers/dom/shared/__tests__/CSSProperty-test.js
531
* should generate browser prefixes for its `isUnitlessNumber`
src/renderers/dom/fiber/__tests__/ReactDOMFiber-test.js
+108
@@ -14,6 +14,7 @@
14
var React = require('React');
15
var ReactDOM = require('ReactDOM');
16
var ReactDOMFeatureFlags = require('ReactDOMFeatureFlags');
17
+var ReactTestUtils = require('ReactTestUtils');
18
19
describe('ReactDOMFiber', () => {
20
var container;
@@ -773,5 +774,112 @@ describe('ReactDOMFiber', () => {
774
var b = ReactDOM.findDOMNode(myNodeB);
775
expect(b.tagName).toBe('SPAN');
776
});
777
+
778
+ it('should bubble events from the portal to the parent', () => {
779
+ var portalContainer = document.createElement('div');
780
+
781
+ var ops = [];
782
+ var portal = null;
783
+
784
+ ReactDOM.render(
785
+ <div onClick={() => ops.push('parent clicked')}>
786
+ {ReactDOM.unstable_createPortal(
787
+ <div onClick={() => ops.push('portal clicked')} ref={n => portal = n}>
788
+ portal
789
+ </div>,
790
+ portalContainer
791
+ )}
792
+ </div>,
793
+ container
794
+ );
795
+
796
+ expect(portal.tagName).toBe('DIV');
797
+
798
+ var fakeNativeEvent = {};
799
+ ReactTestUtils.simulateNativeEventOnNode(
800
+ 'topClick',
801
+ portal,
802
+ fakeNativeEvent
803
+ );
804
+
805
+ expect(ops).toEqual([
806
+ 'portal clicked',
807
+ 'parent clicked',
808
+ ]);
809
+ });
810
+
811
+ it('should not onMouseLeave when staying in the portal', () => {
812
+ var portalContainer = document.createElement('div');
813
+
814
+ var ops = [];
815
+ var firstTarget = null;
816
+ var secondTarget = null;
817
+ var thirdTarget = null;
818
+
819
+ function simulateMouseMove(from, to) {
820
+ if (from) {
821
+ ReactTestUtils.simulateNativeEventOnNode(
822
+ 'topMouseOut',
823
+ from,
824
+ {
825
+ target: from,
826
+ relatedTarget: to,
827
+ }
828
+ );
829
+ }
830
+ if (to) {
831
+ ReactTestUtils.simulateNativeEventOnNode(
832
+ 'topMouseOver',
833
+ to,
834
+ {
835
+ target: to,
836
+ relatedTarget: from,
837
+ }
838
+ );
839
+ }
840
+ }
841
+
842
+ ReactDOM.render(
843
+ <div>
844
+ <div
845
+ onMouseEnter={() => ops.push('enter parent')}
846
+ onMouseLeave={() => ops.push('leave parent')}>
847
+ <div ref={n => firstTarget = n} />
848
+ {ReactDOM.unstable_createPortal(
849
+ <div
850
+ onMouseEnter={() => ops.push('enter portal')}
851
+ onMouseLeave={() => ops.push('leave portal')}
852
+ ref={n => secondTarget = n}>
853
+ portal
854
+ </div>,
855
+ portalContainer
856
+ )}
857
+ </div>
858
+ <div ref={n => thirdTarget = n} />
859
+ </div>,
860
+ container
861
+ );
862
+
863
+ simulateMouseMove(null, firstTarget);
864
+ expect(ops).toEqual([
865
+ 'enter parent',
866
+ ]);
867
+
868
+ ops = [];
869
+
870
+ simulateMouseMove(firstTarget, secondTarget);
871
+ expect(ops).toEqual([
872
+ // Parent did not invoke leave because we're still inside the portal.
873
+ 'enter portal',
874
+ ]);
875
+
876
+ ops = [];
877
+
878
+ simulateMouseMove(secondTarget, thirdTarget);
879
+ expect(ops).toEqual([
880
+ 'leave portal',
881
+ 'leave parent', // Only when we leave the portal does onMouseLeave fire.
882
+ ]);
883
+ });
884
}
885
});