mirror of https://github.com/Squidex/squidex.git
15 changed files with 429 additions and 83 deletions
@ -0,0 +1,113 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Domain.Apps.Core.Apps; |
|||
using Squidex.Domain.Apps.Entities.Contents; |
|||
using Squidex.Infrastructure; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities; |
|||
|
|||
public class ContextHeadersTests |
|||
{ |
|||
private readonly Context sut = Context.Anonymous(new App { Name = "my-app" }); |
|||
|
|||
[Fact] |
|||
public void Should_return_empty_when_header_is_not_set() |
|||
{ |
|||
Assert.Empty(sut.AsStrings("X-Fields")); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData("a,b", new[] { "a", "b" })] |
|||
[InlineData("a, b", new[] { "a", "b" })] |
|||
[InlineData(" a ; b ", new[] { "a", "b" })] |
|||
[InlineData("a,,b", new[] { "a", "b" })] |
|||
[InlineData("a,a,b", new[] { "a", "b" })] |
|||
public void Should_split_and_trim_header(string value, string[] expected) |
|||
{ |
|||
var context = sut.Clone(b => b.SetHeader("X-Fields", value)); |
|||
|
|||
Assert.Equal(expected, context.AsStrings("X-Fields").ToArray()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_ignore_entries_that_are_only_whitespace() |
|||
{ |
|||
// These used to survive as an empty string, which made Languages() throw.
|
|||
var context = sut.Clone(b => b.SetHeader("X-Fields", " , ")); |
|||
|
|||
Assert.Empty(context.AsStrings("X-Fields")); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_reuse_parsed_header() |
|||
{ |
|||
var context = sut.Clone(b => b.SetHeader("X-Fields", "a,b")); |
|||
|
|||
var actual1 = context.AsStrings("X-Fields"); |
|||
var actual2 = context.AsStrings("X-Fields"); |
|||
|
|||
Assert.Same(actual1, actual2); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_not_share_parsed_headers_with_clone() |
|||
{ |
|||
var context1 = sut.Clone(b => b.SetHeader("X-Fields", "a,b")); |
|||
|
|||
// Parse before cloning, so that a shared cache would be visible.
|
|||
Assert.Equal(["a", "b"], context1.AsStrings("X-Fields").ToArray()); |
|||
|
|||
var context2 = context1.Clone(b => b.SetHeader("X-Fields", "c")); |
|||
|
|||
Assert.Equal(["c"], context2.AsStrings("X-Fields").ToArray()); |
|||
Assert.Equal(["a", "b"], context1.AsStrings("X-Fields").ToArray()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_not_see_header_that_has_been_removed_in_clone() |
|||
{ |
|||
var context1 = sut.Clone(b => b.SetHeader("X-Fields", "a,b")); |
|||
|
|||
Assert.NotEmpty(context1.AsStrings("X-Fields")); |
|||
|
|||
var context2 = context1.Clone(b => b.Remove("X-Fields")); |
|||
|
|||
Assert.Empty(context2.AsStrings("X-Fields")); |
|||
Assert.NotEmpty(context1.AsStrings("X-Fields")); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_return_same_context_when_nothing_is_changed() |
|||
{ |
|||
var context = sut.Clone(_ => { }); |
|||
|
|||
Assert.Same(sut, context); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_parse_languages_from_header() |
|||
{ |
|||
var context = sut.Clone(b => b.WithLanguages(["en", "de", "en"])); |
|||
|
|||
Assert.Equal([Language.EN, Language.DE], context.Languages().ToArray()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_keep_headers_when_app_is_replaced() |
|||
{ |
|||
var context1 = sut.Clone(b => b.SetHeader("X-Fields", "a,b")); |
|||
|
|||
var context2 = context1.WithApp(new App { Name = "other-app" }); |
|||
|
|||
Assert.Equal("other-app", context2.App.Name); |
|||
Assert.Equal(["a", "b"], context2.AsStrings("X-Fields").ToArray()); |
|||
|
|||
// The original must not be affected.
|
|||
Assert.Equal("my-app", context1.App.Name); |
|||
} |
|||
} |
|||
@ -0,0 +1,122 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Microsoft.AspNetCore.Http; |
|||
using Squidex.Domain.Apps.Core.Apps; |
|||
using RequestContext = Squidex.Domain.Apps.Entities.Context; |
|||
|
|||
namespace Squidex.Web; |
|||
|
|||
public class ContextProviderTests |
|||
{ |
|||
private readonly IHttpContextAccessor httpContextAccessor = A.Fake<IHttpContextAccessor>(); |
|||
private readonly HttpContext httpContext = new DefaultHttpContext(); |
|||
private readonly App app = new App { Name = "my-app" }; |
|||
private readonly ContextProvider sut; |
|||
|
|||
public ContextProviderTests() |
|||
{ |
|||
// A fake would return a dummy http context, but the fallback is only used when it is null.
|
|||
A.CallTo(() => httpContextAccessor.HttpContext) |
|||
.Returns(null); |
|||
|
|||
sut = new ContextProvider(httpContextAccessor); |
|||
} |
|||
|
|||
private void UseHttpContext() |
|||
{ |
|||
A.CallTo(() => httpContextAccessor.HttpContext) |
|||
.Returns(httpContext); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_provide_context_from_http_context() |
|||
{ |
|||
UseHttpContext(); |
|||
|
|||
var context = new RequestContext(httpContext.User, app); |
|||
|
|||
httpContext.Features.Set(context); |
|||
|
|||
Assert.Same(context, sut.Context); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_create_context_when_http_context_has_none() |
|||
{ |
|||
UseHttpContext(); |
|||
|
|||
Assert.NotNull(sut.Context); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_reuse_created_context_of_http_context() |
|||
{ |
|||
UseHttpContext(); |
|||
|
|||
Assert.Same(sut.Context, sut.Context); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_read_headers_from_request() |
|||
{ |
|||
UseHttpContext(); |
|||
|
|||
httpContext.Request.Headers["X-Fields"] = "a,b"; |
|||
|
|||
Assert.Equal("a,b", sut.Context.Headers["X-Fields"]); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_write_context_to_http_context() |
|||
{ |
|||
UseHttpContext(); |
|||
|
|||
var context = new RequestContext(httpContext.User, app); |
|||
|
|||
sut.Context = context; |
|||
|
|||
Assert.Same(context, httpContext.Features.Get<RequestContext>()); |
|||
Assert.Same(context, sut.Context); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_replace_context_of_http_context() |
|||
{ |
|||
UseHttpContext(); |
|||
|
|||
var context1 = sut.Context; |
|||
var context2 = context1.Clone(b => b.SetHeader("X-Fields", "a,b")); |
|||
|
|||
sut.Context = context2; |
|||
|
|||
Assert.NotSame(context1, sut.Context); |
|||
Assert.Same(context2, sut.Context); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_provide_anonymous_context_without_http_context() |
|||
{ |
|||
Assert.NotNull(sut.Context); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_reuse_anonymous_context_without_http_context() |
|||
{ |
|||
Assert.Same(sut.Context, sut.Context); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_write_context_without_http_context() |
|||
{ |
|||
var context = new RequestContext(httpContext.User, app); |
|||
|
|||
sut.Context = context; |
|||
|
|||
Assert.Same(context, sut.Context); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue