Skip to content

Commit 82b265b

Browse files
committed
add browser storage provider and verification
1 parent 710b8bb commit 82b265b

File tree

66 files changed

+4492
-131
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+4492
-131
lines changed

.github/workflows/ci.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,18 @@ jobs:
2626
- name: Restore dependencies
2727
run: dotnet restore ManagedCode.Storage.slnx
2828

29+
- name: Restore .NET tools
30+
run: dotnet tool restore
31+
2932
- name: Verify formatting
3033
run: dotnet format ManagedCode.Storage.slnx --verify-no-changes --no-restore
3134

3235
- name: Build
3336
run: dotnet build ManagedCode.Storage.slnx --configuration Release --no-restore
3437

38+
- name: Install Playwright browser
39+
run: dotnet playwright -p Tests/ManagedCode.Storage.Tests/ManagedCode.Storage.Tests.csproj install chromium
40+
3541
- name: Test
3642
run: dotnet test Tests/ManagedCode.Storage.Tests/ManagedCode.Storage.Tests.csproj --configuration Release --no-build --verbosity normal --collect:"XPlat Code Coverage"
3743

.github/workflows/release.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,15 @@ jobs:
3535
- name: Restore dependencies
3636
run: dotnet restore ManagedCode.Storage.slnx
3737

38+
- name: Restore .NET tools
39+
run: dotnet tool restore
40+
3841
- name: Build
3942
run: dotnet build ManagedCode.Storage.slnx --configuration Release --no-restore
4043

44+
- name: Install Playwright browser
45+
run: dotnet playwright -p Tests/ManagedCode.Storage.Tests/ManagedCode.Storage.Tests.csproj install chromium
46+
4147
- name: Test
4248
run: dotnet test Tests/ManagedCode.Storage.Tests/ManagedCode.Storage.Tests.csproj --configuration Release --no-build --verbosity normal
4349

AGENTS.md

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ This file defines how AI agents work in this solution.
2525
- `Integraions/ManagedCode.Storage.Orleans/`
2626
- `Integraions/ManagedCode.Storage.Server/`
2727
- `Storages/ManagedCode.Storage.Aws/`
28+
- `Storages/ManagedCode.Storage.Browser/`
2829
- `Storages/ManagedCode.Storage.Azure/`
2930
- `Storages/ManagedCode.Storage.Azure.DataLake/`
3031
- `Storages/ManagedCode.Storage.CloudKit/`
@@ -35,6 +36,8 @@ This file defines how AI agents work in this solution.
3536
- `Storages/ManagedCode.Storage.OneDrive/`
3637
- `Storages/ManagedCode.Storage.Sftp/`
3738
- `Tests/ManagedCode.Storage.Tests/`
39+
- `Tests/ManagedCode.Storage.BrowserServerHost/`
40+
- `Tests/ManagedCode.Storage.BrowserWasmHost/`
3841

3942
## Rule Precedence
4043

