@@ -152,11 +152,11 @@ public async Task Should_resolve_optional_capture_with_default_with_optional_spe
152152 //Then
153153 if ( ShouldBeFound ( path , caseSensitive ) )
154154 {
155- result . Body . AsString ( ) . ShouldEqual ( "OptionalCaptureWithDefault " + expected ) ;
155+ result . Body . AsString ( ) . ShouldEqual ( "OptionalCaptureWithDefault " + expected ) ;
156156 }
157157 else
158158 {
159- result . StatusCode . ShouldEqual ( HttpStatusCode . NotFound ) ;
159+ result . StatusCode . ShouldEqual ( HttpStatusCode . NotFound ) ;
160160 }
161161 }
162162
@@ -174,14 +174,73 @@ public async Task Should_resolve_optional_capture_with_default_with_optional_not
174174 //Then
175175 if ( ShouldBeFound ( path , caseSensitive ) )
176176 {
177- result . Body . AsString ( ) . ShouldEqual ( "OptionalCaptureWithDefault test" ) ;
177+ result . Body . AsString ( ) . ShouldEqual ( "OptionalCaptureWithDefault test" ) ;
178178 }
179179 else
180180 {
181- result . StatusCode . ShouldEqual ( HttpStatusCode . NotFound ) ;
181+ result . StatusCode . ShouldEqual ( HttpStatusCode . NotFound ) ;
182182 }
183183 }
184184
185+ [ Theory ]
186+ [ InlineData ( "/api" , "Single optional segment" ) ]
187+ [ InlineData ( "/api/" , "Single optional segment" ) ]
188+ [ InlineData ( "/api/arg1" , "Single optional segment" ) ]
189+ [ InlineData ( "/api/arg1/" , "Single optional segment" ) ]
190+ [ InlineData ( "/api/arg1/arg2" , "Two optional segments" ) ]
191+ [ InlineData ( "/api/arg1/arg2/" , "Two optional segments" ) ]
192+ [ InlineData ( "/api/arg1/arg2/arg3" , "Three optional segments" ) ]
193+ [ InlineData ( "/api/arg1/arg2/arg3/" , "Three optional segments" ) ]
194+ public async Task Should_Resolve_Optionals_Correctly ( string path , string expected )
195+ {
196+ var browser = InitBrowser ( caseSensitive : false ) ;
197+ var result = await browser . Get ( path ) ;
198+ result . Body . AsString ( ) . ShouldEqual ( expected ) ;
199+ }
200+
201+ [ Theory ]
202+ [ InlineData ( "/api/greedy/arg1" , "Greedy match" ) ]
203+ [ InlineData ( "/api/greedy/arg1/arg2" , "Greedy match" ) ]
204+ public async Task Should_Resolve_Greedy_Alongside_Optionals ( string path , string expected )
205+ {
206+ var browser = InitBrowser ( caseSensitive : false ) ;
207+ var result = await browser . Get ( path ) ;
208+ result . Body . AsString ( ) . ShouldEqual ( expected ) ;
209+ }
210+
211+ [ Theory ]
212+ [ InlineData ( "/optional/literal/bar" , "Single optional segment, literal segment at end" ) ]
213+ [ InlineData ( "/optional/literal/arg1/bar" , "Single optional segment, literal segment at end" ) ]
214+ [ InlineData ( "/optional/literal/arg1/arg2/bar" , "Two optional segments, literal segment at end" ) ]
215+ public async Task Should_Resolve_Optionals_with_Literal_Ends ( string path , string expected )
216+ {
217+ var browser = InitBrowser ( caseSensitive : false ) ;
218+ var result = await browser . Get ( path ) ;
219+ result . Body . AsString ( ) . ShouldEqual ( expected ) ;
220+ }
221+
222+ [ Theory ]
223+ [ InlineData ( "/optional/variable/hello" , "Single hello" ) ]
224+ [ InlineData ( "/optional/variable/hello/there" , "Single hello there" ) ]
225+ [ InlineData ( "/optional/variable/hello/there/everybody" , "Double hello there everybody" ) ]
226+ public async Task Should_Resolve_Optionals_with_Variable_Ends ( string path , string expected )
227+ {
228+ var browser = InitBrowser ( caseSensitive : false ) ;
229+ var result = await browser . Get ( path ) ;
230+ result . Body . AsString ( ) . ShouldEqual ( expected ) ;
231+ }
232+
233+ [ Theory ]
234+ [ InlineData ( "/too/greedy/arg1" , "One arg1" ) ]
235+ [ InlineData ( "/too/greedy/arg1/hello" , "Literal arg1" ) ]
236+ public async Task Should_Not_Be_Too_Greedy ( string path , string expected )
237+ {
238+ var browser = InitBrowser ( caseSensitive : false ) ;
239+ var result = await browser . Get ( path ) ;
240+ var woot = result . Body . AsString ( ) ;
241+ result . Body . AsString ( ) . ShouldEqual ( expected ) ;
242+ }
243+
185244 [ Theory ]
186245 [ InlineData ( "/bleh/this/is/some/stuff" , true , "this/is/some/stuff" ) ]
187246 [ InlineData ( "/bleh/this/is/some/stuff" , false , "this/is/some/stuff" ) ]
@@ -442,6 +501,7 @@ public NoRootModule()
442501 }
443502 }
444503
504+
445505 private class TestModule : NancyModule
446506 {
447507 public TestModule ( )
@@ -475,6 +535,26 @@ public TestModule()
475535 Get ( "/capturenodewithliteral/{file}.html" , args => "CaptureNodeWithLiteral " + args . file + ".html" ) ;
476536
477537 Get ( @"/regex/(?<foo>\d{2,4})/{bar}" , args => string . Format ( "RegEx {0} {1}" , args . foo , args . bar ) ) ;
538+
539+ Get ( "/api/{arg1?}" , args => "Single optional segment" ) ;
540+
541+ Get ( "/api/{arg1?}/{arg2?}" , args => "Two optional segments" ) ;
542+
543+ Get ( "/api/{arg1?}/{arg2?}/{arg3?}" , args => "Three optional segments" ) ;
544+
545+ Get ( "/api/greedy/{something*}" , args => "Greedy match" ) ;
546+
547+ Get ( "/optional/literal/{arg1?}/bar" , args => "Single optional segment, literal segment at end" ) ;
548+
549+ Get ( "/optional/literal/{arg1?}/{arg2?}/bar" , args => "Two optional segments, literal segment at end" ) ;
550+
551+ Get ( "/optional/variable/{arg1?}/{variable}" , args => string . Format ( "Single {0} {1}" , args . arg1 . Value , args . variable . Value ) ) ;
552+
553+ Get ( "/optional/variable/{arg1?}/{arg2?}/{variable}" , args => string . Format ( "Double {0} {1} {2}" , args . arg1 . Value , args . arg2 . Value , args . variable . Value ) ) ;
554+
555+ Get ( "/too/greedy/{arg1*}" , args => string . Format ( "One {0}" , args . arg1 . Value ) ) ;
556+
557+ Get ( "/too/greedy/{arg1*}/hello" , args => string . Format ( "Literal {0}" , args . arg1 . Value ) ) ;
478558 }
479559 }
480560 }
0 commit comments