Files
opencloud/pkg/jmap/jmap_test.go
2026-01-22 09:39:15 +01:00

240 lines
5.7 KiB
Go

package jmap
import (
"context"
"fmt"
"math/rand"
"testing"
"time"
"github.com/opencloud-eu/opencloud/pkg/log"
"github.com/stretchr/testify/require"
)
const mails1 = `{"methodResponses": [
["Email/query",{
"accountId":"j",
"queryState":"sqcakzewfqdk7oay",
"canCalculateChanges":true,
"position":0,
"ids":["fmaaaabh"],
"total":1
},"0"],
["Email/get",{
"accountId":"j",
"state":"sqcakzewfqdk7oay",
"list":[
{"threadId":"bl","id":"fmaaaabh"}
],"notFound":[]
},"1"],
["Thread/get",{
"accountId":"j",
"state":"sqcakzewfqdk7oay",
"list":[
{"id":"bl","emailIds":["fmaaaabh"]}
],"notFound":[]
},"2"],
["Email/get",{
"accountId":"j",
"state":"sqcakzewfqdk7oay",
"list":[
{"threadId":"bl","mailboxIds":{"a":true},"keywords":{},"hasAttachment":false,"from":[{"name":"current generally","email":"current.generally"}],"subject":"eros auctor proin","receivedAt":"2025-04-30T09:47:44Z","size":15423,"preview":"Lorem ipsum dolor sit amet consectetur adipiscing elit sed urna tristique himenaeos eu a mattis laoreet aliquet enim. Magnis est facilisis nibh nisl vitae nisi mauris nostra velit donec erat pellentesque sagittis ligula turpis suscipit ultricies. Morbi ...","id":"fmaaaabh"}
],"notFound":[]
},"3"]
],"sessionState":"3e25b2a0"
}`
const mailboxes = `{"methodResponses": [
["Mailbox/get", {
"accountId":"cs",
"state":"n",
"list": [
{
"id":"a",
"name":"Inbox",
"parentId":null,
"role":"inbox",
"sortOrder":0,
"isSubscribed":true,
"totalEmails":0,
"unreadEmails":0,
"totalThreads":0,
"unreadThreads":0,
"myRights":{
"mayReadItems":true,
"mayAddItems":true,
"mayRemoveItems":true,
"maySetSeen":true,
"maySetKeywords":true,
"mayCreateChild":true,
"mayRename":true,
"mayDelete":true,
"maySubmit":true
}
},{
"id":"b",
"name":"Deleted Items",
"parentId":null,
"role":"trash",
"sortOrder":0,
"isSubscribed":true,
"totalEmails":0,
"unreadEmails":0,
"totalThreads":0,
"unreadThreads":0,
"myRights":{
"mayReadItems":true,
"mayAddItems":true,
"mayRemoveItems":true,
"maySetSeen":true,
"maySetKeywords":true,
"mayCreateChild":true,
"mayRename":true,
"mayDelete":true,
"maySubmit":true
}
},{
"id":"c",
"name":"Junk Mail",
"parentId":null,
"role":"junk",
"sortOrder":0,
"isSubscribed":true,
"totalEmails":0,
"unreadEmails":0,
"totalThreads":0,
"unreadThreads":0,
"myRights":{
"mayReadItems":true,
"mayAddItems":true,
"mayRemoveItems":true,
"maySetSeen":true,
"maySetKeywords":true,
"mayCreateChild":true,
"mayRename":true,
"mayDelete":true,
"maySubmit":true
}
},{
"id":"d",
"name":"Drafts",
"parentId":null,
"role":"drafts",
"sortOrder":0,
"isSubscribed":true,
"totalEmails":0,
"unreadEmails":0,
"totalThreads":0,
"unreadThreads":0,
"myRights":{
"mayReadItems":true,
"mayAddItems":true,
"mayRemoveItems":true,
"maySetSeen":true,
"maySetKeywords":true,
"mayCreateChild":true,
"mayRename":true,
"mayDelete":true,
"maySubmit":true
}
},{
"id":"e",
"name":"Sent Items",
"parentId":null,
"role":"sent",
"sortOrder":0,
"isSubscribed":true,
"totalEmails":0,
"unreadEmails":0,
"totalThreads":0,
"unreadThreads":0,
"myRights":{
"mayReadItems":true,
"mayAddItems":true,
"mayRemoveItems":true,
"maySetSeen":true,
"maySetKeywords":true,
"mayCreateChild":true,
"mayRename":true,
"mayDelete":true,
"maySubmit":true
}
}
],
"notFound":[]
},"0"]
], "sessionState":"3e25b2a0"
}`
type TestJmapWellKnownClient struct {
t *testing.T
}
func NewTestJmapWellKnownClient(t *testing.T) WellKnownClient {
return &TestJmapWellKnownClient{t: t}
}
func (t *TestJmapWellKnownClient) GetWellKnown(username string, logger *log.Logger) (WellKnownResponse, error) {
return WellKnownResponse{
ApiUrl: "test://",
PrimaryAccounts: map[string]string{JmapMail: generateRandomString(2 + seededRand.Intn(10))},
}, nil
}
type TestJmapApiClient struct {
t *testing.T
}
func NewTestJmapApiClient(t *testing.T) ApiClient {
return &TestJmapApiClient{t: t}
}
func (t *TestJmapApiClient) Command(ctx context.Context, logger *log.Logger, request map[string]any) ([]byte, error) {
methodCalls := request["methodCalls"].(*[][]any)
command := (*methodCalls)[0][0].(string)
switch command {
case "Mailbox/get":
return []byte(mailboxes), nil
case "Email/query":
return []byte(mails1), nil
default:
require.Fail(t.t, "unsupported jmap command: %v", command)
return nil, fmt.Errorf("unsupported jmap command: %v", command)
}
}
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
var seededRand *rand.Rand = rand.New(rand.NewSource(time.Now().UnixNano()))
func generateRandomString(length int) string {
b := make([]byte, length)
for i := range b {
b[i] = charset[seededRand.Intn(len(charset))]
}
return string(b)
}
func TestRequests(t *testing.T) {
require := require.New(t)
apiClient := NewTestJmapApiClient(t)
wkClient := NewTestJmapWellKnownClient(t)
logger := log.NopLogger()
ctx := context.Background()
client := NewClient(wkClient, apiClient)
session := Session{AccountId: "123", JmapUrl: "test://"}
folders, err := client.GetMailboxes(session, ctx, &logger)
require.NoError(err)
require.Len(folders.Folders, 5)
emails, err := client.EmailThreadsQuery(session, ctx, &logger, "Inbox")
require.NoError(err)
require.Len(emails.Emails, 1)
email := emails.Emails[0]
require.Equal("eros auctor proin", email.Subject)
require.Equal(false, email.HasAttachments)
}