Best Python code snippet using hypothesis
unit.js
Source:unit.js
1// Not sure why this isn't set by default in qunit.js..2QUnit.jsDump.HTML = false;3$(function(){ // START CLOSURE4var old_jquery = $.fn.jquery < '1.4',5 is_chrome = /chrome/i.test( navigator.userAgent ),6 params_init = 'a[]=4&a[]=5&a[]=6&b[x][]=7&b[y]=8&b[z][]=9&b[z][]=0&b[z][]=true&b[z][]=false&b[z][]=undefined&b[z][]=&c=1',7 init_url,8 ajaxcrawlable_init = $.param.fragment.ajaxCrawlable(),9 aps = Array.prototype.slice;10if ( $.param.querystring() !== params_init || $.param.fragment() !== params_init ) {11 init_url = window.location.href;12 init_url = $.param.querystring( init_url, params_init, 2 );13 init_url = $.param.fragment( init_url, params_init, 2 );14 window.location.href = init_url;15}16$('#jq_version').html( $.fn.jquery );17function notice( txt ) {18 if ( txt ) {19 $('#notice').html( txt );20 } else {21 $('#notice').hide();22 }23};24function run_many_tests() {25 var tests = aps.call( arguments ),26 delay = typeof tests[0] === 'number' && tests.shift(),27 func_each = $.isFunction( tests[0] ) && tests.shift(),28 func_done = $.isFunction( tests[0] ) && tests.shift(),29 result;30 31 function set_result( i, test ) {32 result = $.isArray( test )33 ? func_each.apply( this, test )34 : $.isFunction( test )35 ? test( result )36 : '';37 };38 39 if ( delay ) {40 stop();41 42 (function loopy(){43 test && test.func && test.func( result );44 if ( tests.length ) {45 set_result( 0, tests.shift() );46 setTimeout( loopy, delay );47 } else {48 func_done && func_done();49 start();50 }51 })();52 53 } else {54 $.each( tests, set_result );55 func_done && func_done();56 }57}58////////////////////////////////////////////////////////////////////////////////59////////////////////////////////////////////////////////////////////////////////60module( 'jQuery.param' );61var params_obj = { a:['4','5','6'], b:{x:['7'], y:'8', z:['9','0','true','false','undefined','']}, c:'1' },62 params_obj_coerce = { a:[4,5,6], b:{x:[7], y:8, z:[9,0,true,false,undefined,'']}, c:1 },63 params_str = params_init,64 params_str_old = 'a=4&a=5&a=6&b=[object+Object]&c=1',65 66 // If a params fragment starts with ! and BBQ is not in ajaxCrawlable mode,67 // things can get very ugly, very quickly.68 params_obj_bang = { "!a":['4'], a:['5','6'], b:{x:['7'], y:'8', z:['9','0','true','false','undefined','']}, c:'1' },69 params_obj_bang_coerce = { "!a":[4], a:[5,6], b:{x:[7], y:8, z:[9,0,true,false,undefined,'']}, c:1 };70test( 'jQuery.param.sorted', function() {71 var tests = [72 {73 obj: {z:1,b:2,ab:3,bc:4,ba:5,aa:6,a1:7,x:8},74 traditional: false,75 expected: 'a1=7&aa=6&ab=3&b=2&ba=5&bc=4&x=8&z=1'76 },77 {78 obj: {z:1,b:[6,5,4],x:2,a:[3,2,1]},79 traditional: false,80 expected: 'a[]=3&a[]=2&a[]=1&b[]=6&b[]=5&b[]=4&x=2&z=1',81 expected_old: 'a=3&a=2&a=1&b=6&b=5&b=4&x=2&z=1'82 },83 {84 obj: {z:1,b:[6,5,4],x:2,a:[3,2,1]},85 traditional: true,86 expected: 'a=3&a=2&a=1&b=6&b=5&b=4&x=2&z=1'87 },88 {89 obj: {a:[[4,[5,6]],[[7,8],9]]},90 traditional: false,91 expected: 'a[0][]=4&a[0][1][]=5&a[0][1][]=6&a[1][0][]=7&a[1][0][]=8&a[1][]=9',92 expected_old: 'a=4,5,6&a=7,8,9' // obviously not great, but that's the way jQuery used to roll93 }94 ];95 96 if ( $.fn.jquery != '1.4.1' ) {97 // this explodes in jQuery 1.4.198 tests.push({99 obj: {z:1,'b[]':[6,5,4],x:2,'a[]':[3,2,1]},100 obj_alt: {z:1,b:[6,5,4],x:2,a:[3,2,1]},101 traditional: false,102 expected: 'a[]=3&a[]=2&a[]=1&b[]=6&b[]=5&b[]=4&x=2&z=1'103 });104 }105 106 expect( tests.length * 2 + 6 );107 108 $.each( tests, function(i,test){109 var unsorted = $.param( test.obj, test.traditional ),110 sorted = $.param.sorted( test.obj, test.traditional );111 112 equals( decodeURIComponent( sorted ), old_jquery && test.expected_old || test.expected, 'params should be sorted' );113 same( $.deparam( unsorted, true ), $.deparam( sorted, true ), 'sorted params should deparam the same as unsorted params' )114 });115 116 equals( $.param.fragment( 'foo', '#b=2&a=1' ), 'foo#a=1&b=2', 'params should be sorted' );117 equals( $.param.fragment( 'foo', '#b=2&a=1', 1 ), 'foo#a=1&b=2', 'params should be sorted' );118 equals( $.param.fragment( 'foo', '#b=2&a=1', 2 ), 'foo#b=2&a=1', 'params should NOT be sorted' );119 equals( $.param.fragment( 'foo#c=3&a=4', '#b=2&a=1' ), 'foo#a=1&b=2&c=3', 'params should be sorted' );120 equals( $.param.fragment( 'foo#c=3&a=4', '#b=2&a=1', 1 ), 'foo#a=4&b=2&c=3', 'params should be sorted' );121 equals( $.param.fragment( 'foo#c=3&a=4', '#b=2&a=1', 2 ), 'foo#b=2&a=1', 'params should NOT be sorted' );122 123});124test( 'jQuery.param.querystring', function() {125 expect( 11 );126 127 equals( $.param.querystring( 'http://example.com/' ), '', 'properly identifying params' );128 equals( $.param.querystring( 'http://example.com/?foo' ),'foo', 'properly identifying params' );129 equals( $.param.querystring( 'http://example.com/?foo#bar' ),'foo', 'properly identifying params' );130 equals( $.param.querystring( 'http://example.com/?foo#bar?baz' ),'foo', 'properly identifying params' );131 equals( $.param.querystring( 'http://example.com/#foo' ),'', 'properly identifying params' );132 equals( $.param.querystring( 'http://example.com/#foo?bar' ),'', 'properly identifying params' );133 134 equals( $.param.querystring(), params_str, 'params string from window.location' );135 equals( $.param.querystring( '?' + params_str ), params_str, 'params string from url' );136 equals( $.param.querystring( 'foo.html?' + params_str ), params_str, 'params string from url' );137 equals( $.param.querystring( 'http://a:b@example.com:1234/foo.html?' + params_str ), params_str, 'params string from url' );138 equals( $.param.querystring( 'http://a:b@example.com:1234/foo.html?' + params_str + '#bippity-boppity-boo' ), params_str, 'params string from url' );139});140test( 'jQuery.param.querystring - build URL', function() {141 expect( 10 );142 143 function fake_encode( params_str ) {144 return '?' + $.map( params_str.split('&'), encodeURIComponent ).join('&').replace( /%3D/g, '=' ).replace( /%2B/g, '+' );145 }146 147 var pre = 'http://a:b@example.com:1234/foo.html',148 post = '#get-on-the-floor',149 current_url = pre + post;150 151 run_many_tests(152 153 // execute this for each array item154 function(){155 current_url = $.param.querystring.apply( this, [ current_url ].concat( aps.call( arguments ) ) );156 },157 158 // tests:159 160 [ { a:'2' } ],161 162 function(result){163 equals( current_url, pre + '?a=2' + post, '$.param.querystring( url, Object )' );164 },165 166 [ { b:'2' } ],167 168 function(result){169 equals( current_url, pre + '?a=2&b=2' + post, '$.param.querystring( url, Object )' );170 },171 172 [ { c:true, d:false, e:'undefined', f:'' } ],173 174 function(result){175 equals( current_url, pre + '?a=2&b=2&c=true&d=false&e=undefined&f=' + post, '$.param.querystring( url, Object )' );176 },177 178 [ { a:[4,5,6], b:{x:[7], y:8, z:[9,0,'true','false','undefined','']} }, 2 ],179 180 function(result){181 var params = old_jquery182 ? 'a=4&a=5&a=6&b=[object+Object]'183 : 'a[]=4&a[]=5&a[]=6&b[x][]=7&b[y]=8&b[z][]=9&b[z][]=0&b[z][]=true&b[z][]=false&b[z][]=undefined&b[z][]=';184 185 equals( current_url, pre + fake_encode( params ) + post, '$.param.querystring( url, Object, 2 )' );186 },187 188 [ { a:'1', c:'2' }, 1 ],189 190 function(result){191 var params = old_jquery192 ? 'a=4&a=5&a=6&b=[object+Object]&c=2'193 : 'a[]=4&a[]=5&a[]=6&b[x][]=7&b[y]=8&b[z][]=9&b[z][]=0&b[z][]=true&b[z][]=false&b[z][]=undefined&b[z][]=&c=2';194 195 equals( current_url, pre + fake_encode( params ) + post, '$.param.querystring( url, Object, 1 )' );196 },197 198 [ 'foo=1' ],199 200 function(result){201 var params = old_jquery202 ? 'a=4&a=5&a=6&b=[object+Object]&c=2&foo=1'203 : 'a[]=4&a[]=5&a[]=6&b[x][]=7&b[y]=8&b[z][]=9&b[z][]=0&b[z][]=true&b[z][]=false&b[z][]=undefined&b[z][]=&c=2&foo=1';204 205 equals( current_url, pre + fake_encode( params ) + post, '$.param.querystring( url, String )' );206 },207 208 [ 'foo=2&bar=3', 1 ],209 210 function(result){211 var params = old_jquery212 ? 'a=4&a=5&a=6&b=[object+Object]&bar=3&c=2&foo=1'213 : 'a[]=4&a[]=5&a[]=6&b[x][]=7&b[y]=8&b[z][]=9&b[z][]=0&b[z][]=true&b[z][]=false&b[z][]=undefined&b[z][]=&bar=3&c=2&foo=1';214 215 equals( current_url, pre + fake_encode( params ) + post, '$.param.querystring( url, String, 1 )' );216 },217 218 [ 'http://example.com/test.html?/path/to/file.php#the-cow-goes-moo', 2 ],219 220 function(result){221 equals( current_url, pre + '?/path/to/file.php' + post, '$.param.querystring( url, String, 2 )' );222 },223 224 [ '?another-example', 2 ],225 226 function(result){227 equals( current_url, pre + '?another-example' + post, '$.param.querystring( url, String, 2 )' );228 },229 230 [ 'i_am_out_of_witty_strings', 2 ],231 232 function(result){233 equals( current_url, pre + '?i_am_out_of_witty_strings' + post, '$.param.querystring( url, String, 2 )' );234 }235 236 );237 238});239test( 'jQuery.param.fragment', function() {240 expect( 29 );241 242 equals( $.param.fragment( 'http://example.com/' ), '', 'properly identifying params' );243 equals( $.param.fragment( 'http://example.com/?foo' ),'', 'properly identifying params' );244 equals( $.param.fragment( 'http://example.com/?foo#bar' ),'bar', 'properly identifying params' );245 equals( $.param.fragment( 'http://example.com/?foo#bar?baz' ),'bar?baz', 'properly identifying params' );246 equals( $.param.fragment( 'http://example.com/#foo' ),'foo', 'properly identifying params' );247 equals( $.param.fragment( 'http://example.com/#foo?bar' ),'foo?bar', 'properly identifying params' );248 249 equals( $.param.fragment( 'http://example.com/' ), '', 'properly identifying params' );250 equals( $.param.fragment( 'http://example.com/?foo' ),'', 'properly identifying params' );251 equals( $.param.fragment( 'http://example.com/?foo#!bar' ),'!bar', 'properly identifying params' );252 equals( $.param.fragment( 'http://example.com/?foo#!bar?baz' ),'!bar?baz', 'properly identifying params' );253 equals( $.param.fragment( 'http://example.com/#!foo' ),'!foo', 'properly identifying params' );254 equals( $.param.fragment( 'http://example.com/#!foo?bar' ),'!foo?bar', 'properly identifying params' );255 256 equals( $.param.fragment(), params_str, 'params string from window.location' );257 equals( $.param.fragment( '#' + params_str ), params_str, 'params string from url' );258 equals( $.param.fragment( 'foo.html#' + params_str ), params_str, 'params string from url' );259 equals( $.param.fragment( 'http://a:b@example.com:1234/foo.html#' + params_str ), params_str, 'params string from url' );260 equals( $.param.fragment( 'http://a:b@example.com:1234/foo.html?bippity-boppity-boo#' + params_str ), params_str, 'params string from url' );261 262 $.param.fragment.ajaxCrawlable( true );263 264 equals( $.param.fragment( 'http://example.com/' ), '', 'properly identifying params' );265 equals( $.param.fragment( 'http://example.com/?foo' ),'', 'properly identifying params' );266 equals( $.param.fragment( 'http://example.com/?foo#bar' ),'bar', 'properly identifying params' );267 equals( $.param.fragment( 'http://example.com/?foo#bar?baz' ),'bar?baz', 'properly identifying params' );268 equals( $.param.fragment( 'http://example.com/#foo' ),'foo', 'properly identifying params' );269 equals( $.param.fragment( 'http://example.com/#foo?bar' ),'foo?bar', 'properly identifying params' );270 271 equals( $.param.fragment( 'http://example.com/' ), '', 'properly identifying params' );272 equals( $.param.fragment( 'http://example.com/?foo' ),'', 'properly identifying params' );273 equals( $.param.fragment( 'http://example.com/?foo#!bar' ),'bar', 'properly identifying params' );274 equals( $.param.fragment( 'http://example.com/?foo#!bar?baz' ),'bar?baz', 'properly identifying params' );275 equals( $.param.fragment( 'http://example.com/#!foo' ),'foo', 'properly identifying params' );276 equals( $.param.fragment( 'http://example.com/#!foo?bar' ),'foo?bar', 'properly identifying params' );277 278 $.param.fragment.ajaxCrawlable( false );279 280});281test( 'jQuery.param.fragment - build URL', function() {282 expect( 40 );283 284 function fake_encode( params_str ) {285 return '#' + $.map( params_str.split('&'), encodeURIComponent ).join('&').replace( /%3D/g, '=' ).replace( /%2B/g, '+' );286 }287 288 var pre = 'http://a:b@example.com:1234/foo.html?and-dance-with-me',289 current_url = pre;290 291 run_many_tests(292 293 // execute this for each array item294 function(){295 current_url = $.param.fragment.apply( this, [ current_url ].concat( aps.call( arguments ) ) );296 },297 298 // tests:299 300 [ { a:'2' } ],301 302 function(result){303 equals( current_url, pre + '#a=2', '$.param.fragment( url, Object )' );304 },305 306 [ { b:'2' } ],307 308 function(result){309 equals( current_url, pre + '#a=2&b=2', '$.param.fragment( url, Object )' );310 },311 312 [ { c:true, d:false, e:'undefined', f:'' } ],313 314 function(result){315 equals( current_url, pre + '#a=2&b=2&c=true&d=false&e=undefined&f=', '$.param.fragment( url, Object )' );316 },317 318 [ { a:[4,5,6], b:{x:[7], y:8, z:[9,0,'true','false','undefined','']} }, 2 ],319 320 function(result){321 var params = old_jquery322 ? 'a=4&a=5&a=6&b=[object+Object]'323 : 'a[]=4&a[]=5&a[]=6&b[x][]=7&b[y]=8&b[z][]=9&b[z][]=0&b[z][]=true&b[z][]=false&b[z][]=undefined&b[z][]=';324 325 equals( current_url, pre + fake_encode( params ), '$.param.fragment( url, Object, 2 )' );326 },327 328 [ { a:'1', c:'2' }, 1 ],329 330 function(result){331 var params = old_jquery332 ? 'a=4&a=5&a=6&b=[object+Object]&c=2'333 : 'a[]=4&a[]=5&a[]=6&b[x][]=7&b[y]=8&b[z][]=9&b[z][]=0&b[z][]=true&b[z][]=false&b[z][]=undefined&b[z][]=&c=2';334 335 equals( current_url, pre + fake_encode( params ), '$.param.fragment( url, Object, 1 )' );336 },337 338 [ 'foo=1' ],339 340 function(result){341 var params = old_jquery342 ? 'a=4&a=5&a=6&b=[object+Object]&c=2&foo=1'343 : 'a[]=4&a[]=5&a[]=6&b[x][]=7&b[y]=8&b[z][]=9&b[z][]=0&b[z][]=true&b[z][]=false&b[z][]=undefined&b[z][]=&c=2&foo=1';344 345 equals( current_url, pre + fake_encode( params ), '$.param.fragment( url, String )' );346 },347 348 [ 'foo=2&bar=3', 1 ],349 350 function(result){351 var params = old_jquery352 ? 'a=4&a=5&a=6&b=[object+Object]&bar=3&c=2&foo=1'353 : 'a[]=4&a[]=5&a[]=6&b[x][]=7&b[y]=8&b[z][]=9&b[z][]=0&b[z][]=true&b[z][]=false&b[z][]=undefined&b[z][]=&bar=3&c=2&foo=1';354 355 equals( current_url, pre + fake_encode( params ), '$.param.fragment( url, String, 1 )' );356 },357 358 [ 'http://example.com/test.html?the-cow-goes-moo#/path/to/file.php', 2 ],359 360 function(result){361 equals( current_url, pre + '#/path/to/file.php', '$.param.fragment( url, String, 2 )' );362 },363 364 [ '#another-example', 2 ],365 366 function(result){367 equals( current_url, pre + '#another-example', '$.param.fragment( url, String, 2 )' );368 },369 370 [ 'i_am_out_of_witty_strings', 2 ],371 372 function(result){373 equals( current_url, pre + '#i_am_out_of_witty_strings', '$.param.fragment( url, String, 2 )' );374 }375 376 );377 378 $.param.fragment.ajaxCrawlable( true );379 380 equals( $.param.fragment( 'foo', {} ) , 'foo#!', '$.param.fragment( url, Object )' );381 equals( $.param.fragment( 'foo', { b:2, a:1 } ) , 'foo#!a=1&b=2', '$.param.fragment( url, Object )' );382 equals( $.param.fragment( 'foo#', { b:2, a:1 } ) , 'foo#!a=1&b=2', '$.param.fragment( url, Object )' );383 equals( $.param.fragment( 'foo#!', { b:2, a:1 } ) , 'foo#!a=1&b=2', '$.param.fragment( url, Object )' );384 equals( $.param.fragment( 'foo#c=3&a=4', { b:2, a:1 } ) , 'foo#!a=1&b=2&c=3', '$.param.fragment( url, Object )' );385 equals( $.param.fragment( 'foo#!c=3&a=4', { b:2, a:1 } ) , 'foo#!a=1&b=2&c=3', '$.param.fragment( url, Object )' );386 387 equals( $.param.fragment( 'foo', '' ) , 'foo#!', '$.param.fragment( url, String )' );388 equals( $.param.fragment( 'foo', 'b=2&a=1' ) , 'foo#!a=1&b=2', '$.param.fragment( url, String )' );389 equals( $.param.fragment( 'foo#', 'b=2&a=1' ) , 'foo#!a=1&b=2', '$.param.fragment( url, String )' );390 equals( $.param.fragment( 'foo#!', 'b=2&a=1' ) , 'foo#!a=1&b=2', '$.param.fragment( url, String )' );391 equals( $.param.fragment( 'foo#c=3&a=4', 'b=2&a=1' ) , 'foo#!a=1&b=2&c=3', '$.param.fragment( url, String )' );392 equals( $.param.fragment( 'foo#!c=3&a=4', 'b=2&a=1' ) , 'foo#!a=1&b=2&c=3', '$.param.fragment( url, String )' );393 394 equals( $.param.fragment( 'foo', '#' ) , 'foo#!', '$.param.fragment( url, String )' );395 equals( $.param.fragment( 'foo', '#b=2&a=1' ) , 'foo#!a=1&b=2', '$.param.fragment( url, String )' );396 equals( $.param.fragment( 'foo#', '#b=2&a=1' ) , 'foo#!a=1&b=2', '$.param.fragment( url, String )' );397 equals( $.param.fragment( 'foo#!', '#b=2&a=1' ) , 'foo#!a=1&b=2', '$.param.fragment( url, String )' );398 equals( $.param.fragment( 'foo#c=3&a=4', '#b=2&a=1' ) , 'foo#!a=1&b=2&c=3', '$.param.fragment( url, String )' );399 equals( $.param.fragment( 'foo#!c=3&a=4', '#b=2&a=1' ) , 'foo#!a=1&b=2&c=3', '$.param.fragment( url, String )' );400 401 equals( $.param.fragment( 'foo', '#!' ) , 'foo#!', '$.param.fragment( url, String )' );402 equals( $.param.fragment( 'foo', '#!b=2&a=1' ) , 'foo#!a=1&b=2', '$.param.fragment( url, String )' );403 equals( $.param.fragment( 'foo#', '#!b=2&a=1' ) , 'foo#!a=1&b=2', '$.param.fragment( url, String )' );404 equals( $.param.fragment( 'foo#!', '#!b=2&a=1' ) , 'foo#!a=1&b=2', '$.param.fragment( url, String )' );405 equals( $.param.fragment( 'foo#c=3&a=4', '#!b=2&a=1' ) , 'foo#!a=1&b=2&c=3', '$.param.fragment( url, String )' );406 equals( $.param.fragment( 'foo#!c=3&a=4', '#!b=2&a=1' ) , 'foo#!a=1&b=2&c=3', '$.param.fragment( url, String )' );407 408 $.param.fragment.ajaxCrawlable( false );409 410 // If a params fragment starts with ! and BBQ is not in ajaxCrawlable mode,411 // things can get very ugly, very quickly.412 equals( $.param.fragment( 'foo', '#!' ) , 'foo#!=', '$.param.fragment( url, String )' );413 equals( $.param.fragment( 'foo', '#!b=2&a=1' ) , 'foo#!b=2&a=1', '$.param.fragment( url, String )' );414 equals( $.param.fragment( 'foo#', '#!b=2&a=1' ) , 'foo#!b=2&a=1', '$.param.fragment( url, String )' );415 equals( $.param.fragment( 'foo#!', '#!b=2&a=1' ) , 'foo#!=&!b=2&a=1', '$.param.fragment( url, String )' );416 equals( $.param.fragment( 'foo#c=3&a=4', '#!b=2&a=1' ) , 'foo#!b=2&a=1&c=3', '$.param.fragment( url, String )' );417 equals( $.param.fragment( 'foo#!c=3&a=4', '#!b=2&a=1' ) , 'foo#!b=2&!c=3&a=1', '$.param.fragment( url, String )' );418 419});420test( 'jQuery.param.fragment.ajaxCrawlable', function() {421 expect( 5 );422 423 equals( ajaxcrawlable_init, false, 'ajaxCrawlable is disabled by default' );424 equals( $.param.fragment.ajaxCrawlable( true ), true, 'enabling ajaxCrawlable should return true' );425 equals( $.param.fragment.ajaxCrawlable(), true, 'ajaxCrawlable is now enabled' );426 equals( $.param.fragment.ajaxCrawlable( false ), false, 'disabling ajaxCrawlable should return false' );427 equals( $.param.fragment.ajaxCrawlable(), false, 'ajaxCrawlable is now disabled' );428});429test( 'jQuery.param.fragment.noEscape', function() {430 expect( 2 );431 432 equals( $.param.fragment( '#', { foo: '/a,b@c$d+e&f=g h!' } ), '#foo=/a,b%40c%24d%2Be%26f%3Dg+h!', '/, should be unescaped, everything else but space (+) should be urlencoded' );433 434 $.param.fragment.ajaxCrawlable( true );435 436 equals( $.param.fragment( '#', { foo: '/a,b@c$d+e&f=g h!' } ), '#!foo=/a,b%40c%24d%2Be%26f%3Dg+h!', '/, should be unescaped, everything else but ! and space (+) should be urlencoded' );437 438 $.param.fragment.ajaxCrawlable( false );439});440////////////////////////////////////////////////////////////////////////////////441////////////////////////////////////////////////////////////////////////////////442module( 'jQuery.deparam' );443test( 'jQuery.deparam - 1.4-style params', function() {444 expect( 2 );445 same( $.deparam( params_str ), params_obj, '$.deparam( String )' );446 same( $.deparam( params_str, true ), params_obj_coerce, '$.deparam( String, true )' );447});448test( 'jQuery.deparam - pre-1.4-style params', function() {449 var params_str = 'a=1&a=2&a=3&b=4&c=5&c=6&c=true&c=false&c=undefined&c=&d=7',450 params_obj = { a:['1','2','3'], b:'4', c:['5','6','true','false','undefined',''], d:'7' },451 params_obj_coerce = { a:[1,2,3], b:4, c:[5,6,true,false,undefined,''], d:7 };452 453 expect( 2 );454 same( $.deparam( params_str ), params_obj, '$.deparam( String )' );455 same( $.deparam( params_str, true ), params_obj_coerce, '$.deparam( String, true )' );456});457test( 'jQuery.deparam.querystring', function() {458 expect( 12 );459 460 same( $.deparam.querystring(), params_obj, 'params obj from window.location' );461 same( $.deparam.querystring( true ), params_obj_coerce, 'params obj from window.location, coerced' );462 same( $.deparam.querystring( params_str ), params_obj, 'params obj from string' );463 same( $.deparam.querystring( params_str, true ), params_obj_coerce, 'params obj from string, coerced' );464 same( $.deparam.querystring( '?' + params_str ), params_obj, 'params obj from string' );465 same( $.deparam.querystring( '?' + params_str, true ), params_obj_coerce, 'params obj from string, coerced' );466 same( $.deparam.querystring( 'foo.html?' + params_str ), params_obj, 'params obj from string' );467 same( $.deparam.querystring( 'foo.html?' + params_str, true ), params_obj_coerce, 'params obj from string, coerced' );468 same( $.deparam.querystring( 'http://a:b@example.com:1234/foo.html?' + params_str ), params_obj, 'params obj from string' );469 same( $.deparam.querystring( 'http://a:b@example.com:1234/foo.html?' + params_str, true ), params_obj_coerce, 'params obj from string, coerced' );470 same( $.deparam.querystring( 'http://a:b@example.com:1234/foo.html?' + params_str + '#bippity-boppity-boo' ), params_obj, 'params obj from string' );471 same( $.deparam.querystring( 'http://a:b@example.com:1234/foo.html?' + params_str + '#bippity-boppity-boo', true ), params_obj_coerce, 'params obj from string, coerced' );472});473test( 'jQuery.deparam.fragment', function() {474 expect( 36 );475 476 same( $.deparam.fragment(), params_obj, 'params obj from window.location' );477 same( $.deparam.fragment( true ), params_obj_coerce, 'params obj from window.location, coerced' );478 same( $.deparam.fragment( params_str ), params_obj, 'params obj from string' );479 same( $.deparam.fragment( params_str, true ), params_obj_coerce, 'params obj from string, coerced' );480 481 same( $.deparam.fragment( '#' + params_str ), params_obj, 'params obj from string' );482 same( $.deparam.fragment( '#' + params_str, true ), params_obj_coerce, 'params obj from string, coerced' );483 same( $.deparam.fragment( 'foo.html#' + params_str ), params_obj, 'params obj from string' );484 same( $.deparam.fragment( 'foo.html#' + params_str, true ), params_obj_coerce, 'params obj from string, coerced' );485 same( $.deparam.fragment( 'http://a:b@example.com:1234/foo.html#' + params_str ), params_obj, 'params obj from string' );486 same( $.deparam.fragment( 'http://a:b@example.com:1234/foo.html#' + params_str, true ), params_obj_coerce, 'params obj from string, coerced' );487 same( $.deparam.fragment( 'http://a:b@example.com:1234/foo.html?bippity-boppity-boo#' + params_str ), params_obj, 'params obj from string' );488 same( $.deparam.fragment( 'http://a:b@example.com:1234/foo.html?bippity-boppity-boo#' + params_str, true ), params_obj_coerce, 'params obj from string, coerced' );489 490 // If a params fragment starts with ! and BBQ is not in ajaxCrawlable mode,491 // things can get very ugly, very quickly.492 same( $.deparam.fragment( '#!' + params_str ), params_obj_bang, 'params obj from string' );493 same( $.deparam.fragment( '#!' + params_str, true ), params_obj_bang_coerce, 'params obj from string, coerced' );494 same( $.deparam.fragment( 'foo.html#!' + params_str ), params_obj_bang, 'params obj from string' );495 same( $.deparam.fragment( 'foo.html#!' + params_str, true ), params_obj_bang_coerce, 'params obj from string, coerced' );496 same( $.deparam.fragment( 'http://a:b@example.com:1234/foo.html#!' + params_str ), params_obj_bang, 'params obj from string' );497 same( $.deparam.fragment( 'http://a:b@example.com:1234/foo.html#!' + params_str, true ), params_obj_bang_coerce, 'params obj from string, coerced' );498 same( $.deparam.fragment( 'http://a:b@example.com:1234/foo.html?bippity-boppity-boo#!' + params_str ), params_obj_bang, 'params obj from string' );499 same( $.deparam.fragment( 'http://a:b@example.com:1234/foo.html?bippity-boppity-boo#!' + params_str, true ), params_obj_bang_coerce, 'params obj from string, coerced' );500 501 $.param.fragment.ajaxCrawlable( true );502 503 same( $.deparam.fragment( '#' + params_str ), params_obj, 'params obj from string' );504 same( $.deparam.fragment( '#' + params_str, true ), params_obj_coerce, 'params obj from string, coerced' );505 same( $.deparam.fragment( 'foo.html#' + params_str ), params_obj, 'params obj from string' );506 same( $.deparam.fragment( 'foo.html#' + params_str, true ), params_obj_coerce, 'params obj from string, coerced' );507 same( $.deparam.fragment( 'http://a:b@example.com:1234/foo.html#' + params_str ), params_obj, 'params obj from string' );508 same( $.deparam.fragment( 'http://a:b@example.com:1234/foo.html#' + params_str, true ), params_obj_coerce, 'params obj from string, coerced' );509 same( $.deparam.fragment( 'http://a:b@example.com:1234/foo.html?bippity-boppity-boo#' + params_str ), params_obj, 'params obj from string' );510 same( $.deparam.fragment( 'http://a:b@example.com:1234/foo.html?bippity-boppity-boo#' + params_str, true ), params_obj_coerce, 'params obj from string, coerced' );511 512 same( $.deparam.fragment( '#!' + params_str ), params_obj, 'params obj from string' );513 same( $.deparam.fragment( '#!' + params_str, true ), params_obj_coerce, 'params obj from string, coerced' );514 same( $.deparam.fragment( 'foo.html#!' + params_str ), params_obj, 'params obj from string' );515 same( $.deparam.fragment( 'foo.html#!' + params_str, true ), params_obj_coerce, 'params obj from string, coerced' );516 same( $.deparam.fragment( 'http://a:b@example.com:1234/foo.html#!' + params_str ), params_obj, 'params obj from string' );517 same( $.deparam.fragment( 'http://a:b@example.com:1234/foo.html#!' + params_str, true ), params_obj_coerce, 'params obj from string, coerced' );518 same( $.deparam.fragment( 'http://a:b@example.com:1234/foo.html?bippity-boppity-boo#!' + params_str ), params_obj, 'params obj from string' );519 same( $.deparam.fragment( 'http://a:b@example.com:1234/foo.html?bippity-boppity-boo#!' + params_str, true ), params_obj_coerce, 'params obj from string, coerced' );520 521 $.param.fragment.ajaxCrawlable( false );522});523////////////////////////////////////////////////////////////////////////////////524////////////////////////////////////////////////////////////////////////////////525module( 'jQuery.fn' );526$.elemUrlAttr({ span: 'arbitrary_attr' });527var test_elems = 'a form link span'.split(' ');528function init_url_attr( container, url ) {529 var container = $('<div/>').hide().appendTo('body');530 $.each( test_elems, function(i,v){531 $('<' + v + '/>')532 .attr( $.elemUrlAttr()[ v ], url )533 .appendTo( container );534 });535 return container;536};537function test_url_attr( container ) {538 var url;539 540 $.each( test_elems, function(i,v){541 var val = container.children( v ).attr( $.elemUrlAttr()[ v ] );542 if ( !url ) {543 url = val;544 } else if ( val !== url ) {545 url = -1;546 }547 });548 549 return url;550};551test( 'jQuery.fn.querystring', function() {552 expect( 60 );553 554 function fake_encode( params_str ) {555 return '?' + $.map( params_str.split('&'), encodeURIComponent ).join('&').replace( /%3D/g, '=' ).replace( /%2B/g, '+' );556 }557 558 var pre = 'http://a:b@example.com:1234/foo.html',559 post = '#get-on-the-floor',560 current_url = pre + post;561 562 run_many_tests(563 564 // execute this for each array item565 function(){566 var container,567 elems;568 569 container = init_url_attr( container, current_url );570 elems = container.children('span');571 equals( elems.length, 1, 'select the correct elements' );572 equals( elems.querystring.apply( elems, [ 'arbitrary_attr' ].concat( aps.call( arguments ) ) ), elems, 'pass query string' );573 574 container = init_url_attr( container, current_url );575 elems = container.children('a, link');576 equals( elems.length, 2, 'select the correct elements' );577 equals( elems.querystring.apply( elems, [ 'href' ].concat( aps.call( arguments ) ) ), elems, 'pass query string' );578 579 container = init_url_attr( container, current_url );580 elems = container.children();581 equals( elems.querystring.apply( elems, aps.call( arguments ) ), elems, 'pass query string' );582 583 current_url = test_url_attr( container );584 },585 586 // tests:587 588 [ { a:'2' } ],589 590 function(result){591 equals( current_url, pre + '?a=2' + post, '$.fn.querystring( url, Object )' );592 },593 594 [ { b:'2' } ],595 596 function(result){597 equals( current_url, pre + '?a=2&b=2' + post, '$.fn.querystring( url, Object )' );598 },599 600 [ { c:true, d:false, e:'undefined', f:'' } ],601 602 function(result){603 equals( current_url, pre + '?a=2&b=2&c=true&d=false&e=undefined&f=' + post, '$.fn.querystring( url, Object )' );604 },605 606 [ { a:[4,5,6], b:{x:[7], y:8, z:[9,0,'true','false','undefined','']} }, 2 ],607 608 function(result){609 var params = old_jquery610 ? 'a=4&a=5&a=6&b=[object+Object]'611 : 'a[]=4&a[]=5&a[]=6&b[x][]=7&b[y]=8&b[z][]=9&b[z][]=0&b[z][]=true&b[z][]=false&b[z][]=undefined&b[z][]=';612 613 equals( current_url, pre + fake_encode( params ) + post, '$.fn.querystring( url, Object, 2 )' );614 },615 616 [ { a:'1', c:'2' }, 1 ],617 618 function(result){619 var params = old_jquery620 ? 'a=4&a=5&a=6&b=[object+Object]&c=2'621 : 'a[]=4&a[]=5&a[]=6&b[x][]=7&b[y]=8&b[z][]=9&b[z][]=0&b[z][]=true&b[z][]=false&b[z][]=undefined&b[z][]=&c=2';622 623 equals( current_url, pre + fake_encode( params ) + post, '$.fn.querystring( url, Object, 1 )' );624 },625 626 [ 'foo=1' ],627 628 function(result){629 var params = old_jquery630 ? 'a=4&a=5&a=6&b=[object+Object]&c=2&foo=1'631 : 'a[]=4&a[]=5&a[]=6&b[x][]=7&b[y]=8&b[z][]=9&b[z][]=0&b[z][]=true&b[z][]=false&b[z][]=undefined&b[z][]=&c=2&foo=1';632 633 equals( current_url, pre + fake_encode( params ) + post, '$.fn.querystring( url, String )' );634 },635 636 [ 'foo=2&bar=3', 1 ],637 638 function(result){639 var params = old_jquery640 ? 'a=4&a=5&a=6&b=[object+Object]&bar=3&c=2&foo=1'641 : 'a[]=4&a[]=5&a[]=6&b[x][]=7&b[y]=8&b[z][]=9&b[z][]=0&b[z][]=true&b[z][]=false&b[z][]=undefined&b[z][]=&bar=3&c=2&foo=1';642 643 equals( current_url, pre + fake_encode( params ) + post, '$.fn.querystring( url, String, 1 )' );644 },645 646 [ 'http://example.com/test.html?/path/to/file.php#the-cow-goes-moo', 2 ],647 648 function(result){649 equals( current_url, pre + '?/path/to/file.php' + post, '$.fn.querystring( url, String, 2 )' );650 },651 652 [ '?another-example', 2 ],653 654 function(result){655 equals( current_url, pre + '?another-example' + post, '$.fn.querystring( url, String, 2 )' );656 },657 658 [ 'i_am_out_of_witty_strings', 2 ],659 660 function(result){661 equals( current_url, pre + '?i_am_out_of_witty_strings' + post, '$.fn.querystring( url, String, 2 )' );662 }663 664 );665 666});667test( 'jQuery.fn.fragment', function() {668 expect( 240 );669 670 function fake_encode( params_str ) {671 return '#' + $.map( params_str.split('&'), encodeURIComponent ).join('&').replace( /%3D/g, '=' ).replace( /%2B/g, '+' );672 }673 674 var pre = 'http://a:b@example.com:1234/foo.html?and-dance-with-me',675 current_url = pre;676 677 run_many_tests(678 679 // execute this for each array item680 function( params, merge_mode ){681 current_url = test_fn_fragment( current_url, params, merge_mode );682 },683 684 // tests:685 686 [ { a:'2' } ],687 688 function(result){689 equals( current_url, pre + '#a=2', '$.fn.fragment( url, Object )' );690 },691 692 [ { b:'2' } ],693 694 function(result){695 equals( current_url, pre + '#a=2&b=2', '$.fn.fragment( url, Object )' );696 },697 698 [ { c:true, d:false, e:'undefined', f:'' } ],699 700 function(result){701 equals( current_url, pre + '#a=2&b=2&c=true&d=false&e=undefined&f=', '$.fn.fragment( url, Object )' );702 },703 704 [ { a:[4,5,6], b:{x:[7], y:8, z:[9,0,'true','false','undefined','']} }, 2 ],705 706 function(result){707 var params = old_jquery708 ? 'a=4&a=5&a=6&b=[object+Object]'709 : 'a[]=4&a[]=5&a[]=6&b[x][]=7&b[y]=8&b[z][]=9&b[z][]=0&b[z][]=true&b[z][]=false&b[z][]=undefined&b[z][]=';710 711 equals( current_url, pre + fake_encode( params ), '$.fn.fragment( url, Object, 2 )' );712 },713 714 [ { a:'1', c:'2' }, 1 ],715 716 function(result){717 var params = old_jquery718 ? 'a=4&a=5&a=6&b=[object+Object]&c=2'719 : 'a[]=4&a[]=5&a[]=6&b[x][]=7&b[y]=8&b[z][]=9&b[z][]=0&b[z][]=true&b[z][]=false&b[z][]=undefined&b[z][]=&c=2';720 721 equals( current_url, pre + fake_encode( params ), '$.fn.fragment( url, Object, 1 )' );722 },723 724 [ 'foo=1' ],725 726 function(result){727 var params = old_jquery728 ? 'a=4&a=5&a=6&b=[object+Object]&c=2&foo=1'729 : 'a[]=4&a[]=5&a[]=6&b[x][]=7&b[y]=8&b[z][]=9&b[z][]=0&b[z][]=true&b[z][]=false&b[z][]=undefined&b[z][]=&c=2&foo=1';730 731 equals( current_url, pre + fake_encode( params ), '$.fn.fragment( url, String )' );732 },733 734 [ 'foo=2&bar=3', 1 ],735 736 function(result){737 var params = old_jquery738 ? 'a=4&a=5&a=6&b=[object+Object]&bar=3&c=2&foo=1'739 : 'a[]=4&a[]=5&a[]=6&b[x][]=7&b[y]=8&b[z][]=9&b[z][]=0&b[z][]=true&b[z][]=false&b[z][]=undefined&b[z][]=&bar=3&c=2&foo=1';740 741 equals( current_url, pre + fake_encode( params ), '$.fn.fragment( url, String, 1 )' );742 },743 744 [ 'http://example.com/test.html?the-cow-goes-moo#/path/to/file.php', 2 ],745 746 function(result){747 equals( current_url, pre + '#/path/to/file.php', '$.fn.fragment( url, String, 2 )' );748 },749 750 [ '#another-example', 2 ],751 752 function(result){753 equals( current_url, pre + '#another-example', '$.fn.fragment( url, String, 2 )' );754 },755 756 [ 'i_am_out_of_witty_strings', 2 ],757 758 function(result){759 equals( current_url, pre + '#i_am_out_of_witty_strings', '$.fn.fragment( url, String, 2 )' );760 }761 762 );763 764 $.param.fragment.ajaxCrawlable( true );765 766 function test_fn_fragment( url, params, merge_mode ) {767 var container,768 elems;769 770 container = init_url_attr( container, url );771 elems = container.children('span');772 equals( elems.length, 1, 'select the correct elements' );773 equals( elems.fragment( 'arbitrary_attr', params, merge_mode ), elems, 'pass fragment' );774 775 container = init_url_attr( container, url );776 elems = container.children('a, link');777 equals( elems.length, 2, 'select the correct elements' );778 equals( elems.fragment( params, merge_mode ), elems, 'pass fragment' );779 780 container = init_url_attr( container, url );781 elems = container.children();782 equals( elems.fragment( params, merge_mode ), elems, 'pass fragment' );783 784 return test_url_attr( container );785 };786 787 equals( test_fn_fragment( 'foo', {} ) , 'foo#!', '$.fn.fragment( url, Object )' );788 equals( test_fn_fragment( 'foo', { b:2, a:1 } ) , 'foo#!a=1&b=2', '$.fn.fragment( url, Object )' );789 equals( test_fn_fragment( 'foo#', { b:2, a:1 } ) , 'foo#!a=1&b=2', '$.fn.fragment( url, Object )' );790 equals( test_fn_fragment( 'foo#!', { b:2, a:1 } ) , 'foo#!a=1&b=2', '$.fn.fragment( url, Object )' );791 equals( test_fn_fragment( 'foo#c=3&a=4', { b:2, a:1 } ) , 'foo#!a=1&b=2&c=3', '$.fn.fragment( url, Object )' );792 equals( test_fn_fragment( 'foo#!c=3&a=4', { b:2, a:1 } ) , 'foo#!a=1&b=2&c=3', '$.fn.fragment( url, Object )' );793 794 equals( test_fn_fragment( 'foo', '' ) , 'foo#!', '$.fn.fragment( url, String )' );795 equals( test_fn_fragment( 'foo', 'b=2&a=1' ) , 'foo#!a=1&b=2', '$.fn.fragment( url, String )' );796 equals( test_fn_fragment( 'foo#', 'b=2&a=1' ) , 'foo#!a=1&b=2', '$.fn.fragment( url, String )' );797 equals( test_fn_fragment( 'foo#!', 'b=2&a=1' ) , 'foo#!a=1&b=2', '$.fn.fragment( url, String )' );798 equals( test_fn_fragment( 'foo#c=3&a=4', 'b=2&a=1' ) , 'foo#!a=1&b=2&c=3', '$.fn.fragment( url, String )' );799 equals( test_fn_fragment( 'foo#!c=3&a=4', 'b=2&a=1' ) , 'foo#!a=1&b=2&c=3', '$.fn.fragment( url, String )' );800 801 equals( test_fn_fragment( 'foo', '#' ) , 'foo#!', '$.fn.fragment( url, String )' );802 equals( test_fn_fragment( 'foo', '#b=2&a=1' ) , 'foo#!a=1&b=2', '$.fn.fragment( url, String )' );803 equals( test_fn_fragment( 'foo#', '#b=2&a=1' ) , 'foo#!a=1&b=2', '$.fn.fragment( url, String )' );804 equals( test_fn_fragment( 'foo#!', '#b=2&a=1' ) , 'foo#!a=1&b=2', '$.fn.fragment( url, String )' );805 equals( test_fn_fragment( 'foo#c=3&a=4', '#b=2&a=1' ) , 'foo#!a=1&b=2&c=3', '$.fn.fragment( url, String )' );806 equals( test_fn_fragment( 'foo#!c=3&a=4', '#b=2&a=1' ) , 'foo#!a=1&b=2&c=3', '$.fn.fragment( url, String )' );807 808 equals( test_fn_fragment( 'foo', '#!' ) , 'foo#!', '$.fn.fragment( url, String )' );809 equals( test_fn_fragment( 'foo', '#!b=2&a=1' ) , 'foo#!a=1&b=2', '$.fn.fragment( url, String )' );810 equals( test_fn_fragment( 'foo#', '#!b=2&a=1' ) , 'foo#!a=1&b=2', '$.fn.fragment( url, String )' );811 equals( test_fn_fragment( 'foo#!', '#!b=2&a=1' ) , 'foo#!a=1&b=2', '$.fn.fragment( url, String )' );812 equals( test_fn_fragment( 'foo#c=3&a=4', '#!b=2&a=1' ) , 'foo#!a=1&b=2&c=3', '$.fn.fragment( url, String )' );813 equals( test_fn_fragment( 'foo#!c=3&a=4', '#!b=2&a=1' ) , 'foo#!a=1&b=2&c=3', '$.fn.fragment( url, String )' );814 815 $.param.fragment.ajaxCrawlable( false );816 817 // If a params fragment starts with ! and BBQ is not in ajaxCrawlable mode,818 // things can get very ugly, very quickly.819 equals( test_fn_fragment( 'foo', '#!' ) , 'foo#!=', '$.fn.fragment( url, String )' );820 equals( test_fn_fragment( 'foo', '#!b=2&a=1' ) , 'foo#!b=2&a=1', '$.fn.fragment( url, String )' );821 equals( test_fn_fragment( 'foo#', '#!b=2&a=1' ) , 'foo#!b=2&a=1', '$.fn.fragment( url, String )' );822 equals( test_fn_fragment( 'foo#!', '#!b=2&a=1' ) , 'foo#!=&!b=2&a=1', '$.fn.fragment( url, String )' );823 equals( test_fn_fragment( 'foo#c=3&a=4', '#!b=2&a=1' ) , 'foo#!b=2&a=1&c=3', '$.fn.fragment( url, String )' );824 equals( test_fn_fragment( 'foo#!c=3&a=4', '#!b=2&a=1' ) , 'foo#!b=2&!c=3&a=1', '$.fn.fragment( url, String )' );825 826});827////////////////////////////////////////////////////////////////////////////////828////////////////////////////////////////////////////////////////////////////////829module( 'jQuery.bbq' );830test( 'jQuery.bbq.pushState(), jQuery.bbq.getState(), jQuery.bbq.removeState(), window.onhashchange', function() {831 expect( old_jquery ? 95 : 167 );832 833 var a, b, c, d, e, f, x, y, hash, hash_actual, obj, event, msg = 'Testing window.onhashchange and history';834 835 $.bbq.pushState();836 equals( window.location.hash.replace( /^#/, ''), '', 'window.location hash should be empty' );837 838 $.bbq.pushState({ a:'1', b:'1' });839 same( $.deparam.fragment(), { a:'1', b:'1' }, 'hash should be set properly' );840 841 $(window).bind( 'hashchange', function(evt) {842 var hash_str = $.param.fragment(),843 param_obj = $.bbq.getState(),844 param_val = $.bbq.getState( 'param_name' );845 846 event = evt;847 hash = $.param.fragment();848 hash_actual = location.hash;849 obj = { str: $.bbq.getState(), coerce: $.bbq.getState( true ) };850 a = { str: $.bbq.getState( 'a' ), coerce: $.bbq.getState( 'a', true ) };851 b = { str: $.bbq.getState( 'b' ), coerce: $.bbq.getState( 'b', true ) };852 c = { str: $.bbq.getState( 'c' ), coerce: $.bbq.getState( 'c', true ) };853 d = { str: $.bbq.getState( 'd' ), coerce: $.bbq.getState( 'd', true ) };854 e = { str: $.bbq.getState( 'e' ), coerce: $.bbq.getState( 'e', true ) };855 f = { str: $.bbq.getState( 'f' ), coerce: $.bbq.getState( 'f', true ) };856 857 }).trigger( 'hashchange' );858 859 same( obj.str, { a:'1', b:'1' }, 'hashchange triggered manually: $.bbq.getState()' );860 same( obj.coerce, { a:1, b:1 }, 'hashchange triggered manually: $.bbq.getState( true )' );861 equals( a.str, '1', 'hashchange triggered manually: $.bbq.getState( "a" )' );862 equals( a.coerce, 1, 'hashchange triggered manually: $.bbq.getState( "a", true )' );863 864 if ( !old_jquery ) {865 same( event.getState(), { a:'1', b:'1' }, 'hashchange triggered manually: event.getState()' );866 same( event.getState(true), { a:1, b:1 }, 'hashchange triggered manually: event.getState( true )' );867 equals( event.getState('a'), '1', 'hashchange triggered manually: event.getState( "a" )' );868 equals( event.getState('a',true), 1, 'hashchange triggered manually: event.getState( "a", true )' );869 }870 871 run_many_tests(872 // run asynchronously873 250,874 875 // execute this for each array item876 function(){877 notice( msg += '.' );878 $.bbq.pushState.apply( this, aps.call( arguments ) );879 },880 881 // execute this at the end882 function(){883 notice();884 },885 886 // tests:887 888 [ { a:'2' } ],889 890 function(result){891 equals( hash_actual, '#' + hash, 'hash should begin with #!' );892 same( obj.str, { a:'2', b:'1' }, '$.bbq.getState()' );893 same( obj.coerce, { a:2, b:1 }, '$.bbq.getState( true )' );894 equals( a.str, '2', '$.bbq.getState( "a" )' );895 equals( a.coerce, 2, '$.bbq.getState( "a", true )' );896 if ( !old_jquery ) {897 same( event.getState(), { a:'2', b:'1' }, 'event.getState()' );898 same( event.getState(true), { a:2, b:1 }, 'event.getState( true )' );899 equals( event.getState('a'), '2', 'event.getState( "a" )' );900 equals( event.getState('a',true), 2, 'event.getState( "a", true )' );901 }902 },903 904 [ { b:'2' } ],905 906 function(result){907 equals( hash_actual, '#' + hash, 'hash should begin with #!' );908 same( obj.str, { a:'2', b:'2' }, '$.bbq.getState()' );909 same( obj.coerce, { a:2, b:2 }, '$.bbq.getState( true )' );910 equals( b.str, '2', '$.bbq.getState( "b" )' );911 equals( b.coerce, 2, '$.bbq.getState( "b", true )' );912 if ( !old_jquery ) {913 same( event.getState(), { a:'2', b:'2' }, 'event.getState()' );914 same( event.getState(true), { a:2, b:2 }, 'event.getState( true )' );915 equals( event.getState('b'), '2', 'event.getState( "b" )' );916 equals( event.getState('b',true), 2, 'event.getState( "b", true )' );917 }918 },919 920 [ { c:true, d:false, e:'undefined', f:'' } ],921 922 function(result){923 equals( hash_actual, '#' + hash, 'hash should begin with #!' );924 same( obj.str, { a:'2', b:'2', c:'true', d:'false', e:'undefined', f:'' }, '$.bbq.getState()' );925 same( obj.coerce, { a:2, b:2, c:true, d:false, e:undefined, f:'' }, '$.bbq.getState( true )' );926 equals( c.str, 'true', '$.bbq.getState( "c" )' );927 equals( c.coerce, true, '$.bbq.getState( "c", true )' );928 equals( d.str, 'false', '$.bbq.getState( "d" )' );929 equals( d.coerce, false, '$.bbq.getState( "d", true )' );930 equals( e.str, 'undefined', '$.bbq.getState( "e" )' );931 equals( e.coerce, undefined, '$.bbq.getState( "e", true )' );932 equals( f.str, '', '$.bbq.getState( "f" )' );933 equals( f.coerce, '', '$.bbq.getState( "f", true )' );934 if ( !old_jquery ) {935 same( event.getState(), { a:'2', b:'2', c:'true', d:'false', e:'undefined', f:'' }, 'event.getState()' );936 same( event.getState(true), { a:2, b:2, c:true, d:false, e:undefined, f:'' }, 'event.getState( true )' );937 equals( event.getState('c'), 'true', 'event.getState( "c" )' );938 equals( event.getState('c',true), true, 'event.getState( "c", true )' );939 equals( event.getState('d'), 'false', 'event.getState( "d" )' );940 equals( event.getState('d',true), false, 'event.getState( "d", true )' );941 equals( event.getState('e'), 'undefined', 'event.getState( "e" )' );942 equals( event.getState('e',true), undefined, 'event.getState( "e", true )' );943 equals( event.getState('f'), '', 'event.getState( "f" )' );944 equals( event.getState('f',true), '', 'event.getState( "f", true )' );945 }946 },947 948 function(result){949 $.param.fragment.ajaxCrawlable( true );950 },951 952 function(result){953 $.bbq.removeState( 'c' );954 },955 956 function(result){957 equals( hash_actual, '#!' + hash, 'hash should begin with #!' );958 same( obj.str, { a:'2', b:'2', d:'false', e:'undefined', f:'' }, '$.bbq.getState()' );959 same( obj.coerce, { a:2, b:2, d:false, e:undefined, f:'' }, '$.bbq.getState( true )' );960 equals( a.str, '2', '$.bbq.getState( "a" )' );961 equals( a.coerce, 2, '$.bbq.getState( "a", true )' );962 equals( b.str, '2', '$.bbq.getState( "b" )' );963 equals( b.coerce, 2, '$.bbq.getState( "b", true )' );964 equals( c.str, undefined, '$.bbq.getState( "c" )' );965 equals( c.coerce, undefined, '$.bbq.getState( "c", true )' );966 equals( d.str, 'false', '$.bbq.getState( "d" )' );967 equals( d.coerce, false, '$.bbq.getState( "d", true )' );968 equals( e.str, 'undefined', '$.bbq.getState( "e" )' );969 equals( e.coerce, undefined, '$.bbq.getState( "e", true )' );970 equals( f.str, '', '$.bbq.getState( "f" )' );971 equals( f.coerce, '', '$.bbq.getState( "f", true )' );972 if ( !old_jquery ) {973 same( event.getState(), { a:'2', b:'2', d:'false', e:'undefined', f:'' }, 'event.getState()' );974 same( event.getState(true), { a:2, b:2, d:false, e:undefined, f:'' }, 'event.getState( true )' );975 equals( event.getState('a'), '2', 'event.getState( "a" )' );976 equals( event.getState('a',true), 2, 'event.getState( "a", true )' );977 equals( event.getState('b'), '2', 'event.getState( "b" )' );978 equals( event.getState('b',true), 2, 'event.getState( "b", true )' );979 equals( event.getState('c'), undefined, 'event.getState( "c" )' );980 equals( event.getState('c',true), undefined, 'event.getState( "c", true )' );981 equals( event.getState('d'), 'false', 'event.getState( "d" )' );982 equals( event.getState('d',true), false, 'event.getState( "d", true )' );983 equals( event.getState('e'), 'undefined', 'event.getState( "e" )' );984 equals( event.getState('e',true), undefined, 'event.getState( "e", true )' );985 equals( event.getState('f'), '', 'event.getState( "f" )' );986 equals( event.getState('f',true), '', 'event.getState( "f", true )' );987 }988 },989 990 function(result){991 $.bbq.removeState( [ 'd', 'e', 'f', 'nonexistent' ] );992 },993 994 function(result){995 equals( hash_actual, '#!' + hash, 'hash should begin with #!' );996 same( obj.str, { a:'2', b:'2' }, '$.bbq.getState()' );997 same( obj.coerce, { a:2, b:2 }, '$.bbq.getState( true )' );998 equals( a.str, '2', '$.bbq.getState( "a" )' );999 equals( a.coerce, 2, '$.bbq.getState( "a", true )' );1000 equals( b.str, '2', '$.bbq.getState( "b" )' );1001 equals( b.coerce, 2, '$.bbq.getState( "b", true )' );1002 equals( c.str, undefined, '$.bbq.getState( "c" )' );1003 equals( c.coerce, undefined, '$.bbq.getState( "c", true )' );1004 equals( d.str, undefined, '$.bbq.getState( "d" )' );1005 equals( d.coerce, undefined, '$.bbq.getState( "d", true )' );1006 equals( e.str, undefined, '$.bbq.getState( "e" )' );1007 equals( e.coerce, undefined, '$.bbq.getState( "e", true )' );1008 equals( f.str, undefined, '$.bbq.getState( "f" )' );1009 equals( f.coerce, undefined, '$.bbq.getState( "f", true )' );1010 if ( !old_jquery ) {1011 same( event.getState(), { a:'2', b:'2' }, 'event.getState()' );1012 same( event.getState(true), { a:2, b:2 }, 'event.getState( true )' );1013 equals( event.getState('a'), '2', 'event.getState( "a" )' );1014 equals( event.getState('a',true), 2, 'event.getState( "a", true )' );1015 equals( event.getState('b'), '2', 'event.getState( "b" )' );1016 equals( event.getState('b',true), 2, 'event.getState( "b", true )' );1017 equals( event.getState('c'), undefined, 'event.getState( "c" )' );1018 equals( event.getState('c',true), undefined, 'event.getState( "c", true )' );1019 equals( event.getState('d'), undefined, 'event.getState( "d" )' );1020 equals( event.getState('d',true), undefined, 'event.getState( "d", true )' );1021 equals( event.getState('e'), undefined, 'event.getState( "e" )' );1022 equals( event.getState('e',true), undefined, 'event.getState( "e", true )' );1023 equals( event.getState('f'), undefined, 'event.getState( "f" )' );1024 equals( event.getState('f',true), undefined, 'event.getState( "f", true )' );1025 }1026 },1027 1028 function(result){1029 $.bbq.removeState();1030 },1031 1032 function(result){1033 equals( hash_actual, '#!', 'hash should just be #!' );1034 same( obj.str, {}, '$.bbq.getState()' );1035 same( obj.coerce, {}, '$.bbq.getState( true )' );1036 equals( a.str, undefined, '$.bbq.getState( "a" )' );1037 equals( a.coerce, undefined, '$.bbq.getState( "a", true )' );1038 equals( b.str, undefined, '$.bbq.getState( "b" )' );1039 equals( b.coerce, undefined, '$.bbq.getState( "b", true )' );1040 equals( c.str, undefined, '$.bbq.getState( "c" )' );1041 equals( c.coerce, undefined, '$.bbq.getState( "c", true )' );1042 equals( d.str, undefined, '$.bbq.getState( "d" )' );1043 equals( d.coerce, undefined, '$.bbq.getState( "d", true )' );1044 equals( e.str, undefined, '$.bbq.getState( "e" )' );1045 equals( e.coerce, undefined, '$.bbq.getState( "e", true )' );1046 equals( f.str, undefined, '$.bbq.getState( "f" )' );1047 equals( f.coerce, undefined, '$.bbq.getState( "f", true )' );1048 if ( !old_jquery ) {1049 same( event.getState(), {}, 'event.getState()' );1050 same( event.getState(true), {}, 'event.getState( true )' );1051 equals( event.getState('a'), undefined, 'event.getState( "a" )' );1052 equals( event.getState('a',true), undefined, 'event.getState( "a", true )' );1053 equals( event.getState('b'), undefined, 'event.getState( "b" )' );1054 equals( event.getState('b',true), undefined, 'event.getState( "b", true )' );1055 equals( event.getState('c'), undefined, 'event.getState( "c" )' );1056 equals( event.getState('c',true), undefined, 'event.getState( "c", true )' );1057 equals( event.getState('d'), undefined, 'event.getState( "d" )' );1058 equals( event.getState('d',true), undefined, 'event.getState( "d", true )' );1059 equals( event.getState('e'), undefined, 'event.getState( "e" )' );1060 equals( event.getState('e',true), undefined, 'event.getState( "e", true )' );1061 equals( event.getState('f'), undefined, 'event.getState( "f" )' );1062 equals( event.getState('f',true), undefined, 'event.getState( "f", true )' );1063 }1064 },1065 1066 [ { a:'2', b:'2', c:true, d:false, e:'undefined', f:'' } ],1067 1068 [ { a:[4,5,6], b:{x:[7], y:8, z:[9,0,'true','false','undefined','']} }, 2 ],1069 1070 function(result){1071 var b_str = old_jquery1072 ? '[object Object]'1073 : {x:['7'], y:'8', z:['9','0','true','false','undefined','']},1074 b_coerce = old_jquery1075 ? '[object Object]'1076 : {x:[7], y:8, z:[9,0,true,false,undefined,'']};1077 1078 equals( hash_actual, '#!' + hash, 'hash should begin with #!' );1079 same( obj.str, { a:['4','5','6'], b:b_str }, '$.bbq.getState()' );1080 same( obj.coerce, { a:[4,5,6], b:b_coerce }, '$.bbq.getState( true )' );1081 same( a.str, ['4','5','6'], '$.bbq.getState( "a" )' );1082 same( a.coerce, [4,5,6], '$.bbq.getState( "a", true )' );1083 if ( !old_jquery ) {1084 same( event.getState(), { a:['4','5','6'], b:b_str }, 'event.getState()' );1085 same( event.getState(true), { a:[4,5,6], b:b_coerce }, 'event.getState( true )' );1086 same( event.getState('a'), ['4','5','6'], 'event.getState( "a" )' );1087 same( event.getState('a',true), [4,5,6], 'event.getState( "a", true )' );1088 }1089 },1090 1091 [ { a:'1', c:'2' }, 1 ],1092 1093 function(result){1094 var b_str = old_jquery1095 ? '[object Object]'1096 : {x:['7'], y:'8', z:['9','0','true','false','undefined','']},1097 b_coerce = old_jquery1098 ? '[object Object]'1099 : {x:[7], y:8, z:[9,0,true,false,undefined,'']};1100 1101 equals( hash_actual, '#!' + hash, 'hash should begin with #!' );1102 same( obj.str, { a:['4','5','6'], b:b_str, c:'2' }, '$.bbq.getState()' );1103 same( obj.coerce, { a:[4,5,6], b:b_coerce, c:2 }, '$.bbq.getState( true )' );1104 if ( !old_jquery ) {1105 same( event.getState(), { a:['4','5','6'], b:b_str, c:'2' }, 'event.getState()' );1106 same( event.getState(true), { a:[4,5,6], b:b_coerce, c:2 }, 'event.getState( true )' );1107 }1108 },1109 1110 [ '#/path/to/file.php', 2 ],1111 1112 function(result){1113 equals( hash_actual, '#!' + hash, 'hash should begin with #!' );1114 equals( hash, '/path/to/file.php', '$.param.fragment()' );1115 if ( !old_jquery ) {1116 equals( event.fragment, '/path/to/file.php', 'event.fragment' );1117 }1118 },1119 1120 [],1121 1122 function(result){1123 equals( hash_actual, '#!', 'hash should just be #!' );1124 equals( hash, '', '$.param.fragment()' );1125 if ( !old_jquery ) {1126 equals( event.fragment, '', 'event.fragment' );1127 }1128 },1129 1130 function(result){1131 $(window).bind( 'hashchange', function(evt){1132 x = $.param.fragment();1133 });1134 },1135 1136 [ '#omg_ponies', 2 ],1137 1138 function(result){1139 equals( hash, 'omg_ponies', 'event handler 1: $.param.fragment()' );1140 equals( x, 'omg_ponies', 'event handler 2: $.param.fragment()' );1141 1142 hash = x = '';1143 equals( hash + x, '', 'vars reset' );1144 1145 $(window).triggerHandler( 'hashchange' );1146 equals( hash, 'omg_ponies', 'event handler 1: $.param.fragment()' );1147 equals( x, 'omg_ponies', 'event handler 2: $.param.fragment()' );1148 1149 hash = x = '';1150 equals( hash + x, '', 'vars reset' );1151 1152 $(window).unbind( 'hashchange' );1153 },1154 1155 [ '#almost_done?not_search', 2 ],1156 1157 function(result){1158 equals( hash, '', 'event handler 1: $.param.fragment()' );1159 equals( x, '', 'event handler 2: $.param.fragment()' );1160 1161 var events = $.data( window, 'events' );1162 ok( !events || !events.hashchange, 'hashchange event unbound' );1163 },1164 1165 [ '#' ],1166 1167 function(result){1168 x = [];1169 $(window).bind( 'hashchange', function(evt){1170 x.push( $.param.fragment() );1171 });1172 },1173 1174 function(result){1175 !is_chrome && window.history.go( -1 );1176 },1177 1178 function(result){1179 !is_chrome && window.history.go( -1 );1180 },1181 1182 function(result){1183 !is_chrome && window.history.go( -1 );1184 },1185 1186 function(result){1187 !is_chrome && window.history.go( -1 );1188 },1189 1190 function(result){1191 if ( is_chrome ) {1192 // Read about this issue here: http://benalman.com/news/2009/09/chrome-browser-history-buggine/1193 ok( true, 'history is sporadically broken in chrome, this is a known bug, so this test is skipped in chrome' );1194 } else {1195 same( x, ['almost_done?not_search', 'omg_ponies', '', '/path/to/file.php'], 'back button and window.bbq.go(-1) should work' );1196 }1197 1198 $(window).unbind( 'hashchange' );1199 var events = $.data( window, 'events' );1200 ok( !events || !events.hashchange, 'hashchange event unbound' );1201 },1202 1203 function(result){1204 $.param.fragment.ajaxCrawlable( false );1205 },1206 1207 [ '#all_done' ]1208 1209 );1210 1211});...
playback.js
Source:playback.js
1/*2 * Copyright 2018, GeoSolutions Sas.3 * All rights reserved.4 *5 * This source code is licensed under the BSD-style license found in the6 * LICENSE file in the root directory of this source tree.7 */8import moment from 'moment';9import { get } from 'lodash';10import {11 PLAY,12 PAUSE,13 STOP,14 STATUS,15 SET_FRAMES,16 SET_CURRENT_FRAME,17 TOGGLE_ANIMATION_MODE,18 ANIMATION_STEP_MOVE,19 stop,20 setFrames,21 appendFrames,22 setCurrentFrame,23 framesLoading,24 updateMetadata25} from '../actions/playback';26import { moveTime, SET_CURRENT_TIME, MOVE_TIME } from '../actions/dimension';27import { selectLayer, onRangeChanged, timeDataLoading, SELECT_LAYER, SET_MAP_SYNC } from '../actions/timeline';28import { changeLayerProperties, REMOVE_NODE } from '../actions/layers';29import { error } from '../actions/notifications';30import {31 currentTimeSelector,32 layersWithTimeDataSelector,33 layerTimeSequenceSelectorCreator34} from '../selectors/dimension';35import { LOCATION_CHANGE } from 'connected-react-router';36import {37 currentFrameSelector,38 currentFrameValueSelector,39 lastFrameSelector,40 playbackRangeSelector,41 playbackSettingsSelector,42 frameDurationSelector,43 statusSelector,44 playbackMetadataSelector45} from '../selectors/playback';46import {47 selectedLayerSelector,48 selectedLayerName,49 selectedLayerUrl,50 selectedLayerData,51 selectedLayerTimeDimensionConfiguration,52 rangeSelector,53 timelineLayersSelector,54 multidimOptionsSelectorCreator55} from '../selectors/timeline';56import pausable from '../observables/pausable';57import { wrapStartStop } from '../observables/epics';58import { getDomainValues } from '../api/MultiDim';59import Rx from 'rxjs';60const BUFFER_SIZE = 20;61const PRELOAD_BEFORE = 10;62const toAbsoluteInterval = (start, end) => `${start}/${end}`;63/**64 * Generates the argument to pass to the getDomainValues service.65 * @param {function} getState return the state66 * @param {object} paginationOptions additional options to send to the service. (e.g. `fromValue`)67 */68const domainArgs = (getState, paginationOptions = {}) => {69 const id = selectedLayerSelector(getState());70 const layerName = selectedLayerName(getState());71 const layerUrl = selectedLayerUrl(getState());72 const { startPlaybackTime, endPlaybackTime } = playbackRangeSelector(getState()) || {};73 const shouldFilter = statusSelector(getState()) === STATUS.PLAY || statusSelector(getState()) === STATUS.PAUSE;74 return [layerUrl, layerName, "time", {75 limit: BUFFER_SIZE, // default, can be overridden by pagination options76 time: startPlaybackTime && endPlaybackTime && shouldFilter ? toAbsoluteInterval(startPlaybackTime, endPlaybackTime) : undefined,77 ...paginationOptions78 },79 multidimOptionsSelectorCreator(id)(getState())80 ];81};82/**83 * Emulates the getDomainValues when user wants to animate with fixed step (e.g. 1 hour)84 * Returns the stream that emits an array containing the animation steps.85 *86 * @param {function} getState returns the state87 * @param {objects} param1 the options to use. May contain `fromValue`88 */89const createAnimationValues = (getState, { fromValue, limit = BUFFER_SIZE, sort = "asc" } = {}) => {90 const {91 timeStep,92 stepUnit93 } = playbackSettingsSelector(getState());94 const interval = moment.duration(timeStep, stepUnit);95 const playbackRange = playbackRangeSelector(getState()) || {};96 const startPlaybackTime = playbackRange.startPlaybackTime;97 const endPlaybackTime = playbackRange.endPlaybackTime;98 let currentTime = fromValue !== undefined ? fromValue : startPlaybackTime || currentTimeSelector(getState()) || (new Date()).toString();99 const values = [];100 if (currentTime !== fromValue) {101 values.push(moment(currentTime).toISOString());102 }103 for (let i = 0; i < limit; i++) {104 currentTime = moment(currentTime).add(sort === "asc" ? interval : -1 * interval);105 if (!endPlaybackTime || currentTime.isBefore(endPlaybackTime)) {106 values.push(currentTime.toISOString());107 } else {108 break;109 }110 }111 return Rx.Observable.of(values);112};113/**114 * Gets the static list of times to animate115 */116const filterAnimationValues = (values, getState, {fromValue, limit = BUFFER_SIZE} = {}) => {117 const playbackRange = playbackRangeSelector(getState()) || {};118 const startPlaybackTime = playbackRange.startPlaybackTime;119 const endPlaybackTime = playbackRange.endPlaybackTime;120 return Rx.Observable.of(values121 // remove times before out of playback range122 .filter(v => startPlaybackTime && endPlaybackTime ? moment(v).isSameOrAfter(startPlaybackTime) && moment(v).isSameOrBefore(endPlaybackTime) : true)123 // Remove values before fromValue124 .filter(v => fromValue ? moment(v).isAfter(fromValue) : true)125 // limit size to BUFFER_SIZE126 .slice(0, limit));127};128/**129 * Returns an observable that emit an array of time frames, based of the current configuration:130 * - If configured as fixed steps, it returns the list of next animation frame calculating them131 * - If there is a selected layer and there is the Multidim extension, then use it (in favour of static values configured)132 * - If there are values in the dimension configuration, and the Multidim extension is not present, use them to animate133 * @param {function} getState returns the application state134 * @param {object} options the options that normally match the getDomainValues options135 */136const getAnimationFrames = (getState, options) => {137 if (selectedLayerName(getState())) {138 const values = layerTimeSequenceSelectorCreator(selectedLayerData(getState()))(getState());139 const timeDimConfig = selectedLayerTimeDimensionConfiguration(getState());140 // check if multidim extension is available. It has priority to local values141 if (get(timeDimConfig, "source.type") !== "multidim-extension" && values && values.length > 0) {142 return filterAnimationValues(values, getState, options);143 }144 return getDomainValues(...domainArgs(getState, options))145 .map(res => res.DomainValues.Domain.split(","));146 }147 return createAnimationValues(getState, options);148};149/**150 * Setup animation adding some action before and after the animationEventsStream$151 * Function returns a a function that operates on the stream (aka pipe-able aka let-table operator)152 * @param {function} getState returns the current state153 */154const setupAnimation = (getState = () => ({})) => animationEventsStream$ => {155 const layers = layersWithTimeDataSelector(getState());156 return Rx.Observable.from(157 layers.map(l => changeLayerProperties(l.id, {singleTile: true}))158 ).concat(animationEventsStream$)159 // restore original singleTile configuration160 .concat(Rx.Observable.from(161 layers.map(l => changeLayerProperties(l.id, { singleTile: l.singleTile }))162 ));163};164/**165 * Check if a time is in out of the defined range. If range start or end are not defined, returns false.166 * @param {string|Date} time the time to check167 * @param {Object} interval the interval where the time should stay `{start: ISODate|Date, end: ISODate|Date}168 */169const isOutOfRange = (time, { start, end } = {}) =>170 start && end && ( moment(time).isBefore(start) || moment(time).isAfter(end));171/**172 * When animation start, triggers the flow to retrieve the frames, buffering them:173 * The first setFrames will trigger the animation.174 * On any new animation frame, if the buffer is near to finish, this epic triggers175 * the retrieval of the next frames, until the animation ends.176 */177export const retrieveFramesForPlayback = (action$, { getState = () => { } } = {}) =>178 action$.ofType(PLAY).exhaustMap(() =>179 getAnimationFrames(getState, {180 fromValue:181 // if animation range is set, don't set from value on startup...182 (playbackRangeSelector(getState())183 && playbackRangeSelector(getState()).startPlaybackTime184 && playbackRangeSelector(getState()).endPlaybackTime)185 ? undefined186 // ...otherwise, start from the current time (start animation from cursor position)187 : currentTimeSelector(getState())188 })189 .map((frames) => setFrames(frames))190 .let(wrapStartStop(framesLoading(true), framesLoading(false)), () => Rx.Observable.of(191 error({192 title: "There was an error retrieving animation", // TODO: localize193 message: "Please contact the administrator" // TODO: localize194 }),195 stop()196 ))197 // show loading mask198 .let(wrapStartStop(timeDataLoading(false, true), timeDataLoading(false, false)))199 .concat(200 action$201 .ofType(SET_CURRENT_FRAME)202 .filter(({ frame }) => frame % BUFFER_SIZE === ((BUFFER_SIZE - PRELOAD_BEFORE)))203 .switchMap(() =>204 getAnimationFrames(getState, {205 fromValue: lastFrameSelector(getState())206 })207 .map(appendFrames)208 .let(wrapStartStop(framesLoading(true), framesLoading(false)))209 )210 )211 .takeUntil(action$.ofType(STOP, LOCATION_CHANGE))212 // this removes loading mask even if the STOP action is triggered before frame end (empty result)213 .concat(Rx.Observable.of(timeDataLoading(false, false)))214 .let(setupAnimation(getState))215 );216/**217 * When the new animation frame is triggered, changes the current time, if the next frame is available. Otherwise stops.218 * NOTE: we don't have a count of next animation steps, so we suppose that the selector has already pre-loaded next animation steps.219 */220export const updateCurrentTimeFromAnimation = (action$, { getState = () => { } } = {}) =>221 action$.ofType(SET_CURRENT_FRAME)222 .map(() => currentFrameValueSelector(getState()))223 .map(t => t ? moveTime(t) : stop());224/**225 * When a new frame sequence is set, the animation starts.226 */227export const timeDimensionPlayback = (action$, { getState = () => { } } = {}) =>228 action$.ofType(SET_FRAMES)229 .exhaustMap(() =>230 Rx.Observable.interval(frameDurationSelector(getState()) * 1000)231 .startWith(0) // start immediately232 .let(pausable(233 action$234 .ofType(PLAY, PAUSE)235 .map(a => a.type === PLAY)236 ))237 // pause is with loss, so the count of timer is not correct.238 // the following scan emit a for every event emitted effectively, with correct count239 // TODO: in case of loop, we can reset to 0 on load end.240 .map(() => setCurrentFrame(currentFrameSelector(getState()) + 1))241 .merge( action$.ofType(ANIMATION_STEP_MOVE)242 .map(({direction}) =>243 setCurrentFrame(244 Math.max(0, currentFrameSelector(getState()) + direction)))245 )246 .concat(Rx.Observable.of(stop()))247 .takeUntil(action$.ofType(STOP, LOCATION_CHANGE))248 );249/**250 * Synchronizes the fixed animation step toggle with guide layer on timeline251 */252export const playbackToggleGuideLayerToFixedStep = (action$, { getState = () => { } } = {}) =>253 action$254 .ofType(TOGGLE_ANIMATION_MODE)255 .exhaustMap(() =>256 selectedLayerName(getState())257 // need to deselect258 ? Rx.Observable.of(selectLayer(undefined))259 // need to select first260 : Rx.Observable.of(261 selectLayer(262 get(timelineLayersSelector(getState()), "[0].id")263 )264 )265 );266/**267 * Allow to move time 1 single step. TODO: evaluate to move this in timeline controls268 */269export const playbackMoveStep = (action$, { getState = () => { } } = {}) =>270 action$271 .ofType(ANIMATION_STEP_MOVE)272 .filter(() => statusSelector(getState()) !== STATUS.PLAY /* && statusSelector(getState()) !== STATUS.PAUSE*/) // if is playing, the animation manages this event273 .switchMap(({ direction = 1 }) => {274 const md = playbackMetadataSelector(getState()) || {};275 const currentTime = currentTimeSelector(getState());276 // check if the next/prev value is present in the state (by `playbackCacheNextPreviousTimes`)277 if (currentTime && md.forTime === currentTime) {278 return Rx.Observable.of(direction > 0 ? md.next : md.previous);279 }280 // if not downloaded yet, download it281 return getAnimationFrames(getState, { limit: 1, sort: direction > 0 ? "asc" : "desc", fromValue: currentTimeSelector(getState()) })282 .map(([t] = []) => t);283 }).filter(t => !!t)284 .map(t => moveTime(t));285/**286 * Pre-loads next and previous values for the current time, when change.287 * This is useful to enable/disable playback buttons in guide-layer mode. The state updated by this288 * epic is also used as a cache to load next/previous button (only when the animation is not active)289 */290export const playbackCacheNextPreviousTimes = (action$, { getState = () => { } } = {}) =>291 action$292 .ofType(SET_CURRENT_TIME, MOVE_TIME, SELECT_LAYER, STOP, SET_MAP_SYNC )293 .filter(() => statusSelector(getState()) !== STATUS.PLAY && statusSelector(getState()) !== STATUS.PAUSE)294 .filter(() => selectedLayerSelector(getState()))295 .filter( t => !!t )296 .switchMap(({time: actionTime}) => {297 // get current time in case of SELECT_LAYER298 const time = actionTime || currentTimeSelector(getState());299 return Rx.Observable.forkJoin(300 // TODO: find out a way to optimize and do only one request301 // TODO: support for local list of values (in case of missing multidim-extension)302 getDomainValues(...domainArgs(getState, { sort: "asc", limit: 1, fromValue: time }))303 .map(res => res.DomainValues.Domain.split(","))304 .map(([tt]) => tt).catch(err => err && Rx.Observable.of(null)),305 getDomainValues(...domainArgs(getState, { sort: "desc", limit: 1, fromValue: time }))306 .map(res => res.DomainValues.Domain.split(","))307 .map(([tt]) => tt).catch(err => err && Rx.Observable.of(null))308 ).map(([next, previous]) =>309 updateMetadata({310 forTime: time,311 next,312 previous313 })314 );315 });316/**317 * During animation, on every current time change event, if the current time is out of the current range window, the timeline will shift to318 * current start-end values319 */320export const playbackFollowCursor = (action$, { getState = () => { } } = {}) =>321 action$322 .ofType(MOVE_TIME)323 .filter(({type}) =>324 (type === MOVE_TIME || statusSelector(getState()) === STATUS.PLAY )325 && isOutOfRange(currentTimeSelector(getState()), rangeSelector(getState())))326 .filter(() => get(playbackSettingsSelector(getState()), "following") )327 .switchMap(() => Rx.Observable.of(328 onRangeChanged(329 (() => {330 const currentTime = currentTimeSelector(getState());331 const {start, end} = rangeSelector(getState());332 const difference = moment(end).diff(moment(start));333 const nextEnd = moment(currentTime).add(difference).toISOString();334 return {335 start: currentTime,336 end: nextEnd337 };338 })()339 )340 ));341export const playbackStopWhenDeleteLayer = (action$, { getState = () => {} } = {}) =>342 action$343 .ofType(REMOVE_NODE)344 .filter( () =>345 !selectedLayerSelector(getState())346 && statusSelector(getState()) === "PLAY"347 )348 .switchMap( () => Rx.Observable.of(stop()));349export default {350 retrieveFramesForPlayback,351 updateCurrentTimeFromAnimation,352 timeDimensionPlayback,353 playbackToggleGuideLayerToFixedStep,354 playbackMoveStep,355 playbackCacheNextPreviousTimes,356 playbackFollowCursor,357 playbackStopWhenDeleteLayer...
CourseActions.js
Source:CourseActions.js
1import api from 'api/MasterAPI';2export function getCourseDefs(query) {3 return (dispatch, getState) => {4 // æ«æçæ¥è©¢æ¢ä»¶.5 query = {organizationId:'0', rootCategoryId:'0'};6 return new api(getState().auth).getCourceDefs(query).then((courseDefs)=> dispatch(receiveCourseDefs(courseDefs)));7 }8}9export function receiveCourseDefs(courseDefs) {10 return {11 type: 'MASTER_RECEIVE_COURSEDEFS',12 courseDefs: courseDefs13 }14}15export function getCourseDef(courseDefId) {16 return (dispatch, getState) => {17 return new api(getState().auth).getCourseDef(courseDefId).then((courseDef)=> dispatch(receiveCourseDef(courseDef)));18 }19}20export function receiveCourseDef(courseDef) {21 return {22 type: 'RECEIVE_COURSE_DETAIL',23 courseDef: courseDef24 }25}26export function createCourseDef(courseDef){27 return (dispatch, getState) => {28 return new api(getState().auth).createCourseDef(courseDef).then((success)=> dispatch(getCourseDefs()));29 }30}31export function updateCourseDef(courseDef){32 return (dispatch, getState) => {33 return new api(getState().auth).updateCourseDef(courseDef).then((success)=> dispatch(getCourseDefs()));34 }35}36/** è¨å® courseï¼æå¼æ Course.jsx æå¨æå¼æé²å
¥ç·¨è¼¯æ¨¡å¼ï¼å¨æ²å¼(null)æï¼é²å
¥æ°å¢æ¨¡å¼ **/37export function setCourse(course){38 return {39 type: 'MASTER_SET_COURSE',40 course41 };42}43export function setExamQuestion(examQuestion) {44 return {45 type: 'MASTER_SET_EXAMQUESTION',46 examQuestion47 } ;48}49export function setActivity(activity) {50 return {51 type: 'MASTER_SET_ACTIVITY',52 activity53 } ;54}55export function createCourse(course){56 return (dispatch, getState) => {57 return new api(getState().auth).createCourse(course).then((success)=> dispatch(getCourses(course.courseDefId)));58 }59}60export function updateCourse(course){61 return (dispatch, getState) => {62 return new api(getState().auth).updateCourse(course).then((success)=> dispatch(getCourses(course.courseDefId)));63 }64}65export function getQuestions() {66 return (dispatch, getState) => {67 return new api(getState().auth).getQuestions().then((questions)=> dispatch(receiveQuestions(questions)));68 }69}70export function getExamQuestions() {71 return (dispatch, getState) => {72 return new api(getState().auth).getExamQuestions().then((examQuestions)=> dispatch(receiveExamQuestions(examQuestions)));73 }74}75export function receiveExamQuestions(examQuestions) {76 return {77 type: 'RECEIVE_EXAMQUESTIONS',78 examQuestions: examQuestions79 }80}81export function getTeachingMaterials() {82 return (dispatch, getState) => {83 return new api(getState().auth).getTeachingMaterials().then((teachingMaterials)=> dispatch(receiveTeachingMaterials(teachingMaterials)));84 }85}86export function receiveTeachingMaterials(teachingMaterials) {87 return {88 type: 'RECEIVE_TEACHING_MATERIALS',89 teachingMaterials: teachingMaterials90 }91}92export function getQuestion(questionId) {93 return (dispatch, getState) => {94 return new api(getState().auth).getQuestion(questionId).then((question)=> dispatch(receiveQuestion(question)));95 }96}97export function getExamQuestion(examQuestionId) {98 return (dispatch, getState) => {99 return new api(getState().auth).getExamQuestion(examQuestionId).then((examQuestion)=> dispatch(receiveExamQuestion(examQuestion)));100 }101}102export function receiveQuestion(question) {103 return {104 type: 'RECEIVE_QUESTION_DETAIL',105 question: question106 }107}108export function setQuestion(question) {109 return {110 type: 'RECEIVE_QUESTION_DETAIL',111 question112 } ;113}114export function receiveExamQuestion(examQuestion) {115 return {116 type: 'RECEIVE_EXAMQUESTION_DETAIL',117 examQuestion: examQuestion118 }119}120export function receiveQuestions(questions) {121 return {122 type: 'RECEIVE_QUESTIONS',123 questions: questions124 }125}126export function createQuestion(question){127 return (dispatch, getState) => {128 return new api(getState().auth).createQuestion(question).then((success)=> dispatch(getQuestions()));129 }130}131export function updateQuestion(question){132 return (dispatch, getState) => {133 return new api(getState().auth).updateQuestion(question).then((success)=> dispatch(getQuestions()));134 }135}136export function createExamQuestion(examQuestion){137 return (dispatch, getState) => {138 return new api(getState().auth).createExamQuestion(examQuestion).then((success)=> dispatch(getExamQuestions()));139 }140}141export function updateExamQuestion(examQuestion, examQuestionId){142 return (dispatch, getState) => {143 return new api(getState().auth).updateExamQuestion(examQuestion, examQuestionId).then((success)=> dispatch(getExamQuestions()));144 }145}146export function updateActivitiesOrder(activityOrder, courseId) {147 return(dispatch, getState) => {148 return new api(getState().auth).updateActivitiesOrder(activityOrder, courseId).then((success)=> dispatch(getCourseActivities(courseId)));149 }150}151export function getCourses(courseDefId) {152 return (dispatch, getState) => {153 // dispatch(cleanCourses());154 return new api(getState().auth).getCourses(courseDefId).then((courses)=> dispatch(receiveCourses(courses)));155 }156}157export function receiveCourses(courses) {158 return {159 type: 'RECEIVE_COURSES',160 courses: courses161 }162}163/* course candidates for 'CopyCoursePicker' */164export function getCopyCourses(courseDefId){165 return (dispatch, getState) => {166 // dispatch(cleanCopyCourses());167 return new api(getState().auth).getCourses(courseDefId).then((courses)=> dispatch(receiveCopyCourses(courses)));168 }169}170export function receiveCopyCourses(courses) {171 return {172 type: 'MASTER_RECEIVE_COPY_COURSES',173 courses174 }175}176export function cleanCopyCourses(){177 return {type: 'MASTER_CLEAN_COPY_COURSES'};178}179export function setCopyCourse(course){180 return {181 type: 'MASTER_SET_COPY_COURSE',182 course183 };184}185export function getCourse(courseId) {186 return (dispatch, getState) => {187 return new api(getState().auth).getCourse(courseId).then((course)=> dispatch(receiveCourse(course)));188 }189}190export function receiveCourse(course) {191 return {192 type: 'RECEIVE_COURSE',193 course: course194 }195}196export function getCourseOrderMembers(courseId,query) {197 return (dispatch, getState) => {198 return new api(getState().auth).getCourseOrderMembers(courseId,query).then((members)=> dispatch(receiveCourseOrderMembers(members)));199 }200}201export function receiveCourseOrderMembers(members) {202 return {203 type: 'RECEIVE_COURSE_ORDER_MEMBERS',204 members: members205 }206}207export function createCoursePaidUpload(courseId, members,query) {208 return (dispatch, getState) => {209 return new api(getState().auth).createCoursePaidUpload(courseId,members).then((success) => {210 dispatch(getCourseOrderMembers(courseId, query));211 dispatch(getCoursePaidUpload(courseId, members.members[0].id));212 }); 213 }214}215export function createCourseRefundUpload(courseId, members, query) {216 return (dispatch, getState) => {217 return new api(getState().auth).createCourseRefundUpload(courseId, members).then((success) => {218 dispatch(getCourseOrderMembers(courseId, query)) ;219 dispatch(getCourseRefundUpload(courseId,members.members[0].id)) ;220 });221 }222}223export function getCourseActivities(courseId) {224 return (dispatch, getState) => {225 return new api(getState().auth).getCourseActivities(courseId).then(activities=> dispatch(receiveCourseActivities(activities)));226 }227}228export function receiveCourseActivities(activities) {229 return {230 type: 'RECEIVE_COURSE_ACTIVITIES',231 activities: activities232 }233}234/**************** clean code ***************/235export function cleanCourses(){236 return {type: 'MASTER_CLEAN_COURSES'};237}238export function updateOrderPaymentStatus(orders,courseId, query) {239 return (dispatch, getState) => {240 return new api(getState().auth).updateOrderPaymentStatus(orders).then((success) => dispatch(getCourseOrderMembers(courseId,query)));241 }242}243export function createCourseActivity(courseId, activity) {244 return (dispatch, getState) => {245 return new api(getState().auth).createCourseActivity(courseId, activity).then((success) => dispatch(getCourseActivities(courseId)))246 }247}248export function updateCourseActivity(courseId, activityId, activity) {249 return (dispatch, getState) => {250 return new api(getState().auth).updateCourseActivity(courseId, activityId, activity).then((success) => dispatch(getCourseActivities(courseId)))251 }252}253export function getActivity(courseId, activityId) {254 return (dispatch, getState) => {255 return new api(getState().auth).getActivity(courseId, activityId).then((activity) => dispatch(receiveActivity(activity)))256 }257}258export function receiveActivity(activity) {259 return {260 type: 'RECEIVE_ACTIVITY',261 activity: activity262 }263}264export function getActivityStatistics(courseId) {265 return (dispatch, getState) => {266 return new api(getState().auth).getActivityStatistics(courseId).then((questionnaire) => dispatch(receiveQuestionnaire(questionnaire)))267 }268}269export function receiveQuestionnaire(questionnaire) {270 return {271 type: 'RECEIVE_ACTIVITY_STATISTICS',272 questionnaire: questionnaire273 }274}275export function getCoursePaidMembers(courseId, query) {276 return (dispatch, getState) => {277 return new api(getState().auth).getCoursePaidMembers(courseId, query).then(members=> dispatch(receiveCoursePaidMembers(members)));278 }279}280export function receiveCoursePaidMembers(members) {281 return {282 type: 'RECEIVE_COURSE_PAID_MEMBERS',283 members: members284 }285}286export function getCoursePaidUpload(courseId, memberId) {287 return (dispatch, getState) => {288 return new api(getState().auth).getCoursePaidUpload(courseId, memberId).then((memberCoursePaidUploadRecord)=> 289 dispatch(receiveCoursePaidUpload(memberCoursePaidUploadRecord)));290 }291}292export function receiveCoursePaidUpload(memberCoursePaidUploadRecord) {293 return {294 type: 'RECEIVE_MEMBER_COURSE_PAID_UPLOAD_RECORD',295 memberCoursePaidUploadRecord: memberCoursePaidUploadRecord296 }297}298export function getCourseRefundUpload(courseId, memberId) {299 return (dispatch, getState) => {300 return new api(getState().auth).getCourseRefundUpload(courseId, memberId).then((memberCourseRefundUploadRecord)=> 301 dispatch(receiveCourseRefundUpload(memberCourseRefundUploadRecord)));302 }303}304export function receiveCourseRefundUpload(memberCourseRefundUploadRecord) {305 return {306 type: 'RECEIVE_MEMBER_COURSE_REFUND_UPLOAD_RECORD',307 memberCourseRefundUploadRecord: memberCourseRefundUploadRecord308 }309}310export function setEmptyPaidUpload(memberCoursePaidUploadRecord){311 return {312 type: 'RECEIVE_MEMBER_COURSE_PAID_UPLOAD_RECORD',313 memberCoursePaidUploadRecord:memberCoursePaidUploadRecord314 }315}316export function setEmptyRefundUpload(memberCourseRefundUploadRecord){317 return {318 type: 'RECEIVE_MEMBER_COURSE_REFUND_UPLOAD_RECORD',319 memberCourseRefundUploadRecord:memberCourseRefundUploadRecord320 }321}322export function setEmptyTeachingMaterial(teachingMaterialView){323 return {324 type: 'RECEIVE_TEACHING_MATERIAL_VIEW',325 teachingMaterialView:teachingMaterialView326 }327}328export function setEmptyAttendDate(attendDateView){329 return {330 type: 'RECEIVE_ATTEND_DATE_VIEW',331 attendDateView:attendDateView332 }333}334export function setEmptyChapterScores(chapterScoresView){335 return {336 type: 'RECEIVE_CHAPTER_SCORES_VIEW',337 chapterScoresView:chapterScoresView338 }339}340export function setEmptyNotices(noticeView) {341 return {342 type: 'RECEIVE_NOTICE_VIEW',343 noticeView:noticeView344 }345}346export function getStudentTeachingMaterialView(courseId, memberId) {347 return (dispatch, getState) => {348 return new api(getState().auth).getStudentTeachingMaterialView(courseId, memberId).then((teachingMaterialView) => 349 dispatch(receiveStudentTeachingMaterialView(teachingMaterialView)))350 }351}352export function receiveStudentTeachingMaterialView(teachingMaterialView) {353 return {354 type: 'RECEIVE_TEACHING_MATERIAL_VIEW',355 teachingMaterialView: teachingMaterialView356 }357}358export function getStudentAttendDateView(courseId, memberId) {359 return (dispatch, getState) => {360 return new api(getState().auth).getStudentAttendDateView(courseId, memberId).then((attendDateView) => 361 dispatch(receiveStudentAttendDateView(attendDateView)))362 }363}364export function receiveStudentAttendDateView(attendDateView) {365 return {366 type: 'RECEIVE_ATTEND_DATE_VIEW',367 attendDateView: attendDateView368 }369}370export function getStudentChapterScoresView(courseId, memberId) {371 return (dispatch, getState) => {372 return new api(getState().auth).getStudentChapterScoresView(courseId, memberId).then((chapterScoresView) => 373 dispatch(receiveStudentChapterScoresView(chapterScoresView)))374 }375}376export function receiveStudentChapterScoresView(chapterScoresView) {377 return {378 type: 'RECEIVE_CHAPTER_SCORES_VIEW',379 chapterScoresView: chapterScoresView380 }381}382export function getStudentNoticeView(courseId, memberId) {383 return (dispatch, getState) => {384 return new api(getState().auth).getStudentNoticeView(courseId, memberId).then((noticeView) => 385 dispatch(receiveStudentNoticeView(noticeView)))386 }387}388export function receiveStudentNoticeView(noticeView) {389 return {390 type: 'RECEIVE_NOTICE_VIEW',391 noticeView: noticeView392 }393}394export function getCourseStudentScores(courseId, members, query) {395 return (dispatch, getState) => {396 return new api(getState().auth).getCourseStudentScores(courseId, members).then((success) => 397 dispatch(getCoursePaidMembers(courseId, query)))398 }399} 400export function postAttendStudents(courseId, attendStudents, query) {401 return (dispatch, getState) => {402 return new api(getState().auth).postAttendStudents(courseId, attendStudents).then((success) => 403 dispatch(getCoursePaidMembers(courseId, query)))404 }405}406export function postMemberScores(members, courseId, chapterId, query) {407 return (dispatch, getState) => {408 return new api(getState().auth).postMemberScores(members, courseId, chapterId).then((success) => 409 dispatch(getCoursePaidMembers(courseId, query)))410 }411}412export function postWebNotices(courseId, model, query) {413 return (dispatch, getState) => {414 return new api(getState().auth).postWebNotices(model).then((success) => 415 dispatch(getCoursePaidMembers(courseId, query)))416 }417}418export function getTeachingMaterial(teachingMaterialId) {419 return (dispatch, getState) => {420 return new api(getState().auth).getTeachingMaterial(teachingMaterialId).then((teachingMaterial) => dispatch(receiveTeachingMaterial(teachingMaterial)));421 }422}423export function receiveTeachingMaterial(teachingMaterial) {424 return {425 type: 'RECEIVE_TEACHING_MATERIAL',426 teachingMaterial: teachingMaterial427 }428}429export function updateTeachingMaterial(teachingMaterialId,teachingMaterial) {430 return (dispatch, getState) => {431 return new api(getState().auth).updateTeachingMaterial(teachingMaterialId,teachingMaterial).then((success) =>432 dispatch(getTeachingMaterial(teachingMaterialId)));433 }...
chain.js
Source:chain.js
1describe('tr.Chain', function() {2 var stubTaskA, stubTaskB, stubTaskC, stubTaskD, stubTaskE, stubTaskF;3 beforeEach(function() {4 stubTaskA = new tr.Stub(false, "StubA");5 stubTaskB = new tr.Stub(false, "StubB");6 stubTaskC = new tr.Stub(false, "StubC");7 stubTaskD = new tr.Stub(false, "StubD");8 stubTaskE = new tr.Stub(false, "StubE");9 stubTaskF = new tr.Stub(false, "StubF");10 });11 it('should automatically complete when run with no children', function() {12 var chain = new tr.Chain();13 chain.run();14 expect(chain.getState()).toBe(tr.enums.State.COMPLETED);15 });16 it('should invoke the optional completed callback on success', function() {17 var callback = jasmine.createSpy();18 19 var chain = new tr.Chain(callback).run();20 expect(chain.getState()).toBe(tr.enums.State.COMPLETED);21 expect(callback).toHaveBeenCalled();22 });23 it('should invoke the optional errorred callback on failure', function() {24 var callback = jasmine.createSpy();25 26 var chain = new tr.Chain(null, callback).first(stubTaskA).run();27 stubTaskA.error();28 expect(chain.getState()).toBe(tr.enums.State.ERRORED);29 expect(callback).toHaveBeenCalled();30 });31 it('should start with the task passed to first()', function() {32 var chain = new tr.Chain().first(stubTaskA).run();33 expect(chain.getState()).toBe(tr.enums.State.RUNNING);34 expect(stubTaskA.getState()).toBe(tr.enums.State.RUNNING);35 stubTaskA.complete();36 expect(chain.getState()).toBe(tr.enums.State.COMPLETED);37 expect(stubTaskA.getState()).toBe(tr.enums.State.COMPLETED);38 });39 it('should start with the task passed to then() if none is passed to first()', function() {40 var chain = new tr.Chain().then(stubTaskA).run();41 expect(chain.getState()).toBe(tr.enums.State.RUNNING);42 expect(stubTaskA.getState()).toBe(tr.enums.State.RUNNING);43 stubTaskA.complete();44 expect(chain.getState()).toBe(tr.enums.State.COMPLETED);45 expect(stubTaskA.getState()).toBe(tr.enums.State.COMPLETED);46 });47 it('should fail if first() is called after stubTasks have been added to the chain', function() {48 expect(function() {49 new tr.Chain().first(stubTaskA).first(stubTaskB).run();50 }).toThrow();51 });52 it('should continue from a completed task to the next task passed to then()', function() {53 var chain = new tr.Chain().first(stubTaskA).then(stubTaskB).run();54 expect(chain.getState()).toBe(tr.enums.State.RUNNING);55 expect(stubTaskA.getState()).toBe(tr.enums.State.RUNNING);56 expect(stubTaskB.getState()).toBe(tr.enums.State.INITIALIZED);57 stubTaskA.complete();58 expect(chain.getState()).toBe(tr.enums.State.RUNNING);59 expect(stubTaskA.getState()).toBe(tr.enums.State.COMPLETED);60 expect(stubTaskB.getState()).toBe(tr.enums.State.RUNNING);61 stubTaskB.complete();62 expect(chain.getState()).toBe(tr.enums.State.COMPLETED);63 expect(stubTaskA.getState()).toBe(tr.enums.State.COMPLETED);64 expect(stubTaskB.getState()).toBe(tr.enums.State.COMPLETED);65 });66 it('should execute multiple stubTasks in parallel if they are passed to then then()', function() {67 var chain = new tr.Chain().first(stubTaskA).then(stubTaskB, stubTaskC).run();68 expect(chain.getState()).toBe(tr.enums.State.RUNNING);69 expect(stubTaskA.getState()).toBe(tr.enums.State.RUNNING);70 expect(stubTaskB.getState()).toBe(tr.enums.State.INITIALIZED);71 expect(stubTaskC.getState()).toBe(tr.enums.State.INITIALIZED);72 stubTaskA.complete();73 expect(chain.getState()).toBe(tr.enums.State.RUNNING);74 expect(stubTaskA.getState()).toBe(tr.enums.State.COMPLETED);75 expect(stubTaskB.getState()).toBe(tr.enums.State.RUNNING);76 expect(stubTaskC.getState()).toBe(tr.enums.State.RUNNING);77 stubTaskB.complete();78 expect(chain.getState()).toBe(tr.enums.State.RUNNING);79 expect(stubTaskA.getState()).toBe(tr.enums.State.COMPLETED);80 expect(stubTaskB.getState()).toBe(tr.enums.State.COMPLETED);81 expect(stubTaskC.getState()).toBe(tr.enums.State.RUNNING);82 stubTaskC.complete();83 expect(chain.getState()).toBe(tr.enums.State.COMPLETED);84 expect(stubTaskA.getState()).toBe(tr.enums.State.COMPLETED);85 expect(stubTaskB.getState()).toBe(tr.enums.State.COMPLETED);86 expect(stubTaskC.getState()).toBe(tr.enums.State.COMPLETED);87 });88 it('should execute all of the stubTask(s) passed to or() if the proceeding task fails', function() {89 var chain = new tr.Chain().first(stubTaskA).or(stubTaskB, stubTaskC).run();90 expect(chain.getState()).toBe(tr.enums.State.RUNNING);91 expect(stubTaskA.getState()).toBe(tr.enums.State.RUNNING);92 expect(stubTaskB.getState()).toBe(tr.enums.State.INITIALIZED);93 expect(stubTaskC.getState()).toBe(tr.enums.State.INITIALIZED);94 stubTaskA.error();95 expect(chain.getState()).toBe(tr.enums.State.RUNNING);96 expect(stubTaskA.getState()).toBe(tr.enums.State.ERRORED);97 expect(stubTaskB.getState()).toBe(tr.enums.State.RUNNING);98 expect(stubTaskC.getState()).toBe(tr.enums.State.RUNNING);99 });100 it('should continue if all tasks passed to or() complete', function() {101 var chain = new tr.Chain().first(stubTaskA).or(stubTaskB, stubTaskC).run();102 expect(chain.getState()).toBe(tr.enums.State.RUNNING);103 expect(stubTaskA.getState()).toBe(tr.enums.State.RUNNING);104 expect(stubTaskB.getState()).toBe(tr.enums.State.INITIALIZED);105 expect(stubTaskC.getState()).toBe(tr.enums.State.INITIALIZED);106 stubTaskA.error();107 expect(chain.getState()).toBe(tr.enums.State.RUNNING);108 expect(stubTaskA.getState()).toBe(tr.enums.State.ERRORED);109 expect(stubTaskB.getState()).toBe(tr.enums.State.RUNNING);110 expect(stubTaskC.getState()).toBe(tr.enums.State.RUNNING);111 stubTaskB.complete();112 stubTaskC.complete();113 expect(chain.getState()).toBe(tr.enums.State.COMPLETED);114 expect(stubTaskA.getState()).toBe(tr.enums.State.ERRORED);115 expect(stubTaskB.getState()).toBe(tr.enums.State.COMPLETED);116 expect(stubTaskC.getState()).toBe(tr.enums.State.COMPLETED);117 });118 it('should fail if some of the tasks passed to a single or() error', function() {119 var chain = new tr.Chain().first(stubTaskA).or(stubTaskB, stubTaskC).run();120 expect(chain.getState()).toBe(tr.enums.State.RUNNING);121 expect(stubTaskA.getState()).toBe(tr.enums.State.RUNNING);122 expect(stubTaskB.getState()).toBe(tr.enums.State.INITIALIZED);123 expect(stubTaskC.getState()).toBe(tr.enums.State.INITIALIZED);124 stubTaskA.error();125 expect(chain.getState()).toBe(tr.enums.State.RUNNING);126 expect(stubTaskA.getState()).toBe(tr.enums.State.ERRORED);127 expect(stubTaskB.getState()).toBe(tr.enums.State.RUNNING);128 expect(stubTaskC.getState()).toBe(tr.enums.State.RUNNING);129 stubTaskB.error();130 stubTaskC.complete();131 expect(chain.getState()).toBe(tr.enums.State.ERRORED);132 expect(stubTaskA.getState()).toBe(tr.enums.State.ERRORED);133 expect(stubTaskB.getState()).toBe(tr.enums.State.ERRORED);134 expect(stubTaskC.getState()).toBe(tr.enums.State.COMPLETED);135 });136 it('should not execute the task passed to or() if the proceeding task suceeds', function() {137 var chain = new tr.Chain().first(stubTaskA).or(stubTaskB).then(stubTaskC).run();138 expect(chain.getState()).toBe(tr.enums.State.RUNNING);139 expect(stubTaskA.getState()).toBe(tr.enums.State.RUNNING);140 expect(stubTaskB.getState()).toBe(tr.enums.State.INITIALIZED);141 expect(stubTaskC.getState()).toBe(tr.enums.State.INITIALIZED);142 stubTaskA.complete();143 expect(chain.getState()).toBe(tr.enums.State.RUNNING);144 expect(stubTaskA.getState()).toBe(tr.enums.State.COMPLETED);145 expect(stubTaskB.getState()).toBe(tr.enums.State.INITIALIZED);146 expect(stubTaskC.getState()).toBe(tr.enums.State.RUNNING);147 stubTaskC.complete();148 expect(chain.getState()).toBe(tr.enums.State.COMPLETED);149 expect(stubTaskA.getState()).toBe(tr.enums.State.COMPLETED);150 expect(stubTaskB.getState()).toBe(tr.enums.State.INITIALIZED);151 expect(stubTaskC.getState()).toBe(tr.enums.State.COMPLETED);152 });153 it('should error if no or() task follows a failed stubTask', function() {154 var chain = new tr.Chain().first(stubTaskA).then(stubTaskB).run();155 expect(chain.getState()).toBe(tr.enums.State.RUNNING);156 expect(stubTaskA.getState()).toBe(tr.enums.State.RUNNING);157 expect(stubTaskB.getState()).toBe(tr.enums.State.INITIALIZED);158 stubTaskA.error();159 expect(chain.getState()).toBe(tr.enums.State.ERRORED);160 expect(stubTaskA.getState()).toBe(tr.enums.State.ERRORED);161 expect(stubTaskB.getState()).toBe(tr.enums.State.INITIALIZED);162 });163 it('should error if none of the tasks provided to or() complete', function() {164 var chain = new tr.Chain().first(stubTaskA).or(stubTaskB, stubTaskC).run();165 expect(chain.getState()).toBe(tr.enums.State.RUNNING);166 expect(stubTaskA.getState()).toBe(tr.enums.State.RUNNING);167 expect(stubTaskB.getState()).toBe(tr.enums.State.INITIALIZED);168 expect(stubTaskC.getState()).toBe(tr.enums.State.INITIALIZED);169 stubTaskA.error();170 expect(chain.getState()).toBe(tr.enums.State.RUNNING);171 expect(stubTaskA.getState()).toBe(tr.enums.State.ERRORED);172 expect(stubTaskB.getState()).toBe(tr.enums.State.RUNNING);173 expect(stubTaskC.getState()).toBe(tr.enums.State.RUNNING);174 stubTaskB.error();175 expect(chain.getState()).toBe(tr.enums.State.RUNNING);176 expect(stubTaskA.getState()).toBe(tr.enums.State.ERRORED);177 expect(stubTaskB.getState()).toBe(tr.enums.State.ERRORED);178 expect(stubTaskC.getState()).toBe(tr.enums.State.RUNNING);179 stubTaskC.error();180 expect(chain.getState()).toBe(tr.enums.State.ERRORED);181 expect(stubTaskA.getState()).toBe(tr.enums.State.ERRORED);182 expect(stubTaskB.getState()).toBe(tr.enums.State.ERRORED);183 expect(stubTaskC.getState()).toBe(tr.enums.State.ERRORED);184 });185 it('should allow or() calls to be chained', function() {186 var chain = new tr.Chain().first(stubTaskA).or(stubTaskB).or(stubTaskC).run();187 expect(chain.getState()).toBe(tr.enums.State.RUNNING);188 expect(stubTaskA.getState()).toBe(tr.enums.State.RUNNING);189 expect(stubTaskB.getState()).toBe(tr.enums.State.INITIALIZED);190 expect(stubTaskC.getState()).toBe(tr.enums.State.INITIALIZED);191 stubTaskA.error();192 expect(chain.getState()).toBe(tr.enums.State.RUNNING);193 expect(stubTaskA.getState()).toBe(tr.enums.State.ERRORED);194 expect(stubTaskB.getState()).toBe(tr.enums.State.RUNNING);195 expect(stubTaskC.getState()).toBe(tr.enums.State.INITIALIZED);196 stubTaskB.error();197 expect(chain.getState()).toBe(tr.enums.State.RUNNING);198 expect(stubTaskA.getState()).toBe(tr.enums.State.ERRORED);199 expect(stubTaskB.getState()).toBe(tr.enums.State.ERRORED);200 expect(stubTaskC.getState()).toBe(tr.enums.State.RUNNING);201 stubTaskC.complete();202 expect(chain.getState()).toBe(tr.enums.State.COMPLETED);203 expect(stubTaskA.getState()).toBe(tr.enums.State.ERRORED);204 expect(stubTaskB.getState()).toBe(tr.enums.State.ERRORED);205 expect(stubTaskC.getState()).toBe(tr.enums.State.COMPLETED);206 });207 it('should interrupt children when interrupted', function() {208 var chain = new tr.Chain().first(stubTaskA).then(stubTaskB).run();209 expect(chain.getState()).toBe(tr.enums.State.RUNNING);210 expect(stubTaskA.getState()).toBe(tr.enums.State.RUNNING);211 expect(stubTaskB.getState()).toBe(tr.enums.State.INITIALIZED);212 stubTaskA.complete();213 expect(chain.getState()).toBe(tr.enums.State.RUNNING);214 expect(stubTaskA.getState()).toBe(tr.enums.State.COMPLETED);215 expect(stubTaskB.getState()).toBe(tr.enums.State.RUNNING);216 chain.interrupt();217 expect(chain.getState()).toBe(tr.enums.State.INTERRUPTED);218 expect(stubTaskA.getState()).toBe(tr.enums.State.COMPLETED);219 expect(stubTaskB.getState()).toBe(tr.enums.State.INTERRUPTED);220 });221 it('should reset children when reset', function() {222 var chain = new tr.Chain().first(stubTaskA).then(stubTaskB).run();223 expect(chain.getState()).toBe(tr.enums.State.RUNNING);224 expect(stubTaskA.getState()).toBe(tr.enums.State.RUNNING);225 expect(stubTaskB.getState()).toBe(tr.enums.State.INITIALIZED);226 stubTaskA.error();227 expect(chain.getState()).toBe(tr.enums.State.ERRORED);228 expect(stubTaskA.getState()).toBe(tr.enums.State.ERRORED);229 expect(stubTaskB.getState()).toBe(tr.enums.State.INITIALIZED);230 chain.reset();231 expect(chain.getState()).toBe(tr.enums.State.INITIALIZED);232 expect(stubTaskA.getState()).toBe(tr.enums.State.INITIALIZED);233 expect(stubTaskB.getState()).toBe(tr.enums.State.INITIALIZED);234 });235 it('should return the correct number of children', function() {236 var chain = new tr.Chain().first(stubTaskA).then(stubTaskB, stubTaskC).then(stubTaskD).or(stubTaskE).then(stubTaskF).run();237 expect(chain.getOperationsCount()).toBe(6);238 stubTaskA.complete();239 expect(chain.getCompletedOperationsCount()).toBe(1);240 stubTaskB.complete();241 expect(chain.getCompletedOperationsCount()).toBe(2);242 stubTaskC.complete();243 expect(chain.getCompletedOperationsCount()).toBe(3);244 stubTaskD.complete();245 expect(chain.getCompletedOperationsCount()).toBe(5);246 stubTaskF.complete();247 expect(chain.getCompletedOperationsCount()).toBe(6);248 });249 it('should preserve the parallal behavior of then() when followed by or()', function() {250 var chain = new tr.Chain().first(stubTaskA, stubTaskB).or(stubTaskC).run();251 expect(chain.getState()).toBe(tr.enums.State.RUNNING);252 expect(stubTaskA.getState()).toBe(tr.enums.State.RUNNING);253 expect(stubTaskB.getState()).toBe(tr.enums.State.RUNNING);254 expect(stubTaskC.getState()).toBe(tr.enums.State.INITIALIZED);255 });256 it('should alias or() with else() and otherwise()', function() {257 var chain = new tr.Chain().first(stubTaskA).else(stubTaskB).otherwise(stubTaskC).run();258 expect(chain.getState()).toBe(tr.enums.State.RUNNING);259 expect(stubTaskA.getState()).toBe(tr.enums.State.RUNNING);260 expect(stubTaskB.getState()).toBe(tr.enums.State.INITIALIZED);261 expect(stubTaskC.getState()).toBe(tr.enums.State.INITIALIZED);262 stubTaskA.error();263 expect(chain.getState()).toBe(tr.enums.State.RUNNING);264 expect(stubTaskA.getState()).toBe(tr.enums.State.ERRORED);265 expect(stubTaskB.getState()).toBe(tr.enums.State.RUNNING);266 expect(stubTaskC.getState()).toBe(tr.enums.State.INITIALIZED);267 stubTaskB.error();268 expect(chain.getState()).toBe(tr.enums.State.RUNNING);269 expect(stubTaskA.getState()).toBe(tr.enums.State.ERRORED);270 expect(stubTaskB.getState()).toBe(tr.enums.State.ERRORED);271 expect(stubTaskC.getState()).toBe(tr.enums.State.RUNNING);272 });...
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!