How to change the language of a WebDriver? - webdriver

I want to execute my Selenium tests in different languages. Is it possible to change the language of an existing WebDriver at runtime or do I have to recreate the browser instance?
Right now I'm only using Firefox, but I want to execute tests in different browsers at some later point.
In Firefox I set the language like this:
FirefoxProfile profile = new FirefoxProfile();
profile.setPreference("intl.accept_languages", "de");
WebDriver driver = new FirefoxDriver(profile);
I also implemented a WebDriverPool, which holds a WebDriver instance so it can be shared among tests. If the language can only be set at creation time, I could hold an instance for every locale.
All in all I wonder if I miss something here. Why is it so hard to change the language? shouldn't there be a method like WebDriver.setAcceptLanguages(Locale)?
In a nutshell I have these questions:
Why isn't there WebDriver.setAcceptLanguages(Locale)?
How to change the language for the dirrerent WebDrivers?
Can I change the language at runtime?
How did you guys implement your WebDriverPool or do you recreate them everytime?

I ended up creating a WebDriverPool that creates one instance for every combination of WebDriver type (e.g. FirefoxDriver.class) and Locale (e.g. en_US). Maybe this is usful for someone.
public class WebDriverPool {
private Map<String, WebDriver> drivers = new HashMap<String, WebDriver>();
private List<WebDriver> driversInUse = new ArrayList<WebDriver>();
public WebDriverPool() {
Runtime.getRuntime().addShutdownHook(new Thread(){
#Override
public void run(){
for (WebDriver driver : drivers.values())
driver.close();
if (!driversInUse.isEmpty())
throw new IllegalStateException("There are still drivers in use, did someone forget to return it? (size: " + driversInUse.size() + ")");
}
});
}
private WebDriver createFirefoxDriver(Locale locale){
FirefoxProfile profile = new FirefoxProfile();
profile.setPreference("intl.accept_languages", formatLocale(locale));
return new FirefoxDriver(profile);
}
private String formatLocale(Locale locale) {
return locale.getCountry().length() == 0
? locale.getLanguage()
: locale.getLanguage() + "-" + locale.getCountry().toLowerCase();
}
/**
* #param clazz
* #param locale
* #return web driver which can be new or recycled
*/
public synchronized WebDriver getWebDriver(Class<? extends WebDriver> clazz, Locale locale){
String key = clazz.getName() + "-" + locale;
if(!drivers.containsKey(key)){
if(clazz == FirefoxDriver.class){
drivers.put(key, createFirefoxDriver(locale));
}
// TODO create other drivers here ...
// else if(clazz == ChromeDriver.class){
// drivers.put(key, createChromeDriver(locale));
// }
else{
throw new IllegalArgumentException(clazz.getName() + " not supported yet!");
}
}
WebDriver driver = drivers.get(key);
if(driversInUse.contains(driver))
throw new IllegalStateException("This driver is already in use. Did someone forgot to return it?");
driversInUse.add(driver);
return driver;
}
public synchronized void returnWebDriver(WebDriver driver){
driversInUse.remove(driver);
}
}

You can also do it through about:config in firefox. But you need to use Actions to manipulate it.
Below a java piece of code
Actions act = new Actions(webDriver);
webDriver.get("about:config");
// warning screen
act.sendKeys(Keys.RETURN).perform();
// Go directly to the list, don't use the search option, it's not fast enough
act.sendKeys(Keys.TAB).perform();
// Go to the intl.accept_languages option
act.sendKeys("intl.accept_languages").sendKeys(Keys.RETURN).perform();
// fill the alert with your parameters
webDriver.switchTo().alert().sendKeys("fr, fr-fr, en-us, en");
webDriver.switchTo().alert().accept();

I am afraid that the whole idea of WebDriver is to act like browser - so you can change the language of the browser, but you have to change the locale in the Operating system, or hope that the application will do it for you.
For instance - German number format separates decimal number by comma and English one by dot. If you want to test, how the number format behaves in English locale and in German locale, you can do it only by these two approaches:
Change OS locale from German to English or vice versa
Change browser language and hope that application will change the behavior.
To answer your questions:
There is no setLocale on Webdriver, because WebDriver simulates browser, not OS
I would do it like this (Java code):
private WebDriver driver;
public enum Language {en-us, de}
public WebDriver getDriver(Language lang){
String locale = lang.toString();
FirefoxProfile profile = new FirefoxProfile();
profile.setPreference("intl.accept_languages", locale);
driver = new FirefoxDriver(profile);
return driver;
}
#Test
public void TestNumber(){
WebDriver drv = getDriver(Language.en);
drv.get("http://the-site.com");
WebElement el = drv.findElement //... find element
String number = el.getText();
Assert.assertEquals(number, "123.45");
drv.close();
drv = getDriver(Language.de);
drv.get("http://the-site.com");
WebElement el = drv.findElement //... find element
String number = el.getText();
Assert.assertEquals(number, "123,45");
drv.close();
}
I am afraid you have to close the browser and open it again with different language.
I personally create new instance of the browser for each test.
BTW the above bit of code assumes, that the web application changes the way how to show numbers to the user based on browser language.

