Dealing with positive and negative scenarios together - dn0000001/test-automation GitHub Wiki
Sometimes there are cases in which a page object needs to handle both positive and negative (or multiple) scenarios but the specific case is only know at runtime.
An example of this is login. Most tests assume that login will be successful but what about when login fails due to server issues, etc? Usually, this is not handled and the test fails 1 or more steps after login which can make it more difficult to troubleshoot the issue. We should handle login failure if it occurs. However, the reason that we normally do not is because of performance or we need to check/poll multiple things.
There is now a class to handle these cases. The following is how it was used to handle both the positive and negative cases for login.
OLD Code:
List<WebElement> missingFields = By.cssSelector(".field-message.error").findElements(getDriver());
assertThat(missingFields.size(), is(equalTo(0)));
List<WebElement> signInErrors = By.cssSelector(".message-container.error > .message").findElements(getDriver());
assertThat(signInErrors.size(), is(equalTo(0)));
waitForUrl("/?uli=");
Problems with the code:
The main issue with the code is that if the server is slow responding with the error or the page does not display the error immediately, then both checks can have empty lists.
New Code:
List<Criteria> criteria = new ArrayList<Criteria>();
criteria.add(CriteriaMaker.forUrlContains("/?uli="));
criteria.add(CriteriaMaker.forElementDisplayed(By.cssSelector(".field-message.error")));
criteria.add(CriteriaMaker.forElementDisplayed(By.cssSelector(".message-container.error > .message")));
Conditional conditional = new Conditional(getDriver());
assertThat("Login Failure Detected", conditional.waitForMatch(criteria), is(equalTo(0)));
Code Explanation:
The method conditional.waitForMatch will poll and return the 1st criteria that is matched. Then, we just assert that the index of the matching criteria is the one we expect. In the case, that none of the criteria are matched before timeout occurs, then a runtime exception will be thrown.
It is also possible to get more details from the match by using conditional.getResultInfo() which returns an object with more information. This information can be used to decide which action to take as well.
Additional way to check:
conditional.waitForMatch(criteria);
assertThat("Login Failure Detected", conditional.getResultInfo().getCriteriaType(), is(equalTo(CriteriaType.URL_CONTAINS)));
Note: In this example, the criteria type URL_CONTAINS is unique but the criteria type DISPLAYED is duplicated here.