129 lines
5.0 KiB
Go
129 lines
5.0 KiB
Go
package webui
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"net/http"
|
||
|
|
"net/http/httptest"
|
||
|
|
"strings"
|
||
|
|
"testing"
|
||
|
|
)
|
||
|
|
|
||
|
|
// TestWebmailFolderCreateShowsUpEvenWhenEmpty confirms a freshly created folder is
|
||
|
|
// listed in the sidebar before it holds any messages — the reason
|
||
|
|
// esrv_mailbox_folders exists at all (DistinctFoldersForMailbox alone can't prove a
|
||
|
|
// folder exists until something's actually stored in it).
|
||
|
|
func TestWebmailFolderCreateShowsUpEvenWhenEmpty(t *testing.T) {
|
||
|
|
app := newTestApp(t)
|
||
|
|
mux := app.Mux()
|
||
|
|
domains, _ := app.DB.ListDomains()
|
||
|
|
mailboxID := createTestMailboxWithPassword(t, app, "organizer2@example.com", domains[0].ID, "organizer-password-1!")
|
||
|
|
cookie := webmailLoginSession(t, app, mailboxID)
|
||
|
|
|
||
|
|
req := httptest.NewRequest(http.MethodPost, MailboxPrefix+"/mail/folders/add", strings.NewReader("name=Receipts"))
|
||
|
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||
|
|
req.AddCookie(cookie)
|
||
|
|
rec := httptest.NewRecorder()
|
||
|
|
mux.ServeHTTP(rec, req)
|
||
|
|
if rec.Code != http.StatusFound {
|
||
|
|
t.Fatalf("add folder: status=%d body=%s", rec.Code, rec.Body.String())
|
||
|
|
}
|
||
|
|
|
||
|
|
folders, err := app.DB.ListMailboxFolders(mailboxID)
|
||
|
|
if err != nil || len(folders) != 1 || folders[0] != "Receipts" {
|
||
|
|
t.Fatalf("expected [Receipts] in ListMailboxFolders, got %v (err=%v)", folders, err)
|
||
|
|
}
|
||
|
|
|
||
|
|
inboxReq := httptest.NewRequest(http.MethodGet, MailboxPrefix+"/mail/INBOX", nil)
|
||
|
|
inboxReq.AddCookie(cookie)
|
||
|
|
inboxRec := httptest.NewRecorder()
|
||
|
|
mux.ServeHTTP(inboxRec, inboxReq)
|
||
|
|
if !strings.Contains(inboxRec.Body.String(), `data-folder="Receipts"`) {
|
||
|
|
t.Error("expected the empty new folder to appear in the sidebar")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// TestWebmailFolderCreateRejectsStandardAndDuplicateNames confirms you can't create a
|
||
|
|
// folder that collides with a standard folder or an existing custom one.
|
||
|
|
func TestWebmailFolderCreateRejectsStandardAndDuplicateNames(t *testing.T) {
|
||
|
|
app := newTestApp(t)
|
||
|
|
mux := app.Mux()
|
||
|
|
domains, _ := app.DB.ListDomains()
|
||
|
|
mailboxID := createTestMailboxWithPassword(t, app, "organizer3@example.com", domains[0].ID, "organizer-password-1!")
|
||
|
|
cookie := webmailLoginSession(t, app, mailboxID)
|
||
|
|
|
||
|
|
create := func(name string) {
|
||
|
|
t.Helper()
|
||
|
|
req := httptest.NewRequest(http.MethodPost, MailboxPrefix+"/mail/folders/add", strings.NewReader("name="+name))
|
||
|
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||
|
|
req.AddCookie(cookie)
|
||
|
|
rec := httptest.NewRecorder()
|
||
|
|
mux.ServeHTTP(rec, req)
|
||
|
|
if rec.Code != http.StatusFound {
|
||
|
|
t.Fatalf("create %s: status=%d", name, rec.Code)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
create("Sent") // standard folder name — should be rejected, not duplicated
|
||
|
|
create("Work")
|
||
|
|
create("Work") // duplicate — should be rejected, not duplicated
|
||
|
|
|
||
|
|
folders, err := app.DB.ListMailboxFolders(mailboxID)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
if len(folders) != 1 || folders[0] != "Work" {
|
||
|
|
t.Fatalf("expected exactly [Work] (Sent rejected as standard, duplicate Work rejected), got %v", folders)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// TestWebmailFolderDeleteMovesMessagesToInboxAndCannotDeleteStandard confirms
|
||
|
|
// deleting a custom folder relocates its messages to INBOX, and that a standard
|
||
|
|
// folder can't be deleted via the same route even if requested directly.
|
||
|
|
func TestWebmailFolderDeleteMovesMessagesToInboxAndCannotDeleteStandard(t *testing.T) {
|
||
|
|
app := newTestApp(t)
|
||
|
|
mux := app.Mux()
|
||
|
|
domains, _ := app.DB.ListDomains()
|
||
|
|
mailboxID := createTestMailboxWithPassword(t, app, "organizer4@example.com", domains[0].ID, "organizer-password-1!")
|
||
|
|
cookie := webmailLoginSession(t, app, mailboxID)
|
||
|
|
|
||
|
|
if err := app.DB.CreateMailboxFolder(mailboxID, "Newsletters"); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
raw := "From: a@example.com\r\nTo: organizer4@example.com\r\nSubject: hi\r\n\r\nbody"
|
||
|
|
if _, err := app.Mailstore.StoreMessage(mailboxID, "Newsletters", []byte(raw), "m@example.com", "a@example.com", "hi"); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
|
||
|
|
req := httptest.NewRequest(http.MethodPost, MailboxPrefix+"/mail/folders/Newsletters/remove", nil)
|
||
|
|
req.AddCookie(cookie)
|
||
|
|
rec := httptest.NewRecorder()
|
||
|
|
mux.ServeHTTP(rec, req)
|
||
|
|
if rec.Code != http.StatusFound {
|
||
|
|
t.Fatalf("delete folder: status=%d", rec.Code)
|
||
|
|
}
|
||
|
|
|
||
|
|
remaining, err := app.DB.ListMailboxFolders(mailboxID)
|
||
|
|
if err != nil || len(remaining) != 0 {
|
||
|
|
t.Fatalf("expected the folder record gone, got %v (err=%v)", remaining, err)
|
||
|
|
}
|
||
|
|
inboxMsgs, err := app.DB.ListMessagesInFolder(mailboxID, "INBOX")
|
||
|
|
if err != nil || len(inboxMsgs) != 1 {
|
||
|
|
t.Fatalf("expected the message relocated to INBOX, got %d (err=%v)", len(inboxMsgs), err)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Attempting to delete a standard folder must be rejected, not silently succeed.
|
||
|
|
stdReq := httptest.NewRequest(http.MethodPost, MailboxPrefix+"/mail/folders/Sent/remove", nil)
|
||
|
|
stdReq.AddCookie(cookie)
|
||
|
|
stdRec := httptest.NewRecorder()
|
||
|
|
mux.ServeHTTP(stdRec, stdReq)
|
||
|
|
if stdRec.Code != http.StatusFound {
|
||
|
|
t.Fatalf("delete standard folder: status=%d", stdRec.Code)
|
||
|
|
}
|
||
|
|
sentReq := httptest.NewRequest(http.MethodGet, MailboxPrefix+"/mail/Sent", nil)
|
||
|
|
sentReq.AddCookie(cookie)
|
||
|
|
sentRec := httptest.NewRecorder()
|
||
|
|
mux.ServeHTTP(sentRec, sentReq)
|
||
|
|
if sentRec.Code != http.StatusOK {
|
||
|
|
t.Fatalf("Sent folder should still exist and render normally, status=%d", sentRec.Code)
|
||
|
|
}
|
||
|
|
}
|