Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'doc/development/testing_guide/frontend_testing.md')
-rw-r--r--doc/development/testing_guide/frontend_testing.md193
1 files changed, 36 insertions, 157 deletions
diff --git a/doc/development/testing_guide/frontend_testing.md b/doc/development/testing_guide/frontend_testing.md
index 3af806d8f57..76687db3a3f 100644
--- a/doc/development/testing_guide/frontend_testing.md
+++ b/doc/development/testing_guide/frontend_testing.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Frontend testing standards and style guidelines
There are two types of test suites encountered while developing frontend code
-at GitLab. We use Karma with Jasmine and Jest for JavaScript unit and integration testing,
+at GitLab. We use Jest for JavaScript unit and integration testing,
and RSpec feature tests with Capybara for e2e (end-to-end) integration testing.
Unit and feature tests need to be written for all new features.
@@ -28,46 +28,9 @@ If you are looking for a guide on Vue component testing, you can jump right away
We use Jest to write frontend unit and integration tests.
Jest tests can be found in `/spec/frontend` and `/ee/spec/frontend` in EE.
-## Karma test suite
-
-While GitLab has switched over to [Jest](https://jestjs.io), Karma tests still exist in our
-application because some of our specs require a browser and can't be easily migrated to Jest.
-Those specs intend to eventually drop Karma in favor of either Jest or RSpec. You can track this migration
-in the [related epic](https://gitlab.com/groups/gitlab-org/-/epics/4900).
-
-[Karma](http://karma-runner.github.io/) is a test runner which uses
-[Jasmine](https://jasmine.github.io/) as its test framework. Jest also uses Jasmine as foundation,
-that's why it's looking quite similar.
-
-Karma tests live in `spec/javascripts/` and `/ee/spec/javascripts` in EE.
-
-`app/assets/javascripts/behaviors/autosize.js`
-might have a corresponding `spec/javascripts/behaviors/autosize_spec.js` file.
-
-Keep in mind that in a CI environment, these tests are run in a headless
-browser and you don't have access to certain APIs, such as
-[`Notification`](https://developer.mozilla.org/en-US/docs/Web/API/notification),
-which have to be stubbed.
-
-### Differences to Karma
-
-- Jest runs in a Node.js environment, not in a browser. [An issue exists](https://gitlab.com/gitlab-org/gitlab/-/issues/26982) for running Jest tests in a browser.
-- Because Jest runs in a Node.js environment, it uses [jsdom](https://github.com/jsdom/jsdom) by default. See also its [limitations](#limitations-of-jsdom) below.
-- Jest does not have access to Webpack loaders or aliases.
- The aliases used by Jest are defined in its [own configuration](https://gitlab.com/gitlab-org/gitlab/-/blob/master/jest.config.js).
-- All calls to `setTimeout` and `setInterval` are mocked away. See also [Jest Timer Mocks](https://jestjs.io/docs/timer-mocks).
-- `rewire` is not required because Jest supports mocking modules. See also [Manual Mocks](https://jestjs.io/docs/manual-mocks).
-- No [context object](https://jasmine.github.io/tutorials/your_first_suite#section-The_%3Ccode%3Ethis%3C/code%3E_keyword) is passed to tests in Jest.
- This means sharing `this.something` between `beforeEach()` and `it()` for example does not work.
- Instead you should declare shared variables in the context that they are needed (via `const` / `let`).
-- The following cause tests to fail in Jest:
- - Unmocked requests.
- - Unhandled Promise rejections.
- - Calls to `console.warn`, including warnings from libraries like Vue.
-
### Limitations of jsdom
-As mentioned [above](#differences-to-karma), Jest uses jsdom instead of a browser for running tests.
+Jest uses jsdom instead of a browser for running tests.
This comes with a number of limitations, namely:
- [No scrolling support](https://github.com/jsdom/jsdom/blob/15.1.1/lib/jsdom/browser/Window.js#L623-L625)
@@ -387,8 +350,7 @@ Sometimes we have to test time-sensitive code. For example, recurring events tha
If the application itself is waiting for some time, mock await the waiting. In Jest this is already
[done by default](https://gitlab.com/gitlab-org/gitlab/-/blob/a2128edfee799e49a8732bfa235e2c5e14949c68/jest.config.js#L47)
-(see also [Jest Timer Mocks](https://jestjs.io/docs/timer-mocks)). In Karma you can use the
-[Jasmine mock clock](https://jasmine.github.io/api/2.9/Clock.html).
+(see also [Jest Timer Mocks](https://jestjs.io/docs/timer-mocks)).
```javascript
const doSomethingLater = () => {
@@ -409,20 +371,6 @@ it('does something', () => {
});
```
-**in Karma:**
-
-```javascript
-it('does something', () => {
- jasmine.clock().install();
-
- doSomethingLater();
- jasmine.clock().tick(4000);
-
- expect(something).toBe('done');
- jasmine.clock().uninstall();
-});
-```
-
### Mocking the current location in Jest
NOTE:
@@ -476,8 +424,7 @@ it('passes', () => {
Sometimes a test needs to wait for something to happen in the application before it continues.
Avoid using [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout)
-because it makes the reason for waiting unclear and if used within Karma with a time larger than zero it slows down our test suite.
-Instead use one of the following approaches.
+because it makes the reason for waiting unclear. Instead use one of the following approaches.
#### Promises and Ajax calls
@@ -505,19 +452,6 @@ it('waits for an Ajax call', async () => {
});
```
-**in Karma:**
-
-```javascript
-it('waits for an Ajax call', done => {
- askTheServer()
- .then(() => {
- expect(something).toBe('done');
- })
- .then(done)
- .catch(done.fail);
-});
-```
-
If you are not able to register handlers to the `Promise`, for example because it is executed in a synchronous Vue life cycle hook, take a look at the [waitFor](#wait-until-axios-requests-finish) helpers or you can flush all pending `Promise`s:
**in Jest:**
@@ -548,22 +482,6 @@ it('renders something', () => {
});
```
-**in Karma:**
-
-```javascript
-it('renders something', done => {
- wrapper.setProps({ value: 'new value' });
-
- wrapper.vm
- .$nextTick()
- .then(() => {
- expect(wrapper.text()).toBe('new value');
- })
- .then(done)
- .catch(done.fail);
-});
-```
-
#### Events
If the application triggers an event that you need to wait for in your test, register an event handler which contains
@@ -776,8 +694,6 @@ TBU
### Stubbing and Mocking
-Jasmine provides stubbing and mocking capabilities. There are some subtle differences in how to use it within Karma and Jest.
-
Stubs or spies are often used synonymously. In Jest it's quite easy thanks to the `.spyOn` method.
[Official docs](https://jestjs.io/docs/jest-object#jestspyonobject-methodname)
The more challenging part are mocks, which can be used for functions or even dependencies.
@@ -835,7 +751,6 @@ For running the frontend tests, you need the following commands:
- `rake frontend:fixtures` (re-)generates [fixtures](#frontend-test-fixtures). Make sure that
fixtures are up-to-date before running tests that require them.
- `yarn jest` runs Jest tests.
-- `yarn karma` runs Karma tests.
### Live testing and focused testing -- Jest
@@ -860,49 +775,36 @@ yarn jest ./path/to/folder/
yarn jest term
```
-### Live testing and focused testing -- Karma
+## Frontend test fixtures
-Karma allows something similar, but it's way more costly.
+Frontend fixtures are files containing responses from backend controllers. These responses can be either HTML
+generated from HAML templates or JSON payloads. Frontend tests that rely on these responses are
+often using fixtures to validate correct integration with the backend code.
-Running Karma with `yarn run karma-start` compiles the JavaScript
-assets and runs a server at `http://localhost:9876/` where it automatically
-runs the tests on any browser which connects to it. You can enter that URL on
-multiple browsers at once to have it run the tests on each in parallel.
+### Use fixtures
-While Karma is running, any changes you make instantly trigger a recompile
-and retest of the **entire test suite**, so you can see instantly if you've broken
-a test with your changes. You can use [Jasmine focused](https://jasmine.github.io/2.5/focused_specs.html) or
-excluded tests (with `fdescribe` or `xdescribe`) to get Karma to run only the
-tests you want while you're working on a specific feature, but make sure to
-remove these directives when you commit your code.
+Jest uses `spec/frontend/__helpers__/fixtures.js` to import fixtures in tests.
-It is also possible to only run Karma on specific folders or files by filtering
-the run tests via the argument `--filter-spec` or short `-f`:
+The following are examples of tests that work for Jest:
-```shell
-# Run all files
-yarn karma-start
-# Run specific spec files
-yarn karma-start --filter-spec profile/account/components/update_username_spec.js
-# Run specific spec folder
-yarn karma-start --filter-spec profile/account/components/
-# Run all specs which path contain vue_shared or vie
-yarn karma-start -f vue_shared -f vue_mr_widget
-```
+```javascript
+it('makes a request', () => {
+ const responseBody = getJSONFixture('some/fixture.json'); // loads spec/frontend/fixtures/some/fixture.json
+ axiosMock.onGet(endpoint).reply(200, responseBody);
-You can also use glob syntax to match files. Remember to put quotes around the
-glob otherwise your shell may split it into multiple arguments:
+ myButton.click();
-```shell
-# Run all specs named `file_spec` within the IDE subdirectory
-yarn karma -f 'spec/javascripts/ide/**/file_spec.js'
-```
+ // ...
+});
-## Frontend test fixtures
+it('uses some HTML element', () => {
+ loadFixtures('some/page.html'); // loads spec/frontend/fixtures/some/page.html and adds it to the DOM
-Frontend fixtures are files containing responses from backend controllers. These responses can be either HTML
-generated from HAML templates or JSON payloads. Frontend tests that rely on these responses are
-often using fixtures to validate correct integration with the backend code.
+ const element = document.getElementById('#my-id');
+
+ // ...
+});
+```
### Generate fixtures
@@ -961,34 +863,6 @@ This will create a new fixture located at
You can import the JSON fixture in a Jest test using the `getJSONFixture` method
[as described below](#use-fixtures).
-### Use fixtures
-
-Jest and Karma test suites import fixtures in different ways:
-
-- The Karma test suite are served by [jasmine-jquery](https://github.com/velesin/jasmine-jquery).
-- Jest use `spec/frontend/__helpers__/fixtures.js`.
-
-The following are examples of tests that work for both Karma and Jest:
-
-```javascript
-it('makes a request', () => {
- const responseBody = getJSONFixture('some/fixture.json'); // loads spec/frontend/fixtures/some/fixture.json
- axiosMock.onGet(endpoint).reply(200, responseBody);
-
- myButton.click();
-
- // ...
-});
-
-it('uses some HTML element', () => {
- loadFixtures('some/page.html'); // loads spec/frontend/fixtures/some/page.html and adds it to the DOM
-
- const element = document.getElementById('#my-id');
-
- // ...
-});
-```
-
## Data-driven tests
Similar to [RSpec's parameterized tests](best_practices.md#table-based--parameterized-tests),
@@ -1139,13 +1013,10 @@ Main information on frontend testing levels can be found in the [Testing Levels
Tests relevant for frontend development can be found at the following places:
-- `spec/javascripts/`, for Karma tests
- `spec/frontend/`, for Jest tests
- `spec/features/`, for RSpec tests
-RSpec runs complete [feature tests](testing_levels.md#frontend-feature-tests), while the Jest and Karma directories contain [frontend unit tests](testing_levels.md#frontend-unit-tests), [frontend component tests](testing_levels.md#frontend-component-tests), and [frontend integration tests](testing_levels.md#frontend-integration-tests).
-
-All tests in `spec/javascripts/` are intended to be migrated to `spec/frontend/` (see also [#52483](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/52483)).
+RSpec runs complete [feature tests](testing_levels.md#frontend-feature-tests), while the Jest directories contain [frontend unit tests](testing_levels.md#frontend-unit-tests), [frontend component tests](testing_levels.md#frontend-component-tests), and [frontend integration tests](testing_levels.md#frontend-integration-tests).
Before May 2018, `features/` also contained feature tests run by Spinach. These tests were removed from the codebase in May 2018 ([#23036](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/23036)).
@@ -1161,6 +1032,16 @@ If you introduce new helpers, place them in that directory.
We have a helper available to make testing actions easier, as per [official documentation](https://vuex.vuejs.org/guide/testing.html):
```javascript
+// prefer using like this, a single object argument so parameters are obvious from reading the test
+await testAction({
+ action: actions.actionName,
+ payload: { deleteListId: 1 },
+ state: { lists: [1, 2, 3] },
+ expectedMutations: [ { type: types.MUTATION} ],
+ expectedActions: [],
+});
+
+// old way, don't do this for new tests
testAction(
actions.actionName, // action
{ }, // params to be passed to action
@@ -1177,8 +1058,6 @@ testAction(
);
```
-Check an example in [`spec/frontend/ide/stores/actions_spec.js`](https://gitlab.com/gitlab-org/gitlab/-/blob/fdc7197609dfa7caeb1d962042a26248e49f27da/spec/frontend/ide/stores/actions_spec.js#L392).
-
### Wait until Axios requests finish
<!-- vale gitlab.Spelling = NO -->