How to log in to Chrome with Selenium? - google-chrome

I am testing a Chrome extension which requires the user to be logged in to use, but I cannot figure out how to login with my test account. I have tried logging in to accounts.google.com but this is apparently insufficient; as far as the chrome APIs are concerned there is no authenticated user.
Chrome keeps prompting for login at chrome://chrome-signin but because I can't view the html of the page I can't determine what elements to interact with in Selenium to use it.

You may need to login manually once and then use that for automation.
Try below code , may be it help you:
System.setProperty("webdriver.chrome.driver","<chrome exe path>");
ChromeOptions options = new ChromeOptions();
options.addArguments("user-data-dir= <full local path Google Chrome user data default folder>);
WebDriver driver = new ChromeDriver(options);
driver.get("https://mail.google.com");
Login once manually when browser launched.
Then re-run script now it should use previous login.
Hope it will help you.

I think you can still login automatically. The reason is, when opening the page chrome://chrome-signin, the account textbox is automatically focused, so you just need to use keyboards to login without knowing how the html of the page looks like.
Try the code below (you might need to put some sleep in some places to make sure that everything is loaded properly.
public void loginToChrome(username, password) {
driver.get("chrome://chrome-signin");
var action = new Actions(driver);
action.sendKeys(username).perform();
action.sendKeys(keys.ENTER).perform();
action.sendKeys(password).perform();
action.sendKeys(keys.ENTER).perform();
}

First login to gmail on regular chrome browser (NOT the one triggered by selenium driver). Once you login, install the EditTheCookie extension. And on the gmail tab, click this extension icon. It will give option to copy the cookies in json format to clipboard. Paste that into Gmail.data which will be used in below programme.
Once you past, place that Gmail.data file in a avilable location for below programme (you can place anywhere and update the path of that file in below code accordingly).
I've developed this and is a working solution for me since long.
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Date;
import org.openqa.selenium.Cookie;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import com.google.gson.Gson;
public class LoginUtils {
private static final String GMAIL_LOGIN_URL =
"https://accounts.google.com/signin/v2/identifier";
public static void main(String[] args) {
WebDriver driver = new ChromeDriver();
driver = LoginUtils.login(driver, GMAIL_LOGIN_URL, "Gmail.data");
}
public static final WebDriver login(WebDriver driver, String url, String pathOfJsonFileName) {
Cookies[] data = readJson(pathOfJsonFileName);
driver.navigate().to(url);
// Set the expire time of each cookie.
Date expiryTime = new Date(System.currentTimeMillis() + 1000000000);
for (Cookies cookie : data) {
Cookie ck = new Cookie(cookie.getName(), cookie.getValue(), cookie.getDomain(), cookie.getPath(),
expiryTime, Boolean.parseBoolean(cookie.getSecure()), Boolean.parseBoolean(cookie.getHttpOnly()));
driver.manage().addCookie(ck);
}
return driver;
}
private static final Cookies[] readJson(String jsonFileName) {
String json = null;
try {
byte[] encoded = Files.readAllBytes(Paths.get(jsonFileName));
json = new String(encoded);
} catch (Exception e) {
e.printStackTrace();
}
return new Gson().fromJson(json, Cookies[].class);
}
}

Related

MVC Open binary in Microsoft Word

I support a web application on an intranet which has a word icon the user can click which will then retrieve bytes from a SQL server and then open Microsoft Word to display the document.
While this works well, our organisation is moving from IE to Chrome, and this doesn't work in Chrome, and from what I have heard Chrome doesn't support ActiveX which is what is used to open Microsoft Word.
So we are looking for a solution that will work in Chrome.
A quick example of what we do.
Javascript fired by onclick event
var wordObject = new ActiveXObject("Word.Application");
wordObject.Documents.open('http://localhost:8080/Document/Download/MyDocument.docx?documentId=12345');
wordObject.Visible = true;
Action in Controller
[HttpGet]
public ActionResult Download(int documentId)
{
var result = DocumentService.GetLatestDocumentVersion(documentId);
if (!result.Succeeded)
{
return HttpNotFound();
}
return new DocumentResult(result.Data.FileData, result.Data.FileType, result.Data.FullName);
}
public class DocumentResult : FileContentResult
{
private ContentDisposition _contentDisposition;
public DocumentResult (byte[] fileContents, FileType fileType, string fileDownloadName)
: base(fileContents, fileType.ToMimeType())
{
string disposition = fileType == FileType.Pdf ? DispositionTypeNames.Inline : DispositionTypeNames.Attachment;
_contentDisposition = new ContentDisposition(disposition);
_contentDisposition.FileName = fileDownloadName;
}
}
I want the same functionality but in Chrome, any ideas?
So instead of opening word through javascript you simply replace the url with something like
Document
This uses office uri schemas see https://learn.microsoft.com/en-us/office/client-developer/office-uri-schemes?redirectedfrom=MSDN
Thanks to MS Premier Support.

Selenium: Clear chrome cache

In my application I need a way to clear only the cache of the chrome browser before log out (except cookies - I do not want to delete cookies).
Can any one suggest me a way to click on the CLEAR DATA button in chrome.
I have written the below code but the code is not working.
Configuration :
Chrome Version: Version 65.0.3325.181 (Official Build) (64-bit)
Selenium Version: 3.11.0
//Clear the cache for the ChromeDriver instance.
driver.get("chrome://settings/clearBrowserData");
Thread.sleep(10000);
driver.findElement(By.xpath("//*[#id='clearBrowsingDataConfirm']")).click();
You are using here
driver.findElement(By.xpath("//*[#id='clearBrowsingDataConfirm']")).click();
Unfortunately, this won’t work because the Chrome settings page uses Polymer and WebComponents, need to use query selector using the /deep/ combinator, so selector in this case is * /deep/ #clearBrowsingDataConfirm.
Here is workaround to your problem...you can achieve the same using either one of the following...
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.annotations.Test;
public class ClearChromeCache {
WebDriver driver;
/*This will clear cache*/
#Test
public void clearCache() throws InterruptedException {
System.setProperty("webdriver.chrome.driver","C://WebDrivers/chromedriver.exe");
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.addArguments("disable-infobars");
chromeOptions.addArguments("start-maximized");
driver = new ChromeDriver(chromeOptions);
driver.get("chrome://settings/clearBrowserData");
Thread.sleep(5000);
driver.switchTo().activeElement();
driver.findElement(By.cssSelector("* /deep/ #clearBrowsingDataConfirm")).click();
Thread.sleep(5000);
}
/*This will launch browser with cache disabled*/
#Test
public void launchWithoutCache() throws InterruptedException {
System.setProperty("webdriver.chrome.driver","C://WebDrivers/chromedriver.exe");
DesiredCapabilities cap = DesiredCapabilities.chrome();
cap.setCapability("applicationCacheEnabled", false);
driver = new ChromeDriver(cap);
}
}
Chrome supports DevTools Protocol commands like Network.clearBrowserCache (documentation).
Selenium does not have an interface for this proprietary protocol by default.
You can add support by expanding Selenium's commands:
driver.command_executor._commands['SEND_COMMAND'] = (
'POST', '/session/$sessionId/chromium/send_command'
)
This is how you use it:
driver.execute('SEND_COMMAND', dict(cmd='Network.clearBrowserCache', params={}))
Note: this example is for Selenium for Python, but it's also possible in Selenium for other platforms in a similar way by expanding the commands.
YEAR 2020 Solution (using Selenium 4 alpha):
Using the devtools
private void clearDriverCache(ChromeDriver driver) {
driver.getDevTools().createSessionIfThereIsNotOne();
driver.getDevTools().send(Network.clearBrowserCookies());
// you could also use
// driver.getDevTools().send(Network.clearBrowserCache());
}
Don´t forget the send keys!!!!
For Selenium Basic, below code is functional.
Function clean_cache()
Set driver = New ChromeDriver
Dim keys As New Selenium.keys
driver.Get "chrome://settings/clearBrowserData"
Sleep 5000
driver.SendKeys (keys.Tab)
Sleep 1000
driver.SendKeys (keys.Tab)
Sleep 1000
driver.SendKeys (keys.Tab)
Sleep 1000
driver.SendKeys (keys.Tab)
Sleep 1000
driver.SendKeys (keys.Tab)
Sleep 1000
driver.SendKeys (keys.Tab)
Sleep 1000
driver.SendKeys (keys.Tab)
Sleep 1000
driver.SendKeys (keys.Enter)
Sleep 2000
driver.Quit
End Function
There is another way to click on Clear data button by traversing through shadow tree. If you are trying to locate clear data button by simply searching web element by locator strategy, it won't work due to Chrome browser version upgrade. You need to traverse through shadow tree. You can try below code to click on "Clear data" in advance tab:
package selenium.demo.test;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
public class Test {
static WebDriver driver;
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver","F:\\selenium\\chromedriver.exe");
// Instantiate a ChromeDriver class.
driver=new ChromeDriver();
driver.get("chrome://settings/clearBrowserData");
WebElement root1 = driver.findElement(By.cssSelector("settings-ui"));
// get 1st shadowroot element
WebElement shadowRoot1 = expandRootElement(root1);
// get 2nd parent
WebElement root2 = shadowRoot1.findElement(By.cssSelector("settings-main"));
// get 2nd shadowroot element
WebElement shadowRoot2 = expandRootElement(root2);
// get 3rd parent
WebElement root3 = shadowRoot2.findElement(By.cssSelector("settings-basic-page"));
// get 3rd shadowroot element
WebElement shadowRoot3 = expandRootElement(root3);
// get 4th parent
WebElement root4 = shadowRoot3.findElement(By.cssSelector("settings-section > settings-privacy-page"));
// get 4th shadowroot element
WebElement shadowRoot4 = expandRootElement(root4);
// get 5th parent
WebElement root5 = shadowRoot4.findElement(By.cssSelector("settings-clear-browsing-data-dialog"));
// get 5th shadowroot element
WebElement shadowRoot5 = expandRootElement(root5);
// get 6th parent
WebElement root6 = shadowRoot5.findElement(By.cssSelector("#clearBrowsingDataDialog"));
WebElement root7 = root6.findElement(By.cssSelector("cr-tabs[role='tablist']"));
root7.click();
WebElement clearDataButton = root6.findElement(By.cssSelector("#clearBrowsingDataConfirm"));
clearDataButton.click(); // click that hard to reach button!
driver.quit();
}
private static WebElement expandRootElement(WebElement element) {
WebElement ele = (WebElement) ((JavascriptExecutor) driver)
.executeScript("return arguments[0].shadowRoot", element);
return ele;
}
}
Below snippet navigates to the the chrome settings for clearing the browser data and sends a keypress to the opened dialog. Then it waits for the tab to close. You could easily do these steps manual.
IWebDriver Driver = new ChromeDriver()
Driver.Navigate().GoToUrl("chrome://settings/clearBrowserData");
Driver.SwitchTo().ActiveElement();
Driver.FindElement(By.XPath("//settings-ui")).SendKeys(Keys.Enter);
var wait = new WebDriverWait(Driver, TimeSpan.FromSeconds(30));
wait.Until(wd => wd.Url.StartsWith("chrome://settings"));
this way work for me :
in step one =>
pip install keyboard
step2 : use it in your code =>
from time import sleep
self.driver.get('chrome://settings/clearBrowserData')
sleep(10)
keyboard.send("Enter")
Method #1 worked for me in clearing JWT using python selenium and chromedriver 87.
# method 1
driver.execute_script('window.localStorage.clear()')
# method 2
driver.execute_script('window.sessionStorage.clear()')
The correct solution is deprecated, I've solved the problem by following this guide:
https://www.browserstack.com/guide/how-to-handle-cookies-in-selenium#:~:text=Navigate%20to%20the%20chrome%20settings,to%20open%20Chrome%20Developer%20Tools.
Specifically, using the command:
driver.manage().deleteAllCookies();
self.driver.get('chrome://settings/clearBrowserData')
time.sleep(0.5) # this is necessary
actions = ActionChains(self.driver)
actions.send_keys(Keys.TAB * 7 + Keys.ENTER)
actions.perform()
The controling protocol already have this task:
https://chromedevtools.github.io/devtools-protocol/tot/Network/#method-clearBrowserCache
And selenium v4+ have this implemented in its API:
driver.getDevTools().send(Network.clearBrowserCache());
For older versions of selenium it's still possible to call this method natively using underlying protocol:
private void clearCache(ChromeDriverService service, WebDriver driver) throws IOException {
Map<String, Object> commandParams = new HashMap<>();
commandParams.put("cmd", "Network.clearBrowserCache");
commandParams.put("params", emptyMap());
ObjectMapper objectMapper = new ObjectMapper();
HttpClient httpClient = HttpClientBuilder.create().build();
String command = objectMapper.writeValueAsString(commandParams);
String u = service.getUrl().toString() + "/session/" + driver.getSessionId() + "/chromium/send_command";
HttpPost request = new HttpPost(u);
request.addHeader("content-type", "application/json");
request.setEntity(new StringEntity(command));
httpClient.execute(request);
}
Note: for chromium you should use "/chromium/send_command" endpoint, for chrome: "/goog/cdp/execute".
But as of my experience, these both work the same way in both chrome and chromium.
Just add below code
driver.manage().deleteAllCookies();
Getting NoSuchElement exception :
driver = new ChromeDriver(service, chromeOption());
driver.manage().deleteAllCookies();
driver.get("chrome://settings/clearBrowserData");
staticWait(5);
driver.switchTo().activeElement();
driver.findElement(By.cssSelector("* /deep/ #clearBrowsingDataConfirm")).click();
Chrome Version : 97.0.4692.71

Appium - running browser tests without clearing browser data

I'm testing a web application on Chrome, Android (real device, not emulator) using Appium. Whenever I launch a test, all browser data (bookmarks, history etc.) is deleted. Is there any way to stop this from happening?
I tried setting the noReset capability to true, but that didn't help.
Thank you in advance for any help
public static Uri testServerAddress = new Uri("http://127.0.01:4723/wd/hub"); // Appium is running locally
public static TimeSpan INIT_TIMEOUT_SEC = TimeSpan.FromSeconds(180);
public void SetUpTest()
{
if (driver == null)
{
DesiredCapabilities testCapabilities = new DesiredCapabilities();
testCapabilities.SetCapability("browserName", "Chrome");
testCapabilities.SetCapability("platformName", "Android");
testCapabilities.SetCapability("deviceName", "S(Galaxy S5)");
testCapabilities.SetCapability("noReset", true);
AppUrl = "http://www.google.com/"; //for example
driver = new RemoteWebDriver(testServerAddress, testCapabilities, INIT_TIMEOUT_SEC);
driver.Manage().Timeouts().ImplicitlyWait(new TimeSpan(0, 0, globalTimeoutInSec));
driver.Navigate().GoToUrl(AppUrl);
}
}
Chromedriver always starts totally fresh, nothing is keeping.
There is option to re-use the existent one (using desired capability androidUseRunningApp) but unfortunately Appium any way will kill it.
Please see more details in this post

Uri to open third party apps for wp8

I tried to create an app that opens some third party apps with the help of its Uri from a Tile. Well, it actually works in opening the third party apps but the problem is, first it launches my app(i.e MainPage is visible for a second) and then only it opens the respective app. Is there any way to make my app's MainPage invisible before opening an app or am i missing anything in Capabilities?
Here is my code :
IconicTileData iconicTileData1 = new IconicTileData();
iconicTileData1.Title = name;
iconicTileData1.SmallIconImage = new Uri("/Icons/Small.png", UriKind.Relative);
iconicTileData1.IconImage = new Uri("/Icons/Metro/" + name + "Medium.png", UriKind.Relative);
IconicTileData iconicTileData2 = iconicTileData1;
Uri navigationUri = new Uri("/MainPage.xaml?target=ms-settings-bluetooth:", UriKind.Relative);
ShellTile.Create(navigationUri, (ShellTileData)iconicTileData2, true);
Thanks in advance for your help.
You could try to specify a "custom" page target (instead of MainPage.xaml) and then make a UriMapper that will allow your app to redirect. Here is a nice blog post on creating a UriMapper. Here is some pseudo-code to help:
public class SettingsUriMapper : UriMapperBase
{
public override Uri MapUri(Uri uri)
{
if (uri.OriginalString.StartsWith == "/LaunchSettings.xaml")
{
// parse which settings to go to
// launch settings uri
}
return uri;
}
}

Best Way to keep Settings for a WinRT App?

I'm working on a WinRT app that's actually also a game. I need to keep different information such as audio settings or player statistics somewhere in sort of a file or somehow. If it's a file, just write settings in or... ? I have an idea but I think is way too rudimentary... What is the best approach to obtain this?
Any help or suggestions are greatly appreciated!
Here are some ways to save Data in a WinRT app, the method with Settings in the name is probably what you are looking for!- just added the other ones as well,- you also can serialize data if you want to. This is working code- but don't forget to add error handling etc. It's a simple demo code :)
As for settings, you can save simple settings as key and values, and for more complex settings you can use a container. I've provided both examples here =)
public class StorageExamples
{
public async Task<string> ReadTextFileAsync(string path)
{
var folder = ApplicationData.Current.LocalFolder;
var file = await folder.GetFileAsync(path);
return await FileIO.ReadTextAsync(file);
}
public async void WriteTotextFileAsync(string fileName, string contents)
{
var folder = ApplicationData.Current.LocalFolder;
var file = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
await FileIO.WriteTextAsync(file, contents);
}
public void SaveSettings(string key, string contents)
{
ApplicationData.Current.LocalSettings.Values[key] = contents;
}
public string LoadSettings(string key)
{
var settings = ApplicationData.Current.LocalSettings;
return settings.Values[key].ToString();
}
public void SaveSettingsInContainer(string user, string key, string contents)
{
var localSetting = ApplicationData.Current.LocalSettings;
localSetting.CreateContainer(user, ApplicationDataCreateDisposition.Always);
if (localSetting.Containers.ContainsKey(user))
{
localSetting.Containers[user].Values[key] = contents;
}
}
}
The MSDN has an article on using app settings in Windows Store apps.
The Windows.UI.ApplicationSettings namespace contains all the classes you need.
Provides classes that allow developers to define the app settings that appear in the settings pane of the Windows shell. The settings pane provides a consistent place for users to access app settings.
Basically these classes let you store application settings and hook them into the standard place for all application settings. Your users don't have to learn anything new, the settings will be in the expected place.