capybara can not find file input field to attach file - ruby

I use ruby, cucumber and capybara.
My html looks like this:
<tr>
<th>
Promotion codes
</th><td><div class="t-zone" id="promocodesZone">
<span style="display: inline-block;">
<span class="field"><label class="field-label">File name:
<span style="text-transform: none;" class="status-ok"></span></label></span>
<span class="field"><label class="field-label">Codes available:
<span style="text-transform: none;" class="status-ok">0</span></label></span>
<span class="field"><label class="field-label">Codes used:
<span style="text-transform: none;" class="status-ok"></span></label></span>
<span class="field"><label class="field-label">Codes uploaded on:
<span style="text-transform: none;" class="status-ok"></span></label></span>
</span>
<div style="margin-bottom: 15px;"><div class="t-upload">
<div id="promocodesUpload">
<div class="qq-uploader">
<div class="qq-upload-drop-area" style="display: none;"><span>Drop </span></div>
<a class="qq-upload-button btn" style="position: relative; overflow: hidden; direction: ltr;">Upload
<input type="file" name="file" style="position: absolute; right: 0px; top: 0px; font-family: Arial; font-size: 118px; margin: 0px; padding: 0px; cursor: pointer; opacity: 0;"></a>
<ul class="qq-upload-list"></ul></div></div>
</div>
</div>
</div>
</td>
</tr>
Basically what I need to do is to upload a file by clicking on link "Upload":
<a class="qq-upload-button btn" style="position: relative; overflow: hidden; direction: ltr;">Upload<input type="file" name="file" style="position: absolute; right: 0px; top: 0px; font-family: Arial; font-size: 118px; margin: 0px; padding: 0px; cursor: pointer; opacity: 0;"></a>
But I keep failing because capybara is unable to find the necessary element...
I have tried many things already:
attach_file('//*[#id="promocodesUpload"]/div/a/input', File.absolute_path($campaign_promotional_code_path))
Result: Unable to find file field "//*[#id=\"promocodesUpload\"]/div/a/input" (Capybara::ElementNotFound)
and
within(:xpath, '//*[#id="promocodesUpload"]/div/a') do
attach_file("input", File.absolute_path($campaign_promotional_code_path))
end
Result: Unable to find file field "input" (Capybara::ElementNotFound)
and
attach_file("Upload", File.absolute_path($campaign_promotional_code_path)
Result: Unable to find file field "Upload" (Capybara::ElementNotFound)
and
click_link("Upload")
Result: Unable to find link "Upload" (Capybara::ElementNotFound)
and
Any help please? :)

Try this:
page.driver.browser.all(:xpath, '//input[#name="file"]')[0].send_keys('/home/userA/Desktop/chivalry-medieval-warfare.jpg')
or:
page.driver.browser.all(:xpath, '//input[#type="file"]').last.send_keys('/home/userA/Desktop/chivalry-medieval-warfare.jpg')

Capybara can't find the file input because it's opacity is 0, so it's hidden on the page. - Your best bet is to use execute_script to modify the file inputs style attribute so it becomes visible before calling attach_file

If you have jQuery on your web page:
page.execute_script("$('input[name=file]').css('opacity','1')")
If you don't have jQuery on your web page:
page.execute_script("document.getElementsByName('file')[0].style.opacity = 1")

As per documentation you can set make_visible option to true if the element is hidden somehow.
# will attach file to a descendant file input element that has a name, id, or label_text matching 'My File'
page.attach_file('My File', '/path/to/file.png', make_visible: true)

attach_file("user[logo]", Rails.root + "app/assets/images/image.jpeg", make_visible: true)
It is better: "In the case of the file field being hidden for styling reasons the make_visible option can be used to temporarily change the CSS of the file field, attach the file, and then revert the CSS back to original."
make_visible: true
As recommended here: https://www.rubydoc.info/gems/capybara/Capybara%2FNode%2FActions:attach_file

Related

Text over image working fine in firefox but not in chrome

