Browse Source

UI improved and tests fixed.

pull/98/head
Sebastian Stehle 9 years ago
parent
commit
f11f4fe8ed
  1. 2
      src/Squidex/app/features/webhooks/pages/webhook.component.html
  2. 244
      tests/Squidex.Domain.Apps.Read.Tests/Webhooks/WebhookEnqueuerTests.cs
  3. 72
      tests/Squidex.Infrastructure.Tests/Http/DumpFormatterTests.cs
  4. 28
      tests/Squidex.Infrastructure.Tests/Log/SemanticLogTests.cs

2
src/Squidex/app/features/webhooks/pages/webhook.component.html

@ -23,7 +23,7 @@
<tr>
<td>Url:</td>
<td>
<input class="form-control" formControlName="url" [attr.value]="webhook.url" #inputUrl />
<input type="url" class="form-control" formControlName="url" [attr.value]="webhook.url" #inputUrl />
</td>
<td>
<button type="button" class="btn btn-primary btn-link" [sqxCopy]="inputUrl">

244
tests/Squidex.Domain.Apps.Read.Tests/Webhooks/WebhookEnqueuerTests.cs

@ -1,118 +1,126 @@
//// ==========================================================================
//// WebhookEnqueuerTests.cs
//// Squidex Headless CMS
//// ==========================================================================
//// Copyright (c) Squidex Group
//// All rights reserved.
//// ==========================================================================
//using System;
//using System.Collections.Generic;
//using System.Threading.Tasks;
//using FakeItEasy;
//using Newtonsoft.Json;
//using NodaTime;
//using Squidex.Domain.Apps.Events.Contents;
//using Squidex.Domain.Apps.Read.Webhooks.Repositories;
//using Squidex.Infrastructure;
//using Squidex.Infrastructure.CQRS.Events;
//using Xunit;
//// ReSharper disable MethodSupportsCancellation
//// ReSharper disable ImplicitlyCapturedClosure
//// ReSharper disable ConvertToConstant.Local
//namespace Squidex.Domain.Apps.Read.Webhooks
//{
// public class WebhookEnqueuerTests
// {
// private readonly IClock clock = A.Fake<IClock>();
// private readonly IWebhookRepository webhookRepository = A.Fake<IWebhookRepository>();
// private readonly IWebhookEventRepository webhookEventRepository = A.Fake<IWebhookEventRepository>();
// private readonly TypeNameRegistry typeNameRegisty = new TypeNameRegistry();
// private readonly Instant now = SystemClock.Instance.GetCurrentInstant();
// private readonly WebhookEnqueuer sut;
// public WebhookEnqueuerTests()
// {
// A.CallTo(() => clock.GetCurrentInstant()).Returns(now);
// typeNameRegisty.Map(typeof(ContentCreated));
// sut = new WebhookEnqueuer(
// typeNameRegisty,
// webhookEventRepository,
// webhookRepository,
// clock, new JsonSerializer());
// }
// [Fact]
// public void Should_return_contents_filter_for_events_filter()
// {
// Assert.Equal("^content-", sut.EventsFilter);
// }
// [Fact]
// public void Should_return_type_name_for_name()
// {
// Assert.Equal(typeof(WebhookEnqueuer).Name, sut.Name);
// }
// [Fact]
// public Task Should_do_nothing_on_clear()
// {
// return sut.ClearAsync();
// }
// [Fact]
// public async Task Should_update_repositories_on_successful_requests()
// {
// var appId = new NamedId<Guid>(Guid.NewGuid(), "my-app");
// var schemaId = new NamedId<Guid>(Guid.NewGuid(), "my-schema");
// var @event = Envelope.Create(new ContentCreated { AppId = appId, SchemaId = schemaId });
// var webhook1 = CreateWebhook(1);
// var webhook2 = CreateWebhook(2);
// A.CallTo(() => webhookRepository.QueryByAppAsync(appId.Id))
// .Returns(Task.FromResult<IReadOnlyList<IWebhookEntity>>(new List<IWebhookEntity> { webhook1, webhook2 }));
// await sut.On(@event);
// A.CallTo(() => webhookEventRepository.EnqueueAsync(
// A<WebhookJob>.That.Matches(webhookJob =>
// !string.IsNullOrWhiteSpace(webhookJob.RequestSignature)
// && !string.IsNullOrWhiteSpace(webhookJob.RequestBody)
// && webhookJob.Id != Guid.Empty
// && webhookJob.Expires == now.Plus(Duration.FromDays(2))
// && webhookJob.AppId == appId.Id
// && webhookJob.EventName == "MySchemaCreatedEvent"
// && webhookJob.RequestUrl == webhook1.Url
// && webhookJob.WebhookId == webhook1.Id), now)).MustHaveHappened();
// A.CallTo(() => webhookEventRepository.EnqueueAsync(
// A<WebhookJob>.That.Matches(webhookJob =>
// !string.IsNullOrWhiteSpace(webhookJob.RequestSignature)
// && !string.IsNullOrWhiteSpace(webhookJob.RequestBody)
// && webhookJob.Id != Guid.Empty
// && webhookJob.Expires == now.Plus(Duration.FromDays(2))
// && webhookJob.AppId == appId.Id
// && webhookJob.EventName == "MySchemaCreatedEvent"
// && webhookJob.RequestUrl == webhook2.Url
// && webhookJob.WebhookId == webhook2.Id), now)).MustHaveHappened();
// }
// private static ISchemaWebhookUrlEntity CreateWebhook(int offset)
// {
// var webhook = A.Dummy<ISchemaWebhookUrlEntity>();
// A.CallTo(() => webhook.Id).Returns(Guid.NewGuid());
// A.CallTo(() => webhook.Url).Returns(new Uri($"http://domain{offset}.com"));
// A.CallTo(() => webhook.SharedSecret).Returns($"secret{offset}");
// return webhook;
// }
//}
//}
// ==========================================================================
// WebhookEnqueuerTests.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using FakeItEasy;
using Newtonsoft.Json;
using NodaTime;
using Squidex.Domain.Apps.Core.Webhooks;
using Squidex.Domain.Apps.Events.Contents;
using Squidex.Domain.Apps.Read.Webhooks.Repositories;
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events;
using Xunit;
// ReSharper disable MethodSupportsCancellation
// ReSharper disable ImplicitlyCapturedClosure
// ReSharper disable ConvertToConstant.Local
namespace Squidex.Domain.Apps.Read.Webhooks
{
public class WebhookEnqueuerTests
{
private readonly IClock clock = A.Fake<IClock>();
private readonly IWebhookRepository webhookRepository = A.Fake<IWebhookRepository>();
private readonly IWebhookEventRepository webhookEventRepository = A.Fake<IWebhookEventRepository>();
private readonly TypeNameRegistry typeNameRegisty = new TypeNameRegistry();
private readonly Instant now = SystemClock.Instance.GetCurrentInstant();
private readonly NamedId<Guid> appId = new NamedId<Guid>(Guid.NewGuid(), "my-app");
private readonly NamedId<Guid> schemaId = new NamedId<Guid>(Guid.NewGuid(), "my-schema");
private readonly WebhookEnqueuer sut;
public WebhookEnqueuerTests()
{
A.CallTo(() => clock.GetCurrentInstant()).Returns(now);
typeNameRegisty.Map(typeof(ContentCreated));
sut = new WebhookEnqueuer(
typeNameRegisty,
webhookEventRepository,
webhookRepository,
clock, new JsonSerializer());
}
[Fact]
public void Should_return_contents_filter_for_events_filter()
{
Assert.Equal("^content-", sut.EventsFilter);
}
[Fact]
public void Should_return_type_name_for_name()
{
Assert.Equal(typeof(WebhookEnqueuer).Name, sut.Name);
}
[Fact]
public Task Should_do_nothing_on_clear()
{
return sut.ClearAsync();
}
[Fact]
public async Task Should_update_repositories_on_successful_requests()
{
var @event = Envelope.Create(new ContentCreated { AppId = appId, SchemaId = schemaId });
var webhook1 = CreateWebhook(1);
var webhook2 = CreateWebhook(2);
A.CallTo(() => webhookRepository.QueryByAppAsync(appId.Id))
.Returns(Task.FromResult<IReadOnlyList<IWebhookEntity>>(new List<IWebhookEntity> { webhook1, webhook2 }));
await sut.On(@event);
A.CallTo(() => webhookEventRepository.EnqueueAsync(
A<WebhookJob>.That.Matches(webhookJob =>
!string.IsNullOrWhiteSpace(webhookJob.RequestSignature)
&& !string.IsNullOrWhiteSpace(webhookJob.RequestBody)
&& webhookJob.Id != Guid.Empty
&& webhookJob.Expires == now.Plus(Duration.FromDays(2))
&& webhookJob.AppId == appId.Id
&& webhookJob.EventName == "MySchemaCreatedEvent"
&& webhookJob.RequestUrl == webhook1.Url
&& webhookJob.WebhookId == webhook1.Id), now)).MustHaveHappened();
A.CallTo(() => webhookEventRepository.EnqueueAsync(
A<WebhookJob>.That.Matches(webhookJob =>
!string.IsNullOrWhiteSpace(webhookJob.RequestSignature)
&& !string.IsNullOrWhiteSpace(webhookJob.RequestBody)
&& webhookJob.Id != Guid.Empty
&& webhookJob.Expires == now.Plus(Duration.FromDays(2))
&& webhookJob.AppId == appId.Id
&& webhookJob.EventName == "MySchemaCreatedEvent"
&& webhookJob.RequestUrl == webhook2.Url
&& webhookJob.WebhookId == webhook2.Id), now)).MustHaveHappened();
}
private IWebhookEntity CreateWebhook(int offset)
{
var webhook = A.Dummy<IWebhookEntity>();
var schema = new WebhookSchema
{
SchemaId = schemaId.Id,
SendCreate = true,
SendUpdate = true
};
A.CallTo(() => webhook.Id).Returns(Guid.NewGuid());
A.CallTo(() => webhook.Url).Returns(new Uri($"http://domain{offset}.com"));
A.CallTo(() => webhook.Schemas).Returns(new[] { schema });
A.CallTo(() => webhook.SharedSecret).Returns($"secret{offset}");
return webhook;
}
}
}

