Dusk cannot dismiss dialog because of UnexpectedAlertOpenException - phpunit

I am using Laravel Dusk to write browser tests for a Laravel 5.7 application. In the test I am navigating to the page and clicking a button which triggers a confirm dialog. I am trying to test that dismissing the dialog does not change the page url.
I have tried adding $this-expectException(UnexpectedAlertOpenException::class) before running the test to try to make the code understand a dialog should be shown
{
$this->expectException(UnexpectedAlertOpenException::class);
$this->browse(function (Browser $browser) {
$browser->loginToWave()
->goToSystemsEdit();
$browser->waitFor('#delete-systems-button')
->click('#delete-systems-button')
->assertDialogOpened('This will delete the system. Please seek advice before doing this. Continue?')
->dismissDialog()
->assertPathBeginsWith('systems/edit');
});
}
I expect the test to dismiss the dialog and check the path assertion.
What is actually happening is that an UnexpectedAlertOpenException is thrown:
1) Tests\Browser\Systems\DeleteSystemTest::testSystemNotDeletedIfConfirmIsDismissed
Facebook\WebDriver\Exception\UnexpectedAlertOpenException: unexpected alert open: {Alert text : This will delete the system. Please seek advice before doing this. Continue?}
(Session info: chrome=71.0.3578.98)
(Driver info: chromedriver=2.45.615279 (12b89733300bd268cff3b78fc76cb8f3a7cc44e5),platform=Linux 4.9.125-linuxkit x86_64)
/var/www/html/vendor/facebook/webdriver/lib/Exception/WebDriverException.php:140
/var/www/html/vendor/facebook/webdriver/lib/Remote/HttpCommandExecutor.php:326
/var/www/html/vendor/facebook/webdriver/lib/Remote/RemoteWebDriver.php:547
/var/www/html/vendor/facebook/webdriver/lib/Remote/RemoteWebDriver.php:345
/var/www/html/vendor/laravel/dusk/src/Browser.php:261
/var/www/html/vendor/laravel/dusk/src/Concerns/ProvidesBrowser.php:139
/var/www/html/vendor/laravel/framework/src/Illuminate/Support/Collection.php:418
/var/www/html/vendor/laravel/dusk/src/Concerns/ProvidesBrowser.php:140
/var/www/html/vendor/laravel/dusk/src/Concerns/ProvidesBrowser.php:69
/var/www/html/tests/DuskTestCase.php:68

Related

Unable to close SysBoxForm in unit test X++

When I close a SysQueryForm (by clicking on Ok button), a system generated dialog box appears on the form as shown below:-
I am writing a unit test to close this dialogue box but when I try to close the sysbox form by using the X++ code below:-
using (SysBoxFormAdaptor sysBoxForm = SysBoxFormAdaptor::attach())
{
sysBoxForm.CloseCtrl().click();
}
I am getting the following error:-
Cannot access form CPool id 3: topmost form is SysBoxForm id 181<\error>
There are open forms on the client: {"CPool (3)", "SysBoxForm (181)"}<\error>
To give a context, CPool is the form on which selecting a button opens a SysQueryForm and after selecting a criteria on the SysQueryForm for a particular table due to some join issue this system dialogue comes which cannot be fixed as of now.
I have tried some other ways as well but they too end up throwing the same error.
So the issue is that SysBoxForm is not closing.
Since this is a system generated (kernel level) dialogue, does anyone know how to close it?
So after further debugging I found out that two SysBoxForms are getting opened, one on top of the other. So closed them by attaching SysBoxFormAdaptor twice and it worked:-
using (SysBoxFormAdaptor sysBoxForm = SysBoxFormAdaptor::attach())
{
sysBoxForm.CloseCtrl().click();
}
using (SysBoxFormAdaptor sysBoxForm = SysBoxFormAdaptor::attach())
{
sysBoxForm.CloseCtrl().click();
}
This was the reason I was getting the error that a SysBoxForm is open.

Recognizing and Clicking Alert with RSelenium

