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