72
tests/Squidex.Infrastructure.Tests/Http/DumpFormatterTests.cs

@ -20,15 +20,11 @@ namespace Squidex.Infrastructure.Http
[Fact]
public void Should_format_dump_without_response()
{
var request = new HttpRequestMessage(HttpMethod.Post, new Uri("https://cloud.squidex.io"));
request.Headers.UserAgent.Add(new ProductInfoHeaderValue("Squidex", "1.0"));
request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue("de"));
request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue("en"));
request.Headers.AcceptEncoding.Add(new StringWithQualityHeaderValue("UTF-8"));
var httpRequest = CreateRequest();
var dump = DumpFormatter.BuildDump(request, null, null, null, TimeSpan.FromMinutes(1), true);
var dump = DumpFormatter.BuildDump(httpRequest, null, null, null, TimeSpan.FromMinutes(1), true);
var expected = MakeDump(
var expected = CreateExpectedDump(
"Request:",
"POST: https://cloud.squidex.io/ HTTP/1.1",
"User-Agent: Squidex/1.0",
@ -45,19 +41,12 @@ namespace Squidex.Infrastructure.Http
[Fact]
public void Should_format_dump_without_content()
{
var request = new HttpRequestMessage(HttpMethod.Post, new Uri("https://cloud.squidex.io"));
request.Headers.UserAgent.Add(new ProductInfoHeaderValue("Squidex", "1.0"));
request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue("de"));
request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue("en"));
request.Headers.AcceptEncoding.Add(new StringWithQualityHeaderValue("UTF-8"));
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Headers.TransferEncoding.Add(new TransferCodingHeaderValue("UTF-8"));
response.Headers.Trailer.Add("Expires");
var httpRequest = CreateRequest();
var httpResponse = CreateResponse();
var dump = DumpFormatter.BuildDump(request, response, null, null, TimeSpan.FromMinutes(1), false);
var dump = DumpFormatter.BuildDump(httpRequest, httpResponse, null, null, TimeSpan.FromMinutes(1), false);
var expected = MakeDump(
var expected = CreateExpectedDump(
"Request:",
"POST: https://cloud.squidex.io/ HTTP/1.1",
"User-Agent: Squidex/1.0",
@ -76,23 +65,14 @@ namespace Squidex.Infrastructure.Http
}
[Fact]
public void Should_format_dump_with_content()
public void Should_format_dump_with_content_without_timeout()
{
var request = new HttpRequestMessage(HttpMethod.Post, new Uri("https://cloud.squidex.io"));
request.Headers.UserAgent.Add(new ProductInfoHeaderValue("Squidex", "1.0"));
request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue("de"));
request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue("en"));
request.Headers.AcceptEncoding.Add(new StringWithQualityHeaderValue("UTF-8"));
request.Content = new StringContent("Hello Squidex", Encoding.UTF8, "text/plain");
var httpRequest = CreateRequest(new StringContent("Hello Squidex", Encoding.UTF8, "text/plain"));
var httpResponse = CreateResponse(new StringContent("Hello Back", Encoding.UTF8, "text/plain"));
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Headers.TransferEncoding.Add(new TransferCodingHeaderValue("UTF-8"));
response.Headers.Trailer.Add("Expires");
response.Content = new StringContent("Hello Back", Encoding.UTF8, "text/plain");
var dump = DumpFormatter.BuildDump(httpRequest, httpResponse, "Hello Squidex", "Hello Back", TimeSpan.FromMinutes(1), false);
var dump = DumpFormatter.BuildDump(request, response, "Hello Squidex", "Hello Back", TimeSpan.FromMinutes(1), true);
var expected = MakeDump(
var expected = CreateExpectedDump(
"Request:",
"POST: https://cloud.squidex.io/ HTTP/1.1",
"User-Agent: Squidex/1.0",
@ -116,7 +96,33 @@ namespace Squidex.Infrastructure.Http
Assert.Equal(expected, dump);
}
private static string MakeDump(params string[] input)
private static HttpRequestMessage CreateRequest(HttpContent content = null)
{
var request = new HttpRequestMessage(HttpMethod.Post, new Uri("https://cloud.squidex.io"));
request.Headers.UserAgent.Add(new ProductInfoHeaderValue("Squidex", "1.0"));
request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue("de"));
request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue("en"));
request.Headers.AcceptEncoding.Add(new StringWithQualityHeaderValue("UTF-8"));
request.Content = content;
return request;
}
private static HttpResponseMessage CreateResponse(HttpContent content = null)
{
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Headers.TransferEncoding.Add(new TransferCodingHeaderValue("UTF-8"));
response.Headers.Trailer.Add("Expires");
response.Content = content;
return response;
}
private static string CreateExpectedDump(params string[] input)
{
return string.Join(Environment.NewLine, input) + Environment.NewLine;
}

