From 10fcfb9f1ed665e2baa8e85025a6a14638447fbd Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Thu, 5 Aug 2021 15:19:45 -0400 Subject: [PATCH 1/4] Test the updated MSC2946 room hierarchy endpoint. --- tests/msc2946_test.go | 122 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) diff --git a/tests/msc2946_test.go b/tests/msc2946_test.go index 5280f9b2..c8fa868d 100644 --- a/tests/msc2946_test.go +++ b/tests/msc2946_test.go @@ -220,6 +220,39 @@ func TestClientSpacesSummary(t *testing.T) { }, nil), }, }) + + res = alice.MustDo(t, "GET", []string{"_matrix", "client", "unstable", "org.matrix.msc2946", "rooms", root, "hierarchy"}, nil) + must.MatchResponse(t, res, match.HTTPResponse{ + JSON: []match.JSON{ + match.JSONCheckOff("rooms", []interface{}{ + root, r1, r2, r3, r4, ss1, ss2, + }, func(r gjson.Result) interface{} { + return r.Get("room_id").Str + }, func(roomInt interface{}, data gjson.Result) error { + roomID := roomInt.(string) + // check fields + if name, ok := roomNames[roomID]; ok { + if data.Get("name").Str != name { + return fmt.Errorf("room %s got name %s want %s", roomID, data.Get("name").Str, name) + } + } + if roomID == ss1 { + wantType := "m.space" + if data.Get("room_type").Str != wantType { + return fmt.Errorf("room %s got type %s want %s", roomID, data.Get("room_type").Str, wantType) + } + } + return nil + }), + // Check that the links from Root down to other rooms and spaces exist. + match.JSONCheckOff("rooms.#.children_state|@flatten", []interface{}{ + rootToR1, rootToR2, rootToSS1, + ss1ToSS2, ss2ToR3, ss2ToR4, + }, func(r gjson.Result) interface{} { + return eventKey(r.Get("room_id").Str, r.Get("state_key").Str, r.Get("type").Str) + }, nil), + }, + }) }) // - Setting max_rooms_per_space works correctly @@ -251,6 +284,34 @@ func TestClientSpacesSummary(t *testing.T) { } }) + // - Setting max_depth works correctly + t.Run("max_depth", func(t *testing.T) { + // Should only include R1, SS1, and R2. + query := make(url.Values, 1) + query.Set("max_depth", "1") + res := alice.MustDoFunc( + t, + "GET", + []string{"_matrix", "client", "unstable", "org.matrix.msc2946", "rooms", root, "hierarchy"}, + client.WithQueries(query), + ) + must.MatchResponse(t, res, match.HTTPResponse{ + JSON: []match.JSON{ + match.JSONCheckOff("rooms", []interface{}{ + root, r1, r2, ss1, + }, func(r gjson.Result) interface{} { + return r.Get("room_id").Str + }, nil), + // All of the links are still there. + match.JSONCheckOff("rooms.#.children_state|@flatten", []interface{}{ + rootToR1, rootToR2, rootToSS1, ss1ToSS2, + }, func(r gjson.Result) interface{} { + return eventKey(r.Get("room_id").Str, r.Get("state_key").Str, r.Get("type").Str) + }, nil), + }, + }) + }) + t.Run("redact link", func(t *testing.T) { // Remove the root -> SS1 link alice.SendEventSynced(t, root, b.Event{ @@ -273,6 +334,22 @@ func TestClientSpacesSummary(t *testing.T) { }, nil), }, }) + + res = alice.MustDo(t, "GET", []string{"_matrix", "client", "unstable", "org.matrix.msc2946", "rooms", root, "hierarchy"}, nil) + must.MatchResponse(t, res, match.HTTPResponse{ + JSON: []match.JSON{ + match.JSONCheckOff("rooms", []interface{}{ + root, r1, r2, + }, func(r gjson.Result) interface{} { + return r.Get("room_id").Str + }, nil), + match.JSONCheckOff("rooms.#.children_state|@flatten", []interface{}{ + rootToR1, rootToR2, + }, func(r gjson.Result) interface{} { + return eventKey(r.Get("room_id").Str, r.Get("state_key").Str, r.Get("type").Str) + }, nil), + }, + }) }) } @@ -387,6 +464,21 @@ func TestClientSpacesSummaryJoinRules(t *testing.T) { }, nil), }, }) + res = bob.MustDo(t, "GET", []string{"_matrix", "client", "unstable", "org.matrix.msc2946", "rooms", root, "hierarchy"}, nil) + must.MatchResponse(t, res, match.HTTPResponse{ + JSON: []match.JSON{ + match.JSONCheckOff("rooms", []interface{}{ + root, + }, func(r gjson.Result) interface{} { + return r.Get("room_id").Str + }, nil), + match.JSONCheckOff("rooms.#.children_state|@flatten", []interface{}{ + rootToR1, rootToSS1, + }, func(r gjson.Result) interface{} { + return eventKey(r.Get("room_id").Str, r.Get("state_key").Str, r.Get("type").Str) + }, nil), + }, + }) // Invite to R1 and R3, querying again should only show R1 (since SS1 is not visible). alice.InviteRoom(t, r1, bob.UserID) @@ -407,6 +499,21 @@ func TestClientSpacesSummaryJoinRules(t *testing.T) { }, nil), }, }) + res = bob.MustDo(t, "GET", []string{"_matrix", "client", "unstable", "org.matrix.msc2946", "rooms", root, "hierarchy"}, nil) + must.MatchResponse(t, res, match.HTTPResponse{ + JSON: []match.JSON{ + match.JSONCheckOff("rooms", []interface{}{ + root, r1, + }, func(r gjson.Result) interface{} { + return r.Get("room_id").Str + }, nil), + match.JSONCheckOff("rooms.#.children_state|@flatten", []interface{}{ + rootToR1, rootToSS1, + }, func(r gjson.Result) interface{} { + return eventKey(r.Get("room_id").Str, r.Get("state_key").Str, r.Get("type").Str) + }, nil), + }, + }) // Invite to SS1 and it now appears, as well as the rooms under it. alice.InviteRoom(t, ss1, bob.UserID) @@ -426,6 +533,21 @@ func TestClientSpacesSummaryJoinRules(t *testing.T) { }, nil), }, }) + res = bob.MustDo(t, "GET", []string{"_matrix", "client", "unstable", "org.matrix.msc2946", "rooms", root, "hierarchy"}, nil) + must.MatchResponse(t, res, match.HTTPResponse{ + JSON: []match.JSON{ + match.JSONCheckOff("rooms", []interface{}{ + root, r1, ss1, r2, r3, + }, func(r gjson.Result) interface{} { + return r.Get("room_id").Str + }, nil), + match.JSONCheckOff("rooms.#.children_state|@flatten", []interface{}{ + rootToR1, rootToSS1, ss1ToR2, ss1ToR3, + }, func(r gjson.Result) interface{} { + return eventKey(r.Get("room_id").Str, r.Get("state_key").Str, r.Get("type").Str) + }, nil), + }, + }) } // Tests that MSC2946 works over federation. Creates a space directory like: From be04a662e73f8a7fa98ac1c051b72885f20d28f7 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Fri, 6 Aug 2021 08:06:32 -0400 Subject: [PATCH 2/4] Add tests for pagination. --- tests/msc2946_test.go | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/tests/msc2946_test.go b/tests/msc2946_test.go index c8fa868d..29aefff5 100644 --- a/tests/msc2946_test.go +++ b/tests/msc2946_test.go @@ -312,6 +312,47 @@ func TestClientSpacesSummary(t *testing.T) { }) }) + // - Setting max_depth works correctly + t.Run("pagination", func(t *testing.T) { + // The initial page should only include Root, R1, SS1, and SS2. + query := make(url.Values, 1) + query.Set("limit", "4") + res := alice.MustDoFunc( + t, + "GET", + []string{"_matrix", "client", "unstable", "org.matrix.msc2946", "rooms", root, "hierarchy"}, + client.WithQueries(query), + ) + body := must.MatchResponse(t, res, match.HTTPResponse{ + JSON: []match.JSON{ + match.JSONCheckOff("rooms", []interface{}{ + root, r1, ss1, ss2, + }, func(r gjson.Result) interface{} { + return r.Get("room_id").Str + }, nil), + }, + }) + + // The following page should include R3, R4, and R2. + query = make(url.Values, 1) + query.Set("from", client.GetJSONFieldStr(t, body, "next_token")) + res = alice.MustDoFunc( + t, + "GET", + []string{"_matrix", "client", "unstable", "org.matrix.msc2946", "rooms", root, "hierarchy"}, + client.WithQueries(query), + ) + must.MatchResponse(t, res, match.HTTPResponse{ + JSON: []match.JSON{ + match.JSONCheckOff("rooms", []interface{}{ + r3, r4, r2, + }, func(r gjson.Result) interface{} { + return r.Get("room_id").Str + }, nil), + }, + }) + }) + t.Run("redact link", func(t *testing.T) { // Remove the root -> SS1 link alice.SendEventSynced(t, root, b.Event{ From c359e5a8b04d7a5db8b19886d3bce6b20fe6c5e2 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Fri, 6 Aug 2021 08:19:03 -0400 Subject: [PATCH 3/4] Add tests for suggested_only. --- tests/msc2946_test.go | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/tests/msc2946_test.go b/tests/msc2946_test.go index 29aefff5..81fabafc 100644 --- a/tests/msc2946_test.go +++ b/tests/msc2946_test.go @@ -42,6 +42,7 @@ func eventKey(srcRoomID, dstRoomID, evType string) string { // - the user is joined to all rooms except R4. // - R2 <---> Root is a two-way link. // - The remaining links are just children links. +// - R1 and R2 are suggested rooms. // // Tests that: // - Querying the root returns the entire graph @@ -125,7 +126,8 @@ func TestClientSpacesSummary(t *testing.T) { Type: spaceChildEventType, StateKey: &r1, Content: map[string]interface{}{ - "via": []string{"hs1"}, + "via": []string{"hs1"}, + "suggested": true, }, }) rootToSS1 := eventKey(root, ss1, spaceChildEventType) @@ -141,7 +143,8 @@ func TestClientSpacesSummary(t *testing.T) { Type: spaceChildEventType, StateKey: &r2, Content: map[string]interface{}{ - "via": []string{"hs1"}, + "via": []string{"hs1"}, + "suggested": true, }, }) // Note that this link gets ignored since R2 is not a space. @@ -312,6 +315,34 @@ func TestClientSpacesSummary(t *testing.T) { }) }) + // - Setting suggested_only works correctly + t.Run("suggested_only", func(t *testing.T) { + // Should only include R1, SS1, and R2. + query := make(url.Values, 1) + query.Set("suggested_only", "true") + res := alice.MustDoFunc( + t, + "GET", + []string{"_matrix", "client", "unstable", "org.matrix.msc2946", "rooms", root, "hierarchy"}, + client.WithQueries(query), + ) + must.MatchResponse(t, res, match.HTTPResponse{ + JSON: []match.JSON{ + match.JSONCheckOff("rooms", []interface{}{ + root, r1, r2, + }, func(r gjson.Result) interface{} { + return r.Get("room_id").Str + }, nil), + // All of the links are still there. + match.JSONCheckOff("rooms.#.children_state|@flatten", []interface{}{ + rootToR1, rootToR2, + }, func(r gjson.Result) interface{} { + return eventKey(r.Get("room_id").Str, r.Get("state_key").Str, r.Get("type").Str) + }, nil), + }, + }) + }) + // - Setting max_depth works correctly t.Run("pagination", func(t *testing.T) { // The initial page should only include Root, R1, SS1, and SS2. From 7d408740273da8a307562fbe69163995399cb4a9 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Tue, 10 Aug 2021 11:38:53 -0400 Subject: [PATCH 4/4] Add a note about deprecating the /spaces endpoint. --- tests/msc2946_test.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/msc2946_test.go b/tests/msc2946_test.go index 81fabafc..4ef8f400 100644 --- a/tests/msc2946_test.go +++ b/tests/msc2946_test.go @@ -1,5 +1,18 @@ // +build msc2946 +// This file includes tests for MSC2946, the spaces summary API. +// +// There are currently tests for two unstable versions of it for backwards +// compatibility: +// +// * The /spaces endpoint, which was the original version. +// * The /hierarchy endpoint, which is an updated version. +// +// Both endpoints return data from the same set of rooms / spaces, but have +// different API shapes. +// +// TODO When support for this is stable, the tests for /spaces should be removed. + package tests import (