Page MenuHomeWickedGov Phorge

SpecialBlock.setup.js
No OneTemporary

Size
18 KB
Referenced Files
None
Subscribers
None

SpecialBlock.setup.js

'use strict';
const { mount, VueWrapper } = require( '@vue/test-utils' );
const { createTestingPinia } = require( '@pinia/testing' );
const SpecialBlock = require( '../../../resources/src/mediawiki.special.block/SpecialBlock.vue' );
/**
* Mount the SpecialBlock component with the default configuration,
* wrapping it in a form element and appending it to the document body.
* This is needed because the <form> element is created server-side.
*
* @param {Object} [config] Configuration to override the defaults.
* @param {Array<Object>} [apiMocks] Additional API mocks to add to the default list.
* @return {VueWrapper} The mounted component.
*/
function getSpecialBlock( config = {}, apiMocks = [] ) {
// Other various mocks that may be needed across the test suite.
HTMLElement.prototype.scrollIntoView = jest.fn();
mw.confirmCloseWindow = jest.fn();
// Mock calls to mw.config.get() and mw.Api.prototype.get().
mockMwConfigGet( config );
mockMwApiGet( apiMocks );
// Create a form element and append it to the document body.
const form = document.createElement( 'form' );
document.body.appendChild( form );
// Mount the SpecialBlock component inside the form element.
return mount( SpecialBlock, {
global: {
plugins: [ createTestingPinia( { stubActions: false } ) ]
},
attachTo: form
} );
}
/**
* Mock calls to mw.config.get().
* The default implementation correlates to the SpecialBlock::codexFormData property in PHP.
*
* @param {Object} [config] Will be merged with the defaults.
*/
function mockMwConfigGet( config = {} ) {
const mockConfig = Object.assign( {
blockEnableMultiblocks: true,
blockId: null,
wgNamespaceIds: {
'': '(Main)',
talk: 'Talk',
user: 'User',
// eslint-disable-next-line camelcase
user_talk: 3
},
wgFormattedNamespaces: {
0: '',
1: 'Talk',
2: 'User',
3: 'User talk'
},
wgPageName: 'Special:Block',
wgUserLanguage: 'en',
blockAlreadyBlocked: false,
blockTargetUser: null,
blockTargetExists: null,
blockAdditionalDetailsPreset: [ 'wpAutoBlock' ],
blockAllowsEmailBan: true,
blockAllowsUTEdit: true,
blockAutoblockExpiry: '1 day',
blockCanEditInterface: false,
blockDetailsPreset: [ 'wpCreateAccount' ],
blockExpiryDefault: '',
blockExpiryPreset: null,
blockHideUser: true,
blockExpiryOptions: {
infinite: 'infinite',
'31 horas': '31 hours'
},
blockNamespaceRestrictions: '',
blockPageRestrictions: '',
blockPreErrors: [],
blockReasonMaxLength: 500,
blockReasonOptions: [
{ label: 'Other', value: 'other' },
{
label: 'Common block reasons',
items: [
{ label: 'Vandalism', value: 'Vandalism' },
{ label: 'Spam', value: 'Spam' },
{ label: 'Disruptive editing', value: 'Disruptive editing' }
]
},
{
label: 'Templated reasons',
items: [
{ label: '{{anonblock}}', value: '{{anonblock}}' },
{ label: '{{schoolblock}}', value: '{{schoolblock}}' },
{ label: '{{sockpuppet}}', value: '{{sockpuppet}}' }
]
}
],
blockReasonPreset: '',
blockSuccessMsg: '[[Special:Contributions/ExampleUser|ExampleUser]] has been blocked.',
blockTypePreset: 'sitewide'
}, config );
mw.config.get.mockImplementation( ( key ) => mockConfig[ key ] );
}
/**
* Mock calls to mw.Api.prototype.get() based on given parameters and response.
* The default implementation mocks API GET requests used across the test suite.
*
* @param {Array<Object>} [additionalMocks] Additional mocks to add to the default list.
* Each object should contain the keys `params` and `response`.
* `params` is an Object with sufficient set of parameters to identify the request
* (e.g. `{ list: 'logevents', letype: 'block' }`). The `response` is an Object
* with the expected response data (e.g. `{ query: { logevents: [ ... ] } }`).
*/
function mockMwApiGet( additionalMocks = [] ) {
/**
* This is intended to encapsulate any API requests that
* consistently need to be mocked across the test suite.
*
* @type {Object}
*/
const mocks = [
// Used in BlockLog
{
params: {
list: 'logevents|blocks',
letype: 'block',
letitle: 'User:ExampleUser'
},
response: {
query: {
logevents: [
{
logid: 980,
title: 'User:ExampleUser',
params: {
duration: '1 year',
'duration-l10n': '1 year',
flags: [
'noautoblock'
],
sitewide: true,
expiry: '2029-09-17T14:30:51Z'
},
type: 'block',
user: 'Admin',
timestamp: '2024-09-17T14:30:51Z',
parsedcomment: 'A reason'
}
],
blocks: []
}
}
},
{
params: {
list: 'logevents|blocks',
letype: 'block',
letitle: 'User:ActiveBlockedUser',
bkusers: 'ActiveBlockedUser'
},
response: {
query: {
logevents: [
{
logid: 980,
title: 'User:ActiveBlockedUser',
params: {
duration: '100 years',
'duration-l10n': '100 years',
flags: [
'noautoblock'
],
sitewide: true,
expiry: '2124-09-17T14:30:51Z'
},
type: 'block',
user: 'Admin',
timestamp: '2024-09-17T14:30:51Z',
parsedcomment: 'A reason'
}
],
blocks: [
{
id: 1110,
user: 'ActiveBlockedUser',
timestamp: '2024-09-17T14:30:51Z',
expiry: '2124-09-17T14:30:51Z',
'duration-l10n': '100 years',
by: 'Admin',
anononly: false,
nocreate: false,
autoblock: false,
noemail: true,
allowusertalk: false,
hidden: true,
reason: 'Spamming talk page',
parsedreason: 'Spamming talk page',
restrictions: []
},
{
id: 1116,
user: 'ActiveBlockedUser',
timestamp: '2024-09-17T14:30:51Z',
expiry: '2029-09-17T14:30:51Z',
'duration-l10n': '5 years',
by: 'Admin',
anononly: false,
nocreate: false,
autoblock: false,
noemail: true,
allowusertalk: false,
hidden: true,
reason: 'Spamming talk page',
parsedreason: 'Spamming talk page',
restrictions: []
},
{
id: 1120,
user: 'ActiveBlockedUser',
timestamp: '2024-09-17T14:30:51Z',
expiry: '2029-09-17T14:30:51Z',
'duration-l10n': '5 years',
by: 'Admin',
anononly: false,
nocreate: false,
autoblock: false,
noemail: true,
allowusertalk: false,
hidden: true,
reason: 'Spamming talk page',
parsedreason: 'Spamming talk page',
restrictions: []
}
]
}
}
},
{
params: {
list: 'logevents|blocks',
letype: 'block',
letitle: 'User:NeverBlocked'
},
response: {
query: {
logevents: [],
blocks: []
}
}
},
{
params: {
list: 'logevents|blocks',
letype: 'block',
letitle: 'User:BlockedALot'
},
response: {
continue: {
lecontinue: '20240909144407|979',
continue: '-||blocks'
},
query: {
logevents: [
// 5-year block
{
logid: 980,
title: 'User:BlockedALot',
params: {
duration: '5 years',
'duration-l10n': '5 years',
flags: [
'noautoblock'
],
sitewide: true,
expiry: '2029-09-17T14:30:51Z'
},
type: 'block',
action: 'block',
user: 'Admin',
timestamp: '2024-09-17T14:30:51Z',
parsedcomment: 'A reason'
},
// Unblock event
{
logid: 981,
title: 'User:BlockedALot',
params: { blockId: 999 },
type: 'block',
action: 'unblock',
user: 'Admin',
timestamp: '2024-09-18T14:30:51Z',
parsedcomment: 'A reason'
},
// Indefinite block
{
logid: 982,
title: 'User:BlockedALot',
params: {
duration: 'infinity',
'duration-l10n': 'infinite',
flags: [
'noautoblock'
],
sitewide: true,
expiry: '2029-09-19T14:30:51Z'
},
type: 'block',
action: 'block',
user: 'Admin',
timestamp: '2024-09-19T14:30:51Z',
parsedcomment: 'A reason'
},
// Block with datetime duration
{
logid: 983,
title: 'User:BlockedALot',
params: {
duration: '2029-09-20T14:31:51Z',
'duration-l10n': '5 years and 1 minute',
flags: [
'noautoblock'
],
sitewide: true,
expiry: '2029-09-20T14:31:51Z'
},
type: 'block',
action: 'block',
user: 'Admin',
timestamp: '2024-09-20T14:30:51Z',
parsedcomment: 'A reason'
},
// Reblock
{
logid: 984,
title: 'User:BlockedALot',
params: {
duration: '5 years',
'duration-l10n': '5 years',
flags: [
'noautoblock'
],
sitewide: true,
expiry: '2029-09-21T14:30:51Z'
},
type: 'block',
action: 'reblock',
user: 'Admin',
timestamp: '2024-09-21T14:30:51Z',
parsedcomment: 'A reason'
},
// Other mock blocks
{
logid: 985,
title: 'User:BlockedALot',
params: {
duration: '5 years',
'duration-l10n': '5 years',
flags: [
'noautoblock'
],
sitewide: true,
expiry: '2029-09-22T14:30:51Z'
},
type: 'block',
action: 'block',
user: 'Admin',
timestamp: '2024-09-22T14:30:51Z',
parsedcomment: 'A reason'
},
{
logid: 986,
title: 'User:BlockedALot',
params: {
duration: '5 years',
'duration-l10n': '5 years',
flags: [
'noautoblock'
],
sitewide: true,
expiry: '2029-09-23T14:30:51Z'
},
type: 'block',
action: 'block',
user: 'Admin',
timestamp: '2024-09-23T14:30:51Z',
parsedcomment: 'A reason'
},
{
logid: 987,
title: 'User:BlockedALot',
params: {
duration: '5 years',
'duration-l10n': '5 years',
flags: [
'noautoblock'
],
sitewide: true,
expiry: '2029-09-24T14:30:51Z'
},
type: 'block',
action: 'block',
user: 'Admin',
timestamp: '2024-09-24T14:30:51Z',
parsedcomment: 'A reason'
},
{
logid: 988,
title: 'User:BlockedALot',
params: {
duration: '5 years',
'duration-l10n': '5 years',
flags: [
'noautoblock'
],
sitewide: true,
expiry: '2029-09-25T14:30:51Z'
},
type: 'block',
action: 'block',
user: 'Admin',
timestamp: '2024-09-25T14:30:51Z',
parsedcomment: 'A reason'
},
{
logid: 989,
title: 'User:BlockedALot',
params: {
duration: '5 years',
'duration-l10n': '5 years',
flags: [
'noautoblock'
],
sitewide: true,
expiry: '2029-09-26T14:30:51Z'
},
type: 'block',
action: 'block',
user: 'Admin',
timestamp: '2024-09-26T14:30:51Z',
parsedcomment: 'A reason'
}
],
blocks: []
}
}
},
{
params: {
list: 'logevents|blocks',
letype: 'block',
letitle: 'User:BadNameBlocked'
},
response: {
query: {
logevents: [],
blocks: []
}
}
},
{
params: {
list: 'logevents|blocks',
letype: 'block',
letitle: 'User:NonexistentUser'
},
response: {
query: {
logevents: [],
blocks: []
}
}
},
{
params: {
list: 'logevents',
leaction: 'suppress/block',
letitle: 'User:BadNameBlocked'
},
response: {
query: {
logevents: [
{
logid: 1030,
ns: 2,
title: 'User:BadNameBlocked',
pageid: 583,
logpage: 583,
params: {
duration: 'infinity',
'duration-l10n': 'infinite',
flags: [ 'hiddenname' ],
sitewide: true
},
type: 'suppress',
action: 'block',
user: 'Admin',
timestamp: '2024-11-14T07:30:00Z',
comment: ''
}
]
}
}
},
{
params: {
list: 'logevents',
leaction: 'suppress/reblock',
letitle: 'User:BadNameBlocked'
},
response: {
query: {
logevents: [
{
logid: 1029,
ns: 2,
title: 'User:BadNameBlocked',
pageid: 583,
logpage: 583,
params: {
duration: 'infinity',
'duration-l10n': 'infinite',
flags: [ 'hiddenname' ],
sitewide: true
},
type: 'suppress',
action: 'block',
user: 'Admin',
timestamp: '2024-11-14T07:29:00Z',
comment: ''
},
{
logid: 1031,
ns: 2,
title: 'User:BadNameBlocked',
pageid: 583,
logpage: 583,
params: {
duration: 'infinity',
'duration-l10n': 'infinite',
flags: [ 'hiddenname' ],
sitewide: true
},
type: 'suppress',
action: 'block',
user: 'Admin',
timestamp: '2024-11-14T07:31:00Z',
comment: ''
}
]
}
}
},
{
params: {
list: 'logevents|blocks',
letype: 'block',
letitle: 'User:PartiallyBlockedUser'
},
response: {
query: {
blocks: [
{
id: 1111,
user: 'PartiallyBlockedUser',
by: 'Admin',
timestamp: '2024-09-17T14:30:51Z',
expiry: '2094-09-17T14:30:51Z',
'duration-l10n': '50 years',
reason: 'Vandalizing on [[Project:Foobar]]',
anononly: false,
nocreate: false,
autoblock: true,
noemail: false,
hidden: false,
allowusertalk: true,
partial: true,
restrictions: {
pages: [ {
id: 50,
ns: 4,
title: 'Foobar'
} ],
actions: [ 'upload', 'create' ]
}
}
],
logevents: [
{
logid: 990,
title: 'User:PartiallyBlockedUser',
params: {
duration: '50 years',
'duration-l10n': '50 years',
flags: [],
restrictions: {
pages: [ {
// eslint-disable-next-line camelcase
page_ns: 4,
// eslint-disable-next-line camelcase
page_title: 'Foobar'
} ],
actions: [ 'upload', 'create' ]
},
blockId: 1111,
sitewide: false,
expiry: '2094-09-17T14:30:51Z'
},
type: 'block',
action: 'block',
user: 'Admin',
timestamp: '2024-09-17T14:30:51Z',
parsedcomment: 'Vandalizing on [[Foobar]]'
}
]
}
}
},
// IP with range blocks (T389987)
{
params: {
list: 'logevents|blocks',
letype: 'block',
letitle: 'User:1.2.3.20'
},
response: {
query: {
blocks: [
{
id: 2000,
user: '1.2.3.20',
by: 'Admin',
timestamp: '2025-03-31T23:40:04Z',
expiry: '2025-04-03T23:40:04Z',
'duration-l10n': '3 days',
reason: 'Vandalism',
parsedreason: 'Vandalism',
automatic: false,
anononly: true,
nocreate: true,
autoblock: false,
noemail: false,
hidden: false,
allowusertalk: false,
partial: false,
restrictions: []
}, {
id: 2001,
user: '1.2.0.0/18',
by: 'Admin',
timestamp: '2025-03-31T23:24:54Z',
expiry: '2025-10-01T23:24:54Z',
'duration-l10n': '6 months',
reason: 'Spamming links to external sites',
parsedreason: 'Spamming links to external sites',
rangestart: '1.2.0.0',
rangeend: '1.2.63.255',
automatic: false,
anononly: true,
nocreate: true,
autoblock: false,
noemail: false,
hidden: false,
allowusertalk: true,
partial: false,
restrictions: []
}, {
id: 2002,
user: '1.2.3.20/30',
by: 'Admin',
timestamp: '2025-03-31T23:22:16Z',
expiry: '2027-03-01T23:22:16Z',
'duration-l10n': '1 year, 10 months and 29 days',
reason: 'Inserting false information',
parsedreason: 'Inserting false information',
rangestart: '1.2.3.20',
rangeend: '1.2.3.23',
automatic: false,
anononly: true,
nocreate: true,
autoblock: false,
noemail: false,
hidden: false,
allowusertalk: true,
partial: false,
restrictions: []
}
],
logevents: [
{
logid: 3000,
ns: 2,
title: 'User:1.2.3.20',
pageid: 0,
logpage: 0,
params: {
duration: '3 days',
flags: [
'anononly',
'nocreate',
'nousertalk'
],
blockId: 827,
sitewide: true,
expiry: '2025-04-03T23:40:04Z',
'duration-l10n': '3 days'
},
type: 'block',
action: 'block',
user: 'Admin',
timestamp: '2025-03-31T23:40:04Z',
parsedcomment: 'Unacceptable username'
}
]
}
}
},
{
params: {
list: 'logevents|blocks',
letype: 'block',
letitle: 'User:192.168.0.1'
},
response: {
query: {
blocks: [],
logevents: []
}
}
},
// Used in UserLookup
{
params: {
list: 'allusers',
auprefix: 'ExampleUser'
},
response: {
query: {
allusers: [
{ name: 'ExampleUser' },
{ name: 'ExampleUser2' }
]
}
}
},
{
params: {
list: 'allusers',
auprefix: 'ExampleUser2'
},
response: {
query: {
allusers: [
{ name: 'ExampleUser2' }
]
}
}
},
{
params: {
list: 'allusers',
auprefix: 'NonexistentUser'
},
response: {
query: {
allusers: []
}
}
},
// Add more mocks as needed above this line.
...additionalMocks
];
mw.Api.prototype.get.mockImplementation( ( params ) => {
if ( !params ) {
// eslint-disable-next-line no-console
console.warn( 'No params provided to mw.Api.get()' );
return Promise.resolve( jest.fn() );
}
// Find the appropriate mock from the list based on the expected parameters.
const mock = mocks.find( ( m ) => Object.entries( m.params )
.every( ( [ key, value ] ) => params[ key ] === value )
);
if ( !mock ) {
// eslint-disable-next-line no-console
console.warn( 'No mock found for:', params );
return Promise.resolve( jest.fn() );
}
return Promise.resolve( mock.response );
} );
}
mw.Title.makeTitle = jest.fn().mockReturnValue( {
getUrl: jest.fn()
} );
module.exports = {
getSpecialBlock,
mockMwApiGet,
mockMwConfigGet
};

File Metadata

Mime Type
text/plain
Expires
Tue, Aug 18, 23:38 (5 h, 28 m ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
e3/00/c4b9a65f2213fbb4b575fe370545
Default Alt Text
SpecialBlock.setup.js (18 KB)

Event Timeline