' ).addClass( 'ext-checkuser-tempaccount-specialblock-ips' ) );
// Call the method under test
specialBlock.onLoad();
waitUntilElementDisappears( '.ext-checkuser-tempaccount-specialblock-ips' ).then( () => {
// Verify that the fake "Show IPs" button was removed
assert.strictEqual(
$( '.ext-checkuser-tempaccount-specialblock-ips', $qunitFixture ).length,
0,
'IP reveal button removed'
);
done();
} );
} );
/**
* Check if the request is a query for whether the temporary account exists.
*
* @param {Object} request The request to check
* @return {boolean}
*/
function isUsUsersApiQuery( request ) {
// The 'base' argument is required, but is not affect the test.
const url = new URL( request.url, 'https://www.example.com' );
return (
url.searchParams.get( 'action' ) === 'query' && url.searchParams.get( 'list' ) === 'users' &&
url.searchParams.get( 'ususers' ) === '~2024-1' && request.method === 'GET'
);
}
QUnit.test( 'Test onLoad for a user which matches temporary account format but does not exist', ( assert ) => {
assert.timeout( 1000 );
const done = assert.async( 2 );
// Add the target input with a username that matches the temporary account format,
// but does not exist.
addBlockInputToQUnitTextFixture( '~2024-1' );
// Respond to the 'users' list API query with no data to indicate that the user does not exist
server.respond( ( request ) => {
if ( isUsUsersApiQuery( request ) ) {
request.respond(
200,
{ 'Content-Type': 'application/json' },
'{"query":{"users":[{"name":"~2024-1","missing":true}]}}'
);
// By calling done() here, we assert in the test that the API request was made.
// If no requests are made, then the test will time out.
done();
}
} );
// eslint-disable-next-line no-jquery/no-global-selector
const $qunitFixture = $( '#qunit-fixture' );
// Add a fake SpecialBlock "Show IPs" button to the DOM to verify that it is
// removed when calling onLoad when the target is a non-existent user.
$qunitFixture.append( $( '
' ).addClass( 'ext-checkuser-tempaccount-specialblock-ips' ) );
// Call the method under test
specialBlock.onLoad();
waitUntilElementDisappears( '.ext-checkuser-tempaccount-specialblock-ips' ).then( () => {
// Verify that the fake "Show IPs" button was removed
assert.strictEqual(
$( '.ext-checkuser-tempaccount-specialblock-ips', $qunitFixture ).length,
0,
'IP reveal button removed'
);
done();
} );
} );
/**
* Call the onLoad method, click the button that is created and then verify the text that replaces
* the button is as expected.
*
* @param {string} expectedText The expected text of the element that replaces the button
* @param {Object} assert The QUnit assert object
* @param {*} done Method to call to indicate this method has completed assertions
*/
async function performOnLoadTestWhenButtonClicked( expectedText, assert, done ) {
// Call the method under test
specialBlock.onLoad();
// eslint-disable-next-line no-jquery/no-global-selector
const $qunitFixture = $( '#qunit-fixture' );
await waitUntilElementAppears( '.ext-checkuser-tempaccount-specialblock-ips' ).then( () => {
// Verify that the "Show IP" button is present.
assert.strictEqual(
$( '.ext-checkuser-tempaccount-specialblock-ips-link', $qunitFixture ).length,
1,
'IP reveal button appears'
);
// Click the button.
$( '.ext-checkuser-tempaccount-specialblock-ips-link a', $qunitFixture )[ 0 ].click();
return waitUntilElementDisappears( '.ext-checkuser-tempaccount-specialblock-ips-link' )
.then( () => new Promise( ( resolve ) => {
setTimeout( () => {
// Verify that the button has gone and was replaced with the IP address.
assert.strictEqual(
$( '.ext-checkuser-tempaccount-specialblock-ips', $qunitFixture ).length,
1,
'Container still present after button click'
);
assert.strictEqual(
$( '.ext-checkuser-tempaccount-specialblock-ips', $qunitFixture ).text(),
expectedText,
'Text of element that replaced button'
);
done();
resolve();
} );
} ) );
} );
}
QUnit.test( 'Test onLoad for an existing temporary account with IP data', async ( assert ) => {
assert.timeout( 1000 );
const done = assert.async( 4 );
// Add the target input with a username that matches the temporary account format,
// but does not exist.
addBlockInputToQUnitTextFixture( '~2024-1' );
server.respond( ( request ) => {
if ( isUsUsersApiQuery( request ) ) {
// Handle a request to check that the temporary user exists, and return that it does.
request.respond(
200,
{ 'Content-Type': 'application/json' },
'{"query":{"users":[{"name":"~2024-1","userid":1}]}}'
);
// By calling done() here, we assert in the test that the API request was made.
// If not all the required requests are made, then the test will time out.
done();
} else if (
request.url.includes( 'checkuser/v0/temporaryaccount/~2024-1' ) &&
request.method === 'POST'
) {
// Handle a request to the temporary account API
request.respond( 200, { 'Content-Type': 'application/json' }, '{"ips":["172.20.0.1","1.2.3.4"]}' );
// By calling done() here, we assert in the test that the API request was made.
// If not all the required requests are made, then the test will time out.
done();
}
} );
await performOnLoadTestWhenButtonClicked(
'(checkuser-tempaccount-specialblock-ips: 2,
172.20.0.1(and)(word-separator)
1.2.3.4)',
assert, done
);
// Check that the IPs in the element that replaced the button are
// links to Special:IPContributions for the IP.
// eslint-disable-next-line no-jquery/no-global-selector
const $qunitFixture = $( '#qunit-fixture' );
const $container = $( '.ext-checkuser-tempaccount-specialblock-ips', $qunitFixture );
const $linkElements = $container.find( 'a' );
$linkElements.each( function () {
const ip = $( this ).text();
assert.strictEqual(
$( this ).attr( 'href' ),
'https://www.example.com/wiki/Special:IPContributions/' + ip,
'IP address in element which replaced button has correct URL'
);
} );
done();
} );
QUnit.test( 'Test onLoad for an existing temporary account without IP data', ( assert ) => {
assert.timeout( 1000 );
const done = assert.async( 3 );
// Add the target input with a username that matches the temporary account format,
// but does not exist.
addBlockInputToQUnitTextFixture( '~2024-1' );
server.respond( ( request ) => {
if ( isUsUsersApiQuery( request ) ) {
// Handle a request to check that the temporary user exists, and return that it does.
request.respond(
200,
{ 'Content-Type': 'application/json' },
'{"query":{"users":[{"name":"~2024-1","userid":1}]}}'
);
// By calling done() here, we assert in the test that the API request was made.
// If not all the required requests are made, then the test will time out.
done();
} else if (
request.url.includes( 'checkuser/v0/temporaryaccount/~2024-1' ) &&
request.method === 'POST'
) {
// Handle a request to the temporary account API
request.respond( 200, { 'Content-Type': 'application/json' }, '{"ips":[]}' );
// By calling done() here, we assert in the test that the API request was made.
// If not all the required requests are made, then the test will time out.
done();
}
} );
performOnLoadTestWhenButtonClicked(
'(checkuser-tempaccount-no-ip-results: 90)', assert, done
);
} );
QUnit.test( 'Test onLoad for an existing temporary account but IP data call fails', ( assert ) => {
assert.timeout( 1000 );
const done = assert.async( 3 );
// Add the target input with a username that matches the temporary account format,
// but does not exist.
addBlockInputToQUnitTextFixture( '~2024-1' );
server.respond( ( request ) => {
if ( isUsUsersApiQuery( request ) ) {
// Handle a request to check that the temporary user exists, and return that it does.
request.respond(
200,
{ 'Content-Type': 'application/json' },
'{"query":{"users":[{"name":"~2024-1","userid":1}]}}'
);
// By calling done() here, we assert in the test that the API request was made.
// If not all the required requests are made, then the test will time out.
done();
} else if (
request.url.includes( 'checkuser/v0/temporaryaccount/~2024-1' ) &&
request.method === 'POST'
) {
// Handle a request to the temporary account API by returning a 500 error
request.respond( 500, { 'Content-Type': 'application/json' }, '' );
// By calling done() here, we assert in the test that the API request was made.
// If not all the required requests are made, then the test will time out.
done();
}
} );
performOnLoadTestWhenButtonClicked(
'(checkuser-tempaccount-reveal-ip-error)', assert, done
);
} );
QUnit.test( 'Test onLoad when Codex Special:Block is enabled', ( assert ) => {
mw.config.set( 'wgUseCodexSpecialBlock', true );
// Add a mock block target input to simulate that the page is the block page.
const $blockTargetInput = $( '
' ).attr( 'id', 'mw-bi-target' );
// eslint-disable-next-line no-jquery/no-global-selector
const $qunitFixture = $( '#qunit-fixture' );
$qunitFixture.append( $blockTargetInput );
// Call the method under test
specialBlock.onLoad();
// Fire the 'codex.userlookup' hook with a mock Vue ref and then expect
// that the Show IP button is added to this mock Vue ref.
const customComponents = { value: [] };
mw.hook( 'codex.userlookup' ).fire( customComponents );
assert.strictEqual( customComponents.value.length, 1, 'Component was added' );
assert.strictEqual(
customComponents.value[ 0 ].name,
'ShowIPButton',
'Show IP button component was added'
);
} );