diff options
-rw-r--r-- | app/assets/javascripts/main.js | 2 | ||||
-rw-r--r-- | changelogs/unreleased/61550-next-badge.yml | 5 | ||||
-rw-r--r-- | config/initializers/01_secret_token.rb | 11 | ||||
-rw-r--r-- | doc/development/testing_guide/frontend_testing.md | 183 |
4 files changed, 199 insertions, 2 deletions
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js index b503c746801..213d5c6521a 100644 --- a/app/assets/javascripts/main.js +++ b/app/assets/javascripts/main.js @@ -147,7 +147,7 @@ function deferredInitialisation() { const canaryBadge = document.querySelector('.js-canary-badge'); const canaryLink = document.querySelector('.js-canary-link'); if (canaryBadge) { - canaryBadge.classList.remove('hidden'); + canaryBadge.classList.add('hidden'); } if (canaryLink) { canaryLink.classList.add('hidden'); diff --git a/changelogs/unreleased/61550-next-badge.yml b/changelogs/unreleased/61550-next-badge.yml new file mode 100644 index 00000000000..122e394a68c --- /dev/null +++ b/changelogs/unreleased/61550-next-badge.yml @@ -0,0 +1,5 @@ +--- +title: Fixes next badge being always visible +merge_request: +author: +type: fixed diff --git a/config/initializers/01_secret_token.rb b/config/initializers/01_secret_token.rb index 4328ca509ba..e24b5cbd510 100644 --- a/config/initializers/01_secret_token.rb +++ b/config/initializers/01_secret_token.rb @@ -1,3 +1,14 @@ +# WARNING: If you add a new secret to this file, make sure you also +# update Omnibus GitLab or updates will fail. Omnibus is responsible for +# writing the `secrets.yml` file. If Omnibus doesn't know about a +# secret, Rails will attempt to write to the file, but this will fail +# because Rails doesn't have write access. +# +# As an example: +# * https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/27581 +# * https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/3267 +# +# # This file needs to be loaded BEFORE any initializers that attempt to # prepend modules that require access to secrets (e.g. EE's 0_as_concern.rb). # diff --git a/doc/development/testing_guide/frontend_testing.md b/doc/development/testing_guide/frontend_testing.md index f58a8dcbcdc..9bd99e80357 100644 --- a/doc/development/testing_guide/frontend_testing.md +++ b/doc/development/testing_guide/frontend_testing.md @@ -187,6 +187,7 @@ export default function doSomething() { visitUrl('/foo/bar'); } ``` + ```js // my_module_spec.js import doSomething from '~/my_module'; @@ -213,7 +214,187 @@ Further documentation on the babel rewire pluign API can be found on #### Waiting in tests -If you cannot avoid using [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout) in tests, please use the [Jasmine mock clock](https://jasmine.github.io/api/2.9/Clock.html). +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 passed a time larger than zero it will slow down our test suite. +Instead use one of the following approaches. + +##### Promises and Ajax calls + +Register handler functions to wait for the `Promise` to be resolved. + +```javascript +const askTheServer = () => { + return axios + .get('/endpoint') + .then(response => { + // do something + }) + .catch(error => { + // do something else + }); +}; +``` + +**in Jest:** + +```javascript +it('waits for an Ajax call', () => { + return askTheServer().then(() => { + expect(something).toBe('done'); + }); +}); +``` + +**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—you can flush all pending `Promise`s: + +**in Jest:** + +```javascript +it('waits for an Ajax call', () => { + synchronousFunction(); + jest.runAllTicks(); + + expect(something).toBe('done'); +}); +``` + +**in Karma:** + +You are out of luck. The following only works sometimes and may lead to flaky failures: + +```javascript +it('waits for an Ajax call', done => { + synchronousFunction(); + + // create a new Promise and hope that it resolves after the rest + Promise.resolve() + .then(() => { + expect(something).toBe('done'); + }) + .then(done) + .catch(done.fail); +}); +``` + +##### Vue rendering + +To wait until a Vue component is re-rendered, use either of the equivalent +[`Vue.nextTick()`](https://vuejs.org/v2/api/#Vue-nextTick) or `vm.$nextTick()`. + +**in Jest:** + +```javascript +it('renders something', () => { + wrapper.setProps({ value: 'new value' }); + + return wrapper.vm.$nextTick().then(() => { + expect(wrapper.text()).toBe('new value'); + }); +}); +``` + +**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); +}); +``` + +##### `setTimeout()` / `setInterval()` in application + +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-ce/blob/a2128edfee799e49a8732bfa235e2c5e14949c68/jest.config.js#L47) +(see also [Jest Timer Mocks](https://jestjs.io/docs/en/timer-mocks)). In Karma you can use the +[Jasmine mock clock](https://jasmine.github.io/api/2.9/Clock.html). + +```javascript +const doSomethingLater = () => { + setTimeout(() => { + // do something + }, 4000); +}; +``` + +**in Jest:** + +```javascript +it('does something', () => { + doSomethingLater(); + jest.runAllTimers(); + + expect(something).toBe('done'); +}); +``` + +**in Karma:** + +```javascript +it('does something', () => { + jasmine.clock().install(); + + doSomethingLater(); + jasmine.clock().tick(4000); + + expect(something).toBe('done'); + jasmine.clock().uninstall(); +}); +``` + +##### Events + +If the application triggers an event that you need to wait for in your test, register an event handler which contains +the assertions: + +```javascript +it('waits for an event', done => { + eventHub.$once('someEvent', eventHandler); + + someFunction(); + + function eventHandler() { + expect(something).toBe('done'); + done(); + } +}); +``` + +In Jest you can also use a `Promise` for this: + +```javascript +it('waits for an event', () => { + const eventTriggered = new Promise(resolve => eventHub.$once('someEvent', resolve)); + + someFunction(); + + return eventTriggered.then(() => { + expect(something).toBe('done'); + }); +}); +``` #### Migrating flaky Karma tests to Jest |