Is it really necessary using waitForElement or another wait... if I test javascript single page application with loaded by ajax states? I must precede every action (eg: click,type) by waitForElement.
yes, it is necessary for Ajax. But it is not a problem if you use "don't repeat yourself" principle. You should create method like this:
clickWithExplicitWait(lctr) {
waitForElementPresent(lctr)//uses ajax wait timeout
driver.click(lctr)//uses implicit wait timeout
}
driver.click() uses implicit wait. So you can specify a different timeouts for implicit wait and for explicit "element wait".
You can implement waitForElementPresent() or other similar methods using org.openqa.selenium.support.ui.ExpectedConditions package.
If you need to wait for another element to appear after action, use something like:
clickAndWait(lctrToClick, lctrToWait) {
driver.click(lctrToClick)
waitForElementPresent(lctrToWait)
}
Related
Per definition,
An implicit wait is to tell Web Driver to poll the DOM for a certain amount of time when trying to find an element or elements if they are not immediately available.
See Implicit wait
Timeout for a WebElement will be assigned to the Object page class with the help of AjaxElementLocatorFactory
See AjaxElementLocatorFactory
From above, it's not clear what exactly the difference between implicit wait and AjaxElementLocatorFactory. Please explain.
Implicit Wait
An implicit wait is the approach to configure the WebDriver to poll the DOM for a certain amount of time when trying to find element/s if they are not immediately available within the HTML DOM. The default setting is 0. Once set, the implicit wait is set for the life of the WebDriver object instance.
You can find a couple of relevant discussions in:
Using implicit wait in selenium
selenium implicitly wait doesn't work
Python & Selenium: Difference between driver.implicitly_wait() and time.sleep()
AjaxElementLocatorFactory
AjaxElementLocatorFactory is one of the key advantage in implementing a waiter when using page-factory using the AjaxElementLocatorFactory Class.
AjaxElementLocatorFactory is basically the lazy-loading concept implemented with in Page Factory pattern to identify WebElements only when they are used in any operation i.e. a timeOut for a WebElement which can be assigned to the Object page class with the help of AjaxElementLocatorFactory.
An example:
AjaxElementLocatorFactory myFactory = new AjaxElementLocatorFactory(driver, 20);
PageFactory.initElements(myFactory, this)
Explaination:
In the above code block, when an operation is performed on an element the wait for its visibility starts from that moment only. If the element is not found in the given time interval, Test Case execution will throw NoSuchElementException exception.
You can find a relevant discussion in How to implement AjaxElementLocatorFactory through Selenium and Page Factory?
Implicit wait is something that is relevant to the entire driver object (and applicable to all lookups performed in the context of the driver). AjaxElementLocatorFactory is used when you initiate elements of your Page class. So that the waits are only be relevant to the elements which you describe within your Page class.
Since AjaxElementLocatorFactory utilizes the basic lookups but just wraps it with some more flexible logic, implicit wait that is applicable to all the lookups performed within your driver context might be added to the timeouts you have set up for your AjaxElementLocator (depending on the circumstances). Hence it is not recommended to mix them and in general it is recommended to avoid using implicit waits (it is set to 0 by default).
In asp.net core ViewComponent we have to implement logic in an InvokeAsync method that returns an IViewComponentResult. However I do not have any async logic to perform inside the invoke method. So based on SO post here I have removed the async qualifier and just return Task.FromResult
public Task<IViewComponentResult> InvokeAsync(MyBaseModel model)
{
var name = MyFactory.GetViewComponent(model.DocumentTypeID);
return Task.FromResult<IViewComponentResult>(View(name, model));
}
and then in View ( since I don't have async I am not using await here)
#Component.InvokeAsync("MyViewComponent", new { model = Model })
However view renders this:
System.Threading.Tasks.Task1[Microsoft.AspNetCore.Html.IHtmlContent]`
You must await the Component.InvokeAsync. The fact that your method doesn't do anything async doesn't matter. The method itself is async.
However, that's a bit of an oversimplification. Frankly, the ease of the async/await keywords belies how complicated all this actually is. To be accurate, instead of calling these types of methods "async", it's more appropriate to discuss them as "task-returning". A task is essentially a handle for some operation. That operation could be async or sync. It's most closely associated with async, simply because wrapping sync operations in a task would be pretty pointless in most scenarios. However, the point is that just because something must return a task does not also imply that it must be async.
All async does is allow the possibility of a thread switch. In scenarios where there's some operation, typically involving I/O, that would cause the working thread to be idle for some period of time, the thread becomes available to be used for other work, and the original work may complete on a different thread. Notice the use of the passive language here. Async operations can involve no thread switching; the task could complete on the same thread, as if it was sync. The task could even complete immediately, if the underlying operation has already completed.
In your scenario here, you're not doing any async work, which is fine. However, the method definition requires Task<T> as the return, so you must use Task.FromResult to return your actual result. That's all pretty standard stuff, and seems to be understood already by you. What you're missing, I think, is that you're thinking that since you're not actually doing any asynchronous work, it would be wrong to utilize await. There's nothing magical about the await keyword; it basically just means hold here until the task completes. If there's no async work to be done, as is the case here, the sync code will just run as normal and yield back to the calling code when done, However, as a convenience, await also performs one other vital function: it unwraps the task.
That is where your problem lies. Since you're not awaiting, the task itself is being returned into the Razor view processing pipeline. It doesn't know what to do with that, so it does what it does by default and just calls ToString on it, hence the text you're getting back. Unwrapped, you'd just have IViewComponentResult and Razor does know what to do with that.
If your logic performed inside the invoke method is synchronous, i.e., you don't have any await, you have 2 options:
You can define invoke method without async keyword and it should return Task.FromResult<T>
Use public IViewComponentResult Invoke() instead.
I think the async keyword enables the await keyword and that's pretty much about it. Nothing special about async keyword.
On the main thread where your view is getting rendered, since the tag helper method
to invoke a view component Component.InvokeAsync() is awaitable, you do need to put await keyword there to start the task. await examines the view component rendering to see if it has already completed. If it has, then the main thread just keeps going. Otherwise the main thread will tell the ViewComponent to run.
In default I run tests with goutte. How can I set different driver for one step? For example to take screenshot after failed step I need selenium driver. And I don't know which step will fail.
Have a look at the Mink docs, specifically the managing sessions chapter to learn how to change the default driver. If you're not familiar with Behat hooks it's also good to catch up with Hooking into the Test Process docs.
Here's an example of how you could access mink and change the default session. Once this method is executed, all the following operations on the session object will be perform through the selected driver.
use Behat\Behat\Hook\Scope\BeforeStepScope;
use Behat\Behat\Hook\Scope\AfterStepScope;
class MyContext extends RawMinkContext
{
/**
* #BeforeStep
*/
public function before(BeforeStepScope $scope)
{
// note that this will be called before EVERY step
// add logic here if you want to perform it before SOME steps
// You can't really know if your step will fail though ;)
$mink = $this->getMink();
$mink->setDefaultSessionName('selenium');
}
public function after(AfterStepScope $scope)
{
// here you can inspect $scope to see if your step failed
}
}
This is not a complete solution, but should point you into the right direction if you really want to pursue it.
However, I strongly discourage you from doing so.
If your step failed it was already executed. To make a screenshot you would need to execute the step again with a different driver. The state of the app would be most likely different at this point. You'd also need to fight with differences between the drivers, try to share the cookie etc. It's just not worth the effort.
Instead, simply dump an html. You can always display it in a browser.
How can I simulate this feature? It seems like a conscious choice to have a WaitForDeletedById but not the reverse.
Upon an ajax load, how can I wait for the existence of a new element on the page, rather than the absence of one?
Use setFindTimeout to set how long the test should wait for an element to exist, then use the normal find methods. The only reason that a special waitForDeleted method exists is because it has to use a local polling method to efficiently respond to an element being deleted, whereas waiting for an element until it exists is functionality that is supported natively by the remote Selenium server.
How can I use explicit waits using intern's leadfoot API for functional testing in intern?
There are multiple scenarios where I want to explicitly poll until a condition is met. For example, I want to wait until two or more elements exist in the DOM. Using findAllByCssSelector locks the execution for the whole implicit wait time instead of returning immediately after the condition is true.
All I can see that will help me is the pollUntil helper function, but it looks like this does not have access to any of the module dependencies defined in the test module.
How can I use something like jQuery within pollUntil?
findAllByCssSelector only waits for the implicit wait if no elements are found. If elements exist, the method finishes immediately with whatever it finds, so it's not ideal if you need to wait for a specific number of elements to appear.
pollUntil is the way to go for conditional waits. You are correct, though, that it doesn't have access to your module dependencies. Your dependencies are loaded in the context of Intern's test runner, while the pollUntil condition is going to run in the context of the browser. There are a couple ways to get the code you need into the browser. If you control the test page, you could just modify it to load whatever modules you need before the tests run. If you can't modify the test page, you could use an executeAsync call after loading the page in your test to inject whatever modules you need into the page context.