summaryrefslogtreecommitdiff
path: root/doc/development/testing_guide/best_practices.md
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-04-20 23:50:22 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-04-20 23:50:22 +0000
commit9dc93a4519d9d5d7be48ff274127136236a3adb3 (patch)
tree70467ae3692a0e35e5ea56bcb803eb512a10bedb /doc/development/testing_guide/best_practices.md
parent4b0f34b6d759d6299322b3a54453e930c6121ff0 (diff)
downloadgitlab-ce-9dc93a4519d9d5d7be48ff274127136236a3adb3.tar.gz
Add latest changes from gitlab-org/gitlab@13-11-stable-eev13.11.0-rc43
Diffstat (limited to 'doc/development/testing_guide/best_practices.md')
-rw-r--r--doc/development/testing_guide/best_practices.md134
1 files changed, 131 insertions, 3 deletions
diff --git a/doc/development/testing_guide/best_practices.md b/doc/development/testing_guide/best_practices.md
index ee8401e08d4..828e9925d46 100644
--- a/doc/development/testing_guide/best_practices.md
+++ b/doc/development/testing_guide/best_practices.md
@@ -86,7 +86,7 @@ a parent context. Examples of these are:
- `:clean_gitlab_redis_cache` which provides a clean Redis cache to the examples.
- `:request_store` which provides a request store to the examples.
-Obviously we should reduce test dependencies, and avoiding
+We should reduce test dependencies, and avoiding
capabilities also reduces the amount of set-up needed.
`:js` is particularly important to avoid. This must only be used if the feature
@@ -350,12 +350,140 @@ writing one](testing_levels.md#consider-not-writing-a-system-test)!
- It's ok to look for DOM elements, but don't abuse it, because it makes the tests
more brittle
-#### Debugging Capybara
+#### UI testing
-Sometimes you may need to debug Capybara tests by observing browser behavior.
+When testing the UI, write tests that simulate what a user sees and how they interact with the UI.
+This means preferring Capybara's semantic methods and avoiding querying by IDs, classes, or attributes.
+
+The benefits of testing in this way are that:
+
+- It ensures all interactive elements have an [accessible name](../fe_guide/accessibility.md#provide-accessible-names-for-screen-readers).
+- It is more readable, as it uses more natural language.
+- It is less brittle, as it avoids querying by IDs, classes, and attributes, which are not visible to the user.
+
+We strongly recommend that you query by the element's text label instead of by ID, class name, or `data-testid`.
+
+If needed, you can scope interactions within a specific area of the page by using `within`.
+As you will likely be scoping to an element such as a `div`, which typically does not have a label,
+you may use a `data-testid` selector in this case.
+
+##### Actions
+
+Where possible, use more specific [actions](https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Actions), such as the ones below.
+
+```ruby
+# good
+click_button 'Submit review'
+
+click_link 'UI testing docs'
+
+fill_in 'Search projects', with: 'gitlab' # fill in text input with text
+
+select 'Last updated', from: 'Sort by' # select an option from a select input
+
+check 'Checkbox label'
+uncheck 'Checkbox label'
+
+choose 'Radio input label'
+
+attach_file('Attach a file', '/path/to/file.png')
+
+# bad - interactive elements must have accessible names, so
+# we should be able to use one of the specific actions above
+find('.group-name', text: group.name).click
+find('.js-show-diff-settings').click
+find('[data-testid="submit-review"]').click
+find('input[type="checkbox"]').click
+find('.search').native.send_keys('gitlab')
+```
+
+##### Finders
+
+Where possible, use more specific [finders](https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Finders), such as the ones below.
+
+```ruby
+# good
+find_button 'Submit review'
+find_button 'Submit review', disabled: true
+
+find_link 'UI testing docs'
+find_link 'UI testing docs', href: docs_url
+
+find_field 'Search projects'
+find_field 'Search projects', with: 'gitlab' # find the input field with text
+find_field 'Search projects', disabled: true
+find_field 'Checkbox label', checked: true
+find_field 'Checkbox label', unchecked: true
+
+# acceptable when finding a element that is not a button, link, or field
+find('[data-testid="element"]')
+```
+
+##### Matchers
+
+Where possible, use more specific [matchers](https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/RSpecMatchers), such as the ones below.
+
+```ruby
+# good
+expect(page).to have_button 'Submit review'
+expect(page).to have_button 'Submit review', disabled: true
+expect(page).to have_button 'Notifications', class: 'is-checked' # assert the "Notifications" GlToggle is checked
+
+expect(page).to have_link 'UI testing docs'
+expect(page).to have_link 'UI testing docs', href: docs_url # assert the link has an href
+
+expect(page).to have_field 'Search projects'
+expect(page).to have_field 'Search projects', disabled: true
+expect(page).to have_field 'Search projects', with: 'gitlab' # assert the input field has text
+
+expect(page).to have_checked_field 'Checkbox label'
+expect(page).to have_unchecked_field 'Radio input label'
+
+expect(page).to have_select 'Sort by'
+expect(page).to have_select 'Sort by', selected: 'Last updated' # assert the option is selected
+expect(page).to have_select 'Sort by', options: ['Last updated', 'Created date', 'Due date'] # assert an exact list of options
+expect(page).to have_select 'Sort by', with_options: ['Created date', 'Due date'] # assert a partial list of options
+
+expect(page).to have_text 'Some paragraph text.'
+expect(page).to have_text 'Some paragraph text.', exact: true # assert exact match
+
+expect(page).to have_current_path 'gitlab/gitlab-test/-/issues'
+
+expect(page).to have_title 'Not Found'
+
+# acceptable when a more specific matcher above is not possible
+expect(page).to have_css 'h2', text: 'Issue title'
+expect(page).to have_css 'p', text: 'Issue description', exact: true
+expect(page).to have_css '[data-testid="weight"]', text: 2
+expect(page).to have_css '.atwho-view ul', visible: true
+```
+
+##### Other useful methods
+
+After you retrieve an element using a [finder method](#finders), you can invoke a number of
+[element methods](https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Element)
+on it, such as `hover`.
+
+Capybara tests also have a number of [session methods](https://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Session) available, such as `accept_confirm`.
+
+Some other useful methods are shown below:
+
+```ruby
+refresh # refresh the page
+
+send_keys([:shift, 'i']) # press Shift+I keys to go to the Issues dashboard page
+
+current_window.resize_to(1000, 1000) # resize the window
+
+scroll_to(find_field('Comment')) # scroll to an element
+```
+
+You can also find a number of GitLab custom helpers in the `spec/support/helpers/` directory.
#### Live debug
+Sometimes you may need to debug Capybara tests by observing browser behavior.
+
You can pause Capybara and view the website on the browser by using the
`live_debug` method in your spec. The current page is automatically opened
in your default browser.