Related

Cannot initialize ChromiumWebBrowser inside a JSB-bounded class

I have followed this steps to setup JSB. In my bounded-class, I need to return the source of an API request (I cannot, therefore, use GetPageSourceAsync because no JS context is ever created). So, I use the trick of copying and immediately pasting the page content to a string variable (see result). This code is not working, I get the following exception:
The ChromiumWebBrowser instance creates the underlying Chromium Embedded Framework (CEF) browser instance in an async fashion. The undelying CefBrowser instance is not yet initialized. Use the IsBrowserInitializedChanged event and check the IsBrowserInitialized property to determine when the browser has been initialized.
which is happening on bro.SelectAll();:
public class boundClass
{
ChromiumWebBrowser bro;
public boundClass()
{
bro = new ChromiumWebBrowser("https://google.com");
}
public string getAuthSource(string url)
{
string source = String.Empty;
bro.Load(url);
while (bro.IsLoading)
{
}
bro.SelectAll();
bro.Copy();
string result = Clipboard.GetText();
Clipboard.Clear();
return result;
}
}
What's the problem? The ChromiumWebBrowser seems well-initialized to me...

How to run Selenium Brave web browser webdriver in c#?

Someone kind can help me with this.
I have a problem and it is that I cannot run Selenium in Brave with visual studio. Can someone help me on the code? What would it be to execute it? Because with the visual studio webdriver automatically running chrome, I want to tell it to run Brave. Thank you
Requirements:
Install Nuget Packages (Selenium.Webdriver, Selenium.Chrome.Webdriver)
private string chromeDriverPath = #"C:\Path\To\chromedriver.exe"; //Path to chromedriver.exe
private string braveBrowserPath = #"C:\Path\To\brave.exe"; //Path to brave.exe
private ChromeOptions chromeOptions; //Default value of chromeOptions is null
private IWebDriver driver; //Default value of driver is null
public void LoadChrome() {
try
{
Environment.SetEnvironmentVariable("webdriver.chrome.driver", chromeDriverPath); //Sets process evnironment
chromeOptions = new ChromeOptions(); //Initialize chromeOptions
chromeOptions.BinaryLocation = braveBrowserPath; //Sets the location of Brave
driver = new ChromeDriver(chromeOptions); //Initialize driver with chromeOptions
driver.Manage().Window.Maximize(); //Set Brave window maximized
driver.Navigate().GoToUrl("https://www.google.com/"); //Loads page Google
} catch (Exception ex) {
Console.WriteLine(ex.Message); //Print any errors to console log
}
}
Selenium seems to be pretty easy to use. You can take a look at their API and Documentation that include usages and examples with C# programming language.
There is also a cheat sheet you can use for reference in case you're too lazy to look up API or Documentation.

How to optimize realm.allobjects(class) in Android

