Skip to content

Commit

Permalink
Merge pull request #74 from wildbit/task/add-webhooks-api
Browse files Browse the repository at this point in the history
Task/add webhooks api
  • Loading branch information
vladsandu authored Dec 8, 2019
2 parents 729c9f8 + 79caf86 commit f7cfff8
Show file tree
Hide file tree
Showing 16 changed files with 429 additions and 184 deletions.
79 changes: 4 additions & 75 deletions src/Postmark.Tests/ClientTriggersTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,19 @@ protected override void Setup()
_client = new PostmarkClient(WRITE_TEST_SERVER_TOKEN);
}

public ClientTriggersTests(): base(){
public ClientTriggersTests() : base()
{
this.Cleanup().Wait();
}

private Task Cleanup()
{
return Task.Run(async() =>
return Task.Run(async () =>
{
try
{
var triggers = await _client.SearchTaggedTriggers();
var tasks = new List<Task>();
foreach (var trigger in triggers.Tags)
{
if (trigger.MatchName.StartsWith(_triggerPrefix))
{
var dt = _client.DeleteTagTrigger(trigger.ID);
tasks.Add(dt);
}
}
var inboundTriggers = await _client.GetAllInboundRuleTriggers();
foreach (var inboundRule in inboundTriggers.InboundRules)
{
Expand All @@ -56,70 +49,6 @@ private Task Cleanup()
});
}

[Theory]
[InlineData("qwerty", false)]
[InlineData("pdq", true)]
public async void Client_CanCreateTagTrigger(string matchName, bool trackOpens)
{
var trigger = await _client.CreateTagTriggerAsync(_triggerPrefix + matchName, trackOpens);
var savedTrigger = await _client.GetTagTriggerAsync(trigger.ID);

Assert.Equal(trigger.MatchName, savedTrigger.MatchName);
Assert.Equal(trigger.TrackOpens, savedTrigger.TrackOpens);
Assert.Equal(trigger.ID, savedTrigger.ID);
Assert.Equal(_triggerPrefix + matchName, savedTrigger.MatchName);
Assert.Equal(trackOpens, savedTrigger.TrackOpens);
}

[Fact]
public async void Client_CanGetTagTrigger()
{
var trigger = await _client.CreateTagTriggerAsync(_triggerPrefix + "new-trigger" + DateTime.Now.Ticks);
var savedTrigger = await _client.GetTagTriggerAsync(trigger.ID);

Assert.NotNull(savedTrigger);
}

[Fact]
public async void Client_CanEditTagTrigger()
{
var trigger = await _client.CreateTagTriggerAsync(_triggerPrefix + "new-trigger" + DateTime.Now.Ticks, false);
var updatedTrigger = await _client.UpdateTagTriggerAsync(trigger.ID, _triggerPrefix + "updated" + DateTime.Now.Ticks, true);

Assert.NotEqual(trigger.MatchName, updatedTrigger.MatchName);
Assert.NotEqual(trigger.TrackOpens, updatedTrigger.TrackOpens);
}

[Fact]
public async void Client_CanDeleteTagTrigger()
{
var trigger = await _client.CreateTagTriggerAsync(_triggerPrefix + "new-trigger");
var result = await _client.DeleteTagTrigger(trigger.ID);

Assert.NotNull(result);
Assert.Equal(0, result.ErrorCode);
Assert.Equal(PostmarkStatus.Success, result.Status);
}

[Fact]
public async void Client_CanSearchTagTriggers()
{
var nameprefix = _triggerPrefix + "-tag-" + TESTING_DATE.ToString("o");
var names = Enumerable.Range(0, 10).Select(k => nameprefix + Guid.NewGuid()).ToArray();

var awaitables = names.Select(name => _client.CreateTagTriggerAsync(name));
var results = await Task.WhenAll(awaitables);

foreach (var name in names)
{
var result = (await _client.SearchTaggedTriggers(0, 100, name)).Tags;
Assert.Equal(name, result.Single().MatchName);
}

var allTriggers = await _client.SearchTaggedTriggers();
Assert.Equal(names.Count(), allTriggers.Tags.Count(k => k.MatchName.StartsWith(nameprefix)));
}

[Fact]
public async void Client_CanCreateInboundTrigger()
{
Expand Down
149 changes: 149 additions & 0 deletions src/Postmark.Tests/ClientWebhookTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
using Xunit;
using PostmarkDotNet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using PostmarkDotNet.Exceptions;
using PostmarkDotNet.Model;
using PostmarkDotNet.Model.Webhooks;

namespace Postmark.Tests
{
public class ClientWebhookTests : ClientBaseFixture, IDisposable
{
private PostmarkAdminClient _adminClient;
private PostmarkServer _server;

protected override void Setup()
{
_adminClient = new PostmarkAdminClient(WRITE_ACCOUNT_TOKEN, BASE_URL);
_server = _adminClient.CreateServerAsync($"integration-test-webhooks-{Guid.NewGuid()}").Result;
_client = new PostmarkClient(_server.ApiTokens.First(), BASE_URL);
}

[Fact]
public async Task ClientCanCreateConfiguration()
{
var url = "http://www.test.com/webhook";
var messageStream = "outbound";
var httpAuth = new HttpAuth { Username = "testUser", Password = "testPassword" };
var httpHeaders = new List<HttpHeader> { new HttpHeader { Name = "testName", Value = "testValue" } };
var triggers = new WebhookConfigurationTriggers
{
Bounce = new WebhookConfigurationBounceTrigger { Enabled = true, IncludeContent = true },
Click = new WebhookConfigurationClickTrigger { Enabled = true },
Open = new WebhookConfigurationOpenTrigger { Enabled = true, PostFirstOpenOnly = true },
Delivery = new WebhookConfigurationDeliveryTrigger { Enabled = true },
SpamComplaint = new WebhookConfigurationSpamComplaintTrigger { Enabled = true, IncludeContent = true }
};
var newConfiguration = await _client.CreateWebhookConfigurationAsync(url, messageStream, httpAuth, httpHeaders, triggers);

Assert.NotNull(newConfiguration.ID);
Assert.Equal(url, newConfiguration.Url);
Assert.Equal(messageStream, newConfiguration.MessageStream);
Assert.Equal(httpAuth.Username, newConfiguration.HttpAuth.Username);
Assert.Equal(httpAuth.Password, newConfiguration.HttpAuth.Password);
Assert.Equal(httpHeaders.First().Name, newConfiguration.HttpHeaders.First().Name);
Assert.Equal(httpHeaders.First().Value, newConfiguration.HttpHeaders.First().Value);
Assert.Equal(triggers.Bounce.Enabled, newConfiguration.Triggers.Bounce.Enabled);
Assert.Equal(triggers.Bounce.IncludeContent, newConfiguration.Triggers.Bounce.IncludeContent);
Assert.Equal(triggers.Open.Enabled, newConfiguration.Triggers.Open.Enabled);
Assert.Equal(triggers.Open.PostFirstOpenOnly, newConfiguration.Triggers.Open.PostFirstOpenOnly);
Assert.Equal(triggers.Click.Enabled, newConfiguration.Triggers.Click.Enabled);
Assert.Equal(triggers.Delivery.Enabled, newConfiguration.Triggers.Delivery.Enabled);
Assert.Equal(triggers.SpamComplaint.Enabled, newConfiguration.Triggers.SpamComplaint.Enabled);
Assert.Equal(triggers.SpamComplaint.IncludeContent, newConfiguration.Triggers.SpamComplaint.IncludeContent);
}

[Fact]
public async Task ClientCanGetWebhookConfiguration()
{
var url = "http://www.test123.com/webhook";

var expectedConfiguration = await _client.CreateWebhookConfigurationAsync(url);

var actualConfiguration = await _client.GetWebhookConfigurationAsync(expectedConfiguration.ID.Value);

Assert.Equal(expectedConfiguration.ID, actualConfiguration.ID);
Assert.Equal(expectedConfiguration.Url, actualConfiguration.Url);
Assert.Equal("outbound", actualConfiguration.MessageStream);
}

[Fact]
public async Task ClientCanListWebhookConfigurations()
{
var url1 = "http://www.test1.com/hook" + Guid.NewGuid();
var url2 = "http://www.test2.com/hook" + Guid.NewGuid();
await _client.CreateWebhookConfigurationAsync(url1);
await _client.CreateWebhookConfigurationAsync(url2);

var configurations = await _client.GetWebhookConfigurationsAsync();

Assert.Equal(2, configurations.Webhooks.Count());
Assert.Contains(configurations.Webhooks, k => k.Url == url1);
Assert.Contains(configurations.Webhooks, k => k.Url == url2);
}

[Fact]
public async Task ClientCanDeleteWebhookConfigurations()
{
var createdResponse = await _client.CreateWebhookConfigurationAsync("http://www.test.com/delete-hook");
var configuration = await _client.GetWebhookConfigurationAsync(createdResponse.ID.Value);

var response = await _client.DeleteWebhookConfigurationAsync(configuration.ID.Value);

Assert.Equal(PostmarkStatus.Success, response.Status);

await Assert.ThrowsAsync<PostmarkValidationException>(async () =>
await _client.GetWebhookConfigurationAsync(configuration.ID.Value));
}

[Fact]
public async Task ClientCanEditConfiguration()
{
var url = "http://www.test.com/webhook";
var messageStream = "outbound";
var httpAuth = new HttpAuth { Username = "testUser", Password = "testPassword" };
var httpHeaders = new List<HttpHeader> { new HttpHeader { Name = "testName", Value = "testValue" } };
var triggers = new WebhookConfigurationTriggers
{
Bounce = new WebhookConfigurationBounceTrigger { Enabled = true, IncludeContent = true },
Click = new WebhookConfigurationClickTrigger { Enabled = true },
};
var oldConfig = await _client.CreateWebhookConfigurationAsync(url, messageStream, httpAuth, httpHeaders, triggers);

var newUrl = "http://www.test.com/new-webhook";
var newHttpAuth = new HttpAuth { Username = "updatedUser", Password = "updatedPassword" };
var newHeaders = new List<HttpHeader>();
var triggersUpdate = new WebhookConfigurationTriggers
{
Click = new WebhookConfigurationClickTrigger { Enabled = false }
};
var updatedConfig = await _client.EditWebhookConfigurationAsync(oldConfig.ID.Value, newUrl, newHttpAuth,
newHeaders, triggersUpdate);

Assert.Equal(oldConfig.ID, updatedConfig.ID);
Assert.Equal(oldConfig.MessageStream, updatedConfig.MessageStream);
Assert.Equal(newHttpAuth.Username, updatedConfig.HttpAuth.Username);
Assert.Equal(newHttpAuth.Password, updatedConfig.HttpAuth.Password);
Assert.Equal(newUrl, updatedConfig.Url);
Assert.Equal(newHeaders, updatedConfig.HttpHeaders);
Assert.Equal(triggersUpdate.Click.Enabled, updatedConfig.Triggers.Click.Enabled);
Assert.Equal(triggers.Bounce.Enabled, updatedConfig.Triggers.Bounce.Enabled);
}

private Task Cleanup()
{
return Task.Run(async () =>
{
await _adminClient.DeleteServerAsync(_server.ID);
});
}

public void Dispose()
{
Cleanup().Wait();
}
}
}
10 changes: 1 addition & 9 deletions src/Postmark.Tests/Postmark.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,19 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputType>exe</OutputType>
</PropertyGroup>
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<OutputType>exe</OutputType>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
<ApplicationIcon />
<OutputTypeEx>exe</OutputTypeEx>
<OutputTypeEx>library</OutputTypeEx>
<StartupObject />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="*" />
<PackageReference Include="microsoft.testplatform.testhost" Version="*" />
<PackageReference Include="xunit" Version="*" />
<PackageReference Include="xunit.runner.visualstudio" Version="*" />
</ItemGroup>
Expand Down
10 changes: 0 additions & 10 deletions src/Postmark/Model/PostmarkTaggedTriggerInfo.cs

This file was deleted.

11 changes: 0 additions & 11 deletions src/Postmark/Model/PostmarkTaggedTriggerList.cs

This file was deleted.

12 changes: 12 additions & 0 deletions src/Postmark/Model/Webhooks/HttpAuth.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace PostmarkDotNet.Model.Webhooks
{
/// <summary>
/// Basic HTTP Authentication
/// </summary>
public class HttpAuth
{
public string Username { get; set; }

public string Password { get; set; }
}
}
12 changes: 12 additions & 0 deletions src/Postmark/Model/Webhooks/HttpHeader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace PostmarkDotNet.Model.Webhooks
{
/// <summary>
/// Custom HTTP Header
/// </summary>
public class HttpHeader
{
public string Name { get; set; }

public string Value { get; set; }
}
}
40 changes: 40 additions & 0 deletions src/Postmark/Model/Webhooks/WebhookConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System.Collections.Generic;

namespace PostmarkDotNet.Model.Webhooks
{
/// <summary>
/// The webhook configuration for a specific Server and Message Stream
/// </summary>
public class WebhookConfiguration
{
/// <summary>
/// ID of the webhook configuration.
/// </summary>
public long? ID { get; set; }

/// <summary>
/// The webhook URL
/// </summary>
public string Url { get; set; }

/// <summary>
/// MessageStream identifier that this configuration belongs to
/// </summary>
public string MessageStream { get; set; }

/// <summary>
/// Optional Basic HTTP Authentication credentials
/// </summary>
public HttpAuth HttpAuth { get; set; }

/// <summary>
/// Optional list of custom HttpHeaders to be included
/// </summary>
public IEnumerable<HttpHeader> HttpHeaders { get; set; } = new List<HttpHeader>();

/// <summary>
/// Configuration for the webhook triggers
/// </summary>
public WebhookConfigurationTriggers Triggers { get; set; }
}
}
18 changes: 18 additions & 0 deletions src/Postmark/Model/Webhooks/WebhookConfigurationBounceTrigger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
namespace PostmarkDotNet.Model.Webhooks
{
/// <summary>
/// Settings for Bounce webhooks
/// </summary>
public class WebhookConfigurationBounceTrigger
{
/// <summary>
/// Specifies whether or not webhooks will be triggered by Bounce events
/// </summary>
public bool Enabled { get; set; }

/// <summary>
/// Specifies whether or not the full content of the email bounce is included in webhook POST.
/// </summary>
public bool IncludeContent { get; set; }
}
}
Loading

0 comments on commit f7cfff8

Please sign in to comment.