From d45e53f3507ca2952c16b8acc0e66254de6760bf Mon Sep 17 00:00:00 2001 From: Erik Jan de Wit Date: Wed, 16 Mar 2022 10:39:16 +0100 Subject: [PATCH] Initial version of writing tests document (#2176) --- README.md | 2 + cypress/WRITING_TESTS.md | 87 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 cypress/WRITING_TESTS.md diff --git a/README.md b/README.md index 37919d5c0d..2a31dab99a 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,8 @@ cypress run --spec "cypress/integration/example-test.spec.js" --browser chrome ``` **note**: the complete list of parameters can be found in the [official Cypress documentation](https://docs.cypress.io/guides/guides/command-line.html#Commands). +Read more about [how to write tests](./cypress/WRITING_TESTS.md) + ## Project Structure ```text diff --git a/cypress/WRITING_TESTS.md b/cypress/WRITING_TESTS.md new file mode 100644 index 0000000000..6a79a14adf --- /dev/null +++ b/cypress/WRITING_TESTS.md @@ -0,0 +1,87 @@ +## How to write tests + +### Create PageObjects for the page screens to reuse the methods + +Don't do this: +```typescript +cy.findByTestId("rs-keys-tab").click(); +cy.findByTestId("rs-providers-tab").click(); +cy.findAllByTestId("provider-name-link") + .contains("test_hmac-generated") + .click(); +``` + +Instead use a page object as it is a lot easier to get the intended functionality of the test: +```typescript +realmSettings.goToProvidersTab(); +realmSettings.fillOutForm({ name: "test" }).save(); +``` + +#### Clean code +Write locators in the PageObject layer and in object variables when possible to avoid hardcoding. +Set type of element at the end of the variable name (e.g. saveBtn, nameInput, userDrpDwn…) +Avoid adding “click” to name methods, methods should be named as an action “goToX”, “openX”, “createX”, etc. +Consistent naming (e.g goToTab methods, somewhere named goToTab, other goToXTab) + + +### Test structure + +We have `keycloakBefore` that will navigate to the main page, control request errors and wait for the load to finish. +You can then have multiple test or create a new `describe` block to setup some data for your test. + +```typescript +describe("Realm roles test", () => { + before(() => { + keycloakBefore(); + loginPage.logIn(); + }); + + beforeEach(() => { + sidebarPage.goToRealmRoles(); + }); +``` + +Example of `describe` to setup data for that test: + +```typescript +import adminClient from "../support/util/AdminClient"; + +describe("Edit role details", () => { + before(() => { + adminClient.createRealmRole({ + name: editRoleName, + description, + }); + }); + + after(() => { + adminClient.deleteRealmRole(editRoleName); + }); + + it("Should edit realm role details", () => { + // ... +``` + +### Waiting for results + +Sometimes you will get the following error: +> Cypress failed because the element has been detached from the DOM + +This is because the DOM has been updated in between selectors. You can remedy this by waiting on REST calls. +You can see the rest calls in the cypress IDE. + +```typescript + cy.intercept("/admin/realms/master/").as("search"); + + // ... pressing a button that will perform the search + + cy.wait(["@search"]); // wait for the call named search +``` + +If there were no calls and you still get this error, try using `{force: true}`, but try not to use it everywhere. For example, there could be an unexpected open modal blocking the element, so even the user wouldn’t be able to use that element. + +### Some more reading: + +* [Moises document](https://docs.google.com/document/d/11sm1IpEvVLHO59JEVmwgNOUD0zoP4YMvInIU4v5iVNk/edit) +* [Cypress blog do not get too detached](https://www.cypress.io/blog/2020/07/22/do-not-get-too-detached/) +* [See the clients_test.spec as an example](./cypress/integration/clients_test.spec.ts) \ No newline at end of file