@@ -222,19 +225,21 @@ Toolchain notes:
222225
- Each public API endpoint has at least one test; complex endpoints need tests for different inputs and errors.
223226
- Integration tests must exercise real flows end-to-end, not just call endpoints in isolation.
224227
- Prefer integration or API tests over isolated unit tests.
225-
- Keep mocks to an absolute minimum; prefer real flows using fakes or containers where possible.
228+
- Do not use fakes in automated tests; validate behavior through real runtimes, browser sessions, or containerized dependencies.
229+
- For browser-storage scenarios, verify through handwritten Razor-based test apps in both Blazor WebAssembly and Interactive Server, driven by Playwright against real browser state.
230+
- When browser storage behavior could race across pages or tabs, add explicit concurrency coverage.
226231
- Never write tests that only validate mocked interactions; every test must assert concrete, observable behavior such as state, output, errors, or side effects.
227-
- When faking external APIs, match the official API docs for endpoints, status codes, payloads, and field naming, and prefer `HttpMessageHandler`-based fakes over ad-hoc mocks.
228-
- No mocks for internal systems such as databases, queues, or caches; use containers or fakes as appropriate.
229-
- Mocks are allowed only for external third-party systems.
232+
- When third-party systems must be simulated, prefer real protocol-compatible test infrastructure over in-process fakes.
233+
- No mocks for internal systems such as databases, queues, caches, or browser runtimes.
234+
- Mocks are allowed only as a last resort for external third-party systems when no real or containerized alternative exists, and that exception must be called out explicitly in the task summary.
230235
- Never delete or weaken a test to make it pass.
231236
- Each test must verify a real flow or scenario; tests without meaningful assertions are forbidden.
232237
- Check coverage to find gaps, not to chase a number.
233238
- Tests use `xUnit` + `Shouldly`; choose `[Fact]` for atomic cases and `[Theory]` for data-driven permutations.
234239
- Tests run on `VSTest`; do not mix in `Microsoft.Testing.Platform` assumptions.
235240
- Coverage uses the repo-defined `coverlet.msbuild` flow and must not regress without a written exception.
236241
- Place provider suites under `Tests/ManagedCode.Storage.Tests/Storages/` and reuse `Tests/ManagedCode.Storage.Tests/Common/` helpers for Testcontainers infrastructure such as Azurite, LocalStack, and FakeGcsServer.
237-
- Add fakes or harnesses in `ManagedCode.Storage.TestFakes/` when introducing new providers.
242+
- For browser providers, put end-to-end Playwright coverage in `Tests/ManagedCode.Storage.Tests/Storages/Browser/` and keep the executable test hosts under `Tests/ManagedCode.Storage.BrowserServerHost/` and `Tests/ManagedCode.Storage.BrowserWasmHost/`.
238243

239244
### Storage Platform
240245

@@ -277,6 +282,7 @@ Toolchain notes:
277282
- Remove unused usings and let analyzers guide layout.
278283
- When a `foreach` loop starts by transforming the iteration variable, prefer mapping the sequence explicitly with `.Select(...)` so the intent is clearer.
279284
- Avoid buffering whole files into `MemoryStream` in product code; assume multi-GB files and stream directly to the destination while using incremental hashing or CRC when verification is needed.
285+
- Stream capability properties such as `CanSeek`, `CanWrite`, `Length`, and `Position` must reflect the real backing stream or selected strategy; do not hardcode capability flags in a way that changes stream semantics silently.
280286
- No magic literals; extract them to constants, enums, configuration, or dedicated value types when it improves clarity.
281287

282288
### Git And PRs
@@ -315,4 +321,9 @@ Ask first:
315321

316322
### Likes
317323

324+
- Repository-facing docs, especially `README.md`, should stay in English and describe only the current supported behavior, not transitional legacy or fallback paths.
325+
318326
### Dislikes
327+
328+
- Template-generated scaffolding in tests; keep test hosts and verification surfaces minimal, hand-written, and purpose-built.
329+
- Unnecessary product-code fallbacks; prefer one clear production path unless backward compatibility is an explicit requirement for the task.

Directory.Build.props

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@
2929
<RepositoryUrl>https://github.com/managedcode/Storage</RepositoryUrl>
3030
<PackageProjectUrl>https://github.com/managedcode/Storage</PackageProjectUrl>
3131
<Product>Managed Code - Storage</Product>
32-
<Version>10.0.3</Version>
33-
<PackageVersion>10.0.3</PackageVersion>
32+
<Version>10.0.4</Version>
33+
<PackageVersion>10.0.4</PackageVersion>
3434

3535
</PropertyGroup>
3636

Directory.Packages.props