I'm trying to add some text over an image. I've set the position of the image to relative and the position of the text is absolute. It's working completely fine in Firefox but not in Chrome.
All I see in Chrome is an image.
Can anybody help me out in this ?
My code:
<p class="call text-right hidden-xs tel">
Call: 1-800-378-7566
</p>
<img src="img/slider/slider01.jpg" alt="" title="" style="margin-top:-28px; position:relative;" />
this could help you.
added
<p class="call text-right hidden-xs tel">
<a href="tel:+18003787566" style="position: absolute;
top: 50px;
left: 10px;
padding: 6px;
background-color: #292D30;
font-size: 26px;
padding-left: 100px;
padding-right: 127px;
z-index: 999;">Call: 1-800-378-7566</a>
</p>
Added top and left position as well as added z-index.
See the example
http://jsfiddle.net/nanduh/wo2eyhp6/

getHtml() function in CKEditor not performing as expected

The Project:
I am creating a prototype plugin using CKEditor v4.3.
The plugin loads an iframe of a page I have already created (in the same project). The contents inside the iframe is a necessary part of the project, thus I must use it. Once the plugin loads, I traverse the iframe & get the Body contents of the iframe. After OnOk, I perform getHtml() to get the latest contents and then insertHtml into the editor.
The problem:
The results from getHtml() (see code) is not the same as what is in the dom. The markup is getting changed and removed. All I want is to have the same markup that appears in the dom.
The Code: Here is my plugin code:
var iframeWindow = null;
var theElement = null;
CKEDITOR.plugins.add('airmath',
{
requires: 'iframedialog',
icons: 'airmath',
init: function (editor) {
var height = 480;
var width = 750;
var url = CKEDITOR.basePath + 'plugins/airmath/integration/airmath.html';
CKEDITOR.dialog.addIframe(
'myiframedialogDialog',
'Math Editor',
url, width, height,
function () {
theElement = this.getElement();
iframeWindow = theElement.getFrameDocument().getBody();
},
{
onOk: function () {
editor.insertHtml(iframeWindow.getHtml());
}
}
);
editor.addCommand('myiframedialog', new CKEDITOR.dialogCommand('myiframedialogDialog'));
editor.ui.addButton('AirMath',
{
label: 'Math Editor',
command: 'myiframedialog',
toolbar: 'insert'
});
}
});
The dom:
This is the dom from chrome developer tools:
<span class="MathJax" id="Eq-Editor-Eq-Container-1-1-Frame" role="textbox" aria-readonly="true" style="">
<nobr>
<span class="math" id="MathJax-Span-1" style="width: 15.642em; display: inline-block;">
<span style="display: inline-block; position: relative; width: 7.933em; height: 0px; font-size: 197%;">
<span style="position: absolute; clip: rect(1.461em 1000.002em 2.667em -0.22em); top: -2.314em; left: 0.002em;">
<span class="mrow" id="MathJax-Span-2">
<span class="mstyle" id="MathJax-Span-3">
<span class="mrow" id="MathJax-Span-4">
<span class="texatom" id="MathJax-Span-5">
<span class="mrow" id="MathJax-Span-6">
<span class="mi" id="MathJax-Span-7" style="font-family: MathJax_Math; font-style: italic;">f
<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.065em;">
</span>
</span>
<span class="mfenced" id="MathJax-Span-8">
<span class="mo" id="MathJax-Span-10" style="">
<span style="font-family: MathJax_Main;">(</span>
</span>
<span class="texatom" id="MathJax-Span-11">
<span class="mrow" id="MathJax-Span-12">
<span class="mi" id="MathJax-Span-13" style="font-family: MathJax_Math; font-style: italic;">x</span>
</span>
</span>
<span class="mo" id="MathJax-Span-14" style="">
<span style="font-family: MathJax_Main;">)</span>
</span>
</span>
<span class="mo" id="MathJax-Span-15" style="font-family: MathJax_Main; padding-left: 0.287em;">=</span>
<span class="mn" id="MathJax-Span-16" style="font-family: MathJax_Main; padding-left: 0.287em;">5</span>
<span class="mn" id="MathJax-Span-17" style="font-family: MathJax_Main;">0</span>
<span class="mn" id="MathJax-Span-18" style="font-family: MathJax_Main;">0</span>
<span class="mo" id="MathJax-Span-19" style="font-family: MathJax_Main; padding-left: 0.224em;">×</span>
<span class="mn" id="MathJax-Span-20" style="font-family: MathJax_Main; padding-left: 0.224em;">1</span>
<span class="mo" id="MathJax-Span-21" style="font-family: MathJax_Main;">.</span>
<span class="msup" id="MathJax-Span-22" style="padding-left: 0.16em;">
<span style="display: inline-block; position: relative; width: 0.985em; height: 0px;">
<span style="position: absolute; clip: rect(1.429em 1000.002em 2.286em -0.22em); top: -2.188em; left: 0.002em;">
<span class="mn" id="MathJax-Span-23" style="font-family: MathJax_Main;">2</span>
<span style="display: inline-block; width: 0px; height: 2.191em;">
</span>
</span>
<span style="position: absolute; top: -2.156em; left: 0.509em;">
<span class="mi" id="MathJax-Span-24" style="font-size: 70.7%; font-family: MathJax_Math; font-style: italic;">x</span><span style="display: inline-block; width: 0px; height: 1.747em;">
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
<span style="display: inline-block; width: 0px; height: 2.318em;">
</span>
</span>
</span>
<span style="border-left-width: 0.003em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 2.128em; vertical-align: -0.559em;">
</span>
</span>
</nobr>
</span>
<script id="Eq-Editor-Eq-Container-1-1" type="math/mml"><math xmlns="http://www.w3.org/1998/Math/MathML">
<mstyle displaystyle="true">
<mrow class="MJX-TeXAtom-ORD">
<mi>f</mi>
<mfenced open="(" close=")">
<mrow class="MJX-TeXAtom-ORD">
<mi>x</mi>
</mrow>
</mfenced><mo>=</mo>
<mn>5</mn>
<mn>0</mn><mn>0</mn>
<mo>×<!-- × --></mo>
<mn>1</mn>
<mo>.</mo>
<msup>
<mn>2</mn>
<mi>x</mi>
</msup>
</mrow></mstyle>
</math>
</script>
<input type="text" class="hidden" id="Eq-Container-1_input_Eq-Editor-Eq-Container-1-1" name="Eq-Container-1_input_Eq-Editor-Eq-Container-1-1">
The Results:
And this is what I get in the ckEditor window after clicking "Ok" from the dialog window. Viewing in Source mode:
<div class="mje_editor_row" id="Eq-Editor-Eq-Container-1-1-Row">
<span style="font-size:197%">
<em>f</em>
<span style="font-family:mathjax_main">(</span>
<em>x</em>
<span style="font-family:mathjax_main">)</span>
<span style="font-family:mathjax_main">=</span>
<span style="font-family:mathjax_main">5</span>
<span style="font-family:mathjax_main">0</span>
<span style="font-family:mathjax_main">0</span>
<span style="font-family:mathjax_main">×</span>
<span style="font-family:mathjax_main">1</span>
<span style="font-family:mathjax_main">.</span>
<span style="font-family:mathjax_main">2</span>
<em>x</em>
</span>
<input name="Eq-Container-1_input_Eq-Editor-Eq-Container-1-1" type="text" />
What I've done:
Thinking that there could be a timing issue with my iframe page loading, I tried an alert(iframeWindow.getHtml()); at the bottom of the addIframe function(). I was surprised when it gave me exactly the data as shown in the dom. It was just what I wanted. Also, as a further note, (as a user) I did not make any changes to the iframe data once the dialog loaded. I just clicked Ok after waiting for a couple seconds to see that the page is fully loaded. I have poured through http://ckeditor.com/forums for hints I have reviewed http://stackoverflow.com for help. So far the problem eludes me. I haven't found anything-- although it is probably one of those things staring right at me in the face.
If any of you have experience with this issue, I would love to hear how to solve it. Many thanks!
Success is so sweet when you find the answer you have been looking for! I am new to CKEditor plugin programming - so I just didn't know. It has been a rough road. But I got it. Here is the details.
CKEditor came out with this new layer called ACF (Advanced Content Filtering) in version 4.1. Because I wasn't aren't aware of this extra layer, my HTML tags got stripped out when my plugin sent HTML data to the ckEditor window on editor.insertHtml. After I added allowedContent: true to the plugin code (see below), my HTML is no longer stripped out. No more filtering!
Details about allowing specific tags described here.
And finally, here it mentions about adding config.allowedContent = true to disable content filtering -- which I assumed was something to do in the config.js file, but changing the config.js file in this manner didn't have an effect for me.
Here is a copy of the new changed code:
var iframeWindow = null;
var theElement = null;
var height = 480;
var width = 750;
var url = CKEDITOR.basePath + 'plugins/airmath/integration/airmath.html';
CKEDITOR.plugins.add('airmath',
{
requires: 'iframedialog',
icons: 'airmath',
init: function (editor) {
allowedContent: true,
CKEDITOR.dialog.addIframe(
'myiframedialogDialog',
'Math Editor',
url, width, height,
function () {
theElement = this.getElement();
iframeWindow = theElement.getFrameDocument().getBody();
},
{
onOk: function () {
editor.insertHtml(iframeWindow.getHtml());
}
}
);
editor.addCommand('myiframedialog', new CKEDITOR.dialogCommand('myiframedialogDialog'));
editor.ui.addButton('AirMath',
{
label: 'Math Editor',
command: 'myiframedialog',
toolbar: 'insert'
});
}
});

