| commit | author | age | ||
| 83c3f6 | 1 | ## How does Bootstrap's test suite work? |
| SP | 2 | |
| 3 | Bootstrap uses [QUnit](https://qunitjs.com/) and [Sinon](https://sinonjs.org/). Each plugin has a file dedicated to its tests in `unit/<plugin-name>.js`. | |
| 4 | ||
| 5 | * `unit/` contains the unit test files for each Bootstrap plugin. | |
| 6 | * `vendor/` contains third-party testing-related code (QUnit, jQuery and Sinon). | |
| 7 | * `visual/` contains "visual" tests which are run interactively in real browsers and require manual verification by humans. | |
| 8 | ||
| 9 | To run the unit test suite via [Karma](https://karma-runner.github.io/), run `npm run js-test`. | |
| 10 | ||
| 11 | To run the unit test suite via a real web browser, open `index.html` in the browser. | |
| 12 | ||
| 13 | ||
| 14 | ## How do I add a new unit test? | |
| 15 | ||
| 16 | 1. Locate and open the file dedicated to the plugin which you need to add tests to (`unit/<plugin-name>.js`). | |
| 17 | 2. Review the [QUnit API Documentation](https://api.qunitjs.com/) and use the existing tests as references for how to structure your new tests. | |
| 18 | 3. Write the necessary unit test(s) for the new or revised functionality. | |
| 19 | 4. Run `npm run js-test` to see the results of your newly-added test(s). | |
| 20 | ||
| 21 | **Note:** Your new unit tests should fail before your changes are applied to the plugin, and should pass after your changes are applied to the plugin. | |
| 22 | ||
| 23 | ## What should a unit test look like? | |
| 24 | ||
| 25 | * Each test should have a unique name clearly stating what unit is being tested. | |
| 26 | * Each test should test only one unit per test, although one test can include several assertions. Create multiple tests for multiple units of functionality. | |
| 27 | * Each test should begin with [`assert.expect`](https://api.qunitjs.com/assert/expect/) to ensure that the expected assertions are run. | |
| 28 | * Each test should follow the project's [JavaScript Code Guidelines](https://github.com/twbs/bootstrap/blob/master/CONTRIBUTING.md#js) | |
| 29 | ||
| 30 | ## Code coverage | |
| 31 | ||
| 32 | Currently we're aiming for at least 80% test coverage for our code. To ensure your changes meet or exceed this limit, run `npm run js-compile && npm run js-test` and open the file in `js/coverage/lcov-report/index.html` to see the code coverage for each plugin. See more details when you select a plugin and ensure your change is fully covered by unit tests. | |
| 33 | ||
| 34 | ### Example tests | |
| 35 | ||
| 36 | ```js | |
| 37 | // Synchronous test | |
| 38 | QUnit.test('should describe the unit being tested', function (assert) { | |
| 39 | assert.expect(1) | |
| 40 | var templateHTML = '<div class="alert alert-danger fade show">' + | |
| 41 | '<a class="close" href="#" data-dismiss="alert">×</a>' + | |
| 42 | '<p><strong>Template necessary for the test.</p>' + | |
| 43 | '</div>' | |
| 44 | var $alert = $(templateHTML).appendTo('#qunit-fixture').bootstrapAlert() | |
| 45 | ||
| 46 | $alert.find('.close').trigger('click') | |
| 47 | ||
| 48 | // Make assertion | |
| 49 | assert.strictEqual($alert.hasClass('show'), false, 'remove .show class on .close click') | |
| 50 | }) | |
| 51 | ||
| 52 | // Asynchronous test | |
| 53 | QUnit.test('should describe the unit being tested', function (assert) { | |
| 54 | assert.expect(2) | |
| 55 | var done = assert.async() | |
| 56 | ||
| 57 | var $tooltip = $('<div title="tooltip title"></div>').bootstrapTooltip() | |
| 58 | var tooltipInstance = $tooltip.data('bs.tooltip') | |
| 59 | var spyShow = sinon.spy(tooltipInstance, 'show') | |
| 60 | ||
| 61 | $tooltip.appendTo('#qunit-fixture') | |
| 62 | .on('shown.bs.tooltip', function () { | |
| 63 | assert.ok(true, '"shown" event was fired after calling "show"') | |
| 64 | assert.ok(spyShow.called, 'show called') | |
| 65 | done() | |
| 66 | }) | |
| 67 | .bootstrapTooltip('show') | |
| 68 | }) | |
| 69 | ``` | |