Lines changed: 51 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,53 @@
11
<Project>
2-
<PropertyGroup>
3-
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
4-
</PropertyGroup>
5-
6-
<ItemGroup>
7-
<PackageVersion Include="AWSSDK.S3" Version="4.0.19" />
8-
<PackageVersion Include="Azure.Identity" Version="1.19.0" />
9-
<PackageVersion Include="Azure.Storage.Blobs" Version="12.27.0" />
10-
<PackageVersion Include="Azure.Storage.Files.DataLake" Version="12.25.0" />
11-
<PackageVersion Include="coverlet.collector" Version="8.0.0" />
12-
<PackageVersion Include="coverlet.msbuild" Version="8.0.0" />
13-
<PackageVersion Include="CsvHelper" Version="33.1.0" />
14-
<PackageVersion Include="DotNet.ReproducibleBuilds" Version="1.2.25" />
15-
<PackageVersion Include="Dropbox.Api" Version="7.0.0" />
16-
<PackageVersion Include="Google.Api.Gax" Version="4.13.1" />
17-
<PackageVersion Include="Google.Api.Gax.Rest" Version="4.13.1" />
18-
<PackageVersion Include="Google.Apis.Drive.v3" Version="1.73.0.4068" />
19-
<PackageVersion Include="Google.Apis.Storage.v1" Version="1.73.0.4052" />
20-
<PackageVersion Include="Google.Cloud.Storage.V1" Version="4.14.0" />
21-
<PackageVersion Include="Humanizer.Core" Version="3.0.10" />
22-
<PackageVersion Include="ManagedCode.Communication" Version="10.0.1" />
23-
<PackageVersion Include="ManagedCode.MimeTypes" Version="10.0.1" />
24-
<PackageVersion Include="Microsoft.AspNetCore.Http" Version="2.3.9" />
25-
<PackageVersion Include="Microsoft.AspNetCore.Http.Connections.Client" Version="10.0.5" />
26-
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.5" />
27-
<PackageVersion Include="Microsoft.AspNetCore.SignalR.Client" Version="10.0.5" />
28-
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="10.0.5" />
29-
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.5" />
30-
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.5" />
31-
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.5" />
32-
<PackageVersion Include="Microsoft.Extensions.Logging" Version="10.0.5" />
33-
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.5" />
34-
<PackageVersion Include="Microsoft.Extensions.Options" Version="10.0.5" />
35-
<PackageVersion Include="Microsoft.Graph" Version="5.103.0" />
36-
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
37-
<PackageVersion Include="Microsoft.Orleans.Runtime" Version="10.0.1" />
38-
<PackageVersion Include="Microsoft.Orleans.TestingHost" Version="10.0.1" />
39-
<PackageVersion Include="NetArchTest.Rules" Version="1.3.2" />
40-
<PackageVersion Include="Shouldly" Version="4.3.0" />
41-
<PackageVersion Include="SSH.NET" Version="2025.1.0" />
42-
<PackageVersion Include="Testcontainers" Version="4.11.0" />
43-
<PackageVersion Include="Testcontainers.Azurite" Version="4.11.0" />
44-
<PackageVersion Include="Testcontainers.FakeGcsServer" Version="4.11.0" />
45-
<PackageVersion Include="Testcontainers.LocalStack" Version="4.11.0" />
46-
<PackageVersion Include="Testcontainers.Sftp" Version="4.11.0" />
47-
<PackageVersion Include="xunit" Version="2.9.3" />
48-
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
49-
</ItemGroup>
2+
<PropertyGroup>
3+
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
4+
</PropertyGroup>
5+
<ItemGroup>
6+
<PackageVersion Include="AWSSDK.S3" Version="4.0.19.4" />
7+
<PackageVersion Include="Azure.Identity" Version="1.20.0" />
8+
<PackageVersion Include="Azure.Storage.Blobs" Version="12.27.0" />
9+
<PackageVersion Include="Azure.Storage.Files.DataLake" Version="12.25.0" />
10+
<PackageVersion Include="coverlet.collector" Version="8.0.1" />
11+
<PackageVersion Include="coverlet.msbuild" Version="8.0.1" />
12+
<PackageVersion Include="CsvHelper" Version="33.1.0" />
13+
<PackageVersion Include="DotNet.ReproducibleBuilds" Version="1.2.25" />
14+
<PackageVersion Include="Dropbox.Api" Version="7.0.0" />
15+
<PackageVersion Include="Google.Api.Gax" Version="4.13.1" />
16+
<PackageVersion Include="Google.Api.Gax.Rest" Version="4.13.1" />
17+
<PackageVersion Include="Google.Apis.Drive.v3" Version="1.73.0.4098" />
18+
<PackageVersion Include="Google.Apis.Storage.v1" Version="1.73.0.4052" />
19+
<PackageVersion Include="Google.Cloud.Storage.V1" Version="4.14.0" />
20+
<PackageVersion Include="Humanizer.Core" Version="3.0.10" />
21+
<PackageVersion Include="ManagedCode.Communication" Version="10.0.1" />
22+
<PackageVersion Include="ManagedCode.MimeTypes" Version="10.0.1" />
23+
<PackageVersion Include="Microsoft.AspNetCore.Http" Version="2.3.9" />
24+
<PackageVersion Include="Microsoft.AspNetCore.Http.Connections.Client" Version="10.0.5" />
25+
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.5" />
26+
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="10.0.5" />
27+
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.5" />
28+
<PackageVersion Include="Microsoft.AspNetCore.SignalR.Client" Version="10.0.5" />
29+
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="10.0.5" />
30+
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.5" />
31+
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.5" />
32+
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.5" />
33+
<PackageVersion Include="Microsoft.Extensions.Logging" Version="10.0.5" />
34+
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.5" />
35+
<PackageVersion Include="Microsoft.Extensions.Options" Version="10.0.5" />
36+
<PackageVersion Include="Microsoft.Graph" Version="5.103.0" />
37+
<PackageVersion Include="Microsoft.JSInterop" Version="10.0.5" />
38+
<PackageVersion Include="Microsoft.Playwright" Version="1.58.0" />
39+
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
40+
<PackageVersion Include="Microsoft.Orleans.Runtime" Version="10.0.1" />
41+
<PackageVersion Include="Microsoft.Orleans.TestingHost" Version="10.0.1" />
42+
<PackageVersion Include="NetArchTest.Rules" Version="1.3.2" />
43+
<PackageVersion Include="Shouldly" Version="4.3.0" />
44+
<PackageVersion Include="SSH.NET" Version="2025.1.0" />
45+
<PackageVersion Include="Testcontainers" Version="4.11.0" />
46+
<PackageVersion Include="Testcontainers.Azurite" Version="4.11.0" />
47+
<PackageVersion Include="Testcontainers.FakeGcsServer" Version="4.11.0" />
48+
<PackageVersion Include="Testcontainers.LocalStack" Version="4.11.0" />
49+
<PackageVersion Include="Testcontainers.Sftp" Version="4.11.0" />
50+
<PackageVersion Include="xunit" Version="2.9.3" />
51+
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
52+
</ItemGroup>
5053
</Project>

