' ).attr( 'data-mw-revid', revId );
$qunitFixture.append( $revisionLine );
// Add the temporary account username link for the revision line
const $tempAccountUserLink = makeTempUserLink( username );
$revisionLine.append( $tempAccountUserLink );
temporaryAccountUserLinks.push( $tempAccountUserLink );
} );
// Add some testing log lines
const logLines = { 2: tempName1, 5: tempName2, 6: tempName3 };
Object.entries( logLines ).forEach( ( [ logId, username ] ) => {
const $logLine = $( '
' ).attr( 'data-mw-logid', logId );
$qunitFixture.append( $logLine );
// Add the temporary account username link for the log line
const $tempAccountUserLink = makeTempUserLink( username );
$logLine.append( $tempAccountUserLink );
temporaryAccountUserLinks.push( $tempAccountUserLink );
} );
// Add a temporary account username that is not associated with a revision or log
const $tempAccountUserLink = makeTempUserLink( tempName3 );
$qunitFixture.append( $tempAccountUserLink );
temporaryAccountUserLinks.push( $tempAccountUserLink );
// Verify that before the call to ::addIpRevealButtons there are no Show IP buttons
assert.strictEqual(
$qunitFixture.find( '.ext-checkuser-tempaccount-reveal-ip-button' ).length,
0,
'No IP reveal links before addIpRevealButtons call'
);
// Call addIpRevealButtons on the QUnit fixture
ipReveal.addIpRevealButtons( $qunitFixture );
// Call again to ensure that the buttons can only be added once
ipReveal.addIpRevealButtons( $qunitFixture );
// Verify that the Show IP button was added for all temporary user links
temporaryAccountUserLinks.forEach( ( $element ) => {
assert.strictEqual(
// eslint-disable-next-line no-jquery/no-class-state
$element.next().hasClass( 'ext-checkuser-tempaccount-reveal-ip-button' ), true,
'IP reveal button is directly after temporary account user link after addIpRevealButtons call'
);
assert.strictEqual(
// eslint-disable-next-line no-jquery/no-class-state
$element.next().next().hasClass( 'ext-checkuser-tempaccount-reveal-ip-button' ), false,
'Only one IP reveal button is added after multiple addIpRevealButtons calls'
);
} );
} );
QUnit.test( 'Test makeButton creates expected button', ( assert ) => {
// Call the method under test
const elements = ipReveal.makeButton( tempName1, { targetId: 1, allIds: [ 1 ] }, {} );
const [ $button ] = elements;
assert.strictEqual( elements.length, 1, 'Only the IP reveal button should be returned for non-blocked users' );
// Verify that the button has the expected button text and classes
assert.strictEqual(
$button.text(),
'(checkuser-tempaccount-reveal-ip-button-label)',
'Button text'
);
const expectedClasses = [
'ext-checkuser-tempaccount-reveal-ip-button',
'oo-ui-flaggedElement-progressive',
'oo-ui-buttonElement'
];
expectedClasses.forEach( ( className ) => {
assert.strictEqual(
// eslint-disable-next-line no-jquery/no-class-state
$button.hasClass( className ),
true,
'Button has ' + className + ' class'
);
} );
} );
QUnit.test( 'Test makeButton creates expected button for blocked performer', ( assert ) => {
mw.config.set( 'wgCheckUserIsPerformerBlocked', true );
const elements = ipReveal.makeButton( tempName1, { targetId: 1, allIds: [ 1 ] }, {} );
const [ $button, $blockInfoWidget ] = elements;
assert.strictEqual(
elements.length,
2,
'Both an IP reveal button and a block details button should be returned for non-blocked users'
);
// Verify that the button has the expected button text and classes
assert.strictEqual(
$button.text(),
'(checkuser-tempaccount-reveal-ip-button-label)',
'Button text'
);
assert.strictEqual(
$blockInfoWidget.find( '[role=button]' ).attr( 'title' ),
'(checkuser-tempaccount-reveal-blocked-title)',
'Block info widget title'
);
} );
function performMakeButtonRequestTest( assert, responseCode, responseContent, expectedText ) {
// We need the test to wait a small amount of time for the click events to finish.
const done = assert.async();
server.respond( ( request ) => {
request.respond( responseCode, { 'Content-Type': 'application/json' }, responseContent );
} );
// Call the method under test to get a button
const $button = ipReveal.makeButton( tempName1, { targetId: 1, allIds: [ 1 ] }, {} );
// Add the button to the QUnit fixture
// eslint-disable-next-line no-jquery/no-global-selector
const $qunitFixture = $( '#qunit-fixture' );
$qunitFixture.append( $button );
// Click the button
$( '.ext-checkuser-tempaccount-reveal-ip-button a', $qunitFixture )[ 0 ].click();
waitUntilElementDisappears( '.ext-checkuser-tempaccount-reveal-ip-button' ).then( () => {
// Verify that the button has gone and was replaced with a span containing an error message
assert.strictEqual(
$( '.ext-checkuser-tempaccount-reveal-ip-button', $qunitFixture ).length,
0,
'Button removed after click'
);
assert.strictEqual(
$( '.ext-checkuser-tempaccount-reveal-ip', $qunitFixture ).text(),
expectedText,
'Text of element that replaced button'
);
done();
} );
}
QUnit.test( 'Test makeButton on button click for failed request', ( assert ) => {
performMakeButtonRequestTest( assert, 500, '', '(checkuser-tempaccount-reveal-ip-error)' );
} );
QUnit.test( 'Test makeButton on button click for successful request but missing data', ( assert ) => {
performMakeButtonRequestTest(
assert,
200,
JSON.stringify( {
[ tempName1 ]: {
revIps: {
// The API returns the revIds as strings.
// null indicates the IP is missing from the DB (i.e. that
// it was never there in the first place).
// eslint-disable-next-line quote-props
'1': null
},
logIps: null,
lastUsedIp: null
},
autoReveal: false
} ),
'(checkuser-tempaccount-reveal-ip-missing)'
);
} );
QUnit.test( 'Test makeButton on button click for successful request but expired data', ( assert ) => {
performMakeButtonRequestTest(
assert,
200,
JSON.stringify( {
[ tempName1 ]: {
revIps: {
// The API returns the revIds as strings.
// Having the key missing here indicates that the data has
// expired.
},
logIps: null,
lastUsedIp: null
},
autoReveal: false
} ),
'(checkuser-tempaccount-reveal-ip-expired)'
);
} );
QUnit.test( 'Test makeButton on button click for successful request with data', ( assert ) => {
performMakeButtonRequestTest(
assert,
200,
JSON.stringify( {
[ tempName1 ]: {
revIps: {
// The API returns the revIds as strings
// eslint-disable-next-line quote-props
'1': '127.0.0.1'
},
logIps: null,
lastUsedIp: null
},
autoReveal: false
} ),
'127.0.0.1'
);
} );
QUnit.test( 'Test enableAutoReveal replaces buttons with IPs', function ( assert ) {
const done = assert.async();
server.respond( ( request ) => {
const response = {};
response[ tempName1 ] = { revIps: { 1: '127.0.0.1', 2: '127.0.0.1' }, logIps: null, lastUsedIp: null };
response[ tempName2 ] = { revIps: { 3: '127.0.0.1' }, logIps: null, lastUsedIp: null };
request.respond(
200,
{ 'Content-Type': 'application/json' },
JSON.stringify( response )
);
} );
// eslint-disable-next-line no-jquery/no-global-selector
const $qunitFixture = $( '#qunit-fixture' );
// Add some revision lines with temporary account links
const revisionLines = { 1: tempName1, 2: tempName1, 3: tempName2 };
Object.entries( revisionLines ).forEach( ( [ revId, username ] ) => {
const $revisionLine = $( '
' ).attr( 'data-mw-revid', revId );
$qunitFixture.append( $revisionLine );
const $tempAccountUserLink = makeTempUserLink( username );
$revisionLine.append( $tempAccountUserLink );
$revisionLine.append( ipReveal.makeButton(
username,
{ targetId: revId, allIds: [ revId ] },
{},
$qunitFixture
) );
} );
// Check that auto-reveal mode is switched on
const expiry = Math.round( Date.now() / 1000 ) + 3600;
const utilsMock = this.sandbox.mock( ipRevealUtils );
utilsMock.expects( 'setAutoRevealStatus' )
.once()
.withArgs( expiry )
.returns( $.Deferred().resolve() );
// Enable multi-reveal and switch on auto-reveal mode
ipReveal.enableAutoReveal( expiry, $qunitFixture );
// Check all IPs are revealed
waitUntilElementDisappears( '.ext-checkuser-tempaccount-reveal-ip-button' ).then( () => {
assert.strictEqual(
$( '.ext-checkuser-tempaccount-reveal-ip-button', $qunitFixture ).length,
0,
'IP reveal buttons removed'
);
assert.strictEqual(
$( '.ext-checkuser-tempaccount-reveal-ip', $qunitFixture ).length,
3,
'Revealed IPs added'
);
done();
} );
} );
QUnit.test( 'Test disableAutoReveal replaces IPs with buttons', function ( assert ) {
const done = assert.async();
// eslint-disable-next-line no-jquery/no-global-selector
const $qunitFixture = $( '#qunit-fixture' );
// Add some revision lines with revealed IPs
const revisionLines = { 1: tempName1, 2: tempName1, 3: tempName2 };
Object.entries( revisionLines ).forEach( ( [ revId, username ] ) => {
const $revisionLine = $( '