Creating PageObjects in WebDriverIO - webdriver-io

I've been creating PageObjects for WebDriverIO and have been following the ES6 method for Page Object pattern in the WebDriverIO documentation.
However, someone on my team suggested simply making objects of selectors, and then calling those strings in the tests. Is there a good reason why the Page Object pattern returns elements and not string of the selectors?

Page Object returns elements instead of just the selector string to allow actions to be called directly on the elements e.g.
PageObject.Element.waitForDisplayed()
Instead of you doing
Browser.waitForDisplayed(PageObject.Element)
Which may get lengthy and doesn't chain as well. You can find more actions that can be performed on elements here
However, you can also get the string of the selector if you want by doing
PageObject.Element.selector()
Chaining e.g.
PageObject.Element.waitForDisplayed().click()

I think the point is allow you to use the objects directly. So:
MyPageObject.MyElement.click()
versus:
browser.click(MyPageObject.MyElement)
Just a little less verbose

Related

What is the use of getWrappedElement() method which is declared in WrapsElement interface and why does only Select class implement it?

I am able to understand all the methods implemented in Select class except getWrappedElement() method. Can anyone please help me out on this?
This is used if you have your WebElement encapsulated in some other entity. There are two examples:
org.openqa.selenium.support.ui.Select that actually mimics the behavior of select control. It implements WrapsElement in order to provide the actual element it "decorates" (however it is not a decorator hence I put quotes here).
org.openqa.selenium.support.events.EventFiringWebDriver.EventFiringWebElement which works in pair with EventFiringWebDriver. It actually wraps the base element and allow to run actions before and after your element methods call. Hence you might want to obtain that base WebElement in some reason which is supported by implementation of WrapsElement
In the latter case there is also a code that "consumes" entities implementing WrapsElement. Such objects are expected for example in executeScript in order to unwrap objects you're passing as parameters for your script.
WrappedElement is also used in a number of internal Selenium classes where it tests if an element is the instance of WrappedElement and unwraps it before proceed to next steps.

TestCafe t.eval vs. ClientFunction

What is the difference between TestCafes t.eval() function and ClientFunctions?
I've been using TestCafe for a while now and didn't stumble across the eval function until now.
I am curious, but I also have a concrete use case, which is not the subject of this question, but might help me understand the difference between both.
I'd like to do simple page manipulation tasks like hiding elements from my tests code.
The documentation clearly says that ClientFunction should not be used for this: "Do not modify the tested webpage within client functions. Use test actions to interact with the page instead."
Is the eval function suitable for this?
In essence, they are the same. The difference is that ClientFunction creates an instance that can be saved to a variable and then reused several times, while t.eval works without saving. Also, t.eval is executed immediately, while ClientFunction is not - it creates an instance that you need to call explicitly in order to run it.

Should I put assertions inside object's methods or writing and calling a check representation fuction is enough?t

I wonder if writing a check representation function for an object and calling it while testing is enough to check the object's internal state corectness or should I also put assertions inside methods? Or maybe I should only use assertions inside methods and just don't include them in production version to not slow my app down?

How (and whether) to modify the object in a Chai BDD chain

