oficina / meet Public

Clone
git clone https://amadan.net/oficina/meet

Plain git — no account needed to clone.

Download

Download this file

1package callstest
2
3import (
4 "net/http"
5 "net/url"
6 "strings"
7 "testing"
8 "time"
9)
10
11func enableWaitingRoom(t *testing.T, x *harness, sqid string) {
12 t.Helper()
13 c := x.browser(t)
14 c.signIn("paul@example.com")
15 if r := c.post("/meetings/"+sqid+"/settings", url.Values{"waiting_room": {"on"}}); r.Code != 303 {
16 t.Fatal(r.Code, r.Body.String())
17 }
18}
19
20func TestMeetingDefaultsAndIndependentOverrides(t *testing.T) {
21 x := newHarness(t, "paul@example.com")
22 c := x.browser(t)
23 c.signIn("paul@example.com")
24 old, _ := createMeeting(t, c, "Original", "")
25 if r := c.post("/settings/defaults", url.Values{"require_signin": {"on"}, "waiting_room": {"on"}}); r.Code != 303 {
26 t.Fatal(r.Code)
27 }
28 next, token := createMeeting(t, c, "Restricted", "")
29 if r := x.browser(t).get("/j/" + token); r.Code != 303 || r.Header().Get("Location") != "/signin" {
30 t.Fatal("sign-in not required", r.Code)
31 }
32 for _, tc := range []struct {
33 sqid string
34 checked bool
35 }{{old, false}, {next, true}} {
36 r := c.get("/meetings/" + tc.sqid + "/settings")
37 if r.Code != 200 || strings.Contains(r.Body.String(), " checked") != tc.checked {
38 t.Fatal("settings not retained", r.Body.String())
39 }
40 }
41 if r := c.post("/meetings/"+next+"/settings", url.Values{}); r.Code != 303 {
42 t.Fatal(r.Code)
43 }
44 if r := x.browser(t).get("/j/" + token); r.Code != 200 {
45 t.Fatal("guest override not applied", r.Code)
46 }
47 if r := c.get("/settings"); !strings.Contains(r.Body.String(), " checked") {
48 t.Fatal("override altered defaults")
49 }
50}
51
52func TestAnonymousGuestJoinsWithoutMemberPowers(t *testing.T) {
53 x, sqid, token := memberWithMeeting(t)
54 g := x.browser(t)
55 r := g.get("/j/" + token)
56 if r.Code != 200 || !strings.Contains(r.Body.String(), "oficina-calls://join?") {
57 t.Fatal("missing guest/app choice", r.Code)
58 }
59 if r := g.post("/j/"+token+"/guest", url.Values{"name": {" "}}); r.Code != 422 {
60 t.Fatal("empty name accepted")
61 }
62 if r := g.post("/j/"+token+"/guest", url.Values{"name": {"Visitor"}}); r.Code != 303 {
63 t.Fatal(r.Code, r.Body.String())
64 }
65 if r := g.get("/m/" + sqid + "/join"); r.Code != 200 || !strings.Contains(r.Body.String(), "Visitor") {
66 t.Fatal("guest holding", r.Code, r.Body.String())
67 }
68 for _, path := range []string{"/settings", "/meetings/" + sqid + "/settings", "/"} {
69 if r := g.get(path); r.Code != 404 {
70 t.Fatal("guest can reach", path, r.Code)
71 }
72 }
73 if r := g.post("/meetings/"+sqid+"/settings", url.Values{"waiting_room": {"on"}}); r.Code != 404 {
74 t.Fatal("guest can change settings")
75 }
76 s := g.stream("/m/" + sqid + "/stream")
77 defer s.close()
78 peer, _ := s.hello()
79 if res, b := g.signal(sqid, peer, `{"type":"join"}`); res.StatusCode != http.StatusOK {
80 t.Fatal(res.StatusCode, string(b))
81 }
82 if _, data, ok := s.nextOf("roster", 2*time.Second); !ok || !strings.Contains(string(data), `"kind":"guest"`) {
83 t.Fatal("guest not directly admitted", string(data))
84 }
85}
86
87func TestAnonymousEntryRefusesRestrictedAndRevokedInvitations(t *testing.T) {
88 x, sqid, token := memberWithMeeting(t)
89 m := x.browser(t)
90 m.signIn("paul@example.com")
91 g := x.browser(t)
92 m.post("/meetings/"+sqid+"/settings", url.Values{"require_signin": {"on"}})
93 if r := g.post("/j/"+token+"/guest", url.Values{"name": {"Visitor"}}); r.Code != 303 || r.Header().Get("Location") != "/signin" {
94 t.Fatal("restricted guest POST accepted")
95 }
96 m.post("/meetings/"+sqid+"/settings", url.Values{})
97 g.post("/j/"+token+"/guest", url.Values{"name": {"Visitor"}})
98 m.post("/meetings/"+sqid+"/settings", url.Values{"require_signin": {"on"}})
99 if r := g.get("/m/" + sqid + "/join"); r.Code != 404 {
100 t.Fatal("guest bypassed new sign-in requirement")
101 }
102 m.post("/meetings/"+sqid+"/links", nil)
103 if r := x.browser(t).post("/j/"+token+"/guest", url.Values{"name": {"Visitor"}}); r.Code != 404 {
104 t.Fatal("revoked invitation accepted")
105 }
106}
107
108func TestTurningOffWaitingRoomAdmitsQueuedAnonymousGuest(t *testing.T) {
109 x, sqid, token := memberWithMeeting(t)
110 enableWaitingRoom(t, x, sqid)
111 g := x.browser(t)
112 if r := g.post("/j/"+token+"/guest", url.Values{"name": {"Waiting visitor"}}); r.Code != 303 {
113 t.Fatal(r.Code)
114 }
115 s := g.stream("/m/" + sqid + "/stream")
116 defer s.close()
117 peer, _ := s.hello()
118 if r, b := g.signal(sqid, peer, `{"type":"join"}`); r.StatusCode != 200 {
119 t.Fatal(r.StatusCode, string(b))
120 }
121 if r := g.getStream("/m/" + sqid + "/ice?peer=" + peer); r.Code != 404 {
122 t.Fatal("waiting guest admitted prematurely", r.Code)
123 }
124 member := x.browser(t)
125 member.signIn("paul@example.com")
126 if r := member.post("/meetings/"+sqid+"/settings", url.Values{}); r.Code != 303 {
127 t.Fatal(r.Code)
128 }
129 if _, _, ok := s.nextOf("roster", 2*time.Second); !ok {
130 t.Fatal("queued guest not admitted after disabling waiting room")
131 }
132}
133