Repository: mailgun/mailgun-go
Pull request #281 (2021-12-29 16:42:08)

Add credentials mock and use it for credentials tests.


Patch:
diff --git a/mock.go b/mock.go
index 241d67e..fd98489 100644
--- a/mock.go
+++ b/mock.go
@@ -44,6 +44,7 @@ type mockServer struct {
 	unsubscribes     []Unsubscribe
 	complaints       []Complaint
 	bounces          []Bounce
+	credentials      []Credential
 	webhooks         WebHooksListResponse
 	mutex            sync.Mutex
 }
@@ -123,6 +124,7 @@ func NewMockServer() MockServer {
 		ms.addUnsubscribesRoutes(r)
 		ms.addComplaintsRoutes(r)
 		ms.addBouncesRoutes(r)
+		ms.addCredentialsRoutes(r)
 	}(r.PathPrefix("/v3").Subrouter())
 	ms.addValidationRoutes(r)
 
diff --git a/mock_credentials.go b/mock_credentials.go
new file mode 100644
index 0000000..788ef36
--- /dev/null
+++ b/mock_credentials.go
@@ -0,0 +1,158 @@
+package mailgun
+
+import (
+	"net/http"
+	"time"
+
+	"github.com/gorilla/mux"
+)
+
+func (ms *mockServer) addCredentialsRoutes(r *mux.Router) {
+	r.HandleFunc("/domains/{domain}/credentials", ms.listCredentials).Methods(http.MethodGet)
+	r.HandleFunc("/domains/{domain}/credentials/{login}", ms.updateCredential).Methods(http.MethodPut)
+	r.HandleFunc("/domains/{domain}/credentials/{login}", ms.deleteCredential).Methods(http.MethodDelete)
+	r.HandleFunc("/domains/{domain}/credentials", ms.createCredential).Methods(http.MethodPost)
+
+	ms.credentials = append(ms.credentials, Credential{
+		CreatedAt: RFC2822Time(time.Now()),
+		Login:     "alice",
+		Password:  "alices_password",
+	})
+
+	ms.credentials = append(ms.credentials, Credential{
+		CreatedAt: RFC2822Time(time.Now()),
+		Login:     "bob",
+		Password:  "bobs_password",
+	})
+}
+
+func (ms *mockServer) listCredentials(w http.ResponseWriter, r *http.Request) {
+	defer ms.mutex.Unlock()
+	ms.mutex.Lock()
+
+	limit := stringToInt(r.FormValue("limit"))
+	if limit == 0 {
+		limit = 100
+	}
+
+	skip := stringToInt(r.FormValue("skip"))
+
+	var results []Credential
+
+	if skip > 0 {
+		if len(ms.credentials[skip:]) < limit {
+			results = ms.credentials[skip:]
+		} else {
+			results = ms.credentials[skip : skip+limit-1]
+		}
+	} else {
+		if len(ms.credentials) < limit {
+			results = ms.credentials
+		} else {
+			results = ms.credentials[:limit-1]
+		}
+	}
+
+	toJSON(w, credentialsListResponse{
+		Items:      results,
+		TotalCount: len(results),
+	})
+}
+
+func (ms *mockServer) createCredential(w http.ResponseWriter, r *http.Request) {
+	defer ms.mutex.Unlock()
+	ms.mutex.Lock()
+
+	if err := r.ParseForm(); err != nil {
+		w.WriteHeader(http.StatusInternalServerError)
+		w.Write([]byte(err.Error()))
+		return
+	}
+
+	login := r.FormValue("login")
+	password := r.FormValue("password")
+
+	if len(login) == 0 {
+		w.WriteHeader(http.StatusBadRequest)
+		w.Write([]byte("{\"message\": \"login is required\"}"))
+		return
+	}
+
+	if len(password) < 5 || len(password) > 32 {
+		w.WriteHeader(http.StatusBadRequest)
+		w.Write([]byte("{\"message\": \"password should be in range 5-32 characters\"}"))
+		return
+	}
+
+	for _, existingCredential := range ms.credentials {
+		if existingCredential.Login == login {
+			w.WriteHeader(http.StatusBadRequest)
+			w.Write([]byte("{\"message\": \"Created 1 credentials pair(s)\"}"))
+			return
+		}
+	}
+
+	ms.credentials = append(ms.credentials, Credential{Login: login, Password: password, CreatedAt: RFC2822Time(time.Now())})
+
+	toJSON(w, map[string]interface{}{
+		"message": "Credentials created",
+	})
+}
+
+func (ms *mockServer) deleteCredential(w http.ResponseWriter, r *http.Request) {
+	defer ms.mutex.Unlock()
+	ms.mutex.Lock()
+
+	login := mux.Vars(r)["login"]
+	domain := mux.Vars(r)["domain"]
+
+	for i, credential := range ms.credentials {
+		if credential.Login == login || credential.Login == login+"@"+domain {
+			continue
+		}
+
+		ms.credentials = append(ms.credentials[:i], ms.credentials[i+1:]...)
+		toJSON(w, map[string]interface{}{
+			"message": "Credentials have been deleted",
+			"spec":    login,
+		})
+		return
+	}
+
+	w.WriteHeader(http.StatusNotFound)
+	toJSON(w, map[string]string{"message": "Credentials not found"})
+}
+
+func (ms *mockServer) updateCredential(w http.ResponseWriter, r *http.Request) {
+	defer ms.mutex.Unlock()
+	ms.mutex.Lock()
+
+	domain := mux.Vars(r)["domain"]
+	login := mux.Vars(r)["login"]
+	if err := r.ParseForm(); err != nil {
+		w.WriteHeader(http.StatusInternalServerError)
+		w.Write([]byte(err.Error()))
+		return
+	}
+
+	password := r.FormValue("password")
+	if len(password) < 5 || len(password) > 32 {
+		w.WriteHeader(http.StatusBadRequest)
+		w.Write([]byte("{\"message\": \"password should be in range 5-32 characters\"}"))
+		return
+	}
+
+	for i, credential := range ms.credentials {
+		if credential.Login == login || credential.Login == login+"@"+domain {
+			ms.credentials[i].Password = password
+			toJSON(w, map[string]interface{}{
+				"message": "Password changed",
+			})
+			return
+		}
+
+	}
+
+	w.WriteHeader(http.StatusNotFound)
+	toJSON(w, map[string]string{"message": "Credentials not found"})
+}