Pop up logout button

In my application, logging out is a two way process. When you click on the Logout link on the main screen, it opens up a pop-up for confirmation of logout.
Now, on pop-up, there are two button ( 'Logout' and 'Cancel'). The problem is that I am not able to click on either of them.
Using Firebug console, I confirmed that the XPath which I am using is correct. But when using the same Xpath in webdriver, it's not able to locate the object.
Xpath of the button on the pop-up : //div[3]/div/div/div[2]/div/a/span
Code which I am trying :
IWebElement LogoutButton = WebDriver.FindElement(By.XPath("//div[3]/div/div/div[2]/div/a/span"));
LogoutButton.Click();
Is there any specific method to use here ?? Please let me know.
cheers
EDIT*
<div id="ext-comp-1084" class="x-window x-layer x-window-default x-closable x-window-closable x-window-default-closable x-popup" tabindex="-1" style="opacity: 1; width: 250px; height: 145px; right: auto; left: 755px; top: 147px; z-index: 19000;">
<div id="ext-comp-1084_header" class="x-window-header ext-header ext-header-horizontal x-docked x-unselectable x-window-header-default x-horizontal x-window-header-horizontal x-window-header-default-horizontal x-top x-window-header-top x-window-header-default-top x-docked-top x-window-header-docked-top x-window-header-default-docked-top" style="width: 250px; right: auto; left: 0px; top: 0px;">
<div id="ext-comp-1084-body" class="x-window-body x-window-body-default x-closable x-window-body-closable x-window-body-default-closable x-window-body-default x-window-body-default-closable" style="width: 250px; left: 0px; top: 52px; height: 49px;">
<div id="toolbar-1086" class="x-toolbar x-docked x-toolbar-default x-docked-bottom x-toolbar-docked-bottom x-toolbar-default-docked-bottom x-box-layout-ct" style="width: 250px; right: auto; left: 0px; top: 101px;">
<div id="toolbar-1086-innerCt" class="x-box-inner " role="presentation" style="width: 250px; height: 44px;">
<div id="toolbar-1086-targetEl" class="x-box-target" style="width: 250px;">
<div id="tbspacer-1087" class="x-toolbar-spacer x-box-item x-toolbar-item x-toolbar-spacer-default" style="right: auto; left: 0px; margin: 0px; width: 50px; top: 22px;"></div>
<div id="button-1088" class="x-btn green x-exclude x-unselectable x-box-item x-toolbar-item x-btn-default-toolbar-small x-noicon x-btn-noicon x-btn-default-toolbar-small-noicon" style="border-width: 1px; width: 100px; right: auto; left: 50px; margin: 0px; top: 8px;">
<div id="button-1088-btnWrap" class="x-btn-wrap" unselectable="on">
<a id="button-1088-btnEl" class="x-btn-button" tabindex="0" unselectable="on" hidefocus="on" role="button">
<span id="button-1088-btnInnerEl" class="x-btn-inner x-btn-inner-center" unselectable="on">Logout</span>
<span id="button-1088-btnIconEl" class="x-btn-icon-el " style="" unselectable="on" role="img"></span>
</a>
</div>
</div>
<div id="button-1089" class="x-btn gray x-exclude x-unselectable x-box-item x-toolbar-item x-btn-default-toolbar-small x-noicon x-btn-noicon x-btn-default-toolbar-small-noicon" style="border-width: 1px; width: 80px; right: auto; left: 160px; margin: 0px; top: 8px;">
<div id="button-1089-btnWrap" class="x-btn-wrap" unselectable="on">
<a id="button-1089-btnEl" class="x-btn-button" tabindex="0" unselectable="on" hidefocus="on" role="button">
<span id="button-1089-btnInnerEl" class="x-btn-inner x-btn-inner-center" unselectable="on">Cancel</span>
<span id="button-1089-btnIconEl" class="x-btn-icon-el " style="" unselectable="on" role="img"></span>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
1) First save the instance of main window using below code
String mainWindow = driver.getWindowHandle();
2) //code to click on the Logout link on the main screen
3) then switch webdriver control to pop-up using below code
for(String childWindow : driver.getWindowHandles()){
driver.switchTo().window(childWindow);
}
4) //code to click on pop-up, ( 'Logout' and 'Cancel').

