我需要在Chrome中安装和配置扩展程序,以便在Selenium测试执行期间修改所有请求标头。我已经能够在Saucelabs中通过这个support article的例子来展示如何在本地为Firefox做这个,但不知道如何为Chrome做这件事。
extensions的ChromeDriver文档仅用于安装,而不是配置。
问题
计划是针对SauceLabs运行此计划。会尝试使用ModHeader chrome扩展程序来设置所需的标头值。
编辑1
尝试安装Chrome版本的MODHeader扩展程序,但遇到了类似的问题。能够在本地安装扩展,但在远程执行中会看到错误。
private static IWebDriver GetRemoteDriver(string browser)
{
ChromeOptions options = new ChromeOptions();
options.AddExtensions("Tools/Chrome_ModHeader_2_0_6.crx");
DesiredCapabilities capabilities = DesiredCapabilities.Chrome();
capabilities.SetCapability(ChromeOptions.Capability, options);
capabilities.SetCapability("name", buildContext);
capabilities.SetCapability(CapabilityType.BrowserName, "Chrome");
capabilities.SetCapability(CapabilityType.Version, "");
capabilities.SetCapability(CapabilityType.Platform, "Windows 10");
capabilities.SetCapability("screen-resolution", "1280x1024");
capabilities.SetCapability("username", "SaucelabsUserName");
capabilities.SetCapability("accessKey", "SaucelabsAccessKey");
capabilities.SetCapability("build", "BuildNumber");
capabilities.SetCapability("seleniumVersion", "2.50.1");
return new RemoteWebDriver(new Uri("http://ondemand.saucelabs.com/wd/hub"), capabilities);
}
SauceLabs日志中显示的错误是
[1.968][INFO]: RESPONSE InitSession unknown error: cannot parse capability: chromeOptions
from unknown error: unrecognized chrome option: Arguments
答案 0 :(得分:1)
既然你提到问题主要是在远程而且我注意到你正在使用SauceLabs,你有没有看过这篇文章?
Installing an Firefox Extension such as Modify Headers(You would need download the .xpi file on your machine first):
DesiredCapabilities caps = new DesiredCapabilities();
FirefoxProfile profile = new FirefoxProfile();
profile.addExtension(new File("path\of\Modify Headers xpi file"));
profile.setPreference("general.useragent.override", "UA-STRING");
profile.setPreference("extensions.modify_headers.currentVersion", "0.7.1.1-signed");
profile.setPreference("modifyheaders.headers.count", 1);
profile.setPreference("modifyheaders.headers.action0", "Add");
profile.setPreference("modifyheaders.headers.name0", "X-Forwarded-For");
profile.setPreference("modifyheaders.headers.value0", "161.76.79.1");
profile.setPreference("modifyheaders.headers.enabled0", true);
profile.setPreference("modifyheaders.config.active", true);
profile.setPreference("modifyheaders.config.alwaysOn", true);
profile.setPreference("modifyheaders.config.start", true);
caps.setCapability(FirefoxDriver.PROFILE, profile);
NOTE: If you trying to do the same using C#, you would need to use the ToBase64String() method.
答案 1 :(得分:0)
我设法在Saucelabs的Chrome浏览器上安装扩展程序,如下所示:
ChromeOptions options = new ChromeOptions();
options.addExtensions(new File("/path/to/myextrension.crx"));
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(ChromeOptions.CAPABILITY, options);
capabilities.setBrowserName(DesiredCapabilities.chrome().getBrowserName());
// Rest of capabilities config (version, platform, name, ...)
WebDriver driver = new RemoteWebDriver(new URL("http://saucelabs-url/wd/hub"), capabilities);
答案 2 :(得分:0)
我找到了这个问题的解决方案。它适用于我的Selenium GRID和远程Chrome浏览器。 首先,我将在我的项目资源中存储解压缩的ModHeader(版本1.2.4)扩展。它看起来如此
如果我需要在Chrome中修改标题,请执行以下步骤:
1)解压缩从资源扩展到临时文件夹的文件夹
2)在header.json
中设置标题键和值3)使用Java将此扩展名打包到zip文件
4)将zip文件添加到ChromeOptions
public static IDriver getDriverWithCustomHeader(List<HeaderElement> headerList) {
Logger.info(StringUtils.buildString("Create new instance of Driver with header."));
IDriver driver;
DesiredCapabilities capabilities;
switch (GlobalConfig.getInstance().getDriverType()) {
case CHROME:
// define path to resources
String unpackedExtensionPath = FileUtils.getResourcePath("chrome_extension", true);
// setting headers for extension in unpackaged kind
FileUtils.writeToJson(StringUtils.buildString(unpackedExtensionPath, File.separator, "header.json"), headerList);
// packing prepared extension to ZIP with crx extension
String crxExtensionPath = ZipUtils.packZipWithNameOfFolder(unpackedExtensionPath, "crx");
// creating capability based on packed extension
capabilities = CapabilityFactory.getChromeCapabilitiesWithExtension(crxExtensionPath);
driver = new AppiumDriver(GlobalConfig.getInstance().getHost(), GlobalConfig.getInstance().getPort(),
capabilities);
break;
default:
throw new CommonTestRuntimeException("Unsupported Driver Type for changing head args.");
}
drivers.add(driver);
if (defaultDriver != null) {
closeDefaultDriver();
}
defaultDriver.set(driver);
return driver;
}
文件实用程序
public static String getResourcePath(String resourceName, boolean isDir) {
String jarFileName = new File(FileUtils.class.getClassLoader().getResource(resourceName).getPath()).getAbsolutePath()
.replaceAll("(!|file:\\\\)", "");
if (!(jarFileName.contains(".jar"))) {
return getResourcePath(resourceName);
}
if (isDir) {
return getDirPath(resourceName);
}
return getFilePath(resourceName);
}
private static String getResourcePath(String resourceName) {
String resourcePath = FileUtils.class.getClassLoader().getResource(resourceName).getPath();
if (platformIsWindows()) {
resourcePath = resourcePath.substring(1);
}
return resourcePath;
}
private static boolean platformIsWindows() {
boolean platformIsWindows = (File.separatorChar == '\\') ? true : false;
return platformIsWindows;
}
private static String getDirPath(String dirName) {
JarFile jarFile = null;
//check created or no tmp directory
//and if the directory created already we return "it + dirName"
//else we create tmp directory and copy target resources
if (directoryPath.get() == null) {
//set directory path for each thread
directoryPath.set(Files.createTempDir().getAbsolutePath());
}
//copying resources
if (!new File(directoryPath.get() + File.separator + dirName.replaceAll("/", "")).exists()) {
try {
List<JarEntry> dirEntries = new ArrayList<JarEntry>();
File directory = null;
String jarFileName = new File(FileUtils.class.getClassLoader().getResource(dirName).getPath()).getParent()
.replaceAll("(!|file:\\\\)", "").replaceAll("(!|file:)", "");
jarFile = new JarFile(URLDecoder.decode(jarFileName, "UTF-8"));
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry jarEntry = entries.nextElement();
if (jarEntry.getName().startsWith(dirName)) {
if (jarEntry.getName().replaceAll("/", "").equals(dirName.replaceAll("/", ""))) {
directory = new File(directoryPath.get() + File.separator + dirName.replaceAll("/", ""));
directory.mkdirs();
} else
dirEntries.add(jarEntry);
}
}
if (directory == null) {
throw new CommonTestRuntimeException(StringUtils.buildString("There is no directory ", dirName,
"in the jar file"));
}
for (JarEntry dirEntry : dirEntries) {
if (!dirEntry.isDirectory()) {
File dirFile = new File(directory.getParent() + File.separator + dirEntry.getName());
dirFile.createNewFile();
convertStreamToFile(dirEntry.getName(), dirFile);
} else {
File dirFile = new File(directory.getParent() + File.separator + dirEntry.getName());
dirFile.mkdirs();
}
}
return directory.getAbsolutePath();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
jarFile.close();
} catch (Exception e) {
e.printStackTrace();
}
}
throw new CommonTestRuntimeException("There are problems in creation files in directory " + directoryPath);
} else {
return directoryPath.get() + File.separator + dirName.replaceAll("/", "");
}
}
private static String getFilePath(String fileName) {
try {
String[] fileType = fileName.split("\\.");
int typeIndex = fileType.length;
File file = File.createTempFile(StringUtils.generateRandomString("temp"),
StringUtils.buildString(".", fileType[typeIndex - 1]));
file.deleteOnExit();
convertStreamToFile(fileName, file);
return file.getAbsolutePath();
} catch (IOException e) {
e.printStackTrace();
}
throw new CommonTestRuntimeException("Impossible to get file path");
}
private static void convertStreamToFile(String resourceFileName, File file) throws IOException {
try (InputStream in = FileUtils.class.getClassLoader().getResourceAsStream(resourceFileName);
BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF8"));
FileOutputStream fos = new FileOutputStream(file);
OutputStreamWriter fileOutputStreamWriter = new OutputStreamWriter(fos, "UTF8");
BufferedWriter fileWriter = new BufferedWriter(fileOutputStreamWriter);
) {
String line = null;
while ((line = reader.readLine()) != null) {
fileWriter.write(line + "\n");
}
}
}
public static void writeToJson(String jsonFilePath, Object object) {
try {
Gson gson = new Gson();
FileWriter fileWriter = new FileWriter(jsonFilePath);
fileWriter.write(gson.toJson(object));
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
ZipUtils
public static String packZipWithNameOfFolder(String folder, String extension) {
String outZipPath = folder + "." + extension;
try {
try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(outZipPath))) {
File file = new File(folder);
doZip(file, zos);
}
} catch (IOException e) {
throw new CommonTestRuntimeException("Fail of packaging of folder. ", e);
}
return outZipPath;
}
private static void doZip(File dir, ZipOutputStream out) throws IOException {
for (File f: dir.listFiles()) {
if (f.isDirectory()) {
doZip(f, out);
} else {
out.putNextEntry(new ZipEntry(f.getName()));
try (FileInputStream in = new FileInputStream(f)) {
write(in, out);
}
}
}
}
private static void write (InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer)) >= 0) {
out.write(buffer, 0, len);
}
}
CapabilityFactory.getChromeCapabilitiesWithExtension(...)
public static DesiredCapabilities getChromeCapabilitiesWithExtension(String crxExtensionPath) {
DesiredCapabilities chromeCapabilities = getChromeCapabilities();
Logger.info("Extension path: " + crxExtensionPath);
ChromeOptions options = new ChromeOptions();
options.addExtensions(new File(crxExtensionPath));
options.addArguments("--start-maximized");
chromeCapabilities.setCapability(ChromeOptions.CAPABILITY, options);
return chromeCapabilities;
}
答案 3 :(得分:0)
public void AddHeaderChrome()
{
ChromeOptions options = new ChromeOptions();
options.addExtensions(new File("C:\\Downloads\\ModHeader_v2.0.9.crx"));
DesiredCapabilities capabilities = DesiredCapabilities.internetExplorer();
capabilities.setCapability(CapabilityType.options);
// launch the browser
WebDriver driver = new ChromeDriver(options);
String HeadersName[]=new String[10];
String HeadersValue[]=new String[10];;
int length;
if(ConfigDetails.HeadersName.contains(","))
{
HeadersName=ConfigDetails.HeadersName.split(",");
HeadersValue=ConfigDetails.HeadersValue.split(",");
length=HeadersName.length;
}
else
{
HeadersName[0]=ConfigDetails.HeadersName;
HeadersValue[0]=ConfigDetails.HeadersValue;
length=1;
}
int field_no=1;
for(int i=0;i<length;i++)
{
driver.get("chrome-extension://idgpnmonknjnojddfkpgkljpfnnfcklj/popup.html");
driver.findElement(By.xpath("//input[@id='fl-input-"+field_no+"']")).sendKeys(HeadersName[i]);
driver.findElement(By.xpath("//input[@id='fl-input-"+(field_no+1)+"']")).sendKeys(HeadersValue[i]);
field_no+=2
}
答案 4 :(得分:0)
Chrome上的扩展程序具有常量唯一ID。
您可以使用selenium web驱动程序导航到chrome-extension://<EXTENSION_UUIF>/options.html
,此处options.html
是您定义的首选项页面。
然后执行一段脚本来更改chrome.storage.local
中存储的设置。
答案 5 :(得分:-1)
public void AddHeaderFirefox(FirefoxProfile profile)
{
String directory = System.getProperty("user.dir");
FirefoxProfile profile = new FirefoxProfile();
try
{
profile.addExtension(new File(directory+"/modify-headers-0.7.1.1.xpi"));
}
catch(IOException e)
{
System.out.println(e);
}
String HeadersName[]=new String[10];
String HeadersValue[]=new String[10];
if(ConfigDetails.HeadersName.contains(",") && ConfigDetails.HeadersValue.contains(","))
{
HeadersName=ConfigDetails.HeadersName.split(",");
HeadersValue=ConfigDetails.HeadersValue.split(",");
length=HeadersName.length;
}
You have to parametrise the header USING Split function of java to set
multiple headers.
for(int i=0;i<length;i++)
{
profile.setPreference("modifyheaders.headers.count",i+1);
profile.setPreference("modifyheaders.headers.action"+i, "Add");
profile.setPreference("modifyheaders.headers.name"+i,HeadersName[i]);
profile.setPreference("modifyheaders.headers.value"+i,HeadersValue[i]);
profile.setPreference("modifyheaders.headers.enabled"+i, true);
profile.setPreference("modifyheaders.config.active", true);
profile.setPreference("modifyheaders.config.alwaysOn", true);
}