package controllers import ( "fmt" "net/http" "net/http/httptest" "net/url" "strings" "testing" "GoMembership/internal/config" "GoMembership/internal/constants" "GoMembership/internal/utils" "github.com/gin-gonic/gin" ) type RelayContactRequestTest struct { Input url.Values Name string WantResponse int Assert bool } func TestContactController(t *testing.T) { tests := getContactData() for _, tt := range tests { t.Run(tt.Name, func(t *testing.T) { if err := runSingleTest(&tt); err != nil { t.Errorf("Test failed: %v", err.Error()) } }) } } func (rt *RelayContactRequestTest) SetupContext() (*gin.Context, *httptest.ResponseRecorder, *gin.Engine) { return GetMockedFormContext(rt.Input, "/contact") } func (rt *RelayContactRequestTest) RunHandler(c *gin.Context, router *gin.Engine) { router.POST("/contact", Cc.RelayContactRequest) router.ServeHTTP(c.Writer, c.Request) // Cc.RelayContactRequest(c) } func (rt *RelayContactRequestTest) ValidateResponse(w *httptest.ResponseRecorder) error { if w.Code != rt.WantResponse { return fmt.Errorf("Didn't get the expected response code: got: %v; expected: %v", w.Code, rt.WantResponse) } return nil } func (rt *RelayContactRequestTest) ValidateResult() error { messages := utils.SMTPGetMessages() for _, message := range messages { mail, err := utils.DecodeMail(message.MsgRequest()) if err != nil { return err } if strings.Contains(mail.Subject, constants.MailContactSubject) { if err := checkContactRequestMail(mail, rt); err != nil { return err } } else { return fmt.Errorf("Subject not expected: %v", mail.Subject) } } return nil } func checkContactRequestMail(mail *utils.Email, rt *RelayContactRequestTest) error { if !strings.Contains(mail.To, config.Recipients.ContactForm) { return fmt.Errorf("Contact Information didn't reach the admin! Recipient was: %v instead of %v", mail.To, config.Recipients.ContactForm) } if !strings.Contains(mail.From, config.SMTP.User) { return fmt.Errorf("Contact Information was sent from unexpected address! Sender was: %v instead of %v", mail.From, config.SMTP.User) } //Check if all the relevant data has been passed to the mail. if !strings.Contains(mail.Body, rt.Input.Get("name")) { return fmt.Errorf("User name(%v) has not been rendered in contact mail.", rt.Input.Get("name")) } if !strings.Contains(mail.Body, rt.Input.Get("message")) { return fmt.Errorf("User message(%v) has not been rendered in contact mail.", rt.Input.Get("message")) } return nil } func getBaseRequest() *url.Values { return &url.Values{ "username": {""}, "name": {"My-First and-Last-Name"}, "REPLY_TO": {"name@domain.de"}, "message": {"My message to the world"}, } } func customizeRequest(updates map[string]string) *url.Values { form := getBaseRequest() for key, value := range updates { form.Set(key, value) } return form } func getContactData() []RelayContactRequestTest { return []RelayContactRequestTest{ { Name: "mail empty, should fail", WantResponse: http.StatusNotAcceptable, Assert: false, Input: *customizeRequest( map[string]string{ "REPLY_TO": "", }), }, { Name: "mail invalid, should fail", WantResponse: http.StatusNotAcceptable, Assert: false, Input: *customizeRequest( map[string]string{ "REPLY_TO": "novalid#email.de", }), }, { Name: "No message should fail", WantResponse: http.StatusNotAcceptable, Assert: true, Input: *customizeRequest( map[string]string{ "message": "", }), }, { Name: "Honeypot set, should fail", WantResponse: http.StatusNotAcceptable, Assert: true, Input: *customizeRequest( map[string]string{ "username": "I'm a bot", }), }, { Name: "Correct message, should pass", WantResponse: http.StatusAccepted, Assert: true, Input: *customizeRequest( map[string]string{}), }, } }