diff --git a/.gitignore b/.gitignore index a1e0da3..f0d5f50 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,7 @@ packages/ */mono** */appSettings.json api_referece/* -.sonarqube/ \ No newline at end of file +.sonarqube/ +*.html +*.cobertura.xml +integration-test-report_*.html diff --git a/Contentstack.Management.Core.Tests/Contentstack.Management.Core.Tests.csproj b/Contentstack.Management.Core.Tests/Contentstack.Management.Core.Tests.csproj index 74cce31..aec1149 100644 --- a/Contentstack.Management.Core.Tests/Contentstack.Management.Core.Tests.csproj +++ b/Contentstack.Management.Core.Tests/Contentstack.Management.Core.Tests.csproj @@ -28,6 +28,7 @@ + diff --git a/Contentstack.Management.Core.Tests/Contentstack.cs b/Contentstack.Management.Core.Tests/Contentstack.cs index 2426d71..7ff2492 100644 --- a/Contentstack.Management.Core.Tests/Contentstack.cs +++ b/Contentstack.Management.Core.Tests/Contentstack.cs @@ -1,9 +1,11 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; +using System.Net.Http; using System.Reflection; +using Contentstack.Management.Core.Tests.Helpers; using Contentstack.Management.Core.Tests.Model; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Options; @@ -14,15 +16,6 @@ namespace Contentstack.Management.Core.Tests { public class Contentstack { - private static readonly Lazy - client = - new Lazy(() => - { - ContentstackClientOptions options = Config.GetSection("Contentstack").Get(); - return new ContentstackClient(new OptionsWrapper(options)); - }); - - private static readonly Lazy config = new Lazy(() => @@ -42,13 +35,28 @@ private static readonly Lazy return Config.GetSection("Contentstack:Organization").Get(); }); - public static ContentstackClient Client { get { return client.Value; } } public static IConfigurationRoot Config{ get { return config.Value; } } public static NetworkCredential Credential { get { return credential.Value; } } public static OrganizationModel Organization { get { return organization.Value; } } public static StackModel Stack { get; set; } + /// + /// Creates a new ContentstackClient, logs in via the Login API (never from config), + /// and returns the authenticated client. Callers are responsible for calling Logout() + /// when done. + /// + public static ContentstackClient CreateAuthenticatedClient() + { + ContentstackClientOptions options = Config.GetSection("Contentstack").Get(); + options.Authtoken = null; + var handler = new LoggingHttpHandler(); + var httpClient = new HttpClient(handler); + var client = new ContentstackClient(httpClient, options); + client.Login(Credential); + return client; + } + public static T serialize(JsonSerializer serializer, string filePath) { string response = GetResourceText(filePath); diff --git a/Contentstack.Management.Core.Tests/Helpers/AssertLogger.cs b/Contentstack.Management.Core.Tests/Helpers/AssertLogger.cs new file mode 100644 index 0000000..29216f9 --- /dev/null +++ b/Contentstack.Management.Core.Tests/Helpers/AssertLogger.cs @@ -0,0 +1,114 @@ +using System; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Contentstack.Management.Core.Tests.Helpers +{ + public static class AssertLogger + { + public static void IsNotNull(object value, string name = "") + { + bool passed = value != null; + TestOutputLogger.LogAssertion($"IsNotNull({name})", "NotNull", value?.ToString() ?? "null", passed); + Assert.IsNotNull(value); + } + + public static void IsNull(object value, string name = "") + { + bool passed = value == null; + TestOutputLogger.LogAssertion($"IsNull({name})", "null", value?.ToString() ?? "null", passed); + Assert.IsNull(value); + } + + public static void AreEqual(T expected, T actual, string name = "") + { + bool passed = Equals(expected, actual); + TestOutputLogger.LogAssertion($"AreEqual({name})", expected?.ToString() ?? "null", actual?.ToString() ?? "null", passed); + Assert.AreEqual(expected, actual); + } + + public static void AreEqual(T expected, T actual, string message, string name) + { + bool passed = Equals(expected, actual); + TestOutputLogger.LogAssertion($"AreEqual({name})", expected?.ToString() ?? "null", actual?.ToString() ?? "null", passed); + Assert.AreEqual(expected, actual, message); + } + + public static void IsTrue(bool condition, string name = "") + { + TestOutputLogger.LogAssertion($"IsTrue({name})", "True", condition.ToString(), condition); + Assert.IsTrue(condition); + } + + public static void IsTrue(bool condition, string message, string name) + { + TestOutputLogger.LogAssertion($"IsTrue({name})", "True", condition.ToString(), condition); + Assert.IsTrue(condition, message); + } + + public static void IsFalse(bool condition, string name = "") + { + TestOutputLogger.LogAssertion($"IsFalse({name})", "False", condition.ToString(), !condition); + Assert.IsFalse(condition); + } + + public static void IsFalse(bool condition, string message, string name) + { + TestOutputLogger.LogAssertion($"IsFalse({name})", "False", condition.ToString(), !condition); + Assert.IsFalse(condition, message); + } + + public static void IsInstanceOfType(object value, Type expectedType, string name = "") + { + bool passed = value != null && expectedType.IsInstanceOfType(value); + TestOutputLogger.LogAssertion( + $"IsInstanceOfType({name})", + expectedType?.Name ?? "null", + value?.GetType()?.Name ?? "null", + passed); + Assert.IsInstanceOfType(value, expectedType); + } + + public static T ThrowsException(Action action, string name = "") where T : Exception + { + try + { + action(); + TestOutputLogger.LogAssertion($"ThrowsException<{typeof(T).Name}>({name})", typeof(T).Name, "NoException", false); + throw new AssertFailedException($"Expected exception {typeof(T).Name} was not thrown."); + } + catch (T ex) + { + TestOutputLogger.LogAssertion($"ThrowsException<{typeof(T).Name}>({name})", typeof(T).Name, typeof(T).Name, true); + return ex; + } + catch (AssertFailedException) + { + throw; + } + catch (Exception ex) + { + TestOutputLogger.LogAssertion($"ThrowsException<{typeof(T).Name}>({name})", typeof(T).Name, ex.GetType().Name, false); + throw new AssertFailedException( + $"Expected exception {typeof(T).Name} but got {ex.GetType().Name}: {ex.Message}", ex); + } + } + + public static void Fail(string message) + { + TestOutputLogger.LogAssertion("Fail", "N/A", message ?? "", false); + Assert.Fail(message); + } + + public static void Fail(string message, params object[] parameters) + { + TestOutputLogger.LogAssertion("Fail", "N/A", message ?? "", false); + Assert.Fail(message, parameters); + } + + public static void Inconclusive(string message) + { + TestOutputLogger.LogAssertion("Inconclusive", "N/A", message ?? "", false); + Assert.Inconclusive(message); + } + } +} diff --git a/Contentstack.Management.Core.Tests/Helpers/LoggingHttpHandler.cs b/Contentstack.Management.Core.Tests/Helpers/LoggingHttpHandler.cs new file mode 100644 index 0000000..67a300b --- /dev/null +++ b/Contentstack.Management.Core.Tests/Helpers/LoggingHttpHandler.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Contentstack.Management.Core.Tests.Helpers +{ + public class LoggingHttpHandler : DelegatingHandler + { + public LoggingHttpHandler() : base(new HttpClientHandler()) { } + public LoggingHttpHandler(HttpMessageHandler innerHandler) : base(innerHandler) { } + + protected override async Task SendAsync( + HttpRequestMessage request, CancellationToken cancellationToken) + { + try + { + await CaptureRequest(request); + } + catch + { + // Never let logging break the request + } + + var response = await base.SendAsync(request, cancellationToken); + + try + { + await CaptureResponse(response); + } + catch + { + // Never let logging break the response + } + + return response; + } + + private async Task CaptureRequest(HttpRequestMessage request) + { + var headers = new Dictionary(); + foreach (var h in request.Headers) + headers[h.Key] = string.Join(", ", h.Value); + + string body = null; + if (request.Content != null) + { + foreach (var h in request.Content.Headers) + headers[h.Key] = string.Join(", ", h.Value); + + await request.Content.LoadIntoBufferAsync(); + body = await request.Content.ReadAsStringAsync(); + } + + var curl = BuildCurl(request.Method.ToString(), request.RequestUri?.ToString(), headers, body); + + TestOutputLogger.LogHttpRequest( + method: request.Method.ToString(), + url: request.RequestUri?.ToString() ?? "", + headers: headers, + body: body ?? "", + curlCommand: curl, + sdkMethod: "" + ); + } + + private async Task CaptureResponse(HttpResponseMessage response) + { + var headers = new Dictionary(); + foreach (var h in response.Headers) + headers[h.Key] = string.Join(", ", h.Value); + + string body = null; + if (response.Content != null) + { + foreach (var h in response.Content.Headers) + headers[h.Key] = string.Join(", ", h.Value); + + await response.Content.LoadIntoBufferAsync(); + body = await response.Content.ReadAsStringAsync(); + } + + TestOutputLogger.LogHttpResponse( + statusCode: (int)response.StatusCode, + statusText: response.ReasonPhrase ?? response.StatusCode.ToString(), + headers: headers, + body: body ?? "" + ); + } + + private static string BuildCurl(string method, string url, + IDictionary headers, string body) + { + var sb = new StringBuilder(); + sb.Append($"curl -X {method} \\\n"); + sb.Append($" '{url}' \\\n"); + foreach (var kv in headers) + sb.Append($" -H '{kv.Key}: {kv.Value}' \\\n"); + if (!string.IsNullOrEmpty(body)) + { + var escaped = body.Replace("'", "'\\''"); + sb.Append($" -d '{escaped}'"); + } + return sb.ToString().TrimEnd('\\', '\n', ' '); + } + } +} diff --git a/Contentstack.Management.Core.Tests/Helpers/TestOutputLogger.cs b/Contentstack.Management.Core.Tests/Helpers/TestOutputLogger.cs new file mode 100644 index 0000000..557588a --- /dev/null +++ b/Contentstack.Management.Core.Tests/Helpers/TestOutputLogger.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace Contentstack.Management.Core.Tests.Helpers +{ + public static class TestOutputLogger + { + private const string START_MARKER = "###TEST_OUTPUT_START###"; + private const string END_MARKER = "###TEST_OUTPUT_END###"; + + public static void LogAssertion(string assertionName, object expected, object actual, bool passed) + { + Emit(new Dictionary + { + { "type", "ASSERTION" }, + { "assertionName", assertionName }, + { "expected", expected?.ToString() ?? "null" }, + { "actual", actual?.ToString() ?? "null" }, + { "passed", passed } + }); + } + + public static void LogHttpRequest(string method, string url, + IDictionary headers, string body, + string curlCommand, string sdkMethod) + { + Emit(new Dictionary + { + { "type", "HTTP_REQUEST" }, + { "method", method ?? "" }, + { "url", url ?? "" }, + { "headers", headers ?? new Dictionary() }, + { "body", body ?? "" }, + { "curlCommand", curlCommand ?? "" }, + { "sdkMethod", sdkMethod ?? "" } + }); + } + + public static void LogHttpResponse(int statusCode, string statusText, + IDictionary headers, string body) + { + Emit(new Dictionary + { + { "type", "HTTP_RESPONSE" }, + { "statusCode", statusCode }, + { "statusText", statusText ?? "" }, + { "headers", headers ?? new Dictionary() }, + { "body", body ?? "" } + }); + } + + public static void LogContext(string key, string value) + { + Emit(new Dictionary + { + { "type", "CONTEXT" }, + { "key", key ?? "" }, + { "value", value ?? "" } + }); + } + + private static void Emit(object data) + { + try + { + var json = JsonConvert.SerializeObject(data, Formatting.None); + Console.Write(START_MARKER); + Console.Write(json); + Console.WriteLine(END_MARKER); + } + catch + { + // Never let logging break a test + } + } + } +} diff --git a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack001_LoginTest.cs b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack001_LoginTest.cs index 16aaed8..766dd7b 100644 --- a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack001_LoginTest.cs +++ b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack001_LoginTest.cs @@ -1,11 +1,10 @@ -using System; +using System; using System.Net; +using System.Net.Http; using Contentstack.Management.Core.Exceptions; using Contentstack.Management.Core.Models; +using Contentstack.Management.Core.Tests.Helpers; using Microsoft.VisualStudio.TestTools.UnitTesting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Options; -using System.Threading; using Contentstack.Management.Core.Queryable; using Newtonsoft.Json.Linq; @@ -14,12 +13,20 @@ namespace Contentstack.Management.Core.Tests.IntegrationTest [TestClass] public class Contentstack001_LoginTest { - private readonly IConfigurationRoot _configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build(); + + private static ContentstackClient CreateClientWithLogging() + { + var handler = new LoggingHttpHandler(); + var httpClient = new HttpClient(handler); + return new ContentstackClient(httpClient, new ContentstackClientOptions()); + } + [TestMethod] [DoNotParallelize] public void Test001_Should_Return_Failuer_On_Wrong_Login_Credentials() { - ContentstackClient client = new ContentstackClient(); + TestOutputLogger.LogContext("TestScenario", "WrongCredentials"); + ContentstackClient client = CreateClientWithLogging(); NetworkCredential credentials = new NetworkCredential("mock_user", "mock_pasword"); try @@ -28,54 +35,55 @@ public void Test001_Should_Return_Failuer_On_Wrong_Login_Credentials() } catch (Exception e) { ContentstackErrorException errorException = e as ContentstackErrorException; - Assert.AreEqual(HttpStatusCode.UnprocessableEntity, errorException.StatusCode); - Assert.AreEqual("Looks like your email or password is invalid. Please try again or reset your password.", errorException.Message); - Assert.AreEqual("Looks like your email or password is invalid. Please try again or reset your password.", errorException.ErrorMessage); - Assert.AreEqual(104, errorException.ErrorCode); + AssertLogger.AreEqual(HttpStatusCode.UnprocessableEntity, errorException.StatusCode, "StatusCode"); + AssertLogger.AreEqual("Looks like your email or password is invalid. Please try again or reset your password.", errorException.Message, "Message"); + AssertLogger.AreEqual("Looks like your email or password is invalid. Please try again or reset your password.", errorException.ErrorMessage, "ErrorMessage"); + AssertLogger.AreEqual(104, errorException.ErrorCode, "ErrorCode"); } } [TestMethod] [DoNotParallelize] - public void Test002_Should_Return_Failuer_On_Wrong_Async_Login_Credentials() + public async System.Threading.Tasks.Task Test002_Should_Return_Failuer_On_Wrong_Async_Login_Credentials() { - ContentstackClient client = new ContentstackClient(); + TestOutputLogger.LogContext("TestScenario", "WrongCredentialsAsync"); + ContentstackClient client = CreateClientWithLogging(); NetworkCredential credentials = new NetworkCredential("mock_user", "mock_pasword"); - var response = client.LoginAsync(credentials); - - response.ContinueWith((t) => - { - if (t.IsCompleted && t.Status == System.Threading.Tasks.TaskStatus.Faulted) - { - ContentstackErrorException errorException = t.Exception.InnerException as ContentstackErrorException; - Assert.AreEqual(HttpStatusCode.UnprocessableEntity, errorException.StatusCode); - Assert.AreEqual("Looks like your email or password is invalid. Please try again or reset your password.", errorException.Message); - Assert.AreEqual("Looks like your email or password is invalid. Please try again or reset your password.", errorException.ErrorMessage); - Assert.AreEqual(104, errorException.ErrorCode); - } - }); - Thread.Sleep(3000); + + try + { + await client.LoginAsync(credentials); + AssertLogger.Fail("Expected exception for wrong credentials"); + } + catch (ContentstackErrorException errorException) + { + AssertLogger.AreEqual(HttpStatusCode.UnprocessableEntity, errorException.StatusCode, "StatusCode"); + AssertLogger.AreEqual("Looks like your email or password is invalid. Please try again or reset your password.", errorException.Message, "Message"); + AssertLogger.AreEqual("Looks like your email or password is invalid. Please try again or reset your password.", errorException.ErrorMessage, "ErrorMessage"); + AssertLogger.AreEqual(104, errorException.ErrorCode, "ErrorCode"); + } } [TestMethod] [DoNotParallelize] public async System.Threading.Tasks.Task Test003_Should_Return_Success_On_Async_Login() { - ContentstackClient client = new ContentstackClient(); + TestOutputLogger.LogContext("TestScenario", "AsyncLoginSuccess"); + ContentstackClient client = CreateClientWithLogging(); try { ContentstackResponse contentstackResponse = await client.LoginAsync(Contentstack.Credential); string loginResponse = contentstackResponse.OpenResponse(); - Assert.IsNotNull(client.contentstackOptions.Authtoken); - Assert.IsNotNull(loginResponse); + AssertLogger.IsNotNull(client.contentstackOptions.Authtoken, "Authtoken"); + AssertLogger.IsNotNull(loginResponse, "loginResponse"); await client.LogoutAsync(); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -83,19 +91,20 @@ public async System.Threading.Tasks.Task Test003_Should_Return_Success_On_Async_ [DoNotParallelize] public void Test004_Should_Return_Success_On_Login() { + TestOutputLogger.LogContext("TestScenario", "SyncLoginSuccess"); try { - ContentstackClient client = new ContentstackClient(); + ContentstackClient client = CreateClientWithLogging(); ContentstackResponse contentstackResponse = client.Login(Contentstack.Credential); string loginResponse = contentstackResponse.OpenResponse(); - Assert.IsNotNull(client.contentstackOptions.Authtoken); - Assert.IsNotNull(loginResponse); + AssertLogger.IsNotNull(client.contentstackOptions.Authtoken, "Authtoken"); + AssertLogger.IsNotNull(loginResponse, "loginResponse"); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -103,9 +112,10 @@ public void Test004_Should_Return_Success_On_Login() [DoNotParallelize] public void Test005_Should_Return_Loggedin_User() { + TestOutputLogger.LogContext("TestScenario", "GetUser"); try { - ContentstackClient client = new ContentstackClient(); + ContentstackClient client = CreateClientWithLogging(); client.Login(Contentstack.Credential); @@ -113,12 +123,12 @@ public void Test005_Should_Return_Loggedin_User() var user = response.OpenJObjectResponse(); - Assert.IsNotNull(user); + AssertLogger.IsNotNull(user, "user"); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -126,9 +136,10 @@ public void Test005_Should_Return_Loggedin_User() [DoNotParallelize] public async System.Threading.Tasks.Task Test006_Should_Return_Loggedin_User_Async() { + TestOutputLogger.LogContext("TestScenario", "GetUserAsync"); try { - ContentstackClient client = new ContentstackClient(); + ContentstackClient client = CreateClientWithLogging(); await client.LoginAsync(Contentstack.Credential); @@ -136,15 +147,15 @@ public async System.Threading.Tasks.Task Test006_Should_Return_Loggedin_User_Asy var user = response.OpenJObjectResponse(); - Assert.IsNotNull(user); - Assert.IsNotNull(user["user"]["organizations"]); - Assert.IsInstanceOfType(user["user"]["organizations"], typeof(JArray)); - Assert.IsNull(user["user"]["organizations"][0]["org_roles"]); + AssertLogger.IsNotNull(user, "user"); + AssertLogger.IsNotNull(user["user"]["organizations"], "organizations"); + AssertLogger.IsInstanceOfType(user["user"]["organizations"], typeof(JArray), "organizations"); + AssertLogger.IsNull(user["user"]["organizations"][0]["org_roles"], "org_roles"); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -152,12 +163,13 @@ public async System.Threading.Tasks.Task Test006_Should_Return_Loggedin_User_Asy [DoNotParallelize] public void Test007_Should_Return_Loggedin_User_With_Organizations_detail() { + TestOutputLogger.LogContext("TestScenario", "GetUserWithOrgRoles"); try { ParameterCollection collection = new ParameterCollection(); collection.Add("include_orgs_roles", true); - ContentstackClient client = new ContentstackClient(); + ContentstackClient client = CreateClientWithLogging(); client.Login(Contentstack.Credential); @@ -165,14 +177,14 @@ public void Test007_Should_Return_Loggedin_User_With_Organizations_detail() var user = response.OpenJObjectResponse(); - Assert.IsNotNull(user); - Assert.IsNotNull(user["user"]["organizations"]); - Assert.IsInstanceOfType(user["user"]["organizations"], typeof(JArray)); - Assert.IsNotNull(user["user"]["organizations"][0]["org_roles"]); + AssertLogger.IsNotNull(user, "user"); + AssertLogger.IsNotNull(user["user"]["organizations"], "organizations"); + AssertLogger.IsInstanceOfType(user["user"]["organizations"], typeof(JArray), "organizations"); + AssertLogger.IsNotNull(user["user"]["organizations"][0]["org_roles"], "org_roles"); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -180,23 +192,23 @@ public void Test007_Should_Return_Loggedin_User_With_Organizations_detail() [DoNotParallelize] public void Test008_Should_Fail_Login_With_Invalid_MfaSecret() { - ContentstackClient client = new ContentstackClient(); + TestOutputLogger.LogContext("TestScenario", "InvalidMfaSecret"); + ContentstackClient client = CreateClientWithLogging(); NetworkCredential credentials = new NetworkCredential("test_user", "test_password"); string invalidMfaSecret = "INVALID_BASE32_SECRET!@#"; try { ContentstackResponse contentstackResponse = client.Login(credentials, null, invalidMfaSecret); - Assert.Fail("Expected exception for invalid MFA secret"); + AssertLogger.Fail("Expected exception for invalid MFA secret"); } catch (ArgumentException) { - // Expected exception for invalid Base32 encoding - Assert.IsTrue(true); + AssertLogger.IsTrue(true, "ArgumentException thrown as expected"); } catch (Exception e) { - Assert.Fail($"Unexpected exception type: {e.GetType().Name} - {e.Message}"); + AssertLogger.Fail($"Unexpected exception type: {e.GetType().Name} - {e.Message}"); } } @@ -204,31 +216,29 @@ public void Test008_Should_Fail_Login_With_Invalid_MfaSecret() [DoNotParallelize] public void Test009_Should_Generate_TOTP_Token_With_Valid_MfaSecret() { - ContentstackClient client = new ContentstackClient(); + TestOutputLogger.LogContext("TestScenario", "ValidMfaSecret"); + ContentstackClient client = CreateClientWithLogging(); NetworkCredential credentials = new NetworkCredential("test_user", "test_password"); - string validMfaSecret = "JBSWY3DPEHPK3PXP"; // Valid Base32 test secret + string validMfaSecret = "JBSWY3DPEHPK3PXP"; try { - // This should fail due to invalid credentials, but should succeed in generating TOTP ContentstackResponse contentstackResponse = client.Login(credentials, null, validMfaSecret); } catch (ContentstackErrorException errorException) { - // Expected to fail due to invalid credentials, but we verify it processed the MFA secret - // The error should be about credentials, not about MFA secret format - Assert.AreEqual(HttpStatusCode.UnprocessableEntity, errorException.StatusCode); - Assert.IsTrue(errorException.Message.Contains("email or password") || + AssertLogger.AreEqual(HttpStatusCode.UnprocessableEntity, errorException.StatusCode, "StatusCode"); + AssertLogger.IsTrue(errorException.Message.Contains("email or password") || errorException.Message.Contains("credentials") || - errorException.Message.Contains("authentication")); + errorException.Message.Contains("authentication"), "MFA error message check"); } catch (ArgumentException) { - Assert.Fail("Should not throw ArgumentException for valid MFA secret"); + AssertLogger.Fail("Should not throw ArgumentException for valid MFA secret"); } catch (Exception e) { - Assert.Fail($"Unexpected exception type: {e.GetType().Name} - {e.Message}"); + AssertLogger.Fail($"Unexpected exception type: {e.GetType().Name} - {e.Message}"); } } @@ -236,31 +246,29 @@ public void Test009_Should_Generate_TOTP_Token_With_Valid_MfaSecret() [DoNotParallelize] public async System.Threading.Tasks.Task Test010_Should_Generate_TOTP_Token_With_Valid_MfaSecret_Async() { - ContentstackClient client = new ContentstackClient(); + TestOutputLogger.LogContext("TestScenario", "ValidMfaSecretAsync"); + ContentstackClient client = CreateClientWithLogging(); NetworkCredential credentials = new NetworkCredential("test_user", "test_password"); - string validMfaSecret = "JBSWY3DPEHPK3PXP"; // Valid Base32 test secret + string validMfaSecret = "JBSWY3DPEHPK3PXP"; try { - // This should fail due to invalid credentials, but should succeed in generating TOTP ContentstackResponse contentstackResponse = await client.LoginAsync(credentials, null, validMfaSecret); } catch (ContentstackErrorException errorException) { - // Expected to fail due to invalid credentials, but we verify it processed the MFA secret - // The error should be about credentials, not about MFA secret format - Assert.AreEqual(HttpStatusCode.UnprocessableEntity, errorException.StatusCode); - Assert.IsTrue(errorException.Message.Contains("email or password") || + AssertLogger.AreEqual(HttpStatusCode.UnprocessableEntity, errorException.StatusCode, "StatusCode"); + AssertLogger.IsTrue(errorException.Message.Contains("email or password") || errorException.Message.Contains("credentials") || - errorException.Message.Contains("authentication")); + errorException.Message.Contains("authentication"), "MFA error message check"); } catch (ArgumentException) { - Assert.Fail("Should not throw ArgumentException for valid MFA secret"); + AssertLogger.Fail("Should not throw ArgumentException for valid MFA secret"); } catch (Exception e) { - Assert.Fail($"Unexpected exception type: {e.GetType().Name} - {e.Message}"); + AssertLogger.Fail($"Unexpected exception type: {e.GetType().Name} - {e.Message}"); } } @@ -268,29 +276,220 @@ public async System.Threading.Tasks.Task Test010_Should_Generate_TOTP_Token_With [DoNotParallelize] public void Test011_Should_Prefer_Explicit_Token_Over_MfaSecret() { - ContentstackClient client = new ContentstackClient(); + TestOutputLogger.LogContext("TestScenario", "ExplicitTokenOverMfa"); + ContentstackClient client = CreateClientWithLogging(); NetworkCredential credentials = new NetworkCredential("test_user", "test_password"); string validMfaSecret = "JBSWY3DPEHPK3PXP"; string explicitToken = "123456"; try { - // This should fail due to invalid credentials, but should use explicit token ContentstackResponse contentstackResponse = client.Login(credentials, explicitToken, validMfaSecret); } catch (ContentstackErrorException errorException) { - // Expected to fail due to invalid credentials - // The important thing is that it didn't throw an exception about MFA secret processing - Assert.AreEqual(HttpStatusCode.UnprocessableEntity, errorException.StatusCode); + AssertLogger.AreEqual(HttpStatusCode.UnprocessableEntity, errorException.StatusCode, "StatusCode"); + } + catch (ArgumentException) + { + AssertLogger.Fail("Should not throw ArgumentException when explicit token is provided"); + } + catch (Exception e) + { + AssertLogger.Fail($"Unexpected exception type: {e.GetType().Name} - {e.Message}"); + } + } + + [TestMethod] + [DoNotParallelize] + public void Test012_Should_Throw_InvalidOperation_When_Already_LoggedIn_Sync() + { + TestOutputLogger.LogContext("TestScenario", "AlreadyLoggedInSync"); + ContentstackClient client = CreateClientWithLogging(); + + try + { + client.Login(Contentstack.Credential); + AssertLogger.IsNotNull(client.contentstackOptions.Authtoken, "Authtoken"); + + AssertLogger.ThrowsException(() => + client.Login(Contentstack.Credential), "AlreadyLoggedIn"); + + client.Logout(); + } + catch (Exception e) + { + AssertLogger.Fail($"Unexpected exception: {e.GetType().Name} - {e.Message}"); + } + } + + [TestMethod] + [DoNotParallelize] + public async System.Threading.Tasks.Task Test013_Should_Throw_InvalidOperation_When_Already_LoggedIn_Async() + { + TestOutputLogger.LogContext("TestScenario", "AlreadyLoggedInAsync"); + ContentstackClient client = CreateClientWithLogging(); + + try + { + await client.LoginAsync(Contentstack.Credential); + AssertLogger.IsNotNull(client.contentstackOptions.Authtoken, "Authtoken"); + + await System.Threading.Tasks.Task.Run(() => + AssertLogger.ThrowsException(() => + client.LoginAsync(Contentstack.Credential).GetAwaiter().GetResult(), "AlreadyLoggedInAsync")); + + await client.LogoutAsync(); + } + catch (Exception e) + { + AssertLogger.Fail($"Unexpected exception: {e.GetType().Name} - {e.Message}"); + } + } + + [TestMethod] + [DoNotParallelize] + public void Test014_Should_Throw_ArgumentNullException_For_Null_Credentials_Sync() + { + TestOutputLogger.LogContext("TestScenario", "NullCredentialsSync"); + ContentstackClient client = CreateClientWithLogging(); + + AssertLogger.ThrowsException(() => + client.Login(null), "NullCredentials"); + } + + [TestMethod] + [DoNotParallelize] + public void Test015_Should_Throw_ArgumentNullException_For_Null_Credentials_Async() + { + TestOutputLogger.LogContext("TestScenario", "NullCredentialsAsync"); + ContentstackClient client = CreateClientWithLogging(); + + AssertLogger.ThrowsException(() => + client.LoginAsync(null).GetAwaiter().GetResult(), "NullCredentialsAsync"); + } + + [TestMethod] + [DoNotParallelize] + public async System.Threading.Tasks.Task Test016_Should_Throw_ArgumentException_For_Invalid_MfaSecret_Async() + { + TestOutputLogger.LogContext("TestScenario", "InvalidMfaSecretAsync"); + ContentstackClient client = CreateClientWithLogging(); + NetworkCredential credentials = new NetworkCredential("test_user", "test_password"); + string invalidMfaSecret = "INVALID_BASE32_SECRET!@#"; + + try + { + await client.LoginAsync(credentials, null, invalidMfaSecret); + AssertLogger.Fail("Expected ArgumentException for invalid MFA secret"); } catch (ArgumentException) { - Assert.Fail("Should not throw ArgumentException when explicit token is provided"); + AssertLogger.IsTrue(true, "ArgumentException thrown as expected for async"); + } + catch (Exception e) + { + AssertLogger.Fail($"Unexpected exception type: {e.GetType().Name} - {e.Message}"); + } + } + + [TestMethod] + [DoNotParallelize] + public void Test017_Should_Handle_Valid_Credentials_With_TfaToken_Sync() + { + TestOutputLogger.LogContext("TestScenario", "WrongTfaTokenSync"); + ContentstackClient client = CreateClientWithLogging(); + + try + { + client.Login(Contentstack.Credential, "000000"); + // Account does not have 2FA enabled — tfa_token is ignored by the API and login succeeds. + // This is a valid outcome; assert token is set and clean up. + AssertLogger.IsNotNull(client.contentstackOptions.Authtoken, "Authtoken"); + client.Logout(); + } + catch (ContentstackErrorException errorException) + { + // Account has 2FA enabled — wrong token is correctly rejected with 422. + AssertLogger.AreEqual(HttpStatusCode.UnprocessableEntity, errorException.StatusCode, "StatusCode"); + AssertLogger.IsTrue(errorException.ErrorCode > 0, "TfaErrorCode"); + } + catch (Exception e) + { + AssertLogger.Fail($"Unexpected exception type: {e.GetType().Name} - {e.Message}"); + } + } + + [TestMethod] + [DoNotParallelize] + public async System.Threading.Tasks.Task Test018_Should_Handle_Valid_Credentials_With_TfaToken_Async() + { + TestOutputLogger.LogContext("TestScenario", "WrongTfaTokenAsync"); + ContentstackClient client = CreateClientWithLogging(); + + try + { + await client.LoginAsync(Contentstack.Credential, "000000"); + // Account does not have 2FA enabled — tfa_token is ignored by the API and login succeeds. + // This is a valid outcome; assert token is set and clean up. + AssertLogger.IsNotNull(client.contentstackOptions.Authtoken, "Authtoken"); + await client.LogoutAsync(); + } + catch (ContentstackErrorException errorException) + { + // Account has 2FA enabled — wrong token is correctly rejected with 422. + AssertLogger.AreEqual(HttpStatusCode.UnprocessableEntity, errorException.StatusCode, "StatusCode"); + AssertLogger.IsTrue(errorException.ErrorCode > 0, "TfaErrorCodeAsync"); + } + catch (Exception e) + { + AssertLogger.Fail($"Unexpected exception type: {e.GetType().Name} - {e.Message}"); + } + } + + [TestMethod] + [DoNotParallelize] + public void Test019_Should_Not_Include_TfaToken_When_MfaSecret_Is_Empty_Sync() + { + TestOutputLogger.LogContext("TestScenario", "EmptyMfaSecretSync"); + ContentstackClient client = CreateClientWithLogging(); + NetworkCredential credentials = new NetworkCredential("mock_user", "mock_password"); + + try + { + client.Login(credentials, null, ""); + } + catch (ContentstackErrorException errorException) + { + AssertLogger.AreEqual(HttpStatusCode.UnprocessableEntity, errorException.StatusCode, "StatusCode"); + AssertLogger.AreEqual(104, errorException.ErrorCode, "ErrorCode"); + } + catch (Exception e) + { + AssertLogger.Fail($"Unexpected exception type: {e.GetType().Name} - {e.Message}"); + } + } + + [TestMethod] + [DoNotParallelize] + public async System.Threading.Tasks.Task Test020_Should_Not_Include_TfaToken_When_MfaSecret_Is_Null_Async() + { + TestOutputLogger.LogContext("TestScenario", "NullMfaSecretAsync"); + ContentstackClient client = CreateClientWithLogging(); + NetworkCredential credentials = new NetworkCredential("mock_user", "mock_password"); + + try + { + await client.LoginAsync(credentials, null, null); + } + catch (ContentstackErrorException errorException) + { + AssertLogger.AreEqual(HttpStatusCode.UnprocessableEntity, errorException.StatusCode, "StatusCode"); + AssertLogger.AreEqual(104, errorException.ErrorCode, "ErrorCode"); } catch (Exception e) { - Assert.Fail($"Unexpected exception type: {e.GetType().Name} - {e.Message}"); + AssertLogger.Fail($"Unexpected exception type: {e.GetType().Name} - {e.Message}"); } } } diff --git a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack002_OrganisationTest.cs b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack002_OrganisationTest.cs index 584b520..354278a 100644 --- a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack002_OrganisationTest.cs +++ b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack002_OrganisationTest.cs @@ -1,8 +1,9 @@ -using System; +using System; using System.Net.Mail; using AutoFixture; using Contentstack.Management.Core.Models; using Contentstack.Management.Core.Queryable; +using Contentstack.Management.Core.Tests.Helpers; using Contentstack.Management.Core.Tests.Model; using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json.Linq; @@ -12,6 +13,7 @@ namespace Contentstack.Management.Core.Tests.IntegrationTest [TestClass] public class Contentstack002_OrganisationTest { + private static ContentstackClient _client; private double _count; static string RoleUID = ""; static string EmailSync = "testcs@contentstack.com"; @@ -20,23 +22,37 @@ public class Contentstack002_OrganisationTest static string InviteIDAsync = ""; private readonly IFixture _fixture = new Fixture(); + [ClassInitialize] + public static void ClassInitialize(TestContext context) + { + _client = Contentstack.CreateAuthenticatedClient(); + } + + [ClassCleanup] + public static void ClassCleanup() + { + try { _client?.Logout(); } catch { } + _client = null; + } + [TestMethod] [DoNotParallelize] public void Test001_Should_Return_All_Organizations() { + TestOutputLogger.LogContext("TestScenario", "GetAllOrganizations"); try { - Organization organization = Contentstack.Client.Organization(); + Organization organization = _client.Organization(); ContentstackResponse contentstackResponse = organization.GetOrganizations(); var response = contentstackResponse.OpenJObjectResponse(); - Assert.IsNotNull(response); + AssertLogger.IsNotNull(response, "response"); _count = (response["organizations"] as Newtonsoft.Json.Linq.JArray).Count; } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -45,20 +61,21 @@ public void Test001_Should_Return_All_Organizations() [DoNotParallelize] public async System.Threading.Tasks.Task Test002_Should_Return_All_OrganizationsAsync() { + TestOutputLogger.LogContext("TestScenario", "GetAllOrganizationsAsync"); try { - Organization organization = Contentstack.Client.Organization(); + Organization organization = _client.Organization(); ContentstackResponse contentstackResponse = await organization.GetOrganizationsAsync(); var response = contentstackResponse.OpenJObjectResponse(); - Assert.IsNotNull(response); + AssertLogger.IsNotNull(response, "response"); _count = (response["organizations"] as Newtonsoft.Json.Linq.JArray).Count; } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -67,20 +84,21 @@ public async System.Threading.Tasks.Task Test002_Should_Return_All_Organizations [DoNotParallelize] public void Test003_Should_Return_With_Skipping_Organizations() { + TestOutputLogger.LogContext("TestScenario", "SkipOrganizations"); try { - Organization organization = Contentstack.Client.Organization(); + Organization organization = _client.Organization(); ParameterCollection collection = new ParameterCollection(); collection.Add("skip", 4); ContentstackResponse contentstackResponse = organization.GetOrganizations(collection); var response = contentstackResponse.OpenJObjectResponse(); - Assert.IsNotNull(response); + AssertLogger.IsNotNull(response, "response"); var count = (response["organizations"] as Newtonsoft.Json.Linq.JArray).Count; } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -89,23 +107,25 @@ public void Test003_Should_Return_With_Skipping_Organizations() [DoNotParallelize] public void Test004_Should_Return_Organization_With_UID() { + TestOutputLogger.LogContext("TestScenario", "GetOrganizationByUID"); try { var org = Contentstack.Organization; - Organization organization = Contentstack.Client.Organization(org.Uid); + TestOutputLogger.LogContext("OrganizationUid", org.Uid); + Organization organization = _client.Organization(org.Uid); ContentstackResponse contentstackResponse = organization.GetOrganizations(); var response = contentstackResponse.OpenJObjectResponse(); - Assert.IsNotNull(response); - Assert.IsNotNull(response["organization"]); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.IsNotNull(response["organization"], "organization"); OrganisationResponse model = contentstackResponse.OpenTResponse(); - Assert.AreEqual(org.Name, model.Organization.Name); + AssertLogger.AreEqual(org.Name, model.Organization.Name, "OrganizationName"); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -114,24 +134,25 @@ public void Test004_Should_Return_Organization_With_UID() [DoNotParallelize] public void Test005_Should_Return_Organization_With_UID_Include_Plan() { + TestOutputLogger.LogContext("TestScenario", "GetOrganizationWithPlan"); try { var org = Contentstack.Organization; - Organization organization = Contentstack.Client.Organization(org.Uid); + Organization organization = _client.Organization(org.Uid); ParameterCollection collection = new ParameterCollection(); collection.Add("include_plan", true); ContentstackResponse contentstackResponse = organization.GetOrganizations(collection); var response = contentstackResponse.OpenJObjectResponse(); - Assert.IsNotNull(response); - Assert.IsNotNull(response["organization"]); - Assert.IsNotNull(response["organization"]["plan"]); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.IsNotNull(response["organization"], "organization"); + AssertLogger.IsNotNull(response["organization"]["plan"], "plan"); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -139,22 +160,23 @@ public void Test005_Should_Return_Organization_With_UID_Include_Plan() [DoNotParallelize] public void Test006_Should_Return_Organization_Roles() { + TestOutputLogger.LogContext("TestScenario", "GetOrganizationRoles"); try { var org = Contentstack.Organization; - Organization organization = Contentstack.Client.Organization(org.Uid); + Organization organization = _client.Organization(org.Uid); ContentstackResponse contentstackResponse = organization.Roles(); var response = contentstackResponse.OpenJObjectResponse(); RoleUID = (string)response["roles"][0]["uid"]; - Assert.IsNotNull(response); - Assert.IsNotNull(response["roles"]); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.IsNotNull(response["roles"], "roles"); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -163,20 +185,21 @@ public void Test006_Should_Return_Organization_Roles() [DoNotParallelize] public async System.Threading.Tasks.Task Test007_Should_Return_Organization_RolesAsync() { + TestOutputLogger.LogContext("TestScenario", "GetOrganizationRolesAsync"); try { var org = Contentstack.Organization; - Organization organization = Contentstack.Client.Organization(org.Uid); + Organization organization = _client.Organization(org.Uid); ContentstackResponse contentstackResponse = await organization.RolesAsync(); var response = contentstackResponse.OpenJObjectResponse(); - Assert.IsNotNull(response); - Assert.IsNotNull(response["roles"]); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.IsNotNull(response["roles"], "roles"); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -185,10 +208,11 @@ public async System.Threading.Tasks.Task Test007_Should_Return_Organization_Role [DoNotParallelize] public void Test008_Should_Add_User_To_Organization() { + TestOutputLogger.LogContext("TestScenario", "AddUserToOrg"); try { var org = Contentstack.Organization; - Organization organization = Contentstack.Client.Organization(org.Uid); + Organization organization = _client.Organization(org.Uid); UserInvitation invitation = new UserInvitation() { Email = EmailSync, @@ -200,14 +224,14 @@ public void Test008_Should_Add_User_To_Organization() }, null); var response = contentstackResponse.OpenJObjectResponse(); - Assert.IsNotNull(response); - Assert.AreEqual(1, ((JArray)response["shares"]).Count); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.AreEqual(1, ((JArray)response["shares"]).Count, "sharesCount"); InviteID = (string)response["shares"][0]["uid"]; - Assert.AreEqual("The invitation has been sent successfully.", response["notice"]); + AssertLogger.AreEqual("The invitation has been sent successfully.", (string)response["notice"], "notice"); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -216,10 +240,11 @@ public void Test008_Should_Add_User_To_Organization() [DoNotParallelize] public async System.Threading.Tasks.Task Test009_Should_Add_User_To_Organization() { + TestOutputLogger.LogContext("TestScenario", "AddUserToOrgAsync"); try { var org = Contentstack.Organization; - Organization organization = Contentstack.Client.Organization(org.Uid); + Organization organization = _client.Organization(org.Uid); UserInvitation invitation = new UserInvitation() { Email = EmailAsync, @@ -231,14 +256,14 @@ public async System.Threading.Tasks.Task Test009_Should_Add_User_To_Organization }, null); var response = contentstackResponse.OpenJObjectResponse(); - Assert.IsNotNull(response); - Assert.AreEqual(1, ((JArray)response["shares"]).Count); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.AreEqual(1, ((JArray)response["shares"]).Count, "sharesCount"); InviteIDAsync = (string)response["shares"][0]["uid"]; - Assert.AreEqual("The invitation has been sent successfully.", response["notice"]); + AssertLogger.AreEqual("The invitation has been sent successfully.", (string)response["notice"], "notice"); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -246,20 +271,21 @@ public async System.Threading.Tasks.Task Test009_Should_Add_User_To_Organization [DoNotParallelize] public void Test010_Should_Resend_Invite() { + TestOutputLogger.LogContext("TestScenario", "ResendInvite"); try { var org = Contentstack.Organization; - Organization organization = Contentstack.Client.Organization(org.Uid); + Organization organization = _client.Organization(org.Uid); ContentstackResponse contentstackResponse = organization.ResendInvitation(InviteID); var response = contentstackResponse.OpenJObjectResponse(); - Assert.IsNotNull(response); - Assert.AreEqual("The invitation has been resent successfully.", response["notice"]); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.AreEqual("The invitation has been resent successfully.", (string)response["notice"], "notice"); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -268,19 +294,20 @@ public void Test010_Should_Resend_Invite() [DoNotParallelize] public async System.Threading.Tasks.Task Test011_Should_Resend_Invite() { + TestOutputLogger.LogContext("TestScenario", "ResendInviteAsync"); try { var org = Contentstack.Organization; - Organization organization = Contentstack.Client.Organization(org.Uid); + Organization organization = _client.Organization(org.Uid); ContentstackResponse contentstackResponse = await organization.ResendInvitationAsync(InviteIDAsync); var response = contentstackResponse.OpenJObjectResponse(); - Assert.IsNotNull(response); - Assert.AreEqual("The invitation has been resent successfully.", response["notice"]); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.AreEqual("The invitation has been resent successfully.", (string)response["notice"], "notice"); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -289,20 +316,21 @@ public async System.Threading.Tasks.Task Test011_Should_Resend_Invite() [DoNotParallelize] public void Test012_Should_Remove_User_From_Organization() { + TestOutputLogger.LogContext("TestScenario", "RemoveUser"); try { var org = Contentstack.Organization; - Organization organization = Contentstack.Client.Organization(org.Uid); + Organization organization = _client.Organization(org.Uid); ContentstackResponse contentstackResponse = organization.RemoveUser(new System.Collections.Generic.List() { EmailSync } ); var response = contentstackResponse.OpenJObjectResponse(); - Assert.IsNotNull(response); - Assert.AreEqual("The invitation has been deleted successfully.", response["notice"]); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.AreEqual("The invitation has been deleted successfully.", (string)response["notice"], "notice"); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -311,19 +339,20 @@ public void Test012_Should_Remove_User_From_Organization() [DoNotParallelize] public async System.Threading.Tasks.Task Test013_Should_Remove_User_From_Organization() { + TestOutputLogger.LogContext("TestScenario", "RemoveUserAsync"); try { var org = Contentstack.Organization; - Organization organization = Contentstack.Client.Organization(org.Uid); + Organization organization = _client.Organization(org.Uid); ContentstackResponse contentstackResponse = await organization.RemoveUserAsync(new System.Collections.Generic.List() { EmailAsync }); var response = contentstackResponse.OpenJObjectResponse(); - Assert.IsNotNull(response); - Assert.AreEqual("The invitation has been deleted successfully.", response["notice"]); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.AreEqual("The invitation has been deleted successfully.", (string)response["notice"], "notice"); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -332,22 +361,23 @@ public async System.Threading.Tasks.Task Test013_Should_Remove_User_From_Organiz [DoNotParallelize] public void Test014_Should_Get_All_Invites() { + TestOutputLogger.LogContext("TestScenario", "GetAllInvites"); try { var org = Contentstack.Organization; - Organization organization = Contentstack.Client.Organization(org.Uid); + Organization organization = _client.Organization(org.Uid); ContentstackResponse contentstackResponse = organization.GetInvitations(); var response = contentstackResponse.OpenJObjectResponse(); - Assert.IsNotNull(response); - Assert.IsNotNull(response["shares"]); - Assert.AreEqual(response["shares"].GetType(), typeof(JArray)); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.IsNotNull(response["shares"], "shares"); + AssertLogger.AreEqual(response["shares"].GetType(), typeof(JArray), "sharesType"); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -356,20 +386,21 @@ public void Test014_Should_Get_All_Invites() [DoNotParallelize] public async System.Threading.Tasks.Task Test015_Should_Get_All_Invites_Async() { + TestOutputLogger.LogContext("TestScenario", "GetAllInvitesAsync"); try { var org = Contentstack.Organization; - Organization organization = Contentstack.Client.Organization(org.Uid); + Organization organization = _client.Organization(org.Uid); ContentstackResponse contentstackResponse = await organization.GetInvitationsAsync(); var response = contentstackResponse.OpenJObjectResponse(); - Assert.IsNotNull(response); - Assert.IsNotNull(response["shares"]); - Assert.AreEqual(response["shares"].GetType(), typeof(JArray)); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.IsNotNull(response["shares"], "shares"); + AssertLogger.AreEqual(response["shares"].GetType(), typeof(JArray), "sharesType"); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -378,22 +409,23 @@ public async System.Threading.Tasks.Task Test015_Should_Get_All_Invites_Async() [DoNotParallelize] public void Test016_Should_Get_All_Stacks() { + TestOutputLogger.LogContext("TestScenario", "GetAllStacks"); try { var org = Contentstack.Organization; - Organization organization = Contentstack.Client.Organization(org.Uid); + Organization organization = _client.Organization(org.Uid); ContentstackResponse contentstackResponse = organization.GetStacks(); var response = contentstackResponse.OpenJObjectResponse(); - Assert.IsNotNull(response); - Assert.IsNotNull(response["stacks"]); - Assert.AreEqual(response["stacks"].GetType(), typeof(JArray)); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.IsNotNull(response["stacks"], "stacks"); + AssertLogger.AreEqual(response["stacks"].GetType(), typeof(JArray), "stacksType"); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -402,20 +434,21 @@ public void Test016_Should_Get_All_Stacks() [DoNotParallelize] public async System.Threading.Tasks.Task Test017_Should_Get_All_Stacks_Async() { + TestOutputLogger.LogContext("TestScenario", "GetAllStacksAsync"); try { var org = Contentstack.Organization; - Organization organization = Contentstack.Client.Organization(org.Uid); + Organization organization = _client.Organization(org.Uid); ContentstackResponse contentstackResponse = await organization.GetStacksAsync(); var response = contentstackResponse.OpenJObjectResponse(); - Assert.IsNotNull(response); - Assert.IsNotNull(response["stacks"]); - Assert.AreEqual(response["stacks"].GetType(), typeof(JArray)); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.IsNotNull(response["stacks"], "stacks"); + AssertLogger.AreEqual(response["stacks"].GetType(), typeof(JArray), "stacksType"); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } diff --git a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack003_StackTest.cs b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack003_StackTest.cs index 211a4ca..eb4ba94 100644 --- a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack003_StackTest.cs +++ b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack003_StackTest.cs @@ -1,7 +1,8 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using Contentstack.Management.Core.Models; +using Contentstack.Management.Core.Tests.Helpers; using Contentstack.Management.Core.Tests.Model; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -10,6 +11,7 @@ namespace Contentstack.Management.Core.Tests.IntegrationTest [TestClass] public class Contentstack003_StackTest { + private static ContentstackClient _client; private readonly string _locale = "en-us"; private string _stackName = "DotNet Management Stack"; private string _updatestackName = "DotNet Management SDK Stack"; @@ -17,22 +19,36 @@ public class Contentstack003_StackTest private OrganizationModel _org = Contentstack.Organization; + [ClassInitialize] + public static void ClassInitialize(TestContext context) + { + _client = Contentstack.CreateAuthenticatedClient(); + } + + [ClassCleanup] + public static void ClassCleanup() + { + try { _client?.Logout(); } catch { } + _client = null; + } + [TestMethod] [DoNotParallelize] public void Test001_Should_Return_All_Stacks() { + TestOutputLogger.LogContext("TestScenario", "ReturnAllStacks"); try { - Stack stack = Contentstack.Client.Stack(); + Stack stack = _client.Stack(); ContentstackResponse contentstackResponse = stack.GetAll(); var response = contentstackResponse.OpenJObjectResponse(); - Assert.IsNotNull(response); + AssertLogger.IsNotNull(response, "response"); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -40,18 +56,19 @@ public void Test001_Should_Return_All_Stacks() [DoNotParallelize] public async System.Threading.Tasks.Task Test002_Should_Return_All_StacksAsync() { + TestOutputLogger.LogContext("TestScenario", "ReturnAllStacksAsync"); try { - Stack stack = Contentstack.Client.Stack(); + Stack stack = _client.Stack(); ContentstackResponse contentstackResponse = await stack.GetAllAsync(); var response = contentstackResponse.OpenJObjectResponse(); - Assert.IsNotNull(response); + AssertLogger.IsNotNull(response, "response"); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -60,24 +77,26 @@ public async System.Threading.Tasks.Task Test002_Should_Return_All_StacksAsync() [DoNotParallelize] public void Test003_Should_Create_Stack() { + TestOutputLogger.LogContext("TestScenario", "CreateStack"); try { - Stack stack = Contentstack.Client.Stack(); + Stack stack = _client.Stack(); ContentstackResponse contentstackResponse = stack.Create(_stackName, _locale, _org.Uid); var response = contentstackResponse.OpenJObjectResponse(); StackResponse model = contentstackResponse.OpenTResponse(); Contentstack.Stack = model.Stack; + TestOutputLogger.LogContext("StackApiKey", model.Stack.APIKey); - Assert.IsNotNull(response); - Assert.IsNull(model.Stack.Description); - Assert.AreEqual(_stackName, model.Stack.Name); - Assert.AreEqual(_locale, model.Stack.MasterLocale); - Assert.AreEqual(_org.Uid, model.Stack.OrgUid); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.IsNull(model.Stack.Description, "model.Stack.Description"); + AssertLogger.AreEqual(_stackName, model.Stack.Name, "StackName"); + AssertLogger.AreEqual(_locale, model.Stack.MasterLocale, "MasterLocale"); + AssertLogger.AreEqual(_org.Uid, model.Stack.OrgUid, "OrgUid"); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -85,9 +104,11 @@ public void Test003_Should_Create_Stack() [DoNotParallelize] public void Test004_Should_Update_Stack() { + TestOutputLogger.LogContext("TestScenario", "UpdateStack"); + TestOutputLogger.LogContext("StackApiKey", Contentstack.Stack.APIKey); try { - Stack stack = Contentstack.Client.Stack(Contentstack.Stack.APIKey); + Stack stack = _client.Stack(Contentstack.Stack.APIKey); ContentstackResponse contentstackResponse = stack.Update(_updatestackName); var response = contentstackResponse.OpenJObjectResponse(); @@ -96,16 +117,16 @@ public void Test004_Should_Update_Stack() StackResponse model = contentstackResponse.OpenTResponse(); Contentstack.Stack = model.Stack; - Assert.IsNotNull(response); - Assert.IsNull(model.Stack.Description); - Assert.AreEqual(Contentstack.Stack.APIKey, model.Stack.APIKey); - Assert.AreEqual(_updatestackName, model.Stack.Name); - Assert.AreEqual(_locale, model.Stack.MasterLocale); - Assert.AreEqual(_org.Uid, model.Stack.OrgUid); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.IsNull(model.Stack.Description, "model.Stack.Description"); + AssertLogger.AreEqual(Contentstack.Stack.APIKey, model.Stack.APIKey, "APIKey"); + AssertLogger.AreEqual(_updatestackName, model.Stack.Name, "StackName"); + AssertLogger.AreEqual(_locale, model.Stack.MasterLocale, "MasterLocale"); + AssertLogger.AreEqual(_org.Uid, model.Stack.OrgUid, "OrgUid"); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -113,25 +134,27 @@ public void Test004_Should_Update_Stack() [DoNotParallelize] public async System.Threading.Tasks.Task Test005_Should_Update_Stack_Async() { + TestOutputLogger.LogContext("TestScenario", "UpdateStackAsync"); + TestOutputLogger.LogContext("StackApiKey", Contentstack.Stack.APIKey); try { - Stack stack = Contentstack.Client.Stack(Contentstack.Stack.APIKey); + Stack stack = _client.Stack(Contentstack.Stack.APIKey); ContentstackResponse contentstackResponse = await stack.UpdateAsync(_updatestackName, _description); var response = contentstackResponse.OpenJObjectResponse(); StackResponse model = contentstackResponse.OpenTResponse(); Contentstack.Stack = model.Stack; - Assert.IsNotNull(response); - Assert.AreEqual(Contentstack.Stack.APIKey, model.Stack.APIKey); - Assert.AreEqual(_updatestackName, model.Stack.Name); - Assert.AreEqual(_locale, model.Stack.MasterLocale); - Assert.AreEqual(_description, model.Stack.Description); - Assert.AreEqual(_org.Uid, model.Stack.OrgUid); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.AreEqual(Contentstack.Stack.APIKey, model.Stack.APIKey, "APIKey"); + AssertLogger.AreEqual(_updatestackName, model.Stack.Name, "StackName"); + AssertLogger.AreEqual(_locale, model.Stack.MasterLocale, "MasterLocale"); + AssertLogger.AreEqual(_description, model.Stack.Description, "Description"); + AssertLogger.AreEqual(_org.Uid, model.Stack.OrgUid, "OrgUid"); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -139,24 +162,26 @@ public async System.Threading.Tasks.Task Test005_Should_Update_Stack_Async() [DoNotParallelize] public void Test006_Should_Fetch_Stack() { + TestOutputLogger.LogContext("TestScenario", "FetchStack"); + TestOutputLogger.LogContext("StackApiKey", Contentstack.Stack.APIKey); try { - Stack stack = Contentstack.Client.Stack(Contentstack.Stack.APIKey); + Stack stack = _client.Stack(Contentstack.Stack.APIKey); ContentstackResponse contentstackResponse = stack.Fetch(); var response = contentstackResponse.OpenJObjectResponse(); StackResponse model = contentstackResponse.OpenTResponse(); - Assert.IsNotNull(response); - Assert.AreEqual(Contentstack.Stack.APIKey, model.Stack.APIKey); - Assert.AreEqual(Contentstack.Stack.Name, model.Stack.Name); - Assert.AreEqual(Contentstack.Stack.MasterLocale, model.Stack.MasterLocale); - Assert.AreEqual(Contentstack.Stack.Description, model.Stack.Description); - Assert.AreEqual(Contentstack.Stack.OrgUid, model.Stack.OrgUid); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.AreEqual(Contentstack.Stack.APIKey, model.Stack.APIKey, "APIKey"); + AssertLogger.AreEqual(Contentstack.Stack.Name, model.Stack.Name, "StackName"); + AssertLogger.AreEqual(Contentstack.Stack.MasterLocale, model.Stack.MasterLocale, "MasterLocale"); + AssertLogger.AreEqual(Contentstack.Stack.Description, model.Stack.Description, "Description"); + AssertLogger.AreEqual(Contentstack.Stack.OrgUid, model.Stack.OrgUid, "OrgUid"); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -164,24 +189,26 @@ public void Test006_Should_Fetch_Stack() [DoNotParallelize] public async System.Threading.Tasks.Task Test007_Should_Fetch_StackAsync() { + TestOutputLogger.LogContext("TestScenario", "FetchStackAsync"); + TestOutputLogger.LogContext("StackApiKey", Contentstack.Stack.APIKey); try { - Stack stack = Contentstack.Client.Stack(Contentstack.Stack.APIKey); + Stack stack = _client.Stack(Contentstack.Stack.APIKey); ContentstackResponse contentstackResponse = await stack.FetchAsync(); var response = contentstackResponse.OpenJObjectResponse(); StackResponse model = contentstackResponse.OpenTResponse(); - Assert.IsNotNull(response); - Assert.AreEqual(Contentstack.Stack.APIKey, model.Stack.APIKey); - Assert.AreEqual(Contentstack.Stack.Name, model.Stack.Name); - Assert.AreEqual(Contentstack.Stack.MasterLocale, model.Stack.MasterLocale); - Assert.AreEqual(Contentstack.Stack.Description, model.Stack.Description); - Assert.AreEqual(Contentstack.Stack.OrgUid, model.Stack.OrgUid); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.AreEqual(Contentstack.Stack.APIKey, model.Stack.APIKey, "APIKey"); + AssertLogger.AreEqual(Contentstack.Stack.Name, model.Stack.Name, "StackName"); + AssertLogger.AreEqual(Contentstack.Stack.MasterLocale, model.Stack.MasterLocale, "MasterLocale"); + AssertLogger.AreEqual(Contentstack.Stack.Description, model.Stack.Description, "Description"); + AssertLogger.AreEqual(Contentstack.Stack.OrgUid, model.Stack.OrgUid, "OrgUid"); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -189,9 +216,11 @@ public async System.Threading.Tasks.Task Test007_Should_Fetch_StackAsync() [DoNotParallelize] public void Test008_Add_Stack_Settings() { + TestOutputLogger.LogContext("TestScenario", "AddStackSettings"); + TestOutputLogger.LogContext("StackApiKey", Contentstack.Stack.APIKey); try { - Stack stack = Contentstack.Client.Stack(Contentstack.Stack.APIKey); + Stack stack = _client.Stack(Contentstack.Stack.APIKey); StackSettings settings = new StackSettings() { StackVariables = new Dictionary() @@ -206,14 +235,14 @@ public void Test008_Add_Stack_Settings() var response = contentstackResponse.OpenJObjectResponse(); StackSettingsModel model = contentstackResponse.OpenTResponse(); - Assert.IsNotNull(response); - Assert.AreEqual("Stack settings updated successfully.", model.Notice); - Assert.AreEqual(true, model.StackSettings.StackVariables["enforce_unique_urls"]); - Assert.AreEqual("figure", model.StackSettings.StackVariables["sys_rte_allowed_tags"]); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.AreEqual("Stack settings updated successfully.", model.Notice, "Notice"); + AssertLogger.AreEqual(true, model.StackSettings.StackVariables["enforce_unique_urls"], "enforce_unique_urls"); + AssertLogger.AreEqual("figure", model.StackSettings.StackVariables["sys_rte_allowed_tags"], "sys_rte_allowed_tags"); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -221,23 +250,25 @@ public void Test008_Add_Stack_Settings() [DoNotParallelize] public void Test009_Stack_Settings() { + TestOutputLogger.LogContext("TestScenario", "StackSettings"); + TestOutputLogger.LogContext("StackApiKey", Contentstack.Stack.APIKey); try { - Stack stack = Contentstack.Client.Stack(Contentstack.Stack.APIKey); + Stack stack = _client.Stack(Contentstack.Stack.APIKey); ContentstackResponse contentstackResponse = stack.Settings(); var response = contentstackResponse.OpenJObjectResponse(); StackSettingsModel model = contentstackResponse.OpenTResponse(); - Assert.IsNotNull(response); - Assert.IsNull(model.Notice); - Assert.AreEqual(true, model.StackSettings.StackVariables["enforce_unique_urls"]); - Assert.AreEqual("figure", model.StackSettings.StackVariables["sys_rte_allowed_tags"]); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.IsNull(model.Notice, "model.Notice"); + AssertLogger.AreEqual(true, model.StackSettings.StackVariables["enforce_unique_urls"], "enforce_unique_urls"); + AssertLogger.AreEqual("figure", model.StackSettings.StackVariables["sys_rte_allowed_tags"], "sys_rte_allowed_tags"); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -245,23 +276,25 @@ public void Test009_Stack_Settings() [DoNotParallelize] public void Test010_Reset_Stack_Settings() { + TestOutputLogger.LogContext("TestScenario", "ResetStackSettings"); + TestOutputLogger.LogContext("StackApiKey", Contentstack.Stack.APIKey); try { - Stack stack = Contentstack.Client.Stack(Contentstack.Stack.APIKey); + Stack stack = _client.Stack(Contentstack.Stack.APIKey); ContentstackResponse contentstackResponse = stack.ResetSettings(); var response = contentstackResponse.OpenJObjectResponse(); StackSettingsModel model = contentstackResponse.OpenTResponse(); - Assert.IsNotNull(response); - Assert.AreEqual("Stack settings updated successfully.", model.Notice); - Assert.AreEqual(true, model.StackSettings.StackVariables["enforce_unique_urls"]); - Assert.AreEqual("figure", model.StackSettings.StackVariables["sys_rte_allowed_tags"]); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.AreEqual("Stack settings updated successfully.", model.Notice, "Notice"); + AssertLogger.AreEqual(true, model.StackSettings.StackVariables["enforce_unique_urls"], "enforce_unique_urls"); + AssertLogger.AreEqual("figure", model.StackSettings.StackVariables["sys_rte_allowed_tags"], "sys_rte_allowed_tags"); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -269,9 +302,11 @@ public void Test010_Reset_Stack_Settings() [DoNotParallelize] public async System.Threading.Tasks.Task Test011_Add_Stack_Settings_Async() { + TestOutputLogger.LogContext("TestScenario", "AddStackSettingsAsync"); + TestOutputLogger.LogContext("StackApiKey", Contentstack.Stack.APIKey); try { - Stack stack = Contentstack.Client.Stack(Contentstack.Stack.APIKey); + Stack stack = _client.Stack(Contentstack.Stack.APIKey); StackSettings settings = new StackSettings() { Rte = new Dictionary() @@ -285,13 +320,13 @@ public async System.Threading.Tasks.Task Test011_Add_Stack_Settings_Async() var response = contentstackResponse.OpenJObjectResponse(); StackSettingsModel model = contentstackResponse.OpenTResponse(); - Assert.IsNotNull(response); - Assert.AreEqual("Stack settings updated successfully.", model.Notice); - Assert.AreEqual(true, model.StackSettings.Rte["cs_only_breakline"]); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.AreEqual("Stack settings updated successfully.", model.Notice, "Notice"); + AssertLogger.AreEqual(true, model.StackSettings.Rte["cs_only_breakline"], "cs_only_breakline"); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -299,23 +334,25 @@ public async System.Threading.Tasks.Task Test011_Add_Stack_Settings_Async() [DoNotParallelize] public async System.Threading.Tasks.Task Test012_Reset_Stack_Settings_Async() { + TestOutputLogger.LogContext("TestScenario", "ResetStackSettingsAsync"); + TestOutputLogger.LogContext("StackApiKey", Contentstack.Stack.APIKey); try { - Stack stack = Contentstack.Client.Stack(Contentstack.Stack.APIKey); + Stack stack = _client.Stack(Contentstack.Stack.APIKey); ContentstackResponse contentstackResponse = await stack.ResetSettingsAsync(); var response = contentstackResponse.OpenJObjectResponse(); StackSettingsModel model = contentstackResponse.OpenTResponse(); - Assert.IsNotNull(response); - Assert.AreEqual("Stack settings updated successfully.", model.Notice); - Assert.AreEqual(true, model.StackSettings.StackVariables["enforce_unique_urls"]); - Assert.AreEqual("figure", model.StackSettings.StackVariables["sys_rte_allowed_tags"]); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.AreEqual("Stack settings updated successfully.", model.Notice, "Notice"); + AssertLogger.AreEqual(true, model.StackSettings.StackVariables["enforce_unique_urls"], "enforce_unique_urls"); + AssertLogger.AreEqual("figure", model.StackSettings.StackVariables["sys_rte_allowed_tags"], "sys_rte_allowed_tags"); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } @@ -323,22 +360,24 @@ public async System.Threading.Tasks.Task Test012_Reset_Stack_Settings_Async() [DoNotParallelize] public async System.Threading.Tasks.Task Test013_Stack_Settings_Async() { + TestOutputLogger.LogContext("TestScenario", "StackSettingsAsync"); + TestOutputLogger.LogContext("StackApiKey", Contentstack.Stack.APIKey); try { - Stack stack = Contentstack.Client.Stack(Contentstack.Stack.APIKey); + Stack stack = _client.Stack(Contentstack.Stack.APIKey); ContentstackResponse contentstackResponse = await stack.SettingsAsync(); var response = contentstackResponse.OpenJObjectResponse(); StackSettingsModel model = contentstackResponse.OpenTResponse(); - Assert.IsNotNull(response); - Assert.AreEqual(true, model.StackSettings.StackVariables["enforce_unique_urls"]); - Assert.AreEqual("figure", model.StackSettings.StackVariables["sys_rte_allowed_tags"]); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.AreEqual(true, model.StackSettings.StackVariables["enforce_unique_urls"], "enforce_unique_urls"); + AssertLogger.AreEqual("figure", model.StackSettings.StackVariables["sys_rte_allowed_tags"], "sys_rte_allowed_tags"); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } } diff --git a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack004_ReleaseTest.cs b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack004_ReleaseTest.cs index 66f9014..cf5cb53 100644 --- a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack004_ReleaseTest.cs +++ b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack004_ReleaseTest.cs @@ -14,15 +14,29 @@ namespace Contentstack.Management.Core.Tests.IntegrationTest [TestClass] public class Contentstack004_ReleaseTest { + private static ContentstackClient _client; private Stack _stack; private string _testReleaseName = "DotNet SDK Integration Test Release"; private string _testReleaseDescription = "Release created for .NET SDK integration testing"; + [ClassInitialize] + public static void ClassInitialize(TestContext context) + { + _client = Contentstack.CreateAuthenticatedClient(); + } + + [ClassCleanup] + public static void ClassCleanup() + { + try { _client?.Logout(); } catch { } + _client = null; + } + [TestInitialize] public async Task Initialize() { - StackResponse response = StackResponse.getStack(Contentstack.Client.serializer); - _stack = Contentstack.Client.Stack(response.Stack.APIKey); + StackResponse response = StackResponse.getStack(_client.serializer); + _stack = _client.Stack(response.Stack.APIKey); } diff --git a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack011_GlobalFieldTest.cs b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack011_GlobalFieldTest.cs index aa7d4b7..d2d9f84 100644 --- a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack011_GlobalFieldTest.cs +++ b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack011_GlobalFieldTest.cs @@ -1,8 +1,9 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using AutoFixture; using Contentstack.Management.Core.Models; +using Contentstack.Management.Core.Tests.Helpers; using Contentstack.Management.Core.Tests.Model; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -11,134 +12,163 @@ namespace Contentstack.Management.Core.Tests.IntegrationTest [TestClass] public class Contentstack004_GlobalFieldTest { + private static ContentstackClient _client; private Stack _stack; private ContentModelling _modelling; + + [ClassInitialize] + public static void ClassInitialize(TestContext context) + { + _client = Contentstack.CreateAuthenticatedClient(); + } + + [ClassCleanup] + public static void ClassCleanup() + { + try { _client?.Logout(); } catch { } + _client = null; + } + [TestInitialize] public void Initialize () { - StackResponse response = StackResponse.getStack(Contentstack.Client.serializer); - _stack = Contentstack.Client.Stack(response.Stack.APIKey); - _modelling = Contentstack.serialize(Contentstack.Client.serializer, "globalfield.json"); + StackResponse response = StackResponse.getStack(_client.serializer); + _stack = _client.Stack(response.Stack.APIKey); + _modelling = Contentstack.serialize(_client.serializer, "globalfield.json"); } [TestMethod] [DoNotParallelize] public void Test001_Should_Create_Global_Field() { + TestOutputLogger.LogContext("TestScenario", "CreateGlobalField"); ContentstackResponse response = _stack.GlobalField().Create(_modelling); GlobalFieldModel globalField = response.OpenTResponse(); - Assert.IsNotNull(response); - Assert.IsNotNull(globalField); - Assert.IsNotNull(globalField.Modelling); - Assert.AreEqual(_modelling.Title, globalField.Modelling.Title); - Assert.AreEqual(_modelling.Uid, globalField.Modelling.Uid); - Assert.AreEqual(_modelling.Schema.Count, globalField.Modelling.Schema.Count); + TestOutputLogger.LogContext("GlobalField", _modelling.Uid); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.IsNotNull(globalField, "globalField"); + AssertLogger.IsNotNull(globalField.Modelling, "globalField.Modelling"); + AssertLogger.AreEqual(_modelling.Title, globalField.Modelling.Title, "Title"); + AssertLogger.AreEqual(_modelling.Uid, globalField.Modelling.Uid, "Uid"); + AssertLogger.AreEqual(_modelling.Schema.Count, globalField.Modelling.Schema.Count, "SchemaCount"); } [TestMethod] [DoNotParallelize] public void Test002_Should_Fetch_Global_Field() { + TestOutputLogger.LogContext("TestScenario", "FetchGlobalField"); + TestOutputLogger.LogContext("GlobalField", _modelling.Uid); ContentstackResponse response = _stack.GlobalField(_modelling.Uid).Fetch(); GlobalFieldModel globalField = response.OpenTResponse(); - Assert.IsNotNull(response); - Assert.IsNotNull(globalField); - Assert.IsNotNull(globalField.Modelling); - Assert.AreEqual(_modelling.Title, globalField.Modelling.Title); - Assert.AreEqual(_modelling.Uid, globalField.Modelling.Uid); - Assert.AreEqual(_modelling.Schema.Count, globalField.Modelling.Schema.Count); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.IsNotNull(globalField, "globalField"); + AssertLogger.IsNotNull(globalField.Modelling, "globalField.Modelling"); + AssertLogger.AreEqual(_modelling.Title, globalField.Modelling.Title, "Title"); + AssertLogger.AreEqual(_modelling.Uid, globalField.Modelling.Uid, "Uid"); + AssertLogger.AreEqual(_modelling.Schema.Count, globalField.Modelling.Schema.Count, "SchemaCount"); } [TestMethod] [DoNotParallelize] public async System.Threading.Tasks.Task Test003_Should_Fetch_Async_Global_Field() { + TestOutputLogger.LogContext("TestScenario", "FetchAsyncGlobalField"); + TestOutputLogger.LogContext("GlobalField", _modelling.Uid); ContentstackResponse response = await _stack.GlobalField(_modelling.Uid).FetchAsync(); GlobalFieldModel globalField = response.OpenTResponse(); - Assert.IsNotNull(response); - Assert.IsNotNull(globalField); - Assert.IsNotNull(globalField.Modelling); - Assert.AreEqual(_modelling.Title, globalField.Modelling.Title); - Assert.AreEqual(_modelling.Uid, globalField.Modelling.Uid); - Assert.AreEqual(_modelling.Schema.Count, globalField.Modelling.Schema.Count); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.IsNotNull(globalField, "globalField"); + AssertLogger.IsNotNull(globalField.Modelling, "globalField.Modelling"); + AssertLogger.AreEqual(_modelling.Title, globalField.Modelling.Title, "Title"); + AssertLogger.AreEqual(_modelling.Uid, globalField.Modelling.Uid, "Uid"); + AssertLogger.AreEqual(_modelling.Schema.Count, globalField.Modelling.Schema.Count, "SchemaCount"); } [TestMethod] [DoNotParallelize] public void Test004_Should_Update_Global_Field() { + TestOutputLogger.LogContext("TestScenario", "UpdateGlobalField"); + TestOutputLogger.LogContext("GlobalField", _modelling.Uid); _modelling.Title = "Updated title"; ContentstackResponse response = _stack.GlobalField(_modelling.Uid).Update(_modelling); GlobalFieldModel globalField = response.OpenTResponse(); - Assert.IsNotNull(response); - Assert.IsNotNull(globalField); - Assert.IsNotNull(globalField.Modelling); - Assert.AreEqual(_modelling.Title, globalField.Modelling.Title); - Assert.AreEqual(_modelling.Uid, globalField.Modelling.Uid); - Assert.AreEqual(_modelling.Schema.Count, globalField.Modelling.Schema.Count); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.IsNotNull(globalField, "globalField"); + AssertLogger.IsNotNull(globalField.Modelling, "globalField.Modelling"); + AssertLogger.AreEqual(_modelling.Title, globalField.Modelling.Title, "Title"); + AssertLogger.AreEqual(_modelling.Uid, globalField.Modelling.Uid, "Uid"); + AssertLogger.AreEqual(_modelling.Schema.Count, globalField.Modelling.Schema.Count, "SchemaCount"); } [TestMethod] [DoNotParallelize] public async System.Threading.Tasks.Task Test005_Should_Update_Async_Global_Field() { + TestOutputLogger.LogContext("TestScenario", "UpdateAsyncGlobalField"); + TestOutputLogger.LogContext("GlobalField", _modelling.Uid); _modelling.Title = "First Async"; ContentstackResponse response = await _stack.GlobalField(_modelling.Uid).UpdateAsync(_modelling); GlobalFieldModel globalField = response.OpenTResponse(); - Assert.IsNotNull(response); - Assert.IsNotNull(globalField); - Assert.IsNotNull(globalField.Modelling); - Assert.AreEqual(_modelling.Title, globalField.Modelling.Title); - Assert.AreEqual(_modelling.Uid, globalField.Modelling.Uid); - Assert.AreEqual(_modelling.Schema.Count, globalField.Modelling.Schema.Count); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.IsNotNull(globalField, "globalField"); + AssertLogger.IsNotNull(globalField.Modelling, "globalField.Modelling"); + AssertLogger.AreEqual(_modelling.Title, globalField.Modelling.Title, "Title"); + AssertLogger.AreEqual(_modelling.Uid, globalField.Modelling.Uid, "Uid"); + AssertLogger.AreEqual(_modelling.Schema.Count, globalField.Modelling.Schema.Count, "SchemaCount"); } [TestMethod] [DoNotParallelize] public void Test006_Should_Query_Global_Field() { + TestOutputLogger.LogContext("TestScenario", "QueryGlobalField"); ContentstackResponse response = _stack.GlobalField().Query().Find(); GlobalFieldsModel globalField = response.OpenTResponse(); - Assert.IsNotNull(response); - Assert.IsNotNull(globalField); - Assert.IsNotNull(globalField.Modellings); - Assert.AreEqual(1, globalField.Modellings.Count); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.IsNotNull(globalField, "globalField"); + AssertLogger.IsNotNull(globalField.Modellings, "globalField.Modellings"); + AssertLogger.AreEqual(1, globalField.Modellings.Count, "ModellingsCount"); } [TestMethod] [DoNotParallelize] public void Test006a_Should_Query_Global_Field_With_ApiVersion() { + TestOutputLogger.LogContext("TestScenario", "QueryGlobalFieldWithApiVersion"); ContentstackResponse response = _stack.GlobalField(apiVersion: "3.2").Query().Find(); GlobalFieldsModel globalField = response.OpenTResponse(); - Assert.IsNotNull(response); - Assert.IsNotNull(globalField); - Assert.IsNotNull(globalField.Modellings); - Assert.AreEqual(1, globalField.Modellings.Count); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.IsNotNull(globalField, "globalField"); + AssertLogger.IsNotNull(globalField.Modellings, "globalField.Modellings"); + AssertLogger.AreEqual(1, globalField.Modellings.Count, "ModellingsCount"); } [TestMethod] [DoNotParallelize] public async System.Threading.Tasks.Task Test007_Should_Query_Async_Global_Field() { + TestOutputLogger.LogContext("TestScenario", "QueryAsyncGlobalField"); ContentstackResponse response = await _stack.GlobalField().Query().FindAsync(); GlobalFieldsModel globalField = response.OpenTResponse(); - Assert.IsNotNull(response); - Assert.IsNotNull(globalField); - Assert.IsNotNull(globalField.Modellings); - Assert.AreEqual(1, globalField.Modellings.Count); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.IsNotNull(globalField, "globalField"); + AssertLogger.IsNotNull(globalField.Modellings, "globalField.Modellings"); + AssertLogger.AreEqual(1, globalField.Modellings.Count, "ModellingsCount"); } [TestMethod] [DoNotParallelize] public async System.Threading.Tasks.Task Test007a_Should_Query_Async_Global_Field_With_ApiVersion() { + TestOutputLogger.LogContext("TestScenario", "QueryAsyncGlobalFieldWithApiVersion"); ContentstackResponse response = await _stack.GlobalField(apiVersion: "3.2").Query().FindAsync(); GlobalFieldsModel globalField = response.OpenTResponse(); - Assert.IsNotNull(response); - Assert.IsNotNull(globalField); - Assert.IsNotNull(globalField.Modellings); - Assert.AreEqual(1, globalField.Modellings.Count); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.IsNotNull(globalField, "globalField"); + AssertLogger.IsNotNull(globalField.Modellings, "globalField.Modellings"); + AssertLogger.AreEqual(1, globalField.Modellings.Count, "ModellingsCount"); } } } diff --git a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack012_ContentTypeTest.cs b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack012_ContentTypeTest.cs index d9b006f..f244d6a 100644 --- a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack012_ContentTypeTest.cs +++ b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack012_ContentTypeTest.cs @@ -1,6 +1,7 @@ -using System; +using System; using System.Collections.Generic; using Contentstack.Management.Core.Models; +using Contentstack.Management.Core.Tests.Helpers; using Contentstack.Management.Core.Tests.Model; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -9,98 +10,124 @@ namespace Contentstack.Management.Core.Tests.IntegrationTest [TestClass] public class Contentstack005_ContentTypeTest { + private static ContentstackClient _client; private Stack _stack; private ContentModelling _singlePage; private ContentModelling _multiPage; + [ClassInitialize] + public static void ClassInitialize(TestContext context) + { + _client = Contentstack.CreateAuthenticatedClient(); + } + + [ClassCleanup] + public static void ClassCleanup() + { + try { _client?.Logout(); } catch { } + _client = null; + } + [TestInitialize] public void Initialize () { - StackResponse response = StackResponse.getStack(Contentstack.Client.serializer); - _stack = Contentstack.Client.Stack(response.Stack.APIKey); - _singlePage = Contentstack.serialize(Contentstack.Client.serializer, "singlepageCT.json"); - _multiPage = Contentstack.serialize(Contentstack.Client.serializer, "multiPageCT.json"); + StackResponse response = StackResponse.getStack(_client.serializer); + _stack = _client.Stack(response.Stack.APIKey); + _singlePage = Contentstack.serialize(_client.serializer, "singlepageCT.json"); + _multiPage = Contentstack.serialize(_client.serializer, "multiPageCT.json"); } [TestMethod] [DoNotParallelize] public void Test001_Should_Create_Content_Type() { + TestOutputLogger.LogContext("TestScenario", "CreateContentType_SinglePage"); ContentstackResponse response = _stack.ContentType().Create(_singlePage); ContentTypeModel ContentType = response.OpenTResponse(); - Assert.IsNotNull(response); - Assert.IsNotNull(ContentType); - Assert.IsNotNull(ContentType.Modelling); - Assert.AreEqual(_singlePage.Title, ContentType.Modelling.Title); - Assert.AreEqual(_singlePage.Uid, ContentType.Modelling.Uid); - Assert.AreEqual(_singlePage.Schema.Count, ContentType.Modelling.Schema.Count); + TestOutputLogger.LogContext("ContentType", _singlePage.Uid); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.IsNotNull(ContentType, "ContentType"); + AssertLogger.IsNotNull(ContentType.Modelling, "ContentType.Modelling"); + AssertLogger.AreEqual(_singlePage.Title, ContentType.Modelling.Title, "Title"); + AssertLogger.AreEqual(_singlePage.Uid, ContentType.Modelling.Uid, "Uid"); + AssertLogger.AreEqual(_singlePage.Schema.Count, ContentType.Modelling.Schema.Count, "SchemaCount"); } [TestMethod] [DoNotParallelize] public void Test002_Should_Create_Content_Type() { + TestOutputLogger.LogContext("TestScenario", "CreateContentType_MultiPage"); ContentstackResponse response = _stack.ContentType().Create(_multiPage); ContentTypeModel ContentType = response.OpenTResponse(); - Assert.IsNotNull(response); - Assert.IsNotNull(ContentType); - Assert.IsNotNull(ContentType.Modelling); - Assert.AreEqual(_multiPage.Title, ContentType.Modelling.Title); - Assert.AreEqual(_multiPage.Uid, ContentType.Modelling.Uid); - Assert.AreEqual(_multiPage.Schema.Count, ContentType.Modelling.Schema.Count); + TestOutputLogger.LogContext("ContentType", _multiPage.Uid); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.IsNotNull(ContentType, "ContentType"); + AssertLogger.IsNotNull(ContentType.Modelling, "ContentType.Modelling"); + AssertLogger.AreEqual(_multiPage.Title, ContentType.Modelling.Title, "Title"); + AssertLogger.AreEqual(_multiPage.Uid, ContentType.Modelling.Uid, "Uid"); + AssertLogger.AreEqual(_multiPage.Schema.Count, ContentType.Modelling.Schema.Count, "SchemaCount"); } [TestMethod] [DoNotParallelize] public void Test003_Should_Fetch_Content_Type() { + TestOutputLogger.LogContext("TestScenario", "FetchContentType"); + TestOutputLogger.LogContext("ContentType", _multiPage.Uid); ContentstackResponse response = _stack.ContentType(_multiPage.Uid).Fetch(); ContentTypeModel ContentType = response.OpenTResponse(); - Assert.IsNotNull(response); - Assert.IsNotNull(ContentType); - Assert.IsNotNull(ContentType.Modelling); - Assert.AreEqual(_multiPage.Title, ContentType.Modelling.Title); - Assert.AreEqual(_multiPage.Uid, ContentType.Modelling.Uid); - Assert.AreEqual(_multiPage.Schema.Count, ContentType.Modelling.Schema.Count); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.IsNotNull(ContentType, "ContentType"); + AssertLogger.IsNotNull(ContentType.Modelling, "ContentType.Modelling"); + AssertLogger.AreEqual(_multiPage.Title, ContentType.Modelling.Title, "Title"); + AssertLogger.AreEqual(_multiPage.Uid, ContentType.Modelling.Uid, "Uid"); + AssertLogger.AreEqual(_multiPage.Schema.Count, ContentType.Modelling.Schema.Count, "SchemaCount"); } [TestMethod] [DoNotParallelize] public async System.Threading.Tasks.Task Test004_Should_Fetch_Async_Content_Type() { + TestOutputLogger.LogContext("TestScenario", "FetchAsyncContentType"); + TestOutputLogger.LogContext("ContentType", _singlePage.Uid); ContentstackResponse response = await _stack.ContentType(_singlePage.Uid).FetchAsync(); ContentTypeModel ContentType = response.OpenTResponse(); - Assert.IsNotNull(response); - Assert.IsNotNull(ContentType); - Assert.IsNotNull(ContentType.Modelling); - Assert.AreEqual(_singlePage.Title, ContentType.Modelling.Title); - Assert.AreEqual(_singlePage.Uid, ContentType.Modelling.Uid); - Assert.AreEqual(_singlePage.Schema.Count, ContentType.Modelling.Schema.Count); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.IsNotNull(ContentType, "ContentType"); + AssertLogger.IsNotNull(ContentType.Modelling, "ContentType.Modelling"); + AssertLogger.AreEqual(_singlePage.Title, ContentType.Modelling.Title, "Title"); + AssertLogger.AreEqual(_singlePage.Uid, ContentType.Modelling.Uid, "Uid"); + AssertLogger.AreEqual(_singlePage.Schema.Count, ContentType.Modelling.Schema.Count, "SchemaCount"); } [TestMethod] [DoNotParallelize] public void Test005_Should_Update_Content_Type() { - _multiPage.Schema = Contentstack.serializeArray>(Contentstack.Client.serializer, "contentTypeSchema.json"); ; + TestOutputLogger.LogContext("TestScenario", "UpdateContentType"); + TestOutputLogger.LogContext("ContentType", _multiPage.Uid); + _multiPage.Schema = Contentstack.serializeArray>(_client.serializer, "contentTypeSchema.json"); ; ContentstackResponse response = _stack.ContentType(_multiPage.Uid).Update(_multiPage); ContentTypeModel ContentType = response.OpenTResponse(); - Assert.IsNotNull(response); - Assert.IsNotNull(ContentType); - Assert.IsNotNull(ContentType.Modelling); - Assert.AreEqual(_multiPage.Title, ContentType.Modelling.Title); - Assert.AreEqual(_multiPage.Uid, ContentType.Modelling.Uid); - Assert.AreEqual(_multiPage.Schema.Count, ContentType.Modelling.Schema.Count); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.IsNotNull(ContentType, "ContentType"); + AssertLogger.IsNotNull(ContentType.Modelling, "ContentType.Modelling"); + AssertLogger.AreEqual(_multiPage.Title, ContentType.Modelling.Title, "Title"); + AssertLogger.AreEqual(_multiPage.Uid, ContentType.Modelling.Uid, "Uid"); + AssertLogger.AreEqual(_multiPage.Schema.Count, ContentType.Modelling.Schema.Count, "SchemaCount"); } [TestMethod] [DoNotParallelize] public async System.Threading.Tasks.Task Test006_Should_Update_Async_Content_Type() { + TestOutputLogger.LogContext("TestScenario", "UpdateAsyncContentType"); + TestOutputLogger.LogContext("ContentType", _multiPage.Uid); try { // Load the existing schema - _multiPage.Schema = Contentstack.serializeArray>(Contentstack.Client.serializer, "contentTypeSchema.json"); + _multiPage.Schema = Contentstack.serializeArray>(_client.serializer, "contentTypeSchema.json"); // Add a new text field to the schema var newTextField = new Models.Fields.TextboxField @@ -121,21 +148,21 @@ public async System.Threading.Tasks.Task Test006_Should_Update_Async_Content_Typ if (response.IsSuccessStatusCode) { ContentTypeModel ContentType = response.OpenTResponse(); - Assert.IsNotNull(response); - Assert.IsNotNull(ContentType); - Assert.IsNotNull(ContentType.Modelling); - Assert.AreEqual(_multiPage.Uid, ContentType.Modelling.Uid); - Assert.AreEqual(_multiPage.Schema.Count, ContentType.Modelling.Schema.Count); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.IsNotNull(ContentType, "ContentType"); + AssertLogger.IsNotNull(ContentType.Modelling, "ContentType.Modelling"); + AssertLogger.AreEqual(_multiPage.Uid, ContentType.Modelling.Uid, "Uid"); + AssertLogger.AreEqual(_multiPage.Schema.Count, ContentType.Modelling.Schema.Count, "SchemaCount"); Console.WriteLine($"Successfully updated content type with {ContentType.Modelling.Schema.Count} fields"); } else { - Assert.Fail($"Update failed with status {response.StatusCode}: {response.OpenResponse()}"); + AssertLogger.Fail($"Update failed with status {response.StatusCode}: {response.OpenResponse()}"); } } catch (Exception ex) { - Assert.Fail($"Exception during async update: {ex.Message}"); + AssertLogger.Fail($"Exception during async update: {ex.Message}"); } } @@ -143,24 +170,26 @@ public async System.Threading.Tasks.Task Test006_Should_Update_Async_Content_Typ [DoNotParallelize] public void Test007_Should_Query_Content_Type() { + TestOutputLogger.LogContext("TestScenario", "QueryContentType"); ContentstackResponse response = _stack.ContentType().Query().Find(); ContentTypesModel ContentType = response.OpenTResponse(); - Assert.IsNotNull(response); - Assert.IsNotNull(ContentType); - Assert.IsNotNull(ContentType.Modellings); - Assert.AreEqual(2, ContentType.Modellings.Count); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.IsNotNull(ContentType, "ContentType"); + AssertLogger.IsNotNull(ContentType.Modellings, "ContentType.Modellings"); + AssertLogger.AreEqual(2, ContentType.Modellings.Count, "ModellingsCount"); } [TestMethod] [DoNotParallelize] public async System.Threading.Tasks.Task Test008_Should_Query_Async_Content_Type() { + TestOutputLogger.LogContext("TestScenario", "QueryAsyncContentType"); ContentstackResponse response = await _stack.ContentType().Query().FindAsync(); ContentTypesModel ContentType = response.OpenTResponse(); - Assert.IsNotNull(response); - Assert.IsNotNull(ContentType); - Assert.IsNotNull(ContentType.Modellings); - Assert.AreEqual(2, ContentType.Modellings.Count); + AssertLogger.IsNotNull(response, "response"); + AssertLogger.IsNotNull(ContentType, "ContentType"); + AssertLogger.IsNotNull(ContentType.Modellings, "ContentType.Modellings"); + AssertLogger.AreEqual(2, ContentType.Modellings.Count, "ModellingsCount"); } } } diff --git a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack012_NestedGlobalFieldTest.cs b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack012_NestedGlobalFieldTest.cs index 545789a..c0e8f1d 100644 --- a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack012_NestedGlobalFieldTest.cs +++ b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack012_NestedGlobalFieldTest.cs @@ -15,13 +15,27 @@ namespace Contentstack.Management.Core.Tests.IntegrationTest [TestClass] public class Contentstack008_NestedGlobalFieldTest { + private static ContentstackClient _client; private Stack _stack; + [ClassInitialize] + public static void ClassInitialize(TestContext context) + { + _client = Contentstack.CreateAuthenticatedClient(); + } + + [ClassCleanup] + public static void ClassCleanup() + { + try { _client?.Logout(); } catch { } + _client = null; + } + [TestInitialize] public void Initialize() { - StackResponse response = StackResponse.getStack(Contentstack.Client.serializer); - _stack = Contentstack.Client.Stack(response.Stack.APIKey); + StackResponse response = StackResponse.getStack(_client.serializer); + _stack = _client.Stack(response.Stack.APIKey); } private ContentModelling CreateReferencedGlobalFieldModel() diff --git a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack013_AssetTest.cs b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack013_AssetTest.cs index 0f699fe..2028a7f 100644 --- a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack013_AssetTest.cs +++ b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack013_AssetTest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Contentstack.Management.Core.Models; using Contentstack.Management.Core.Models.CustomExtension; +using Contentstack.Management.Core.Tests.Helpers; using Contentstack.Management.Core.Tests.Model; using Contentstack.Management.Core.Exceptions; using Microsoft.AspNetCore.Http.Internal; @@ -17,28 +18,44 @@ namespace Contentstack.Management.Core.Tests.IntegrationTest [TestClass] public class Contentstack006_AssetTest { + private static ContentstackClient _client; private Stack _stack; + [ClassInitialize] + public static void ClassInitialize(TestContext context) + { + _client = Contentstack.CreateAuthenticatedClient(); + } + + [ClassCleanup] + public static void ClassCleanup() + { + try { _client?.Logout(); } catch { } + _client = null; + } + [TestInitialize] public void Initialize() { - StackResponse response = StackResponse.getStack(Contentstack.Client.serializer); - _stack = Contentstack.Client.Stack(response.Stack.APIKey); + StackResponse response = StackResponse.getStack(_client.serializer); + _stack = _client.Stack(response.Stack.APIKey); } [TestMethod] [DoNotParallelize] public void Test001_Should_Create_Asset() { + TestOutputLogger.LogContext("TestScenario", "CreateAsset"); var path = Path.Combine(System.Environment.CurrentDirectory, "../../../Mock/contentTypeSchema.json"); try { AssetModel asset = new AssetModel("contentTypeSchema.json", path, "application/json", title:"New.json", description:"new test desc", parentUID: null, tags:"one,two"); ContentstackResponse response = _stack.Asset().Create(asset); - + TestOutputLogger.LogContext("StackAPIKey", _stack?.APIKey ?? "null"); + if (response.IsSuccessStatusCode) { - Assert.AreEqual(System.Net.HttpStatusCode.Created, response.StatusCode); + AssertLogger.AreEqual(System.Net.HttpStatusCode.Created, response.StatusCode, "CreateAsset_StatusCode"); } else { @@ -47,7 +64,7 @@ public void Test001_Should_Create_Asset() } catch (Exception e) { - Assert.Fail("Asset Creation Failed ", e.Message); + AssertLogger.Fail("Asset Creation Failed ", e.Message); } } @@ -56,20 +73,22 @@ public void Test001_Should_Create_Asset() [DoNotParallelize] public void Test002_Should_Create_Dashboard() { + TestOutputLogger.LogContext("TestScenario", "CreateDashboard"); var path = Path.Combine(System.Environment.CurrentDirectory, "../../../Mock/customUpload.html"); try { DashboardWidgetModel dashboard = new DashboardWidgetModel(path, "text/html", "Dashboard", isEnable: true, defaultWidth: "half", tags: "one,two"); ContentstackResponse response = _stack.Extension().Upload(dashboard); - + TestOutputLogger.LogContext("StackAPIKey", _stack?.APIKey ?? "null"); + if (response.IsSuccessStatusCode) { - Assert.AreEqual(System.Net.HttpStatusCode.Created, response.StatusCode); + AssertLogger.AreEqual(System.Net.HttpStatusCode.Created, response.StatusCode, "CreateDashboard_StatusCode"); } } catch (Exception e) { - Assert.Fail("Dashboard Creation Failed ", e.Message); + AssertLogger.Fail("Dashboard Creation Failed ", e.Message); } } @@ -77,6 +96,7 @@ public void Test002_Should_Create_Dashboard() [DoNotParallelize] public void Test003_Should_Create_Custom_Widget() { + TestOutputLogger.LogContext("TestScenario", "CreateCustomWidget"); var path = Path.Combine(System.Environment.CurrentDirectory, "../../../Mock/customUpload.html"); try { @@ -88,15 +108,16 @@ public void Test003_Should_Create_Custom_Widget() } }, tags: "one,two"); ContentstackResponse response = _stack.Extension().Upload(customWidget); - + TestOutputLogger.LogContext("StackAPIKey", _stack?.APIKey ?? "null"); + if (response.IsSuccessStatusCode) { - Assert.AreEqual(System.Net.HttpStatusCode.Created, response.StatusCode); + AssertLogger.AreEqual(System.Net.HttpStatusCode.Created, response.StatusCode, "CreateCustomWidget_StatusCode"); } } catch (Exception e) { - Assert.Fail("Custom Widget Creation Failed ", e.Message); + AssertLogger.Fail("Custom Widget Creation Failed ", e.Message); } } @@ -104,20 +125,22 @@ public void Test003_Should_Create_Custom_Widget() [DoNotParallelize] public void Test004_Should_Create_Custom_field() { + TestOutputLogger.LogContext("TestScenario", "CreateCustomField"); var path = Path.Combine(System.Environment.CurrentDirectory, "../../../Mock/customUpload.html"); try { CustomFieldModel fieldModel = new CustomFieldModel(path, "text/html", "Custom field Upload", "text", isMultiple: false, tags: "one,two"); ContentstackResponse response = _stack.Extension().Upload(fieldModel); - + TestOutputLogger.LogContext("StackAPIKey", _stack?.APIKey ?? "null"); + if (response.IsSuccessStatusCode) { - Assert.AreEqual(System.Net.HttpStatusCode.Created, response.StatusCode); + AssertLogger.AreEqual(System.Net.HttpStatusCode.Created, response.StatusCode, "CreateCustomField_StatusCode"); } } catch (Exception e) { - Assert.Fail("Custom Field Creation Failed ", e.Message); + AssertLogger.Fail("Custom Field Creation Failed ", e.Message); } } @@ -127,29 +150,32 @@ public void Test004_Should_Create_Custom_field() [DoNotParallelize] public void Test005_Should_Create_Asset_Async() { + TestOutputLogger.LogContext("TestScenario", "CreateAssetAsync"); var path = Path.Combine(System.Environment.CurrentDirectory, "../../../Mock/contentTypeSchema.json"); try { AssetModel asset = new AssetModel("async_asset.json", path, "application/json", title:"Async Asset", description:"async test asset", parentUID: null, tags:"async,test"); ContentstackResponse response = _stack.Asset().CreateAsync(asset).Result; - + TestOutputLogger.LogContext("StackAPIKey", _stack?.APIKey ?? "null"); + if (response.IsSuccessStatusCode) { - Assert.AreEqual(System.Net.HttpStatusCode.Created, response.StatusCode); + AssertLogger.AreEqual(System.Net.HttpStatusCode.Created, response.StatusCode, "CreateAssetAsync_StatusCode"); var responseObject = response.OpenJObjectResponse(); if (responseObject["asset"] != null) { _testAssetUid = responseObject["asset"]["uid"]?.ToString(); + TestOutputLogger.LogContext("AssetUID", _testAssetUid ?? "null"); } } else { - Assert.Fail("Asset Creation Async Failed"); + AssertLogger.Fail("Asset Creation Async Failed"); } } catch (Exception ex) { - Assert.Fail("Asset Creation Async Failed ",ex.Message); + AssertLogger.Fail("Asset Creation Async Failed ",ex.Message); } } @@ -157,6 +183,7 @@ public void Test005_Should_Create_Asset_Async() [DoNotParallelize] public void Test006_Should_Fetch_Asset() { + TestOutputLogger.LogContext("TestScenario", "FetchAsset"); try { if (string.IsNullOrEmpty(_testAssetUid)) @@ -166,23 +193,24 @@ public void Test006_Should_Fetch_Asset() if (!string.IsNullOrEmpty(_testAssetUid)) { + TestOutputLogger.LogContext("AssetUID", _testAssetUid); ContentstackResponse response = _stack.Asset(_testAssetUid).Fetch(); - + if (response.IsSuccessStatusCode) { - Assert.AreEqual(System.Net.HttpStatusCode.OK, response.StatusCode); + AssertLogger.AreEqual(System.Net.HttpStatusCode.OK, response.StatusCode, "FetchAsset_StatusCode"); var responseObject = response.OpenJObjectResponse(); - Assert.IsNotNull(responseObject["asset"], "Response should contain asset object"); + AssertLogger.IsNotNull(responseObject["asset"], "FetchAsset_ResponseContainsAsset"); } else { - Assert.Fail("The Asset is Not Getting Created"); + AssertLogger.Fail("The Asset is Not Getting Created"); } } } catch (Exception e) { - Assert.Fail("Asset Fetch Failed ",e.Message); + AssertLogger.Fail("Asset Fetch Failed ",e.Message); } } @@ -190,6 +218,7 @@ public void Test006_Should_Fetch_Asset() [DoNotParallelize] public void Test007_Should_Fetch_Asset_Async() { + TestOutputLogger.LogContext("TestScenario", "FetchAssetAsync"); try { if (string.IsNullOrEmpty(_testAssetUid)) @@ -199,23 +228,24 @@ public void Test007_Should_Fetch_Asset_Async() if (!string.IsNullOrEmpty(_testAssetUid)) { + TestOutputLogger.LogContext("AssetUID", _testAssetUid); ContentstackResponse response = _stack.Asset(_testAssetUid).FetchAsync().Result; - + if (response.IsSuccessStatusCode) { - Assert.AreEqual(System.Net.HttpStatusCode.OK, response.StatusCode); + AssertLogger.AreEqual(System.Net.HttpStatusCode.OK, response.StatusCode, "FetchAssetAsync_StatusCode"); var responseObject = response.OpenJObjectResponse(); - Assert.IsNotNull(responseObject["asset"], "Response should contain asset object"); + AssertLogger.IsNotNull(responseObject["asset"], "FetchAssetAsync_ResponseContainsAsset"); } else { - Assert.Fail("Asset Fetch Async Failed"); + AssertLogger.Fail("Asset Fetch Async Failed"); } } } catch (Exception e) { - Assert.Fail("Asset Fetch Async Failed ",e.Message); + AssertLogger.Fail("Asset Fetch Async Failed ",e.Message); } } @@ -223,6 +253,7 @@ public void Test007_Should_Fetch_Asset_Async() [DoNotParallelize] public void Test008_Should_Update_Asset() { + TestOutputLogger.LogContext("TestScenario", "UpdateAsset"); try { if (string.IsNullOrEmpty(_testAssetUid)) @@ -232,26 +263,27 @@ public void Test008_Should_Update_Asset() if (!string.IsNullOrEmpty(_testAssetUid)) { + TestOutputLogger.LogContext("AssetUID", _testAssetUid); var path = Path.Combine(System.Environment.CurrentDirectory, "../../../Mock/contentTypeSchema.json"); AssetModel updatedAsset = new AssetModel("updated_asset.json", path, "application/json", title:"Updated Asset", description:"updated test asset", parentUID: null, tags:"updated,test"); - + ContentstackResponse response = _stack.Asset(_testAssetUid).Update(updatedAsset); - + if (response.IsSuccessStatusCode) { - Assert.AreEqual(System.Net.HttpStatusCode.OK, response.StatusCode); + AssertLogger.AreEqual(System.Net.HttpStatusCode.OK, response.StatusCode, "UpdateAsset_StatusCode"); var responseObject = response.OpenJObjectResponse(); - Assert.IsNotNull(responseObject["asset"], "Response should contain asset object"); + AssertLogger.IsNotNull(responseObject["asset"], "UpdateAsset_ResponseContainsAsset"); } else { - Assert.Fail("Asset update Failed"); + AssertLogger.Fail("Asset update Failed"); } } } catch (Exception e) { - Assert.Fail("Asset Update Failed ",e.Message); + AssertLogger.Fail("Asset Update Failed ",e.Message); } } @@ -259,6 +291,7 @@ public void Test008_Should_Update_Asset() [DoNotParallelize] public void Test009_Should_Update_Asset_Async() { + TestOutputLogger.LogContext("TestScenario", "UpdateAssetAsync"); try { if (string.IsNullOrEmpty(_testAssetUid)) @@ -268,26 +301,27 @@ public void Test009_Should_Update_Asset_Async() if (!string.IsNullOrEmpty(_testAssetUid)) { + TestOutputLogger.LogContext("AssetUID", _testAssetUid); var path = Path.Combine(System.Environment.CurrentDirectory, "../../../Mock/contentTypeSchema.json"); AssetModel updatedAsset = new AssetModel("async_updated_asset.json", path, "application/json", title:"Async Updated Asset", description:"async updated test asset", parentUID: null, tags:"async,updated,test"); - + ContentstackResponse response = _stack.Asset(_testAssetUid).UpdateAsync(updatedAsset).Result; - + if (response.IsSuccessStatusCode) { - Assert.AreEqual(System.Net.HttpStatusCode.OK, response.StatusCode); + AssertLogger.AreEqual(System.Net.HttpStatusCode.OK, response.StatusCode, "UpdateAssetAsync_StatusCode"); var responseObject = response.OpenJObjectResponse(); - Assert.IsNotNull(responseObject["asset"], "Response should contain asset object"); + AssertLogger.IsNotNull(responseObject["asset"], "UpdateAssetAsync_ResponseContainsAsset"); } else { - Assert.Fail("Asset Update Async Failed"); + AssertLogger.Fail("Asset Update Async Failed"); } } } catch (Exception e) { - Assert.Fail("Asset Update Async Failed ",e.Message); + AssertLogger.Fail("Asset Update Async Failed ",e.Message); } } @@ -295,24 +329,26 @@ public void Test009_Should_Update_Asset_Async() [DoNotParallelize] public void Test010_Should_Query_Assets() { + TestOutputLogger.LogContext("TestScenario", "QueryAssets"); try { + TestOutputLogger.LogContext("StackAPIKey", _stack?.APIKey ?? "null"); ContentstackResponse response = _stack.Asset().Query().Find(); - + if (response.IsSuccessStatusCode) { - Assert.AreEqual(System.Net.HttpStatusCode.OK, response.StatusCode); + AssertLogger.AreEqual(System.Net.HttpStatusCode.OK, response.StatusCode, "QueryAssets_StatusCode"); var responseObject = response.OpenJObjectResponse(); - Assert.IsNotNull(responseObject["assets"], "Response should contain assets array"); + AssertLogger.IsNotNull(responseObject["assets"], "QueryAssets_ResponseContainsAssets"); } else { - Assert.Fail("Querying the Asset Failed"); + AssertLogger.Fail("Querying the Asset Failed"); } } catch (ContentstackErrorException ex) { - Assert.Fail("Querying the Asset Failed ",ex.Message); + AssertLogger.Fail("Querying the Asset Failed ",ex.Message); } } @@ -320,28 +356,30 @@ public void Test010_Should_Query_Assets() [DoNotParallelize] public void Test011_Should_Query_Assets_With_Parameters() { + TestOutputLogger.LogContext("TestScenario", "QueryAssetsWithParameters"); try { + TestOutputLogger.LogContext("StackAPIKey", _stack?.APIKey ?? "null"); var query = _stack.Asset().Query(); query.Limit(5); query.Skip(0); - + ContentstackResponse response = query.Find(); - + if (response.IsSuccessStatusCode) { - Assert.AreEqual(System.Net.HttpStatusCode.OK, response.StatusCode); + AssertLogger.AreEqual(System.Net.HttpStatusCode.OK, response.StatusCode, "QueryAssetsWithParams_StatusCode"); var responseObject = response.OpenJObjectResponse(); - Assert.IsNotNull(responseObject["assets"], "Response should contain assets array"); + AssertLogger.IsNotNull(responseObject["assets"], "QueryAssetsWithParams_ResponseContainsAssets"); } else { - Assert.Fail("Querying the Asset Failed"); + AssertLogger.Fail("Querying the Asset Failed"); } } catch (Exception e) { - Assert.Fail("Querying the Asset Failed ",e.Message); + AssertLogger.Fail("Querying the Asset Failed ",e.Message); } } @@ -349,6 +387,7 @@ public void Test011_Should_Query_Assets_With_Parameters() [DoNotParallelize] public void Test012_Should_Delete_Asset() { + TestOutputLogger.LogContext("TestScenario", "DeleteAsset"); try { if (string.IsNullOrEmpty(_testAssetUid)) @@ -358,22 +397,23 @@ public void Test012_Should_Delete_Asset() if (!string.IsNullOrEmpty(_testAssetUid)) { + TestOutputLogger.LogContext("AssetUID", _testAssetUid); ContentstackResponse response = _stack.Asset(_testAssetUid).Delete(); - + if (response.IsSuccessStatusCode) { - Assert.AreEqual(System.Net.HttpStatusCode.OK, response.StatusCode); + AssertLogger.AreEqual(System.Net.HttpStatusCode.OK, response.StatusCode, "DeleteAsset_StatusCode"); _testAssetUid = null; // Clear the UID since asset is deleted } else { - Assert.Fail("Deleting the Asset Failed"); + AssertLogger.Fail("Deleting the Asset Failed"); } } } catch (Exception e) { - Assert.Fail("Deleting the Asset Failed ",e.Message); + AssertLogger.Fail("Deleting the Asset Failed ",e.Message); } } @@ -381,39 +421,42 @@ public void Test012_Should_Delete_Asset() [DoNotParallelize] public void Test013_Should_Delete_Asset_Async() { + TestOutputLogger.LogContext("TestScenario", "DeleteAssetAsync"); try { + TestOutputLogger.LogContext("StackAPIKey", _stack?.APIKey ?? "null"); var path = Path.Combine(System.Environment.CurrentDirectory, "../../../Mock/contentTypeSchema.json"); AssetModel asset = new AssetModel("delete_asset.json", path, "application/json", title:"Delete Asset", description:"asset for deletion", parentUID: null, tags:"delete,test"); ContentstackResponse createResponse = _stack.Asset().CreateAsync(asset).Result; - + if (createResponse.IsSuccessStatusCode) { var responseObject = createResponse.OpenJObjectResponse(); string assetUid = responseObject["asset"]["uid"]?.ToString(); - + TestOutputLogger.LogContext("AssetUID", assetUid ?? "null"); + if (!string.IsNullOrEmpty(assetUid)) { ContentstackResponse deleteResponse = _stack.Asset(assetUid).DeleteAsync().Result; - + if (deleteResponse.IsSuccessStatusCode) { - Assert.AreEqual(System.Net.HttpStatusCode.OK, deleteResponse.StatusCode); + AssertLogger.AreEqual(System.Net.HttpStatusCode.OK, deleteResponse.StatusCode, "DeleteAssetAsync_StatusCode"); } else { - Assert.Fail("Deleting Asset Async Failed"); + AssertLogger.Fail("Deleting Asset Async Failed"); } } } else { - Assert.Fail("Deleting Asset Async Failed"); + AssertLogger.Fail("Deleting Asset Async Failed"); } } catch (Exception e) { - Assert.Fail("Deleting Asset Async Failed ",e.Message); + AssertLogger.Fail("Deleting Asset Async Failed ",e.Message); } } @@ -424,27 +467,30 @@ public void Test013_Should_Delete_Asset_Async() [DoNotParallelize] public void Test014_Should_Create_Folder() { + TestOutputLogger.LogContext("TestScenario", "CreateFolder"); try { + TestOutputLogger.LogContext("StackAPIKey", _stack?.APIKey ?? "null"); ContentstackResponse response = _stack.Asset().Folder().Create("Test Folder", null); - + if (response.IsSuccessStatusCode) { - Assert.AreEqual(System.Net.HttpStatusCode.Created, response.StatusCode); + AssertLogger.AreEqual(System.Net.HttpStatusCode.Created, response.StatusCode, "CreateFolder_StatusCode"); var responseObject = response.OpenJObjectResponse(); if (responseObject["asset"] != null) { _testFolderUid = responseObject["asset"]["uid"]?.ToString(); + TestOutputLogger.LogContext("FolderUID", _testFolderUid ?? "null"); } } else { - Assert.Fail("Folder Creation Failed"); + AssertLogger.Fail("Folder Creation Failed"); } } catch (Exception e) { - Assert.Fail("Folder Creation Failed ",e.Message); + AssertLogger.Fail("Folder Creation Failed ",e.Message); } } @@ -452,6 +498,7 @@ public void Test014_Should_Create_Folder() [DoNotParallelize] public void Test015_Should_Create_Subfolder() { + TestOutputLogger.LogContext("TestScenario", "CreateSubfolder"); try { if (string.IsNullOrEmpty(_testFolderUid)) @@ -461,23 +508,24 @@ public void Test015_Should_Create_Subfolder() if (!string.IsNullOrEmpty(_testFolderUid)) { + TestOutputLogger.LogContext("FolderUID", _testFolderUid); ContentstackResponse response = _stack.Asset().Folder().Create("Test Subfolder", _testFolderUid); - + if (response.IsSuccessStatusCode) { - Assert.AreEqual(System.Net.HttpStatusCode.Created, response.StatusCode); + AssertLogger.AreEqual(System.Net.HttpStatusCode.Created, response.StatusCode, "CreateSubfolder_StatusCode"); var responseObject = response.OpenJObjectResponse(); - Assert.IsNotNull(responseObject["asset"], "Response should contain folder object"); + AssertLogger.IsNotNull(responseObject["asset"], "CreateSubfolder_ResponseContainsFolder"); } else { - Assert.Fail("SubFolder Creation Failed"); + AssertLogger.Fail("SubFolder Creation Failed"); } } } catch (Exception e) { - Assert.Fail("SubFolder Fetch Failed ",e.Message); + AssertLogger.Fail("SubFolder Fetch Failed ",e.Message); } } @@ -485,6 +533,7 @@ public void Test015_Should_Create_Subfolder() [DoNotParallelize] public void Test016_Should_Fetch_Folder() { + TestOutputLogger.LogContext("TestScenario", "FetchFolder"); try { if (string.IsNullOrEmpty(_testFolderUid)) @@ -494,23 +543,24 @@ public void Test016_Should_Fetch_Folder() if (!string.IsNullOrEmpty(_testFolderUid)) { + TestOutputLogger.LogContext("FolderUID", _testFolderUid); ContentstackResponse response = _stack.Asset().Folder(_testFolderUid).Fetch(); - + if (response.IsSuccessStatusCode) { - Assert.AreEqual(System.Net.HttpStatusCode.OK, response.StatusCode); + AssertLogger.AreEqual(System.Net.HttpStatusCode.OK, response.StatusCode, "FetchFolder_StatusCode"); var responseObject = response.OpenJObjectResponse(); - Assert.IsNotNull(responseObject["asset"], "Response should contain folder object"); + AssertLogger.IsNotNull(responseObject["asset"], "FetchFolder_ResponseContainsFolder"); } else { - Assert.Fail("Fetch Failed for Folder"); + AssertLogger.Fail("Fetch Failed for Folder"); } } } catch (Exception e) { - Assert.Fail("Fetch Async Failed for Folder ",e.Message); + AssertLogger.Fail("Fetch Async Failed for Folder ",e.Message); } } @@ -518,6 +568,7 @@ public void Test016_Should_Fetch_Folder() [DoNotParallelize] public void Test017_Should_Fetch_Folder_Async() { + TestOutputLogger.LogContext("TestScenario", "FetchFolderAsync"); try { if (string.IsNullOrEmpty(_testFolderUid)) @@ -527,23 +578,24 @@ public void Test017_Should_Fetch_Folder_Async() if (!string.IsNullOrEmpty(_testFolderUid)) { + TestOutputLogger.LogContext("FolderUID", _testFolderUid); ContentstackResponse response = _stack.Asset().Folder(_testFolderUid).FetchAsync().Result; - + if (response.IsSuccessStatusCode) { - Assert.AreEqual(System.Net.HttpStatusCode.OK, response.StatusCode); + AssertLogger.AreEqual(System.Net.HttpStatusCode.OK, response.StatusCode, "FetchFolderAsync_StatusCode"); var responseObject = response.OpenJObjectResponse(); - Assert.IsNotNull(responseObject["asset"], "Response should contain folder object"); + AssertLogger.IsNotNull(responseObject["asset"], "FetchFolderAsync_ResponseContainsFolder"); } else { - Assert.Fail("Fetch Async Failed"); + AssertLogger.Fail("Fetch Async Failed"); } } } catch (Exception e) { - Assert.Fail("Fetch Async Failed for Folder ",e.Message); + AssertLogger.Fail("Fetch Async Failed for Folder ",e.Message); } } @@ -551,6 +603,7 @@ public void Test017_Should_Fetch_Folder_Async() [DoNotParallelize] public void Test018_Should_Update_Folder() { + TestOutputLogger.LogContext("TestScenario", "UpdateFolder"); try { if (string.IsNullOrEmpty(_testFolderUid)) @@ -560,23 +613,24 @@ public void Test018_Should_Update_Folder() if (!string.IsNullOrEmpty(_testFolderUid)) { + TestOutputLogger.LogContext("FolderUID", _testFolderUid); ContentstackResponse response = _stack.Asset().Folder(_testFolderUid).Update("Updated Test Folder", null); - + if (response.IsSuccessStatusCode) { - Assert.AreEqual(System.Net.HttpStatusCode.Created, response.StatusCode); + AssertLogger.AreEqual(System.Net.HttpStatusCode.Created, response.StatusCode, "UpdateFolder_StatusCode"); var responseObject = response.OpenJObjectResponse(); - Assert.IsNotNull(responseObject["asset"], "Response should contain folder object"); + AssertLogger.IsNotNull(responseObject["asset"], "UpdateFolder_ResponseContainsFolder"); } else { - Assert.Fail("Folder update Failed"); + AssertLogger.Fail("Folder update Failed"); } } } catch (Exception e) { - Assert.Fail("Folder Update Async Failed ",e.Message); + AssertLogger.Fail("Folder Update Async Failed ",e.Message); } } @@ -584,6 +638,7 @@ public void Test018_Should_Update_Folder() [DoNotParallelize] public void Test019_Should_Update_Folder_Async() { + TestOutputLogger.LogContext("TestScenario", "UpdateFolderAsync"); try { // First create a folder if we don't have one @@ -594,23 +649,24 @@ public void Test019_Should_Update_Folder_Async() if (!string.IsNullOrEmpty(_testFolderUid)) { + TestOutputLogger.LogContext("FolderUID", _testFolderUid); ContentstackResponse response = _stack.Asset().Folder(_testFolderUid).UpdateAsync("Async Updated Test Folder", null).Result; - + if (response.IsSuccessStatusCode) { - Assert.AreEqual(System.Net.HttpStatusCode.Created, response.StatusCode); + AssertLogger.AreEqual(System.Net.HttpStatusCode.Created, response.StatusCode, "UpdateFolderAsync_StatusCode"); var responseObject = response.OpenJObjectResponse(); - Assert.IsNotNull(responseObject["asset"], "Response should contain folder object"); + AssertLogger.IsNotNull(responseObject["asset"], "UpdateFolderAsync_ResponseContainsFolder"); } else { - Assert.Fail("Folder Update Async Failed"); + AssertLogger.Fail("Folder Update Async Failed"); } } } catch (Exception e) { - Assert.Fail("Folder Delete Failed ",e.Message); + AssertLogger.Fail("Folder Delete Failed ",e.Message); } } @@ -618,6 +674,7 @@ public void Test019_Should_Update_Folder_Async() [DoNotParallelize] public void Test022_Should_Delete_Folder() { + TestOutputLogger.LogContext("TestScenario", "DeleteFolder"); try { // First create a folder if we don't have one @@ -628,22 +685,23 @@ public void Test022_Should_Delete_Folder() if (!string.IsNullOrEmpty(_testFolderUid)) { + TestOutputLogger.LogContext("FolderUID", _testFolderUid); ContentstackResponse response = _stack.Asset().Folder(_testFolderUid).Delete(); - + if (response.IsSuccessStatusCode) { - Assert.AreEqual(System.Net.HttpStatusCode.OK, response.StatusCode); + AssertLogger.AreEqual(System.Net.HttpStatusCode.OK, response.StatusCode, "DeleteFolder_StatusCode"); _testFolderUid = null; // Clear the UID since folder is deleted } else { - Assert.Fail("Delete Folder Failed"); + AssertLogger.Fail("Delete Folder Failed"); } } } catch (Exception e) { - Assert.Fail("Delete Folder Async Failed ",e.Message); + AssertLogger.Fail("Delete Folder Async Failed ",e.Message); } } @@ -651,38 +709,41 @@ public void Test022_Should_Delete_Folder() [DoNotParallelize] public void Test023_Should_Delete_Folder_Async() { + TestOutputLogger.LogContext("TestScenario", "DeleteFolderAsync"); try { // Create a new folder for deletion + TestOutputLogger.LogContext("StackAPIKey", _stack?.APIKey ?? "null"); ContentstackResponse createResponse = _stack.Asset().Folder().Create("Delete Test Folder", null); - + if (createResponse.IsSuccessStatusCode) { var responseObject = createResponse.OpenJObjectResponse(); string folderUid = responseObject["asset"]["uid"]?.ToString(); - + TestOutputLogger.LogContext("FolderUID", folderUid ?? "null"); + if (!string.IsNullOrEmpty(folderUid)) { ContentstackResponse deleteResponse = _stack.Asset().Folder(folderUid).DeleteAsync().Result; - + if (deleteResponse.IsSuccessStatusCode) { - Assert.AreEqual(System.Net.HttpStatusCode.OK, deleteResponse.StatusCode); + AssertLogger.AreEqual(System.Net.HttpStatusCode.OK, deleteResponse.StatusCode, "DeleteFolderAsync_StatusCode"); } else { - Assert.Fail("The Delete Folder Async Failed"); + AssertLogger.Fail("The Delete Folder Async Failed"); } } } else { - Assert.Fail("The Create Folder Call Failed"); + AssertLogger.Fail("The Create Folder Call Failed"); } } catch (Exception e) { - Assert.Fail("Delete Folder Async Failed ",e.Message); + AssertLogger.Fail("Delete Folder Async Failed ",e.Message); } } @@ -691,48 +752,50 @@ public void Test023_Should_Delete_Folder_Async() [DoNotParallelize] public void Test024_Should_Handle_Invalid_Asset_Operations() { + TestOutputLogger.LogContext("TestScenario", "HandleInvalidAssetOperations"); string invalidAssetUid = "invalid_asset_uid_12345"; - + TestOutputLogger.LogContext("InvalidAssetUID", invalidAssetUid); + // Test fetching non-existent asset - expect exception try { _stack.Asset(invalidAssetUid).Fetch(); - Assert.Fail("Expected exception for invalid asset fetch, but operation succeeded"); + AssertLogger.Fail("Expected exception for invalid asset fetch, but operation succeeded"); } catch (ContentstackErrorException ex) { // Expected exception for invalid asset operations - Assert.IsTrue(ex.Message.Contains("not found") || ex.Message.Contains("invalid"), - $"Expected 'not found' or 'invalid' in exception message, got: {ex.Message}"); + AssertLogger.IsTrue(ex.Message.Contains("not found") || ex.Message.Contains("invalid"), + $"Expected 'not found' or 'invalid' in exception message, got: {ex.Message}", "InvalidAssetFetch_ExceptionMessage"); } - + // Test updating non-existent asset - expect exception try { var path = Path.Combine(System.Environment.CurrentDirectory, "../../../Mock/contentTypeSchema.json"); AssetModel updateModel = new AssetModel("invalid_asset.json", path, "application/json", title:"Invalid Asset", description:"invalid test asset", parentUID: null, tags:"invalid,test"); - + _stack.Asset(invalidAssetUid).Update(updateModel); - Assert.Fail("Expected exception for invalid asset update, but operation succeeded"); + AssertLogger.Fail("Expected exception for invalid asset update, but operation succeeded"); } catch (ContentstackErrorException ex) { // Expected exception for invalid asset operations - Assert.IsTrue(ex.Message.Contains("not found") || ex.Message.Contains("invalid"), - $"Expected 'not found' or 'invalid' in exception message, got: {ex.Message}"); + AssertLogger.IsTrue(ex.Message.Contains("not found") || ex.Message.Contains("invalid"), + $"Expected 'not found' or 'invalid' in exception message, got: {ex.Message}", "InvalidAssetUpdate_ExceptionMessage"); } - + // Test deleting non-existent asset - expect exception try { _stack.Asset(invalidAssetUid).Delete(); - Assert.Fail("Expected exception for invalid asset delete, but operation succeeded"); + AssertLogger.Fail("Expected exception for invalid asset delete, but operation succeeded"); } catch (ContentstackErrorException ex) { // Expected exception for invalid asset operations - Assert.IsTrue(ex.Message.Contains("not found") || ex.Message.Contains("invalid"), - $"Expected 'not found' or 'invalid' in exception message, got: {ex.Message}"); + AssertLogger.IsTrue(ex.Message.Contains("not found") || ex.Message.Contains("invalid"), + $"Expected 'not found' or 'invalid' in exception message, got: {ex.Message}", "InvalidAssetDelete_ExceptionMessage"); } } @@ -740,8 +803,10 @@ public void Test024_Should_Handle_Invalid_Asset_Operations() [DoNotParallelize] public void Test026_Should_Handle_Invalid_Folder_Operations() { + TestOutputLogger.LogContext("TestScenario", "HandleInvalidFolderOperations"); string invalidFolderUid = "invalid_folder_uid_12345"; - + TestOutputLogger.LogContext("InvalidFolderUID", invalidFolderUid); + // Test fetching non-existent folder - expect ContentstackErrorException bool fetchExceptionThrown = false; try @@ -755,8 +820,8 @@ public void Test026_Should_Handle_Invalid_Folder_Operations() Console.WriteLine($"Expected ContentstackErrorException for invalid folder fetch: {ex.Message}"); fetchExceptionThrown = true; } - Assert.IsTrue(fetchExceptionThrown, "Expected ContentstackErrorException for invalid folder fetch"); - + AssertLogger.IsTrue(fetchExceptionThrown, "Expected ContentstackErrorException for invalid folder fetch", "InvalidFolderFetch_ExceptionThrown"); + // Test updating non-existent folder - API may succeed or throw exception try { @@ -771,7 +836,7 @@ public void Test026_Should_Handle_Invalid_Folder_Operations() Console.WriteLine($"Expected ContentstackErrorException for invalid folder update: {ex.Message}"); } // Don't assert on update behavior as API may handle this differently - + // Test deleting non-existent folder - API may succeed or throw exception try { @@ -792,19 +857,21 @@ public void Test026_Should_Handle_Invalid_Folder_Operations() [DoNotParallelize] public void Test027_Should_Handle_Asset_Creation_With_Invalid_File() { + TestOutputLogger.LogContext("TestScenario", "HandleAssetCreationWithInvalidFile"); string invalidPath = Path.Combine(System.Environment.CurrentDirectory, "non_existent_file.json"); - + TestOutputLogger.LogContext("InvalidFilePath", invalidPath); + // Expect FileNotFoundException during AssetModel construction due to file not found try { new AssetModel("invalid_file.json", invalidPath, "application/json", title:"Invalid File Asset", description:"asset with invalid file", parentUID: null, tags:"invalid,file"); - Assert.Fail("Expected FileNotFoundException during AssetModel construction, but it succeeded"); + AssertLogger.Fail("Expected FileNotFoundException during AssetModel construction, but it succeeded"); } catch (FileNotFoundException ex) { // Expected exception for file not found during AssetModel construction - Assert.IsTrue(ex.Message.Contains("non_existent_file.json") || ex.Message.Contains("Could not find file"), - $"Expected file not found exception, got: {ex.Message}"); + AssertLogger.IsTrue(ex.Message.Contains("non_existent_file.json") || ex.Message.Contains("Could not find file"), + $"Expected file not found exception, got: {ex.Message}", "InvalidFileAsset_ExceptionMessage"); } } @@ -812,27 +879,30 @@ public void Test027_Should_Handle_Asset_Creation_With_Invalid_File() [DoNotParallelize] public void Test029_Should_Handle_Query_With_Invalid_Parameters() { + TestOutputLogger.LogContext("TestScenario", "HandleQueryWithInvalidParameters"); + TestOutputLogger.LogContext("StackAPIKey", _stack?.APIKey ?? "null"); + // Test asset query with invalid parameters - expect exception to be raised directly var assetQuery = _stack.Asset().Query(); assetQuery.Limit(-1); // Invalid limit assetQuery.Skip(-1); // Invalid skip - + try { assetQuery.Find(); - Assert.Fail("Expected exception for invalid query parameters, but operation succeeded"); + AssertLogger.Fail("Expected exception for invalid query parameters, but operation succeeded"); } catch (ArgumentException ex) { // Expected exception for invalid parameters - Assert.IsTrue(ex.Message.Contains("limit") || ex.Message.Contains("skip") || ex.Message.Contains("invalid"), - $"Expected parameter validation error, got: {ex.Message}"); + AssertLogger.IsTrue(ex.Message.Contains("limit") || ex.Message.Contains("skip") || ex.Message.Contains("invalid"), + $"Expected parameter validation error, got: {ex.Message}", "InvalidQuery_ArgumentException"); } catch (ContentstackErrorException ex) { // Expected ContentstackErrorException for invalid parameters - Assert.IsTrue(ex.Message.Contains("parameter") || ex.Message.Contains("invalid") || ex.Message.Contains("limit") || ex.Message.Contains("skip"), - $"Expected parameter validation error, got: {ex.Message}"); + AssertLogger.IsTrue(ex.Message.Contains("parameter") || ex.Message.Contains("invalid") || ex.Message.Contains("limit") || ex.Message.Contains("skip"), + $"Expected parameter validation error, got: {ex.Message}", "InvalidQuery_ContentstackErrorException"); } } @@ -840,30 +910,32 @@ public void Test029_Should_Handle_Query_With_Invalid_Parameters() [DoNotParallelize] public void Test030_Should_Handle_Empty_Query_Results() { + TestOutputLogger.LogContext("TestScenario", "HandleEmptyQueryResults"); try { + TestOutputLogger.LogContext("StackAPIKey", _stack?.APIKey ?? "null"); // Test query with very high skip value to get empty results var assetQuery = _stack.Asset().Query(); assetQuery.Skip(999999); assetQuery.Limit(1); - + ContentstackResponse response = assetQuery.Find(); - + if (response.IsSuccessStatusCode) { - Assert.AreEqual(System.Net.HttpStatusCode.OK, response.StatusCode); + AssertLogger.AreEqual(System.Net.HttpStatusCode.OK, response.StatusCode, "EmptyQuery_StatusCode"); var responseObject = response.OpenJObjectResponse(); - Assert.IsNotNull(responseObject["assets"], "Response should contain assets array"); + AssertLogger.IsNotNull(responseObject["assets"], "EmptyQuery_ResponseContainsAssets"); // Empty results are valid, so we don't assert on count } else { - Assert.Fail("Asset Querying with Empty Query Failed"); + AssertLogger.Fail("Asset Querying with Empty Query Failed"); } } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.Fail(e.Message); } } diff --git a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack014_EntryTest.cs b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack014_EntryTest.cs index 6f21559..93e6b5c 100644 --- a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack014_EntryTest.cs +++ b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack014_EntryTest.cs @@ -1,8 +1,9 @@ -using System; +using System; using System.Collections.Generic; using Contentstack.Management.Core.Models; using Contentstack.Management.Core.Models.Fields; using Contentstack.Management.Core.Utils; +using Contentstack.Management.Core.Tests.Helpers; using Contentstack.Management.Core.Tests.Model; using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json; @@ -13,19 +14,34 @@ namespace Contentstack.Management.Core.Tests.IntegrationTest [TestClass] public class Contentstack007_EntryTest { + private static ContentstackClient _client; private Stack _stack; + [ClassInitialize] + public static void ClassInitialize(TestContext context) + { + _client = Contentstack.CreateAuthenticatedClient(); + } + + [ClassCleanup] + public static void ClassCleanup() + { + try { _client?.Logout(); } catch { } + _client = null; + } + [TestInitialize] public void Initialize() { - StackResponse response = StackResponse.getStack(Contentstack.Client.serializer); - _stack = Contentstack.Client.Stack(response.Stack.APIKey); + StackResponse response = StackResponse.getStack(_client.serializer); + _stack = _client.Stack(response.Stack.APIKey); } [TestMethod] [DoNotParallelize] public async System.Threading.Tasks.Task Test001_Should_Create_Entry() { + TestOutputLogger.LogContext("TestScenario", "CreateSinglePageEntry"); try { // First ensure the content type exists by trying to fetch it @@ -73,6 +89,7 @@ public async System.Threading.Tasks.Task Test001_Should_Create_Entry() } } + TestOutputLogger.LogContext("ContentType", "single_page"); // Create entry for single_page content type var singlePageEntry = new SinglePageEntry { @@ -82,27 +99,28 @@ public async System.Threading.Tasks.Task Test001_Should_Create_Entry() }; ContentstackResponse response = await _stack.ContentType("single_page").Entry().CreateAsync(singlePageEntry); - + if (response.IsSuccessStatusCode) { var responseObject = response.OpenJObjectResponse(); - Assert.IsNotNull(responseObject["entry"], "Response should contain entry object"); - + AssertLogger.IsNotNull(responseObject["entry"], "responseObject_entry"); + var entryData = responseObject["entry"] as Newtonsoft.Json.Linq.JObject; - Assert.IsNotNull(entryData["uid"], "Entry should have UID"); - Assert.AreEqual(singlePageEntry.Title, entryData["title"]?.ToString(), "Entry title should match"); - Assert.AreEqual(singlePageEntry.Url, entryData["url"]?.ToString(), "Entry URL should match"); - + AssertLogger.IsNotNull(entryData["uid"], "entry_uid"); + AssertLogger.AreEqual(singlePageEntry.Title, entryData["title"]?.ToString(), "Entry title should match", "entry_title"); + AssertLogger.AreEqual(singlePageEntry.Url, entryData["url"]?.ToString(), "Entry URL should match", "entry_url"); + + TestOutputLogger.LogContext("Entry", entryData["uid"]?.ToString()); Console.WriteLine($"Successfully created single page entry: {entryData["uid"]}"); } else { - Assert.Fail("Entry Creation Failed"); + AssertLogger.Fail("Entry Creation Failed"); } } catch (Exception ex) { - Assert.Fail("Entry Creation Failed", ex.Message); + AssertLogger.Fail("Entry Creation Failed", ex.Message); Console.WriteLine($"Create single page entry test encountered exception: {ex.Message}"); } } @@ -111,6 +129,7 @@ public async System.Threading.Tasks.Task Test001_Should_Create_Entry() [DoNotParallelize] public async System.Threading.Tasks.Task Test002_Should_Create_MultiPage_Entry() { + TestOutputLogger.LogContext("TestScenario", "CreateMultiPageEntry"); try { // First ensure the content type exists by trying to fetch it @@ -157,6 +176,7 @@ public async System.Threading.Tasks.Task Test002_Should_Create_MultiPage_Entry() } } + TestOutputLogger.LogContext("ContentType", "multi_page"); // Create entry for multi_page content type var multiPageEntry = new MultiPageEntry { @@ -166,27 +186,28 @@ public async System.Threading.Tasks.Task Test002_Should_Create_MultiPage_Entry() }; ContentstackResponse response = await _stack.ContentType("multi_page").Entry().CreateAsync(multiPageEntry); - + if (response.IsSuccessStatusCode) { var responseObject = response.OpenJObjectResponse(); - Assert.IsNotNull(responseObject["entry"], "Response should contain entry object"); - + AssertLogger.IsNotNull(responseObject["entry"], "responseObject_entry"); + var entryData = responseObject["entry"] as Newtonsoft.Json.Linq.JObject; - Assert.IsNotNull(entryData["uid"], "Entry should have UID"); - Assert.AreEqual(multiPageEntry.Title, entryData["title"]?.ToString(), "Entry title should match"); - Assert.AreEqual(multiPageEntry.Url, entryData["url"]?.ToString(), "Entry URL should match"); - + AssertLogger.IsNotNull(entryData["uid"], "entry_uid"); + AssertLogger.AreEqual(multiPageEntry.Title, entryData["title"]?.ToString(), "Entry title should match", "entry_title"); + AssertLogger.AreEqual(multiPageEntry.Url, entryData["url"]?.ToString(), "Entry URL should match", "entry_url"); + + TestOutputLogger.LogContext("Entry", entryData["uid"]?.ToString()); Console.WriteLine($"Successfully created multi page entry: {entryData["uid"]}"); } else { - Assert.Fail("Entry Crreation Failed"); + AssertLogger.Fail("Entry Crreation Failed"); } } catch (Exception ex) { - Assert.Fail("Entry Creation Failed ", ex.Message); + AssertLogger.Fail("Entry Creation Failed ", ex.Message); } } @@ -194,8 +215,10 @@ public async System.Threading.Tasks.Task Test002_Should_Create_MultiPage_Entry() [DoNotParallelize] public async System.Threading.Tasks.Task Test003_Should_Fetch_Entry() { + TestOutputLogger.LogContext("TestScenario", "FetchEntry"); try { + TestOutputLogger.LogContext("ContentType", "single_page"); var singlePageEntry = new SinglePageEntry { Title = "Test Entry for Fetch", @@ -204,39 +227,40 @@ public async System.Threading.Tasks.Task Test003_Should_Fetch_Entry() }; ContentstackResponse createResponse = await _stack.ContentType("single_page").Entry().CreateAsync(singlePageEntry); - + if (createResponse.IsSuccessStatusCode) { var createObject = createResponse.OpenJObjectResponse(); var entryUid = createObject["entry"]["uid"]?.ToString(); - Assert.IsNotNull(entryUid, "Created entry should have UID"); + AssertLogger.IsNotNull(entryUid, "created_entry_uid"); + TestOutputLogger.LogContext("Entry", entryUid); ContentstackResponse fetchResponse = await _stack.ContentType("single_page").Entry(entryUid).FetchAsync(); - + if (fetchResponse.IsSuccessStatusCode) { var fetchObject = fetchResponse.OpenJObjectResponse(); - Assert.IsNotNull(fetchObject["entry"], "Response should contain entry object"); - + AssertLogger.IsNotNull(fetchObject["entry"], "fetchObject_entry"); + var entryData = fetchObject["entry"] as Newtonsoft.Json.Linq.JObject; - Assert.AreEqual(entryUid, entryData["uid"]?.ToString(), "Fetched entry UID should match"); - Assert.AreEqual(singlePageEntry.Title, entryData["title"]?.ToString(), "Fetched entry title should match"); - + AssertLogger.AreEqual(entryUid, entryData["uid"]?.ToString(), "Fetched entry UID should match", "fetched_entry_uid"); + AssertLogger.AreEqual(singlePageEntry.Title, entryData["title"]?.ToString(), "Fetched entry title should match", "fetched_entry_title"); + Console.WriteLine($"Successfully fetched entry: {entryUid}"); } else { - Assert.Fail("Entry Fetch Failed"); + AssertLogger.Fail("Entry Fetch Failed"); } } else { - Assert.Fail("Entry Creation for Fetch Failed"); + AssertLogger.Fail("Entry Creation for Fetch Failed"); } } catch (Exception ex) { - Assert.Fail("Entry Fetch Failed", ex.Message); + AssertLogger.Fail("Entry Fetch Failed", ex.Message); } } @@ -244,8 +268,10 @@ public async System.Threading.Tasks.Task Test003_Should_Fetch_Entry() [DoNotParallelize] public async System.Threading.Tasks.Task Test004_Should_Update_Entry() { + TestOutputLogger.LogContext("TestScenario", "UpdateEntry"); try { + TestOutputLogger.LogContext("ContentType", "single_page"); // First create an entry to update var singlePageEntry = new SinglePageEntry { @@ -255,12 +281,13 @@ public async System.Threading.Tasks.Task Test004_Should_Update_Entry() }; ContentstackResponse createResponse = await _stack.ContentType("single_page").Entry().CreateAsync(singlePageEntry); - + if (createResponse.IsSuccessStatusCode) { var createObject = createResponse.OpenJObjectResponse(); var entryUid = createObject["entry"]["uid"]?.ToString(); - Assert.IsNotNull(entryUid, "Created entry should have UID"); + AssertLogger.IsNotNull(entryUid, "created_entry_uid"); + TestOutputLogger.LogContext("Entry", entryUid); // Update the entry var updatedEntry = new SinglePageEntry @@ -271,32 +298,32 @@ public async System.Threading.Tasks.Task Test004_Should_Update_Entry() }; ContentstackResponse updateResponse = await _stack.ContentType("single_page").Entry(entryUid).UpdateAsync(updatedEntry); - + if (updateResponse.IsSuccessStatusCode) { var updateObject = updateResponse.OpenJObjectResponse(); - Assert.IsNotNull(updateObject["entry"], "Response should contain entry object"); - + AssertLogger.IsNotNull(updateObject["entry"], "updateObject_entry"); + var entryData = updateObject["entry"] as Newtonsoft.Json.Linq.JObject; - Assert.AreEqual(entryUid, entryData["uid"]?.ToString(), "Updated entry UID should match"); - Assert.AreEqual(updatedEntry.Title, entryData["title"]?.ToString(), "Updated entry title should match"); - Assert.AreEqual(updatedEntry.Url, entryData["url"]?.ToString(), "Updated entry URL should match"); - + AssertLogger.AreEqual(entryUid, entryData["uid"]?.ToString(), "Updated entry UID should match", "updated_entry_uid"); + AssertLogger.AreEqual(updatedEntry.Title, entryData["title"]?.ToString(), "Updated entry title should match", "updated_entry_title"); + AssertLogger.AreEqual(updatedEntry.Url, entryData["url"]?.ToString(), "Updated entry URL should match", "updated_entry_url"); + Console.WriteLine($"Successfully updated entry: {entryUid}"); } else { - Assert.Fail("Entry Update Failed"); + AssertLogger.Fail("Entry Update Failed"); } } else { - Assert.Fail("Entry Creation for Update Failed"); + AssertLogger.Fail("Entry Creation for Update Failed"); } } catch (Exception ex) { - Assert.Fail("Entry Update Failed",ex.Message); + AssertLogger.Fail("Entry Update Failed",ex.Message); } } @@ -304,28 +331,30 @@ public async System.Threading.Tasks.Task Test004_Should_Update_Entry() [DoNotParallelize] public async System.Threading.Tasks.Task Test005_Should_Query_Entries() { + TestOutputLogger.LogContext("TestScenario", "QueryEntries"); try { + TestOutputLogger.LogContext("ContentType", "single_page"); ContentstackResponse response = await _stack.ContentType("single_page").Entry().Query().FindAsync(); - + if (response.IsSuccessStatusCode) { var responseObject = response.OpenJObjectResponse(); - Assert.IsNotNull(responseObject["entries"], "Response should contain entries array"); - + AssertLogger.IsNotNull(responseObject["entries"], "responseObject_entries"); + var entries = responseObject["entries"] as Newtonsoft.Json.Linq.JArray; - Assert.IsNotNull(entries, "Entries should be an array"); - + AssertLogger.IsNotNull(entries, "entries_array"); + Console.WriteLine($"Successfully queried {entries.Count} entries for single_page content type"); } else { - Assert.Fail("Entry Query Failed"); + AssertLogger.Fail("Entry Query Failed"); } } catch (Exception ex) { - Assert.Fail("Entry Query Failed ", ex.Message); + AssertLogger.Fail("Entry Query Failed ", ex.Message); } } @@ -333,8 +362,10 @@ public async System.Threading.Tasks.Task Test005_Should_Query_Entries() [DoNotParallelize] public async System.Threading.Tasks.Task Test006_Should_Delete_Entry() { + TestOutputLogger.LogContext("TestScenario", "DeleteEntry"); try { + TestOutputLogger.LogContext("ContentType", "single_page"); var singlePageEntry = new SinglePageEntry { Title = "Entry to Delete", @@ -343,15 +374,16 @@ public async System.Threading.Tasks.Task Test006_Should_Delete_Entry() }; ContentstackResponse createResponse = await _stack.ContentType("single_page").Entry().CreateAsync(singlePageEntry); - + if (createResponse.IsSuccessStatusCode) { var createObject = createResponse.OpenJObjectResponse(); var entryUid = createObject["entry"]["uid"]?.ToString(); - Assert.IsNotNull(entryUid, "Created entry should have UID"); + AssertLogger.IsNotNull(entryUid, "created_entry_uid"); + TestOutputLogger.LogContext("Entry", entryUid); ContentstackResponse deleteResponse = await _stack.ContentType("single_page").Entry(entryUid).DeleteAsync(); - + if (deleteResponse.IsSuccessStatusCode) { Console.WriteLine($"Successfully deleted entry: {entryUid}"); @@ -363,12 +395,12 @@ public async System.Threading.Tasks.Task Test006_Should_Delete_Entry() } else { - Assert.Fail("Entry Delete Async Failed"); + AssertLogger.Fail("Entry Delete Async Failed"); } } catch (Exception ex) { - Assert.Fail("Entry Delete Async Failed ", ex.Message); + AssertLogger.Fail("Entry Delete Async Failed ", ex.Message); } } diff --git a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack015_BulkOperationTest.cs b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack015_BulkOperationTest.cs index 562239d..9c61f86 100644 --- a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack015_BulkOperationTest.cs +++ b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack015_BulkOperationTest.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Contentstack.Management.Core.Exceptions; using Contentstack.Management.Core.Models; +using Contentstack.Management.Core.Tests.Helpers; using Contentstack.Management.Core.Models.Fields; using Contentstack.Management.Core.Tests.Model; using Contentstack.Management.Core.Abstractions; @@ -43,9 +44,9 @@ public class Contentstack015_BulkOperationTest private static void FailWithError(string operation, Exception ex) { if (ex is ContentstackErrorException cex) - Assert.Fail($"{operation} failed. HTTP {(int)cex.StatusCode} ({cex.StatusCode}). ErrorCode: {cex.ErrorCode}. Message: {cex.ErrorMessage ?? cex.Message}"); + AssertLogger.Fail($"{operation} failed. HTTP {(int)cex.StatusCode} ({cex.StatusCode}). ErrorCode: {cex.ErrorCode}. Message: {cex.ErrorMessage ?? cex.Message}"); else - Assert.Fail($"{operation} failed: {ex.Message}"); + AssertLogger.Fail($"{operation} failed: {ex.Message}"); } /// @@ -54,23 +55,26 @@ private static void FailWithError(string operation, Exception ex) private static void AssertWorkflowCreated() { string reason = string.IsNullOrEmpty(_bulkTestWorkflowSetupError) ? "Check auth and stack permissions for workflow create." : _bulkTestWorkflowSetupError; - Assert.IsFalse(string.IsNullOrEmpty(_bulkTestWorkflowUid), "Workflow was not created in ClassInitialize. " + reason); - Assert.IsFalse(string.IsNullOrEmpty(_bulkTestWorkflowStage1Uid), "Workflow Stage 1 (New stage 1) was not set. " + reason); - Assert.IsFalse(string.IsNullOrEmpty(_bulkTestWorkflowStage2Uid), "Workflow Stage 2 (New stage 2) was not set. " + reason); + AssertLogger.IsFalse(string.IsNullOrEmpty(_bulkTestWorkflowUid), "Workflow was not created in ClassInitialize. " + reason, "WorkflowUid"); + AssertLogger.IsFalse(string.IsNullOrEmpty(_bulkTestWorkflowStage1Uid), "Workflow Stage 1 (New stage 1) was not set. " + reason, "WorkflowStage1Uid"); + AssertLogger.IsFalse(string.IsNullOrEmpty(_bulkTestWorkflowStage2Uid), "Workflow Stage 2 (New stage 2) was not set. " + reason, "WorkflowStage2Uid"); } + private static ContentstackClient _client; + /// /// Returns a Stack instance for the test run (used by ClassInitialize/ClassCleanup). /// private static Stack GetStack() { - StackResponse response = StackResponse.getStack(Contentstack.Client.serializer); - return Contentstack.Client.Stack(response.Stack.APIKey); + StackResponse response = StackResponse.getStack(_client.serializer); + return _client.Stack(response.Stack.APIKey); } [ClassInitialize] public static void ClassInitialize(TestContext context) { + _client = Contentstack.CreateAuthenticatedClient(); try { Stack stack = GetStack(); @@ -86,13 +90,15 @@ public static void ClassInitialize(TestContext context) public static void ClassCleanup() { // Intentionally no cleanup: workflow, publish rules, and entries are left so you can verify them in the UI. + try { _client?.Logout(); } catch { } + _client = null; } [TestInitialize] public async Task Initialize() { - StackResponse response = StackResponse.getStack(Contentstack.Client.serializer); - _stack = Contentstack.Client.Stack(response.Stack.APIKey); + StackResponse response = StackResponse.getStack(_client.serializer); + _stack = _client.Stack(response.Stack.APIKey); // Create test environment and release for bulk operations (for new stack) try @@ -137,6 +143,7 @@ public async Task Initialize() [DoNotParallelize] public void Test000a_Should_Create_Workflow_With_Two_Stages() { + TestOutputLogger.LogContext("TestScenario", "CreateWorkflowWithTwoStages"); try { const string workflowName = "workflow_test"; @@ -162,8 +169,8 @@ public void Test000a_Should_Create_Workflow_With_Two_Stages() _bulkTestWorkflowStage1Uid = existingStages[0]["uid"]?.ToString(); _bulkTestWorkflowStage2Uid = existingStages[1]["uid"]?.ToString(); _bulkTestWorkflowStageUid = _bulkTestWorkflowStage2Uid; - Assert.IsNotNull(_bulkTestWorkflowStage1Uid, "Stage 1 UID null in existing workflow."); - Assert.IsNotNull(_bulkTestWorkflowStage2Uid, "Stage 2 UID null in existing workflow."); + AssertLogger.IsNotNull(_bulkTestWorkflowStage1Uid, "Stage1Uid"); + AssertLogger.IsNotNull(_bulkTestWorkflowStage2Uid, "Stage2Uid"); return; // Already exists with stages – nothing more to do } } @@ -228,19 +235,20 @@ public void Test000a_Should_Create_Workflow_With_Two_Stages() string responseBody = null; try { responseBody = response.OpenResponse(); } catch { } - Assert.IsNotNull(response); - Assert.IsTrue(response.IsSuccessStatusCode, - $"Workflow create failed: HTTP {(int)response.StatusCode}.\n--- REQUEST BODY ---\n{sentJson}\n--- RESPONSE BODY ---\n{responseBody}"); + AssertLogger.IsNotNull(response, "workflowCreateResponse"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, + $"Workflow create failed: HTTP {(int)response.StatusCode}.\n--- REQUEST BODY ---\n{sentJson}\n--- RESPONSE BODY ---\n{responseBody}", "workflowCreateSuccess"); var responseJson = JObject.Parse(responseBody ?? "{}"); var workflowObj = responseJson["workflow"]; - Assert.IsNotNull(workflowObj, "Response missing 'workflow' key."); - Assert.IsFalse(string.IsNullOrEmpty(workflowObj["uid"]?.ToString()), "Workflow UID is empty."); + AssertLogger.IsNotNull(workflowObj, "workflowObj"); + AssertLogger.IsFalse(string.IsNullOrEmpty(workflowObj["uid"]?.ToString()), "Workflow UID is empty.", "workflowUid"); _bulkTestWorkflowUid = workflowObj["uid"].ToString(); + TestOutputLogger.LogContext("WorkflowUid", _bulkTestWorkflowUid); var stages = workflowObj["workflow_stages"] as JArray; - Assert.IsNotNull(stages, "workflow_stages missing from response."); - Assert.IsTrue(stages.Count >= 2, $"Expected at least 2 stages, got {stages.Count}."); + AssertLogger.IsNotNull(stages, "workflow_stages"); + AssertLogger.IsTrue(stages.Count >= 2, $"Expected at least 2 stages, got {stages.Count}.", "stagesCount"); _bulkTestWorkflowStage1Uid = stages[0]["uid"].ToString(); // New stage 1 _bulkTestWorkflowStage2Uid = stages[1]["uid"].ToString(); // New stage 2 _bulkTestWorkflowStageUid = _bulkTestWorkflowStage2Uid; @@ -255,14 +263,17 @@ public void Test000a_Should_Create_Workflow_With_Two_Stages() [DoNotParallelize] public void Test000b_Should_Create_Publishing_Rule_For_Workflow_Stage2() { + TestOutputLogger.LogContext("TestScenario", "CreatePublishingRuleForWorkflowStage2"); try { - Assert.IsFalse(string.IsNullOrEmpty(_bulkTestWorkflowUid), "Workflow UID not set. Run Test000a first."); - Assert.IsFalse(string.IsNullOrEmpty(_bulkTestWorkflowStage2Uid), "Workflow Stage 2 UID not set. Run Test000a first."); + AssertLogger.IsFalse(string.IsNullOrEmpty(_bulkTestWorkflowUid), "Workflow UID not set. Run Test000a first.", "WorkflowUid"); + AssertLogger.IsFalse(string.IsNullOrEmpty(_bulkTestWorkflowStage2Uid), "Workflow Stage 2 UID not set. Run Test000a first.", "WorkflowStage2Uid"); if (string.IsNullOrEmpty(_bulkTestEnvironmentUid)) EnsureBulkTestEnvironment(_stack); - Assert.IsFalse(string.IsNullOrEmpty(_bulkTestEnvironmentUid), "No environment. Run Test000c or ensure ClassInitialize ran (ensure environment failed)."); + AssertLogger.IsFalse(string.IsNullOrEmpty(_bulkTestEnvironmentUid), "No environment. Run Test000c or ensure ClassInitialize ran (ensure environment failed).", "EnvironmentUid"); + TestOutputLogger.LogContext("WorkflowUid", _bulkTestWorkflowUid ?? ""); + TestOutputLogger.LogContext("EnvironmentUid", _bulkTestEnvironmentUid ?? ""); // Find existing publish rule for this workflow + stage + environment (e.g. from a previous run) try @@ -309,14 +320,14 @@ public void Test000b_Should_Create_Publishing_Rule_For_Workflow_Stage2() string responseBody = null; try { responseBody = response.OpenResponse(); } catch { } - Assert.IsNotNull(response); - Assert.IsTrue(response.IsSuccessStatusCode, - $"Publish rule create failed: HTTP {(int)response.StatusCode}.\n--- REQUEST BODY ---\n{sentJson}\n--- RESPONSE BODY ---\n{responseBody}"); + AssertLogger.IsNotNull(response, "publishRuleResponse"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, + $"Publish rule create failed: HTTP {(int)response.StatusCode}.\n--- REQUEST BODY ---\n{sentJson}\n--- RESPONSE BODY ---\n{responseBody}", "publishRuleCreateSuccess"); var responseJson = JObject.Parse(responseBody ?? "{}"); var ruleObj = responseJson["publishing_rule"]; - Assert.IsNotNull(ruleObj, "Response missing 'publishing_rule' key."); - Assert.IsFalse(string.IsNullOrEmpty(ruleObj["uid"]?.ToString()), "Publishing rule UID is empty."); + AssertLogger.IsNotNull(ruleObj, "publishing_rule"); + AssertLogger.IsFalse(string.IsNullOrEmpty(ruleObj["uid"]?.ToString()), "Publishing rule UID is empty.", "publishRuleUid"); _bulkTestPublishRuleUid = ruleObj["uid"].ToString(); } @@ -331,6 +342,8 @@ public void Test000b_Should_Create_Publishing_Rule_For_Workflow_Stage2() [DoNotParallelize] public async Task Test001_Should_Create_Content_Type_With_Title_Field() { + TestOutputLogger.LogContext("TestScenario", "CreateContentTypeWithTitleField"); + TestOutputLogger.LogContext("ContentType", _contentTypeUid); try { try { await CreateTestEnvironment(); } catch (ContentstackErrorException) { /* optional */ } @@ -358,10 +371,10 @@ public async Task Test001_Should_Create_Content_Type_With_Title_Field() ContentstackResponse response = _stack.ContentType().Create(contentModelling); var responseJson = response.OpenJObjectResponse(); - Assert.IsNotNull(response); - Assert.IsTrue(response.IsSuccessStatusCode); - Assert.IsNotNull(responseJson["content_type"]); - Assert.AreEqual(_contentTypeUid, responseJson["content_type"]["uid"].ToString()); + AssertLogger.IsNotNull(response, "createContentTypeResponse"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, "contentTypeCreateSuccess"); + AssertLogger.IsNotNull(responseJson["content_type"], "content_type"); + AssertLogger.AreEqual(_contentTypeUid, responseJson["content_type"]["uid"].ToString(), "contentTypeUid"); } catch (Exception ex) { @@ -373,6 +386,8 @@ public async Task Test001_Should_Create_Content_Type_With_Title_Field() [DoNotParallelize] public async Task Test002_Should_Create_Five_Entries() { + TestOutputLogger.LogContext("TestScenario", "CreateFiveEntries"); + TestOutputLogger.LogContext("ContentType", _contentTypeUid); try { AssertWorkflowCreated(); @@ -416,10 +431,10 @@ public async Task Test002_Should_Create_Five_Entries() ContentstackResponse response = _stack.ContentType(_contentTypeUid).Entry().Create(entry); var responseJson = response.OpenJObjectResponse(); - Assert.IsNotNull(response); - Assert.IsTrue(response.IsSuccessStatusCode); - Assert.IsNotNull(responseJson["entry"]); - Assert.IsNotNull(responseJson["entry"]["uid"]); + AssertLogger.IsNotNull(response, "createEntryResponse"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, "entryCreateSuccess"); + AssertLogger.IsNotNull(responseJson["entry"], "entry"); + AssertLogger.IsNotNull(responseJson["entry"]["uid"], "entryUid"); int version = responseJson["entry"]["_version"] != null ? (int)responseJson["entry"]["_version"] : 1; _createdEntries.Add(new EntryInfo @@ -430,7 +445,7 @@ public async Task Test002_Should_Create_Five_Entries() }); } - Assert.AreEqual(5, _createdEntries.Count, "Should have created exactly 5 entries"); + AssertLogger.AreEqual(5, _createdEntries.Count, "Should have created exactly 5 entries", "createdEntriesCount"); await AssignEntriesToWorkflowStagesAsync(_createdEntries); } @@ -444,11 +459,13 @@ public async Task Test002_Should_Create_Five_Entries() [DoNotParallelize] public async Task Test003_Should_Perform_Bulk_Publish_Operation() { + TestOutputLogger.LogContext("TestScenario", "BulkPublishOperation"); + TestOutputLogger.LogContext("ContentType", _contentTypeUid); try { // Fetch existing entries from the content type List availableEntries = await FetchExistingEntries(); - Assert.IsTrue(availableEntries.Count > 0, "No entries available for bulk operation"); + AssertLogger.IsTrue(availableEntries.Count > 0, "No entries available for bulk operation", "availableEntriesCount"); // Get available environments or use empty list if none available List availableEnvironments = await GetAvailableEnvironments(); @@ -471,8 +488,8 @@ public async Task Test003_Should_Perform_Bulk_Publish_Operation() ContentstackResponse response = _stack.BulkOperation().Publish(publishDetails, skipWorkflowStage: true, approvals: true); var responseJson = response.OpenJObjectResponse(); - Assert.IsNotNull(response); - Assert.IsTrue(response.IsSuccessStatusCode); + AssertLogger.IsNotNull(response, "bulkPublishResponse"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, "bulkPublishSuccess"); } catch (ContentstackErrorException cex) when ((int)cex.StatusCode == 422) { @@ -489,11 +506,13 @@ public async Task Test003_Should_Perform_Bulk_Publish_Operation() [DoNotParallelize] public async Task Test004_Should_Perform_Bulk_Unpublish_Operation() { + TestOutputLogger.LogContext("TestScenario", "BulkUnpublishOperation"); + TestOutputLogger.LogContext("ContentType", _contentTypeUid); try { // Fetch existing entries from the content type List availableEntries = await FetchExistingEntries(); - Assert.IsTrue(availableEntries.Count > 0, "No entries available for bulk operation"); + AssertLogger.IsTrue(availableEntries.Count > 0, "No entries available for bulk operation", "availableEntriesCount"); // Get available environments List availableEnvironments = await GetAvailableEnvironments(); @@ -516,8 +535,8 @@ public async Task Test004_Should_Perform_Bulk_Unpublish_Operation() ContentstackResponse response = _stack.BulkOperation().Unpublish(unpublishDetails, skipWorkflowStage: true, approvals: true); var responseJson = response.OpenJObjectResponse(); - Assert.IsNotNull(response); - Assert.IsTrue(response.IsSuccessStatusCode); + AssertLogger.IsNotNull(response, "bulkUnpublishResponse"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, "bulkUnpublishSuccess"); } catch (ContentstackErrorException cex) when ((int)cex.StatusCode == 422) { @@ -534,14 +553,17 @@ public async Task Test004_Should_Perform_Bulk_Unpublish_Operation() [DoNotParallelize] public async Task Test003a_Should_Perform_Bulk_Publish_With_SkipWorkflowStage_And_Approvals() { + TestOutputLogger.LogContext("TestScenario", "BulkPublishWithSkipWorkflowStageAndApprovals"); + TestOutputLogger.LogContext("ContentType", _contentTypeUid); try { if (string.IsNullOrEmpty(_bulkTestEnvironmentUid)) await EnsureBulkTestEnvironmentAsync(_stack); - Assert.IsFalse(string.IsNullOrEmpty(_bulkTestEnvironmentUid), "No environment. Ensure Test000c or ClassInitialize ran."); + AssertLogger.IsFalse(string.IsNullOrEmpty(_bulkTestEnvironmentUid), "No environment. Ensure Test000c or ClassInitialize ran.", "EnvironmentUid"); + TestOutputLogger.LogContext("EnvironmentUid", _bulkTestEnvironmentUid ?? ""); List availableEntries = await FetchExistingEntries(); - Assert.IsTrue(availableEntries.Count > 0, "No entries available for bulk operation. Run Test002 first."); + AssertLogger.IsTrue(availableEntries.Count > 0, "No entries available for bulk operation. Run Test002 first.", "availableEntriesCount"); var publishDetails = new BulkPublishDetails { @@ -559,12 +581,12 @@ public async Task Test003a_Should_Perform_Bulk_Publish_With_SkipWorkflowStage_An ContentstackResponse response = _stack.BulkOperation().Publish(publishDetails, skipWorkflowStage: true, approvals: true); - Assert.IsNotNull(response); - Assert.IsTrue(response.IsSuccessStatusCode, $"Bulk publish failed with status {(int)response.StatusCode} ({response.StatusCode})."); - Assert.AreEqual(HttpStatusCode.OK, response.StatusCode, $"Expected 200 OK, got {(int)response.StatusCode}."); + AssertLogger.IsNotNull(response, "bulkPublishResponse"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Bulk publish failed with status {(int)response.StatusCode} ({response.StatusCode}).", "bulkPublishSuccess"); + AssertLogger.AreEqual(HttpStatusCode.OK, response.StatusCode, $"Expected 200 OK, got {(int)response.StatusCode}.", "statusCode"); var responseJson = response.OpenJObjectResponse(); - Assert.IsNotNull(responseJson); + AssertLogger.IsNotNull(responseJson, "responseJson"); } catch (Exception ex) { @@ -574,16 +596,16 @@ public async Task Test003a_Should_Perform_Bulk_Publish_With_SkipWorkflowStage_An ? JsonConvert.SerializeObject(cex.Errors, Formatting.Indented) : "(none)"; string failMessage = string.Format( - "Assert.Fail failed. Bulk publish with skipWorkflowStage and approvals failed. HTTP {0} ({1}). ErrorCode: {2}. Message: {3}. Errors: {4}", + "Bulk publish with skipWorkflowStage and approvals failed. HTTP {0} ({1}). ErrorCode: {2}. Message: {3}. Errors: {4}", (int)cex.StatusCode, cex.StatusCode, cex.ErrorCode, cex.ErrorMessage ?? cex.Message, errorsJson); if ((int)cex.StatusCode == 422 && cex.ErrorCode == 141) { Console.WriteLine(failMessage); - Assert.AreEqual(422, (int)cex.StatusCode, "Expected 422 Unprocessable Entity."); - Assert.AreEqual(141, cex.ErrorCode, "Expected ErrorCode 141 (entries do not satisfy publish rules)."); + AssertLogger.AreEqual(422, (int)cex.StatusCode, "Expected 422 Unprocessable Entity.", "statusCode"); + AssertLogger.AreEqual(141, cex.ErrorCode, "Expected ErrorCode 141 (entries do not satisfy publish rules).", "errorCode"); return; } - Assert.Fail(failMessage); + AssertLogger.Fail(failMessage); } else { @@ -596,14 +618,17 @@ public async Task Test003a_Should_Perform_Bulk_Publish_With_SkipWorkflowStage_An [DoNotParallelize] public async Task Test004a_Should_Perform_Bulk_UnPublish_With_SkipWorkflowStage_And_Approvals() { + TestOutputLogger.LogContext("TestScenario", "BulkUnpublishWithSkipWorkflowStageAndApprovals"); + TestOutputLogger.LogContext("ContentType", _contentTypeUid); try { if (string.IsNullOrEmpty(_bulkTestEnvironmentUid)) await EnsureBulkTestEnvironmentAsync(_stack); - Assert.IsFalse(string.IsNullOrEmpty(_bulkTestEnvironmentUid), "No environment. Ensure Test000c or ClassInitialize ran."); + AssertLogger.IsFalse(string.IsNullOrEmpty(_bulkTestEnvironmentUid), "No environment. Ensure Test000c or ClassInitialize ran.", "EnvironmentUid"); + TestOutputLogger.LogContext("EnvironmentUid", _bulkTestEnvironmentUid ?? ""); List availableEntries = await FetchExistingEntries(); - Assert.IsTrue(availableEntries.Count > 0, "No entries available for bulk operation. Run Test002 first."); + AssertLogger.IsTrue(availableEntries.Count > 0, "No entries available for bulk operation. Run Test002 first.", "availableEntriesCount"); var publishDetails = new BulkPublishDetails { @@ -621,12 +646,12 @@ public async Task Test004a_Should_Perform_Bulk_UnPublish_With_SkipWorkflowStage_ ContentstackResponse response = _stack.BulkOperation().Unpublish(publishDetails, skipWorkflowStage: false, approvals: true); - Assert.IsNotNull(response); - Assert.IsTrue(response.IsSuccessStatusCode, $"Bulk publish failed with status {(int)response.StatusCode} ({response.StatusCode})."); - Assert.AreEqual(HttpStatusCode.OK, response.StatusCode, $"Expected 200 OK, got {(int)response.StatusCode}."); + AssertLogger.IsNotNull(response, "bulkUnpublishResponse"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Bulk publish failed with status {(int)response.StatusCode} ({response.StatusCode}).", "bulkUnpublishSuccess"); + AssertLogger.AreEqual(HttpStatusCode.OK, response.StatusCode, $"Expected 200 OK, got {(int)response.StatusCode}.", "statusCode"); var responseJson = response.OpenJObjectResponse(); - Assert.IsNotNull(responseJson); + AssertLogger.IsNotNull(responseJson, "responseJson"); } catch (Exception ex) { @@ -636,16 +661,16 @@ public async Task Test004a_Should_Perform_Bulk_UnPublish_With_SkipWorkflowStage_ ? JsonConvert.SerializeObject(cex.Errors, Formatting.Indented) : "(none)"; string failMessage = string.Format( - "Assert.Fail failed. Bulk unpublish with skipWorkflowStage and approvals failed. HTTP {0} ({1}). ErrorCode: {2}. Message: {3}. Errors: {4}", + "Bulk unpublish with skipWorkflowStage and approvals failed. HTTP {0} ({1}). ErrorCode: {2}. Message: {3}. Errors: {4}", (int)cex.StatusCode, cex.StatusCode, cex.ErrorCode, cex.ErrorMessage ?? cex.Message, errorsJson); if ((int)cex.StatusCode == 422 && (cex.ErrorCode == 141 || cex.ErrorCode == 0)) { Console.WriteLine(failMessage); - Assert.AreEqual(422, (int)cex.StatusCode, "Expected 422 Unprocessable Entity."); - Assert.IsTrue(cex.ErrorCode == 141 || cex.ErrorCode == 0, "Expected ErrorCode 141 or 0 (entries do not satisfy publish rules)."); + AssertLogger.AreEqual(422, (int)cex.StatusCode, "Expected 422 Unprocessable Entity.", "statusCode"); + AssertLogger.IsTrue(cex.ErrorCode == 141 || cex.ErrorCode == 0, "Expected ErrorCode 141 or 0 (entries do not satisfy publish rules).", "errorCode"); return; } - Assert.Fail(failMessage); + AssertLogger.Fail(failMessage); } else { @@ -658,14 +683,16 @@ public async Task Test004a_Should_Perform_Bulk_UnPublish_With_SkipWorkflowStage_ [DoNotParallelize] public async Task Test003b_Should_Perform_Bulk_Publish_With_ApiVersion_3_2_With_SkipWorkflowStage_And_Approvals() { + TestOutputLogger.LogContext("TestScenario", "BulkPublishApiVersion32WithSkipWorkflowStageAndApprovals"); + TestOutputLogger.LogContext("ContentType", _contentTypeUid); try { if (string.IsNullOrEmpty(_bulkTestEnvironmentUid)) await EnsureBulkTestEnvironmentAsync(_stack); - Assert.IsFalse(string.IsNullOrEmpty(_bulkTestEnvironmentUid), "No environment. Ensure Test000c or ClassInitialize ran."); + AssertLogger.IsFalse(string.IsNullOrEmpty(_bulkTestEnvironmentUid), "No environment. Ensure Test000c or ClassInitialize ran.", "EnvironmentUid"); List availableEntries = await FetchExistingEntries(); - Assert.IsTrue(availableEntries.Count > 0, "No entries available for bulk operation. Run Test002 first."); + AssertLogger.IsTrue(availableEntries.Count > 0, "No entries available for bulk operation. Run Test002 first.", "availableEntriesCount"); var publishDetails = new BulkPublishDetails { @@ -683,12 +710,12 @@ public async Task Test003b_Should_Perform_Bulk_Publish_With_ApiVersion_3_2_With_ ContentstackResponse response = _stack.BulkOperation().Publish(publishDetails, skipWorkflowStage: true, approvals: true, apiVersion: "3.2"); - Assert.IsNotNull(response); - Assert.IsTrue(response.IsSuccessStatusCode, $"Bulk publish with api_version 3.2 failed with status {(int)response.StatusCode} ({response.StatusCode})."); - Assert.AreEqual(HttpStatusCode.OK, response.StatusCode, $"Expected 200 OK, got {(int)response.StatusCode}."); + AssertLogger.IsNotNull(response, "bulkPublishResponse"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Bulk publish with api_version 3.2 failed with status {(int)response.StatusCode} ({response.StatusCode}).", "bulkPublishSuccess"); + AssertLogger.AreEqual(HttpStatusCode.OK, response.StatusCode, $"Expected 200 OK, got {(int)response.StatusCode}.", "statusCode"); var responseJson = response.OpenJObjectResponse(); - Assert.IsNotNull(responseJson); + AssertLogger.IsNotNull(responseJson, "responseJson"); } catch (Exception ex) { @@ -700,14 +727,16 @@ public async Task Test003b_Should_Perform_Bulk_Publish_With_ApiVersion_3_2_With_ [DoNotParallelize] public async Task Test004b_Should_Perform_Bulk_UnPublish_With_ApiVersion_3_2_With_SkipWorkflowStage_And_Approvals() { + TestOutputLogger.LogContext("TestScenario", "BulkUnpublishApiVersion32WithSkipWorkflowStageAndApprovals"); + TestOutputLogger.LogContext("ContentType", _contentTypeUid); try { if (string.IsNullOrEmpty(_bulkTestEnvironmentUid)) await EnsureBulkTestEnvironmentAsync(_stack); - Assert.IsFalse(string.IsNullOrEmpty(_bulkTestEnvironmentUid), "No environment. Ensure Test000c or ClassInitialize ran."); + AssertLogger.IsFalse(string.IsNullOrEmpty(_bulkTestEnvironmentUid), "No environment. Ensure Test000c or ClassInitialize ran.", "EnvironmentUid"); List availableEntries = await FetchExistingEntries(); - Assert.IsTrue(availableEntries.Count > 0, "No entries available for bulk operation. Run Test002 first."); + AssertLogger.IsTrue(availableEntries.Count > 0, "No entries available for bulk operation. Run Test002 first.", "availableEntriesCount"); var publishDetails = new BulkPublishDetails { @@ -725,12 +754,12 @@ public async Task Test004b_Should_Perform_Bulk_UnPublish_With_ApiVersion_3_2_Wit ContentstackResponse response = _stack.BulkOperation().Unpublish(publishDetails, skipWorkflowStage: true, approvals: true, apiVersion: "3.2"); - Assert.IsNotNull(response); - Assert.IsTrue(response.IsSuccessStatusCode, $"Bulk unpublish with api_version 3.2 failed with status {(int)response.StatusCode} ({response.StatusCode})."); - Assert.AreEqual(HttpStatusCode.OK, response.StatusCode, $"Expected 200 OK, got {(int)response.StatusCode}."); + AssertLogger.IsNotNull(response, "bulkUnpublishResponse"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Bulk unpublish with api_version 3.2 failed with status {(int)response.StatusCode} ({response.StatusCode}).", "bulkUnpublishSuccess"); + AssertLogger.AreEqual(HttpStatusCode.OK, response.StatusCode, $"Expected 200 OK, got {(int)response.StatusCode}.", "statusCode"); var responseJson = response.OpenJObjectResponse(); - Assert.IsNotNull(responseJson); + AssertLogger.IsNotNull(responseJson, "responseJson"); } catch (Exception ex) { @@ -743,15 +772,19 @@ public async Task Test004b_Should_Perform_Bulk_UnPublish_With_ApiVersion_3_2_Wit [DoNotParallelize] public async Task Test005_Should_Perform_Bulk_Release_Operations() { + TestOutputLogger.LogContext("TestScenario", "BulkReleaseOperations"); + TestOutputLogger.LogContext("ContentType", _contentTypeUid); try { // Fetch existing entries from the content type List availableEntries = await FetchExistingEntries(); - Assert.IsTrue(availableEntries.Count > 0, "No entries available for bulk operation"); + AssertLogger.IsTrue(availableEntries.Count > 0, "No entries available for bulk operation", "availableEntriesCount"); // Fetch an available release string availableReleaseUid = await FetchAvailableRelease(); - Assert.IsFalse(string.IsNullOrEmpty(availableReleaseUid), "No release available for bulk operations"); + AssertLogger.IsFalse(string.IsNullOrEmpty(availableReleaseUid), "No release available for bulk operations", "availableReleaseUid"); + if (!string.IsNullOrEmpty(availableReleaseUid)) + TestOutputLogger.LogContext("ReleaseUid", availableReleaseUid); // First, add items to the release var addItemsData = new BulkAddItemsData @@ -785,11 +818,11 @@ public async Task Test005_Should_Perform_Bulk_Release_Operations() ContentstackResponse releaseResponse = _stack.BulkOperation().AddItems(releaseData, "2.0"); var releaseResponseJson = releaseResponse.OpenJObjectResponse(); - Assert.IsNotNull(releaseResponse); - Assert.IsTrue(releaseResponse.IsSuccessStatusCode); + AssertLogger.IsNotNull(releaseResponse, "releaseResponse"); + AssertLogger.IsTrue(releaseResponse.IsSuccessStatusCode, "releaseAddItemsSuccess"); // Check if job was created - Assert.IsNotNull(releaseResponseJson["job_id"]); + AssertLogger.IsNotNull(releaseResponseJson["job_id"], "job_id"); string jobId = releaseResponseJson["job_id"].ToString(); // Wait a bit and check job status @@ -806,15 +839,19 @@ public async Task Test005_Should_Perform_Bulk_Release_Operations() [DoNotParallelize] public async Task Test006_Should_Update_Items_In_Release() { + TestOutputLogger.LogContext("TestScenario", "UpdateItemsInRelease"); + TestOutputLogger.LogContext("ContentType", _contentTypeUid); try { // Fetch existing entries from the content type List availableEntries = await FetchExistingEntries(); - Assert.IsTrue(availableEntries.Count > 0, "No entries available for bulk operation"); + AssertLogger.IsTrue(availableEntries.Count > 0, "No entries available for bulk operation", "availableEntriesCount"); // Fetch an available release string availableReleaseUid = await FetchAvailableRelease(); - Assert.IsFalse(string.IsNullOrEmpty(availableReleaseUid), "No release available for bulk operations"); + AssertLogger.IsFalse(string.IsNullOrEmpty(availableReleaseUid), "No release available for bulk operations", "availableReleaseUid"); + if (!string.IsNullOrEmpty(availableReleaseUid)) + TestOutputLogger.LogContext("ReleaseUid", availableReleaseUid); // Alternative: Test bulk update items with version 2.0 for release items var releaseData = new BulkAddItemsData @@ -837,8 +874,8 @@ public async Task Test006_Should_Update_Items_In_Release() ContentstackResponse bulkUpdateResponse = _stack.BulkOperation().UpdateItems(releaseData, "2.0"); var bulkUpdateResponseJson = bulkUpdateResponse.OpenJObjectResponse(); - Assert.IsNotNull(bulkUpdateResponse); - Assert.IsTrue(bulkUpdateResponse.IsSuccessStatusCode); + AssertLogger.IsNotNull(bulkUpdateResponse, "bulkUpdateResponse"); + AssertLogger.IsTrue(bulkUpdateResponse.IsSuccessStatusCode, "bulkUpdateSuccess"); if (bulkUpdateResponseJson["job_id"] != null) { @@ -859,10 +896,12 @@ public async Task Test006_Should_Update_Items_In_Release() [DoNotParallelize] public async Task Test007_Should_Perform_Bulk_Delete_Operation() { + TestOutputLogger.LogContext("TestScenario", "BulkDeleteOperation"); + TestOutputLogger.LogContext("ContentType", _contentTypeUid); try { List availableEntries = await FetchExistingEntries(); - Assert.IsTrue(availableEntries.Count > 0, "No entries available for bulk operation"); + AssertLogger.IsTrue(availableEntries.Count > 0, "No entries available for bulk operation", "availableEntriesCount"); var deleteDetails = new BulkDeleteDetails { @@ -875,8 +914,8 @@ public async Task Test007_Should_Perform_Bulk_Delete_Operation() }; // Skip actual delete so entries remain for UI verification. SDK usage is validated by building the payload. - Assert.IsNotNull(deleteDetails); - Assert.IsTrue(deleteDetails.Entries.Count > 0); + AssertLogger.IsNotNull(deleteDetails, "deleteDetails"); + AssertLogger.IsTrue(deleteDetails.Entries.Count > 0, "deleteDetailsEntriesCount"); } catch (Exception ex) { @@ -889,11 +928,13 @@ public async Task Test007_Should_Perform_Bulk_Delete_Operation() [DoNotParallelize] public async Task Test008_Should_Perform_Bulk_Workflow_Operations() { + TestOutputLogger.LogContext("TestScenario", "BulkWorkflowOperations"); + TestOutputLogger.LogContext("ContentType", _contentTypeUid); try { // Fetch existing entries from the content type List availableEntries = await FetchExistingEntries(); - Assert.IsTrue(availableEntries.Count > 0, "No entries available for bulk operation"); + AssertLogger.IsTrue(availableEntries.Count > 0, "No entries available for bulk operation", "availableEntriesCount"); // Test bulk workflow update operations (use real stage UID from EnsureBulkTestWorkflowAndPublishingRuleAsync when available) string workflowStageUid = !string.IsNullOrEmpty(_bulkTestWorkflowStageUid) ? _bulkTestWorkflowStageUid : "workflow_stage_uid"; @@ -917,9 +958,9 @@ public async Task Test008_Should_Perform_Bulk_Workflow_Operations() ContentstackResponse response = _stack.BulkOperation().Update(workflowUpdateBody); var responseJson = response.OpenJObjectResponse(); - Assert.IsNotNull(response); - Assert.IsTrue(response.IsSuccessStatusCode); - Assert.IsNotNull(responseJson["job_id"]); + AssertLogger.IsNotNull(response, "bulkWorkflowResponse"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, "bulkWorkflowSuccess"); + AssertLogger.IsNotNull(responseJson["job_id"], "job_id"); string jobId = responseJson["job_id"].ToString(); await CheckBulkJobStatus(jobId); } @@ -937,6 +978,8 @@ public async Task Test008_Should_Perform_Bulk_Workflow_Operations() [DoNotParallelize] public void Test009_Should_Cleanup_Test_Resources() { + TestOutputLogger.LogContext("TestScenario", "CleanupTestResources"); + TestOutputLogger.LogContext("ContentType", _contentTypeUid); try { // 1. Delete all entries created during the test run @@ -1018,8 +1061,8 @@ private async Task CheckBulkJobStatus(string jobId, string bulkVersion = null) ContentstackResponse statusResponse = await _stack.BulkOperation().JobStatusAsync(jobId, bulkVersion); var statusJson = statusResponse.OpenJObjectResponse(); - Assert.IsNotNull(statusResponse); - Assert.IsTrue(statusResponse.IsSuccessStatusCode); + AssertLogger.IsNotNull(statusResponse, "jobStatusResponse"); + AssertLogger.IsTrue(statusResponse.IsSuccessStatusCode, "jobStatusSuccess"); } catch (Exception e) { diff --git a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack016_DeliveryTokenTest.cs b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack016_DeliveryTokenTest.cs index ca4e6d4..fc30861 100644 --- a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack016_DeliveryTokenTest.cs +++ b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack016_DeliveryTokenTest.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Contentstack.Management.Core.Models; using Contentstack.Management.Core.Models.Token; +using Contentstack.Management.Core.Tests.Helpers; using Contentstack.Management.Core.Tests.Model; using Contentstack.Management.Core.Queryable; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -14,40 +15,32 @@ namespace Contentstack.Management.Core.Tests.IntegrationTest [TestClass] public class Contentstack016_DeliveryTokenTest { + private static ContentstackClient _client; private Stack _stack; private string _deliveryTokenUid; private string _testEnvironmentUid = "test_delivery_environment"; private DeliveryTokenModel _testTokenModel; + [ClassInitialize] + public static void ClassInitialize(TestContext context) + { + _client = Contentstack.CreateAuthenticatedClient(); + } + + [ClassCleanup] + public static void ClassCleanup() + { + try { _client?.Logout(); } catch { } + _client = null; + } + [TestInitialize] public async Task Initialize() { try { - // First, ensure the client is logged in - try - { - ContentstackResponse loginResponse = Contentstack.Client.Login(Contentstack.Credential); - if (!loginResponse.IsSuccessStatusCode) - { - Assert.Fail($"Login failed: {loginResponse.OpenResponse()}"); - } - } - catch (Exception loginEx) - { - // If already logged in, that's fine - continue with the test - if (loginEx.Message.Contains("already logged in")) - { - Console.WriteLine("Client already logged in, continuing with test"); - } - else - { - throw; // Re-throw if it's a different error - } - } - - StackResponse response = StackResponse.getStack(Contentstack.Client.serializer); - _stack = Contentstack.Client.Stack(response.Stack.APIKey); + StackResponse response = StackResponse.getStack(_client.serializer); + _stack = _client.Stack(response.Stack.APIKey); await CreateTestEnvironment(); @@ -80,7 +73,7 @@ public async Task Initialize() } catch (Exception ex) { - Assert.Fail($"Initialize failed: {ex.Message}"); + AssertLogger.Fail($"Initialize failed: {ex.Message}"); } } @@ -88,28 +81,30 @@ public async Task Initialize() [DoNotParallelize] public async Task Test001_Should_Create_Delivery_Token() { + TestOutputLogger.LogContext("TestScenario", "Test001_Should_Create_Delivery_Token"); try { ContentstackResponse response = _stack.DeliveryToken().Create(_testTokenModel); - Assert.IsTrue(response.IsSuccessStatusCode, $"Create delivery token failed"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, "Create delivery token failed", "CreateDeliveryTokenSuccess"); var responseObject = response.OpenJObjectResponse(); - Assert.IsNotNull(responseObject["token"], "Response should contain token object"); + AssertLogger.IsNotNull(responseObject["token"], "Response should contain token object"); var tokenData = responseObject["token"] as JObject; - Assert.IsNotNull(tokenData["uid"], "Token should have UID"); - Assert.AreEqual(_testTokenModel.Name, tokenData["name"]?.ToString(), "Token name should match"); - Assert.AreEqual(_testTokenModel.Description, tokenData["description"]?.ToString(), "Token description should match"); + AssertLogger.IsNotNull(tokenData["uid"], "Token should have UID"); + AssertLogger.AreEqual(_testTokenModel.Name, tokenData["name"]?.ToString(), "Token name should match", "TokenName"); + AssertLogger.AreEqual(_testTokenModel.Description, tokenData["description"]?.ToString(), "Token description should match", "TokenDescription"); _deliveryTokenUid = tokenData["uid"]?.ToString(); - Assert.IsNotNull(_deliveryTokenUid, "Delivery token UID should not be null"); + AssertLogger.IsNotNull(_deliveryTokenUid, "Delivery token UID should not be null"); + TestOutputLogger.LogContext("DeliveryTokenUid", _deliveryTokenUid ?? ""); Console.WriteLine($"Created delivery token with UID: {_deliveryTokenUid}"); } catch (Exception ex) { - Assert.Fail("Create delivery token test failed", ex.Message); + AssertLogger.Fail("Create delivery token test failed", ex.Message); } } @@ -117,6 +112,7 @@ public async Task Test001_Should_Create_Delivery_Token() [DoNotParallelize] public async Task Test002_Should_Create_Delivery_Token_Async() { + TestOutputLogger.LogContext("TestScenario", "Test002_Should_Create_Delivery_Token_Async"); try { var asyncTokenModel = new DeliveryTokenModel @@ -148,16 +144,17 @@ public async Task Test002_Should_Create_Delivery_Token_Async() ContentstackResponse response = await _stack.DeliveryToken().CreateAsync(asyncTokenModel); - Assert.IsTrue(response.IsSuccessStatusCode, $"Async create delivery token failed"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, "Async create delivery token failed", "AsyncCreateSuccess"); var responseObject = response.OpenJObjectResponse(); - Assert.IsNotNull(responseObject["token"], "Response should contain token object"); + AssertLogger.IsNotNull(responseObject["token"], "Response should contain token object"); var tokenData = responseObject["token"] as JObject; - Assert.IsNotNull(tokenData["uid"], "Token should have UID"); - Assert.AreEqual(asyncTokenModel.Name, tokenData["name"]?.ToString(), "Token name should match"); + AssertLogger.IsNotNull(tokenData["uid"], "Token should have UID"); + AssertLogger.AreEqual(asyncTokenModel.Name, tokenData["name"]?.ToString(), "Token name should match", "AsyncTokenName"); string asyncTokenUid = tokenData["uid"]?.ToString(); + TestOutputLogger.LogContext("AsyncCreatedTokenUid", asyncTokenUid ?? ""); if (!string.IsNullOrEmpty(asyncTokenUid)) { @@ -167,7 +164,7 @@ public async Task Test002_Should_Create_Delivery_Token_Async() } catch (Exception ex) { - Assert.Fail("Async create delivery token test failed", ex.Message); + AssertLogger.Fail("Async create delivery token test failed", ex.Message); } } @@ -175,6 +172,7 @@ public async Task Test002_Should_Create_Delivery_Token_Async() [DoNotParallelize] public async Task Test003_Should_Fetch_Delivery_Token() { + TestOutputLogger.LogContext("TestScenario", "Test003_Should_Fetch_Delivery_Token"); try { if (string.IsNullOrEmpty(_deliveryTokenUid)) @@ -182,22 +180,23 @@ public async Task Test003_Should_Fetch_Delivery_Token() await Test001_Should_Create_Delivery_Token(); } + TestOutputLogger.LogContext("DeliveryTokenUid", _deliveryTokenUid ?? ""); ContentstackResponse response = _stack.DeliveryToken(_deliveryTokenUid).Fetch(); - Assert.IsTrue(response.IsSuccessStatusCode, $"Fetch delivery token failed"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, "Fetch delivery token failed", "FetchSuccess"); var responseObject = response.OpenJObjectResponse(); - Assert.IsNotNull(responseObject["token"], "Response should contain token object"); + AssertLogger.IsNotNull(responseObject["token"], "Response should contain token object"); var tokenData = responseObject["token"] as JObject; - Assert.AreEqual(_deliveryTokenUid, tokenData["uid"]?.ToString(), "Token UID should match"); - Assert.AreEqual(_testTokenModel.Name, tokenData["name"]?.ToString(), "Token name should match"); - Assert.IsNotNull(tokenData["token"], "Token should have access token"); + AssertLogger.AreEqual(_deliveryTokenUid, tokenData["uid"]?.ToString(), "Token UID should match", "TokenUid"); + AssertLogger.AreEqual(_testTokenModel.Name, tokenData["name"]?.ToString(), "Token name should match", "TokenName"); + AssertLogger.IsNotNull(tokenData["token"], "Token should have access token"); } catch (Exception ex) { - Assert.Fail($"Fetch delivery token test failed: {ex.Message}"); + AssertLogger.Fail($"Fetch delivery token test failed: {ex.Message}"); } } @@ -205,6 +204,7 @@ public async Task Test003_Should_Fetch_Delivery_Token() [DoNotParallelize] public async Task Test004_Should_Fetch_Delivery_Token_Async() { + TestOutputLogger.LogContext("TestScenario", "Test004_Should_Fetch_Delivery_Token_Async"); try { if (string.IsNullOrEmpty(_deliveryTokenUid)) @@ -212,20 +212,21 @@ public async Task Test004_Should_Fetch_Delivery_Token_Async() await Test001_Should_Create_Delivery_Token(); } + TestOutputLogger.LogContext("DeliveryTokenUid", _deliveryTokenUid ?? ""); ContentstackResponse response = await _stack.DeliveryToken(_deliveryTokenUid).FetchAsync(); - Assert.IsTrue(response.IsSuccessStatusCode, $"Async fetch delivery token failed"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, "Async fetch delivery token failed", "AsyncFetchSuccess"); var responseObject = response.OpenJObjectResponse(); - Assert.IsNotNull(responseObject["token"], "Response should contain token object"); + AssertLogger.IsNotNull(responseObject["token"], "Response should contain token object"); var tokenData = responseObject["token"] as JObject; - Assert.AreEqual(_deliveryTokenUid, tokenData["uid"]?.ToString(), "Token UID should match"); - Assert.IsNotNull(tokenData["token"], "Token should have access token"); + AssertLogger.AreEqual(_deliveryTokenUid, tokenData["uid"]?.ToString(), "Token UID should match", "TokenUid"); + AssertLogger.IsNotNull(tokenData["token"], "Token should have access token"); } catch (Exception ex) { - Assert.Fail($"Async fetch delivery token test failed: {ex.Message}"); + AssertLogger.Fail($"Async fetch delivery token test failed: {ex.Message}"); } } @@ -233,6 +234,7 @@ public async Task Test004_Should_Fetch_Delivery_Token_Async() [DoNotParallelize] public async Task Test005_Should_Update_Delivery_Token() { + TestOutputLogger.LogContext("TestScenario", "Test005_Should_Update_Delivery_Token"); try { if (string.IsNullOrEmpty(_deliveryTokenUid)) @@ -240,6 +242,7 @@ public async Task Test005_Should_Update_Delivery_Token() await Test001_Should_Create_Delivery_Token(); } + TestOutputLogger.LogContext("DeliveryTokenUid", _deliveryTokenUid ?? ""); var updateModel = new DeliveryTokenModel { Name = "Updated Test Delivery Token", @@ -269,19 +272,19 @@ public async Task Test005_Should_Update_Delivery_Token() ContentstackResponse response = _stack.DeliveryToken(_deliveryTokenUid).Update(updateModel); - Assert.IsTrue(response.IsSuccessStatusCode, $"Update delivery token failed"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, "Update delivery token failed", "UpdateSuccess"); var responseObject = response.OpenJObjectResponse(); - Assert.IsNotNull(responseObject["token"], "Response should contain token object"); + AssertLogger.IsNotNull(responseObject["token"], "Response should contain token object"); var tokenData = responseObject["token"] as JObject; - Assert.AreEqual(_deliveryTokenUid, tokenData["uid"]?.ToString(), "Token UID should match"); - Assert.AreEqual(updateModel.Name, tokenData["name"]?.ToString(), "Updated token name should match"); - Assert.AreEqual(updateModel.Description, tokenData["description"]?.ToString(), "Updated token description should match"); + AssertLogger.AreEqual(_deliveryTokenUid, tokenData["uid"]?.ToString(), "Token UID should match", "TokenUid"); + AssertLogger.AreEqual(updateModel.Name, tokenData["name"]?.ToString(), "Updated token name should match", "UpdatedTokenName"); + AssertLogger.AreEqual(updateModel.Description, tokenData["description"]?.ToString(), "Updated token description should match", "UpdatedTokenDescription"); } catch (Exception ex) { - Assert.Fail($"Update delivery token test failed: {ex.Message}"); + AssertLogger.Fail($"Update delivery token test failed: {ex.Message}"); } } @@ -289,6 +292,7 @@ public async Task Test005_Should_Update_Delivery_Token() [DoNotParallelize] public async Task Test006_Should_Update_Delivery_Token_Async() { + TestOutputLogger.LogContext("TestScenario", "Test006_Should_Update_Delivery_Token_Async"); try { if (string.IsNullOrEmpty(_deliveryTokenUid)) @@ -296,6 +300,7 @@ public async Task Test006_Should_Update_Delivery_Token_Async() await Test001_Should_Create_Delivery_Token(); } + TestOutputLogger.LogContext("DeliveryTokenUid", _deliveryTokenUid ?? ""); var updateModel = new DeliveryTokenModel { Name = "Async Updated Test Delivery Token", @@ -325,19 +330,19 @@ public async Task Test006_Should_Update_Delivery_Token_Async() ContentstackResponse response = await _stack.DeliveryToken(_deliveryTokenUid).UpdateAsync(updateModel); - Assert.IsTrue(response.IsSuccessStatusCode, $"Async update delivery token failed"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, "Async update delivery token failed", "AsyncUpdateSuccess"); var responseObject = response.OpenJObjectResponse(); - Assert.IsNotNull(responseObject["token"], "Response should contain token object"); + AssertLogger.IsNotNull(responseObject["token"], "Response should contain token object"); var tokenData = responseObject["token"] as JObject; - Assert.AreEqual(_deliveryTokenUid, tokenData["uid"]?.ToString(), "Token UID should match"); - Assert.AreEqual(updateModel.Name, tokenData["name"]?.ToString(), "Updated token name should match"); + AssertLogger.AreEqual(_deliveryTokenUid, tokenData["uid"]?.ToString(), "Token UID should match", "TokenUid"); + AssertLogger.AreEqual(updateModel.Name, tokenData["name"]?.ToString(), "Updated token name should match", "UpdatedTokenName"); } catch (Exception ex) { - Assert.Fail($"Async update delivery token test failed: {ex.Message}"); + AssertLogger.Fail($"Async update delivery token test failed: {ex.Message}"); } } @@ -345,6 +350,7 @@ public async Task Test006_Should_Update_Delivery_Token_Async() [DoNotParallelize] public async Task Test007_Should_Query_All_Delivery_Tokens() { + TestOutputLogger.LogContext("TestScenario", "Test007_Should_Query_All_Delivery_Tokens"); try { if (string.IsNullOrEmpty(_deliveryTokenUid)) @@ -352,15 +358,16 @@ public async Task Test007_Should_Query_All_Delivery_Tokens() await Test001_Should_Create_Delivery_Token(); } + TestOutputLogger.LogContext("DeliveryTokenUid", _deliveryTokenUid ?? ""); ContentstackResponse response = _stack.DeliveryToken().Query().Find(); - Assert.IsTrue(response.IsSuccessStatusCode, $"Query delivery tokens failed"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, "Query delivery tokens failed", "QuerySuccess"); var responseObject = response.OpenJObjectResponse(); - Assert.IsNotNull(responseObject["tokens"], "Response should contain tokens array"); + AssertLogger.IsNotNull(responseObject["tokens"], "Response should contain tokens array"); var tokens = responseObject["tokens"] as JArray; - Assert.IsTrue(tokens.Count > 0, "Should have at least one delivery token"); + AssertLogger.IsTrue(tokens.Count > 0, "Should have at least one delivery token", "TokensCountGreaterThanZero"); bool foundTestToken = false; foreach (var token in tokens) @@ -372,12 +379,12 @@ public async Task Test007_Should_Query_All_Delivery_Tokens() } } - Assert.IsTrue(foundTestToken, "Test token should be found in query results"); + AssertLogger.IsTrue(foundTestToken, "Test token should be found in query results", "TestTokenFoundInQuery"); } catch (Exception ex) { - Assert.Fail($"Query delivery tokens test failed: {ex.Message}"); + AssertLogger.Fail($"Query delivery tokens test failed: {ex.Message}"); } } @@ -385,6 +392,7 @@ public async Task Test007_Should_Query_All_Delivery_Tokens() [DoNotParallelize] public async Task Test008_Should_Query_Delivery_Tokens_With_Parameters() { + TestOutputLogger.LogContext("TestScenario", "Test008_Should_Query_Delivery_Tokens_With_Parameters"); try { if (string.IsNullOrEmpty(_deliveryTokenUid)) @@ -392,24 +400,25 @@ public async Task Test008_Should_Query_Delivery_Tokens_With_Parameters() await Test001_Should_Create_Delivery_Token(); } + TestOutputLogger.LogContext("DeliveryTokenUid", _deliveryTokenUid ?? ""); var parameters = new ParameterCollection(); parameters.Add("limit", "5"); parameters.Add("skip", "0"); ContentstackResponse response = _stack.DeliveryToken().Query().Limit(5).Skip(0).Find(); - Assert.IsTrue(response.IsSuccessStatusCode, $"Query delivery tokens with parameters failed"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, "Query delivery tokens with parameters failed", "QueryWithParamsSuccess"); var responseObject = response.OpenJObjectResponse(); - Assert.IsNotNull(responseObject["tokens"], "Response should contain tokens array"); + AssertLogger.IsNotNull(responseObject["tokens"], "Response should contain tokens array"); var tokens = responseObject["tokens"] as JArray; - Assert.IsTrue(tokens.Count <= 5, "Should respect limit parameter"); + AssertLogger.IsTrue(tokens.Count <= 5, "Should respect limit parameter", "RespectLimitParam"); } catch (Exception ex) { - Assert.Fail($"Query delivery tokens with parameters test failed: {ex.Message}"); + AssertLogger.Fail($"Query delivery tokens with parameters test failed: {ex.Message}"); } } @@ -417,10 +426,12 @@ public async Task Test008_Should_Query_Delivery_Tokens_With_Parameters() [DoNotParallelize] public async Task Test009_Should_Create_Token_With_Multiple_Environments() { + TestOutputLogger.LogContext("TestScenario", "Test009_Should_Create_Token_With_Multiple_Environments"); try { string secondEnvironmentUid = "test_delivery_environment_2"; await CreateTestEnvironment(secondEnvironmentUid); + TestOutputLogger.LogContext("SecondEnvironmentUid", secondEnvironmentUid); var multiEnvTokenModel = new DeliveryTokenModel { @@ -451,17 +462,18 @@ public async Task Test009_Should_Create_Token_With_Multiple_Environments() ContentstackResponse response = _stack.DeliveryToken().Create(multiEnvTokenModel); - Assert.IsTrue(response.IsSuccessStatusCode, $"Create multi-environment delivery token failed"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, "Create multi-environment delivery token failed", "MultiEnvCreateSuccess"); var responseObject = response.OpenJObjectResponse(); var tokenData = responseObject["token"] as JObject; - Assert.IsNotNull(tokenData["uid"], "Token should have UID"); + AssertLogger.IsNotNull(tokenData["uid"], "Token should have UID"); string multiEnvTokenUid = tokenData["uid"]?.ToString(); + TestOutputLogger.LogContext("MultiEnvTokenUid", multiEnvTokenUid ?? ""); var scope = tokenData["scope"] as JArray; - Assert.IsNotNull(scope, "Token should have scope"); - Assert.IsTrue(scope.Count > 0, "Token should have at least one scope"); + AssertLogger.IsNotNull(scope, "Token should have scope"); + AssertLogger.IsTrue(scope.Count > 0, "Token should have at least one scope", "ScopeCount"); if (!string.IsNullOrEmpty(multiEnvTokenUid)) { @@ -473,7 +485,7 @@ public async Task Test009_Should_Create_Token_With_Multiple_Environments() } catch (Exception ex) { - Assert.Fail($"Multi-environment delivery token test failed: {ex.Message}"); + AssertLogger.Fail($"Multi-environment delivery token test failed: {ex.Message}"); } } @@ -481,6 +493,7 @@ public async Task Test009_Should_Create_Token_With_Multiple_Environments() [DoNotParallelize] public async Task Test011_Should_Create_Token_With_Complex_Scope() { + TestOutputLogger.LogContext("TestScenario", "Test011_Should_Create_Token_With_Complex_Scope"); try { var complexScopeTokenModel = new DeliveryTokenModel @@ -512,18 +525,19 @@ public async Task Test011_Should_Create_Token_With_Complex_Scope() ContentstackResponse response = _stack.DeliveryToken().Create(complexScopeTokenModel); - Assert.IsTrue(response.IsSuccessStatusCode, $"Create complex scope delivery token failed"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, "Create complex scope delivery token failed", "ComplexScopeCreateSuccess"); var responseObject = response.OpenJObjectResponse(); var tokenData = responseObject["token"] as JObject; - Assert.IsNotNull(tokenData["uid"], "Token should have UID"); + AssertLogger.IsNotNull(tokenData["uid"], "Token should have UID"); string complexScopeTokenUid = tokenData["uid"]?.ToString(); + TestOutputLogger.LogContext("ComplexScopeTokenUid", complexScopeTokenUid ?? ""); // Verify multiple scopes var scope = tokenData["scope"] as JArray; - Assert.IsNotNull(scope, "Token should have scope"); - Assert.IsTrue(scope.Count >= 2, "Token should have multiple scopes"); + AssertLogger.IsNotNull(scope, "Token should have scope"); + AssertLogger.IsTrue(scope.Count >= 2, "Token should have multiple scopes", "ScopeCountMultiple"); // Clean up the complex scope token if (!string.IsNullOrEmpty(complexScopeTokenUid)) @@ -534,7 +548,7 @@ public async Task Test011_Should_Create_Token_With_Complex_Scope() } catch (Exception ex) { - Assert.Fail($"Complex scope delivery token test failed: {ex.Message}"); + AssertLogger.Fail($"Complex scope delivery token test failed: {ex.Message}"); } } @@ -542,6 +556,7 @@ public async Task Test011_Should_Create_Token_With_Complex_Scope() [DoNotParallelize] public async Task Test012_Should_Create_Token_With_UI_Structure() { + TestOutputLogger.LogContext("TestScenario", "Test012_Should_Create_Token_With_UI_Structure"); try { // Test with the exact structure from UI as provided by user @@ -574,19 +589,20 @@ public async Task Test012_Should_Create_Token_With_UI_Structure() ContentstackResponse response = _stack.DeliveryToken().Create(uiStructureTokenModel); - Assert.IsTrue(response.IsSuccessStatusCode, $"Create UI structure delivery token failed"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, "Create UI structure delivery token failed", "UIStructureCreateSuccess"); var responseObject = response.OpenJObjectResponse(); var tokenData = responseObject["token"] as JObject; - Assert.IsNotNull(tokenData["uid"], "Token should have UID"); - Assert.AreEqual(uiStructureTokenModel.Name, tokenData["name"]?.ToString(), "Token name should match"); + AssertLogger.IsNotNull(tokenData["uid"], "Token should have UID"); + AssertLogger.AreEqual(uiStructureTokenModel.Name, tokenData["name"]?.ToString(), "Token name should match", "UITokenName"); // Verify the scope structure matches UI format var scope = tokenData["scope"] as JArray; - Assert.IsNotNull(scope, "Token should have scope"); - Assert.IsTrue(scope.Count == 2, "Token should have 2 scope modules (environment and branch)"); + AssertLogger.IsNotNull(scope, "Token should have scope"); + AssertLogger.IsTrue(scope.Count == 2, "Token should have 2 scope modules (environment and branch)", "UIScopeCount"); string uiTokenUid = tokenData["uid"]?.ToString(); + TestOutputLogger.LogContext("UITokenUid", uiTokenUid ?? ""); // Clean up the UI structure token if (!string.IsNullOrEmpty(uiTokenUid)) @@ -597,7 +613,7 @@ public async Task Test012_Should_Create_Token_With_UI_Structure() } catch (Exception ex) { - Assert.Fail($"UI structure delivery token test failed: {ex.Message}"); + AssertLogger.Fail($"UI structure delivery token test failed: {ex.Message}"); } } @@ -605,6 +621,7 @@ public async Task Test012_Should_Create_Token_With_UI_Structure() [DoNotParallelize] public async Task Test015_Should_Query_Delivery_Tokens_Async() { + TestOutputLogger.LogContext("TestScenario", "Test015_Should_Query_Delivery_Tokens_Async"); try { // Ensure we have at least one token @@ -613,15 +630,16 @@ public async Task Test015_Should_Query_Delivery_Tokens_Async() await Test001_Should_Create_Delivery_Token(); } + TestOutputLogger.LogContext("DeliveryTokenUid", _deliveryTokenUid ?? ""); ContentstackResponse response = await _stack.DeliveryToken().Query().FindAsync(); - Assert.IsTrue(response.IsSuccessStatusCode, $"Async query delivery tokens failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Async query delivery tokens failed: {response.OpenResponse()}", "AsyncQuerySuccess"); var responseObject = response.OpenJObjectResponse(); - Assert.IsNotNull(responseObject["tokens"], "Response should contain tokens array"); + AssertLogger.IsNotNull(responseObject["tokens"], "Response should contain tokens array"); var tokens = responseObject["tokens"] as JArray; - Assert.IsTrue(tokens.Count > 0, "Should have at least one delivery token"); + AssertLogger.IsTrue(tokens.Count > 0, "Should have at least one delivery token", "AsyncTokensCount"); bool foundTestToken = false; foreach (var token in tokens) @@ -633,12 +651,12 @@ public async Task Test015_Should_Query_Delivery_Tokens_Async() } } - Assert.IsTrue(foundTestToken, "Test token should be found in async query results"); + AssertLogger.IsTrue(foundTestToken, "Test token should be found in async query results", "TestTokenFoundInAsyncQuery"); } catch (Exception ex) { - Assert.Fail($"Async query delivery tokens test failed: {ex.Message}"); + AssertLogger.Fail($"Async query delivery tokens test failed: {ex.Message}"); } } @@ -646,6 +664,7 @@ public async Task Test015_Should_Query_Delivery_Tokens_Async() [DoNotParallelize] public async Task Test016_Should_Create_Token_With_Empty_Description() { + TestOutputLogger.LogContext("TestScenario", "Test016_Should_Create_Token_With_Empty_Description"); try { var emptyDescTokenModel = new DeliveryTokenModel @@ -677,14 +696,15 @@ public async Task Test016_Should_Create_Token_With_Empty_Description() ContentstackResponse response = _stack.DeliveryToken().Create(emptyDescTokenModel); - Assert.IsTrue(response.IsSuccessStatusCode, $"Create token with empty description failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Create token with empty description failed: {response.OpenResponse()}", "EmptyDescCreateSuccess"); var responseObject = response.OpenJObjectResponse(); var tokenData = responseObject["token"] as JObject; - Assert.IsNotNull(tokenData["uid"], "Token should have UID"); - Assert.AreEqual(emptyDescTokenModel.Name, tokenData["name"]?.ToString(), "Token name should match"); + AssertLogger.IsNotNull(tokenData["uid"], "Token should have UID"); + AssertLogger.AreEqual(emptyDescTokenModel.Name, tokenData["name"]?.ToString(), "Token name should match", "EmptyDescTokenName"); string emptyDescTokenUid = tokenData["uid"]?.ToString(); + TestOutputLogger.LogContext("EmptyDescTokenUid", emptyDescTokenUid ?? ""); // Clean up the empty description token if (!string.IsNullOrEmpty(emptyDescTokenUid)) @@ -695,7 +715,7 @@ public async Task Test016_Should_Create_Token_With_Empty_Description() } catch (Exception ex) { - Assert.Fail($"Empty description token test failed: {ex.Message}"); + AssertLogger.Fail($"Empty description token test failed: {ex.Message}"); } } @@ -703,6 +723,7 @@ public async Task Test016_Should_Create_Token_With_Empty_Description() [DoNotParallelize] public async Task Test017_Should_Validate_Environment_Scope_Requirement() { + TestOutputLogger.LogContext("TestScenario", "Test017_Should_Validate_Environment_Scope_Requirement"); try { // Test that environment-only scope is rejected by API @@ -737,15 +758,15 @@ public async Task Test017_Should_Validate_Environment_Scope_Requirement() } // If no exception was thrown, check the response status - Assert.IsFalse(response.IsSuccessStatusCode, "Environment-only token should be rejected by API"); - Assert.IsTrue(response.StatusCode == System.Net.HttpStatusCode.BadRequest || + AssertLogger.IsFalse(response.IsSuccessStatusCode, "Environment-only token should be rejected by API", "EnvOnlyRejected"); + AssertLogger.IsTrue(response.StatusCode == System.Net.HttpStatusCode.BadRequest || response.StatusCode == System.Net.HttpStatusCode.UnprocessableEntity, - $"Expected 400 or 422 for environment-only token, got {response.StatusCode}"); + $"Expected 400 or 422 for environment-only token, got {response.StatusCode}", "Expected400Or422"); } catch (Exception ex) { - Assert.Fail($"Environment scope validation test failed: {ex.Message}"); + AssertLogger.Fail($"Environment scope validation test failed: {ex.Message}"); } } @@ -753,6 +774,7 @@ public async Task Test017_Should_Validate_Environment_Scope_Requirement() [DoNotParallelize] public async Task Test018_Should_Validate_Branch_Scope_Requirement() { + TestOutputLogger.LogContext("TestScenario", "Test018_Should_Validate_Branch_Scope_Requirement"); try { // Test that branch-only scope is rejected by API @@ -787,15 +809,15 @@ public async Task Test018_Should_Validate_Branch_Scope_Requirement() } // If no exception was thrown, check the response status - Assert.IsFalse(response.IsSuccessStatusCode, "Branch-only token should be rejected by API"); - Assert.IsTrue(response.StatusCode == System.Net.HttpStatusCode.BadRequest || + AssertLogger.IsFalse(response.IsSuccessStatusCode, "Branch-only token should be rejected by API", "BranchOnlyRejected"); + AssertLogger.IsTrue(response.StatusCode == System.Net.HttpStatusCode.BadRequest || response.StatusCode == System.Net.HttpStatusCode.UnprocessableEntity, - $"Expected 400 or 422 for branch-only token, got {response.StatusCode}"); + $"Expected 400 or 422 for branch-only token, got {response.StatusCode}", "Expected400Or422"); } catch (Exception ex) { - Assert.Fail($"Branch scope validation test failed: {ex.Message}"); + AssertLogger.Fail($"Branch scope validation test failed: {ex.Message}"); } } @@ -803,6 +825,7 @@ public async Task Test018_Should_Validate_Branch_Scope_Requirement() [DoNotParallelize] public async Task Test019_Should_Delete_Delivery_Token() { + TestOutputLogger.LogContext("TestScenario", "Test019_Should_Delete_Delivery_Token"); try { // Ensure we have a token to delete @@ -812,24 +835,25 @@ public async Task Test019_Should_Delete_Delivery_Token() } string tokenUidToDelete = _deliveryTokenUid; - Assert.IsNotNull(tokenUidToDelete, "Should have a valid token UID to delete"); + AssertLogger.IsNotNull(tokenUidToDelete, "Should have a valid token UID to delete"); + TestOutputLogger.LogContext("TokenUidToDelete", tokenUidToDelete ?? ""); // Test synchronous delete ContentstackResponse response = _stack.DeliveryToken(tokenUidToDelete).Delete(); - Assert.IsTrue(response.IsSuccessStatusCode, $"Delete delivery token failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Delete delivery token failed: {response.OpenResponse()}", "DeleteSuccess"); // Verify token is deleted by trying to fetch it try { ContentstackResponse fetchResponse = _stack.DeliveryToken(tokenUidToDelete).Fetch(); - Assert.IsFalse(fetchResponse.IsSuccessStatusCode, "Deleted token should not be fetchable"); + AssertLogger.IsFalse(fetchResponse.IsSuccessStatusCode, "Deleted token should not be fetchable", "DeletedTokenNotFetchable"); // Verify the response indicates the token was not found - Assert.IsTrue(fetchResponse.StatusCode == System.Net.HttpStatusCode.NotFound || + AssertLogger.IsTrue(fetchResponse.StatusCode == System.Net.HttpStatusCode.NotFound || fetchResponse.StatusCode == System.Net.HttpStatusCode.UnprocessableEntity || fetchResponse.StatusCode == System.Net.HttpStatusCode.BadRequest, - $"Expected 404, 422, or 400 for deleted token fetch, got {fetchResponse.StatusCode}"); + $"Expected 404, 422, or 400 for deleted token fetch, got {fetchResponse.StatusCode}", "Expected404Or422Or400"); } catch (Exception ex) { @@ -842,7 +866,7 @@ public async Task Test019_Should_Delete_Delivery_Token() } catch (Exception ex) { - Assert.Fail("Delete delivery token test failed", ex.Message); + AssertLogger.Fail("Delete delivery token test failed", ex.Message); } } @@ -869,7 +893,7 @@ public async Task Cleanup() } catch (Exception ex) { - Assert.Fail("Cleanup failed", ex.Message); + AssertLogger.Fail("Cleanup failed", ex.Message); } } @@ -980,4 +1004,4 @@ private async Task CleanupTestEnvironment(string environmentUid = null) #endregion } -} \ No newline at end of file +} diff --git a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack017_TaxonomyTest.cs b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack017_TaxonomyTest.cs index e57c031..ba34b4c 100644 --- a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack017_TaxonomyTest.cs +++ b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack017_TaxonomyTest.cs @@ -7,6 +7,7 @@ using Contentstack.Management.Core.Exceptions; using Contentstack.Management.Core.Models; using Contentstack.Management.Core.Queryable; +using Contentstack.Management.Core.Tests.Helpers; using Contentstack.Management.Core.Tests.Model; using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json.Linq; @@ -16,22 +17,31 @@ namespace Contentstack.Management.Core.Tests.IntegrationTest [TestClass] public class Contentstack017_TaxonomyTest { + private static ContentstackClient _client; private static string _taxonomyUid; private static string _asyncCreatedTaxonomyUid; private static string _importedTaxonomyUid; private static string _testLocaleCode; + private static string _asyncTestLocaleCode; private static bool _weCreatedTestLocale; + private static bool _weCreatedAsyncTestLocale; private static List _createdTermUids; private static string _rootTermUid; private static string _childTermUid; private Stack _stack; private TaxonomyModel _createModel; + [ClassInitialize] + public static void ClassInitialize(TestContext context) + { + _client = Contentstack.CreateAuthenticatedClient(); + } + [TestInitialize] public void Initialize() { - StackResponse response = StackResponse.getStack(Contentstack.Client.serializer); - _stack = Contentstack.Client.Stack(response.Stack.APIKey); + StackResponse response = StackResponse.getStack(_client.serializer); + _stack = _client.Stack(response.Stack.APIKey); if (_taxonomyUid == null) _taxonomyUid = "taxonomy_integration_test_" + Guid.NewGuid().ToString("N").Substring(0, 8); _createdTermUids = _createdTermUids ?? new List(); @@ -47,76 +57,87 @@ public void Initialize() [DoNotParallelize] public void Test001_Should_Create_Taxonomy() { + TestOutputLogger.LogContext("TestScenario", "Test001_Should_Create_Taxonomy"); + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); ContentstackResponse response = _stack.Taxonomy().Create(_createModel); - Assert.IsTrue(response.IsSuccessStatusCode, $"Create failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Create failed: {response.OpenResponse()}", "CreateSuccess"); var wrapper = response.OpenTResponse(); - Assert.IsNotNull(wrapper?.Taxonomy); - Assert.AreEqual(_createModel.Uid, wrapper.Taxonomy.Uid); - Assert.AreEqual(_createModel.Name, wrapper.Taxonomy.Name); - Assert.AreEqual(_createModel.Description, wrapper.Taxonomy.Description); + AssertLogger.IsNotNull(wrapper?.Taxonomy, "Wrapper taxonomy"); + AssertLogger.AreEqual(_createModel.Uid, wrapper.Taxonomy.Uid, "TaxonomyUid"); + AssertLogger.AreEqual(_createModel.Name, wrapper.Taxonomy.Name, "TaxonomyName"); + AssertLogger.AreEqual(_createModel.Description, wrapper.Taxonomy.Description, "TaxonomyDescription"); } [TestMethod] [DoNotParallelize] public void Test002_Should_Fetch_Taxonomy() { + TestOutputLogger.LogContext("TestScenario", "Test002_Should_Fetch_Taxonomy"); + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); ContentstackResponse response = _stack.Taxonomy(_taxonomyUid).Fetch(); - Assert.IsTrue(response.IsSuccessStatusCode, $"Fetch failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Fetch failed: {response.OpenResponse()}", "FetchSuccess"); var wrapper = response.OpenTResponse(); - Assert.IsNotNull(wrapper?.Taxonomy); - Assert.AreEqual(_taxonomyUid, wrapper.Taxonomy.Uid); - Assert.IsNotNull(wrapper.Taxonomy.Name); + AssertLogger.IsNotNull(wrapper?.Taxonomy, "Wrapper taxonomy"); + AssertLogger.AreEqual(_taxonomyUid, wrapper.Taxonomy.Uid, "TaxonomyUid"); + AssertLogger.IsNotNull(wrapper.Taxonomy.Name, "Taxonomy name"); } [TestMethod] [DoNotParallelize] public void Test003_Should_Query_Taxonomies() { + TestOutputLogger.LogContext("TestScenario", "Test003_Should_Query_Taxonomies"); ContentstackResponse response = _stack.Taxonomy().Query().Find(); - Assert.IsTrue(response.IsSuccessStatusCode, $"Query failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Query failed: {response.OpenResponse()}", "QuerySuccess"); var wrapper = response.OpenTResponse(); - Assert.IsNotNull(wrapper?.Taxonomies); - Assert.IsTrue(wrapper.Taxonomies.Count >= 0); + AssertLogger.IsNotNull(wrapper?.Taxonomies, "Wrapper taxonomies"); + AssertLogger.IsTrue(wrapper.Taxonomies.Count >= 0, "Taxonomies count", "TaxonomiesCount"); } [TestMethod] [DoNotParallelize] public void Test004_Should_Update_Taxonomy() { + TestOutputLogger.LogContext("TestScenario", "Test004_Should_Update_Taxonomy"); + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); var updateModel = new TaxonomyModel { Name = "Taxonomy Integration Test Updated", Description = "Updated description" }; ContentstackResponse response = _stack.Taxonomy(_taxonomyUid).Update(updateModel); - Assert.IsTrue(response.IsSuccessStatusCode, $"Update failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Update failed: {response.OpenResponse()}", "UpdateSuccess"); var wrapper = response.OpenTResponse(); - Assert.IsNotNull(wrapper?.Taxonomy); - Assert.AreEqual("Taxonomy Integration Test Updated", wrapper.Taxonomy.Name); - Assert.AreEqual("Updated description", wrapper.Taxonomy.Description); + AssertLogger.IsNotNull(wrapper?.Taxonomy, "Wrapper taxonomy"); + AssertLogger.AreEqual("Taxonomy Integration Test Updated", wrapper.Taxonomy.Name, "UpdatedName"); + AssertLogger.AreEqual("Updated description", wrapper.Taxonomy.Description, "UpdatedDescription"); } [TestMethod] [DoNotParallelize] public async Task Test005_Should_Fetch_Taxonomy_Async() { + TestOutputLogger.LogContext("TestScenario", "Test005_Should_Fetch_Taxonomy_Async"); + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); ContentstackResponse response = await _stack.Taxonomy(_taxonomyUid).FetchAsync(); - Assert.IsTrue(response.IsSuccessStatusCode, $"FetchAsync failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"FetchAsync failed: {response.OpenResponse()}", "FetchAsyncSuccess"); var wrapper = response.OpenTResponse(); - Assert.IsNotNull(wrapper?.Taxonomy); - Assert.AreEqual(_taxonomyUid, wrapper.Taxonomy.Uid); + AssertLogger.IsNotNull(wrapper?.Taxonomy, "Wrapper taxonomy"); + AssertLogger.AreEqual(_taxonomyUid, wrapper.Taxonomy.Uid, "TaxonomyUid"); } [TestMethod] [DoNotParallelize] public async Task Test006_Should_Create_Taxonomy_Async() { + TestOutputLogger.LogContext("TestScenario", "Test006_Should_Create_Taxonomy_Async"); _asyncCreatedTaxonomyUid = "taxonomy_async_" + Guid.NewGuid().ToString("N").Substring(0, 8); + TestOutputLogger.LogContext("AsyncCreatedTaxonomyUid", _asyncCreatedTaxonomyUid); var model = new TaxonomyModel { Uid = _asyncCreatedTaxonomyUid, @@ -124,82 +145,94 @@ public async Task Test006_Should_Create_Taxonomy_Async() Description = "Created via CreateAsync" }; ContentstackResponse response = await _stack.Taxonomy().CreateAsync(model); - Assert.IsTrue(response.IsSuccessStatusCode, $"CreateAsync failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"CreateAsync failed: {response.OpenResponse()}", "CreateAsyncSuccess"); var wrapper = response.OpenTResponse(); - Assert.IsNotNull(wrapper?.Taxonomy); - Assert.AreEqual(_asyncCreatedTaxonomyUid, wrapper.Taxonomy.Uid); + AssertLogger.IsNotNull(wrapper?.Taxonomy, "Wrapper taxonomy"); + AssertLogger.AreEqual(_asyncCreatedTaxonomyUid, wrapper.Taxonomy.Uid, "AsyncTaxonomyUid"); } [TestMethod] [DoNotParallelize] public async Task Test007_Should_Update_Taxonomy_Async() { + TestOutputLogger.LogContext("TestScenario", "Test007_Should_Update_Taxonomy_Async"); + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); var updateModel = new TaxonomyModel { Name = "Taxonomy Integration Test Updated Async", Description = "Updated via UpdateAsync" }; ContentstackResponse response = await _stack.Taxonomy(_taxonomyUid).UpdateAsync(updateModel); - Assert.IsTrue(response.IsSuccessStatusCode, $"UpdateAsync failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"UpdateAsync failed: {response.OpenResponse()}", "UpdateAsyncSuccess"); var wrapper = response.OpenTResponse(); - Assert.IsNotNull(wrapper?.Taxonomy); - Assert.AreEqual("Taxonomy Integration Test Updated Async", wrapper.Taxonomy.Name); + AssertLogger.IsNotNull(wrapper?.Taxonomy, "Wrapper taxonomy"); + AssertLogger.AreEqual("Taxonomy Integration Test Updated Async", wrapper.Taxonomy.Name, "UpdatedAsyncName"); } [TestMethod] [DoNotParallelize] public async Task Test008_Should_Query_Taxonomies_Async() { + TestOutputLogger.LogContext("TestScenario", "Test008_Should_Query_Taxonomies_Async"); ContentstackResponse response = await _stack.Taxonomy().Query().FindAsync(); - Assert.IsTrue(response.IsSuccessStatusCode, $"Query FindAsync failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Query FindAsync failed: {response.OpenResponse()}", "QueryFindAsyncSuccess"); var wrapper = response.OpenTResponse(); - Assert.IsNotNull(wrapper?.Taxonomies); - Assert.IsTrue(wrapper.Taxonomies.Count >= 0); + AssertLogger.IsNotNull(wrapper?.Taxonomies, "Wrapper taxonomies"); + AssertLogger.IsTrue(wrapper.Taxonomies.Count >= 0, "Taxonomies count", "TaxonomiesCount"); } [TestMethod] [DoNotParallelize] public void Test009_Should_Get_Taxonomy_Locales() { + TestOutputLogger.LogContext("TestScenario", "Test009_Should_Get_Taxonomy_Locales"); + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); ContentstackResponse response = _stack.Taxonomy(_taxonomyUid).Locales(); - Assert.IsTrue(response.IsSuccessStatusCode, $"Locales failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Locales failed: {response.OpenResponse()}", "LocalesSuccess"); var jobj = response.OpenJObjectResponse(); - Assert.IsNotNull(jobj["taxonomies"]); + AssertLogger.IsNotNull(jobj["taxonomies"], "Taxonomies in locales response"); } [TestMethod] [DoNotParallelize] public async Task Test010_Should_Get_Taxonomy_Locales_Async() { + TestOutputLogger.LogContext("TestScenario", "Test010_Should_Get_Taxonomy_Locales_Async"); + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); ContentstackResponse response = await _stack.Taxonomy(_taxonomyUid).LocalesAsync(); - Assert.IsTrue(response.IsSuccessStatusCode, $"LocalesAsync failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"LocalesAsync failed: {response.OpenResponse()}", "LocalesAsyncSuccess"); var jobj = response.OpenJObjectResponse(); - Assert.IsNotNull(jobj["taxonomies"]); + AssertLogger.IsNotNull(jobj["taxonomies"], "Taxonomies in locales response"); } [TestMethod] [DoNotParallelize] public void Test011_Should_Localize_Taxonomy() { + TestOutputLogger.LogContext("TestScenario", "Test011_Should_Localize_Taxonomy"); _weCreatedTestLocale = false; ContentstackResponse localesResponse = _stack.Locale().Query().Find(); - Assert.IsTrue(localesResponse.IsSuccessStatusCode, $"Query locales failed: {localesResponse.OpenResponse()}"); + AssertLogger.IsTrue(localesResponse.IsSuccessStatusCode, $"Query locales failed: {localesResponse.OpenResponse()}", "QueryLocalesSuccess"); var jobj = localesResponse.OpenJObjectResponse(); var localesArray = jobj["locales"] as JArray ?? jobj["items"] as JArray; if (localesArray == null || localesArray.Count == 0) { - Assert.Inconclusive("Stack has no locales; skipping taxonomy localize tests."); + AssertLogger.Inconclusive("Stack has no locales; skipping taxonomy localize tests."); return; } string masterLocale = "en-us"; _testLocaleCode = null; + _asyncTestLocaleCode = null; foreach (var item in localesArray) { var code = item["code"]?.ToString(); if (string.IsNullOrEmpty(code)) continue; - if (!string.Equals(code, masterLocale, StringComparison.OrdinalIgnoreCase)) - { + if (string.Equals(code, masterLocale, StringComparison.OrdinalIgnoreCase)) continue; + if (_testLocaleCode == null) _testLocaleCode = code; + else if (_asyncTestLocaleCode == null) + { + _asyncTestLocaleCode = code; break; } } @@ -226,10 +259,33 @@ public void Test011_Should_Localize_Taxonomy() } if (string.IsNullOrEmpty(_testLocaleCode)) { - Assert.Inconclusive("Stack has no non-master locale and could not create one; skipping taxonomy localize tests."); + AssertLogger.Inconclusive("Stack has no non-master locale and could not create one; skipping taxonomy localize tests."); return; } + if (string.IsNullOrEmpty(_asyncTestLocaleCode)) + { + try + { + _asyncTestLocaleCode = "mr-in"; + var localeModel = new LocaleModel + { + Code = _asyncTestLocaleCode, + Name = "Marathi (India)" + }; + ContentstackResponse createResponse = _stack.Locale().Create(localeModel); + if (createResponse.IsSuccessStatusCode) + _weCreatedAsyncTestLocale = true; + else + _asyncTestLocaleCode = null; + } + catch (ContentstackErrorException) + { + _asyncTestLocaleCode = null; + } + } + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); + TestOutputLogger.LogContext("TestLocaleCode", _testLocaleCode ?? ""); var localizeModel = new TaxonomyModel { Uid = _taxonomyUid, @@ -239,17 +295,47 @@ public void Test011_Should_Localize_Taxonomy() var coll = new ParameterCollection(); coll.Add("locale", _testLocaleCode); ContentstackResponse response = _stack.Taxonomy(_taxonomyUid).Localize(localizeModel, coll); - Assert.IsTrue(response.IsSuccessStatusCode, $"Localize failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Localize failed: {response.OpenResponse()}", "LocalizeSuccess"); var wrapper = response.OpenTResponse(); - Assert.IsNotNull(wrapper?.Taxonomy); + AssertLogger.IsNotNull(wrapper?.Taxonomy, "Wrapper taxonomy"); if (!string.IsNullOrEmpty(wrapper.Taxonomy.Locale)) - Assert.AreEqual(_testLocaleCode, wrapper.Taxonomy.Locale); + AssertLogger.AreEqual(_testLocaleCode, wrapper.Taxonomy.Locale, "LocalizedLocale"); + } + + [TestMethod] + [DoNotParallelize] + public async Task Test012_Should_Localize_Taxonomy_Async() + { + TestOutputLogger.LogContext("TestScenario", "Test012_Should_Localize_Taxonomy_Async"); + if (string.IsNullOrEmpty(_asyncTestLocaleCode)) + { + AssertLogger.Inconclusive("No second non-master locale available; skipping async taxonomy localize test."); + return; + } + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); + TestOutputLogger.LogContext("AsyncTestLocaleCode", _asyncTestLocaleCode ?? ""); + var localizeModel = new TaxonomyModel + { + Uid = _taxonomyUid, + Name = "Taxonomy Localized Async", + Description = "Localized description async" + }; + var coll = new ParameterCollection(); + coll.Add("locale", _asyncTestLocaleCode); + ContentstackResponse response = await _stack.Taxonomy(_taxonomyUid).LocalizeAsync(localizeModel, coll); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"LocalizeAsync failed: {response.OpenResponse()}", "LocalizeAsyncSuccess"); + var wrapper = response.OpenTResponse(); + AssertLogger.IsNotNull(wrapper?.Taxonomy, "Wrapper taxonomy"); + if (!string.IsNullOrEmpty(wrapper.Taxonomy.Locale)) + AssertLogger.AreEqual(_asyncTestLocaleCode, wrapper.Taxonomy.Locale, "LocalizedAsyncLocale"); } [TestMethod] [DoNotParallelize] public void Test013_Should_Throw_When_Localize_With_Invalid_Locale() { + TestOutputLogger.LogContext("TestScenario", "Test013_Should_Throw_When_Localize_With_Invalid_Locale"); + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); var localizeModel = new TaxonomyModel { Uid = _taxonomyUid, @@ -258,23 +344,25 @@ public void Test013_Should_Throw_When_Localize_With_Invalid_Locale() }; var coll = new ParameterCollection(); coll.Add("locale", "invalid_locale_code_xyz"); - Assert.ThrowsException(() => - _stack.Taxonomy(_taxonomyUid).Localize(localizeModel, coll)); + AssertLogger.ThrowsException(() => + _stack.Taxonomy(_taxonomyUid).Localize(localizeModel, coll), "LocalizeInvalidLocale"); } [TestMethod] [DoNotParallelize] public void Test014_Should_Import_Taxonomy() { + TestOutputLogger.LogContext("TestScenario", "Test014_Should_Import_Taxonomy"); string importUid = "taxonomy_import_" + Guid.NewGuid().ToString("N").Substring(0, 8); + TestOutputLogger.LogContext("ImportUid", importUid); string json = $"{{\"taxonomy\":{{\"uid\":\"{importUid}\",\"name\":\"Imported Taxonomy\",\"description\":\"Imported\"}}}}"; using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(json))) { var importModel = new TaxonomyImportModel(stream, "taxonomy.json"); ContentstackResponse response = _stack.Taxonomy().Import(importModel); - Assert.IsTrue(response.IsSuccessStatusCode, $"Import failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Import failed: {response.OpenResponse()}", "ImportSuccess"); var wrapper = response.OpenTResponse(); - Assert.IsNotNull(wrapper?.Taxonomy); + AssertLogger.IsNotNull(wrapper?.Taxonomy, "Imported taxonomy"); _importedTaxonomyUid = wrapper.Taxonomy.Uid ?? importUid; } } @@ -283,15 +371,17 @@ public void Test014_Should_Import_Taxonomy() [DoNotParallelize] public async Task Test015_Should_Import_Taxonomy_Async() { + TestOutputLogger.LogContext("TestScenario", "Test015_Should_Import_Taxonomy_Async"); string importUid = "taxonomy_import_async_" + Guid.NewGuid().ToString("N").Substring(0, 8); + TestOutputLogger.LogContext("ImportUid", importUid); string json = $"{{\"taxonomy\":{{\"uid\":\"{importUid}\",\"name\":\"Imported Async\",\"description\":\"Imported via Async\"}}}}"; using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(json))) { var importModel = new TaxonomyImportModel(stream, "taxonomy.json"); ContentstackResponse response = await _stack.Taxonomy().ImportAsync(importModel); - Assert.IsTrue(response.IsSuccessStatusCode, $"ImportAsync failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"ImportAsync failed: {response.OpenResponse()}", "ImportAsyncSuccess"); var wrapper = response.OpenTResponse(); - Assert.IsNotNull(wrapper?.Taxonomy); + AssertLogger.IsNotNull(wrapper?.Taxonomy, "Imported taxonomy"); } } @@ -299,7 +389,10 @@ public async Task Test015_Should_Import_Taxonomy_Async() [DoNotParallelize] public void Test016_Should_Create_Root_Term() { + TestOutputLogger.LogContext("TestScenario", "Test016_Should_Create_Root_Term"); + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); _rootTermUid = "term_root_" + Guid.NewGuid().ToString("N").Substring(0, 8); + TestOutputLogger.LogContext("RootTermUid", _rootTermUid); var termModel = new TermModel { Uid = _rootTermUid, @@ -307,10 +400,10 @@ public void Test016_Should_Create_Root_Term() ParentUid = null }; ContentstackResponse response = _stack.Taxonomy(_taxonomyUid).Terms().Create(termModel); - Assert.IsTrue(response.IsSuccessStatusCode, $"Create term failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Create term failed: {response.OpenResponse()}", "CreateTermSuccess"); var wrapper = response.OpenTResponse(); - Assert.IsNotNull(wrapper?.Term); - Assert.AreEqual(_rootTermUid, wrapper.Term.Uid); + AssertLogger.IsNotNull(wrapper?.Term, "Term in response"); + AssertLogger.AreEqual(_rootTermUid, wrapper.Term.Uid, "RootTermUid"); _createdTermUids.Add(_rootTermUid); } @@ -318,7 +411,11 @@ public void Test016_Should_Create_Root_Term() [DoNotParallelize] public void Test017_Should_Create_Child_Term() { + TestOutputLogger.LogContext("TestScenario", "Test017_Should_Create_Child_Term"); + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); + TestOutputLogger.LogContext("RootTermUid", _rootTermUid ?? ""); _childTermUid = "term_child_" + Guid.NewGuid().ToString("N").Substring(0, 8); + TestOutputLogger.LogContext("ChildTermUid", _childTermUid); var termModel = new TermModel { Uid = _childTermUid, @@ -326,10 +423,10 @@ public void Test017_Should_Create_Child_Term() ParentUid = _rootTermUid }; ContentstackResponse response = _stack.Taxonomy(_taxonomyUid).Terms().Create(termModel); - Assert.IsTrue(response.IsSuccessStatusCode, $"Create child term failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Create child term failed: {response.OpenResponse()}", "CreateChildTermSuccess"); var wrapper = response.OpenTResponse(); - Assert.IsNotNull(wrapper?.Term); - Assert.AreEqual(_childTermUid, wrapper.Term.Uid); + AssertLogger.IsNotNull(wrapper?.Term, "Term in response"); + AssertLogger.AreEqual(_childTermUid, wrapper.Term.Uid, "ChildTermUid"); _createdTermUids.Add(_childTermUid); } @@ -337,147 +434,185 @@ public void Test017_Should_Create_Child_Term() [DoNotParallelize] public void Test018_Should_Fetch_Term() { + TestOutputLogger.LogContext("TestScenario", "Test018_Should_Fetch_Term"); + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); + TestOutputLogger.LogContext("RootTermUid", _rootTermUid ?? ""); ContentstackResponse response = _stack.Taxonomy(_taxonomyUid).Terms(_rootTermUid).Fetch(); - Assert.IsTrue(response.IsSuccessStatusCode, $"Fetch term failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Fetch term failed: {response.OpenResponse()}", "FetchTermSuccess"); var wrapper = response.OpenTResponse(); - Assert.IsNotNull(wrapper?.Term); - Assert.AreEqual(_rootTermUid, wrapper.Term.Uid); + AssertLogger.IsNotNull(wrapper?.Term, "Term in response"); + AssertLogger.AreEqual(_rootTermUid, wrapper.Term.Uid, "RootTermUid"); } [TestMethod] [DoNotParallelize] public async Task Test019_Should_Fetch_Term_Async() { + TestOutputLogger.LogContext("TestScenario", "Test019_Should_Fetch_Term_Async"); + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); + TestOutputLogger.LogContext("RootTermUid", _rootTermUid ?? ""); ContentstackResponse response = await _stack.Taxonomy(_taxonomyUid).Terms(_rootTermUid).FetchAsync(); - Assert.IsTrue(response.IsSuccessStatusCode, $"FetchAsync term failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"FetchAsync term failed: {response.OpenResponse()}", "FetchAsyncTermSuccess"); var wrapper = response.OpenTResponse(); - Assert.IsNotNull(wrapper?.Term); - Assert.AreEqual(_rootTermUid, wrapper.Term.Uid); + AssertLogger.IsNotNull(wrapper?.Term, "Term in response"); + AssertLogger.AreEqual(_rootTermUid, wrapper.Term.Uid, "RootTermUid"); } [TestMethod] [DoNotParallelize] public void Test020_Should_Query_Terms() { + TestOutputLogger.LogContext("TestScenario", "Test020_Should_Query_Terms"); + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); ContentstackResponse response = _stack.Taxonomy(_taxonomyUid).Terms().Query().Find(); - Assert.IsTrue(response.IsSuccessStatusCode, $"Query terms failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Query terms failed: {response.OpenResponse()}", "QueryTermsSuccess"); var wrapper = response.OpenTResponse(); - Assert.IsNotNull(wrapper?.Terms); - Assert.IsTrue(wrapper.Terms.Count >= 0); + AssertLogger.IsNotNull(wrapper?.Terms, "Terms in response"); + AssertLogger.IsTrue(wrapper.Terms.Count >= 0, "Terms count", "TermsCount"); } [TestMethod] [DoNotParallelize] public async Task Test021_Should_Query_Terms_Async() { + TestOutputLogger.LogContext("TestScenario", "Test021_Should_Query_Terms_Async"); + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); ContentstackResponse response = await _stack.Taxonomy(_taxonomyUid).Terms().Query().FindAsync(); - Assert.IsTrue(response.IsSuccessStatusCode, $"Query terms Async failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Query terms Async failed: {response.OpenResponse()}", "QueryTermsAsyncSuccess"); var wrapper = response.OpenTResponse(); - Assert.IsNotNull(wrapper?.Terms); - Assert.IsTrue(wrapper.Terms.Count >= 0); + AssertLogger.IsNotNull(wrapper?.Terms, "Terms in response"); + AssertLogger.IsTrue(wrapper.Terms.Count >= 0, "Terms count", "TermsCount"); } [TestMethod] [DoNotParallelize] public void Test022_Should_Update_Term() { + TestOutputLogger.LogContext("TestScenario", "Test022_Should_Update_Term"); + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); + TestOutputLogger.LogContext("RootTermUid", _rootTermUid ?? ""); var updateModel = new TermModel { Name = "Root Term Updated", ParentUid = null }; ContentstackResponse response = _stack.Taxonomy(_taxonomyUid).Terms(_rootTermUid).Update(updateModel); - Assert.IsTrue(response.IsSuccessStatusCode, $"Update term failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Update term failed: {response.OpenResponse()}", "UpdateTermSuccess"); var wrapper = response.OpenTResponse(); - Assert.IsNotNull(wrapper?.Term); - Assert.AreEqual("Root Term Updated", wrapper.Term.Name); + AssertLogger.IsNotNull(wrapper?.Term, "Term in response"); + AssertLogger.AreEqual("Root Term Updated", wrapper.Term.Name, "UpdatedTermName"); } [TestMethod] [DoNotParallelize] public async Task Test023_Should_Update_Term_Async() { + TestOutputLogger.LogContext("TestScenario", "Test023_Should_Update_Term_Async"); + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); + TestOutputLogger.LogContext("RootTermUid", _rootTermUid ?? ""); var updateModel = new TermModel { Name = "Root Term Updated Async", ParentUid = null }; ContentstackResponse response = await _stack.Taxonomy(_taxonomyUid).Terms(_rootTermUid).UpdateAsync(updateModel); - Assert.IsTrue(response.IsSuccessStatusCode, $"UpdateAsync term failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"UpdateAsync term failed: {response.OpenResponse()}", "UpdateAsyncTermSuccess"); var wrapper = response.OpenTResponse(); - Assert.IsNotNull(wrapper?.Term); - Assert.AreEqual("Root Term Updated Async", wrapper.Term.Name); + AssertLogger.IsNotNull(wrapper?.Term, "Term in response"); + AssertLogger.AreEqual("Root Term Updated Async", wrapper.Term.Name, "UpdatedAsyncTermName"); } [TestMethod] [DoNotParallelize] public void Test024_Should_Get_Term_Ancestors() { + TestOutputLogger.LogContext("TestScenario", "Test024_Should_Get_Term_Ancestors"); + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); + TestOutputLogger.LogContext("ChildTermUid", _childTermUid ?? ""); ContentstackResponse response = _stack.Taxonomy(_taxonomyUid).Terms(_childTermUid).Ancestors(); - Assert.IsTrue(response.IsSuccessStatusCode, $"Ancestors failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Ancestors failed: {response.OpenResponse()}", "AncestorsSuccess"); var jobj = response.OpenJObjectResponse(); - Assert.IsNotNull(jobj); + AssertLogger.IsNotNull(jobj, "Ancestors response"); } [TestMethod] [DoNotParallelize] public async Task Test025_Should_Get_Term_Ancestors_Async() { + TestOutputLogger.LogContext("TestScenario", "Test025_Should_Get_Term_Ancestors_Async"); + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); + TestOutputLogger.LogContext("ChildTermUid", _childTermUid ?? ""); ContentstackResponse response = await _stack.Taxonomy(_taxonomyUid).Terms(_childTermUid).AncestorsAsync(); - Assert.IsTrue(response.IsSuccessStatusCode, $"AncestorsAsync failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"AncestorsAsync failed: {response.OpenResponse()}", "AncestorsAsyncSuccess"); var jobj = response.OpenJObjectResponse(); - Assert.IsNotNull(jobj); + AssertLogger.IsNotNull(jobj, "Ancestors async response"); } [TestMethod] [DoNotParallelize] public void Test026_Should_Get_Term_Descendants() { + TestOutputLogger.LogContext("TestScenario", "Test026_Should_Get_Term_Descendants"); + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); + TestOutputLogger.LogContext("RootTermUid", _rootTermUid ?? ""); ContentstackResponse response = _stack.Taxonomy(_taxonomyUid).Terms(_rootTermUid).Descendants(); - Assert.IsTrue(response.IsSuccessStatusCode, $"Descendants failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Descendants failed: {response.OpenResponse()}", "DescendantsSuccess"); var jobj = response.OpenJObjectResponse(); - Assert.IsNotNull(jobj); + AssertLogger.IsNotNull(jobj, "Descendants response"); } [TestMethod] [DoNotParallelize] public async Task Test027_Should_Get_Term_Descendants_Async() { + TestOutputLogger.LogContext("TestScenario", "Test027_Should_Get_Term_Descendants_Async"); + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); + TestOutputLogger.LogContext("RootTermUid", _rootTermUid ?? ""); ContentstackResponse response = await _stack.Taxonomy(_taxonomyUid).Terms(_rootTermUid).DescendantsAsync(); - Assert.IsTrue(response.IsSuccessStatusCode, $"DescendantsAsync failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"DescendantsAsync failed: {response.OpenResponse()}", "DescendantsAsyncSuccess"); var jobj = response.OpenJObjectResponse(); - Assert.IsNotNull(jobj); + AssertLogger.IsNotNull(jobj, "Descendants async response"); } [TestMethod] [DoNotParallelize] public void Test028_Should_Get_Term_Locales() { + TestOutputLogger.LogContext("TestScenario", "Test028_Should_Get_Term_Locales"); + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); + TestOutputLogger.LogContext("RootTermUid", _rootTermUid ?? ""); ContentstackResponse response = _stack.Taxonomy(_taxonomyUid).Terms(_rootTermUid).Locales(); - Assert.IsTrue(response.IsSuccessStatusCode, $"Term Locales failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Term Locales failed: {response.OpenResponse()}", "TermLocalesSuccess"); var jobj = response.OpenJObjectResponse(); - Assert.IsNotNull(jobj["terms"]); + AssertLogger.IsNotNull(jobj["terms"], "Terms in locales response"); } [TestMethod] [DoNotParallelize] public async Task Test029_Should_Get_Term_Locales_Async() { + TestOutputLogger.LogContext("TestScenario", "Test029_Should_Get_Term_Locales_Async"); + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); + TestOutputLogger.LogContext("RootTermUid", _rootTermUid ?? ""); ContentstackResponse response = await _stack.Taxonomy(_taxonomyUid).Terms(_rootTermUid).LocalesAsync(); - Assert.IsTrue(response.IsSuccessStatusCode, $"Term LocalesAsync failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Term LocalesAsync failed: {response.OpenResponse()}", "TermLocalesAsyncSuccess"); var jobj = response.OpenJObjectResponse(); - Assert.IsNotNull(jobj["terms"]); + AssertLogger.IsNotNull(jobj["terms"], "Terms in locales async response"); } [TestMethod] [DoNotParallelize] public void Test030_Should_Localize_Term() { + TestOutputLogger.LogContext("TestScenario", "Test030_Should_Localize_Term"); if (string.IsNullOrEmpty(_testLocaleCode)) { - Assert.Inconclusive("No non-master locale available."); + AssertLogger.Inconclusive("No non-master locale available."); return; } + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); + TestOutputLogger.LogContext("RootTermUid", _rootTermUid ?? ""); + TestOutputLogger.LogContext("TestLocaleCode", _testLocaleCode ?? ""); var localizeModel = new TermModel { Uid = _rootTermUid, @@ -487,102 +622,113 @@ public void Test030_Should_Localize_Term() var coll = new ParameterCollection(); coll.Add("locale", _testLocaleCode); ContentstackResponse response = _stack.Taxonomy(_taxonomyUid).Terms(_rootTermUid).Localize(localizeModel, coll); - Assert.IsTrue(response.IsSuccessStatusCode, $"Term Localize failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Term Localize failed: {response.OpenResponse()}", "TermLocalizeSuccess"); + var wrapper = response.OpenTResponse(); + AssertLogger.IsNotNull(wrapper?.Term, "Term in response"); + } + + [TestMethod] + [DoNotParallelize] + public async Task Test031_Should_Localize_Term_Async() + { + TestOutputLogger.LogContext("TestScenario", "Test031_Should_Localize_Term_Async"); + if (string.IsNullOrEmpty(_asyncTestLocaleCode)) + { + AssertLogger.Inconclusive("No second non-master locale available."); + return; + } + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); + TestOutputLogger.LogContext("RootTermUid", _rootTermUid ?? ""); + TestOutputLogger.LogContext("AsyncTestLocaleCode", _asyncTestLocaleCode ?? ""); + var localizeModel = new TermModel + { + Uid = _rootTermUid, + Name = "Root Term Localized Async", + ParentUid = null + }; + var coll = new ParameterCollection(); + coll.Add("locale", _asyncTestLocaleCode); + ContentstackResponse response = await _stack.Taxonomy(_taxonomyUid).Terms(_rootTermUid).LocalizeAsync(localizeModel, coll); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Term LocalizeAsync failed: {response.OpenResponse()}", "TermLocalizeAsyncSuccess"); var wrapper = response.OpenTResponse(); - Assert.IsNotNull(wrapper?.Term); + AssertLogger.IsNotNull(wrapper?.Term, "Term in response"); } [TestMethod] [DoNotParallelize] public void Test032_Should_Move_Term() { + TestOutputLogger.LogContext("TestScenario", "Test032_Should_Move_Term"); + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); + TestOutputLogger.LogContext("ChildTermUid", _childTermUid ?? ""); + TestOutputLogger.LogContext("RootTermUid", _rootTermUid ?? ""); var moveModel = new TermMoveModel { ParentUid = _rootTermUid, - Order = 0 + Order = 1 }; - ContentstackResponse response = null; - try - { - response = _stack.Taxonomy(_taxonomyUid).Terms(_childTermUid).Move(moveModel, null); - } - catch (ContentstackErrorException) - { - try - { - var coll = new ParameterCollection(); - coll.Add("force", true); - response = _stack.Taxonomy(_taxonomyUid).Terms(_childTermUid).Move(moveModel, coll); - } - catch (ContentstackErrorException ex) - { - Assert.Inconclusive("Move term failed: {0}", ex.Message); - return; - } - } - Assert.IsTrue(response.IsSuccessStatusCode, $"Move term failed: {response.OpenResponse()}"); + var coll = new ParameterCollection(); + coll.Add("force", true); + ContentstackResponse response = _stack.Taxonomy(_taxonomyUid).Terms(_childTermUid).Move(moveModel, coll); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Move term failed: {response.OpenResponse()}", "MoveTermSuccess"); var wrapper = response.OpenTResponse(); - Assert.IsNotNull(wrapper?.Term); + AssertLogger.IsNotNull(wrapper?.Term, "Term in response"); } [TestMethod] [DoNotParallelize] public async Task Test033_Should_Move_Term_Async() { + TestOutputLogger.LogContext("TestScenario", "Test033_Should_Move_Term_Async"); + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); + TestOutputLogger.LogContext("ChildTermUid", _childTermUid ?? ""); + TestOutputLogger.LogContext("RootTermUid", _rootTermUid ?? ""); var moveModel = new TermMoveModel { ParentUid = _rootTermUid, Order = 1 }; - ContentstackResponse response = null; - try - { - response = await _stack.Taxonomy(_taxonomyUid).Terms(_childTermUid).MoveAsync(moveModel, null); - } - catch (ContentstackErrorException) - { - try - { - var coll = new ParameterCollection(); - coll.Add("force", true); - response = await _stack.Taxonomy(_taxonomyUid).Terms(_childTermUid).MoveAsync(moveModel, coll); - } - catch (ContentstackErrorException ex) - { - Assert.Inconclusive("Move term failed: {0}", ex.Message); - return; - } - } - Assert.IsTrue(response.IsSuccessStatusCode, $"MoveAsync term failed: {response.OpenResponse()}"); + var coll = new ParameterCollection(); + coll.Add("force", true); + ContentstackResponse response = await _stack.Taxonomy(_taxonomyUid).Terms(_childTermUid).MoveAsync(moveModel, coll); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"MoveAsync term failed: {response.OpenResponse()}", "MoveAsyncTermSuccess"); var wrapper = response.OpenTResponse(); - Assert.IsNotNull(wrapper?.Term); + AssertLogger.IsNotNull(wrapper?.Term, "Term in response"); } [TestMethod] [DoNotParallelize] public void Test034_Should_Search_Terms() { + TestOutputLogger.LogContext("TestScenario", "Test034_Should_Search_Terms"); + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); ContentstackResponse response = _stack.Taxonomy(_taxonomyUid).Terms().Search("Root"); - Assert.IsTrue(response.IsSuccessStatusCode, $"Search terms failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Search terms failed: {response.OpenResponse()}", "SearchTermsSuccess"); var jobj = response.OpenJObjectResponse(); - Assert.IsNotNull(jobj["terms"] ?? jobj["items"]); + AssertLogger.IsNotNull(jobj["terms"] ?? jobj["items"], "Terms or items in search response"); } [TestMethod] [DoNotParallelize] public async Task Test035_Should_Search_Terms_Async() { + TestOutputLogger.LogContext("TestScenario", "Test035_Should_Search_Terms_Async"); + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); ContentstackResponse response = await _stack.Taxonomy(_taxonomyUid).Terms().SearchAsync("Root"); - Assert.IsTrue(response.IsSuccessStatusCode, $"SearchAsync terms failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"SearchAsync terms failed: {response.OpenResponse()}", "SearchAsyncTermsSuccess"); var jobj = response.OpenJObjectResponse(); - Assert.IsNotNull(jobj["terms"] ?? jobj["items"]); + AssertLogger.IsNotNull(jobj["terms"] ?? jobj["items"], "Terms or items in search async response"); } [TestMethod] [DoNotParallelize] public void Test036_Should_Create_Term_Async() { + TestOutputLogger.LogContext("TestScenario", "Test036_Should_Create_Term_Async"); + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); + TestOutputLogger.LogContext("RootTermUid", _rootTermUid ?? ""); string termUid = "term_async_" + Guid.NewGuid().ToString("N").Substring(0, 8); + TestOutputLogger.LogContext("AsyncTermUid", termUid); var termModel = new TermModel { Uid = termUid, @@ -590,9 +736,9 @@ public void Test036_Should_Create_Term_Async() ParentUid = _rootTermUid }; ContentstackResponse response = _stack.Taxonomy(_taxonomyUid).Terms().CreateAsync(termModel).GetAwaiter().GetResult(); - Assert.IsTrue(response.IsSuccessStatusCode, $"CreateAsync term failed: {response.OpenResponse()}"); + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"CreateAsync term failed: {response.OpenResponse()}", "CreateAsyncTermSuccess"); var wrapper = response.OpenTResponse(); - Assert.IsNotNull(wrapper?.Term); + AssertLogger.IsNotNull(wrapper?.Term, "Term in response"); _createdTermUids.Add(termUid); } @@ -600,56 +746,65 @@ public void Test036_Should_Create_Term_Async() [DoNotParallelize] public void Test037_Should_Throw_When_Update_NonExistent_Taxonomy() { + TestOutputLogger.LogContext("TestScenario", "Test037_Should_Throw_When_Update_NonExistent_Taxonomy"); var updateModel = new TaxonomyModel { Name = "No", Description = "No" }; - Assert.ThrowsException(() => - _stack.Taxonomy("non_existent_taxonomy_uid_12345").Update(updateModel)); + AssertLogger.ThrowsException(() => + _stack.Taxonomy("non_existent_taxonomy_uid_12345").Update(updateModel), "UpdateNonExistentTaxonomy"); } [TestMethod] [DoNotParallelize] public void Test038_Should_Throw_When_Fetch_NonExistent_Taxonomy() { - Assert.ThrowsException(() => - _stack.Taxonomy("non_existent_taxonomy_uid_12345").Fetch()); + TestOutputLogger.LogContext("TestScenario", "Test038_Should_Throw_When_Fetch_NonExistent_Taxonomy"); + AssertLogger.ThrowsException(() => + _stack.Taxonomy("non_existent_taxonomy_uid_12345").Fetch(), "FetchNonExistentTaxonomy"); } [TestMethod] [DoNotParallelize] public void Test039_Should_Throw_When_Delete_NonExistent_Taxonomy() { - Assert.ThrowsException(() => - _stack.Taxonomy("non_existent_taxonomy_uid_12345").Delete()); + TestOutputLogger.LogContext("TestScenario", "Test039_Should_Throw_When_Delete_NonExistent_Taxonomy"); + AssertLogger.ThrowsException(() => + _stack.Taxonomy("non_existent_taxonomy_uid_12345").Delete(), "DeleteNonExistentTaxonomy"); } [TestMethod] [DoNotParallelize] public void Test040_Should_Throw_When_Fetch_NonExistent_Term() { - Assert.ThrowsException(() => - _stack.Taxonomy(_taxonomyUid).Terms("non_existent_term_uid_12345").Fetch()); + TestOutputLogger.LogContext("TestScenario", "Test040_Should_Throw_When_Fetch_NonExistent_Term"); + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); + AssertLogger.ThrowsException(() => + _stack.Taxonomy(_taxonomyUid).Terms("non_existent_term_uid_12345").Fetch(), "FetchNonExistentTerm"); } [TestMethod] [DoNotParallelize] public void Test041_Should_Throw_When_Update_NonExistent_Term() { + TestOutputLogger.LogContext("TestScenario", "Test041_Should_Throw_When_Update_NonExistent_Term"); + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); var updateModel = new TermModel { Name = "No", ParentUid = null }; - Assert.ThrowsException(() => - _stack.Taxonomy(_taxonomyUid).Terms("non_existent_term_uid_12345").Update(updateModel)); + AssertLogger.ThrowsException(() => + _stack.Taxonomy(_taxonomyUid).Terms("non_existent_term_uid_12345").Update(updateModel), "UpdateNonExistentTerm"); } [TestMethod] [DoNotParallelize] public void Test042_Should_Throw_When_Delete_NonExistent_Term() { - Assert.ThrowsException(() => - _stack.Taxonomy(_taxonomyUid).Terms("non_existent_term_uid_12345").Delete()); + TestOutputLogger.LogContext("TestScenario", "Test042_Should_Throw_When_Delete_NonExistent_Term"); + TestOutputLogger.LogContext("TaxonomyUid", _taxonomyUid ?? ""); + AssertLogger.ThrowsException(() => + _stack.Taxonomy(_taxonomyUid).Terms("non_existent_term_uid_12345").Delete(), "DeleteNonExistentTerm"); } private static Stack GetStack() { - StackResponse response = StackResponse.getStack(Contentstack.Client.serializer); - return Contentstack.Client.Stack(response.Stack.APIKey); + StackResponse response = StackResponse.getStack(_client.serializer); + return _client.Stack(response.Stack.APIKey); } [ClassCleanup] @@ -722,6 +877,19 @@ public static void Cleanup() } } + if (_weCreatedAsyncTestLocale && !string.IsNullOrEmpty(_asyncTestLocaleCode)) + { + try + { + stack.Locale(_asyncTestLocaleCode).Delete(); + Console.WriteLine($"[Cleanup] Deleted async test locale: {_asyncTestLocaleCode}"); + } + catch (Exception ex) + { + Console.WriteLine($"[Cleanup] Failed to delete async test locale {_asyncTestLocaleCode}: {ex.Message}"); + } + } + if (_weCreatedTestLocale && !string.IsNullOrEmpty(_testLocaleCode)) { try @@ -739,6 +907,9 @@ public static void Cleanup() { Console.WriteLine($"[Cleanup] Cleanup failed: {ex.Message}"); } + + try { _client?.Logout(); } catch { } + _client = null; } } } diff --git a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack999_LogoutTest.cs b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack999_LogoutTest.cs index 8411323..538387b 100644 --- a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack999_LogoutTest.cs +++ b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack999_LogoutTest.cs @@ -1,4 +1,6 @@ -using System; +using System; +using System.Net.Http; +using Contentstack.Management.Core.Tests.Helpers; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Contentstack.Management.Core.Tests.IntegrationTest @@ -6,22 +8,75 @@ namespace Contentstack.Management.Core.Tests.IntegrationTest [TestClass] public class Contentstack999_LogoutTest { + private static ContentstackClient CreateClientWithLogging() + { + var handler = new LoggingHttpHandler(); + var httpClient = new HttpClient(handler); + return new ContentstackClient(httpClient, new ContentstackClientOptions()); + } + [TestMethod] [DoNotParallelize] - public void Test001_Should_Return_Success_On_Logout() + public void Test001_Should_Return_Success_On_Sync_Logout() { + TestOutputLogger.LogContext("TestScenario", "SyncLogout"); try { - ContentstackClient client = Contentstack.Client; + ContentstackClient client = Contentstack.CreateAuthenticatedClient(); + AssertLogger.IsNotNull(client.contentstackOptions.Authtoken, "AuthtokenBeforeLogout"); + ContentstackResponse contentstackResponse = client.Logout(); string loginResponse = contentstackResponse.OpenResponse(); - Assert.IsNull(client.contentstackOptions.Authtoken); - Assert.IsNotNull(loginResponse); + AssertLogger.IsNull(client.contentstackOptions.Authtoken, "AuthtokenAfterLogout"); + AssertLogger.IsNotNull(loginResponse, "LogoutResponse"); + } + catch (Exception e) + { + AssertLogger.Fail(e.Message); + } + } + + [TestMethod] + [DoNotParallelize] + public async System.Threading.Tasks.Task Test002_Should_Return_Success_On_Async_Logout() + { + TestOutputLogger.LogContext("TestScenario", "AsyncLogout"); + try + { + ContentstackClient client = Contentstack.CreateAuthenticatedClient(); + AssertLogger.IsNotNull(client.contentstackOptions.Authtoken, "AuthtokenBeforeLogout"); + + ContentstackResponse contentstackResponse = await client.LogoutAsync(); + string logoutResponse = contentstackResponse.OpenResponse(); + + AssertLogger.IsNull(client.contentstackOptions.Authtoken, "AuthtokenAfterLogout"); + AssertLogger.IsNotNull(logoutResponse, "LogoutResponse"); + } + catch (Exception e) + { + AssertLogger.Fail(e.Message); + } + } + + [TestMethod] + [DoNotParallelize] + public void Test003_Should_Handle_Logout_When_Not_LoggedIn() + { + TestOutputLogger.LogContext("TestScenario", "LogoutWhenNotLoggedIn"); + ContentstackClient client = CreateClientWithLogging(); + + AssertLogger.IsNull(client.contentstackOptions.Authtoken, "AuthtokenNotSet"); + + try + { + client.Logout(); } catch (Exception e) { - Assert.Fail(e.Message); + AssertLogger.IsTrue( + e.Message.Contains("token") || e.Message.Contains("Authentication") || e.Message.Contains("not logged in"), + "LogoutNotLoggedInError"); } } } diff --git a/Scripts/generate_integration_test_report.py b/Scripts/generate_integration_test_report.py new file mode 100644 index 0000000..f97cb95 --- /dev/null +++ b/Scripts/generate_integration_test_report.py @@ -0,0 +1,924 @@ +#!/usr/bin/env python3 +""" +Integration Test Report Generator for .NET CMA SDK +Parses TRX (results) + Cobertura (coverage) + Structured StdOut (HTTP, assertions, context) +into a single interactive HTML report. +No external dependencies — uses only Python standard library. +""" + +import xml.etree.ElementTree as ET +import os +import sys +import re +import json +import argparse +from datetime import datetime + + +class IntegrationTestReportGenerator: + def __init__(self, trx_path, coverage_path=None): + self.trx_path = trx_path + self.coverage_path = coverage_path + self.results = { + 'total': 0, + 'passed': 0, + 'failed': 0, + 'skipped': 0, + 'duration_seconds': 0, + 'tests': [] + } + self.coverage = { + 'lines_pct': 0, + 'branches_pct': 0, + 'statements_pct': 0, + 'functions_pct': 0 + } + self.file_coverage = [] + + # ──────────────────── TRX PARSING ──────────────────── + + def parse_trx(self): + tree = ET.parse(self.trx_path) + root = tree.getroot() + ns = {'t': 'http://microsoft.com/schemas/VisualStudio/TeamTest/2010'} + + counters = root.find('.//t:ResultSummary/t:Counters', ns) + if counters is not None: + self.results['total'] = int(counters.get('total', 0)) + self.results['passed'] = int(counters.get('passed', 0)) + self.results['failed'] = int(counters.get('failed', 0)) + self.results['skipped'] = int(counters.get('notExecuted', 0)) + + times = root.find('.//t:Times', ns) + if times is not None: + try: + start = times.get('start', '') + finish = times.get('finish', '') + if start and finish: + fmt = '%Y-%m-%dT%H:%M:%S.%f' + s = start.split('+')[0].split('-')[0:3] + start_clean = re.sub(r'[+-]\d{2}:\d{2}$', '', start) + finish_clean = re.sub(r'[+-]\d{2}:\d{2}$', '', finish) + for fmt_try in ['%Y-%m-%dT%H:%M:%S.%f', '%Y-%m-%dT%H:%M:%S']: + try: + dt_start = datetime.strptime(start_clean, fmt_try) + dt_finish = datetime.strptime(finish_clean, fmt_try) + self.results['duration_seconds'] = (dt_finish - dt_start).total_seconds() + break + except ValueError: + continue + except Exception: + pass + + integration_total = 0 + integration_passed = 0 + integration_failed = 0 + integration_skipped = 0 + + for result in root.findall('.//t:UnitTestResult', ns): + test_id = result.get('testId', '') + test_name = result.get('testName', '') + outcome = result.get('outcome', 'Unknown') + duration_str = result.get('duration', '0') + duration = self._parse_duration(duration_str) + + test_def = root.find(f".//t:UnitTest[@id='{test_id}']/t:TestMethod", ns) + class_name = test_def.get('className', '') if test_def is not None else '' + + if 'IntegrationTest' not in class_name: + continue + + parts = class_name.split(',')[0].rsplit('.', 1) + file_name = parts[-1] if len(parts) > 1 else class_name + + error_msg = error_trace = None + error_info = result.find('.//t:ErrorInfo', ns) + if error_info is not None: + msg_el = error_info.find('t:Message', ns) + stk_el = error_info.find('t:StackTrace', ns) + if msg_el is not None: + error_msg = msg_el.text + if stk_el is not None: + error_trace = stk_el.text + + structured = None + stdout_el = result.find('.//t:StdOut', ns) + if stdout_el is not None and stdout_el.text: + structured = self._parse_structured_output(stdout_el.text) + + integration_total += 1 + if outcome == 'Passed': + integration_passed += 1 + elif outcome == 'Failed': + integration_failed += 1 + elif outcome in ('NotExecuted', 'Inconclusive'): + integration_skipped += 1 + + self.results['tests'].append({ + 'name': test_name, + 'outcome': outcome, + 'duration': duration, + 'file': file_name, + 'error_message': error_msg, + 'error_stacktrace': error_trace, + 'structured': structured + }) + + self.results['total'] = integration_total + self.results['passed'] = integration_passed + self.results['failed'] = integration_failed + self.results['skipped'] = integration_skipped + + def _parse_duration(self, duration_str): + try: + parts = duration_str.split(':') + if len(parts) == 3: + h, m = int(parts[0]), int(parts[1]) + s = float(parts[2]) + total = h * 3600 + m * 60 + s + return f"{total:.2f}s" + except Exception: + pass + return duration_str + + # ──────────────────── COBERTURA PARSING ──────────────────── + + def parse_coverage(self): + if not self.coverage_path or not os.path.exists(self.coverage_path): + return + try: + tree = ET.parse(self.coverage_path) + root = tree.getroot() + self.coverage['lines_pct'] = float(root.get('line-rate', 0)) * 100 + self.coverage['branches_pct'] = float(root.get('branch-rate', 0)) * 100 + self.coverage['statements_pct'] = self.coverage['lines_pct'] + + total_methods = 0 + covered_methods = 0 + for method in root.iter('method'): + total_methods += 1 + lr = float(method.get('line-rate', 0)) + if lr > 0: + covered_methods += 1 + if total_methods > 0: + self.coverage['functions_pct'] = (covered_methods / total_methods) * 100 + + self._parse_file_coverage(root) + except Exception as e: + print(f"Warning: Could not parse coverage file: {e}") + + def _parse_file_coverage(self, root): + file_data = {} + for cls in root.iter('class'): + filename = cls.get('filename', '') + if not filename: + continue + + if filename not in file_data: + file_data[filename] = { + 'lines': {}, + 'branches_covered': 0, + 'branches_total': 0, + 'methods_total': 0, + 'methods_covered': 0, + } + + entry = file_data[filename] + + for method in cls.findall('methods/method'): + entry['methods_total'] += 1 + if float(method.get('line-rate', 0)) > 0: + entry['methods_covered'] += 1 + + for line in cls.iter('line'): + num = int(line.get('number', 0)) + hits = int(line.get('hits', 0)) + is_branch = line.get('branch', 'False').lower() == 'true' + + if num in entry['lines']: + entry['lines'][num]['hits'] = max(entry['lines'][num]['hits'], hits) + if is_branch: + entry['lines'][num]['is_branch'] = True + cond = line.get('condition-coverage', '') + covered, total = self._parse_condition_coverage(cond) + entry['lines'][num]['br_covered'] = max(entry['lines'][num].get('br_covered', 0), covered) + entry['lines'][num]['br_total'] = max(entry['lines'][num].get('br_total', 0), total) + else: + br_covered, br_total = 0, 0 + if is_branch: + cond = line.get('condition-coverage', '') + br_covered, br_total = self._parse_condition_coverage(cond) + entry['lines'][num] = { + 'hits': hits, + 'is_branch': is_branch, + 'br_covered': br_covered, + 'br_total': br_total, + } + + self.file_coverage = [] + for filename in sorted(file_data.keys()): + entry = file_data[filename] + lines_total = len(entry['lines']) + lines_covered = sum(1 for l in entry['lines'].values() if l['hits'] > 0) + uncovered = sorted(num for num, l in entry['lines'].items() if l['hits'] == 0) + + br_total = sum(l.get('br_total', 0) for l in entry['lines'].values() if l.get('is_branch')) + br_covered = sum(l.get('br_covered', 0) for l in entry['lines'].values() if l.get('is_branch')) + + self.file_coverage.append({ + 'filename': filename, + 'lines_pct': (lines_covered / lines_total * 100) if lines_total > 0 else 100, + 'statements_pct': (lines_covered / lines_total * 100) if lines_total > 0 else 100, + 'branches_pct': (br_covered / br_total * 100) if br_total > 0 else 100, + 'functions_pct': (entry['methods_covered'] / entry['methods_total'] * 100) if entry['methods_total'] > 0 else 100, + 'uncovered_lines': uncovered, + }) + + @staticmethod + def _parse_condition_coverage(cond_str): + m = re.match(r'(\d+)%\s*\((\d+)/(\d+)\)', cond_str) + if m: + return int(m.group(2)), int(m.group(3)) + return 0, 0 + + @staticmethod + def _collapse_line_ranges(lines): + if not lines: + return '' + ranges = [] + start = prev = lines[0] + for num in lines[1:]: + if num == prev + 1: + prev = num + else: + ranges.append(f"{start}-{prev}" if start != prev else str(start)) + start = prev = num + ranges.append(f"{start}-{prev}" if start != prev else str(start)) + return ','.join(ranges) + + # ──────────────────── STRUCTURED OUTPUT ──────────────────── + + def _parse_structured_output(self, text): + data = { + 'assertions': [], + 'requests': [], + 'responses': [], + 'context': [] + } + pattern = r'###TEST_OUTPUT_START###(.+?)###TEST_OUTPUT_END###' + for match in re.findall(pattern, text, re.DOTALL): + try: + obj = json.loads(match) + t = obj.get('type', '').upper() + if t == 'ASSERTION': + data['assertions'].append({ + 'name': obj.get('assertionName', ''), + 'expected': obj.get('expected', ''), + 'actual': obj.get('actual', ''), + 'passed': obj.get('passed', True) + }) + elif t == 'HTTP_REQUEST': + data['requests'].append({ + 'method': obj.get('method', ''), + 'url': obj.get('url', ''), + 'headers': obj.get('headers', {}), + 'body': obj.get('body', ''), + 'curl': obj.get('curlCommand', ''), + 'sdkMethod': obj.get('sdkMethod', '') + }) + elif t == 'HTTP_RESPONSE': + data['responses'].append({ + 'statusCode': obj.get('statusCode', 0), + 'statusText': obj.get('statusText', ''), + 'headers': obj.get('headers', {}), + 'body': obj.get('body', '') + }) + elif t == 'CONTEXT': + data['context'].append({ + 'key': obj.get('key', ''), + 'value': obj.get('value', '') + }) + except json.JSONDecodeError: + continue + return data + + # ──────────────────── HTML HELPERS ──────────────────── + + @staticmethod + def _esc(text): + if text is None: + return "" + text = str(text) + return (text + .replace('&', '&') + .replace('<', '<') + .replace('>', '>') + .replace('"', '"') + .replace("'", ''')) + + def _format_duration_display(self, seconds): + if seconds < 60: + return f"{seconds:.1f}s" + elif seconds < 3600: + m = int(seconds // 60) + s = seconds % 60 + return f"{m}m {s:.0f}s" + else: + h = int(seconds // 3600) + m = int((seconds % 3600) // 60) + return f"{h}h {m}m" + + # ──────────────────── HTML GENERATION ──────────────────── + + def generate_html(self, output_path): + pass_rate = (self.results['passed'] / self.results['total'] * 100) if self.results['total'] > 0 else 0 + duration_display = self._format_duration_display(self.results['duration_seconds']) + + by_file = {} + for test in self.results['tests']: + by_file.setdefault(test['file'], []).append(test) + + html = self._html_head() + html += self._html_header(pass_rate) + html += self._html_kpi_bar(duration_display) + html += self._html_pass_rate(pass_rate) + html += self._html_coverage_table() + html += self._html_test_navigation(by_file) + html += self._html_file_coverage_table() + html += self._html_footer() + html += self._html_scripts() + html += "" + + with open(output_path, 'w', encoding='utf-8') as f: + f.write(html) + return output_path + + def _html_head(self): + return f""" + + + + + .NET CMA SDK - Integration Test Report + + + +
+""" + + def _html_header(self, pass_rate): + now = datetime.now().strftime('%B %d, %Y at %I:%M %p') + return f""" +
+

Integration Test Results

+

.NET CMA SDK — {now}

+
+""" + + def _html_kpi_bar(self, duration_display): + r = self.results + return f""" +
+
{r['total']}
Total Tests
+
{r['passed']}
Passed
+
{r['failed']}
Failed
+
{r['skipped']}
Skipped
+
{duration_display}
Duration
+
+""" + + def _html_pass_rate(self, pass_rate): + return f""" +
+

Pass Rate

+
+
{pass_rate:.1f}%
+
+
+""" + + def _html_coverage_table(self): + c = self.coverage + if c['lines_pct'] == 0 and c['branches_pct'] == 0: + return "" + + def cov_class(pct): + if pct >= 80: return 'cov-good' + if pct >= 50: return 'cov-warn' + return 'cov-bad' + + return f""" +
+

Global Code Coverage

+ + + + + + + + + + +
StatementsBranchesFunctionsLines
{c['statements_pct']:.1f}%{c['branches_pct']:.1f}%{c['functions_pct']:.1f}%{c['lines_pct']:.1f}%
+
+""" + + def _html_file_coverage_table(self): + if not self.file_coverage: + return "" + + def cov_class(pct): + if pct >= 80: return 'cov-good' + if pct >= 50: return 'cov-warn' + return 'cov-bad' + + c = self.coverage + html = """ +
+

File-wise Code Coverage

+ + + + + + + +""" + html += f""" + + + + + + + +""" + + for fc in self.file_coverage: + uncovered = fc['uncovered_lines'] + if len(uncovered) == 0: + uncov_str = '' + elif len(uncovered) == 1: + uncov_str = str(uncovered[0]) + else: + uncov_str = f"{uncovered[0]}-{uncovered[-1]}" + display_name = fc['filename'] + parts = display_name.replace('\\', '/').rsplit('/', 1) + if len(parts) == 2: + dir_part, base = parts + display_name = f'{self._esc(dir_part)}/{self._esc(base)}' + else: + display_name = self._esc(display_name) + + html += f""" + + + + + + + +""" + + html += """ +
File% Stmts% Branch% Funcs% LinesUncovered Line #s
All files{c['statements_pct']:.1f}%{c['branches_pct']:.1f}%{c['functions_pct']:.1f}%{c['lines_pct']:.1f}%
{display_name}{fc['statements_pct']:.1f}%{fc['branches_pct']:.1f}%{fc['functions_pct']:.1f}%{fc['lines_pct']:.1f}%{self._esc(uncov_str)}
+
+""" + return html + + def _html_test_navigation(self, by_file): + html = '

Test Results by Integration File

' + + for file_name in sorted(by_file.keys()): + tests = by_file[file_name] + passed = sum(1 for t in tests if t['outcome'] == 'Passed') + failed = sum(1 for t in tests if t['outcome'] == 'Failed') + skipped = sum(1 for t in tests if t['outcome'] in ('NotExecuted', 'Inconclusive')) + safe_id = re.sub(r'[^a-zA-Z0-9]', '_', file_name) + + html += f""" +
+
+
+ + {self._esc(file_name)} +
+
+ {passed} passed · + {failed} failed · + {skipped} skipped · + {len(tests)} total +
+
+
+ + + + + + + +""" + for idx, test in enumerate(tests): + status_cls = 'status-passed' if test['outcome'] == 'Passed' else 'status-failed' if test['outcome'] == 'Failed' else 'status-skipped' + icon = '✅' if test['outcome'] == 'Passed' else '❌' if test['outcome'] == 'Failed' else '⏭' + test_id = f"test-{safe_id}-{idx}" + + html += f""" + + + + + +""" + html += """ + +
Test NameStatusDuration
+
{icon} {self._esc(test['name'])}
+""" + detail = self._html_test_detail(test, test_id) + html += detail + html += f""" +
{test['outcome']}{test['duration']}
+
+
+""" + html += "
" + return html + + def _html_test_detail(self, test, test_id): + s = test.get('structured') + has_error = test['outcome'] == 'Failed' and (test.get('error_message') or test.get('error_stacktrace')) + has_structured = s and (s.get('assertions') or s.get('requests') or s.get('responses') or s.get('context')) + + if not has_error and not has_structured: + return "" + + html = f'
' + + if has_error: + html += '
' + if test.get('error_message'): + html += f'
Error:
{self._esc(test["error_message"])}
' + if test.get('error_stacktrace'): + html += f"""
Stack Trace +
{self._esc(test["error_stacktrace"])}
""" + html += '
' + + if not s: + html += '
' + return html + + if s.get('assertions'): + html += '

Assertions

' + for a in s['assertions']: + icon = '✅' if a.get('passed', True) else '❌' + row_cls = '' if a.get('passed', True) else 'a-failed' + html += f""" +
+
{icon}{self._esc(a['name'])}
+
+
Expected:
{self._esc(str(a['expected']))}
+
Actual:
{self._esc(str(a['actual']))}
+
+
""" + html += '
' + + requests = s.get('requests', []) + responses = s.get('responses', []) + pairs = max(len(requests), len(responses)) + if pairs > 0: + html += '

HTTP Transactions

' + for i in range(pairs): + req = requests[i] if i < len(requests) else None + res = responses[i] if i < len(responses) else None + + if req: + sdk_badge = '' + if req.get('sdkMethod'): + sdk_badge = f'
SDK Method: {self._esc(req["sdkMethod"])}
' + html += f""" +
+ {sdk_badge} +
{self._esc(req['method'])}{self._esc(req['url'])}
""" + if req.get('headers'): + hdr_text = '\n'.join(f"{k}: {v}" for k, v in req['headers'].items()) + html += f""" +
Request Headers
{self._esc(hdr_text)}
""" + if req.get('body'): + html += f""" +
Request Body
{self._esc(req['body'][:5000])}
""" + if req.get('curl'): + curl_id = f"curl-{test_id}-{i}" + html += f""" +
cURL Command +
{self._esc(req['curl'])}
+ +
""" + html += '
' + + if res: + sc = res.get('statusCode', 0) + status_cls = 'rs-success' if 200 <= sc < 300 else 'rs-error' + html += f""" +
+
{sc} {self._esc(res.get('statusText', ''))}
""" + if res.get('headers'): + hdr_text = '\n'.join(f"{k}: {v}" for k, v in res['headers'].items()) + html += f""" +
Response Headers
{self._esc(hdr_text)}
""" + if res.get('body'): + body_text = res['body'] + truncated = len(body_text) > 3000 + display_body = body_text[:3000] if truncated else body_text + try: + parsed = json.loads(display_body) + display_body = json.dumps(parsed, indent=2)[:3000] + except (json.JSONDecodeError, ValueError): + pass + body_id = f"resbody-{test_id}-{i}" + html += f""" +
Response Body +
{self._esc(display_body)}
""" + if truncated: + html += f'' + html += f'' + html += '
' + html += '
' + html += '
' + + if s.get('context'): + html += """ +
+ Test Context + """ + for ctx in s['context']: + html += f""" + + + + """ + html += '
{self._esc(ctx['key'])}{self._esc(str(ctx['value']))}
' + + html += '
' + return html + + def _html_footer(self): + now = datetime.now().strftime('%Y-%m-%d at %H:%M:%S') + return f""" + +""" + + def _html_scripts(self): + return """ + +""" + + +def main(): + parser = argparse.ArgumentParser(description='Integration Test Report Generator for .NET CMA SDK') + parser.add_argument('trx_file', help='Path to the .trx test results file') + parser.add_argument('--coverage', help='Path to coverage.cobertura.xml file', default=None) + parser.add_argument('--output', help='Output HTML file path', default=None) + args = parser.parse_args() + + if not os.path.exists(args.trx_file): + print(f"Error: TRX file not found: {args.trx_file}") + sys.exit(1) + + print("=" * 70) + print(" .NET CMA SDK - Integration Test Report Generator") + print("=" * 70) + + generator = IntegrationTestReportGenerator(args.trx_file, args.coverage) + + print(f"\nParsing TRX: {args.trx_file}") + generator.parse_trx() + print(f" Found {generator.results['total']} integration tests") + print(f" Passed: {generator.results['passed']}") + print(f" Failed: {generator.results['failed']}") + print(f" Skipped: {generator.results['skipped']}") + + if args.coverage: + print(f"\nParsing Coverage: {args.coverage}") + generator.parse_coverage() + c = generator.coverage + print(f" Lines: {c['lines_pct']:.1f}%") + print(f" Branches: {c['branches_pct']:.1f}%") + print(f" Functions: {c['functions_pct']:.1f}%") + + timestamp = datetime.now().strftime('%Y%m%d_%H%M%S') + output_file = args.output or f'integration-test-report_{timestamp}.html' + + print(f"\nGenerating HTML report...") + generator.generate_html(output_file) + + print(f"\n{'=' * 70}") + print(f" Report generated: {os.path.abspath(output_file)}") + print(f"{'=' * 70}") + print(f"\n open {os.path.abspath(output_file)}") + + +if __name__ == "__main__": + main() diff --git a/Scripts/run-integration-tests-with-report.sh b/Scripts/run-integration-tests-with-report.sh new file mode 100755 index 0000000..662e10f --- /dev/null +++ b/Scripts/run-integration-tests-with-report.sh @@ -0,0 +1,71 @@ +#!/bin/bash +set -e + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +TIMESTAMP=$(date +"%Y%m%d_%H%M%S") +TEST_PROJECT="Contentstack.Management.Core.Tests" + +echo "======================================================" +echo " CMA SDK — Integration Test Report Generator" +echo "======================================================" +echo "" +echo "Project: $PROJECT_ROOT" +echo "Run ID: $TIMESTAMP" +echo "" + +# Step 1: Run ONLY integration tests, collect TRX + coverage +TRX_FILE="IntegrationTest-Report-${TIMESTAMP}.trx" +echo "Step 1: Running integration tests..." +dotnet test "$PROJECT_ROOT/$TEST_PROJECT/$TEST_PROJECT.csproj" \ + --filter "FullyQualifiedName~IntegrationTest" \ + --logger "trx;LogFileName=$TRX_FILE" \ + --results-directory "$PROJECT_ROOT/$TEST_PROJECT/TestResults" \ + --collect:"XPlat code coverage" \ + --verbosity quiet || true + +echo "" +echo "Tests completed." +echo "" + +# Step 2: Locate the cobertura coverage file (most recent) +COBERTURA="" +if [ -d "$PROJECT_ROOT/$TEST_PROJECT/TestResults" ]; then + COBERTURA=$(find "$PROJECT_ROOT/$TEST_PROJECT/TestResults" \ + -name "coverage.cobertura.xml" 2>/dev/null | sort -r | head -1) +fi + +TRX_PATH="$PROJECT_ROOT/$TEST_PROJECT/TestResults/$TRX_FILE" +echo "TRX: $TRX_PATH" +echo "Coverage: ${COBERTURA:-Not found}" +echo "" + +# Step 3: Generate the HTML report +echo "Step 2: Generating HTML report..." +cd "$PROJECT_ROOT" + +COVERAGE_ARG="" +if [ -n "$COBERTURA" ]; then + COVERAGE_ARG="--coverage $COBERTURA" +fi + +OUTPUT_FILE="$PROJECT_ROOT/integration-test-report_${TIMESTAMP}.html" + +python3 "$PROJECT_ROOT/Scripts/generate_integration_test_report.py" \ + "$TRX_PATH" \ + $COVERAGE_ARG \ + --output "$OUTPUT_FILE" + +echo "" +echo "======================================================" +echo " All Done!" +echo "======================================================" +echo "" +if [ -f "$OUTPUT_FILE" ]; then + echo "Report: $OUTPUT_FILE" + echo "" + echo "To open: open $OUTPUT_FILE" +else + echo "Warning: Report file not found. Check output above for errors." +fi +echo ""