I'm having some difficulty with an alert I receive during a for loop. Effectively, I can't figure out how to recognize the alert when it comes up and then close it. So far, I've tried this:
if (is.character(mybrowser$getAlertText()) == TRUE) {
mybrowser$acceptAlert
}
I got it to recognize the alert text once, but when I try to use that in the if statement above it doesn't work. For reference, this is what the alert looks like (I'm using Windows 10, I know, I know).
UPDATE: I tried using a try function and it still won't close the alert but hangs instead. When I stop the program and attempt to close the alert in the console with mybrowser$acceptAlert(), it won't recognize the alert and hangs as well. mybrowser$switchToWindow(window) hangs as well. The page appears to be loading while the alert appears. I don't know if that matters.
I noticed you mentioned you've tried try function but alert still be there sometimes. You can try try(mybrowser$acceptAlert(), silent = TRUE) to handle error message instead of detecting your browser receiving an alert or not.
If alert happened, acceptAlert() function would be equivalent to clicking the OK button. If not, try() function would store error messages and handle it.

watchOS simple wakeup

Here is some watchOS code I have working on the Similator(Watch):
.....
let interval = 60.0
NSTimer.scheduledTimerWithTimeInterval(interval,
target: self,
selector: #selector(InterfaceController.timerDidEnd(_:)),
userInfo: nil, repeats: false)
.....
func timerDidEnd(timer:NSTimer) {
print("Time is over! Please wake up!")
}
From Xcode I run the app, the first part of the code above gets executed. Then I hit Command-Shift-H and the app goes in the background.
After one minute I see in the debugging console the message: Time is over! Please wake up!
All works as I expect. My question is:
What should I write inside the function timerDidEnd(), in order to have the app wake up from the background on the simulator, rather than just printing the current message in the debugger?
There's nothing you can write inside a timer action that will bring an app to the foreground. Only the user can resume an app.
If you think about it, it would confusing and disruptive for the user if an app could programmatically bring itself to the foreground whenever it wanted.
The only way to resume an app is by the user reacting to a notification. This is similar to what happens on the phone when the user taps notification actions from the home screen.

How to test a confirm dialog with Cucumber?

