I've jjust started off with Selenium Webdriver and I've hit an issuee straight away involving the buttons I'm trying to select/click all have no IDs and share the same class.
So I'm wondering how I select these by the unique text they contain.
I'm thinking possibly with css selector maybe, but I'm unsure how to also tell it to look for specific text to select the element.
All I currently have is:
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenQA.Selenium.Internal;
namespace SeleniumTest1.Methods
{
public class HomePage
{
private readonly IWebDriver _browser;
public HomePage(IWebDriver browser)
{
_browser = browser;
}
public IWebElement SearchBox()
{
return _browser.FindElement(By.Id("searchBox"));
}
public void ImageButton()
{
_browser.FindElement(By.CssSelector("a")).Click();
}
}
}
Very basic so far.
Where I have the CssSelector I'm not sure if theres anyway to say select "a" containing text "xyz".
I've tried search for ways but can't find anything, though I feel this must be an issue which has been raised before, thanks.
Fairly easy if you use xpath.
if it has unique text your xpath should look like something like this
//button[.='xyz']
So, here "." points to the parent in HTML hierarchy and just look for text
You can find the link by the visible text.
IWebElement XyzLink= _browser.FindElement(By.LinkText("xyz"));
Also you can locate the link by partial link text as follows,
IWebElement XyzPartialLink= _browser.FindElement(By.PartialLinkText("XYZ"));
For example this will locate a link element which contains 'XYZ' in its text.
Related
I have a problem, I want to write a code in selenium C# (or another way) that getting dynamic value from a webpage (like clock) and display in my APP, The value of the variable within the webpage changes frequently and I want to display this value in my APP,I use a string variable to display value.
with below code:
string realTime= driver.FindElement(By.XPath("//span[#class='RealServerTime']")).Text;
but its a static text, and it does not display changes to the value of the variable, I don't really know that I can use selenium for this or not!? can everyone help me? thanks a lot
This is my code:
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Surena
{
class Timing
{
IWebDriver driver = new ChromeDriver();
public void clock(string textSend)
{
driver.Url = "http://www.tsetmc.com/Loader.aspx?ParTree=15";
string realTime= driver.FindElement(By.XPath("//span[#class='RealServerTime']")).Text;
}
}
}
You could use WebDriverWait class to wait until given change and set condition that Text or other value change.
https://www.selenium.dev/selenium/docs/api/dotnet/html/T_OpenQA_Selenium_Support_UI_WebDriverWait.htm
I have page which downloads a file which shows a dialog on the bottom with OPEN SAVE CANCEL options, how can I click those options ? I am using IE browser, I saw some solutions using third party AutoIt, Robot class, but I am looking with Selenium and C# only. Attached is the image of what I am talking.. Any idea how can we do this ?
AutoItX3 autoit = new AutoItX3();
autoit.WinActivate("Save");
Thread.Sleep(1000);
autoit.Send("{F6}");
Thread.Sleep(1000);
autoit.Send("{TAB}");
Thread.Sleep(1000);
autoit.Send("{ENTER}");
You can try this code.
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;
using OpenQA.Selenium.IE;
using OpenQA.Selenium.Support.UI;
using System.Threading;
using System.Collections.Generic;
using System.Windows.Forms;
//using NUnit.Framework;
namespace SampleTest
{
[TestMethod]
public void Download()
{
IWebDriver driver = new InternetExplorerDriver(#"C:\Users\hamit\Desktop\Selenium\IEDriverServer_Win32_2.48.0");
driver.Navigate().GoToUrl("https://www.spotify.com/se/download/windows/");
Thread.Sleep(2000);
SendKeys.SendWait("#{TAB}"); Thread.Sleep(100);
SendKeys.SendWait("#{TAB}"); Thread.Sleep(100);
SendKeys.SendWait("#{DOWN}"); Thread.Sleep(100);
SendKeys.SendWait("#{DOWN}"); Thread.Sleep(100);
SendKeys.SendWait("#{Enter}");
}
}
like an option - try get all exist buttons and then filter by inner text
var posibleButtons = driver.FindElements(By.TagName("button")).Where(el => el.Text.Contains("Open"));
posibleButtons.Where(// try use some other filters, maybe by styles or ets...
IE 11 for security reasons do not allow us to skip that part. Since this is not the DOM, you cannot handle it with selenium..
AutoIT or similar tools are the only option, which makes the test less reliable..
instead, we added API calls to get the documents instead of actually downloading them.
Tried in Java, file was downloaded.
driver.findElement(By.xpath("//body")).sendKeys(Keys.chord(Keys.CONTROL, "j"));
Thread.sleep(2000);
Robot rb = new Robot();
rb.keyPress(KeyEvent.VK_ENTER);
Explaination:
1 First click on the button / link to download the file.this pop up will be seen enter image description here
2. Click "Ctrl+j" this will open the "View Downloads pop up".
3.Then click enter , since the focus will be on the recent file, it
will be downloaded
I have a web page in my web project “CalculatorWeb” where I placed a single text box with id “txtNum1”
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<form id="frmCalc">
<div style="padding-top:20px;">
My Sample Text Box <br/><br/>
<input id="txtNum1" type="text" />
</div>
</form>
</body>
</html>
Nothing fancy so the page loads up as below
Now I created a feature file “BrowserTest1.feature” to my project “Calculator.Specs”. The code as follows
Feature: BrowserTest1
In order to check url
As browser
I want to be see url of page
#mytag
Scenario: Go to URL
Given I have entered 'http://localhost:58529/'
When I go to that url
Then there is a text box on the page with id 'txtNum1'
I then code a file BrowserTest.cs for unit tests implementation
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
using TechTalk.SpecFlow;
namespace Calculator.Specs
{
[Binding]
class BrowserTest
{
public string urlPath;
[Given(#"I have entered 'http://localhost:58529/'")]
protected void SetURL()
{
string URLPath = "http://localhost:58529/";
urlPath = URLPath;
}
[When(#"I go to that url")]
protected void NavigateToURL()
{
using (var driver = new ChromeDriver())
{
driver.Navigate().GoToUrl(urlPath);
}
}
[Then(#"there is a text box on the page with id 'txtNum1'")]
protected void TxtBoxExists()
{
bool txtExists = false;
using (var driver = new ChromeDriver())
{
IWebElement txtBox1 = driver.FindElement(By.Id("txtNum1"));
if (txtBox1 != null)
{
txtExists = true;
}
}
Assert.AreEqual(true, txtExists);
}
}
}
As far as I am aware I do have all the required references for Visual Studio IDE to SpecFlow/Selenium integration
When I do run the unit test the web page loads up fine , however I get a failing test when I try to find the element with ID “txtNum1” even though the text box with that ID does exist on the page
Exception details appear as follows
Can anybody point me in the right direction as to what am I missing to enable Selenium to find the text box on the page with ID “txtNum1”
you need to use the same instance of driver between steps, otherwise the driver that navigates to the page is different from the driver that you are trying to get the element from.
you have a couple of choices for this. The simplest is to create a field for your driver instance and use the field in all the steps. This will work as long as all your steps are in the same file.
The other option is to store the driver object in the ScenarioContext.Current (or FeatureContext.Current). These are dictionaries so you can do this:
ScenarioContext.Current["webDriver"] = driver;
This will work ok, but you'll have to cast everytime you get the driver out as the dictionary just takes objects, but you'll be able to share your driver instance between steps regardless of which file they are in.
The third (and IMHO best) option is to create a WebDriverContext class and accept this in your step class constructor. Create your driver once in there (in its constructor) and then every step can use the WebDriverContext instance to access the shared driver.
An example of setting this up can be seen in the answer here
Your driver just needs to proceed a little slower
Add some delay before each driver.FindElement, for instance with :
Thread.Sleep(2000);
IWebElement txtBox1 = driver.FindElement(By.Id("txtNum1"));
Or better yet :
WebDriverWait wait = new WebDriverWait(driver, new TimeSpan(0,0,10));
wait.Until(ExpectedConditions.ElementIsVisible(By.Id("txtNum1")));
IWebElement txtBox1 = driver.FindElement(By.Id("txtNum1"));
Found the answer after a bit of code examination. This issue was to do with multiple instances of ChromeDriver in the code. So the first instance was loading the page but when I was trying to find an item on the page I was using a new instance of the page instead of the one that was already used to load the page. So this second instance of the chrome driver with no page loaded was always returning exception with no item found as the there was no page loaded on this instance of chrome driver
I know, few methods like, appending runat="server" attributes to div elements, n then accessing it from codebehind(aspx.cs) file, and also, some jquery javascript methods., but here what I actually need is, to "access the div element in my c# classes which is under appcode folder." Is it possible?
I was thinking whether something like below is possible. Ex:
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
public class psv_class()
{
public static void psv_method(Label lb,HtmlDivElement htmldiv)
{
lb.Text="my custom error msg..";
htmldiv.Visible=true;
}
}
and then i can call this method in my aspx.cs file, by passing parameters wherever i need..
psv_class.psv_method(Label1,StatusMsgDiv);
here, above i am sure, HtmlDivElement class doesn't exist in .Net framework, but hoping for some alternate methods.
You have the answer in your using statements:
public static void psv_method(Label lb, HtmlControl htmldiv)
{
lb.Text = "my custom error msg..";
htmldiv.Visible = true;
}
a HTML div with runat="server" attribute is a HtmlControl object.
using "HtmlContainerControl" in place of "HtmlDivElement" did fulfill my need in my above example..
I've search the forum, but I coundn't find anything that quite satisfied me.
In Microsoft Visual Studio 2010, when I try to add a WPF User Control I get this error:
"Value cannot be null. Parameter name: objectType"
Then when I want to select the hosted content, I get this error :
"An error occured trying to add references for type 'PolyPuttZe.GameCanvas', or finding the type. Make sure the project references are correct."
I followed this tutorial : http://www.switchonthecode.com/tutorials/wpf-tutorial-using-wpf-in-winforms
Thanks!
EDIT:
This is the code I wrote :
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.Integration;
namespace PolyPuttZe
{
public partial class Game : Form
{
public Game()
{
InitializeComponent();
}
}
}
Here's a more useful answer for the next person that has this issue - you need to create your WPF user control and build the solution first. Then open/create the form and add an Element Host and set it to your control. This is likely what the accepted answer means as starting over would work as well if you create the WPF control first.