diff --git a/docusaurus/docs/internal/testing/e2e-test.md b/docusaurus/docs/internal/testing/e2e-test.md index 7c0ee253da..6f15e287e7 100644 --- a/docusaurus/docs/internal/testing/e2e-test.md +++ b/docusaurus/docs/internal/testing/e2e-test.md @@ -141,32 +141,76 @@ new LoginPagePo().username().set('admin') ``` POs all inherit a root `component.po`. Common component functionality can be added there. They also expose their core cypress (chainable) element. -### Best Practices to keep in mind when writing tests -- When selecting an element be sure to use the attribute `data-testid` if it exists, even in case of lists where elements are distinguished by an index suffix. -- Utilize the `afterAll()` hook to clean up so that subsequent tests are not affected by resources created during test execution. -- We should not add locators for DOM elements in the test files directly, we should instead create a class in a PO file for a given dashboard page which contains the locators that identify the page elements. From there, call the methods in the test file. -For example, let’s say we wanted to automate the dashboard login page. -The login page uses the common component for `LabeledInput` so first we create a `LabeledInputPo` which contains methods for actions to perform on a given input box such as `clear()`, `set()`, etc. -Then we create the `LoginPagePo` which contains methods such as `username()`. For the `username()` method we create an instance of `LabeledInputPo` object and pass in the locator for the page element. +### Best Practices -```ts -import LabeledInputPo from '@/cypress/e2e/po/components/labeled-input.po'; +#### data-testid +When selecting an element priority should be given to the attribute `data-testid`, if this does not exist using a specific css selector can be used. +- In some cases, including lists, the data-testid is dynamically created with a context prefix or index, so check the DOM even if it code it's not obvious -username(): LabeledInputPo { - return new LabeledInputPo('[data-testid="local-login-username"]'); - } -``` +#### Keep it clean +Utilize the `beforeAll` and `afterAll` hooks to setup the test, and then clean up afterwards. Be careful though, these won't run again if Cypress retries individual failed tests -Lastly, we create a test file and call the `username()` method to utilize it in the test. +Returning the environment to it's original state via afterAll is important to avoid subsequent tests being affected, for example by resources created during test execution. -```ts -import { LoginPagePo } from '@/cypress/e2e/po/pages/login-page.po'; +#### Where's my Page Object? + +Page Objects (POs) generally represent UI components or pages. + +A UI component could be +- quite core + - `LabeledInput` +- intermediate + - `ArrayList` (contains `LabeledInput`s), + - `shell/edit/networking.k8s.io.ingress/Certificate.vue` (contains `ArrayList`) +- singular at the page level + - `shell/edit/networking.k8s.io.ingress/index.vue` (contains `networking.k8s.io.ingress/Certificate.vue`) +- generic, and singular at the page level + - `shell/components/ResourceDetail/index.vue` (contains `shell/edit/networking.k8s.io.ingress/index.vue`) -const loginPage = new LoginPagePo(); +A Page component could be more conceptual, for example the `Edit Service` page (which under the hood is `shell/pages/c/_cluster/_product/_resource/_id`). -loginPage.username().set(TEST_USERNAME); +**When writing tests start by first searching at the page level and then working further down the stack towards the core component. Once a PO is found work back up the stack, implementing POs as required.** + +##### Example +Considering the chain above, if we were to test the Create/Edit Ingress's page's Certificate tabs Hosts list consider the DOM + +``` +