mediawiki-extensions-Popups/tests/node-qunit/gateway/mediawiki.test.js

262 lines
7.4 KiB
JavaScript
Raw Normal View History

import { createModel } from '../../../src/preview/model';
import createMediaWikiApiGateway from '../../../src/gateway/mediawiki';
const DEFAULT_CONSTANTS = {
THUMBNAIL_SIZE: 300,
EXTRACT_LENGTH: 525
},
MEDIAWIKI_API_RESPONSE = {
query: {
pages: [
{
contentmodel: 'wikitext',
extract: 'Richard Paul "Rick" Astley is an English singer, songwriter, musician, and radio personality. His 1987 song, "Never Gonna Give You Up" was a No. 1 hit single in 25 countries. By the time of his retirement in 1993, Astley had sold approximately 40 million records worldwide.\nAstley made a comeback in 2007, becoming an Internet phenomenon when his video "Never Gonna Give You Up" became integral to the meme known as "rickrolling". Astley was voted "Best Act Ever" by Internet users at the',
lastrevid: 748725726,
length: 32132,
fullurl: 'https://en.wikipedia.org/wiki/Rick_Astley',
editurl: 'https://en.wikipedia.org/w/index.php?title=Rick_Astley&action=edit',
canonicalurl: 'https://en.wikipedia.org/wiki/Rick_Astley',
ns: 0,
pageid: 447541,
pagelanguage: 'en',
pagelanguagedir: 'ltr',
pagelanguagehtmlcode: 'en',
revisions: [ {
timestamp: '2016-11-10T00:14:14Z'
} ],
thumbnail: {
height: 300,
source: 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/6d/Rick_Astley_-_Pepsifest_2009.jpg/200px-Rick_Astley_-_Pepsifest_2009.jpg',
width: 200
},
title: 'Rick Astley',
touched: '2016-11-10T00:14:14Z'
}
]
}
},
MEDIAWIKI_API_RESPONSE_PREVIEW_MODEL = createModel(
'Rick Astley',
'https://en.wikipedia.org/wiki/Rick_Astley',
'en',
'ltr',
[ document.createTextNode( 'Richard Paul "Rick" Astley is an English singer, songwriter, musician, and radio personality. His 1987 song, "Never Gonna Give You Up" was a No. 1 hit single in 25 countries. By the time of his retirement in 1993, Astley had sold approximately 40 million records worldwide.\nAstley made a comeback in 2007, becoming an Internet phenomenon when his video "Never Gonna Give You Up" became integral to the meme known as "rickrolling". Astley was voted "Best Act Ever" by Internet users at the' ) ],
undefined,
{
height: 300,
source: 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/6d/Rick_Astley_-_Pepsifest_2009.jpg/200px-Rick_Astley_-_Pepsifest_2009.jpg',
width: 200
},
447541
);
QUnit.module( 'ext.popups/gateway/mediawiki', {
beforeEach() {
mediaWiki.RegExp = {
escape: this.sandbox.spy(
( str ) => str.replace( /([\\{}()|.?*+\-^$[\]])/g, '\\$1' )
)
};
},
afterEach() {
mediaWiki.RegExp = null;
}
} );
QUnit.test( 'MediaWiki API gateway is called with correct arguments', function ( assert ) {
const config = $.extend( {}, DEFAULT_CONSTANTS, {
acceptLanguage: 'pl'
} );
const spy = this.sandbox.spy(),
api = {
get: spy
},
gateway = createMediaWikiApiGateway( api, config ),
expectedOptions = {
action: 'query',
prop: 'info|extracts|pageimages|revisions|info',
formatversion: 2,
redirects: true,
exintro: true,
exchars: 525,
explaintext: true,
piprop: 'thumbnail',
pithumbsize: DEFAULT_CONSTANTS.THUMBNAIL_SIZE,
pilicense: 'any',
rvprop: 'timestamp',
inprop: 'url',
titles: 'Test Title',
smaxage: 300,
maxage: 300,
uselang: 'content'
},
expectedHeaders = {
headers: {
'X-Analytics': 'preview=1',
'Accept-Language': 'pl'
}
};
gateway.fetch( 'Test Title' );
assert.deepEqual( spy.getCall( 0 ).args[ 0 ], expectedOptions, 'options' );
assert.deepEqual( spy.getCall( 0 ).args[ 1 ], expectedHeaders, 'headers' );
} );
QUnit.test( 'MediaWiki API gateway is correctly extracting the page data from the response ', function ( assert ) {
const api = {
get: this.sandbox.stub()
},
gateway = createMediaWikiApiGateway( api, DEFAULT_CONSTANTS ),
errorCases = [
{},
{
query: {}
},
{
query: {
pages: []
}
}
],
successCases = [
[
{
query: {
pages: [ { someData: 'Yes' } ]
}
},
{
someData: 'Yes'
}
]
];
assert.expect(
errorCases.length + successCases.length,
'All assertions are executed.'
);
errorCases.forEach( ( data, i ) => {
assert.throws(
() => { gateway.extractPageFromResponse( data ); },
`Case ${i}: the gateway throws an error.`
);
} );
successCases.forEach( ( data, i ) => {
assert.deepEqual(
gateway.extractPageFromResponse( data[ 0 ] ),
data[ 1 ],
`Case ${i}: the gateway extracts the response.`
);
} );
} );
QUnit.test( 'MediaWiki API gateway is correctly converting the page data to a model', ( assert ) => {
const gateway = createMediaWikiApiGateway(),
page = gateway.extractPageFromResponse( MEDIAWIKI_API_RESPONSE );
assert.deepEqual(
gateway.convertPageToModel( gateway.formatPlainTextExtract( page ) ),
MEDIAWIKI_API_RESPONSE_PREVIEW_MODEL,
'The gateway converts the page preview response.'
);
} );
QUnit.test( 'MediaWiki API gateway handles API failure', function ( assert ) {
const api = {
get: this.sandbox.stub()
.returns( $.Deferred().reject( { status: 400 } ).promise() )
},
gateway = createMediaWikiApiGateway( api, DEFAULT_CONSTANTS );
return gateway.getPageSummary( 'Test Title' ).catch( () => {
assert.ok( true, 'The gateway threw an error.' );
} );
} );
Update: cancel unused HTTP requests in flight Whenever an HTTP request sequence is started, i.e. wait for the fetch start time, issue a network request, and return the result, abort the process if the results are known to no longer be needed. This occurs when a user has dwelt upon one link and then abandoned it either during the fetch start wait time or during the fetch network request itself. This change is accomplished by preserving the pending promises in two actions, LINK_DWELL and FETCH_START, and whenever the ABANDON_START action is issued, it now aborts any previously pending XHR-like promise, called a "AbortPromise" which is just a thenable with an abort() method. There is a similar concept in Core: https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+/ecc812f06e7dff587b3f31dc18189adbf4616351/resources/src/mediawiki.api/index.js. Aborting pending requests has big implications for client and server logging as requests are quickly canceled, especially on slower connections. These differences can be observed on the network tab of DevTools and the log in Redux DevTools. Consider, for instance, the scenario of dwelling upon and quickly abandoning a single link prior to this patch: BOOT EVENT_LOGGED LINK_DWELL FETCH_START ABANDON_START FETCH_END STATSV_LOGGED ABANDON_END EVENT_LOGGED FETCH_COMPLETE And after this patch when the fetch timer is canceled (prior to an actual network request): BOOT EVENT_LOGGED LINK_DWELL ABANDON_START ABANDON_END EVENT_LOGGED In the above sequence, FETCH_* and STATSV_LOGGED actions never occur. And after this patch when the network request itself is canceled: BOOT EVENT_LOGGED LINK_DWELL FETCH_START ABANDON_START FETCH_FAILED STATSV_LOGGED FETCH_COMPLETE ABANDON_END EVENT_LOGGED FETCH_FAILED occurs intentionally, STATSV_LOGGED and FETCH_COMPLETE still happen even though the fetch didn't complete successfully, and FETCH_END doesn't. Additionally, since less data is transmitted, it's possible that the timing and success rate of logging will improve on low bandwidth connections. Also, this patch tries to revise the JSDocs where possible to support type checking and fix a call to the missing assert.fail() function in changeListener.test.js. Bug: T197700 Change-Id: I9a73b3086fc8fb0edd897a347b5497d5362e20ef
2018-06-25 13:26:11 +00:00
QUnit.test( 'MediaWiki API gateway returns the correct data', function ( assert ) {
const api = {
get: this.sandbox.stub().returns(
$.Deferred().resolve( MEDIAWIKI_API_RESPONSE ).promise()
)
},
gateway = createMediaWikiApiGateway( api, DEFAULT_CONSTANTS );
return gateway.getPageSummary( 'Test Title' ).then( ( result ) => {
assert.deepEqual(
result,
MEDIAWIKI_API_RESPONSE_PREVIEW_MODEL,
'The gateway converts the page preview response.'
);
} );
} );
Update: cancel unused HTTP requests in flight Whenever an HTTP request sequence is started, i.e. wait for the fetch start time, issue a network request, and return the result, abort the process if the results are known to no longer be needed. This occurs when a user has dwelt upon one link and then abandoned it either during the fetch start wait time or during the fetch network request itself. This change is accomplished by preserving the pending promises in two actions, LINK_DWELL and FETCH_START, and whenever the ABANDON_START action is issued, it now aborts any previously pending XHR-like promise, called a "AbortPromise" which is just a thenable with an abort() method. There is a similar concept in Core: https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+/ecc812f06e7dff587b3f31dc18189adbf4616351/resources/src/mediawiki.api/index.js. Aborting pending requests has big implications for client and server logging as requests are quickly canceled, especially on slower connections. These differences can be observed on the network tab of DevTools and the log in Redux DevTools. Consider, for instance, the scenario of dwelling upon and quickly abandoning a single link prior to this patch: BOOT EVENT_LOGGED LINK_DWELL FETCH_START ABANDON_START FETCH_END STATSV_LOGGED ABANDON_END EVENT_LOGGED FETCH_COMPLETE And after this patch when the fetch timer is canceled (prior to an actual network request): BOOT EVENT_LOGGED LINK_DWELL ABANDON_START ABANDON_END EVENT_LOGGED In the above sequence, FETCH_* and STATSV_LOGGED actions never occur. And after this patch when the network request itself is canceled: BOOT EVENT_LOGGED LINK_DWELL FETCH_START ABANDON_START FETCH_FAILED STATSV_LOGGED FETCH_COMPLETE ABANDON_END EVENT_LOGGED FETCH_FAILED occurs intentionally, STATSV_LOGGED and FETCH_COMPLETE still happen even though the fetch didn't complete successfully, and FETCH_END doesn't. Additionally, since less data is transmitted, it's possible that the timing and success rate of logging will improve on low bandwidth connections. Also, this patch tries to revise the JSDocs where possible to support type checking and fix a call to the missing assert.fail() function in changeListener.test.js. Bug: T197700 Change-Id: I9a73b3086fc8fb0edd897a347b5497d5362e20ef
2018-06-25 13:26:11 +00:00
QUnit.test( 'MediaWiki API gateway handles missing pages', function ( assert ) {
const response = {
query: {
pages: [ {
canonicalurl: 'http://dev.wiki.local.wmftest.net:8080/wiki/Missing_page',
contentmodel: 'wikitext',
editurl: 'http://dev.wiki.local.wmftest.net:8080/w/index.php?title=Missing_page&action=edit',
fullurl: 'http://dev.wiki.local.wmftest.net:8080/wiki/Missing_page',
missing: true,
ns: 0,
pagelanguage: 'en',
pagelanguagedir: 'ltr',
pagelanguagehtmlcode: 'en',
title: 'Missing page'
} ]
}
},
model = createModel(
'Missing page',
'http://dev.wiki.local.wmftest.net:8080/wiki/Missing_page',
'en',
'ltr',
undefined,
undefined,
undefined
),
api = {
get: this.sandbox.stub().returns(
$.Deferred().resolve( response ).promise()
)
},
gateway = createMediaWikiApiGateway( api, DEFAULT_CONSTANTS );
return gateway.getPageSummary( 'Test Title' ).then( ( result ) => {
assert.deepEqual(
result,
model,
'The gateway converts the page preview response.'
);
} );
} );
Update: cancel unused HTTP requests in flight Whenever an HTTP request sequence is started, i.e. wait for the fetch start time, issue a network request, and return the result, abort the process if the results are known to no longer be needed. This occurs when a user has dwelt upon one link and then abandoned it either during the fetch start wait time or during the fetch network request itself. This change is accomplished by preserving the pending promises in two actions, LINK_DWELL and FETCH_START, and whenever the ABANDON_START action is issued, it now aborts any previously pending XHR-like promise, called a "AbortPromise" which is just a thenable with an abort() method. There is a similar concept in Core: https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+/ecc812f06e7dff587b3f31dc18189adbf4616351/resources/src/mediawiki.api/index.js. Aborting pending requests has big implications for client and server logging as requests are quickly canceled, especially on slower connections. These differences can be observed on the network tab of DevTools and the log in Redux DevTools. Consider, for instance, the scenario of dwelling upon and quickly abandoning a single link prior to this patch: BOOT EVENT_LOGGED LINK_DWELL FETCH_START ABANDON_START FETCH_END STATSV_LOGGED ABANDON_END EVENT_LOGGED FETCH_COMPLETE And after this patch when the fetch timer is canceled (prior to an actual network request): BOOT EVENT_LOGGED LINK_DWELL ABANDON_START ABANDON_END EVENT_LOGGED In the above sequence, FETCH_* and STATSV_LOGGED actions never occur. And after this patch when the network request itself is canceled: BOOT EVENT_LOGGED LINK_DWELL FETCH_START ABANDON_START FETCH_FAILED STATSV_LOGGED FETCH_COMPLETE ABANDON_END EVENT_LOGGED FETCH_FAILED occurs intentionally, STATSV_LOGGED and FETCH_COMPLETE still happen even though the fetch didn't complete successfully, and FETCH_END doesn't. Additionally, since less data is transmitted, it's possible that the timing and success rate of logging will improve on low bandwidth connections. Also, this patch tries to revise the JSDocs where possible to support type checking and fix a call to the missing assert.fail() function in changeListener.test.js. Bug: T197700 Change-Id: I9a73b3086fc8fb0edd897a347b5497d5362e20ef
2018-06-25 13:26:11 +00:00
QUnit.test( 'MediaWiki API gateway is abortable', function ( assert ) {
assert.expect( 1, 'All assertions are executed.' );
const
deferred = $.Deferred(),
api = {
get: this.sandbox.stub().returns(
deferred.promise( { abort() { deferred.reject( 'http' ); } } )
)
},
gateway = createMediaWikiApiGateway( api, DEFAULT_CONSTANTS );
const xhr = gateway.getPageSummary( 'Test Title' );
const chain = xhr.then( () => {
assert.ok( false, 'It never calls a thenable after rejection' );
} ).catch( data => {
assert.strictEqual( data, 'http' );
} );
xhr.abort();
return chain;
} );