diff --git a/services/integration_tests/tests/common/auth_helpers.rs b/services/integration_tests/tests/common/auth_helpers.rs index 8ac471000..8af44a23f 100644 --- a/services/integration_tests/tests/common/auth_helpers.rs +++ b/services/integration_tests/tests/common/auth_helpers.rs @@ -213,8 +213,10 @@ impl TestAuthConfig { /// 2. Set JWT_SECRET in .env file /// 3. Load .env before running tests (e.g., `source .env` or use dotenv) pub fn get_test_jwt_secret() -> String { - std::env::var("JWT_SECRET").expect( - "FATAL: JWT_SECRET must be set in .env file for E2E tests\n\ + // WAVE 149 Agent 411: Trim whitespace to match API Gateway behavior + std::env::var("JWT_SECRET") + .expect( + "FATAL: JWT_SECRET must be set in .env file for E2E tests\n\ \n\ Setup:\n\ 1. Copy .env.example to .env\n\ @@ -222,7 +224,9 @@ pub fn get_test_jwt_secret() -> String { 3. Run: export $(cat .env | xargs)\n\ \n\ Example: JWT_SECRET=OvFLDUbIDak3CSCi5t6zKfsAp65cjTOJ85q9YE+TFY8b361DGg1gSTra2rW6mps3cWrRGQ/NXRA5uftUpMldvOaEHMMgfBs4JjVODDElREdvUFm0EttD1A==", - ) + ) + .trim() + .to_string() } /// Get test user ID (consistent across tests) @@ -492,6 +496,7 @@ mod tests { } #[test] + #[serial_test::serial] // WAVE 149 Agent 415: Prevent test pollution from remove_var #[should_panic(expected = "JWT_SECRET must be set")] fn test_get_test_jwt_secret_fails_without_env() { // Clear JWT_SECRET to test fail-fast behavior diff --git a/services/trading_service/tests/auth_security_tests.rs b/services/trading_service/tests/auth_security_tests.rs index a3d33cb3e..f08656816 100644 --- a/services/trading_service/tests/auth_security_tests.rs +++ b/services/trading_service/tests/auth_security_tests.rs @@ -435,6 +435,7 @@ async fn test_jwt_token_with_all_role_types() -> Result<()> { // These tests verify the behavior through the public API #[test] +#[serial_test::serial] // WAVE 149 Agent 415: Prevent test pollution from remove_var fn test_jwt_secret_valid_strong_secret() { std::env::set_var("JWT_SECRET", TEST_JWT_SECRET); let result = AuthConfig::new(); @@ -443,6 +444,7 @@ fn test_jwt_secret_valid_strong_secret() { } #[test] +#[serial_test::serial] // WAVE 149 Agent 415: Prevent test pollution from remove_var fn test_jwt_secret_too_short_rejected() { let short_secret = "TooShort123!@#"; // Only 14 chars, needs 64 std::env::set_var("JWT_SECRET", short_secret); @@ -453,6 +455,7 @@ fn test_jwt_secret_too_short_rejected() { } #[test] +#[serial_test::serial] // WAVE 149 Agent 415: Prevent test pollution from remove_var fn test_jwt_secret_too_long_rejected() { let long_secret = "a".repeat(2000); // >1024 chars std::env::set_var("JWT_SECRET", &long_secret); @@ -463,6 +466,7 @@ fn test_jwt_secret_too_long_rejected() { } #[test] +#[serial_test::serial] // WAVE 149 Agent 415: Prevent test pollution from remove_var fn test_jwt_secret_no_lowercase_rejected() { let no_lowercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()ABCDEFGHIJKLMNOPQR"; std::env::set_var("JWT_SECRET", no_lowercase); @@ -473,6 +477,7 @@ fn test_jwt_secret_no_lowercase_rejected() { } #[test] +#[serial_test::serial] // WAVE 149 Agent 415: Prevent test pollution from remove_var fn test_jwt_secret_no_uppercase_rejected() { let no_uppercase = "abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()abcdefghijklmnopqr"; std::env::set_var("JWT_SECRET", no_uppercase); @@ -483,6 +488,7 @@ fn test_jwt_secret_no_uppercase_rejected() { } #[test] +#[serial_test::serial] // WAVE 149 Agent 415: Prevent test pollution from remove_var fn test_jwt_secret_no_digits_rejected() { let no_digits = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()"; std::env::set_var("JWT_SECRET", no_digits); @@ -493,6 +499,7 @@ fn test_jwt_secret_no_digits_rejected() { } #[test] +#[serial_test::serial] // WAVE 149 Agent 415: Prevent test pollution from remove_var fn test_jwt_secret_no_symbols_rejected() { let no_symbols = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; std::env::set_var("JWT_SECRET", no_symbols); @@ -503,6 +510,7 @@ fn test_jwt_secret_no_symbols_rejected() { } #[test] +#[serial_test::serial] // WAVE 149 Agent 415: Prevent test pollution from remove_var fn test_jwt_secret_repeated_characters_rejected() { let repeated = "Aaaaa1!Aaaaa1!Aaaaa1!Aaaaa1!Aaaaa1!Aaaaa1!Aaaaa1!Aaaaa1!Aaaaa1!"; // >3 repeated 'a' std::env::set_var("JWT_SECRET", repeated); @@ -513,6 +521,7 @@ fn test_jwt_secret_repeated_characters_rejected() { } #[test] +#[serial_test::serial] // WAVE 149 Agent 415: Prevent test pollution from remove_var fn test_jwt_secret_sequential_pattern_rejected() { let sequential = "abcd1234ABCD!@#$abcd1234ABCD!@#$abcd1234ABCD!@#$abcd1234ABCD!"; std::env::set_var("JWT_SECRET", sequential); @@ -523,6 +532,7 @@ fn test_jwt_secret_sequential_pattern_rejected() { } #[test] +#[serial_test::serial] // WAVE 149 Agent 415: Prevent test pollution from remove_var fn test_jwt_secret_weak_dictionary_words_rejected() { let dictionary = "Password123!Password123!Password123!Password123!Password123!Pass"; std::env::set_var("JWT_SECRET", dictionary); @@ -533,6 +543,7 @@ fn test_jwt_secret_weak_dictionary_words_rejected() { } #[test] +#[serial_test::serial] // WAVE 149 Agent 415: Prevent test pollution from remove_var fn test_jwt_secret_low_entropy_rejected() { // Repetitive pattern with low entropy let low_entropy = "A1!a".repeat(20); // Repeating 4-char pattern @@ -544,6 +555,7 @@ fn test_jwt_secret_low_entropy_rejected() { } #[test] +#[serial_test::serial] // WAVE 149 Agent 415: Prevent test pollution from remove_var fn test_jwt_secret_load_from_file_priority() { // Test JWT_SECRET_FILE takes priority over JWT_SECRET let temp_dir = std::env::temp_dir();