55using Contentstack . Management . Core . Models ;
66using Contentstack . Management . Core . Tests . Helpers ;
77using Microsoft . VisualStudio . TestTools . UnitTesting ;
8- using Microsoft . Extensions . Configuration ;
9- using Microsoft . Extensions . Options ;
10- using System . Threading ;
118using Contentstack . Management . Core . Queryable ;
129using Newtonsoft . Json . Linq ;
1310
@@ -16,7 +13,6 @@ namespace Contentstack.Management.Core.Tests.IntegrationTest
1613 [ TestClass ]
1714 public class Contentstack001_LoginTest
1815 {
19- private readonly IConfigurationRoot _configuration = new ConfigurationBuilder ( ) . AddJsonFile ( "appsettings.json" ) . Build ( ) ;
2016
2117 private static ContentstackClient CreateClientWithLogging ( )
2218 {
@@ -48,25 +44,24 @@ public void Test001_Should_Return_Failuer_On_Wrong_Login_Credentials()
4844
4945 [ TestMethod ]
5046 [ DoNotParallelize ]
51- public void Test002_Should_Return_Failuer_On_Wrong_Async_Login_Credentials ( )
47+ public async System . Threading . Tasks . Task Test002_Should_Return_Failuer_On_Wrong_Async_Login_Credentials ( )
5248 {
5349 TestOutputLogger . LogContext ( "TestScenario" , "WrongCredentialsAsync" ) ;
5450 ContentstackClient client = CreateClientWithLogging ( ) ;
5551 NetworkCredential credentials = new NetworkCredential ( "mock_user" , "mock_pasword" ) ;
56- var response = client . LoginAsync ( credentials ) ;
57-
58- response . ContinueWith ( ( t ) =>
59- {
60- if ( t . IsCompleted && t . Status == System . Threading . Tasks . TaskStatus . Faulted )
61- {
62- ContentstackErrorException errorException = t . Exception . InnerException as ContentstackErrorException ;
63- AssertLogger . AreEqual ( HttpStatusCode . UnprocessableEntity , errorException . StatusCode , "StatusCode" ) ;
64- AssertLogger . AreEqual ( "Looks like your email or password is invalid. Please try again or reset your password." , errorException . Message , "Message" ) ;
65- AssertLogger . AreEqual ( "Looks like your email or password is invalid. Please try again or reset your password." , errorException . ErrorMessage , "ErrorMessage" ) ;
66- AssertLogger . AreEqual ( 104 , errorException . ErrorCode , "ErrorCode" ) ;
67- }
68- } ) ;
69- Thread . Sleep ( 3000 ) ;
52+
53+ try
54+ {
55+ await client . LoginAsync ( credentials ) ;
56+ AssertLogger . Fail ( "Expected exception for wrong credentials" ) ;
57+ }
58+ catch ( ContentstackErrorException errorException )
59+ {
60+ AssertLogger . AreEqual ( HttpStatusCode . UnprocessableEntity , errorException . StatusCode , "StatusCode" ) ;
61+ AssertLogger . AreEqual ( "Looks like your email or password is invalid. Please try again or reset your password." , errorException . Message , "Message" ) ;
62+ AssertLogger . AreEqual ( "Looks like your email or password is invalid. Please try again or reset your password." , errorException . ErrorMessage , "ErrorMessage" ) ;
63+ AssertLogger . AreEqual ( 104 , errorException . ErrorCode , "ErrorCode" ) ;
64+ }
7065 }
7166
7267 [ TestMethod ]
@@ -304,5 +299,198 @@ public void Test011_Should_Prefer_Explicit_Token_Over_MfaSecret()
304299 AssertLogger . Fail ( $ "Unexpected exception type: { e . GetType ( ) . Name } - { e . Message } ") ;
305300 }
306301 }
302+
303+ [ TestMethod ]
304+ [ DoNotParallelize ]
305+ public void Test012_Should_Throw_InvalidOperation_When_Already_LoggedIn_Sync ( )
306+ {
307+ TestOutputLogger . LogContext ( "TestScenario" , "AlreadyLoggedInSync" ) ;
308+ ContentstackClient client = CreateClientWithLogging ( ) ;
309+
310+ try
311+ {
312+ client . Login ( Contentstack . Credential ) ;
313+ AssertLogger . IsNotNull ( client . contentstackOptions . Authtoken , "Authtoken" ) ;
314+
315+ AssertLogger . ThrowsException < InvalidOperationException > ( ( ) =>
316+ client . Login ( Contentstack . Credential ) , "AlreadyLoggedIn" ) ;
317+
318+ client . Logout ( ) ;
319+ }
320+ catch ( Exception e )
321+ {
322+ AssertLogger . Fail ( $ "Unexpected exception: { e . GetType ( ) . Name } - { e . Message } ") ;
323+ }
324+ }
325+
326+ [ TestMethod ]
327+ [ DoNotParallelize ]
328+ public async System . Threading . Tasks . Task Test013_Should_Throw_InvalidOperation_When_Already_LoggedIn_Async ( )
329+ {
330+ TestOutputLogger . LogContext ( "TestScenario" , "AlreadyLoggedInAsync" ) ;
331+ ContentstackClient client = CreateClientWithLogging ( ) ;
332+
333+ try
334+ {
335+ await client . LoginAsync ( Contentstack . Credential ) ;
336+ AssertLogger . IsNotNull ( client . contentstackOptions . Authtoken , "Authtoken" ) ;
337+
338+ await System . Threading . Tasks . Task . Run ( ( ) =>
339+ AssertLogger . ThrowsException < InvalidOperationException > ( ( ) =>
340+ client . LoginAsync ( Contentstack . Credential ) . GetAwaiter ( ) . GetResult ( ) , "AlreadyLoggedInAsync" ) ) ;
341+
342+ await client . LogoutAsync ( ) ;
343+ }
344+ catch ( Exception e )
345+ {
346+ AssertLogger . Fail ( $ "Unexpected exception: { e . GetType ( ) . Name } - { e . Message } ") ;
347+ }
348+ }
349+
350+ [ TestMethod ]
351+ [ DoNotParallelize ]
352+ public void Test014_Should_Throw_ArgumentNullException_For_Null_Credentials_Sync ( )
353+ {
354+ TestOutputLogger . LogContext ( "TestScenario" , "NullCredentialsSync" ) ;
355+ ContentstackClient client = CreateClientWithLogging ( ) ;
356+
357+ AssertLogger . ThrowsException < ArgumentNullException > ( ( ) =>
358+ client . Login ( null ) , "NullCredentials" ) ;
359+ }
360+
361+ [ TestMethod ]
362+ [ DoNotParallelize ]
363+ public void Test015_Should_Throw_ArgumentNullException_For_Null_Credentials_Async ( )
364+ {
365+ TestOutputLogger . LogContext ( "TestScenario" , "NullCredentialsAsync" ) ;
366+ ContentstackClient client = CreateClientWithLogging ( ) ;
367+
368+ AssertLogger . ThrowsException < ArgumentNullException > ( ( ) =>
369+ client . LoginAsync ( null ) . GetAwaiter ( ) . GetResult ( ) , "NullCredentialsAsync" ) ;
370+ }
371+
372+ [ TestMethod ]
373+ [ DoNotParallelize ]
374+ public async System . Threading . Tasks . Task Test016_Should_Throw_ArgumentException_For_Invalid_MfaSecret_Async ( )
375+ {
376+ TestOutputLogger . LogContext ( "TestScenario" , "InvalidMfaSecretAsync" ) ;
377+ ContentstackClient client = CreateClientWithLogging ( ) ;
378+ NetworkCredential credentials = new NetworkCredential ( "test_user" , "test_password" ) ;
379+ string invalidMfaSecret = "INVALID_BASE32_SECRET!@#" ;
380+
381+ try
382+ {
383+ await client . LoginAsync ( credentials , null , invalidMfaSecret ) ;
384+ AssertLogger . Fail ( "Expected ArgumentException for invalid MFA secret" ) ;
385+ }
386+ catch ( ArgumentException )
387+ {
388+ AssertLogger . IsTrue ( true , "ArgumentException thrown as expected for async" ) ;
389+ }
390+ catch ( Exception e )
391+ {
392+ AssertLogger . Fail ( $ "Unexpected exception type: { e . GetType ( ) . Name } - { e . Message } ") ;
393+ }
394+ }
395+
396+ [ TestMethod ]
397+ [ DoNotParallelize ]
398+ public void Test017_Should_Handle_Valid_Credentials_With_TfaToken_Sync ( )
399+ {
400+ TestOutputLogger . LogContext ( "TestScenario" , "WrongTfaTokenSync" ) ;
401+ ContentstackClient client = CreateClientWithLogging ( ) ;
402+
403+ try
404+ {
405+ client . Login ( Contentstack . Credential , "000000" ) ;
406+ // Account does not have 2FA enabled — tfa_token is ignored by the API and login succeeds.
407+ // This is a valid outcome; assert token is set and clean up.
408+ AssertLogger . IsNotNull ( client . contentstackOptions . Authtoken , "Authtoken" ) ;
409+ client . Logout ( ) ;
410+ }
411+ catch ( ContentstackErrorException errorException )
412+ {
413+ // Account has 2FA enabled — wrong token is correctly rejected with 422.
414+ AssertLogger . AreEqual ( HttpStatusCode . UnprocessableEntity , errorException . StatusCode , "StatusCode" ) ;
415+ AssertLogger . IsTrue ( errorException . ErrorCode > 0 , "TfaErrorCode" ) ;
416+ }
417+ catch ( Exception e )
418+ {
419+ AssertLogger . Fail ( $ "Unexpected exception type: { e . GetType ( ) . Name } - { e . Message } ") ;
420+ }
421+ }
422+
423+ [ TestMethod ]
424+ [ DoNotParallelize ]
425+ public async System . Threading . Tasks . Task Test018_Should_Handle_Valid_Credentials_With_TfaToken_Async ( )
426+ {
427+ TestOutputLogger . LogContext ( "TestScenario" , "WrongTfaTokenAsync" ) ;
428+ ContentstackClient client = CreateClientWithLogging ( ) ;
429+
430+ try
431+ {
432+ await client . LoginAsync ( Contentstack . Credential , "000000" ) ;
433+ // Account does not have 2FA enabled — tfa_token is ignored by the API and login succeeds.
434+ // This is a valid outcome; assert token is set and clean up.
435+ AssertLogger . IsNotNull ( client . contentstackOptions . Authtoken , "Authtoken" ) ;
436+ await client . LogoutAsync ( ) ;
437+ }
438+ catch ( ContentstackErrorException errorException )
439+ {
440+ // Account has 2FA enabled — wrong token is correctly rejected with 422.
441+ AssertLogger . AreEqual ( HttpStatusCode . UnprocessableEntity , errorException . StatusCode , "StatusCode" ) ;
442+ AssertLogger . IsTrue ( errorException . ErrorCode > 0 , "TfaErrorCodeAsync" ) ;
443+ }
444+ catch ( Exception e )
445+ {
446+ AssertLogger . Fail ( $ "Unexpected exception type: { e . GetType ( ) . Name } - { e . Message } ") ;
447+ }
448+ }
449+
450+ [ TestMethod ]
451+ [ DoNotParallelize ]
452+ public void Test019_Should_Not_Include_TfaToken_When_MfaSecret_Is_Empty_Sync ( )
453+ {
454+ TestOutputLogger . LogContext ( "TestScenario" , "EmptyMfaSecretSync" ) ;
455+ ContentstackClient client = CreateClientWithLogging ( ) ;
456+ NetworkCredential credentials = new NetworkCredential ( "mock_user" , "mock_password" ) ;
457+
458+ try
459+ {
460+ client . Login ( credentials , null , "" ) ;
461+ }
462+ catch ( ContentstackErrorException errorException )
463+ {
464+ AssertLogger . AreEqual ( HttpStatusCode . UnprocessableEntity , errorException . StatusCode , "StatusCode" ) ;
465+ AssertLogger . AreEqual ( 104 , errorException . ErrorCode , "ErrorCode" ) ;
466+ }
467+ catch ( Exception e )
468+ {
469+ AssertLogger . Fail ( $ "Unexpected exception type: { e . GetType ( ) . Name } - { e . Message } ") ;
470+ }
471+ }
472+
473+ [ TestMethod ]
474+ [ DoNotParallelize ]
475+ public async System . Threading . Tasks . Task Test020_Should_Not_Include_TfaToken_When_MfaSecret_Is_Null_Async ( )
476+ {
477+ TestOutputLogger . LogContext ( "TestScenario" , "NullMfaSecretAsync" ) ;
478+ ContentstackClient client = CreateClientWithLogging ( ) ;
479+ NetworkCredential credentials = new NetworkCredential ( "mock_user" , "mock_password" ) ;
480+
481+ try
482+ {
483+ await client . LoginAsync ( credentials , null , null ) ;
484+ }
485+ catch ( ContentstackErrorException errorException )
486+ {
487+ AssertLogger . AreEqual ( HttpStatusCode . UnprocessableEntity , errorException . StatusCode , "StatusCode" ) ;
488+ AssertLogger . AreEqual ( 104 , errorException . ErrorCode , "ErrorCode" ) ;
489+ }
490+ catch ( Exception e )
491+ {
492+ AssertLogger . Fail ( $ "Unexpected exception type: { e . GetType ( ) . Name } - { e . Message } ") ;
493+ }
494+ }
307495 }
308496}
0 commit comments