/
githubmirror
/
aspnetcore
Обзор
Документация
Войти
/
githubmirror
/
aspnetcore
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Components/Endpoints/test/TempData/CookieTempDataProviderTest.cs
190 строк
7 KB
Daria Tiurina
TempData support for Blazor (#64749)
03 фев 2026, 14:53
Не верифицирован
03 фев 2026, 14:53
65468ce
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; namespace Microsoft.AspNetCore.Components.Endpoints; public class CookieTempDataProviderTest { private readonly CookieTempDataProvider _cookieTempDataProvider; internal TempData CreateTempData() { return new TempData(() => new Dictionary<string, object>()); } public CookieTempDataProviderTest() { _cookieTempDataProvider = new CookieTempDataProvider( new EphemeralDataProtectionProvider(), Options.Create<RazorComponentsServiceOptions>(new()), new JsonTempDataSerializer(), NullLogger<CookieTempDataProvider>.Instance); } [Fact] public void Load_ReturnsEmptyTempData_WhenNoCookieExists() { var httpContext = CreateHttpContext(); var tempData = _cookieTempDataProvider.LoadTempData(httpContext); Assert.NotNull(tempData); Assert.Empty(tempData); } [Fact] public void Load_ReturnsEmptyTempData_AndClearsCookie_WhenDataIsInvalid() { var httpContext = CreateHttpContext(); httpContext.Request.Headers["Cookie"] = ".AspNetCore.Components.TempData=not-valid-base64!!!"; var tempData = _cookieTempDataProvider.LoadTempData(httpContext); Assert.NotNull(tempData); Assert.Empty(tempData); // Cookie should be deleted when invalid var cookieFeature = httpContext.Features.Get<TestResponseCookiesFeature>(); Assert.NotNull(cookieFeature); Assert.Contains(".AspNetCore.Components.TempData", cookieFeature.DeletedCookies); } [Fact] public void Save_DeletesCookie_WhenNoDataToSave() { var httpContext = CreateHttpContext(); var tempData = CreateTempData(); _cookieTempDataProvider.SaveTempData(httpContext, tempData.Save()); var cookieFeature = httpContext.Features.Get<TestResponseCookiesFeature>(); Assert.NotNull(cookieFeature); Assert.Contains(".AspNetCore.Components.TempData", cookieFeature.DeletedCookies); } [Fact] public void Save_SetsCookie_WhenDataExists() { var httpContext = CreateHttpContext(); var tempData = CreateTempData(); tempData["Key1"] = "Value1"; _cookieTempDataProvider.SaveTempData(httpContext, tempData.Save()); var cookieFeature = httpContext.Features.Get<TestResponseCookiesFeature>(); Assert.NotNull(cookieFeature); Assert.Contains(".AspNetCore.Components.TempData", cookieFeature.SetCookies.Keys); } [Fact] public void Save_ThrowsForUnsupportedType() { var httpContext = CreateHttpContext(); var tempData = CreateTempData(); tempData["Key"] = new object(); Assert.Throws<InvalidOperationException>(() => _cookieTempDataProvider.SaveTempData(httpContext, tempData.Save())); } [Fact] public void RoundTrip_SaveAndLoad_WorksCorrectly() { var httpContext = CreateHttpContext(); var tempData = CreateTempData(); tempData["StringKey"] = "StringValue"; tempData["IntKey"] = 42; _cookieTempDataProvider.SaveTempData(httpContext, tempData.Save()); SimulateCookieRoundTrip(httpContext); var loadedTempData = _cookieTempDataProvider.LoadTempData(httpContext); Assert.Equal("StringValue", loadedTempData["StringKey"]); Assert.Equal(42, Assert.IsType<int>(loadedTempData["IntKey"])); } private static DefaultHttpContext CreateHttpContext() { var services = new ServiceCollection() .AddSingleton<IDataProtectionProvider, PassThroughDataProtectionProvider>() .BuildServiceProvider(); var httpContext = new DefaultHttpContext { RequestServices = services }; httpContext.Request.Scheme = "https"; httpContext.Request.Host = new HostString("localhost"); var cookieFeature = new TestResponseCookiesFeature(); httpContext.Features.Set(cookieFeature); httpContext.Features.Set<IResponseCookiesFeature>(cookieFeature); return httpContext; } private static void SimulateCookieRoundTrip(HttpContext httpContext) { var cookieFeature = httpContext.Features.Get<TestResponseCookiesFeature>(); if (cookieFeature != null && cookieFeature.SetCookies.TryGetValue(".AspNetCore.Components.TempData", out var cookieValue)) { httpContext.Request.Headers["Cookie"] = $".AspNetCore.Components.TempData={cookieValue}"; } } private class PassThroughDataProtectionProvider : IDataProtectionProvider { public IDataProtector CreateProtector(string purpose) => new PassThroughDataProtector(); private class PassThroughDataProtector : IDataProtector { public IDataProtector CreateProtector(string purpose) => this; public byte[] Protect(byte[] plaintext) => plaintext; public byte[] Unprotect(byte[] protectedData) => protectedData; } } private class TestResponseCookiesFeature : IResponseCookiesFeature { public Dictionary<string, string> SetCookies { get; } = new(); public HashSet<string> DeletedCookies { get; } = new(); public IResponseCookies Cookies => new TestResponseCookies(this); private class TestResponseCookies : IResponseCookies { private readonly TestResponseCookiesFeature _feature; public TestResponseCookies(TestResponseCookiesFeature feature) { _feature = feature; } public void Append(string key, string value) => Append(key, value, new CookieOptions()); public void Append(string key, string value, CookieOptions options) { // ChunkingCookieManager deletes by appending with expired date (UnixEpoch) if (options.Expires.HasValue && options.Expires.Value <= DateTimeOffset.UnixEpoch) { _feature.DeletedCookies.Add(key); } else { _feature.SetCookies[key] = value; } } public void Delete(string key) => Delete(key, new CookieOptions()); public void Delete(string key, CookieOptions options) { _feature.DeletedCookies.Add(key); } } } }