Files
kandev/apps/backend/internal/linear/mock_client_test.go
T
João Salavisa 5936bb6808 test: add e2e coverage and mock backends for jira and linear integrations (#771)
* test: add e2e coverage and mock backends for jira and linear integrations

Adds in-memory MockClient + MockController for both integrations gated by
KANDEV_MOCK_{JIRA,LINEAR}=true, plus apiClient mock helpers and Playwright
specs covering settings and import flows.

Also fixes ValidatedPopover's TriggerButton silently dropping radix Slot's
onClick handler — the popover wouldn't open under any synthetic-click path
(including Playwright). Spreads `...rest` onto the inner Button.

Reworks the integration cleanup hook in test-base as an auto fixture so it
runs for every test using the imported `test` object, not just tests in the
fixture file itself.

* fix: address PR review feedback on jira/linear mocks and e2e specs

- Fix SetAuthResult docstrings: nil simulates an unconfigured state, not the default success.
- Drop unused JSON tags from doneTransitionCall and setStateCall (Go-only test fixtures).
- Track Linear issue insertion order so SearchIssues returns deterministic results instead of map-iteration shuffle.
- Document filterByJQL precedence at the SearchTickets call site so the all-hits-on-no-match fallback is visible.
- Wait for the post-save auth-health probe before forcing a failure in the seeded-failure tests, eliminating a goroutine race.
- Reorder authMethod precedence in setJiraConfig/setLinearConfig to put the spread first so 'caller wins' reads naturally.

---------

Co-authored-by: Kandev Agent <agent@kandev.dev>
2026-05-02 14:41:36 +01:00

98 lines
2.8 KiB
Go

package linear
import (
"context"
"errors"
"net/http"
"testing"
)
func TestMockClient_DefaultsToSuccessfulAuth(t *testing.T) {
m := NewMockClient()
res, err := m.TestAuth(context.Background())
if err != nil {
t.Fatalf("TestAuth: %v", err)
}
if !res.OK {
t.Fatalf("expected OK=true by default, got %+v", res)
}
}
func TestMockClient_SetAuthResultIsReturned(t *testing.T) {
m := NewMockClient()
m.SetAuthResult(&TestConnectionResult{OK: false, Error: "401 Unauthorized"})
res, _ := m.TestAuth(context.Background())
if res.OK || res.Error != "401 Unauthorized" {
t.Fatalf("unexpected result: %+v", res)
}
}
func TestMockClient_TeamsAndStatesAreSeparate(t *testing.T) {
m := NewMockClient()
m.SetTeams([]LinearTeam{{ID: "t1", Key: "ENG", Name: "Engineering"}})
m.SetStates("ENG", []LinearWorkflowState{{ID: "s1", Name: "Todo", Type: "unstarted"}})
teams, _ := m.ListTeams(context.Background())
if len(teams) != 1 || teams[0].Key != "ENG" {
t.Fatalf("teams unexpected: %+v", teams)
}
states, _ := m.ListStates(context.Background(), "ENG")
if len(states) != 1 || states[0].Name != "Todo" {
t.Fatalf("states unexpected: %+v", states)
}
other, _ := m.ListStates(context.Background(), "DESIGN")
if len(other) != 0 {
t.Fatalf("states for unknown team should be empty, got %+v", other)
}
}
func TestMockClient_GetIssueRoundtrip(t *testing.T) {
m := NewMockClient()
m.AddIssue(&LinearIssue{Identifier: "ENG-12", Title: "Test issue"})
got, err := m.GetIssue(context.Background(), "ENG-12")
if err != nil {
t.Fatalf("GetIssue: %v", err)
}
if got.Title != "Test issue" {
t.Fatalf("unexpected title %q", got.Title)
}
}
func TestMockClient_GetIssueUnknownReturns404(t *testing.T) {
m := NewMockClient()
_, err := m.GetIssue(context.Background(), "NOPE-1")
var apiErr *APIError
if !errors.As(err, &apiErr) || apiErr.StatusCode != http.StatusNotFound {
t.Fatalf("expected 404, got %v", err)
}
}
func TestMockClient_SetIssueStateRecordsCall(t *testing.T) {
m := NewMockClient()
if err := m.SetIssueState(context.Background(), "issue-id", "state-id"); err != nil {
t.Fatalf("SetIssueState: %v", err)
}
calls := m.SetStateCalls()
if len(calls) != 1 || calls[0].IssueID != "issue-id" || calls[0].StateID != "state-id" {
t.Fatalf("unexpected calls: %+v", calls)
}
}
func TestMockClient_ResetClearsState(t *testing.T) {
m := NewMockClient()
m.AddIssue(&LinearIssue{Identifier: "X-1"})
m.SetTeams([]LinearTeam{{Key: "X"}})
m.SetAuthResult(&TestConnectionResult{OK: false, Error: "boom"})
m.Reset()
res, _ := m.TestAuth(context.Background())
if !res.OK {
t.Fatalf("Reset did not restore default auth result: %+v", res)
}
teams, _ := m.ListTeams(context.Background())
if len(teams) != 0 {
t.Fatalf("Reset did not clear teams")
}
if _, err := m.GetIssue(context.Background(), "X-1"); err == nil {
t.Fatalf("Reset did not clear issues")
}
}