Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions src/WayfarerMobile.Core/Interfaces/ISseClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,6 @@ public interface ISseClient : IDisposable

#region Methods

/// <summary>
/// Subscribe to per-user SSE channel for location updates.
/// </summary>
/// <param name="userName">Username to subscribe to.</param>
/// <param name="cancellationToken">Token to cancel the subscription.</param>
/// <returns>Task that completes when subscription ends.</returns>
Task SubscribeToUserAsync(string userName, CancellationToken cancellationToken = default);

/// <summary>
/// Subscribe to consolidated group SSE channel for location and membership updates.
/// All event types (location, visibility-changed, member-left, etc.) come through this single stream.
Expand Down
2 changes: 1 addition & 1 deletion src/WayfarerMobile.Core/Models/SseEventModels.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ namespace WayfarerMobile.Core.Models;

/// <summary>
/// SSE event for location updates.
/// Received from channels: location-update-{userName} or group-{groupId} (consolidated)
/// Received from the consolidated group-{groupId} channel.
/// </summary>
public class SseLocationEvent
{
Expand Down
20 changes: 0 additions & 20 deletions src/WayfarerMobile/Services/SseClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,26 +125,6 @@ public SseClient(

#region Public Methods

/// <inheritdoc />
public async Task SubscribeToUserAsync(string userName, CancellationToken cancellationToken = default)
{
if (string.IsNullOrWhiteSpace(userName))
{
_logger.LogWarning("Cannot subscribe to SSE: userName is empty");
return;
}

string? serverUrl = _settings.ServerUrl;
if (string.IsNullOrWhiteSpace(serverUrl))
{
_logger.LogError("Server URL not configured for SSE subscription");
return;
}

string url = $"{serverUrl.TrimEnd('/')}/api/mobile/sse/location-update/{Uri.EscapeDataString(userName)}";
await SubscribeAsync(url, $"user:{userName}", cancellationToken).ConfigureAwait(false);
}

/// <inheritdoc />
public async Task SubscribeToGroupAsync(string groupId, CancellationToken cancellationToken = default)
{
Expand Down
54 changes: 2 additions & 52 deletions tests/WayfarerMobile.Tests/Unit/Services/SseClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -161,47 +161,6 @@ public void Reconnecting_CanSubscribeAndUnsubscribe()
eventRaised.Should().BeFalse();
}

[Fact]
public async Task SubscribeToUserAsync_EmptyUserName_LogsWarningAndReturns()
{
var client = CreateClient();
await client.SubscribeToUserAsync(string.Empty);
client.IsConnected.Should().BeFalse();
}

[Fact]
public async Task SubscribeToUserAsync_NoServerUrl_LogsErrorAndReturns()
{
_mockSettings.Setup(s => s.ServerUrl).Returns((string?)null);
var client = CreateClient();
await client.SubscribeToUserAsync("testuser");
client.IsConnected.Should().BeFalse();
}

[Fact]
public async Task SubscribeToUserAsync_ValidUserName_BuildsCorrectUrl()
{
_mockSettings.Setup(s => s.ServerUrl).Returns("https://api.example.com");
string? capturedUrl = null;

_mockHttpHandler
.Protected()
.Setup<Task<HttpResponseMessage>>(
"SendAsync",
ItExpr.IsAny<HttpRequestMessage>(),
ItExpr.IsAny<CancellationToken>())
.Callback<HttpRequestMessage, CancellationToken>((req, _) => capturedUrl = req.RequestUri?.ToString())
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent("") });

var client = CreateClient();
using var cts = new CancellationTokenSource(100);
try { await client.SubscribeToUserAsync("testuser", cts.Token); }
catch (OperationCanceledException) { }
catch (HttpRequestException) { }

capturedUrl.Should().Be("https://api.example.com/api/mobile/sse/location-update/testuser");
}

[Fact]
public async Task SubscribeToGroupAsync_EmptyGroupId_LogsWarningAndReturns()
{
Expand Down Expand Up @@ -252,7 +211,7 @@ public async Task Subscribe_SetsAuthorizationHeader()

var client = CreateClient();
using var cts = new CancellationTokenSource(100);
try { await client.SubscribeToUserAsync("testuser", cts.Token); }
try { await client.SubscribeToGroupAsync("group-abc-123", cts.Token); }
catch (OperationCanceledException) { }
catch (HttpRequestException) { }

Expand All @@ -277,7 +236,7 @@ public async Task Subscribe_SetsAcceptHeader()

var client = CreateClient();
using var cts = new CancellationTokenSource(100);
try { await client.SubscribeToUserAsync("testuser", cts.Token); }
try { await client.SubscribeToGroupAsync("group-abc-123", cts.Token); }
catch (OperationCanceledException) { }
catch (HttpRequestException) { }

Expand Down Expand Up @@ -535,15 +494,6 @@ public TestSseClient(ISettingsService settings, ILogger<TestSseClient> logger, I
_httpClientFactory = httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory));
}

public Task SubscribeToUserAsync(string userName, CancellationToken cancellationToken = default)
{
if (string.IsNullOrWhiteSpace(userName)) { _logger.LogWarning("userName is empty"); return Task.CompletedTask; }
var serverUrl = _settings.ServerUrl;
if (string.IsNullOrWhiteSpace(serverUrl)) { _logger.LogError("Server URL not configured"); return Task.CompletedTask; }
var url = serverUrl.TrimEnd((char)47) + "/api/mobile/sse/location-update/" + Uri.EscapeDataString(userName);
return SubscribeAsync(url, "user:" + userName, cancellationToken);
}

public Task SubscribeToGroupAsync(string groupId, CancellationToken cancellationToken = default)
{
if (string.IsNullOrWhiteSpace(groupId)) { _logger.LogWarning("groupId is empty"); return Task.CompletedTask; }
Expand Down
Loading