I want to use Realm to replace SqLite in Android to store a list of classes, my code is very simple as below.
public class MyRealmObject extends RealmObject {
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
private String field;
...
}
List<MyObject> myObjects = new ArrayList();
Realm realm = Realm.getInstance(this);
for(MyRealmObject realm : realm.allobjects(MyRealmObject.class)) {
myObjects.add(new MyObject(realm));
}
realm.close();
return myObjects;
However, its performance is actually slower than a simple SqlLite table on my tested device, am I using it the wrong way? Is there any optimization tricks?
Why do you want to wrap all your RealmObjects in the MyObject class?. Especially copying the entire result set means you will loose the benefit of using Realm, namely that it doesn't copy data unless needed to.
RealmResults implements the List interface so you should be able to use the two interchangeably.
List<MyRealmObject> myObjects;
Realm realm = Realm.getInstance(this);
myObjects = realm.allObjects(MyRealmObject.class();
return myObjects;

How to specify a button to open an URL?

I want to write a web application that triggers the default email client of the user to send an email.
Thus, I created a Link, that leads to an URL conforming to the mailto URI scheme (http://en.wikipedia.org/wiki/Mailto):
Link emailLink = new Link("Send Email",
new ExternalResource("mailto:someone#example.com"));
However, instead of using a Link, I want to provide a Button that allows to trigger the respective functionality. But, for buttons I cannot set an ExternalResource to be opened.
Does anybody know to solve this problem for Buttons, or how to create a Link that looks and behaves exactly like a button? I also tried some CCS modification but did not manage the task by myself. I also found some solutions for former Vaadin versions (https://vaadin.com/forum/#!/thread/69989), but, unfortunately they do not work for Vaadin 7.
I remember solving a similar problem using a ResourceReference.
Button emailButton = new Button("Email");
content.addComponent(emailButton);
Resource res = new ExternalResource("mailto:someone#example.com");
final ResourceReference rr = ResourceReference.create(res, content, "email");
emailButton.addClickListener(new Button.ClickListener() {
#Override
public void buttonClick(ClickEvent event) {
Page.getCurrent().open(rr.getURL(), null);
}
});
For solving similar issue, I applied previously:
String email="info#ORGNAME.org";
Link l=new Link();
l.setResource(new ExternalResource("mailto:" + email));
l.setCaption("Send email to " + email);
addComponent(l);
After some further tries a managed to adapt the proposed LinkButton solution from https://vaadin.com/forum/#!/thread/69989 for Vaadin 7:
public class LinkButton extends Button {
public LinkButton(final String url, String caption) {
super(caption);
setImmediate(true);
addClickListener(new Button.ClickListener() {
private static final long serialVersionUID = -2607584137357484607L;
#Override
public void buttonClick(ClickEvent event) {
LinkButton.this.getUI().getPage().open(url, "_blank");
}
});
}
}
However, this solution is still not perfect as it causes the opening of a popup window being blocked by some web browsers.

rso between flex and red5. I can create but cant read

so im still stuck on this that i can create remote shared object but cant read while im notified about changes. im using trunk version of red5, and flex 4.0 with flash builder. in debug i can see that changeLog has name of the changed value of rso, but object itself has undefined value.
Currently im working on local windows machine, but tried everything on ubuntu server 10.04 and got the same results. i can connect to the room, create a shared object and all client are notified about that, but only the user who changed the value of rso can read the value that one time, other just get undefined value.
Does anybody has any experience with this issue? I would really appreciate any help, because this is just driving me crazy, im for about three weeks, read all tutorials about rso and cant get any solution. I tried with persistent and non-persistent, initiated by server and by client, but all the time get the same results.
there is my code on the client side:
protected function application1_creationCompleteHandler(event:FlexEvent):void {
var room_id:Number = vars("room");
connection = new NetConnection();
connection.connect("rtmp://127.0.0.1/video/" + room_id);
connection.addEventListener(NetStatusEvent.NET_STATUS, onConnected);
connection.client = this;
}
private function onConnected(event:NetStatusEvent) : void {
if(event.info.code == "NetConnection.Connect.Success") {
so = SharedObject.getRemote("video", connection.uri, true);
so.addEventListener(SyncEvent.SYNC, onSync);
so.connect(connection);
} else {
Alert.show("Unsuccessful Connection", "Information");
}
private function onSync(event:SyncEvent):void {
if(so.data["video"] != undefined)
Alert.show(so.data["video"].toString(), "Information");
}
on the server side i have:
ISharedObject so;
IServiceCapableConnection iconn;
public static IScope iroom;
/** {#inheritDoc} */
#Override
public boolean connect(IConnection conn, IScope scope, Object[] params) {
iconn = (IServiceCapableConnection)conn;
if (!super.connect(conn, scope, params)) {
return false;
}
System.out.println("Connected True");
return true;
}
/** {#inheritDoc} */
#Override
public void disconnect(IConnection conn, IScope scope) {
super.disconnect(conn, scope);
}
#Override
public boolean roomStart(IScope room) {
if (!super.roomStart(room))
return false;
createSharedObject(room, "video", true);
so = getSharedObject(room, "video");
System.out.println("Room created succesfully");
ISharedObjectListener listener = new SOEventListener();
so.addSharedObjectListener(listener);
return true;
}
with listener on the client side i cant make output in console and see that rso is changed and what is current value, although im checking the persistence rso file on red5 server and the that look like everything is working and the only thing what is missing is opportunity to read value for all clients.
I will appreciate any help. Thanks
big problem appears not such a big. Problem was with encoding, which is AMF3 by default since AS3 and all i need to do, just change the encoding to AMF0.
connection = new NetConnection();
connection.objectEncoding = ObjectEncoding.AMF0;
connection.connect("rtmp://127.0.0.1/video/" + room_id);
Hope that helps for anybody, because somehow there is not a lot information about things like these on the net.

Resources