docs: Update documentation for 145 files

Generated by AurionDocs
Job ID: 934f8c39-8082-4942-8d17-72ed8f5f8d50
Source commit: 40aea9a
This commit is contained in:
Hue
2026-07-23 11:44:20 +02:00
parent 40aea9a04b
commit 607217b314
144 changed files with 5098 additions and 6498 deletions
@@ -22,29 +22,29 @@ internal sealed class FakeChannelService : IChannelService
```
A lightweight test double that implements IChannelService by returning pre-configured results for each operation. Use this in unit tests to simulate success, failure, or specific payloads from channel-related operations without wiring up real storage or network dependencies.
A test double that implements [`IChannelService`](../../EchoHub.Core/Contracts/IChannelService.cs.md) and lets tests control the results of channel-related operations by setting public properties. Use `FakeChannelService` in unit tests when you need a simple, configurable implementation of [`IChannelService`](../../EchoHub.Core/Contracts/IChannelService.cs.md) without using a mocking framework.
## Remarks
The fake exposes properties you set from tests (for example CreateResult, TopicResult, ChannelListToReturn, MembershipResult, CryptoToReturn, KeyEnvelopeToReturn, ChannelMetaToReturn, SystemChannelToReturn and others). Most methods return Task.FromResult(...) of those properties or a default failure (ChannelOperationResult.Fail(ChannelError.ValidationFailed, "Not configured")) when a result property has not been provided. EnsureSystemChannelAsync returns the configured SystemChannelToReturn or a minimal default ChannelDto (with a new Guid and IsSystem = true) when not configured.
`FakeChannelService` is a lightweight, stateful fake intended for unit tests. Each operation returns the value of a corresponding public property (for example, `CreateResult`, `UpdateTopicResult`, `DeleteResult`), or a sensible default when a property is not set. This makes it easy to simulate success, failure, and edge cases for callers of [`IChannelService`](../../EchoHub.Core/Contracts/IChannelService.cs.md) without wiring up a full service or external dependencies. [`EnsureSystemChannelAsync`](../../EchoHub.Server/Services/ChannelService.cs.md) will return `SystemChannelToReturn` if set; otherwise it constructs a fallback [`ChannelDto`](../../EchoHub.Core/DTOs/ChatDtos.cs.md) with deterministic fields (a new `Guid`, the supplied `channelName`/`topic`, `DateTimeOffset.UnixEpoch`, and other boolean flags as shown in the implementation).
## Example
```csharp
// Arrange: create the fake and configure the CreateChannelAsync result
// Arrange
var fake = new FakeChannelService();
var created = new ChannelDto(Guid.NewGuid(), "my-channel", "topic", false, 0, DateTimeOffset.UnixEpoch, false, false, false);
fake.CreateResult = ChannelOperationResult.Success(created);
var createdChannel = new ChannelDto(Guid.NewGuid(), "room", null, false, 0, DateTimeOffset.UtcNow, false, false, false);
fake.CreateResult = ChannelOperationResult.Success(createdChannel);
// Act: call the service (synchronously here via Task.Result for brevity in tests)
var result = fake.CreateChannelAsync(Guid.NewGuid(), "my-channel", "topic", isPublic: true).Result;
// Act
var result = await fake.CreateChannelAsync(Guid.NewGuid(), "room", null, true);
// Assert: the configured success is returned
// Assert
if (!result.IsSuccess) throw new Exception("expected success");
```
## Notes
- The fake uses Task.FromResult and no asynchronous I/O; it's intended only for synchronous-style unit tests and will not reproduce concurrency or latency characteristics of a real implementation.
- If you forget to set a specific "Result" property (e.g. CreateResult, UpdateTopicResult, RekeyResult), the fake returns ChannelOperationResult.Fail(ChannelError.ValidationFailed, "Not configured").
- EnsureSystemChannelAsync will fabricate a new ChannelDto with a fresh Guid when SystemChannelToReturn is not set; tests that rely on a stable id should explicitly set SystemChannelToReturn.
- The fake exposes mutable public properties; tests must set the appropriate property (for example `CreateResult` or `UpdateTopicResult`) before invoking the corresponding method. Properties are read/write and not thread-safe.
- Several methods return a failure when their result property is unset: operations like `CreateChannelAsync`, [`UpdateTopicAsync`](../../EchoHub.Server/Services/ChannelService.cs.md), [`SetChannelPasswordAsync`](../../EchoHub.Server/Services/ChannelService.cs.md), `RekeyChannelAsync`, and `DeleteChannelAsync` return `ChannelOperationResult.Fail(ChannelError.ValidationFailed, "Not configured")` unless the corresponding property is provided. Tests that expect success must assign a matching [`ChannelOperationResult`](../../EchoHub.Core/DTOs/CommonDtos.cs.md) first.
- The XML summary suggests the fake "records method calls," but the implementation only exposes configurable return properties and does not record call history. If call-count or argument inspection is required, extend the fake (or use a mocking library) to capture that information.
---
@@ -57,34 +57,34 @@ internal sealed class FakeChatService : IChatService
```
A test double that implements IChatService for use in unit tests. It records calls (connected users, disconnections, joins/leaves, sent messages, status updates) into public lists and returns configurable, pre-seeded results (history, errors, online users, channels). Reach for this when you need a deterministic, inspectable chat service in tests rather than the real implementation.
Fake test double implementing [`IChatService`](../../EchoHub.Core/Contracts/IChatService.cs.md) that records every call into in-memory lists and returns configurable, pre-set responses. Use `FakeChatService` in unit or integration tests when you need to assert which [`IChatService`](../../EchoHub.Core/Contracts/IChatService.cs.md) methods were invoked or control what the hub/client sees without running a real chat backend.
## Remarks
FakeChatService exists solely to make tests observable and controllable: callers can assert that particular chat operations were invoked by inspecting the public lists, and tests can control what operations return by setting the configurable properties (HistoryToReturn, JoinError, SendMessageError, etc.). It does not perform any real validation or I/O and intentionally records inputs (including join passwords) so tests can verify them.
`FakeChatService` is a combined stub-and-spy: each [`IChatService`](../../EchoHub.Core/Contracts/IChatService.cs.md) method either appends a record to one of the public lists (for later assertions) and/or returns the values exposed on its configurable properties. This lets tests both (a) inject specific return values such as `HistoryToReturn`, `JoinError`, `SendMessageError`, `ChannelsForUserToReturn`, and `OnlineUsersToReturn`, and (b) verify side-effects by inspecting `ConnectedUsers`, `DisconnectedConnections`, `JoinedChannels`, `LeftChannels`, `SentMessages`, `StatusUpdates`, and `JoinKeys`. It implements the full [`IChatService`](../../EchoHub.Core/Contracts/IChatService.cs.md) surface so it can be passed anywhere the production service is expected without additional shimming.
## Example
```csharp
// Typical usage in a unit test
var svc = new FakeChatService();
// Arrange
var fake = new FakeChatService();
var sampleMessage = new MessageDto(/* ... */); // construct as needed
fake.HistoryToReturn = new List<MessageDto> { sampleMessage };
fake.JoinPasswordRequired = true;
// Simulate a user connecting
await svc.UserConnectedAsync("conn-1", Guid.NewGuid(), "alice");
// svc.ConnectedUsers now contains "alice"
// Act
var joinResult = await fake.JoinChannelAsync("conn-1", Guid.NewGuid(), "alice", "general", "secret");
await fake.SendMessageAsync(Guid.NewGuid(), "alice", "general", "hello world");
// Simulate joining a channel (password may be null)
var (history, error, passwordRequired) = await svc.JoinChannelAsync("conn-1", Guid.NewGuid(), "alice", "#room", null);
// svc.JoinedChannels contains ("#room", "alice") and svc.JoinKeys contains the password passed
// Simulate sending a message and configure an error result
svc.SendMessageError = "rate-limited";
var sendErr = await svc.SendMessageAsync(Guid.NewGuid(), "alice", "#room", "hello world");
// sendErr == "rate-limited" and svc.SentMessages contains ("#room", "hello world")
// Assert (inspect recorded calls and configured return)
// joinResult.History contains the configured MessageDto
// fake.JoinedChannels contains ("general", "alice")
// fake.JoinKeys contains the supplied password "secret"
// fake.SentMessages contains ("general", "hello world")
```
## Notes
- The public list properties are mutable and intended for test inspection; tests should reset or recreate the FakeChatService between cases to avoid cross-test contamination.
- JoinChannelAsync records the supplied password into JoinKeys — this test double intentionally captures sensitive inputs for verification, so treat recorded passwords carefully in test logs.
- This implementation makes no concurrency guarantees; if tests exercise the fake from multiple threads you may encounter race conditions.
- `FakeChatService` is not thread-safe: all recorded collections are plain `List<T>` instances and are mutated without synchronization. Reset or recreate the instance between parallel tests.
- Several methods ignore some input parameters: for example, [`GetChannelHistoryAsync`](../../EchoHub.Server/Services/ChatService.cs.md) always returns `HistoryToReturn` and does not use the `count` or `offset` arguments; tests relying on real paging behavior will not be exercised by this fake.
- Default behaviors are simple and explicit: [`UserDisconnectedAsync`](../../EchoHub.Server/Services/ChatService.cs.md) returns `null` by default, [`SendMessageAsync`](../../EchoHub.Server/Services/ChatService.cs.md) returns whatever `SendMessageError` is set to, and the various `Broadcast*` methods are no-ops. Tests that need side-effects from broadcasts must simulate them explicitly.
---
@@ -97,26 +97,15 @@ internal sealed class FakeEncryptionService : IMessageEncryptionService
```
It is a test double that mimics encrypted content by prefixing plaintext with a fixed marker, allowing tests to verify code paths that handle encrypted data without introducing real cryptography.
FakeEncryptionService is a compact, test-oriented implementation that simulates encryption by prefixing plaintext with a fixed marker. It implements [`IMessageEncryptionService`](../../EchoHub.Core/Contracts/IMessageEncryptionService.cs.md) and is intended for test scenarios where deterministic, invertible behavior is enough to exercise encryption flows without pulling in real cryptography. Encrypt("hello") produces `"$ENC$hello"`, and Decrypt("$ENC$hello") returns the original text. If a value to decrypt does not start with the expected prefix, Decrypt simply returns the input unchanged. The nullable helpers `EncryptNullable` and `DecryptNullable` mirror the non-nullable versions, preserving null semantics. The `EncryptDatabaseEnabled` flag is always true in this fake, enabling components that check encryption per database usage to behave consistently in tests.
## Remarks
This internal, sealed class provides a deterministic, reversible "encryption" scheme for testing scenarios that depend on encrypted strings. By implementing IMessageEncryptionService, it enables tests to validate integration points that consume or produce ciphertext without relying on real cryptographic routines. The EncryptDatabaseEnabled property being true signals that encryption should be considered active in the test database layer. Use this class when you need predictable, fast behavior in unit tests that exercise encryption-related code paths.
## Example
```csharp
var service = new FakeEncryptionService();
string ciphertext = service.Encrypt("hello"); // "$ENC$hello"
string plaintext = service.Decrypt(ciphertext); // "hello"
string? nullCipher = service.EncryptNullable(null); // null
string? nullPlain = service.DecryptNullable(null); // null
string? recovered = service.DecryptNullable(ciphertext); // "hello"
```
Designed as a lightweight test double, this class enforces the [`IMessageEncryptionService`](../../EchoHub.Core/Contracts/IMessageEncryptionService.cs.md) contract while avoiding real crypto. It makes the encryption step observable through a constant prefix, enabling tests to locate and verify encrypted payloads, and to simulate database encryption paths via `EncryptDatabaseEnabled`. By keeping it internal and sealed, the implementation is deliberately opaque to prevent accidental misuse outside tests and to preserve a predictable test surface.
## Notes
- This is a fake encryption shim for tests; it is not cryptographically secure.
- Decrypt only removes the prefix if present; non-prefixed content is returned unchanged.
- EncryptNullable/DecryptNullable are null-safe helpers that simplify test code.
- This is a non-secure stub and should never be used for production encryption or storage.
- Because the type is `internal`, it is intended for test code within the same assembly (or a friend-accessible setup). If you need to reference it from production-like tests, ensure appropriate internals visibility is configured.
---
@@ -129,15 +118,35 @@ internal sealed class FakeUserService : IUserService
```
A lightweight test double of IUserService that records calls and returns pre-configured results. Use this in unit or integration tests when you need to simulate authentication, registration, and profile lookups without exercising the real user backend.
Lightweight test double implementing [`IUserService`](../../EchoHub.Core/Contracts/IUserService.cs.md) that lets tests control return values and observe calls. Set the public properties `AuthResult`, `RegisterResult`, and `ProfileToReturn` to force specific outcomes; inspect `RegisterInviteCodes` to assert which `inviteCode` values were passed to `RegisterUserAsync`.
## Remarks
This class exposes mutable properties (AuthResult, RegisterResult, ProfileToReturn) that callers set to control the behavior of the corresponding IUserService methods. It also records invite codes passed to RegisterUserAsync in RegisterInviteCodes so tests can assert which invite codes were used. The SuccessResult helper creates a typical successful UserOperationResult with a UserProfileDto for convenience; other operations (UpdateProfileAsync, SetAvatarAsync) are intentionally left to always return a NotFound failure to indicate they are not implemented in this fake.
`FakeUserService` exists as an in-memory test helper to avoid exercising real persistence or external systems. All [`IUserService`](../../EchoHub.Core/Contracts/IUserService.cs.md) methods return completed tasks via `Task.FromResult`, so calls are synchronous from the test's perspective and easy to arrange. Use `SuccessResult` to construct a successful [`UserOperationResult`](../../EchoHub.Core/DTOs/CommonDtos.cs.md) containing a [`UserProfileDto`](../../EchoHub.Core/DTOs/ProfileDtos.cs.md) (it sets `UserStatus.Online`, `ServerRole.Member`, and timestamps using `DateTimeOffset.UtcNow`). The class is intended for unit tests where you need deterministic control over authentication/registration/profile responses and simple verification of arguments.
## Example
```csharp
// Arrange
var svc = new FakeUserService();
var userId = Guid.NewGuid();
svc.AuthResult = FakeUserService.SuccessResult(userId, "alice");
svc.RegisterResult = UserOperationResult.Fail(UserError.AlreadyExists, "already");
// Act
var auth = await svc.AuthenticateUserAsync("alice", "pw");
await svc.RegisterUserAsync("bob", "pw", inviteCode: "INV-123");
// Assert
if (!auth.IsSuccess) throw new Exception("expected success");
// Verify that the invite code passed to RegisterUserAsync was recorded
if (svc.RegisterInviteCodes.Count != 1 || svc.RegisterInviteCodes[0] != "INV-123")
throw new Exception("invite code not recorded");
```
## Notes
- The fake is stateful: AuthResult, RegisterResult, ProfileToReturn and RegisterInviteCodes are mutable. Reset or recreate the FakeUserService between tests to avoid cross-test contamination.
- If AuthResult or RegisterResult are left null, AuthenticateUserAsync and RegisterUserAsync return default Fail results (InvalidCredentials and AlreadyExists respectively) with explanatory messages.
- UpdateProfileAsync and SetAvatarAsync always return a NotFound failure ("Not configured"). They are placeholders rather than working implementations.
- `RegisterInviteCodes` is a plain `List<string?>` that records the raw `inviteCode` argument (including `null`) in call order and is not synchronized; concurrent test runs must not share a single instance without synchronization.
- `SuccessResult` populates timestamps using `DateTimeOffset.UtcNow`, so created [`UserProfileDto`](../../EchoHub.Core/DTOs/ProfileDtos.cs.md) instances will have varying timestamp values; avoid strict equality checks against fixed timestamps.
- [`UpdateProfileAsync`](../../EchoHub.Client/Services/ApiClient.cs.md) and `SetAvatarAsync` always return a failure (`UserError.NotFound` with message "Not configured") unless the test replaces these behaviors; they are placeholders rather than functioning update/asset implementations.
---
@@ -150,17 +159,17 @@ internal sealed class TestDuplexStream : Stream
```
A lightweight in-memory duplex Stream intended for tests: it supplies readable bytes from a preloaded input buffer and captures all written bytes to a separate output buffer that can be inspected. Use this when you need to simulate a readable/writable stream (for example, feeding input to code that reads a Stream and asserting what that code wrote) without interacting with files or the console.
A lightweight in-memory duplex `Stream` intended for tests: it exposes a readable input buffer (populated from the `input` constructor argument) and a separate writable output buffer that callers can inspect via `GetOutput` and `GetOutputLines`. Use `TestDuplexStream` when you need to inject deterministic input into code that reads from a `Stream` and capture what that code writes, without opening real network sockets or files.
## Remarks
This class models a unidirectional read buffer and a separate write buffer so consumers can read a fixed input and concurrently write output without interfering with each other. It intentionally implements only the Stream surface required by simple producers/consumers: reading delegates to an internal MemoryStream created from the provided input string; writing appends to a second MemoryStream. The stream is non-seekable to better emulate pipes or network streams and to discourage tests from relying on seeking behavior.
`TestDuplexStream` intentionally implements only the minimal `Stream` surface needed for typical read/write/flush scenarios in tests. Reads come from the private `_readBuffer` initialized from the constructor `input`, while writes are appended to the private `_writeBuffer` and later returned by `GetOutput`. The class is not seekable (seeking, `Length`, and `Position` throw `NotSupportedException`) because the read and write sides are logically independent buffers rather than a single random-access backing store. The implementation disposes both internal buffers in `Dispose(bool)` so test code should treat a disposed `TestDuplexStream` as unusable.
## Notes
- The stream does not support seeking: Position, Length, Seek and SetLength all throw NotSupportedException.
- GetOutput trims a UTF-8 BOM from the captured bytes because StreamWriter may emit one; tests that rely on raw bytes should use _writeBuffer directly instead of GetOutput (the internal buffer is disposed on Dispose()).
- GetOutputLines splits on the Windows CRLF sequence ("\r\n") and removes empty entries; inputs using only "\n" will not be split by this helper.
- The class is intended for test use and does not provide synchronization; concurrent access from multiple threads is not guaranteed to be safe.
- `GetOutput` strips a leading UTF-8 BOM (the code calls `TrimStart('\uFEFF')`); that handles writers that emit a BOM but also means a deliberate leading U+FEFF in written data will be removed.
- `GetOutputLines` splits on the literal CR+LF sequence (`"\r\n"`) and uses `StringSplitOptions.RemoveEmptyEntries`, so lone `"\n"` line endings or blank lines may not be handled as callers expect.
- Seeking and length-related members are not supported: `Seek`, `SetLength`, `Position` and `Length` throw `NotSupportedException`.
- Reading consumes the provided input buffer; once `Read`/`ReadAsync` drain the `_readBuffer`, subsequent reads return 0 (end-of-stream) unless a new instance is created.
- The class is a test helper and does not provide synchronization for concurrent callers; concurrent reads/writes from multiple threads are not guaranteed to be safe.
---
@@ -173,22 +182,8 @@ internal static class TestIrcConnectionFactory
```
Creates a convenient factory for constructing IrcClientConnection instances that are wired to an in-memory TestDuplexStream, enabling deterministic unit tests of IRC-related behavior without a real network. Use Create to supply a set of incoming lines that the client will read from; the method returns both the constructed IrcClientConnection and the TestDuplexStream so you can inspect what the client writes. Use CreateAuthenticated to obtain a connection that is already registered and authenticated, with nickname/username and a UserId, so tests can focus on post-auth flow without performing login or handshake.
## Remarks
TestIrcConnectionFactory centralizes test harness setup, reducing boilerplate in tests that exercise IRC server interaction. It returns both the connection and the stream to let tests feed input and observe output, including greeting lines or protocol messages. The authenticated variant preconfigures identity and flags (IsRegistered and IsAuthenticated) to simulate a fully connected client, enabling tests that assume a ready-to-use session.
## Example
```csharp
// Example: raw connection with input lines
var (conn, stream) = TestIrcConnectionFactory.Create("PING :server", ":server 001 :Welcome");
// Example: authenticated connection
var (authConn, authStream) = TestIrcConnectionFactory.CreateAuthenticated(nickname: "alice");
```
## Notes
- The factory creates a real TcpClient under the hood; the IrcClientConnection uses that client but all I/O is performed via the in-memory TestDuplexStream, so tests must dispose the resources (the stream and client) when finished to avoid leaks.
- CreateAuthenticated defaults nickname to "alice" and generates a new GUID for UserId if none is supplied; pass explicit values for deterministic testing.
TestIrcConnectionFactory is an internal static test helper that creates [`IrcClientConnection`](../../EchoHub.Server.Irc/IrcClientConnection.cs.md) instances backed by a `TestDuplexStream` for unit testing. It provides two entry points: `Create`, which builds a new connection wired to an in-memory duplex stream seeded with the supplied input lines; and `CreateAuthenticated`, which builds a pre-authenticated, registered connection by populating identity fields and authentication flags. The input lines are joined with `
` and a trailing `
` is appended if any lines are provided, simulating lines received from an IRC server. The returned tuple gives tests both the [`IrcClientConnection`](../../EchoHub.Server.Irc/IrcClientConnection.cs.md) and the `TestDuplexStream`, enabling observation of outgoing data and control of inbound data.
---