Reading/Web/QUnit test guidelines

Writing modules
Modules should be prefixed with "MobileFrontend". QUnit supports filtering.

e.g.

Writing tests
Test names should start with the method name. If no instantiation is needed use the pound sign.

Testing Views
There are two recommended patterns for testing Views inside MobileFrontend and getting 100% code coverage. Ideally, we would generate screenshots and look for differences, but this is currently not supported.

Pattern 1 - test constructor
This test pattern ensures the View constructor is called with the right parameters. It assumes the templating code and View code is well tested. This doesn't test the output of the HTML so be careful when using it.

Pattern 2 - test output
You can test the HTML of a MobileFrontend View by diving into the $el property.

When doing this, you get full confidence that your View is rendering as expected. Be careful, as CSS is loaded separate to HTML in headless mode so testing whether an element is visible might not be wise.

This method is usually recommended when there is no test coverage in other forms e.g. Selenium integration tests or UI regression tests.

We recommend querying the resulting HTML rather than testing the HTML string, as particularly in larger components this could make refactoring the HTML makeup of View's difficult in future. For instance, it would be frustrating if adding an aria attribute for accessibility to a Button caused 10+ unit tests to fail!

Testing View Events
Note, it might make sense in some unit tests to trigger events to ensure a View is behaving correctly. However, a Selenium browser test may work just as well. When writing any test, make sure you explain your motivation in the commit message!

Making assertions
Always test the comparison itself;


 * Avoid,   (Sinon.JS); QUnit cannot print useful failure messages in these cases.
 * Prefer,   (Sinon.JS); QUnit can print a useful failure diff.


 * Always use ; never use  . The Wikimedia lint rules require strict   and forbid loose  equality comparisons. This should apply to QUnit as well.
 * Avoid  when tests are synchronous; consider   when asynchronous assertions are necessary. In synchronous tests, tallying the assertion count can add noise without providing much value. For asynchronous tests, setting expectations can help catch programmer errors.
 * Always add an assertion failure message.
 * When a test fails we know why it fails. The message " " is less meaningful then " "
 * Use  rather than   when possible.
 * Asynchronous tests should return a Promise. Use helper functions where possible to keep code simple.
 * Use fake objects where possible. Do not stub the prototype. Especially with regards to mw.Api which can cause HTTP requests
 * Avoid doing  - instead pass a FakeApi as a parameter. If code doesn't support this, it should!

Under discussion

 * We could use eslint to enforce some of these practices, but it may be overkill.