ManagedCode.Storage.slnx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
</Folder>
1313
<Folder Name="/Storages/">
1414
<Project Path="Storages/ManagedCode.Storage.Aws/ManagedCode.Storage.Aws.csproj" />
15+
<Project Path="Storages/ManagedCode.Storage.Browser/ManagedCode.Storage.Browser.csproj" />
1516
<Project Path="Storages/ManagedCode.Storage.Azure.DataLake/ManagedCode.Storage.Azure.DataLake.csproj" />
1617
<Project Path="Storages/ManagedCode.Storage.Azure/ManagedCode.Storage.Azure.csproj" />
1718
<Project Path="Storages/ManagedCode.Storage.FileSystem/ManagedCode.Storage.FileSystem.csproj" />
@@ -23,6 +24,8 @@
2324
<Project Path="Storages/ManagedCode.Storage.CloudKit/ManagedCode.Storage.CloudKit.csproj" />
2425
</Folder>
2526
<Folder Name="/Tests/">
27+
<Project Path="Tests/ManagedCode.Storage.BrowserServerHost/ManagedCode.Storage.BrowserServerHost.csproj" />
28+
<Project Path="Tests/ManagedCode.Storage.BrowserWasmHost/ManagedCode.Storage.BrowserWasmHost.csproj" />
2629
<Project Path="Tests/ManagedCode.Storage.Tests/ManagedCode.Storage.Tests.csproj" />
2730
</Folder>
2831
<Project Path="ManagedCode.Storage.Core/ManagedCode.Storage.Core.csproj" />

0 commit comments

Comments
 (0)