diff --git a/NEW/tests/JdeScoping.Api.IntegrationTests/ClientIntegration/ClientIntegrationCollection.cs b/NEW/tests/JdeScoping.Api.IntegrationTests/ClientIntegration/ClientIntegrationCollection.cs
new file mode 100644
index 0000000..60a5f14
--- /dev/null
+++ b/NEW/tests/JdeScoping.Api.IntegrationTests/ClientIntegration/ClientIntegrationCollection.cs
@@ -0,0 +1,10 @@
+namespace JdeScoping.Api.IntegrationTests.ClientIntegration;
+
+///
+/// Collection definition for client integration tests.
+/// Prevents parallel execution to avoid auth state conflicts.
+///
+[CollectionDefinition("ClientIntegration")]
+public class ClientIntegrationCollection : ICollectionFixture
+{
+}
diff --git a/NEW/tests/JdeScoping.Api.IntegrationTests/ClientIntegration/ClientIntegrationTestBase.cs b/NEW/tests/JdeScoping.Api.IntegrationTests/ClientIntegration/ClientIntegrationTestBase.cs
new file mode 100644
index 0000000..1851695
--- /dev/null
+++ b/NEW/tests/JdeScoping.Api.IntegrationTests/ClientIntegration/ClientIntegrationTestBase.cs
@@ -0,0 +1,77 @@
+using System.Security.Cryptography;
+using System.Text;
+using System.Text.Json;
+using JdeScoping.Client.Services;
+using JdeScoping.Core.Models.Auth;
+using Microsoft.AspNetCore.Mvc.Testing;
+
+namespace JdeScoping.Api.IntegrationTests.ClientIntegration;
+
+///
+/// Base class for API client integration tests.
+/// Provides shared HttpClient with cookie handling for auth state.
+///
+[Collection("ClientIntegration")]
+public abstract class ClientIntegrationTestBase : IClassFixture
+{
+ protected readonly TestWebApplicationFactory Factory;
+ protected readonly HttpClient SharedClient;
+
+ // API clients share the authenticated HttpClient
+ protected readonly SearchApiClient SearchClient;
+ protected readonly LookupApiClient LookupClient;
+ protected readonly AuthApiClient AuthClient;
+ protected readonly FileApiClient FileClient;
+
+ protected ClientIntegrationTestBase(TestWebApplicationFactory factory)
+ {
+ Factory = factory;
+ SharedClient = factory.CreateClient(new WebApplicationFactoryClientOptions
+ {
+ HandleCookies = true,
+ AllowAutoRedirect = false
+ });
+
+ // All clients share the same HttpClient (cookie container)
+ SearchClient = new SearchApiClient(SharedClient);
+ LookupClient = new LookupApiClient(SharedClient);
+ FileClient = new FileApiClient(SharedClient);
+ AuthClient = new AuthApiClient(SharedClient);
+ }
+
+ ///
+ /// Performs login with encrypted credentials.
+ ///
+ protected async Task LoginAsync(string username = "testuser", string password = "testpass")
+ {
+ // Step 1: Get public key
+ var publicKeyResult = await AuthClient.GetPublicKeyAsync();
+ if (!publicKeyResult.IsSuccess)
+ throw new Exception("Failed to get public key");
+
+ // Step 2: Encrypt credentials
+ var loginModel = new LoginModel { Username = username, Password = password };
+ var json = JsonSerializer.Serialize(loginModel);
+ var plaintext = Encoding.UTF8.GetBytes(json);
+
+ using var rsa = RSA.Create();
+ rsa.ImportFromPem(publicKeyResult.Value.PublicKeyPem);
+ var ciphertext = rsa.Encrypt(plaintext, RSAEncryptionPadding.OaepSHA256);
+
+ // Step 3: Login
+ var encryptedRequest = new EncryptedLoginRequest(Convert.ToBase64String(ciphertext));
+ var loginResult = await AuthClient.LoginAsync(encryptedRequest);
+
+ if (!loginResult.IsSuccess || !loginResult.Value.Success)
+ throw new Exception($"Login failed: {loginResult.Value?.ErrorMessage ?? "Unknown error"}");
+ }
+
+ ///
+ /// Creates a fresh HttpClient without cookies for testing unauthorized scenarios.
+ ///
+ protected HttpClient CreateFreshClient() => Factory.CreateClient(new WebApplicationFactoryClientOptions
+ {
+ HandleCookies = false,
+ AllowAutoRedirect = false
+ });
+}