forked from wgroeneveld/go-jamming
refactor out mocks in separate package
This commit is contained in:
parent
2b31d8c016
commit
c77ac41e1c
|
@ -1,5 +1,6 @@
|
|||
|
||||
data/*
|
||||
testdata
|
||||
|
||||
# this is the binary
|
||||
go-jamming
|
||||
|
|
|
@ -32,7 +32,9 @@ func (s *server) authorizedOnly(h http.HandlerFunc) http.HandlerFunc {
|
|||
|
||||
func Start() {
|
||||
r := mux.NewRouter()
|
||||
server := &server{router: r, conf: common.Configure()}
|
||||
config := common.Configure()
|
||||
config.SetupDataDirs()
|
||||
server := &server{router: r, conf: config}
|
||||
|
||||
server.routes()
|
||||
http.Handle("/", r)
|
||||
|
|
|
@ -43,6 +43,7 @@ func HandlePost(conf *common.Config) http.HandlerFunc {
|
|||
}
|
||||
recv := &receiver{
|
||||
restClient: httpClient,
|
||||
conf: conf,
|
||||
}
|
||||
|
||||
go recv.receive(wm)
|
||||
|
|
|
@ -3,7 +3,10 @@ package webmention
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"crypto/md5"
|
||||
|
||||
"github.com/wgroeneveld/go-jamming/common"
|
||||
"github.com/wgroeneveld/go-jamming/rest"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
|
@ -18,10 +21,17 @@ func (wm *webmention) String() string {
|
|||
return fmt.Sprintf("source: %s, target: %s", wm.source, wm.target)
|
||||
}
|
||||
|
||||
func (wm *webmention) asPath(conf *common.Config) string {
|
||||
filename := fmt.Sprintf("%x", md5.Sum([]byte("source=" + wm.source + ",target=" + wm.target)))
|
||||
domain, _ := conf.FetchDomain(wm.target)
|
||||
return conf.DataPath + "/" + domain + "/" + filename + ".json"
|
||||
}
|
||||
|
||||
// used as a "class" to iject dependencies, just to be able to test. Do NOT like htis.
|
||||
// Is there a better way? e.g. in validate, I just pass rest.Client as an arg. Not great either.
|
||||
type receiver struct {
|
||||
restClient rest.Client
|
||||
conf *common.Config
|
||||
}
|
||||
|
||||
func (recv *receiver) receive(wm webmention) {
|
||||
|
@ -38,7 +48,7 @@ func (recv *receiver) receive(wm webmention) {
|
|||
}
|
||||
|
||||
func (recv *receiver) deletePossibleOlderWebmention(wm webmention) {
|
||||
|
||||
os.Remove(wm.asPath(recv.conf))
|
||||
}
|
||||
|
||||
func (recv *receiver) processSourceBody(body string, wm webmention) {
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
|
||||
package webmention
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"os"
|
||||
"errors"
|
||||
|
||||
"github.com/wgroeneveld/go-jamming/common"
|
||||
"github.com/wgroeneveld/go-jamming/mocks"
|
||||
)
|
||||
|
||||
var conf = &common.Config{
|
||||
AllowedWebmentionSources: []string {
|
||||
"jefklakscodex.com",
|
||||
},
|
||||
DataPath: "testdata",
|
||||
}
|
||||
|
||||
|
||||
func TestConvertWebmentionToPath(t *testing.T) {
|
||||
wm := webmention{
|
||||
source: "https://brainbaking.com",
|
||||
target: "https://jefklakscodex.com/articles",
|
||||
}
|
||||
|
||||
result := wm.asPath(conf)
|
||||
if result != "testdata/jefklakscodex.com/99be66594fdfcf482545fead8e7e4948.json" {
|
||||
t.Fatalf("md5 hash check failed, got " + result)
|
||||
}
|
||||
}
|
||||
|
||||
func writeSomethingTo(filename string) {
|
||||
file, _ := os.Create(filename)
|
||||
file.WriteString("lolz")
|
||||
defer file.Close()
|
||||
}
|
||||
|
||||
func TestReceiveTargetDoesNotExistAnymoreDeletesPossiblyOlderWebmention(t *testing.T) {
|
||||
os.MkdirAll("testdata/jefklakscodex.com", os.ModePerm)
|
||||
defer os.RemoveAll("testdata")
|
||||
|
||||
wm := webmention{
|
||||
source: "https://brainbaking.com",
|
||||
target: "https://jefklakscodex.com/articles",
|
||||
}
|
||||
filename := wm.asPath(conf)
|
||||
writeSomethingTo(filename)
|
||||
|
||||
client := &mocks.RestClientMock{
|
||||
GetBodyFunc: func(url string) (string, error) {
|
||||
return "", errors.New("whoops")
|
||||
},
|
||||
}
|
||||
receiver := &receiver {
|
||||
conf: conf,
|
||||
restClient: client,
|
||||
}
|
||||
|
||||
receiver.receive(wm)
|
||||
if _, err := os.Stat(filename); err == nil {
|
||||
t.Fatalf("Expected possibly older webmention to be deleted, but it wasn't!")
|
||||
}
|
||||
}
|
|
@ -16,12 +16,11 @@ func isValidUrl(url string) bool {
|
|||
}
|
||||
|
||||
func isValidDomain(url string, conf *common.Config) bool {
|
||||
for _, domain := range conf.AllowedWebmentionSources {
|
||||
if strings.Index(url, domain) != -1 {
|
||||
return true
|
||||
}
|
||||
_, err := conf.FetchDomain(url)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return false
|
||||
return true
|
||||
}
|
||||
|
||||
func isValidTargetUrl(url string, httpClient rest.Client) bool {
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"net/http"
|
||||
|
||||
"github.com/wgroeneveld/go-jamming/common"
|
||||
"github.com/wgroeneveld/go-jamming/mocks"
|
||||
)
|
||||
|
||||
type httpReqMock struct {
|
||||
|
@ -114,21 +115,8 @@ func TestValidate(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// neat trick! https://medium.com/@matryer/meet-moq-easily-mock-interfaces-in-go-476444187d10
|
||||
type restClientMock struct {
|
||||
GetFunc func(string) (*http.Response, error)
|
||||
}
|
||||
|
||||
// although these are still requied to match the rest.Client interface.
|
||||
func (m *restClientMock) Get(url string) (*http.Response, error) {
|
||||
return m.GetFunc(url)
|
||||
}
|
||||
func (m *restClientMock) GetBody(url string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func TestIsValidTargetUrlFalseIfGetFails(t *testing.T) {
|
||||
client := &restClientMock{
|
||||
client := &mocks.RestClientMock{
|
||||
GetFunc: func(url string) (*http.Response, error) {
|
||||
return nil, errors.New("whoops")
|
||||
},
|
||||
|
@ -140,7 +128,7 @@ func TestIsValidTargetUrlFalseIfGetFails(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestIsValidTargetUrlTrueIfGetSucceeds(t *testing.T) {
|
||||
client := &restClientMock{
|
||||
client := &mocks.RestClientMock{
|
||||
GetFunc: func(url string) (*http.Response, error) {
|
||||
return nil, nil
|
||||
},
|
||||
|
|
|
@ -4,16 +4,37 @@ package common
|
|||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Port int
|
||||
Token string
|
||||
UtcOffset int
|
||||
DataPath string
|
||||
AllowedWebmentionSources []string
|
||||
DisallowedWebmentionDomains []string
|
||||
}
|
||||
|
||||
func (c *Config) FetchDomain(url string) (string, error) {
|
||||
for _, domain := range c.AllowedWebmentionSources {
|
||||
if strings.Index(url, domain) != -1 {
|
||||
return domain, nil
|
||||
}
|
||||
}
|
||||
return "", errors.New("no allowed domain found for url " + url)
|
||||
}
|
||||
|
||||
func (c *Config) SetupDataDirs() {
|
||||
for _, domain := range c.AllowedWebmentionSources {
|
||||
os.MkdirAll(c.DataPath + "/" + domain, os.ModePerm)
|
||||
log.Info().Str("allowedDomain", domain).Msg("Configured")
|
||||
}
|
||||
}
|
||||
|
||||
func Configure() (c *Config) {
|
||||
portstr := os.Getenv("PORT")
|
||||
port, err := strconv.Atoi(portstr)
|
||||
|
@ -29,6 +50,7 @@ func Configure() (c *Config) {
|
|||
Port: port,
|
||||
Token: token,
|
||||
UtcOffset: 60,
|
||||
DataPath: "data",
|
||||
AllowedWebmentionSources: []string{ "brainbaking.com", "jefklakscodex.com" },
|
||||
DisallowedWebmentionDomains: []string{ "youtube.com" },
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// neat trick! https://medium.com/@matryer/meet-moq-easily-mock-interfaces-in-go-476444187d10
|
||||
type RestClientMock struct {
|
||||
GetFunc func(string) (*http.Response, error)
|
||||
GetBodyFunc func(string) (string, error)
|
||||
}
|
||||
|
||||
// although these are still requied to match the rest.Client interface.
|
||||
func (m *RestClientMock) Get(url string) (*http.Response, error) {
|
||||
return m.GetFunc(url)
|
||||
}
|
||||
func (m *RestClientMock) GetBody(url string) (string, error) {
|
||||
return m.GetBodyFunc(url)
|
||||
}
|
||||
|
Loading…
Reference in New Issue