Skip to content

Commit

Permalink
mgr/dashboard: replace E2E test moveClick with clickCheckbox
Browse files Browse the repository at this point in the history
Ceph Dashboard replaces the original checkbox with a fancy replacement
using the pseudo selector "::before" inside the <label> tag. When the
fancy replacement checkbox is clicked, it actually triggers a click on
the label of the checkbox. `clickCheckbox` does the same.

Removed `moveClick` as it was used to perform an action that the user
would not be able to perform, namely clicking on the checkbox instead of
the checkboxes' label. It was also used for cases where it was not
necessary to be used for, hence the replacement `clickCheckbox` has been
introduced. It checks if the argument passed to it is of type `checkbox`
or `label`. If it is of type `label`, the label will be clicked. If it
is of type `checkbox`, the corresponding `label` is determined and
clicked. This replaces the old implementation with a solution that has
an easy to understand purpose. It also prevents every false application.

This method is designed to be used on all checkboxes of Ceph Dashboard.

Fixes: https://tracker.ceph.com/issues/40693

Signed-off-by: Patrick Seidensal <[email protected]>
  • Loading branch information
p-se committed Aug 28, 2019
1 parent a69a804 commit be3d0c0
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 12 deletions.
26 changes: 21 additions & 5 deletions src/pybind/mgr/dashboard/HACKING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@ There are a few ways how you can try to resolve this:
again in order to reinstall them
- Clear the cache of jest by running ``npx jest --clearCache``

Running End-to-End Tests
~~~~~~~~~~~~~~~~~~~~~~~~
Running End-to-End (E2E) Tests
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

We use `Protractor <http://www.protractortest.org/>`__ to run our frontend E2E
tests.
Expand Down Expand Up @@ -184,13 +184,29 @@ Note::
Writing End-to-End Tests
~~~~~~~~~~~~~~~~~~~~~~~~

To be used methods
..................

For clicking checkboxes, the ``clickCheckbox`` method is supposed to be used.
Due an adaption of the ``<input type="checkbox">`` tag, the original checkbox
is hidden and unclickable. Instead, a fancier replacement is shown. When the
developer tries to use `ElementFinder::click()` on such a checkbox, it will
raise an error. The ``clickCheckbox`` method prevents that by clicking the
label of the checkbox, like a regular user would do.

The PagerHelper class
.....................

The ``PageHelper`` class is supposed to be used for general purpose code that
can be used on various pages or suites. Examples are
``getTableCellByContent()``, ``getTabsCount()`` or ``checkCheckbox()``. Every
method that could be useful on several pages belongs there. Also, methods
can be used on various pages or suites.

Examples are

- ``getTableCellByContent()`` - returns a table cell by its content
- ``getTabsCount()`` - returns the amount of tabs
- ``clickCheckbox()`` - clicks a checkbox

Every method that could be useful on several pages belongs there. Also, methods
which enhance the derived classes of the PageHelper belong there. A good
example for such a case is the ``restrictTo()`` decorator. It ensures that a
method implemented in a subclass of PageHelper is called on the correct page.
Expand Down
38 changes: 31 additions & 7 deletions src/pybind/mgr/dashboard/frontend/e2e/page-helper.po.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,38 @@ export abstract class PageHelper {
* Used for instances where a modal container would receive the click rather
* than the desired element.
*
* https://stackoverflow.com/questions/26211751/protractor-chrome-driver-element-is-not-clickable-at-point
* Our <input type="checkbox"> tag is not visible. Instead of the real
* checkbox, a replacement is shown which is supposed to have an adapted
* style. The replacement checkbox shown is part of the label and is rendered
* in the "::before" pseudo element of the label, hence the label is always
* clicked when the user clicks the replacement checkbox.
*
* This method finds corresponding label to the given checkbox and clicks it
* instead of the (fake) checkbox, like it is the case with real users.
*
* Alternatively, the checkbox' label can be passed.
*
* @param elem The checkbox or corresponding label
*/
moveClick(object) {
return browser
.actions()
.mouseMove(object)
.click()
.perform();
async clickCheckbox(elem: ElementFinder): Promise<void> {
const tagName = await elem.getTagName();
let label: ElementFinder = null; // Both types are clickable

if (tagName === 'input') {
if ((await elem.getAttribute('type')) === 'checkbox') {
label = elem.element(by.xpath('..')).$(`label[for="${await elem.getAttribute('id')}"]`);
} else {
return Promise.reject('element <input> must be of type checkbox');
}
} else if (tagName === 'label') {
label = elem;
} else {
return Promise.reject(
`element <${tagName}> is not of the correct type. You need to pass a checkbox or label`
);
}

return label.click();
}

/**
Expand Down

0 comments on commit be3d0c0

Please sign in to comment.