| File: Shared\TestLocalStorage.cs | Web Access |
| Project: src\tests\Aspire.Dashboard.Components.Tests\Aspire.Dashboard.Components.Tests.csproj (Aspire.Dashboard.Components.Tests) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using Aspire.Dashboard.Model.BrowserStorage; namespace Aspire.Dashboard.Components.Tests.Shared; public sealed class TestLocalStorage : ILocalStorage { private readonly Dictionary<string, object?> _unprotectedValues = new(StringComparer.Ordinal); public Func<string, Task>? OnBeforeGetUnprotectedAsync { get; set; } public Func<string, (bool Success, object? Value)>? OnGetUnprotectedAsync { get; set; } public Action<string, object?>? OnSetUnprotectedAsync { get; set; } public Func<string, (bool Success, object? Value)>? OnGetAsync { get; set; } /// <summary> /// Gets or sets a function that returns whether reading a key fails, as when the circuit is disconnected. /// </summary> public Func<string, bool>? IsUnprotectedReadFailed { get; set; } public Task<StorageResult<T>> GetAsync<T>(string key) { if (OnGetAsync is { } callback) { var (success, value) = callback(key); return Task.FromResult(new StorageResult<T>(success: success, value: (T)(value ?? default(T))!)); } return Task.FromResult(new StorageResult<T>(success: false, value: default)); } public async Task<StorageResult<T>> GetUnprotectedAsync<T>(string key) { if (OnBeforeGetUnprotectedAsync is { } beforeCallback) { await beforeCallback(key); } if (IsUnprotectedReadFailed?.Invoke(key) == true) { return new StorageResult<T>(success: false, value: default) { ReadFailed = true }; } // Callbacks return (false, null) for keys they don't provide, so those keys fall back to saved values. Use // IsUnprotectedReadFailed to simulate a failed read. if (OnGetUnprotectedAsync is { } callback) { var (success, value) = callback(key); if (success) { return new StorageResult<T>(success: success, value: (T)(value ?? default(T))!); } } // Like a browser, return what was saved. Settings stores read the stored value before every save, so a // storage that forgot saved values would make them drop their own changes. lock (_unprotectedValues) { if (_unprotectedValues.TryGetValue(key, out var savedValue) && savedValue is T typedValue) { return new StorageResult<T>(success: true, value: typedValue); } } return new StorageResult<T>(success: false, value: default); } public Task<StorageResult<string>> GetRawUnprotectedAsync(string key) { if (IsUnprotectedReadFailed?.Invoke(key) == true) { return Task.FromResult(new StorageResult<string>(success: false, value: null) { ReadFailed = true }); } lock (_unprotectedValues) { return Task.FromResult(_unprotectedValues.TryGetValue(key, out var savedValue) && savedValue is string text ? new StorageResult<string>(success: true, value: text) : new StorageResult<string>(success: false, value: null)); } } public Task SetRawUnprotectedAsync(string key, string value) { lock (_unprotectedValues) { _unprotectedValues[key] = value; } return Task.CompletedTask; } public Task SetAsync<T>(string key, T value) { return Task.CompletedTask; } public Task SetUnprotectedAsync<T>(string key, T value) { lock (_unprotectedValues) { _unprotectedValues[key] = value; } if (OnSetUnprotectedAsync is { } callback) { callback(key, value); } return Task.CompletedTask; } }