Skip to content

Commit c068d31

Browse files
sebmarkbagegaearon
authored andcommittedJan 23, 2019
Add unit tests for concurrent mode event dispatching (#14415)
1 parent db695c4 commit c068d31

File tree

1 file changed

+186
-0
lines changed

1 file changed

+186
-0
lines changed
 

Diff for: ‎packages/react-dom/src/__tests__/ReactDOMFiberAsync-test.internal.js

+186
Original file line numberDiff line numberDiff line change
@@ -491,5 +491,191 @@ describe('ReactDOMFiberAsync', () => {
491491
expect(container.textContent).toEqual('1');
492492
expect(returnValue).toBe(undefined);
493493
});
494+
495+
it('ignores discrete events on a pending removed element', () => {
496+
const disableButtonRef = React.createRef();
497+
const submitButtonRef = React.createRef();
498+
499+
let formSubmitted = false;
500+
501+
class Form extends React.Component {
502+
state = {active: true};
503+
disableForm = () => {
504+
this.setState({active: false});
505+
};
506+
submitForm = () => {
507+
formSubmitted = true; // This should not get invoked
508+
};
509+
render() {
510+
return (
511+
<div>
512+
<button onClick={this.disableForm} ref={disableButtonRef}>
513+
Disable
514+
</button>
515+
{this.state.active ? (
516+
<button onClick={this.submitForm} ref={submitButtonRef}>
517+
Submit
518+
</button>
519+
) : null}
520+
</div>
521+
);
522+
}
523+
}
524+
525+
const root = ReactDOM.unstable_createRoot(container);
526+
root.render(<Form />);
527+
// Flush
528+
jest.runAllTimers();
529+
530+
let disableButton = disableButtonRef.current;
531+
expect(disableButton.tagName).toBe('BUTTON');
532+
533+
// Dispatch a click event on the Disable-button.
534+
let firstEvent = document.createEvent('Event');
535+
firstEvent.initEvent('click', true, true);
536+
disableButton.dispatchEvent(firstEvent);
537+
538+
// There should now be a pending update to disable the form.
539+
540+
// This should not have flushed yet since it's in concurrent mode.
541+
let submitButton = submitButtonRef.current;
542+
expect(submitButton.tagName).toBe('BUTTON');
543+
544+
// In the meantime, we can dispatch a new client event on the submit button.
545+
let secondEvent = document.createEvent('Event');
546+
secondEvent.initEvent('click', true, true);
547+
// This should force the pending update to flush which disables the submit button before the event is invoked.
548+
submitButton.dispatchEvent(secondEvent);
549+
550+
// Therefore the form should never have been submitted.
551+
expect(formSubmitted).toBe(false);
552+
553+
expect(submitButtonRef.current).toBe(null);
554+
});
555+
556+
it('ignores discrete events on a pending removed event listener', () => {
557+
const disableButtonRef = React.createRef();
558+
const submitButtonRef = React.createRef();
559+
560+
let formSubmitted = false;
561+
562+
class Form extends React.Component {
563+
state = {active: true};
564+
disableForm = () => {
565+
this.setState({active: false});
566+
};
567+
submitForm = () => {
568+
formSubmitted = true; // This should not get invoked
569+
};
570+
disabledSubmitForm = () => {
571+
// The form is disabled.
572+
};
573+
render() {
574+
return (
575+
<div>
576+
<button onClick={this.disableForm} ref={disableButtonRef}>
577+
Disable
578+
</button>
579+
<button
580+
onClick={
581+
this.state.active ? this.submitForm : this.disabledSubmitForm
582+
}
583+
ref={submitButtonRef}>
584+
Submit
585+
</button>{' '}
586+
: null}
587+
</div>
588+
);
589+
}
590+
}
591+
592+
const root = ReactDOM.unstable_createRoot(container);
593+
root.render(<Form />);
594+
// Flush
595+
jest.runAllTimers();
596+
597+
let disableButton = disableButtonRef.current;
598+
expect(disableButton.tagName).toBe('BUTTON');
599+
600+
// Dispatch a click event on the Disable-button.
601+
let firstEvent = document.createEvent('Event');
602+
firstEvent.initEvent('click', true, true);
603+
disableButton.dispatchEvent(firstEvent);
604+
605+
// There should now be a pending update to disable the form.
606+
607+
// This should not have flushed yet since it's in concurrent mode.
608+
let submitButton = submitButtonRef.current;
609+
expect(submitButton.tagName).toBe('BUTTON');
610+
611+
// In the meantime, we can dispatch a new client event on the submit button.
612+
let secondEvent = document.createEvent('Event');
613+
secondEvent.initEvent('click', true, true);
614+
// This should force the pending update to flush which disables the submit button before the event is invoked.
615+
submitButton.dispatchEvent(secondEvent);
616+
617+
// Therefore the form should never have been submitted.
618+
expect(formSubmitted).toBe(false);
619+
});
620+
621+
it('uses the newest discrete events on a pending changed event listener', () => {
622+
const enableButtonRef = React.createRef();
623+
const submitButtonRef = React.createRef();
624+
625+
let formSubmitted = false;
626+
627+
class Form extends React.Component {
628+
state = {active: false};
629+
enableForm = () => {
630+
this.setState({active: true});
631+
};
632+
submitForm = () => {
633+
formSubmitted = true; // This should happen
634+
};
635+
render() {
636+
return (
637+
<div>
638+
<button onClick={this.enableForm} ref={enableButtonRef}>
639+
Enable
640+
</button>
641+
<button
642+
onClick={this.state.active ? this.submitForm : null}
643+
ref={submitButtonRef}>
644+
Submit
645+
</button>{' '}
646+
: null}
647+
</div>
648+
);
649+
}
650+
}
651+
652+
const root = ReactDOM.unstable_createRoot(container);
653+
root.render(<Form />);
654+
// Flush
655+
jest.runAllTimers();
656+
657+
let enableButton = enableButtonRef.current;
658+
expect(enableButton.tagName).toBe('BUTTON');
659+
660+
// Dispatch a click event on the Enable-button.
661+
let firstEvent = document.createEvent('Event');
662+
firstEvent.initEvent('click', true, true);
663+
enableButton.dispatchEvent(firstEvent);
664+
665+
// There should now be a pending update to enable the form.
666+
667+
// This should not have flushed yet since it's in concurrent mode.
668+
let submitButton = submitButtonRef.current;
669+
expect(submitButton.tagName).toBe('BUTTON');
670+
671+
// In the meantime, we can dispatch a new client event on the submit button.
672+
let secondEvent = document.createEvent('Event');
673+
secondEvent.initEvent('click', true, true);
674+
// This should force the pending update to flush which enables the submit button before the event is invoked.
675+
submitButton.dispatchEvent(secondEvent);
676+
677+
// Therefore the form should have been submitted.
678+
expect(formSubmitted).toBe(true);
679+
});
494680
});
495681
});

0 commit comments

Comments
 (0)
Please sign in to comment.