1package xmpp
2
3import (
4	"bytes"
5	"encoding/xml"
6	"strings"
7
8	"github.com/coyim/coyim/xmpp/data"
9	. "gopkg.in/check.v1"
10)
11
12type MUCSuite struct{}
13
14var _ = Suite(&MUCSuite{})
15
16func (s *MUCSuite) Test_CanJoinRoom(c *C) {
17	mockOut := &mockConnIOReaderWriter{}
18	conn := conn{
19		out:  mockOut,
20		rand: &mockConnIOReaderWriter{read: []byte("123555111654")},
21	}
22
23	err := conn.GetChatContext().EnterRoom(&data.Occupant{
24		Room:   data.Room{ID: "coyim", Service: "chat.coy.im"},
25		Handle: "i_am_coy",
26	})
27	c.Assert(err, IsNil)
28	c.Assert(string(mockOut.write), Equals, `<presence xmlns="jabber:client" `+
29		`id="3544672884359377457" `+
30		`to="coyim@chat.coy.im/i_am_coy">`+
31		`<x xmlns='http://jabber.org/protocol/muc'/>`+
32		`</presence>`)
33}
34
35func (s *MUCSuite) Test_CanLeaveRoom(c *C) {
36	mockOut := &mockConnIOReaderWriter{}
37	conn := conn{
38		out:  mockOut,
39		rand: &mockConnIOReaderWriter{read: []byte("123555111654")},
40	}
41
42	err := conn.GetChatContext().LeaveRoom(&data.Occupant{
43		Room:   data.Room{ID: "coyim", Service: "chat.coy.im"},
44		Handle: "i_am_coy",
45	})
46	c.Assert(err, IsNil)
47	c.Assert(string(mockOut.write), Equals, `<presence xmlns="jabber:client" `+
48		`id="3544672884359377457" `+
49		`to="coyim@chat.coy.im/i_am_coy" `+
50		`type="unavailable">`+
51		`<x xmlns='http://jabber.org/protocol/muc'/>`+
52		`</presence>`)
53}
54
55func (s *MUCSuite) Test_CanRequestRoomConfigForm(c *C) {
56
57	//See Example 165. Service Sends Configuration Form to Owner
58	expectedResponse := `<iq xmlns='jabber:client' from='coven@chat.shakespeare.lit'
59    id='1'
60    to='crone1@shakespeare.lit/desktop'
61    type='result'>
62  <query xmlns='http://jabber.org/protocol/muc#owner'>
63    <x xmlns='jabber:x:data' type='form'>
64      <title>Configuration for "coven" Room</title>
65      <instructions>
66        Complete this form to modify the
67        configuration of your room.
68      </instructions>
69      <field
70          type='hidden'
71          var='FORM_TYPE'>
72        <value>http://jabber.org/protocol/muc#roomconfig</value>
73      </field>
74      <field
75          label='Natural-Language Room Name'
76          type='text-single'
77          var='muc#roomconfig_roomname'>
78        <value>A Dark Cave</value>
79      </field>
80      <field
81          label='Short Description of Room'
82          type='text-single'
83          var='muc#roomconfig_roomdesc'>
84        <value>The place for all good witches!</value>
85      </field>
86      <!-- There is more in the example, but we removed in favor of brevity -->
87    </x>
88  </query>
89</iq>`
90
91	mockIn := xml.NewDecoder(strings.NewReader(expectedResponse))
92	mockOut := &mockConnIOReaderWriter{}
93
94	conn := conn{
95		in:  mockIn,
96		out: mockOut,
97
98		jid: "crone1@shakespeare.lit/desktop",
99
100		inflights: make(map[data.Cookie]inflight),
101		rand:      bytes.NewBuffer([]byte{1, 0, 0, 0, 0, 0, 0, 0}),
102	}
103
104	go func() {
105		for len(conn.inflights) == 0 {
106		}
107		conn.Next()
108	}()
109
110	result, err := conn.GetChatContext().RequestRoomConfigForm(&data.Room{ID: "coven", Service: "chat.shakespeare.lit"})
111
112	c.Assert(err, IsNil)
113
114	c.Assert(result, DeepEquals, &data.Form{
115		XMLName:      xml.Name{Space: "jabber:x:data", Local: "x"},
116		Type:         "form",
117		Title:        "Configuration for \"coven\" Room",
118		Instructions: "\n        Complete this form to modify the\n        configuration of your room.\n      ",
119		Fields: []data.FormFieldX{
120			data.FormFieldX{
121				XMLName: xml.Name{
122					Space: "jabber:x:data", Local: "field",
123				},
124				Var:    "FORM_TYPE",
125				Type:   "hidden",
126				Values: []string{"http://jabber.org/protocol/muc#roomconfig"},
127			},
128			data.FormFieldX{
129				XMLName: xml.Name{Space: "jabber:x:data", Local: "field"},
130				Var:     "muc#roomconfig_roomname",
131				Type:    "text-single",
132				Label:   "Natural-Language Room Name",
133				Values:  []string{"A Dark Cave"},
134			},
135			data.FormFieldX{
136				XMLName: xml.Name{Space: "jabber:x:data", Local: "field"},
137				Var:     "muc#roomconfig_roomdesc",
138				Type:    "text-single",
139				Label:   "Short Description of Room",
140				Values:  []string{"The place for all good witches!"},
141			},
142		},
143	})
144
145	c.Assert(string(mockOut.write), Equals,
146		`<iq xmlns='jabber:client' `+
147			`to='coven@chat.shakespeare.lit' `+
148			`from='crone1@shakespeare.lit/desktop' `+
149			`type='get' `+
150			`id='1'`+
151			`>`+
152			`<query xmlns="http://jabber.org/protocol/muc#owner"></query>`+
153			`</iq>`)
154}
155
156func (s *MUCSuite) Test_CanUpdateRoomConfig(c *C) {
157	//See Example 159. Owner Submits Configuration Form
158	expectedRequest := `<iq xmlns='jabber:client' ` +
159		`to='coven@chat.shakespeare.lit' ` +
160		`from='crone1@shakespeare.lit/desktop' ` +
161		`type='set' ` +
162		`id='1'` +
163		`>` +
164		`<query xmlns="http://jabber.org/protocol/muc#owner">` +
165		`<x xmlns="jabber:x:data" type="submit">` +
166		`<field var="FORM_TYPE">` +
167		`<value>http://jabber.org/protocol/muc#roomconfig</value>` +
168		`</field>` +
169		`<field var="muc#roomconfig_roomname">` +
170		`<value>A Dark Cave</value>` +
171		`</field>` +
172		`<field var="muc#roomconfig_roomdesc">` +
173		`<value>The place for all good witches!</value>` +
174		`</field>` +
175		`<field var="muc#roomconfig_roomadmins">` +
176		`<value>wiccarocks@shakespeare.lit</value>` +
177		`<value>hecate@shakespeare.lit</value>` +
178		`</field>` +
179		`</x>` +
180		`</query>` +
181		`</iq>`
182
183	mockOut := &mockConnIOReaderWriter{}
184
185	conn := conn{
186		out: mockOut,
187
188		jid: "crone1@shakespeare.lit/desktop",
189
190		inflights: make(map[data.Cookie]inflight),
191		rand:      bytes.NewBuffer([]byte{1, 0, 0, 0, 0, 0, 0, 0}),
192	}
193
194	err := conn.GetChatContext().UpdateRoomConfig(
195		&data.Room{ID: "coven", Service: "chat.shakespeare.lit"},
196		&data.Form{
197			Type: "submit",
198			Fields: []data.FormFieldX{
199				data.FormFieldX{
200					Var:    "FORM_TYPE",
201					Values: []string{"http://jabber.org/protocol/muc#roomconfig"},
202				},
203				data.FormFieldX{
204					Var:    "muc#roomconfig_roomname",
205					Values: []string{"A Dark Cave"},
206				},
207				data.FormFieldX{
208					Var:    "muc#roomconfig_roomdesc",
209					Values: []string{"The place for all good witches!"},
210				},
211				data.FormFieldX{
212					Var: "muc#roomconfig_roomadmins",
213					Values: []string{
214						"wiccarocks@shakespeare.lit",
215						"hecate@shakespeare.lit",
216					},
217				},
218			},
219		})
220
221	c.Assert(err, IsNil)
222	c.Assert(string(mockOut.write), Equals, expectedRequest)
223}
224
225func (s *MUCSuite) Test_parseRoomInfo(c *C) {
226
227	//Sample data.DiscoveryInfoQuery: We need to parse Forms[], RoomType, Rooms[],
228	query := &data.DiscoveryInfoQuery{
229		XMLName: xml.Name{Space: "http://jabber.org/protocol/disco#info", Local: "query"},
230		Node:    "",
231		Identities: []data.DiscoveryIdentity{
232			data.DiscoveryIdentity{
233				XMLName:  xml.Name{Space: "http://jabber.org/protocol/disco#info", Local: "identity"},
234				Lang:     "",
235				Category: "conference",
236				Type:     "text",
237				Name:     "coyim-test",
238			},
239		},
240		Features: []data.DiscoveryFeature{
241			data.DiscoveryFeature{XMLName: xml.Name{Space: "http://jabber.org/protocol/disco#info", Local: "feature"},
242				Var: "http://jabber.org/protocol/muc",
243			},
244			data.DiscoveryFeature{XMLName: xml.Name{Space: "http://jabber.org/protocol/disco#info", Local: "feature"},
245				Var: "muc_unsecured",
246			},
247			data.DiscoveryFeature{XMLName: xml.Name{Space: "http://jabber.org/protocol/disco#info", Local: "feature"},
248				Var: "muc_unmoderated",
249			},
250			data.DiscoveryFeature{XMLName: xml.Name{Space: "http://jabber.org/protocol/disco#info", Local: "feature"},
251				Var: "muc_open",
252			},
253			data.DiscoveryFeature{XMLName: xml.Name{Space: "http://jabber.org/protocol/disco#info", Local: "feature"},
254				Var: "muc_temporary",
255			},
256			data.DiscoveryFeature{XMLName: xml.Name{Space: "http://jabber.org/protocol/disco#info", Local: "feature"},
257				Var: "muc_public",
258			},
259			data.DiscoveryFeature{XMLName: xml.Name{Space: "http://jabber.org/protocol/disco#info", Local: "feature"},
260				Var: "muc_semianonymous",
261			},
262		},
263		Forms: []data.Form{
264			data.Form{XMLName: xml.Name{Space: "jabber:x:data", Local: "x"},
265				Type:         "result",
266				Title:        "",
267				Instructions: "",
268				Fields: []data.FormFieldX{
269					data.FormFieldX{XMLName: xml.Name{Space: "jabber:x:data", Local: "field"},
270						Desc: "", Var: "FORM_TYPE", Type: "hidden", Label: "",
271						Required: (*data.FormFieldRequiredX)(nil),
272						Values:   []string{"http://jabber.org/protocol/muc#roominfo"},
273						Options:  []data.FormFieldOptionX(nil),
274						Media:    []data.FormFieldMediaX(nil),
275					},
276					data.FormFieldX{XMLName: xml.Name{Space: "jabber:x:data", Local: "field"},
277						Desc: "", Var: "muc#roominfo_description", Type: "text-single", Label: "Description",
278						Required: (*data.FormFieldRequiredX)(nil),
279						Values:   []string{"CoyIM testing room"},
280						Options:  []data.FormFieldOptionX(nil),
281						Media:    []data.FormFieldMediaX(nil),
282					},
283					data.FormFieldX{XMLName: xml.Name{Space: "jabber:x:data", Local: "field"},
284						Desc: "", Var: "muc#roominfo_occupants", Type: "text-single", Label: "Number of occupants",
285						Required: (*data.FormFieldRequiredX)(nil),
286						Values:   []string{"1"},
287						Options:  []data.FormFieldOptionX(nil),
288						Media:    []data.FormFieldMediaX(nil),
289					},
290				},
291			},
292		},
293		ResultSet: (*data.ResultSet)(nil),
294	}
295
296	roomInfo := parseRoomInformation(query)
297
298	c.Assert(roomInfo.Description, Equals, "CoyIM testing room")
299	c.Assert(roomInfo.Occupants, Equals, 1)
300	c.Assert(roomInfo.PasswordProtected, Equals, false)
301	c.Assert(roomInfo.Moderated, Equals, false)
302	c.Assert(roomInfo.Open, Equals, true)
303	c.Assert(roomInfo.Persistent, Equals, false)
304	c.Assert(roomInfo.Public, Equals, true)
305	c.Assert(roomInfo.SemiAnonymous, Equals, true)
306}
307