@@ -87,7 +87,7 @@ public void ProgrammaticNavigationToNotExistingPathReExecutesTo404(bool streamin
8787 {
8888 string streamingPath = streaming ? "-streaming" : "" ;
8989 Navigate ( $ "{ ServerPathBase } /reexecution/redirection-not-found-ssr{ streamingPath } ?navigate-programmatically=true") ;
90- Assert404ReExecuted ( ) ;
90+ AssertReExecutionPageRendered ( ) ;
9191 }
9292
9393 [ Theory ]
@@ -98,7 +98,7 @@ public void LinkNavigationToNotExistingPathReExecutesTo404(bool streaming)
9898 string streamingPath = streaming ? "-streaming" : "" ;
9999 Navigate ( $ "{ ServerPathBase } /reexecution/redirection-not-found-ssr{ streamingPath } ") ;
100100 Browser . Click ( By . Id ( "link-to-not-existing-page" ) ) ;
101- Assert404ReExecuted ( ) ;
101+ AssertReExecutionPageRendered ( ) ;
102102 }
103103
104104 [ Theory ]
@@ -111,40 +111,175 @@ public void BrowserNavigationToNotExistingPathReExecutesTo404(bool streaming)
111111 // will not be activated, see configuration in Startup
112112 string streamingPath = streaming ? "-streaming" : "" ;
113113 Navigate ( $ "{ ServerPathBase } /reexecution/not-existing-page-ssr{ streamingPath } ") ;
114- Assert404ReExecuted ( ) ;
114+ AssertReExecutionPageRendered ( ) ;
115115 }
116116
117- private void Assert404ReExecuted ( ) =>
117+ private void AssertReExecutionPageRendered ( ) =>
118118 Browser . Equal ( "Welcome On Page Re-executed After Not Found Event" , ( ) => Browser . Exists ( By . Id ( "test-info" ) ) . Text ) ;
119119
120+ private void AssertNotFoundPageRendered ( )
121+ {
122+ Browser . Equal ( "Welcome On Custom Not Found Page" , ( ) => Browser . FindElement ( By . Id ( "test-info" ) ) . Text ) ;
123+ // custom page should have a custom layout
124+ Browser . Equal ( "About" , ( ) => Browser . FindElement ( By . Id ( "about-link" ) ) . Text ) ;
125+ }
126+
127+ private void AssertUrlNotChanged ( string expectedUrl ) =>
128+ Browser . True ( ( ) => Browser . Url . Contains ( expectedUrl ) , $ "Expected URL to contain '{ expectedUrl } ', but found '{ Browser . Url } '") ;
129+
130+ private void AssertUrlChanged ( string urlPart ) =>
131+ Browser . False ( ( ) => Browser . Url . Contains ( urlPart ) , $ "Expected URL not to contain '{ urlPart } ', but found '{ Browser . Url } '") ;
132+
120133 [ Theory ]
121- [ InlineData ( true ) ]
122- [ InlineData ( false ) ]
123- public void CanRenderNotFoundPage ( bool streamingStarted )
134+ [ InlineData ( true , true ) ]
135+ [ InlineData ( true , false ) ]
136+ [ InlineData ( false , true ) ]
137+ [ InlineData ( false , false ) ]
138+ // When response has not started, it does not matter how we arrive the the page setting the not found status code.
139+ // We can navigate straight to the testing page, skipping the index page.
140+ public void NotFoundSetOnInitialization_ResponseNotStarted_SSR ( bool hasReExecutionMiddleware , bool hasCustomNotFoundPageSet )
124141 {
125- string streamingPath = streamingStarted ? "-streaming" : "" ;
126- Navigate ( $ "{ ServerPathBase } /set-not-found-ssr{ streamingPath } ?useCustomNotFoundPage=true") ;
142+ string reexecution = hasReExecutionMiddleware ? "/reexecution" : "" ;
143+ string testUrl = $ "{ ServerPathBase } { reexecution } /set-not-found-ssr?useCustomNotFoundPage={ hasCustomNotFoundPageSet } ";
144+ Navigate ( testUrl ) ;
127145
128- var infoText = Browser . FindElement ( By . Id ( "test-info" ) ) . Text ;
129- Assert . Contains ( "Welcome On Custom Not Found Page" , infoText ) ;
130- // custom page should have a custom layout
131- var aboutLink = Browser . FindElement ( By . Id ( "about-link" ) ) . Text ;
132- Assert . Contains ( "About" , aboutLink ) ;
146+ if ( hasCustomNotFoundPageSet )
147+ {
148+ AssertNotFoundPageRendered ( ) ;
149+ }
150+ else
151+ {
152+ AssertNotFoundFragmentRendered ( ) ;
153+ }
154+ AssertUrlNotChanged ( testUrl ) ;
133155 }
134156
157+ // If the response has started, it matters how we arrive the the page setting the not found status code
158+ // because we are rendering client-side. In browser-initiated navigation and form submissions, the headers
159+ // don't contain enhanced-nav and we redirect to the not found page. In link clicking navigation,
160+ // the headers contain enhanced-nav, redirection is not needed and the original url will be preserved.
161+
135162 [ Theory ]
136- [ InlineData ( false ) ]
137- [ InlineData ( true ) ]
138- public void DoesNotReExecuteIf404WasHandled ( bool streamingStarted )
163+ [ InlineData ( true , true ) ] // manual testing works, why Selenium does not?
164+ [ InlineData ( true , false ) ]
165+ [ InlineData ( false , true ) ] // manual testing works, why Selenium does not?
166+ [ InlineData ( false , false ) ]
167+ // enhanced navigation is switched off for browser navigation
168+ public void NotFoundSetOnInitialization_ResponseStarted_BrowserNavigation_SSR ( bool hasReExecutionMiddleware , bool hasCustomNotFoundPageSet )
169+ {
170+ string reexecution = hasReExecutionMiddleware ? "/reexecution" : "" ;
171+ string testUrl = $ "{ ServerPathBase } { reexecution } /set-not-found-ssr-streaming?useCustomNotFoundPage={ hasCustomNotFoundPageSet } ";
172+ Navigate ( testUrl ) ;
173+ AssertNotFoundRendered_ResponseStarted_Or_POST ( hasReExecutionMiddleware , hasCustomNotFoundPageSet , testUrl ) ;
174+ bool throwsException = ! hasCustomNotFoundPageSet && ! hasReExecutionMiddleware ;
175+ if ( throwsException )
176+ {
177+ AssertUrlNotChanged ( testUrl ) ;
178+ }
179+ else
180+ {
181+ AssertUrlChanged ( testUrl ) ;
182+ }
183+ }
184+
185+ private void AssertNotFoundRendered_ResponseStarted_Or_POST ( bool hasReExecutionMiddleware , bool hasCustomNotFoundPageSet , string testUrl )
186+ {
187+ if ( hasCustomNotFoundPageSet )
188+ {
189+ AssertNotFoundPageRendered ( ) ;
190+ }
191+ else if ( hasReExecutionMiddleware )
192+ {
193+ AssertReExecutionPageRendered ( ) ;
194+ }
195+ else
196+ {
197+ // this throws an exception logged the server
198+ AssertNotFoundContentNotRendered ( ) ;
199+ }
200+ }
201+
202+ [ Theory ]
203+ //[InlineData(true, true)] // ActiveIssue("NotFoundPageRoute is not set in Router")
204+ [ InlineData ( true , false ) ]
205+ //[InlineData(false, true)] // ActiveIssue("NotFoundPageRoute is not set in Router")
206+ [ InlineData ( false , false ) ]
207+ // enhanced navigation is switched on for link navigation
208+ public void NotFoundSetOnInitialization_ResponseStarted_LinkNavigation_SSR ( bool hasReExecutionMiddleware , bool hasCustomNotFoundPageSet )
209+ {
210+ string testUrl = NavigateByLinkToPageTestingNotFound ( "Sets" , hasReExecutionMiddleware , hasCustomNotFoundPageSet ) ;
211+ AssertNotFoundRendered_ResponseStarted_Or_POST ( hasReExecutionMiddleware , hasCustomNotFoundPageSet , testUrl ) ;
212+ AssertUrlNotChanged ( testUrl ) ;
213+ }
214+
215+ private string NavigateByLinkToPageTestingNotFound ( string action , bool hasReExecutionMiddleware , bool hasCustomNotFoundPageSet )
216+ {
217+ string reexecution = hasReExecutionMiddleware ? "/reexecution" : "" ;
218+ Navigate ( $ "{ ServerPathBase } /not-found-index?useCustomNotFoundPage={ hasCustomNotFoundPageSet } ") ;
219+ Browser . Equal ( "List of Not Found test pages" , ( ) => Browser . FindElement ( By . Id ( "test-info" ) ) . Text ) ;
220+ string reexecutionText = hasReExecutionMiddleware ? " with reexecution" : "" ;
221+ var link = Browser . FindElement ( By . LinkText ( $ "PageThat{ action } NotFound-streaming{ reexecutionText } ") ) ;
222+ var testUrl = link . GetAttribute ( "href" ) ;
223+ link . Click ( ) ;
224+ return testUrl ;
225+ }
226+
227+ [ Theory ]
228+ //[InlineData(true, true)] // ActiveIssue("NotFoundPageRoute is not set in Router")
229+ [ InlineData ( true , false ) ]
230+ //[InlineData(false, true)] // ActiveIssue("NotFoundPageRoute is not set in Router")
231+ [ InlineData ( false , false ) ]
232+ // NotFound triggered by POST cannot get rendered in the same batch and we rely on the client to render it
233+ // However, because it is triggered by form POST, it won't have enhanced-nav headers
234+ public void NotFoundSetOnFormSubmit_ResponseNotStarted_SSR ( bool hasReExecutionMiddleware , bool hasCustomNotFoundPageSet )
235+ {
236+ string reexecution = hasReExecutionMiddleware ? "/reexecution" : "" ;
237+ string testUrl = $ "{ ServerPathBase } { reexecution } /post-not-found-ssr-streaming?useCustomNotFoundPage={ hasCustomNotFoundPageSet } ";
238+ Navigate ( testUrl ) ;
239+ Browser . FindElement ( By . Id ( "not-found-form" ) ) . FindElement ( By . TagName ( "button" ) ) . Click ( ) ;
240+
241+ AssertNotFoundRendered_ResponseStarted_Or_POST ( hasReExecutionMiddleware , hasCustomNotFoundPageSet , testUrl ) ;
242+ bool throwsException = ! hasCustomNotFoundPageSet && ! hasReExecutionMiddleware ;
243+ if ( throwsException )
244+ {
245+ AssertUrlNotChanged ( testUrl ) ;
246+ }
247+ else
248+ {
249+ AssertUrlChanged ( testUrl ) ;
250+ }
251+ }
252+
253+ [ Theory ]
254+ //[InlineData(true, true)] // ActiveIssue("NotFoundPageRoute is not set in Router")
255+ [ InlineData ( true , false ) ]
256+ //[InlineData(false, true)] // ActiveIssue("NotFoundPageRoute is not set in Router")
257+ [ InlineData ( false , false ) ]
258+ public void NotFoundSetOnFormSubmit_ResponseStarted_SSR ( bool hasReExecutionMiddleware , bool hasCustomNotFoundPageSet )
139259 {
140- string streamingPath = streamingStarted ? "-streaming" : "" ;
141- Navigate ( $ "{ ServerPathBase } /reexecution/set-not-found-ssr{ streamingPath } ") ;
142- AssertNotFoundFragmentRendered ( ) ;
260+ string reexecution = hasReExecutionMiddleware ? "/reexecution" : "" ;
261+ string testUrl = $ "{ ServerPathBase } { reexecution } /post-not-found-ssr-streaming?useCustomNotFoundPage={ hasCustomNotFoundPageSet } ";
262+ Navigate ( testUrl ) ;
263+ Browser . FindElement ( By . Id ( "not-found-form" ) ) . FindElement ( By . TagName ( "button" ) ) . Click ( ) ;
264+
265+ AssertNotFoundRendered_ResponseStarted_Or_POST ( hasReExecutionMiddleware , hasCustomNotFoundPageSet , testUrl ) ;
266+ bool throwsException = ! hasCustomNotFoundPageSet && ! hasReExecutionMiddleware ;
267+ if ( throwsException )
268+ {
269+ AssertUrlNotChanged ( testUrl ) ;
270+ }
271+ else
272+ {
273+ AssertUrlChanged ( testUrl ) ;
274+ }
143275 }
144276
145277 private void AssertNotFoundFragmentRendered ( ) =>
146278 Browser . Equal ( "There's nothing here" , ( ) => Browser . FindElement ( By . Id ( "not-found-fragment" ) ) . Text ) ;
147279
280+ private void AssertNotFoundContentNotRendered ( ) =>
281+ Browser . Equal ( "Any content" , ( ) => Browser . FindElement ( By . Id ( "test-info" ) ) . Text ) ;
282+
148283 [ Fact ]
149284 public void StatusCodePagesWithReExecution ( )
150285 {
0 commit comments