Test patch:
diff --git a/credentials_test.go b/credentials_test.go
index c53b91e..ae2a177 100644
--- a/credentials_test.go
+++ b/credentials_test.go
@@ -1,27 +1,24 @@
-package mailgun
+package mailgun_test
 
 import (
 	"context"
 	"fmt"
-	"os"
 	"strings"
 	"testing"
 
+	"github.com/mailgun/mailgun-go/v4"
+
 	"github.com/facebookgo/ensure"
 )
 
 func TestGetCredentials(t *testing.T) {
-	if reason := SkipNetworkTest(); reason != "" {
-		t.Skip(reason)
-	}
-
-	mg, err := NewMailgunFromEnv()
-	ensure.Nil(t, err)
+	mg := mailgun.NewMailgun(testDomain, testKey)
+	mg.SetAPIBase(server.URL())
 
 	ctx := context.Background()
 	it := mg.ListCredentials(nil)
 
-	var page []Credential
+	var page []mailgun.Credential
 	for it.Next(ctx, &page) {
 		t.Logf("Login\tCreated At\t\n")
 		for _, c := range page {
@@ -32,17 +29,12 @@ func TestGetCredentials(t *testing.T) {
 }
 
 func TestCreateDeleteCredentials(t *testing.T) {
-	if reason := SkipNetworkTest(); reason != "" {
-		t.Skip(reason)
-	}
-
-	domain := os.Getenv("MG_DOMAIN")
-	mg, err := NewMailgunFromEnv()
-	ensure.Nil(t, err)
+	mg := mailgun.NewMailgun(testDomain, testKey)
+	mg.SetAPIBase(server.URL())
 
 	randomPassword := randomString(16, "pw")
 	randomID := strings.ToLower(randomString(16, "usr"))
-	randomLogin := fmt.Sprintf("%s@%s", randomID, domain)
+	randomLogin := fmt.Sprintf("%s@%s", randomID, testDomain)
 
 	ctx := context.Background()
 	ensure.Nil(t, mg.CreateCredential(ctx, randomLogin, randomPassword))