I am using Ruby on Rails with Cucumber and Capybara.
How would I go about testing a simple confirm command ("Are you sure?")?
Also, where could I find further documentation on this issue?
The selenium driver now supports this
From Capybara you would access it like this:
page.driver.browser.switch_to.alert.accept
or
page.driver.browser.switch_to.alert.dismiss
or
page.driver.browser.switch_to.alert.text
Seems like there's no way to do it in Capybara, unfortunately. But if you're running your tests with the Selenium driver (and probably other drivers that support JavaScript), you can hack it. Just before performing the action that would bring up the confirm dialog, override the confirm method to always return true. That way the dialog will never be displayed, and your tests can continue as if the user had pressed the OK button. If you want to simulate the reverse, simply change it to return false.
page.evaluate_script('window.confirm = function() { return true; }')
page.click('Remove')
I've implemented these two web steps in /features/step_definitions/web_steps.rb:
When /^I confirm popup$/ do
page.driver.browser.switch_to.alert.accept
end
When /^I dismiss popup$/ do
page.driver.browser.switch_to.alert.dismiss
end
If you want to specifically test the message being displayed, here's a particularly hacky way to do so. I don't endorse it as beautiful code, but it gets the job done. You'll need to load http://plugins.jquery.com/node/1386/release, or change it to do cookies natively if you don't want jQuery.
Use this sort of story:
Given I am on the menu page for the current booking
And a confirmation box saying "The menu is £3.50 over budget. Click Ok to confirm anyway, or Cancel if you want to make changes." should pop up
And I want to click "Ok"
When I press "Confirm menu"
Then the confirmation box should have been displayed
And these steps
Given /^a confirmation box saying "([^"]*)" should pop up$/ do |message|
#expected_message = message
end
Given /^I want to click "([^"]*)"$/ do |option|
retval = (option == "Ok") ? "true" : "false"
page.evaluate_script("window.confirm = function (msg) {
$.cookie('confirm_message', msg)
return #{retval}
}")
end
Then /^the confirmation box should have been displayed$/ do
page.evaluate_script("$.cookie('confirm_message')").should_not be_nil
page.evaluate_script("$.cookie('confirm_message')").should eq(#expected_message)
page.evaluate_script("$.cookie('confirm_message', null)")
end
Updating this for current releases of Capybara. Most Capybara drivers today support the modal API. To accept a confirm modal you would do
accept_confirm do # dismiss_confirm if not accepting
click_link 'delete' # whatever action triggers the modal to appear
end
This can be used in Cucumber with something like
When /^(?:|I )press "([^"]*)" and confirm "([^"]*)"$/ do |button, msg|
accept_confirm msg do
click_button(button)
end
end
which will click the named button and then accept a confirm box with text matching msg
The capybara-webkit driver supports this as well.
Scenario: Illustrate an example has dialog confirm with text
#
When I confirm the browser dialog with tile "Are you sure?"
#
=====================================================================
my step definition here:
And(/^I confirm the browser dialog with title "([^"]*)"$/) do |title|
if page.driver.class == Capybara::Selenium::Driver
page.driver.browser.switch_to.alert.text.should eq(title)
page.driver.browser.switch_to.alert.accept
elsif page.driver.class == Capybara::Webkit::Driver
sleep 1 # prevent test from failing by waiting for popup
page.driver.browser.confirm_messages.should eq(title)
page.driver.browser.accept_js_confirms
else
raise "Unsupported driver"
end
end
Prickle adds some handy convenience methods for working with popups in selenium and webkit
This gist has steps to test a JS confirm dialog in Rails 2 and 3 with any Capybara driver.
It's an adaptation of a previous answer, but doesn't need the jQuery Cookie plugin.
Tried the above answers with no luck. In the end this worked for me:
#browser.alert.ok

Selenium IDE click() timeout

I have a simple page that returns an ajax success/error message on submission. The form is submitted using a standard ASP.Net linkbutton.
My Selenium test correctly clicks the linkbutton, however the click event times out and fails. The rest of the testcase conditions pass (as selenium is successfully clicking the link and the ajax success message is displayed).
All I can think is that for some reason click() is calling waitForPageToLoad which is why it is timing out. Is there any way to suppress this, or am I barking up the wrong tree?
Is there an alternative way to handle the click that doesn't care what happens after the event fires?
More Info: Selenium IDE 1.0.2 hosted in Firefox 3.5.2 on Vista (don't ask)
Workaround
I've managed to get my test to pass by creating my own click() function in user-extensions.js that does not call Selenium.decorateFunctionWithTimeout(). While my test does pass now, this is not really an ideal solution.
If you'd like to try this yourself, add the following to user-extensions.js (make sure you are referencing this file in your Se:IDE configuration via Tools | Selenium IDE | Options | Options | General | Selenium Core extensions)
Selenium.prototype.doBeatnicClick = function(locator) {
/**
* Clicks on a link, button, checkbox or radio button.
* Hacky workaround for timeout problem with linkbutton.
* Suspect there is an issue with Selenium.decorateFunctionWithTimeout()
*/
var element = this.browserbot.findElement(locator);
var elementWithHref = getAncestorOrSelfWithJavascriptHref(element);
if (browserVersion.isChrome && elementWithHref != null) {
var win = elementWithHref.ownerDocument.defaultView;
var originalLocation = win.location.href;
var originalHref = elementWithHref.href;
elementWithHref.href = 'javascript:try { '
+ originalHref.replace(/^\s*javascript:/i, "")
+ ' } finally { window._executingJavascriptHref = undefined; }';
win._executingJavascriptHref = true;
this.browserbot.clickElement(element);
}
this.browserbot.clickElement(element);
};
Reload Se:IDE and you'll have access to a new command, beatnicClick() which should work where you're experiencing a click() timeout.
Hopefully this will be patched, or fixed in the next release of Se:IDE.
I believe this is raised in the OpenQA Jira: http://jira.openqa.org/browse/SIDE-316. It has also been discussed here: http://clearspace.openqa.org/message/64455
Until the issue has been resolved you can revert to the 1.0b2 version of Selenium IDE http://release.seleniumhq.org/selenium-ide/1.0-beta-2/ but this wont install on Firefox 3.5.x unless you disable extensions.checkCompatability in about:config. See http://kb.mozillazine.org/Extensions.checkCompatibility
I was hitting what I assume is this bug when testing a GWT site with Selenium IDE 1.0.2. I just updated to 1.0.4 and don't have it any more.

Resources