package registrar import ( "crypto/tls" "crypto/x509" "encoding/json" "io" "net/http" "net/http/httptest" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.fixergrid.net/servicedemon/pubsub" ) func TestHandleRegisterPendingApproval(t *testing.T) { resp := httptest.NewRecorder() req := NewTestRequest(t, http.MethodPost, "http://example.com/v1/register", nil). WithFakeTLSState("dev-app-1.delivery.engineering"). Create() repo := NewRepo() pubsub := pubsub.New() subscriber := pubsub.Subscribe(REGISTRATION_TOPIC) NewRegistrar(pubsub, repo).HandleRegistration(resp, req) assert.Equal(t, http.StatusCreated, resp.Code) body, err := io.ReadAll(resp.Body) require.NoError(t, err) assert.Equal(t, []byte(`{"status": "pending_approval"}`), body) assert.Equal(t, 1, repo.PendingApprovalCount()) expectedEvent := map[string]string{ "name": "dev-app-1.delivery.engineering", "type": "ApplicationRegistrationSubmitted", } assertMessage(t, expectedEvent, subscriber) } func TestHandleRegisterAlreadyRegistered(t *testing.T) { resp := httptest.NewRecorder() req := NewTestRequest(t, http.MethodPost, "http://example.com/v1/register", nil). WithFakeTLSState("dev-app-1.delivery.engineering"). Create() pubsub := pubsub.New() repo := NewRepo() appID := repo.StartAppRegistration("dev-app-1.delivery.engineering") repo.ApproveApp(appID) NewRegistrar(pubsub, repo).HandleRegistration(resp, req) assert.Equal(t, http.StatusOK, resp.Code) body, err := io.ReadAll(resp.Body) require.NoError(t, err) assert.Equal(t, []byte(`{"status": "registered"}`), body) } func TestHandleRegisterNotYetApproved(t *testing.T) { resp := httptest.NewRecorder() req := NewTestRequest(t, http.MethodPost, "http://example.com/v1/register", nil). WithFakeTLSState("dev-app-1.delivery.engineering"). Create() pubsub := pubsub.New() repo := NewRepo() repo.StartAppRegistration("dev-app-1.delivery.engineering") NewRegistrar(pubsub, repo).HandleRegistration(resp, req) assert.Equal(t, http.StatusOK, resp.Code) body, err := io.ReadAll(resp.Body) require.NoError(t, err) assert.Equal(t, []byte(`{"status": "pending_approval"}`), body) } func assertMessage(t *testing.T, expected map[string]string, sender <-chan string) { timer := time.After(2 * time.Second) for { select { case msg := <-sender: compareMessage(t, expected, msg) return case <-timer: t.Fatal("failed waiting for message") } } } func compareMessage(t *testing.T, expected map[string]string, observed string) { observedEvent := map[string]string{} require.NoError(t, json.Unmarshal([]byte(observed), &observedEvent)) assert.NotEmpty(t, observedEvent["id"]) for k, v := range expected { assert.Equal(t, v, observedEvent[k]) } } type TestRequest http.Request func NewTestRequest(t *testing.T, method string, url string, body io.Reader) TestRequest { req, err := http.NewRequest(method, url, body) require.NoError(t, err) return TestRequest(*req) } func (tr TestRequest) WithFakeTLSState(dnsName string) TestRequest { cert := x509.Certificate{ DNSNames: []string{ dnsName, }, } tr.TLS = &tls.ConnectionState{ PeerCertificates: []*x509.Certificate{&cert}, } return tr } func (tr TestRequest) Create() *http.Request { req := http.Request(tr) return &req }