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
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
using OpenCode.Sdk.Tests.Credentials;
using OpenCode.Sdk.Tests.Debug;
using OpenCode.Sdk.Tests.Experimental;
using OpenCode.Sdk.Tests.FileSystem;
using OpenCode.Sdk.Tests.Forms;
using OpenCode.Sdk.Tests.Harness;
using OpenCode.Sdk.Tests.Integrations;
using OpenCode.Sdk.Tests.Support;
using OpenCode.Sdk.Tests.Worktrees;

Expand All @@ -23,6 +25,8 @@ .. CredentialsDeclaredErrors.Rows(),
.. DebugDeclaredErrors.Rows(),
.. ExperimentalDeclaredErrors.Rows(),
.. FormsDeclaredErrors.Rows(),
.. FileSystemDeclaredErrors.Rows(),
.. IntegrationsDeclaredErrors.Rows(),
];

[Test]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,31 +52,6 @@ await Assert.That(scenario.Requests.Single().RequestUri!.AbsoluteUri)
.IsEqualTo("http://localhost:4096/api/fs/list?location[directory]=%2Frepo&path=src");
}

[Test]
public async Task ListEntriesAsync_Should_Throw_The_Declared_400_Error()
{
using var scenario = ContractScenario.Responding(HttpStatusCode.BadRequest, WireBodyData.InvalidRequestError);

var exception = await Assert
.That(async () => _ = await scenario.Client.FileSystem.ListEntriesAsync())
.Throws<OpenCodeApiException>();

await Assert.That(exception!.Status).IsEqualTo(400);
await Assert.That(exception.Error).IsTypeOf<InvalidRequestError>();
}

[Test]
public async Task ListEntriesAsync_Should_Return_The_401_Error_On_The_NoThrow_Spine()
{
using var scenario = ContractScenario.Responding(HttpStatusCode.Unauthorized, WireBodyData.UnauthorizedError);

var response = await scenario.Client.FileSystem.ListEntriesAsync(requestOptions: OpenCodeRequestOptions.NoThrow);

await Assert.That(response.IsError).IsTrue();
await Assert.That(response.Status).IsEqualTo(401);
await Assert.That(response.Error).IsTypeOf<UnauthorizedError>();
}

[Test]
public async Task FindEntriesAsync_Should_Return_The_Typed_Entries_With_Their_Location()
{
Expand Down Expand Up @@ -109,33 +84,6 @@ await Assert.That(scenario.Requests.Single().RequestUri!.AbsoluteUri)
.IsEqualTo("http://localhost:4096/api/fs/find?query=todo&type=directory&limit=10");
}

[Test]
public async Task FindEntriesAsync_Should_Throw_The_Declared_400_Error()
{
using var scenario = ContractScenario.Responding(HttpStatusCode.BadRequest, WireBodyData.InvalidRequestError);

var exception = await Assert
.That(async () => _ = await scenario.Client.FileSystem.FindEntriesAsync(new FsFindRequest { Query = "todo" }))
.Throws<OpenCodeApiException>();

await Assert.That(exception!.Status).IsEqualTo(400);
await Assert.That(exception.Error).IsTypeOf<InvalidRequestError>();
}

[Test]
public async Task FindEntriesAsync_Should_Return_The_401_Error_On_The_NoThrow_Spine()
{
using var scenario = ContractScenario.Responding(HttpStatusCode.Unauthorized, WireBodyData.UnauthorizedError);

var response = await scenario.Client.FileSystem.FindEntriesAsync(
new FsFindRequest { Query = "todo" },
OpenCodeRequestOptions.NoThrow);

await Assert.That(response.IsError).IsTrue();
await Assert.That(response.Status).IsEqualTo(401);
await Assert.That(response.Error).IsTypeOf<UnauthorizedError>();
}

/// <summary>
/// A file is raw bytes, not text: bytes that are not valid UTF-8 come back unchanged, beside
/// the Content-Type the server declared from the file's extension.
Expand Down
59 changes: 59 additions & 0 deletions tests/OpenCode.Sdk.Tests/FileSystem/FileSystemDeclaredErrors.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using System.Net;
using OpenCode.Sdk.Models;
using OpenCode.Sdk.Tests.Common.Support;
using OpenCode.Sdk.Tests.Support;

namespace OpenCode.Sdk.Tests.FileSystem;

