Merge "selenium: invoke jobs to enforce eventual consistency"
[lhc/web/wiklou.git] / tests / qunit / suites / resources / mediawiki.widgets / MediaSearch / mediawiki.widgets.APIResultsQueue.test.js
1 /*!
2 * VisualEditor DataModel ResourceQueue tests.
3 *
4 * @copyright 2011-2018 VisualEditor Team and others; see http://ve.mit-license.org
5 */
6
7 QUnit.module( 'mediawiki.widgets.APIResultsQueue' );
8
9 ( function () {
10 var itemCounter, FullResourceProvider, EmptyResourceProvider, SingleResultResourceProvider;
11
12 itemCounter = 0;
13 FullResourceProvider = function ( config ) {
14 this.timer = null;
15 this.responseDelay = 1;
16 // Inheritance
17 FullResourceProvider.super.call( this, '', config );
18 };
19 EmptyResourceProvider = function ( config ) {
20 this.timer = null;
21 this.responseDelay = 1;
22 // Inheritance
23 EmptyResourceProvider.super.call( this, '', config );
24 };
25 SingleResultResourceProvider = function ( config ) {
26 this.timer = null;
27 this.responseDelay = 1;
28 // Inheritance
29 SingleResultResourceProvider.super.call( this, '', config );
30 };
31
32 OO.inheritClass( FullResourceProvider, mw.widgets.APIResultsProvider );
33 OO.inheritClass( EmptyResourceProvider, mw.widgets.APIResultsProvider );
34 OO.inheritClass( SingleResultResourceProvider, mw.widgets.APIResultsProvider );
35
36 FullResourceProvider.prototype.getResults = function ( howMany ) {
37 var i, timer,
38 result = [],
39 deferred = $.Deferred();
40
41 for ( i = itemCounter; i < itemCounter + howMany; i++ ) {
42 result.push( 'result ' + ( i + 1 ) );
43 }
44 itemCounter = i;
45
46 timer = setTimeout(
47 function () {
48 // Always resolve with some values
49 deferred.resolve( result );
50 },
51 this.responseDelay );
52
53 return deferred.promise( { abort: function () { clearTimeout( timer ); } } );
54 };
55
56 EmptyResourceProvider.prototype.getResults = function () {
57 var provider = this,
58 deferred = $.Deferred(),
59 timer = setTimeout(
60 function () {
61 provider.toggleDepleted( true );
62 // Always resolve with empty value
63 deferred.resolve( [] );
64 },
65 this.responseDelay );
66
67 return deferred.promise( { abort: function () { clearTimeout( timer ); } } );
68 };
69
70 SingleResultResourceProvider.prototype.getResults = function ( howMany ) {
71 var timer,
72 provider = this,
73 deferred = $.Deferred();
74
75 timer = setTimeout(
76 function () {
77 provider.toggleDepleted( howMany > 1 );
78 // Always resolve with one value
79 deferred.resolve( [ 'one result (' + ( itemCounter++ + 1 ) + ')' ] );
80 },
81 this.responseDelay );
82
83 return deferred.promise( { abort: function () { clearTimeout( timer ); } } );
84 };
85
86 /* Tests */
87
88 QUnit.test( 'Query providers', function ( assert ) {
89 var done = assert.async(),
90 providers = [
91 new FullResourceProvider(),
92 new EmptyResourceProvider(),
93 new SingleResultResourceProvider()
94 ],
95 queue = new mw.widgets.APIResultsQueue( {
96 threshold: 2
97 } );
98
99 assert.expect( 15 );
100
101 // Add providers to queue
102 queue.setProviders( providers );
103
104 // Set parameters and fetch
105 queue.setParams( { foo: 'bar' } );
106
107 queue.get( 10 )
108 .then( function ( data ) {
109 // Check that we received all requested results
110 assert.strictEqual( data.length, 10, 'Query 1: Results received.' );
111 // We've asked for 10 items + 2 threshold from all providers.
112 // Provider 1 returned 12 results
113 // Provider 2 returned 0 results
114 // Provider 3 returned 1 results
115 // Overall 13 results. 10 were retrieved. 3 left in queue.
116 assert.strictEqual( queue.getQueueSize(), 3, 'Query 1: Remaining queue size.' );
117
118 // Check if sources are depleted
119 assert.strictEqual( providers[ 0 ].isDepleted(), false, 'Query 1: Full provider not depleted.' );
120 assert.strictEqual( providers[ 1 ].isDepleted(), true, 'Query 1: Empty provider is depleted.' );
121 assert.strictEqual( providers[ 2 ].isDepleted(), true, 'Query 1: Single result provider is depleted.' );
122
123 // Ask for more results
124 return queue.get( 10 );
125 } )
126 .then( function ( data1 ) {
127 // This time, only provider 1 was queried, because the other
128 // two were marked as depleted.
129 // * We asked for 10 items
130 // * There are currently 3 items in the queue
131 // * The queue queried provider #1 for 12 items
132 // * The queue returned 10 results as requested
133 // * 5 results are now left in the queue.
134 assert.strictEqual( data1.length, 10, 'Query 1: Second set of results received.' );
135 assert.strictEqual( queue.getQueueSize(), 5, 'Query 1: Remaining queue size.' );
136
137 // Change the query
138 queue.setParams( { foo: 'baz' } );
139 // Check if sources are depleted
140 assert.strictEqual( providers[ 0 ].isDepleted(), false, 'Query 2: Full provider not depleted.' );
141 assert.strictEqual( providers[ 1 ].isDepleted(), false, 'Query 2: Empty provider not depleted.' );
142 assert.strictEqual( providers[ 2 ].isDepleted(), false, 'Query 2: Single result provider not depleted.' );
143
144 return queue.get( 10 );
145 } )
146 .then( function ( data2 ) {
147 // This should be the same as the very first result
148 assert.strictEqual( data2.length, 10, 'Query 2: Results received.' );
149 assert.strictEqual( queue.getQueueSize(), 3, 'Query 2: Remaining queue size.' );
150 // Check if sources are depleted
151 assert.strictEqual( providers[ 0 ].isDepleted(), false, 'Query 2: Full provider not depleted.' );
152 assert.strictEqual( providers[ 1 ].isDepleted(), true, 'Query 2: Empty provider is not depleted.' );
153 assert.strictEqual( providers[ 2 ].isDepleted(), true, 'Query 2: Single result provider is not depleted.' );
154 } )
155 // Finish the async test
156 .then( done );
157 } );
158
159 QUnit.test( 'Abort providers', function ( assert ) {
160 var done = assert.async(),
161 completed = false,
162 biggerQueue = new mw.widgets.APIResultsQueue( {
163 threshold: 5
164 } ),
165 providers = [
166 new FullResourceProvider(),
167 new EmptyResourceProvider(),
168 new SingleResultResourceProvider()
169 ];
170
171 assert.expect( 1 );
172
173 // Make the delay higher
174 providers.forEach( function ( provider ) { provider.responseDelay = 3; } );
175
176 // Add providers to queue
177 biggerQueue.setProviders( providers );
178
179 biggerQueue.setParams( { foo: 'bar' } );
180 biggerQueue.get( 100 )
181 .always( function () {
182 // This should only run if the promise wasn't aborted
183 completed = true;
184 } );
185
186 // Make the delay higher
187 providers.forEach( function ( provider ) { provider.responseDelay = 5; } );
188
189 biggerQueue.setParams( { foo: 'baz' } );
190 biggerQueue.get( 10 )
191 .then( function () {
192 assert.strictEqual( completed, false, 'Provider promises aborted.' );
193 } )
194 // Finish the async test
195 .then( done );
196 } );
197 }() );