Files
imap-copier/internal/httpapi/run_test.go
T
2026-07-17 11:42:34 +07:00

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")
}
}