Skip to content
quarry Artifact [484c456a5b]
Login

Artifact [484c456a5b]

Artifact 484c456a5b7dca824fa11aa2699c4e205f2743ed396b4158cfad6fab3101d53f:


package web

import (
	"context"
	"io"
	"net/http"
	"net/http/httptest"
	"net/url"
	"strings"
	"testing"

	"craftdesign.group/quarry/internal/api"
	"craftdesign.group/quarry/internal/ops"
)

type promoteStubIn struct {
	Repo string `json:"repo" path:"repo"`
	ID   string `json:"id" path:"id"`
}

type promoteStubOut struct {
	ID string `json:"id"`
}

// A promotion that lost to another comes back as a refusal page with
// its code, like every coded refusal, and a way back: to the ticket it
// became when there is one, else to the local ticket still being
// promoted.
func TestALosingPromotionRendersItsRefusalHook(t *testing.T) {
	for _, tc := range []struct {
		code   string
		fields map[string]string
		back   string
	}{
		{api.RefusalAlreadyPromoted, map[string]string{"to": "f0551171f055"}, "/r/alpha/ticket/f0551171f055"},
		{api.RefusalBeingPromoted, nil, "/r/alpha/ticket/a1a1a1a1a1a1"},
	} {
		t.Run(tc.code, func(t *testing.T) {
			r := viewRegistry(t, nil)
			if err := ops.Register(r, ops.Op[promoteStubIn, promoteStubOut]{
				Name: "ticket.promote", Caps: "a", Doc: "test stub", Kind: ops.Command, Auth: ops.Token,
				Route: "POST /api/v1/r/{repo}/ticket/{id}/promote",
				Run: func(context.Context, promoteStubIn) (promoteStubOut, error) {
					return promoteStubOut{}, &ops.Refusal{Code: tc.code, Message: "lost", Fields: tc.fields}
				},
			}); err != nil {
				t.Fatal(err)
			}
			srv := httptest.NewServer(HandlerWith(r, nil, nil, nil))
			defer srv.Close()
			c := srv.Client()
			c.CheckRedirect = func(*http.Request, []*http.Request) error { return http.ErrUseLastResponse }
			resp, err := c.PostForm(srv.URL+"/r/alpha/ticket/a1a1a1a1a1a1/promote", url.Values{})
			if err != nil {
				t.Fatal(err)
			}
			defer resp.Body.Close()
			b, _ := io.ReadAll(resp.Body)
			html := string(b)
			if resp.StatusCode != http.StatusBadRequest {
				t.Fatalf("FAIL: status %d, want 400:\n%.600s", resp.StatusCode, html)
			}
			if !strings.Contains(html, `data-refusal="`+tc.code+`"`) {
				t.Fatalf("FAIL: no data-refusal hook for %s:\n%.1200s", tc.code, html)
			}
			if !strings.Contains(html, `data-hook="refusal-back" href="`+tc.back+`"`) {
				t.Fatalf("FAIL: no way back to %s:\n%.1200s", tc.back, html)
			}
			t.Log("ok")
		})
	}
}