mirror of https://github.com/Squidex/squidex.git
Browse Source
* Error simulation * Improved tests. * Increase test verbosity * Disable slow test.pull/546/head
committed by
GitHub
7 changed files with 340 additions and 50 deletions
@ -0,0 +1,85 @@ |
|||
<!DOCTYPE html> |
|||
<html> |
|||
|
|||
<head> |
|||
<meta charset="utf-8"> |
|||
|
|||
<!-- Load the editor sdk from the local folder or https://cloud.squidex.io/scripts/editor-sdk.js --> |
|||
<script src="editor-sdk.js"></script> |
|||
<script src="https://unpkg.com/react@16/umd/react.production.min.js"></script> |
|||
<script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script> |
|||
<script src="https://unpkg.com/@rjsf/core/dist/react-jsonschema-form.js"></script> |
|||
|
|||
<link rel="stylesheet" type="text/css" href="https://cloud.squidex.io/build/app.css"> |
|||
|
|||
<style> |
|||
body { |
|||
background: none; |
|||
} |
|||
|
|||
#root__title { |
|||
display: none; |
|||
} |
|||
</style> |
|||
</head> |
|||
|
|||
<body> |
|||
<div id="editor"></div> |
|||
|
|||
<script> |
|||
const Form = JSONSchemaForm.default; |
|||
|
|||
const field = new SquidexFormField(); |
|||
|
|||
function Editor() { |
|||
var stateDisabled = React.useState(false); // Use ES5 language features only. |
|||
var stateValue = React.useState(undefined); |
|||
var stateSchema = React.useState(undefined); |
|||
|
|||
React.useEffect(function () { |
|||
field.onDisabled(function (disabled) { |
|||
stateDisabled[1](disabled); |
|||
}); |
|||
|
|||
field.onValueChanged(function (value) { |
|||
stateValue[1](value); |
|||
}); |
|||
|
|||
if (window.location.hash && window.location.hash.length > 1) { |
|||
fetch(window.location.hash.substr(1)) |
|||
.then(x => x.json()) |
|||
.then(x => stateSchema[1](x)); |
|||
} |
|||
}, []); |
|||
|
|||
const doBlur = React.useCallback(function () { |
|||
field.touched(); |
|||
}, []); |
|||
|
|||
const doChange = React.useCallback(function (editor) { |
|||
if (editor.errors.length === 0) { |
|||
field.valueChanged(editor.formData); |
|||
} |
|||
}, []); |
|||
|
|||
if (!stateSchema[0]) { |
|||
return null; |
|||
} |
|||
|
|||
return ( |
|||
React.createElement(Form, { |
|||
formData: stateValue[0], |
|||
disabled: stateDisabled[0], |
|||
onChange: doChange, |
|||
onBlur: doBlur, |
|||
schema: stateSchema[0], |
|||
children: [] // Hide submit button |
|||
}) |
|||
); |
|||
} |
|||
|
|||
ReactDOM.render(React.createElement(Editor), document.getElementById("editor")); |
|||
</script> |
|||
</body> |
|||
|
|||
</html> |
|||
@ -0,0 +1,172 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Elasticsearch.Net; |
|||
using FakeItEasy; |
|||
using GraphQL; |
|||
using Grpc.Core.Logging; |
|||
using Microsoft.AspNetCore.Http; |
|||
using Microsoft.AspNetCore.Http.Features; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.AspNetCore.Mvc.Infrastructure; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Log; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Web.Pipeline |
|||
{ |
|||
public class RequestExceptionMiddlewareTests |
|||
{ |
|||
private readonly ISemanticLog log = A.Fake<ISemanticLog>(); |
|||
private readonly IActionResultExecutor<ObjectResult> resultWriter = A.Fake<IActionResultExecutor<ObjectResult>>(); |
|||
private readonly IHttpResponseFeature responseFeature = A.Fake<IHttpResponseFeature>(); |
|||
private readonly HttpContext httpContext = new DefaultHttpContext(); |
|||
private readonly RequestDelegate next; |
|||
private readonly RequestExceptionMiddleware sut; |
|||
private bool isNextCalled; |
|||
|
|||
public RequestExceptionMiddlewareTests() |
|||
{ |
|||
next = new RequestDelegate(context => |
|||
{ |
|||
isNextCalled = true; |
|||
|
|||
return Task.CompletedTask; |
|||
}); |
|||
|
|||
httpContext.Features.Set(responseFeature); |
|||
|
|||
sut = new RequestExceptionMiddleware(resultWriter, log); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_write_test_error_if_valid_status_code() |
|||
{ |
|||
httpContext.Request.QueryString = new QueryString("?error=412"); |
|||
|
|||
await sut.InvokeAsync(httpContext, next); |
|||
|
|||
Assert.False(isNextCalled); |
|||
|
|||
A.CallTo(() => resultWriter.ExecuteAsync(A<ActionContext>._, |
|||
A<ObjectResult>.That.Matches(x => x.StatusCode == 412 && x.Value is ErrorDto))) |
|||
.MustHaveHappened(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_not_test_error_if_invalid_status_code() |
|||
{ |
|||
httpContext.Request.QueryString = new QueryString("?error=hello"); |
|||
|
|||
await sut.InvokeAsync(httpContext, next); |
|||
|
|||
Assert.True(isNextCalled); |
|||
|
|||
A.CallTo(() => resultWriter.ExecuteAsync(A<ActionContext>._, A<ObjectResult>._)) |
|||
.MustNotHaveHappened(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_not_test_error_if_invalid_error_status_code() |
|||
{ |
|||
httpContext.Request.QueryString = new QueryString("?error=99"); |
|||
|
|||
await sut.InvokeAsync(httpContext, next); |
|||
|
|||
Assert.True(isNextCalled); |
|||
|
|||
A.CallTo(() => resultWriter.ExecuteAsync(A<ActionContext>._, A<ObjectResult>._)) |
|||
.MustNotHaveHappened(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_handle_exception() |
|||
{ |
|||
var failingNext = new RequestDelegate(context => |
|||
{ |
|||
throw new InvalidOperationException(); |
|||
}); |
|||
|
|||
await sut.InvokeAsync(httpContext, failingNext); |
|||
|
|||
A.CallTo(() => resultWriter.ExecuteAsync(A<ActionContext>._, |
|||
A<ObjectResult>.That.Matches(x => x.StatusCode == 500 && x.Value is ErrorDto))) |
|||
.MustHaveHappened(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_log_exception() |
|||
{ |
|||
var ex = new InvalidOperationException(); |
|||
|
|||
var failingNext = new RequestDelegate(context => |
|||
{ |
|||
throw ex; |
|||
}); |
|||
|
|||
await sut.InvokeAsync(httpContext, failingNext); |
|||
|
|||
A.CallTo(() => log.Log(SemanticLogLevel.Error, ex, A<LogFormatter>._)) |
|||
.MustHaveHappened(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_not_handle_exception_if_response_body_written() |
|||
{ |
|||
A.CallTo(() => responseFeature.HasStarted) |
|||
.Returns(true); |
|||
|
|||
var failingNext = new RequestDelegate(context => |
|||
{ |
|||
throw new InvalidOperationException(); |
|||
}); |
|||
|
|||
await sut.InvokeAsync(httpContext, failingNext); |
|||
|
|||
A.CallTo(() => resultWriter.ExecuteAsync(A<ActionContext>._, A<ObjectResult>._)) |
|||
.MustNotHaveHappened(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_handle_error_status_code() |
|||
{ |
|||
var failingNext = new RequestDelegate(context => |
|||
{ |
|||
context.Response.StatusCode = 412; |
|||
|
|||
return Task.CompletedTask; |
|||
}); |
|||
|
|||
await sut.InvokeAsync(httpContext, failingNext); |
|||
|
|||
A.CallTo(() => resultWriter.ExecuteAsync(A<ActionContext>._, |
|||
A<ObjectResult>.That.Matches(x => x.StatusCode == 412 && x.Value is ErrorDto))) |
|||
.MustHaveHappened(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_not_handle_error_status_code_if_response_body_written() |
|||
{ |
|||
A.CallTo(() => responseFeature.HasStarted) |
|||
.Returns(true); |
|||
|
|||
var failingNext = new RequestDelegate(context => |
|||
{ |
|||
context.Response.StatusCode = 412; |
|||
|
|||
return Task.CompletedTask; |
|||
}); |
|||
|
|||
await sut.InvokeAsync(httpContext, failingNext); |
|||
|
|||
A.CallTo(() => resultWriter.ExecuteAsync(A<ActionContext>._, A<ObjectResult>._)) |
|||
.MustNotHaveHappened(); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue