diff --git a/src/ZendeskApi_v2/Requests/HelpCenter/Articles.cs b/src/ZendeskApi_v2/Requests/HelpCenter/Articles.cs index 38656801..3412ec5b 100644 --- a/src/ZendeskApi_v2/Requests/HelpCenter/Articles.cs +++ b/src/ZendeskApi_v2/Requests/HelpCenter/Articles.cs @@ -1,12 +1,15 @@ using System; using System.Collections.Generic; + #if ASYNC + using System.Threading.Tasks; + #endif + using ZendeskApi_v2.Extensions; using ZendeskApi_v2.Models.Articles; - namespace ZendeskApi_v2.Requests.HelpCenter { [Flags] @@ -19,39 +22,60 @@ public enum ArticleSideLoadOptionsEnum Translations = 16 } - public interface IArticles : ICore { #if SYNC + IndividualArticleResponse GetArticle(long articleId, ArticleSideLoadOptionsEnum sideloadOptions = ArticleSideLoadOptionsEnum.None); + GroupArticleResponse GetArticles(ArticleSideLoadOptionsEnum sideloadOptions = ArticleSideLoadOptionsEnum.None, ArticleSortingOptions options = null, int? perPage = null, int? page = null); + GroupArticleResponse GetArticlesByCategoryId(long categoryId, ArticleSideLoadOptionsEnum sideloadOptions = ArticleSideLoadOptionsEnum.None, ArticleSortingOptions options = null); + GroupArticleResponse GetArticlesBySectionId(long sectionId, ArticleSideLoadOptionsEnum sideloadOptions = ArticleSideLoadOptionsEnum.None, ArticleSortingOptions options = null); + GroupArticleResponse GetArticlesByUserId(long userId); + GroupArticleResponse GetArticlesSinceDateTime(DateTime startTime); + ArticleSearchResults SearchArticlesFor(string query, string category = "", string section = "", string labels = "", string locale = "", DateTime? createdBefore = null, DateTime? createdAfter = null, DateTime? createdAt = null, DateTime? updatedBefore = null, DateTime? updatedAfter = null, DateTime? updatedAt = null); + IndividualArticleResponse CreateArticle(long sectionId, Article article); + IndividualArticleResponse UpdateArticle(Article article); + bool DeleteArticle(long id); + #endif #if ASYNC + Task GetArticleAsync(long articleId, ArticleSideLoadOptionsEnum sideloadOptions = ArticleSideLoadOptionsEnum.None); + Task GetArticlesAsync(ArticleSideLoadOptionsEnum sideloadOptions = ArticleSideLoadOptionsEnum.None, ArticleSortingOptions options = null, int? perPage = null, int? page = null); + Task GetArticlesByCategoryIdAsync(long categoryId, ArticleSideLoadOptionsEnum sideloadOptions = ArticleSideLoadOptionsEnum.None, ArticleSortingOptions options = null); + Task GetArticlesBySectionIdAsync(long sectionId, ArticleSideLoadOptionsEnum sideloadOptions = ArticleSideLoadOptionsEnum.None, ArticleSortingOptions options = null); + Task GetArticlesByUserIdAsync(long userId); + Task GetArticlesSinceDateTimeAsync(DateTime startTime); + Task SearchArticlesForAsync(string query, string category = "", string section = "", string labels = "", string locale = "", DateTime? createdBefore = null, DateTime? createdAfter = null, DateTime? createdAt = null, DateTime? updatedBefore = null, DateTime? updatedAfter = null, DateTime? updatedAt = null); + Task CreateArticleAsync(long sectionId, Article article); + Task UpdateArticleAsync(Article article); + Task DeleteArticleAsync(long id); -#endif +#endif } public class Articles : Core, IArticles { private readonly string urlPrefix = "help_center"; + public Articles(string yourZendeskUrl, string user, string password, string apiToken, string p_OAuthToken, string locale) : base(yourZendeskUrl, user, password, apiToken, p_OAuthToken) { @@ -62,6 +86,7 @@ public Articles(string yourZendeskUrl, string user, string password, string apiT } #if SYNC + public IndividualArticleResponse GetArticle(long articleId, ArticleSideLoadOptionsEnum sideloadOptions = ArticleSideLoadOptionsEnum.None) { var resourceUrl = this.GetFormattedArticleUri($"{urlPrefix}/articles/{articleId}.json", sideloadOptions); @@ -91,6 +116,7 @@ public GroupArticleResponse GetArticlesBySectionId(long sectionId, ArticleSideLo return GenericGet(resourceUrl); } + public GroupArticleResponse GetArticlesByUserId(long userId) { return GenericGet($"help_center/users/{userId}/articles.json"); @@ -124,8 +150,10 @@ public bool DeleteArticle(long id) { return GenericDelete($"help_center/articles/{id}.json"); } + #endif #if ASYNC + public async Task GetArticleAsync(long articleId, ArticleSideLoadOptionsEnum sideloadOptions = ArticleSideLoadOptionsEnum.None) { var resourceUrl = this.GetFormattedArticleUri($"{urlPrefix}/articles/{articleId}.json", sideloadOptions); @@ -169,7 +197,7 @@ public async Task GetArticlesSinceDateTimeAsync(DateTime s public async Task SearchArticlesForAsync(string query, string category = "", string section = "", string labels = "", string locale = "", DateTime? createdBefore = null, DateTime? createdAfter = null, DateTime? createdAt = null, DateTime? updatedBefore = null, DateTime? updatedAfter = null, DateTime? updatedAt = null) { var querystringParams = new Dictionary { { "category", category }, { "section", section }, { "label_names", labels }, - { "locale", locale },{ "created_before", $"{createdBefore.Value:yyyy-MM-dd}" }, {"created_after" , $"{createdAfter:yyyy-MM-dd}" }, + { "locale", locale },{ "created_before", $"{createdBefore:yyyy-MM-dd}" }, {"created_after" , $"{createdAfter:yyyy-MM-dd}" }, { "created_at", $"{createdAt:yyyy-MM-dd}"}, { "updated_before", $"{updatedBefore:yyyy-MM-dd}"}, {"updated_after" , $"{updatedAfter:yyyy-MM-dd}" }, { "updated_at", $"{updatedAt:yyyy-MM-dd}"} }; @@ -190,6 +218,7 @@ public async Task DeleteArticleAsync(long id) { return await GenericDeleteAsync($"help_center/articles/{id}.json"); } + #endif private string GetFormattedArticlesUri(string resourceUrl, ArticleSortingOptions options, ArticleSideLoadOptionsEnum sideloadOptions) @@ -222,7 +251,6 @@ private string GetFormattedArticlesUri(string resourceUrl, ArticleSortingOptions private string GetFormattedArticleUri(string resourceUrl, ArticleSideLoadOptionsEnum sideloadOptions) { - var sideLoads = sideloadOptions.ToString().ToLower().Replace(" ", ""); if (sideloadOptions != ArticleSideLoadOptionsEnum.None) { @@ -239,4 +267,4 @@ private string GetFormattedArticleUri(string resourceUrl, ArticleSideLoadOptions return resourceUrl; } } -} \ No newline at end of file +} diff --git a/test/ZendeskApi_v2.Test/GlobalSuppressions.cs b/test/ZendeskApi_v2.Test/GlobalSuppressions.cs new file mode 100644 index 00000000..8910cd21 --- /dev/null +++ b/test/ZendeskApi_v2.Test/GlobalSuppressions.cs @@ -0,0 +1,7 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Security", "SEC0112:Path Tampering Unvalidated File Path", Justification = "Unit Test", Scope = "type", Target = "Tests.UserTests")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Security", "SEC0112:Path Tampering Unvalidated File Path", Justification = "Unit Test", Scope = "type", Target = "Tests.TicketTests")] diff --git a/test/ZendeskApi_v2.Test/HelpCenter/ArticleTests.cs b/test/ZendeskApi_v2.Test/HelpCenter/ArticleTests.cs index f2d6697f..f330c8e1 100644 --- a/test/ZendeskApi_v2.Test/HelpCenter/ArticleTests.cs +++ b/test/ZendeskApi_v2.Test/HelpCenter/ArticleTests.cs @@ -48,7 +48,6 @@ public void CanGetArticles() Assert.That(res1.Articles[0].SectionId, Is.EqualTo(202119686)); } - #region Sideloaded Content public void CanGetArticleSideloadedWith() { var res = api.HelpCenter.Articles.GetArticles(ArticleSideLoadOptionsEnum.Sections | ArticleSideLoadOptionsEnum.Categories | ArticleSideLoadOptionsEnum.Users); @@ -139,7 +138,6 @@ public void CanGetArticlesSortedInACategory() Assert.IsTrue(articlesAscending.Articles[0].Title != articlesDescending.Articles[0].Title); } - #endregion [Test] public void CanCreateUpdateAndDeleteArticles() @@ -232,7 +230,7 @@ public async Task TestCaseForIssue220() Section section = (await apiForUser2.HelpCenter.Sections.GetSectionByIdAsync(responsSection.Section.Id.Value)).Section; - // user 2 is a member of the testing tag so we should get the section + // user 2 is a member of the testing tag so we should get the section Assert.That(section, Is.Not.Null); responsSection.Section.AccessPolicy = new AccessPolicy { ViewableBy = ViewableBy.signed_in_users, RequiredTags = new List { "monkey" } }; @@ -256,7 +254,6 @@ public async Task CanGetSecondPageUisngGetByPageUrl() var resp = await api.HelpCenter.Articles.GetByPageUrlAsync(res.NextPage, pageSize); Assert.That(resp.Page, Is.EqualTo(2)); - } [Test] @@ -275,4 +272,4 @@ public void CanSearchForArticles() Assert.That(resp.Count, Is.GreaterThan(0)); } } -} \ No newline at end of file +} diff --git a/test/ZendeskApi_v2.Test/TicketTests.cs b/test/ZendeskApi_v2.Test/TicketTests.cs index b13676a1..ba324a5d 100644 --- a/test/ZendeskApi_v2.Test/TicketTests.cs +++ b/test/ZendeskApi_v2.Test/TicketTests.cs @@ -635,11 +635,13 @@ public async Task CanAddAttachmentToTicketAsync() [Test] public void CanAddAttachmentToTicket() { + var path = Path.Combine(TestContext.CurrentContext.TestDirectory, "testupload.txt"); + var res = api.Attachments.UploadAttachment(new ZenFile() { ContentType = "text/plain", FileName = "testupload.txt", - FileData = File.ReadAllBytes(TestContext.CurrentContext.TestDirectory + "\\testupload.txt") + FileData = File.ReadAllBytes(path) }); var ticket = new Ticket() diff --git a/test/ZendeskApi_v2.Test/TriggerTests.cs b/test/ZendeskApi_v2.Test/TriggerTests.cs index 8e074922..f011fbb5 100644 --- a/test/ZendeskApi_v2.Test/TriggerTests.cs +++ b/test/ZendeskApi_v2.Test/TriggerTests.cs @@ -25,7 +25,6 @@ public void Init() } } - [Test] public void CanGetTriggers() { @@ -33,7 +32,7 @@ public void CanGetTriggers() Assert.Greater(res.Count, 0); var ind = api.Triggers.GetTriggerById(res.Triggers[0].Id.Value); - Assert.AreEqual(ind.Trigger.Id, res.Triggers[0].Id); + Assert.AreEqual(ind.Trigger.Id, res.Triggers[0].Id); } [Test] @@ -56,7 +55,7 @@ public void CanCreateUpdateAndDeleteTriggers() Assert.Greater(res.Trigger.Id, 0); res.Trigger.Title = "Test Trigger Updated"; - var update = api.Triggers.UpdateTrigger(res.Trigger); + var update = api.Triggers.UpdateTrigger(res.Trigger); Assert.AreEqual(update.Trigger.Title, res.Trigger.Title); Assert.True(api.Triggers.DeleteTrigger(res.Trigger.Id.Value)); @@ -65,25 +64,25 @@ public void CanCreateUpdateAndDeleteTriggers() [Test] public void CanReorderTriggers() { - var res = api.Triggers.GetActiveTriggers().Triggers; + var res = api.Triggers.GetActiveTriggers().Triggers; Assert.AreEqual(res.Count(), 0); var trigger = new Trigger() { - Title = "Test Trigger1", - Active = true, + Title = "Test Trigger1", + Active = true, Conditions = new Conditions() { All = new List() { new All() { Field = "status", Operator = "is", Value = "open" } }, Any = new List() }, - Actions = new List() { new Action() { Field = "group_id", Value = "20402842" } }, - Position = 5000 + Actions = new List() { new Action() { Field = "group_id", Value = "20402842" } }, + Position = 5000 }; var trigger2 = new Trigger() { - Title = "Test Trigger2", - Active = true, + Title = "Test Trigger2", + Active = true, Conditions = new Conditions() { All = new List() { new All() { Field = "status", Operator = "is", Value = "open" } }, Any = new List() }, - Actions = new List() { new Action() { Field = "group_id", Value = "20402842" } }, - Position = 6000 + Actions = new List() { new Action() { Field = "group_id", Value = "20402842" } }, + Position = 6000 }; var res2 = api.Triggers.CreateTrigger(trigger); @@ -101,4 +100,4 @@ public void CanReorderTriggers() Assert.True(api.Triggers.DeleteTrigger(res3.Trigger.Id.Value)); } } -} \ No newline at end of file +} diff --git a/test/ZendeskApi_v2.Test/UserTests.cs b/test/ZendeskApi_v2.Test/UserTests.cs index dc939582..92d6a69c 100644 --- a/test/ZendeskApi_v2.Test/UserTests.cs +++ b/test/ZendeskApi_v2.Test/UserTests.cs @@ -16,7 +16,7 @@ namespace Tests [Category("Users")] public class UserTests { - ZendeskApi api = new ZendeskApi(Settings.Site, Settings.AdminEmail, Settings.AdminPassword); + private ZendeskApi api = new ZendeskApi(Settings.Site, Settings.AdminEmail, Settings.AdminPassword); [Test] public void CanGetUsers() @@ -24,7 +24,7 @@ public void CanGetUsers() var res = api.Users.GetAllUsers(); Assert.True(res.Count > 0); } - + [Test] public void CanGetAgents() { @@ -99,7 +99,7 @@ public void CanCreateUpdateSuspendAndDeleteUser() var list = api.Users.GetAllUsers(); var users = list.Users.Where(x => x.Email == "test772@tester.com"); - foreach(var u in users) + foreach (var u in users) { api.Users.DeleteUser(u.Id.Value); } @@ -130,7 +130,6 @@ public void CanCreateUpdateSuspendAndDeleteUser() var blah = api.Users.GetUser(res1.User.Id.Value); Assert.AreEqual(res1.User.Phone, res2.User.Phone); - var res3 = api.Users.SuspendUser(res2.User.Id.Value); Assert.IsTrue(res3.User.Suspended); @@ -292,31 +291,34 @@ public void CanGetMultipleUsersAsync() [Test] public void CanSetUserPhoto() { + var path = Path.Combine(TestContext.CurrentContext.TestDirectory, "gracehoppertocat3.jpg"); + var file = new ZenFile() { ContentType = "image/jpeg", FileName = "gracehoppertocat3.jpg", - FileData = File.ReadAllBytes(TestContext.CurrentContext.TestDirectory + "\\gracehoppertocat3.jpg") + FileData = File.ReadAllBytes(path) }; var user = api.Users.SetUserPhoto(Settings.UserId, file); Assert.That(user.User.Photo.ContentUrl, Is.Not.Null); - Assert.That(user.User.Photo.Size, Is.EqualTo(6553)); + Assert.That(user.User.Photo.Size, Is.Not.Zero); } [Test] public async Task CanSetUserPhotoAsync() { + var path = Path.Combine(TestContext.CurrentContext.TestDirectory, "gracehoppertocat3.jpg"); var file = new ZenFile() { ContentType = "image/jpeg", FileName = "gracehoppertocat3.jpg", - FileData = File.ReadAllBytes(TestContext.CurrentContext.TestDirectory + "\\gracehoppertocat3.jpg") + FileData = File.ReadAllBytes(path) }; var user = await api.Users.SetUserPhotoAsync(Settings.UserId, file); Assert.That(user.User.Photo.ContentUrl, Is.Not.Null); - Assert.That(user.User.Photo.Size, Is.EqualTo(6553)); + Assert.That(user.User.Photo.Size, Is.Not.Zero); } [Test]