28
tests/Squidex.Infrastructure.Tests/Log/SemanticLogTests.cs

@ -8,6 +8,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using FakeItEasy;
using Microsoft.Extensions.Logging;
using Squidex.Infrastructure.Log.Adapter;
@ -293,6 +294,33 @@ namespace Squidex.Infrastructure.Log
Assert.Equal(expected, output);
}
[Fact]
public void Should_catch_all_exceptions_from_all_channels_when_exceptions_are_thrown()
{
var exception1 = new InvalidOperationException();
var exception2 = new InvalidOperationException();
var channel1 = A.Fake<ILogChannel>();
var channel2 = A.Fake<ILogChannel>();
A.CallTo(() => channel1.Log(A<SemanticLogLevel>.Ignored, A<string>.Ignored)).Throws(exception1);
A.CallTo(() => channel2.Log(A<SemanticLogLevel>.Ignored, A<string>.Ignored)).Throws(exception2);
var sut = new SemanticLog(new[] { channel1, channel2 }, Enumerable.Empty<ILogAppender>(), () => new JsonLogWriter());
try
{
sut.Log(SemanticLogLevel.Debug, w => w.WriteProperty("should", "throw"));
Assert.False(true);
}
catch (AggregateException ex)
{
Assert.Equal(exception1, ex.InnerExceptions[0]);
Assert.Equal(exception2, ex.InnerExceptions[1]);
}
}
private static string LogTest(Action<IObjectWriter> writer)
{
IObjectWriter sut = new JsonLogWriter();

Loading…
Cancel
Save