@@ -655,256 +655,6 @@ test.describe("ErrorBoundary", () => {
655
655
} ) ;
656
656
} ) ;
657
657
658
- test . describe ( "loaderData in ErrorBoundary" , ( ) => {
659
- let fixture : Fixture ;
660
- let appFixture : AppFixture ;
661
- let consoleErrors : string [ ] ;
662
- let oldConsoleError : ( ) => void ;
663
-
664
- test . beforeAll ( async ( ) => {
665
- fixture = await createFixture ( {
666
- files : {
667
- "app/root.tsx" : js `
668
- import { Links, Meta, Outlet, Scripts } from "react-router";
669
-
670
- export default function Root() {
671
- return (
672
- <html lang="en">
673
- <head>
674
- <Meta />
675
- <Links />
676
- </head>
677
- <body>
678
- <main>
679
- <Outlet />
680
- </main>
681
- <Scripts />
682
- </body>
683
- </html>
684
- );
685
- }
686
- ` ,
687
-
688
- "app/routes/parent.tsx" : js `
689
- import { Outlet, useLoaderData, useMatches, useRouteError } from "react-router";
690
-
691
- export function loader() {
692
- return "PARENT";
693
- }
694
-
695
- export default function () {
696
- return (
697
- <div>
698
- <p id="parent-data">{useLoaderData()}</p>
699
- <Outlet />
700
- </div>
701
- )
702
- }
703
-
704
- export function ErrorBoundary() {
705
- let error = useRouteError();
706
- return (
707
- <>
708
- <p id="parent-data">{useLoaderData()}</p>
709
- <p id="parent-matches-data">
710
- {useMatches().find(m => m.id === 'routes/parent').data}
711
- </p>
712
- <p id="parent-error">{error.message}</p>
713
- </>
714
- );
715
- }
716
- ` ,
717
-
718
- "app/routes/parent.child-with-boundary.tsx" : js `
719
- import { Form, useLoaderData, useRouteError } from "react-router";
720
-
721
- export function loader() {
722
- return "CHILD";
723
- }
724
-
725
- export function action() {
726
- throw new Error("Broken!");
727
- }
728
-
729
- export default function () {
730
- return (
731
- <>
732
- <p id="child-data">{useLoaderData()}</p>
733
- <Form method="post">
734
- <button type="submit" name="key" value="value">
735
- Submit
736
- </button>
737
- </Form>
738
- </>
739
- )
740
- }
741
-
742
- export function ErrorBoundary() {
743
- let error = useRouteError();
744
- return (
745
- <>
746
- <p id="child-data">{useLoaderData()}</p>
747
- <p id="child-error">{error.message}</p>
748
- </>
749
- );
750
- }
751
- ` ,
752
-
753
- "app/routes/parent.child-without-boundary.tsx" : js `
754
- import { Form, useLoaderData } from "react-router";
755
-
756
- export function loader() {
757
- return "CHILD";
758
- }
759
-
760
- export function action() {
761
- throw new Error("Broken!");
762
- }
763
-
764
- export default function () {
765
- return (
766
- <>
767
- <p id="child-data">{useLoaderData()}</p>
768
- <Form method="post">
769
- <button type="submit" name="key" value="value">
770
- Submit
771
- </button>
772
- </Form>
773
- </>
774
- )
775
- }
776
- ` ,
777
- } ,
778
- } ) ;
779
-
780
- appFixture = await createAppFixture ( fixture , ServerMode . Development ) ;
781
- } ) ;
782
-
783
- test . afterAll ( ( ) => {
784
- appFixture . close ( ) ;
785
- } ) ;
786
-
787
- test . beforeEach ( ( { page } ) => {
788
- oldConsoleError = console . error ;
789
- console . error = ( ) => { } ;
790
- consoleErrors = [ ] ;
791
- // Listen for all console events and handle errors
792
- page . on ( "console" , ( msg ) => {
793
- if ( msg . type ( ) === "error" ) {
794
- consoleErrors . push ( msg . text ( ) ) ;
795
- }
796
- } ) ;
797
- } ) ;
798
-
799
- test . afterEach ( ( ) => {
800
- console . error = oldConsoleError ;
801
- } ) ;
802
-
803
- test . describe ( "without JavaScript" , ( ) => {
804
- test . use ( { javaScriptEnabled : false } ) ;
805
- runBoundaryTests ( ) ;
806
- } ) ;
807
-
808
- test . describe ( "with JavaScript" , ( ) => {
809
- test . use ( { javaScriptEnabled : true } ) ;
810
- runBoundaryTests ( ) ;
811
- } ) ;
812
-
813
- function runBoundaryTests ( ) {
814
- test ( "Prevents useLoaderData in self ErrorBoundary" , async ( {
815
- page,
816
- javaScriptEnabled,
817
- } ) => {
818
- let app = new PlaywrightFixture ( appFixture , page ) ;
819
- await app . goto ( "/parent/child-with-boundary" ) ;
820
-
821
- expect ( await app . getHtml ( "#parent-data" ) ) . toEqual (
822
- '<p id="parent-data">PARENT</p>'
823
- ) ;
824
- expect ( await app . getHtml ( "#child-data" ) ) . toEqual (
825
- '<p id="child-data">CHILD</p>'
826
- ) ;
827
- expect ( consoleErrors ) . toEqual ( [ ] ) ;
828
-
829
- await app . clickSubmitButton ( "/parent/child-with-boundary" ) ;
830
- await page . waitForSelector ( "#child-error" ) ;
831
-
832
- expect ( await app . getHtml ( "#child-error" ) ) . toEqual (
833
- '<p id="child-error">Broken!</p>'
834
- ) ;
835
- expect ( await app . getHtml ( "#parent-data" ) ) . toEqual (
836
- '<p id="parent-data">PARENT</p>'
837
- ) ;
838
- expect ( await app . getHtml ( "#child-data" ) ) . toEqual (
839
- '<p id="child-data"></p>'
840
- ) ;
841
-
842
- // Only look for this message. Chromium browsers will also log the
843
- // network error but firefox does not
844
- // "Failed to load resource: the server responded with a status of 500 (Internal Server Error)",
845
- let msg =
846
- "You cannot `useLoaderData` in an errorElement (routeId: routes/parent.child-with-boundary)" ;
847
- if ( javaScriptEnabled ) {
848
- expect ( consoleErrors . filter ( ( m ) => m === msg ) ) . toEqual ( [ msg ] ) ;
849
- } else {
850
- // We don't get the useLoaderData message in the client when JS is disabled
851
- expect ( consoleErrors . filter ( ( m ) => m === msg ) ) . toEqual ( [ ] ) ;
852
- }
853
- } ) ;
854
-
855
- test ( "Prevents useLoaderData in bubbled ErrorBoundary" , async ( {
856
- page,
857
- javaScriptEnabled,
858
- } ) => {
859
- let app = new PlaywrightFixture ( appFixture , page ) ;
860
- await app . goto ( "/parent/child-without-boundary" ) ;
861
-
862
- expect ( await app . getHtml ( "#parent-data" ) ) . toEqual (
863
- '<p id="parent-data">PARENT</p>'
864
- ) ;
865
- expect ( await app . getHtml ( "#child-data" ) ) . toEqual (
866
- '<p id="child-data">CHILD</p>'
867
- ) ;
868
- expect ( consoleErrors ) . toEqual ( [ ] ) ;
869
-
870
- await app . clickSubmitButton ( "/parent/child-without-boundary" ) ;
871
- await page . waitForSelector ( "#parent-error" ) ;
872
-
873
- expect ( await app . getHtml ( "#parent-error" ) ) . toEqual (
874
- '<p id="parent-error">Broken!</p>'
875
- ) ;
876
- if ( javaScriptEnabled ) {
877
- // This data remains in single fetch with JS because we don't revalidate
878
- // due to the 500 action response
879
- expect ( await app . getHtml ( "#parent-matches-data" ) ) . toEqual (
880
- '<p id="parent-matches-data">PARENT</p>'
881
- ) ;
882
- } else {
883
- // But without JS document requests call all loaders up to the
884
- // boundary route so parent's data clears out
885
- expect ( await app . getHtml ( "#parent-matches-data" ) ) . toEqual (
886
- '<p id="parent-matches-data"></p>'
887
- ) ;
888
- }
889
- expect ( await app . getHtml ( "#parent-data" ) ) . toEqual (
890
- '<p id="parent-data"></p>'
891
- ) ;
892
-
893
- // Only look for this message. Chromium browsers will also log the
894
- // network error but firefox does not
895
- // "Failed to load resource: the server responded with a status of 500 (Internal Server Error)",
896
- let msg =
897
- "You cannot `useLoaderData` in an errorElement (routeId: routes/parent)" ;
898
- if ( javaScriptEnabled ) {
899
- expect ( consoleErrors . filter ( ( m ) => m === msg ) ) . toEqual ( [ msg ] ) ;
900
- } else {
901
- // We don't get the useLoaderData message in the client when JS is disabled
902
- expect ( consoleErrors . filter ( ( m ) => m === msg ) ) . toEqual ( [ ] ) ;
903
- }
904
- } ) ;
905
- }
906
- } ) ;
907
-
908
658
test . describe ( "Default ErrorBoundary" , ( ) => {
909
659
let fixture : Fixture ;
910
660
let appFixture : AppFixture ;
0 commit comments