using System; using System.IO; using System.Linq; using System.Threading.Tasks; using SharepointToolbox.Infrastructure.Auth; using Xunit; namespace SharepointToolbox.Tests.Auth; [Trait("Category", "Unit")] public class MsalClientFactoryTests : IDisposable { private readonly string _tempCacheDir; public MsalClientFactoryTests() { _tempCacheDir = Path.Combine(Path.GetTempPath(), "MsalClientFactoryTests_" + Guid.NewGuid()); Directory.CreateDirectory(_tempCacheDir); } public void Dispose() { try { Directory.Delete(_tempCacheDir, recursive: true); } catch { /* best effort */ } } [Fact] public async Task GetOrCreateAsync_SameClientId_ReturnsSameInstance() { var factory = new MsalClientFactory(_tempCacheDir); var pca1 = await factory.GetOrCreateAsync("clientA"); var pca2 = await factory.GetOrCreateAsync("clientA"); Assert.Same(pca1, pca2); } [Fact] public async Task GetOrCreateAsync_DifferentClientIds_ReturnDifferentInstances() { var factory = new MsalClientFactory(_tempCacheDir); var pcaA = await factory.GetOrCreateAsync("clientA"); var pcaB = await factory.GetOrCreateAsync("clientB"); Assert.NotSame(pcaA, pcaB); } [Fact] public async Task GetOrCreateAsync_ConcurrentCalls_DoNotCreateDuplicateInstances() { var factory = new MsalClientFactory(_tempCacheDir); // Run 10 concurrent calls with the same clientId var tasks = Enumerable.Range(0, 10) .Select(_ => factory.GetOrCreateAsync("clientConcurrent")) .ToArray(); var results = await Task.WhenAll(tasks); // All 10 results must be the exact same instance var first = results[0]; Assert.All(results, r => Assert.Same(first, r)); } [Fact] public void CacheDirectory_ResolvesToAppData_Not_Hardcoded() { // The default (no-arg) constructor must use %AppData%\SharepointToolbox\auth var factory = new MsalClientFactory(); var expectedBase = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); var expectedDir = Path.Combine(expectedBase, "SharepointToolbox", "auth"); Assert.Equal(expectedDir, factory.CacheDirectory); } }