107 lines
3.5 KiB
Go
107 lines
3.5 KiB
Go
package httpapi
|
|
|
|
import (
|
|
"io"
|
|
"mime/multipart"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/vasyansk/imap-copier/internal/config"
|
|
)
|
|
|
|
func TestImportCSVFailsOnBadEncKey(t *testing.T) {
|
|
// EncKey wrong size => crypto.Encrypt errors => handler must NOT return success
|
|
s := &Server{cfg: config.Config{EncKey: make([]byte, 16)}}
|
|
body := &strings.Builder{}
|
|
mw := multipart.NewWriter(body)
|
|
fw, _ := mw.CreateFormFile("file", "a.csv")
|
|
fw.Write([]byte("a@x,p1,a@y,p2\n"))
|
|
mw.Close()
|
|
req := httptest.NewRequest("POST", "/api/tasks/1/import", strings.NewReader(body.String()))
|
|
req.Header.Set("Content-Type", mw.FormDataContentType())
|
|
req.SetPathValue("id", "1")
|
|
rw := httptest.NewRecorder()
|
|
s.handleImportCSV(rw, req)
|
|
if rw.Code == 200 || rw.Code == 201 {
|
|
t.Fatalf("import must fail on bad EncKey, got %d", rw.Code)
|
|
}
|
|
}
|
|
|
|
// importReq builds a multipart import request with the given CSV payload and
|
|
// extra form fields, then returns it with the uploaded file ready to read.
|
|
func importReq(t *testing.T, csv string, fields map[string]string) (*http.Request, io.Reader) {
|
|
t.Helper()
|
|
body := &strings.Builder{}
|
|
mw := multipart.NewWriter(body)
|
|
for k, v := range fields {
|
|
_ = mw.WriteField(k, v)
|
|
}
|
|
fw, _ := mw.CreateFormFile("file", "a.csv")
|
|
fw.Write([]byte(csv))
|
|
mw.Close()
|
|
req := httptest.NewRequest("POST", "/api/tasks/1/import", strings.NewReader(body.String()))
|
|
req.Header.Set("Content-Type", mw.FormDataContentType())
|
|
req.SetPathValue("id", "1")
|
|
file, _, err := req.FormFile("file")
|
|
if err != nil {
|
|
t.Fatalf("form file: %v", err)
|
|
}
|
|
return req, file
|
|
}
|
|
|
|
const kerioCSV = "Name;FullName;Description;Enable;DataSource\n" +
|
|
"info;;InfoPass11;Yes;Internal\n"
|
|
|
|
func TestParseImportRowsUsesKerioParserWithDomain(t *testing.T) {
|
|
req, file := importReq(t, kerioCSV, map[string]string{"format": "kerio", "domain": "example.test"})
|
|
rows, err := parseImportRows(req, file)
|
|
if err != nil {
|
|
t.Fatalf("parse: %v", err)
|
|
}
|
|
if len(rows) != 1 || rows[0].SrcLogin != "info@example.test" || rows[0].DstLogin != "info@example.test" {
|
|
t.Fatalf("kerio rows must carry the supplied domain on both sides, got %+v", rows)
|
|
}
|
|
}
|
|
|
|
func TestParseImportRowsKerioRequiresDomain(t *testing.T) {
|
|
req, file := importReq(t, kerioCSV, map[string]string{"format": "kerio"})
|
|
if _, err := parseImportRows(req, file); err == nil {
|
|
t.Fatal("kerio import without a domain must error")
|
|
}
|
|
}
|
|
|
|
func TestParseImportRowsDefaultsToPlainFormat(t *testing.T) {
|
|
req, file := importReq(t, "a@x,p1,a@y,p2\n", nil)
|
|
rows, err := parseImportRows(req, file)
|
|
if err != nil {
|
|
t.Fatalf("parse: %v", err)
|
|
}
|
|
if len(rows) != 1 || rows[0].SrcLogin != "a@x" || rows[0].DstPass != "p2" {
|
|
t.Fatalf("no format field must keep the 4-column parser, got %+v", rows)
|
|
}
|
|
}
|
|
|
|
func TestParseRunAccountIDs(t *testing.T) {
|
|
// empty body => nil (run all)
|
|
req := httptest.NewRequest("POST", "/api/tasks/1/run", strings.NewReader(""))
|
|
ids, err := parseRunAccountIDs(req)
|
|
if err != nil || ids != nil {
|
|
t.Fatalf("empty body must yield nil ids, got %v err=%v", ids, err)
|
|
}
|
|
|
|
// explicit selection
|
|
req = httptest.NewRequest("POST", "/api/tasks/1/run", strings.NewReader(`{"account_ids":[3,7]}`))
|
|
ids, err = parseRunAccountIDs(req)
|
|
if err != nil || len(ids) != 2 || ids[0] != 3 || ids[1] != 7 {
|
|
t.Fatalf("must parse account_ids, got %v err=%v", ids, err)
|
|
}
|
|
|
|
// malformed JSON => error
|
|
req = httptest.NewRequest("POST", "/api/tasks/1/run", strings.NewReader(`{bad`))
|
|
if _, err := parseRunAccountIDs(req); err == nil {
|
|
t.Fatal("malformed body must error")
|
|
}
|
|
}
|