test(canvas/store): add arrangeChildren coverage — sort, slot, and API PATCH #1293
@@ -1224,3 +1224,117 @@ describe("moveNode", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("arrangeChildren", () => {
|
||||
it("is a no-op when the parent has no children", () => {
|
||||
useCanvasStore.getState().hydrate([
|
||||
makeWS({ id: "parent", name: "Parent", x: 100, y: 200 }),
|
||||
]);
|
||||
expect(() => useCanvasStore.getState().arrangeChildren("parent")).not.toThrow();
|
||||
// No fetch calls should be made
|
||||
expect(global.fetch).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("sorts children by name and assigns default slot positions", () => {
|
||||
// Children are: Bob, Alice — after localeSort: Alice(0), Bob(1)
|
||||
// defaultChildSlot(0) = {x: 16, y: 130} (PARENT_SIDE_PADDING, PARENT_HEADER_PADDING)
|
||||
// defaultChildSlot(1) = {x: 270, y: 130} (16 + 240 + 14, 130)
|
||||
useCanvasStore.getState().hydrate([
|
||||
makeWS({ id: "parent", name: "Parent", x: 100, y: 200 }),
|
||||
makeWS({ id: "ws-bob", name: "Bob", x: 0, y: 0, parent_id: "parent" }),
|
||||
makeWS({ id: "ws-alice", name: "Alice", x: 0, y: 0, parent_id: "parent" }),
|
||||
]);
|
||||
|
||||
useCanvasStore.getState().arrangeChildren("parent");
|
||||
|
||||
const nodes = useCanvasStore.getState().nodes;
|
||||
const alice = nodes.find((n) => n.id === "ws-alice")!;
|
||||
const bob = nodes.find((n) => n.id === "ws-bob")!;
|
||||
|
||||
// Alice is first alphabetically → index 0 → {x: 16, y: 130}
|
||||
expect(alice.position).toEqual({ x: 16, y: 130 });
|
||||
// Bob is second alphabetically → index 1 → {x: 270, y: 130}
|
||||
expect(bob.position).toEqual({ x: 270, y: 130 });
|
||||
});
|
||||
|
||||
it("PATCHes each child with absolute canvas coordinates (parent position + slot)", async () => {
|
||||
// Parent at (100, 200). Alice slot = {x: 16, y: 130}.
|
||||
// absX = 16 + 100 = 116, absY = 130 + 200 = 330.
|
||||
const mock = global.fetch as ReturnType<typeof vi.fn>;
|
||||
useCanvasStore.getState().hydrate([
|
||||
makeWS({ id: "parent", name: "Parent", x: 100, y: 200 }),
|
||||
makeWS({ id: "ws-alice", name: "Alice", x: 0, y: 0, parent_id: "parent" }),
|
||||
]);
|
||||
|
||||
useCanvasStore.getState().arrangeChildren("parent");
|
||||
|
||||
await vi.waitFor(() => {
|
||||
expect(mock).toHaveBeenCalledWith(
|
||||
expect.stringContaining("/workspaces/ws-alice"),
|
||||
expect.objectContaining({
|
||||
method: "PATCH",
|
||||
body: JSON.stringify({ x: 116, y: 330 }),
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("setCollapsed", () => {
|
||||
it("collapsing a parent hides its direct child", () => {
|
||||
// parentMinSizeFromChildren([{width:240, height:130}]) = {width: 560, height: 302}
|
||||
useCanvasStore.getState().hydrate([
|
||||
makeWS({ id: "parent", name: "Parent" }),
|
||||
makeWS({ id: "child", name: "Child", parent_id: "parent" }),
|
||||
]);
|
||||
// Manually set parent size so it has an expanded size
|
||||
useCanvasStore.setState({
|
||||
nodes: useCanvasStore.getState().nodes.map((n) =>
|
||||
n.id === "parent" ? { ...n, width: 560, height: 302 } : n,
|
||||
),
|
||||
});
|
||||
|
||||
useCanvasStore.getState().setCollapsed("parent", true);
|
||||
|
||||
const parent = useCanvasStore.getState().nodes.find((n) => n.id === "parent")!;
|
||||
const child = useCanvasStore.getState().nodes.find((n) => n.id === "child")!;
|
||||
|
||||
expect(parent.data.collapsed).toBe(true);
|
||||
expect(parent.width).toBe(240); // CHILD_DEFAULT_WIDTH
|
||||
expect(parent.height).toBe(130); // CHILD_DEFAULT_HEIGHT
|
||||
expect(child.hidden).toBe(true); // child is hidden because parent is collapsed
|
||||
});
|
||||
|
||||
it("expanding a parent reveals its direct child", () => {
|
||||
useCanvasStore.getState().hydrate([
|
||||
makeWS({ id: "parent", name: "Parent" }),
|
||||
makeWS({ id: "child", name: "Child", parent_id: "parent" }),
|
||||
]);
|
||||
useCanvasStore.setState({
|
||||
nodes: useCanvasStore.getState().nodes.map((n) =>
|
||||
n.id === "parent"
|
||||
? { ...n, width: 240, height: 130, data: { ...n.data, collapsed: true } }
|
||||
: n,
|
||||
),
|
||||
});
|
||||
|
||||
useCanvasStore.getState().setCollapsed("parent", false);
|
||||
|
||||
const parent = useCanvasStore.getState().nodes.find((n) => n.id === "parent")!;
|
||||
const child = useCanvasStore.getState().nodes.find((n) => n.id === "child")!;
|
||||
|
||||
expect(parent.data.collapsed).toBe(false);
|
||||
expect(child.hidden).toBe(false); // child is visible when parent is expanded
|
||||
});
|
||||
|
||||
it("is a no-op for a non-existent parentId", () => {
|
||||
useCanvasStore.getState().hydrate([
|
||||
makeWS({ id: "parent", name: "Parent" }),
|
||||
makeWS({ id: "child", name: "Child", parent_id: "parent" }),
|
||||
]);
|
||||
// Should not throw even when parentId doesn't exist
|
||||
expect(() => useCanvasStore.getState().setCollapsed("nonexistent", true)).not.toThrow();
|
||||
// Nodes should be unchanged
|
||||
expect(useCanvasStore.getState().nodes).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/DATA-DOG/go-sqlmock"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// TestExtractExpiresInSeconds covers the JSON parser used at enqueue time
|
||||
@@ -58,3 +67,361 @@ func TestExtractExpiresInSeconds(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// ─── QueueDepth ─────────────────────────────────────────────────────────────
|
||||
|
||||
// TestQueueDepth_Success verifies QueueDepth returns the COUNT of queued items
|
||||
// for a workspace.
|
||||
func TestQueueDepth_Success(t *testing.T) {
|
||||
mock := setupTestDB(t)
|
||||
|
||||
mock.ExpectQuery(`SELECT COUNT\(\*\) FROM a2a_queue WHERE workspace_id = \$1 AND status = 'queued'`).
|
||||
WithArgs("ws-queue-depth-1").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(7))
|
||||
|
||||
got := QueueDepth(context.Background(), "ws-queue-depth-1")
|
||||
if got != 7 {
|
||||
t.Errorf("QueueDepth() = %d; want 7", got)
|
||||
}
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unmet: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestQueueDepth_EmptyQueue returns 0 when no queued items exist.
|
||||
func TestQueueDepth_EmptyQueue(t *testing.T) {
|
||||
mock := setupTestDB(t)
|
||||
|
||||
mock.ExpectQuery(`SELECT COUNT\(\*\) FROM a2a_queue WHERE workspace_id = \$1 AND status = 'queued'`).
|
||||
WithArgs("ws-empty").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(0))
|
||||
|
||||
got := QueueDepth(context.Background(), "ws-empty")
|
||||
if got != 0 {
|
||||
t.Errorf("QueueDepth() = %d; want 0", got)
|
||||
}
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unmet: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestQueueDepth_QueryError returns 0 on DB error (non-fatal; caller only uses
|
||||
// the count for display purposes).
|
||||
func TestQueueDepth_QueryError_ReturnsZero(t *testing.T) {
|
||||
mock := setupTestDB(t)
|
||||
|
||||
mock.ExpectQuery(`SELECT COUNT\(\*\) FROM a2a_queue WHERE workspace_id = \$1 AND status = 'queued'`).
|
||||
WithArgs("ws-err").
|
||||
WillReturnError(errors.New("connection refused"))
|
||||
|
||||
// QueueDepth swallows the error and returns 0.
|
||||
got := QueueDepth(context.Background(), "ws-err")
|
||||
if got != 0 {
|
||||
t.Errorf("QueueDepth() on error = %d; want 0", got)
|
||||
}
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unmet: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// ─── QueueStatusByID ────────────────────────────────────────────────────────
|
||||
|
||||
// TestQueueStatusByID_Success verifies QueueStatusByID returns a fully-populated
|
||||
// QueueStatus from the LEFT JOIN of a2a_queue and activity_logs.
|
||||
func TestQueueStatusByID_Success(t *testing.T) {
|
||||
mock := setupTestDB(t)
|
||||
|
||||
// The LEFT JOIN query returns all queue columns + NULL for activity_logs
|
||||
// when no delegation row exists.
|
||||
mock.ExpectQuery(`SELECT\s+q\.id,\s+q\.workspace_id,\s+q\.status,\s+q\.priority,\s+q\.attempts,\s+q\.last_error,\s+q\.enqueued_at::text,\s+q\.dispatched_at::text,\s+q\.completed_at::text,\s+q\.expires_at::text,\s+al\.response_body::text\s+FROM a2a_queue q\s+LEFT JOIN activity_logs al`).
|
||||
WithArgs("queue-ok-1").
|
||||
WillReturnRows(sqlmock.NewRows([]string{
|
||||
"id", "workspace_id", "status", "priority", "attempts",
|
||||
"last_error", "enqueued_at", "dispatched_at", "completed_at", "expires_at",
|
||||
"response_body",
|
||||
}).AddRow(
|
||||
"queue-ok-1", "ws-1", "queued", 50, 1,
|
||||
nil, "2026-05-16T10:00:00Z", nil, nil, "2026-05-16T12:00:00Z",
|
||||
nil,
|
||||
))
|
||||
|
||||
qs, err := QueueStatusByID(context.Background(), "queue-ok-1")
|
||||
if err != nil {
|
||||
t.Fatalf("QueueStatusByID() error = %v; want nil", err)
|
||||
}
|
||||
if qs.ID != "queue-ok-1" {
|
||||
t.Errorf("ID = %q; want queue-ok-1", qs.ID)
|
||||
}
|
||||
if qs.WorkspaceID != "ws-1" {
|
||||
t.Errorf("WorkspaceID = %q; want ws-1", qs.WorkspaceID)
|
||||
}
|
||||
if qs.Status != "queued" {
|
||||
t.Errorf("Status = %q; want queued", qs.Status)
|
||||
}
|
||||
if qs.Priority != 50 {
|
||||
t.Errorf("Priority = %d; want 50", qs.Priority)
|
||||
}
|
||||
if qs.Attempts != 1 {
|
||||
t.Errorf("Attempts = %d; want 1", qs.Attempts)
|
||||
}
|
||||
if qs.LastError != nil {
|
||||
t.Errorf("LastError = %v; want nil", qs.LastError)
|
||||
}
|
||||
if qs.EnqueuedAt != "2026-05-16T10:00:00Z" {
|
||||
t.Errorf("EnqueuedAt = %q; want 2026-05-16T10:00:00Z", qs.EnqueuedAt)
|
||||
}
|
||||
if qs.DispatchedAt != nil {
|
||||
t.Errorf("DispatchedAt = %v; want nil", qs.DispatchedAt)
|
||||
}
|
||||
if qs.CompletedAt != nil {
|
||||
t.Errorf("CompletedAt = %v; want nil", qs.CompletedAt)
|
||||
}
|
||||
if *qs.ExpiresAt != "2026-05-16T12:00:00Z" {
|
||||
t.Errorf("ExpiresAt = %v; want 2026-05-16T12:00:00Z", qs.ExpiresAt)
|
||||
}
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unmet: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestQueueStatusByID_CompletedWithResponse verifies that a completed queue item
|
||||
// populates ResponseBody from the LEFT JOINed activity_logs row.
|
||||
func TestQueueStatusByID_CompletedWithResponse(t *testing.T) {
|
||||
mock := setupTestDB(t)
|
||||
|
||||
respBody := `{"result":"done"}`
|
||||
mock.ExpectQuery(`SELECT\s+q\.id`).
|
||||
WithArgs("queue-done-1").
|
||||
WillReturnRows(sqlmock.NewRows([]string{
|
||||
"id", "workspace_id", "status", "priority", "attempts",
|
||||
"last_error", "enqueued_at", "dispatched_at", "completed_at", "expires_at",
|
||||
"response_body",
|
||||
}).AddRow(
|
||||
"queue-done-1", "ws-1", "completed", 50, 1,
|
||||
nil, "2026-05-16T10:00:00Z", "2026-05-16T10:01:00Z", "2026-05-16T10:02:00Z", nil,
|
||||
respBody,
|
||||
))
|
||||
|
||||
qs, err := QueueStatusByID(context.Background(), "queue-done-1")
|
||||
if err != nil {
|
||||
t.Fatalf("QueueStatusByID() error = %v; want nil", err)
|
||||
}
|
||||
if qs.Status != "completed" {
|
||||
t.Errorf("Status = %q; want completed", qs.Status)
|
||||
}
|
||||
if qs.ResponseBody == nil {
|
||||
t.Fatal("ResponseBody = nil; want non-nil for completed item")
|
||||
}
|
||||
var resp map[string]interface{}
|
||||
if err := json.Unmarshal(qs.ResponseBody, &resp); err != nil {
|
||||
t.Fatalf("ResponseBody not valid JSON: %v", err)
|
||||
}
|
||||
if resp["result"] != "done" {
|
||||
t.Errorf("ResponseBody result = %v; want done", resp["result"])
|
||||
}
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unmet: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestQueueStatusByID_ErrNoRows returns sql.ErrNoRows when the queue ID doesn't exist.
|
||||
func TestQueueStatusByID_ErrNoRows(t *testing.T) {
|
||||
mock := setupTestDB(t)
|
||||
|
||||
mock.ExpectQuery(`SELECT\s+q\.id`).
|
||||
WithArgs("queue-missing").
|
||||
WillReturnError(sql.ErrNoRows)
|
||||
|
||||
_, err := QueueStatusByID(context.Background(), "queue-missing")
|
||||
if !errors.Is(err, sql.ErrNoRows) {
|
||||
t.Errorf("QueueStatusByID() error = %v; want sql.ErrNoRows", err)
|
||||
}
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unmet: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestQueueStatusByID_QueryError propagates DB errors as-is.
|
||||
func TestQueueStatusByID_QueryError(t *testing.T) {
|
||||
mock := setupTestDB(t)
|
||||
|
||||
mock.ExpectQuery(`SELECT\s+q\.id`).
|
||||
WithArgs("queue-err").
|
||||
WillReturnError(errors.New("connection refused"))
|
||||
|
||||
_, err := QueueStatusByID(context.Background(), "queue-err")
|
||||
if err == nil {
|
||||
t.Fatal("QueueStatusByID() error = nil; want non-nil")
|
||||
}
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unmet: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// ─── GetA2AQueueStatus (HTTP handler) ─────────────────────────────────────
|
||||
|
||||
func newGetA2AQueueStatusHarness(t *testing.T) (sqlmock.Sqlmock, *httptest.ResponseRecorder, *gin.Context) {
|
||||
mock := setupTestDB(t)
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
return mock, w, c
|
||||
}
|
||||
|
||||
func TestGetA2AQueueStatus_MissingQueueID_Returns400(t *testing.T) {
|
||||
_, w, c := newGetA2AQueueStatusHarness(t)
|
||||
c.Params = gin.Params{{Key: "id", Value: "ws-1"}, {Key: "queue_id", Value: ""}}
|
||||
c.Request = httptest.NewRequest("GET", "/", nil)
|
||||
|
||||
h := newHandlerWithTestDeps(t)
|
||||
h.GetA2AQueueStatus(c)
|
||||
|
||||
if w.Code != http.StatusBadRequest {
|
||||
t.Errorf("expected 400, got %d: %s", w.Code, w.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetA2AQueueStatus_NoIdentity_Returns404(t *testing.T) {
|
||||
_, w, c := newGetA2AQueueStatusHarness(t)
|
||||
c.Params = gin.Params{{Key: "id", Value: "ws-1"}, {Key: "queue_id", Value: "q-123"}}
|
||||
c.Request = httptest.NewRequest("GET", "/", nil)
|
||||
|
||||
h := newHandlerWithTestDeps(t)
|
||||
h.GetA2AQueueStatus(c)
|
||||
|
||||
// Returns 404 (not 401) per the existence-non-inference policy.
|
||||
if w.Code != http.StatusNotFound {
|
||||
t.Errorf("expected 404, got %d: %s", w.Code, w.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetA2AQueueStatus_QueueNotFound_Returns404(t *testing.T) {
|
||||
mock, w, c := newGetA2AQueueStatusHarness(t)
|
||||
c.Params = gin.Params{{Key: "id", Value: "ws-1"}, {Key: "queue_id", Value: "q-404"}}
|
||||
c.Request = httptest.NewRequest("GET", "/", nil)
|
||||
c.Request.Header.Set("X-Workspace-ID", "ws-1")
|
||||
|
||||
mock.ExpectQuery(`SELECT caller_id, workspace_id FROM a2a_queue WHERE id = \$1`).
|
||||
WithArgs("q-404").
|
||||
WillReturnError(sql.ErrNoRows)
|
||||
|
||||
h := newHandlerWithTestDeps(t)
|
||||
h.GetA2AQueueStatus(c)
|
||||
|
||||
if w.Code != http.StatusNotFound {
|
||||
t.Errorf("expected 404, got %d: %s", w.Code, w.Body.String())
|
||||
}
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unmet: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetA2AQueueStatus_UnauthorizedCaller_Returns404(t *testing.T) {
|
||||
mock, w, c := newGetA2AQueueStatusHarness(t)
|
||||
c.Params = gin.Params{{Key: "id", Value: "ws-1"}, {Key: "queue_id", Value: "q-unauth"}}
|
||||
c.Request = httptest.NewRequest("GET", "/", nil)
|
||||
c.Request.Header.Set("X-Workspace-ID", "ws-wrong")
|
||||
|
||||
mock.ExpectQuery(`SELECT caller_id, workspace_id FROM a2a_queue WHERE id = \$1`).
|
||||
WithArgs("q-unauth").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"caller_id", "workspace_id"}).
|
||||
AddRow("ws-caller-a", "ws-target-b"))
|
||||
|
||||
h := newHandlerWithTestDeps(t)
|
||||
h.GetA2AQueueStatus(c)
|
||||
|
||||
// Returns 404 per the existence-non-inference policy.
|
||||
if w.Code != http.StatusNotFound {
|
||||
t.Errorf("expected 404, got %d: %s", w.Code, w.Body.String())
|
||||
}
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unmet: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetA2AQueueStatus_AuthorizedAsTarget_Success(t *testing.T) {
|
||||
mock, w, c := newGetA2AQueueStatusHarness(t)
|
||||
c.Params = gin.Params{{Key: "id", Value: "ws-1"}, {Key: "queue_id", Value: "q-ok"}}
|
||||
c.Request = httptest.NewRequest("GET", "/", nil)
|
||||
c.Request.Header.Set("X-Workspace-ID", "ws-target")
|
||||
|
||||
mock.ExpectQuery(`SELECT caller_id, workspace_id FROM a2a_queue WHERE id = \$1`).
|
||||
WithArgs("q-ok").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"caller_id", "workspace_id"}).
|
||||
AddRow("ws-caller", "ws-target"))
|
||||
|
||||
mock.ExpectQuery(`SELECT\s+q\.id`).
|
||||
WithArgs("q-ok").
|
||||
WillReturnRows(sqlmock.NewRows([]string{
|
||||
"id", "workspace_id", "status", "priority", "attempts",
|
||||
"last_error", "enqueued_at", "dispatched_at", "completed_at", "expires_at",
|
||||
"response_body",
|
||||
}).AddRow(
|
||||
"q-ok", "ws-target", "queued", 50, 1,
|
||||
nil, "2026-05-16T10:00:00Z", nil, nil, nil,
|
||||
nil,
|
||||
))
|
||||
|
||||
h := newHandlerWithTestDeps(t)
|
||||
h.GetA2AQueueStatus(c)
|
||||
|
||||
if w.Code != http.StatusOK {
|
||||
t.Errorf("expected 200, got %d: %s", w.Code, w.Body.String())
|
||||
}
|
||||
var qs QueueStatus
|
||||
if err := json.Unmarshal(w.Body.Bytes(), &qs); err != nil {
|
||||
t.Fatalf("body parse: %v", err)
|
||||
}
|
||||
if qs.ID != "q-ok" {
|
||||
t.Errorf("queue_id = %q; want q-ok", qs.ID)
|
||||
}
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unmet: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetA2AQueueStatus_QueueRowLookupError_Returns500(t *testing.T) {
|
||||
mock, w, c := newGetA2AQueueStatusHarness(t)
|
||||
c.Params = gin.Params{{Key: "id", Value: "ws-1"}, {Key: "queue_id", Value: "q-lookup-err"}}
|
||||
c.Request = httptest.NewRequest("GET", "/", nil)
|
||||
c.Request.Header.Set("X-Workspace-ID", "ws-1")
|
||||
|
||||
mock.ExpectQuery(`SELECT caller_id, workspace_id FROM a2a_queue WHERE id = \$1`).
|
||||
WithArgs("q-lookup-err").
|
||||
WillReturnError(errors.New("connection refused"))
|
||||
|
||||
h := newHandlerWithTestDeps(t)
|
||||
h.GetA2AQueueStatus(c)
|
||||
|
||||
if w.Code != http.StatusInternalServerError {
|
||||
t.Errorf("expected 500, got %d: %s", w.Code, w.Body.String())
|
||||
}
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unmet: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetA2AQueueStatus_StatusFetchError_Returns500(t *testing.T) {
|
||||
mock, w, c := newGetA2AQueueStatusHarness(t)
|
||||
c.Params = gin.Params{{Key: "id", Value: "ws-1"}, {Key: "queue_id", Value: "q-status-err"}}
|
||||
c.Request = httptest.NewRequest("GET", "/", nil)
|
||||
c.Request.Header.Set("X-Workspace-ID", "ws-1")
|
||||
|
||||
mock.ExpectQuery(`SELECT caller_id, workspace_id FROM a2a_queue WHERE id = \$1`).
|
||||
WithArgs("q-status-err").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"caller_id", "workspace_id"}).
|
||||
AddRow("ws-1", "ws-1"))
|
||||
|
||||
mock.ExpectQuery(`SELECT\s+q\.id`).
|
||||
WithArgs("q-status-err").
|
||||
WillReturnError(errors.New("connection refused"))
|
||||
|
||||
h := newHandlerWithTestDeps(t)
|
||||
h.GetA2AQueueStatus(c)
|
||||
|
||||
if w.Code != http.StatusInternalServerError {
|
||||
t.Errorf("expected 500, got %d: %s", w.Code, w.Body.String())
|
||||
}
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Errorf("unmet: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user