complement/tests/csapi/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

186 lines
6.8 KiB
Go

package csapi_tests
import (
"net/http"
"testing"
"github.com/matrix-org/complement"
"github.com/matrix-org/complement/client"
"github.com/matrix-org/complement/helpers"
"github.com/matrix-org/complement/match"
"github.com/matrix-org/complement/must"
"github.com/tidwall/gjson"
)
func TestRoomsInvite(t *testing.T) {
deployment := complement.Deploy(t, 1)
defer deployment.Destroy(t)
alice := deployment.Register(t, "hs1", helpers.RegistrationOpts{})
bob := deployment.Register(t, "hs1", helpers.RegistrationOpts{})
t.Run("Parallel", func(t *testing.T) {
// sytest: Can invite users to invite-only rooms
t.Run("Can invite users to invite-only rooms", func(t *testing.T) {
t.Parallel()
roomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "private_chat",
})
alice.MustInviteRoom(t, roomID, bob.UserID)
bob.MustSyncUntil(t, client.SyncReq{}, client.SyncInvitedTo(bob.UserID, roomID))
bob.MustJoinRoom(t, roomID, []string{})
bob.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(bob.UserID, roomID))
alice.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(bob.UserID, roomID))
})
// sytest: Uninvited users cannot join the room
t.Run("Uninvited users cannot join the room", func(t *testing.T) {
t.Parallel()
roomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "private_chat",
})
res := bob.JoinRoom(t, roomID, nil)
must.MatchResponse(t, res, match.HTTPResponse{
StatusCode: http.StatusForbidden,
})
})
// sytest: Invited user can reject invite
t.Run("Invited user can reject invite", func(t *testing.T) {
t.Parallel()
roomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "private_chat",
})
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 for empty room
t.Run("Invited user can reject invite for empty room", func(t *testing.T) {
t.Parallel()
roomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "private_chat",
})
aliceSince := alice.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(alice.UserID, roomID))
alice.MustInviteRoom(t, roomID, bob.UserID)
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)
bobSince = bob.MustSyncUntil(t, client.SyncReq{Since: bobSince}, client.SyncLeftFrom(bob.UserID, roomID))
// sytest: Invited user can reject local invite after originator leaves
// Bob should not see an invite when syncing
res, _ := bob.MustSync(t, client.SyncReq{Since: bobSince})
// we filter on the specific roomID, since we run in parallel
if res.Get("rooms.invite." + client.GjsonEscape(roomID)).Exists() {
t.Fatalf("rooms.invite should not exist: %+v", res.Get("rooms.invite").Raw)
}
})
// sytest: Users cannot invite themselves to a room
t.Run("Users cannot invite themselves to a room", func(t *testing.T) {
t.Parallel()
roomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "private_chat",
})
res := alice.InviteRoom(t, roomID, alice.UserID)
must.MatchResponse(t, res, match.HTTPResponse{
StatusCode: http.StatusForbidden,
})
})
// sytest: Users cannot invite a user that is already in the room
t.Run("Users cannot invite a user that is already in the room", func(t *testing.T) {
t.Parallel()
roomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "private_chat",
})
alice.MustInviteRoom(t, roomID, bob.UserID)
bob.MustSyncUntil(t, client.SyncReq{}, client.SyncInvitedTo(bob.UserID, roomID))
bob.MustJoinRoom(t, roomID, []string{})
alice.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(bob.UserID, roomID))
res := alice.InviteRoom(t, roomID, bob.UserID)
must.MatchResponse(t, res, match.HTTPResponse{
StatusCode: http.StatusForbidden,
})
})
// sytest: Invited user can see room metadata
t.Run("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",
})
alice.MustInviteRoom(t, roomID, bob.UserID)
bob.MustSyncUntil(t, client.SyncReq{}, client.SyncInvitedTo(bob.UserID, roomID))
res, _ := bob.MustSync(t, client.SyncReq{})
verifyState(t, res, roomID, alice)
})
// sytest: Test that we can be reinvited to a room we created
// This is a "multi_test" in Sytest
t.Run("Test that we can be reinvited to a room we created", func(t *testing.T) {
t.Parallel()
roomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "private_chat",
})
// Invite & join bob
alice.MustInviteRoom(t, roomID, bob.UserID)
bob.MustSyncUntil(t, client.SyncReq{}, client.SyncInvitedTo(bob.UserID, roomID))
bob.MustJoinRoom(t, roomID, []string{})
alice.MustSyncUntil(t, client.SyncReq{}, client.SyncInvitedTo(bob.UserID, roomID))
// Raise the powerlevel
reqBody := client.WithJSONBody(t, map[string]interface{}{
"users": map[string]int64{
bob.UserID: 100,
},
})
alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.power_levels"}, reqBody)
// Alice leaves the room
alice.MustLeaveRoom(t, roomID)
bob.MustSyncUntil(t, client.SyncReq{}, client.SyncLeftFrom(alice.UserID, roomID))
// Bob re-invites Alice
bob.MustInviteRoom(t, roomID, alice.UserID)
alice.MustSyncUntil(t, client.SyncReq{}, client.SyncInvitedTo(alice.UserID, roomID))
// Alice should be able to rejoin
alice.MustJoinRoom(t, roomID, []string{})
bob.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(alice.UserID, roomID))
})
})
}
// verifyState checks that the fields in "wantFields" are present in invite_state.events
func verifyState(t *testing.T, res gjson.Result, roomID string, cl *client.CSAPI) {
wantFields := map[string]string{
"m.room.join_rules": "join_rule",
"m.room.name": "name",
}
for _, event := range res.Get("rooms.invite." + client.GjsonEscape(roomID) + ".invite_state.events").Array() {
eventType := event.Get("type").Str
field, ok := wantFields[eventType]
if !ok {
continue
}
eventContent := event.Get("content." + field).Str
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, eventContent),
},
})
}
}