I have a test, where I an trying to change the configuration:
$this->getModule('WebDriver')->_reconfigure([...]);
This shows what I am trying to do under "Dynamic Configration": http://codeception.com/docs/06-ReusingTestCode#.VnXNjq6rTUI
Edit:
It appears that I have to call this on the moduleContainer, but this is located at:
$I->scenario->test->moduleContainer->getModule('WebDriver')->_getConfig('url');
However $test is under private access, and there is no getTest() method.
Documentation says: You may call it from a helper class and pass in all the fields you want to change.
Add reconfigure method to your Acceptance helper and call it from your test.
Related
If I define a selector or function in one test, can I access it in another test or a test in another file/fixture? Similarly, is there a way to implement page models and for tests to use selectors defined within page?
TestCafe Studio does not allow sharing selectors and functions defined via the "Define Element Selector" and "Define Function" actions in codeless testing. However, you can import selectors using the Run TestCafe Script action.
For example:
The application I'm automating is using jQuery and ajax calls. Hence before interacting with elements, I wait for document to be ready and all ajax calls to complete. Only then I interact with element like sendKeys(), click() etc
For this, I need to add that method (say waitForDocumentReadyAndAjaxTocomplete()) explicitly everywhere wherever element is being interacted.
Is there anyway I can call that method waitForDocumentReadyAndAjaxTocomplete() implicitly before interacting with an element?
Yes, there is a way. You can create an utility class which creates your identifier using the locator you want to use and in the method where you create the identifier you can call the waitForDocumentReadyAndAjaxTocomplete method.
Basically the utility class will handle the call and you can actually have a try catch or a polling mechanism to optimize the call to the method as suits your requirement.
This way you donot have to call the waitForDocumentReadyAndAjaxTocomplete method everytime. It will be called in your utility class.
You can use the power of PageFactory.initElements(..) where you can:
Design your bindings in Page Object pattern
Intitialize elements of your page classes using your custom ElementLocatorFactory / ElementLocator. Where you can can add waiting of your dom events before finding elements.
You can check how AjaxElementLocatorFactory is implemented. There should not be issues with following this approach sine all key methods are public so can be simply overriden.
However I guess you will have to supply #CacheLookup annotation to all your fields annotated with #FindBy
I am looking to access the element and by variables which are globally available in my test, but when I try to call them from a helper module required/imported by the test I get an undefined error. How can I import these variables directly?
Make sure detox.init() call happens earlier than you access those variables (element, by) because init method is the actual place where Detox globally exposes them.
After you call await detox.init(<your options>), you'll be able to initialize your helpers.
Looks like PageObject doesn't work any more in Codeception 2.1
exactly it is impossible to use methods in PageObject class!
I do not want to put any methods to AcceptancTtester class, I would like to keep it as on example in codeception website in PageObject class
Just simply try to reproduce provided by codeception example from this page http://codeception.com/docs/06-ReusingTestCode#PageObjects
When try to run will get an error like:
[PHPUnit_Framework_Exception] Argument 1 passed to Page\Login::__construct() must be an instance of Page\AcceptanceTester
I guess it is because of _bootstrap.php is empty now
Could some one tell what we should I add to _bootstrap.php file (Before it profiled automatically while creating new Page using generate command from console)
It looks like a bug in documentation:
AcceptanceTester is not in the Page namespace.
Change
public function __construct(AcceptanceTester $I)
to
public function __construct(\AcceptanceTester $I)
I'm using openui5. There is a constructor Function for UI control Button,unable to see the prototype properties of the Button but the same thing when executed in browser console, shows up!
sap.m.Button.prototype.Move = function(){
console.log('Move');
}
var oButton = new sap.m.Button({text:"Hello"});
oButton.Move(); // throws undefined function!
The same code when executed browser in console, it works!
jsbin --> http://jsbin.com/tepum/1/edit
After running the code I find that creating the first instance of sap.m.Button causes script to change the prototype of sap.m.Button. It's valid in JavaScript but not very smart if you ask me.
A first creation causes a synchronous request (no no as well) to fetch library-parameters.json.
If you run the code the second time it will have prototype.move because creating an instance of Button will not change the Button.prototype.
The capital M in Move would suggest a constructor function so I would advice changing it to lower case.
Since fetching the parameters is synchronous you can create the first instance and then set the prototype:
console.log("First Button creation changes Button.prototype");
var oButton = new sap.m.Button({text:"Hello"});
sap.m.Button.prototype.move = function(){
console.log('Move');
}
oButton.placeAt('content');
oButton.move(); // logs Move
My guess is that this is done to lazy load controls, if a Button is never created then the json config files are never loaded for these unused controls. It has a couple of drawbacks though.
You have to create an instance first before you can set the prototype.
The config files are synchronously loaded so when creating first instance of many controls with a slow connection would cause the app to be unresponsive.
A better way would be for a factory function to return a promise so you create the control the same way every time and the config files can be fetched asynchronously.
[update]
Looking at the config it seems to be config for the whole gui library so I can't see any reason why this is loaded only after creating a first instance. A library that changes it's object definitions when creating instances is not very easy to extend because it's unpredictable. If it only changes prototype on first creation then it should be fine but it looks like the makers of the library didn't want people to extend it or they would not make the object definition unpredictable. If there is an api documentation available then maybe try to check that.
[update]
It seems the "correct" way to extend controls is to use extend.
#HMR is right the correct way to extend a control is by using the extend function provided by UI5 managed objects, see http://jsbin.com/linob/1/edit
in the example below when debugging as mentoned by others you will notice that the control is lazy loaded when required, any changes you make prior are lost when loaded
jQuery.sap.declare("my.Button");
jQuery.sap.require("sap.m.Button");
sap.m.Button.extend("my.Button", {
renderer: {}
});
my.Button.prototype.Move = function() {
console.log('Move');
};
var oButton = new my.Button({
text: "Hello"
});
oButton.placeAt('content');
oButton.Move();
It's not hiding the prototype per se. If a constructor function exits normally then you get that function's prototype. But, if a constructor function actually returns some other object then you get that other object's prototype, so it's not valid to assume that just because you added to the Button prototype that when you call new Button() that you will see your method on whatever you get back. I'm sure if you de-obfuscate that code you'll find that the constructor you are calling has a "return new SomeOtherInstanceOfButton()" or similar at the end of it.
Edit: Ok it's a bit difficult to see what's really going on in that sap code but, it looks like they have code that overwrites the prototypes of controls to add features to them, such as: sap.ui.core.EnabledPropagator, and those things aren't run until you actually instantiate a button. So if you change your code to instantiate the button on the page, then add to it's prototype, then construct and call the method, it works fine. Like so:
http://jsbin.com/benajuko/2/edit
So I guess my answer is, when you run it from console it's finished mucking around with that prototype, whereas in your test you were adding to the prototype, then constructing the button for the first time (which changes the prototype again) then trying to call your old one, which is no longer there.