mirror of
https://gitea.com/gitea/tea.git
synced 2026-10-26 19:11:25 +01:00
Add NotFoundError, ConflictError and AmbiguousError so commands can report "issue #999 not found in alice/project" or "alice/old-stuff is archived" instead of the transport's status text. Classify wraps a failure with the resource the caller names; ClassifyRequest infers it from the endpoint for failures no service classified, and maps the refusals Gitea explains (archived repository, merged or draft pull request, own review, existing resource, unknown user, disabled workflow, completed run, reused SSH key). Page reports the X-Total-Count that listWindow discarded, NameOrID resolves a resource by ID or name (numeric values are IDs first, ambiguous names list their IDs), and rawPage pages raw collection endpoints. Signed-off-by: bircni <bircni@icloud.com>
78 lines
2.5 KiB
Go
78 lines
2.5 KiB
Go
// Copyright 2026 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package services
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"gitea.dev/tea/internal/transport"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// newTestClient serves handler for the duration of the test and returns a client for it.
|
|
// Requests probing the server version or API schema fail the test: tea targets one Gitea
|
|
// release and must never gate operations on either.
|
|
func newTestClient(t *testing.T, handler http.Handler) *transport.Client {
|
|
t.Helper()
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if strings.HasSuffix(r.URL.Path, "/api/v1/version") || strings.HasSuffix(r.URL.Path, "/swagger.v1.json") {
|
|
t.Errorf("unexpected capability probe %s", r.URL.Path)
|
|
w.WriteHeader(http.StatusTeapot)
|
|
return
|
|
}
|
|
handler.ServeHTTP(w, r)
|
|
}))
|
|
t.Cleanup(server.Close)
|
|
return transport.New(server.URL, "", false)
|
|
}
|
|
|
|
// requestJSON decodes the JSON object a handler received.
|
|
func requestJSON(t *testing.T, r *http.Request) map[string]any {
|
|
t.Helper()
|
|
var payload map[string]any
|
|
assert.NoError(t, json.NewDecoder(r.Body).Decode(&payload))
|
|
return payload
|
|
}
|
|
|
|
func TestNameOrIDPrefersIDsThenExactThenFoldedNames(t *testing.T) {
|
|
type label struct {
|
|
id int64
|
|
name string
|
|
}
|
|
labels := []label{{11, "bug"}, {12, "Bug"}, {13, "7"}, {7, "seven"}, {20, "kind/feature"}, {21, "dup"}, {22, "dup"}}
|
|
lookup := NameOrID[label]{Kind: "label", Scope: "alice/project", ID: func(l label) int64 { return l.id }, Name: func(l label) string { return l.name }}
|
|
for _, tc := range []struct {
|
|
raw string
|
|
byName bool
|
|
want int64
|
|
err string
|
|
}{
|
|
{raw: "7", want: 7},
|
|
{raw: "7", byName: true, want: 13},
|
|
{raw: "13", want: 13},
|
|
{raw: "bug", want: 11},
|
|
{raw: "BUG", err: `label "BUG" is ambiguous in alice/project (IDs 11, 12); pass an ID`},
|
|
{raw: "KIND/FEATURE", want: 20},
|
|
{raw: " kind/feature ", want: 20},
|
|
{raw: "dup", err: `label "dup" is ambiguous in alice/project (IDs 21, 22); pass an ID`},
|
|
{raw: "nope", err: `label "nope" not found in alice/project`},
|
|
{raw: "99", err: "label 99 not found in alice/project"},
|
|
{raw: "99", byName: true, err: `label "99" not found in alice/project`},
|
|
} {
|
|
lookup.ByName = tc.byName
|
|
got, err := lookup.Find(labels, tc.raw)
|
|
if tc.err != "" {
|
|
require.EqualError(t, err, tc.err, tc.raw)
|
|
continue
|
|
}
|
|
require.NoError(t, err, tc.raw)
|
|
require.Equal(t, tc.want, got.id, tc.raw)
|
|
}
|
|
}
|