Vue.js/Testing

Vue.js encourages you to break up the elements of a UI into isolated components that are responsible for their own content and behavior. Additionally, these components rely on a virtual DOM and typically have little need for direct reliance on browser-specific APIs. UIs built with Vue.js are thus well-suited for unit-testing in a headless, Node.js-based environment. In many cases it is possible (and easy!) to test behaviors from the command-line that could previously only be captured in end-to-end, Selenium-style tests (clicks, key events, and other simulated user interactions).

This page is intended as a high-level guide for how to test Vue.js code in a MediaWiki environment. Many of the tools relied on here (Jest, vue-test-utils, etc.) have extensive documentation of their own which is worth studying as well.

Getting started
This guide will cover how to use Vue's official testing library with Jest in the context of a MediaWiki extension. Testing Vue code in Core should be similar but some adjustments may be needed.

Jest
Jest is a "batteries-included" test runner developed by Facebook. In addition to the  test runner itself, the software includes an expectation library and extensive mocking capabilities (there is no need to use Sinon alongside Jest, for example). Jest also sets up a JSDOM environment automatically.

One of the biggest advantages of using Jest with Vue is that it is possible to test single-file Vue components ( files) without relying on a bundling tool like Webpack, by using the   pre-processor. Since some teams will be shipping ES5 Vue components that don't rely on Webpack, this should help to reduce unnecessary complexity in test setup.

Vue Test Utils
Vue Test Utils is the official unit testing utility library for Vue.js. The project website contains extensive documentation (both API-level and a more narrative "guide").

Setup
You will need to add the following libraries to  as  :


 * (required if using without a build-step)
 * (required if using without a build-step)
 * (required if using without a build-step)
 * (required if using without a build-step)
 * (required if using without a build-step)
 * (required if using without a build-step)

A standard test script in  might look like this:

In addition to these libraries and some sort of testing script, you will need to add two top-level files:  (configuration properties) and   (code to be run before starting the test suite, to set up an appropriate environment).

Jest config file
This file defines Jest's configuration. Jest ships with reasonable defaults here, but there are couple of properties which are worth knowing about:

Vue-Jest configuration
The following properties should be added to get Jest to transform Vue single-file components:

Coverage
To generate Istanbul-style coverage reports, the following config properties are needed:

Specify setup file
See the next section for an example of how to use a setup file.

Jest setup file
Jest allows you to define a setup file which is run before the start of the entire test suite. This is useful for setting up a MediaWiki browser environment, where a lot of objects tend to be exposed in the global namespace. Your setup file can load real code or Jest mock functions as needed. The example below sets up jQuery, OOJS, and OOUI using NPM packages and then stubs out a global MW object with methods that may need to exist during testing:

Simulating a MediaWiki environment
By using a Jest setup file (see above) it is possible to fake most of the properties/methods added to the global scope by MW Core, other extensions, etc. A lot of the mocking code from the mw-node-qunit library could be easily adapted here, for example.

Mocking resource modules
In addition to mocking out aspects of the MediaWiki browser environment, you may need to mock entire modules that are loaded via  in ResourceLoader. Some Wikibase dependencies may need to be mocked in this way, for example. This is also useful if ResourceLoader exposes code with a module name that differs from the name of the equivalent NPM package ( vs   for example).

Example: Mock a Wikibase ResourceLoader module with a placeholder TBD