public static class FileSystemDeclaredErrors
{
private static readonly DeclaredErrorDoor ListEntriesDoor = new(
nameof(FileSystemClient.ListEntriesAsync),
"fs.list",
"get",
"/api/fs/list",
static async (client, options) => await client.FileSystem.ListEntriesAsync(requestOptions: options));

private static readonly DeclaredErrorDoor FindEntriesDoor = new(
nameof(FileSystemClient.FindEntriesAsync),
"fs.find",
"get",
"/api/fs/find",
static async (client, options) => await client.FileSystem.FindEntriesAsync(new FsFindRequest { Query = "todo" }, options));

public static IEnumerable<Func<DeclaredErrorCase>> Rows() =>
[
static () => new(
"fs.list:400:InvalidRequestError",
ListEntriesDoor,
HttpStatusCode.BadRequest,
WireBodyData.InvalidRequestError,
"InvalidRequestError",
typeof(InvalidRequestError),
"#/paths/~1api~1fs~1list/get/responses/400/content/application~1json/schema"),
static () => new(
"fs.list:401:UnauthorizedError",
ListEntriesDoor,
HttpStatusCode.Unauthorized,
WireBodyData.UnauthorizedError,
"UnauthorizedError",
typeof(UnauthorizedError),
"#/paths/~1api~1fs~1list/get/responses/401/content/application~1json/schema"),
static () => new(
"fs.find:400:InvalidRequestError",
FindEntriesDoor,
HttpStatusCode.BadRequest,
WireBodyData.InvalidRequestError,
"InvalidRequestError",
typeof(InvalidRequestError),
"#/paths/~1api~1fs~1find/get/responses/400/content/application~1json/schema"),
static () => new(
"fs.find:401:UnauthorizedError",
FindEntriesDoor,
HttpStatusCode.Unauthorized,
WireBodyData.UnauthorizedError,
"UnauthorizedError",
typeof(UnauthorizedError),
"#/paths/~1api~1fs~1find/get/responses/401/content/application~1json/schema"),
];
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ await Assert.That(scenario.Requests.Single().RequestUri)
}

[Test]
public async Task GetIntegrationAsync_Should_Return_The_Typed_Integration()
public async Task GetAsync_Should_Return_The_Typed_Integration()
{
const string integration = "{\"id\":\"int_1\",\"name\":\"GitHub\",\"methods\":[],\"connections\":[]}";
using var scenario = ContractScenario.Responding(HttpStatusCode.OK, WireBodyData.LocationEnvelope(integration));
Expand All @@ -41,7 +41,7 @@ await Assert.That(scenario.Requests.Single().RequestUri)
}

[Test]
public async Task GetIntegrationAsync_Should_Throw_The_Declared_404_When_The_Integration_Is_Unknown()
public async Task GetAsync_Should_Throw_The_Declared_404_When_The_Integration_Is_Unknown()
{
using var scenario = ContractScenario.Responding(HttpStatusCode.NotFound, WireBodyData.IntegrationNotFoundError);

Expand All @@ -55,33 +55,7 @@ public async Task GetIntegrationAsync_Should_Throw_The_Declared_404_When_The_Int
}

[Test]
public async Task GetIntegrationAsync_Should_Throw_The_Declared_400_Error()
{
using var scenario = ContractScenario.Responding(HttpStatusCode.BadRequest, WireBodyData.InvalidRequestError);

var exception = await Assert
.That(async () => _ = await scenario.Client.Integrations.GetIntegrationClient("int_1").GetAsync())
.Throws<OpenCodeApiException>();

await Assert.That(exception!.Status).IsEqualTo(400);
await Assert.That(exception.Error).IsTypeOf<InvalidRequestError>();
}

[Test]
public async Task GetIntegrationAsync_Should_Return_The_401_Error_On_The_NoThrow_Spine()
{
using var scenario = ContractScenario.Responding(HttpStatusCode.Unauthorized, WireBodyData.UnauthorizedError);

var response = await scenario.Client.Integrations.GetIntegrationClient("int_1")
.GetAsync(requestOptions: OpenCodeRequestOptions.NoThrow);

await Assert.That(response.IsError).IsTrue();
await Assert.That(response.Status).IsEqualTo(401);
await Assert.That(response.Error).IsTypeOf<UnauthorizedError>();
}

[Test]
public async Task PostConnectKeyAsync_Should_Send_The_Typed_Body_On_The_Handle_Route()
public async Task ConnectWithKeyAsync_Should_Send_The_Typed_Body_On_The_Handle_Route()
{
using var scenario = ContractScenario.Responding(HttpStatusCode.NoContent, string.Empty);

Expand All @@ -96,35 +70,7 @@ public async Task PostConnectKeyAsync_Should_Send_The_Typed_Body_On_The_Handle_R
}

