Files

153 lines
5.0 KiB
C#
Raw Permalink Normal View History

2026-08-12 14:04:55 +03:00
using RudderSdk.Core;
using RudderSdk.Core.Abstractions;
using RudderSdk.Core.Models.Auth;
using Xunit;
namespace RudderSdk.Core.Tests;
public sealed class RudderClientTests
{
[Fact]
public void Constructor_Composes_All_Runtime_Services()
{
var client = CreateClient();
Assert.NotNull(client.Auth);
Assert.NotNull(client.Player);
Assert.NotNull(client.RemoteConfig);
Assert.NotNull(client.Storage);
Assert.NotNull(client.Stores);
Assert.NotNull(client.Leaderboards);
Assert.NotNull(client.Inventory);
Assert.NotNull(client.BattlePass);
Assert.NotNull(client.Quests);
Assert.NotNull(client.Scenario);
Assert.NotNull(client.Effects);
2026-08-12 14:04:55 +03:00
}
[Fact]
public void Constructor_Requires_BaseUrl_And_ProjectKey()
{
Assert.Throws<ArgumentException>(() => new RudderClient(new RudderClientOptions { ProjectKey = "key" }));
Assert.Throws<ArgumentException>(() => new RudderClient(new RudderClientOptions { BaseUrl = "http://localhost" }));
}
[Fact]
public void Constructor_Uses_HttpClientTransport_By_Default()
{
var client = new RudderClient(new RudderClientOptions
{
BaseUrl = "http://localhost:8082",
ProjectKey = "project-key"
});
Assert.NotNull(client);
}
[Fact]
public async Task Auth_LoginWithDevice_Saves_Tokens_And_Raises_SignedIn()
{
var transport = new FakeTransport();
transport.Responses[typeof(LoginViaDeviceResponse)] = new LoginViaDeviceResponse
{
AccessToken = "access-token",
RefreshToken = "refresh-token"
};
var tokenStore = new FakeTokenStore();
var client = CreateClient(transport: transport, tokenStore: tokenStore);
var states = new List<RudderAuthState>();
client.Auth.AuthStateChanged += states.Add;
await client.Auth.LoginWithDeviceAsync("en", "en", "nickname");
var request = Assert.IsType<LoginViaDeviceRequest>(transport.LastRequest);
Assert.Equal("POST", transport.LastMethod);
Assert.Equal("/sdk/v1/authorization/device", transport.LastPath);
Assert.Equal("nickname", request.Nickname);
Assert.Equal("access-token", tokenStore.AccessToken);
Assert.Equal("refresh-token", tokenStore.RefreshToken);
Assert.Equal(new[] { RudderAuthState.SignedIn }, states);
}
[Fact]
public void Auth_Logout_Clears_Tokens_And_Raises_SignedOut()
{
var tokenStore = new FakeTokenStore { AccessToken = "a", RefreshToken = "r" };
var client = CreateClient(tokenStore: tokenStore);
var states = new List<RudderAuthState>();
client.Auth.AuthStateChanged += states.Add;
client.Auth.Logout();
Assert.Null(tokenStore.AccessToken);
Assert.Null(tokenStore.RefreshToken);
Assert.Equal(new[] { RudderAuthState.SignedOut }, states);
}
private static RudderClient CreateClient(
FakeTransport? transport = null,
FakeTokenStore? tokenStore = null)
2026-08-12 14:04:55 +03:00
{
return new RudderClient(new RudderClientOptions
{
BaseUrl = "http://localhost:8082",
ProjectKey = "project-key",
Transport = transport ?? new FakeTransport(),
TokenStore = tokenStore ?? new FakeTokenStore(),
DeviceIdProvider = new FakeDeviceIdProvider()
2026-08-12 14:04:55 +03:00
});
}
internal sealed class FakeTransport : IRudderTransport
{
public Dictionary<Type, object> Responses { get; } = new();
public string? LastMethod { get; private set; }
public string? LastPath { get; private set; }
public object? LastRequest { get; private set; }
public string? LastAccessToken { get; private set; }
public Task<TResponse> SendAsync<TRequest, TResponse>(
string method,
string path,
TRequest? request,
string? accessToken,
CancellationToken cancellationToken = default)
{
LastMethod = method;
LastPath = path;
LastRequest = request;
LastAccessToken = accessToken;
if (Responses.TryGetValue(typeof(TResponse), out var response))
return Task.FromResult((TResponse)response);
return Task.FromResult(default(TResponse)!);
}
}
internal sealed class FakeTokenStore : ITokenStore
{
public string? AccessToken { get; set; }
public string? RefreshToken { get; set; }
public string? GetAccessToken() => AccessToken;
public string? GetRefreshToken() => RefreshToken;
public void SaveTokens(string accessToken, string refreshToken)
{
AccessToken = accessToken;
RefreshToken = refreshToken;
}
public void Clear()
{
AccessToken = null;
RefreshToken = null;
}
}
private sealed class FakeDeviceIdProvider : IDeviceIdProvider
{
public string DeviceId => "device-id";
}
}