mirror of https://github.com/jlelse/GoBlog
Add automatic test for contact submissions and some other small improvements
parent
e9632720a3
commit
4857a82493
@ -0,0 +1,75 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.goblog.app/app/pkgs/contenttype"
|
||||
"go.goblog.app/app/pkgs/mocksmtp"
|
||||
)
|
||||
|
||||
func Test_contact(t *testing.T) {
|
||||
|
||||
// Start the SMTP server
|
||||
port, rd, err := mocksmtp.StartMockSMTPServer()
|
||||
require.NoError(t, err)
|
||||
|
||||
// Init everything
|
||||
app := &goBlog{
|
||||
cfg: &config{
|
||||
Db: &configDb{
|
||||
File: filepath.Join(t.TempDir(), "test.db"),
|
||||
},
|
||||
Server: &configServer{
|
||||
PublicAddress: "https://example.com",
|
||||
},
|
||||
Blogs: map[string]*configBlog{
|
||||
"en": {
|
||||
Lang: "en",
|
||||
// Config for contact
|
||||
Contact: &configContact{
|
||||
Enabled: true,
|
||||
SMTPPort: port,
|
||||
SMTPHost: "127.0.0.1",
|
||||
SMTPUser: "user",
|
||||
SMTPPassword: "pass",
|
||||
EmailTo: "to@example.org",
|
||||
EmailFrom: "from@example.org",
|
||||
},
|
||||
},
|
||||
},
|
||||
DefaultBlog: "en",
|
||||
User: &configUser{},
|
||||
},
|
||||
}
|
||||
_ = app.initDatabase(false)
|
||||
app.initComponents(false)
|
||||
|
||||
// Make contact form request
|
||||
rec := httptest.NewRecorder()
|
||||
data := url.Values{}
|
||||
data.Add("name", "Test User")
|
||||
data.Add("email", "test@example.net")
|
||||
data.Add("website", "https://test.example.com")
|
||||
data.Add("message", "This is a test contact message")
|
||||
req := httptest.NewRequest(http.MethodPost, "/contact", strings.NewReader(data.Encode()))
|
||||
req.Header.Add(contentType, contenttype.WWWForm)
|
||||
app.sendContactSubmission(rec, req.WithContext(context.WithValue(req.Context(), blogKey, "en")))
|
||||
require.Equal(t, http.StatusOK, rec.Result().StatusCode)
|
||||
|
||||
// Check sent mail
|
||||
received, err := rd()
|
||||
require.NoError(t, err)
|
||||
assert.Contains(t, received, "This is a test contact message")
|
||||
assert.Contains(t, received, "test@example.net")
|
||||
assert.Contains(t, received, "https://test.example.com")
|
||||
assert.Contains(t, received, "Test User")
|
||||
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
// This package contains code to mock an SMTP server and test mail sending.
|
||||
|
||||
package mocksmtp
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/textproto"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Inspired by https://play.golang.org/p/8mfrqNVWTPK
|
||||
|
||||
type ReceivedGetter func() (string, error)
|
||||
|
||||
func StartMockSMTPServer() (port int, rg ReceivedGetter, err error) {
|
||||
|
||||
// Default server responses
|
||||
serverResponses := []string{
|
||||
"220 smtp.example.com Service ready",
|
||||
"250-ELHO -> ok",
|
||||
"250-Show Options for ESMTP",
|
||||
"250-8BITMIME",
|
||||
"250-SIZE",
|
||||
"250-AUTH LOGIN PLAIN",
|
||||
"250 HELP",
|
||||
"235 AUTH -> ok",
|
||||
"250 MAIL FROM -> ok",
|
||||
"250 RCPT TO -> ok",
|
||||
"354 DATA",
|
||||
"250 ... -> ok",
|
||||
"221 QUIT",
|
||||
}
|
||||
|
||||
// Channel to check if error occured or done
|
||||
var errOrDone = make(chan error)
|
||||
|
||||
// Received data buffer
|
||||
var buffer bytes.Buffer
|
||||
bufferWriter := bufio.NewWriter(&buffer)
|
||||
|
||||
// Start server on random port
|
||||
mockSmtpServer, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
// Get port from listener
|
||||
_, portStr, err := net.SplitHostPort(mockSmtpServer.Addr().String())
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
port, err = strconv.Atoi(portStr)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
// Run mock SMTP server
|
||||
go func() {
|
||||
defer close(errOrDone)
|
||||
defer bufferWriter.Flush()
|
||||
defer mockSmtpServer.Close()
|
||||
|
||||
conn, err := mockSmtpServer.Accept()
|
||||
if err != nil {
|
||||
errOrDone <- err
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
tc := textproto.NewConn(conn)
|
||||
defer tc.Close()
|
||||
|
||||
for _, res := range serverResponses {
|
||||
if res == "" {
|
||||
break
|
||||
}
|
||||
|
||||
_ = tc.PrintfLine("%s", res)
|
||||
|
||||
if len(res) >= 4 && res[3] == '-' {
|
||||
continue
|
||||
}
|
||||
|
||||
if res == "221 QUIT" {
|
||||
return
|
||||
}
|
||||
|
||||
for {
|
||||
msg, err := tc.ReadLine()
|
||||
if err != nil {
|
||||
errOrDone <- err
|
||||
return
|
||||
}
|
||||
|
||||
_, _ = fmt.Fprintf(bufferWriter, "%s\n", msg)
|
||||
|
||||
if res != "354 DATA" || msg == "." {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Define function to get received data
|
||||
getReceivedData := func() (string, error) {
|
||||
err, hasErr := <-errOrDone
|
||||
if hasErr {
|
||||
return "", err
|
||||
}
|
||||
return buffer.String(), nil
|
||||
}
|
||||
|
||||
// Return port and function
|
||||
return port, getReceivedData, nil
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package mocksmtp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/smtp"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_mocksmtp(t *testing.T) {
|
||||
// Start mock SMTP server
|
||||
port, getRecievedData, err := StartMockSMTPServer()
|
||||
require.NoError(t, err)
|
||||
|
||||
// Send mail
|
||||
err = smtp.SendMail(
|
||||
fmt.Sprintf("127.0.0.1:%d", port),
|
||||
smtp.PlainAuth("", "user", "pass", "127.0.0.1"),
|
||||
"admin@smtp.example.com",
|
||||
[]string{"user@smtp.example.com"},
|
||||
[]byte("From: admin@smtp.example.com\nTo: user@smtp.example.com\nSubject: Test\nMIME-version: 1.0\nContent-Type: text/html; charset=\"UTF-8\"\n\nThis is a test mail."),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Get received data
|
||||
recievedData, err := getRecievedData()
|
||||
require.NoError(t, err)
|
||||
assert.Contains(t, recievedData, "From:")
|
||||
assert.Contains(t, recievedData, "This is a test mail")
|
||||
}
|
Loading…
Reference in New Issue