[Test]
public async Task PostConnectKeyAsync_Should_Throw_The_Declared_400_Error()
{
using var scenario = ContractScenario.Responding(HttpStatusCode.BadRequest, WireBodyData.InvalidRequestError);

var exception = await Assert
.That(async () => _ = await scenario.Client.Integrations.GetIntegrationClient("int_1")
.ConnectWithKeyAsync(new IntegrationConnectKeyRequest { Key = "sk-test" }))
.Throws<OpenCodeApiException>();

await Assert.That(exception!.Status).IsEqualTo(400);
await Assert.That(exception.Error).IsTypeOf<InvalidRequestError>();
}

[Test]
public async Task PostConnectKeyAsync_Should_Return_The_401_Error_On_The_NoThrow_Spine()
{
using var scenario = ContractScenario.Responding(HttpStatusCode.Unauthorized, WireBodyData.UnauthorizedError);

var response = await scenario.Client.Integrations.GetIntegrationClient("int_1").ConnectWithKeyAsync(
new IntegrationConnectKeyRequest { Key = "sk-test" },
requestOptions: OpenCodeRequestOptions.NoThrow);

await Assert.That(response.IsError).IsTrue();
await Assert.That(response.Status).IsEqualTo(401);
await Assert.That(response.Error).IsTypeOf<UnauthorizedError>();
}

[Test]
public async Task PostOAuthConnectAsync_Should_Return_The_Typed_Attempt()
public async Task BeginOAuthConnectionAsync_Should_Return_The_Typed_Attempt()
{
const string attempt = "{\"attemptID\":\"att_1\",\"url\":\"https://example.test/authorize\","
+ "\"instructions\":\"Open the link\",\"mode\":\"auto\",\"time\":{\"created\":1,\"expires\":2}}";
Expand All @@ -141,31 +87,4 @@ await Assert.That(scenario.Requests.Single().RequestUri)
await Assert.That(scenario.Requests.Single().Body).IsEqualTo("{\"methodID\":\"github\"}");
}

[Test]
public async Task PostOAuthConnectAsync_Should_Throw_The_Declared_400_Error()
{
using var scenario = ContractScenario.Responding(HttpStatusCode.BadRequest, WireBodyData.InvalidRequestError);

var exception = await Assert
.That(async () => _ = await scenario.Client.Integrations.GetIntegrationClient("int_1")
.BeginOAuthConnectionAsync(new IntegrationOAuthConnectRequest { MethodId = "github" }))
.Throws<OpenCodeApiException>();

await Assert.That(exception!.Status).IsEqualTo(400);
await Assert.That(exception.Error).IsTypeOf<InvalidRequestError>();
}

[Test]
public async Task PostOAuthConnectAsync_Should_Return_The_401_Error_On_The_NoThrow_Spine()
{
using var scenario = ContractScenario.Responding(HttpStatusCode.Unauthorized, WireBodyData.UnauthorizedError);

var response = await scenario.Client.Integrations.GetIntegrationClient("int_1").BeginOAuthConnectionAsync(
new IntegrationOAuthConnectRequest { MethodId = "github" },
requestOptions: OpenCodeRequestOptions.NoThrow);

await Assert.That(response.IsError).IsTrue();
await Assert.That(response.Status).IsEqualTo(401);
await Assert.That(response.Error).IsTypeOf<UnauthorizedError>();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Net;
using OpenCode.Sdk.Models;
using OpenCode.Sdk.Tests.Support;

namespace OpenCode.Sdk.Tests.Integrations;
Expand Down Expand Up @@ -45,28 +44,4 @@ public async Task ListIntegrationsAsync_Should_Return_An_Empty_List()
await Assert.That(response.Integrations).IsEmpty();
}

[Test]
public async Task ListIntegrationsAsync_Should_Throw_The_Declared_400_Error()
{
using var scenario = ContractScenario.Responding(HttpStatusCode.BadRequest, WireBodyData.InvalidRequestError);

var exception = await Assert
.That(async () => _ = await scenario.Client.Integrations.ListIntegrationsAsync())
.Throws<OpenCodeApiException>();

await Assert.That(exception!.Status).IsEqualTo(400);
await Assert.That(exception.Error).IsTypeOf<InvalidRequestError>();
}

[Test]
public async Task ListIntegrationsAsync_Should_Return_The_401_Error_On_The_NoThrow_Spine()
{
using var scenario = ContractScenario.Responding(HttpStatusCode.Unauthorized, WireBodyData.UnauthorizedError);

var response = await scenario.Client.Integrations.ListIntegrationsAsync(requestOptions: OpenCodeRequestOptions.NoThrow);

await Assert.That(response.IsError).IsTrue();
await Assert.That(response.Status).IsEqualTo(401);
await Assert.That(response.Error).IsTypeOf<UnauthorizedError>();
}
}
Loading
Loading