mirror of
https://github.com/alexhopeoconnor/binarylane-dotnet.git
synced 2026-10-04 02:18:11 +10:00
158 lines
6.2 KiB
C#
158 lines
6.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Net;
|
|
using System.Net.Http;
|
|
using System.Text.Json;
|
|
using System.Threading.Tasks;
|
|
using BinaryLane.Api.V2;
|
|
using BinaryLane.Api.V2.Authentication;
|
|
using BinaryLane.Api.V2.Models;
|
|
using Xunit;
|
|
|
|
namespace BinaryLane.Api.Tests;
|
|
|
|
public sealed class ClientResourceTests
|
|
{
|
|
[Fact]
|
|
public async Task ServersListAllFollowsTheProviderNextPageLink()
|
|
{
|
|
var requestCount = 0;
|
|
using var httpClient = new HttpClient(new HttpClientTestHandler((request, _) =>
|
|
{
|
|
requestCount++;
|
|
var json = request.RequestUri!.Query.Contains("page=2", StringComparison.Ordinal)
|
|
? "{\"meta\":{\"total\":2},\"links\":{\"pages\":{}},\"servers\":[{\"id\":2,\"name\":\"two\",\"status\":\"active\"}]}"
|
|
: "{\"meta\":{\"total\":2},\"links\":{\"pages\":{\"next\":\"/v2/servers?page=2\"}},\"servers\":[{\"id\":1,\"name\":\"one\",\"status\":\"active\"}]}";
|
|
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(json) });
|
|
}))
|
|
{
|
|
BaseAddress = new Uri("https://api.example.test/"),
|
|
};
|
|
var client = new BinaryLaneClient(httpClient, new StaticBinaryLaneTokenProvider("token"));
|
|
var servers = new List<Server>();
|
|
|
|
await foreach (var server in client.Servers.ListAllAsync())
|
|
{
|
|
servers.Add(server);
|
|
}
|
|
|
|
Assert.Equal(2, requestCount);
|
|
Assert.Collection(
|
|
servers,
|
|
server => Assert.Equal("one", server.Name),
|
|
server => Assert.Equal("two", server.Name));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ServersListAllStopsWhenTheProviderRepeatsANextPageLink()
|
|
{
|
|
var requestCount = 0;
|
|
using var httpClient = new HttpClient(new HttpClientTestHandler((_, _) =>
|
|
{
|
|
requestCount++;
|
|
const string json = "{\"meta\":{\"total\":1},\"links\":{\"pages\":{\"next\":\"/v2/servers?page=1\"}},\"servers\":[{\"id\":1,\"name\":\"one\",\"status\":\"active\"}]}";
|
|
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(json) });
|
|
}))
|
|
{
|
|
BaseAddress = new Uri("https://api.example.test/"),
|
|
};
|
|
var client = new BinaryLaneClient(httpClient, new StaticBinaryLaneTokenProvider("token"));
|
|
|
|
var exception = await Assert.ThrowsAsync<InvalidOperationException>(async () =>
|
|
{
|
|
await foreach (var _ in client.Servers.ListAllAsync())
|
|
{
|
|
}
|
|
});
|
|
|
|
Assert.Contains("repeated pagination link", exception.Message, StringComparison.Ordinal);
|
|
Assert.Equal(2, requestCount);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task SubmitActionUsesRealActionsEndpointAndReportsAcceptedStatus()
|
|
{
|
|
HttpRequestMessage? received = null;
|
|
string? body = null;
|
|
using var httpClient = new HttpClient(new HttpClientTestHandler(async (request, cancellationToken) =>
|
|
{
|
|
received = request;
|
|
body = request.Content is null ? null : await request.Content.ReadAsStringAsync(cancellationToken);
|
|
return new HttpResponseMessage(HttpStatusCode.Accepted)
|
|
{
|
|
Content = new StringContent("{\"action\":{\"id\":9,\"type\":\"power_on\",\"status\":\"in-progress\",\"started_at\":\"2026-01-01T00:00:00Z\"}}"),
|
|
};
|
|
}))
|
|
{
|
|
BaseAddress = new Uri("https://api.example.test/"),
|
|
};
|
|
var client = new BinaryLaneClient(httpClient, new StaticBinaryLaneTokenProvider("token"));
|
|
|
|
var submission = await client.Servers.SubmitActionAsync(123, new PowerOnServerAction());
|
|
|
|
Assert.NotNull(received);
|
|
Assert.Equal("/v2/servers/123/actions", received!.RequestUri!.AbsolutePath);
|
|
Assert.Equal("POST", received.Method.Method);
|
|
Assert.Contains("\"type\":\"power_on\"", body!, StringComparison.Ordinal);
|
|
Assert.True(submission.IsAccepted);
|
|
Assert.Equal(9, submission.Action!.Id);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ListEndpointsRejectAResponseWithoutTheExpectedCollectionEnvelope()
|
|
{
|
|
using var httpClient = new HttpClient(new HttpClientTestHandler((_, _) =>
|
|
Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)
|
|
{
|
|
Content = new StringContent("{\"meta\":{\"total\":0},\"wrong_collection\":[]}"),
|
|
})))
|
|
{
|
|
BaseAddress = new Uri("https://api.example.test/"),
|
|
};
|
|
var client = new BinaryLaneClient(httpClient, new StaticBinaryLaneTokenProvider("token"));
|
|
|
|
var exception = await Assert.ThrowsAsync<JsonException>(() => client.Servers.ListAsync());
|
|
|
|
Assert.Contains("servers", exception.Message, StringComparison.Ordinal);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task UserDataUsesTheDocumentedDirectResponseBody()
|
|
{
|
|
using var httpClient = new HttpClient(new HttpClientTestHandler((request, _) =>
|
|
{
|
|
Assert.Equal("/v2/servers/123/user_data", request.RequestUri!.AbsolutePath);
|
|
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)
|
|
{
|
|
Content = new StringContent("{\"user_data\":\"#cloud-config\"}"),
|
|
});
|
|
}))
|
|
{
|
|
BaseAddress = new Uri("https://api.example.test/"),
|
|
};
|
|
var client = new BinaryLaneClient(httpClient, new StaticBinaryLaneTokenProvider("token"));
|
|
|
|
var userData = await client.Servers.GetUserDataAsync(123);
|
|
|
|
Assert.Equal("#cloud-config", userData.Value);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ListEndpointsRejectNullItemsRatherThanSilentlyDroppingThem()
|
|
{
|
|
using var httpClient = new HttpClient(new HttpClientTestHandler((_, _) =>
|
|
Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)
|
|
{
|
|
Content = new StringContent("{\"meta\":{\"total\":1},\"servers\":[null]}"),
|
|
})))
|
|
{
|
|
BaseAddress = new Uri("https://api.example.test/"),
|
|
};
|
|
var client = new BinaryLaneClient(httpClient, new StaticBinaryLaneTokenProvider("token"));
|
|
|
|
var exception = await Assert.ThrowsAsync<JsonException>(() => client.Servers.ListAsync());
|
|
|
|
Assert.Contains("servers", exception.Message, StringComparison.Ordinal);
|
|
}
|
|
}
|