Get iframe name with Vbscript

How do I extract the iframe name with vbscript? like for example if my string value is
<DIV style="MARGIN-TOP: 0px; WIDTH: 670px; HEIGHT: 210px; VISIBILITY: visible; MARGIN-LEFT: -335px; TOP: 48px" id=TB_window><DIV id=TB_title> <DIV id=TB_ajaxWindowTitle>Add Media</DIV> <DIV id=TB_closeAjaxWindow><A id=TB_closeWindowButton title=Close href="#" jQuery172014112867239284427="140"><IMG src="http://www.gorgeoushentai.com/wp-includes/js/thickbox/tb-close.png"></A></DIV></DIV><IFRAME style="WIDTH: 670px; HEIGHT: 180px" id=TB_iframeContent onload=tb_showIframe() src="http://www.gorgeoushentai.com/wp-admin/media-upload.php?post_id=168&" frameBorder=0 name=TB_iframeContent656 hspace=0>This feature requires inline frames. You have iframes disabled or your browser does not support them.</IFRAME></DIV>
Then the extracted value would be TB_iframeContent656
I attempted to write the code in vbscript but it doesn't work
<script type="text/vbscript">
box="<DIV style=""MARGIN-TOP: 0px; WIDTH: 670px; HEIGHT: 210px; VISIBILITY: visible; MARGIN-LEFT: -335px; TOP: 48px"" id=TB_window><DIV id=TB_title> <DIV id=TB_ajaxWindowTitle>Add Media</DIV> <DIV id=TB_closeAjaxWindow><A id=TB_closeWindowButton title=Close href=""#"" jQuery172014112867239284427=""140""><IMG src=""http://www.gorgeoushentai.com/wp-includes/js/thickbox/tb-close.png""></A></DIV></DIV><IFRAME style=""WIDTH: 670px; HEIGHT: 180px"" id=TB_iframeContent onload=tb_showIframe() src=""http://www.gorgeoushentai.com/wp-admin/media-upload.php?post_id=168&"" frameBorder=0 name=TB_iframeContent656 hspace=0>This feature requires inline frames. You have iframes disabled or your browser does not support them.</IFRAME></DIV>"
data = box.document.getElementById("TB_iframeContent").name
document.write(data)
</script>
There are two things wrong with your code:
A string object doesn't contain a value/method named document.
When you execute it like this the code will be executed before the document is created so stuff like the iframe won't exist yet, so obviously such an element can't be found.
Look at the code below for a working example. First of all it will look at the actual page instead of a string. The WindowLoad function makes sure the page is loaded before executing the code.
<html>
<head>
<script type="text/vbscript">
Set window.onload = GetRef("WindowLoad")
Function WindowLoad
Dim somediv
Set somediv = document.getElementById("someid")
Dim data
Set data = document.getElementById("TB_iframeContent")
if data Is Nothing then
MsgBox("element does not exist")
else
somediv.InnerHTML = data.name
end if
End Function
</script>
</head>
<body>
<!-- Some ID for testing purposes -->
<div id="someid"></div>
<!-- The DIV with the iframe -->
<div style="MARGIN-TOP: 0px; WIDTH: 670px; HEIGHT: 210px; VISIBILITY: visible; MARGIN-LEFT: -335px; TOP: 48px" id=TB_window>
<div id=TB_title>
<div id=TB_ajaxWindowTitle>Add Media</DIV>
<DIV id=TB_closeAjaxWindow><A id=TB_closeWindowButton title=Close href="#" jQuery172014112867239284427="140">
<IMG src="http://www.gorgeoushentai.com/wp-includes/js/thickbox/tb-close.png"></A>
</DIV>
</DIV>
<IFRAME style="WIDTH: 670px; HEIGHT: 180px" id=TB_iframeContent onload=tb_showIframe() src="http://www.gorgeoushentai.com/wp-admin/media-upload.php?post_id=168&" frameBorder=0 name=TB_iframeContent656 hspace=0>This feature requires inline frames. You have iframes disabled or your browser does not support them.</IFRAME>
</DIV>
</body>
</html>

