package gitea import ( "context" "encoding/json" "errors" "io" "net/http" "net/http/httptest" "strings" "testing" "go.maximumdirect.net/releasekit/internal/forge" ) func TestBackendTagCommitUsesEscapedFullTagAndAuthentication(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if got, want := r.RequestURI, "/api/v1/repos/owner/project/tags/v1.2.3%2Frc.1"; got != want { t.Errorf("request URI = %q, want %q", got, want) } if got, want := r.Header.Get("Authorization"), "token fixture-secret-token"; got != want { t.Errorf("authorization = %q, want %q", got, want) } _ = json.NewEncoder(w).Encode(map[string]any{"commit": map[string]string{"sha": "abcdef"}}) })) defer server.Close() backend := NewBackend(testDestination(server.URL), server.Client()) commit, err := backend.TagCommit(context.Background(), "v1.2.3/rc.1") if err != nil || commit != "abcdef" { t.Fatalf("TagCommit() = %q, %v", commit, err) } } func TestBackendFindReleaseReturnsNeutralNotFound(t *testing.T) { server := httptest.NewServer(http.NotFoundHandler()) defer server.Close() backend := NewBackend(testDestination(server.URL), server.Client()) _, err := backend.FindRelease(context.Background(), "v1.2.3") var failure *forge.Failure if !errors.As(err, &failure) || failure.Kind != forge.FailureNotFound { t.Fatalf("FindRelease() error = %v, want neutral not-found failure", err) } var cause *Failure if !errors.As(err, &cause) || cause.StatusCode != http.StatusNotFound { t.Fatalf("FindRelease() error cause = %v, want Gitea 404 diagnostic", err) } } func TestBackendFindReleaseDoesNotRequireWriteResponseFields(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { _ = json.NewEncoder(w).Encode(releaseResponse{TagName: "v1.2.3", Name: "Release"}) })) defer server.Close() backend := NewBackend(testDestination(server.URL), server.Client()) release, err := backend.FindRelease(context.Background(), "v1.2.3") if err != nil { t.Fatal(err) } if release.Tag != "v1.2.3" || release.Title != "Release" || release.Handle == nil { t.Fatalf("FindRelease() = %#v", release) } } func TestBackendListsMetadataAndOpensCallerOwnedAssetStream(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if got, want := r.Header.Get("Authorization"), "token fixture-secret-token"; got != want { t.Errorf("authorization = %q, want %q", got, want) } switch r.URL.Path { case "/api/v1/repos/owner/project/releases/tags/v1.2.3": _ = json.NewEncoder(w).Encode(releaseResponse{ID: 12, TagName: "v1.2.3"}) case "/api/v1/repos/owner/project/releases/12/assets": _ = json.NewEncoder(w).Encode([]assetResponse{{ID: 4, Name: "app.bin", Size: 4, BrowserDownloadURL: "/files/app"}}) case "/files/app": _, _ = io.WriteString(w, "data") default: t.Errorf("unexpected path %q", r.URL.Path) http.NotFound(w, r) } })) defer server.Close() backend := NewBackend(testDestination(server.URL), server.Client()) release, err := backend.FindRelease(context.Background(), "v1.2.3") if err != nil { t.Fatal(err) } assets, err := backend.ListAssets(context.Background(), release.Handle) if err != nil { t.Fatal(err) } if len(assets) != 1 || assets[0].Filename != "app.bin" || assets[0].Size != 4 || assets[0].Handle == nil { t.Fatalf("ListAssets() = %#v", assets) } stream, err := backend.OpenAsset(context.Background(), assets[0].Handle) if err != nil { t.Fatal(err) } content, readErr := io.ReadAll(stream) closeErr := stream.Close() if readErr != nil || closeErr != nil || string(content) != "data" { t.Fatalf("OpenAsset() content = %q, read error = %v, close error = %v", content, readErr, closeErr) } } func TestBackendRejectsAssetHandleFromAnotherBackendType(t *testing.T) { backend := NewBackend(testDestination("http://example.test"), nil) _, err := backend.OpenAsset(context.Background(), strings.NewReader("asset")) var failure *forge.Failure if !errors.As(err, &failure) || failure.Kind != forge.FailureInvalid { t.Fatalf("OpenAsset() error = %v, want invalid handle", err) } }