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
ac643ae6
Commit
ac643ae6
authored
Dec 20, 2017
by
JC Brand
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor views to use Backbone.OrderedListView
parent
102f39ed
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
174 additions
and
214 deletions
+174
-214
spec/chatbox.js
spec/chatbox.js
+30
-28
spec/controlbox.js
spec/controlbox.js
+75
-70
spec/protocol.js
spec/protocol.js
+22
-12
src/config.js
src/config.js
+1
-0
src/converse-core.js
src/converse-core.js
+1
-2
src/converse-muc.js
src/converse-muc.js
+10
-54
src/converse-rosterview.js
src/converse-rosterview.js
+34
-48
tests/mock.js
tests/mock.js
+1
-0
No files found.
spec/chatbox.js
View file @
ac643ae6
...
...
@@ -73,21 +73,25 @@
spyOn
(
_converse
.
chatboxviews
,
'
trimChats
'
);
expect
(
$
(
"
#conversejs .chatbox
"
).
length
).
toBe
(
1
);
// Controlbox is open
var
online_contacts
=
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group .current-xmpp-contact a.open-chat
'
);
expect
(
online_contacts
.
length
).
toBe
(
15
);
for
(
i
=
0
;
i
<
online_contacts
.
length
;
i
++
)
{
$el
=
$
(
online_contacts
[
i
]);
jid
=
$el
.
text
().
trim
().
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
$el
.
click
();
chatboxview
=
_converse
.
chatboxviews
.
get
(
jid
);
expect
(
_converse
.
chatboxes
.
length
).
toEqual
(
i
+
2
);
expect
(
_converse
.
chatboxviews
.
trimChats
).
toHaveBeenCalled
();
// Check that new chat boxes are created to the left of the
// controlbox (but to the right of all existing chat boxes)
expect
(
$
(
"
#conversejs .chatbox
"
).
length
).
toBe
(
i
+
2
);
expect
(
$
(
"
#conversejs .chatbox
"
)[
1
].
id
).
toBe
(
chatboxview
.
model
.
get
(
'
box_id
'
));
}
done
();
test_utils
.
waitUntil
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group li
'
).
length
;
},
700
).
then
(
function
()
{
var
online_contacts
=
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group .current-xmpp-contact a.open-chat
'
);
expect
(
online_contacts
.
length
).
toBe
(
15
);
for
(
i
=
0
;
i
<
online_contacts
.
length
;
i
++
)
{
$el
=
$
(
online_contacts
[
i
]);
jid
=
$el
.
text
().
trim
().
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
$el
.
click
();
chatboxview
=
_converse
.
chatboxviews
.
get
(
jid
);
expect
(
_converse
.
chatboxes
.
length
).
toEqual
(
i
+
2
);
expect
(
_converse
.
chatboxviews
.
trimChats
).
toHaveBeenCalled
();
// Check that new chat boxes are created to the left of the
// controlbox (but to the right of all existing chat boxes)
expect
(
$
(
"
#conversejs .chatbox
"
).
length
).
toBe
(
i
+
2
);
expect
(
$
(
"
#conversejs .chatbox
"
)[
1
].
id
).
toBe
(
chatboxview
.
model
.
get
(
'
box_id
'
));
}
done
();
});
}));
it
(
"
can be trimmed to conserve space
"
,
...
...
@@ -109,10 +113,10 @@
spyOn
(
trimmed_chatboxes
,
'
removeChat
'
).
and
.
callThrough
();
expect
(
$
(
"
#conversejs .chatbox
"
).
length
).
toBe
(
1
);
// Controlbox is open
_converse
.
rosterview
.
update
();
// XXX: Hack to make sure $roster element is attaced.
_converse
.
rosterview
.
update
();
// XXX: Hack to make sure $roster element is attac
h
ed.
test_utils
.
waitUntil
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group
'
).
length
;
},
3
00
).
then
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group
li
'
).
length
;
},
7
00
).
then
(
function
()
{
// Test that they can be maximized again
var
online_contacts
=
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group .current-xmpp-contact a.open-chat
'
);
expect
(
online_contacts
.
length
).
toBe
(
15
);
...
...
@@ -836,10 +840,9 @@
}).
c
(
'
body
'
).
t
(
'
Message:
'
+
i
).
up
()
.
c
(
'
active
'
,
{
'
xmlns
'
:
'
http://jabber.org/protocol/chatstates
'
}).
tree
());
}
test_utils
.
waitUntil
(
function
()
{
return
chatboxview
.
$content
.
scrollTop
();
},
1000
)
.
then
(
function
()
{
return
test_utils
.
waitUntil
(
function
()
{
return
chatboxview
.
$content
.
scrollTop
();
},
1000
).
then
(
function
()
{
return
test_utils
.
waitUntil
(
function
()
{
return
!
chatboxview
.
model
.
get
(
'
auto_scrolled
'
);
},
500
);
...
...
@@ -872,7 +875,7 @@
chatboxview
.
$content
.
scrollTop
(
chatboxview
.
$content
[
0
].
scrollHeight
);
return
test_utils
.
waitUntil
(
function
()
{
return
!
chatboxview
.
$
(
'
.new-msgs-indicator
'
).
is
(
'
:visible
'
);
},
5
00
);
},
7
00
);
}).
then
(
done
);
}));
...
...
@@ -1541,7 +1544,7 @@
view
.
model
.
maximize
();
return
test_utils
.
waitUntil
(
function
()
{
return
view
.
model
.
get
(
'
chat_state
'
)
===
'
active
'
;
},
5
00
);
},
7
00
);
}).
then
(
function
()
{
expect
(
_converse
.
connection
.
send
).
toHaveBeenCalled
();
var
calls
=
_
.
filter
(
_converse
.
connection
.
send
.
calls
.
all
(),
function
(
call
)
{
...
...
@@ -1693,9 +1696,8 @@
test_utils
.
openControlBox
();
test_utils
.
openContactsPanel
(
_converse
);
test_utils
.
waitUntil
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group
'
).
length
;
},
300
)
.
then
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group li
'
).
length
;
},
700
).
then
(
function
()
{
_converse
.
TIMEOUTS
.
PAUSED
=
200
;
// Make the timeout shorter so that we can test
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
...
...
@@ -1715,7 +1717,7 @@
return
test_utils
.
waitUntil
(
function
()
{
return
view
.
model
.
get
(
'
chat_state
'
)
===
'
paused
'
;
},
500
);
}).
then
(
function
()
{
}).
then
(
function
()
{
expect
(
_converse
.
connection
.
send
).
toHaveBeenCalled
();
var
calls
=
_
.
filter
(
_converse
.
connection
.
send
.
calls
.
all
(),
function
(
call
)
{
return
call
.
args
[
0
]
instanceof
Strophe
.
Builder
;
...
...
spec/controlbox.js
View file @
ac643ae6
...
...
@@ -182,14 +182,14 @@
var
promise
=
test_utils
.
waitUntil
(
function
()
{
return
$roster
.
find
(
'
li:visible
'
).
length
===
15
;
},
5
00
).
then
(
function
(
contacts
)
{
},
6
00
).
then
(
function
(
contacts
)
{
expect
(
$roster
.
find
(
'
ul.roster-group-contacts:visible
'
).
length
).
toBe
(
5
);
$filter
.
val
(
"
candice
"
);
$filter
.
trigger
(
'
keydown
'
);
return
test_utils
.
waitUntil
(
function
()
{
return
$roster
.
find
(
'
li:visible
'
).
length
===
1
;
},
5
00
);
},
6
00
);
}).
then
(
function
(
contacts
)
{
// Only one roster contact is now visible
expect
(
$roster
.
find
(
'
li:visible
'
).
length
).
toBe
(
1
);
...
...
@@ -203,7 +203,7 @@
$filter
.
trigger
(
'
keydown
'
);
return
test_utils
.
waitUntil
(
function
()
{
return
$roster
.
find
(
'
li:visible
'
).
length
===
5
;
},
5
00
)
},
6
00
)
}).
then
(
function
(
contacts
)
{
// Five roster contact is now visible
expect
(
$roster
.
find
(
'
li:visible
'
).
length
).
toBe
(
5
);
...
...
@@ -220,7 +220,7 @@
$filter
.
trigger
(
'
keydown
'
);
return
test_utils
.
waitUntil
(
function
()
{
return
$roster
.
find
(
'
li:visible
'
).
length
===
0
;
},
5
00
)
},
6
00
)
}).
then
(
function
()
{
expect
(
$roster
.
find
(
'
ul.roster-group-contacts:visible a.group-toggle
'
).
length
).
toBe
(
0
);
$filter
=
_converse
.
rosterview
.
$
(
'
.roster-filter
'
);
...
...
@@ -228,7 +228,7 @@
$filter
.
trigger
(
'
keydown
'
);
return
test_utils
.
waitUntil
(
function
()
{
return
$roster
.
find
(
'
li:visible
'
).
length
===
15
;
},
5
00
)
},
6
00
)
}).
then
(
function
()
{
expect
(
$roster
.
find
(
'
ul.roster-group-contacts:visible
'
).
length
).
toBe
(
5
);
_converse
.
roster_groups
=
false
;
...
...
@@ -253,14 +253,14 @@
$type
.
val
(
'
groups
'
);
test_utils
.
waitUntil
(
function
()
{
return
$roster
.
find
(
'
li:visible
'
).
length
===
15
;
},
5
00
).
then
(
function
()
{
},
6
00
).
then
(
function
()
{
expect
(
$roster
.
find
(
'
div.roster-group:visible a.group-toggle
'
).
length
).
toBe
(
5
);
$filter
.
val
(
"
colleagues
"
);
$filter
.
trigger
(
'
keydown
'
);
return
test_utils
.
waitUntil
(
function
()
{
return
$roster
.
find
(
'
div.roster-group:not(.collapsed) a.group-toggle
'
).
length
===
1
;
},
5
00
);
},
6
00
);
}).
then
(
function
()
{
expect
(
_
.
trim
(
$roster
.
find
(
'
div.roster-group:not(.collapsed) a
'
).
eq
(
0
).
text
())).
toBe
(
'
colleagues
'
);
expect
(
$roster
.
find
(
'
div.roster-group:not(.collapsed) li:visible
'
).
length
).
toBe
(
3
);
...
...
@@ -281,7 +281,7 @@
$filter
.
trigger
(
'
keydown
'
);
return
test_utils
.
waitUntil
(
function
()
{
return
$roster
.
find
(
'
div.roster-group.collapsed a.group-toggle
'
).
length
===
0
;
},
5
00
);
},
6
00
);
}).
then
(
function
()
{
expect
(
$roster
.
find
(
'
div.roster-group:not(collapsed)
'
).
length
).
toBe
(
5
);
expect
(
$roster
.
find
(
'
div.roster-group:not(collapsed) li
'
).
length
).
toBe
(
15
);
...
...
@@ -418,8 +418,8 @@
});
}
test_utils
.
waitUntil
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
li:visible
'
).
length
;
},
5
00
).
then
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
li:visible
'
).
length
===
30
;
},
6
00
).
then
(
function
()
{
// Check that usernames appear alphabetically per group
_
.
each
(
groups
,
function
(
name
)
{
var
$contacts
=
_converse
.
rosterview
.
$
(
'
.roster-group[data-group="
'
+
name
+
'
"] li
'
);
...
...
@@ -528,7 +528,7 @@
_addContacts
(
_converse
);
test_utils
.
waitUntil
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
li
'
).
length
;
},
5
00
).
then
(
function
()
{
},
7
00
).
then
(
function
()
{
expect
(
_converse
.
rosterview
.
$el
.
is
(
'
:visible
'
)).
toEqual
(
true
);
expect
(
_converse
.
rosterview
.
update
).
toHaveBeenCalled
();
expect
(
_converse
.
rosterview
.
$el
.
find
(
'
li:visible
'
).
length
).
toBe
(
3
);
...
...
@@ -575,13 +575,12 @@
});
test_utils
.
waitUntil
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
"
.pending-contact-name:contains('
"
+
name
+
"
')
"
).
length
;
},
500
)
.
then
(
function
()
{
},
700
).
then
(
function
()
{
_converse
.
rosterview
.
$el
.
find
(
"
.pending-contact-name:contains('
"
+
name
+
"
')
"
)
.
parent
().
siblings
(
'
.remove-xmpp-contact
'
).
click
();
return
test_utils
.
waitUntil
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
"
.pending-contact-name:contains('
"
+
name
+
"
')
"
).
length
===
0
},
5
00
)
},
7
00
)
}).
then
(
function
()
{
expect
(
window
.
confirm
).
toHaveBeenCalled
();
expect
(
_converse
.
connection
.
sendIQ
).
toHaveBeenCalled
();
...
...
@@ -609,9 +608,9 @@
if
(
typeof
callback
===
"
function
"
)
{
return
callback
();
}
});
test_utils
.
waitUntil
(
function
()
{
return
_converse
.
rosterview
.
get
(
'
Pending contacts
'
).
$el
.
is
(
'
:visible
'
)
;
},
500
)
.
then
(
function
()
{
var
$pending_contacts
=
_converse
.
rosterview
.
get
(
'
Pending contacts
'
).
$el
;
return
$pending_contacts
.
is
(
'
:visible
'
)
&&
$pending_contacts
.
find
(
'
li:visible
'
).
length
;
},
700
)
.
then
(
function
()
{
_converse
.
rosterview
.
$el
.
find
(
"
.pending-contact-name:contains('
"
+
name
+
"
')
"
)
.
parent
().
siblings
(
'
.remove-xmpp-contact
'
).
click
();
expect
(
window
.
confirm
).
toHaveBeenCalled
();
...
...
@@ -644,6 +643,7 @@
function
(
done
,
_converse
)
{
var
i
,
t
;
test_utils
.
openControlBox
();
spyOn
(
_converse
,
'
emit
'
);
spyOn
(
_converse
.
rosterview
,
'
update
'
).
and
.
callThrough
();
for
(
i
=
0
;
i
<
mock
.
pend_names
.
length
;
i
++
)
{
...
...
@@ -655,18 +655,25 @@
});
expect
(
_converse
.
rosterview
.
update
).
toHaveBeenCalled
();
}
// Check that they are sorted alphabetically
t
=
_
.
reduce
(
_converse
.
rosterview
.
get
(
'
Pending contacts
'
).
$el
.
find
(
'
.pending-xmpp-contact span
'
),
function
(
result
,
value
)
{
return
result
+
_
.
trim
(
value
.
textContent
);
},
''
);
expect
(
t
).
toEqual
(
mock
.
pend_names
.
slice
(
0
,
i
+
1
).
sort
().
join
(
''
));
done
();
return
test_utils
.
waitUntil
(
function
()
{
return
_converse
.
rosterview
.
get
(
'
Pending contacts
'
).
$el
.
find
(
'
li:visible
'
).
length
;
},
700
).
then
(
function
()
{
// Check that they are sorted alphabetically
t
=
_
.
reduce
(
_converse
.
rosterview
.
get
(
'
Pending contacts
'
).
$el
.
find
(
'
.pending-xmpp-contact span
'
),
function
(
result
,
value
)
{
return
result
+
_
.
trim
(
value
.
textContent
);
},
''
);
expect
(
t
).
toEqual
(
mock
.
pend_names
.
slice
(
0
,
i
+
1
).
sort
().
join
(
''
));
done
();
});
}));
});
describe
(
"
Existing Contacts
"
,
function
()
{
var
_addContacts
=
function
(
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
).
openControlBox
().
openContactsPanel
(
_converse
);
test_utils
.
createContacts
(
_converse
,
'
current
'
)
.
openControlBox
()
.
openContactsPanel
(
_converse
);
};
it
(
"
can be collapsed under their own header
"
,
...
...
@@ -717,6 +724,7 @@
null
,
[
'
rosterGroupsFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
openControlBox
();
spyOn
(
_converse
.
rosterview
,
'
update
'
).
and
.
callThrough
();
for
(
var
i
=
0
;
i
<
mock
.
cur_names
.
length
;
i
++
)
{
_converse
.
roster
.
create
({
...
...
@@ -729,11 +737,13 @@
}
test_utils
.
waitUntil
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
li
'
).
length
;
}).
then
(
function
()
{
}
,
600
).
then
(
function
()
{
// Check that they are sorted alphabetically
var
t
=
_
.
reduce
(
_converse
.
rosterview
.
$
(
'
.roster-group
'
).
find
(
'
.current-xmpp-contact.offline a.open-chat
'
),
function
(
result
,
value
)
{
return
result
+
_
.
trim
(
value
.
textContent
);
},
''
);
var
t
=
_
.
reduce
(
_converse
.
rosterview
.
$
(
'
.roster-group
'
)
.
find
(
'
.current-xmpp-contact.offline a.open-chat
'
),
function
(
result
,
value
)
{
return
result
+
_
.
trim
(
value
.
textContent
);
},
''
);
expect
(
t
).
toEqual
(
mock
.
cur_names
.
slice
(
0
,
i
+
1
).
sort
().
join
(
''
));
done
();
});
...
...
@@ -781,9 +791,8 @@
fullname
:
name
});
test_utils
.
waitUntil
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group
'
).
length
;
},
500
)
.
then
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group li
'
).
length
;
},
700
).
then
(
function
()
{
spyOn
(
window
,
'
confirm
'
).
and
.
returnValue
(
true
);
spyOn
(
contact
,
'
removeFromRoster
'
);
spyOn
(
_converse
.
connection
,
'
sendIQ
'
).
and
.
callFake
(
function
(
iq
,
callback
)
{
...
...
@@ -808,9 +817,8 @@
_addContacts
(
_converse
);
test_utils
.
waitUntil
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group
'
).
length
;
},
500
)
.
then
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group li
'
).
length
;
},
700
).
then
(
function
()
{
var
jid
,
t
;
spyOn
(
_converse
,
'
emit
'
);
spyOn
(
_converse
.
rosterview
,
'
update
'
).
and
.
callThrough
();
...
...
@@ -836,9 +844,8 @@
_addContacts
(
_converse
);
test_utils
.
waitUntil
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group
'
).
length
;
},
500
)
.
then
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group li
'
).
length
;
},
700
).
then
(
function
()
{
var
jid
,
t
;
spyOn
(
_converse
,
'
emit
'
);
spyOn
(
_converse
.
rosterview
,
'
update
'
).
and
.
callThrough
();
...
...
@@ -865,9 +872,8 @@
_addContacts
(
_converse
);
test_utils
.
waitUntil
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group
'
).
length
;
},
500
)
.
then
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group li
'
).
length
;
},
700
).
then
(
function
()
{
var
jid
,
t
;
spyOn
(
_converse
,
'
emit
'
);
spyOn
(
_converse
.
rosterview
,
'
update
'
).
and
.
callThrough
();
...
...
@@ -894,9 +900,8 @@
_addContacts
(
_converse
);
test_utils
.
waitUntil
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group
'
).
length
;
},
500
)
.
then
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group li
'
).
length
;
},
700
).
then
(
function
()
{
var
jid
,
t
;
spyOn
(
_converse
,
'
emit
'
);
spyOn
(
_converse
.
rosterview
,
'
update
'
).
and
.
callThrough
();
...
...
@@ -923,7 +928,7 @@
_addContacts
(
_converse
);
test_utils
.
waitUntil
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group
'
).
length
;
return
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group
li
'
).
length
;
},
500
)
.
then
(
function
()
{
var
jid
,
t
;
...
...
@@ -952,8 +957,8 @@
_addContacts
(
_converse
);
test_utils
.
waitUntil
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group
'
).
length
;
},
5
00
).
then
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group li
'
).
length
;
},
7
00
).
then
(
function
()
{
var
i
,
jid
;
for
(
i
=
0
;
i
<
3
;
i
++
)
{
jid
=
mock
.
cur_names
[
i
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
...
...
@@ -1071,13 +1076,17 @@
fullname
:
mock
.
req_names
[
i
]
});
}
expect
(
_converse
.
rosterview
.
update
).
toHaveBeenCalled
();
// Check that they are sorted alphabetically
children
=
_converse
.
rosterview
.
get
(
'
Contact requests
'
).
$el
.
find
(
'
.requesting-xmpp-contact span
'
);
names
=
[];
children
.
each
(
addName
);
expect
(
names
.
join
(
''
)).
toEqual
(
mock
.
req_names
.
slice
(
0
,
mock
.
req_names
.
length
+
1
).
sort
().
join
(
''
));
done
();
test_utils
.
waitUntil
(
function
()
{
return
_converse
.
rosterview
.
get
(
'
Contact requests
'
).
$el
.
find
(
'
li
'
).
length
;
},
700
).
then
(
function
()
{
expect
(
_converse
.
rosterview
.
update
).
toHaveBeenCalled
();
// Check that they are sorted alphabetically
children
=
_converse
.
rosterview
.
get
(
'
Contact requests
'
).
$el
.
find
(
'
.requesting-xmpp-contact span
'
);
names
=
[];
children
.
each
(
addName
);
expect
(
names
.
join
(
''
)).
toEqual
(
mock
.
req_names
.
slice
(
0
,
mock
.
req_names
.
length
+
1
).
sort
().
join
(
''
));
done
();
});
}));
it
(
"
do not have a header if there aren't any
"
,
...
...
@@ -1096,9 +1105,8 @@
fullname
:
name
});
test_utils
.
waitUntil
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group
'
).
length
;
},
500
)
.
then
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group li
'
).
length
;
},
700
).
then
(
function
()
{
expect
(
_converse
.
rosterview
.
get
(
'
Contact requests
'
).
$el
.
is
(
'
:visible
'
)).
toEqual
(
true
);
_converse
.
rosterview
.
$el
.
find
(
"
.req-contact-name:contains('
"
+
name
+
"
')
"
)
.
parent
().
siblings
(
'
.request-actions
'
)
...
...
@@ -1116,8 +1124,8 @@
test_utils
.
createContacts
(
_converse
,
'
requesting
'
).
openControlBox
();
test_utils
.
waitUntil
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group
'
).
length
;
},
5
00
).
then
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group
li
'
).
length
;
},
7
00
).
then
(
function
()
{
checkHeaderToggling
.
apply
(
_converse
,
[
_converse
.
rosterview
.
get
(
'
Contact requests
'
).
$el
]
...
...
@@ -1132,9 +1140,8 @@
test_utils
.
createContacts
(
_converse
,
'
requesting
'
).
openControlBox
();
test_utils
.
waitUntil
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group
'
).
length
;
},
500
)
.
then
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group li
'
).
length
;
},
700
).
then
(
function
()
{
// TODO: Testing can be more thorough here, the user is
// actually not accepted/authorized because of
// mock_connection.
...
...
@@ -1161,9 +1168,8 @@
test_utils
.
createContacts
(
_converse
,
'
requesting
'
).
openControlBox
();
test_utils
.
waitUntil
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group
'
).
length
;
},
500
)
.
then
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group li
'
).
length
;
},
700
).
then
(
function
()
{
_converse
.
rosterview
.
update
();
// XXX: Hack to make sure $roster element is attaced.
var
name
=
mock
.
req_names
.
sort
()[
1
];
var
jid
=
name
.
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
...
...
@@ -1193,7 +1199,7 @@
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
test_utils
.
waitUntil
(
function
()
{
return
$
(
'
a:contains("Contact requests")
'
).
length
;
}).
then
(
function
()
{
}
,
700
).
then
(
function
()
{
expect
(
_converse
.
roster
.
pluck
(
'
jid
'
).
length
).
toBe
(
1
);
expect
(
_
.
includes
(
_converse
.
roster
.
pluck
(
'
jid
'
),
'
data@enterprise
'
)).
toBeTruthy
();
// Taken from the spec
...
...
@@ -1265,9 +1271,8 @@
test_utils
.
createContacts
(
_converse
,
'
all
'
).
openControlBox
();
test_utils
.
openContactsPanel
(
_converse
);
test_utils
.
waitUntil
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group
'
).
length
;
},
500
)
.
then
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group li
'
).
length
;
},
700
).
then
(
function
()
{
var
jid
,
name
,
i
;
for
(
i
=
0
;
i
<
mock
.
cur_names
.
length
;
i
++
)
{
name
=
mock
.
cur_names
[
i
];
...
...
@@ -1324,8 +1329,8 @@
fullname
:
mock
.
pend_names
[
0
]
});
test_utils
.
waitUntil
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group
'
).
length
;
},
5
00
).
then
(
function
()
{
return
_converse
.
rosterview
.
$el
.
find
(
'
.roster-group
li
'
).
length
;
},
7
00
).
then
(
function
()
{
// Checking that only one entry is created because both JID is same (Case sensitive check)
expect
(
_converse
.
rosterview
.
$el
.
find
(
'
li:visible
'
).
length
).
toBe
(
1
);
expect
(
_converse
.
rosterview
.
update
).
toHaveBeenCalled
();
...
...
spec/protocol.js
View file @
ac643ae6
...
...
@@ -228,11 +228,11 @@
expect
(
_converse
.
roster
.
updateContact
).
toHaveBeenCalled
();
// Check that the user is now properly shown as a pending
// contact in the roster.
var
$header
=
$
(
'
a:contains("Pending contacts")
'
);
return
test_utils
.
waitUntil
(
function
()
{
return
$
(
'
a:contains("Pending contacts")
'
).
length
&&
$header
.
is
(
"
:visible
"
);
},
300
);
var
$header
=
$
(
'
a:contains("Pending contacts")
'
);
var
$contacts
=
$header
.
parent
().
find
(
'
li
'
);
return
$contacts
.
length
;
},
600
);
}).
then
(
function
()
{
var
$header
=
$
(
'
a:contains("Pending contacts")
'
);
var
$contacts
=
$header
.
parent
().
find
(
'
li
'
);
...
...
@@ -297,10 +297,16 @@
// The contact should now be visible as an existing
// contact (but still offline).
$header
=
$
(
'
a:contains("My contacts")
'
);
return
test_utils
.
waitUntil
(
function
()
{
var
$header
=
$
(
'
a:contains("My contacts")
'
);
var
$contacts
=
$header
.
parent
().
find
(
'
li
'
);
return
$contacts
.
length
;
},
600
);
}).
then
(
function
()
{
var
$header
=
$
(
'
a:contains("My contacts")
'
);
expect
(
$header
.
length
).
toBe
(
1
);
expect
(
$header
.
is
(
"
:visible
"
)).
toBeTruthy
();
$contacts
=
$header
.
parent
().
find
(
'
li
'
);
var
$contacts
=
$header
.
parent
().
find
(
'
li
'
);
expect
(
$contacts
.
length
).
toBe
(
1
);
// Check that it has the right classes and text
expect
(
$contacts
.
hasClass
(
'
to
'
)).
toBeTruthy
();
...
...
@@ -482,10 +488,12 @@
sent_IQ
=
iq
;
IQ_id
=
sendIQ
.
bind
(
this
)(
iq
,
callback
,
errback
);
});
return
test_utils
.
waitUntil
(
function
()
{
var
$header
=
$
(
'
a:contains("My contacts")
'
);
var
$contacts
=
$header
.
parent
().
find
(
'
li
'
);
return
$contacts
.
length
;
},
600
).
then
(
function
()
{
test_utils
.
waitUntil
(
function
()
{
return
$
(
'
a:contains("My contacts")
'
).
length
;
}).
then
(
function
()
{
var
$header
=
$
(
'
a:contains("My contacts")
'
);
// remove the first user
$
(
$header
.
parent
().
find
(
'
li .remove-xmpp-contact
'
).
get
(
0
)).
click
();
...
...
@@ -547,9 +555,11 @@
'
xmlns
'
:
Strophe
.
NS
.
NICK
,
}).
t
(
'
Clint Contact
'
);
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
test_utils
.
waitUntil
(
function
()
{
return
$
(
'
a:contains("Contact requests")
'
).
length
;
}).
then
(
function
()
{
return
test_utils
.
waitUntil
(
function
()
{
var
$header
=
$
(
'
a:contains("Contact requests")
'
);
var
$contacts
=
$header
.
parent
().
find
(
'
li
'
);
return
$contacts
.
length
;
},
600
).
then
(
function
()
{
expect
(
_converse
.
emit
).
toHaveBeenCalledWith
(
'
contactRequest
'
,
jasmine
.
any
(
Object
));
var
$header
=
$
(
'
a:contains("Contact requests")
'
);
expect
(
$header
.
length
).
toBe
(
1
);
...
...
src/config.js
View file @
ac643ae6
...
...
@@ -22,6 +22,7 @@ require.config({
"
backbone.browserStorage
"
:
"
node_modules/backbone.browserStorage/backbone.browserStorage
"
,
"
backbone.noconflict
"
:
"
src/backbone.noconflict
"
,
"
backbone.overview
"
:
"
node_modules/backbone.overview/backbone.overview
"
,
"
backbone.orderedlistview
"
:
"
node_modules/backbone.overview/backbone.orderedlistview
"
,
"
backbone.vdomview
"
:
"
node_modules/backbone.vdomview/backbone.vdomview
"
,
"
emojione
"
:
"
node_modules/emojione/lib/js/emojione
"
,
"
es6-promise
"
:
"
node_modules/es6-promise/dist/es6-promise.auto
"
,
...
...
src/converse-core.js
View file @
ac643ae6
...
...
@@ -16,8 +16,7 @@
"
strophe
"
,
"
pluggable
"
,
"
backbone.noconflict
"
,
"
backbone.browserStorage
"
,
"
backbone.overview
"
,
"
backbone.browserStorage
"
],
factory
);
}(
this
,
function
(
sizzle
,
Promise
,
_
,
polyfill
,
i18n
,
utils
,
moment
,
Strophe
,
pluggable
,
Backbone
)
{
...
...
src/converse-muc.js
View file @
ac643ae6
...
...
@@ -37,6 +37,8 @@
"
awesomplete
"
,
"
converse-chatview
"
,
"
converse-disco
"
,
"
backbone.overview
"
,
"
backbone.orderedlistview
"
,
"
backbone.vdomview
"
],
factory
);
}(
this
,
function
(
...
...
@@ -2213,16 +2215,17 @@
},
});
_converse
.
ChatRoomOccupantsView
=
Backbone
.
O
verv
iew
.
extend
({
_converse
.
ChatRoomOccupantsView
=
Backbone
.
O
rderedListV
iew
.
extend
({
tagName
:
'
div
'
,
className
:
'
occupants
'
,
listItems
:
'
model
'
,
sortEvent
:
'
change:role
'
,
listSelector
:
'
.occupant-list
'
,
ItemView
:
_converse
.
ChatRoomOccupantView
,
initialize
()
{
this
.
model
.
on
(
"
add
"
,
this
.
onOccupantAdded
,
this
);
this
.
model
.
on
(
"
change:role
"
,
(
occupant
)
=>
{
this
.
model
.
sort
();
this
.
positionOccupant
(
occupant
);
});
Backbone
.
OrderedListView
.
prototype
.
initialize
.
apply
(
this
,
arguments
);
this
.
chatroomview
=
this
.
model
.
chatroomview
;
this
.
chatroomview
.
model
.
on
(
'
change:open
'
,
this
.
renderInviteWidget
,
this
);
...
...
@@ -2247,9 +2250,7 @@
this
.
model
.
fetch
({
'
add
'
:
true
,
'
silent
'
:
true
,
'
success
'
:
()
=>
{
this
.
model
.
each
(
this
.
onOccupantAdded
.
bind
(
this
));
}
'
success
'
:
this
.
sortAndPositionAllItems
.
bind
(
this
)
});
},
...
...
@@ -2353,57 +2354,12 @@
this
.
debouncedRenderRoomFeatures
();
},
setOccupantsHeight
()
{
const
el
=
this
.
el
.
querySelector
(
'
.chatroom-features
'
);
this
.
el
.
querySelector
(
'
.occupant-list
'
).
style
.
cssText
=
`height: calc(100% -
${
el
.
offsetHeight
}
px - 5em);`
;
},
positionOccupant
(
occupant
)
{
/* Positions an occupant correctly in the list of
* occupants.
*
* IMPORTANT: there's an important implicit assumption being
* made here. And that is that initially this method gets called
* for each occupant in the right positional order.
*
* In other words, it gets called for the 0th, then the
* 1st, then the 2nd, 3rd and so on.
*
* That's why we call it in the "success" handler after
* fetching the occupants, so that we know we have ALL of
* them and that they're sorted.
*/
const
view
=
this
.
get
(
occupant
.
get
(
'
id
'
));
view
.
render
();
const
list
=
this
.
el
.
querySelector
(
'
.occupant-list
'
);
const
index
=
this
.
model
.
indexOf
(
view
.
model
);
if
(
index
===
0
)
{
list
.
insertAdjacentElement
(
'
afterbegin
'
,
view
.
el
);
}
else
if
(
index
===
(
this
.
model
.
length
-
1
))
{
list
.
insertAdjacentElement
(
'
beforeend
'
,
view
.
el
);
}
else
{
const
neighbour_el
=
list
.
querySelector
(
'
li:nth-child(
'
+
index
+
'
)
'
);
neighbour_el
.
insertAdjacentElement
(
'
afterend
'
,
view
.
el
);
}
return
view
;
},
onOccupantAdded
(
item
)
{
let
view
=
this
.
get
(
item
.
get
(
'
id
'
));
if
(
!
view
)
{
view
=
this
.
add
(
item
.
get
(
'
id
'
),
new
_converse
.
ChatRoomOccupantView
({
model
:
item
})
);
}
else
{
view
.
model
=
item
;
view
.
initialize
();
}
this
.
positionOccupant
(
item
);
},
parsePresence
(
pres
)
{
const
id
=
Strophe
.
getResourceFromJid
(
pres
.
getAttribute
(
"
from
"
));
const
data
=
{
...
...
src/converse-rosterview.js
View file @
ac643ae6
...
...
@@ -285,8 +285,12 @@
this
.
model
.
on
(
"
reset
"
,
this
.
reset
,
this
);
_converse
.
on
(
'
rosterGroupsFetched
'
,
this
.
positionFetchedGroups
,
this
);
_converse
.
on
(
'
rosterContactsFetched
'
,
()
=>
{
_converse
.
roster
.
each
(
this
.
onContactAdded
.
bind
(
this
));
_converse
.
roster
.
each
((
contact
)
=>
{
this
.
addRosterContact
(
contact
,
{
'
silent
'
:
true
});
});
this
.
update
();
this
.
updateFilter
();
this
.
trigger
(
'
rosterContactsFetchedAndProcessed
'
);
});
this
.
createRosterFilter
();
},
...
...
@@ -474,11 +478,11 @@
return
this
.
model
.
create
({
name
,
id
:
b64_sha1
(
name
)});
},
addContactToGroup
(
contact
,
name
)
{
this
.
getGroup
(
name
).
contacts
.
add
(
contact
);
addContactToGroup
(
contact
,
name
,
options
)
{
this
.
getGroup
(
name
).
contacts
.
add
(
contact
,
options
);
},
addExistingContact
(
contact
)
{
addExistingContact
(
contact
,
options
)
{
let
groups
;
if
(
_converse
.
roster_groups
)
{
groups
=
contact
.
get
(
'
groups
'
);
...
...
@@ -488,17 +492,17 @@
}
else
{
groups
=
[
HEADER_CURRENT_CONTACTS
];
}
_
.
each
(
groups
,
_
.
bind
(
this
.
addContactToGroup
,
this
,
contact
));
_
.
each
(
groups
,
_
.
bind
(
this
.
addContactToGroup
,
this
,
contact
,
_
,
options
));
},
addRosterContact
(
contact
)
{
addRosterContact
(
contact
,
options
)
{
if
(
contact
.
get
(
'
subscription
'
)
===
'
both
'
||
contact
.
get
(
'
subscription
'
)
===
'
to
'
)
{
this
.
addExistingContact
(
contact
);
this
.
addExistingContact
(
contact
,
options
);
}
else
{
if
((
contact
.
get
(
'
ask
'
)
===
'
subscribe
'
)
||
(
contact
.
get
(
'
subscription
'
)
===
'
from
'
))
{
this
.
addContactToGroup
(
contact
,
HEADER_PENDING_CONTACTS
);
this
.
addContactToGroup
(
contact
,
HEADER_PENDING_CONTACTS
,
options
);
}
else
if
(
contact
.
get
(
'
requesting
'
)
===
true
)
{
this
.
addContactToGroup
(
contact
,
HEADER_REQUESTING_CONTACTS
);
this
.
addContactToGroup
(
contact
,
HEADER_REQUESTING_CONTACTS
,
options
);
}
}
return
this
;
...
...
@@ -670,22 +674,34 @@
});
_converse
.
RosterGroupView
=
Backbone
.
O
verv
iew
.
extend
({
_converse
.
RosterGroupView
=
Backbone
.
O
rderedListV
iew
.
extend
({
tagName
:
'
div
'
,
className
:
'
roster-group
'
,
events
:
{
"
click a.group-toggle
"
:
"
toggle
"
},
listItems
:
'
model.contacts
'
,
sortEvent
:
'
change:chat_status
'
,
listSelector
:
'
.roster-group-contacts
'
,
ItemView
:
_converse
.
RosterContactView
,
initialize
()
{
this
.
sortEventually
=
_
.
debounce
(
this
.
sortAndPositionAll
,
500
);
this
.
model
.
contacts
.
on
(
"
add
"
,
this
.
onContactAdded
,
this
);
Backbone
.
OrderedListView
.
prototype
.
initialize
.
apply
(
this
,
arguments
);
this
.
model
.
contacts
.
on
(
"
change:subscription
"
,
this
.
onContactSubscriptionChange
,
this
);
this
.
model
.
contacts
.
on
(
"
change:requesting
"
,
this
.
onContactRequestChange
,
this
);
this
.
model
.
contacts
.
on
(
"
change:chat_status
"
,
this
.
sortEventually
,
this
);
this
.
model
.
contacts
.
on
(
"
destroy
"
,
this
.
onRemove
,
this
);
this
.
model
.
contacts
.
on
(
"
remove
"
,
this
.
onRemove
,
this
);
_converse
.
roster
.
on
(
'
change:groups
'
,
this
.
onContactGroupChange
,
this
);
// This event gets triggered once *all* contacts (i.e. not
// just this group's) have been fetched from browser
// storage or the XMPP server and once they've been
// assigned to their various groups.
_converse
.
rosterview
.
on
(
'
rosterContactsFetchedAndProcessed
'
,
this
.
sortAndPositionAllItems
.
bind
(
this
)
);
},
render
()
{
...
...
@@ -700,49 +716,19 @@
return
this
;
},
createContactView
(
contact
)
{
const
contact_view
=
new
_converse
.
RosterContactView
({
model
:
contact
});
this
.
add
(
contact
.
get
(
'
id
'
),
contact_view
);
contact_view
.
render
();
return
contact_view
;
},
onContactAdded
(
contact
)
{
const
contact_view
=
this
.
positionContact
(
contact
);
createItemView
(
contact
)
{
const
contact_view
=
Backbone
.
OrderedListView
.
prototype
.
createItemView
.
apply
(
this
,
arguments
);
if
(
contact_view
.
mayBeShown
())
{
if
(
this
.
model
.
get
(
'
state
'
)
===
_converse
.
CLOSED
)
{
u
.
hideElement
(
contact_view
.
el
);
u
.
showElement
(
this
.
el
);
}
else
{
u
.
showElement
(
contact_view
.
el
);
u
.
showElement
(
this
.
el
);
}
u
.
showElement
(
this
.
el
);
}
},
positionContact
(
contact
)
{
/* Place the contact's DOM element in the correct alphabetical
* position amongst the other contacts in this group.
*/
const
view
=
this
.
get
(
contact
.
get
(
'
id
'
))
||
this
.
createContactView
(
contact
);
const
list
=
this
.
contacts_el
;
const
index
=
this
.
model
.
contacts
.
indexOf
(
contact
);
if
(
index
===
0
)
{
list
.
insertAdjacentElement
(
'
afterbegin
'
,
view
.
el
);
}
else
if
(
index
===
(
this
.
model
.
contacts
.
length
-
1
))
{
list
.
insertAdjacentElement
(
'
beforeend
'
,
view
.
el
);
}
else
{
const
neighbour_el
=
list
.
querySelector
(
'
li:nth-child(
'
+
index
+
'
)
'
);
neighbour_el
.
insertAdjacentElement
(
'
afterend
'
,
view
.
el
);
}
return
view
;
},
sortAndPositionAll
()
{
this
.
model
.
contacts
.
sort
();
this
.
model
.
contacts
.
each
(
this
.
positionContact
.
bind
(
this
));
},
show
()
{
u
.
showElement
(
this
.
el
);
_
.
each
(
this
.
getAll
(),
(
contact_view
)
=>
{
...
...
@@ -851,7 +837,7 @@
if
(
in_this_group
&&
!
in_this_overview
)
{
this
.
model
.
contacts
.
remove
(
cid
);
}
else
if
(
!
in_this_group
&&
in_this_overview
)
{
this
.
onContactAdded
(
contact
);
this
.
items
.
trigger
(
'
add
'
,
contact
);
}
},
...
...
tests/mock.js
View file @
ac643ae6
...
...
@@ -106,6 +106,7 @@
'
bosh_service_url
'
:
'
localhost
'
,
'
connection
'
:
connection
,
'
animate
'
:
false
,
'
use_emojione
'
:
false
,
'
no_trimming
'
:
true
,
'
auto_login
'
:
true
,
'
jid
'
:
'
dummy@localhost
'
,
...
...
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