From 14c10b801600a9a10b413cb79cfcc15116062719 Mon Sep 17 00:00:00 2001 From: Kirill Kondratyuk Date: Tue, 28 Aug 2018 14:28:35 +0300 Subject: [PATCH 1/6] Update template function --- src/SparkPost/ITemplates.cs | 9 +++++++++ src/SparkPost/Templates.cs | 20 ++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/SparkPost/ITemplates.cs b/src/SparkPost/ITemplates.cs index c3cf8302..d1df7acc 100644 --- a/src/SparkPost/ITemplates.cs +++ b/src/SparkPost/ITemplates.cs @@ -25,5 +25,14 @@ public interface ITemplates Task List(); Task Delete(string templateId); + + /// + /// Updates an email template. + /// + /// The id of the template to update. + /// The properties of the template to update. Exclude ID from update + /// If true, updates the most recent published template. If the query param is not passed or set to false, it will result in an update to the draft version. + /// The response from the API. + Task Update(string templateId, Template template, bool? updatePublished = null); } } diff --git a/src/SparkPost/Templates.cs b/src/SparkPost/Templates.cs index c12a17bb..45a1f5fd 100644 --- a/src/SparkPost/Templates.cs +++ b/src/SparkPost/Templates.cs @@ -147,5 +147,25 @@ public async Task Delete(string templateId) var response = await requestSender.Send(request); return response.StatusCode == HttpStatusCode.OK; } + + public async Task Update(string templateId, Template template, bool? updatePublished = null) + { + var request = new Request + { + Url = $"api/{client.Version}/templates/{templateId}", + Method = "PUT", + Data = dataMapper.ToDictionary(template) + }; + + if (updatePublished != null) + { + string updatePublishedValue = updatePublished.ToString().ToLower(); + request.Url += $"?update_published={updatePublishedValue}"; + } + + var response = await requestSender.Send(request); + if (response.StatusCode != HttpStatusCode.OK) throw new ResponseException(response); + return true; + } } } From 020005a6ec49bba71744b9cd641cf899228a6f77 Mon Sep 17 00:00:00 2001 From: Kirill Kondratyuk Date: Tue, 28 Aug 2018 15:50:39 +0300 Subject: [PATCH 2/6] Create model for update templates --- src/SparkPost/DataMapper.cs | 6 ++++++ src/SparkPost/ITemplates.cs | 4 ++-- src/SparkPost/Template.cs | 20 ++++++++++++++++++-- src/SparkPost/Templates.cs | 2 +- 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/SparkPost/DataMapper.cs b/src/SparkPost/DataMapper.cs index ba94e6c0..fdfa1da2 100644 --- a/src/SparkPost/DataMapper.cs +++ b/src/SparkPost/DataMapper.cs @@ -34,6 +34,7 @@ public interface IDataMapper IDictionary ToDictionaryMethods(); IDictionary ToDictionary(RecipientList recipientList); IDictionary ToDictionary(Template template); + IDictionary ToDictionary(TemplateUpdate template); IDictionary ToDictionary(TemplateContent templateContent); IDictionary ToDictionary(TemplateOptions templateOptions); IDictionary ToDictionary(MetricsQuery query); @@ -214,6 +215,11 @@ public virtual IDictionary ToDictionary(Template template) return WithCommonConventions(template); } + public virtual IDictionary ToDictionary(TemplateUpdate template) + { + return WithCommonConventions(template); + } + public virtual IDictionary ToDictionary(TemplateContent templateContent) { return WithCommonConventions(templateContent); diff --git a/src/SparkPost/ITemplates.cs b/src/SparkPost/ITemplates.cs index d1df7acc..dd483ac2 100644 --- a/src/SparkPost/ITemplates.cs +++ b/src/SparkPost/ITemplates.cs @@ -30,9 +30,9 @@ public interface ITemplates /// Updates an email template. /// /// The id of the template to update. - /// The properties of the template to update. Exclude ID from update + /// The properties of the template to update (exclude ID from update) /// If true, updates the most recent published template. If the query param is not passed or set to false, it will result in an update to the draft version. /// The response from the API. - Task Update(string templateId, Template template, bool? updatePublished = null); + Task Update(string templateId, TemplateUpdate template, bool? updatePublished = null); } } diff --git a/src/SparkPost/Template.cs b/src/SparkPost/Template.cs index d94e50bc..f2b8b35e 100644 --- a/src/SparkPost/Template.cs +++ b/src/SparkPost/Template.cs @@ -21,11 +21,27 @@ public class TemplateListItem : TemplateBase public DateTime LastUpdateTime { get; set; } } - public class TemplateBase + public class TemplateBase : TemplateInfo { public string Id { get; set; } + } + + public class TemplateInfo + { public string Name { get; set; } - public string Description { get; set; } public bool Published { get; set; } + public string Description { get; set; } + } + + public class TemplateUpdate : TemplateInfo + { + public TemplateUpdate() + { + Content = new TemplateContent(); + Options = new TemplateOptions(); + } + + public TemplateContent Content { get; set; } + public TemplateOptions Options { get; set; } } } diff --git a/src/SparkPost/Templates.cs b/src/SparkPost/Templates.cs index 45a1f5fd..8d327aef 100644 --- a/src/SparkPost/Templates.cs +++ b/src/SparkPost/Templates.cs @@ -148,7 +148,7 @@ public async Task Delete(string templateId) return response.StatusCode == HttpStatusCode.OK; } - public async Task Update(string templateId, Template template, bool? updatePublished = null) + public async Task Update(string templateId, TemplateUpdate template, bool? updatePublished = null) { var request = new Request { From 972fb99657ab8448a076c22894d44f968aa8496b Mon Sep 17 00:00:00 2001 From: Kirill Kondratyuk Date: Tue, 28 Aug 2018 16:17:04 +0300 Subject: [PATCH 3/6] Revert "Create model for update templates" This reverts commit 020005a6ec49bba71744b9cd641cf899228a6f77. --- src/SparkPost/DataMapper.cs | 6 ------ src/SparkPost/ITemplates.cs | 4 ++-- src/SparkPost/Template.cs | 20 ++------------------ src/SparkPost/Templates.cs | 2 +- 4 files changed, 5 insertions(+), 27 deletions(-) diff --git a/src/SparkPost/DataMapper.cs b/src/SparkPost/DataMapper.cs index fdfa1da2..ba94e6c0 100644 --- a/src/SparkPost/DataMapper.cs +++ b/src/SparkPost/DataMapper.cs @@ -34,7 +34,6 @@ public interface IDataMapper IDictionary ToDictionaryMethods(); IDictionary ToDictionary(RecipientList recipientList); IDictionary ToDictionary(Template template); - IDictionary ToDictionary(TemplateUpdate template); IDictionary ToDictionary(TemplateContent templateContent); IDictionary ToDictionary(TemplateOptions templateOptions); IDictionary ToDictionary(MetricsQuery query); @@ -215,11 +214,6 @@ public virtual IDictionary ToDictionary(Template template) return WithCommonConventions(template); } - public virtual IDictionary ToDictionary(TemplateUpdate template) - { - return WithCommonConventions(template); - } - public virtual IDictionary ToDictionary(TemplateContent templateContent) { return WithCommonConventions(templateContent); diff --git a/src/SparkPost/ITemplates.cs b/src/SparkPost/ITemplates.cs index dd483ac2..d1df7acc 100644 --- a/src/SparkPost/ITemplates.cs +++ b/src/SparkPost/ITemplates.cs @@ -30,9 +30,9 @@ public interface ITemplates /// Updates an email template. /// /// The id of the template to update. - /// The properties of the template to update (exclude ID from update) + /// The properties of the template to update. Exclude ID from update /// If true, updates the most recent published template. If the query param is not passed or set to false, it will result in an update to the draft version. /// The response from the API. - Task Update(string templateId, TemplateUpdate template, bool? updatePublished = null); + Task Update(string templateId, Template template, bool? updatePublished = null); } } diff --git a/src/SparkPost/Template.cs b/src/SparkPost/Template.cs index f2b8b35e..d94e50bc 100644 --- a/src/SparkPost/Template.cs +++ b/src/SparkPost/Template.cs @@ -21,27 +21,11 @@ public class TemplateListItem : TemplateBase public DateTime LastUpdateTime { get; set; } } - public class TemplateBase : TemplateInfo + public class TemplateBase { public string Id { get; set; } - } - - public class TemplateInfo - { public string Name { get; set; } - public bool Published { get; set; } public string Description { get; set; } - } - - public class TemplateUpdate : TemplateInfo - { - public TemplateUpdate() - { - Content = new TemplateContent(); - Options = new TemplateOptions(); - } - - public TemplateContent Content { get; set; } - public TemplateOptions Options { get; set; } + public bool Published { get; set; } } } diff --git a/src/SparkPost/Templates.cs b/src/SparkPost/Templates.cs index 8d327aef..45a1f5fd 100644 --- a/src/SparkPost/Templates.cs +++ b/src/SparkPost/Templates.cs @@ -148,7 +148,7 @@ public async Task Delete(string templateId) return response.StatusCode == HttpStatusCode.OK; } - public async Task Update(string templateId, TemplateUpdate template, bool? updatePublished = null) + public async Task Update(string templateId, Template template, bool? updatePublished = null) { var request = new Request { From e900353fbf545ec3d287cad3ff803cae9ed34318 Mon Sep 17 00:00:00 2001 From: jgunter7 <9407707+jgunter7@users.noreply.github.com> Date: Tue, 28 May 2019 13:37:03 -0400 Subject: [PATCH 4/6] Add has_draft + has_published feature --- src/SparkPost/RetrieveTemplateResponse.cs | 2 ++ src/SparkPost/Template.cs | 2 ++ src/SparkPost/Templates.cs | 6 +++++- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/SparkPost/RetrieveTemplateResponse.cs b/src/SparkPost/RetrieveTemplateResponse.cs index f1ce051b..f60ff527 100644 --- a/src/SparkPost/RetrieveTemplateResponse.cs +++ b/src/SparkPost/RetrieveTemplateResponse.cs @@ -18,6 +18,8 @@ public RetrieveTemplateResponse() public string Name { get; set; } public string Description { get; set; } public bool Published { get; set; } + public bool HasDraft { get; set; } + public bool HasPublished { get; set; } public DateTime LastUpdateTime { get; set; } public DateTime? LastUse { get; set; } public TemplateOptions Options { get; set; } diff --git a/src/SparkPost/Template.cs b/src/SparkPost/Template.cs index d94e50bc..bf5ae3c9 100644 --- a/src/SparkPost/Template.cs +++ b/src/SparkPost/Template.cs @@ -27,5 +27,7 @@ public class TemplateBase public string Name { get; set; } public string Description { get; set; } public bool Published { get; set; } + public bool HasDraft { get; set; } + public bool HasPublished { get; set; } } } diff --git a/src/SparkPost/Templates.cs b/src/SparkPost/Templates.cs index 45a1f5fd..656bef97 100644 --- a/src/SparkPost/Templates.cs +++ b/src/SparkPost/Templates.cs @@ -81,6 +81,8 @@ public async Task Retrieve(string templateId, bool? dr Published = results.published, LastUpdateTime = results.last_update_time, LastUse = (results.last_use == null) ? null : results.last_use, + HasDraft = results.has_draft, + HasPublished = results.has_published, Options = new TemplateOptions() { ClickTracking = results.options.click_tracking, @@ -124,7 +126,9 @@ public async Task List() Name = result.name, LastUpdateTime = result.last_update_time, Description = result.description, - Published = result.published + Published = result.published, + HasDraft = result.has_draft, + HasPublished = result.has_published }); return new RetrieveTemplatesResponse From fae19dd6c9e0b92f9c148a902ba2a7ee6dcf701f Mon Sep 17 00:00:00 2001 From: Jason Gunter Date: Wed, 29 May 2019 09:33:19 -0400 Subject: [PATCH 5/6] added unit tests for has_draft and update template --- src/SparkPost.Tests/DataMapperTests.cs | 51 +++++ src/SparkPost.Tests/SparkPost.Tests.csproj | 1 + src/SparkPost.Tests/TemplateTests.cs | 207 +++++++++++++++++++++ src/SparkPost/Templates.cs | 24 ++- 4 files changed, 276 insertions(+), 7 deletions(-) create mode 100644 src/SparkPost.Tests/TemplateTests.cs diff --git a/src/SparkPost.Tests/DataMapperTests.cs b/src/SparkPost.Tests/DataMapperTests.cs index 3a6e54e3..9faa1f18 100644 --- a/src/SparkPost.Tests/DataMapperTests.cs +++ b/src/SparkPost.Tests/DataMapperTests.cs @@ -1307,5 +1307,56 @@ public void limit() Assert.That(dict["limit"].CastTo(), Is.EqualTo(r)); } } + + [TestFixture] + public class TemplateMappingTests + { + private DataMapper _mapper; + private Template _template; + + [SetUp] + public void Setup() + { + _template = new Template(); + _mapper = new DataMapper("v1"); + } + + [Test] + public void has_draft() + { + bool hasDraftValue = false; + _template.HasDraft = hasDraftValue; + var dict = _mapper.ToDictionary(_template); + Assert.AreEqual(hasDraftValue, dict["has_draft"]); + } + + [Test] + public void has_published() + { + bool value = true; + _template.HasPublished = value; + var dict = _mapper.ToDictionary(_template); + Assert.AreEqual(value, dict["has_published"]); + } + + [Test] + public void has_option_click_tracking() + { + bool value = true; + _template.Options.ClickTracking = value; + var dict = _mapper.ToDictionary(_template); + var optionsDict = (Dictionary)dict["options"]; + Assert.AreEqual(value, optionsDict["click_tracking"]); + } + + [Test] + [ExpectedException(typeof(KeyNotFoundException))] + public void has_option_click_tracking_null() + { + var dict = _mapper.ToDictionary(_template); + var optionsDict = (Dictionary)dict["options"]; + Assert.AreEqual(true, optionsDict["click_tracking"]); + } + } } } \ No newline at end of file diff --git a/src/SparkPost.Tests/SparkPost.Tests.csproj b/src/SparkPost.Tests/SparkPost.Tests.csproj index 5a2d99f7..d002a6e0 100644 --- a/src/SparkPost.Tests/SparkPost.Tests.csproj +++ b/src/SparkPost.Tests/SparkPost.Tests.csproj @@ -117,6 +117,7 @@ + diff --git a/src/SparkPost.Tests/TemplateTests.cs b/src/SparkPost.Tests/TemplateTests.cs new file mode 100644 index 00000000..4c95f424 --- /dev/null +++ b/src/SparkPost.Tests/TemplateTests.cs @@ -0,0 +1,207 @@ +using AutoMoq.Helpers; +using Moq; +using NUnit.Framework; +using Should; +using SparkPost.RequestSenders; +using System; +using System.Collections.Generic; +using System.Net; +using System.Threading.Tasks; + +namespace SparkPost.Tests +{ + public class TemplateTests + { + [TestFixture] + public class DeleteTests : AutoMoqTestFixture + { + private Response _response; + private Template _template; + + [SetUp] + public void Setup() + { + ResetSubject(); + + _response = new Response { StatusCode = HttpStatusCode.NoContent }; + + Mocked() + .Setup(x => x.Send(It.IsAny())) + .Returns(Task.FromResult(_response)); + + _template = new Template() + { + Id = Guid.NewGuid().ToString() + }; + } + + [Test] + public async void It_should_return_false_if_the_status_is_not_ok() + { + var result = await Subject.Delete(_template.Id); + result.ShouldBeFalse(); + } + + [Test] + public async void It_should_return_false_if_the_web_request_returns_anything_but_no_content() + { + _response.StatusCode = HttpStatusCode.Accepted; + (await Subject.Delete(_template.Id)).ShouldBeFalse(); + + _response.StatusCode = HttpStatusCode.Ambiguous; + (await Subject.Delete(_template.Id)).ShouldBeFalse(); + + _response.StatusCode = HttpStatusCode.UpgradeRequired; + (await Subject.Delete(_template.Id)).ShouldBeFalse(); + } + + [Test] + public async void It_should_build_the_web_request_parameters_correctly() + { + var version = Guid.NewGuid().ToString(); + + Mocked() + .Setup(x => x.Version) + .Returns(version); + + Mocked() + .Setup(x => x.Send(It.IsAny())) + .Callback((Request r) => + { + r.Url.ShouldEqual($"api/{version}/templates/{_template.Id}"); + r.Method.ShouldEqual("DELETE"); + }) + .Returns(Task.FromResult(_response)); + + await Subject.Delete(_template.Id); + } + } + + [TestFixture] + public class CreateOrUpdateTests : AutoMoqTestFixture + { + private Response _response; + private List