diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0dd22eb..8b35a7a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,8 @@
# Changelog
+## [v0.3.2](https://github.com/contentstack/contentstack-management-dotnet/tree/v0.3.2)
+ - Fix
+ - Added Test cases for the Release
+
## [v0.3.1](https://github.com/contentstack/contentstack-management-dotnet/tree/v0.3.1)
- Fix
- Fixed apiVersion param in Publish/Unpublish methods
diff --git a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack004_ReleaseTest.cs b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack004_ReleaseTest.cs
new file mode 100644
index 0000000..fb4fbce
--- /dev/null
+++ b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack004_ReleaseTest.cs
@@ -0,0 +1,975 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Contentstack.Management.Core.Models;
+using Contentstack.Management.Core.Tests.Model;
+using Contentstack.Management.Core.Queryable;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Newtonsoft.Json.Linq;
+using Contentstack.Management.Core.Exceptions;
+
+namespace Contentstack.Management.Core.Tests.IntegrationTest
+{
+ [TestClass]
+ public class Contentstack004_ReleaseTest
+ {
+ private Stack _stack;
+ private string _testReleaseName = "DotNet SDK Integration Test Release";
+ private string _testReleaseDescription = "Release created for .NET SDK integration testing";
+
+ [TestInitialize]
+ public async Task Initialize()
+ {
+ StackResponse response = StackResponse.getStack(Contentstack.Client.serializer);
+ _stack = Contentstack.Client.Stack(response.Stack.APIKey);
+ }
+
+
+
+ ///
+ /// Helper method to create a clean release for testing
+ ///
+ private string CreateTestRelease()
+ {
+ try
+ {
+ var releaseModel = new ReleaseModel
+ {
+ Name = _testReleaseName,
+ Description = _testReleaseDescription,
+ Locked = false,
+ Archived = false
+ };
+
+ ContentstackResponse contentstackResponse = _stack.Release().Create(releaseModel);
+ var response = contentstackResponse.OpenJObjectResponse();
+
+ if (!contentstackResponse.IsSuccessStatusCode || response?["release"] == null)
+ {
+ throw new Exception($"Failed to create release. Status: {contentstackResponse.StatusCode}");
+ }
+
+ return response["release"]["uid"].ToString();
+ }
+ catch (Exception e)
+ {
+ throw new Exception($"CreateTestRelease failed: {e.Message}", e);
+ }
+ }
+
+ [TestMethod]
+ [DoNotParallelize]
+ public void Test001_Should_Create_Release()
+ {
+ string releaseUid = null;
+ try
+ {
+ releaseUid = CreateTestRelease();
+
+ Assert.IsNotNull(releaseUid);
+
+ ContentstackResponse contentstackResponse = _stack.Release(releaseUid).Fetch();
+ var response = contentstackResponse.OpenJObjectResponse();
+
+ Assert.IsNotNull(response);
+ Assert.IsTrue(contentstackResponse.IsSuccessStatusCode);
+ Assert.IsNotNull(response["release"]);
+ Assert.AreEqual(_testReleaseName, response["release"]["name"].ToString());
+ Assert.AreEqual(_testReleaseDescription, response["release"]["description"].ToString());
+ }
+ catch (Exception e)
+ {
+ Assert.Fail($"Create release failed: {e.Message}");
+ }
+ finally
+ {
+ if (!string.IsNullOrEmpty(releaseUid))
+ {
+ try
+ {
+ _stack.Release(releaseUid).Delete();
+ }
+ catch
+ {
+
+ }
+ }
+ }
+ }
+
+ ///
+ /// Async helper method to create a clean release for testing
+ ///
+ private async Task CreateTestReleaseAsync()
+ {
+ try
+ {
+ var releaseModel = new ReleaseModel
+ {
+ Name = _testReleaseName,
+ Description = _testReleaseDescription,
+ Locked = false,
+ Archived = false
+ };
+
+ ContentstackResponse contentstackResponse = await _stack.Release().CreateAsync(releaseModel);
+ var response = contentstackResponse.OpenJObjectResponse();
+
+ if (!contentstackResponse.IsSuccessStatusCode || response?["release"] == null)
+ {
+ throw new Exception($"Failed to create release. Status: {contentstackResponse.StatusCode}");
+ }
+
+ return response["release"]["uid"].ToString();
+ }
+ catch (Exception e)
+ {
+ throw new Exception($"CreateTestReleaseAsync failed: {e.Message}", e);
+ }
+ }
+
+ ///
+ /// Helper method to create 6 numbered test releases
+ ///
+ private List CreateSixNumberedReleases()
+ {
+ var releaseUids = new List();
+
+ try
+ {
+ for (int i = 1; i <= 6; i++)
+ {
+ var releaseModel = new ReleaseModel
+ {
+ Name = $"{_testReleaseName} {i}",
+ Description = $"{_testReleaseDescription} (Number {i})",
+ Locked = false,
+ Archived = false
+ };
+
+ ContentstackResponse contentstackResponse = _stack.Release().Create(releaseModel);
+ var response = contentstackResponse.OpenJObjectResponse();
+
+ if (!contentstackResponse.IsSuccessStatusCode || response?["release"] == null)
+ {
+ throw new Exception($"Failed to create release {i}. Status: {contentstackResponse.StatusCode}");
+ }
+
+ releaseUids.Add(response["release"]["uid"].ToString());
+ }
+
+ return releaseUids;
+ }
+ catch (Exception e)
+ {
+ foreach (var uid in releaseUids)
+ {
+ try
+ {
+ _stack.Release(uid).Delete();
+ }
+ catch
+ {
+ }
+ }
+ throw new Exception($"CreateSixNumberedReleases failed: {e.Message}", e);
+ }
+ }
+
+ ///
+ /// Async helper method to create 6 numbered test releases
+ ///
+ private async Task> CreateSixNumberedReleasesAsync()
+ {
+ var releaseUids = new List();
+
+ try
+ {
+ for (int i = 1; i <= 6; i++)
+ {
+ var releaseModel = new ReleaseModel
+ {
+ Name = $"{_testReleaseName} {i}",
+ Description = $"{_testReleaseDescription} (Number {i})",
+ Locked = false,
+ Archived = false
+ };
+
+ ContentstackResponse contentstackResponse = await _stack.Release().CreateAsync(releaseModel);
+ var response = contentstackResponse.OpenJObjectResponse();
+
+ if (!contentstackResponse.IsSuccessStatusCode || response?["release"] == null)
+ {
+ throw new Exception($"Failed to create release {i}. Status: {contentstackResponse.StatusCode}");
+ }
+
+ releaseUids.Add(response["release"]["uid"].ToString());
+ }
+
+ return releaseUids;
+ }
+ catch (Exception e)
+ {
+ foreach (var uid in releaseUids)
+ {
+ try
+ {
+ await _stack.Release(uid).DeleteAsync();
+ }
+ catch
+ {
+ }
+ }
+ throw new Exception($"CreateSixNumberedReleasesAsync failed: {e.Message}", e);
+ }
+ }
+
+ ///
+ /// Helper method to clean up a list of releases
+ ///
+ private void CleanupReleases(List releaseUids)
+ {
+ if (releaseUids != null)
+ {
+ foreach (var uid in releaseUids)
+ {
+ try
+ {
+ _stack.Release(uid).Delete();
+ }
+ catch
+ {
+ }
+ }
+ }
+ }
+
+ ///
+ /// Async helper method to clean up a list of releases
+ ///
+ private async Task CleanupReleasesAsync(List releaseUids)
+ {
+ if (releaseUids != null)
+ {
+ foreach (var uid in releaseUids)
+ {
+ try
+ {
+ await _stack.Release(uid).DeleteAsync();
+ }
+ catch
+ {
+ }
+ }
+ }
+ }
+
+ [TestMethod]
+ [DoNotParallelize]
+ public async Task Test002_Should_Create_Release_Async()
+ {
+ string releaseUid = null;
+ try
+ {
+ releaseUid = await CreateTestReleaseAsync();
+
+ Assert.IsNotNull(releaseUid);
+
+ ContentstackResponse contentstackResponse = await _stack.Release(releaseUid).FetchAsync();
+ var response = contentstackResponse.OpenJObjectResponse();
+
+ Assert.IsNotNull(response);
+ Assert.IsTrue(contentstackResponse.IsSuccessStatusCode);
+ Assert.IsNotNull(response["release"]);
+ Assert.AreEqual(_testReleaseName, response["release"]["name"].ToString());
+ Assert.AreEqual(_testReleaseDescription, response["release"]["description"].ToString());
+ }
+ catch (Exception e)
+ {
+ Assert.Fail($"Create release async failed: {e.Message}");
+ }
+ finally
+ {
+ if (!string.IsNullOrEmpty(releaseUid))
+ {
+ try
+ {
+ await _stack.Release(releaseUid).DeleteAsync();
+ }
+ catch
+ {
+ // Ignore cleanup failures
+ }
+ }
+ }
+ }
+
+ [TestMethod]
+ [DoNotParallelize]
+ public void Test003_Should_Query_All_Releases()
+ {
+ List releaseUids = null;
+ try
+ {
+ releaseUids = CreateSixNumberedReleases();
+
+ ContentstackResponse contentstackResponse = _stack.Release().Query().Find();
+ var response = contentstackResponse.OpenJObjectResponse();
+
+ Assert.IsNotNull(response);
+ Assert.IsTrue(contentstackResponse.IsSuccessStatusCode);
+ Assert.IsNotNull(response["releases"]);
+
+ var releases = response["releases"] as JArray;
+ Assert.IsNotNull(releases);
+
+ Assert.IsTrue(releases.Count >= 6, $"Expected at least 6 releases, but found {releases.Count}");
+
+ var releaseNames = releases.Select(r => r["name"]?.ToString()).ToList();
+ for (int i = 1; i <= 6; i++)
+ {
+ string expectedName = $"{_testReleaseName} {i}";
+ Assert.IsTrue(releaseNames.Contains(expectedName),
+ $"Expected to find release with name '{expectedName}' in query results");
+ }
+ }
+ catch (Exception e)
+ {
+ Assert.Fail($"Query all releases failed: {e.Message}");
+ }
+ finally
+ {
+ CleanupReleases(releaseUids);
+ }
+ }
+
+ [TestMethod]
+ [DoNotParallelize]
+ public async Task Test004_Should_Query_All_Releases_Async()
+ {
+ List releaseUids = null;
+ try
+ {
+ releaseUids = await CreateSixNumberedReleasesAsync();
+
+ ContentstackResponse contentstackResponse = await _stack.Release().Query().FindAsync();
+ var response = contentstackResponse.OpenJObjectResponse();
+
+ Assert.IsNotNull(response);
+ Assert.IsTrue(contentstackResponse.IsSuccessStatusCode);
+ Assert.IsNotNull(response["releases"]);
+
+ var releases = response["releases"] as JArray;
+ Assert.IsNotNull(releases);
+
+ Assert.IsTrue(releases.Count >= 6, $"Expected at least 6 releases, but found {releases.Count}");
+
+ var releaseNames = releases.Select(r => r["name"]?.ToString()).ToList();
+ for (int i = 1; i <= 6; i++)
+ {
+ string expectedName = $"{_testReleaseName} {i}";
+ Assert.IsTrue(releaseNames.Contains(expectedName),
+ $"Expected to find release with name '{expectedName}' in query results");
+ }
+ }
+ catch (Exception e)
+ {
+ Assert.Fail($"Query all releases async failed: {e.Message}");
+ }
+ finally
+ {
+ await CleanupReleasesAsync(releaseUids);
+ }
+ }
+
+ [TestMethod]
+ [DoNotParallelize]
+ public void Test005_Should_Fetch_Release()
+ {
+ List releaseUids = null;
+ try
+ {
+ releaseUids = CreateSixNumberedReleases();
+
+ string releaseToFetch = releaseUids[2];
+ ContentstackResponse contentstackResponse = _stack.Release(releaseToFetch).Fetch();
+ var response = contentstackResponse.OpenJObjectResponse();
+
+ Assert.IsNotNull(response);
+ Assert.IsTrue(contentstackResponse.IsSuccessStatusCode);
+ Assert.IsNotNull(response["release"]);
+ Assert.AreEqual(releaseToFetch, response["release"]["uid"].ToString());
+ Assert.AreEqual($"{_testReleaseName} 3", response["release"]["name"].ToString());
+ Assert.AreEqual($"{_testReleaseDescription} (Number 3)", response["release"]["description"].ToString());
+ }
+ catch (Exception e)
+ {
+ Assert.Fail($"Fetch release failed: {e.Message}");
+ }
+ finally
+ {
+ CleanupReleases(releaseUids);
+ }
+ }
+
+ [TestMethod]
+ [DoNotParallelize]
+ public async Task Test006_Should_Fetch_Release_Async()
+ {
+ List releaseUids = null;
+ try
+ {
+ releaseUids = await CreateSixNumberedReleasesAsync();
+
+ string releaseToFetch = releaseUids[4];
+ ContentstackResponse contentstackResponse = await _stack.Release(releaseToFetch).FetchAsync();
+ var response = contentstackResponse.OpenJObjectResponse();
+
+ Assert.IsNotNull(response);
+ Assert.IsTrue(contentstackResponse.IsSuccessStatusCode);
+ Assert.IsNotNull(response["release"]);
+ Assert.AreEqual(releaseToFetch, response["release"]["uid"].ToString());
+ Assert.AreEqual($"{_testReleaseName} 5", response["release"]["name"].ToString());
+ Assert.AreEqual($"{_testReleaseDescription} (Number 5)", response["release"]["description"].ToString());
+ }
+ catch (Exception e)
+ {
+ Assert.Fail($"Fetch release async failed: {e.Message}");
+ }
+ finally
+ {
+ await CleanupReleasesAsync(releaseUids);
+ }
+ }
+
+ [TestMethod]
+ [DoNotParallelize]
+ public void Test007_Should_Update_Release()
+ {
+ string releaseUid = null;
+ try
+ {
+ releaseUid = CreateTestRelease();
+
+ var updateModel = new ReleaseModel
+ {
+ Name = _testReleaseName + " Updated",
+ Description = _testReleaseDescription + " (Updated)",
+ Locked = false,
+ Archived = false
+ };
+
+ ContentstackResponse contentstackResponse = _stack.Release(releaseUid).Update(updateModel);
+ var response = contentstackResponse.OpenJObjectResponse();
+
+ Assert.IsNotNull(response);
+ Assert.IsTrue(contentstackResponse.IsSuccessStatusCode);
+ Assert.IsNotNull(response["release"]);
+ Assert.AreEqual(_testReleaseName + " Updated", response["release"]["name"].ToString());
+ Assert.AreEqual(_testReleaseDescription + " (Updated)", response["release"]["description"].ToString());
+ }
+ catch (Exception e)
+ {
+ Assert.Fail($"Update release failed: {e.Message}");
+ }
+ finally
+ {
+ if (!string.IsNullOrEmpty(releaseUid))
+ {
+ try
+ {
+ _stack.Release(releaseUid).Delete();
+ }
+ catch
+ {
+ }
+ }
+ }
+ }
+
+ [TestMethod]
+ [DoNotParallelize]
+ public async Task Test008_Should_Update_Release_Async()
+ {
+ string releaseUid = null;
+ try
+ {
+ releaseUid = await CreateTestReleaseAsync();
+
+ var updateModel = new ReleaseModel
+ {
+ Name = _testReleaseName + " Updated Async",
+ Description = _testReleaseDescription + " (Updated Async)",
+ Locked = false,
+ Archived = false
+ };
+
+ ContentstackResponse contentstackResponse = await _stack.Release(releaseUid).UpdateAsync(updateModel);
+ var response = contentstackResponse.OpenJObjectResponse();
+
+ Assert.IsNotNull(response);
+ Assert.IsTrue(contentstackResponse.IsSuccessStatusCode);
+ Assert.IsNotNull(response["release"]);
+ Assert.AreEqual(_testReleaseName + " Updated Async", response["release"]["name"].ToString());
+ Assert.AreEqual(_testReleaseDescription + " (Updated Async)", response["release"]["description"].ToString());
+ }
+ catch (Exception e)
+ {
+ Assert.Fail($"Update release async failed: {e.Message}");
+ }
+ finally
+ {
+ if (!string.IsNullOrEmpty(releaseUid))
+ {
+ try
+ {
+ await _stack.Release(releaseUid).DeleteAsync();
+ }
+ catch
+ {
+ }
+ }
+ }
+ }
+
+ [TestMethod]
+ [DoNotParallelize]
+ public void Test009_Should_Clone_Release()
+ {
+ string originalReleaseUid = null;
+ string clonedReleaseUid = null;
+ try
+ {
+ originalReleaseUid = CreateTestRelease();
+
+ string cloneName = _testReleaseName + " Cloned";
+ string cloneDescription = _testReleaseDescription + " (Cloned)";
+
+ ContentstackResponse contentstackResponse = _stack.Release(originalReleaseUid).Clone(cloneName, cloneDescription);
+ var response = contentstackResponse.OpenJObjectResponse();
+
+ Assert.IsNotNull(response);
+ Assert.IsTrue(contentstackResponse.IsSuccessStatusCode);
+ Assert.IsNotNull(response["release"]);
+ Assert.AreEqual(cloneName, response["release"]["name"].ToString());
+
+ clonedReleaseUid = response["release"]["uid"].ToString();
+ Assert.IsNotNull(clonedReleaseUid);
+ Assert.AreNotEqual(originalReleaseUid, clonedReleaseUid);
+ }
+ catch (Exception e)
+ {
+ Assert.Fail($"Clone release failed: {e.Message}");
+ }
+ finally
+ {
+ if (!string.IsNullOrEmpty(clonedReleaseUid))
+ {
+ try
+ {
+ _stack.Release(clonedReleaseUid).Delete();
+ }
+ catch
+ {
+ }
+ }
+ if (!string.IsNullOrEmpty(originalReleaseUid))
+ {
+ try
+ {
+ _stack.Release(originalReleaseUid).Delete();
+ }
+ catch
+ {
+ }
+ }
+ }
+ }
+
+ [TestMethod]
+ [DoNotParallelize]
+ public async Task Test010_Should_Clone_Release_Async()
+ {
+ string originalReleaseUid = null;
+ string clonedReleaseUid = null;
+ try
+ {
+ originalReleaseUid = await CreateTestReleaseAsync();
+
+ string cloneName = _testReleaseName + " Cloned Async";
+ string cloneDescription = _testReleaseDescription + " (Cloned Async)";
+
+ ContentstackResponse contentstackResponse = await _stack.Release(originalReleaseUid).CloneAsync(cloneName, cloneDescription);
+ var response = contentstackResponse.OpenJObjectResponse();
+
+ Assert.IsNotNull(response);
+ Assert.IsTrue(contentstackResponse.IsSuccessStatusCode);
+ Assert.IsNotNull(response["release"]);
+ Assert.AreEqual(cloneName, response["release"]["name"].ToString());
+
+ clonedReleaseUid = response["release"]["uid"].ToString();
+ Assert.IsNotNull(clonedReleaseUid);
+ Assert.AreNotEqual(originalReleaseUid, clonedReleaseUid);
+ }
+ catch (Exception e)
+ {
+ Assert.Fail($"Clone release async failed: {e.Message}");
+ }
+ finally
+ {
+ if (!string.IsNullOrEmpty(clonedReleaseUid))
+ {
+ try
+ {
+ await _stack.Release(clonedReleaseUid).DeleteAsync();
+ }
+ catch
+ {
+ }
+ }
+ if (!string.IsNullOrEmpty(originalReleaseUid))
+ {
+ try
+ {
+ await _stack.Release(originalReleaseUid).DeleteAsync();
+ }
+ catch
+ {
+ }
+ }
+ }
+ }
+
+ [TestMethod]
+ [DoNotParallelize]
+ public void Test011_Should_Query_Release_With_Parameters()
+ {
+ try
+ {
+ List releaseUids = CreateSixNumberedReleases();
+ var parameters = new ParameterCollection();
+ parameters.Add("include_count", "true");
+ parameters.Add("limit", "5");
+
+ ContentstackResponse contentstackResponse = _stack.Release().Query().Limit(5).Find();
+ var response = contentstackResponse.OpenJObjectResponse();
+
+ Assert.IsNotNull(response);
+ Assert.IsTrue(contentstackResponse.IsSuccessStatusCode);
+ Assert.IsNotNull(response["releases"]);
+ CleanupReleases(releaseUids);
+ }
+ catch (Exception e)
+ {
+ Assert.Fail($"Query release with parameters failed: {e.Message}");
+ }
+ }
+
+ [TestMethod]
+ [DoNotParallelize]
+ public async Task Test012_Should_Query_Release_With_Parameters_Async()
+ {
+ try
+ {
+ List releaseUids =await CreateSixNumberedReleasesAsync();
+ var parameters = new ParameterCollection();
+ parameters.Add("include_count", "true");
+ parameters.Add("limit", "5");
+
+ ContentstackResponse contentstackResponse = await _stack.Release().Query().Limit(5).FindAsync();
+ var response = contentstackResponse.OpenJObjectResponse();
+
+ Assert.IsNotNull(response);
+ Assert.IsTrue(contentstackResponse.IsSuccessStatusCode);
+ Assert.IsNotNull(response["releases"]);
+ await CleanupReleasesAsync(releaseUids);
+ }
+ catch (Exception e)
+ {
+ Assert.Fail($"Query release with parameters async failed: {e.Message}");
+ }
+ }
+
+ [TestMethod]
+ [DoNotParallelize]
+ public void Test013_Should_Create_Release_With_ParameterCollection()
+ {
+ try
+ {
+ var releaseModel = new ReleaseModel
+ {
+ Name = _testReleaseName + " With Params",
+ Description = _testReleaseDescription + " (With Parameters)",
+ Locked = false,
+ Archived = false
+ };
+
+ var parameters = new ParameterCollection();
+ parameters.Add("include_count", "true");
+
+ ContentstackResponse contentstackResponse = _stack.Release().Create(releaseModel, parameters);
+ var response = contentstackResponse.OpenJObjectResponse();
+
+ Assert.IsNotNull(response);
+ Assert.IsTrue(contentstackResponse.IsSuccessStatusCode);
+ Assert.IsNotNull(response["release"]);
+
+ string releaseUid = response["release"]["uid"].ToString();
+ Assert.IsNotNull(releaseUid);
+
+ _stack.Release(releaseUid).Delete();
+ }
+ catch (Exception e)
+ {
+ Assert.Fail($"Create release with parameters failed: {e.Message}");
+ }
+ }
+
+ [TestMethod]
+ [DoNotParallelize]
+ public async Task Test014_Should_Create_Release_With_ParameterCollection_Async()
+ {
+ try
+ {
+ var releaseModel = new ReleaseModel
+ {
+ Name = _testReleaseName + " With Params Async",
+ Description = _testReleaseDescription + " (With Parameters Async)",
+ Locked = false,
+ Archived = false
+ };
+
+ var parameters = new ParameterCollection();
+ parameters.Add("include_count", "true");
+
+ ContentstackResponse contentstackResponse = await _stack.Release().CreateAsync(releaseModel, parameters);
+ var response = contentstackResponse.OpenJObjectResponse();
+
+ Assert.IsNotNull(response);
+ Assert.IsTrue(contentstackResponse.IsSuccessStatusCode);
+ Assert.IsNotNull(response["release"]);
+
+ string releaseUid = response["release"]["uid"].ToString();
+ Assert.IsNotNull(releaseUid);
+
+ await _stack.Release(releaseUid).DeleteAsync();
+ }
+ catch (Exception e)
+ {
+ Assert.Fail($"Create release with parameters async failed: {e.Message}");
+ }
+ }
+
+ [TestMethod]
+ [DoNotParallelize]
+ public void Test015_Should_Get_Release_Items()
+ {
+ string releaseUid = null;
+ try
+ {
+ releaseUid = CreateTestRelease();
+
+ ContentstackResponse contentstackResponse = _stack.Release(releaseUid).Item().GetAll();
+ var response = contentstackResponse.OpenJObjectResponse();
+
+ Assert.IsNotNull(response);
+ Assert.IsTrue(contentstackResponse.IsSuccessStatusCode);
+ }
+ catch (Exception e)
+ {
+ Assert.Fail($"Get release items failed: {e.Message}");
+ }
+ finally
+ {
+ if (!string.IsNullOrEmpty(releaseUid))
+ {
+ try
+ {
+ _stack.Release(releaseUid).Delete();
+ }
+ catch
+ {
+ }
+ }
+ }
+ }
+
+ [TestMethod]
+ [DoNotParallelize]
+ public async Task Test016_Should_Get_Release_Items_Async()
+ {
+ string releaseUid = null;
+ try
+ {
+ releaseUid = await CreateTestReleaseAsync();
+
+ ContentstackResponse contentstackResponse = await _stack.Release(releaseUid).Item().GetAllAsync();
+ var response = contentstackResponse.OpenJObjectResponse();
+
+ Assert.IsNotNull(response);
+ Assert.IsTrue(contentstackResponse.IsSuccessStatusCode);
+ }
+ catch (Exception e)
+ {
+ Assert.Fail($"Get release items async failed: {e.Message}");
+ }
+ finally
+ {
+ if (!string.IsNullOrEmpty(releaseUid))
+ {
+ try
+ {
+ await _stack.Release(releaseUid).DeleteAsync();
+ }
+ catch
+ {
+ }
+ }
+ }
+ }
+
+ [TestMethod]
+ [DoNotParallelize]
+ public void Test017_Should_Handle_Release_Not_Found()
+ {
+ try
+ {
+ string nonExistentUid = "non_existent_release_uid_12345";
+
+ try
+ {
+ ContentstackResponse contentstackResponse = _stack.Release(nonExistentUid).Fetch();
+ Assert.IsFalse(contentstackResponse.IsSuccessStatusCode);
+ }
+ catch (Exception ex)
+ {
+
+ if (ex is ContentstackErrorException csException)
+ {
+ Assert.IsTrue(
+ csException.ErrorMessage?.Contains("Release does not exist") == true ||
+ csException.ErrorCode == 141 ||
+ csException.Message?.Contains("Release does not exist") == true,
+ $"Expected 'Release does not exist' error, but got: ErrorCode={csException.ErrorCode}, Message='{csException.Message}', ErrorMessage='{csException.ErrorMessage}'"
+ );
+ }
+ else
+ {
+ Assert.IsTrue(
+ ex.Message?.Contains("Release does not exist") == true ||
+ ex.Message?.Contains("not found") == true ||
+ ex.Message?.Contains("404") == true,
+ $"Expected 'Release does not exist' error, but got: {ex.Message}"
+ );
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ Assert.Fail($"Handle release not found test failed: {e.Message}");
+ }
+ }
+
+ [TestMethod]
+ [DoNotParallelize]
+ public async Task Test018_Should_Handle_Release_Not_Found_Async()
+ {
+ try
+ {
+ string nonExistentUid = "non_existent_release_uid_12345";
+
+ try
+ {
+ ContentstackResponse contentstackResponse = await _stack.Release(nonExistentUid).FetchAsync();
+ Assert.IsFalse(contentstackResponse.IsSuccessStatusCode);
+ }
+ catch (Exception ex)
+ {
+ if (ex is ContentstackErrorException csException)
+ {
+ Assert.IsTrue(
+ csException.ErrorMessage?.Contains("Release does not exist") == true ||
+ csException.ErrorCode == 141 ||
+ csException.Message?.Contains("Release does not exist") == true,
+ $"Expected 'Release does not exist' error, but got: ErrorCode={csException.ErrorCode}, Message='{csException.Message}', ErrorMessage='{csException.ErrorMessage}'"
+ );
+ }
+ else
+ {
+ Assert.IsTrue(
+ ex.Message?.Contains("Release does not exist") == true ||
+ ex.Message?.Contains("not found") == true ||
+ ex.Message?.Contains("404") == true,
+ $"Expected 'Release does not exist' error, but got: {ex.Message}"
+ );
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ Assert.Fail($"Handle release not found async test failed: {e.Message}");
+ }
+ }
+
+ [TestMethod]
+ [DoNotParallelize]
+ public void Test019_Should_Delete_Release()
+ {
+ try
+ {
+ var releaseModel = new ReleaseModel
+ {
+ Name = _testReleaseName + " For Deletion",
+ Description = _testReleaseDescription + " (To be deleted)",
+ Locked = false,
+ Archived = false
+ };
+
+ ContentstackResponse createResponse = _stack.Release().Create(releaseModel);
+ var createResponseJson = createResponse.OpenJObjectResponse();
+ string releaseToDeleteUid = createResponseJson["release"]["uid"].ToString();
+
+ ContentstackResponse contentstackResponse = _stack.Release(releaseToDeleteUid).Delete();
+
+ Assert.IsNotNull(contentstackResponse);
+ Assert.IsTrue(contentstackResponse.IsSuccessStatusCode);
+ }
+ catch (Exception e)
+ {
+ Assert.Fail($"Delete release failed: {e.Message}");
+ }
+ }
+
+ [TestMethod]
+ [DoNotParallelize]
+ public async Task Test020_Should_Delete_Release_Async()
+ {
+ try
+ {
+ var releaseModel = new ReleaseModel
+ {
+ Name = _testReleaseName + " For Deletion Async",
+ Description = _testReleaseDescription + " (To be deleted async)",
+ Locked = false,
+ Archived = false
+ };
+
+ ContentstackResponse createResponse = await _stack.Release().CreateAsync(releaseModel);
+ var createResponseJson = createResponse.OpenJObjectResponse();
+ string releaseToDeleteUid = createResponseJson["release"]["uid"].ToString();
+
+ ContentstackResponse contentstackResponse = await _stack.Release(releaseToDeleteUid).DeleteAsync();
+
+ Assert.IsNotNull(contentstackResponse);
+ Assert.IsTrue(contentstackResponse.IsSuccessStatusCode);
+ }
+ catch (Exception e)
+ {
+ Assert.Fail($"Delete release async failed: {e.Message}");
+ }
+ }
+
+
+ }
+}
\ No newline at end of file
diff --git a/Contentstack.Management.Core.Unit.Tests/Models/ReleaseTest.cs b/Contentstack.Management.Core.Unit.Tests/Models/ReleaseTest.cs
index 16f6170..a764b86 100644
--- a/Contentstack.Management.Core.Unit.Tests/Models/ReleaseTest.cs
+++ b/Contentstack.Management.Core.Unit.Tests/Models/ReleaseTest.cs
@@ -177,5 +177,235 @@ public async System.Threading.Tasks.Task Initialize_Release_Clone_Async()
Assert.AreEqual(_contentstackResponse.OpenResponse(), response.OpenResponse());
Assert.AreEqual(_contentstackResponse.OpenJObjectResponse().ToString(), response.OpenJObjectResponse().ToString());
}
+
+ [TestMethod]
+ public void Should_Deploy_Release()
+ {
+ ContentstackResponse response = _stack.Release(_fixture.Create()).Deploy(_fixture.Create());
+
+ Assert.AreEqual(_contentstackResponse.OpenResponse(), response.OpenResponse());
+ Assert.AreEqual(_contentstackResponse.OpenJObjectResponse().ToString(), response.OpenJObjectResponse().ToString());
+ }
+
+ [TestMethod]
+ public async System.Threading.Tasks.Task Should_Deploy_Release_Async()
+ {
+ ContentstackResponse response = await _stack.Release(_fixture.Create()).DeployAsync(_fixture.Create());
+
+ Assert.AreEqual(_contentstackResponse.OpenResponse(), response.OpenResponse());
+ Assert.AreEqual(_contentstackResponse.OpenJObjectResponse().ToString(), response.OpenJObjectResponse().ToString());
+ }
+
+ [TestMethod]
+ public void Should_Create_Release_With_ParameterCollection()
+ {
+ var parameters = new ParameterCollection();
+ parameters.Add("include_count", "true");
+ ContentstackResponse response = _stack.Release().Create(_fixture.Create(), parameters);
+
+ Assert.AreEqual(_contentstackResponse.OpenResponse(), response.OpenResponse());
+ Assert.AreEqual(_contentstackResponse.OpenJObjectResponse().ToString(), response.OpenJObjectResponse().ToString());
+ }
+
+ [TestMethod]
+ public async System.Threading.Tasks.Task Should_Create_Release_With_ParameterCollection_Async()
+ {
+ var parameters = new ParameterCollection();
+ parameters.Add("include_count", "true");
+ ContentstackResponse response = await _stack.Release().CreateAsync(_fixture.Create(), parameters);
+
+ Assert.AreEqual(_contentstackResponse.OpenResponse(), response.OpenResponse());
+ Assert.AreEqual(_contentstackResponse.OpenJObjectResponse().ToString(), response.OpenJObjectResponse().ToString());
+ }
+
+ [TestMethod]
+ public void Should_Update_Release_With_ParameterCollection()
+ {
+ var parameters = new ParameterCollection();
+ parameters.Add("include_count", "true");
+ ContentstackResponse response = _stack.Release(_fixture.Create()).Update(_fixture.Create(), parameters);
+
+ Assert.AreEqual(_contentstackResponse.OpenResponse(), response.OpenResponse());
+ Assert.AreEqual(_contentstackResponse.OpenJObjectResponse().ToString(), response.OpenJObjectResponse().ToString());
+ }
+
+ [TestMethod]
+ public async System.Threading.Tasks.Task Should_Update_Release_With_ParameterCollection_Async()
+ {
+ var parameters = new ParameterCollection();
+ parameters.Add("include_count", "true");
+ ContentstackResponse response = await _stack.Release(_fixture.Create()).UpdateAsync(_fixture.Create(), parameters);
+
+ Assert.AreEqual(_contentstackResponse.OpenResponse(), response.OpenResponse());
+ Assert.AreEqual(_contentstackResponse.OpenJObjectResponse().ToString(), response.OpenJObjectResponse().ToString());
+ }
+
+ [TestMethod]
+ public void Should_Throw_Exception_Deploy_Without_Uid()
+ {
+ Release release = new Release(_stack);
+ Assert.ThrowsException(() => release.Deploy(_fixture.Create()));
+ }
+
+ [TestMethod]
+ public async System.Threading.Tasks.Task Should_Throw_Exception_Deploy_Without_Uid_Async()
+ {
+ Release release = new Release(_stack);
+ await Assert.ThrowsExceptionAsync(() => release.DeployAsync(_fixture.Create()));
+ }
+
+ [TestMethod]
+ public void Should_Throw_Exception_Clone_Empty_Name()
+ {
+ Release release = new Release(_stack, _fixture.Create());
+ Assert.ThrowsException(() => release.Clone(string.Empty, _fixture.Create()));
+ }
+
+ [TestMethod]
+ public async System.Threading.Tasks.Task Should_Throw_Exception_Clone_Empty_Name_Async()
+ {
+ Release release = new Release(_stack, _fixture.Create());
+ await Assert.ThrowsExceptionAsync(() => release.CloneAsync(string.Empty, _fixture.Create()));
+ }
+
+ [TestMethod]
+ public void Should_Accept_Clone_Whitespace_Name()
+ {
+ Release release = new Release(_stack, _fixture.Create());
+ string whitespaceDescription = _fixture.Create();
+
+ // Whitespace names are accepted by the Clone method (only null/empty are rejected)
+ ContentstackResponse response = release.Clone(" ", whitespaceDescription);
+
+ Assert.AreEqual(_contentstackResponse.OpenResponse(), response.OpenResponse());
+ Assert.AreEqual(_contentstackResponse.OpenJObjectResponse().ToString(), response.OpenJObjectResponse().ToString());
+ }
+
+ [TestMethod]
+ public async System.Threading.Tasks.Task Should_Accept_Clone_Whitespace_Name_Async()
+ {
+ Release release = new Release(_stack, _fixture.Create());
+ string whitespaceDescription = _fixture.Create();
+
+ // Whitespace names are accepted by the Clone method (only null/empty are rejected)
+ ContentstackResponse response = await release.CloneAsync(" ", whitespaceDescription);
+
+ Assert.AreEqual(_contentstackResponse.OpenResponse(), response.OpenResponse());
+ Assert.AreEqual(_contentstackResponse.OpenJObjectResponse().ToString(), response.OpenJObjectResponse().ToString());
+ }
+
+ [TestMethod]
+ public void Should_Clone_Release_With_Description()
+ {
+ string name = _fixture.Create();
+ string description = _fixture.Create();
+ ContentstackResponse response = _stack.Release(_fixture.Create()).Clone(name, description);
+
+ Assert.AreEqual(_contentstackResponse.OpenResponse(), response.OpenResponse());
+ Assert.AreEqual(_contentstackResponse.OpenJObjectResponse().ToString(), response.OpenJObjectResponse().ToString());
+ }
+
+ [TestMethod]
+ public async System.Threading.Tasks.Task Should_Clone_Release_With_Description_Async()
+ {
+ string name = _fixture.Create();
+ string description = _fixture.Create();
+ ContentstackResponse response = await _stack.Release(_fixture.Create()).CloneAsync(name, description);
+
+ Assert.AreEqual(_contentstackResponse.OpenResponse(), response.OpenResponse());
+ Assert.AreEqual(_contentstackResponse.OpenJObjectResponse().ToString(), response.OpenJObjectResponse().ToString());
+ }
+
+ [TestMethod]
+ public void Should_Clone_Release_Without_Description()
+ {
+ string name = _fixture.Create();
+ ContentstackResponse response = _stack.Release(_fixture.Create()).Clone(name, null);
+
+ Assert.AreEqual(_contentstackResponse.OpenResponse(), response.OpenResponse());
+ Assert.AreEqual(_contentstackResponse.OpenJObjectResponse().ToString(), response.OpenJObjectResponse().ToString());
+ }
+
+ [TestMethod]
+ public async System.Threading.Tasks.Task Should_Clone_Release_Without_Description_Async()
+ {
+ string name = _fixture.Create();
+ ContentstackResponse response = await _stack.Release(_fixture.Create()).CloneAsync(name, null);
+
+ Assert.AreEqual(_contentstackResponse.OpenResponse(), response.OpenResponse());
+ Assert.AreEqual(_contentstackResponse.OpenJObjectResponse().ToString(), response.OpenJObjectResponse().ToString());
+ }
+
+ [TestMethod]
+ public void Should_Create_Release_With_Null_ParameterCollection()
+ {
+ ContentstackResponse response = _stack.Release().Create(_fixture.Create(), null);
+
+ Assert.AreEqual(_contentstackResponse.OpenResponse(), response.OpenResponse());
+ Assert.AreEqual(_contentstackResponse.OpenJObjectResponse().ToString(), response.OpenJObjectResponse().ToString());
+ }
+
+ [TestMethod]
+ public async System.Threading.Tasks.Task Should_Create_Release_With_Null_ParameterCollection_Async()
+ {
+ ContentstackResponse response = await _stack.Release().CreateAsync(_fixture.Create(), null);
+
+ Assert.AreEqual(_contentstackResponse.OpenResponse(), response.OpenResponse());
+ Assert.AreEqual(_contentstackResponse.OpenJObjectResponse().ToString(), response.OpenJObjectResponse().ToString());
+ }
+
+ [TestMethod]
+ public void Should_Update_Release_With_Null_ParameterCollection()
+ {
+ ContentstackResponse response = _stack.Release(_fixture.Create()).Update(_fixture.Create(), null);
+
+ Assert.AreEqual(_contentstackResponse.OpenResponse(), response.OpenResponse());
+ Assert.AreEqual(_contentstackResponse.OpenJObjectResponse().ToString(), response.OpenJObjectResponse().ToString());
+ }
+
+ [TestMethod]
+ public async System.Threading.Tasks.Task Should_Update_Release_With_Null_ParameterCollection_Async()
+ {
+ ContentstackResponse response = await _stack.Release(_fixture.Create()).UpdateAsync(_fixture.Create(), null);
+
+ Assert.AreEqual(_contentstackResponse.OpenResponse(), response.OpenResponse());
+ Assert.AreEqual(_contentstackResponse.OpenJObjectResponse().ToString(), response.OpenJObjectResponse().ToString());
+ }
+
+ [TestMethod]
+ public void Should_Verify_Resource_Path_Without_Uid()
+ {
+ Release release = new Release(_stack);
+ Assert.AreEqual("/releases", release.resourcePath);
+ }
+
+ [TestMethod]
+ public void Should_Verify_Resource_Path_With_Uid()
+ {
+ string uid = _fixture.Create();
+ Release release = new Release(_stack, uid);
+ Assert.AreEqual($"/releases/{uid}", release.resourcePath);
+ }
+
+ [TestMethod]
+ public void Should_Return_ReleaseItem_Instance()
+ {
+ string uid = _fixture.Create();
+ Release release = new Release(_stack, uid);
+ ReleaseItem releaseItem = release.Item();
+
+ Assert.IsNotNull(releaseItem);
+ Assert.AreEqual(typeof(ReleaseItem), releaseItem.GetType());
+ }
+
+ [TestMethod]
+ public void Should_Return_Query_Instance()
+ {
+ Release release = new Release(_stack);
+ Query query = release.Query();
+
+ Assert.IsNotNull(query);
+ Assert.AreEqual(typeof(Query), query.GetType());
+ }
}
}
diff --git a/Contentstack.Management.Core.Unit.Tests/Models/StackTest.cs b/Contentstack.Management.Core.Unit.Tests/Models/StackTest.cs
index 20de201..618af0d 100644
--- a/Contentstack.Management.Core.Unit.Tests/Models/StackTest.cs
+++ b/Contentstack.Management.Core.Unit.Tests/Models/StackTest.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using AutoFixture;
using Contentstack.Management.Core.Models;
+using Contentstack.Management.Core.Queryable;
using Contentstack.Management.Core.Unit.Tests.Mokes;
using Microsoft.VisualStudio.TestTools.UnitTesting;
@@ -1623,6 +1624,128 @@ public void Should_Throw_Bulk_Operation_With_Null_Release_Data()
Assert.ThrowsExceptionAsync(() => stack.BulkOperation().ReleaseItemsAsync(null));
}
+ [TestMethod]
+ public void Should_Return_Release_Instance()
+ {
+ client.contentstackOptions.Authtoken = _fixture.Create();
+ Stack stack = new Stack(client, _fixture.Create());
+
+ Release release = stack.Release();
+
+ Assert.IsNotNull(release);
+ Assert.AreEqual(typeof(Release), release.GetType());
+ Assert.IsNull(release.Uid);
+ Assert.AreEqual("/releases", release.resourcePath);
+ }
+
+ [TestMethod]
+ public void Should_Return_Release_Instance_With_Uid()
+ {
+ client.contentstackOptions.Authtoken = _fixture.Create();
+ Stack stack = new Stack(client, _fixture.Create());
+ string releaseUid = _fixture.Create();
+
+ Release release = stack.Release(releaseUid);
+
+ Assert.IsNotNull(release);
+ Assert.AreEqual(typeof(Release), release.GetType());
+ Assert.AreEqual(releaseUid, release.Uid);
+ Assert.AreEqual($"/releases/{releaseUid}", release.resourcePath);
+ }
+
+ [TestMethod]
+ public void Should_Create_Multiple_Release_Instances()
+ {
+ client.contentstackOptions.Authtoken = _fixture.Create();
+ Stack stack = new Stack(client, _fixture.Create());
+ string uid1 = _fixture.Create();
+ string uid2 = _fixture.Create();
+
+ Release release1 = stack.Release();
+ Release release2 = stack.Release(uid1);
+ Release release3 = stack.Release(uid2);
+
+ Assert.IsNotNull(release1);
+ Assert.IsNotNull(release2);
+ Assert.IsNotNull(release3);
+ Assert.AreNotSame(release1, release2);
+ Assert.AreNotSame(release2, release3);
+ Assert.IsNull(release1.Uid);
+ Assert.AreEqual(uid1, release2.Uid);
+ Assert.AreEqual(uid2, release3.Uid);
+ }
+
+ [TestMethod]
+ public void Should_Return_Release_With_Same_Stack_Reference()
+ {
+ client.contentstackOptions.Authtoken = _fixture.Create();
+ Stack stack = new Stack(client, _fixture.Create());
+
+ Release release = stack.Release();
+
+ Assert.IsNotNull(release);
+ // We can't directly access the stack property as it's internal,
+ // but we can verify the release instance is properly initialized
+ Assert.AreEqual(typeof(Release), release.GetType());
+ }
+
+ [TestMethod]
+ public void Should_Return_Release_Query_Instance()
+ {
+ client.contentstackOptions.Authtoken = _fixture.Create();
+ Stack stack = new Stack(client, _fixture.Create());
+
+ Release release = stack.Release();
+ Query query = release.Query();
+
+ Assert.IsNotNull(query);
+ Assert.AreEqual(typeof(Query), query.GetType());
+ }
+
+ [TestMethod]
+ public void Should_Return_ReleaseItem_Instance_With_Uid()
+ {
+ client.contentstackOptions.Authtoken = _fixture.Create();
+ Stack stack = new Stack(client, _fixture.Create());
+ string releaseUid = _fixture.Create();
+
+ Release release = stack.Release(releaseUid);
+ ReleaseItem releaseItem = release.Item();
+
+ Assert.IsNotNull(releaseItem);
+ Assert.AreEqual(typeof(ReleaseItem), releaseItem.GetType());
+ }
+
+ [TestMethod]
+ public void Should_Handle_Null_Uid_In_Release()
+ {
+ client.contentstackOptions.Authtoken = _fixture.Create();
+ Stack stack = new Stack(client, _fixture.Create());
+
+ Release release1 = stack.Release(null);
+ Release release2 = stack.Release();
+
+ Assert.IsNotNull(release1);
+ Assert.IsNotNull(release2);
+ Assert.IsNull(release1.Uid);
+ Assert.IsNull(release2.Uid);
+ Assert.AreEqual("/releases", release1.resourcePath);
+ Assert.AreEqual("/releases", release2.resourcePath);
+ }
+
+ [TestMethod]
+ public void Should_Handle_Empty_String_Uid_In_Release()
+ {
+ client.contentstackOptions.Authtoken = _fixture.Create();
+ Stack stack = new Stack(client, _fixture.Create());
+
+ Release release = stack.Release(string.Empty);
+
+ Assert.IsNotNull(release);
+ Assert.AreEqual(string.Empty, release.Uid);
+ Assert.AreEqual("/releases/", release.resourcePath);
+ }
+
#endregion
}
}
diff --git a/Contentstack.Management.Core/ContentstackClient.cs b/Contentstack.Management.Core/ContentstackClient.cs
index 27d153a..ddbcc25 100644
--- a/Contentstack.Management.Core/ContentstackClient.cs
+++ b/Contentstack.Management.Core/ContentstackClient.cs
@@ -35,7 +35,7 @@ public class ContentstackClient : IContentstackClient
private HttpClient _httpClient;
private bool _disposed = false;
- private string Version => "0.3.1";
+ private string Version => "0.3.2";
private string xUserAgent => $"contentstack-management-dotnet/{Version}";
#endregion
diff --git a/Directory.Build.props b/Directory.Build.props
index 863283f..216b2fd 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,5 +1,5 @@
- 0.3.1
+ 0.3.2