Permalink
Browse files

Merge pull request #769 from grumpydev/ViewErrorPages

Added tests and fix for view location error.
  • Loading branch information...
2 parents df74331 + a9c21b4 commit e5f8dc1c56056b297a3560315c4ccc017c650969 @thecodejunkie thecodejunkie committed Oct 2, 2012
Showing with 108 additions and 31 deletions.
  1. +107 −16 src/Nancy.Tests.Functional/Tests/ContentNegotiationFixture.cs
  2. +1 −15 src/Nancy/Routing/DefaultRouteInvoker.cs
@@ -4,6 +4,7 @@ namespace Nancy.Tests.Functional.Tests
using System.Collections.Generic;
using System.IO;
+ using Nancy.ErrorHandling;
using Nancy.IO;
using Nancy.Responses.Negotiation;
using Nancy.Testing;
@@ -372,22 +373,6 @@ public void Should_add_link_header_for_matching_response_processors()
Assert.True(response.Headers["Link"].Contains(@"</.xml>; rel=""application/xml"""));
}
- private static Func<dynamic, dynamic> CreateNegotiatedResponse(Action<Negotiator> action = null)
- {
- var context =
- new NancyContext { NegotiationContext = new NegotiationContext() };
-
- var negotiator =
- new Negotiator(context);
-
- if (action != null)
- {
- action.Invoke(negotiator);
- }
-
- return parameters => negotiator;
- }
-
[Fact]
public void Should_set_negotiated_status_code_to_response_when_set_as_integer()
{
@@ -442,6 +427,77 @@ public void Should_set_negotiated_status_code_to_response_when_set_as_httpstatus
Assert.Equal(HttpStatusCode.InsufficientStorage, response.StatusCode);
}
+ [Fact]
+ public void Should_throw_exception_if_view_location_fails()
+ {
+ var browser = new Browser(with =>
+ {
+ with.ResponseProcessor<ViewProcessor>();
+
+ with.Module(new FakeModuleInvalidViewName());
+ });
+
+ // When
+ var result = Record.Exception(() =>
+ {
+ var response = browser.Get(
+ "/FakeModuleInvalidViewName",
+ with =>
+ { with.Accept("text/html", 1.0m); });
+ });
+
+ // Then
+ Assert.NotNull(result);
+ Assert.Contains("Unable to locate view", result.ToString());
+ }
+
+ [Fact]
+ public void Should_use_next_processor_if_processor_returns_null()
+ {
+ // Given
+ var browser = new Browser(with =>
+ {
+ with.ResponseProcessors(typeof(NullProcessor), typeof(TestProcessor));
+
+ with.Module(new ConfigurableNancyModule(x =>
+ {
+ x.Get("/test", CreateNegotiatedResponse(config =>
+ {
+ config.WithAllowedMediaRange("application/xml");
+ }));
+ }));
+ });
+
+ // When
+ var response = browser.Get("/test", with =>
+ {
+ with.Accept("application/xml", 0.9m);
+ });
+
+ // Then
+ var bodyResult = response.Body.AsString();
+ Assert.True(bodyResult.StartsWith("application/xml"), string.Format("Body should have started with 'application/xml' but was actually '{0}'", bodyResult));
+ }
+
+ private static Func<dynamic, dynamic> CreateNegotiatedResponse(Action<Negotiator> action = null)
+ {
+ var context =
+ new NancyContext { NegotiationContext = new NegotiationContext() };
+
+ var negotiator =
+ new Negotiator(context);
+
+ if (action != null)
+ {
+ action.Invoke(negotiator);
+ }
+
+ return parameters =>
+ {
+ return negotiator;
+ };
+ }
+
/// <summary>
/// Test response processor that will accept any type
/// and put the content type and model type into the
@@ -475,6 +531,33 @@ public Response Process(MediaRange requestedMediaRange, dynamic model, NancyCont
}
}
+ public class NullProcessor : IResponseProcessor
+ {
+ private const string ResponseTemplate = "{0}\n{1}";
+
+ public IEnumerable<Tuple<string, MediaRange>> ExtensionMappings
+ {
+ get
+ {
+ yield break;
+ }
+ }
+
+ public ProcessorMatch CanProcess(MediaRange requestedMediaRange, dynamic model, NancyContext context)
+ {
+ return new ProcessorMatch
+ {
+ RequestedContentTypeResult = MatchResult.ExactMatch,
+ ModelResult = MatchResult.ExactMatch
+ };
+ }
+
+ public Response Process(MediaRange requestedMediaRange, dynamic model, NancyContext context)
+ {
+ return null;
+ }
+ }
+
public class ModelProcessor : IResponseProcessor
{
private const string ResponseTemplate = "{0}\n{1}";
@@ -501,5 +584,13 @@ public Response Process(MediaRange requestedMediaRange, dynamic model, NancyCont
return (string) model;
}
}
+
+ public class FakeModuleInvalidViewName : NancyModule
+ {
+ public FakeModuleInvalidViewName()
+ {
+ Get["/FakeModuleInvalidViewName"] = _ => View["blahblahblah"];
+ }
+ }
}
}
@@ -100,7 +100,7 @@ private static Response NegotiateResponse(IEnumerable<Tuple<string, IEnumerable<
context.WriteTraceLog(sb => sb.AppendFormat("[DefaultRouteInvoker] Invoking processor: {0}\n", processorType));
var response =
- SafeInvokeResponseProcessor(prioritizedProcessor.Item1, compatibleHeader.Item1, negotiator.NegotiationContext.GetModelForMediaRange(compatibleHeader.Item1), context);
+ prioritizedProcessor.Item1.Process(compatibleHeader.Item1, negotiator.NegotiationContext.GetModelForMediaRange(compatibleHeader.Item1), context);
if (response != null)
{
@@ -247,20 +247,6 @@ private static void AddLinkHeaders(NancyContext context, IEnumerable<Tuple<strin
return currentHeaders;
}
- private static Response SafeInvokeResponseProcessor(IResponseProcessor responseProcessor, MediaRange mediaRange, object model, NancyContext context)
- {
- try
- {
- return responseProcessor.Process(mediaRange, model, context);
- }
- catch (Exception e)
- {
- context.WriteTraceLog(sb => sb.AppendFormat("[DefaultRouteInvoker] Processor threw {0} exception: {1}", e.GetType(), e.Message));
- }
-
- return null;
- }
-
private static Negotiator GetNegotiator(object routeResult, NancyContext context)
{
var negotiator = routeResult as Negotiator;

0 comments on commit e5f8dc1

Please sign in to comment.