2017-06-27 14:55:11 +02:00
set _global ( '$' , global . make _zjquery ( ) ) ;
2017-06-29 20:46:27 +02:00
set _global ( 'i18n' , global . stub _i18n ) ;
2017-02-24 16:18:56 +01:00
set _global ( 'page_params' , {
2017-07-07 03:59:08 +02:00
use _websockets : true ,
2017-02-24 16:18:56 +01:00
} ) ;
2017-07-07 03:59:08 +02:00
set _global ( 'navigator' , { } ) ;
2017-02-24 16:18:56 +01:00
set _global ( 'document' , {
location : {
} ,
} ) ;
2017-06-28 19:24:53 +02:00
set _global ( 'channel' , { } ) ;
2017-06-28 20:28:18 +02:00
set _global ( 'templates' , { } ) ;
2017-02-24 16:18:56 +01:00
2017-06-27 14:55:11 +02:00
var noop = function ( ) { } ;
2017-06-29 06:54:10 +02:00
set _global ( 'blueslip' , { } ) ;
set _global ( 'drafts' , {
delete _draft _after _send : noop ,
} ) ;
set _global ( 'resize' , {
resize _bottom _whitespace : noop ,
} ) ;
set _global ( 'feature_flags' , {
resize _bottom _whitespace : noop ,
} ) ;
set _global ( 'echo' , { } ) ;
2017-07-07 03:59:08 +02:00
set _global ( 'socket' , { } ) ;
set _global ( 'Socket' , function ( ) {
return global . socket ;
} ) ;
2017-07-08 00:11:52 +02:00
set _global ( 'stream_edit' , { } ) ;
2017-06-29 06:54:10 +02:00
2017-07-06 21:57:25 +02:00
// Setting these up so that we can test that links to uploads within messages are
// automatically converted to server relative links.
global . document . location . protocol = 'https:' ;
global . document . location . host = 'foo.com' ;
2017-02-24 16:18:56 +01:00
add _dependencies ( {
2017-06-27 14:55:11 +02:00
common : 'js/common' ,
2017-04-15 01:15:59 +02:00
compose _state : 'js/compose_state' ,
2017-06-29 06:54:10 +02:00
compose _ui : 'js/compose_ui.js' ,
2017-06-28 13:10:46 +02:00
Handlebars : 'handlebars' ,
2017-02-24 23:51:23 +01:00
people : 'js/people' ,
2017-02-24 16:18:56 +01:00
stream _data : 'js/stream_data' ,
util : 'js/util' ,
} ) ;
var compose = require ( 'js/compose.js' ) ;
2017-07-07 03:59:08 +02:00
page _params . use _websockets = false ;
2017-02-24 16:18:56 +01:00
2017-02-24 23:51:23 +01:00
var me = {
email : 'me@example.com' ,
user _id : 30 ,
full _name : 'Me Myself' ,
} ;
var alice = {
email : 'alice@example.com' ,
user _id : 31 ,
full _name : 'Alice' ,
} ;
var bob = {
email : 'bob@example.com' ,
user _id : 32 ,
full _name : 'Bob' ,
} ;
people . add ( me ) ;
people . initialize _current _user ( me . user _id ) ;
people . add ( alice ) ;
people . add ( bob ) ;
2017-06-28 21:52:36 +02:00
( function test _update _email ( ) {
compose _state . recipient ( '' ) ;
assert . equal ( compose . update _email ( ) , undefined ) ;
compose _state . recipient ( 'bob@example.com' ) ;
compose . update _email ( 32 , 'bob_alias@example.com' ) ;
assert . equal ( compose _state . recipient ( ) , 'bob_alias@example.com' ) ;
} ( ) ) ;
2017-06-28 12:55:04 +02:00
( function test _validate _stream _message _address _info ( ) {
var sub = {
stream _id : 101 ,
name : 'social' ,
subscribed : true ,
} ;
stream _data . add _sub ( 'social' , sub ) ;
assert ( compose . validate _stream _message _address _info ( 'social' ) ) ;
2017-06-28 13:10:46 +02:00
$ ( '#stream' ) . select ( noop ) ;
assert ( ! compose . validate _stream _message _address _info ( 'foobar' ) ) ;
assert . equal ( $ ( '#error-msg' ) . html ( ) , "<p>The stream <b>foobar</b> does not exist.</p><p>Manage your subscriptions <a href='#streams/all'>on your Streams page</a>.</p>" ) ;
2017-06-28 19:24:53 +02:00
sub . subscribed = false ;
stream _data . add _sub ( 'social' , sub ) ;
assert ( ! compose . validate _stream _message _address _info ( 'social' ) ) ;
assert . equal ( $ ( '#error-msg' ) . html ( ) , "<p>You're not subscribed to the stream <b>social</b>.</p><p>Manage your subscriptions <a href='#streams/all'>on your Streams page</a>.</p>" ) ;
global . page _params . narrow _stream = false ;
channel . post = function ( payload ) {
assert . equal ( payload . data . stream , 'social' ) ;
payload . data . subscribed = true ;
payload . success ( payload . data ) ;
} ;
assert ( compose . validate _stream _message _address _info ( 'social' ) ) ;
sub . name = 'Frontend' ;
sub . stream _id = 102 ;
stream _data . add _sub ( 'Frontend' , sub ) ;
channel . post = function ( payload ) {
assert . equal ( payload . data . stream , 'Frontend' ) ;
payload . data . subscribed = false ;
payload . success ( payload . data ) ;
} ;
assert ( ! compose . validate _stream _message _address _info ( 'Frontend' ) ) ;
assert . equal ( $ ( '#error-msg' ) . html ( ) , "<p>You're not subscribed to the stream <b>Frontend</b>.</p><p>Manage your subscriptions <a href='#streams/all'>on your Streams page</a>.</p>" ) ;
channel . post = function ( payload ) {
assert . equal ( payload . data . stream , 'Frontend' ) ;
payload . error ( { status : 404 } ) ;
} ;
assert ( ! compose . validate _stream _message _address _info ( 'Frontend' ) ) ;
assert . equal ( $ ( '#error-msg' ) . html ( ) , "<p>The stream <b>Frontend</b> does not exist.</p><p>Manage your subscriptions <a href='#streams/all'>on your Streams page</a>.</p>" ) ;
channel . post = function ( payload ) {
assert . equal ( payload . data . stream , 'social' ) ;
payload . error ( { status : 500 } ) ;
} ;
assert ( ! compose . validate _stream _message _address _info ( 'social' ) ) ;
assert . equal ( $ ( '#error-msg' ) . html ( ) , i18n . t ( "Error checking subscription" ) ) ;
2017-06-28 12:55:04 +02:00
} ( ) ) ;
2017-02-24 23:51:23 +01:00
2017-06-27 14:55:11 +02:00
( function test _validate ( ) {
$ ( "#compose-send-button" ) . removeAttr ( 'disabled' ) ;
$ ( "#compose-send-button" ) . focus ( ) ;
$ ( "#sending-indicator" ) . hide ( ) ;
$ ( "#new_message_content" ) . select ( noop ) ;
assert ( ! compose . validate ( ) ) ;
assert ( ! $ ( "#sending-indicator" ) . visible ( ) ) ;
assert ( ! $ ( "#compose-send-button" ) . is _focused ( ) ) ;
assert . equal ( $ ( "#compose-send-button" ) . attr ( 'disabled' ) , undefined ) ;
2017-06-29 20:48:49 +02:00
assert . equal ( $ ( '#error-msg' ) . html ( ) , i18n . t ( 'You have nothing to send!' ) ) ;
2017-06-27 14:55:11 +02:00
$ ( "#new_message_content" ) . val ( 'foobarfoobar' ) ;
var zephyr _checked = false ;
$ ( "#zephyr-mirror-error" ) . is = function ( ) {
if ( ! zephyr _checked ) {
zephyr _checked = true ;
return true ;
}
return false ;
} ;
assert ( ! compose . validate ( ) ) ;
assert ( zephyr _checked ) ;
2017-06-29 20:48:49 +02:00
assert . equal ( $ ( '#error-msg' ) . html ( ) , i18n . t ( 'You need to be running Zephyr mirroring in order to send messages!' ) ) ;
2017-06-27 14:55:11 +02:00
compose _state . set _message _type ( 'private' ) ;
compose _state . recipient ( '' ) ;
$ ( "#private_message_recipient" ) . select ( noop ) ;
assert ( ! compose . validate ( ) ) ;
2017-06-29 20:48:49 +02:00
assert . equal ( $ ( '#error-msg' ) . html ( ) , i18n . t ( 'Please specify at least one recipient' ) ) ;
2017-06-27 14:55:11 +02:00
compose _state . recipient ( 'foo@zulip.com' ) ;
global . page _params . realm _is _zephyr _mirror _realm = true ;
assert ( compose . validate ( ) ) ;
global . page _params . realm _is _zephyr _mirror _realm = false ;
assert ( ! compose . validate ( ) ) ;
assert . equal ( $ ( '#error-msg' ) . html ( ) , i18n . t ( 'The recipient foo@zulip.com is not valid' , { } ) ) ;
compose _state . recipient ( 'foo@zulip.com,alice@zulip.com' ) ;
assert ( ! compose . validate ( ) ) ;
assert . equal ( $ ( '#error-msg' ) . html ( ) , i18n . t ( 'The recipients foo@zulip.com,alice@zulip.com are not valid' , { } ) ) ;
people . add _in _realm ( bob ) ;
compose _state . recipient ( 'bob@example.com' ) ;
assert ( compose . validate ( ) ) ;
compose _state . set _message _type ( 'stream' ) ;
compose _state . stream _name ( '' ) ;
$ ( "#stream" ) . select ( noop ) ;
assert ( ! compose . validate ( ) ) ;
2017-06-29 20:48:49 +02:00
assert . equal ( $ ( '#error-msg' ) . html ( ) , i18n . t ( 'Please specify a stream' ) ) ;
2017-06-27 14:55:11 +02:00
compose _state . stream _name ( 'Denmark' ) ;
global . page _params . realm _mandatory _topics = true ;
compose _state . subject ( '' ) ;
$ ( "#subject" ) . select ( noop ) ;
assert ( ! compose . validate ( ) ) ;
2017-06-29 20:48:49 +02:00
assert . equal ( $ ( '#error-msg' ) . html ( ) , i18n . t ( 'Please specify a topic' ) ) ;
2017-06-27 14:55:11 +02:00
} ( ) ) ;
2017-06-28 21:36:57 +02:00
( function test _get _invalid _recipient _emails ( ) {
var feedback _bot = {
email : 'feedback@example.com' ,
user _id : 124 ,
full _name : 'Feedback Bot' ,
} ;
global . page _params . cross _realm _bots = [ feedback _bot ] ;
global . page _params . user _id = 30 ;
people . initialize ( ) ;
compose _state . recipient ( 'feedback@example.com' ) ;
assert . deepEqual ( compose . get _invalid _recipient _emails ( ) , [ ] ) ;
} ( ) ) ;
2017-06-28 20:28:18 +02:00
( function test _validate _stream _message ( ) {
// This test is in kind of continuation to test_validate but since it is
// primarly used to get coverage over functions called from validate()
// we are seperating it up in different test. Though their relative position
// of execution should not be changed.
global . page _params . realm _mandatory _topics = false ;
var sub = {
stream _id : 101 ,
name : 'social' ,
subscribed : true ,
} ;
stream _data . add _sub ( 'social' , sub ) ;
compose _state . stream _name ( 'social' ) ;
assert ( compose . validate ( ) ) ;
assert ( ! $ ( "#compose-all-everyone" ) . visible ( ) ) ;
assert ( ! $ ( "#send-status" ) . visible ( ) ) ;
stream _data . get _subscriber _count = function ( stream _name ) {
assert . equal ( stream _name , 'social' ) ;
return 16 ;
} ;
global . templates . render = function ( template _name , data ) {
assert . equal ( template _name , 'compose_all_everyone' ) ;
assert . equal ( data . count , 16 ) ;
return 'compose_all_everyone_stub' ;
} ;
$ ( '#compose-all-everyone' ) . is = function ( sel ) {
if ( sel === ':visible' ) {
return $ ( '#compose-all-everyone' ) . visible ( ) ;
}
} ;
var compose _content ;
$ ( '#compose-all-everyone' ) . append = function ( data ) {
compose _content = data ;
} ;
compose _state . message _content ( 'Hey @all' ) ;
assert ( ! compose . validate ( ) ) ;
assert . equal ( $ ( "#compose-send-button" ) . attr ( 'disabled' ) , undefined ) ;
assert ( ! $ ( "#send-status" ) . visible ( ) ) ;
assert . equal ( compose _content , 'compose_all_everyone_stub' ) ;
assert ( $ ( "#compose-all-everyone" ) . visible ( ) ) ;
} ( ) ) ;
2017-06-29 06:54:10 +02:00
( function test _send _message _success ( ) {
blueslip . error = noop ;
blueslip . log = noop ;
$ ( "#new_message_content" ) . val ( 'foobarfoobar' ) ;
$ ( "#new_message_content" ) . blur ( ) ;
$ ( "#send-status" ) . show ( ) ;
$ ( "#compose-send-button" ) . attr ( 'disabled' , 'disabled' ) ;
$ ( "#sending-indicator" ) . show ( ) ;
global . feature _flags . log _send _times = true ;
global . feature _flags . collect _send _times = true ;
var set _timeout _called = false ;
global . patch _builtin ( 'setTimeout' , function ( func , delay ) {
assert . equal ( delay , 5000 ) ;
func ( ) ;
set _timeout _called = true ;
} ) ;
var server _events _triggered ;
global . server _events = {
restart _get _events : function ( ) {
server _events _triggered = true ;
} ,
} ;
var reify _message _id _checked ;
echo . reify _message _id = function ( local _id , message _id ) {
assert . equal ( local _id , 1001 ) ;
assert . equal ( message _id , 12 ) ;
reify _message _id _checked = true ;
} ;
var test _date = 'Wed Jun 28 2017 22:12:48 GMT+0000 (UTC)' ;
compose . send _message _success ( 1001 , 12 , new Date ( test _date ) , false ) ;
assert . equal ( $ ( "#new_message_content" ) . val ( ) , '' ) ;
assert ( $ ( "#new_message_content" ) . is _focused ( ) ) ;
assert ( ! $ ( "#send-status" ) . visible ( ) ) ;
assert . equal ( $ ( "#compose-send-button" ) . attr ( 'disabled' ) , undefined ) ;
assert ( ! $ ( "#sending-indicator" ) . visible ( ) ) ;
assert . equal ( _ . keys ( compose . send _times _data ) . length , 1 ) ;
assert . equal ( compose . send _times _data [ 12 ] . start . getTime ( ) , new Date ( test _date ) . getTime ( ) ) ;
assert ( ! compose . send _times _data [ 12 ] . locally _echoed ) ;
assert ( reify _message _id _checked ) ;
assert ( server _events _triggered ) ;
assert ( set _timeout _called ) ;
} ( ) ) ;
2017-06-29 14:02:42 +02:00
( function test _mark _rendered _content _disparity ( ) {
compose . mark _rendered _content _disparity ( 13 , true ) ;
assert . deepEqual ( compose . send _times _data [ 13 ] , { rendered _content _disparity : true } ) ;
} ( ) ) ;
2017-06-29 14:31:26 +02:00
( function test _report _as _received ( ) {
var msg = {
id : 12 ,
sent _by _me : true ,
} ;
var set _timeout _called = false ;
global . patch _builtin ( 'setTimeout' , function ( func , delay ) {
assert . equal ( delay , 0 ) ;
func ( ) ;
set _timeout _called = true ;
} ) ;
compose . send _times _data [ 12 ] . locally _echoed = true ;
channel . post = function ( payload ) {
assert . equal ( payload . url , '/json/report_send_time' ) ;
assert . equal ( typeof ( payload . data . time ) , 'string' ) ;
assert ( payload . data . locally _echoed ) ;
assert ( ! payload . data . rendered _content _disparity ) ;
} ;
compose . report _as _received ( msg ) ;
assert . equal ( typeof ( compose . send _times _data [ 12 ] . received ) , 'object' ) ;
assert . equal ( typeof ( compose . send _times _data [ 12 ] . displayed ) , 'object' ) ;
assert ( set _timeout _called ) ;
delete compose . send _times _data [ 13 ] ;
msg . id = 13 ;
compose . report _as _received ( msg ) ;
assert . equal ( typeof ( compose . send _times _data [ 13 ] . received ) , 'object' ) ;
assert . equal ( typeof ( compose . send _times _data [ 13 ] . displayed ) , 'object' ) ;
} ( ) ) ;
2017-07-06 21:57:25 +02:00
( function test _send _message ( ) {
// This is the common setup stuff for all of the four tests.
var stub _state ;
function initialize _state _stub _dict ( ) {
stub _state = { } ;
stub _state . local _id _counter = 0 ;
stub _state . send _msg _ajax _post _called = 0 ;
stub _state . get _events _running _called = 0 ;
stub _state . server _events _triggered = 0 ;
stub _state . reify _message _id _checked = 0 ;
return stub _state ;
}
global . patch _builtin ( 'setTimeout' , function ( func ) {
func ( ) ;
} ) ;
global . server _events = {
restart _get _events : function ( ) {
stub _state . server _events _triggered += 1 ;
} ,
assert _get _events _running : function ( ) {
stub _state . get _events _running _called += 1 ;
} ,
} ;
// Tests start here.
( function test _message _send _success _codepath ( ) {
stub _state = initialize _state _stub _dict ( ) ;
compose _state . subject ( '' ) ;
compose _state . set _message _type ( 'private' ) ;
page _params . user _id = 101 ;
compose _state . recipient ( 'alice@example.com' ) ;
echo . try _deliver _locally = function ( ) {
stub _state . local _id _counter += 1 ;
return stub _state . local _id _counter ;
} ;
channel . post = function ( payload ) {
var single _msg = {
type : 'private' ,
content : '[foobar](/user_uploads/123456)' ,
sender _id : 101 ,
queue _id : undefined ,
stream : '' ,
subject : '' ,
to : '["alice@example.com"]' ,
reply _to : 'alice@example.com' ,
private _message _recipient : 'alice@example.com' ,
to _user _ids : '31' ,
local _id : 1 ,
} ;
assert . equal ( payload . url , '/json/messages' ) ;
assert . equal ( _ . keys ( payload . data ) . length , 11 ) ;
assert . deepEqual ( payload . data , single _msg ) ;
payload . data . id = stub _state . local _id _counter ;
payload . success ( payload . data ) ;
stub _state . send _msg _ajax _post _called += 1 ;
} ;
echo . reify _message _id = function ( local _id , message _id ) {
assert . equal ( typeof ( local _id ) , 'number' ) ;
assert . equal ( typeof ( message _id ) , 'number' ) ;
stub _state . reify _message _id _checked += 1 ;
} ;
compose . send _times _data = { } ;
// Setting message content with a host server link and we will assert
// later that this has been converted to a relative link.
$ ( "#new_message_content" ) . val ( '[foobar]' +
'(https://foo.com/user_uploads/123456)' ) ;
$ ( "#new_message_content" ) . blur ( ) ;
$ ( "#send-status" ) . show ( ) ;
$ ( "#compose-send-button" ) . attr ( 'disabled' , 'disabled' ) ;
$ ( "#sending-indicator" ) . show ( ) ;
compose . send _message ( ) ;
var state = {
local _id _counter : 1 ,
get _events _running _called : 1 ,
reify _message _id _checked : 1 ,
send _msg _ajax _post _called : 1 ,
server _events _triggered : 1 ,
} ;
assert . deepEqual ( stub _state , state ) ;
assert . equal ( _ . keys ( compose . send _times _data ) . length , 1 ) ;
assert . equal ( $ ( "#new_message_content" ) . val ( ) , '' ) ;
assert ( $ ( "#new_message_content" ) . is _focused ( ) ) ;
assert ( ! $ ( "#send-status" ) . visible ( ) ) ;
assert . equal ( $ ( "#compose-send-button" ) . attr ( 'disabled' ) , undefined ) ;
assert ( ! $ ( "#sending-indicator" ) . visible ( ) ) ;
} ( ) ) ;
( function test _error _code _path _when _error _type _not _timeout ( ) {
stub _state = initialize _state _stub _dict ( ) ;
compose _state . set _message _type ( 'stream' ) ;
var server _error _triggered = false ;
channel . post = function ( payload ) {
payload . error ( '500' , 'Internal Server Error' ) ;
stub _state . send _msg _ajax _post _called += 1 ;
server _error _triggered = true ;
} ;
var reload _initiate _triggered = false ;
global . reload = {
is _pending : function ( ) { return true ; } ,
initiate : function ( ) {
reload _initiate _triggered = true ;
} ,
} ;
compose . send _message ( ) ;
var state = {
local _id _counter : 1 ,
get _events _running _called : 1 ,
reify _message _id _checked : 0 ,
send _msg _ajax _post _called : 1 ,
server _events _triggered : 0 ,
} ;
assert . deepEqual ( stub _state , state ) ;
assert . equal ( _ . keys ( compose . send _times _data ) . length , 1 ) ;
assert ( server _error _triggered ) ;
assert ( reload _initiate _triggered ) ;
} ( ) ) ;
// This is the additional setup which is common to both the tests below.
var server _error _triggered = false ;
var reload _initiate _triggered = false ;
channel . post = function ( payload ) {
payload . error ( '408' , 'timeout' ) ;
stub _state . send _msg _ajax _post _called += 1 ;
server _error _triggered = true ;
} ;
var xhr _error _msg _checked = false ;
channel . xhr _error _message = function ( error , xhr ) {
assert . equal ( error , 'Error sending message' ) ;
assert . equal ( xhr , '408' ) ;
xhr _error _msg _checked = true ;
return 'Error sending message: Server says 408' ;
} ;
var echo _error _msg _checked = false ;
echo . message _send _error = function ( local _id , error _response ) {
assert . equal ( local _id , 1 ) ;
assert . equal ( error _response , 'Error sending message: Server says 408' ) ;
echo _error _msg _checked = true ;
} ;
// Tests start here.
( function test _param _error _function _passed _from _send _message ( ) {
stub _state = initialize _state _stub _dict ( ) ;
compose . send _message ( ) ;
var state = {
local _id _counter : 1 ,
get _events _running _called : 1 ,
reify _message _id _checked : 0 ,
send _msg _ajax _post _called : 1 ,
server _events _triggered : 0 ,
} ;
assert . deepEqual ( stub _state , state ) ;
assert . equal ( _ . keys ( compose . send _times _data ) . length , 1 ) ;
assert ( server _error _triggered ) ;
assert ( ! reload _initiate _triggered ) ;
assert ( xhr _error _msg _checked ) ;
assert ( echo _error _msg _checked ) ;
} ( ) ) ;
( function test _error _codepath _local _id _undefined ( ) {
stub _state = initialize _state _stub _dict ( ) ;
$ ( "#new_message_content" ) . val ( 'foobarfoobar' ) ;
$ ( "#new_message_content" ) . blur ( ) ;
$ ( "#send-status" ) . show ( ) ;
$ ( "#compose-send-button" ) . attr ( 'disabled' , 'disabled' ) ;
$ ( "#sending-indicator" ) . show ( ) ;
$ ( "#new_message_content" ) . select ( noop ) ;
echo _error _msg _checked = false ;
xhr _error _msg _checked = false ;
server _error _triggered = false ;
reload _initiate _triggered = false ;
echo . try _deliver _locally = function ( ) {
return ;
} ;
compose . send _message ( ) ;
var state = {
local _id _counter : 0 ,
get _events _running _called : 1 ,
reify _message _id _checked : 0 ,
send _msg _ajax _post _called : 1 ,
server _events _triggered : 0 ,
} ;
assert . deepEqual ( stub _state , state ) ;
assert . equal ( _ . keys ( compose . send _times _data ) . length , 1 ) ;
assert ( server _error _triggered ) ;
assert ( ! reload _initiate _triggered ) ;
assert ( xhr _error _msg _checked ) ;
assert ( ! echo _error _msg _checked ) ;
assert . equal ( $ ( "#compose-send-button" ) . attr ( 'disabled' ) , undefined ) ;
assert . equal ( $ ( '#error-msg' ) . html ( ) ,
'Error sending message: Server says 408' ) ;
assert . equal ( $ ( "#new_message_content" ) . val ( ) , 'foobarfoobar' ) ;
assert ( $ ( "#new_message_content" ) . is _focused ( ) ) ;
assert ( $ ( "#send-status" ) . visible ( ) ) ;
assert . equal ( $ ( "#compose-send-button" ) . attr ( 'disabled' ) , undefined ) ;
assert ( ! $ ( "#sending-indicator" ) . visible ( ) ) ;
} ( ) ) ;
} ( ) ) ;
2017-07-07 00:33:46 +02:00
( function test _enter _with _preview _open ( ) {
$ ( "#new_message_content" ) . hide ( ) ;
$ ( "#undo_markdown_preview" ) . show ( ) ;
$ ( "#preview_message_area" ) . show ( ) ;
$ ( "#markdown_preview" ) . hide ( ) ;
page _params . enter _sends = true ;
var send _message _called = false ;
compose . send _message = function ( ) {
send _message _called = true ;
} ;
compose . enter _with _preview _open ( ) ;
assert ( $ ( "#new_message_content" ) . visible ( ) ) ;
assert ( ! $ ( "#undo_markdown_preview" ) . visible ( ) ) ;
assert ( ! $ ( "#preview_message_area" ) . visible ( ) ) ;
assert ( $ ( "#markdown_preview" ) . visible ( ) ) ;
assert ( send _message _called ) ;
page _params . enter _sends = false ;
$ ( "#new_message_content" ) . blur ( ) ;
compose . enter _with _preview _open ( ) ;
assert ( $ ( "#new_message_content" ) . is _focused ( ) ) ;
} ( ) ) ;
2017-07-07 00:48:51 +02:00
( function test _finish ( ) {
( function test _when _compose _validation _fails ( ) {
$ ( "#compose_invite_users" ) . show ( ) ;
$ ( "#compose-send-button" ) . removeAttr ( 'disabled' ) ;
$ ( "#compose-send-button" ) . focus ( ) ;
$ ( "#sending-indicator" ) . hide ( ) ;
$ ( "#new_message_content" ) . select ( noop ) ;
$ ( "#new_message_content" ) . val ( '' ) ;
var res = compose . finish ( ) ;
assert . equal ( res , false ) ;
assert ( ! $ ( "#compose_invite_users" ) . visible ( ) ) ;
assert ( ! $ ( "#sending-indicator" ) . visible ( ) ) ;
assert ( ! $ ( "#compose-send-button" ) . is _focused ( ) ) ;
assert . equal ( $ ( "#compose-send-button" ) . attr ( 'disabled' ) , undefined ) ;
assert . equal ( $ ( '#error-msg' ) . html ( ) , i18n . t ( 'You have nothing to send!' ) ) ;
} ( ) ) ;
( function test _when _compose _validation _succeed ( ) {
$ ( "#new_message_content" ) . hide ( ) ;
$ ( "#undo_markdown_preview" ) . show ( ) ;
$ ( "#preview_message_area" ) . show ( ) ;
$ ( "#markdown_preview" ) . hide ( ) ;
$ ( "#new_message_content" ) . val ( 'foobarfoobar' ) ;
compose _state . set _message _type ( 'private' ) ;
compose _state . recipient ( 'bob@example.com' ) ;
var compose _finished _event _checked = false ;
$ . stub _selector ( document , {
trigger : function ( e ) {
assert . equal ( e . name , 'compose_finished.zulip' ) ;
compose _finished _event _checked = true ;
} ,
} ) ;
var send _message _called = false ;
compose . send _message = function ( ) {
send _message _called = true ;
} ;
assert ( compose . finish ( ) ) ;
assert ( $ ( "#new_message_content" ) . visible ( ) ) ;
assert ( ! $ ( "#undo_markdown_preview" ) . visible ( ) ) ;
assert ( ! $ ( "#preview_message_area" ) . visible ( ) ) ;
assert ( $ ( "#markdown_preview" ) . visible ( ) ) ;
assert ( send _message _called ) ;
assert ( compose _finished _event _checked ) ;
} ( ) ) ;
} ( ) ) ;
2017-07-07 15:44:39 +02:00
( function test _abort _xhr ( ) {
$ ( "#compose-send-button" ) . attr ( 'disabled' , 'disabled' ) ;
var compose _removedata _checked = false ;
$ ( '#compose' ) . removeData = function ( sel ) {
assert . equal ( sel , 'filedrop_xhr' ) ;
compose _removedata _checked = true ;
} ;
var xhr _abort _checked = false ;
$ ( "#compose" ) . data = function ( sel ) {
assert . equal ( sel , 'filedrop_xhr' ) ;
return {
abort : function ( ) {
xhr _abort _checked = true ;
} ,
} ;
} ;
compose . abort _xhr ( ) ;
assert . equal ( $ ( "#compose-send-button" ) . attr ( ) , undefined ) ;
assert ( xhr _abort _checked ) ;
assert ( compose _removedata _checked ) ;
} ( ) ) ;
2017-07-07 15:14:00 +02:00
function verify _filedrop _payload ( payload ) {
assert . equal ( payload . url , '/json/upload_file' ) ;
assert . equal ( payload . fallback _id , 'file_input' ) ;
assert . equal ( payload . paramname , 'file' ) ;
assert . equal ( payload . maxfilesize , 512 ) ;
assert . equal ( payload . data . csrfmiddlewaretoken , 'fake-csrf-token' ) ;
assert . deepEqual ( payload . raw _droppable , [ 'text/uri-list' , 'text/plain' ] ) ;
assert . equal ( typeof ( payload . drop ) , 'function' ) ;
assert . equal ( typeof ( payload . progressUpdated ) , 'function' ) ;
assert . equal ( typeof ( payload . error ) , 'function' ) ;
assert . equal ( typeof ( payload . uploadFinished ) , 'function' ) ;
assert . equal ( typeof ( payload . rawDrop ) , 'function' ) ;
}
function test _raw _file _drop ( raw _drop _func ) {
compose _state . set _message _type ( false ) ;
var compose _actions _start _checked = false ;
global . compose _actions = {
start : function ( msg _type ) {
assert . equal ( msg _type , 'stream' ) ;
compose _actions _start _checked = true ;
} ,
} ;
$ ( "#new_message_content" ) . val ( 'Old content ' ) ;
var compose _ui _autosize _textarea _checked = false ;
compose _ui . autosize _textarea = function ( ) {
compose _ui _autosize _textarea _checked = true ;
} ;
// Call the method here!
raw _drop _func ( 'new contents' ) ;
assert ( compose _actions _start _checked ) ;
assert . equal ( $ ( "#new_message_content" ) . val ( ) , 'Old content new contents' ) ;
assert ( compose _ui _autosize _textarea _checked ) ;
}
( function test _initialize ( ) {
// In this test we mostly do the setup stuff in addition to testing the
// normal workflow of the function. All the tests for the on functions are
// done in subsequent tests directly below this test.
var resize _watch _manual _resize _checked = false ;
resize . watch _manual _resize = function ( elem ) {
assert . equal ( '#new_message_content' , elem ) ;
resize _watch _manual _resize _checked = true ;
} ;
global . window = {
XMLHttpRequest : true ,
bridge : true ,
} ;
var xmlhttprequest _checked = false ;
set _global ( 'XMLHttpRequest' , function ( ) {
this . upload = true ;
xmlhttprequest _checked = true ;
} ) ;
$ ( "#compose #attach_files" ) . addClass ( "notdisplayed" ) ;
2017-07-08 15:16:19 +02:00
global . document = 'document-stub' ;
2017-07-07 15:14:00 +02:00
global . csrf _token = 'fake-csrf-token' ;
var filedrop _in _compose _checked = false ;
page _params . maxfilesize = 512 ;
$ ( "#compose" ) . filedrop = function ( payload ) {
verify _filedrop _payload ( payload ) ;
test _raw _file _drop ( payload . rawDrop ) ;
filedrop _in _compose _checked = true ;
} ;
compose . initialize ( ) ;
assert ( resize _watch _manual _resize _checked ) ;
assert ( xmlhttprequest _checked ) ;
assert ( ! $ ( "#compose #attach_files" ) . hasClass ( "notdisplayed" ) ) ;
assert ( filedrop _in _compose _checked ) ;
function reset _jquery ( ) {
// Avoid leaks.
set _global ( '$' , global . make _zjquery ( ) ) ;
// Bypass filedrop (we already tested it above).
$ ( "#compose" ) . filedrop = noop ;
}
var compose _actions _start _checked ;
function set _up _compose _start _mock ( expected _opts ) {
compose _actions _start _checked = false ;
global . compose _actions = {
start : function ( msg _type , opts ) {
assert . equal ( msg _type , 'stream' ) ;
assert . deepEqual ( opts , expected _opts ) ;
compose _actions _start _checked = true ;
} ,
} ;
}
( function test _page _params _narrow _path ( ) {
page _params . narrow = true ;
reset _jquery ( ) ;
set _up _compose _start _mock ( { } ) ;
compose . initialize ( ) ;
assert ( compose _actions _start _checked ) ;
} ( ) ) ;
( function test _page _params _narrow _topic ( ) {
page _params . narrow _topic = 'testing' ;
reset _jquery ( ) ;
set _up _compose _start _mock ( { subject : 'testing' } ) ;
compose . initialize ( ) ;
assert ( compose _actions _start _checked ) ;
} ( ) ) ;
} ( ) ) ;
2017-07-07 03:59:08 +02:00
function test _with _mock _socket ( test _params ) {
var socket _send _called ;
var send _args = { } ;
global . socket . send = function ( request , success , error ) {
global . socket . send = undefined ;
socket _send _called = true ;
// Save off args for check_send_args callback.
send _args . request = request ;
send _args . success = success ;
send _args . error = error ;
} ;
// Run the actual code here.
test _params . run _code ( ) ;
assert ( socket _send _called ) ;
test _params . check _send _args ( send _args ) ;
}
( function test _transmit _message ( ) {
page _params . use _websockets = true ;
global . navigator . userAgent = 'unittest_transmit_message' ;
// Our request is mostly unimportant, except that the
// socket_user_agent field will be added.
var request = { foo : 'bar' } ;
// Our success function gets passed all the way through to
// socket.send, so we can just use a stub to test that.
var success = 'success-function-stub' ;
// Our error function gets wrapped, so we set up a real
// function to test the wrapping mechanism.
var error _func _checked = false ;
var error = function ( error _msg ) {
assert . equal ( error _msg , 'Error sending message: simulated_error' ) ;
error _func _checked = true ;
} ;
test _with _mock _socket ( {
run _code : function ( ) {
compose . transmit _message ( request , success , error ) ;
} ,
check _send _args : function ( send _args ) {
// The real code patches new data on the request, rather
// than making a copy, so we test both that it didn't
// clone the object and that it did add a field.
assert . equal ( send _args . request , request ) ;
assert . deepEqual ( send _args . request , {
foo : 'bar' ,
socket _user _agent : 'unittest_transmit_message' ,
} ) ;
// Our success function never gets wrapped.
assert . equal ( send _args . success , success ) ;
// Our error function does get wrapped, so we test by
// using socket.send's error callback, which should
// invoke our test error function via a wrapper
// function in the real code.
send _args . error ( 'response' , { msg : 'simulated_error' } ) ;
assert ( error _func _checked ) ;
} ,
} ) ;
} ( ) ) ;
2017-07-07 15:41:13 +02:00
( function test _update _fade ( ) {
var selector = '#stream,#subject,#private_message_recipient' ;
var keyup _handler _func = $ ( selector ) . get _on _handler ( 'keyup' ) ;
var set _focused _recipient _checked = false ;
var update _faded _messages _checked = false ;
global . compose _fade = {
set _focused _recipient : function ( msg _type ) {
assert . equal ( msg _type , 'private' ) ;
set _focused _recipient _checked = true ;
} ,
update _faded _messages : function ( ) {
update _faded _messages _checked = true ;
} ,
} ;
compose _state . set _message _type ( false ) ;
keyup _handler _func ( ) ;
assert ( ! set _focused _recipient _checked ) ;
assert ( ! update _faded _messages _checked ) ;
compose _state . set _message _type ( 'private' ) ;
keyup _handler _func ( ) ;
assert ( set _focused _recipient _checked ) ;
assert ( update _faded _messages _checked ) ;
} ( ) ) ;
2017-07-07 15:42:51 +02:00
( function test _trigger _submit _compose _form ( ) {
var prevent _default _checked = false ;
var compose _finish _checked = false ;
var e = {
preventDefault : function ( ) {
prevent _default _checked = true ;
} ,
} ;
compose . finish = function ( ) {
compose _finish _checked = true ;
} ;
var submit _handler = $ ( '#compose form' ) . get _on _handler ( 'submit' ) ;
submit _handler ( e ) ;
assert ( prevent _default _checked ) ;
assert ( compose _finish _checked ) ;
} ( ) ) ;
2017-07-08 00:06:38 +02:00
( function test _on _events ( ) {
( function test _usermention _completed _zulip _triggered ( ) {
var handler = $ ( document ) . get _on _handler ( 'usermention_completed.zulip' ) ;
var data = {
mentioned : {
email : 'foo@bar.com' ,
} ,
} ;
2017-07-09 14:13:42 +02:00
$ ( '#compose_invite_users .compose_invite_user' ) . length = 0 ;
function test _noop _case ( msg _type , is _zephyr _mirror , mentioned _full _name ) {
2017-07-08 00:06:38 +02:00
compose _state . set _message _type ( msg _type ) ;
page _params . realm _is _zephyr _mirror _realm = is _zephyr _mirror ;
data . mentioned . full _name = mentioned _full _name ;
handler ( { } , data ) ;
2017-07-09 14:13:42 +02:00
assert . equal ( $ ( '#compose_invite_users' ) . visible ( ) , false ) ;
2017-07-08 00:06:38 +02:00
}
2017-07-09 14:13:42 +02:00
test _noop _case ( 'private' , true , 'everyone' ) ;
test _noop _case ( 'stream' , true , 'everyone' ) ;
test _noop _case ( 'stream' , false , 'everyone' ) ;
// Test mentioning a user that should gets a warning.
$ ( "#compose_invite_users" ) . hide ( ) ;
compose _state . set _message _type ( 'stream' ) ;
page _params . realm _is _zephyr _mirror _realm = false ;
var checks = [
( function ( ) {
var called ;
compose _fade . would _receive _message = function ( email ) {
called = true ;
assert . equal ( email , 'foo@bar.com' ) ;
return false ;
} ;
return function ( ) { assert ( called ) ; } ;
} ( ) ) ,
( function ( ) {
var called ;
templates . render = function ( template _name , context ) {
called = true ;
assert . equal ( template _name , 'compose-invite-users' ) ;
assert . equal ( context . email , 'foo@bar.com' ) ;
assert . equal ( context . name , 'Foo Barson' ) ;
return 'fake-compose-invite-user-template' ;
} ;
return function ( ) { assert ( called ) ; } ;
} ( ) ) ,
( function ( ) {
var called ;
$ ( "#compose_invite_users" ) . append = function ( html ) {
called = true ;
assert . equal ( html , 'fake-compose-invite-user-template' ) ;
} ;
return function ( ) { assert ( called ) ; } ;
} ( ) ) ,
] ;
data = {
mentioned : {
email : 'foo@bar.com' ,
full _name : 'Foo Barson' ,
} ,
} ;
handler ( { } , data ) ;
assert . equal ( $ ( '#compose_invite_users' ) . visible ( ) , true ) ;
_ . each ( checks , function ( f ) { f ( ) ; } ) ;
// Simulate that the row was added to the DOM.
var warning _row = $ ( '<warning row>' ) ;
var looked _for _existing ;
warning _row . data = function ( field ) {
assert . equal ( field , 'useremail' ) ;
looked _for _existing = true ;
return 'foo@bar.com' ;
} ;
var previous _users = $ ( '#compose_invite_users .compose_invite_user' ) ;
previous _users . length = 1 ;
previous _users [ 0 ] = warning _row ;
// Now try to mention the same person again. The template should
// not render.
templates . render = noop ;
handler ( { } , data ) ;
assert . equal ( $ ( '#compose_invite_users' ) . visible ( ) , true ) ;
assert ( looked _for _existing ) ;
2017-07-08 00:06:38 +02:00
} ( ) ) ;
2017-07-08 00:09:13 +02:00
( function test _compose _all _everyone _confirm _clicked ( ) {
var handler = $ ( "#compose-all-everyone" )
. get _on _handler ( 'click' , '.compose-all-everyone-confirm' ) ;
var container = $ . create ( 'fake compose-all-everyone' ) ;
var container _removed = false ;
container . remove = function ( ) {
container _removed = true ;
} ;
var target = $ . create ( 'fake click target (compose-all-everyone)' ) ;
target . set _parents _result ( '.compose-all-everyone' , container ) ;
$ ( "#compose-all-everyone" ) . show ( ) ;
$ ( "#send-status" ) . show ( ) ;
var compose _finish _checked = false ;
compose . finish = function ( ) {
compose _finish _checked = true ;
} ;
var event = {
preventDefault : noop ,
target : target ,
} ;
handler ( event ) ;
assert ( container _removed ) ;
assert ( compose _finish _checked ) ;
assert ( ! $ ( "#compose-all-everyone" ) . visible ( ) ) ;
assert ( ! $ ( "#send-status" ) . visible ( ) ) ;
} ( ) ) ;
2017-07-08 00:11:52 +02:00
( function test _compose _invite _users _clicked ( ) {
var handler = $ ( "#compose_invite_users" )
. get _on _handler ( 'click' , '.compose_invite_link' ) ;
var subscription = {
stream _id : 102 ,
name : 'test' ,
subscribed : true ,
} ;
var invite _user _to _stream _called = false ;
stream _edit . invite _user _to _stream = function ( email , sub , success ) {
invite _user _to _stream _called = true ;
assert . equal ( email , 'foo@bar.com' ) ;
assert . equal ( sub , subscription ) ;
success ( ) ; // This will check success callback path.
} ;
var container = $ . create ( 'fake compose_invite_users' ) ;
var container _removed = false ;
container . remove = function ( ) {
container _removed = true ;
} ;
var target = $ . create ( 'fake click target (compose_invite_link)' ) ;
target . set _parents _result ( '.compose_invite_user' , container ) ;
var event = {
preventDefault : noop ,
target : target ,
} ;
// .data in zjquery is a noop by default, so handler should just return
handler ( event ) ;
assert ( ! invite _user _to _stream _called ) ;
assert ( ! container _removed ) ;
// !sub will result false here and we check the failure code path.
blueslip . warn = function ( err _msg ) {
assert . equal ( err _msg , 'Stream no longer exists: no-stream' ) ;
} ;
$ ( '#stream' ) . val ( 'no-stream' ) ;
container . data = function ( field ) {
assert . equal ( field , 'useremail' ) ;
return 'foo@bar.com' ;
} ;
var invite _err _sel = '.compose_invite_user_error' ;
container . set _find _results ( invite _err _sel , $ ( invite _err _sel ) ) ;
target . removeAttr ( 'disabled' ) ;
$ ( invite _err _sel ) . hide ( ) ;
handler ( event ) ;
assert ( $ ( invite _err _sel ) . visible ( ) ) ;
assert ( target . attr ( 'disabled' ) ) ;
assert ( ! invite _user _to _stream _called ) ;
assert ( ! container _removed ) ;
// !sub will result in true here and we check the success code path.
stream _data . add _sub ( 'test' , subscription ) ;
$ ( '#stream' ) . val ( 'test' ) ;
var all _invite _children _called = false ;
$ ( "#compose_invite_users" ) . children = function ( ) {
all _invite _children _called = true ;
return [ ] ;
} ;
$ ( "#compose_invite_users" ) . show ( ) ;
handler ( event ) ;
assert ( container _removed ) ;
assert ( ! $ ( "#compose_invite_users" ) . visible ( ) ) ;
assert ( invite _user _to _stream _called ) ;
assert ( all _invite _children _called ) ;
} ( ) ) ;
2017-07-08 00:13:14 +02:00
( function test _compose _invite _close _clicked ( ) {
var handler = $ ( "#compose_invite_users" )
. get _on _handler ( 'click' , '.compose_invite_close' ) ;
var container = $ . create ( 'fake compose_invite_users_close' ) ;
var container _removed = false ;
container . remove = function ( ) {
container _removed = true ;
} ;
var target = $ . create ( 'fake click target (compose_invite_close)' ) ;
target . set _parents _result ( '.compose_invite_user' , container ) ;
var event = {
preventDefault : noop ,
target : target ,
} ;
var all _invite _children _called = false ;
$ ( "#compose_invite_users" ) . children = function ( ) {
all _invite _children _called = true ;
return [ ] ;
} ;
$ ( "#compose_invite_users" ) . show ( ) ;
handler ( event ) ;
assert ( container _removed ) ;
assert ( all _invite _children _called ) ;
assert ( ! $ ( "#compose_invite_users" ) . visible ( ) ) ;
} ( ) ) ;
2017-07-08 00:06:38 +02:00
} ( ) ) ;
2017-02-24 16:18:56 +01:00
( function test _set _focused _recipient ( ) {
var sub = {
stream _id : 101 ,
name : 'social' ,
subscribed : true ,
} ;
stream _data . add _sub ( 'social' , sub ) ;
var page = {
'#stream' : 'social' ,
'#subject' : 'lunch' ,
'#new_message_content' : 'burrito' ,
'#private_message_recipient' : 'alice@example.com, bob@example.com' ,
} ;
global . $ = function ( selector ) {
return {
val : function ( ) {
return page [ selector ] ;
} ,
} ;
} ;
2017-04-24 20:35:26 +02:00
global . compose _state . get _message _type = function ( ) {
2017-02-24 16:18:56 +01:00
return 'stream' ;
} ;
global . $ . trim = function ( s ) {
return s ;
} ;
2017-03-29 08:54:26 +02:00
var message = compose . create _message _object ( ) ;
2017-02-24 16:18:56 +01:00
assert . equal ( message . to , 'social' ) ;
assert . equal ( message . subject , 'lunch' ) ;
assert . equal ( message . content , 'burrito' ) ;
2017-04-24 20:35:26 +02:00
global . compose _state . get _message _type = function ( ) {
2017-02-24 16:18:56 +01:00
return 'private' ;
} ;
2017-03-29 08:54:26 +02:00
message = compose . create _message _object ( ) ;
2017-02-24 16:18:56 +01:00
assert . deepEqual ( message . to , [ 'alice@example.com' , 'bob@example.com' ] ) ;
2017-02-24 23:51:23 +01:00
assert . equal ( message . to _user _ids , '31,32' ) ;
2017-02-24 16:18:56 +01:00
assert . equal ( message . content , 'burrito' ) ;
} ( ) ) ;