gplx/mediawiki/tests/jest/mediawiki.special.block/SpecialBlock.setup.js

358 lines
8.5 KiB
JavaScript

'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();
// 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( {
wgFormattedNamespaces: {
0: '(Main)',
1: 'Talk',
2: 'User',
3: 'User talk'
},
wgUserLanguage: 'en',
blockAlreadyBlocked: false,
blockTargetUser: null,
blockAdditionalDetailsPreset: [ 'wpAutoBlock' ],
blockAllowsEmailBan: true,
blockAllowsUTEdit: true,
blockAutoblockExpiry: '1 day',
blockDetailsPreset: [],
blockExpiryDefault: '',
blockExpiryPreset: null,
blockHideUser: true,
blockExpiryOptions: {
infinite: 'infinite',
'31 horas': '31 hours'
},
blockNamespaceRestrictions: '',
blockPageRestrictions: '',
blockPreErrors: [],
blockReasonOptions: [
{ label: 'block-reason-1', value: 'block-reason-1' },
{ label: 'block-reason-2', value: 'block-reason-2' }
],
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 TargetBlockLog
{
params: {
list: 'logevents',
letype: 'block',
letitle: 'User:ExampleUser'
},
response: {
query: {
logevents: [
{
logid: 980,
title: 'User:ExampleUser',
params: {
duration: '1 year',
flags: [
'noautoblock'
],
sitewide: true,
expiry: '2029-09-17T14:30:51Z'
},
type: 'block',
user: 'Admin',
timestamp: '2024-09-17T14:30:51Z',
comment: 'A reason'
}
]
}
}
},
{
params: {
list: 'logevents',
letype: 'block',
letitle: 'User:NeverBlocked'
},
response: {
query: {
logevents: []
}
}
},
{
params: {
list: 'logevents',
letype: 'block',
letitle: 'User:BlockedALot'
},
response: {
continue: {
lecontinue: '20240909144407|979',
continue: '-||'
},
query: {
logevents: [
{
logid: 980,
title: 'User:BlockedALot',
params: {
duration: '1 year',
flags: [
'noautoblock'
],
sitewide: true,
expiry: '2029-09-17T14:30:51Z'
},
type: 'block',
user: 'Admin',
timestamp: '2024-09-17T14:30:51Z',
comment: 'A reason'
},
{
logid: 981,
title: 'User:BlockedALot',
params: {
duration: '1 year',
flags: [
'noautoblock'
],
sitewide: true,
expiry: '2029-09-18T14:30:51Z'
},
type: 'block',
user: 'Admin',
timestamp: '2024-09-18T14:30:51Z',
comment: 'A reason'
},
{
logid: 982,
title: 'User:BlockedALot',
params: {
duration: '1 year',
flags: [
'noautoblock'
],
sitewide: true,
expiry: '2029-09-19T14:30:51Z'
},
type: 'block',
user: 'Admin',
timestamp: '2024-09-19T14:30:51Z',
comment: 'A reason'
},
{
logid: 983,
title: 'User:BlockedALot',
params: {
duration: '1 year',
flags: [
'noautoblock'
],
sitewide: true,
expiry: '2029-09-20T14:30:51Z'
},
type: 'block',
user: 'Admin',
timestamp: '2024-09-20T14:30:51Z',
comment: 'A reason'
},
{
logid: 984,
title: 'User:BlockedALot',
params: {
duration: '1 year',
flags: [
'noautoblock'
],
sitewide: true,
expiry: '2029-09-21T14:30:51Z'
},
type: 'block',
user: 'Admin',
timestamp: '2024-09-21T14:30:51Z',
comment: 'A reason'
},
{
logid: 985,
title: 'User:BlockedALot',
params: {
duration: '1 year',
flags: [
'noautoblock'
],
sitewide: true,
expiry: '2029-09-22T14:30:51Z'
},
type: 'block',
user: 'Admin',
timestamp: '2024-09-22T14:30:51Z',
comment: 'A reason'
},
{
logid: 986,
title: 'User:BlockedALot',
params: {
duration: '1 year',
flags: [
'noautoblock'
],
sitewide: true,
expiry: '2029-09-23T14:30:51Z'
},
type: 'block',
user: 'Admin',
timestamp: '2024-09-23T14:30:51Z',
comment: 'A reason'
},
{
logid: 987,
title: 'User:BlockedALot',
params: {
duration: '1 year',
flags: [
'noautoblock'
],
sitewide: true,
expiry: '2029-09-24T14:30:51Z'
},
type: 'block',
user: 'Admin',
timestamp: '2024-09-24T14:30:51Z',
comment: 'A reason'
},
{
logid: 988,
title: 'User:BlockedALot',
params: {
duration: '1 year',
flags: [
'noautoblock'
],
sitewide: true,
expiry: '2029-09-25T14:30:51Z'
},
type: 'block',
user: 'Admin',
timestamp: '2024-09-25T14:30:51Z',
comment: 'A reason'
},
{
logid: 989,
title: 'User:BlockedALot',
params: {
duration: '1 year',
flags: [
'noautoblock'
],
sitewide: true,
expiry: '2029-09-26T14:30:51Z'
},
type: 'block',
user: 'Admin',
timestamp: '2024-09-26T14:30:51Z',
comment: 'A reason'
}
]
}
}
},
// Used in UserLookup
{
params: {
list: 'allusers'
},
response: {
query: {
allusers: [
{ name: 'UserLookup1' },
{ name: 'UserLookup2' }
]
}
}
},
// 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 );
} );
}
module.exports = {
getSpecialBlock,
mockMwApiGet,
mockMwConfigGet
};