package query import ( "net/mail" "testing" "time" "forge.cadoles.com/Cadoles/fake-smtp/internal/model" "github.com/pkg/errors" ) type emailMatcherTestCase struct { Name string Search *InboxSearch Email *model.Email Matcher emailMatcherFunc Expect bool } func TestEmailMatcher(t *testing.T) { t.Parallel() johnDoeAddr, err := mail.ParseAddress("john.doe@test.local") if err != nil { t.Fatal(errors.WithStack(err)) } adaLovelaceAddr, err := mail.ParseAddress("ada.lovelace@test.local") if err != nil { t.Fatal(errors.WithStack(err)) } now := time.Now() testCases := []emailMatcherTestCase{ { Name: "Simple matching header", Email: &model.Email{ Headers: map[string][]string{ "X-Swift-To": {johnDoeAddr.Address}, }, }, Search: &InboxSearch{ Headers: map[string]string{ "X-Swift-To": johnDoeAddr.Address, }, }, Matcher: matchHeaders, Expect: true, }, { Name: "Multiple matching header", Email: &model.Email{ Headers: map[string][]string{ "X-Swift-To": {johnDoeAddr.Address}, "Content-Type": {"multipart/alternative; boundary=\"_=_swift_1645181013_7b80ab8ab386ba4fcaff4f6f79593adb_=_\""}, }, }, Search: &InboxSearch{ Headers: map[string]string{ "X-Swift-To": johnDoeAddr.Address, "Content-Type": "multipart/alternative", }, }, Matcher: matchHeaders, Expect: true, }, { Name: "Simple non matching header", Email: &model.Email{ Headers: map[string][]string{ "X-Swift-To": {johnDoeAddr.Address}, }, }, Search: &InboxSearch{ Headers: map[string]string{ "X-Swift-To": adaLovelaceAddr.Address, }, }, Matcher: matchHeaders, Expect: false, }, { Name: "Multiple non matching headers", Email: &model.Email{ Headers: map[string][]string{ "X-Swift-To": {johnDoeAddr.Address}, "Content-Type": {"foo/bar"}, }, }, Search: &InboxSearch{ Headers: map[string]string{ "X-Swift-To": johnDoeAddr.Address, "Content-Type": "multipart/alternative", }, }, Matcher: matchHeaders, Expect: false, }, { Name: "Simple to", Email: &model.Email{ To: []*mail.Address{johnDoeAddr}, }, Search: &InboxSearch{ To: johnDoeAddr.Address, }, Matcher: matchTo, Expect: true, }, { Name: "Simple from", Email: &model.Email{ From: []*mail.Address{johnDoeAddr}, }, Search: &InboxSearch{ From: johnDoeAddr.Address, }, Matcher: matchFrom, Expect: true, }, { Name: "Simple after", Email: &model.Email{ SentAt: now, }, Search: &InboxSearch{ After: now.Add(-5 * time.Second), }, Matcher: matchAfter, Expect: true, }, { Name: "Simple before", Email: &model.Email{ SentAt: now, }, Search: &InboxSearch{ Before: now.Add(5 * time.Second), }, Matcher: matchBefore, Expect: true, }, { Name: "Matching composite", Email: &model.Email{ SentAt: now, Headers: map[string][]string{ "X-Swift-To": {johnDoeAddr.Address}, "Content-Type": {"multipart/alternative; boundary=\"_=_swift_1645181013_7b80ab8ab386ba4fcaff4f6f79593adb_=_\""}, }, }, Search: &InboxSearch{ Before: now.Add(5 * time.Second), Headers: map[string]string{ "X-Swift-To": johnDoeAddr.Address, "Content-Type": "multipart/alternative", }, }, Matcher: and(matchBefore, matchHeaders), Expect: true, }, { Name: "Non matching composite", Email: &model.Email{ SentAt: now, Headers: map[string][]string{ "X-Swift-To": {johnDoeAddr.Address}, "Content-Type": {"multipart/alternative; boundary=\"_=_swift_1645181013_7b80ab8ab386ba4fcaff4f6f79593adb_=_\""}, }, }, Search: &InboxSearch{ Before: now.Add(5 * time.Second), Headers: map[string]string{ "X-Swift-To": adaLovelaceAddr.Address, "Content-Type": "multipart/alternative", }, }, Matcher: and(matchBefore, matchHeaders), Expect: false, }, } for _, tc := range testCases { func(tc emailMatcherTestCase) { t.Run(tc.Name, func(t *testing.T) { t.Parallel() if e, g := tc.Expect, tc.Matcher(tc.Email, tc.Search); e != g { t.Errorf("'%s': expected '%v', got '%v'", tc.Name, e, g) } }) }(tc) } }