Reputation: 474141
In one of our tests, we have the following set of expectations:
expect(headerPage.dashboard.isDisplayed()).toBe(true);
expect(headerPage.queue.isDisplayed()).toBe(true);
expect(headerPage.claimSearch.isDisplayed()).toBe(true);
expect(headerPage.claim.isDisplayed()).toBe(true);
expect(headerPage.case.isDisplayed()).toBe(true);
expect(headerPage.calendar.isDisplayed()).toBe(true);
On one hand, having multiple simple expectations provide a more precise and understandable feedback, but, on another, this looks like it violates the DRY principle and the "one expectation per test" commonly acceptable guideline.
Is there a way to convert/simplify it to a single expect?
headerPage
is a Page Object, dashboard
and other page object fields are navigation links.
Upvotes: 11
Views: 349
Reputation: 561
If this is logic you are using across multiple specs, you could look into jasmine custom matchers to encapsulate the logic.
It would be written somewhat like this:
var customMatchers = {
toDisplayWidgets: function(util, customEqualityTests) {
return {
compare: function(actual, expected) {
function isDisplayingWidgets(page) {
return page.dashboard.isDisplayed() &&
page.queue.isDisplayed() &&
page.claimSearch.isDisplayed() &&
page.claim.isDisplayed() &&
page.case.isDisplayed() &&
page.calendar.isDisplayed();
}
var result = {};
result.pass = isDisplayingWidgets(actual);
if (!result.pass) {
result.message = 'dashboard is not displayed';
}
return result;
}
}
}
Add the matcher to your current test
jasmine.addMatchers(customMatchers);
And then in your tests you could just assert with
expect(headerPage).toDisplayWidgets();
Upvotes: 1
Reputation: 474141
Alternative approach. What I've ended up with was to add a page object method that returns the labels of the currently visible navigation links:
this.getVisibleLinks = function () {
return $$(".ap-header-nav-tabs li a").filter(function (link) {
return link.isDisplayed();
}).getText();
};
Then, the above test would be transformed to a concise and readable:
expect(headerPage.getVisibleLinks()).toEqual(["Dashboard", "Queue", "Claim Search", ...]);
Upvotes: 1
Reputation: 33439
I think you've misunderstood the purpose of the "one expectation per test" guideline. The point isn't to combine a bunch of expectations into a single expectation, it's to split up your expectations into separate tests.
To follow the spirit of that guideline, you would write your tests like this:
describe("The header page", function () {
var headerPage;
beforeEach(function () {
//Common logic here
});
it("displays the dashboard", function () {
expect(headerPage.dashboard.isDisplayed()).toBe(true);
});
it("displays the queue", function () {
expect(headerPage.queue.isDisplayed()).toBe(true);
});
it("displays the claimSearch", function () {
expect(headerPage.claimSearch.isDisplayed()).toBe(true);
});
//etc.
});
That's a fair bit more verbose than what you have; but that's why these are guidelines not rules. It's a tradeoff between how verbose you make your tests, versus how easy they are to debug later. ("The header page displays the dashboard: FAILED") is a very clear and specific test failure message, compared to getting the same failure message regardless of which expectation actually failed.
I definitely would not try to combine all of these lines into a single line. If you don't want to split it into a bunch of different test cases I would just leave it how it is.
Upvotes: 14
Reputation: 2394
what about using a helper function that returns results of all the tests, something like
expect(headerDisplayTests()).toBe(true);
function headerDisplayTests() {
return headerPage.dashboard.isDisplayed() &&
headerPage.queue.isDisplayed() &&
headerPage.claimSearch.isDisplayed() &&
headerPage.claim.isDisplayed() &&
headerPage.case.isDisplayed() &&
headerPage.calendar.isDisplayed();
}
Upvotes: -1