Skip to content

Commit

Permalink
handler_test: add testApiRequest, testMailtoEvent
Browse files Browse the repository at this point in the history
This does away with the need to pass a byte array to
fixture.handleApiRequest and fixture.handleMailtoEvent. This will, in
turn, make it easier to write more test without messing up a byte array.

Also introduces a new, but skipped, test case for a successful
/subscribe request. The plan is to test the individual smaller methods
more rigourously, then only add a few high-level request cases to cover
major flows. Several of these will duplicate, or eliminate, cases from
bin/smoke-test.sh.
  • Loading branch information
mbland committed Mar 30, 2023
1 parent ff1f333 commit f80e15e
Showing 1 changed file with 101 additions and 38 deletions.
139 changes: 101 additions & 38 deletions handler/handler_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package handler

import (
"fmt"
"net/http"
"testing"

Expand All @@ -11,6 +10,24 @@ import (
"gotest.tools/assert"
)

type testApiRequest struct {
RawPath string
Headers map[string]string
Body string
}

type testMailtoEvent struct {
From []string
To []string
Subject string
SpfVerdict string
DkimVerdict string
SpamVerdict string
VirusVerdict string
DmarcVerdict string
DmarcPolicy string
}

type testAgent struct {
Email string
Uid uuid.UUID
Expand Down Expand Up @@ -40,15 +57,18 @@ func (a *testAgent) Unsubscribe(
}

type fixture struct {
e Event
h *Handler
e Event
ta *testAgent
h *Handler
}

func newFixture() *fixture {
ta := &testAgent{}
return &fixture{
ta: ta,
h: NewHandler(
"mike-bland.com",
&testAgent{},
ta,
RedirectPaths{
"invalid",
"already-subscribed",
Expand All @@ -61,57 +81,100 @@ func newFixture() *fixture {
}

func (f *fixture) handleApiRequest(
data []byte,
testReq *testApiRequest,
) (*events.APIGatewayV2HTTPResponse, error) {
if err := f.e.UnmarshalJSON(data); err != nil {
return nil, err
} else if f.e.Type != ApiRequest {
return nil, fmt.Errorf("not an API request: %s", f.e.Type)
}
f.e.Type = ApiRequest
fReq := &f.e.ApiRequest
fReq.RawPath = testReq.RawPath
fReq.Headers = testReq.Headers
fReq.Body = testReq.Body
response, err := f.h.HandleEvent(&f.e)
return response.(*events.APIGatewayV2HTTPResponse), err
}

func (f *fixture) handleMailtoEvent(data []byte) (any, error) {
if err := f.e.UnmarshalJSON(data); err != nil {
return nil, err
} else if f.e.Type != MailtoEvent {
return nil, fmt.Errorf("not a mailto event: %s", f.e.Type)
}
func (f *fixture) handleMailtoEvent(e *testMailtoEvent) (any, error) {
f.e.Type = MailtoEvent
ses := events.SimpleEmailService{}
headers := ses.Mail.CommonHeaders
receipt := &ses.Receipt

headers.From = e.From
headers.To = e.To
headers.Subject = e.Subject

receipt.SPFVerdict.Status = e.SpfVerdict
receipt.DKIMVerdict.Status = e.DkimVerdict
receipt.SpamVerdict.Status = e.SpamVerdict
receipt.VirusVerdict.Status = e.VirusVerdict
receipt.DMARCVerdict.Status = e.DmarcVerdict
receipt.DMARCPolicy = e.DmarcPolicy

f.e.MailtoEvent.Records = append(
f.e.MailtoEvent.Records, events.SimpleEmailRecord{SES: ses},
)
return f.h.HandleEvent(&f.e)
}

func TestIgnoreUnexpectedEvent(t *testing.T) {
f := newFixture()
func TestHandleEvent(t *testing.T) {
t.Run("IgnoresUnexpectedEvent", func(t *testing.T) {
f := newFixture()

response, err := f.h.HandleEvent(&f.e)
response, err := f.h.HandleEvent(&f.e)

assert.NilError(t, err)
assert.Equal(t, nil, response)
assert.NilError(t, err)
assert.Equal(t, nil, response)
})
}

func TestApiRequestReturnsInvalidRequestLocationUntilImplemented(t *testing.T) {
f := newFixture()

response, err := f.handleApiRequest([]byte(`{
"rawPath": "/subscribe",
"body": "email=mbland%40acm.org"
}`))

assert.NilError(t, err)
assert.Equal(t, response.StatusCode, http.StatusSeeOther)
assert.Equal(t, response.Headers["Location"], f.h.Redirects[ops.Invalid])
func TestSubscribeRequest(t *testing.T) {
t.Run("Successful", func(t *testing.T) {
t.Skip("not yet implemented")
f := newFixture()
f.ta.ReturnValue = ops.Subscribed

response, err := f.handleApiRequest(&testApiRequest{
RawPath: "/subscribe",
Headers: map[string]string{
"Content-Type": "application/x-www-form-urlencoded",
},
Body: "email=mbland%40acm.org",
})

assert.NilError(t, err)
assert.Equal(t, f.ta.Email, "mbland@acm.org")
assert.Equal(t, response.StatusCode, http.StatusSeeOther)
assert.Equal(
t, response.Headers["Location"], f.h.Redirects[ops.Subscribed],
)
})

t.Run("ReturnsInvalidRequestIfParsingFails", func(t *testing.T) {
f := newFixture()

response, err := f.handleApiRequest(&testApiRequest{
RawPath: "/subscribe",
Headers: map[string]string{
"Content-Type": "application/x-www-form-urlencoded",
},
Body: "email=mbland%20acm.org",
})

assert.NilError(t, err)
assert.Equal(t, f.ta.Email, "")
assert.Equal(t, response.StatusCode, http.StatusSeeOther)
assert.Equal(
t, response.Headers["Location"], f.h.Redirects[ops.Invalid],
)
})
}

func TestMailtoEventDoesNothingUntilImplemented(t *testing.T) {
f := newFixture()

response, err := f.handleMailtoEvent([]byte(`{
"Records": [{ "ses": { "mail": { "commonHeaders": {
"to": [ "unsubscribe@mike-bland.com" ],
"subject": "foo@bar.com UID"
}}}}]
}`))
response, err := f.handleMailtoEvent(&testMailtoEvent{
To: []string{"unsubscribe@mike-bland.com"},
Subject: "foo@bar.com UID",
})

assert.NilError(t, err)
assert.Equal(t, nil, response)
Expand Down

0 comments on commit f80e15e

Please sign in to comment.