how to click on strange select list element?

I have a problem selecting the options in unidentified dropdown menu. Elements of the dropdown appears when i click on dropdown arrow, but I cant click on them, because I don't know their id's or other properties that I can use.
Here is the code. I can't select from select_list with:
on_page(RegistrationPage).id_of_select_list_with_options = "8"
or
#browser.select_list(:name => "field_profile_bday[0][value][day]").select("8")
or
#browser.select_list(:id => "edit-field-profile-bday-0-value-day").select("8")
The error is: Element is not currently visible and so may not be interacted with (Selenium::WebDriver::Error::ElementNotVisibleError)
When I click on combo-button element dropdown list appears, but I can't select elements in it because they appear in combo-selected div after selecting. (Like "Jour" text in combo-selected div, it is there by default)
Here is the html:
<div class="form-item" id="edit-field-profile-bday-0-value-day-wrapper">
<label for="edit-field-profile-bday-0-value-day">Jour : <span class="form-required" title="Ce champ est obligatoire.">*</span></label>
<select name="field_profile_bday[0][value][day]" class="form-select required date-day" id="edit-field-profile-bday-0-value-day" ><option value="" selected="selected">Jour</option><option value="1">1</option><option value="2">2</option><option value="3">3</option><option value="4">4</option><option value="5">5</option><option value="6">6</option><option value="7">7</option><option value="8">8</option><option value="9">9</option><option value="10">10</option><option value="11">11</option><option value="12">12</option><option value="13">13</option><option value="14">14</option><option value="15">15</option><option value="16">16</option><option value="17">17</option><option value="18">18</option><option value="19">19</option><option value="20">20</option><option value="21">21</option><option value="22">22</option><option value="23">23</option><option value="24">24</option><option value="25">25</option><option value="26">26</option><option value="27">27</option><option value="28">28</option><option value="29">29</option><option value="30">30</option><option value="31">31</option></select>
</div>
<div class="combo-wrapper" style="display: inline-block; width: 61px; height: 24px; " tabindex="0"><div class="combo-button" style="width: 24px; height: 24px; display: inline-block; ">+</div><div class="combo-selected" style="width: 37px; height: 24px; display: inline-block; ">Jour</div></div>
<div class="combo-button" style="width: 24px; height: 24px; display: inline-block; ">+</div>
<div class="combo-selected" style="width: 37px; height: 24px; display: inline-block; ">Jour</div>
"Jour"
</div>
Instead of .select("8"). Try something like:
#browser.select_list(:name => "field_profile_bday[0][value][day]").option(:value, '8').select
or
#browser.select_list(:name => "field_profile_bday[0][value][day]").options[7].select
I think you needed to point to the option element and then use inherent select method. Hope this works. Good Luck!

Resources