I am using ChaiJS with my Casper-Chai plugin, and I am not sure how to go about a particular issue I am encountering.
I would like to be able to write tests such as:
expect(casper).selector("#waldo").to.be.visible;
This is pretty straightforward, with a call such as
utils.addChainableMethod(chai.Assertion.prototype, 'selector',
selectorMethod, selectorChainableMethod);
utils.addMethod(chai.Assertion.prototype, 'visible', visibleMethod);
Where the *Method references are to functions that perform respective tests or chainable calls.
My question is what is the best way to have e.g. 'selector' modify descendants in the chain. Two options come to mind:
use utils.flag(chai, 'object') to change it to the selector; or
create a new flag with e.g. utils.flag(chai, 'casper-selector')
When 'visible' is called, it can read the respective flag. Where modifying the 'object' seems to be useful is when calling e.g. 'length' later-on. However, I am concerned somewhat about unexpected side-effects of changing the 'object'.
I may also want to modify the object, for 'length' tests, down the chain, such as:
// there can be only one!
expect(casper).selector("#waldo").length(1)
// but that one has 4 classes
expect(casper).selector("#waldo").class.to.have.length(4)
Grateful for any thoughts and input.
---- EDIT ----
Okay, so here is the conceptual challenge that gave root to Casper-Chai, that requires a bit of a description of what Casper is and why Casper-Chai should be a Chai plugin and not just an alternative to the existing Casper API. Casper is a wrapper around the PhantomJS headless web browser, and as such Casper runs two effectively two distinct virtual machines: A
"Controller" and a headless web browser.
There is no DOM or "document" or "window" object in the controller; the Controller is in this respect a lot like Node.js, albeit using the WebKit javascript parser. In parallel, PhantomJS starts a headless web browser. The Controller can then communicate through a PhantomJS/Casper API to the headless browser. The Controller can tell the headless browser what pages to load, what javascript to run (which is like typing javascript into the console), and even mimic events such as keyboard input and mouse clicks. The headless browser has a full DOM and javascript stack: it is a web-page loaded in WebKit. You can capture screenshots of what WebKit would render.
Casper-Chai is run in the Controller. Tests created in Mocha + Chai in the Controller are meant to evaluate against the state of the headless browser. Although we can copy state from the browser to the Controller and run tests on that copied state, my limited experimentation with that design revealed problems inherent to the design (i.e. efficiency, race conditions, performance, and potential side-effects). The problem is that the browser state is dynamic, complex, and can be unwieldy.
So taking John's example, expect(casper.find("#waldo")).to.be.visible would not work, since there is no DOM, unless the object returned by Casper did some sort of lazy evaluation/mediation. Even if we serialized and copied the HTML element there there is no CSS in the Controller. Then, even if there were CSS for #waldo, there is no way to test the hierarchy as if it were a web-browser. We would have to copy a substantial portion of the DOM and all the CSS and then replicate a web-browser to test whether #waldo is visible - for every single test. Casper-Chai is meant to avoid this problem by running the tests in the browser.
Just for a little extra illumination, a trivial comparison is getting the number of elements that match a selector. One could write expect(casper.evaluate(function () {return __utils__.findAll('.my_class')}).to.have.length(4), where casper.evaluate runs the given function in the headless browser and returns a list of DOM elements matching the selector as strings; and you can think of __utils__ as Casper's version of jQuery. Alternatively, one could write expect(casper).selector('.my_class').to.have.length(4) where selector becomes the 'object' and it has a getter .length that calls 'casper.evaluate(function () { return utils.findAll('.my_class').length`. Only the integer length is returned. For a short number of tests either works fine, but for larger numbers of tests this performance characteristic becomes impactful (here, in this simplistic form, and potentially to a substantially greater extent in more complex cases).
One could of course write expect(casper.evaluate(function () { __utils__.findAll('.my_class').length }).equal(4), but if one is going to write tests like this, why bother with BDD/Chai? It eliminates the benefit of readability that Chai offers.
It is also worth noting that there may be multiple Casper instances in the Controller, corresponding to multiple PhantomJS pages. Think of them as spooky tabs.
So given Domenic's answer that modifying the 'object' flag is the appropriate way to go about it, this seems the most practical way - subject to any thoughts in light of the above description.
I hope the above describes why Casper-Chai should be a plugin and not just an API extension to Casper. I'll also run this by Casper's author to see if he has any input.
It may not be a perfect relationship, but I am hopeful that Casper & Chai can get along handily. :)
The difficulty stems from the fact that casper has a highly procedural API, with methods like Casper#click(String selector) and Casper#fetchText(String selector). To fit naturally with chai, an object-oriented API is needed, e.g. Casper#find(String selector) (returning a CasperSelection object), CasperSelection#click(), CasperSelection#text(), etc.
Therefore I suggest you extend the casper object itself with a find or selector method which returns an object on which you can base your assertions. Then you will not need to change the object flag.
expect(casper.find("#waldo")).to.be.visible;
expect(casper.find("#waldo")).to.have.length(1)
expect(casper.find("#waldo").class).to.have.length(4)
I mostly agree with #John. You're performing your expectations on some other object, so saying
expect(casper).select("#waldo").to.have.length(1)
is very strange. You're not expecting anything about casper, you're expecting something about casper.find("#waldo"). Consider also the should syntax:
casper.should.select("#waldo").have.length(1)
// vs.
casper.find("#waldo").should.have.length(1)
That said, if you're dead set on this kind of API, this is exactly what the object flag is for. Chai even does this, to make assertions like
myObj.should.have.property("foo").that.equals("bar")
work well:
https://github.com/chaijs/chai/blob/49a465517331308695c3d8262cdad42c3ac591ef/lib/chai/core/assertions.js#L773

Is there a way in IntelliJ to make a usage search of a method and filter this by specific arguments passed to the method?

I have a method in my Service class which executes an hibernate update for any domain object:
update(Object obj)
It's called from lot's of classes in my project for different kind of objects. I would like to find all usages of this method when it's called for a specific domain object. I.e. call methods call wich executes an update of my Title object:
serviceClass.update(Title title)
I'm using IntelliJ as my IDE and I'm wondering if there is a way to find all those usages.
Does anyone have an IDEA how to do this?
Thanks a lot in advance,
Ronny
I've tried it with a small sample project and was able to achieve the desired behavior using Structural Search and Replace feature with the modified method calls template:
$MethodCall$ Text constraints, Text/regexp should be set to update so that methods with other names are ignored. $Parameter$ Occurrences count, Minimum count should be set to 1 to ignore method calls with no or more parameters.
Results:
If you're interested in the call chains that are providing a specific input into a given method, try the Analyze->Data Flow to Here command.
This allows you to see which values are passed in, through which call chains. And, for example, where null values might be coming from.
Quite a powerful feature, really.