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
506aa331
Commit
506aa331
authored
Jul 30, 2018
by
JC Brand
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Wait for promises before opening chats in API methods
parent
cb118b9c
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
2491 additions
and
2401 deletions
+2491
-2401
CHANGES.md
CHANGES.md
+3
-0
dist/converse.js
dist/converse.js
+24
-19
spec/bookmarks.js
spec/bookmarks.js
+93
-97
spec/chatbox.js
spec/chatbox.js
+463
-441
spec/chatroom.js
spec/chatroom.js
+735
-725
spec/http-file-upload.js
spec/http-file-upload.js
+291
-295
spec/messages.js
spec/messages.js
+636
-598
spec/minchats.js
spec/minchats.js
+43
-36
spec/roomslist.js
spec/roomslist.js
+105
-102
spec/spoilers.js
spec/spoilers.js
+26
-22
spec/user-details-modal.js
spec/user-details-modal.js
+10
-9
src/converse-muc-views.js
src/converse-muc-views.js
+1
-2
src/i18n.js
src/i18n.js
+7
-2
tests/utils.js
tests/utils.js
+54
-53
No files found.
CHANGES.md
View file @
506aa331
...
...
@@ -39,6 +39,9 @@
-
New API method
`_converse.api.vcard.update`
.
-
The
`contactStatusChanged`
event has been renamed to
`contactPresenceChanged`
and a event
`presenceChanged`
is now also triggered on the contact.
-
`_converse.api.chats.open`
and
`_converse.api.rooms.open`
now returns a
`Presence`
which resolves with the
`Backbone.Model`
representing the chat
object.
## UI changes
...
...
dist/converse.js
View file @
506aa331
...
...
@@ -76149,17 +76149,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
this.model.on('show', this.show, this);
this.model.occupants.on('add', this.showJoinNotification, this);
this.model.occupants.on('remove', this.showLeaveNotification, this);
this.model.occupants.on('change:show', occupant => {
if (!occupant.isMember() || _.includes(occupant.get('states'), '303')) {
return;
}
if (occupant.get('show') === 'offline') {
this.showLeaveNotification(occupant);
} else if (occupant.get('show') === 'online') {
this.showJoinNotification(occupant);
}
});
this.model.occupants.on('change:show', this.showJoinOrLeaveNotification, this);
this.createEmojiPicker();
this.createOccupantsView();
this.render().insertIntoDOM();
...
...
@@ -76169,8 +76159,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
const handler = () => {
if (!u.isPersistableModel(this.model)) {
// Happens during tests, nothing to do if this
// is a hanging chatbox (i.e. not in the
// collection anymore).
// is a hanging chatbox (i.e. not in the collection anymore).
return;
}
...
...
@@ -77047,6 +77036,18 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
}
},
showJoinOrLeaveNotification(occupant) {
if (!occupant.isMember() || _.includes(occupant.get('states'), '303')) {
return;
}
if (occupant.get('show') === 'offline') {
this.showLeaveNotification(occupant);
} else if (occupant.get('show') === 'online') {
this.showJoinNotification(occupant);
}
},
showJoinNotification(occupant) {
if (this.model.get('connection_status') !== converse.ROOMSTATUS.ENTERED) {
return;
...
...
@@ -77094,10 +77095,9 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
showLeaveNotification(occupant) {
const nick = occupant.get('nick'),
stat = occupant.get('status'),
last_el = this.content.lastElementChild,
last_msg_date = last_el.getAttribute('data-isodate');
last_el = this.content.lastElementChild;
if (
_.includes(_.get(last_el, 'classList', []), 'chat-info') && moment(last_msg_date
).isSame(new Date(), "day") && _.get(last_el, 'dataset', {}).join === `"${nick}"`) {
if (
last_el && _.includes(_.get(last_el, 'classList', []), 'chat-info') && moment(last_el.getAttribute('data-isodate')
).isSame(new Date(), "day") && _.get(last_el, 'dataset', {}).join === `"${nick}"`) {
let message;
if (_.isNil(stat)) {
...
...
@@ -77128,7 +77128,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
'data': `data-leave="${nick}"`
};
if (_.includes(_.get(last_el, 'classList', []), 'chat-info') && _.get(last_el, 'dataset', {}).leavejoin === `"${nick}"`) {
if (
last_el &&
_.includes(_.get(last_el, 'classList', []), 'chat-info') && _.get(last_el, 'dataset', {}).leavejoin === `"${nick}"`) {
last_el.outerHTML = tpl_info(data);
} else {
const el = u.stringToElement(tpl_info(data));
...
...
@@ -83843,8 +83843,13 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
xhr.onload = function () {
if (xhr.status >= 200 && xhr.status < 400) {
jed_instance = new Jed(window.JSON.parse(xhr.responseText));
resolve();
try {
const data = window.JSON.parse(xhr.responseText);
jed_instance = new Jed(data);
resolve();
} catch (e) {
xhr.onerror(e);
}
} else {
xhr.onerror();
}
spec/bookmarks.js
View file @
506aa331
...
...
@@ -34,24 +34,24 @@
});
spyOn
(
_converse
.
connection
,
'
getUniqueId
'
).
and
.
callThrough
();
test_utils
.
openChatRoom
(
_converse
,
'
theplay
'
,
'
conference.shakespeare.lit
'
,
'
JC
'
)
;
var
jid
=
'
theplay@conference.shakespeare.lit
'
;
var
view
=
_converse
.
chatboxviews
.
get
(
jid
);
spyOn
(
view
,
'
renderBookmarkForm
'
).
and
.
callThrough
()
;
spyOn
(
view
,
'
closeForm
'
).
and
.
callThrough
(
);
test_utils
.
waitUntil
(
function
()
{
return
!
_
.
isNull
(
view
.
el
.
querySelector
(
'
.toggle-bookmark
'
));
}
,
300
).
then
(
function
()
{
var
$bookmark
=
$
(
view
.
el
).
find
(
'
.toggle-bookmark
'
);
$bookmark
[
0
]
.
click
();
let
view
;
test_utils
.
openChatRoom
(
_converse
,
'
theplay
'
,
'
conference.shakespeare.lit
'
,
'
JC
'
)
.
then
(()
=>
{
var
jid
=
'
theplay@conference.shakespeare.lit
'
;
view
=
_converse
.
chatboxviews
.
get
(
jid
);
spyOn
(
view
,
'
renderBookmarkForm
'
).
and
.
callThrough
();
spyOn
(
view
,
'
closeForm
'
).
and
.
callThrough
();
return
test_utils
.
waitUntil
(()
=>
!
_
.
isNull
(
view
.
el
.
querySelector
(
'
.toggle-bookmark
'
)
));
}
).
then
(()
=>
{
var
bookmark
=
view
.
el
.
querySelector
(
'
.toggle-bookmark
'
);
bookmark
.
click
();
expect
(
view
.
renderBookmarkForm
).
toHaveBeenCalled
();
view
.
el
.
querySelector
(
'
.button-cancel
'
).
click
();
expect
(
view
.
closeForm
).
toHaveBeenCalled
();
expect
(
$bookmark
.
hasClass
(
'
on-button
'
),
false
);
expect
(
u
.
hasClass
(
'
on-button
'
,
bookmark
),
false
);
$bookmark
[
0
]
.
click
();
bookmark
.
click
();
expect
(
view
.
renderBookmarkForm
).
toHaveBeenCalled
();
/* Client uploads data:
...
...
@@ -93,7 +93,7 @@
view
.
el
.
querySelector
(
'
.btn-primary
'
).
click
();
expect
(
view
.
model
.
get
(
'
bookmarked
'
)).
toBeTruthy
();
expect
(
$bookmark
.
hasClass
(
'
on-button
'
),
true
);
expect
(
u
.
hasClass
(
'
on-button
'
,
bookmark
),
true
);
expect
(
sent_stanza
.
toLocaleString
()).
toBe
(
"
<iq type='set' from='dummy@localhost/resource' xmlns='jabber:client' id='
"
+
IQ_id
+
"
'>
"
+
...
...
@@ -175,100 +175,96 @@
it
(
"
displays that it's bookmarked through its bookmark icon
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
function
(
done
,
_converse
)
{
let
view
;
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
_converse
.
bare_jid
,
[{
'
category
'
:
'
pubsub
'
,
'
type
'
:
'
pep
'
}],
[
'
http://jabber.org/protocol/pubsub#publish-options
'
]
).
then
(
function
()
{
test_utils
.
openChatRoom
(
_converse
,
'
lounge
'
,
'
localhost
'
,
'
dummy
'
);
var
view
=
_converse
.
chatboxviews
.
get
(
'
lounge@localhost
'
);
test_utils
.
waitUntil
(
function
()
{
return
!
_
.
isNull
(
view
.
el
.
querySelector
(
'
.toggle-bookmark
'
));
},
300
).
then
(
function
()
{
var
bookmark_icon
=
view
.
el
.
querySelector
(
'
.toggle-bookmark
'
);
expect
(
_
.
includes
(
bookmark_icon
.
classList
,
'
button-on
'
)).
toBeFalsy
();
view
.
model
.
set
(
'
bookmarked
'
,
true
);
expect
(
_
.
includes
(
bookmark_icon
.
classList
,
'
button-on
'
)).
toBeTruthy
();
view
.
model
.
set
(
'
bookmarked
'
,
false
);
expect
(
_
.
includes
(
bookmark_icon
.
classList
,
'
button-on
'
)).
toBeFalsy
();
done
();
});
).
then
(()
=>
test_utils
.
openChatRoom
(
_converse
,
'
lounge
'
,
'
localhost
'
,
'
dummy
'
))
.
then
(()
=>
{
view
=
_converse
.
chatboxviews
.
get
(
'
lounge@localhost
'
);
return
test_utils
.
waitUntil
(()
=>
!
_
.
isNull
(
view
.
el
.
querySelector
(
'
.toggle-bookmark
'
)))
}).
then
(
function
()
{
var
bookmark_icon
=
view
.
el
.
querySelector
(
'
.toggle-bookmark
'
);
expect
(
_
.
includes
(
bookmark_icon
.
classList
,
'
button-on
'
)).
toBeFalsy
();
view
.
model
.
set
(
'
bookmarked
'
,
true
);
expect
(
_
.
includes
(
bookmark_icon
.
classList
,
'
button-on
'
)).
toBeTruthy
();
view
.
model
.
set
(
'
bookmarked
'
,
false
);
expect
(
_
.
includes
(
bookmark_icon
.
classList
,
'
button-on
'
)).
toBeFalsy
();
done
();
});
}));
it
(
"
can be unbookmarked
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
function
(
done
,
_converse
)
{
let
sent_stanza
,
IQ_id
,
view
,
sendIQ
;
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
_converse
.
bare_jid
,
[{
'
category
'
:
'
pubsub
'
,
'
type
'
:
'
pep
'
}],
[
'
http://jabber.org/protocol/pubsub#publish-options
'
]
).
then
(
function
()
{
var
sent_stanza
,
IQ_id
;
var
sendIQ
=
_converse
.
connection
.
sendIQ
;
test_utils
.
openChatRoom
(
_converse
,
'
theplay
'
,
'
conference.shakespeare.lit
'
,
'
JC
'
);
).
then
(()
=>
{
sendIQ
=
_converse
.
connection
.
sendIQ
;
return
test_utils
.
openChatRoom
(
_converse
,
'
theplay
'
,
'
conference.shakespeare.lit
'
,
'
JC
'
);
}).
then
(()
=>
{
var
jid
=
'
theplay@conference.shakespeare.lit
'
;
var
view
=
_converse
.
chatboxviews
.
get
(
jid
);
view
=
_converse
.
chatboxviews
.
get
(
jid
);
return
test_utils
.
waitUntil
(()
=>
!
_
.
isNull
(
view
.
el
.
querySelector
(
'
.toggle-bookmark
'
)));
}).
then
(
function
()
{
spyOn
(
view
,
'
toggleBookmark
'
).
and
.
callThrough
();
spyOn
(
_converse
.
bookmarks
,
'
sendBookmarkStanza
'
).
and
.
callThrough
();
view
.
delegateEvents
();
test_utils
.
waitUntil
(
function
()
{
return
!
_
.
isNull
(
view
.
el
.
querySelector
(
'
.toggle-bookmark
'
));
},
300
).
then
(
function
()
{
spyOn
(
view
,
'
toggleBookmark
'
).
and
.
callThrough
();
spyOn
(
_converse
.
bookmarks
,
'
sendBookmarkStanza
'
).
and
.
callThrough
();
view
.
delegateEvents
();
_converse
.
bookmarks
.
create
({
'
jid
'
:
view
.
model
.
get
(
'
jid
'
),
'
autojoin
'
:
false
,
'
name
'
:
'
The Play
'
,
'
nick
'
:
'
Othello
'
});
expect
(
_converse
.
bookmarks
.
length
).
toBe
(
1
);
expect
(
view
.
model
.
get
(
'
bookmarked
'
)).
toBeTruthy
();
var
$bookmark_icon
=
$
(
view
.
el
.
querySelector
(
'
.toggle-bookmark
'
));
expect
(
$bookmark_icon
.
hasClass
(
'
button-on
'
)).
toBeTruthy
();
spyOn
(
_converse
.
connection
,
'
sendIQ
'
).
and
.
callFake
(
function
(
iq
,
callback
,
errback
)
{
sent_stanza
=
iq
;
IQ_id
=
sendIQ
.
bind
(
this
)(
iq
,
callback
,
errback
);
});
spyOn
(
_converse
.
connection
,
'
getUniqueId
'
).
and
.
callThrough
();
$bookmark_icon
[
0
].
click
();
expect
(
view
.
toggleBookmark
).
toHaveBeenCalled
();
expect
(
$bookmark_icon
.
hasClass
(
'
button-on
'
)).
toBeFalsy
();
expect
(
_converse
.
bookmarks
.
length
).
toBe
(
0
);
// Check that an IQ stanza is sent out, containing no
// conferences to bookmark (since we removed the one and
// only bookmark).
expect
(
sent_stanza
.
toLocaleString
()).
toBe
(
"
<iq type='set' from='dummy@localhost/resource' xmlns='jabber:client' id='
"
+
IQ_id
+
"
'>
"
+
"
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
"
+
"
<publish node='storage:bookmarks'>
"
+
"
<item id='current'>
"
+
"
<storage xmlns='storage:bookmarks'/>
"
+
"
</item>
"
+
"
</publish>
"
+
"
<publish-options>
"
+
"
<x xmlns='jabber:x:data' type='submit'>
"
+
"
<field var='FORM_TYPE' type='hidden'>
"
+
"
<value>http://jabber.org/protocol/pubsub#publish-options</value>
"
+
"
</field>
"
+
"
<field var='pubsub#persist_items'>
"
+
"
<value>true</value>
"
+
"
</field>
"
+
"
<field var='pubsub#access_model'>
"
+
"
<value>whitelist</value>
"
+
"
</field>
"
+
"
</x>
"
+
"
</publish-options>
"
+
"
</pubsub>
"
+
"
</iq>
"
);
done
();
_converse
.
bookmarks
.
create
({
'
jid
'
:
view
.
model
.
get
(
'
jid
'
),
'
autojoin
'
:
false
,
'
name
'
:
'
The Play
'
,
'
nick
'
:
'
Othello
'
});
expect
(
_converse
.
bookmarks
.
length
).
toBe
(
1
);
expect
(
view
.
model
.
get
(
'
bookmarked
'
)).
toBeTruthy
();
var
bookmark_icon
=
view
.
el
.
querySelector
(
'
.toggle-bookmark
'
);
expect
(
u
.
hasClass
(
'
button-on
'
,
bookmark_icon
)).
toBeTruthy
();
spyOn
(
_converse
.
connection
,
'
sendIQ
'
).
and
.
callFake
(
function
(
iq
,
callback
,
errback
)
{
sent_stanza
=
iq
;
IQ_id
=
sendIQ
.
bind
(
this
)(
iq
,
callback
,
errback
);
});
spyOn
(
_converse
.
connection
,
'
getUniqueId
'
).
and
.
callThrough
();
bookmark_icon
.
click
();
expect
(
view
.
toggleBookmark
).
toHaveBeenCalled
();
expect
(
u
.
hasClass
(
'
button-on
'
,
bookmark_icon
)).
toBeFalsy
();
expect
(
_converse
.
bookmarks
.
length
).
toBe
(
0
);
// Check that an IQ stanza is sent out, containing no
// conferences to bookmark (since we removed the one and
// only bookmark).
expect
(
sent_stanza
.
toLocaleString
()).
toBe
(
"
<iq type='set' from='dummy@localhost/resource' xmlns='jabber:client' id='
"
+
IQ_id
+
"
'>
"
+
"
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
"
+
"
<publish node='storage:bookmarks'>
"
+
"
<item id='current'>
"
+
"
<storage xmlns='storage:bookmarks'/>
"
+
"
</item>
"
+
"
</publish>
"
+
"
<publish-options>
"
+
"
<x xmlns='jabber:x:data' type='submit'>
"
+
"
<field var='FORM_TYPE' type='hidden'>
"
+
"
<value>http://jabber.org/protocol/pubsub#publish-options</value>
"
+
"
</field>
"
+
"
<field var='pubsub#persist_items'>
"
+
"
<value>true</value>
"
+
"
</field>
"
+
"
<field var='pubsub#access_model'>
"
+
"
<value>whitelist</value>
"
+
"
</field>
"
+
"
</x>
"
+
"
</publish-options>
"
+
"
</pubsub>
"
+
"
</iq>
"
);
done
();
});
}));
});
...
...
@@ -585,9 +581,8 @@
'
name
'
:
'
The Play
'
,
'
nick
'
:
''
});
test_utils
.
waitUntil
(
function
()
{
return
$
(
'
#chatrooms .bookmarks.rooms-list .room-item:visible
'
).
length
;
},
300
).
then
(
function
()
{
test_utils
.
waitUntil
(()
=>
$
(
'
#chatrooms .bookmarks.rooms-list .room-item:visible
'
).
length
).
then
(
function
()
{
expect
(
$
(
'
#chatrooms .bookmarks.rooms-list
'
).
hasClass
(
'
collapsed
'
)).
toBeFalsy
();
expect
(
$
(
'
#chatrooms .bookmarks.rooms-list .room-item:visible
'
).
length
).
toBe
(
1
);
expect
(
_converse
.
bookmarksview
.
list_model
.
get
(
'
toggle-state
'
)).
toBe
(
_converse
.
OPENED
);
...
...
@@ -612,6 +607,7 @@
{
hide_open_bookmarks
:
true
},
function
(
done
,
_converse
)
{
const
jid
=
'
room@conference.example.org
'
;
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
_converse
.
bare_jid
,
[{
'
category
'
:
'
pubsub
'
,
'
type
'
:
'
pep
'
}],
...
...
@@ -625,14 +621,12 @@
_converse
.
emit
(
'
bookmarksInitialized
'
);
// Check that it's there
var
jid
=
'
room@conference.example.org
'
;
_converse
.
bookmarks
.
create
({
'
jid
'
:
jid
,
'
autojoin
'
:
false
,
'
name
'
:
'
The Play
'
,
'
nick
'
:
'
Othello
'
});
expect
(
_converse
.
bookmarks
.
length
).
toBe
(
1
);
var
room_els
=
_converse
.
bookmarksview
.
el
.
querySelectorAll
(
"
.open-room
"
);
expect
(
room_els
.
length
).
toBe
(
1
);
...
...
@@ -640,9 +634,11 @@
// Check that it disappears once the room is opened
var
bookmark
=
_converse
.
bookmarksview
.
el
.
querySelector
(
"
.open-room
"
);
bookmark
.
click
();
return
test_utils
.
waitUntil
(()
=>
_converse
.
chatboxviews
.
get
(
jid
));
}).
then
(()
=>
{
expect
(
u
.
hasClass
(
'
hidden
'
,
_converse
.
bookmarksview
.
el
.
querySelector
(
"
.available-chatroom
"
))).
toBeTruthy
();
// Check that it reappears once the room is closed
var
view
=
_converse
.
chatboxviews
.
get
(
jid
);
const
view
=
_converse
.
chatboxviews
.
get
(
jid
);
view
.
close
();
expect
(
u
.
hasClass
(
'
hidden
'
,
_converse
.
bookmarksview
.
el
.
querySelector
(
"
.available-chatroom
"
))).
toBeFalsy
();
done
();
...
...
spec/chatbox.js
View file @
506aa331
...
...
@@ -7,11 +7,12 @@
],
factory
);
}
(
this
,
function
(
$
,
jasmine
,
mock
,
test_utils
)
{
"
use strict
"
;
var
_
=
converse
.
env
.
_
;
var
$iq
=
converse
.
env
.
$iq
;
var
$msg
=
converse
.
env
.
$msg
;
var
Strophe
=
converse
.
env
.
Strophe
;
var
u
=
converse
.
env
.
utils
;
const
_
=
converse
.
env
.
_
;
const
$iq
=
converse
.
env
.
$iq
;
const
$msg
=
converse
.
env
.
$msg
;
const
Strophe
=
converse
.
env
.
Strophe
;
const
u
=
converse
.
env
.
utils
;
const
sizzle
=
converse
.
env
.
sizzle
;
return
describe
(
"
Chatboxes
"
,
function
()
{
...
...
@@ -158,45 +159,50 @@
}));
it
(
"
can be trimmed to conserve space
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
function
(
done
,
_converse
)
{
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
function
(
done
,
_converse
)
{
spyOn
(
_converse
.
chatboxviews
,
'
trimChats
'
);
const
trimmed_chatboxes
=
_converse
.
minimized_chats
;
spyOn
(
trimmed_chatboxes
,
'
addChat
'
).
and
.
callThrough
();
spyOn
(
trimmed_chatboxes
,
'
removeChat
'
).
and
.
callThrough
();
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
test_utils
.
openControlBox
();
var
i
,
$el
,
jid
,
chatbox
,
chatboxview
,
trimmedview
;
let
online_contacts
;
var
i
,
jid
,
chatbox
,
chatboxview
,
trimmedview
;
// openControlBox was called earlier, so the controlbox is
// visible, but no other chat boxes have been created.
var
trimmed_chatboxes
=
_converse
.
minimized_chats
;
expect
(
_converse
.
chatboxes
.
length
).
toEqual
(
1
);
spyOn
(
_converse
.
chatboxviews
,
'
trimChats
'
);
spyOn
(
trimmed_chatboxes
,
'
addChat
'
).
and
.
callThrough
();
spyOn
(
trimmed_chatboxes
,
'
removeChat
'
).
and
.
callThrough
();
expect
(
$
(
"
#conversejs .chatbox
"
).
length
).
toBe
(
1
);
// Controlbox is open
expect
(
document
.
querySelectorAll
(
"
#conversejs .chatbox
"
).
length
).
toBe
(
1
);
// Controlbox is open
_converse
.
rosterview
.
update
();
// XXX: Hack to make sure $roster element is attached.
test_utils
.
waitUntil
(
function
()
{
return
$
(
_converse
.
rosterview
.
el
).
find
(
'
.roster-group li
'
).
length
;
},
700
).
then
(
function
()
{
test_utils
.
waitUntil
(()
=>
_converse
.
rosterview
.
el
.
querySelectorAll
(
'
.roster-group li
'
).
length
)
.
then
(()
=>
{
// Test that they can be maximized again
var
online_contacts
=
$
(
_converse
.
rosterview
.
el
).
find
(
'
.roster-group .current-xmpp-contact a.open-chat
'
);
online_contacts
=
_converse
.
rosterview
.
el
.
querySelectorAll
(
'
.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
=
_
.
trim
(
$el
.
text
().
trim
()).
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
$el
[
0
].
click
();
expect
(
_converse
.
chatboxviews
.
trimChats
).
toHaveBeenCalled
();
const
el
=
online_contacts
[
i
];
el
.
click
();
}
return
test_utils
.
waitUntil
(()
=>
_converse
.
chatboxes
.
length
==
16
)
}).
then
(()
=>
{
expect
(
_converse
.
chatboxviews
.
trimChats
.
calls
.
count
()).
toBe
(
16
);
for
(
i
=
0
;
i
<
online_contacts
.
length
;
i
++
)
{
const
el
=
online_contacts
[
i
];
jid
=
_
.
trim
(
el
.
textContent
.
trim
()).
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
chatboxview
=
_converse
.
chatboxviews
.
get
(
jid
);
spyOn
(
chatboxview
,
'
minimize
'
).
and
.
callThrough
();
chatboxview
.
model
.
set
({
'
minimized
'
:
true
});
expect
(
trimmed_chatboxes
.
addChat
).
toHaveBeenCalled
();
expect
(
chatboxview
.
minimize
).
toHaveBeenCalled
();
}
return
test_utils
.
waitUntil
(
function
()
{
return
_converse
.
chatboxviews
.
keys
().
length
>
1
;
},
500
);
return
test_utils
.
waitUntil
(()
=>
_converse
.
chatboxviews
.
keys
().
length
);
}).
then
(
function
()
{
var
key
=
_converse
.
chatboxviews
.
keys
()[
1
];
trimmedview
=
trimmed_chatboxes
.
get
(
key
);
...
...
@@ -208,10 +214,9 @@
expect
(
trimmedview
.
restore
).
toHaveBeenCalled
();
expect
(
chatbox
.
maximize
).
toHaveBeenCalled
();
expect
(
_converse
.
chatboxviews
.
trimChats
).
toHaveBeenCalled
(
);
expect
(
_converse
.
chatboxviews
.
trimChats
.
calls
.
count
()).
toBe
(
17
);
done
();
});
done
();
}));
it
(
"
can be opened in minimized mode initially
"
,
...
...
@@ -237,29 +242,26 @@
it
(
"
is focused if its already open and you click on its corresponding roster item
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
function
(
done
,
_converse
)
{
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
rosterview
.
update
();
// XXX: Hack to make sure $roster element is attaced.
_converse
.
emit
(
'
rosterContactsFetched
'
);
test_utils
.
openControlBox
();
var
contact_jid
=
mock
.
cur_names
[
2
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
var
$el
,
jid
,
chatbox
;
const
contact_jid
=
mock
.
cur_names
[
2
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
let
el
,
jid
;
// openControlBox was called earlier, so the controlbox is
// visible, but no other chat boxes have been created.
expect
(
_converse
.
chatboxes
.
length
).
toEqual
(
1
);
chatbox
=
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
$el
=
$
(
_converse
.
rosterview
.
el
).
find
(
'
a.open-chat:contains("
'
+
chatbox
.
getDisplayName
()
+
'
")
'
);
jid
=
$el
.
text
().
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
spyOn
(
_converse
,
'
emit
'
);
$el
[
0
].
click
();
test_utils
.
waitUntil
(
function
()
{
return
_converse
.
emit
.
calls
.
count
();
},
300
).
then
(
function
()
{
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
)
.
then
((
view
)
=>
{
el
=
sizzle
(
'
a.open-chat:contains("
'
+
view
.
model
.
getDisplayName
()
+
'
")
'
,
_converse
.
rosterview
.
el
).
pop
();
jid
=
el
.
textContent
.
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
spyOn
(
_converse
,
'
emit
'
);
el
.
click
();
return
test_utils
.
waitUntil
(()
=>
_converse
.
emit
.
calls
.
count
(),
500
);
}).
then
(()
=>
{
expect
(
_converse
.
chatboxes
.
length
).
toEqual
(
2
);
expect
(
_converse
.
emit
).
toHaveBeenCalledWith
(
'
chatBoxFocused
'
,
jasmine
.
any
(
Object
));
done
();
...
...
@@ -268,10 +270,11 @@
it
(
"
can be saved to, and retrieved from, browserStorage
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
,
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
test_utils
.
openControlBox
();
spyOn
(
_converse
,
'
emit
'
);
...
...
@@ -279,41 +282,46 @@
test_utils
.
openControlBox
();
test_utils
.
openChatBoxes
(
_converse
,
6
);
expect
(
_converse
.
chatboxviews
.
trimChats
).
toHaveBeenCalled
();
// We instantiate a new ChatBoxes collection, which by default
// will be empty.
var
newchatboxes
=
new
_converse
.
ChatBoxes
();
expect
(
newchatboxes
.
length
).
toEqual
(
0
);
// The chatboxes will then be fetched from browserStorage inside the
// onConnected method
newchatboxes
.
onConnected
();
expect
(
newchatboxes
.
length
).
toEqual
(
7
);
// Check that the chatboxes items retrieved from browserStorage
// have the same attributes values as the original ones.
var
attrs
=
[
'
id
'
,
'
box_id
'
,
'
visible
'
];
var
new_attrs
,
old_attrs
;
for
(
var
i
=
0
;
i
<
attrs
.
length
;
i
++
)
{
new_attrs
=
_
.
map
(
_
.
map
(
newchatboxes
.
models
,
'
attributes
'
),
attrs
[
i
]);
old_attrs
=
_
.
map
(
_
.
map
(
_converse
.
chatboxes
.
models
,
'
attributes
'
),
attrs
[
i
]);
expect
(
_
.
isEqual
(
new_attrs
,
old_attrs
)).
toEqual
(
true
);
}
_converse
.
rosterview
.
render
();
done
();
return
test_utils
.
waitUntil
(()
=>
_converse
.
chatboxes
.
length
==
7
).
then
(()
=>
{
expect
(
_converse
.
chatboxviews
.
trimChats
).
toHaveBeenCalled
();
// We instantiate a new ChatBoxes collection, which by default
// will be empty.
const
newchatboxes
=
new
_converse
.
ChatBoxes
();
expect
(
newchatboxes
.
length
).
toEqual
(
0
);
// The chatboxes will then be fetched from browserStorage inside the
// onConnected method
newchatboxes
.
onConnected
();
expect
(
newchatboxes
.
length
).
toEqual
(
7
);
// Check that the chatboxes items retrieved from browserStorage
// have the same attributes values as the original ones.
const
attrs
=
[
'
id
'
,
'
box_id
'
,
'
visible
'
];
let
new_attrs
,
old_attrs
;
for
(
var
i
=
0
;
i
<
attrs
.
length
;
i
++
)
{
new_attrs
=
_
.
map
(
_
.
map
(
newchatboxes
.
models
,
'
attributes
'
),
attrs
[
i
]);
old_attrs
=
_
.
map
(
_
.
map
(
_converse
.
chatboxes
.
models
,
'
attributes
'
),
attrs
[
i
]);
expect
(
_
.
isEqual
(
new_attrs
,
old_attrs
)).
toEqual
(
true
);
}
_converse
.
rosterview
.
render
();
done
();
}).
catch
(
_
.
partial
(
_converse
.
log
,
_
,
Strophe
.
LogLevel
.
FATAL
));
}));
it
(
"
can be closed by clicking a DOM element with class 'close-chatbox-button'
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
test_utils
.
openControlBox
();
test_utils
.
waitUntil
(
function
()
{
return
$
(
_converse
.
rosterview
.
el
).
find
(
'
.roster-group
'
).
length
;
},
300
).
then
(
function
()
{
var
chatbox
=
test_utils
.
openChatBoxes
(
_converse
,
1
)[
0
],
controlview
=
_converse
.
chatboxviews
.
get
(
'
controlbox
'
),
// The controlbox is currently open
chatview
=
_converse
.
chatboxviews
.
get
(
chatbox
.
get
(
'
jid
'
));
const
contact_jid
=
mock
.
cur_names
[
7
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
waitUntil
(()
=>
_converse
.
rosterview
.
el
.
querySelectorAll
(
'
.roster-group
'
).
length
)
.
then
(()
=>
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
))
.
then
(()
=>
{
var
controlview
=
_converse
.
chatboxviews
.
get
(
'
controlbox
'
),
// The controlbox is currently open
chatview
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
spyOn
(
chatview
,
'
close
'
).
and
.
callThrough
();
spyOn
(
controlview
,
'
close
'
).
and
.
callThrough
();
spyOn
(
_converse
,
'
emit
'
);
...
...
@@ -338,20 +346,22 @@
it
(
"
can be minimized by clicking a DOM element with class 'toggle-chatbox-button'
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
var
chatview
;
let
chatview
;
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
test_utils
.
openControlBox
();
test_utils
.
waitUntil
(
function
()
{
return
$
(
_converse
.
rosterview
.
el
).
find
(
'
.roster-group
'
).
length
;
},
300
)
.
then
(
function
()
{
var
chatbox
=
test_utils
.
openChatBoxes
(
_converse
,
1
)[
0
],
trimmed_chatboxes
=
_converse
.
minimized_chats
,
const
contact_jid
=
mock
.
cur_names
[
7
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
waitUntil
(()
=>
_converse
.
rosterview
.
el
.
querySelectorAll
(
'
.roster-group
'
).
length
)
.
then
(
()
=>
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
))
.
then
(()
=>
{
var
trimmed_chatboxes
=
_converse
.
minimized_chats
,
trimmedview
;
chatview
=
_converse
.
chatboxviews
.
get
(
c
hatbox
.
get
(
'
jid
'
)
);
chatview
=
_converse
.
chatboxviews
.
get
(
c
ontact_jid
);
spyOn
(
chatview
,
'
minimize
'
).
and
.
callThrough
();
spyOn
(
_converse
,
'
emit
'
);
// We need to rebind all events otherwise our spy won't be called
...
...
@@ -372,9 +382,7 @@
expect
(
trimmedview
.
restore
).
toHaveBeenCalled
();
expect
(
_converse
.
emit
).
toHaveBeenCalledWith
(
'
chatBoxMaximized
'
,
jasmine
.
any
(
Object
));
return
test_utils
.
waitUntil
(
function
()
{
return
$
(
chatview
.
el
).
find
(
'
.chat-body
'
).
is
(
'
:visible
'
);
},
500
);
return
test_utils
.
waitUntil
(()
=>
u
.
isVisible
(
chatview
.
el
.
querySelector
(
'
.chat-body
'
)),
500
);
}).
then
(
function
()
{
expect
(
$
(
chatview
.
el
).
find
(
'
.toggle-chatbox-button
'
).
hasClass
(
'
fa-minus
'
)).
toBeTruthy
();
expect
(
$
(
chatview
.
el
).
find
(
'
.toggle-chatbox-button
'
).
hasClass
(
'
fa-plus
'
)).
toBeFalsy
();
...
...
@@ -385,14 +393,14 @@
it
(
"
will be removed from browserStorage when closed
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
test_utils
.
openControlBox
();
test_utils
.
waitUntil
(
function
()
{
return
$
(
_converse
.
rosterview
.
el
).
find
(
'
.roster-group
'
).
length
;
},
300
).
then
(
function
()
{
test_utils
.
waitUntil
(()
=>
_converse
.
rosterview
.
el
.
querySelectorAll
(
'
.roster-group
'
).
length
)
.
then
(()
=>
{
spyOn
(
_converse
,
'
emit
'
);
spyOn
(
_converse
.
chatboxviews
,
'
trimChats
'
);
_converse
.
chatboxes
.
browserStorage
.
_clear
();
...
...
@@ -403,6 +411,8 @@
expect
(
_converse
.
chatboxes
.
length
).
toEqual
(
1
);
expect
(
_converse
.
chatboxes
.
pluck
(
'
id
'
)).
toEqual
([
'
controlbox
'
]);
test_utils
.
openChatBoxes
(
_converse
,
6
);
return
test_utils
.
waitUntil
(()
=>
_converse
.
chatboxes
.
length
==
7
)
}).
then
(()
=>
{
expect
(
_converse
.
chatboxviews
.
trimChats
).
toHaveBeenCalled
();
expect
(
_converse
.
chatboxes
.
length
).
toEqual
(
7
);
expect
(
_converse
.
emit
).
toHaveBeenCalledWith
(
'
chatBoxOpened
'
,
jasmine
.
any
(
Object
));
...
...
@@ -428,77 +438,70 @@
it
(
"
can be found on each chat box
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
test_utils
.
openControlBox
();
var
contact_jid
=
mock
.
cur_names
[
2
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
var
chatbox
=
_converse
.
chatboxes
.
get
(
contact_jid
);
var
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
expect
(
chatbox
).
toBeDefined
();
expect
(
view
).
toBeDefined
();
var
toolbar
=
view
.
el
.
querySelector
(
'
ul.chat-toolbar
'
);
expect
(
_
.
isElement
(
toolbar
)).
toBe
(
true
);
expect
(
toolbar
.
querySelectorAll
(
'
:scope > li
'
).
length
).
toBe
(
1
);
done
();
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
)
.
then
(()
=>
{
var
chatbox
=
_converse
.
chatboxes
.
get
(
contact_jid
);
var
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
expect
(
chatbox
).
toBeDefined
();
expect
(
view
).
toBeDefined
();
var
toolbar
=
view
.
el
.
querySelector
(
'
ul.chat-toolbar
'
);
expect
(
_
.
isElement
(
toolbar
)).
toBe
(
true
);
expect
(
toolbar
.
querySelectorAll
(
'
:scope > li
'
).
length
).
toBe
(
1
);
done
();
});
}));
it
(
"
contains a button for inserting emojis
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
test_utils
.
openControlBox
();
var
contact_jid
=
mock
.
cur_names
[
2
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
)
;
var
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
var
toolbar
=
view
.
el
.
querySelector
(
'
ul.chat-toolbar
'
);
expect
(
toolbar
.
querySelectorAll
(
'
li.toggle-smiley
'
).
length
).
toBe
(
1
);
// Register spies
spyOn
(
view
,
'
toggleEmojiMenu
'
).
and
.
callThrough
(
);
spyOn
(
view
,
'
insertEmoji
'
).
and
.
callThrough
();
view
.
delegateEvents
();
// We need to rebind all events otherwise our spy won't be called
toolbar
.
querySelector
(
'
li.toggle-smiley
'
).
click
();
var
timeout
=
false
;
let
timeout
=
false
,
view
,
toolbar
;
const
contact_jid
=
mock
.
cur_names
[
2
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
)
.
then
(()
=>
{
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
toolbar
=
view
.
el
.
querySelector
(
'
ul.chat-toolbar
'
);
expect
(
toolbar
.
querySelectorAll
(
'
li.toggle-smiley
'
).
length
).
toBe
(
1
);
// Register spies
spyOn
(
view
,
'
toggleEmojiMenu
'
).
and
.
callThrough
();
spyOn
(
view
,
'
insertEmoji
'
).
and
.
callThrough
();
view
.
delegateEvents
();
// We need to rebind all events otherwise our spy won't be called
toolbar
.
querySelector
(
'
li.toggle-smiley
'
).
click
()
;
test_utils
.
waitUntil
(
function
()
{
return
u
.
isVisible
(
view
.
el
.
querySelector
(
'
.toggle-smiley .emoji-picker-container
'
));
},
500
).
then
(
function
()
{
return
test_utils
.
waitUntil
(()
=>
u
.
isVisible
(
view
.
el
.
querySelector
(
'
.toggle-smiley .emoji-picker-container
'
),
500
));
}).
then
(()
=>
{
var
picker
=
view
.
el
.
querySelector
(
'
.toggle-smiley .emoji-picker-container
'
);
var
items
=
picker
.
querySelectorAll
(
'
.emoji-picker li
'
);
items
[
0
].
click
()
expect
(
view
.
insertEmoji
).
toHaveBeenCalled
();
setTimeout
(
function
()
{
timeout
=
true
;
},
100
);
return
test_utils
.
waitUntil
(
function
()
{
return
timeout
;
},
500
);
}).
then
(
function
()
{
return
test_utils
.
waitUntil
(()
=>
timeout
,
500
);
}).
then
(()
=>
{
timeout
=
false
;
toolbar
.
querySelector
(
'
li.toggle-smiley
'
).
click
();
// Close the panel again
return
test_utils
.
waitUntil
(
function
()
{
return
!
view
.
el
.
querySelector
(
'
.toggle-smiley .toolbar-menu
'
).
offsetHeight
;
},
500
);
}).
then
(
function
()
{
return
test_utils
.
waitUntil
(()
=>
!
view
.
el
.
querySelector
(
'
.toggle-smiley .toolbar-menu
'
).
offsetHeight
,
500
);
}).
then
(()
=>
{
setTimeout
(
function
()
{
timeout
=
true
;
},
100
);
return
test_utils
.
waitUntil
(
function
()
{
return
timeout
;
},
500
);
}).
then
(
function
()
{
return
test_utils
.
waitUntil
(()
=>
timeout
,
500
);
}).
then
(()
=>
{
toolbar
.
querySelector
(
'
li.toggle-smiley
'
).
click
();
expect
(
view
.
toggleEmojiMenu
).
toHaveBeenCalled
();
return
test_utils
.
waitUntil
(
function
()
{
var
$picker
=
$
(
view
.
el
).
find
(
'
.toggle-smiley .emoji-picker-container
'
);
return
u
.
isVisible
(
$picker
[
0
]);
},
500
);
}).
then
(
function
()
{
return
test_utils
.
waitUntil
(()
=>
u
.
isVisible
(
view
.
el
.
querySelector
(
'
.toggle-smiley .emoji-picker-container
'
)),
500
);
}).
then
(()
=>
{
var
nodes
=
view
.
el
.
querySelectorAll
(
'
.toggle-smiley ul li
'
);
nodes
[
nodes
.
length
-
1
].
click
();
expect
(
view
.
el
.
querySelector
(
'
textarea.chat-textarea
'
).
value
).
toBe
(
'
:grinning:
'
);
...
...
@@ -509,34 +512,38 @@
it
(
"
can contain a button for starting a call
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
test_utils
.
openControlBox
();
var
view
;
var
contact_jid
=
mock
.
cur_names
[
2
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
let
view
,
toolbar
,
call_button
;
const
contact_jid
=
mock
.
cur_names
[
2
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
spyOn
(
_converse
,
'
emit
'
);
// First check that the button doesn't show if it's not enabled
// via "visible_toolbar_buttons"
_converse
.
visible_toolbar_buttons
.
call
=
false
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
var
toolbar
=
view
.
el
.
querySelector
(
'
ul.chat-toolbar
'
);
var
call_button
=
toolbar
.
querySelector
(
'
.toggle-call
'
);
expect
(
_
.
isNull
(
call_button
)).
toBeTruthy
();
view
.
close
();
// Now check that it's shown if enabled and that it emits
// callButtonClicked
_converse
.
visible_toolbar_buttons
.
call
=
true
;
// enable the button
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
toolbar
=
view
.
el
.
querySelector
(
'
ul.chat-toolbar
'
);
call_button
=
toolbar
.
querySelector
(
'
.toggle-call
'
);
call_button
.
click
();
expect
(
_converse
.
emit
).
toHaveBeenCalledWith
(
'
callButtonClicked
'
,
jasmine
.
any
(
Object
));
done
();
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
)
.
then
(()
=>
{
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
toolbar
=
view
.
el
.
querySelector
(
'
ul.chat-toolbar
'
);
call_button
=
toolbar
.
querySelector
(
'
.toggle-call
'
);
expect
(
_
.
isNull
(
call_button
)).
toBeTruthy
();
view
.
close
();
// Now check that it's shown if enabled and that it emits
// callButtonClicked
_converse
.
visible_toolbar_buttons
.
call
=
true
;
// enable the button
return
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
}).
then
(()
=>
{
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
toolbar
=
view
.
el
.
querySelector
(
'
ul.chat-toolbar
'
);
call_button
=
toolbar
.
querySelector
(
'
.toggle-call
'
);
call_button
.
click
();
expect
(
_converse
.
emit
).
toHaveBeenCalledWith
(
'
callButtonClicked
'
,
jasmine
.
any
(
Object
));
done
();
});
}));
});
...
...
@@ -568,17 +575,19 @@
it
(
"
is sent when the user opens a chat box
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
const
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openControlBox
();
test_utils
.
waitUntil
(
function
()
{
return
$
(
_converse
.
rosterview
.
el
).
find
(
'
.roster-group
'
).
length
;
},
300
).
then
(
function
()
{
spyOn
(
_converse
.
connection
,
'
send
'
);
var
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
return
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
)
;
}).
then
(()
=>
{
var
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
expect
(
view
.
model
.
get
(
'
chat_state
'
)).
toBe
(
'
active
'
);
expect
(
_converse
.
connection
.
send
).
toHaveBeenCalled
();
...
...
@@ -593,26 +602,24 @@
}));
it
(
"
is sent when the user maximizes a minimized a chat box
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
test_utils
.
openControlBox
();
var
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
waitUntil
(
function
()
{
return
$
(
_converse
.
rosterview
.
el
).
find
(
'
.roster-group
'
).
length
;
},
500
).
then
(
function
()
{
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
test_utils
.
waitUntil
(()
=>
_converse
.
rosterview
.
el
.
querySelectorAll
(
'
.roster-group
'
).
length
)
.
then
(()
=>
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
))
.
then
(()
=>
{
var
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
view
.
model
.
minimize
();
expect
(
view
.
model
.
get
(
'
chat_state
'
)).
toBe
(
'
inactive
'
);
spyOn
(
_converse
.
connection
,
'
send
'
);
view
.
model
.
maximize
();
return
test_utils
.
waitUntil
(
function
()
{
return
view
.
model
.
get
(
'
chat_state
'
)
===
'
active
'
;
},
700
);
}).
then
(
function
()
{
return
test_utils
.
waitUntil
(()
=>
view
.
model
.
get
(
'
chat_state
'
)
===
'
active
'
,
700
);
}).
then
(()
=>
{
expect
(
_converse
.
connection
.
send
).
toHaveBeenCalled
();
var
calls
=
_
.
filter
(
_converse
.
connection
.
send
.
calls
.
all
(),
function
(
call
)
{
return
call
.
args
[
0
]
instanceof
Strophe
.
Builder
;
...
...
@@ -633,16 +640,17 @@
it
(
"
is sent as soon as the user starts typing a message which is not a command
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
test_utils
.
openControlBox
();
test_utils
.
waitUntil
(
function
()
{
return
$
(
_converse
.
rosterview
.
el
).
find
(
'
.roster-group
'
).
length
;
},
300
).
then
(
function
()
{
var
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
const
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
waitUntil
(()
=>
_converse
.
rosterview
.
el
.
querySelectorAll
(
'
.roster-group
'
).
length
)
.
then
(()
=>
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
))
.
then
(()
=>
{
var
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
expect
(
view
.
model
.
get
(
'
chat_state
'
)).
toBe
(
'
active
'
);
spyOn
(
_converse
.
connection
,
'
send
'
);
...
...
@@ -720,21 +728,20 @@
it
(
"
can be a composing carbon message that this user sent from a different client
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
var
contact
,
sent_stanza
,
IQ_id
,
stanza
;
let
contact
,
sent_stanza
,
IQ_id
,
stanza
,
recipient_jid
;
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
'
localhost
'
,
[],
[
'
vcard-temp
'
])
.
then
(()
=>
test_utils
.
waitUntil
(()
=>
_converse
.
xmppstatus
.
vcard
.
get
(
'
fullname
'
)))
.
then
(
function
()
{
return
test_utils
.
waitUntil
(
function
()
{
return
_converse
.
xmppstatus
.
vcard
.
get
(
'
fullname
'
);
},
300
);
}).
then
(
function
()
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
// Send a message from a different resource
spyOn
(
_converse
,
'
log
'
);
var
recipient_jid
=
mock
.
cur_names
[
5
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
recipient_jid
);
recipient_jid
=
mock
.
cur_names
[
5
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
return
test_utils
.
openChatBoxFor
(
_converse
,
recipient_jid
);
}).
then
(()
=>
{
var
msg
=
$msg
({
'
from
'
:
_converse
.
bare_jid
,
'
id
'
:
(
new
Date
()).
getTime
(),
...
...
@@ -771,19 +778,19 @@
it
(
"
is sent if the user has stopped typing since 30 seconds
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
var
view
,
contact_jid
;
let
view
;
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
const
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openControlBox
();
test_utils
.
waitUntil
(
function
()
{
return
$
(
_converse
.
rosterview
.
el
).
find
(
'
.roster-group li
'
).
length
;
},
700
).
then
(
function
()
{
test_utils
.
waitUntil
(()
=>
_converse
.
rosterview
.
el
.
querySelectorAll
(
'
.roster-group li
'
).
length
,
700
)
.
then
(()
=>
{
_converse
.
TIMEOUTS
.
PAUSED
=
200
;
// Make the timeout shorter so that we can test
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
return
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
}).
then
(()
=>
{
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
spyOn
(
_converse
.
connection
,
'
send
'
);
spyOn
(
view
,
'
setChatState
'
).
and
.
callThrough
();
...
...
@@ -796,10 +803,8 @@
expect
(
_converse
.
connection
.
send
).
toHaveBeenCalled
();
var
$stanza
=
$
(
_converse
.
connection
.
send
.
calls
.
argsFor
(
0
)[
0
].
tree
());
expect
(
$stanza
.
children
().
get
(
0
).
tagName
).
toBe
(
'
composing
'
);
return
test_utils
.
waitUntil
(
function
()
{
return
view
.
model
.
get
(
'
chat_state
'
)
===
'
paused
'
;
},
500
);
}).
then
(
function
()
{
return
test_utils
.
waitUntil
(()
=>
view
.
model
.
get
(
'
chat_state
'
)
===
'
paused
'
,
500
);
}).
then
(()
=>
{
expect
(
_converse
.
connection
.
send
).
toHaveBeenCalled
();
var
calls
=
_
.
filter
(
_converse
.
connection
.
send
.
calls
.
all
(),
function
(
call
)
{
return
call
.
args
[
0
]
instanceof
Strophe
.
Builder
;
...
...
@@ -828,7 +833,7 @@
});
expect
(
view
.
model
.
get
(
'
chat_state
'
)).
toBe
(
'
composing
'
);
done
();
})
;
})
.
catch
(
_
.
partial
(
_converse
.
log
,
_
,
Strophe
.
LogLevel
.
FATAL
))
}));
it
(
"
will be shown if received
"
,
...
...
@@ -868,21 +873,20 @@
it
(
"
can be a paused carbon message that this user sent from a different client
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
var
contact
,
sent_stanza
,
IQ_id
,
stanza
;
let
contact
,
sent_stanza
,
IQ_id
,
stanza
,
recipient_jid
;
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
'
localhost
'
,
[],
[
'
vcard-temp
'
])
.
then
(
function
()
{
return
test_utils
.
waitUntil
(
function
()
{
return
_converse
.
xmppstatus
.
vcard
.
get
(
'
fullname
'
);
},
300
);
}).
then
(
function
()
{
.
then
(()
=>
test_utils
.
waitUntil
(()
=>
_converse
.
xmppstatus
.
vcard
.
get
(
'
fullname
'
)))
.
then
(()
=>
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
// Send a message from a different resource
spyOn
(
_converse
,
'
log
'
);
var
recipient_jid
=
mock
.
cur_names
[
5
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
recipient_jid
);
recipient_jid
=
mock
.
cur_names
[
5
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
return
test_utils
.
openChatBoxFor
(
_converse
,
recipient_jid
);
}).
then
(()
=>
{
var
msg
=
$msg
({
'
from
'
:
_converse
.
bare_jid
,
'
id
'
:
(
new
Date
()).
getTime
(),
...
...
@@ -979,38 +983,40 @@
it
(
"
is sent when the user a minimizes a chat box
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
test_utils
.
openControlBox
();
var
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
var
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
spyOn
(
_converse
.
connection
,
'
send
'
);
view
.
minimize
();
expect
(
view
.
model
.
get
(
'
chat_state
'
)).
toBe
(
'
inactive
'
);
expect
(
_converse
.
connection
.
send
).
toHaveBeenCalled
();
var
$stanza
=
$
(
_converse
.
connection
.
send
.
calls
.
argsFor
(
0
)[
0
].
tree
());
expect
(
$stanza
.
attr
(
'
to
'
)).
toBe
(
contact_jid
);
expect
(
$stanza
.
children
().
get
(
0
).
tagName
).
toBe
(
'
inactive
'
);
done
();
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
)
.
then
(()
=>
{
var
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
spyOn
(
_converse
.
connection
,
'
send
'
);
view
.
minimize
();
expect
(
view
.
model
.
get
(
'
chat_state
'
)).
toBe
(
'
inactive
'
);
expect
(
_converse
.
connection
.
send
).
toHaveBeenCalled
();
var
$stanza
=
$
(
_converse
.
connection
.
send
.
calls
.
argsFor
(
0
)[
0
].
tree
());
expect
(
$stanza
.
attr
(
'
to
'
)).
toBe
(
contact_jid
);
expect
(
$stanza
.
children
().
get
(
0
).
tagName
).
toBe
(
'
inactive
'
);
done
();
});
}));
it
(
"
is sent if the user closes a chat box
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
const
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openControlBox
();
test_utils
.
waitUntil
(
function
()
{
return
$
(
_converse
.
rosterview
.
el
).
find
(
'
.roster-group
'
).
length
;
},
300
).
then
(
function
()
{
var
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
var
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
test_utils
.
waitUntil
(()
=>
_converse
.
rosterview
.
el
.
querySelectorAll
(
'
.roster-group
'
).
length
)
.
then
(()
=>
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
))
.
then
((
view
)
=>
{
expect
(
view
.
model
.
get
(
'
chat_state
'
)).
toBe
(
'
active
'
);
spyOn
(
_converse
.
connection
,
'
send
'
);
view
.
close
();
...
...
@@ -1028,40 +1034,43 @@
it
(
"
will clear any other chat status notifications
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
test_utils
.
openControlBox
();
const
sender_jid
=
mock
.
cur_names
[
1
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
// See XEP-0085 http://xmpp.org/extensions/xep-0085.html#definitions
spyOn
(
_converse
,
'
emit
'
);
var
sender_jid
=
mock
.
cur_names
[
1
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
);
var
view
=
_converse
.
chatboxviews
.
get
(
sender_jid
);
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-event
'
).
length
).
toBe
(
0
);
// Insert <composing> message, to also check that
// text messages are inserted correctly with
// temporary chat events in the chat contents.
var
msg
=
$msg
({
'
to
'
:
_converse
.
bare_jid
,
'
xmlns
'
:
'
jabber:client
'
,
'
from
'
:
sender_jid
,
'
type
'
:
'
chat
'
})
.
c
(
'
composing
'
,
{
'
xmlns
'
:
Strophe
.
NS
.
CHATSTATES
}).
up
()
.
tree
();
_converse
.
chatboxes
.
onMessage
(
msg
);
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-state-notification
'
).
length
).
toBe
(
1
);
msg
=
$msg
({
from
:
sender_jid
,
to
:
_converse
.
connection
.
jid
,
type
:
'
chat
'
,
id
:
(
new
Date
()).
getTime
()
}).
c
(
'
body
'
).
c
(
'
inactive
'
,
{
'
xmlns
'
:
Strophe
.
NS
.
CHATSTATES
}).
tree
();
_converse
.
chatboxes
.
onMessage
(
msg
);
expect
(
_converse
.
emit
).
toHaveBeenCalledWith
(
'
message
'
,
jasmine
.
any
(
Object
));
expect
(
$
(
view
.
el
).
find
(
'
.chat-state-notification
'
).
length
).
toBe
(
0
);
done
();
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
)
.
then
(()
=>
{
var
view
=
_converse
.
chatboxviews
.
get
(
sender_jid
);
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-event
'
).
length
).
toBe
(
0
);
// Insert <composing> message, to also check that
// text messages are inserted correctly with
// temporary chat events in the chat contents.
var
msg
=
$msg
({
'
to
'
:
_converse
.
bare_jid
,
'
xmlns
'
:
'
jabber:client
'
,
'
from
'
:
sender_jid
,
'
type
'
:
'
chat
'
})
.
c
(
'
composing
'
,
{
'
xmlns
'
:
Strophe
.
NS
.
CHATSTATES
}).
up
()
.
tree
();
_converse
.
chatboxes
.
onMessage
(
msg
);
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-state-notification
'
).
length
).
toBe
(
1
);
msg
=
$msg
({
from
:
sender_jid
,
to
:
_converse
.
connection
.
jid
,
type
:
'
chat
'
,
id
:
(
new
Date
()).
getTime
()
}).
c
(
'
body
'
).
c
(
'
inactive
'
,
{
'
xmlns
'
:
Strophe
.
NS
.
CHATSTATES
}).
tree
();
_converse
.
chatboxes
.
onMessage
(
msg
);
expect
(
_converse
.
emit
).
toHaveBeenCalledWith
(
'
message
'
,
jasmine
.
any
(
Object
));
expect
(
$
(
view
.
el
).
find
(
'
.chat-state-notification
'
).
length
).
toBe
(
0
);
done
();
});
}));
});
...
...
@@ -1103,39 +1112,42 @@
it
(
"
'/clear' can be used to clear messages in a conversation
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
test_utils
.
openControlBox
();
const
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
spyOn
(
_converse
,
'
emit
'
);
var
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
var
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
var
message
=
'
This message is another sent from this chatbox
'
;
// Lets make sure there is at least one message already
// (e.g for when this test is run on its own).
test_utils
.
sendMessage
(
view
,
message
);
expect
(
view
.
model
.
messages
.
length
>
0
).
toBeTruthy
();
expect
(
view
.
model
.
messages
.
browserStorage
.
records
.
length
>
0
).
toBeTruthy
();
expect
(
_converse
.
emit
).
toHaveBeenCalledWith
(
'
messageSend
'
,
message
);
message
=
'
/clear
'
;
spyOn
(
view
,
'
onMessageSubmitted
'
).
and
.
callThrough
();
spyOn
(
view
,
'
clearMessages
'
).
and
.
callThrough
();
spyOn
(
window
,
'
confirm
'
).
and
.
callFake
(
function
()
{
return
true
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
)
.
then
(()
=>
{
var
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
var
message
=
'
This message is another sent from this chatbox
'
;
// Lets make sure there is at least one message already
// (e.g for when this test is run on its own).
test_utils
.
sendMessage
(
view
,
message
);
expect
(
view
.
model
.
messages
.
length
>
0
).
toBeTruthy
();
expect
(
view
.
model
.
messages
.
browserStorage
.
records
.
length
>
0
).
toBeTruthy
();
expect
(
_converse
.
emit
).
toHaveBeenCalledWith
(
'
messageSend
'
,
message
);
message
=
'
/clear
'
;
spyOn
(
view
,
'
onMessageSubmitted
'
).
and
.
callThrough
();
spyOn
(
view
,
'
clearMessages
'
).
and
.
callThrough
();
spyOn
(
window
,
'
confirm
'
).
and
.
callFake
(
function
()
{
return
true
;
});
test_utils
.
sendMessage
(
view
,
message
);
expect
(
view
.
onMessageSubmitted
).
toHaveBeenCalled
();
expect
(
view
.
clearMessages
).
toHaveBeenCalled
();
expect
(
window
.
confirm
).
toHaveBeenCalled
();
expect
(
view
.
model
.
messages
.
length
,
0
);
// The messages must be removed from the chatbox
expect
(
view
.
model
.
messages
.
browserStorage
.
records
.
length
,
0
);
// And also from browserStorage
expect
(
_converse
.
emit
.
calls
.
count
(),
1
);
expect
(
_converse
.
emit
.
calls
.
mostRecent
().
args
,
[
'
messageSend
'
,
message
]);
done
();
});
test_utils
.
sendMessage
(
view
,
message
);
expect
(
view
.
onMessageSubmitted
).
toHaveBeenCalled
();
expect
(
view
.
clearMessages
).
toHaveBeenCalled
();
expect
(
window
.
confirm
).
toHaveBeenCalled
();
expect
(
view
.
model
.
messages
.
length
,
0
);
// The messages must be removed from the chatbox
expect
(
view
.
model
.
messages
.
browserStorage
.
records
.
length
,
0
);
// And also from browserStorage
expect
(
_converse
.
emit
.
calls
.
count
(),
1
);
expect
(
_converse
.
emit
.
calls
.
mostRecent
().
args
,
[
'
messageSend
'
,
message
]);
done
();
}));
});
...
...
@@ -1267,133 +1279,133 @@
it
(
"
is incremented when the message is received and ChatBoxView is scrolled up
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
var
sender_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
,
msg
=
test_utils
.
createChatMessage
(
_converse
,
sender_jid
,
'
This message will be unread
'
);
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
);
var
chatbox
=
_converse
.
chatboxes
.
get
(
sender_jid
);
chatbox
.
save
(
'
scrolled
'
,
true
);
const
sender_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
,
msg
=
test_utils
.
createChatMessage
(
_converse
,
sender_jid
,
'
This message will be unread
'
);
_converse
.
chatboxes
.
onMessage
(
msg
);
expect
(
chatbox
.
get
(
'
num_unread
'
)).
toBe
(
1
);
done
();
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
)
.
then
((
view
)
=>
{
view
.
model
.
save
(
'
scrolled
'
,
true
);
_converse
.
chatboxes
.
onMessage
(
msg
);
expect
(
view
.
model
.
get
(
'
num_unread
'
)).
toBe
(
1
);
done
();
});
}));
it
(
"
is not incremented when the message is received and ChatBoxView is scrolled down
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
var
sender_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
,
msg
=
test_utils
.
createChatMessage
(
_converse
,
sender_jid
,
'
This message will be read
'
);
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
);
var
chatbox
=
_converse
.
chatboxes
.
get
(
sender_jid
);
const
sender_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
,
msg
=
test_utils
.
createChatMessage
(
_converse
,
sender_jid
,
'
This message will be read
'
);
_converse
.
chatboxes
.
onMessage
(
msg
);
expect
(
chatbox
.
get
(
'
num_unread
'
)).
toBe
(
0
);
done
();
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
)
.
then
(()
=>
{
var
chatbox
=
_converse
.
chatboxes
.
get
(
sender_jid
);
_converse
.
chatboxes
.
onMessage
(
msg
);
expect
(
chatbox
.
get
(
'
num_unread
'
)).
toBe
(
0
);
done
();
});
}));
it
(
"
is incremeted when message is received, chatbox is scrolled down and the window is not focused
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
function
(
done
,
_converse
)
{
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
var
sender_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
var
msgFactory
=
function
()
{
return
test_utils
.
createChatMessage
(
_converse
,
sender_jid
,
'
This message will be unread
'
);
};
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
);
var
chatbox
=
_converse
.
chatboxes
.
get
(
sender_jid
);
_converse
.
windowState
=
'
hidden
'
;
_converse
.
chatboxes
.
onMessage
(
msgFactory
());
expect
(
chatbox
.
get
(
'
num_unread
'
)).
toBe
(
1
);
done
();
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
)
.
then
(()
=>
{
var
chatbox
=
_converse
.
chatboxes
.
get
(
sender_jid
);
_converse
.
windowState
=
'
hidden
'
;
_converse
.
chatboxes
.
onMessage
(
msgFactory
());
expect
(
chatbox
.
get
(
'
num_unread
'
)).
toBe
(
1
);
done
();
});
}));
it
(
"
is incremeted when message is received, chatbox is scrolled up and the window is not focused
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroup
sFetched
'
],
{},
function
(
done
,
_converse
)
{
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxe
sFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
var
sender_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
var
msgFactory
=
function
()
{
return
test_utils
.
createChatMessage
(
_converse
,
sender_jid
,
'
This message will be unread
'
);
};
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
);
var
chatbox
=
_converse
.
chatboxes
.
get
(
sender_jid
);
chatbox
.
save
(
'
scrolled
'
,
true
);
_converse
.
windowState
=
'
hidden
'
;
_converse
.
chatboxes
.
onMessage
(
msgFactory
());
expect
(
chatbox
.
get
(
'
num_unread
'
)).
toBe
(
1
);
done
();
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
)
.
then
(()
=>
{
var
chatbox
=
_converse
.
chatboxes
.
get
(
sender_jid
);
chatbox
.
save
(
'
scrolled
'
,
true
);
_converse
.
windowState
=
'
hidden
'
;
_converse
.
chatboxes
.
onMessage
(
msgFactory
());
expect
(
chatbox
.
get
(
'
num_unread
'
)).
toBe
(
1
);
done
();
});
}));
it
(
"
is cleared when ChatBoxView was scrolled down and the window become focused
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroup
sFetched
'
],
{},
function
(
done
,
_converse
)
{
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxe
sFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
var
sender_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
const
sender_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
var
msgFactory
=
function
()
{
return
test_utils
.
createChatMessage
(
_converse
,
sender_jid
,
'
This message will be unread
'
);
};
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
);
var
chatbox
=
_converse
.
chatboxes
.
get
(
sender_jid
);
_converse
.
windowState
=
'
hidden
'
;
_converse
.
chatboxes
.
onMessage
(
msgFactory
());
expect
(
chatbox
.
get
(
'
num_unread
'
)).
toBe
(
1
);
_converse
.
saveWindowState
(
null
,
'
focus
'
);
expect
(
chatbox
.
get
(
'
num_unread
'
)).
toBe
(
0
);
done
();
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
)
.
then
(()
=>
{
const
chatbox
=
_converse
.
chatboxes
.
get
(
sender_jid
);
_converse
.
windowState
=
'
hidden
'
;
_converse
.
chatboxes
.
onMessage
(
msgFactory
());
expect
(
chatbox
.
get
(
'
num_unread
'
)).
toBe
(
1
);
_converse
.
saveWindowState
(
null
,
'
focus
'
);
expect
(
chatbox
.
get
(
'
num_unread
'
)).
toBe
(
0
);
done
();
});
}));
it
(
"
is not cleared when ChatBoxView was scrolled up and the windows become focused
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroup
sFetched
'
],
{},
function
(
done
,
_converse
)
{
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxe
sFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
var
sender_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
var
msgFactory
=
function
()
{
return
test_utils
.
createChatMessage
(
_converse
,
sender_jid
,
'
This message will be unread
'
);
};
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
);
var
chatbox
=
_converse
.
chatboxes
.
get
(
sender_jid
);
chatbox
.
save
(
'
scrolled
'
,
true
);
_converse
.
windowState
=
'
hidden
'
;
_converse
.
chatboxes
.
onMessage
(
msgFactory
());
expect
(
chatbox
.
get
(
'
num_unread
'
)).
toBe
(
1
);
_converse
.
saveWindowState
(
null
,
'
focus
'
);
expect
(
chatbox
.
get
(
'
num_unread
'
)).
toBe
(
1
);
done
();
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
)
.
then
(()
=>
{
var
chatbox
=
_converse
.
chatboxes
.
get
(
sender_jid
);
chatbox
.
save
(
'
scrolled
'
,
true
);
_converse
.
windowState
=
'
hidden
'
;
_converse
.
chatboxes
.
onMessage
(
msgFactory
());
expect
(
chatbox
.
get
(
'
num_unread
'
)).
toBe
(
1
);
_converse
.
saveWindowState
(
null
,
'
focus
'
);
expect
(
chatbox
.
get
(
'
num_unread
'
)).
toBe
(
1
);
done
();
});
}));
});
...
...
@@ -1401,16 +1413,16 @@
it
(
"
is updated when message is received and chatbox is scrolled up
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
test_utils
.
waitUntil
(
function
()
{
return
$
(
_converse
.
rosterview
.
el
).
find
(
'
.roster-group
'
).
length
;
},
500
)
.
then
(
function
()
{
var
sender_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
const
sender_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
waitUntil
(()
=>
_converse
.
rosterview
.
el
.
querySelectorAll
(
'
.roster-group
'
).
length
,
500
)
.
then
(()
=>
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
))
.
then
(()
=>
{
var
chatbox
=
_converse
.
chatboxes
.
get
(
sender_jid
);
chatbox
.
save
(
'
scrolled
'
,
true
);
...
...
@@ -1433,16 +1445,16 @@
it
(
"
is updated when message is received and chatbox is minimized
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
test_utils
.
waitUntil
(
function
()
{
return
$
(
_converse
.
rosterview
.
el
).
find
(
'
.roster-group
'
).
length
;
},
500
)
.
then
(
function
()
{
var
sender_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
const
sender_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
waitUntil
(()
=>
_converse
.
rosterview
.
el
.
querySelectorAll
(
'
.roster-group
'
).
length
,
500
)
.
then
(()
=>
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
))
.
then
(()
=>
{
var
chatbox
=
_converse
.
chatboxes
.
get
(
sender_jid
);
var
chatboxview
=
_converse
.
chatboxviews
.
get
(
sender_jid
);
chatboxview
.
minimize
();
...
...
@@ -1466,16 +1478,16 @@
it
(
"
is cleared when chatbox is maximzied after receiving messages in minimized mode
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
test_utils
.
waitUntil
(
function
()
{
return
$
(
_converse
.
rosterview
.
el
).
find
(
'
.roster-group
'
).
length
;
},
500
)
.
then
(
function
()
{
var
sender_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
const
sender_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
waitUntil
(()
=>
_converse
.
rosterview
.
el
.
querySelectorAll
(
'
.roster-group
'
).
length
,
500
)
.
then
(()
=>
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
))
.
then
(()
=>
{
var
chatbox
=
_converse
.
chatboxes
.
get
(
sender_jid
);
var
chatboxview
=
_converse
.
chatboxviews
.
get
(
sender_jid
);
var
msgsIndicatorSelector
=
'
a.open-chat:contains("
'
+
chatbox
.
get
(
'
fullname
'
)
+
'
") .msgs-indicator
'
;
...
...
@@ -1483,7 +1495,6 @@
var
msgFactory
=
function
()
{
return
test_utils
.
createChatMessage
(
_converse
,
sender_jid
,
'
This message will be received as unread, but eventually will be read
'
);
};
chatboxview
.
minimize
();
_converse
.
chatboxes
.
onMessage
(
msgFactory
());
...
...
@@ -1500,16 +1511,16 @@
it
(
"
is cleared when unread messages are viewed which were received in scrolled-up chatbox
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
test_utils
.
waitUntil
(
function
()
{
return
$
(
_converse
.
rosterview
.
el
).
find
(
'
.roster-group
'
).
length
;
},
500
)
.
then
(
function
()
{
var
sender_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
const
sender_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
waitUntil
(()
=>
_converse
.
rosterview
.
el
.
querySelectorAll
(
'
.roster-group
'
).
length
,
500
)
.
then
(()
=>
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
))
.
then
(()
=>
{
var
chatbox
=
_converse
.
chatboxes
.
get
(
sender_jid
);
var
chatboxview
=
_converse
.
chatboxviews
.
get
(
sender_jid
);
var
msgFactory
=
function
()
{
...
...
@@ -1532,16 +1543,16 @@
it
(
"
is not cleared after user clicks on roster view when chatbox is already opened and scrolled up
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
test_utils
.
waitUntil
(
function
()
{
return
$
(
_converse
.
rosterview
.
el
).
find
(
'
.roster-group
'
).
length
;
},
500
)
.
then
(
function
()
{
var
sender_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
const
sender_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
waitUntil
(()
=>
_converse
.
rosterview
.
el
.
querySelectorAll
(
'
.roster-group
'
).
length
,
500
)
.
then
(()
=>
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
))
.
then
(()
=>
{
var
chatbox
=
_converse
.
chatboxes
.
get
(
sender_jid
);
var
chatboxview
=
_converse
.
chatboxviews
.
get
(
sender_jid
);
var
msgFactory
=
function
()
{
...
...
@@ -1565,89 +1576,100 @@
describe
(
"
A Minimized ChatBoxView's Unread Message Count
"
,
function
()
{
it
(
"
is displayed when scrolled up chatbox is minimized after receiving unread messages
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroup
sFetched
'
],
{},
function
(
done
,
_converse
)
{
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxe
sFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
const
sender_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
var
sender_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
);
var
msgFactory
=
function
()
{
return
test_utils
.
createChatMessage
(
_converse
,
sender_jid
,
'
This message will be received as unread, but eventually will be read
'
);
};
var
selectUnreadMsgCount
=
function
()
{
var
minimizedChatBoxView
=
_converse
.
minimized_chats
.
get
(
sender_jid
);
return
$
(
minimizedChatBoxView
.
el
).
find
(
'
.message-count
'
);
};
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
)
.
then
(()
=>
{
const
msgFactory
=
function
()
{
return
test_utils
.
createChatMessage
(
_converse
,
sender_jid
,
'
This message will be received as unread, but eventually will be read
'
);
};
const
selectUnreadMsgCount
=
function
()
{
const
minimizedChatBoxView
=
_converse
.
minimized_chats
.
get
(
sender_jid
);
return
$
(
minimizedChatBoxView
.
el
).
find
(
'
.message-count
'
);
};
var
chatbox
=
_converse
.
chatboxes
.
get
(
sender_jid
);
chatbox
.
save
(
'
scrolled
'
,
true
);
_converse
.
chatboxes
.
onMessage
(
msgFactory
());
const
chatbox
=
_converse
.
chatboxes
.
get
(
sender_jid
);
chatbox
.
save
(
'
scrolled
'
,
true
);
_converse
.
chatboxes
.
onMessage
(
msgFactory
());
var
chatboxview
=
_converse
.
chatboxviews
.
get
(
sender_jid
);
chatboxview
.
minimize
();
const
chatboxview
=
_converse
.
chatboxviews
.
get
(
sender_jid
);
chatboxview
.
minimize
();
var
$unreadMsgCount
=
selectUnreadMsgCount
();
expect
(
u
.
isVisible
(
$unreadMsgCount
[
0
])).
toBeTruthy
();
expect
(
$unreadMsgCount
.
html
()).
toBe
(
'
1
'
);
done
();
const
$unreadMsgCount
=
selectUnreadMsgCount
();
expect
(
u
.
isVisible
(
$unreadMsgCount
[
0
])).
toBeTruthy
();
expect
(
$unreadMsgCount
.
html
()).
toBe
(
'
1
'
);
done
();
});
}));
it
(
"
is incremented when message is received and windows is not focused
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroup
sFetched
'
],
{},
function
(
done
,
_converse
)
{
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxe
sFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
const
sender_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
var
sender_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
);
var
msgFactory
=
function
()
{
return
test_utils
.
createChatMessage
(
_converse
,
sender_jid
,
'
This message will be received as unread, but eventually will be read
'
);
};
var
selectUnreadMsgCount
=
function
()
{
var
minimizedChatBoxView
=
_converse
.
minimized_chats
.
get
(
sender_jid
);
return
$
(
minimizedChatBoxView
.
el
).
find
(
'
.message-count
'
);
};
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
)
.
then
(()
=>
{
const
msgFactory
=
function
()
{
return
test_utils
.
createChatMessage
(
_converse
,
sender_jid
,
'
This message will be received as unread, but eventually will be read
'
);
};
const
selectUnreadMsgCount
=
function
()
{
const
minimizedChatBoxView
=
_converse
.
minimized_chats
.
get
(
sender_jid
);
return
$
(
minimizedChatBoxView
.
el
).
find
(
'
.message-count
'
);
};
var
chatboxview
=
_converse
.
chatboxviews
.
get
(
sender_jid
);
chatboxview
.
minimize
();
const
chatboxview
=
_converse
.
chatboxviews
.
get
(
sender_jid
);
chatboxview
.
minimize
();
_converse
.
chatboxes
.
onMessage
(
msgFactory
());
_converse
.
chatboxes
.
onMessage
(
msgFactory
());
var
$unreadMsgCount
=
selectUnreadMsgCount
();
expect
(
u
.
isVisible
(
$unreadMsgCount
[
0
])).
toBeTruthy
();
expect
(
$unreadMsgCount
.
html
()).
toBe
(
'
1
'
);
done
();
const
$unreadMsgCount
=
selectUnreadMsgCount
();
expect
(
u
.
isVisible
(
$unreadMsgCount
[
0
])).
toBeTruthy
();
expect
(
$unreadMsgCount
.
html
()).
toBe
(
'
1
'
);
done
();
});
}));
it
(
"
will render Openstreetmap-URL from geo-URI
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroup
sFetched
'
],
{},
function
(
done
,
_converse
)
{
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxe
sFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
var
base_url
=
document
.
URL
.
split
(
window
.
location
.
pathname
)[
0
];
var
message
=
"
geo:37.786971,-122.399677
"
;
var
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
var
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
let
view
;
const
base_url
=
document
.
URL
.
split
(
window
.
location
.
pathname
)[
0
],
message
=
"
geo:37.786971,-122.399677
"
,
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
)
.
then
(()
=>
{
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
spyOn
(
view
.
model
,
'
sendMessage
'
).
and
.
callThrough
();
test_utils
.
sendMessage
(
view
,
message
);
test_utils
.
waitUntil
(
function
()
{
return
$
(
view
.
el
).
find
(
'
.chat-content
'
).
find
(
'
.chat-msg
'
).
length
;
},
1000
).
then
(
function
()
{
expect
(
view
.
model
.
sendMessage
).
toHaveBeenCalled
();
var
msg
=
$
(
view
.
el
).
find
(
'
.chat-content
'
).
find
(
'
.chat-msg
'
).
last
().
find
(
'
.chat-msg__text
'
);
expect
(
msg
.
html
()).
toEqual
(
'
<a target="_blank" rel="noopener" href="https://www.openstreetmap.org/?mlat=37.786971&
'
+
'
mlon=-122.399677#map=18/37.786971/-122.399677">https://www.openstreetmap.org/?mlat=37.7869
'
+
'
71&mlon=-122.399677#map=18/37.786971/-122.399677</a>
'
);
done
();
});
}));
return
test_utils
.
waitUntil
(()
=>
view
.
el
.
querySelectorAll
(
'
.chat-content .chat-msg
'
).
length
,
1000
);
}).
then
(()
=>
{
expect
(
view
.
model
.
sendMessage
).
toHaveBeenCalled
();
var
msg
=
$
(
view
.
el
).
find
(
'
.chat-content
'
).
find
(
'
.chat-msg
'
).
last
().
find
(
'
.chat-msg__text
'
);
expect
(
msg
.
html
()).
toEqual
(
'
<a target="_blank" rel="noopener" href="https://www.openstreetmap.org/?mlat=37.786971&
'
+
'
mlon=-122.399677#map=18/37.786971/-122.399677">https://www.openstreetmap.org/?mlat=37.7869
'
+
'
71&mlon=-122.399677#map=18/37.786971/-122.399677</a>
'
);
done
();
});
}));
});
});
}));
spec/chatroom.js
View file @
506aa331
This source diff could not be displayed because it is too large. You can
view the blob
instead.
spec/http-file-upload.js
View file @
506aa331
...
...
@@ -225,25 +225,28 @@
[{
'
category
'
:
'
server
'
,
'
type
'
:
'
IM
'
}],
[
'
http://jabber.org/protocol/disco#items
'
],
[],
'
info
'
).
then
(
function
()
{
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
_converse
.
domain
,
[],
[],
[
'
upload.localhost
'
],
'
items
'
).
then
(
function
()
{
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
'
upload.localhost
'
,
[],
[
Strophe
.
NS
.
HTTPUPLOAD
],
[]).
then
(
function
()
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
var
contact_jid
=
mock
.
cur_names
[
2
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
var
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
test_utils
.
waitUntil
(
function
()
{
return
view
.
el
.
querySelector
(
'
.upload-file
'
);
},
150
).
then
(
function
()
{
expect
(
view
.
el
.
querySelector
(
'
.chat-toolbar .upload-file
'
)).
not
.
toBe
(
null
);
done
();
});
});
let
contact_jid
,
view
;
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
_converse
.
domain
,
[],
[],
[
'
upload.localhost
'
],
'
items
'
)
.
then
(()
=>
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
'
upload.localhost
'
,
[],
[
Strophe
.
NS
.
HTTPUPLOAD
],
[]))
.
then
(()
=>
{
test_utils
.
createContacts
(
_converse
,
'
current
'
,
3
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
contact_jid
=
mock
.
cur_names
[
2
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
return
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
}).
then
(()
=>
{
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
test_utils
.
waitUntil
(()
=>
view
.
el
.
querySelector
(
'
.upload-file
'
));
}).
then
(()
=>
{
expect
(
view
.
el
.
querySelector
(
'
.chat-toolbar .upload-file
'
)).
not
.
toBe
(
null
);
done
();
});
});
}));
it
(
"
appears in MUC chats
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
waitUntilDiscoConfirmed
(
...
...
@@ -251,19 +254,15 @@
[{
'
category
'
:
'
server
'
,
'
type
'
:
'
IM
'
}],
[
'
http://jabber.org/protocol/disco#items
'
],
[],
'
info
'
).
then
(
function
()
{
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
_converse
.
domain
,
[],
[],
[
'
upload.localhost
'
],
'
items
'
).
then
(
function
()
{
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
'
upload.localhost
'
,
[],
[
Strophe
.
NS
.
HTTPUPLOAD
],
[]).
then
(
function
()
{
test_utils
.
openAndEnterChatRoom
(
_converse
,
'
lounge
'
,
'
localhost
'
,
'
dummy
'
).
then
(
function
()
{
var
view
=
_converse
.
chatboxviews
.
get
(
'
lounge@localhost
'
);
test_utils
.
waitUntil
(
function
()
{
return
view
.
el
.
querySelector
(
'
.upload-file
'
);
}).
then
(
function
()
{
expect
(
view
.
el
.
querySelector
(
'
.chat-toolbar .upload-file
'
)).
not
.
toBe
(
null
);
done
();
});
});
});
});
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
_converse
.
domain
,
[],
[],
[
'
upload.localhost
'
],
'
items
'
)
.
then
(()
=>
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
'
upload.localhost
'
,
[],
[
Strophe
.
NS
.
HTTPUPLOAD
],
[]))
.
then
(()
=>
test_utils
.
openAndEnterChatRoom
(
_converse
,
'
lounge
'
,
'
localhost
'
,
'
dummy
'
))
.
then
(()
=>
test_utils
.
waitUntil
(()
=>
_converse
.
chatboxviews
.
get
(
'
lounge@localhost
'
).
el
.
querySelector
(
'
.upload-file
'
)))
.
then
(()
=>
{
const
view
=
_converse
.
chatboxviews
.
get
(
'
lounge@localhost
'
);
expect
(
view
.
el
.
querySelector
(
'
.chat-toolbar .upload-file
'
)).
not
.
toBe
(
null
);
done
();
}).
catch
(
_
.
partial
(
_converse
.
log
,
_
,
Strophe
.
LogLevel
.
FATAL
));
});
}));
...
...
@@ -277,101 +276,104 @@
var
send_backup
=
XMLHttpRequest
.
prototype
.
send
;
var
IQ_stanzas
=
_converse
.
connection
.
IQ_stanzas
;
let
contact_jid
;
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
_converse
.
domain
,
[],
[],
[
'
upload.montague.tld
'
],
'
items
'
).
then
(
function
()
{
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
'
upload.montague.tld
'
,
[],
[
Strophe
.
NS
.
HTTPUPLOAD
],
[]).
then
(
function
()
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
var
contact_jid
=
mock
.
cur_names
[
2
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
var
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
var
file
=
{
'
type
'
:
'
image/jpeg
'
,
'
size
'
:
'
23456
'
,
'
lastModifiedDate
'
:
""
,
'
name
'
:
"
my-juliet.jpg
"
};
view
.
model
.
sendFiles
([
file
]);
return
test_utils
.
waitUntil
(
function
()
{
return
_
.
filter
(
IQ_stanzas
,
function
(
iq
)
{
return
iq
.
nodeTree
.
querySelector
(
'
iq[to="upload.montague.tld"] request
'
);
}).
length
>
0
;
}).
then
(
function
()
{
var
iq
=
IQ_stanzas
.
pop
();
expect
(
iq
.
toLocaleString
()).
toBe
(
"
<iq from='dummy@localhost/resource'
"
+
"
to='upload.montague.tld'
"
+
"
type='get'
"
+
"
xmlns='jabber:client'
"
+
"
id='
"
+
iq
.
nodeTree
.
getAttribute
(
'
id
'
)
+
"
'>
"
+
"
<request xmlns='urn:xmpp:http:upload:0'
"
+
"
filename='my-juliet.jpg'
"
+
"
size='23456'
"
+
"
content-type='image/jpeg'/>
"
+
"
</iq>
"
);
var
base_url
=
document
.
URL
.
split
(
window
.
location
.
pathname
)[
0
];
var
message
=
base_url
+
"
/logo/conversejs-filled.svg
"
;
var
stanza
=
Strophe
.
xmlHtmlNode
(
"
<iq from='upload.montague.tld'
"
+
"
id='
"
+
iq
.
nodeTree
.
getAttribute
(
'
id
'
)
+
"
'
"
+
"
to='dummy@localhost/resource'
"
+
"
type='result'>
"
+
"
<slot xmlns='urn:xmpp:http:upload:0'>
"
+
"
<put url='https://upload.montague.tld/4a771ac1-f0b2-4a4a-9700-f2a26fa2bb67/my-juliet.jpg'>
"
+
"
<header name='Authorization'>Basic Base64String==</header>
"
+
"
<header name='Cookie'>foo=bar; user=romeo</header>
"
+
"
</put>
"
+
"
<get url='
"
+
message
+
"
' />
"
+
"
</slot>
"
+
"
</iq>
"
).
firstElementChild
;
spyOn
(
XMLHttpRequest
.
prototype
,
'
send
'
).
and
.
callFake
(
function
()
{
const
message
=
view
.
model
.
messages
.
at
(
0
);
expect
(
view
.
el
.
querySelector
(
'
.chat-content progress
'
).
getAttribute
(
'
value
'
)).
toBe
(
'
0
'
);
message
.
set
(
'
progress
'
,
0.5
);
expect
(
view
.
el
.
querySelector
(
'
.chat-content progress
'
).
getAttribute
(
'
value
'
)).
toBe
(
'
0.5
'
);
message
.
set
(
'
progress
'
,
1
);
expect
(
view
.
el
.
querySelector
(
'
.chat-content progress
'
).
getAttribute
(
'
value
'
)).
toBe
(
'
1
'
);
message
.
save
({
'
upload
'
:
_converse
.
SUCCESS
,
'
oob_url
'
:
message
.
get
(
'
get
'
),
'
message
'
:
message
.
get
(
'
get
'
)
});
});
var
sent_stanza
;
spyOn
(
_converse
.
connection
,
'
send
'
).
and
.
callFake
(
function
(
stanza
)
{
sent_stanza
=
stanza
;
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
_converse
.
domain
,
[],
[],
[
'
upload.montague.tld
'
],
'
items
'
)
.
then
(()
=>
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
'
upload.montague.tld
'
,
[],
[
Strophe
.
NS
.
HTTPUPLOAD
],
[]))
.
then
(()
=>
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
contact_jid
=
mock
.
cur_names
[
2
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
return
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
}).
then
(()
=>
{
var
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
var
file
=
{
'
type
'
:
'
image/jpeg
'
,
'
size
'
:
'
23456
'
,
'
lastModifiedDate
'
:
""
,
'
name
'
:
"
my-juliet.jpg
"
};
view
.
model
.
sendFiles
([
file
]);
return
test_utils
.
waitUntil
(
function
()
{
return
_
.
filter
(
IQ_stanzas
,
function
(
iq
)
{
return
iq
.
nodeTree
.
querySelector
(
'
iq[to="upload.montague.tld"] request
'
);
}).
length
>
0
;
}).
then
(
function
()
{
var
iq
=
IQ_stanzas
.
pop
();
expect
(
iq
.
toLocaleString
()).
toBe
(
"
<iq from='dummy@localhost/resource'
"
+
"
to='upload.montague.tld'
"
+
"
type='get'
"
+
"
xmlns='jabber:client'
"
+
"
id='
"
+
iq
.
nodeTree
.
getAttribute
(
'
id
'
)
+
"
'>
"
+
"
<request xmlns='urn:xmpp:http:upload:0'
"
+
"
filename='my-juliet.jpg'
"
+
"
size='23456'
"
+
"
content-type='image/jpeg'/>
"
+
"
</iq>
"
);
var
base_url
=
document
.
URL
.
split
(
window
.
location
.
pathname
)[
0
];
var
message
=
base_url
+
"
/logo/conversejs-filled.svg
"
;
var
stanza
=
Strophe
.
xmlHtmlNode
(
"
<iq from='upload.montague.tld'
"
+
"
id='
"
+
iq
.
nodeTree
.
getAttribute
(
'
id
'
)
+
"
'
"
+
"
to='dummy@localhost/resource'
"
+
"
type='result'>
"
+
"
<slot xmlns='urn:xmpp:http:upload:0'>
"
+
"
<put url='https://upload.montague.tld/4a771ac1-f0b2-4a4a-9700-f2a26fa2bb67/my-juliet.jpg'>
"
+
"
<header name='Authorization'>Basic Base64String==</header>
"
+
"
<header name='Cookie'>foo=bar; user=romeo</header>
"
+
"
</put>
"
+
"
<get url='
"
+
message
+
"
' />
"
+
"
</slot>
"
+
"
</iq>
"
).
firstElementChild
;
spyOn
(
XMLHttpRequest
.
prototype
,
'
send
'
).
and
.
callFake
(
function
()
{
const
message
=
view
.
model
.
messages
.
at
(
0
);
expect
(
view
.
el
.
querySelector
(
'
.chat-content progress
'
).
getAttribute
(
'
value
'
)).
toBe
(
'
0
'
);
message
.
set
(
'
progress
'
,
0.5
);
expect
(
view
.
el
.
querySelector
(
'
.chat-content progress
'
).
getAttribute
(
'
value
'
)).
toBe
(
'
0.5
'
);
message
.
set
(
'
progress
'
,
1
);
expect
(
view
.
el
.
querySelector
(
'
.chat-content progress
'
).
getAttribute
(
'
value
'
)).
toBe
(
'
1
'
);
message
.
save
({
'
upload
'
:
_converse
.
SUCCESS
,
'
oob_url
'
:
message
.
get
(
'
get
'
),
'
message
'
:
message
.
get
(
'
get
'
)
});
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
});
var
sent_stanza
;
spyOn
(
_converse
.
connection
,
'
send
'
).
and
.
callFake
(
function
(
stanza
)
{
sent_stanza
=
stanza
;
});
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
return
test_utils
.
waitUntil
(
function
()
{
return
sent_stanza
;
},
1000
).
then
(
function
()
{
expect
(
sent_stanza
.
toLocaleString
()).
toBe
(
"
<message from='dummy@localhost/resource'
"
+
"
to='irini.vlastuin@localhost'
"
+
"
type='chat'
"
+
"
id='
"
+
sent_stanza
.
nodeTree
.
getAttribute
(
'
id
'
)
+
"
' xmlns='jabber:client'>
"
+
"
<body>
"
+
message
+
"
</body>
"
+
"
<active xmlns='http://jabber.org/protocol/chatstates'/>
"
+
"
<x xmlns='jabber:x:oob'>
"
+
"
<url>
"
+
message
+
"
</url>
"
+
"
</x>
"
+
"
</message>
"
);
return
test_utils
.
waitUntil
(
function
()
{
return
sent_stanza
;
},
1000
).
then
(
function
()
{
expect
(
sent_stanza
.
toLocaleString
()).
toBe
(
"
<message from='dummy@localhost/resource'
"
+
"
to='irini.vlastuin@localhost'
"
+
"
type='chat'
"
+
"
id='
"
+
sent_stanza
.
nodeTree
.
getAttribute
(
'
id
'
)
+
"
' xmlns='jabber:client'>
"
+
"
<body>
"
+
message
+
"
</body>
"
+
"
<active xmlns='http://jabber.org/protocol/chatstates'/>
"
+
"
<x xmlns='jabber:x:oob'>
"
+
"
<url>
"
+
message
+
"
</url>
"
+
"
</x>
"
+
"
</message>
"
);
return
test_utils
.
waitUntil
(
function
()
{
return
view
.
el
.
querySelector
(
'
.chat-image
'
);
},
1000
);
}).
then
(
function
()
{
// Check that the image renders
expect
(
view
.
el
.
querySelector
(
'
.chat-msg .chat-msg__media
'
).
innerHTML
.
trim
()).
toEqual
(
`<!-- src/templates/image.html -->\n`
+
`<a href="
${
window
.
location
.
origin
}
/logo/conversejs-filled.svg" target="_blank" rel="noopener">`
+
`<img class="chat-image img-thumbnail" src="
${
window
.
location
.
origin
}
/logo/conversejs-filled.svg">`
+
`</a>`
);
XMLHttpRequest
.
prototype
.
send
=
send_backup
;
done
();
});
return
view
.
el
.
querySelector
(
'
.chat-image
'
);
},
1000
);
}).
then
(
function
()
{
// Check that the image renders
expect
(
view
.
el
.
querySelector
(
'
.chat-msg .chat-msg__media
'
).
innerHTML
.
trim
()).
toEqual
(
`<!-- src/templates/image.html -->\n`
+
`<a href="
${
window
.
location
.
origin
}
/logo/conversejs-filled.svg" target="_blank" rel="noopener">`
+
`<img class="chat-image img-thumbnail" src="
${
window
.
location
.
origin
}
/logo/conversejs-filled.svg">`
+
`</a>`
);
XMLHttpRequest
.
prototype
.
send
=
send_backup
;
done
();
});
});
});
...
...
@@ -487,56 +489,53 @@
});
}));
it
(
"
shows and error message if the file is too large
"
,
mock
.
initConverseWithAsync
(
function
(
done
,
_converse
)
{
var
IQ_stanzas
=
_converse
.
connection
.
IQ_stanzas
;
var
IQ_ids
=
_converse
.
connection
.
IQ_ids
;
var
send_backup
=
XMLHttpRequest
.
prototype
.
send
;
it
(
"
shows an error message if the file is too large
"
,
mock
.
initConverseWithAsync
(
function
(
done
,
_converse
)
{
const
IQ_stanzas
=
_converse
.
connection
.
IQ_stanzas
;
const
IQ_ids
=
_converse
.
connection
.
IQ_ids
;
const
send_backup
=
XMLHttpRequest
.
prototype
.
send
;
let
view
,
contact_jid
;
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
_converse
.
bare_jid
,
[],
[])
.
then
(()
=>
test_utils
.
waitUntil
(()
=>
_
.
filter
(
IQ_stanzas
,
(
iq
)
=>
iq
.
nodeTree
.
querySelector
(
'
iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#info"]
'
)).
length
)).
then
(()
=>
{
var
stanza
=
_
.
find
(
IQ_stanzas
,
function
(
iq
)
{
return
iq
.
nodeTree
.
querySelector
(
'
iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#info"]
'
);
});
var
info_IQ_id
=
IQ_ids
[
IQ_stanzas
.
indexOf
(
stanza
)];
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
_converse
.
bare_jid
,
[],
[]).
then
(
function
()
{
test_utils
.
waitUntil
(
function
()
{
stanza
=
$iq
({
'
type
'
:
'
result
'
,
'
from
'
:
'
localhost
'
,
'
to
'
:
'
dummy@localhost/resource
'
,
'
id
'
:
info_IQ_id
}).
c
(
'
query
'
,
{
'
xmlns
'
:
'
http://jabber.org/protocol/disco#info
'
})
.
c
(
'
identity
'
,
{
'
category
'
:
'
server
'
,
'
type
'
:
'
im
'
}).
up
()
.
c
(
'
feature
'
,
{
'
var
'
:
'
http://jabber.org/protocol/disco#info
'
}).
up
()
.
c
(
'
feature
'
,
{
'
var
'
:
'
http://jabber.org/protocol/disco#items
'
});
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
return
_converse
.
api
.
disco
.
entities
.
get
();
}).
then
(
function
(
entities
)
{
expect
(
entities
.
length
).
toBe
(
2
);
expect
(
_
.
includes
(
entities
.
pluck
(
'
jid
'
),
'
localhost
'
)).
toBe
(
true
);
expect
(
_
.
includes
(
entities
.
pluck
(
'
jid
'
),
'
dummy@localhost
'
)).
toBe
(
true
);
expect
(
entities
.
get
(
_converse
.
domain
).
features
.
length
).
toBe
(
2
);
expect
(
entities
.
get
(
_converse
.
domain
).
identities
.
length
).
toBe
(
1
);
return
test_utils
.
waitUntil
(
function
()
{
// Converse.js sees that the entity has a disco#items feature,
// so it will make a query for it.
return
_
.
filter
(
IQ_stanzas
,
function
(
iq
)
{
return
iq
.
nodeTree
.
querySelector
(
'
iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#info"]
'
);
return
iq
.
nodeTree
.
querySelector
(
'
iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#items"]
'
);
}).
length
>
0
;
},
300
).
then
(
function
()
{
var
stanza
=
_
.
find
(
IQ_stanzas
,
function
(
iq
)
{
return
iq
.
nodeTree
.
querySelector
(
'
iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#info"]
'
);
});
var
info_IQ_id
=
IQ_ids
[
IQ_stanzas
.
indexOf
(
stanza
)];
stanza
=
$iq
({
'
type
'
:
'
result
'
,
'
from
'
:
'
localhost
'
,
'
to
'
:
'
dummy@localhost/resource
'
,
'
id
'
:
info_IQ_id
}).
c
(
'
query
'
,
{
'
xmlns
'
:
'
http://jabber.org/protocol/disco#info
'
})
.
c
(
'
identity
'
,
{
'
category
'
:
'
server
'
,
'
type
'
:
'
im
'
}).
up
()
.
c
(
'
feature
'
,
{
'
var
'
:
'
http://jabber.org/protocol/disco#info
'
}).
up
()
.
c
(
'
feature
'
,
{
'
var
'
:
'
http://jabber.org/protocol/disco#items
'
});
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
_converse
.
api
.
disco
.
entities
.
get
().
then
(
function
(
entities
)
{
expect
(
entities
.
length
).
toBe
(
2
);
expect
(
_
.
includes
(
entities
.
pluck
(
'
jid
'
),
'
localhost
'
)).
toBe
(
true
);
expect
(
_
.
includes
(
entities
.
pluck
(
'
jid
'
),
'
dummy@localhost
'
)).
toBe
(
true
);
expect
(
entities
.
get
(
_converse
.
domain
).
features
.
length
).
toBe
(
2
);
expect
(
entities
.
get
(
_converse
.
domain
).
identities
.
length
).
toBe
(
1
);
return
test_utils
.
waitUntil
(
function
()
{
// Converse.js sees that the entity has a disco#items feature,
// so it will make a query for it.
return
_
.
filter
(
IQ_stanzas
,
function
(
iq
)
{
return
iq
.
nodeTree
.
querySelector
(
'
iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#items"]
'
);
}).
length
>
0
;
},
300
);
});
}).
then
(
function
()
{
},
300
);
}).
then
(
function
()
{
var
stanza
=
_
.
find
(
IQ_stanzas
,
function
(
iq
)
{
return
iq
.
nodeTree
.
querySelector
(
'
iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#items"]
'
);
});
...
...
@@ -550,77 +549,77 @@
.
c
(
'
item
'
,
{
'
jid
'
:
'
upload.localhost
'
,
'
name
'
:
'
HTTP File Upload
'
});
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
_converse
.
api
.
disco
.
entities
.
get
().
then
(
function
(
entities
)
{
expect
(
entities
.
length
).
toBe
(
2
);
expect
(
entities
.
get
(
'
localhost
'
).
items
.
length
).
toBe
(
1
);
return
test_utils
.
waitUntil
(
function
()
{
// Converse.js sees that the entity has a disco#info feature,
// so it will make a query for it.
return
_
.
filter
(
IQ_stanzas
,
function
(
iq
)
{
return
iq
.
nodeTree
.
querySelector
(
'
iq[to="upload.localhost"] query[xmlns="http://jabber.org/protocol/disco#info"]
'
);
}).
length
>
0
;
},
300
);
});
}).
then
(
function
()
{
var
stanza
=
_
.
find
(
IQ_stanzas
,
function
(
iq
)
{
return
iq
.
nodeTree
.
querySelector
(
'
iq[to="upload.localhost"] query[xmlns="http://jabber.org/protocol/disco#info"]
'
);
});
var
IQ_id
=
IQ_ids
[
IQ_stanzas
.
indexOf
(
stanza
)];
expect
(
stanza
.
toLocaleString
()).
toBe
(
"
<iq from='dummy@localhost/resource' to='upload.localhost' type='get' xmlns='jabber:client' id='
"
+
IQ_id
+
"
'>
"
+
"
<query xmlns='http://jabber.org/protocol/disco#info'/>
"
+
"
</iq>
"
);
// Upload service responds and reports a maximum file size of 5MiB
stanza
=
$iq
({
'
type
'
:
'
result
'
,
'
to
'
:
'
dummy@localhost/resource
'
,
'
id
'
:
IQ_id
,
'
from
'
:
'
upload.localhost
'
})
.
c
(
'
query
'
,
{
'
xmlns
'
:
'
http://jabber.org/protocol/disco#info
'
})
.
c
(
'
identity
'
,
{
'
category
'
:
'
store
'
,
'
type
'
:
'
file
'
,
'
name
'
:
'
HTTP File Upload
'
}).
up
()
.
c
(
'
feature
'
,
{
'
var
'
:
'
urn:xmpp:http:upload:0
'
}).
up
()
.
c
(
'
x
'
,
{
'
type
'
:
'
result
'
,
'
xmlns
'
:
'
jabber:x:data
'
})
.
c
(
'
field
'
,
{
'
var
'
:
'
FORM_TYPE
'
,
'
type
'
:
'
hidden
'
})
.
c
(
'
value
'
).
t
(
'
urn:xmpp:http:upload:0
'
).
up
().
up
()
.
c
(
'
field
'
,
{
'
var
'
:
'
max-file-size
'
})
.
c
(
'
value
'
).
t
(
'
5242880
'
);
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
_converse
.
api
.
disco
.
entities
.
get
().
then
(
function
(
entities
)
{
expect
(
entities
.
get
(
'
localhost
'
).
items
.
get
(
'
upload.localhost
'
).
identities
.
where
({
'
category
'
:
'
store
'
}).
length
).
toBe
(
1
);
_converse
.
api
.
disco
.
supports
(
Strophe
.
NS
.
HTTPUPLOAD
,
_converse
.
domain
).
then
(
function
(
result
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
var
contact_jid
=
mock
.
cur_names
[
2
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
var
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
var
file
=
{
'
type
'
:
'
image/jpeg
'
,
'
size
'
:
'
5242881
'
,
'
lastModifiedDate
'
:
""
,
'
name
'
:
"
my-juliet.jpg
"
};
view
.
model
.
sendFiles
([
file
]);
return
test_utils
.
waitUntil
(
function
()
{
return
view
.
el
.
querySelectorAll
(
'
.message
'
).
length
;
}).
then
(
function
()
{
const
messages
=
view
.
el
.
querySelectorAll
(
'
.message.chat-error
'
);
expect
(
messages
.
length
).
toBe
(
1
);
expect
(
messages
[
0
].
textContent
).
toBe
(
'
The size of your file, my-juliet.jpg, exceeds the maximum allowed by your server, which is 5 MB.
'
);
done
();
});
}
);
}).
catch
(
_
.
partial
(
_converse
.
log
,
_
,
Strophe
.
LogLevel
.
FATAL
));
})
});
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
_converse
.
api
.
disco
.
entities
.
get
().
then
(
function
(
entities
)
{
expect
(
entities
.
length
).
toBe
(
2
);
expect
(
entities
.
get
(
'
localhost
'
).
items
.
length
).
toBe
(
1
);
return
test_utils
.
waitUntil
(
function
()
{
// Converse.js sees that the entity has a disco#info feature,
// so it will make a query for it.
return
_
.
filter
(
IQ_stanzas
,
function
(
iq
)
{
return
iq
.
nodeTree
.
querySelector
(
'
iq[to="upload.localhost"] query[xmlns="http://jabber.org/protocol/disco#info"]
'
);
}).
length
>
0
;
},
300
);
});
}).
then
(
function
()
{
var
stanza
=
_
.
find
(
IQ_stanzas
,
function
(
iq
)
{
return
iq
.
nodeTree
.
querySelector
(
'
iq[to="upload.localhost"] query[xmlns="http://jabber.org/protocol/disco#info"]
'
);
});
var
IQ_id
=
IQ_ids
[
IQ_stanzas
.
indexOf
(
stanza
)];
expect
(
stanza
.
toLocaleString
()).
toBe
(
"
<iq from='dummy@localhost/resource' to='upload.localhost' type='get' xmlns='jabber:client' id='
"
+
IQ_id
+
"
'>
"
+
"
<query xmlns='http://jabber.org/protocol/disco#info'/>
"
+
"
</iq>
"
);
// Upload service responds and reports a maximum file size of 5MiB
stanza
=
$iq
({
'
type
'
:
'
result
'
,
'
to
'
:
'
dummy@localhost/resource
'
,
'
id
'
:
IQ_id
,
'
from
'
:
'
upload.localhost
'
})
.
c
(
'
query
'
,
{
'
xmlns
'
:
'
http://jabber.org/protocol/disco#info
'
})
.
c
(
'
identity
'
,
{
'
category
'
:
'
store
'
,
'
type
'
:
'
file
'
,
'
name
'
:
'
HTTP File Upload
'
}).
up
()
.
c
(
'
feature
'
,
{
'
var
'
:
'
urn:xmpp:http:upload:0
'
}).
up
()
.
c
(
'
x
'
,
{
'
type
'
:
'
result
'
,
'
xmlns
'
:
'
jabber:x:data
'
})
.
c
(
'
field
'
,
{
'
var
'
:
'
FORM_TYPE
'
,
'
type
'
:
'
hidden
'
})
.
c
(
'
value
'
).
t
(
'
urn:xmpp:http:upload:0
'
).
up
().
up
()
.
c
(
'
field
'
,
{
'
var
'
:
'
max-file-size
'
})
.
c
(
'
value
'
).
t
(
'
5242880
'
);
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
return
_converse
.
api
.
disco
.
entities
.
get
();
}).
then
(
function
(
entities
)
{
expect
(
entities
.
get
(
'
localhost
'
).
items
.
get
(
'
upload.localhost
'
).
identities
.
where
({
'
category
'
:
'
store
'
}).
length
).
toBe
(
1
);
return
_converse
.
api
.
disco
.
supports
(
Strophe
.
NS
.
HTTPUPLOAD
,
_converse
.
domain
);
}).
then
(
function
(
result
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
contact_jid
=
mock
.
cur_names
[
2
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
return
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
}).
then
(()
=>
{
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
var
file
=
{
'
type
'
:
'
image/jpeg
'
,
'
size
'
:
'
5242881
'
,
'
lastModifiedDate
'
:
""
,
'
name
'
:
"
my-juliet.jpg
"
};
view
.
model
.
sendFiles
([
file
]);
return
test_utils
.
waitUntil
(()
=>
view
.
el
.
querySelectorAll
(
'
.message
'
).
length
)
}).
then
(
function
()
{
const
messages
=
view
.
el
.
querySelectorAll
(
'
.message.chat-error
'
);
expect
(
messages
.
length
).
toBe
(
1
);
expect
(
messages
[
0
].
textContent
).
toBe
(
'
The size of your file, my-juliet.jpg, exceeds the maximum allowed by your server, which is 5 MB.
'
);
done
();
}).
catch
(
_
.
partial
(
_converse
.
log
,
_
,
Strophe
.
LogLevel
.
FATAL
))
}));
});
});
describe
(
"
While a file is being uploaded
"
,
function
()
{
it
(
"
shows a progress bar
"
,
mock
.
initConverseWithAsync
(
function
(
done
,
_converse
)
{
it
(
"
shows a progress bar
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
_converse
.
domain
,
[{
'
category
'
:
'
server
'
,
'
type
'
:
'
IM
'
}],
...
...
@@ -628,77 +627,74 @@
var
send_backup
=
XMLHttpRequest
.
prototype
.
send
;
var
IQ_stanzas
=
_converse
.
connection
.
IQ_stanzas
;
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
_converse
.
domain
,
[],
[],
[
'
upload.montague.tld
'
],
'
items
'
).
then
(
function
()
{
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
'
upload.montague.tld
'
,
[],
[
Strophe
.
NS
.
HTTPUPLOAD
],
[]).
then
(
function
()
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
var
contact_jid
=
mock
.
cur_names
[
2
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
var
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
var
file
=
{
'
type
'
:
'
image/jpeg
'
,
'
size
'
:
'
23456
'
,
'
lastModifiedDate
'
:
""
,
'
name
'
:
"
my-juliet.jpg
"
};
view
.
model
.
sendFiles
([
file
]);
return
test_utils
.
waitUntil
(
function
()
{
return
_
.
filter
(
IQ_stanzas
,
function
(
iq
)
{
return
iq
.
nodeTree
.
querySelector
(
'
iq[to="upload.montague.tld"] request
'
);
}).
length
>
0
;
}).
then
(
function
()
{
var
iq
=
IQ_stanzas
.
pop
();
expect
(
iq
.
toLocaleString
()).
toBe
(
"
<iq from='dummy@localhost/resource'
"
+
"
to='upload.montague.tld'
"
+
"
type='get'
"
+
"
xmlns='jabber:client'
"
+
"
id='
"
+
iq
.
nodeTree
.
getAttribute
(
'
id
'
)
+
"
'>
"
+
"
<request xmlns='urn:xmpp:http:upload:0'
"
+
"
filename='my-juliet.jpg'
"
+
"
size='23456'
"
+
"
content-type='image/jpeg'/>
"
+
"
</iq>
"
);
var
base_url
=
document
.
URL
.
split
(
window
.
location
.
pathname
)[
0
];
var
message
=
base_url
+
"
/logo/conversejs-filled.svg
"
;
var
stanza
=
Strophe
.
xmlHtmlNode
(
"
<iq from='upload.montague.tld'
"
+
"
id='
"
+
iq
.
nodeTree
.
getAttribute
(
'
id
'
)
+
"
'
"
+
"
to='dummy@localhost/resource'
"
+
"
type='result'>
"
+
"
<slot xmlns='urn:xmpp:http:upload:0'>
"
+
"
<put url='https://upload.montague.tld/4a771ac1-f0b2-4a4a-9700-f2a26fa2bb67/my-juliet.jpg'>
"
+
"
<header name='Authorization'>Basic Base64String==</header>
"
+
"
<header name='Cookie'>foo=bar; user=romeo</header>
"
+
"
</put>
"
+
"
<get url='
"
+
message
+
"
' />
"
+
"
</slot>
"
+
"
</iq>
"
).
firstElementChild
;
spyOn
(
XMLHttpRequest
.
prototype
,
'
send
'
).
and
.
callFake
(
function
()
{
const
message
=
view
.
model
.
messages
.
at
(
0
);
expect
(
view
.
el
.
querySelector
(
'
.chat-content progress
'
).
getAttribute
(
'
value
'
)).
toBe
(
'
0
'
);
message
.
set
(
'
progress
'
,
0.5
);
expect
(
view
.
el
.
querySelector
(
'
.chat-content progress
'
).
getAttribute
(
'
value
'
)).
toBe
(
'
0.5
'
);
message
.
set
(
'
progress
'
,
1
);
expect
(
view
.
el
.
querySelector
(
'
.chat-content progress
'
).
getAttribute
(
'
value
'
)).
toBe
(
'
1
'
);
expect
(
view
.
el
.
querySelector
(
'
.chat-content .chat-msg__text
'
).
textContent
).
toBe
(
'
Uploading file: my-juliet.jpg, 22.91 KB
'
);
done
();
});
var
sent_stanza
;
spyOn
(
_converse
.
connection
,
'
send
'
).
and
.
callFake
(
function
(
stanza
)
{
sent_stanza
=
stanza
;
});
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
});
let
view
,
contact_jid
;
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
_converse
.
domain
,
[],
[],
[
'
upload.montague.tld
'
],
'
items
'
)
.
then
(()
=>
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
'
upload.montague.tld
'
,
[],
[
Strophe
.
NS
.
HTTPUPLOAD
],
[]))
.
then
(()
=>
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
contact_jid
=
mock
.
cur_names
[
2
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
return
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
}).
then
(()
=>
{
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
const
file
=
{
'
type
'
:
'
image/jpeg
'
,
'
size
'
:
'
23456
'
,
'
lastModifiedDate
'
:
""
,
'
name
'
:
"
my-juliet.jpg
"
};
view
.
model
.
sendFiles
([
file
]);
return
test_utils
.
waitUntil
(()
=>
_
.
filter
(
IQ_stanzas
,
(
iq
)
=>
iq
.
nodeTree
.
querySelector
(
'
iq[to="upload.montague.tld"] request
'
)).
length
)
}).
then
(
function
()
{
const
iq
=
IQ_stanzas
.
pop
();
expect
(
iq
.
toLocaleString
()).
toBe
(
"
<iq from='dummy@localhost/resource'
"
+
"
to='upload.montague.tld'
"
+
"
type='get'
"
+
"
xmlns='jabber:client'
"
+
"
id='
"
+
iq
.
nodeTree
.
getAttribute
(
'
id
'
)
+
"
'>
"
+
"
<request xmlns='urn:xmpp:http:upload:0'
"
+
"
filename='my-juliet.jpg'
"
+
"
size='23456'
"
+
"
content-type='image/jpeg'/>
"
+
"
</iq>
"
);
const
base_url
=
document
.
URL
.
split
(
window
.
location
.
pathname
)[
0
];
const
message
=
base_url
+
"
/logo/conversejs-filled.svg
"
;
const
stanza
=
Strophe
.
xmlHtmlNode
(
"
<iq from='upload.montague.tld'
"
+
"
id='
"
+
iq
.
nodeTree
.
getAttribute
(
'
id
'
)
+
"
'
"
+
"
to='dummy@localhost/resource'
"
+
"
type='result'>
"
+
"
<slot xmlns='urn:xmpp:http:upload:0'>
"
+
"
<put url='https://upload.montague.tld/4a771ac1-f0b2-4a4a-9700-f2a26fa2bb67/my-juliet.jpg'>
"
+
"
<header name='Authorization'>Basic Base64String==</header>
"
+
"
<header name='Cookie'>foo=bar; user=romeo</header>
"
+
"
</put>
"
+
"
<get url='
"
+
message
+
"
' />
"
+
"
</slot>
"
+
"
</iq>
"
).
firstElementChild
;
spyOn
(
XMLHttpRequest
.
prototype
,
'
send
'
).
and
.
callFake
(
function
()
{
const
message
=
view
.
model
.
messages
.
at
(
0
);
expect
(
view
.
el
.
querySelector
(
'
.chat-content progress
'
).
getAttribute
(
'
value
'
)).
toBe
(
'
0
'
);
message
.
set
(
'
progress
'
,
0.5
);
expect
(
view
.
el
.
querySelector
(
'
.chat-content progress
'
).
getAttribute
(
'
value
'
)).
toBe
(
'
0.5
'
);
message
.
set
(
'
progress
'
,
1
);
expect
(
view
.
el
.
querySelector
(
'
.chat-content progress
'
).
getAttribute
(
'
value
'
)).
toBe
(
'
1
'
);
expect
(
view
.
el
.
querySelector
(
'
.chat-content .chat-msg__text
'
).
textContent
).
toBe
(
'
Uploading file: my-juliet.jpg, 22.91 KB
'
);
done
();
});
var
sent_stanza
;
spyOn
(
_converse
.
connection
,
'
send
'
).
and
.
callFake
(
function
(
stanza
)
{
sent_stanza
=
stanza
;
});
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
});
});
}));
});
});
});
}));
spec/messages.js
View file @
506aa331
...
...
@@ -21,247 +21,251 @@
it
(
"
can be sent as a correction by clicking the pencil icon
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
,
1
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
test_utils
.
openControlBox
();
const
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
)
.
then
(()
=>
{
const
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
const
textarea
=
view
.
el
.
querySelector
(
'
textarea.chat-textarea
'
);
const
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
const
textarea
=
view
.
el
.
querySelector
(
'
textarea.chat-textarea
'
);
textarea
.
value
=
'
But soft, what light through yonder airlock breaks?
'
;
view
.
keyPressed
({
target
:
textarea
,
preventDefault
:
_
.
noop
,
keyCode
:
13
// Enter
});
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
expect
(
view
.
el
.
querySelector
(
'
.chat-msg__text
'
).
textContent
)
.
toBe
(
'
But soft, what light through yonder airlock breaks?
'
);
expect
(
textarea
.
value
).
toBe
(
''
);
textarea
.
value
=
'
But soft, what light through yonder airlock breaks?
'
;
view
.
keyPressed
({
target
:
textarea
,
preventDefault
:
_
.
noop
,
keyCode
:
13
// Enter
});
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
expect
(
view
.
el
.
querySelector
(
'
.chat-msg__text
'
).
textContent
)
.
toBe
(
'
But soft, what light through yonder airlock breaks?
'
);
expect
(
textarea
.
value
).
toBe
(
''
);
const
first_msg
=
view
.
model
.
messages
.
findWhere
({
'
message
'
:
'
But soft, what light through yonder airlock breaks?
'
});
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-msg .chat-msg__action
'
).
length
).
toBe
(
1
);
let
action
=
view
.
el
.
querySelector
(
'
.chat-msg .chat-msg__action
'
);
expect
(
action
.
getAttribute
(
'
title
'
)).
toBe
(
'
Edit this message
'
);
action
.
style
.
opacity
=
1
;
action
.
click
();
expect
(
textarea
.
value
).
toBe
(
'
But soft, what light through yonder airlock breaks?
'
);
expect
(
view
.
model
.
messages
.
at
(
0
).
get
(
'
correcting
'
)).
toBe
(
true
);
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
expect
(
u
.
hasClass
(
'
correcting
'
,
view
.
el
.
querySelector
(
'
.chat-msg
'
))).
toBe
(
true
);
spyOn
(
_converse
.
connection
,
'
send
'
);
textarea
.
value
=
'
But soft, what light through yonder window breaks?
'
;
view
.
keyPressed
({
target
:
textarea
,
preventDefault
:
_
.
noop
,
keyCode
:
13
// Enter
const
first_msg
=
view
.
model
.
messages
.
findWhere
({
'
message
'
:
'
But soft, what light through yonder airlock breaks?
'
});
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-msg .chat-msg__action
'
).
length
).
toBe
(
1
);
let
action
=
view
.
el
.
querySelector
(
'
.chat-msg .chat-msg__action
'
);
expect
(
action
.
getAttribute
(
'
title
'
)).
toBe
(
'
Edit this message
'
);
action
.
style
.
opacity
=
1
;
action
.
click
();
expect
(
textarea
.
value
).
toBe
(
'
But soft, what light through yonder airlock breaks?
'
);
expect
(
view
.
model
.
messages
.
at
(
0
).
get
(
'
correcting
'
)).
toBe
(
true
);
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
expect
(
u
.
hasClass
(
'
correcting
'
,
view
.
el
.
querySelector
(
'
.chat-msg
'
))).
toBe
(
true
);
spyOn
(
_converse
.
connection
,
'
send
'
);
textarea
.
value
=
'
But soft, what light through yonder window breaks?
'
;
view
.
keyPressed
({
target
:
textarea
,
preventDefault
:
_
.
noop
,
keyCode
:
13
// Enter
});
expect
(
_converse
.
connection
.
send
).
toHaveBeenCalled
();
const
msg
=
_converse
.
connection
.
send
.
calls
.
all
()[
0
].
args
[
0
];
expect
(
msg
.
toLocaleString
())
.
toBe
(
`<message from='dummy@localhost/resource' `
+
`to='max.frankfurter@localhost' type='chat' id='
${
msg
.
nodeTree
.
getAttribute
(
'
id
'
)}
' `
+
`xmlns='jabber:client'>`
+
`<body>But soft, what light through yonder window breaks?</body>`
+
`<active xmlns='http://jabber.org/protocol/chatstates'/>`
+
`<replace xmlns='urn:xmpp:message-correct:0' id='
${
first_msg
.
get
(
'
msgid
'
)}
'/>`
+
`</message>`
);
expect
(
view
.
model
.
messages
.
models
.
length
).
toBe
(
1
);
const
corrected_message
=
view
.
model
.
messages
.
at
(
0
);
expect
(
corrected_message
.
get
(
'
msgid
'
)).
toBe
(
first_msg
.
get
(
'
msgid
'
));
expect
(
corrected_message
.
get
(
'
correcting
'
)).
toBe
(
false
);
expect
(
corrected_message
.
get
(
'
older_versions
'
).
length
).
toBe
(
1
);
expect
(
corrected_message
.
get
(
'
older_versions
'
)[
0
]).
toBe
(
'
But soft, what light through yonder airlock breaks?
'
);
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
expect
(
u
.
hasClass
(
'
correcting
'
,
view
.
el
.
querySelector
(
'
.chat-msg
'
))).
toBe
(
false
);
// Test that clicking the pencil icon a second time cancels editing.
action
=
view
.
el
.
querySelector
(
'
.chat-msg .chat-msg__action
'
);
action
.
style
.
opacity
=
1
;
action
.
click
();
expect
(
textarea
.
value
).
toBe
(
'
But soft, what light through yonder window breaks?
'
);
expect
(
view
.
model
.
messages
.
at
(
0
).
get
(
'
correcting
'
)).
toBe
(
true
);
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
expect
(
u
.
hasClass
(
'
correcting
'
,
view
.
el
.
querySelector
(
'
.chat-msg
'
))).
toBe
(
true
);
action
=
view
.
el
.
querySelector
(
'
.chat-msg .chat-msg__action
'
);
action
.
style
.
opacity
=
1
;
action
.
click
();
expect
(
textarea
.
value
).
toBe
(
''
);
expect
(
view
.
model
.
messages
.
at
(
0
).
get
(
'
correcting
'
)).
toBe
(
false
);
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
expect
(
u
.
hasClass
(
'
correcting
'
,
view
.
el
.
querySelector
(
'
.chat-msg
'
))).
toBe
(
false
);
// Test that messages from other users don't have the pencil icon
_converse
.
chatboxes
.
onMessage
(
$msg
({
'
from
'
:
contact_jid
,
'
to
'
:
_converse
.
connection
.
jid
,
'
type
'
:
'
chat
'
,
'
id
'
:
(
new
Date
()).
getTime
()
}).
c
(
'
body
'
).
t
(
'
Hello
'
).
up
()
.
c
(
'
active
'
,
{
'
xmlns
'
:
'
http://jabber.org/protocol/chatstates
'
}).
tree
()
);
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-msg .chat-msg__action
'
).
length
).
toBe
(
1
);
done
();
});
expect
(
_converse
.
connection
.
send
).
toHaveBeenCalled
();
const
msg
=
_converse
.
connection
.
send
.
calls
.
all
()[
0
].
args
[
0
];
expect
(
msg
.
toLocaleString
())
.
toBe
(
`<message from='dummy@localhost/resource' `
+
`to='max.frankfurter@localhost' type='chat' id='
${
msg
.
nodeTree
.
getAttribute
(
'
id
'
)}
' `
+
`xmlns='jabber:client'>`
+
`<body>But soft, what light through yonder window breaks?</body>`
+
`<active xmlns='http://jabber.org/protocol/chatstates'/>`
+
`<replace xmlns='urn:xmpp:message-correct:0' id='
${
first_msg
.
get
(
'
msgid
'
)}
'/>`
+
`</message>`
);
expect
(
view
.
model
.
messages
.
models
.
length
).
toBe
(
1
);
const
corrected_message
=
view
.
model
.
messages
.
at
(
0
);
expect
(
corrected_message
.
get
(
'
msgid
'
)).
toBe
(
first_msg
.
get
(
'
msgid
'
));
expect
(
corrected_message
.
get
(
'
correcting
'
)).
toBe
(
false
);
expect
(
corrected_message
.
get
(
'
older_versions
'
).
length
).
toBe
(
1
);
expect
(
corrected_message
.
get
(
'
older_versions
'
)[
0
]).
toBe
(
'
But soft, what light through yonder airlock breaks?
'
);
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
expect
(
u
.
hasClass
(
'
correcting
'
,
view
.
el
.
querySelector
(
'
.chat-msg
'
))).
toBe
(
false
);
// Test that clicking the pencil icon a second time cancels editing.
action
=
view
.
el
.
querySelector
(
'
.chat-msg .chat-msg__action
'
);
action
.
style
.
opacity
=
1
;
action
.
click
();
expect
(
textarea
.
value
).
toBe
(
'
But soft, what light through yonder window breaks?
'
);
expect
(
view
.
model
.
messages
.
at
(
0
).
get
(
'
correcting
'
)).
toBe
(
true
);
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
expect
(
u
.
hasClass
(
'
correcting
'
,
view
.
el
.
querySelector
(
'
.chat-msg
'
))).
toBe
(
true
);
action
=
view
.
el
.
querySelector
(
'
.chat-msg .chat-msg__action
'
);
action
.
style
.
opacity
=
1
;
action
.
click
();
expect
(
textarea
.
value
).
toBe
(
''
);
expect
(
view
.
model
.
messages
.
at
(
0
).
get
(
'
correcting
'
)).
toBe
(
false
);
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
expect
(
u
.
hasClass
(
'
correcting
'
,
view
.
el
.
querySelector
(
'
.chat-msg
'
))).
toBe
(
false
);
// Test that messages from other users don't have the pencil icon
_converse
.
chatboxes
.
onMessage
(
$msg
({
'
from
'
:
contact_jid
,
'
to
'
:
_converse
.
connection
.
jid
,
'
type
'
:
'
chat
'
,
'
id
'
:
(
new
Date
()).
getTime
()
}).
c
(
'
body
'
).
t
(
'
Hello
'
).
up
()
.
c
(
'
active
'
,
{
'
xmlns
'
:
'
http://jabber.org/protocol/chatstates
'
}).
tree
()
);
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-msg .chat-msg__action
'
).
length
).
toBe
(
1
);
done
();
}));
it
(
"
can be sent as a correction by using the up arrow
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
,
1
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
test_utils
.
openControlBox
();
const
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
)
.
then
(()
=>
{
const
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
const
textarea
=
view
.
el
.
querySelector
(
'
textarea.chat-textarea
'
);
expect
(
textarea
.
value
).
toBe
(
''
);
view
.
keyPressed
({
target
:
textarea
,
keyCode
:
38
// Up arrow
});
expect
(
textarea
.
value
).
toBe
(
''
);
const
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
const
textarea
=
view
.
el
.
querySelector
(
'
textarea.chat-textarea
'
);
expect
(
textarea
.
value
).
toBe
(
''
);
view
.
keyPressed
({
target
:
textarea
,
keyCode
:
38
// Up arrow
});
expect
(
textarea
.
value
).
toBe
(
''
);
textarea
.
value
=
'
But soft, what light through yonder airlock breaks?
'
;
view
.
keyPressed
({
target
:
textarea
,
preventDefault
:
_
.
noop
,
keyCode
:
13
// Enter
});
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
expect
(
view
.
el
.
querySelector
(
'
.chat-msg__text
'
).
textContent
)
.
toBe
(
'
But soft, what light through yonder airlock breaks?
'
);
textarea
.
value
=
'
But soft, what light through yonder airlock breaks?
'
;
view
.
keyPressed
({
target
:
textarea
,
preventDefault
:
_
.
noop
,
keyCode
:
13
// Enter
});
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
expect
(
view
.
el
.
querySelector
(
'
.chat-msg__text
'
).
textContent
)
.
toBe
(
'
But soft, what light through yonder airlock breaks?
'
);
const
first_msg
=
view
.
model
.
messages
.
findWhere
({
'
message
'
:
'
But soft, what light through yonder airlock breaks?
'
});
expect
(
textarea
.
value
).
toBe
(
''
);
view
.
keyPressed
({
target
:
textarea
,
keyCode
:
38
// Up arrow
});
expect
(
textarea
.
value
).
toBe
(
'
But soft, what light through yonder airlock breaks?
'
);
expect
(
view
.
model
.
messages
.
at
(
0
).
get
(
'
correcting
'
)).
toBe
(
true
);
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
expect
(
u
.
hasClass
(
'
correcting
'
,
view
.
el
.
querySelector
(
'
.chat-msg
'
))).
toBe
(
true
);
spyOn
(
_converse
.
connection
,
'
send
'
);
textarea
.
value
=
'
But soft, what light through yonder window breaks?
'
;
view
.
keyPressed
({
target
:
textarea
,
preventDefault
:
_
.
noop
,
keyCode
:
13
// Enter
});
expect
(
_converse
.
connection
.
send
).
toHaveBeenCalled
();
const
msg
=
_converse
.
connection
.
send
.
calls
.
all
()[
0
].
args
[
0
];
expect
(
msg
.
toLocaleString
())
.
toBe
(
`<message from='dummy@localhost/resource' `
+
`to='max.frankfurter@localhost' type='chat' id='
${
msg
.
nodeTree
.
getAttribute
(
'
id
'
)}
' `
+
`xmlns='jabber:client'>`
+
`<body>But soft, what light through yonder window breaks?</body>`
+
`<active xmlns='http://jabber.org/protocol/chatstates'/>`
+
`<replace xmlns='urn:xmpp:message-correct:0' id='
${
first_msg
.
get
(
'
msgid
'
)}
'/>`
+
`</message>`
);
expect
(
view
.
model
.
messages
.
models
.
length
).
toBe
(
1
);
const
corrected_message
=
view
.
model
.
messages
.
at
(
0
);
expect
(
corrected_message
.
get
(
'
msgid
'
)).
toBe
(
first_msg
.
get
(
'
msgid
'
));
expect
(
corrected_message
.
get
(
'
correcting
'
)).
toBe
(
false
);
expect
(
corrected_message
.
get
(
'
older_versions
'
).
length
).
toBe
(
1
);
expect
(
corrected_message
.
get
(
'
older_versions
'
)[
0
]).
toBe
(
'
But soft, what light through yonder airlock breaks?
'
);
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
expect
(
u
.
hasClass
(
'
correcting
'
,
view
.
el
.
querySelector
(
'
.chat-msg
'
))).
toBe
(
false
);
// Test that pressing the down arrow cancels message correction
expect
(
textarea
.
value
).
toBe
(
''
);
view
.
keyPressed
({
target
:
textarea
,
keyCode
:
38
// Up arrow
});
expect
(
textarea
.
value
).
toBe
(
'
But soft, what light through yonder window breaks?
'
);
expect
(
view
.
model
.
messages
.
at
(
0
).
get
(
'
correcting
'
)).
toBe
(
true
);
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
expect
(
u
.
hasClass
(
'
correcting
'
,
view
.
el
.
querySelector
(
'
.chat-msg
'
))).
toBe
(
true
);
expect
(
textarea
.
value
).
toBe
(
'
But soft, what light through yonder window breaks?
'
);
view
.
keyPressed
({
target
:
textarea
,
keyCode
:
40
// Down arrow
});
expect
(
textarea
.
value
).
toBe
(
''
);
expect
(
view
.
model
.
messages
.
at
(
0
).
get
(
'
correcting
'
)).
toBe
(
false
);
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
expect
(
u
.
hasClass
(
'
correcting
'
,
view
.
el
.
querySelector
(
'
.chat-msg
'
))).
toBe
(
false
);
textarea
.
value
=
'
It is the east, and Juliet is the one.
'
;
view
.
keyPressed
({
target
:
textarea
,
preventDefault
:
_
.
noop
,
keyCode
:
13
// Enter
});
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
2
);
const
first_msg
=
view
.
model
.
messages
.
findWhere
({
'
message
'
:
'
But soft, what light through yonder airlock breaks?
'
});
expect
(
textarea
.
value
).
toBe
(
''
);
view
.
keyPressed
({
target
:
textarea
,
keyCode
:
38
// Up arrow
});
expect
(
textarea
.
value
).
toBe
(
'
But soft, what light through yonder airlock breaks?
'
);
expect
(
view
.
model
.
messages
.
at
(
0
).
get
(
'
correcting
'
)).
toBe
(
true
);
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
expect
(
u
.
hasClass
(
'
correcting
'
,
view
.
el
.
querySelector
(
'
.chat-msg
'
))).
toBe
(
true
);
textarea
.
value
=
'
Arise, fair sun, and kill the envious moon
'
;
view
.
keyPressed
({
target
:
textarea
,
preventDefault
:
_
.
noop
,
keyCode
:
13
// Enter
});
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
3
);
spyOn
(
_converse
.
connection
,
'
send
'
);
textarea
.
value
=
'
But soft, what light through yonder window breaks?
'
;
view
.
keyPressed
({
target
:
textarea
,
preventDefault
:
_
.
noop
,
keyCode
:
13
// Enter
});
expect
(
_converse
.
connection
.
send
).
toHaveBeenCalled
();
view
.
keyPressed
({
target
:
textarea
,
keyCode
:
38
// Up arrow
});
expect
(
textarea
.
value
).
toBe
(
'
Arise, fair sun, and kill the envious moon
'
);
expect
(
view
.
model
.
messages
.
at
(
0
).
get
(
'
correcting
'
)).
toBeFalsy
();
expect
(
view
.
model
.
messages
.
at
(
1
).
get
(
'
correcting
'
)).
toBeFalsy
();
expect
(
view
.
model
.
messages
.
at
(
2
).
get
(
'
correcting
'
)).
toBe
(
true
);
textarea
.
selectionEnd
=
0
;
// Happens by pressing up,
// but for some reason not in tests, so we set it manually.
view
.
keyPressed
({
target
:
textarea
,
keyCode
:
38
// Up arrow
});
expect
(
textarea
.
value
).
toBe
(
'
It is the east, and Juliet is the one.
'
);
expect
(
view
.
model
.
messages
.
at
(
0
).
get
(
'
correcting
'
)).
toBeFalsy
();
expect
(
view
.
model
.
messages
.
at
(
1
).
get
(
'
correcting
'
)).
toBe
(
true
);
expect
(
view
.
model
.
messages
.
at
(
2
).
get
(
'
correcting
'
)).
toBeFalsy
();
textarea
.
value
=
'
It is the east, and Juliet is the sun.
'
;
view
.
keyPressed
({
target
:
textarea
,
preventDefault
:
_
.
noop
,
keyCode
:
13
// Enter
const
msg
=
_converse
.
connection
.
send
.
calls
.
all
()[
0
].
args
[
0
];
expect
(
msg
.
toLocaleString
())
.
toBe
(
`<message from='dummy@localhost/resource' `
+
`to='max.frankfurter@localhost' type='chat' id='
${
msg
.
nodeTree
.
getAttribute
(
'
id
'
)}
' `
+
`xmlns='jabber:client'>`
+
`<body>But soft, what light through yonder window breaks?</body>`
+
`<active xmlns='http://jabber.org/protocol/chatstates'/>`
+
`<replace xmlns='urn:xmpp:message-correct:0' id='
${
first_msg
.
get
(
'
msgid
'
)}
'/>`
+
`</message>`
);
expect
(
view
.
model
.
messages
.
models
.
length
).
toBe
(
1
);
const
corrected_message
=
view
.
model
.
messages
.
at
(
0
);
expect
(
corrected_message
.
get
(
'
msgid
'
)).
toBe
(
first_msg
.
get
(
'
msgid
'
));
expect
(
corrected_message
.
get
(
'
correcting
'
)).
toBe
(
false
);
expect
(
corrected_message
.
get
(
'
older_versions
'
).
length
).
toBe
(
1
);
expect
(
corrected_message
.
get
(
'
older_versions
'
)[
0
]).
toBe
(
'
But soft, what light through yonder airlock breaks?
'
);
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
expect
(
u
.
hasClass
(
'
correcting
'
,
view
.
el
.
querySelector
(
'
.chat-msg
'
))).
toBe
(
false
);
// Test that pressing the down arrow cancels message correction
expect
(
textarea
.
value
).
toBe
(
''
);
view
.
keyPressed
({
target
:
textarea
,
keyCode
:
38
// Up arrow
});
expect
(
textarea
.
value
).
toBe
(
'
But soft, what light through yonder window breaks?
'
);
expect
(
view
.
model
.
messages
.
at
(
0
).
get
(
'
correcting
'
)).
toBe
(
true
);
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
expect
(
u
.
hasClass
(
'
correcting
'
,
view
.
el
.
querySelector
(
'
.chat-msg
'
))).
toBe
(
true
);
expect
(
textarea
.
value
).
toBe
(
'
But soft, what light through yonder window breaks?
'
);
view
.
keyPressed
({
target
:
textarea
,
keyCode
:
40
// Down arrow
});
expect
(
textarea
.
value
).
toBe
(
''
);
expect
(
view
.
model
.
messages
.
at
(
0
).
get
(
'
correcting
'
)).
toBe
(
false
);
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
expect
(
u
.
hasClass
(
'
correcting
'
,
view
.
el
.
querySelector
(
'
.chat-msg
'
))).
toBe
(
false
);
textarea
.
value
=
'
It is the east, and Juliet is the one.
'
;
view
.
keyPressed
({
target
:
textarea
,
preventDefault
:
_
.
noop
,
keyCode
:
13
// Enter
});
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
2
);
textarea
.
value
=
'
Arise, fair sun, and kill the envious moon
'
;
view
.
keyPressed
({
target
:
textarea
,
preventDefault
:
_
.
noop
,
keyCode
:
13
// Enter
});
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
3
);
view
.
keyPressed
({
target
:
textarea
,
keyCode
:
38
// Up arrow
});
expect
(
textarea
.
value
).
toBe
(
'
Arise, fair sun, and kill the envious moon
'
);
expect
(
view
.
model
.
messages
.
at
(
0
).
get
(
'
correcting
'
)).
toBeFalsy
();
expect
(
view
.
model
.
messages
.
at
(
1
).
get
(
'
correcting
'
)).
toBeFalsy
();
expect
(
view
.
model
.
messages
.
at
(
2
).
get
(
'
correcting
'
)).
toBe
(
true
);
textarea
.
selectionEnd
=
0
;
// Happens by pressing up,
// but for some reason not in tests, so we set it manually.
view
.
keyPressed
({
target
:
textarea
,
keyCode
:
38
// Up arrow
});
expect
(
textarea
.
value
).
toBe
(
'
It is the east, and Juliet is the one.
'
);
expect
(
view
.
model
.
messages
.
at
(
0
).
get
(
'
correcting
'
)).
toBeFalsy
();
expect
(
view
.
model
.
messages
.
at
(
1
).
get
(
'
correcting
'
)).
toBe
(
true
);
expect
(
view
.
model
.
messages
.
at
(
2
).
get
(
'
correcting
'
)).
toBeFalsy
();
textarea
.
value
=
'
It is the east, and Juliet is the sun.
'
;
view
.
keyPressed
({
target
:
textarea
,
preventDefault
:
_
.
noop
,
keyCode
:
13
// Enter
});
expect
(
textarea
.
value
).
toBe
(
''
);
const
messages
=
view
.
el
.
querySelectorAll
(
'
.chat-msg
'
);
expect
(
messages
.
length
).
toBe
(
3
);
expect
(
messages
[
0
].
querySelector
(
'
.chat-msg__text
'
).
textContent
)
.
toBe
(
'
But soft, what light through yonder window breaks?
'
);
expect
(
messages
[
1
].
querySelector
(
'
.chat-msg__text
'
).
textContent
)
.
toBe
(
'
It is the east, and Juliet is the sun.
'
);
expect
(
messages
[
2
].
querySelector
(
'
.chat-msg__text
'
).
textContent
)
.
toBe
(
'
Arise, fair sun, and kill the envious moon
'
);
expect
(
view
.
model
.
messages
.
at
(
0
).
get
(
'
correcting
'
)).
toBeFalsy
();
expect
(
view
.
model
.
messages
.
at
(
1
).
get
(
'
correcting
'
)).
toBeFalsy
();
expect
(
view
.
model
.
messages
.
at
(
2
).
get
(
'
correcting
'
)).
toBeFalsy
();
done
();
});
expect
(
textarea
.
value
).
toBe
(
''
);
const
messages
=
view
.
el
.
querySelectorAll
(
'
.chat-msg
'
);
expect
(
messages
.
length
).
toBe
(
3
);
expect
(
messages
[
0
].
querySelector
(
'
.chat-msg__text
'
).
textContent
)
.
toBe
(
'
But soft, what light through yonder window breaks?
'
);
expect
(
messages
[
1
].
querySelector
(
'
.chat-msg__text
'
).
textContent
)
.
toBe
(
'
It is the east, and Juliet is the sun.
'
);
expect
(
messages
[
2
].
querySelector
(
'
.chat-msg__text
'
).
textContent
)
.
toBe
(
'
Arise, fair sun, and kill the envious moon
'
);
expect
(
view
.
model
.
messages
.
at
(
0
).
get
(
'
correcting
'
)).
toBeFalsy
();
expect
(
view
.
model
.
messages
.
at
(
1
).
get
(
'
correcting
'
)).
toBeFalsy
();
expect
(
view
.
model
.
messages
.
at
(
2
).
get
(
'
correcting
'
)).
toBeFalsy
();
done
();
}));
...
...
@@ -321,65 +325,67 @@
it
(
"
can be replaced with a correction
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
,
1
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
test_utils
.
openControlBox
();
const
message
=
'
This is a received message
'
;
const
sender_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
);
const
msg_id
=
u
.
getUniqueId
();
_converse
.
chatboxes
.
onMessage
(
$msg
({
'
from
'
:
sender_jid
,
'
to
'
:
_converse
.
connection
.
jid
,
'
type
'
:
'
chat
'
,
'
id
'
:
msg_id
,
}).
c
(
'
body
'
).
t
(
'
But soft, what light through yonder airlock breaks?
'
).
tree
());
var
chatboxview
=
_converse
.
chatboxviews
.
get
(
sender_jid
);
expect
(
chatboxview
.
el
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
expect
(
chatboxview
.
el
.
querySelector
(
'
.chat-msg__text
'
).
textContent
)
.
toBe
(
'
But soft, what light through yonder airlock breaks?
'
);
_converse
.
chatboxes
.
onMessage
(
$msg
({
'
from
'
:
sender_jid
,
'
to
'
:
_converse
.
connection
.
jid
,
'
type
'
:
'
chat
'
,
'
id
'
:
u
.
getUniqueId
(),
}).
c
(
'
body
'
).
t
(
'
But soft, what light through yonder chimney breaks?
'
).
up
()
.
c
(
'
replace
'
,
{
'
id
'
:
msg_id
,
'
xmlns
'
:
'
urn:xmpp:message-correct:0
'
}).
tree
());
test_utils
.
waitUntil
(()
=>
chatboxview
.
el
.
querySelector
(
'
.chat-msg__text
'
).
textContent
===
'
But soft, what light through yonder chimney breaks?
'
).
then
(()
=>
{
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
)
.
then
(()
=>
{
const
msg_id
=
u
.
getUniqueId
();
_converse
.
chatboxes
.
onMessage
(
$msg
({
'
from
'
:
sender_jid
,
'
to
'
:
_converse
.
connection
.
jid
,
'
type
'
:
'
chat
'
,
'
id
'
:
msg_id
,
}).
c
(
'
body
'
).
t
(
'
But soft, what light through yonder airlock breaks?
'
).
tree
());
var
chatboxview
=
_converse
.
chatboxviews
.
get
(
sender_jid
);
expect
(
chatboxview
.
el
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
expect
(
chatboxview
.
el
.
querySelectorAll
(
'
.chat-msg__content .fa-edit
'
).
length
).
toBe
(
1
);
expect
(
chatboxview
.
el
.
querySelector
(
'
.chat-msg__text
'
).
textContent
)
.
toBe
(
'
But soft, what light through yonder airlock breaks?
'
);
_converse
.
chatboxes
.
onMessage
(
$msg
({
'
from
'
:
sender_jid
,
'
to
'
:
_converse
.
connection
.
jid
,
'
type
'
:
'
chat
'
,
'
id
'
:
u
.
getUniqueId
(),
}).
c
(
'
body
'
).
t
(
'
But soft, what light through yonder
window
breaks?
'
).
up
()
}).
c
(
'
body
'
).
t
(
'
But soft, what light through yonder
chimney
breaks?
'
).
up
()
.
c
(
'
replace
'
,
{
'
id
'
:
msg_id
,
'
xmlns
'
:
'
urn:xmpp:message-correct:0
'
}).
tree
());
return
test_utils
.
waitUntil
(()
=>
chatboxview
.
el
.
querySelector
(
'
.chat-msg__text
'
).
textContent
===
'
But soft, what light through yonder window breaks?
'
);
}).
then
(()
=>
{
expect
(
chatboxview
.
el
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
expect
(
chatboxview
.
el
.
querySelectorAll
(
'
.chat-msg__content .fa-edit
'
).
length
).
toBe
(
1
);
chatboxview
.
el
.
querySelector
(
'
.chat-msg__content .fa-edit
'
).
click
();
const
modal
=
chatboxview
.
model
.
messages
.
at
(
0
).
message_versions_modal
;
return
test_utils
.
waitUntil
(()
=>
u
.
isVisible
(
modal
.
el
),
1000
);
}).
then
(()
=>
{
const
modal
=
chatboxview
.
model
.
messages
.
at
(
0
).
message_versions_modal
;
const
older_msgs
=
modal
.
el
.
querySelectorAll
(
'
.older-msg
'
);
expect
(
older_msgs
.
length
).
toBe
(
2
);
expect
(
older_msgs
[
0
].
textContent
).
toBe
(
'
But soft, what light through yonder airlock breaks?
'
);
expect
(
older_msgs
[
1
].
textContent
).
toBe
(
'
But soft, what light through yonder chimney breaks?
'
);
done
();
test_utils
.
waitUntil
(()
=>
chatboxview
.
el
.
querySelector
(
'
.chat-msg__text
'
).
textContent
===
'
But soft, what light through yonder chimney breaks?
'
).
then
(()
=>
{
expect
(
chatboxview
.
el
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
expect
(
chatboxview
.
el
.
querySelectorAll
(
'
.chat-msg__content .fa-edit
'
).
length
).
toBe
(
1
);
_converse
.
chatboxes
.
onMessage
(
$msg
({
'
from
'
:
sender_jid
,
'
to
'
:
_converse
.
connection
.
jid
,
'
type
'
:
'
chat
'
,
'
id
'
:
u
.
getUniqueId
(),
}).
c
(
'
body
'
).
t
(
'
But soft, what light through yonder window breaks?
'
).
up
()
.
c
(
'
replace
'
,
{
'
id
'
:
msg_id
,
'
xmlns
'
:
'
urn:xmpp:message-correct:0
'
}).
tree
());
return
test_utils
.
waitUntil
(()
=>
chatboxview
.
el
.
querySelector
(
'
.chat-msg__text
'
).
textContent
===
'
But soft, what light through yonder window breaks?
'
);
}).
then
(()
=>
{
expect
(
chatboxview
.
el
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
expect
(
chatboxview
.
el
.
querySelectorAll
(
'
.chat-msg__content .fa-edit
'
).
length
).
toBe
(
1
);
chatboxview
.
el
.
querySelector
(
'
.chat-msg__content .fa-edit
'
).
click
();
const
modal
=
chatboxview
.
model
.
messages
.
at
(
0
).
message_versions_modal
;
return
test_utils
.
waitUntil
(()
=>
u
.
isVisible
(
modal
.
el
),
1000
);
}).
then
(()
=>
{
const
modal
=
chatboxview
.
model
.
messages
.
at
(
0
).
message_versions_modal
;
const
older_msgs
=
modal
.
el
.
querySelectorAll
(
'
.older-msg
'
);
expect
(
older_msgs
.
length
).
toBe
(
2
);
expect
(
older_msgs
[
0
].
textContent
).
toBe
(
'
But soft, what light through yonder airlock breaks?
'
);
expect
(
older_msgs
[
1
].
textContent
).
toBe
(
'
But soft, what light through yonder chimney breaks?
'
);
done
();
});
});
}));
...
...
@@ -500,10 +506,11 @@
it
(
"
will have the error message displayed after itself
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
test_utils
.
openControlBox
();
// TODO: what could still be done for error
...
...
@@ -513,154 +520,152 @@
// that.
/* <message from="scotty@enterprise.com/_converse.js-84843526"
* to="kirk@enterprise.com.com"
* type="chat"
* id="82bc02ce-9651-4336-baf0-fa04762ed8d2"
* xmlns="jabber:client">
* <body>yo</body>
* <active xmlns="http://jabber.org/protocol/chatstates"/>
* </message>
*/
* to="kirk@enterprise.com.com"
* type="chat"
* id="82bc02ce-9651-4336-baf0-fa04762ed8d2"
* xmlns="jabber:client">
* <body>yo</body>
* <active xmlns="http://jabber.org/protocol/chatstates"/>
* </message>
*/
var
sender_jid
=
mock
.
cur_names
[
5
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
var
fullname
=
_converse
.
xmppstatus
.
get
(
'
fullname
'
);
fullname
=
_
.
isEmpty
(
fullname
)?
_converse
.
bare_jid
:
fullname
;
_converse
.
api
.
chats
.
open
(
sender_jid
);
var
msg_text
=
'
This message will not be sent, due to an error
'
;
var
view
=
_converse
.
chatboxviews
.
get
(
sender_jid
);
var
message
=
view
.
model
.
messages
.
create
({
'
msgid
'
:
'
82bc02ce-9651-4336-baf0-fa04762ed8d2
'
,
'
fullname
'
:
fullname
,
'
sender
'
:
'
me
'
,
'
time
'
:
moment
().
format
(),
'
message
'
:
msg_text
});
view
.
model
.
sendMessage
(
message
);
var
$chat_content
=
$
(
view
.
el
).
find
(
'
.chat-content
'
);
var
msg_txt
=
$chat_content
.
find
(
'
.chat-msg:last
'
).
find
(
'
.chat-msg__text
'
).
text
();
expect
(
msg_txt
).
toEqual
(
msg_text
);
// We send another message, for which an error will
// not be received, to test that errors appear
// after the relevant message.
msg_text
=
'
This message will be sent, and also receive an error
'
;
message
=
view
.
model
.
messages
.
create
({
'
msgid
'
:
'
6fcdeee3-000f-4ce8-a17e-9ce28f0ae104
'
,
'
fullname
'
:
fullname
,
'
sender
'
:
'
me
'
,
'
time
'
:
moment
().
format
(),
'
message
'
:
msg_text
_converse
.
api
.
chats
.
open
(
sender_jid
)
.
then
(()
=>
{
var
msg_text
=
'
This message will not be sent, due to an error
'
;
var
view
=
_converse
.
chatboxviews
.
get
(
sender_jid
);
var
message
=
view
.
model
.
messages
.
create
({
'
msgid
'
:
'
82bc02ce-9651-4336-baf0-fa04762ed8d2
'
,
'
fullname
'
:
fullname
,
'
sender
'
:
'
me
'
,
'
time
'
:
moment
().
format
(),
'
message
'
:
msg_text
});
view
.
model
.
sendMessage
(
message
);
var
$chat_content
=
$
(
view
.
el
).
find
(
'
.chat-content
'
);
var
msg_txt
=
$chat_content
.
find
(
'
.chat-msg:last
'
).
find
(
'
.chat-msg__text
'
).
text
();
expect
(
msg_txt
).
toEqual
(
msg_text
);
// We send another message, for which an error will
// not be received, to test that errors appear
// after the relevant message.
msg_text
=
'
This message will be sent, and also receive an error
'
;
message
=
view
.
model
.
messages
.
create
({
'
msgid
'
:
'
6fcdeee3-000f-4ce8-a17e-9ce28f0ae104
'
,
'
fullname
'
:
fullname
,
'
sender
'
:
'
me
'
,
'
time
'
:
moment
().
format
(),
'
message
'
:
msg_text
});
view
.
model
.
sendMessage
(
message
);
msg_txt
=
$chat_content
.
find
(
'
.chat-msg:last
'
).
find
(
'
.chat-msg__text
'
).
text
();
expect
(
msg_txt
).
toEqual
(
msg_text
);
/* <message xmlns="jabber:client"
* to="scotty@enterprise.com/_converse.js-84843526"
* type="error"
* id="82bc02ce-9651-4336-baf0-fa04762ed8d2"
* from="kirk@enterprise.com.com">
* <error type="cancel">
* <remote-server-not-found xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
* <text xmlns="urn:ietf:params:xml:ns:xmpp-stanzas">Server-to-server connection failed: Connecting failed: connection timeout</text>
* </error>
* </message>
*/
var
error_txt
=
'
Server-to-server connection failed: Connecting failed: connection timeout
'
;
var
stanza
=
$msg
({
'
to
'
:
_converse
.
connection
.
jid
,
'
type
'
:
'
error
'
,
'
id
'
:
'
82bc02ce-9651-4336-baf0-fa04762ed8d2
'
,
'
from
'
:
sender_jid
})
.
c
(
'
error
'
,
{
'
type
'
:
'
cancel
'
})
.
c
(
'
remote-server-not-found
'
,
{
'
xmlns
'
:
"
urn:ietf:params:xml:ns:xmpp-stanzas
"
}).
up
()
.
c
(
'
text
'
,
{
'
xmlns
'
:
"
urn:ietf:params:xml:ns:xmpp-stanzas
"
})
.
t
(
'
Server-to-server connection failed: Connecting failed: connection timeout
'
);
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
expect
(
$chat_content
.
find
(
'
.chat-error
'
).
text
()).
toEqual
(
error_txt
);
stanza
=
$msg
({
'
to
'
:
_converse
.
connection
.
jid
,
'
type
'
:
'
error
'
,
'
id
'
:
'
some-other-unused-id
'
,
'
from
'
:
sender_jid
})
.
c
(
'
error
'
,
{
'
type
'
:
'
cancel
'
})
.
c
(
'
remote-server-not-found
'
,
{
'
xmlns
'
:
"
urn:ietf:params:xml:ns:xmpp-stanzas
"
}).
up
()
.
c
(
'
text
'
,
{
'
xmlns
'
:
"
urn:ietf:params:xml:ns:xmpp-stanzas
"
})
.
t
(
'
Server-to-server connection failed: Connecting failed: connection timeout
'
);
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
expect
(
$chat_content
.
find
(
'
.chat-error
'
).
length
).
toEqual
(
2
);
// If the last message is already an error message,
// then we don't render it another time.
stanza
=
$msg
({
'
to
'
:
_converse
.
connection
.
jid
,
'
type
'
:
'
error
'
,
'
id
'
:
'
another-unused-id
'
,
'
from
'
:
sender_jid
})
.
c
(
'
error
'
,
{
'
type
'
:
'
cancel
'
})
.
c
(
'
remote-server-not-found
'
,
{
'
xmlns
'
:
"
urn:ietf:params:xml:ns:xmpp-stanzas
"
}).
up
()
.
c
(
'
text
'
,
{
'
xmlns
'
:
"
urn:ietf:params:xml:ns:xmpp-stanzas
"
})
.
t
(
'
Server-to-server connection failed: Connecting failed: connection timeout
'
);
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
expect
(
$chat_content
.
find
(
'
.chat-error
'
).
length
).
toEqual
(
2
);
// A different error message will however render
stanza
=
$msg
({
'
to
'
:
_converse
.
connection
.
jid
,
'
type
'
:
'
error
'
,
'
id
'
:
'
another-id
'
,
'
from
'
:
sender_jid
})
.
c
(
'
error
'
,
{
'
type
'
:
'
cancel
'
})
.
c
(
'
remote-server-not-found
'
,
{
'
xmlns
'
:
"
urn:ietf:params:xml:ns:xmpp-stanzas
"
}).
up
()
.
c
(
'
text
'
,
{
'
xmlns
'
:
"
urn:ietf:params:xml:ns:xmpp-stanzas
"
})
.
t
(
'
Something else went wrong as well
'
);
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
expect
(
$chat_content
.
find
(
'
.chat-error
'
).
length
).
toEqual
(
3
);
done
();
});
view
.
model
.
sendMessage
(
message
);
msg_txt
=
$chat_content
.
find
(
'
.chat-msg:last
'
).
find
(
'
.chat-msg__text
'
).
text
();
expect
(
msg_txt
).
toEqual
(
msg_text
);
/* <message xmlns="jabber:client"
* to="scotty@enterprise.com/_converse.js-84843526"
* type="error"
* id="82bc02ce-9651-4336-baf0-fa04762ed8d2"
* from="kirk@enterprise.com.com">
* <error type="cancel">
* <remote-server-not-found xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
* <text xmlns="urn:ietf:params:xml:ns:xmpp-stanzas">Server-to-server connection failed: Connecting failed: connection timeout</text>
* </error>
* </message>
*/
var
error_txt
=
'
Server-to-server connection failed: Connecting failed: connection timeout
'
;
var
stanza
=
$msg
({
'
to
'
:
_converse
.
connection
.
jid
,
'
type
'
:
'
error
'
,
'
id
'
:
'
82bc02ce-9651-4336-baf0-fa04762ed8d2
'
,
'
from
'
:
sender_jid
})
.
c
(
'
error
'
,
{
'
type
'
:
'
cancel
'
})
.
c
(
'
remote-server-not-found
'
,
{
'
xmlns
'
:
"
urn:ietf:params:xml:ns:xmpp-stanzas
"
}).
up
()
.
c
(
'
text
'
,
{
'
xmlns
'
:
"
urn:ietf:params:xml:ns:xmpp-stanzas
"
})
.
t
(
'
Server-to-server connection failed: Connecting failed: connection timeout
'
);
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
expect
(
$chat_content
.
find
(
'
.chat-error
'
).
text
()).
toEqual
(
error_txt
);
stanza
=
$msg
({
'
to
'
:
_converse
.
connection
.
jid
,
'
type
'
:
'
error
'
,
'
id
'
:
'
some-other-unused-id
'
,
'
from
'
:
sender_jid
})
.
c
(
'
error
'
,
{
'
type
'
:
'
cancel
'
})
.
c
(
'
remote-server-not-found
'
,
{
'
xmlns
'
:
"
urn:ietf:params:xml:ns:xmpp-stanzas
"
}).
up
()
.
c
(
'
text
'
,
{
'
xmlns
'
:
"
urn:ietf:params:xml:ns:xmpp-stanzas
"
})
.
t
(
'
Server-to-server connection failed: Connecting failed: connection timeout
'
);
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
expect
(
$chat_content
.
find
(
'
.chat-error
'
).
length
).
toEqual
(
2
);
// If the last message is already an error message,
// then we don't render it another time.
stanza
=
$msg
({
'
to
'
:
_converse
.
connection
.
jid
,
'
type
'
:
'
error
'
,
'
id
'
:
'
another-unused-id
'
,
'
from
'
:
sender_jid
})
.
c
(
'
error
'
,
{
'
type
'
:
'
cancel
'
})
.
c
(
'
remote-server-not-found
'
,
{
'
xmlns
'
:
"
urn:ietf:params:xml:ns:xmpp-stanzas
"
}).
up
()
.
c
(
'
text
'
,
{
'
xmlns
'
:
"
urn:ietf:params:xml:ns:xmpp-stanzas
"
})
.
t
(
'
Server-to-server connection failed: Connecting failed: connection timeout
'
);
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
expect
(
$chat_content
.
find
(
'
.chat-error
'
).
length
).
toEqual
(
2
);
// A different error message will however render
stanza
=
$msg
({
'
to
'
:
_converse
.
connection
.
jid
,
'
type
'
:
'
error
'
,
'
id
'
:
'
another-id
'
,
'
from
'
:
sender_jid
})
.
c
(
'
error
'
,
{
'
type
'
:
'
cancel
'
})
.
c
(
'
remote-server-not-found
'
,
{
'
xmlns
'
:
"
urn:ietf:params:xml:ns:xmpp-stanzas
"
}).
up
()
.
c
(
'
text
'
,
{
'
xmlns
'
:
"
urn:ietf:params:xml:ns:xmpp-stanzas
"
})
.
t
(
'
Something else went wrong as well
'
);
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
expect
(
$chat_content
.
find
(
'
.chat-error
'
).
length
).
toEqual
(
3
);
done
();
}));
});
it
(
"
will cause the chat area to be scrolled down only if it was at the bottom originally
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
test_utils
.
openControlBox
();
var
sender_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
);
var
chatboxview
=
_converse
.
chatboxviews
.
get
(
sender_jid
);
spyOn
(
chatboxview
,
'
onScrolledDown
'
).
and
.
callThrough
();
// Create enough messages so that there's a scrollbar.
var
message
=
'
This message is received while the chat area is scrolled up
'
;
for
(
var
i
=
0
;
i
<
20
;
i
++
)
{
_converse
.
chatboxes
.
onMessage
(
$msg
({
from
:
sender_jid
,
to
:
_converse
.
connection
.
jid
,
type
:
'
chat
'
,
id
:
(
new
Date
()).
getTime
()
}).
c
(
'
body
'
).
t
(
'
Message:
'
+
i
).
up
()
.
c
(
'
active
'
,
{
'
xmlns
'
:
'
http://jabber.org/protocol/chatstates
'
}).
tree
());
}
return
test_utils
.
waitUntil
(
function
()
{
return
chatboxview
.
content
.
scrollTop
;
},
1000
).
then
(
function
()
{
return
test_utils
.
waitUntil
(
function
()
{
return
!
chatboxview
.
model
.
get
(
'
auto_scrolled
'
);
},
500
);
}).
then
(
function
()
{
let
chatboxview
;
const
sender_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
const
message
=
'
This message is received while the chat area is scrolled up
'
;
test_utils
.
openChatBoxFor
(
_converse
,
sender_jid
)
.
then
(()
=>
{
chatboxview
=
_converse
.
chatboxviews
.
get
(
sender_jid
);
spyOn
(
chatboxview
,
'
onScrolledDown
'
).
and
.
callThrough
();
// Create enough messages so that there's a scrollbar.
for
(
var
i
=
0
;
i
<
20
;
i
++
)
{
_converse
.
chatboxes
.
onMessage
(
$msg
({
from
:
sender_jid
,
to
:
_converse
.
connection
.
jid
,
type
:
'
chat
'
,
id
:
(
new
Date
()).
getTime
()
}).
c
(
'
body
'
).
t
(
'
Message:
'
+
i
).
up
()
.
c
(
'
active
'
,
{
'
xmlns
'
:
'
http://jabber.org/protocol/chatstates
'
}).
tree
());
}
return
test_utils
.
waitUntil
(()
=>
chatboxview
.
content
.
scrollTop
,
1000
)
.
then
(()
=>
test_utils
.
waitUntil
(()
=>
!
chatboxview
.
model
.
get
(
'
auto_scrolled
'
),
500
))
}).
then
(()
=>
{
chatboxview
.
content
.
scrollTop
=
0
;
return
test_utils
.
waitUntil
(
function
()
{
return
chatboxview
.
model
.
get
(
'
scrolled
'
);
},
900
);
}).
then
(
function
()
{
return
test_utils
.
waitUntil
(()
=>
chatboxview
.
model
.
get
(
'
scrolled
'
),
900
);
}).
then
(()
=>
{
_converse
.
chatboxes
.
onMessage
(
$msg
({
from
:
sender_jid
,
to
:
_converse
.
connection
.
jid
,
...
...
@@ -1109,23 +1114,22 @@
it
(
"
received for a minimized chat box will increment a counter on its header
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
if
(
_converse
.
view_mode
===
'
fullscreen
'
)
{
return
done
();
}
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
const
contact_name
=
mock
.
cur_names
[
0
];
const
contact_jid
=
contact_name
.
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openControlBox
();
test_utils
.
waitUntil
(
function
()
{
return
$
(
_converse
.
rosterview
.
el
).
find
(
'
.roster-group
'
).
length
;
},
300
)
.
then
(
function
()
{
var
contact_name
=
mock
.
cur_names
[
0
];
var
contact_jid
=
contact_name
.
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
spyOn
(
_converse
,
'
emit
'
).
and
.
callThrough
();
spyOn
(
_converse
,
'
emit
'
).
and
.
callThrough
();
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
test_utils
.
waitUntil
(()
=>
_converse
.
rosterview
.
el
.
querySelectorAll
(
'
.roster-group
'
).
length
)
.
then
(()
=>
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
))
.
then
(()
=>
{
var
chatview
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
expect
(
u
.
isVisible
(
chatview
.
el
)).
toBeTruthy
();
expect
(
chatview
.
model
.
get
(
'
minimized
'
)).
toBeFalsy
();
...
...
@@ -1171,19 +1175,18 @@
it
(
"
will indicate when it has a time difference of more than a day between it and its predecessor
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
test_utils
.
openControlBox
();
test_utils
.
waitUntil
(
function
()
{
return
$
(
_converse
.
rosterview
.
el
).
find
(
'
.roster-group
'
).
length
;
},
300
)
.
then
(
function
()
{
spyOn
(
_converse
,
'
emit
'
);
var
contact_name
=
mock
.
cur_names
[
1
];
var
contact_jid
=
contact_name
.
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
spyOn
(
_converse
,
'
emit
'
);
const
contact_name
=
mock
.
cur_names
[
1
];
const
contact_jid
=
contact_name
.
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
waitUntil
(()
=>
_converse
.
rosterview
.
el
.
querySelectorAll
(
'
.roster-group
'
).
length
)
.
then
(()
=>
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
))
.
then
(()
=>
{
test_utils
.
clearChatBoxMessages
(
_converse
,
contact_jid
);
var
one_day_ago
=
moment
();
one_day_ago
.
subtract
(
'
days
'
,
1
);
...
...
@@ -1269,117 +1272,132 @@
}));
it
(
"
can be sent from a chatbox, and will appear inside it
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroup
sFetched
'
],
{},
function
(
done
,
_converse
)
{
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxe
sFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
test_utils
.
openControlBox
();
spyOn
(
_converse
,
'
emit
'
);
var
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
expect
(
_converse
.
emit
).
toHaveBeenCalledWith
(
'
chatBoxFocused
'
,
jasmine
.
any
(
Object
));
var
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
var
message
=
'
This message is sent from this chatbox
'
;
spyOn
(
view
.
model
,
'
sendMessage
'
).
and
.
callThrough
();
test_utils
.
sendMessage
(
view
,
message
);
expect
(
view
.
model
.
sendMessage
).
toHaveBeenCalled
();
expect
(
view
.
model
.
messages
.
length
,
2
);
expect
(
_converse
.
emit
.
calls
.
mostRecent
().
args
,
[
'
messageSend
'
,
message
]);
expect
(
$
(
view
.
el
).
find
(
'
.chat-content
'
).
find
(
'
.chat-msg
'
).
last
().
find
(
'
.chat-msg__text
'
).
text
()).
toEqual
(
message
);
done
();
const
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
)
.
then
(()
=>
{
expect
(
_converse
.
emit
).
toHaveBeenCalledWith
(
'
chatBoxFocused
'
,
jasmine
.
any
(
Object
));
const
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
const
message
=
'
This message is sent from this chatbox
'
;
spyOn
(
view
.
model
,
'
sendMessage
'
).
and
.
callThrough
();
test_utils
.
sendMessage
(
view
,
message
);
expect
(
view
.
model
.
sendMessage
).
toHaveBeenCalled
();
expect
(
view
.
model
.
messages
.
length
,
2
);
expect
(
_converse
.
emit
.
calls
.
mostRecent
().
args
,
[
'
messageSend
'
,
message
]);
expect
(
$
(
view
.
el
).
find
(
'
.chat-content
'
).
find
(
'
.chat-msg
'
).
last
().
find
(
'
.chat-msg__text
'
).
text
()).
toEqual
(
message
);
done
();
});
}));
it
(
"
is sanitized to prevent Javascript injection attacks
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
test_utils
.
openControlBox
();
var
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
var
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
var
message
=
'
<p>This message contains <em>some</em> <b>markup</b></p>
'
;
spyOn
(
view
.
model
,
'
sendMessage
'
).
and
.
callThrough
();
test_utils
.
sendMessage
(
view
,
message
);
expect
(
view
.
model
.
sendMessage
).
toHaveBeenCalled
();
var
msg
=
$
(
view
.
el
).
find
(
'
.chat-content
'
).
find
(
'
.chat-msg
'
).
last
().
find
(
'
.chat-msg__text
'
);
expect
(
msg
.
text
()).
toEqual
(
message
);
expect
(
msg
.
html
()).
toEqual
(
'
<p>This message contains <em>some</em> <b>markup</b></p>
'
);
done
();
const
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
)
.
then
(()
=>
{
const
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
const
message
=
'
<p>This message contains <em>some</em> <b>markup</b></p>
'
;
spyOn
(
view
.
model
,
'
sendMessage
'
).
and
.
callThrough
();
test_utils
.
sendMessage
(
view
,
message
);
expect
(
view
.
model
.
sendMessage
).
toHaveBeenCalled
();
const
msg
=
$
(
view
.
el
).
find
(
'
.chat-content
'
).
find
(
'
.chat-msg
'
).
last
().
find
(
'
.chat-msg__text
'
);
expect
(
msg
.
text
()).
toEqual
(
message
);
expect
(
msg
.
html
()).
toEqual
(
'
<p>This message contains <em>some</em> <b>markup</b></p>
'
);
done
();
});
}));
it
(
"
can contain hyperlinks, which will be clickable
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
test_utils
.
openControlBox
();
var
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
var
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
var
message
=
'
This message contains a hyperlink: www.opkode.com
'
;
spyOn
(
view
.
model
,
'
sendMessage
'
).
and
.
callThrough
();
test_utils
.
sendMessage
(
view
,
message
);
expect
(
view
.
model
.
sendMessage
).
toHaveBeenCalled
();
var
msg
=
$
(
view
.
el
).
find
(
'
.chat-content
'
).
find
(
'
.chat-msg
'
).
last
().
find
(
'
.chat-msg__text
'
);
expect
(
msg
.
text
()).
toEqual
(
message
);
expect
(
msg
.
html
()).
toEqual
(
'
This message contains a hyperlink: <a target="_blank" rel="noopener" href="http://www.opkode.com">www.opkode.com</a>
'
);
done
();
const
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
)
.
then
(()
=>
{
const
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
const
message
=
'
This message contains a hyperlink: www.opkode.com
'
;
spyOn
(
view
.
model
,
'
sendMessage
'
).
and
.
callThrough
();
test_utils
.
sendMessage
(
view
,
message
);
expect
(
view
.
model
.
sendMessage
).
toHaveBeenCalled
();
const
msg
=
$
(
view
.
el
).
find
(
'
.chat-content
'
).
find
(
'
.chat-msg
'
).
last
().
find
(
'
.chat-msg__text
'
);
expect
(
msg
.
text
()).
toEqual
(
message
);
expect
(
msg
.
html
()).
toEqual
(
'
This message contains a hyperlink: <a target="_blank" rel="noopener" href="http://www.opkode.com">www.opkode.com</a>
'
);
done
();
});
}));
it
(
"
will have properly escaped URLs
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroup
sFetched
'
],
{},
function
(
done
,
_converse
)
{
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxe
sFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
test_utils
.
openControlBox
();
var
message
,
msg
;
var
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
var
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
spyOn
(
view
.
model
,
'
sendMessage
'
).
and
.
callThrough
();
message
=
"
http://www.opkode.com/'onmouseover='alert(1)'whatever
"
;
test_utils
.
sendMessage
(
view
,
message
);
expect
(
view
.
model
.
sendMessage
).
toHaveBeenCalled
();
msg
=
$
(
view
.
el
).
find
(
'
.chat-content
'
).
find
(
'
.chat-msg
'
).
last
().
find
(
'
.chat-msg__text
'
);
expect
(
msg
.
text
()).
toEqual
(
message
);
expect
(
msg
.
html
()).
toEqual
(
'
<a target="_blank" rel="noopener" href="http://www.opkode.com/%27onmouseover=%27alert%281%29%27whatever">http://www.opkode.com/
\'
onmouseover=
\'
alert(1)
\'
whatever</a>
'
);
message
=
'
http://www.opkode.com/"onmouseover="alert(1)"whatever
'
;
test_utils
.
sendMessage
(
view
,
message
);
expect
(
view
.
model
.
sendMessage
).
toHaveBeenCalled
();
msg
=
$
(
view
.
el
).
find
(
'
.chat-content
'
).
find
(
'
.chat-msg
'
).
last
().
find
(
'
.chat-msg__text
'
);
expect
(
msg
.
text
()).
toEqual
(
message
);
expect
(
msg
.
html
()).
toEqual
(
'
<a target="_blank" rel="noopener" href="http://www.opkode.com/%22onmouseover=%22alert%281%29%22whatever">http://www.opkode.com/"onmouseover="alert(1)"whatever</a>
'
);
message
=
"
https://en.wikipedia.org/wiki/Ender's_Game
"
;
test_utils
.
sendMessage
(
view
,
message
);
expect
(
view
.
model
.
sendMessage
).
toHaveBeenCalled
();
msg
=
$
(
view
.
el
).
find
(
'
.chat-content
'
).
find
(
'
.chat-msg
'
).
last
().
find
(
'
.chat-msg__text
'
);
expect
(
msg
.
text
()).
toEqual
(
message
);
expect
(
msg
.
html
()).
toEqual
(
'
<a target="_blank" rel="noopener" href="https://en.wikipedia.org/wiki/Ender%27s_Game">
'
+
message
+
'
</a>
'
);
message
=
"
https://en.wikipedia.org/wiki/Ender's_Game
"
;
test_utils
.
sendMessage
(
view
,
message
);
expect
(
view
.
model
.
sendMessage
).
toHaveBeenCalled
();
msg
=
$
(
view
.
el
).
find
(
'
.chat-content
'
).
find
(
'
.chat-msg
'
).
last
().
find
(
'
.chat-msg__text
'
);
expect
(
msg
.
text
()).
toEqual
(
message
);
expect
(
msg
.
html
()).
toEqual
(
'
<a target="_blank" rel="noopener" href="https://en.wikipedia.org/wiki/Ender%27s_Game">
'
+
message
+
'
</a>
'
);
done
();
let
message
,
msg
;
const
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
)
.
then
(()
=>
{
var
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
spyOn
(
view
.
model
,
'
sendMessage
'
).
and
.
callThrough
();
message
=
"
http://www.opkode.com/'onmouseover='alert(1)'whatever
"
;
test_utils
.
sendMessage
(
view
,
message
);
expect
(
view
.
model
.
sendMessage
).
toHaveBeenCalled
();
msg
=
$
(
view
.
el
).
find
(
'
.chat-content
'
).
find
(
'
.chat-msg
'
).
last
().
find
(
'
.chat-msg__text
'
);
expect
(
msg
.
text
()).
toEqual
(
message
);
expect
(
msg
.
html
()).
toEqual
(
'
<a target="_blank" rel="noopener" href="http://www.opkode.com/%27onmouseover=%27alert%281%29%27whatever">http://www.opkode.com/
\'
onmouseover=
\'
alert(1)
\'
whatever</a>
'
);
message
=
'
http://www.opkode.com/"onmouseover="alert(1)"whatever
'
;
test_utils
.
sendMessage
(
view
,
message
);
expect
(
view
.
model
.
sendMessage
).
toHaveBeenCalled
();
msg
=
$
(
view
.
el
).
find
(
'
.chat-content
'
).
find
(
'
.chat-msg
'
).
last
().
find
(
'
.chat-msg__text
'
);
expect
(
msg
.
text
()).
toEqual
(
message
);
expect
(
msg
.
html
()).
toEqual
(
'
<a target="_blank" rel="noopener" href="http://www.opkode.com/%22onmouseover=%22alert%281%29%22whatever">http://www.opkode.com/"onmouseover="alert(1)"whatever</a>
'
);
message
=
"
https://en.wikipedia.org/wiki/Ender's_Game
"
;
test_utils
.
sendMessage
(
view
,
message
);
expect
(
view
.
model
.
sendMessage
).
toHaveBeenCalled
();
msg
=
$
(
view
.
el
).
find
(
'
.chat-content
'
).
find
(
'
.chat-msg
'
).
last
().
find
(
'
.chat-msg__text
'
);
expect
(
msg
.
text
()).
toEqual
(
message
);
expect
(
msg
.
html
()).
toEqual
(
'
<a target="_blank" rel="noopener" href="https://en.wikipedia.org/wiki/Ender%27s_Game">
'
+
message
+
'
</a>
'
);
message
=
"
https://en.wikipedia.org/wiki/Ender's_Game
"
;
test_utils
.
sendMessage
(
view
,
message
);
expect
(
view
.
model
.
sendMessage
).
toHaveBeenCalled
();
msg
=
$
(
view
.
el
).
find
(
'
.chat-content
'
).
find
(
'
.chat-msg
'
).
last
().
find
(
'
.chat-msg__text
'
);
expect
(
msg
.
text
()).
toEqual
(
message
);
expect
(
msg
.
html
()).
toEqual
(
'
<a target="_blank" rel="noopener" href="https://en.wikipedia.org/wiki/Ender%27s_Game">
'
+
message
+
'
</a>
'
);
done
();
});
}));
it
(
"
will render newlines
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
function
(
done
,
_converse
)
{
it
(
"
will render newlines
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
const
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
...
...
@@ -1416,20 +1434,23 @@
}));
it
(
"
will render images from their URLs
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroup
sFetched
'
],
{},
function
(
done
,
_converse
)
{
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxe
sFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
,
1
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
const
base_url
=
document
.
URL
.
split
(
window
.
location
.
pathname
)[
0
];
let
message
=
base_url
+
"
/logo/conversejs-filled.svg
"
;
const
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
const
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
spyOn
(
view
.
model
,
'
sendMessage
'
).
and
.
callThrough
();
test_utils
.
sendMessage
(
view
,
message
);
test_utils
.
waitUntil
(()
=>
view
.
el
.
querySelectorAll
(
'
.chat-content .chat-image
'
).
length
,
1000
).
then
(()
=>
{
let
view
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
)
.
then
(()
=>
{
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
spyOn
(
view
.
model
,
'
sendMessage
'
).
and
.
callThrough
();
test_utils
.
sendMessage
(
view
,
message
);
return
test_utils
.
waitUntil
(()
=>
view
.
el
.
querySelectorAll
(
'
.chat-content .chat-image
'
).
length
,
1000
)
}).
then
(()
=>
{
expect
(
view
.
model
.
sendMessage
).
toHaveBeenCalled
();
const
msg
=
$
(
view
.
el
).
find
(
'
.chat-content .chat-msg
'
).
last
().
find
(
'
.chat-msg__text
'
);
expect
(
msg
.
html
().
trim
()).
toEqual
(
...
...
@@ -1461,30 +1482,33 @@
}));
it
(
"
will render the message time as configured
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{}
,
function
(
done
,
_converse
)
{
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
]
,
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
_converse
.
time_format
=
'
hh:mm
'
;
var
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
var
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
var
message
=
'
This message is sent from this chatbox
'
;
test_utils
.
sendMessage
(
view
,
message
);
const
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
)
.
then
(()
=>
{
const
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
const
message
=
'
This message is sent from this chatbox
'
;
test_utils
.
sendMessage
(
view
,
message
);
var
chatbox
=
_converse
.
chatboxes
.
get
(
contact_jid
);
expect
(
chatbox
.
messages
.
models
.
length
,
1
);
var
msg_object
=
chatbox
.
messages
.
models
[
0
];
const
chatbox
=
_converse
.
chatboxes
.
get
(
contact_jid
);
expect
(
chatbox
.
messages
.
models
.
length
,
1
);
const
msg_object
=
chatbox
.
messages
.
models
[
0
];
var
msg_author
=
view
.
el
.
querySelector
(
'
.chat-content .chat-msg:last-child .chat-msg__author
'
);
expect
(
msg_author
.
textContent
.
trim
()).
toBe
(
'
Max Mustermann
'
);
const
msg_author
=
view
.
el
.
querySelector
(
'
.chat-content .chat-msg:last-child .chat-msg__author
'
);
expect
(
msg_author
.
textContent
.
trim
()).
toBe
(
'
Max Mustermann
'
);
var
msg_time
=
view
.
el
.
querySelector
(
'
.chat-content .chat-msg:last-child .chat-msg__time
'
);
var
time
=
moment
(
msg_object
.
get
(
'
time
'
)).
format
(
_converse
.
time_format
);
expect
(
msg_time
.
textContent
).
toBe
(
time
);
done
();
const
msg_time
=
view
.
el
.
querySelector
(
'
.chat-content .chat-msg:last-child .chat-msg__time
'
);
const
time
=
moment
(
msg_object
.
get
(
'
time
'
)).
format
(
_converse
.
time_format
);
expect
(
msg_time
.
textContent
).
toBe
(
time
);
done
();
});
}));
it
(
"
will be correctly identified and rendered as a followup message
"
,
...
...
@@ -1655,29 +1679,33 @@
}));
describe
(
"
which contains a OOB URL
"
,
function
()
{
describe
(
"
which contains a
n
OOB URL
"
,
function
()
{
it
(
"
will render audio from oob mp3 URLs
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroup
sFetched
'
],
{},
function
(
done
,
_converse
)
{
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxe
sFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
,
1
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
const
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
const
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
spyOn
(
view
.
model
,
'
sendMessage
'
).
and
.
callThrough
();
let
view
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
)
.
then
(()
=>
{
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
spyOn
(
view
.
model
,
'
sendMessage
'
).
and
.
callThrough
();
const
stanza
=
Strophe
.
xmlHtmlNode
(
"
<message from='
"
+
contact_jid
+
"
'
"
+
"
type='chat'
"
+
"
to='dummy@localhost/resource'>
"
+
"
<body>Have you heard this funny audio?</body>
"
+
"
<x xmlns='jabber:x:oob'><url>http://localhost/audio.mp3</url></x>
"
+
"
</message>
"
).
firstChild
;
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
const
stanza
=
Strophe
.
xmlHtmlNode
(
"
<message from='
"
+
contact_jid
+
"
'
"
+
"
type='chat'
"
+
"
to='dummy@localhost/resource'>
"
+
"
<body>Have you heard this funny audio?</body>
"
+
"
<x xmlns='jabber:x:oob'><url>http://localhost/audio.mp3</url></x>
"
+
"
</message>
"
).
firstChild
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
test_utils
.
waitUntil
(()
=>
view
.
el
.
querySelectorAll
(
'
.chat-content .chat-msg audio
'
).
length
,
1000
).
then
(
function
()
{
return
test_utils
.
waitUntil
(()
=>
view
.
el
.
querySelectorAll
(
'
.chat-content .chat-msg audio
'
).
length
,
1000
);
}).
then
(()
=>
{
let
msg
=
view
.
el
.
querySelector
(
'
.chat-msg .chat-msg__text
'
);
expect
(
msg
.
outerHTML
).
toEqual
(
'
<div class="chat-msg__text">Have you heard this funny audio?</div>
'
);
let
media
=
view
.
el
.
querySelector
(
'
.chat-msg .chat-msg__media
'
);
...
...
@@ -1708,76 +1736,83 @@
}));
it
(
"
will render video from oob mp4 URLs
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroup
sFetched
'
],
{},
function
(
done
,
_converse
)
{
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxe
sFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
const
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
const
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
spyOn
(
view
.
model
,
'
sendMessage
'
).
and
.
callThrough
();
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
)
.
then
(()
=>
{
const
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
spyOn
(
view
.
model
,
'
sendMessage
'
).
and
.
callThrough
();
const
stanza
=
Strophe
.
xmlHtmlNode
(
"
<message from='
"
+
contact_jid
+
"
'
"
+
"
type='chat'
"
+
"
to='dummy@localhost/resource'>
"
+
"
<body>Have you seen this funny video?</body>
"
+
"
<x xmlns='jabber:x:oob'><url>http://localhost/video.mp4</url></x>
"
+
"
</message>
"
).
firstChild
;
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
test_utils
.
waitUntil
(()
=>
view
.
el
.
querySelectorAll
(
'
.chat-content .chat-msg video
'
).
length
,
2000
).
then
(
function
()
{
let
msg
=
view
.
el
.
querySelector
(
'
.chat-msg .chat-msg__text
'
);
expect
(
msg
.
outerHTML
).
toEqual
(
'
<div class="chat-msg__text">Have you seen this funny video?</div>
'
);
let
media
=
view
.
el
.
querySelector
(
'
.chat-msg .chat-msg__media
'
);
expect
(
media
.
innerHTML
.
replace
(
/
(\r\n
|
\n
|
\r)
/gm
,
""
)).
toEqual
(
'
<!-- src/templates/video.html -->
'
+
'
<video controls=""><source src="http://localhost/video.mp4" type="video/mp4"></video>
'
+
'
<a target="_blank" rel="noopener" href="http://localhost/video.mp4">Download video file</a>
'
);
// If the <url> and <body> contents is the same, don't duplicate.
const
stanza
=
Strophe
.
xmlHtmlNode
(
"
<message from='
"
+
contact_jid
+
"
'
"
+
"
type='chat'
"
+
"
to='dummy@localhost/resource'>
"
+
"
<body>
http://localhost/video.mp4
</body>
"
+
"
<body>
Have you seen this funny video?
</body>
"
+
"
<x xmlns='jabber:x:oob'><url>http://localhost/video.mp4</url></x>
"
+
"
</message>
"
).
firstChild
;
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
msg
=
view
.
el
.
querySelector
(
'
.chat-msg:last-child .chat-msg__text
'
);
expect
(
msg
.
innerHTML
).
toEqual
(
'
<!-- message gets added here via renderMessage -->
'
);
// Emtpy
media
=
view
.
el
.
querySelector
(
'
.chat-msg:last-child .chat-msg__media
'
);
expect
(
media
.
innerHTML
.
replace
(
/
(\r\n
|
\n
|
\r)
/gm
,
""
)).
toEqual
(
'
<!-- src/templates/video.html -->
'
+
'
<video controls=""><source src="http://localhost/video.mp4" type="video/mp4"></video>
'
+
'
<a target="_blank" rel="noopener" href="http://localhost/video.mp4">Download video file</a>
'
);
done
();
test_utils
.
waitUntil
(()
=>
view
.
el
.
querySelectorAll
(
'
.chat-content .chat-msg video
'
).
length
,
2000
).
then
(
function
()
{
let
msg
=
view
.
el
.
querySelector
(
'
.chat-msg .chat-msg__text
'
);
expect
(
msg
.
outerHTML
).
toEqual
(
'
<div class="chat-msg__text">Have you seen this funny video?</div>
'
);
let
media
=
view
.
el
.
querySelector
(
'
.chat-msg .chat-msg__media
'
);
expect
(
media
.
innerHTML
.
replace
(
/
(\r\n
|
\n
|
\r)
/gm
,
""
)).
toEqual
(
'
<!-- src/templates/video.html -->
'
+
'
<video controls=""><source src="http://localhost/video.mp4" type="video/mp4"></video>
'
+
'
<a target="_blank" rel="noopener" href="http://localhost/video.mp4">Download video file</a>
'
);
// If the <url> and <body> contents is the same, don't duplicate.
const
stanza
=
Strophe
.
xmlHtmlNode
(
"
<message from='
"
+
contact_jid
+
"
'
"
+
"
type='chat'
"
+
"
to='dummy@localhost/resource'>
"
+
"
<body>http://localhost/video.mp4</body>
"
+
"
<x xmlns='jabber:x:oob'><url>http://localhost/video.mp4</url></x>
"
+
"
</message>
"
).
firstChild
;
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
msg
=
view
.
el
.
querySelector
(
'
.chat-msg:last-child .chat-msg__text
'
);
expect
(
msg
.
innerHTML
).
toEqual
(
'
<!-- message gets added here via renderMessage -->
'
);
// Emtpy
media
=
view
.
el
.
querySelector
(
'
.chat-msg:last-child .chat-msg__media
'
);
expect
(
media
.
innerHTML
.
replace
(
/
(\r\n
|
\n
|
\r)
/gm
,
""
)).
toEqual
(
'
<!-- src/templates/video.html -->
'
+
'
<video controls=""><source src="http://localhost/video.mp4" type="video/mp4"></video>
'
+
'
<a target="_blank" rel="noopener" href="http://localhost/video.mp4">Download video file</a>
'
);
done
();
});
});
}));
it
(
"
will render download links for files from oob URLs
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
,
1
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
const
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
const
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
spyOn
(
view
.
model
,
'
sendMessage
'
).
and
.
callThrough
();
let
view
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
)
.
then
(()
=>
{
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
spyOn
(
view
.
model
,
'
sendMessage
'
).
and
.
callThrough
();
const
stanza
=
Strophe
.
xmlHtmlNode
(
"
<message from='
"
+
contact_jid
+
"
'
"
+
"
type='chat'
"
+
"
to='dummy@localhost/resource'>
"
+
"
<body>Have you downloaded this funny file?</body>
"
+
"
<x xmlns='jabber:x:oob'><url>http://localhost/funny.pdf</url></x>
"
+
"
</message>
"
).
firstChild
;
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
const
stanza
=
Strophe
.
xmlHtmlNode
(
"
<message from='
"
+
contact_jid
+
"
'
"
+
"
type='chat'
"
+
"
to='dummy@localhost/resource'>
"
+
"
<body>Have you downloaded this funny file?</body>
"
+
"
<x xmlns='jabber:x:oob'><url>http://localhost/funny.pdf</url></x>
"
+
"
</message>
"
).
firstChild
;
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
test_utils
.
waitUntil
(()
=>
view
.
el
.
querySelectorAll
(
'
.chat-content .chat-msg a
'
).
length
,
1000
).
then
(
function
()
{
test_utils
.
waitUntil
(()
=>
view
.
el
.
querySelectorAll
(
'
.chat-content .chat-msg a
'
).
length
,
1000
);
}).
then
(
function
()
{
const
msg
=
view
.
el
.
querySelector
(
'
.chat-msg .chat-msg__text
'
);
expect
(
msg
.
outerHTML
).
toEqual
(
'
<div class="chat-msg__text">Have you downloaded this funny file?</div>
'
);
const
media
=
view
.
el
.
querySelector
(
'
.chat-msg .chat-msg__media
'
);
...
...
@@ -1789,28 +1824,31 @@
}));
it
(
"
will render images from oob URLs
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroup
sFetched
'
],
{},
function
(
done
,
_converse
)
{
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxe
sFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
const
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
const
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
spyOn
(
view
.
model
,
'
sendMessage
'
).
and
.
callThrough
();
const
base_url
=
document
.
URL
.
split
(
window
.
location
.
pathname
)[
0
];
const
url
=
base_url
+
"
/logo/conversejs-filled.svg
"
;
const
stanza
=
Strophe
.
xmlHtmlNode
(
"
<message from='
"
+
contact_jid
+
"
'
"
+
"
type='chat'
"
+
"
to='dummy@localhost/resource'>
"
+
"
<body>Have you seen this funny image?</body>
"
+
"
<x xmlns='jabber:x:oob'><url>
"
+
url
+
"
</url></x>
"
+
"
</message>
"
).
firstChild
;
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
let
view
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
)
.
then
(()
=>
{
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
spyOn
(
view
.
model
,
'
sendMessage
'
).
and
.
callThrough
();
const
base_url
=
document
.
URL
.
split
(
window
.
location
.
pathname
)[
0
];
const
url
=
base_url
+
"
/logo/conversejs-filled.svg
"
;
test_utils
.
waitUntil
(()
=>
view
.
el
.
querySelectorAll
(
'
.chat-content .chat-msg img
'
).
length
,
2000
).
then
(
function
()
{
const
stanza
=
Strophe
.
xmlHtmlNode
(
"
<message from='
"
+
contact_jid
+
"
'
"
+
"
type='chat'
"
+
"
to='dummy@localhost/resource'>
"
+
"
<body>Have you seen this funny image?</body>
"
+
"
<x xmlns='jabber:x:oob'><url>
"
+
url
+
"
</url></x>
"
+
"
</message>
"
).
firstChild
;
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
return
test_utils
.
waitUntil
(()
=>
view
.
el
.
querySelectorAll
(
'
.chat-content .chat-msg img
'
).
length
,
2000
);
}).
then
(
function
()
{
const
msg
=
view
.
el
.
querySelector
(
'
.chat-msg .chat-msg__text
'
);
expect
(
msg
.
outerHTML
).
toEqual
(
'
<div class="chat-msg__text">Have you seen this funny image?</div>
'
);
const
media
=
view
.
el
.
querySelector
(
'
.chat-msg .chat-msg__media
'
);
...
...
spec/minchats.js
View file @
506aa331
...
...
@@ -13,32 +13,37 @@
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
test_utils
.
openControlBox
();
_converse
.
minimized_chats
.
toggleview
.
model
.
browserStorage
.
_clear
();
_converse
.
minimized_chats
.
initToggle
();
var
contact_jid
,
chatview
;
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
chatview
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
expect
(
chatview
.
model
.
get
(
'
minimized
'
)).
toBeFalsy
();
expect
(
$
(
_converse
.
minimized_chats
.
el
).
is
(
'
:visible
'
)).
toBeFalsy
();
chatview
.
el
.
querySelector
(
'
.toggle-chatbox-button
'
).
click
();
expect
(
chatview
.
model
.
get
(
'
minimized
'
)).
toBeTruthy
();
expect
(
$
(
_converse
.
minimized_chats
.
el
).
is
(
'
:visible
'
)).
toBeTruthy
();
expect
(
_converse
.
minimized_chats
.
keys
().
length
).
toBe
(
1
);
expect
(
_converse
.
minimized_chats
.
keys
()[
0
]).
toBe
(
contact_jid
);
contact_jid
=
mock
.
cur_names
[
1
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
chatview
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
expect
(
chatview
.
model
.
get
(
'
minimized
'
)).
toBeFalsy
();
chatview
.
el
.
querySelector
(
'
.toggle-chatbox-button
'
).
click
();
expect
(
chatview
.
model
.
get
(
'
minimized
'
)).
toBeTruthy
();
expect
(
$
(
_converse
.
minimized_chats
.
el
).
is
(
'
:visible
'
)).
toBeTruthy
();
expect
(
_converse
.
minimized_chats
.
keys
().
length
).
toBe
(
2
);
expect
(
_
.
includes
(
_converse
.
minimized_chats
.
keys
(),
contact_jid
)).
toBeTruthy
();
done
();
let
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
let
chatview
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
)
.
then
(()
=>
{
chatview
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
expect
(
chatview
.
model
.
get
(
'
minimized
'
)).
toBeFalsy
();
expect
(
$
(
_converse
.
minimized_chats
.
el
).
is
(
'
:visible
'
)).
toBeFalsy
();
chatview
.
el
.
querySelector
(
'
.toggle-chatbox-button
'
).
click
();
expect
(
chatview
.
model
.
get
(
'
minimized
'
)).
toBeTruthy
();
expect
(
$
(
_converse
.
minimized_chats
.
el
).
is
(
'
:visible
'
)).
toBeTruthy
();
expect
(
_converse
.
minimized_chats
.
keys
().
length
).
toBe
(
1
);
expect
(
_converse
.
minimized_chats
.
keys
()[
0
]).
toBe
(
contact_jid
);
contact_jid
=
mock
.
cur_names
[
1
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
return
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
);
}).
then
(()
=>
{
chatview
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
expect
(
chatview
.
model
.
get
(
'
minimized
'
)).
toBeFalsy
();
chatview
.
el
.
querySelector
(
'
.toggle-chatbox-button
'
).
click
();
expect
(
chatview
.
model
.
get
(
'
minimized
'
)).
toBeTruthy
();
expect
(
$
(
_converse
.
minimized_chats
.
el
).
is
(
'
:visible
'
)).
toBeTruthy
();
expect
(
_converse
.
minimized_chats
.
keys
().
length
).
toBe
(
2
);
expect
(
_
.
includes
(
_converse
.
minimized_chats
.
keys
(),
contact_jid
)).
toBeTruthy
();
done
();
});
}));
it
(
"
can be toggled to hide or show minimized chats
"
,
...
...
@@ -47,24 +52,26 @@
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
test_utils
.
openControlBox
();
_converse
.
minimized_chats
.
toggleview
.
model
.
browserStorage
.
_clear
();
_converse
.
minimized_chats
.
initToggle
();
var
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
)
;
var
chatview
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
expect
(
$
(
_converse
.
minimized_chats
.
el
).
is
(
'
:visible
'
)).
toBeFalsy
(
);
chatview
.
model
.
set
({
'
minimized
'
:
true
}
);
expect
(
$
(
_converse
.
minimized_chats
.
el
).
is
(
'
:visible
'
)).
toBeTruthy
(
);
expect
(
_converse
.
minimized_chats
.
keys
().
length
).
toBe
(
1
);
expect
(
_converse
.
minimized_chats
.
keys
()[
0
]).
toBe
(
contact_jid
);
expect
(
$
(
_converse
.
minimized_chats
.
el
.
querySelector
(
'
.minimized-chats-flyout
'
)).
is
(
'
:visible
'
)).
toBeTruthy
(
);
expect
(
_converse
.
minimized_chats
.
toggleview
.
model
.
get
(
'
collapsed
'
)).
toBeFals
y
();
_converse
.
minimized_chats
.
el
.
querySelector
(
'
#toggle-minimized-chats
'
).
click
();
return
test_utils
.
waitUntil
(()
=>
u
.
isVisible
(
u
.
isVisible
(
_converse
.
minimized_chats
.
el
.
querySelector
(
'
.minimized-chats-flyout
'
))))
.
then
(
function
()
{
const
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
)
.
then
(()
=>
{
const
chatview
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
expect
(
u
.
isVisible
(
_converse
.
minimized_chats
.
el
)).
toBeFalsy
(
);
chatview
.
model
.
set
({
'
minimized
'
:
true
}
);
expect
(
u
.
isVisible
(
_converse
.
minimized_chats
.
el
)).
toBeTruthy
(
);
expect
(
_converse
.
minimized_chats
.
keys
().
length
).
toBe
(
1
);
expect
(
_converse
.
minimized_chats
.
keys
()[
0
]).
toBe
(
contact_jid
);
expect
(
u
.
isVisible
(
_converse
.
minimized_chats
.
el
.
querySelector
(
'
.minimized-chats-flyout
'
))).
toBeTruth
y
();
expect
(
_converse
.
minimized_chats
.
toggleview
.
model
.
get
(
'
collapsed
'
)).
toBeFalsy
();
_converse
.
minimized_chats
.
el
.
querySelector
(
'
#toggle-minimized-chats
'
).
click
();
return
test_utils
.
waitUntil
(()
=>
u
.
isVisible
(
_converse
.
minimized_chats
.
el
.
querySelector
(
'
.minimized-chats-flyout
'
)));
}).
then
(()
=>
{
expect
(
_converse
.
minimized_chats
.
toggleview
.
model
.
get
(
'
collapsed
'
)).
toBeTruthy
();
done
();
});
...
...
spec/roomslist.js
View file @
506aa331
...
...
@@ -12,44 +12,46 @@
describe
(
"
A list of open rooms
"
,
function
()
{
it
(
"
is shown in the
\"
Rooms
\"
panel
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{
allow_bookmarks
:
false
// Makes testing easier, otherwise we
// have to mock stanza traffic.
},
function
(
done
,
_converse
)
{
test_utils
.
openControlBox
();
var
controlbox
=
_converse
.
chatboxviews
.
get
(
'
controlbox
'
);
var
list
=
controlbox
.
el
.
querySelector
(
'
div.rooms-list-container
'
);
const
controlbox
=
_converse
.
chatboxviews
.
get
(
'
controlbox
'
);
let
list
=
controlbox
.
el
.
querySelector
(
'
div.rooms-list-container
'
);
expect
(
_
.
includes
(
list
.
classList
,
'
hidden
'
)).
toBeTruthy
();
test_utils
.
openChatRoom
(
_converse
,
'
room
'
,
'
conference.shakespeare.lit
'
,
'
JC
'
);
expect
(
_
.
isUndefined
(
_converse
.
rooms_list_view
)).
toBeFalsy
();
var
room_els
=
_converse
.
rooms_list_view
.
el
.
querySelectorAll
(
"
.open-room
"
);
expect
(
room_els
.
length
).
toBe
(
1
);
expect
(
room_els
[
0
].
innerText
).
toBe
(
'
room@conference.shakespeare.lit
'
);
test_utils
.
openChatRoom
(
_converse
,
'
lounge
'
,
'
localhost
'
,
'
dummy
'
);
room_els
=
_converse
.
rooms_list_view
.
el
.
querySelectorAll
(
"
.open-room
"
);
expect
(
room_els
.
length
).
toBe
(
2
);
var
view
=
_converse
.
chatboxviews
.
get
(
'
room@conference.shakespeare.lit
'
);
view
.
close
();
room_els
=
_converse
.
rooms_list_view
.
el
.
querySelectorAll
(
"
.open-room
"
);
expect
(
room_els
.
length
).
toBe
(
1
);
expect
(
room_els
[
0
].
innerText
).
toBe
(
'
lounge@localhost
'
);
list
=
controlbox
.
el
.
querySelector
(
'
div.rooms-list-container
'
);
expect
(
_
.
includes
(
list
.
classList
,
'
hidden
'
)).
toBeFalsy
();
view
=
_converse
.
chatboxviews
.
get
(
'
lounge@localhost
'
);
view
.
close
();
room_els
=
_converse
.
rooms_list_view
.
el
.
querySelectorAll
(
"
.open-room
"
);
expect
(
room_els
.
length
).
toBe
(
0
);
list
=
controlbox
.
el
.
querySelector
(
'
div.rooms-list-container
'
);
expect
(
_
.
includes
(
list
.
classList
,
'
hidden
'
)).
toBeTruthy
();
done
();
let
room_els
;
test_utils
.
openChatRoom
(
_converse
,
'
room
'
,
'
conference.shakespeare.lit
'
,
'
JC
'
)
.
then
(()
=>
{
expect
(
_
.
isUndefined
(
_converse
.
rooms_list_view
)).
toBeFalsy
();
room_els
=
_converse
.
rooms_list_view
.
el
.
querySelectorAll
(
"
.open-room
"
);
expect
(
room_els
.
length
).
toBe
(
1
);
expect
(
room_els
[
0
].
innerText
).
toBe
(
'
room@conference.shakespeare.lit
'
);
return
test_utils
.
openChatRoom
(
_converse
,
'
lounge
'
,
'
localhost
'
,
'
dummy
'
);
}).
then
(()
=>
{
room_els
=
_converse
.
rooms_list_view
.
el
.
querySelectorAll
(
"
.open-room
"
);
expect
(
room_els
.
length
).
toBe
(
2
);
var
view
=
_converse
.
chatboxviews
.
get
(
'
room@conference.shakespeare.lit
'
);
view
.
close
();
room_els
=
_converse
.
rooms_list_view
.
el
.
querySelectorAll
(
"
.open-room
"
);
expect
(
room_els
.
length
).
toBe
(
1
);
expect
(
room_els
[
0
].
innerText
).
toBe
(
'
lounge@localhost
'
);
list
=
controlbox
.
el
.
querySelector
(
'
div.rooms-list-container
'
);
expect
(
_
.
includes
(
list
.
classList
,
'
hidden
'
)).
toBeFalsy
();
view
=
_converse
.
chatboxviews
.
get
(
'
lounge@localhost
'
);
view
.
close
();
room_els
=
_converse
.
rooms_list_view
.
el
.
querySelectorAll
(
"
.open-room
"
);
expect
(
room_els
.
length
).
toBe
(
0
);
list
=
controlbox
.
el
.
querySelector
(
'
div.rooms-list-container
'
);
expect
(
_
.
includes
(
list
.
classList
,
'
hidden
'
)).
toBeTruthy
();
done
();
});
}
));
});
...
...
@@ -57,79 +59,81 @@
describe
(
"
A groupchat shown in the groupchats list
"
,
function
()
{
it
(
"
is highlighted if its currently open
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{
whitelisted_plugins
:
[
'
converse-roomslist
'
],
allow_bookmarks
:
false
// Makes testing easier, otherwise we
// have to mock stanza traffic.
},
function
(
done
,
_converse
)
{
spyOn
(
_converse
,
'
isSingleton
'
).
and
.
callFake
(
function
()
{
return
true
;
});
spyOn
(
_converse
,
'
isSingleton
'
).
and
.
callFake
(()
=>
true
);
let
room_els
,
item
;
test_utils
.
openControlBox
();
_converse
.
api
.
rooms
.
open
(
'
coven@chat.shakespeare.lit
'
,
{
'
nick
'
:
'
some1
'
});
let
room_els
=
_converse
.
rooms_list_view
.
el
.
querySelectorAll
(
"
.available-chatroom
"
);
expect
(
room_els
.
length
).
toBe
(
1
);
let
item
=
room_els
[
0
];
expect
(
u
.
hasClass
(
'
open
'
,
item
)).
toBe
(
true
);
expect
(
item
.
textContent
.
trim
()).
toBe
(
'
coven@chat.shakespeare.lit
'
);
_converse
.
api
.
rooms
.
open
(
'
coven@chat.shakespeare.lit
'
,
{
'
nick
'
:
'
some1
'
})
.
then
(()
=>
{
room_els
=
_converse
.
rooms_list_view
.
el
.
querySelectorAll
(
"
.available-chatroom
"
);
expect
(
room_els
.
length
).
toBe
(
1
);
_converse
.
api
.
rooms
.
open
(
'
balcony@chat.shakespeare.lit
'
,
{
'
nick
'
:
'
some1
'
});
room_els
=
_converse
.
rooms_list_view
.
el
.
querySelectorAll
(
"
.open-room
"
);
expect
(
room_els
.
length
).
toBe
(
2
);
item
=
room_els
[
0
];
expect
(
u
.
hasClass
(
'
open
'
,
item
)).
toBe
(
true
);
expect
(
item
.
textContent
.
trim
()).
toBe
(
'
coven@chat.shakespeare.lit
'
);
return
_converse
.
api
.
rooms
.
open
(
'
balcony@chat.shakespeare.lit
'
,
{
'
nick
'
:
'
some1
'
});
}).
then
(()
=>
{
room_els
=
_converse
.
rooms_list_view
.
el
.
querySelectorAll
(
"
.open-room
"
);
expect
(
room_els
.
length
).
toBe
(
2
);
room_els
=
_converse
.
rooms_list_view
.
el
.
querySelectorAll
(
"
.available-chatroom.open
"
);
expect
(
room_els
.
length
).
toBe
(
1
);
item
=
room_els
[
0
];
expect
(
item
.
textContent
.
trim
()).
toBe
(
'
balcony@chat.shakespeare.lit
'
);
done
();
room_els
=
_converse
.
rooms_list_view
.
el
.
querySelectorAll
(
"
.available-chatroom.open
"
);
expect
(
room_els
.
length
).
toBe
(
1
);
item
=
room_els
[
0
];
expect
(
item
.
textContent
.
trim
()).
toBe
(
'
balcony@chat.shakespeare.lit
'
);
done
();
});
}));
it
(
"
has an info icon which opens a details modal when clicked
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{
whitelisted_plugins
:
[
'
converse-roomslist
'
],
allow_bookmarks
:
false
// Makes testing easier, otherwise we
// have to mock stanza traffic.
},
function
(
done
,
_converse
)
{
let
view
;
test_utils
.
openControlBox
();
_converse
.
api
.
rooms
.
open
(
'
coven@chat.shakespeare.lit
'
,
{
'
nick
'
:
'
some1
'
})
;
const
view
=
_converse
.
chatboxviews
.
get
(
'
coven@chat.shakespeare.lit
'
);
const
last_stanza
=
_
.
last
(
_converse
.
connection
.
IQ_stanzas
).
nodeTree
;
const
IQ_id
=
last_stanza
.
getAttribute
(
'
id
'
)
;
const
features_stanza
=
$iq
({
'
from
'
:
'
coven@chat.shakespeare.lit
'
,
'
id
'
:
IQ_id
,
'
to
'
:
'
dummy@localhost/desktop
'
,
'
type
'
:
'
result
'
})
.
c
(
'
query
'
,
{
'
xmlns
'
:
'
http://jabber.org/protocol/disco#info
'
})
.
c
(
'
identity
'
,
{
'
category
'
:
'
conference
'
,
'
name
'
:
'
A Dark Cav
e
'
,
'
type
'
:
'
text
'
}).
up
()
.
c
(
'
feature
'
,
{
'
var
'
:
'
http://jabber.org/protocol/muc
'
}).
up
()
.
c
(
'
feature
'
,
{
'
var
'
:
'
muc_passwordprotected
'
}).
up
()
.
c
(
'
feature
'
,
{
'
var
'
:
'
muc_hidden
'
}).
up
()
.
c
(
'
feature
'
,
{
'
var
'
:
'
muc_temporary
'
}).
up
()
.
c
(
'
feature
'
,
{
'
var
'
:
'
muc_open
'
}).
up
()
.
c
(
'
feature
'
,
{
'
var
'
:
'
muc_unmoderated
'
}).
up
()
.
c
(
'
feature
'
,
{
'
var
'
:
'
muc_nonanonymous
'
}).
up
()
.
c
(
'
feature
'
,
{
'
var
'
:
'
urn:xmpp:mam:0
'
}).
up
()
.
c
(
'
x
'
,
{
'
xmlns
'
:
'
jabber:x:data
'
,
'
type
'
:
'
result
'
}
)
.
c
(
'
field
'
,
{
'
var
'
:
'
FORM_TYPE
'
,
'
type
'
:
'
hidden
'
})
.
c
(
'
value
'
).
t
(
'
http://jabber.org/protocol/muc#roominfo
'
).
up
().
up
(
)
.
c
(
'
field
'
,
{
'
type
'
:
'
text-single
'
,
'
var
'
:
'
muc#roominfo_description
'
,
'
label
'
:
'
Description
'
}
)
.
c
(
'
value
'
).
t
(
'
This is the description
'
).
up
().
up
(
)
.
c
(
'
field
'
,
{
'
type
'
:
'
text-single
'
,
'
var
'
:
'
muc#roominfo_occupants
'
,
'
label
'
:
'
Number of occupants
'
}
)
.
c
(
'
value
'
).
t
(
0
);
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
features_stanza
)
);
test_utils
.
waitUntil
(()
=>
view
.
model
.
get
(
'
connection_status
'
)
===
converse
.
ROOMSTATUS
.
CONNECTING
)
.
then
(
function
()
{
_converse
.
api
.
rooms
.
open
(
'
coven@chat.shakespeare.lit
'
,
{
'
nick
'
:
'
some1
'
})
.
then
(()
=>
{
view
=
_converse
.
chatboxviews
.
get
(
'
coven@chat.shakespeare.lit
'
)
;
const
last_stanza
=
_
.
last
(
_converse
.
connection
.
IQ_stanzas
).
nodeTree
;
const
IQ_id
=
last_stanza
.
getAttribute
(
'
id
'
);
const
features_stanza
=
$iq
({
'
from
'
:
'
coven@chat.shakespeare.lit
'
,
'
id
'
:
IQ_id
,
'
to
'
:
'
dummy@localhost/desktop
'
,
'
type
'
:
'
result
'
})
.
c
(
'
query
'
,
{
'
xmlns
'
:
'
http://jabber.org/protocol/disco#info
'
})
.
c
(
'
identity
'
,
{
'
category
'
:
'
conferenc
e
'
,
'
name
'
:
'
A Dark Cave
'
,
'
type
'
:
'
text
'
}).
up
()
.
c
(
'
feature
'
,
{
'
var
'
:
'
http://jabber.org/protocol/muc
'
}).
up
()
.
c
(
'
feature
'
,
{
'
var
'
:
'
muc_passwordprotected
'
}).
up
()
.
c
(
'
feature
'
,
{
'
var
'
:
'
muc_hidden
'
}).
up
()
.
c
(
'
feature
'
,
{
'
var
'
:
'
muc_temporary
'
}).
up
()
.
c
(
'
feature
'
,
{
'
var
'
:
'
muc_open
'
}).
up
()
.
c
(
'
feature
'
,
{
'
var
'
:
'
muc_unmoderated
'
}).
up
()
.
c
(
'
feature
'
,
{
'
var
'
:
'
muc_nonanonymous
'
}).
up
()
.
c
(
'
feature
'
,
{
'
var
'
:
'
urn:xmpp:mam:0
'
}).
up
(
)
.
c
(
'
x
'
,
{
'
xmlns
'
:
'
jabber:x:data
'
,
'
type
'
:
'
result
'
})
.
c
(
'
field
'
,
{
'
var
'
:
'
FORM_TYPE
'
,
'
type
'
:
'
hidden
'
}
)
.
c
(
'
value
'
).
t
(
'
http://jabber.org/protocol/muc#roominfo
'
).
up
().
up
(
)
.
c
(
'
field
'
,
{
'
type
'
:
'
text-single
'
,
'
var
'
:
'
muc#roominfo_description
'
,
'
label
'
:
'
Description
'
}
)
.
c
(
'
value
'
).
t
(
'
This is the description
'
).
up
().
up
(
)
.
c
(
'
field
'
,
{
'
type
'
:
'
text-single
'
,
'
var
'
:
'
muc#roominfo_occupants
'
,
'
label
'
:
'
Number of occupants
'
})
.
c
(
'
value
'
).
t
(
0
);
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
features_stanza
));
return
test_utils
.
waitUntil
(()
=>
view
.
model
.
get
(
'
connection_status
'
)
===
converse
.
ROOMSTATUS
.
CONNECTING
)
})
.
then
(
function
()
{
var
presence
=
$pres
({
to
:
_converse
.
connection
.
jid
,
from
:
'
coven@chat.shakespeare.lit/some1
'
,
...
...
@@ -201,23 +205,22 @@
},
function
(
done
,
_converse
)
{
spyOn
(
window
,
'
confirm
'
).
and
.
callFake
(
function
()
{
return
true
;
});
spyOn
(
window
,
'
confirm
'
).
and
.
callFake
(()
=>
true
);
expect
(
_converse
.
chatboxes
.
length
).
toBe
(
1
);
test_utils
.
openChatRoom
(
_converse
,
'
lounge
'
,
'
conference.shakespeare.lit
'
,
'
JC
'
);
expect
(
_converse
.
chatboxes
.
length
).
toBe
(
2
);
var
room_els
=
_converse
.
rooms_list_view
.
el
.
querySelectorAll
(
"
.open-room
"
);
expect
(
room_els
.
length
).
toBe
(
1
);
var
close_el
=
_converse
.
rooms_list_view
.
el
.
querySelector
(
"
.close-room
"
);
close_el
.
click
();
expect
(
window
.
confirm
).
toHaveBeenCalledWith
(
'
Are you sure you want to leave the groupchat lounge@conference.shakespeare.lit?
'
);
room_els
=
_converse
.
rooms_list_view
.
el
.
querySelectorAll
(
"
.open-room
"
);
expect
(
room_els
.
length
).
toBe
(
0
);
expect
(
_converse
.
chatboxes
.
length
).
toBe
(
1
);
done
();
test_utils
.
openChatRoom
(
_converse
,
'
lounge
'
,
'
conference.shakespeare.lit
'
,
'
JC
'
)
.
then
(()
=>
{
expect
(
_converse
.
chatboxes
.
length
).
toBe
(
2
);
var
room_els
=
_converse
.
rooms_list_view
.
el
.
querySelectorAll
(
"
.open-room
"
);
expect
(
room_els
.
length
).
toBe
(
1
);
var
close_el
=
_converse
.
rooms_list_view
.
el
.
querySelector
(
"
.close-room
"
);
close_el
.
click
();
expect
(
window
.
confirm
).
toHaveBeenCalledWith
(
'
Are you sure you want to leave the groupchat lounge@conference.shakespeare.lit?
'
);
room_els
=
_converse
.
rooms_list_view
.
el
.
querySelectorAll
(
"
.open-room
"
);
expect
(
room_els
.
length
).
toBe
(
0
);
expect
(
_converse
.
chatboxes
.
length
).
toBe
(
1
);
done
();
});
}));
it
(
"
shows unread messages directed at the user
"
,
mock
.
initConverseWithAsync
(
...
...
spec/spoilers.js
View file @
506aa331
...
...
@@ -92,12 +92,14 @@
it
(
"
can be sent without a hint
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
test_utils
.
createContacts
(
_converse
,
'
current
'
,
1
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
test_utils
.
openControlBox
();
var
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
const
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
// XXX: We need to send a presence from the contact, so that we
// have a resource, that resource is then queried to see
...
...
@@ -108,9 +110,9 @@
'
to
'
:
'
dummy@localhost
'
});
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
presence
));
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
)
;
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
contact_jid
+
'
/phone
'
,
[],
[
Strophe
.
NS
.
SPOILER
]).
then
(
function
()
{
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
)
.
then
(()
=>
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
contact_jid
+
'
/phone
'
,
[],
[
Strophe
.
NS
.
SPOILER
]))
.
then
(()
=>
{
var
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
spyOn
(
view
,
'
onMessageSubmitted
'
).
and
.
callThrough
();
spyOn
(
_converse
.
connection
,
'
send
'
);
...
...
@@ -167,10 +169,12 @@
it
(
"
can be sent with a hint
"
,
mock
.
initConverseWithPromises
(
null
,
[
'
rosterGroupsFetched
'
],
{},
null
,
[
'
rosterGroupsFetched
'
,
'
chatBoxesFetched
'
],
{},
function
(
done
,
_converse
)
{
test_utils
.
createContacts
(
_converse
,
'
current
'
);
test_utils
.
createContacts
(
_converse
,
'
current
'
,
1
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
test_utils
.
openControlBox
();
var
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
...
...
@@ -183,9 +187,9 @@
'
to
'
:
'
dummy@localhost
'
});
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
presence
));
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
)
;
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
contact_jid
+
'
/phone
'
,
[],
[
Strophe
.
NS
.
SPOILER
]).
then
(
function
()
{
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
)
.
then
(()
=>
test_utils
.
waitUntilDiscoConfirmed
(
_converse
,
contact_jid
+
'
/phone
'
,
[],
[
Strophe
.
NS
.
SPOILER
]))
.
then
(()
=>
{
var
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
var
spoiler_toggle
=
view
.
el
.
querySelector
(
'
.toggle-compose-spoiler
'
);
spoiler_toggle
.
click
();
...
...
@@ -206,17 +210,17 @@
expect
(
view
.
onMessageSubmitted
).
toHaveBeenCalled
();
/* Test the XML stanza
*
* <message from="dummy@localhost/resource"
* to="max.frankfurter@localhost"
* type="chat"
* id="4547c38b-d98b-45a5-8f44-b4004dbc335e"
* xmlns="jabber:client">
* <body>This is the spoiler</body>
* <active xmlns="http://jabber.org/protocol/chatstates"/>
* <spoiler xmlns="urn:xmpp:spoiler:0">This is the hint</spoiler>
* </message>"
*/
*
* <message from="dummy@localhost/resource"
* to="max.frankfurter@localhost"
* type="chat"
* id="4547c38b-d98b-45a5-8f44-b4004dbc335e"
* xmlns="jabber:client">
* <body>This is the spoiler</body>
* <active xmlns="http://jabber.org/protocol/chatstates"/>
* <spoiler xmlns="urn:xmpp:spoiler:0">This is the hint</spoiler>
* </message>"
*/
var
stanza
=
_converse
.
connection
.
send
.
calls
.
argsFor
(
0
)[
0
].
tree
();
var
spoiler_el
=
stanza
.
querySelector
(
'
spoiler[xmlns="urn:xmpp:spoiler:0"]
'
);
...
...
spec/user-details-modal.js
View file @
506aa331
...
...
@@ -58,16 +58,17 @@
test_utils
.
createContacts
(
_converse
,
'
current
'
);
_converse
.
emit
(
'
rosterContactsFetched
'
);
let
view
,
modal
;
const
contact_jid
=
mock
.
cur_names
[
0
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
)
;
const
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
const
show_modal_button
=
view
.
el
.
querySelector
(
'
.show-user-details-modal
'
);
expect
(
u
.
isVisible
(
show_modal_button
)).
toBeTruthy
();
show_modal_button
.
click
();
const
modal
=
view
.
user_details_modal
;
test_utils
.
waitUntil
(()
=>
u
.
isVisible
(
modal
.
el
),
2000
)
.
then
(
function
()
{
test_utils
.
openChatBoxFor
(
_converse
,
contact_jid
)
.
then
(()
=>
{
view
=
_converse
.
chatboxviews
.
get
(
contact_jid
);
const
show_modal_button
=
view
.
el
.
querySelector
(
'
.show-user-details-modal
'
);
expect
(
u
.
isVisible
(
show_modal_button
)).
toBeTruthy
();
show_modal_button
.
click
();
modal
=
view
.
user_details_modal
;
return
test_utils
.
waitUntil
(()
=>
u
.
isVisible
(
modal
.
el
),
2000
);
})
.
then
(
function
()
{
spyOn
(
window
,
'
confirm
'
).
and
.
returnValue
(
true
);
spyOn
(
view
.
model
.
contact
,
'
removeFromRoster
'
).
and
.
callFake
(
function
(
callback
,
errback
)
{
errback
();
...
...
src/converse-muc-views.js
View file @
506aa331
...
...
@@ -561,8 +561,7 @@
const
handler
=
()
=>
{
if
(
!
u
.
isPersistableModel
(
this
.
model
))
{
// Happens during tests, nothing to do if this
// is a hanging chatbox (i.e. not in the
// collection anymore).
// is a hanging chatbox (i.e. not in the collection anymore).
return
;
}
this
.
populateAndJoin
();
...
...
src/i18n.js
View file @
506aa331
...
...
@@ -148,8 +148,13 @@
);
xhr
.
onload
=
function
()
{
if
(
xhr
.
status
>=
200
&&
xhr
.
status
<
400
)
{
jed_instance
=
new
Jed
(
window
.
JSON
.
parse
(
xhr
.
responseText
));
resolve
();
try
{
const
data
=
window
.
JSON
.
parse
(
xhr
.
responseText
);
jed_instance
=
new
Jed
(
data
);
resolve
();
}
catch
(
e
)
{
xhr
.
onerror
(
e
);
}
}
else
{
xhr
.
onerror
();
}
...
...
tests/utils.js
View file @
506aa331
...
...
@@ -98,8 +98,9 @@
return
views
;
};
utils
.
openChatBoxFor
=
function
(
converse
,
jid
)
{
return
converse
.
roster
.
get
(
jid
).
trigger
(
"
open
"
);
utils
.
openChatBoxFor
=
function
(
_converse
,
jid
)
{
_converse
.
roster
.
get
(
jid
).
trigger
(
"
open
"
);
return
utils
.
waitUntil
(()
=>
_converse
.
chatboxviews
.
get
(
jid
));
};
utils
.
openChatRoomViaModal
=
function
(
_converse
,
jid
,
nick
)
{
...
...
@@ -121,64 +122,64 @@
};
utils
.
openChatRoom
=
function
(
_converse
,
room
,
server
,
nick
)
{
_converse
.
api
.
rooms
.
open
(
`
${
room
}
@
${
server
}
`
);
return
_converse
.
api
.
rooms
.
open
(
`
${
room
}
@
${
server
}
`
);
};
utils
.
openAndEnterChatRoom
=
function
(
_converse
,
room
,
server
,
nick
)
{
let
last_stanza
;
return
new
Promise
(
function
(
resolve
,
reject
)
{
_converse
.
api
.
rooms
.
open
(
`
${
room
}
@
${
server
}
`
);
const
view
=
_converse
.
chatboxviews
.
get
((
room
+
'
@
'
+
server
).
toLowerCase
());
// We pretend this is a new room, so no disco info is returned.
let
last_stanza
=
_
.
last
(
_converse
.
connection
.
IQ_stanzas
).
nodeTree
;
const
IQ_id
=
last_stanza
.
getAttribute
(
'
id
'
);
const
features_stanza
=
$iq
({
'
from
'
:
room
+
'
@
'
+
server
,
'
id
'
:
IQ_id
,
'
to
'
:
nick
+
'
@
'
+
server
,
'
type
'
:
'
error
'
}).
c
(
'
error
'
,
{
'
type
'
:
'
cancel
'
})
.
c
(
'
item-not-found
'
,
{
'
xmlns
'
:
"
urn:ietf:params:xml:ns:xmpp-stanzas
"
});
_converse
.
connection
.
_dataRecv
(
utils
.
createRequest
(
features_stanza
));
utils
.
waitUntil
(()
=>
{
return
_
.
filter
(
_converse
.
connection
.
IQ_stanzas
,
(
node
)
=>
{
const
query
=
node
.
nodeTree
.
querySelector
(
'
query
'
);
if
(
query
&&
query
.
getAttribute
(
'
node
'
)
===
'
x-roomuser-item
'
)
{
last_stanza
=
node
.
nodeTree
;
return
true
;
}
}).
length
}).
then
(
function
()
{
// The XMPP server returns the reserved nick for this user.
return
new
Promise
((
resolve
,
reject
)
=>
{
return
_converse
.
api
.
rooms
.
open
(
`
${
room
}
@
${
server
}
`
).
then
(()
=>
{
const
view
=
_converse
.
chatboxviews
.
get
((
room
+
'
@
'
+
server
).
toLowerCase
());
// We pretend this is a new room, so no disco info is returned.
let
last_stanza
=
_
.
last
(
_converse
.
connection
.
IQ_stanzas
).
nodeTree
;
const
IQ_id
=
last_stanza
.
getAttribute
(
'
id
'
);
const
stanza
=
$iq
({
'
type
'
:
'
result
'
,
'
id
'
:
IQ_id
,
'
from
'
:
view
.
model
.
get
(
'
jid
'
),
'
to
'
:
_converse
.
connection
.
jid
}).
c
(
'
query
'
,
{
'
xmlns
'
:
'
http://jabber.org/protocol/disco#info
'
,
'
node
'
:
'
x-roomuser-item
'
})
.
c
(
'
identity
'
,
{
'
category
'
:
'
conference
'
,
'
name
'
:
nick
,
'
type
'
:
'
text
'
});
_converse
.
connection
.
_dataRecv
(
utils
.
createRequest
(
stanza
));
// The user has just entered the room (because join was called)
// and receives their own presence from the server.
// See example 24: http://xmpp.org/extensions/xep-0045.html#enter-pres
var
presence
=
$pres
({
to
:
_converse
.
connection
.
jid
,
from
:
room
+
'
@
'
+
server
+
'
/
'
+
nick
,
id
:
'
DC352437-C019-40EC-B590-AF29E879AF97
'
}).
c
(
'
x
'
).
attrs
({
xmlns
:
'
http://jabber.org/protocol/muc#user
'
})
.
c
(
'
item
'
).
attrs
({
affiliation
:
'
member
'
,
jid
:
_converse
.
bare_jid
,
role
:
'
participant
'
}).
up
()
.
c
(
'
status
'
).
attrs
({
code
:
'
110
'
});
_converse
.
connection
.
_dataRecv
(
utils
.
createRequest
(
presence
));
resolve
();
const
features_stanza
=
$iq
({
'
from
'
:
room
+
'
@
'
+
server
,
'
id
'
:
IQ_id
,
'
to
'
:
nick
+
'
@
'
+
server
,
'
type
'
:
'
error
'
}).
c
(
'
error
'
,
{
'
type
'
:
'
cancel
'
})
.
c
(
'
item-not-found
'
,
{
'
xmlns
'
:
"
urn:ietf:params:xml:ns:xmpp-stanzas
"
});
_converse
.
connection
.
_dataRecv
(
utils
.
createRequest
(
features_stanza
));
utils
.
waitUntil
(()
=>
{
return
_
.
filter
(
_converse
.
connection
.
IQ_stanzas
,
(
node
)
=>
{
const
query
=
node
.
nodeTree
.
querySelector
(
'
query
'
);
if
(
query
&&
query
.
getAttribute
(
'
node
'
)
===
'
x-roomuser-item
'
)
{
last_stanza
=
node
.
nodeTree
;
return
true
;
}
}).
length
}).
then
(
function
()
{
// The XMPP server returns the reserved nick for this user.
const
IQ_id
=
last_stanza
.
getAttribute
(
'
id
'
);
const
stanza
=
$iq
({
'
type
'
:
'
result
'
,
'
id
'
:
IQ_id
,
'
from
'
:
view
.
model
.
get
(
'
jid
'
),
'
to
'
:
_converse
.
connection
.
jid
}).
c
(
'
query
'
,
{
'
xmlns
'
:
'
http://jabber.org/protocol/disco#info
'
,
'
node
'
:
'
x-roomuser-item
'
})
.
c
(
'
identity
'
,
{
'
category
'
:
'
conference
'
,
'
name
'
:
nick
,
'
type
'
:
'
text
'
});
_converse
.
connection
.
_dataRecv
(
utils
.
createRequest
(
stanza
));
// The user has just entered the room (because join was called)
// and receives their own presence from the server.
// See example 24: http://xmpp.org/extensions/xep-0045.html#enter-pres
var
presence
=
$pres
({
to
:
_converse
.
connection
.
jid
,
from
:
room
+
'
@
'
+
server
+
'
/
'
+
nick
,
id
:
'
DC352437-C019-40EC-B590-AF29E879AF97
'
}).
c
(
'
x
'
).
attrs
({
xmlns
:
'
http://jabber.org/protocol/muc#user
'
})
.
c
(
'
item
'
).
attrs
({
affiliation
:
'
member
'
,
jid
:
_converse
.
bare_jid
,
role
:
'
participant
'
}).
up
()
.
c
(
'
status
'
).
attrs
({
code
:
'
110
'
});
_converse
.
connection
.
_dataRecv
(
utils
.
createRequest
(
presence
));
resolve
();
}).
catch
(
_
.
partial
(
console
.
error
,
_
));
}).
catch
(
_
.
partial
(
console
.
error
,
_
));
}).
catch
(
_
.
partial
(
console
.
error
,
_
));
};
...
...
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