Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
converse.js
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
converse.js
Commits
6553b5ba
Commit
6553b5ba
authored
May 11, 2013
by
JC Brand
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of github.com:jcbrand/converse.js
parents
d6ecef48
ef38fd09
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
576 additions
and
177 deletions
+576
-177
CHANGES.rst
CHANGES.rst
+14
-9
Libraries/strophe.muc.js
Libraries/strophe.muc.js
+1
-0
converse.css
converse.css
+45
-3
converse.js
converse.js
+201
-49
mock.js
mock.js
+43
-0
spec/ChatRoomSpec.js
spec/ChatRoomSpec.js
+239
-0
spec/MainSpec.js
spec/MainSpec.js
+14
-102
tests_main.js
tests_main.js
+19
-14
No files found.
CHANGES.rst
View file @
6553b5ba
...
@@ -4,22 +4,27 @@ Changelog
...
@@ -4,22 +4,27 @@ Changelog
0.3 (unreleased)
0.3 (unreleased)
----------------
----------------
- Add vCard support [jcbrand]
- Add vCard support
- Remember custom status messages upon reload. [jcbrand]
[jcbrand]
- Remove jquery-ui dependency. [jcbrand]
- Remember custom status messages upon reload.
[jcbrand]
- Remove jquery-ui dependency.
[jcbrand]
- Use backbone.localStorage to store the contacts roster, open chatboxes and
- Use backbone.localStorage to store the contacts roster, open chatboxes and
chat messages. [jcbrand]
chat messages.
- Fixed user status handling, which wasn't 100% according to the
[jcbrand]
spec. [jcbrand]
- Fixed user status handling, which wasn't 100% according to the spec.
- Separate messages according to day in chats. [jcbrand]
[jcbrand]
- Separate messages according to day in chats.
[jcbrand]
- Add support for specifying the BOSH bind URL as configuration setting.
- Add support for specifying the BOSH bind URL as configuration setting.
[jcbrand]
[jcbrand]
- Improve the message counter to only increment when the window is not focused
- Improve the message counter to only increment when the window is not focused
[witekdev]
[witekdev]
- Make fetching of list of chatrooms on a server a configuration option.
- Make fetching of list of chatrooms on a server a configuration option.
[jcbrand]
[jcbrand]
- Use service discovery to show
whether a chatroom is password protected as
- Use service discovery to show
all available features on a room.
well as its number of occupents.
[jcbrand]
[jcbrand]
0.2 (2013-03-28)
0.2 (2013-03-28)
...
...
Libraries/strophe.muc.js
View file @
6553b5ba
...
@@ -57,6 +57,7 @@
...
@@ -57,6 +57,7 @@
* (String) nick - Optional nickname to use in the chat room.
* (String) nick - Optional nickname to use in the chat room.
* (Function) msg_handler_cb - The function call to handle messages from the specified chat room.
* (Function) msg_handler_cb - The function call to handle messages from the specified chat room.
* (Function) pres_handler_cb - The function call back to handle presence in the chat room.
* (Function) pres_handler_cb - The function call back to handle presence in the chat room.
* (Function) roster_cb - The function call back to handle roster changes in the chat room.
* (String) password - The optional password to use. (password protected rooms only)
* (String) password - The optional password to use. (password protected rooms only)
*/
*/
var
msg
,
room_nick
,
_this
=
this
;
var
msg
,
room_nick
,
_this
=
this
;
...
...
converse.css
View file @
6553b5ba
...
@@ -92,7 +92,11 @@ img.spinner {
...
@@ -92,7 +92,11 @@ img.spinner {
display
:
block
;
display
:
block
;
font-size
:
12px
;
font-size
:
12px
;
padding
:
0.5em
0
0
0.5em
;
padding
:
0.5em
0
0
0.5em
;
cursor
:
default
;
}
ul
.participant-list
li
.moderator
{
color
:
#FE0007
;
}
}
.chatroom
form
.sendXMPPMessage
{
.chatroom
form
.sendXMPPMessage
{
...
@@ -223,6 +227,7 @@ div.chat-title {
...
@@ -223,6 +227,7 @@ div.chat-title {
text-overflow
:
ellipsis
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
white-space
:
nowrap
;
text-shadow
:
rgba
(
0
,
0
,
0
,
0.51
)
0
-1px
0
;
text-shadow
:
rgba
(
0
,
0
,
0
,
0.51
)
0
-1px
0
;
height
:
1em
;
}
}
.chat-head-chatbox
,
.chat-head-chatbox
,
...
@@ -441,7 +446,7 @@ form.search-xmpp-contact input {
...
@@ -441,7 +446,7 @@ form.search-xmpp-contact input {
text-overflow
:
ellipsis
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
white-space
:
nowrap
;
display
:
inline-block
;
display
:
inline-block
;
width
:
1
6
0px
;
width
:
1
7
0px
;
}
}
#available-chatrooms
dt
,
#available-chatrooms
dt
,
...
@@ -468,6 +473,41 @@ dd.available-chatroom,
...
@@ -468,6 +473,41 @@ dd.available-chatroom,
text-shadow
:
0
1px
0
rgba
(
250
,
250
,
250
,
1
);
text-shadow
:
0
1px
0
rgba
(
250
,
250
,
250
,
1
);
}
}
.room-info
{
font-size
:
11px
;
font-style
:
normal
;
font-weight
:
normal
;
}
p
.room-info
{
margin
:
0
;
padding
:
0
;
display
:
block
;
white-space
:
normal
;
}
a
.room-info
{
background
:
url('images/information.png')
no-repeat
right
top
;
width
:
22px
;
float
:
right
;
display
:
none
;
}
a
.open-room
{
display
:
inline-block
;
white-space
:
nowrap
;
text-overflow
:
ellipsis
;
overflow-x
:
hidden
;
}
dd
.available-chatroom
:hover
a
.room-info
{
display
:
inline-block
;
}
dd
.available-chatroom
:hover
a
.open-room
{
width
:
75%
;
}
#converse-roster
dd
a
.remove-xmpp-contact
{
#converse-roster
dd
a
.remove-xmpp-contact
{
background
:
url('images/delete_icon.png')
no-repeat
right
top
;
background
:
url('images/delete_icon.png')
no-repeat
right
top
;
padding
:
0
0
1em
0
;
padding
:
0
0
1em
0
;
...
@@ -477,11 +517,11 @@ dd.available-chatroom,
...
@@ -477,11 +517,11 @@ dd.available-chatroom,
display
:
none
;
display
:
none
;
}
}
#converse-roster
dd
:hover
*[
class
*=
"remove-xmpp-contact"
]
{
#converse-roster
dd
:hover
a
.remove-xmpp-contact
{
display
:
inline-block
;
display
:
inline-block
;
}
}
#converse-roster
dd
:hover
*[
class
*=
"open-chat"
]
{
#converse-roster
dd
:hover
a
.open-chat
{
width
:
75%
;
width
:
75%
;
}
}
...
@@ -541,10 +581,12 @@ form#converse-login {
...
@@ -541,10 +581,12 @@ form#converse-login {
form
#converse-login
input
{
form
#converse-login
input
{
display
:
block
;
display
:
block
;
width
:
90%
;
}
}
form
#converse-login
.login-submit
{
form
#converse-login
.login-submit
{
margin-top
:
1em
;
margin-top
:
1em
;
width
:
auto
;
}
}
form
.set-xmpp-status
,
form
.set-xmpp-status
,
...
...
converse.js
View file @
6553b5ba
...
@@ -684,14 +684,56 @@
...
@@ -684,14 +684,56 @@
events
:
{
events
:
{
'
submit form.add-chatroom
'
:
'
createChatRoom
'
,
'
submit form.add-chatroom
'
:
'
createChatRoom
'
,
'
click input#show-rooms
'
:
'
showRooms
'
,
'
click input#show-rooms
'
:
'
showRooms
'
,
'
click a.open-room
'
:
'
createChatRoom
'
'
click a.open-room
'
:
'
createChatRoom
'
,
'
click a.room-info
'
:
'
showRoomInfo
'
},
},
room_template
:
_
.
template
(
room_template
:
_
.
template
(
'
<dd class="available-chatroom">
'
+
'
<dd class="available-chatroom">
'
+
'
<a class="open-room {{classes}}" data-room-jid="{{jid}}"
'
+
'
<a class="open-room" data-room-jid="{{jid}}" title="Click to open this room" href="#">{{name}}</a>
'
+
'
title="{{desc}}"
'
+
'
<a class="room-info" data-room-jid="{{jid}}" title="Show more information on this room" href="#"> </a>
'
+
'
href="#">
'
+
'
</dd>
'
),
'
{{name}}</a> {{occ}}</dd>
'
),
room_description_template
:
_
.
template
(
'
<div class="room-info">
'
+
'
<p class="room-info"><strong>Description:</strong> {{desc}}</p>
'
+
'
<p class="room-info"><strong>Occupants:</strong> {{occ}}</p>
'
+
'
<p class="room-info"><strong>Features:</strong> <ul>
'
+
'
{[ if (passwordprotected) { ]}
'
+
'
<li class="room-info locked">Requires authentication</li>
'
+
'
{[ } ]}
'
+
'
{[ if (hidden) { ]}
'
+
'
<li class="room-info">Hidden</li>
'
+
'
{[ } ]}
'
+
'
{[ if (membersonly) { ]}
'
+
'
<li class="room-info">Requires an invitation</li>
'
+
'
{[ } ]}
'
+
'
{[ if (moderated) { ]}
'
+
'
<li class="room-info">Moderated</li>
'
+
'
{[ } ]}
'
+
'
{[ if (nonanonymous) { ]}
'
+
'
<li class="room-info">Non-anonymous</li>
'
+
'
{[ } ]}
'
+
'
{[ if (open) { ]}
'
+
'
<li class="room-info">Open room</li>
'
+
'
{[ } ]}
'
+
'
{[ if (persistent) { ]}
'
+
'
<li class="room-info">Permanent room</li>
'
+
'
{[ } ]}
'
+
'
{[ if (publicroom) { ]}
'
+
'
<li class="room-info">Public</li>
'
+
'
{[ } ]}
'
+
'
{[ if (semianonymous) { ]}
'
+
'
<li class="room-info">Semi-anonymous</li>
'
+
'
{[ } ]}
'
+
'
{[ if (temporary) { ]}
'
+
'
<li class="room-info">Temporary room</li>
'
+
'
{[ } ]}
'
+
'
{[ if (unmoderated) { ]}
'
+
'
<li class="room-info">Unmoderated</li>
'
+
'
{[ } ]}
'
+
'
</p>
'
+
'
</div>
'
),
tab_template
:
_
.
template
(
'
<li><a class="s" href="#chatrooms">Rooms</a></li>
'
),
tab_template
:
_
.
template
(
'
<li><a class="s" href="#chatrooms">Rooms</a></li>
'
),
...
@@ -720,37 +762,23 @@
...
@@ -720,37 +762,23 @@
converse
.
connection
.
muc
.
listRooms
(
converse
.
connection
.
muc
.
listRooms
(
this
.
muc_domain
,
this
.
muc_domain
,
$
.
proxy
(
function
(
iq
)
{
// Success
$
.
proxy
(
function
(
iq
)
{
// Success
var
name
,
jid
,
i
,
that
=
this
,
$available_chatrooms
=
this
.
$el
.
find
(
'
#available-chatrooms
'
);
var
name
,
jid
,
i
,
fragment
,
this
.
rdict
=
{};
that
=
this
,
$available_chatrooms
=
this
.
$el
.
find
(
'
#available-chatrooms
'
);
this
.
rooms
=
$
(
iq
).
find
(
'
query
'
).
find
(
'
item
'
);
this
.
rooms
=
$
(
iq
).
find
(
'
query
'
).
find
(
'
item
'
);
this
.
rooms
.
each
(
function
(
i
)
{
that
.
rdict
[
$
(
this
).
attr
(
'
jid
'
)]
=
this
;
});
this
.
fragment
=
document
.
createDocumentFragment
();
if
(
this
.
rooms
.
length
)
{
if
(
this
.
rooms
.
length
)
{
$available_chatrooms
.
html
(
'
<dt>Rooms on
'
+
this
.
muc_domain
+
'
</dt>
'
);
$available_chatrooms
.
html
(
'
<dt>Rooms on
'
+
this
.
muc_domain
+
'
</dt>
'
);
_
.
each
(
this
.
rooms
,
$
.
proxy
(
function
(
room
,
idx
)
{
fragment
=
document
.
createDocumentFragment
();
converse
.
connection
.
disco
.
info
(
for
(
i
=
0
;
i
<
this
.
rooms
.
length
;
i
++
)
{
$
(
room
).
attr
(
'
jid
'
),
name
=
Strophe
.
unescapeNode
(
$
(
this
.
rooms
[
i
]).
attr
(
'
name
'
)
||
$
(
this
.
rooms
[
i
]).
attr
(
'
jid
'
));
null
,
jid
=
$
(
this
.
rooms
[
i
]).
attr
(
'
jid
'
);
$
.
proxy
(
function
(
stanza
)
{
fragment
.
appendChild
(
$
(
this
.
room_template
({
var
name
=
$
(
stanza
).
find
(
'
identity
'
).
attr
(
'
name
'
);
'
name
'
:
name
,
var
desc
=
$
(
stanza
).
find
(
'
field[var="muc#roominfo_description"] value
'
).
text
();
'
jid
'
:
jid
var
occ
=
$
(
stanza
).
find
(
'
field[var="muc#roominfo_occupants"] value
'
).
text
();
}))[
0
]);
var
locked
=
$
(
stanza
).
find
(
'
feature[var="muc_passwordprotected"]
'
).
length
;
}
var
jid
=
$
(
stanza
).
attr
(
'
from
'
);
$available_chatrooms
.
append
(
fragment
);
var
classes
=
locked
&&
'
locked
'
||
''
;
$
(
'
input#show-rooms
'
).
show
().
siblings
(
'
img.spinner
'
).
remove
();
delete
this
.
rdict
[
jid
];
this
.
$el
.
find
(
'
#available-chatrooms
'
).
append
(
this
.
room_template
({
'
name
'
:
name
,
'
desc
'
:
desc
,
'
occ
'
:
occ
,
'
jid
'
:
jid
,
'
classes
'
:
classes
}));
if
(
_
.
keys
(
this
.
rdict
).
length
===
0
)
{
$
(
'
input#show-rooms
'
).
show
().
siblings
(
'
img.spinner
'
).
remove
();
}
},
this
));
},
this
));
}
else
{
}
else
{
$available_chatrooms
.
html
(
'
<dt>No rooms on
'
+
this
.
muc_domain
+
'
</dt>
'
);
$available_chatrooms
.
html
(
'
<dt>No rooms on
'
+
this
.
muc_domain
+
'
</dt>
'
);
$
(
'
input#show-rooms
'
).
show
().
siblings
(
'
img.spinner
'
).
remove
();
$
(
'
input#show-rooms
'
).
show
().
siblings
(
'
img.spinner
'
).
remove
();
...
@@ -780,6 +808,53 @@
...
@@ -780,6 +808,53 @@
this
.
updateRoomsList
();
this
.
updateRoomsList
();
},
},
showRoomInfo
:
function
(
ev
)
{
var
target
=
ev
.
target
,
$dd
=
$
(
target
).
parent
(
'
dd
'
),
$div
=
$dd
.
find
(
'
div.room-info
'
);
if
(
$div
.
length
)
{
$div
.
remove
();
}
else
{
$dd
.
append
(
'
<img class="spinner" src="images/spinner.gif"/>
'
);
converse
.
connection
.
disco
.
info
(
$
(
target
).
attr
(
'
data-room-jid
'
),
null
,
$
.
proxy
(
function
(
stanza
)
{
var
$stanza
=
$
(
stanza
);
// All MUC features shown here: http://xmpp.org/registrar/disco-features.html
var
desc
=
$stanza
.
find
(
'
field[var="muc#roominfo_description"] value
'
).
text
();
var
occ
=
$stanza
.
find
(
'
field[var="muc#roominfo_occupants"] value
'
).
text
();
var
hidden
=
$stanza
.
find
(
'
feature[var="muc_hidden"]
'
).
length
;
var
membersonly
=
$stanza
.
find
(
'
feature[var="muc_membersonly"]
'
).
length
;
var
moderated
=
$stanza
.
find
(
'
feature[var="muc_moderated"]
'
).
length
;
var
nonanonymous
=
$stanza
.
find
(
'
feature[var="muc_nonanonymous"]
'
).
length
;
var
open
=
$stanza
.
find
(
'
feature[var="muc_open"]
'
).
length
;
var
passwordprotected
=
$stanza
.
find
(
'
feature[var="muc_passwordprotected"]
'
).
length
;
var
persistent
=
$stanza
.
find
(
'
feature[var="muc_persistent"]
'
).
length
;
var
publicroom
=
$stanza
.
find
(
'
feature[var="muc_public"]
'
).
length
;
var
semianonymous
=
$stanza
.
find
(
'
feature[var="muc_semianonymous"]
'
).
length
;
var
temporary
=
$stanza
.
find
(
'
feature[var="muc_temporary"]
'
).
length
;
var
unmoderated
=
$stanza
.
find
(
'
feature[var="muc_unmoderated"]
'
).
length
;
$dd
.
find
(
'
img.spinner
'
).
replaceWith
(
this
.
room_description_template
({
'
desc
'
:
desc
,
'
occ
'
:
occ
,
'
hidden
'
:
hidden
,
'
membersonly
'
:
membersonly
,
'
moderated
'
:
moderated
,
'
nonanonymous
'
:
nonanonymous
,
'
open
'
:
open
,
'
passwordprotected
'
:
passwordprotected
,
'
persistent
'
:
persistent
,
'
publicroom
'
:
publicroom
,
'
semianonymous
'
:
semianonymous
,
'
temporary
'
:
temporary
,
'
unmoderated
'
:
unmoderated
}));
},
this
));
}
},
createChatRoom
:
function
(
ev
)
{
createChatRoom
:
function
(
ev
)
{
ev
.
preventDefault
();
ev
.
preventDefault
();
var
name
,
server
,
jid
,
$name
,
$server
,
errors
;
var
name
,
server
,
jid
,
$name
,
$server
,
errors
;
...
@@ -986,7 +1061,8 @@
...
@@ -986,7 +1061,8 @@
this
.
model
.
get
(
'
nick
'
),
this
.
model
.
get
(
'
nick
'
),
$
.
proxy
(
this
.
onChatRoomMessage
,
this
),
$
.
proxy
(
this
.
onChatRoomMessage
,
this
),
$
.
proxy
(
this
.
onChatRoomPresence
,
this
),
$
.
proxy
(
this
.
onChatRoomPresence
,
this
),
$
.
proxy
(
this
.
onChatRoomRoster
,
this
));
$
.
proxy
(
this
.
onChatRoomRoster
,
this
),
null
);
this
.
model
.
messages
.
on
(
'
add
'
,
this
.
showMessage
,
this
);
this
.
model
.
messages
.
on
(
'
add
'
,
this
.
showMessage
,
this
);
this
.
model
.
on
(
'
destroy
'
,
function
(
model
,
response
,
options
)
{
this
.
model
.
on
(
'
destroy
'
,
function
(
model
,
response
,
options
)
{
...
@@ -1004,22 +1080,84 @@
...
@@ -1004,22 +1080,84 @@
onLeave
:
function
()
{},
onLeave
:
function
()
{},
showRoomConfigOptions
:
function
(
stanza
)
{
// FIXME: Show a proper configuration form
var
$chat_content
=
this
.
$el
.
find
(
'
.chat-content
'
),
$stanza
=
$
(
stanza
),
$fields
=
$stanza
.
find
(
'
field
'
),
title
=
$stanza
.
find
(
'
title
'
).
text
(),
instructions
=
$stanza
.
find
(
'
instructions
'
).
text
(),
i
;
$chat_content
.
append
(
title
);
$chat_content
.
append
(
instructions
);
for
(
i
=
0
;
i
<
$fields
.
length
;
i
++
)
{
$field
=
$
(
$fields
[
i
]);
$chat_content
.
append
(
'
<label>
'
+
$field
.
attr
(
'
label
'
)
+
'
</label>
'
);
// $chat_content.append('<input type="text" name=">'+$field.attr('label')+'</label>');
}
},
onChatRoomPresence
:
function
(
presence
,
room
)
{
onChatRoomPresence
:
function
(
presence
,
room
)
{
var
nick
=
room
.
nick
,
var
nick
=
room
.
nick
,
$presence
=
$
(
presence
),
$presence
=
$
(
presence
),
from
=
$presence
.
attr
(
'
from
'
);
from
=
$presence
.
attr
(
'
from
'
)
,
item
;
if
(
$presence
.
attr
(
'
type
'
)
!==
'
error
'
)
{
if
(
$presence
.
attr
(
'
type
'
)
!==
'
error
'
)
{
if
(
$presence
.
find
(
"
status[code='201']
"
).
length
)
{
// This is a new chatroom. We create an instant
// chatroom, and let the user manually set any
// configuration setting. (2nd part is TODO)
converse
.
connection
.
muc
.
createInstantRoom
(
room
.
name
);
/* TODO: Find a place for this code (it configures a
* newly created chatroom).
* -------------------------------------------------
$item = $presence.find('item');
if ($item.length) {
if ($item.attr('affiliation') == 'owner') {
if (false) {
} else {
converse.connection.muc.configure(
room.name,
$.proxy(this.showRoomConfigOptions, this)
);
}
}
}
*/
}
// check for status 110 to see if it's our own presence
// check for status 110 to see if it's our own presence
if
(
$presence
.
find
(
"
status[code='110']
"
).
length
)
{
if
(
$presence
.
find
(
"
status[code='110']
"
).
length
)
{
// check if server changed our nick
if
(
$presence
.
find
(
"
status[code='210']
"
).
length
)
{
if
(
$presence
.
find
(
"
status[code='210']
"
).
length
)
{
// check if server changed our nick
this
.
model
.
set
({
'
nick
'
:
Strophe
.
getResourceFromJid
(
from
)});
this
.
model
.
set
({
'
nick
'
:
Strophe
.
getResourceFromJid
(
from
)});
}
}
}
}
}
else
{
}
else
{
var
error
=
$presence
.
find
(
'
error
'
);
var
$error
=
$presence
.
find
(
'
error
'
),
if
(
$
(
error
).
attr
(
'
type
'
)
==
'
auth
'
)
{
$chat_content
=
this
.
$el
.
find
(
'
.chat-content
'
);
this
.
$el
.
find
(
'
.chat-content
'
).
append
(
'
Sorry, this chatroom is restricted
'
);
if
(
$error
.
attr
(
'
type
'
)
==
'
auth
'
)
{
if
(
$error
.
find
(
'
not-authorized
'
).
length
)
{
$chat_content
.
append
(
'
This chatroom requires a password
'
);
}
else
if
(
$error
.
find
(
'
registration-required
'
).
length
)
{
$chat_content
.
append
(
'
You are not on the member list of this room
'
);
}
else
if
(
$error
.
find
(
'
forbidden
'
).
length
)
{
$chat_content
.
append
(
'
You have been banned from this room
'
);
}
}
else
if
(
$error
.
attr
(
'
type
'
)
==
'
modify
'
)
{
if
(
$error
.
find
(
'
jid-malformed
'
).
length
)
{
$chat_content
.
append
(
'
No nickname was specified
'
);
}
}
else
if
(
$error
.
attr
(
'
type
'
)
==
'
cancel
'
)
{
if
(
$error
.
find
(
'
not-allowed
'
).
length
)
{
$chat_content
.
append
(
'
You are not allowed to create new rooms
'
);
}
else
if
(
$error
.
find
(
'
not-acceptable
'
).
length
)
{
$chat_content
.
append
(
"
Your nickname doesn't conform to the room's policies
"
);
}
else
if
(
$error
.
find
(
'
conflict
'
).
length
)
{
$chat_content
.
append
(
"
Your nickname is already taken
"
);
}
else
if
(
$error
.
find
(
'
item-not-found
'
).
length
)
{
$chat_content
.
append
(
"
This room does not (yet) exist
"
);
}
else
if
(
$error
.
find
(
'
service-unavailable
'
).
length
)
{
$chat_content
.
append
(
"
This room has reached it's maximum number of occupants
"
);
}
}
}
}
}
return
true
;
return
true
;
...
@@ -1108,16 +1246,32 @@
...
@@ -1108,16 +1246,32 @@
return
true
;
return
true
;
},
},
occupant_template
:
_
.
template
(
'
<li class="{{role}}"
'
+
'
{[ if (role === "moderator") { ]}
'
+
'
title="This user is a moderator"
'
+
'
{[ } ]}
'
+
'
{[ if (role === "participant") { ]}
'
+
'
title="This user can send messages in this room"
'
+
'
{[ } ]}
'
+
'
{[ if (role === "visitor") { ]}
'
+
'
title="This user can NOT send messages in this room"
'
+
'
{[ } ]}
'
+
'
>{{nick}}</li>
'
),
onChatRoomRoster
:
function
(
roster
,
room
)
{
onChatRoomRoster
:
function
(
roster
,
room
)
{
// underscore size is needed because roster is an object
var
controlboxview
=
converse
.
chatboxesview
.
views
.
controlbox
,
var
controlboxview
=
converse
.
chatboxesview
.
views
.
controlbox
,
roster_size
=
_
.
size
(
roster
),
roster_size
=
_
.
size
(
roster
),
$participant_list
=
this
.
$el
.
find
(
'
.participant-list
'
),
$participant_list
=
this
.
$el
.
find
(
'
.participant-list
'
),
participants
=
[],
participants
=
[],
keys
=
_
.
keys
(
roster
),
i
;
i
;
this
.
$el
.
find
(
'
.participant-list
'
).
empty
();
this
.
$el
.
find
(
'
.participant-list
'
).
empty
();
for
(
i
=
0
;
i
<
roster_size
;
i
++
)
{
for
(
i
=
0
;
i
<
roster_size
;
i
++
)
{
participants
.
push
(
'
<li>
'
+
Strophe
.
unescapeNode
(
_
.
keys
(
roster
)[
i
])
+
'
</li>
'
);
participants
.
push
(
this
.
occupant_template
({
role
:
roster
[
keys
[
i
]].
role
,
nick
:
Strophe
.
unescapeNode
(
keys
[
i
])
}));
}
}
$participant_list
.
append
(
participants
.
join
(
""
));
$participant_list
.
append
(
participants
.
join
(
""
));
return
true
;
return
true
;
...
@@ -1344,7 +1498,6 @@
...
@@ -1344,7 +1498,6 @@
this
.
$el
.
addClass
(
'
current-xmpp-contact
'
);
this
.
$el
.
addClass
(
'
current-xmpp-contact
'
);
this
.
$el
.
html
(
this
.
template
(
item
.
toJSON
()));
this
.
$el
.
html
(
this
.
template
(
item
.
toJSON
()));
}
}
return
this
;
return
this
;
},
},
...
@@ -1802,7 +1955,6 @@
...
@@ -1802,7 +1955,6 @@
converse
.
connection
.
send
(
$pres
().
c
(
'
show
'
).
t
(
this
.
get
(
'
status
'
)).
up
().
c
(
'
status
'
).
t
(
status_message
));
converse
.
connection
.
send
(
$pres
().
c
(
'
show
'
).
t
(
this
.
get
(
'
status
'
)).
up
().
c
(
'
status
'
).
t
(
status_message
));
this
.
save
({
'
status_message
'
:
status_message
});
this
.
save
({
'
status_message
'
:
status_message
});
}
}
});
});
converse
.
XMPPStatusView
=
Backbone
.
View
.
extend
({
converse
.
XMPPStatusView
=
Backbone
.
View
.
extend
({
...
@@ -1834,7 +1986,6 @@
...
@@ -1834,7 +1986,6 @@
'
<a class="change-xmpp-status-message" href="#" Title="Click here to write a custom status message"></a>
'
+
'
<a class="change-xmpp-status-message" href="#" Title="Click here to write a custom status message"></a>
'
+
'
</div>
'
),
'
</div>
'
),
renderStatusChangeForm
:
function
(
ev
)
{
renderStatusChangeForm
:
function
(
ev
)
{
ev
.
preventDefault
();
ev
.
preventDefault
();
var
status_message
=
this
.
model
.
get
(
'
status
'
)
||
'
offline
'
;
var
status_message
=
this
.
model
.
get
(
'
status
'
)
||
'
offline
'
;
...
@@ -1937,6 +2088,7 @@
...
@@ -1937,6 +2088,7 @@
* This collection stores Feature Models, representing features
* This collection stores Feature Models, representing features
* provided by available XMPP entities (e.g. servers)
* provided by available XMPP entities (e.g. servers)
* See XEP-0030 for more details: http://xmpp.org/extensions/xep-0030.html
* See XEP-0030 for more details: http://xmpp.org/extensions/xep-0030.html
* All features are shown here: http://xmpp.org/registrar/disco-features.html
*/
*/
model
:
converse
.
Feature
,
model
:
converse
.
Feature
,
initialize
:
function
()
{
initialize
:
function
()
{
...
@@ -2114,8 +2266,8 @@
...
@@ -2114,8 +2266,8 @@
converse
.
onConnected
=
function
(
connection
)
{
converse
.
onConnected
=
function
(
connection
)
{
this
.
connection
=
connection
;
this
.
connection
=
connection
;
//
this.connection.xmlInput = function (body) { console.log(body); };
this
.
connection
.
xmlInput
=
function
(
body
)
{
console
.
log
(
body
);
};
//
this.connection.xmlOutput = function (body) { console.log(body); };
this
.
connection
.
xmlOutput
=
function
(
body
)
{
console
.
log
(
body
);
};
this
.
bare_jid
=
Strophe
.
getBareJidFromJid
(
this
.
connection
.
jid
);
this
.
bare_jid
=
Strophe
.
getBareJidFromJid
(
this
.
connection
.
jid
);
this
.
domain
=
Strophe
.
getDomainFromJid
(
this
.
connection
.
jid
);
this
.
domain
=
Strophe
.
getDomainFromJid
(
this
.
connection
.
jid
);
this
.
features
=
new
this
.
Features
();
this
.
features
=
new
this
.
Features
();
...
...
mock.js
0 → 100644
View file @
6553b5ba
(
function
(
root
,
factory
)
{
define
(
"
mock
"
,
[
'
converse
'
],
function
()
{
return
factory
();
});
}(
this
,
function
(
converse
)
{
var
mock_connection
=
{
'
muc
'
:
{
'
listRooms
'
:
function
()
{},
'
join
'
:
function
()
{},
'
leave
'
:
function
()
{}
},
'
jid
'
:
'
dummy@localhost
'
,
'
addHandler
'
:
function
(
handler
,
ns
,
name
,
type
,
id
,
from
,
options
)
{
return
function
()
{};
},
'
send
'
:
function
()
{},
'
roster
'
:
{
'
add
'
:
function
()
{},
'
authorize
'
:
function
()
{},
'
unauthorize
'
:
function
()
{},
'
get
'
:
function
()
{},
'
subscribe
'
:
function
()
{},
'
registerCallback
'
:
function
()
{}
},
'
vcard
'
:
{
'
get
'
:
function
(
callback
,
jid
)
{
var
name
=
jid
.
split
(
'
@
'
)[
0
].
replace
(
'
.
'
,
'
'
).
split
(
'
'
);
var
firstname
=
name
[
0
].
charAt
(
0
).
toUpperCase
()
+
name
[
0
].
slice
(
1
);
var
lastname
=
name
[
1
].
charAt
(
0
).
toUpperCase
()
+
name
[
1
].
slice
(
1
);
var
fullname
=
firstname
+
'
'
+
lastname
;
var
vcard
=
$iq
().
c
(
'
vCard
'
).
c
(
'
FN
'
).
t
(
fullname
);
callback
(
vcard
.
tree
());
}
},
'
disco
'
:
{
'
info
'
:
function
()
{},
'
items
'
:
function
()
{}
}
};
return
mock_connection
;
}));
spec/ChatRoomSpec.js
0 → 100644
View file @
6553b5ba
(
function
(
root
,
factory
)
{
define
([
"
converse
"
,
"
mock
"
],
function
(
converse
,
mock_connection
)
{
return
factory
(
converse
,
mock_connection
);
}
);
}
(
this
,
function
(
converse
,
mock_connection
)
{
return
describe
(
"
ChatRooms
"
,
$
.
proxy
(
function
()
{
var
chatroom_names
=
[
'
Dyon van de Wege
'
,
'
Thomas Kalb
'
,
'
Dirk Theissen
'
,
'
Felix Hofmann
'
,
'
Ka Lek
'
,
'
Anne Ebersbacher
'
];
describe
(
"
A Chat Room
"
,
$
.
proxy
(
function
()
{
beforeEach
(
$
.
proxy
(
function
()
{
if
(
!
$
(
"
div#controlbox
"
).
is
(
'
:visible
'
))
{
$
(
'
.toggle-online-users
'
).
click
();
}
var
roomspanel
=
this
.
chatboxesview
.
views
.
controlbox
.
roomspanel
;
var
$input
=
roomspanel
.
$el
.
find
(
'
input.new-chatroom-name
'
);
var
$server
=
roomspanel
.
$el
.
find
(
'
input.new-chatroom-server
'
);
$input
.
val
(
'
lounge
'
);
$server
.
val
(
'
muc.localhost
'
);
roomspanel
.
$el
.
find
(
'
form
'
).
submit
();
$
(
'
.toggle-online-users
'
).
click
();
},
converse
));
it
(
"
shows users currently present in the room
"
,
$
.
proxy
(
function
()
{
var
chatroomview
=
this
.
chatboxesview
.
views
[
'
lounge@muc.localhost
'
];
var
$participant_list
=
chatroomview
.
$el
.
find
(
'
.participant-list
'
);
var
roster
=
{},
room
=
{},
i
;
for
(
i
=
0
;
i
<
chatroom_names
.
length
-
1
;
i
++
)
{
roster
[
chatroom_names
[
i
]]
=
{};
chatroomview
.
onChatRoomRoster
(
roster
,
room
);
expect
(
$participant_list
.
find
(
'
li
'
).
length
).
toBe
(
1
+
i
);
expect
(
$
(
$participant_list
.
find
(
'
li
'
)[
i
]).
text
()).
toBe
(
chatroom_names
[
i
]);
}
roster
[
converse
.
bare_jid
]
=
{};
chatroomview
.
onChatRoomRoster
(
roster
,
room
);
},
converse
));
it
(
"
indicates moderators by means of a special css class and tooltip
"
,
$
.
proxy
(
function
()
{
var
chatroomview
=
this
.
chatboxesview
.
views
[
'
lounge@muc.localhost
'
];
var
$participant_list
=
chatroomview
.
$el
.
find
(
'
.participant-list
'
);
var
roster
=
{},
idx
=
chatroom_names
.
length
-
1
;
roster
[
chatroom_names
[
idx
]]
=
{};
roster
[
chatroom_names
[
idx
]].
role
=
'
moderator
'
;
chatroomview
.
onChatRoomRoster
(
roster
,
{});
occupant
=
$participant_list
.
find
(
'
li
'
);
expect
(
occupant
.
length
).
toBe
(
1
);
expect
(
$
(
occupant
).
text
()).
toBe
(
chatroom_names
[
idx
]);
expect
(
$
(
occupant
).
attr
(
'
class
'
)).
toBe
(
'
moderator
'
);
expect
(
$
(
occupant
).
attr
(
'
title
'
)).
toBe
(
'
This user is a moderator
'
);
},
converse
));
it
(
"
can be saved to, and retrieved from, localStorage
"
,
$
.
proxy
(
function
()
{
// We instantiate a new ChatBoxes collection, which by default
// will be empty.
var
newchatboxes
=
new
this
.
ChatBoxes
();
expect
(
newchatboxes
.
length
).
toEqual
(
0
);
// The chatboxes will then be fetched from localStorage inside the
// onConnected method
newchatboxes
.
onConnected
();
expect
(
newchatboxes
.
length
).
toEqual
(
1
);
// Check that the chatrooms retrieved from localStorage
// have the same attributes values as the original ones.
attrs
=
[
'
id
'
,
'
box_id
'
,
'
visible
'
];
for
(
i
=
0
;
i
<
attrs
.
length
;
i
++
)
{
new_attrs
=
_
.
pluck
(
_
.
pluck
(
newchatboxes
.
models
,
'
attributes
'
),
attrs
[
i
]);
old_attrs
=
_
.
pluck
(
_
.
pluck
(
this
.
chatboxes
.
models
,
'
attributes
'
),
attrs
[
i
]);
expect
(
_
.
isEqual
(
new_attrs
,
old_attrs
)).
toEqual
(
true
);
}
this
.
rosterview
.
render
();
},
converse
));
it
(
"
can be closed again by clicking a DOM element with class 'close-chatbox-button'
"
,
$
.
proxy
(
function
()
{
var
view
=
this
.
chatboxesview
.
views
[
'
lounge@muc.localhost
'
],
chatroom
=
view
.
model
,
$el
;
spyOn
(
view
,
'
closeChat
'
).
andCallThrough
();
spyOn
(
converse
.
connection
.
muc
,
'
leave
'
);
view
.
delegateEvents
();
// We need to rebind all events otherwise our spy won't be called
view
.
$el
.
find
(
'
.close-chatbox-button
'
).
click
();
expect
(
view
.
closeChat
).
toHaveBeenCalled
();
expect
(
converse
.
connection
.
muc
.
leave
).
toHaveBeenCalled
();
},
converse
));
},
converse
));
describe
(
"
When attempting to enter a chatroom
"
,
$
.
proxy
(
function
()
{
beforeEach
(
$
.
proxy
(
function
()
{
var
roomspanel
=
this
.
chatboxesview
.
views
.
controlbox
.
roomspanel
;
var
$input
=
roomspanel
.
$el
.
find
(
'
input.new-chatroom-name
'
);
var
$server
=
roomspanel
.
$el
.
find
(
'
input.new-chatroom-server
'
);
$input
.
val
(
'
problematic
'
);
$server
.
val
(
'
muc.localhost
'
);
roomspanel
.
$el
.
find
(
'
form
'
).
submit
();
},
converse
));
afterEach
(
$
.
proxy
(
function
()
{
var
view
=
this
.
chatboxesview
.
views
[
'
problematic@muc.localhost
'
];
view
.
closeChat
();
},
converse
));
it
(
"
will show an error message if the room requires a password
"
,
$
.
proxy
(
function
()
{
var
presence
=
$pres
().
attrs
({
from
:
'
coven@chat.shakespeare.lit/thirdwitch
'
,
id
:
'
n13mt3l
'
,
to
:
'
hag66@shakespeare.lit/pda
'
,
type
:
'
error
'
})
.
c
(
'
x
'
).
attrs
({
xmlns
:
'
http://jabber.org/protocol/muc
'
}).
up
()
.
c
(
'
error
'
).
attrs
({
by
:
'
coven@chat.shakespeare.lit
'
,
type
:
'
auth
'
})
.
c
(
'
not-authorized
'
).
attrs
({
xmlns
:
'
urn:ietf:params:xml:ns:xmpp-stanzas
'
}).
nodeTree
;
var
view
=
this
.
chatboxesview
.
views
[
'
problematic@muc.localhost
'
];
view
.
onChatRoomPresence
(
presence
,
{
'
nick
'
:
'
dummy
'
});
var
$chat_content
=
view
.
$el
.
find
(
'
.chat-content
'
);
expect
(
$chat_content
.
text
()).
toBe
(
'
This chatroom requires a password
'
);
},
converse
));
it
(
"
will show an error message if the room is members-only and the user not included
"
,
$
.
proxy
(
function
()
{
var
presence
=
$pres
().
attrs
({
from
:
'
coven@chat.shakespeare.lit/thirdwitch
'
,
id
:
'
n13mt3l
'
,
to
:
'
hag66@shakespeare.lit/pda
'
,
type
:
'
error
'
})
.
c
(
'
x
'
).
attrs
({
xmlns
:
'
http://jabber.org/protocol/muc
'
}).
up
()
.
c
(
'
error
'
).
attrs
({
by
:
'
coven@chat.shakespeare.lit
'
,
type
:
'
auth
'
})
.
c
(
'
registration-required
'
).
attrs
({
xmlns
:
'
urn:ietf:params:xml:ns:xmpp-stanzas
'
}).
nodeTree
;
var
view
=
this
.
chatboxesview
.
views
[
'
problematic@muc.localhost
'
];
view
.
onChatRoomPresence
(
presence
,
{
'
nick
'
:
'
dummy
'
});
var
$chat_content
=
view
.
$el
.
find
(
'
.chat-content
'
);
expect
(
$chat_content
.
text
()).
toBe
(
'
You are not on the member list of this room
'
);
},
converse
));
it
(
"
will show an error message if the user has been banned
"
,
$
.
proxy
(
function
()
{
var
presence
=
$pres
().
attrs
({
from
:
'
coven@chat.shakespeare.lit/thirdwitch
'
,
id
:
'
n13mt3l
'
,
to
:
'
hag66@shakespeare.lit/pda
'
,
type
:
'
error
'
})
.
c
(
'
x
'
).
attrs
({
xmlns
:
'
http://jabber.org/protocol/muc
'
}).
up
()
.
c
(
'
error
'
).
attrs
({
by
:
'
coven@chat.shakespeare.lit
'
,
type
:
'
auth
'
})
.
c
(
'
forbidden
'
).
attrs
({
xmlns
:
'
urn:ietf:params:xml:ns:xmpp-stanzas
'
}).
nodeTree
;
var
view
=
this
.
chatboxesview
.
views
[
'
problematic@muc.localhost
'
];
view
.
onChatRoomPresence
(
presence
,
{
'
nick
'
:
'
dummy
'
});
var
$chat_content
=
view
.
$el
.
find
(
'
.chat-content
'
);
expect
(
$chat_content
.
text
()).
toBe
(
'
You have been banned from this room
'
);
},
converse
));
it
(
"
will show an error message if no nickname was specified for the user
"
,
$
.
proxy
(
function
()
{
var
presence
=
$pres
().
attrs
({
from
:
'
coven@chat.shakespeare.lit/thirdwitch
'
,
id
:
'
n13mt3l
'
,
to
:
'
hag66@shakespeare.lit/pda
'
,
type
:
'
error
'
})
.
c
(
'
x
'
).
attrs
({
xmlns
:
'
http://jabber.org/protocol/muc
'
}).
up
()
.
c
(
'
error
'
).
attrs
({
by
:
'
coven@chat.shakespeare.lit
'
,
type
:
'
modify
'
})
.
c
(
'
jid-malformed
'
).
attrs
({
xmlns
:
'
urn:ietf:params:xml:ns:xmpp-stanzas
'
}).
nodeTree
;
var
view
=
this
.
chatboxesview
.
views
[
'
problematic@muc.localhost
'
];
view
.
onChatRoomPresence
(
presence
,
{
'
nick
'
:
'
dummy
'
});
var
$chat_content
=
view
.
$el
.
find
(
'
.chat-content
'
);
expect
(
$chat_content
.
text
()).
toBe
(
'
No nickname was specified
'
);
},
converse
));
it
(
"
will show an error message if the user is not allowed to have created the room
"
,
$
.
proxy
(
function
()
{
var
presence
=
$pres
().
attrs
({
from
:
'
coven@chat.shakespeare.lit/thirdwitch
'
,
id
:
'
n13mt3l
'
,
to
:
'
hag66@shakespeare.lit/pda
'
,
type
:
'
error
'
})
.
c
(
'
x
'
).
attrs
({
xmlns
:
'
http://jabber.org/protocol/muc
'
}).
up
()
.
c
(
'
error
'
).
attrs
({
by
:
'
coven@chat.shakespeare.lit
'
,
type
:
'
cancel
'
})
.
c
(
'
not-allowed
'
).
attrs
({
xmlns
:
'
urn:ietf:params:xml:ns:xmpp-stanzas
'
}).
nodeTree
;
var
view
=
this
.
chatboxesview
.
views
[
'
problematic@muc.localhost
'
];
view
.
onChatRoomPresence
(
presence
,
{
'
nick
'
:
'
dummy
'
});
var
$chat_content
=
view
.
$el
.
find
(
'
.chat-content
'
);
expect
(
$chat_content
.
text
()).
toBe
(
'
You are not allowed to create new rooms
'
);
},
converse
));
it
(
"
will show an error message if the user's nickname doesn't conform to room policy
"
,
$
.
proxy
(
function
()
{
var
presence
=
$pres
().
attrs
({
from
:
'
coven@chat.shakespeare.lit/thirdwitch
'
,
id
:
'
n13mt3l
'
,
to
:
'
hag66@shakespeare.lit/pda
'
,
type
:
'
error
'
})
.
c
(
'
x
'
).
attrs
({
xmlns
:
'
http://jabber.org/protocol/muc
'
}).
up
()
.
c
(
'
error
'
).
attrs
({
by
:
'
coven@chat.shakespeare.lit
'
,
type
:
'
cancel
'
})
.
c
(
'
not-acceptable
'
).
attrs
({
xmlns
:
'
urn:ietf:params:xml:ns:xmpp-stanzas
'
}).
nodeTree
;
var
view
=
this
.
chatboxesview
.
views
[
'
problematic@muc.localhost
'
];
view
.
onChatRoomPresence
(
presence
,
{
'
nick
'
:
'
dummy
'
});
var
$chat_content
=
view
.
$el
.
find
(
'
.chat-content
'
);
expect
(
$chat_content
.
text
()).
toBe
(
"
Your nickname doesn't conform to the room's policies
"
);
},
converse
));
it
(
"
will show an error message if the user's nickname is already taken
"
,
$
.
proxy
(
function
()
{
var
presence
=
$pres
().
attrs
({
from
:
'
coven@chat.shakespeare.lit/thirdwitch
'
,
id
:
'
n13mt3l
'
,
to
:
'
hag66@shakespeare.lit/pda
'
,
type
:
'
error
'
})
.
c
(
'
x
'
).
attrs
({
xmlns
:
'
http://jabber.org/protocol/muc
'
}).
up
()
.
c
(
'
error
'
).
attrs
({
by
:
'
coven@chat.shakespeare.lit
'
,
type
:
'
cancel
'
})
.
c
(
'
conflict
'
).
attrs
({
xmlns
:
'
urn:ietf:params:xml:ns:xmpp-stanzas
'
}).
nodeTree
;
var
view
=
this
.
chatboxesview
.
views
[
'
problematic@muc.localhost
'
];
view
.
onChatRoomPresence
(
presence
,
{
'
nick
'
:
'
dummy
'
});
var
$chat_content
=
view
.
$el
.
find
(
'
.chat-content
'
);
expect
(
$chat_content
.
text
()).
toBe
(
"
Your nickname is already taken
"
);
},
converse
));
it
(
"
will show an error message if the room doesn't yet exist
"
,
$
.
proxy
(
function
()
{
var
presence
=
$pres
().
attrs
({
from
:
'
coven@chat.shakespeare.lit/thirdwitch
'
,
id
:
'
n13mt3l
'
,
to
:
'
hag66@shakespeare.lit/pda
'
,
type
:
'
error
'
})
.
c
(
'
x
'
).
attrs
({
xmlns
:
'
http://jabber.org/protocol/muc
'
}).
up
()
.
c
(
'
error
'
).
attrs
({
by
:
'
coven@chat.shakespeare.lit
'
,
type
:
'
cancel
'
})
.
c
(
'
item-not-found
'
).
attrs
({
xmlns
:
'
urn:ietf:params:xml:ns:xmpp-stanzas
'
}).
nodeTree
;
var
view
=
this
.
chatboxesview
.
views
[
'
problematic@muc.localhost
'
];
view
.
onChatRoomPresence
(
presence
,
{
'
nick
'
:
'
dummy
'
});
var
$chat_content
=
view
.
$el
.
find
(
'
.chat-content
'
);
expect
(
$chat_content
.
text
()).
toBe
(
"
This room does not (yet) exist
"
);
},
converse
));
it
(
"
will show an error message if the room has reached it's maximum number of occupants
"
,
$
.
proxy
(
function
()
{
var
presence
=
$pres
().
attrs
({
from
:
'
coven@chat.shakespeare.lit/thirdwitch
'
,
id
:
'
n13mt3l
'
,
to
:
'
hag66@shakespeare.lit/pda
'
,
type
:
'
error
'
})
.
c
(
'
x
'
).
attrs
({
xmlns
:
'
http://jabber.org/protocol/muc
'
}).
up
()
.
c
(
'
error
'
).
attrs
({
by
:
'
coven@chat.shakespeare.lit
'
,
type
:
'
cancel
'
})
.
c
(
'
service-unavailable
'
).
attrs
({
xmlns
:
'
urn:ietf:params:xml:ns:xmpp-stanzas
'
}).
nodeTree
;
var
view
=
this
.
chatboxesview
.
views
[
'
problematic@muc.localhost
'
];
view
.
onChatRoomPresence
(
presence
,
{
'
nick
'
:
'
dummy
'
});
var
$chat_content
=
view
.
$el
.
find
(
'
.chat-content
'
);
expect
(
$chat_content
.
text
()).
toBe
(
"
This room has reached it's maximum number of occupants
"
);
},
converse
));
},
converse
));
},
converse
));
}));
spec/MainSpec.js
View file @
6553b5ba
(
function
(
root
,
factory
)
{
(
function
(
root
,
factory
)
{
define
([
define
([
"
converse
"
"
converse
"
,
],
function
(
converse
)
{
"
mock
"
return
factory
(
converse
);
],
function
(
converse
,
mock_connection
)
{
return
factory
(
converse
,
mock_connection
);
}
}
);
);
}
(
this
,
function
(
converse
)
{
}
(
this
,
function
(
converse
,
mock_connection
)
{
return
describe
(
"
Converse.js
"
,
$
.
proxy
(
function
()
{
return
describe
(
"
Converse.js
"
,
$
.
proxy
(
function
()
{
// Names from http://www.fakenamegenerator.com/
// Names from http://www.fakenamegenerator.com/
var
req_names
=
[
var
req_names
=
[
...
@@ -20,56 +20,7 @@
...
@@ -20,56 +20,7 @@
'
Robin Schook
'
,
'
Marcel Eberhardt
'
,
'
Simone Brauer
'
,
'
Asmaa Haakman
'
,
'
Felix Amsel
'
,
'
Robin Schook
'
,
'
Marcel Eberhardt
'
,
'
Simone Brauer
'
,
'
Asmaa Haakman
'
,
'
Felix Amsel
'
,
'
Lena Grunewald
'
,
'
Laura Grunewald
'
,
'
Mandy Seiler
'
,
'
Sven Bosch
'
,
'
Nuriye Cuypers
'
'
Lena Grunewald
'
,
'
Laura Grunewald
'
,
'
Mandy Seiler
'
,
'
Sven Bosch
'
,
'
Nuriye Cuypers
'
];
];
var
chatroom_names
=
[
'
Dyon van de Wege
'
,
'
Thomas Kalb
'
,
'
Dirk Theissen
'
,
'
Felix Hofmann
'
,
'
Ka Lek
'
,
'
Anne Ebersbacher
'
];
var
num_contacts
=
req_names
.
length
+
pend_names
.
length
+
cur_names
.
length
;
var
num_contacts
=
req_names
.
length
+
pend_names
.
length
+
cur_names
.
length
;
mock_connection
=
{
'
muc
'
:
{
'
listRooms
'
:
function
()
{},
'
join
'
:
function
()
{},
'
leave
'
:
function
()
{}
},
'
jid
'
:
'
dummy@localhost
'
,
'
addHandler
'
:
function
(
handler
,
ns
,
name
,
type
,
id
,
from
,
options
)
{
return
function
()
{};
},
'
send
'
:
function
()
{},
'
roster
'
:
{
'
add
'
:
function
()
{},
'
authorize
'
:
function
()
{},
'
unauthorize
'
:
function
()
{},
'
get
'
:
function
()
{},
'
subscribe
'
:
function
()
{},
'
registerCallback
'
:
function
()
{}
},
'
vcard
'
:
{
'
get
'
:
function
(
callback
,
jid
)
{
var
name
=
jid
.
split
(
'
@
'
)[
0
].
replace
(
'
.
'
,
'
'
).
split
(
'
'
);
var
firstname
=
name
[
0
].
charAt
(
0
).
toUpperCase
()
+
name
[
0
].
slice
(
1
);
var
lastname
=
name
[
1
].
charAt
(
0
).
toUpperCase
()
+
name
[
1
].
slice
(
1
);
var
fullname
=
firstname
+
'
'
+
lastname
;
var
vcard
=
$iq
().
c
(
'
vCard
'
).
c
(
'
FN
'
).
t
(
fullname
);
callback
(
vcard
.
tree
());
}
},
'
disco
'
:
{
'
info
'
:
function
()
{},
'
items
'
:
function
()
{}
}
};
// Clear localStorage
window
.
localStorage
.
clear
();
this
.
initialize
({
prebind
:
false
,
xhr_user_search
:
false
,
auto_subscribe
:
false
,
animate
:
false
});
this
.
onConnected
(
mock_connection
);
// Variable declarations for specs
var
open_controlbox
;
var
open_controlbox
;
describe
(
"
The Control Box
"
,
$
.
proxy
(
function
()
{
describe
(
"
The Control Box
"
,
$
.
proxy
(
function
()
{
...
@@ -82,8 +33,10 @@
...
@@ -82,8 +33,10 @@
// open yet.
// open yet.
expect
(
$
(
"
div#controlbox
"
).
is
(
'
:visible
'
)).
toBe
(
false
);
expect
(
$
(
"
div#controlbox
"
).
is
(
'
:visible
'
)).
toBe
(
false
);
spyOn
(
this
,
'
toggleControlBox
'
).
andCallThrough
();
spyOn
(
this
,
'
toggleControlBox
'
).
andCallThrough
();
spyOn
(
this
,
'
showControlBox
'
).
andCallThrough
();
$
(
'
.toggle-online-users
'
).
click
();
$
(
'
.toggle-online-users
'
).
click
();
expect
(
this
.
toggleControlBox
).
toHaveBeenCalled
();
expect
(
this
.
toggleControlBox
).
toHaveBeenCalled
();
expect
(
this
.
showControlBox
).
toHaveBeenCalled
();
expect
(
$
(
"
div#controlbox
"
).
is
(
'
:visible
'
)).
toBe
(
true
);
expect
(
$
(
"
div#controlbox
"
).
is
(
'
:visible
'
)).
toBe
(
true
);
},
converse
);
},
converse
);
it
(
"
can be opened by clicking a DOM element with class 'toggle-online-users'
"
,
open_controlbox
);
it
(
"
can be opened by clicking a DOM element with class 'toggle-online-users'
"
,
open_controlbox
);
...
@@ -577,8 +530,13 @@
...
@@ -577,8 +530,13 @@
it
(
"
is cleared when the window is focused
"
,
$
.
proxy
(
function
()
{
it
(
"
is cleared when the window is focused
"
,
$
.
proxy
(
function
()
{
spyOn
(
converse
,
'
clearMsgCounter
'
).
andCallThrough
();
spyOn
(
converse
,
'
clearMsgCounter
'
).
andCallThrough
();
$
(
window
).
trigger
(
'
focus
'
);
runs
(
function
()
{
expect
(
converse
.
clearMsgCounter
).
toHaveBeenCalled
();
$
(
window
).
trigger
(
'
focus
'
);
});
waits
(
50
);
runs
(
function
()
{
expect
(
converse
.
clearMsgCounter
).
toHaveBeenCalled
();
});
},
converse
));
},
converse
));
it
(
"
is not incremented when the message is received and the window is focused
"
,
$
.
proxy
(
function
()
{
it
(
"
is not incremented when the message is received and the window is focused
"
,
$
.
proxy
(
function
()
{
...
@@ -667,51 +625,5 @@
...
@@ -667,51 +625,5 @@
},
converse
));
},
converse
));
},
converse
));
},
converse
));
},
converse
));
},
converse
));
describe
(
"
A Chat Room
"
,
$
.
proxy
(
function
()
{
it
(
"
shows users currently present in the room
"
,
$
.
proxy
(
function
()
{
var
chatroomview
=
this
.
chatboxesview
.
views
[
'
lounge@muc.localhost
'
];
var
$participant_list
=
chatroomview
.
$el
.
find
(
'
.participant-list
'
);
var
roster
=
{},
room
=
{},
i
;
for
(
i
=
0
;
i
<
chatroom_names
.
length
;
i
++
)
{
roster
[
chatroom_names
[
i
]]
=
{};
chatroomview
.
onChatRoomRoster
(
roster
,
room
);
expect
(
$participant_list
.
find
(
'
li
'
).
length
).
toBe
(
1
+
i
);
expect
(
$
(
$participant_list
.
find
(
'
li
'
)[
i
]).
text
()).
toBe
(
chatroom_names
[
i
]);
}
roster
[
converse
.
bare_jid
]
=
{};
chatroomview
.
onChatRoomRoster
(
roster
,
room
);
},
converse
));
it
(
"
can be saved to, and retrieved from, localStorage
"
,
$
.
proxy
(
function
()
{
// We instantiate a new ChatBoxes collection, which by default
// will be empty.
var
newchatboxes
=
new
this
.
ChatBoxes
();
expect
(
newchatboxes
.
length
).
toEqual
(
0
);
// The chatboxes will then be fetched from localStorage inside the
// onConnected method
newchatboxes
.
onConnected
();
expect
(
newchatboxes
.
length
).
toEqual
(
2
);
// controlbox is also included
// Check that the chatrooms retrieved from localStorage
// have the same attributes values as the original ones.
attrs
=
[
'
id
'
,
'
box_id
'
,
'
visible
'
];
for
(
i
=
0
;
i
<
attrs
.
length
;
i
++
)
{
new_attrs
=
_
.
pluck
(
_
.
pluck
(
newchatboxes
.
models
,
'
attributes
'
),
attrs
[
i
]);
old_attrs
=
_
.
pluck
(
_
.
pluck
(
this
.
chatboxes
.
models
,
'
attributes
'
),
attrs
[
i
]);
expect
(
_
.
isEqual
(
new_attrs
,
old_attrs
)).
toEqual
(
true
);
}
this
.
rosterview
.
render
();
},
converse
));
it
(
"
can be closed again by clicking a DOM element with class 'close-chatbox-button'
"
,
$
.
proxy
(
function
()
{
var
view
=
this
.
chatboxesview
.
views
[
'
lounge@muc.localhost
'
],
chatroom
=
view
.
model
,
$el
;
spyOn
(
view
,
'
closeChat
'
).
andCallThrough
();
spyOn
(
converse
.
connection
.
muc
,
'
leave
'
);
view
.
delegateEvents
();
// We need to rebind all events otherwise our spy won't be called
view
.
$el
.
find
(
'
.close-chatbox-button
'
).
click
();
expect
(
view
.
closeChat
).
toHaveBeenCalled
();
expect
(
converse
.
connection
.
muc
.
leave
).
toHaveBeenCalled
();
},
converse
));
},
converse
));
},
converse
));
},
converse
));
}));
}));
tests_main.js
View file @
6553b5ba
require
([
"
jquery
"
,
"
spec/MainSpec
"
],
function
(
$
)
{
require
([
"
jquery
"
,
"
converse
"
,
"
mock
"
,
"
spec/MainSpec
"
,
"
spec/ChatRoomSpec
"
],
function
(
$
,
converse
,
mock_connection
)
{
// Set up converse.js
$
(
function
(
$
)
{
window
.
localStorage
.
clear
();
var
jasmineEnv
=
jasmine
.
getEnv
();
converse
.
initialize
({
jasmineEnv
.
updateInterval
=
500
;
prebind
:
false
,
xhr_user_search
:
false
,
var
htmlReporter
=
new
jasmine
.
HtmlReporter
();
auto_subscribe
:
false
,
animate
:
false
jasmineEnv
.
addReporter
(
htmlReporter
);
jasmineEnv
.
specFilter
=
function
(
spec
)
{
return
htmlReporter
.
specFilter
(
spec
);
};
jasmineEnv
.
execute
();
});
});
converse
.
onConnected
(
mock_connection
);
// Jasmine stuff
var
jasmineEnv
=
jasmine
.
getEnv
();
jasmineEnv
.
updateInterval
=
50
;
var
htmlReporter
=
new
jasmine
.
HtmlReporter
();
jasmineEnv
.
addReporter
(
htmlReporter
);
jasmineEnv
.
specFilter
=
function
(
spec
)
{
return
htmlReporter
.
specFilter
(
spec
);
};
jasmineEnv
.
execute
();
});
});
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment