mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-01-23 04:50:45 -06:00
groupware: improve JMAP ContactCard integration tests
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
package jmap
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"slices"
|
||||
@@ -10,7 +9,6 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/opencloud-eu/opencloud/pkg/jscontact"
|
||||
"github.com/opencloud-eu/opencloud/pkg/structs"
|
||||
)
|
||||
|
||||
func TestContacts(t *testing.T) {
|
||||
@@ -26,7 +24,7 @@ func TestContacts(t *testing.T) {
|
||||
require.NoError(err)
|
||||
defer s.Close()
|
||||
|
||||
accountId, addressbookId, cardsById, sentById, boxes, err := s.fillContacts(t, count)
|
||||
accountId, addressbookId, expectedContactCardsById, boxes, err := s.fillContacts(t, count)
|
||||
require.NoError(err)
|
||||
require.NotEmpty(accountId)
|
||||
require.NotEmpty(addressbookId)
|
||||
@@ -49,17 +47,9 @@ func TestContacts(t *testing.T) {
|
||||
require.Len(contacts, int(count))
|
||||
|
||||
for _, actual := range contacts {
|
||||
expected, ok := cardsById[actual.Id]
|
||||
expected, ok := expectedContactCardsById[actual.Id]
|
||||
require.True(ok, "failed to find created contact by its id")
|
||||
sent := sentById[actual.Id]
|
||||
matchContact(t, actual, expected, sent, func() (jscontact.ContactCard, error) {
|
||||
cards, _, _, _, err := s.client.GetContactCardsById(accountId, s.session, t.Context(), s.logger, "", []string{actual.Id})
|
||||
if err != nil {
|
||||
return jscontact.ContactCard{}, err
|
||||
}
|
||||
require.Contains(cards, actual.Id)
|
||||
return cards[actual.Id], nil
|
||||
})
|
||||
matchContact(t, actual, expected)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,23 +66,6 @@ func allTrue[S any](t *testing.T, s S, exceptions ...string) {
|
||||
}
|
||||
}
|
||||
|
||||
func matchContact(t *testing.T, actual jscontact.ContactCard, expected jscontact.ContactCard, sent map[string]any, fetcher func() (jscontact.ContactCard, error)) {
|
||||
require := require.New(t)
|
||||
if structs.AnyValue(expected.Media, func(media jscontact.Media) bool { return media.BlobId != "" }) {
|
||||
fmt.Printf("\x1b[33;1m----------------------------------------------------------\x1b[0m\n")
|
||||
fmt.Printf("\x1b[45;1m expected media: \x1b[0m\n%v\n\n", expected.Media)
|
||||
fmt.Printf("\x1b[46;1m actual media: \x1b[0m\n%v\n\n", actual.Media)
|
||||
fmt.Printf("\x1b[43;1m sent: \x1b[0m\n%v\n\n", sent)
|
||||
fmt.Printf("\x1b[44;1m pulling: \x1b[0m\n")
|
||||
_, err := fetcher()
|
||||
require.NoError(err)
|
||||
fmt.Printf("\x1b[44;1m pulled. \x1b[0m\n")
|
||||
}
|
||||
|
||||
require.Equal(expected.Name, actual.Name)
|
||||
require.Equal(expected.Emails, actual.Emails)
|
||||
require.Equal(expected.Organizations, actual.Organizations)
|
||||
require.Equal(expected.Media, actual.Media)
|
||||
|
||||
require.Equal(expected, actual)
|
||||
func matchContact(t *testing.T, actual jscontact.ContactCard, expected jscontact.ContactCard) {
|
||||
require.Equal(t, expected, actual)
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"net/mail"
|
||||
"net/url"
|
||||
"os"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"slices"
|
||||
"strconv"
|
||||
@@ -792,7 +793,7 @@ type ContactsBoxes struct {
|
||||
func (s *StalwartTest) fillContacts(
|
||||
t *testing.T,
|
||||
count uint,
|
||||
) (string, string, map[string]jscontact.ContactCard, map[string]map[string]any, ContactsBoxes, error) {
|
||||
) (string, string, map[string]jscontact.ContactCard, ContactsBoxes, error) {
|
||||
require := require.New(t)
|
||||
c, err := NewTestJmapClient(s.session, s.username, s.password, true, true)
|
||||
require.NoError(err)
|
||||
@@ -821,8 +822,9 @@ func (s *StalwartTest) fillContacts(
|
||||
}
|
||||
require.NotEmpty(addressbookId)
|
||||
|
||||
u := true
|
||||
|
||||
filled := map[string]jscontact.ContactCard{}
|
||||
sent := map[string]map[string]any{}
|
||||
for i := range count {
|
||||
person := gofakeit.Person()
|
||||
nameMap, nameObj := createName(person)
|
||||
@@ -896,14 +898,14 @@ func (s *StalwartTest) fillContacts(
|
||||
"number": tel,
|
||||
"features": structs.MapKeys(features, func(f jscontact.PhoneFeature) string { return string(f) }),
|
||||
"contexts": structs.MapKeys(contexts, func(c jscontact.PhoneContext) string { return string(c) }),
|
||||
}, jscontact.Phone{
|
||||
//Type: jscontact.PhoneType,
|
||||
}, untype(jscontact.Phone{
|
||||
Type: jscontact.PhoneType,
|
||||
Number: tel,
|
||||
Features: features,
|
||||
Contexts: contexts,
|
||||
}, nil
|
||||
}, u), nil
|
||||
}); err != nil {
|
||||
return "", "", nil, nil, boxes, err
|
||||
return "", "", nil, boxes, err
|
||||
}
|
||||
if err := propmap(i%5 < 4, 1, 2, contact, "addresses", &card.Addresses, func(i int, id string) (map[string]any, jscontact.Address, error) {
|
||||
var source *gofakeit.AddressInfo
|
||||
@@ -936,15 +938,15 @@ func (s *StalwartTest) fillContacts(
|
||||
"defaultSeparator": ", ",
|
||||
"isOrdered": true,
|
||||
"timeZone": tz,
|
||||
}, jscontact.Address{
|
||||
//Type: jscontact.AddressType,
|
||||
}, untype(jscontact.Address{
|
||||
Type: jscontact.AddressType,
|
||||
Components: components,
|
||||
DefaultSeparator: ", ",
|
||||
IsOrdered: true,
|
||||
TimeZone: tz,
|
||||
}, nil
|
||||
}, u), nil
|
||||
}); err != nil {
|
||||
return "", "", nil, nil, boxes, err
|
||||
return "", "", nil, boxes, err
|
||||
}
|
||||
if err := propmap(i%2 == 0, 1, 2, contact, "onlineServices", &card.OnlineServices, func(i int, id string) (map[string]any, jscontact.OnlineService, error) {
|
||||
boxes.onlineService = true
|
||||
@@ -955,35 +957,35 @@ func (s *StalwartTest) fillContacts(
|
||||
"service": "Mastodon",
|
||||
"user": "@" + person.Contact.Email,
|
||||
"uri": "https://mastodon.example.com/@" + strings.ToLower(person.FirstName),
|
||||
}, jscontact.OnlineService{
|
||||
//Type: jscontact.OnlineServiceType,
|
||||
}, untype(jscontact.OnlineService{
|
||||
Type: jscontact.OnlineServiceType,
|
||||
Service: "Mastodon",
|
||||
User: "@" + person.Contact.Email,
|
||||
Uri: "https://mastodon.example.com/@" + strings.ToLower(person.FirstName),
|
||||
}, nil
|
||||
}, u), nil
|
||||
case 1:
|
||||
return map[string]any{
|
||||
"@type": "OnlineService",
|
||||
"uri": "xmpp:" + person.Contact.Email,
|
||||
}, jscontact.OnlineService{
|
||||
//Type: jscontact.OnlineServiceType,
|
||||
Uri: "xmpp:" + person.Contact.Email,
|
||||
}, nil
|
||||
}, untype(jscontact.OnlineService{
|
||||
Type: jscontact.OnlineServiceType,
|
||||
Uri: "xmpp:" + person.Contact.Email,
|
||||
}, u), nil
|
||||
default:
|
||||
return map[string]any{
|
||||
"@type": "OnlineService",
|
||||
"service": "Discord",
|
||||
"user": person.Contact.Email,
|
||||
"uri": "https://discord.example.com/user/" + person.Contact.Email,
|
||||
}, jscontact.OnlineService{
|
||||
//Type: jscontact.OnlineServiceType,
|
||||
}, untype(jscontact.OnlineService{
|
||||
Type: jscontact.OnlineServiceType,
|
||||
Service: "Discord",
|
||||
User: person.Contact.Email,
|
||||
Uri: "https://discord.example.com/user/" + person.Contact.Email,
|
||||
}, nil
|
||||
}, u), nil
|
||||
}
|
||||
}); err != nil {
|
||||
return "", "", nil, nil, boxes, err
|
||||
return "", "", nil, boxes, err
|
||||
}
|
||||
|
||||
if err := propmap(i%3 == 0, 1, 2, contact, "preferredLanguages", &card.PreferredLanguages, func(i int, id string) (map[string]any, jscontact.LanguagePref, error) {
|
||||
@@ -995,14 +997,14 @@ func (s *StalwartTest) fillContacts(
|
||||
"language": lang,
|
||||
"contexts": toBoolMap(contexts),
|
||||
"pref": i + 1,
|
||||
}, jscontact.LanguagePref{
|
||||
// Type: jscontact.LanguagePrefType,
|
||||
}, untype(jscontact.LanguagePref{
|
||||
Type: jscontact.LanguagePrefType,
|
||||
Language: lang,
|
||||
Contexts: toBoolMap(structs.Map(contexts, func(s string) jscontact.LanguagePrefContext { return jscontact.LanguagePrefContext(s) })),
|
||||
Pref: uint(i + 1),
|
||||
}, nil
|
||||
}, u), nil
|
||||
}); err != nil {
|
||||
return "", "", nil, nil, boxes, err
|
||||
return "", "", nil, boxes, err
|
||||
}
|
||||
|
||||
if i%2 == 0 {
|
||||
@@ -1019,23 +1021,23 @@ func (s *StalwartTest) fillContacts(
|
||||
"name": person.Job.Company,
|
||||
"contexts": toBoolMapS("work"),
|
||||
}
|
||||
organizationObjs[orgId] = jscontact.Organization{
|
||||
// Type: jscontact.OrganizationType,
|
||||
organizationObjs[orgId] = untype(jscontact.Organization{
|
||||
Type: jscontact.OrganizationType,
|
||||
Name: person.Job.Company,
|
||||
Contexts: toBoolMapS(jscontact.OrganizationContextWork),
|
||||
}
|
||||
}, u)
|
||||
titleMaps[titleId] = map[string]any{
|
||||
"@type": "Title",
|
||||
"kind": "title",
|
||||
"name": person.Job.Title,
|
||||
"organizationId": orgId,
|
||||
}
|
||||
titleObjs[titleId] = jscontact.Title{
|
||||
// Type: jscontact.TitleType,
|
||||
titleObjs[titleId] = untype(jscontact.Title{
|
||||
Type: jscontact.TitleType,
|
||||
Kind: jscontact.TitleKindTitle,
|
||||
Name: person.Job.Title,
|
||||
OrganizationId: orgId,
|
||||
}
|
||||
}, u)
|
||||
}
|
||||
contact["organizations"] = organizationMaps
|
||||
contact["titles"] = titleMaps
|
||||
@@ -1058,12 +1060,12 @@ func (s *StalwartTest) fillContacts(
|
||||
return map[string]any{
|
||||
"@type": "CryptoKey",
|
||||
"uri": "data:application/pgp-keys;base64," + encoded,
|
||||
}, jscontact.CryptoKey{
|
||||
// Type: jscontact.CryptoKeyType,
|
||||
Uri: "data:application/pgp-keys;base64," + encoded,
|
||||
}, nil
|
||||
}, untype(jscontact.CryptoKey{
|
||||
Type: jscontact.CryptoKeyType,
|
||||
Uri: "data:application/pgp-keys;base64," + encoded,
|
||||
}, u), nil
|
||||
}); err != nil {
|
||||
return "", "", nil, nil, boxes, err
|
||||
return "", "", nil, boxes, err
|
||||
}
|
||||
|
||||
if err := propmap(i%2 == 0, 1, 2, contact, "media", &card.Media, func(i int, id string) (map[string]any, jscontact.Media, error) {
|
||||
@@ -1085,16 +1087,16 @@ func (s *StalwartTest) fillContacts(
|
||||
"mediaType": mime,
|
||||
"contexts": structs.MapKeys(contexts, func(c jscontact.MediaContext) string { return string(c) }),
|
||||
"label": label,
|
||||
}, jscontact.Media{
|
||||
// Type: jscontact.MediaType,
|
||||
}, untype(jscontact.Media{
|
||||
Type: jscontact.MediaType,
|
||||
Kind: jscontact.MediaKindPhoto,
|
||||
Uri: uri,
|
||||
MediaType: mime,
|
||||
Contexts: contexts,
|
||||
Label: label,
|
||||
}, nil
|
||||
// currently does not work, reported as https://github.com/stalwartlabs/stalwart/issues/2431
|
||||
case 99: // change this to 1 to enable it again
|
||||
}, u), nil
|
||||
// currently not supported, reported as https://github.com/stalwartlabs/stalwart/issues/2431
|
||||
case -1: // change this to 1 to enable it again
|
||||
boxes.mediaWithBlobId = true
|
||||
size := pickRandom(16, 24, 32, 48, 64)
|
||||
img := gofakeit.ImageJpeg(size, size)
|
||||
@@ -1109,14 +1111,14 @@ func (s *StalwartTest) fillContacts(
|
||||
"blobId": blob.BlobId,
|
||||
"contexts": structs.MapKeys(contexts, func(c jscontact.MediaContext) string { return string(c) }),
|
||||
"label": label,
|
||||
}, jscontact.Media{
|
||||
// Type: jscontact.MediaType,
|
||||
}, untype(jscontact.Media{
|
||||
Type: jscontact.MediaType,
|
||||
Kind: jscontact.MediaKindPhoto,
|
||||
BlobId: blob.BlobId,
|
||||
MediaType: blob.Type,
|
||||
Contexts: contexts,
|
||||
Label: label,
|
||||
}, nil
|
||||
}, u), nil
|
||||
|
||||
default:
|
||||
boxes.mediaWithExternalUri = true
|
||||
@@ -1129,16 +1131,16 @@ func (s *StalwartTest) fillContacts(
|
||||
"uri": uri,
|
||||
"contexts": structs.MapKeys(contexts, func(c jscontact.MediaContext) string { return string(c) }),
|
||||
"label": label,
|
||||
}, jscontact.Media{
|
||||
// Type: jscontact.MediaType,
|
||||
}, untype(jscontact.Media{
|
||||
Type: jscontact.MediaType,
|
||||
Kind: jscontact.MediaKindPhoto,
|
||||
Uri: uri,
|
||||
Contexts: contexts,
|
||||
Label: label,
|
||||
}, nil
|
||||
}, u), nil
|
||||
}
|
||||
}); err != nil {
|
||||
return "", "", nil, nil, boxes, err
|
||||
return "", "", nil, boxes, err
|
||||
}
|
||||
if err := propmap(i%2 == 0, 1, 1, contact, "links", &card.Links, func(i int, id string) (map[string]any, jscontact.Link, error) {
|
||||
boxes.link = true
|
||||
@@ -1147,26 +1149,32 @@ func (s *StalwartTest) fillContacts(
|
||||
"kind": "contact",
|
||||
"uri": "mailto:" + person.Contact.Email,
|
||||
"pref": (i + 1) * 10,
|
||||
}, jscontact.Link{
|
||||
// Type: jscontact.LinkType,
|
||||
}, untype(jscontact.Link{
|
||||
Type: jscontact.LinkType,
|
||||
Kind: jscontact.LinkKindContact,
|
||||
Uri: "mailto:" + person.Contact.Email,
|
||||
Pref: uint((i + 1) * 10),
|
||||
}, nil
|
||||
}, u), nil
|
||||
}); err != nil {
|
||||
return "", "", nil, nil, boxes, err
|
||||
return "", "", nil, boxes, err
|
||||
}
|
||||
|
||||
id, err := s.CreateContact(c, accountId, contact)
|
||||
if err != nil {
|
||||
return "", "", nil, nil, boxes, err
|
||||
return "", "", nil, boxes, err
|
||||
}
|
||||
card.Id = id
|
||||
filled[id] = card
|
||||
sent[id] = contact
|
||||
printer(fmt.Sprintf("🧑🏻 created %*s/%v uid=%v", int(math.Log10(float64(count))+1), strconv.Itoa(int(i+1)), count, id))
|
||||
}
|
||||
return accountId, addressbookId, filled, sent, boxes, nil
|
||||
return accountId, addressbookId, filled, boxes, nil
|
||||
}
|
||||
|
||||
func untype[S any](s S, t bool) S {
|
||||
if t {
|
||||
reflect.ValueOf(&s).Elem().FieldByName("Type").SetString("")
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *StalwartTest) CreateContact(j *TestJmapClient, accountId string, contact map[string]any) (string, error) {
|
||||
|
||||
@@ -149,9 +149,9 @@ func TestAnyValue(t *testing.T) {
|
||||
|
||||
assert.True(t, AnyValue(map[string]bool{"a": true, "b": false}, always))
|
||||
assert.False(t, AnyValue(map[string]bool{}, always))
|
||||
assert.False(t, AnyValue[string, bool](nil, always))
|
||||
assert.False(t, AnyValue[string](nil, always))
|
||||
assert.False(t, AnyValue(map[string]bool{"a": true, "b": false}, never))
|
||||
assert.False(t, AnyValue[string, bool](nil, never))
|
||||
assert.False(t, AnyValue[string](nil, never))
|
||||
}
|
||||
|
||||
func TestAnyItem(t *testing.T) {
|
||||
@@ -160,7 +160,7 @@ func TestAnyItem(t *testing.T) {
|
||||
|
||||
assert.True(t, AnyItem(map[string]bool{"a": true, "b": false}, always))
|
||||
assert.False(t, AnyItem(map[string]bool{}, always))
|
||||
assert.False(t, AnyItem[string, bool](nil, always))
|
||||
assert.False(t, AnyItem(nil, always))
|
||||
assert.False(t, AnyItem(map[string]bool{"a": true, "b": false}, never))
|
||||
assert.False(t, AnyItem[string, bool](nil, never))
|
||||
assert.False(t, AnyItem(nil, never))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user