Skip to content

Commit 6a10106

Browse files
committed
MSC4308: Thread Subscriptions extension to Sliding Sync tests
1 parent 109ba45 commit 6a10106

2 files changed

Lines changed: 111 additions & 0 deletions

File tree

client/client.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"encoding/json"
99
"fmt"
1010
"io"
11+
"log"
1112
"math/rand"
1213
"net/http"
1314
"net/http/httputil"
@@ -752,6 +753,19 @@ func (t *loggedRoundTripper) RoundTrip(req *http.Request) (*http.Response, error
752753
return res, err
753754
}
754755

756+
// Extracts a JSON object given a search key
757+
// Caller must check `result.Exists()` to see whether the object actually exists.
758+
func GetOptionalJSONFieldObject(t ct.TestLike, body []byte, wantKey string) gjson.Result {
759+
t.Helper()
760+
res := gjson.GetBytes(body, wantKey)
761+
if !res.Exists() {
762+
log.Printf("OptionalJSONFieldObject: key '%s' absent from %s", wantKey, string(body))
763+
} else if !res.IsObject() {
764+
ct.Fatalf(t, "OptionalJSONFieldObject: key '%s' is not an object, body: %s", wantKey, string(body))
765+
}
766+
return res
767+
}
768+
755769
// GetJSONFieldStr extracts a value from a byte-encoded JSON body given a search key
756770
func GetJSONFieldStr(t ct.TestLike, body []byte, wantKey string) string {
757771
t.Helper()
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package tests
2+
3+
import (
4+
"testing"
5+
6+
"github.com/matrix-org/complement"
7+
"github.com/matrix-org/complement/b"
8+
"github.com/matrix-org/complement/client"
9+
"github.com/matrix-org/complement/helpers"
10+
"github.com/matrix-org/complement/match"
11+
"github.com/matrix-org/complement/must"
12+
"github.com/tidwall/gjson"
13+
)
14+
15+
func MustDoSlidingSync(t *testing.T, user *client.CSAPI, pos string, thread_subs_ext map[string]interface{}) (string, gjson.Result) {
16+
body := map[string]interface{}{
17+
"extensions": map[string]interface{}{
18+
"io.element.msc4308.thread_subscriptions": thread_subs_ext,
19+
},
20+
}
21+
if pos != "" {
22+
body["pos"] = pos
23+
}
24+
resp := user.MustDo(t, "POST", []string{"_matrix", "client", "unstable", "org.matrix.simplified_msc3575", "sync"}, client.WithJSONBody(t, body))
25+
respBody := client.ParseJSON(t, resp)
26+
27+
newPos := client.GetJSONFieldStr(t, respBody, "pos")
28+
extension := client.GetOptionalJSONFieldObject(t, respBody, "extensions.io\\.element\\.msc4308\\.thread_subscriptions")
29+
if !extension.Exists() {
30+
// Missing extension is semantically the same as an empty one
31+
// So eliminate the nil for simplicity
32+
extension = gjson.Parse("{}")
33+
}
34+
return newPos, extension
35+
}
36+
37+
func TestThreadSubscriptionsSlidingSync(t *testing.T) {
38+
deployment := complement.Deploy(t, 1)
39+
defer deployment.Destroy(t)
40+
41+
t.Run("Receives thread subscriptions over initial sliding sync", func(t *testing.T) {
42+
alice := deployment.Register(t, "hs1", helpers.RegistrationOpts{})
43+
roomID := alice.MustCreateRoom(t, map[string]interface{}{})
44+
threadRootID := alice.SendEventSynced(t, roomID, b.Event{
45+
Type: "m.room.message",
46+
Content: map[string]interface{}{
47+
"msgtype": "m.text",
48+
"body": "what do you think? reply in a thread!",
49+
},
50+
})
51+
52+
// Subscribe to the thread manually
53+
alice.MustDo(t, "PUT", []string{"_matrix", "client", "unstable", "io.element.msc4306", "rooms", roomID, "thread", threadRootID, "subscription"}, client.WithJSONBody(t, map[string]interface{}{}))
54+
55+
_, ext := MustDoSlidingSync(t, alice, "", map[string]interface{}{
56+
"enabled": true,
57+
"limit": 2,
58+
})
59+
60+
must.MatchGJSON(t, ext,
61+
match.JSONKeyTypeEqual("subscribed."+gjson.Escape(roomID)+"."+gjson.Escape(threadRootID)+".bump_stamp", gjson.Number),
62+
match.JSONKeyEqual("subscribed."+gjson.Escape(roomID)+"."+gjson.Escape(threadRootID)+".automatic", false),
63+
)
64+
})
65+
66+
t.Run("Receives thread subscriptions over incremental sliding sync", func(t *testing.T) {
67+
alice := deployment.Register(t, "hs1", helpers.RegistrationOpts{})
68+
roomID := alice.MustCreateRoom(t, map[string]interface{}{})
69+
threadRootID := alice.SendEventSynced(t, roomID, b.Event{
70+
Type: "m.room.message",
71+
Content: map[string]interface{}{
72+
"msgtype": "m.text",
73+
"body": "what do you think? reply in a thread!",
74+
},
75+
})
76+
77+
newPos, ext := MustDoSlidingSync(t, alice, "", map[string]interface{}{
78+
"enabled": true,
79+
"limit": 2,
80+
})
81+
must.MatchGJSON(t, ext,
82+
match.JSONKeyMissing("subscribed"))
83+
84+
// Subscribe to the thread manually
85+
alice.MustDo(t, "PUT", []string{"_matrix", "client", "unstable", "io.element.msc4306", "rooms", roomID, "thread", threadRootID, "subscription"}, client.WithJSONBody(t, map[string]interface{}{}))
86+
87+
_, ext = MustDoSlidingSync(t, alice, newPos, map[string]interface{}{
88+
"enabled": true,
89+
"limit": 2,
90+
})
91+
92+
must.MatchGJSON(t, ext,
93+
match.JSONKeyTypeEqual("subscribed."+gjson.Escape(roomID)+"."+gjson.Escape(threadRootID)+".bump_stamp", gjson.Number),
94+
match.JSONKeyEqual("subscribed."+gjson.Escape(roomID)+"."+gjson.Escape(threadRootID)+".automatic", false),
95+
)
96+
})
97+
}

0 commit comments

Comments
 (0)