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.
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.
* 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();
}
/**