complement/tests/federation_rooms_invite_test.go
kegsay a669c750c8
Remove Deployment.Client and change Deploy (#676)
* Remove Deployment.Client and change Deploy

- `Deployment.Client` was used to get pre-registered clients. Now we want tests to register new users for each test, for dirty runs. So swap for `Deployment.Register` everywhere.
- `Deploy` was used to deploy a blueprint. We don't want this to enable dirty runs. So replace it with the number of servers you need e.g `Deploy(t, 2)`.

* Fix up more broken refactoring

* unbreak tests; make user localpart look nicer

* Alice and bob must share a room for presence

* Fix user directory test

* Fix race condition caused by making the room later than before
2023-10-17 18:07:43 +01:00

140 lines
5 KiB
Go

package tests
import (
"testing"
"github.com/matrix-org/complement"
"github.com/matrix-org/gomatrixserverlib/spec"
"github.com/tidwall/gjson"
"github.com/matrix-org/complement/client"
"github.com/matrix-org/complement/helpers"
"github.com/matrix-org/complement/match"
"github.com/matrix-org/complement/must"
)
func TestFederationRoomsInvite(t *testing.T) {
deployment := complement.Deploy(t, 2)
defer deployment.Destroy(t)
alice := deployment.Register(t, "hs1", helpers.RegistrationOpts{})
bob := deployment.Register(t, "hs2", helpers.RegistrationOpts{})
t.Run("Parallel", func(t *testing.T) {
// sytest: Invited user can reject invite over federation
t.Run("Invited user can reject invite over federation", func(t *testing.T) {
t.Parallel()
roomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "private_chat",
"invite": []string{bob.UserID},
})
bob.MustSyncUntil(t, client.SyncReq{}, client.SyncInvitedTo(bob.UserID, roomID))
bob.MustLeaveRoom(t, roomID)
alice.MustSyncUntil(t, client.SyncReq{}, client.SyncLeftFrom(bob.UserID, roomID))
})
// sytest: Invited user can reject invite over federation several times
t.Run("Invited user can reject invite over federation several times", func(t *testing.T) {
t.Parallel()
roomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "private_chat",
})
for i := 0; i < 3; i++ {
alice.MustInviteRoom(t, roomID, bob.UserID)
bob.MustSyncUntil(t, client.SyncReq{}, client.SyncInvitedTo(bob.UserID, roomID))
bob.MustLeaveRoom(t, roomID)
alice.MustSyncUntil(t, client.SyncReq{}, client.SyncLeftFrom(bob.UserID, roomID))
}
})
// sytest: Invited user can reject invite over federation for empty room
t.Run("Invited user can reject invite over federation for empty room", func(t *testing.T) {
t.Parallel()
roomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "private_chat",
"invite": []string{bob.UserID},
})
aliceSince := alice.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(alice.UserID, roomID))
bobSince := bob.MustSyncUntil(t, client.SyncReq{}, client.SyncInvitedTo(bob.UserID, roomID))
alice.MustLeaveRoom(t, roomID)
alice.MustSyncUntil(t, client.SyncReq{Since: aliceSince}, client.SyncLeftFrom(alice.UserID, roomID))
bob.MustLeaveRoom(t, roomID)
bob.MustSyncUntil(t, client.SyncReq{Since: bobSince}, client.SyncLeftFrom(bob.UserID, roomID))
})
// sytest: Remote invited user can see room metadata
t.Run("Remote invited user can see room metadata", func(t *testing.T) {
t.Parallel()
roomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "private_chat",
"name": "Invites room",
"invite": []string{bob.UserID},
})
wantFields := map[string]string{
"m.room.join_rules": "join_rule",
"m.room.name": "name",
}
wantValues := map[string]string{
"m.room.join_rules": "invite",
"m.room.name": "Invites room",
}
bob.MustSyncUntil(t, client.SyncReq{}, client.SyncInvitedTo(bob.UserID, roomID))
res, _ := bob.MustSync(t, client.SyncReq{})
verifyState(t, res, wantFields, wantValues, roomID, alice)
})
t.Run("Invited user has 'is_direct' flag in prev_content after joining", func(t *testing.T) {
roomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "private_chat",
"name": "Invites room",
// invite Bob and make the room a DM, so we can verify m.direct flag is in the prev_content after joining
"invite": []string{bob.UserID},
"is_direct": true,
})
bob.MustJoinRoom(t, roomID, []string{})
bob.MustSyncUntil(t, client.SyncReq{},
client.SyncTimelineHas(roomID, func(result gjson.Result) bool {
// We expect a membership event ..
if result.Get("type").Str != spec.MRoomMember {
return false
}
// .. for Bob
if result.Get("state_key").Str != bob.UserID {
return false
}
// Check that we've got tbe expected is_idrect flag
return result.Get("unsigned.prev_content.membership").Str == "invite" &&
result.Get("unsigned.prev_content.is_direct").Bool() == true &&
result.Get("unsigned.prev_sender").Str == alice.UserID
}),
)
})
})
}
// verifyState checks that the fields in "wantFields" are present in invite_state.events
func verifyState(t *testing.T, res gjson.Result, wantFields, wantValues map[string]string, roomID string, cl *client.CSAPI) {
inviteEvents := res.Get("rooms.invite." + client.GjsonEscape(roomID) + ".invite_state.events")
if !inviteEvents.Exists() {
t.Errorf("expected invite events, but they don't exist")
}
for _, event := range inviteEvents.Array() {
eventType := event.Get("type").Str
field, ok := wantFields[eventType]
if !ok {
continue
}
wantValue := wantValues[eventType]
eventStateKey := event.Get("state_key").Str
res := cl.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", eventType, eventStateKey})
must.MatchResponse(t, res, match.HTTPResponse{
JSON: []match.JSON{
match.JSONKeyEqual(field, wantValue),
},
})
}
}