aboutsummaryrefslogtreecommitdiffstats
path: root/tests/jest
Commit message (Collapse)AuthorAgeFilesLines
...
* SpecialBlock.vue: keep track of promises in the store, add loading stateMusikAnimal2024-11-263-13/+36
| | | | | | | | | | | | | | | | | | Introduce pushPromise() and a local promises ref to the store. This keeps track of UI-blocking API requests, ensuring the form is disabled while the requests are awaiting response. This is meant to be reminiscent of OOUI's pushPending(). A native JavaScript Set is used to ensure uniqueness and without the need to name the promises. BlockLog is reworked to use the getBlockLogData() from the store so that we get the block log and active blocks in the same API request. The promise is cached locally to ensure there are no duplicate requests across BlockLog instances. Remove ref from `details` as it is not exported or meant to be mutable. Bug: T380437 Change-Id: I9c018f85c4ccdf5aa75a3fb24c7363e62d33f938
* SpecialBlock [Codex]: use confirmation dialog instead of checkboxMusikAnimal2024-11-204-38/+62
| | | | | | | | | | | | | | | | | | | | | | Add a reusable ConfirmationDialog, akin to OO.ui.confirm(). A local prop to track the 'open' state is required, but otherwise you only need to provide 'title', the content (the only slot), and what to do on confirmation via the 'confirm' event. SpecialBlock.vue – where form submission is handled – is responsible for opening this dialog, while the store has a watcher to set the confirmationMessage ref. TODOs are left to further abstract ConfirmationDialog and other eligible components for general use in MediaWiki (T375220). Simplify some components by putting the formSubmitted prop into the store. Update tests and use toStrictEqual() instead of toBe(), following the same convention of strict equality comparisons used in JS and QUnit tests. Bug: T376754 Change-Id: I73d4fecb7f91e565a9029311c6d5cd9cfe7ab230
* Merge "SpecialBlock: Update window URL when changing target, without reload"jenkins-bot2024-11-191-1/+1
|\
| * SpecialBlock: Update window URL when changing target, without reloadSam Wilson2024-11-191-1/+1
| | | | | | | | | | | | | | | | Use History.replaceState() to rewrite the window's URL when the block target is changed. Bug: T379877 Change-Id: I697ce72f8a4af9a034e5036d9d2a330a3d68906e
* | SpecialBlock: Separate API requests for suppress block and reblockSam Wilson2024-11-192-0/+88
|/ | | | | | | | Separate out the two API requests for suppress/block and suppress/reblock log events, so that their combined count can be used for the max displayed. Bug: T377725 Change-Id: Id11ead96ae75c147dfe2a7154dea5b0335c9f807
* SpecialBlock [Codex]: Reset form after saving blockMusikAnimal2024-11-162-2/+7
| | | | | | | | | | | | | | Reset fields after saving block. Leave target field populated so that block logs are loaded and newly created block can be displayed. Rework ExpiryField's setDurationFormat() to initially run via the watcher of the store's expiry, and ensure validations are only ran on form submission. Update tests against child components to call $reset directly. Bug: T379215 Change-Id: I3df4a155c6d82a66a8e3a52792d94329cc1eb1e4
* ExpiryField.vue: react to changes to the store's expiryMusikAnimal2024-11-152-4/+20
| | | | | | | | | | | | | | | | The reactivity to expiry changes was broken in Id6cff21eee. Now that the expiry is in the store, listen to it and react accordingly, and gaurd against circular reactivity by ensuring the new value is different. Change setDurationFromGiven() to handle blank values. Add test and remove setting of modelValue (which is a relic from before Id6cff21eee). Fix test that incorrectly was setting the datetime input with seconds, which the browser does not accept. Change-Id: Iec8ec431185a77235f458516cce3c11e7e8eb9b6
* SpecialBlock [Codex]: only supply reblock parameter when trueMusikAnimal2024-11-132-1/+24
| | | | | | | | | | | The Action API's boolean type treats the presence of a parameter as true. This patch fixes the behaviour by only passing in the 'reblock' key when the alreadyBlocked prop is set. In doing so, block conflict detection now works as expected. Update tests accordingly. Change-Id: If180226a84849d6f9fd257050893334fe38e623a
* SpecialBlock: Fix logic of showing User_talk editing block optionSam Wilson2024-11-041-7/+8
| | | | | | | | Rather than hiding the 'Editing their own talk page' checkbox when a partial block includes the User_talk namespace, show it. Bug: T377722 Change-Id: Ib8fd6e449d3cb79584d1c0c7d205ef290c184fec
* SpecialBlock: Unify block log accordionsSam Wilson2024-10-312-7/+8
| | | | | | | | | | Merge the TargetBlockLog and TargetActiveBlocks components in to a single BlockLog component that can handle the various differences in the way each type should work. This will make it easier to next add the surppress log accordion as well. Bug: T377725 Change-Id: I237844a35f65beda896c4ba88653e6ad5fc9bc57
* SpecialBlock: Hide user talk checkbox when not applicableSam Wilson2024-10-292-0/+23
| | | | | | | | Hide the disableUTEdit checkbox when the block is partial and it includes blocking the User_talk namespace. Bug: T377722 Change-Id: Ie92d682b9f01124edf1d7be1cefe81d48e99e0fc
* Merge "SpecialBlock [Vue]: sync target user selection and make input clearable"jenkins-bot2024-10-281-4/+8
|\
| * SpecialBlock [Vue]: sync target user selection and make input clearableMusikAnimal2024-10-221-4/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | Rework the TargetBlockLog component to use the Composition API and the Pinia store. Update Pinia store on selection changes. Add the 'clearable' option to the Lookup component, allowing the user to "reset" things that listen to the target user field, such as the block log. Also hide table headings if there are no results. Bug: T377707 Change-Id: Ia3745ffe858152c6152b1d3b37c6d19d9fb4b712
* | SpecialBlock: Move additional options to their own componentSam Wilson2024-10-253-13/+34
| | | | | | | | | | | | | | | | | | | | | | | | | | Move the four additional block options to their own component (called AdditionalDetailsField), so we can have easier control over displaying them etc. All the logic for showing or hiding is moved to the block store. The existing BlockDetailsOptions component can be changed in a separate patch to only handle the block details. Bug: T377509 Change-Id: I2b4c7eaeded68435df04faf1df915572948ffae8
* | mediawiki.special.block: "Editing their own talk page" is invertedhmonroy2024-10-211-0/+1
|/ | | | | | | | 'allowusertalk' should be set in the block API call when the "Editing their own talk page" is NOT checked. Bug: T376924 Change-Id: I19bab1e4dd6172e3d43c4bbda50765a173f6bcf0
* SpecialBlock [Vue]: add NamespacesField and PagesField componentsMusikAnimal2024-10-161-0/+8
| | | | | | | | | | | | | | | These use the new CdxMultiselectLookup component. Values for the two inputs can be pre-filled with the 'wpPageRestrictions' and 'wpNamespaceRestrictions' URL parameters. Tests to be added in a future patch (along with other tests around partial blocks). Bug: T362718 Bug: T362912 Bug: T368583 Change-Id: I53739bcdd63870fbfb57bc96298fc8d467bdfc2b
* SpecialBlock [Vue]: require confirmation for hidehuser and self blocksMusikAnimal2024-10-162-10/+97
| | | | | | | | | | | | | | | | | | Special:Block is supposed to show a 'Confirm block' checkbox under two conditions: if the 'hide username' option is being used, or if the user is blocking themselves. This patch takes the SPA-like behaviour a step further and will disable the submit button and show the confirmation checkbox if the user target is changed to the current user, or if the 'Hide username' checkbox is checked. The logic of hiding the confirm checkbox and re-enabling the submit button should follow the same rules. Add `withSubmission()` helper to SpecialBlock.test.js and add test cases for the newly added code. Bug: T376754 Change-Id: Ie990051ae62b11f3a27bbc4cfc5c714a0096e2f3
* SpecialBlock [Vue]: add Pinia store for state managementMusikAnimal2024-10-164-6/+20
| | | | | | | | | | | | | | | | | | | | | | | Add a 'block' Pinia store to house all block-related data use in the SpecialBlock.vue application. Minimal refactoring is done to make use of the store, rather than passing around props. UserLookup is reworked to only update the store's targetUser property on a 'change' event, since the Codex Lookup component wants a "selection" while we want to allow arbitrary input. This means anything that listens to changes to the targetUser isn't fired off too quickly (i.e. API requests, or flashing error states). Other changes: * Remove 'disabled' attribute from ExpiryField as the disabled state is applied automatically. * Change SpecialBlock.test.js to test against a date that's not a mere decade away. Bug: T376741 Depends-On: Ia88d987bf7e5afa1a17d63b4ebc96448ccec2f6c Change-Id: Id6cff21eeeeb86876e59f70994ad10658ab6d9be
* Merge "SpecialBlock.setup.js: mock blockTypePreset to prevent Vue warnings"jenkins-bot2024-10-111-1/+2
|\
| * SpecialBlock.setup.js: mock blockTypePreset to prevent Vue warningsMusikAnimal2024-10-101-1/+2
| | | | | | | | Change-Id: Ibdbb04ef23ed1ad1a4d2a33facb721998eb74e93
* | mediawiki.special.block: Add "See full log" linkTheresNoTime2024-10-102-1/+190
|/ | | | | | | | Add a "See full log" link to TargetBlockLog Add Jest test to TargetBlockLog Bug: T376742 Change-Id: Ibf1ef088c23fa67c1710ea037cc5838977113007
* mediawiki.special.block: Modify TargetBlockLog behaviourTheresNoTime2024-10-102-1/+49
| | | | | | | | | Remove the "target" column Add a column "type" with fields "Blocked"/"Unblocked" Add Jest test for TargetBlockLog Bug: T368111 Change-Id: I3e9145df62046baaa3fe762a6f57c932a976508c
* ExpiryField.vue: fix preselection of expiry field and add testsMusikAnimal2024-10-082-3/+97
| | | | | | | | | | | | | | | | | With this change, the ?wpExpiry query param and the interface message [[MediaWiki:Ipb-default-expiry]] accept only the following formats: * /\d+ [a-z]+s?/ – such as "1 month", "2 weeks", etc. * infinity values: 'infinite', 'indefinite', 'infinity', 'never' * ISO 8601-like datestamp In addition, [[MediaWiki:Ipboptions]] now requires an option be preset with the value 'infinite'. Rename `blockDefaultExpiry` to `blockExpiryDefault` for consistency. Bug: T368583 Change-Id: Ibc648117e6d4981c84e9df9f933ba033d339e908
* mediawiki.special.block [Vue]: add form validations and error statesMusikAnimal2024-10-033-13/+72
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | We leverage the native browser validations for most fields (i.e. `required` attribute on TextInputs). After form submission, the user is brought to the erroneous field and given browser-provided validation messages, displayed using Codex. Browser validation may later be upstreamed to Codex (T373872), after which we won't need ValidatingTextInput, or the custom handling in UserLookup. ExpiryField was written prior to CdxRadio supporting a custom-input slot. Rework the CdxRadios in ExpiryField to use the new slot, and apply `status` and `messages` to the nested CdxField instead of the entire ExpiryField, so that validation states are applied only to the invalid elements. For now, there is only one other custom validation that cannot be provided by the browser: requiring a selection for "Preset duration". Validation logic is contained within ExpiryField, but since this field doesn't effect `checkValidity()`, we need to check the expiry value in SpecialBlock.vue on form submission. This is necessary since we don't to show error states when the component is first mounted. Also make tests a bit more DRY by adding a new `getSpecialBlock()` method to the setup file. Bug: T369471 Change-Id: Iff340e8747329678b80ca00c768fabec2c194320
* mediawiki.special.block: Set reblock in API call if already blockedTheresNoTime2024-10-011-0/+1
| | | | | | | | Use `alreadyBlocked.value` to conditionally set `reblock` param in API call. Bug: T358934 Change-Id: Idf9deb35557d25714abb8af239c2c54a77b6cf7f
* mediawiki.special.block [Vue]: surface server-side msgs + loading stateMusikAnimal2024-10-012-10/+24
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | This adds a new message box for successful messages, and reworks the old one to handle all error messages. Error messages are inline for now (like the old Special:Block). Note these are only the server-side messages, that chiefly serve as a fallback for clientside error states which will be tackled in a future patch. A loading state is added for the block API request by simply disabling the form fields. Once completed, the user is scrolled to the top to view the appropriate messaging. This uses "smooth" scrolling so that it's a bit less "in your face", but this is subject to design review. For now, it's just important the user is brought to the approriate error message. Other changes: * Add a bit of left margin to the inline error message, consistent with the no-JS version of this page. Without this, things "jump" a bit as the Vue applicaton loads. More refinements for this to come later. * Fix styles for .mw-block-partial-options to be exactly the same as Codex labels. * Remove unnecessary IIFE from init.js, and add a class to the form so we can style it closer to the designs. Bug: T369471 Bug: T358934 Change-Id: I47344e9581439289642c9424a5f229929805cdbe
* mediawiki.special.block [Vue]: fix form submission and add testsMusikAnimal2024-09-293-36/+123
| | | | | | | | | | | | | | | | | Add a blockType v-model to BlockTypeField, and use that to determine if we are placing a partial or sitewide block. Also set the default to be 'sitewide'. Give ExpiryField datetime input the form name `wpExpiry-other` to match current Special:Block. Introduce mockMwApiGet() to the test suite which provides mocks for the known API calls, and warns about those that aren't. Additional mocks or overrides can be provided per-test as needed. This system hopefully will help make the Jest suite more robust with realistic data to work with. Bug: T358934 Change-Id: I5e1baaeb4dc9ae8ef9fcb44513b1c6a675eb94d1
* UserLookup.vue [Special:Block]: bind input-value and selected separatelyMusikAnimal2024-09-291-12/+18
| | | | | | | | | | | Other changes: * Emit update:modelValue so the parent component has the new value * Abort any pending API requests when user input changes * Adjust test to use the more appropriate flushPromises() instead of nextTick(), and utilize beforeAll() hook. Follow-Up: Iceaedbb1e3496c52b49a2b96d65445da45261b9f Change-Id: I943767f8814134c1d53a34e3bcb883c0e982d782
* TargetActiveBlocks/TargetBlockLog: Populate table components with blocksTheresNoTime2024-09-251-0/+23
| | | | | | | | | | Add TargetActiveBlocks/TargetBlockLog tables to Special:Block. Hide TargetActiveBlocks behind `blockEnableMultiblocks` flag. Add util.js for common function(s) Bug: T368062 Bug: T368111 Change-Id: Id4783c042cbf14a0de89a27f474cebbd102dff18
* mediawiki.special.block: make submit destructive and use old messagesMusikAnimal2024-09-184-23/+81
| | | | | | | | | | | | | | | | | | | | | SpecialBlock calls HTMLForm::setSubmitDestructive(). This patch applies that to the new Vue version of Special:Block. Additionally, since we're not going to enable multiblocks in the initial launch, the submit button message is changed to as it was before. "Save block" is questionable even for multiblocks. It will likely be a while before we iron out the UI for multiblocks, so we might as well remove now-unused 'block-save' message. The "[username] is already blocked" message is now also surfaced, i.e. browsing to [[Special:Block/someblockuser]]. Like the old Special:Block, changes to the block target field won't re-query to see if the user is already blocked (though that would be a fine improvement). However *unlike* the old Special:Block, such changes do make the message disappear. Bug: T373572 Change-Id: Iceaedbb1e3496c52b49a2b96d65445da45261b9f
* mediawiki.special.block: add reason fieldhmonroy2024-09-111-3/+7
| | | | | | | | | | | | | | | Add Html::listDropdownOptionsCodex() that takes a bulleted list like [[MediaWiki:Ipbreason-dropdown]] and adapts the data struture for use with a Codex Select component. Currently optgroups are not supported (T367241) so we show the optgroup labels as disabled options instead. URL query string parameters do not yet prefill any fields. This will be tackled as part of T368583. Bug: T362912 Change-Id: Ib89dcf35ca2a1cd74404c42f5411d7c095b98952
* Add Jest to MW Core for testing Vue componentsEric Gardner2024-09-114-0/+332
This brings Jest to MW Core so that Vue components can more easily be tested. Packages ending with 'icons.json' are auto-mapped to the @wikimedia/codex-icons package, establishing a new convention. Jest is needed for testing Vue, but can be used for general JS testing as well. Documentation to come at https://www.mediawiki.org/wiki/Jest Usage: to run the tests, run "npx jest" or "npm run jest" in the root folder. This could be aliased to a "test:unit" script in package.json if desired. In order to make a Vue component testable, it is required to follow the `module.exports = exports` pattern. See: https://nodejs.org/api/modules.html#exports-shortcut A default jest.setup.js is added that mocks Core's mw global object, as well as providing the $i18n Vue plugin. This is based on Extension:GrowthExperiments (GPL-3.0-or-later). See https://w.wiki/B9vM An initial test for mediawiki.special.block is added, exemplifying how to mock calls to mw.config.get(). NOTE: The "overrides" added to package.json is a temporary measure to get around a current issue with caniuse-lite and the stylelint plugin that relies on it. See: https://github.com/RJWadley/stylelint-no-unsupported-browser-features/issues/299 Bug: T251790 Change-Id: I1af15e038d17b0f1c645fc5debf9db5846f6215c