aboutsummaryrefslogtreecommitdiffstats
path: root/server
Commit message (Collapse)AuthorAgeFilesLines
...
* Call error handler even if critical notification write fails (#16951)Artur Signell2015-02-281-12/+11
| | | | Change-Id: I4d18aa54c48487081a626749916e3342888eb71e
* Add pluggable mechanism for loading classes for a design (#16583)Leif Åstrand2015-02-263-40/+241
| | | | Change-Id: I2ac17e3c5a7c36492567238af8f4cf6723b0ec69
* Cleanup UI even if detach fails (#16651)Artur Signell2015-02-231-1/+6
| | | | Change-Id: Iefc27b7047836243268970605ba2e946fac55e95
* Fix RpcDataProviderExtension value change listener setup (#16550)Teemu Suo-Anttila2015-02-201-31/+55
| | | | | | | This patch changes value change listener mapping from itemid based to index based mapping. This makes removing rows much less error prone Change-Id: I77e9078de4ae61ce5d752cc394aa47bccd505e70
* Ensure resource is valid before writing to it (#16862)Artur Signell2015-02-201-0/+19
| | | | Change-Id: I61e0003a2301100a5f0bfc18581a279207c4e812
* Enable navigation on a readonly Calendar. (#16523)Sauli Tähkäpää2015-02-191-6/+0
| | | | | | | | | - Month view: navigate to week and day views - Week view: navigate to day view and to next and prev weeks - Day view: navigate to next and prev days - Month view: hidden events can be expanded to view. Change-Id: I19c64ae64c55b8e07be7f73be64e18e700f849b5
* Declarative support for Image, Flash, BrowserFrame (#15551,#16327,#15552,#16325)Artur Signell2015-02-197-0/+422
| | | | Change-Id: Icef0b3c4e652421265714c4fd29dee150bcc8cd0
* Fix NullPointerException when changing Grid container (#16559)Johannes Dahlström2015-02-194-12/+112
| | | | Change-Id: I6e8ca4af7baf0b560e9f28dfd6b7dd437c1a4254
* Refactor critical notifications handling. (#16592)Sauli Tähkäpää2015-02-192-34/+91
| | | | Change-Id: I235804a80b1d70a564a54953b9255416a7386fe6
* Properly handle null in critical notifications (#16592)Artur Signell2015-02-192-2/+26
| | | | Change-Id: I85994e47f99e2ac5431e67c56f432380e84af23d
* Remove grid.[set|get]EditorField(Object, Field) (#16538)Leif Åstrand2015-02-103-67/+54
| | | | Change-Id: Ia5c09b80e32f9842fb4680f035b53cea755cb451
* Fix @since for 7.4Artur Signell2015-02-101-1/+1
| | | | Change-Id: I71f3a7cd6b91174c306e5cd60e20dbf0150f4a53
* Rename getCancelCaption to mention Editor (#16551)Leif Åstrand2015-02-101-1/+1
| | | | Change-Id: If0e323fcdbac519cf204d8183d2d5f9f4465a907
* Rename com.vaadin.ui.renderer to com.vaadin.ui.renderers (#16521)Leif Åstrand2015-02-0614-15/+15
| | | | Change-Id: I6fd0313aaba5619a55f03fb52d72c032ea18f409
* Add API for controlling deselection for single select model (#16567)Leif Åstrand2015-02-061-0/+30
| | | | Change-Id: Ieb245205b3a311a4563f39bc48baadc44e218b61
* Show editor save error (#16602)Leif Åstrand2015-02-061-9/+30
| | | | Change-Id: I2727a9fabef4291798e97495c2df86b077387cbb
* Highlights erroneous cells in Grid editor (#16575)Henrik Paul2015-02-061-15/+61
| | | | Change-Id: Ie1f9d738db7a03ddb01b968782ad5e4877af1d7e
* Grid columns can now be marked as non-editable (#16538)Johannes Dahlström2015-02-062-17/+130
| | | | | | | | | | | | Non-editable columns are not assigned editor fields. When the editor is active, any non-editable content is not displayed (this should changein the future). This is separate from setting the property or editor field read-only - in those cases the field is still used to display the data which may not be desired and will fail if there is no converter. Also add Column.setEditorField(Field<?>) and the corresponding getter. Change-Id: Ice17c357895cb63a8e1bfd6abaffc1d803399e98
* Declarative support for ProgressBar (#16316)Artur Signell2015-02-064-82/+99
| | | | Change-Id: I8c13b19218e0da936abdb0860d492a3d5a096aa7
* Declarative support for Link (#16322)Artur Signell2015-02-052-0/+102
| | | | Change-Id: I02f36b5e89bdf2673696de6dd8fd217835e759d1
* New declarative testsArtur Signell2015-02-058-4/+402
| | | | | | | | | | | * ListSelect (#15547) * ComboBox (#15546) * NativeSelect (#15548) * Upload (#16323) * Tree (#16317) * TwinColSelect (#16317) Change-Id: Ic3443ec94971dc5bf9f63c8c11e5023863f9588c
* Refactored and updated (Popup|Inline|)DateField declarative testsArtur Signell2015-02-054-99/+214
| | | | Change-Id: I1dc27ed0a61aea0e9c263a88885e8d20c815bc92
* Declarative support for RichTextArea (#16326)Artur Signell2015-02-052-0/+73
| | | | Change-Id: I1e373124f371947eabbf330145fe507caf24fd62
* Declarative support for AbstractSelect (#15545)Artur Signell2015-02-057-4/+409
| | | | Change-Id: Ie66ee3f2b02ce7b6aa2edb66176bfbf5bdcd6c33
* Render Object.toString() when no converter is set (#15417)Artur Signell2015-02-052-15/+17
| | | | Change-Id: I8a00857d5829cd01ceb98c4264029f62e45e7073
* Simplified declarative convertersArtur Signell2015-02-055-54/+234
| | | | | | | | * Removed shortcut interface * Moved TimeZone converter to a separate class * Moved Enum converter to a separate class Change-Id: I2b959e3a002e6319912212df4a62a3bd05677f80
* Prevent AlwaysLockedVaadinSession from being GCed during testArtur Signell2015-02-051-13/+3
| | | | Change-Id: Id6e2e6c7e013e8c667f658d5877c5db7d072106b
* Add missing @since to VScrollTable and Table.Sauli Tähkäpää2015-02-051-1/+7
| | | | Change-Id: I7f249c880464b38226856a00882a05af80991d48
* Prevent MockVaadinSession from becomming GCedLeif Åstrand2015-02-051-0/+21
| | | | | | | This fixes the issue discussed in #14595 for the framework's internal tests (if they use MockVaadinSession). Change-Id: I1956680ac065428be41b2ad43fbb80503351b366
* Makes it possible to change save/cancel captions in Grid editor (#16551)Henrik Paul2015-02-051-0/+50
| | | | Change-Id: I4e303613f66a13b3ad6a9b2284537e5548391a4a
* Use cache when reading declarative format (#16572)Artur Signell2015-02-051-2/+2
| | | | Change-Id: I313ff4e88e13a9c160a4717a40cb13352a30bd6b
* Make server unit tests pass in Eclipse (#16581)Artur Signell2015-02-053-2/+27
| | | | Change-Id: Ieb9d00fe8412ed6fb0921d07e0511eb922268375
* Use non-blocking Map implementation for caches (#16582)Leif Åstrand2015-02-054-19/+11
| | | | Change-Id: Id2d3bc317f6763480b2ef5ce71244f048c5cfc26
* Base classes for declarative testsArtur Signell2015-02-059-0/+724
| | | | Change-Id: Ia3a421b84eac0252a6e1b8238756eeaac2a35b6e
* Defer RPC calls in RpcDataProvider to avoid cache issues (#16505)Teemu Suo-Anttila2015-02-051-30/+82
| | | | | | | | This patch defers cache refresh and row adding/removing. These calls are omitted completely when making initial response to the client or updating the size with bare ItemSetChangeEvents. Change-Id: I6b350680b3e2381caf6a66c9a4ad283207d024dc
* Add methods for getting invalid fields from a FieldGroup (#13775)Artur Signell2015-02-043-20/+319
| | | | | | | | | | | | * Method for retrieving all failing fields exceptions from a CommitException * Methods for handling commit errors in Grid (#16515) * Show editor row validation errors only on the fields (#16509) Change-Id: Iabef662579e4ccae3803a513205e46542c41cce2 Conflicts: server/src/com/vaadin/ui/Grid.java
* Use a custom field factory for editor row (#16513)Artur Signell2015-02-042-5/+78
| | | | Change-Id: I0102d93c7f661993a5a07d2bcdf511f433419300
* Declarative for DateFields (and related) with ISO8601 (#16313)Miki2015-02-0316-366/+1445
| | | | | | | | | | DesignAttributeHandler supports method names that contains some words in uppercase DesignAttributeHandler and other components now use extensible Formatter with Converters rather than static methods Change-Id: I9f68414bd4821f47ff37a26375091d154cae9a93
* Getter for editor field factory (#16512)Artur Signell2015-02-021-0/+12
| | | | Change-Id: Ib4e8cf909dcc67c1239e7aaf1fcee7430ce09026
* Revert "Make table selectable based on presence of ValueChangeListener ↵7.4.0.beta3Artur Signell2015-01-302-88/+6
| | | | | | (#13864)." This reverts commit 7305474e4a666d8b986d1d95e7a89fed64277935.
* Revert "StringToCollectionConverter class implementation (#15464)."Artur Signell2015-01-302-383/+0
| | | | This reverts commit 69cd990c9b83851a959a7d3f5b88138283f3e500.
* Revert "Grid now uses ObjectRenderer by default (#15417)"Artur Signell2015-01-293-103/+26
| | | | This reverts commit abaec0217b3351d6f1835d7095ed2a3958fbfcdb.
* Do not loop infinitely when encountering an invalid tag name (#16522)Artur Signell2015-01-292-19/+114
| | | | | | Also do not write to sysout Change-Id: Idae318a851323cd27b3363d12e8080101e996d9c
* Merge "Merge branch 'origin/grid'"Artur Signell2015-01-2948-84/+11262
|\
| * Merge remote-tracking branch 'origin/master' into gridArtur Signell2015-01-284-7/+135
| |\ | | | | | | | | | | | | | | | | | | Conflicts: client/src/com/vaadin/client/ui/VWindow.java Change-Id: I1a35db88a2b11acf76b58c417575451edfdb275d
| * | Better human readable captions for nested properties (#16433)Artur Signell2015-01-271-1/+1
| | | | | | | | | | | | Change-Id: I680ab6b2b4ac2c6101b97581feb52cf68adcead1
| * | Grid now uses ObjectRenderer by default (#15417)Henrik Paul2015-01-273-26/+103
| | | | | | | | | | | | Change-Id: I2aa8105c0eadbadb29f9aab9e3e3aeb21629f6f3
| * | Use elemental.json and not org.json in OSGi (#16490)Artur Signell2015-01-271-1/+1
| | | | | | | | | | | | Change-Id: Ib11880b020f0f60c9e0808409d243e6c4d6c05aa
| * | Fix RpcDataProvider cache clearing on bare ItemSetChange (#16481)Teemu Suo-Anttila2015-01-271-68/+83
| | | | | | | | | | | | | | | | | | | | | This patch optimizes value change listeners and updates a bit in order to make clean up on cache invalidation easier to perform. Change-Id: I6ae3e0ef5046bd5f404f5e0a440607cabd48c6a4
| * | Merge remote-tracking branch 'origin/master' into HEADArtur Signell2015-01-263-15/+94
| |\ \ | | | | | | | | | | | | Change-Id: I42718fcc8a07ca46f7e58016d3caf287ce88e3ed
) { assert.ok( this === defer, "Defer passed as this & first argument" ); this.resolve( "done" ); } ).done( function( value ) { assert.strictEqual( value, "done", "Passed function executed" ); } ); createDeferred( function( defer ) { var promise = defer.promise(), func = function() {}, funcPromise = defer.promise( func ); assert.strictEqual( defer.promise(), promise, "promise is always the same" ); assert.strictEqual( funcPromise, func, "non objects get extended" ); jQuery.each( promise, function( key ) { if ( !jQuery.isFunction( promise[ key ] ) ) { assert.ok( false, key + " is a function (" + jQuery.type( promise[ key ] ) + ")" ); } if ( promise[ key ] !== func[ key ] ) { assert.strictEqual( func[ key ], promise[ key ], key + " is the same" ); } } ); } ); jQuery.expandedEach = jQuery.each; jQuery.expandedEach( "resolve reject".split( " " ), function( _, change ) { createDeferred( function( defer ) { assert.strictEqual( defer.state(), "pending", "pending after creation" ); var checked = 0; defer.progress( function( value ) { assert.strictEqual( value, checked, "Progress: right value (" + value + ") received" ); } ); for ( checked = 0; checked < 3; checked++ ) { defer.notify( checked ); } assert.strictEqual( defer.state(), "pending", "pending after notification" ); defer[ change ](); assert.notStrictEqual( defer.state(), "pending", "not pending after " + change ); defer.notify(); } ); } ); } ); } ); QUnit.test( "jQuery.Deferred - chainability", function( assert ) { var defer = jQuery.Deferred(); assert.expect( 10 ); jQuery.expandedEach = jQuery.each; jQuery.expandedEach( "resolve reject notify resolveWith rejectWith notifyWith done fail progress always".split( " " ), function( _, method ) { var object = { m: defer[ method ] }; assert.strictEqual( object.m(), object, method + " is chainable" ); } ); } ); QUnit.test( "jQuery.Deferred.then - filtering (done)", function( assert ) { assert.expect( 4 ); var value1, value2, value3, defer = jQuery.Deferred(), piped = defer.then( function( a, b ) { return a * b; } ), done = jQuery.map( new Array( 3 ), function() { return assert.async(); } ); piped.done( function( result ) { value3 = result; } ); defer.done( function( a, b ) { value1 = a; value2 = b; } ); defer.resolve( 2, 3 ).then( function() { assert.strictEqual( value1, 2, "first resolve value ok" ); assert.strictEqual( value2, 3, "second resolve value ok" ); assert.strictEqual( value3, 6, "result of filter ok" ); done.pop().call(); } ); jQuery.Deferred().reject().then( function() { assert.ok( false, "then should not be called on reject" ); } ).then( null, done.pop() ); jQuery.Deferred().resolve().then( jQuery.noop ).done( function( value ) { assert.strictEqual( value, undefined, "then done callback can return undefined/null" ); done.pop().call(); } ); } ); QUnit.test( "jQuery.Deferred.then - filtering (fail)", function( assert ) { assert.expect( 4 ); var value1, value2, value3, defer = jQuery.Deferred(), piped = defer.then( null, function( a, b ) { return a * b; } ), done = jQuery.map( new Array( 3 ), function() { return assert.async(); } ); piped.done( function( result ) { value3 = result; } ); defer.fail( function( a, b ) { value1 = a; value2 = b; } ); defer.reject( 2, 3 ).then( null, function() { assert.strictEqual( value1, 2, "first reject value ok" ); assert.strictEqual( value2, 3, "second reject value ok" ); assert.strictEqual( value3, 6, "result of filter ok" ); done.pop().call(); } ); jQuery.Deferred().resolve().then( null, function() { assert.ok( false, "then should not be called on resolve" ); } ).then( done.pop() ); jQuery.Deferred().reject().then( null, jQuery.noop ).done( function( value ) { assert.strictEqual( value, undefined, "then fail callback can return undefined/null" ); done.pop().call(); } ); } ); QUnit.test( "jQuery.Deferred.catch", function( assert ) { assert.expect( 4 ); var value1, value2, value3, defer = jQuery.Deferred(), piped = defer[ "catch" ]( function( a, b ) { return a * b; } ), done = jQuery.map( new Array( 3 ), function() { return assert.async(); } ); piped.done( function( result ) { value3 = result; } ); defer.fail( function( a, b ) { value1 = a; value2 = b; } ); defer.reject( 2, 3 )[ "catch" ]( function() { assert.strictEqual( value1, 2, "first reject value ok" ); assert.strictEqual( value2, 3, "second reject value ok" ); assert.strictEqual( value3, 6, "result of filter ok" ); done.pop().call(); } ); jQuery.Deferred().resolve()[ "catch" ]( function() { assert.ok( false, "then should not be called on resolve" ); } ).then( done.pop() ); jQuery.Deferred().reject()[ "catch" ]( jQuery.noop ).done( function( value ) { assert.strictEqual( value, undefined, "then fail callback can return undefined/null" ); done.pop().call(); } ); } ); QUnit.test( "[PIPE ONLY] jQuery.Deferred.pipe - filtering (fail)", function( assert ) { assert.expect( 4 ); var value1, value2, value3, defer = jQuery.Deferred(), piped = defer.pipe( null, function( a, b ) { return a * b; } ), done = jQuery.map( new Array( 3 ), function() { return assert.async(); } ); piped.fail( function( result ) { value3 = result; } ); defer.fail( function( a, b ) { value1 = a; value2 = b; } ); defer.reject( 2, 3 ).pipe( null, function() { assert.strictEqual( value1, 2, "first reject value ok" ); assert.strictEqual( value2, 3, "second reject value ok" ); assert.strictEqual( value3, 6, "result of filter ok" ); done.pop().call(); } ); jQuery.Deferred().resolve().pipe( null, function() { assert.ok( false, "then should not be called on resolve" ); } ).then( done.pop() ); jQuery.Deferred().reject().pipe( null, jQuery.noop ).fail( function( value ) { assert.strictEqual( value, undefined, "then fail callback can return undefined/null" ); done.pop().call(); } ); } ); QUnit.test( "jQuery.Deferred.then - filtering (progress)", function( assert ) { assert.expect( 3 ); var value1, value2, value3, defer = jQuery.Deferred(), piped = defer.then( null, null, function( a, b ) { return a * b; } ), done = assert.async(); piped.progress( function( result ) { value3 = result; } ); defer.progress( function( a, b ) { value1 = a; value2 = b; } ); defer.notify( 2, 3 ).then( null, null, function() { assert.strictEqual( value1, 2, "first progress value ok" ); assert.strictEqual( value2, 3, "second progress value ok" ); assert.strictEqual( value3, 6, "result of filter ok" ); done(); } ); } ); QUnit.test( "jQuery.Deferred.then - deferred (done)", function( assert ) { assert.expect( 3 ); var value1, value2, value3, defer = jQuery.Deferred(), piped = defer.then( function( a, b ) { return jQuery.Deferred( function( defer ) { defer.reject( a * b ); } ); } ), done = assert.async(); piped.fail( function( result ) { value3 = result; } ); defer.done( function( a, b ) { value1 = a; value2 = b; } ); defer.resolve( 2, 3 ); piped.fail( function() { assert.strictEqual( value1, 2, "first resolve value ok" ); assert.strictEqual( value2, 3, "second resolve value ok" ); assert.strictEqual( value3, 6, "result of filter ok" ); done(); } ); } ); QUnit.test( "jQuery.Deferred.then - deferred (fail)", function( assert ) { assert.expect( 3 ); var value1, value2, value3, defer = jQuery.Deferred(), piped = defer.then( null, function( a, b ) { return jQuery.Deferred( function( defer ) { defer.resolve( a * b ); } ); } ), done = assert.async(); piped.done( function( result ) { value3 = result; } ); defer.fail( function( a, b ) { value1 = a; value2 = b; } ); defer.reject( 2, 3 ); piped.done( function() { assert.strictEqual( value1, 2, "first reject value ok" ); assert.strictEqual( value2, 3, "second reject value ok" ); assert.strictEqual( value3, 6, "result of filter ok" ); done(); } ); } ); QUnit.test( "jQuery.Deferred.then - deferred (progress)", function( assert ) { assert.expect( 3 ); var value1, value2, value3, defer = jQuery.Deferred(), piped = defer.then( null, null, function( a, b ) { return jQuery.Deferred( function( defer ) { defer.resolve( a * b ); } ); } ), done = assert.async(); piped.progress( function( result ) { return jQuery.Deferred().resolve().then( function() { return result; } ).then( function( result ) { value3 = result; } ); } ); defer.progress( function( a, b ) { value1 = a; value2 = b; } ); defer.notify( 2, 3 ); piped.then( null, null, function( result ) { return jQuery.Deferred().resolve().then( function() { return result; } ).then( function() { assert.strictEqual( value1, 2, "first progress value ok" ); assert.strictEqual( value2, 3, "second progress value ok" ); assert.strictEqual( value3, 6, "result of filter ok" ); done(); } ); } ); } ); QUnit.test( "[PIPE ONLY] jQuery.Deferred.pipe - deferred (progress)", function( assert ) { assert.expect( 3 ); var value1, value2, value3, defer = jQuery.Deferred(), piped = defer.pipe( null, null, function( a, b ) { return jQuery.Deferred( function( defer ) { defer.resolve( a * b ); } ); } ), done = assert.async(); piped.done( function( result ) { value3 = result; } ); defer.progress( function( a, b ) { value1 = a; value2 = b; } ); defer.notify( 2, 3 ); piped.done( function() { assert.strictEqual( value1, 2, "first progress value ok" ); assert.strictEqual( value2, 3, "second progress value ok" ); assert.strictEqual( value3, 6, "result of filter ok" ); done(); } ); } ); QUnit.test( "jQuery.Deferred.then - context", function( assert ) { assert.expect( 7 ); var defer, piped, defer2, piped2, context = {}, done = jQuery.map( new Array( 4 ), function() { return assert.async(); } ); jQuery.Deferred().resolveWith( context, [ 2 ] ).then( function( value ) { return value * 3; } ).done( function( value ) { assert.notStrictEqual( this, context, "custom context not propagated through .then" ); assert.strictEqual( value, 6, "proper value received" ); done.pop().call(); } ); jQuery.Deferred().resolve().then( function() { return jQuery.Deferred().resolveWith( context ); } ).done( function() { assert.strictEqual( this, context, "custom context of returned deferred correctly propagated" ); done.pop().call(); } ); defer = jQuery.Deferred(); piped = defer.then( function( value ) { return value * 3; } ); defer.resolve( 2 ); piped.done( function( value ) { assert.strictEqual( this, piped, "default context gets updated to latest promise in the chain" ); assert.strictEqual( value, 6, "proper value received" ); done.pop().call(); } ); defer2 = jQuery.Deferred(); piped2 = defer2.then(); defer2.resolve( 2 ); piped2.done( function( value ) { assert.strictEqual( this, piped2, "default context updated to latest promise in the chain (without passing function)" ); assert.strictEqual( value, 2, "proper value received (without passing function)" ); done.pop().call(); } ); } ); QUnit.test( "[PIPE ONLY] jQuery.Deferred.pipe - context", function( assert ) { assert.expect( 7 ); var defer, piped, defer2, piped2, context = {}, done = jQuery.map( new Array( 4 ), function() { return assert.async(); } ); jQuery.Deferred().resolveWith( context, [ 2 ] ).pipe( function( value ) { return value * 3; } ).done( function( value ) { assert.strictEqual( this, context, "[PIPE ONLY] custom context correctly propagated" ); assert.strictEqual( value, 6, "proper value received" ); done.pop().call(); } ); jQuery.Deferred().resolve().pipe( function() { return jQuery.Deferred().resolveWith( context ); } ).done( function() { assert.strictEqual( this, context, "custom context of returned deferred correctly propagated" ); done.pop().call(); } ); defer = jQuery.Deferred(); piped = defer.pipe( function( value ) { return value * 3; } ); defer.resolve( 2 ); piped.done( function( value ) { assert.strictEqual( this, piped, "default context gets updated to latest promise in the chain" ); assert.strictEqual( value, 6, "proper value received" ); done.pop().call(); } ); defer2 = jQuery.Deferred(); piped2 = defer2.pipe(); defer2.resolve( 2 ); piped2.done( function( value ) { assert.strictEqual( this, piped2, "default context updated to latest promise in the chain (without passing function)" ); assert.strictEqual( value, 2, "proper value received (without passing function)" ); done.pop().call(); } ); } ); QUnit.test( "jQuery.Deferred.then - spec compatibility", function( assert ) { assert.expect( 1 ); var done = assert.async(); var defer = jQuery.Deferred().done( function() { setTimeout( done ); throw new Error(); } ); defer.then( function() { assert.ok( true, "errors in .done callbacks don't stop .then handlers" ); } ); try { defer.resolve(); } catch ( _ ) {} } ); QUnit.test( "jQuery.Deferred - 1.x/2.x compatibility", function( assert ) { assert.expect( 8 ); var context = { id: "callback context" }, thenable = jQuery.Deferred().resolve( "thenable fulfillment" ).promise(), done = jQuery.map( new Array( 8 ), function() { return assert.async(); } ); thenable.unwrapped = false; jQuery.Deferred().resolve( 1, 2 ).then( function() { assert.deepEqual( [].slice.call( arguments ), [ 1, 2 ], ".then fulfillment callbacks receive all resolution values" ); done.pop().call(); } ); jQuery.Deferred().reject( 1, 2 ).then( null, function() { assert.deepEqual( [].slice.call( arguments ), [ 1, 2 ], ".then rejection callbacks receive all rejection values" ); done.pop().call(); } ); jQuery.Deferred().notify( 1, 2 ).then( null, null, function() { assert.deepEqual( [].slice.call( arguments ), [ 1, 2 ], ".then progress callbacks receive all progress values" ); done.pop().call(); } ); jQuery.Deferred().resolveWith( context ).then( function() { assert.deepEqual( this, context, ".then fulfillment callbacks receive context" ); done.pop().call(); } ); jQuery.Deferred().rejectWith( context ).then( null, function() { assert.deepEqual( this, context, ".then rejection callbacks receive context" ); done.pop().call(); } ); jQuery.Deferred().notifyWith( context ).then( null, null, function() { assert.deepEqual( this, context, ".then progress callbacks receive context" ); done.pop().call(); } ); jQuery.Deferred().resolve( thenable ).done( function( value ) { assert.strictEqual( value, thenable, ".done doesn't unwrap thenables" ); done.pop().call(); } ); jQuery.Deferred().notify( thenable ).then().then( null, null, function( value ) { assert.strictEqual( value, "thenable fulfillment", ".then implicit progress callbacks unwrap thenables" ); done.pop().call(); } ); } ); QUnit.test( "jQuery.Deferred.then - progress and thenables", function( assert ) { assert.expect( 2 ); var trigger = jQuery.Deferred().notify(), expectedProgress = [ "baz", "baz" ], done = jQuery.map( new Array( 2 ), function() { return assert.async(); } ), failer = function( evt ) { return function() { assert.ok( false, "no unexpected " + evt ); }; }; trigger.then( null, null, function() { var notifier = jQuery.Deferred().notify( "foo" ); setTimeout( function() { notifier.notify( "bar" ).resolve( "baz" ); } ); return notifier; } ).then( failer( "fulfill" ), failer( "reject" ), function( v ) { assert.strictEqual( v, expectedProgress.shift(), "expected progress value" ); done.pop().call(); } ); trigger.notify(); } ); QUnit.test( "jQuery.Deferred - notify and resolve", function( assert ) { assert.expect( 7 ); var notifiedResolved = jQuery.Deferred().notify( "foo" )/*xxx .resolve( "bar" )*/, done = jQuery.map( new Array( 3 ), function() { return assert.async(); } ); notifiedResolved.progress( function( v ) { assert.strictEqual( v, "foo", "progress value" ); } ); notifiedResolved.pipe().progress( function( v ) { assert.strictEqual( v, "foo", "piped progress value" ); } ); notifiedResolved.pipe( null, null, function() { return "baz"; } ).progress( function( v ) { assert.strictEqual( v, "baz", "replaced piped progress value" ); } ); notifiedResolved.pipe( null, null, function() { return jQuery.Deferred().notify( "baz" ).resolve( "quux" ); } ).progress( function( v ) { assert.strictEqual( v, "baz", "deferred replaced piped progress value" ); } ); notifiedResolved.then().progress( function( v ) { assert.strictEqual( v, "foo", "then'd progress value" ); done.pop().call(); } ); notifiedResolved.then( null, null, function() { return "baz"; } ).progress( function( v ) { assert.strictEqual( v, "baz", "replaced then'd progress value" ); done.pop().call(); } ); notifiedResolved.then( null, null, function() { return jQuery.Deferred().notify( "baz" ).resolve( "quux" ); } ).progress( function( v ) { // Progress from the surrogate deferred is ignored assert.strictEqual( v, "quux", "deferred replaced then'd progress value" ); done.pop().call(); } ); } ); QUnit.test( "jQuery.when", function( assert ) { assert.expect( 37 ); // Some other objects jQuery.each( { "an empty string": "", "a non-empty string": "some string", "zero": 0, "a number other than zero": 1, "true": true, "false": false, "null": null, "undefined": undefined, "a plain object": {}, "an array": [ 1, 2, 3 ] }, function( message, value ) { assert.ok( jQuery.isFunction( jQuery.when( value ).done( function( resolveValue ) { assert.strictEqual( this, window, "Context is the global object with " + message ); assert.strictEqual( resolveValue, value, "Test the promise was resolved with " + message ); } ).promise ), "Test " + message + " triggers the creation of a new Promise" ); } ); assert.ok( jQuery.isFunction( jQuery.when().done( function( resolveValue ) { assert.strictEqual( this, window, "Test the promise was resolved with window as its context" ); assert.strictEqual( resolveValue, undefined, "Test the promise was resolved with no parameter" ); } ).promise ), "Test calling when with no parameter triggers the creation of a new Promise" ); var cache, context = {}; jQuery.when( jQuery.Deferred().resolveWith( context ) ).done( function() { assert.strictEqual( this, context, "when( promise ) propagates context" ); } ); jQuery.each( [ 1, 2, 3 ], function( k, i ) { jQuery.when( cache || jQuery.Deferred( function() { this.resolve( i ); } ) ).done( function( value ) { assert.strictEqual( value, 1, "Function executed" + ( i > 1 ? " only once" : "" ) ); cache = value; } ); } ); } ); QUnit.test( "jQuery.when - joined", function( assert ) { assert.expect( 81 ); var deferreds = { rawValue: 1, fulfilled: jQuery.Deferred().resolve( 1 ), rejected: jQuery.Deferred().reject( 0 ), eventuallyFulfilled: jQuery.Deferred().notify( true ), eventuallyRejected: jQuery.Deferred().notify( true ), fulfilledStandardPromise: Promise.resolve( 1 ), rejectedStandardPromise: Promise.reject( 0 ) }, willSucceed = { rawValue: true, fulfilled: true, eventuallyFulfilled: true, fulfilledStandardPromise: true }, willError = { rejected: true, eventuallyRejected: true, rejectedStandardPromise: true }, counter = 49; QUnit.stop(); function restart() { if ( !--counter ) { QUnit.start(); } } jQuery.each( deferreds, function( id1, defer1 ) { jQuery.each( deferreds, function( id2, defer2 ) { var shouldResolve = willSucceed[ id1 ] && willSucceed[ id2 ], shouldError = willError[ id1 ] || willError[ id2 ], expected = shouldResolve ? [ 1, 1 ] : [ 0, undefined ], code = "jQuery.when( " + id1 + ", " + id2 + " )", context1 = defer1 && jQuery.isFunction( defer1.promise ) ? defer1.promise() : window, context2 = defer2 && jQuery.isFunction( defer2.promise ) ? defer2.promise() : window; jQuery.when( defer1, defer2 ).done( function( a, b ) { if ( shouldResolve ) { assert.deepEqual( [ a, b ], expected, code + " => resolve" ); assert.strictEqual( this[ 0 ], context1, code + " => first context OK" ); assert.strictEqual( this[ 1 ], context2, code + " => second context OK" ); } else { assert.ok( false, code + " => resolve" ); } } ).fail( function( a, b ) { if ( shouldError ) { assert.deepEqual( [ a, b ], expected, code + " => reject" ); } else { assert.ok( false, code + " => reject" ); } } ).always( restart ); } ); } ); deferreds.eventuallyFulfilled.resolve( 1 ); deferreds.eventuallyRejected.reject( 0 ); } ); QUnit.test( "jQuery.when - notify does not affect resolved", function( assert ) { assert.expect( 3 ); var a = jQuery.Deferred().notify( 1 ).resolve( 4 ), b = jQuery.Deferred().notify( 2 ).resolve( 5 ), c = jQuery.Deferred().notify( 3 ).resolve( 6 ); jQuery.when( a, b, c ).done( function( a, b, c ) { assert.strictEqual( a, 4, "first resolve value ok" ); assert.strictEqual( b, 5, "second resolve value ok" ); assert.strictEqual( c, 6, "third resolve value ok" ); } ).fail( function() { assert.ok( false, "Error on resolve" ); } ); } ); QUnit.test( "jQuery.when - filtering", function( assert ) { assert.expect( 2 ); function increment( x ) { return x + 1; } QUnit.stop(); jQuery.when( jQuery.Deferred().resolve( 3 ).then( increment ), jQuery.Deferred().reject( 5 ).then( null, increment ) ).done( function( four, six ) { assert.strictEqual( four, 4, "resolved value incremented" ); assert.strictEqual( six, 6, "rejected value incremented" ); QUnit.start(); } ); } ); QUnit.test( "jQuery.when - exceptions", function( assert ) { assert.expect( 2 ); function woops() { throw "exception thrown"; } QUnit.stop(); jQuery.Deferred().resolve().then( woops ).fail( function( doneException ) { assert.strictEqual( doneException, "exception thrown", "throwing in done handler" ); jQuery.Deferred().reject().then( null, woops ).fail( function( failException ) { assert.strictEqual( failException, "exception thrown", "throwing in fail handler" ); QUnit.start(); } ); } ); } ); QUnit.test( "jQuery.when - chaining", function( assert ) { assert.expect( 4 ); var defer = jQuery.Deferred(); function chain() { return defer; } function chainStandard() { return Promise.resolve( "std deferred" ); } QUnit.stop(); jQuery.when( jQuery.Deferred().resolve( 3 ).then( chain ), jQuery.Deferred().reject( 5 ).then( null, chain ), jQuery.Deferred().resolve( 3 ).then( chainStandard ), jQuery.Deferred().reject( 5 ).then( null, chainStandard ) ).done( function( v1, v2, s1, s2 ) { assert.strictEqual( v1, "other deferred", "chaining in done handler" ); assert.strictEqual( v2, "other deferred", "chaining in fail handler" ); assert.strictEqual( s1, "std deferred", "chaining thenable in done handler" ); assert.strictEqual( s2, "std deferred", "chaining thenable in fail handler" ); QUnit.start(); } ); defer.resolve( "other deferred" ); } ); QUnit.test( "jQuery.when - solitary thenables", function( assert ) { assert.expect( 1 ); var done = assert.async(), rejected = new Promise( function( resolve, reject ) { setTimeout( function() { reject( "rejected" ); }, 100 ); } ); jQuery.when( rejected ).then( function() { assert.ok( false, "Rejected, solitary, non-Deferred thenable should not resolve" ); done(); }, function() { assert.ok( true, "Rejected, solitary, non-Deferred thenable rejected properly" ); done(); } ); } ); QUnit.test( "jQuery.when does not reuse a solitary jQuery Deferred (gh-2018)", function( assert ) { assert.expect( 2 ); var defer = jQuery.Deferred().resolve(), promise = jQuery.when( defer ); assert.equal( promise.state(), "resolved", "Master Deferred is immediately resolved" ); assert.notStrictEqual( defer.promise(), promise, "jQuery.when returns the master deferred's promise" ); } );