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
Expand all
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
This diff is collapsed.
Click to expand it.
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