From 20428706372983507a3cbe973894e6bd2925b1d3 Mon Sep 17 00:00:00 2001 From: raj pandey Date: Tue, 23 Sep 2025 18:02:47 +0530 Subject: [PATCH 1/3] Feat: Added Support for AWS AU Region, Version bump and Test case Fixes --- CHANGELOG.md | 6 ++++++ Contentstack.Core.Tests/EntryTest.cs | 2 +- Contentstack.Core.Tests/QueryTest.cs | 20 +++++++++---------- Contentstack.Core/Configuration/Config.cs | 2 +- .../Internals/ContentstackRegion.cs | 11 ++++++++-- .../Internals/HttpRequestHandler.cs | 2 +- Directory.Build.props | 2 +- 7 files changed, 29 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d30baa..171471c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +### Version: 2.24.0 +#### Date: Sep-29-2025 + +##### Feat: +- Added Support For AWS-AU Region + ### Version: 2.23.0 #### Date: Aug-05-2025 diff --git a/Contentstack.Core.Tests/EntryTest.cs b/Contentstack.Core.Tests/EntryTest.cs index f7f7778..8f80222 100644 --- a/Contentstack.Core.Tests/EntryTest.cs +++ b/Contentstack.Core.Tests/EntryTest.cs @@ -339,7 +339,7 @@ public async Task GetHTMLText() { ContentType contenttype = client.ContentType(source); - string uid = await GetUID("source"); + string uid = await GetUID("source1"); Entry sourceEntry = contenttype.Entry(uid); var result = await sourceEntry.Fetch(); diff --git a/Contentstack.Core.Tests/QueryTest.cs b/Contentstack.Core.Tests/QueryTest.cs index d5a2a06..2ec98ee 100644 --- a/Contentstack.Core.Tests/QueryTest.cs +++ b/Contentstack.Core.Tests/QueryTest.cs @@ -174,7 +174,7 @@ public async Task GreaterThanForNumber() public async Task GreaterThanForDate() { Query query = client.ContentType(source).Query(); - query.GreaterThan("date", "2018-05-04"); + query.GreaterThan("date", "2015-05-03"); var result = await query.Find(); if (result == null && result.Items.Count() == 0) { @@ -188,7 +188,7 @@ public async Task GreaterThanForDate() bool IsTrue = false; foreach (var data in result.Items) { - IsTrue = DateTime.Compare(DateTime.Parse(Convert.ToString(data.Date)), DateTime.Parse("2018-05-04")) > 0; + IsTrue = DateTime.Compare(DateTime.Parse(Convert.ToString(data.Date)), DateTime.Parse("2015-05-03")) > 0; if (!IsTrue) break; @@ -291,14 +291,14 @@ public async Task LessThanForDate() { Query query = client.ContentType(source).Query(); - query.LessThan("date", "2018-05-04"); + query.LessThan("date", "2025-05-04"); var result = await query.Find(); if (result.Items != null) { bool IsTrue = false; foreach (var data in result.Items) { - DateTime dateToCompareWith = DateTime.Parse("2018-05-04"); + DateTime dateToCompareWith = DateTime.Parse("2025-05-04"); DateTime dateToCompare = DateTime.Parse(Convert.ToString(data.Date)); IsTrue = DateTime.Compare(dateToCompare, dateToCompareWith) < 0; if (!IsTrue) @@ -596,7 +596,7 @@ public async Task WhereForBoolen() public async Task NotEqualToForBoolean() { Query query = client.ContentType(source).Query(); - query.NotEqualTo("boolean", true); + query.NotEqualTo("boolean", false); var result = await query.Find(); if (result == null && result.Items.Count() == 0) { @@ -611,7 +611,7 @@ public async Task NotEqualToForBoolean() bool IsTrue = false; foreach (var data in result.Items) { - IsTrue = data.Boolean.Equals(false); + IsTrue = data.Boolean.Equals(true); if (!IsTrue) break; } @@ -772,7 +772,7 @@ public async Task ContainedInForText() public async Task ContainedInForNumber() { Query query = client.ContentType(source).Query(); - query.ContainedIn("number", new object[] { 12, 3 }); + query.ContainedIn("number", new object[] { 4 }); var result = await query.Find(); if (result == null && result.Items.Count() == 0) { @@ -789,7 +789,7 @@ public async Task ContainedInForNumber() foreach (var data in result.Items) { - IsTrue = data.Number == 12 || data.Number == 3; + IsTrue = data.Number == 4 || data.Number == 3; if (!IsTrue) break; } @@ -840,7 +840,7 @@ public async Task ContainedInForDate() public async Task ContainedInForGroup() { Query query = client.ContentType(source).Query(); - query.ContainedIn("group.name", new object[] { "First", "third" }); + query.ContainedIn("group.name", new object[] { "Forth" }); var result = await query.Find(); if (result == null && result.Items.Count() == 0) { @@ -861,7 +861,7 @@ public async Task ContainedInForGroup() { if (item.Key.Equals("name")) { - IsTrue = Convert.ToString(item.Value).Equals("First") || Convert.ToString(item.Value).Equals("third"); + IsTrue = Convert.ToString(item.Value).Equals("Forth") || Convert.ToString(item.Value).Equals("third"); } } } diff --git a/Contentstack.Core/Configuration/Config.cs b/Contentstack.Core/Configuration/Config.cs index 4c50718..d5ce479 100644 --- a/Contentstack.Core/Configuration/Config.cs +++ b/Contentstack.Core/Configuration/Config.cs @@ -120,7 +120,7 @@ internal string HostURL { get { - if (Region == ContentstackRegion.EU || Region == ContentstackRegion.AZURE_EU || Region == ContentstackRegion.AZURE_NA || Region == ContentstackRegion.GCP_NA) + if (Region == ContentstackRegion.EU || Region == ContentstackRegion.AZURE_EU || Region == ContentstackRegion.AZURE_NA || Region == ContentstackRegion.GCP_NA || Region==ContentstackRegion.AU) return "cdn.contentstack.com"; return "cdn.contentstack.io"; } diff --git a/Contentstack.Core/Internals/ContentstackRegion.cs b/Contentstack.Core/Internals/ContentstackRegion.cs index 7df9b68..2d8f638 100644 --- a/Contentstack.Core/Internals/ContentstackRegion.cs +++ b/Contentstack.Core/Internals/ContentstackRegion.cs @@ -26,7 +26,12 @@ public enum ContentstackRegion /// /// To specify GCP_NA region. /// - GCP_NA + GCP_NA, + + /// + /// To specify AWS_AU region. + /// + AU } @@ -40,7 +45,9 @@ internal enum ContentstackRegionCode azure_na, - gcp_na + gcp_na, + + au, } } diff --git a/Contentstack.Core/Internals/HttpRequestHandler.cs b/Contentstack.Core/Internals/HttpRequestHandler.cs index 9a1938a..85f8a10 100644 --- a/Contentstack.Core/Internals/HttpRequestHandler.cs +++ b/Contentstack.Core/Internals/HttpRequestHandler.cs @@ -48,7 +48,7 @@ public async Task ProcessRequest(string Url, Dictionary var request = (HttpWebRequest)WebRequest.Create(uri); request.Method = "GET"; request.ContentType = "application/json"; - request.Headers["x-user-agent"]="contentstack-delivery-dotnet/2.23.0"; + request.Headers["x-user-agent"]="contentstack-delivery-dotnet/2.24.0"; request.Timeout = timeout; if (proxy != null) diff --git a/Directory.Build.props b/Directory.Build.props index 4f68ca3..2263977 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,5 +1,5 @@ - 2.23.0 + 2.24.0 From 0022da345e9fccab5ccacfd074b2ed985ad96042 Mon Sep 17 00:00:00 2001 From: raj pandey Date: Tue, 23 Sep 2025 18:18:36 +0530 Subject: [PATCH 2/3] Unit Test Cases --- Contentstack.Core.Tests/RegionHandlerTest.cs | 332 +++++++++++++++++++ 1 file changed, 332 insertions(+) create mode 100644 Contentstack.Core.Tests/RegionHandlerTest.cs diff --git a/Contentstack.Core.Tests/RegionHandlerTest.cs b/Contentstack.Core.Tests/RegionHandlerTest.cs new file mode 100644 index 0000000..44e1f70 --- /dev/null +++ b/Contentstack.Core.Tests/RegionHandlerTest.cs @@ -0,0 +1,332 @@ +using System; +using System.Reflection; +using Xunit; +using Contentstack.Core; +using Contentstack.Core.Configuration; +using Contentstack.Core.Internals; +using Microsoft.Extensions.Options; + +namespace Contentstack.Core.Tests +{ + public class RegionHandlerTest + { + #region ContentstackRegion Enum Tests + + [Theory] + [InlineData(ContentstackRegion.US, 0)] + [InlineData(ContentstackRegion.EU, 1)] + [InlineData(ContentstackRegion.AZURE_EU, 2)] + [InlineData(ContentstackRegion.AZURE_NA, 3)] + [InlineData(ContentstackRegion.GCP_NA, 4)] + [InlineData(ContentstackRegion.AU, 5)] + public void ContentstackRegion_EnumValues_AreCorrect(ContentstackRegion region, int expectedValue) + { + Assert.Equal(expectedValue, (int)region); + } + + [Fact] + public void ContentstackRegion_AllValues_AreDefined() + { + var regions = Enum.GetValues(); + Assert.Equal(6, regions.Length); + Assert.Contains(ContentstackRegion.US, regions); + Assert.Contains(ContentstackRegion.EU, regions); + Assert.Contains(ContentstackRegion.AZURE_EU, regions); + Assert.Contains(ContentstackRegion.AZURE_NA, regions); + Assert.Contains(ContentstackRegion.GCP_NA, regions); + Assert.Contains(ContentstackRegion.AU, regions); + } + + #endregion + + #region ContentstackOptions Region Tests + + [Fact] + public void ContentstackOptions_Region_DefaultValue_IsUS() + { + var options = new ContentstackOptions(); + Assert.Equal(ContentstackRegion.US, options.Region); + } + + [Theory] + [InlineData(ContentstackRegion.US)] + [InlineData(ContentstackRegion.EU)] + [InlineData(ContentstackRegion.AZURE_EU)] + [InlineData(ContentstackRegion.AZURE_NA)] + [InlineData(ContentstackRegion.GCP_NA)] + [InlineData(ContentstackRegion.AU)] + public void ContentstackOptions_Region_CanBeSet(ContentstackRegion region) + { + var options = new ContentstackOptions(); + options.Region = region; + Assert.Equal(region, options.Region); + } + + #endregion + + #region ContentstackClient Region Tests + + [Theory] + [InlineData(ContentstackRegion.US)] + [InlineData(ContentstackRegion.EU)] + [InlineData(ContentstackRegion.AZURE_EU)] + [InlineData(ContentstackRegion.AZURE_NA)] + [InlineData(ContentstackRegion.GCP_NA)] + [InlineData(ContentstackRegion.AU)] + public void ContentstackClient_Constructor_WithRegion_SetsCorrectRegion(ContentstackRegion region) + { + var options = new ContentstackOptions + { + ApiKey = "test_api_key", + DeliveryToken = "test_delivery_token", + Environment = "test_environment", + Region = region + }; + + var client = new ContentstackClient(options); + + // Access the private Config field to verify region is set + var configField = typeof(ContentstackClient).GetField("Config", BindingFlags.NonPublic | BindingFlags.Instance); + var config = configField.GetValue(client); + var regionProperty = config.GetType().GetProperty("Region"); + var actualRegion = (ContentstackRegion)regionProperty.GetValue(config); + + Assert.Equal(region, actualRegion); + } + + [Theory] + [InlineData(ContentstackRegion.US)] + [InlineData(ContentstackRegion.EU)] + [InlineData(ContentstackRegion.AZURE_EU)] + [InlineData(ContentstackRegion.AZURE_NA)] + [InlineData(ContentstackRegion.GCP_NA)] + [InlineData(ContentstackRegion.AU)] + public void ContentstackClient_Constructor_WithRegionParameter_SetsCorrectRegion(ContentstackRegion region) + { + var client = new ContentstackClient("test_api_key", "test_delivery_token", "test_environment", region: region); + + // Access the private Config field to verify region is set + var configField = typeof(ContentstackClient).GetField("Config", BindingFlags.NonPublic | BindingFlags.Instance); + var config = configField.GetValue(client); + var regionProperty = config.GetType().GetProperty("Region"); + var actualRegion = (ContentstackRegion)regionProperty.GetValue(config); + + Assert.Equal(region, actualRegion); + } + + [Fact] + public void ContentstackClient_Constructor_WithOptionsWrapper_SetsCorrectRegion() + { + var options = new ContentstackOptions + { + ApiKey = "test_api_key", + DeliveryToken = "test_delivery_token", + Environment = "test_environment", + Region = ContentstackRegion.AU + }; + + var optionsWrapper = new OptionsWrapper(options); + var client = new ContentstackClient(optionsWrapper); + + // Access the private Config field to verify region is set + var configField = typeof(ContentstackClient).GetField("Config", BindingFlags.NonPublic | BindingFlags.Instance); + var config = configField.GetValue(client); + var regionProperty = config.GetType().GetProperty("Region"); + var actualRegion = (ContentstackRegion)regionProperty.GetValue(config); + + Assert.Equal(ContentstackRegion.AU, actualRegion); + } + + [Fact] + public void ContentstackClient_Constructor_DefaultRegion_IsUS() + { + var options = new ContentstackOptions + { + ApiKey = "test_api_key", + DeliveryToken = "test_delivery_token", + Environment = "test_environment" + // Region not set, should default to US + }; + + var client = new ContentstackClient(options); + + // Access the private Config field to verify region is set + var configField = typeof(ContentstackClient).GetField("Config", BindingFlags.NonPublic | BindingFlags.Instance); + var config = configField.GetValue(client); + var regionProperty = config.GetType().GetProperty("Region"); + var actualRegion = (ContentstackRegion)regionProperty.GetValue(config); + + Assert.Equal(ContentstackRegion.US, actualRegion); + } + + #endregion + + #region Integration Tests + + [Theory] + [InlineData(ContentstackRegion.US, "https://cdn.contentstack.io/v3")] + [InlineData(ContentstackRegion.EU, "https://eu-cdn.contentstack.com/v3")] + [InlineData(ContentstackRegion.AZURE_EU, "https://azure-eu-cdn.contentstack.com/v3")] + [InlineData(ContentstackRegion.AZURE_NA, "https://azure-na-cdn.contentstack.com/v3")] + [InlineData(ContentstackRegion.GCP_NA, "https://gcp-na-cdn.contentstack.com/v3")] + [InlineData(ContentstackRegion.AU, "https://au-cdn.contentstack.com/v3")] + public void ContentstackClient_Integration_GeneratesCorrectBaseUrl(ContentstackRegion region, string expectedBaseUrl) + { + var options = new ContentstackOptions + { + ApiKey = "test_api_key", + DeliveryToken = "test_delivery_token", + Environment = "test_environment", + Region = region + }; + + var client = new ContentstackClient(options); + + // Access the private Config field to get BaseUrl + var configField = typeof(ContentstackClient).GetField("Config", BindingFlags.NonPublic | BindingFlags.Instance); + var config = configField.GetValue(client); + var baseUrlProperty = config.GetType().GetProperty("BaseUrl"); + var actualBaseUrl = baseUrlProperty.GetValue(config) as string; + + Assert.Equal(expectedBaseUrl, actualBaseUrl); + } + + [Fact] + public void ContentstackClient_Integration_WithCustomHost_OverridesRegionHost() + { + var options = new ContentstackOptions + { + ApiKey = "test_api_key", + DeliveryToken = "test_delivery_token", + Environment = "test_environment", + Region = ContentstackRegion.EU, + Host = "custom.contentstack.com" + }; + + var client = new ContentstackClient(options); + + // Access the private Config field to get BaseUrl + var configField = typeof(ContentstackClient).GetField("Config", BindingFlags.NonPublic | BindingFlags.Instance); + var config = configField.GetValue(client); + var baseUrlProperty = config.GetType().GetProperty("BaseUrl"); + var actualBaseUrl = baseUrlProperty.GetValue(config) as string; + + // Should use custom host instead of region-specific host + Assert.Equal("https://eu-custom.contentstack.com/v3", actualBaseUrl); + } + + [Fact] + public void ContentstackClient_Integration_WithCustomVersion_AppendsToBaseUrl() + { + var options = new ContentstackOptions + { + ApiKey = "test_api_key", + DeliveryToken = "test_delivery_token", + Environment = "test_environment", + Region = ContentstackRegion.AU, + Version = "v2" + }; + + var client = new ContentstackClient(options); + + // Access the private Config field to get BaseUrl + var configField = typeof(ContentstackClient).GetField("Config", BindingFlags.NonPublic | BindingFlags.Instance); + var config = configField.GetValue(client); + var baseUrlProperty = config.GetType().GetProperty("BaseUrl"); + var actualBaseUrl = baseUrlProperty.GetValue(config) as string; + + Assert.Equal("https://au-cdn.contentstack.com/v2", actualBaseUrl); + } + + #endregion + + #region Edge Cases and Error Scenarios + + [Fact] + public void ContentstackRegion_Enum_CanBeParsedFromString() + { + Assert.True(Enum.TryParse("US", out var usRegion)); + Assert.Equal(ContentstackRegion.US, usRegion); + + Assert.True(Enum.TryParse("EU", out var euRegion)); + Assert.Equal(ContentstackRegion.EU, euRegion); + + Assert.True(Enum.TryParse("AU", out var auRegion)); + Assert.Equal(ContentstackRegion.AU, auRegion); + } + + [Fact] + public void ContentstackRegion_Enum_CanBeParsedFromStringIgnoreCase() + { + Assert.True(Enum.TryParse("us", true, out var usRegion)); + Assert.Equal(ContentstackRegion.US, usRegion); + + Assert.True(Enum.TryParse("eu", true, out var euRegion)); + Assert.Equal(ContentstackRegion.EU, euRegion); + + Assert.True(Enum.TryParse("au", true, out var auRegion)); + Assert.Equal(ContentstackRegion.AU, auRegion); + } + + [Fact] + public void ContentstackRegion_Enum_InvalidString_ReturnsFalse() + { + Assert.False(Enum.TryParse("INVALID", out var invalidRegion)); + Assert.Equal(default(ContentstackRegion), invalidRegion); + } + + [Fact] + public void ContentstackOptions_Region_CanBeChangedAfterCreation() + { + var options = new ContentstackOptions + { + Region = ContentstackRegion.US + }; + + Assert.Equal(ContentstackRegion.US, options.Region); + + options.Region = ContentstackRegion.AU; + Assert.Equal(ContentstackRegion.AU, options.Region); + } + + [Fact] + public void ContentstackClient_WithDifferentRegions_CreatesDifferentInstances() + { + var usOptions = new ContentstackOptions + { + ApiKey = "test_api_key", + DeliveryToken = "test_delivery_token", + Environment = "test_environment", + Region = ContentstackRegion.US + }; + + var auOptions = new ContentstackOptions + { + ApiKey = "test_api_key", + DeliveryToken = "test_delivery_token", + Environment = "test_environment", + Region = ContentstackRegion.AU + }; + + var usClient = new ContentstackClient(usOptions); + var auClient = new ContentstackClient(auOptions); + + // Access the private Config field to verify different regions + var configField = typeof(ContentstackClient).GetField("Config", BindingFlags.NonPublic | BindingFlags.Instance); + + var usConfig = configField.GetValue(usClient); + var usRegionProperty = usConfig.GetType().GetProperty("Region"); + var usRegion = (ContentstackRegion)usRegionProperty.GetValue(usConfig); + + var auConfig = configField.GetValue(auClient); + var auRegionProperty = auConfig.GetType().GetProperty("Region"); + var auRegion = (ContentstackRegion)auRegionProperty.GetValue(auConfig); + + Assert.NotEqual(usRegion, auRegion); + Assert.Equal(ContentstackRegion.US, usRegion); + Assert.Equal(ContentstackRegion.AU, auRegion); + } + + #endregion + } +} \ No newline at end of file From 30e16211473db0c2aeaf6857c47f37e13af38bf4 Mon Sep 17 00:00:00 2001 From: raj pandey Date: Tue, 23 Sep 2025 18:21:45 +0530 Subject: [PATCH 3/3] talisman update --- .talismanrc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.talismanrc b/.talismanrc index 4b13327..7654d1e 100644 --- a/.talismanrc +++ b/.talismanrc @@ -22,3 +22,5 @@ fileignoreconfig: checksum: b63897181a8cb5993d1305248cfc3e711c4039b5677b6c1e4e2a639e4ecb391b - filename: Contentstack.Core.Tests/AssetTest.cs checksum: 3e7bf50c7223c458561f0217484d5e70cf3770490c569e0a7083b0a12af9ab86 +- filename: Contentstack.Core.Tests/RegionHandlerTest.cs + checksum: 69899138754908e156aa477d775d12fd6b3fefc1a6c2afec22cb409bd6e6446c