I have an angularjs webpage that prompts when I perform certain action on the page. The code should ignore and continue if there is no prompt, but if a prompt appears then ensure that the javascript prompt is accepted.
When I use firebug, I get the following property of the element.
/html/body/div[2]
The div[number] changes as and when I go to this page.I am not able to use the same in XPath as everytime the test case is executed, the div element would change. Also the div has an attribute of tabindex = -1.
bool status = false;
WebDriverWait wait = new WebDriverWait(webDriver, TimeSpan.FromSeconds(10));
IWebElement alert;
if (wait.Until(ExpectedConditions.InvisibilityOfElementLocated((By.XPath("/html/body/div[2]")
{
Console.WriteLine("I am in if loop");
status = false;
}
else
{
Console.WriteLine("I am in else loop");
alert = Browser.Driver.FindElement(By.XPath("/html/body/div[2]"));
((IJavaScriptExecutor)webDriver).ExecuteScript("arguments[0].click()", alert);
status = true;
}
return status;
How do I handle such a dialog box and ensure that the same is accepted when it appears.
Thanks.
You can derive the xpath using the title of the alert. May be like below. (I do not know the exact html, just imagining the header text is in some span tag)
alert = Browser.Driver.FindElement(By.XPath("/html/body//div/span[contains(text(),'Apply changes to controller configuration')]"));
(//) can avoid using index to your div tag.
Related
I currently have column A in the spreadsheet filled with checkboxes and have getA1Notation() used to grab this action when the user checks a box. I would then like to run an HTML dialog that has buttons to create an action for that row (HTML script not created yet, just running this test).
The issue I am running into is that when I put the HTML dialog box into a loop, it does not appear when the action (clicking on the checkbox) is done. I can replace the HTML dialog box with a prompt response or alert with buttons and it works perfect, but I would like to use an html box to have multiple custom buttons.
I am very new to using Apps Script for spreadsheets, so thank you for any help.
CODE:
function onEdit(e) {
for (var counter = 0; counter <= 500; counter = counter + 1)
{
const a1 = SpreadsheetApp.getActiveSheet().getRange(2+counter, 1).getA1Notation();
if (e.range.getA1Notation() == a1)
{
SpreadsheetApp.getActiveSheet().getRange(2+counter, 15).setValue('Hello'); //this is just to test the loop is working and doing this action anytime I click a checkbox
var tester = HtmlService.createHtmlOutput("<p>test</p").setWidth(250).setHeight(300);
SpreadsheetApp.getUi().showModelessDialog(tester, "teest");
}
}
}
Assign a function to each row
function onMyEdit(e) {
const sh = e.range.getSheet();
if(sh.getName() == "your sheet name" && e.range.rowStart < rowactions.length) {
const rowactions = ["","funk1","funk2","funk3"];//assigned functions
executeFunctionByName(rowactions[e.range.rowStart])
}
}
function executeFunctionByName(func) {
this[func]();
}
Probably need an installalble onedit.
Just stop, don't use a simple trigger that use a loop to show a dialog / sidebar.
The above because simple triggers have limitations, i.e. they have a shorter execution time limit, and they can't do some things that a function called from button / custom menu can do. They might be able to do certain tasks when the spreadsheet owner activates a trigger that might not work when a editor do the same.
By the other hand, SpreadsheetApp.getUi().showModelessDialog(tester, "teest"); is asynchronous, meaning that after executing this statement the runtime will execute the next one immediately, it will not wait for the Google Sheets UI to load the dialog.
Related
Creating a Dialog Prompt Box from an onEdit Function isn't working
I'm facing the following issue in protractor with jasmine
Click/mouse hover not working because of fixed top navigation bar in my application. I need to click/perform mouse hover on a web page.
Unfortunately that element is displaying behind that fixed navigation bar. So scroll till element present & click by x & y coordinates are not working.
My dependencies are :
protractor version 5.2.2
node 8.9.3
selenium standalone 3.13
chrome driver-2.40
chromebrowser v67
OS- Windows 10
Thanks in advance
Try using prototype executeScript
Just try clicking that element from the browser console using id,name or xpath.
For example :
var el = element(by.module('header'));
var tag = browser.executeScript('return arguments[0].click()', el).then(function() {
expect(something).toMatch(something);
});
Another way, along the same lines as what Bharath Kumar S and knowing JeffC's caveat that this approach is cheating, I had a similar issue where the App-Header kept getting in my way of clicking, and I knew I was willing to never need it (so, for instance, to find other ways to navigate or log out and not check for stuff that was on it). I, therefore, did the following, which solved the problem. Note if you refresh the screen, you have to call it again. Also note I am using a number of functions from https://github.com/hetznercloud/protractor-test-helper, which do what you would expect from their names.
var removeAppHeaderIfAny = async function() {
//this function hides the app header
//it is useful to avoid having covers there when Protractor worries that something else will get the click
let found = false;
try {
found = await waitToBeDisplayed(by.className("app-header"), 2000);
} catch (e) {
let s: string = "" + e;
if (s.search("TimeoutError") != 0) flowLog("presumably fine, cover already removed: " + e);
found = false;
}
if (!found) return;
if (found) {
let coverElement = await element(by.className("app-header"));
browser.executeScript(
"arguments[0].style.visibility='hidden';",
coverElement
);
await waitToBeNotDisplayed(by.className("app-header"), 10000);
}
return;
//note after this is called you will not see the item, so you cannot click it
};
As I look at the code, it strikes me one can probably remove the if (found) and associated brackets at the end. But I pasted in something I know has been working, so I am not messing with that.
As indicated up front, I knew I was willing to forego use of the app-header, and it is a bit crude.
I am creating an automated testing program with webdriverjs of an application where the 'Next' buttons are often disabled for a time, then enabled. The automation waits for the button to become enabled, then clicks the button.
The class of a button in particular toggles from : 'btn btn-next disabled' to 'btn btn-next'
I have come up with the following solution but wonder if there was a better way?
browser.wait(until.elementLocated(By.css('nav a[class="btn btn-next"]')),
timeout, 'button still disabled after timeout').then(function() {
browser.findElement(By.css('nav a[class="btn btn-next"]')).click();
});
Which seems to do the trick.
Originally my idea was to run function such as:
tryToClick = function(element){
var classValue = element.getAttribute("class");
isDisabled = classValue.search('disabled') !== -1 ? true : false;
if(isDisabled){
setTimeout(function () {
tryToClick(element);
}, 500);
} else {
element.click();
}
}
However, methods such as search, split, contains, etc resulted in errors. Does anyone know why?
Function name is elementToBeClickable()
Example:
WebDriverWait wait = new WebDriverWait(driver, 5);
wait.until(ExpectedConditions.elementToBeClickable(By.css('nav a[class="btn btn-next"]')));
In Webdriver JS you can use until.elementIsDisabled or until.elementIsEnabled
var theButton = driver.findElement(By.css('nav a[class="btn"));
driver.wait(until.elementIsDisabled(theButton)), 10000, 'element is still enabled, sorry.').then(function(){
theButton.click();
});
But it looks like you are selecting an entire class of buttons, if so, make sure your iterate over them and click the one you want, or use css nth-child();
I typically work in Java and C#, but there should be an equivalent option in JS. You will want to do an explicit wait using:
Until.ElementIsEnabled(<locator>)
If there isn't an equivalent to the above wait..until, you could resolve the issue by using element.isEnabled() == false in place of the isDisabled variable. In your code.
I understand that Ext.Msg.Confirm is asynchronous, and will proceed if you do not provide a callback.
Below is my code - this is called if the user tries to navigate from the current screen while in edit mode. I'm passing in a callback to the method - fn is my callback event, but regardless of how I code this the logic continues to navigate away from the page. Is there anyway to stop propagation until the user has selected yes or no in the confirmation box?
Here is the code for the Confirmation:
displaySaveConfirmation: function(fn) {
var title = 'Do you want to Save?'
var msg = 'You are currently Editing Standard Text. Would you like to save your changes?'
var box = Ext.Msg.confirm(title, msg, function(buttonId, value) {
if (buttonId === 'no'){
fn.call();
} else {
return false;
}
}, this );
box.setZIndex(400);
box.setCls('alert-box');
var buttons = Ext.ComponentQuery.query('button', box);
for (var i=0; i<buttons.length; i++) {
if (buttons[i].getItemId()=="no")
buttons[i].addCls('blackBtn');
else if (buttons[i].getItemId()=="yes")
buttons[i].addCls('blueBtn');
this.addReleaseEvent(box, buttons[i]);
}
},
As of now you do the following:
The event is fired
You open the MessageBox
Your function returns, and it does not return "false".
The browser navigates away before the user can click "yes" or "no".
What you want to do is the following:
The event is fired
You open the MessageBox
Your function returns false.
The browser does not navigate away.
The user clicks "yes" or "no".
If the answer is "yes", you navigate to the previously requested target page manually (e.g. close the browser window, use history.back() or similar).
Alternatively, if the work to get that up and running (and tested, with all the possible cases how to navigate away and how to find the target) is too much, you can opt for the window.alert dialog instead, which does not look nearly as nice, but works synchronously.
Or you can do as I did: I just returned false after bringing up a MessageBox that says: "You cannot leave the page during edit. Please save or abort the post."
How to return the results from the submission of a form to an iframe in cakephp?
Another question is, how to return some message to iframe for every iteration over the loop of a controller action. lets say it iterates for 10 times, so after every iteration, it will immediately show message like"iteration 1 completed" and so on... in the iframe....
I think you need to look at an AJAX approach to this. You can use Javascript to poke data into the iframe, but iterative interaction between the view and the controller is best done with an AJAX connection.
This is a quick and dirty approach I took.
At the end of the controller action:
App::import('Helper', 'Javascript');
$javascript = new JavascriptHelper();
echo($javascript->object($returnVals)); // allows passing of array
exit(1);
In the view, you need to capture the returned value and parse using JSON.parse:
<snip-->
if(xmlHttp)
{
xmlHttp.open("POST",actionURL,true);
xmlHttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
xmlHttp.onreadystatechange = function()
{
if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
{
doAction(xmlHttp.responseText,zone);
}
<--snip>
function doAction(props,zone)
{
var newProps = JSON.parse(props);//needs to be parsed into a JS object.
//other stuff here
}