diff --git a/Source/StrongGrid.UnitTests/Models/SingleSendTests.cs b/Source/StrongGrid.UnitTests/Models/SingleSendTests.cs new file mode 100644 index 00000000..8097d4de --- /dev/null +++ b/Source/StrongGrid.UnitTests/Models/SingleSendTests.cs @@ -0,0 +1,67 @@ +using Shouldly; +using StrongGrid.Json; +using StrongGrid.Models; +using System; +using System.Text.Json; +using Xunit; + +namespace StrongGrid.UnitTests.Models +{ + public class SingleSendTests + { + private const string SINGLE_SEND_JSON = @"{ + ""id"":""5e0555c5-cb50-11ee-a09e-6aa2ee6dcd4d"", + ""name"":""StrongGrid Unit Testing: single send"", + ""status"":""draft"", + ""categories"":[""category1"",""category2""], + ""send_at"":null, + ""send_to"":{ + ""list_ids"":[""a21d5383-1f7c-4e7a-bf2e-511467f58e7d""], + ""segment_ids"":[], + ""all"":false + }, + ""updated_at"":""2024-02-14T15:47:34Z"", + ""created_at"":""2024-02-14T15:47:33Z"", + ""email_config"":{ + ""subject"":""This is the subject"", + ""html_content"":""This is the HTML conytent"", + ""plain_content"":""This is the text content"", + ""generate_plain_content"":false, + ""editor"":""code"", + ""suppression_group_id"":54321, + ""custom_unsubscribe_url"":null, + ""sender_id"":12345, + ""ip_pool"":null + } + }"; + + [Fact] + public void Parse_processed_JSON() + { + // Arrange + + // Act + var result = JsonSerializer.Deserialize(SINGLE_SEND_JSON, JsonFormatter.DeserializerOptions); + + // Assert + result.Categories.ShouldBe(new[] { "category1", "category2" }); + result.EmailConfig.HtmlContent.ShouldBe("This is the HTML conytent"); + result.EmailConfig.IpPool.ShouldBeNull(); + result.EmailConfig.Subject.ShouldBe("This is the subject"); + result.EmailConfig.TextContent.ShouldBe("This is the text content"); + result.EmailConfig.CustomUnsubscribeUrl.ShouldBeNull(); + result.EmailConfig.EditorType.ShouldBe(EditorType.Code); + result.EmailConfig.GeneratePlainContent.ShouldBeFalse(); + result.EmailConfig.SenderId.ShouldBe(12345); + result.EmailConfig.SuppressionGroupId.ShouldBe(54321); + result.CreatedOn.ShouldBe(new DateTime(2024, 2, 14, 15, 47, 33, DateTimeKind.Utc)); + result.Id.ShouldBe("5e0555c5-cb50-11ee-a09e-6aa2ee6dcd4d"); + result.Recipients.Lists.ShouldBe(new[] { "a21d5383-1f7c-4e7a-bf2e-511467f58e7d" }); + result.Recipients.Segments.ShouldBe(Array.Empty()); + result.Name.ShouldBe("StrongGrid Unit Testing: single send"); + result.SendOn.ShouldBeNull(); + result.Status.ShouldBe(SingleSendStatus.Draft); + result.UpdatedOn.ShouldBe(new DateTime(2024, 2, 14, 15, 47, 34, DateTimeKind.Utc)); + } + } +} diff --git a/Source/StrongGrid/Json/EpochConverter.cs b/Source/StrongGrid/Json/EpochConverter.cs index 7f798b5d..ec0a4431 100644 --- a/Source/StrongGrid/Json/EpochConverter.cs +++ b/Source/StrongGrid/Json/EpochConverter.cs @@ -12,8 +12,14 @@ internal class EpochConverter : BaseJsonConverter { public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - var secondsSinceEpoch = reader.GetInt64(); - return secondsSinceEpoch.FromUnixTime(); + switch (reader.TokenType) + { + case JsonTokenType.Number: + var secondsSinceEpoch = reader.GetInt64(); + return secondsSinceEpoch.FromUnixTime(); + default: + throw new Exception($"Unable to convert {reader.TokenType.ToEnumString()} to DateTime"); + } } public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) diff --git a/Source/StrongGrid/Json/StrongGridJsonSerializerContext.cs b/Source/StrongGrid/Json/StrongGridJsonSerializerContext.cs index 26e2979c..0bcb9cdb 100644 --- a/Source/StrongGrid/Json/StrongGridJsonSerializerContext.cs +++ b/Source/StrongGrid/Json/StrongGridJsonSerializerContext.cs @@ -170,7 +170,7 @@ namespace StrongGrid.Json [JsonSerializable(typeof(StrongGrid.Models.SenderReputation))] [JsonSerializable(typeof(StrongGrid.Models.SingleSend))] [JsonSerializable(typeof(StrongGrid.Models.SingleSendEmailConfig))] - [JsonSerializable(typeof(StrongGrid.Models.SingleSendSendTo))] + [JsonSerializable(typeof(StrongGrid.Models.SingleSendRecipients))] [JsonSerializable(typeof(StrongGrid.Models.SingleSendStatus))] [JsonSerializable(typeof(StrongGrid.Models.SpamCheckingSettings))] [JsonSerializable(typeof(StrongGrid.Models.SpamCheckSettings))] @@ -378,7 +378,7 @@ namespace StrongGrid.Json [JsonSerializable(typeof(StrongGrid.Models.SenderReputation[]))] [JsonSerializable(typeof(StrongGrid.Models.SingleSend[]))] [JsonSerializable(typeof(StrongGrid.Models.SingleSendEmailConfig[]))] - [JsonSerializable(typeof(StrongGrid.Models.SingleSendSendTo[]))] + [JsonSerializable(typeof(StrongGrid.Models.SingleSendRecipients[]))] [JsonSerializable(typeof(StrongGrid.Models.SingleSendStatus[]))] [JsonSerializable(typeof(StrongGrid.Models.SpamCheckingSettings[]))] [JsonSerializable(typeof(StrongGrid.Models.SpamCheckSettings[]))] diff --git a/Source/StrongGrid/Models/SingleSend.cs b/Source/StrongGrid/Models/SingleSend.cs index 64072f1f..19d128d7 100644 --- a/Source/StrongGrid/Models/SingleSend.cs +++ b/Source/StrongGrid/Models/SingleSend.cs @@ -72,152 +72,15 @@ public class SingleSend public DateTime? CreatedOn { get; set; } /// - /// Gets or sets the subject. + /// Gets or sets the configuration about the email that will be sent to the recipients. /// - /// - /// The subject. - /// - [JsonIgnore] - public string Subject - { - get => EmailConfig.Subject; - set => EmailConfig.Subject = value; - } - - /// - /// Gets or sets the HTML content. - /// - /// - /// The HTML content. - /// - [JsonIgnore] - public string HtmlContent - { - get => EmailConfig.HtmlContent; - set => EmailConfig.HtmlContent = value; - } - - /// - /// Gets or sets the plain text content. - /// - /// - /// The plain text content. - /// - [JsonIgnore] - public string TextContent - { - get => EmailConfig.TextContent; - set => EmailConfig.TextContent = value; - } - - /// - /// Gets or sets a value indicating whether the plain content should be generated. - /// - /// - /// The generate_plain_content. - /// - [JsonIgnore] - public bool GeneratePlainContent - { - get => EmailConfig.GeneratePlainContent; - set => EmailConfig.GeneratePlainContent = value; - } - - /// - /// Gets or sets the type of editor used in the UI. - /// - /// - /// The type of editor. - /// - [JsonIgnore] - public EditorType EditorType - { - get => EmailConfig.EditorType; - set => EmailConfig.EditorType = value; - } - - /// - /// Gets or sets the sender identifier. - /// - /// - /// The sender identifier. - /// - [JsonIgnore] - public long SenderId - { - get => EmailConfig.SenderId; - set => EmailConfig.SenderId = value; - } - - /// - /// Gets or sets the custom unsubscribe URL. - /// - /// - /// The custom unsubscribe URL. - /// - [JsonIgnore] - public string CustomUnsubscribeUrl - { - get => EmailConfig.CustomUnsubscribeUrl; - set => EmailConfig.CustomUnsubscribeUrl = value; - } - - /// - /// Gets or sets the suppression group identifier. - /// - /// - /// The suppression group identifier. - /// - [JsonIgnore] - public long? SuppressionGroupId - { - get => EmailConfig.SuppressionGroupId; - set => EmailConfig.SuppressionGroupId = value; - } - - /// - /// Gets or sets the ip pool. - /// - /// - /// The ip pool. - /// - [JsonIgnore] - public string IpPool - { - get => EmailConfig.IpPool; - set => EmailConfig.IpPool = value; - } - - /// - /// Gets or sets the lists. - /// - /// - /// The lists. - /// - [JsonIgnore] - public string[] Lists - { - get => SendTo.Lists; - set => SendTo.Lists = value; - } + [JsonPropertyName("email_config")] + public SingleSendEmailConfig EmailConfig { get; set; } /// - /// Gets or sets the segments. + /// Gets or sets the information about who will receive this Single Send. /// - /// - /// The segments. - /// - [JsonIgnore] - public string[] Segments - { - get => SendTo.Segments; - set => SendTo.Segments = value; - } - - [JsonPropertyName("email_config")] - private SingleSendEmailConfig EmailConfig { get; set; } - [JsonPropertyName("send_to")] - private SingleSendSendTo SendTo { get; set; } + public SingleSendRecipients Recipients { get; set; } } } diff --git a/Source/StrongGrid/Models/SingleSendEmailConfig.cs b/Source/StrongGrid/Models/SingleSendEmailConfig.cs index d4426a34..42fae651 100644 --- a/Source/StrongGrid/Models/SingleSendEmailConfig.cs +++ b/Source/StrongGrid/Models/SingleSendEmailConfig.cs @@ -5,7 +5,7 @@ namespace StrongGrid.Models /// /// Single Send email config. /// - internal class SingleSendEmailConfig + public class SingleSendEmailConfig { /// /// Gets or sets the subject. diff --git a/Source/StrongGrid/Models/SingleSendSendTo.cs b/Source/StrongGrid/Models/SingleSendRecipients.cs similarity index 86% rename from Source/StrongGrid/Models/SingleSendSendTo.cs rename to Source/StrongGrid/Models/SingleSendRecipients.cs index 9a8e30fd..f6f8428b 100644 --- a/Source/StrongGrid/Models/SingleSendSendTo.cs +++ b/Source/StrongGrid/Models/SingleSendRecipients.cs @@ -3,9 +3,9 @@ namespace StrongGrid.Models { /// - /// Single Send send to. + /// The recipients of a Single Send. /// - internal class SingleSendSendTo + public class SingleSendRecipients { /// /// Gets or sets the lists. diff --git a/Source/StrongGrid/Resources/Mail.cs b/Source/StrongGrid/Resources/Mail.cs index e8dc9ce7..c4fd2766 100644 --- a/Source/StrongGrid/Resources/Mail.cs +++ b/Source/StrongGrid/Resources/Mail.cs @@ -150,9 +150,9 @@ public async Task SendAsync( foreach (var personalization in personalizationsCopy) { // Make sure the arrays are not null otherwise Linq's 'Except' method will throw a ArgumentNull exception (See GH-286). - if (personalization.To == null) personalization.To = Array.Empty(); - if (personalization.Cc == null) personalization.Cc = Array.Empty(); - if (personalization.Bcc == null) personalization.Bcc = Array.Empty(); + personalization.To ??= Array.Empty(); + personalization.Cc ??= Array.Empty(); + personalization.Bcc ??= Array.Empty(); // Avoid duplicate addresses. This is important because SendGrid does not throw any // exception when a recipient is duplicated (which gives you the impression the email diff --git a/build.cake b/build.cake index d1be6211..0dfa1487 100644 --- a/build.cake +++ b/build.cake @@ -2,8 +2,8 @@ #tool dotnet:?package=GitVersion.Tool&version=5.12.0 #tool dotnet:?package=coveralls.net&version=4.0.1 #tool nuget:https://f.feedz.io/jericho/jericho/nuget/?package=GitReleaseManager&version=0.17.0-collaborators0003 -#tool nuget:?package=ReportGenerator&version=5.2.0 -#tool nuget:?package=xunit.runner.console&version=2.6.6 +#tool nuget:?package=ReportGenerator&version=5.2.1 +#tool nuget:?package=xunit.runner.console&version=2.7.0 #tool nuget:?package=CodecovUploader&version=0.7.1 // Install addins. diff --git a/global.json b/global.json index f43378f6..667094ad 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.101", + "version": "8.0.201", "rollForward": "patch", "allowPrerelease": false }