这是本节的多页打印视图。 点击此处打印.

返回本页常规视图.

浏览器交互

获取浏览器信息

获取标题

从浏览器中读取当前页面的标题:

 String title = driver.getTitle();
title = driver.title
 String title = driver.Title;
 it 'gets the current title' do
 let title = await driver.getTitle();
driver.title

获取当前 URL

您可以从浏览器的地址栏读取当前的 URL,使用:

 String url = driver.getCurrentUrl();
url = driver.current_url
 String url = driver.Url;
 it 'gets the current url' do
 let currentUrl = await driver.getCurrentUrl();
driver.currentUrl

1 - 浏览器导航

打开网站

启动浏览器后你要做的第一件事就是打开你的网站。这可以通过一行代码实现:

 //Convenient  driver.get("https://selenium.dev");   //Longer way  driver.navigate().to("https://selenium.dev");
driver.get("https://www.selenium.dev/selenium/web/index.html")
 //Convenient  driver.Url = "https://selenium.dev";  //Longer  driver.Navigate().GoToUrl("https://selenium.dev");
  it 'navigates to a page' do  driver.navigate.to 'https://www.selenium.dev/'
 //Convenient  await driver.get('https://www.selenium.dev');   //Longer way  await driver.navigate().to("https://www.selenium.dev/selenium/web/index.html");
// 简便的方法 driver.get("https://selenium.dev")  // 更长的方法 driver.navigate().to("https://selenium.dev")

后退

按下浏览器的后退按钮:

 //Back  driver.navigate().back();
driver.back()
 //Back  driver.Navigate().Back();
 driver.navigate.to 'https://www.selenium.dev/'
 //Back  await driver.navigate().back();
driver.navigate().back() 

前进

按下浏览器的前进键:

 //Forward  driver.navigate().forward();
driver.forward()
 //Forward  driver.Navigate().Forward();
 driver.navigate.to 'https://www.selenium.dev/selenium/web/inputs.html'
 //Forward  await driver.navigate().forward();
driver.navigate().forward()

刷新

刷新当前页面:

 //Refresh  driver.navigate().refresh();
driver.refresh()
 //Refresh  driver.Navigate().Refresh();
 it 'refreshes the page' do
 //Refresh  await driver.navigate().refresh();
driver.navigate().refresh()

2 - JavaScript 警告框,提示框和确认框

WebDriver提供了一个API, 用于处理JavaScript提供的三种类型的原生弹窗消息. 这些弹窗由浏览器提供限定的样式.

Alerts 警告框

其中最基本的称为警告框, 它显示一条自定义消息, 以及一个用于关闭该警告的按钮, 在大多数浏览器中标记为"确定"(OK). 在大多数浏览器中, 也可以通过按"关闭"(close)按钮将其关闭, 但这始终与“确定”按钮具有相同的作用. 查看样例警告框.

WebDriver可以从弹窗获取文本并接受或关闭这些警告.

 import static org.junit.jupiter.api.Assertions.assertEquals;  public class AlertsTest extends BaseTest {   @BeforeEach
 element = driver.find_element(By.LINK_TEXT, "See an example alert")  element.click()   wait = WebDriverWait(driver, timeout=2)  alert = wait.until(lambda d : d.switch_to.alert)  text = alert.text  alert.accept()
//Click the link to activate the alert driver.FindElement(By.LinkText("See an example alert")).Click();  //Wait for the alert to be displayed and store it in a variable IAlert alert = wait.Until(ExpectedConditions.AlertIsPresent());  //Store the alert text in a variable string text = alert.Text;  //Press the OK button alert.Accept();  
 # Store the alert reference in a variable  alert = driver.switch_to.alert   # Get the text of the alert  alert.text   # Press on Cancel button  alert.dismiss
 let alert = await driver.switchTo().alert();  let alertText = await alert.getText();  await alert.accept();
//Click the link to activate the alert driver.findElement(By.linkText("See an example alert")).click()  //Wait for the alert to be displayed and store it in a variable val alert = wait.until(ExpectedConditions.alertIsPresent())  //Store the alert text in a variable val text = alert.getText()  //Press the OK button alert.accept()  

Confirm 确认框

确认框类似于警告框, 不同之处在于用户还可以选择取消消息. 查看样例确认框.

此示例还呈现了警告的另一种实现:

 driver.findElement(By.id("slow-alert")).click();   wait.until(ExpectedConditions.alertIsPresent());   Alert alert = driver.switchTo().alert();  Assertions.assertEquals("Slow", alert.getText());   alert.accept();
 element = driver.find_element(By.LINK_TEXT, "See a sample confirm")  driver.execute_script("arguments[0].click();", element)   wait = WebDriverWait(driver, timeout=2)  alert = wait.until(lambda d : d.switch_to.alert)  text = alert.text  alert.dismiss()
//Click the link to activate the alert driver.FindElement(By.LinkText("See a sample confirm")).Click();  //Wait for the alert to be displayed wait.Until(ExpectedConditions.AlertIsPresent());  //Store the alert in a variable IAlert alert = driver.SwitchTo().Alert();  //Store the alert in a variable for reuse string text = alert.Text;  //Press the Cancel button alert.Dismiss();  
 # Store the alert reference in a variable  alert = driver.switch_to.alert   # Get the text of the alert  alert.text   # Press on Cancel button  alert.dismiss
 let alert = await driver.switchTo().alert();  let alertText = await alert.getText();  await alert.dismiss();
//Click the link to activate the alert driver.findElement(By.linkText("See a sample confirm")).click()  //Wait for the alert to be displayed wait.until(ExpectedConditions.alertIsPresent())  //Store the alert in a variable val alert = driver.switchTo().alert()  //Store the alert in a variable for reuse val text = alert.text  //Press the Cancel button alert.dismiss()  

Prompt 提示框

提示框与确认框相似, 不同之处在于它们还包括文本输入. 与处理表单元素类似, 您可以使用WebDriver的sendKeys来填写响应. 这将完全替换占位符文本. 按下取消按钮将不会提交任何文本. 查看样例提示框.

 @Test  public void promptDisplayAndInputTest() {  driver.get("https://www.selenium.dev/selenium/web/alerts.html#");  driver.findElement(By.id("prompt")).click();   //Wait for the alert to be displayed and store it in a variable
 element = driver.find_element(By.LINK_TEXT, "See a sample prompt")  driver.execute_script("arguments[0].click();", element)   wait = WebDriverWait(driver, timeout=2)  alert = wait.until(lambda d : d.switch_to.alert)  alert.send_keys("Selenium")  text = alert.text  alert.accept()
//Click the link to activate the alert driver.FindElement(By.LinkText("See a sample prompt")).Click();  //Wait for the alert to be displayed and store it in a variable IAlert alert = wait.Until(ExpectedConditions.AlertIsPresent());  //Type your message alert.SendKeys("Selenium");  //Press the OK button alert.Accept();  
 # Store the alert reference in a variable  alert = driver.switch_to.alert   # Type a message  alert.send_keys('selenium')   # Press on Ok button  alert.accept
 let alert = await driver.switchTo().alert();  //Type your message  await alert.sendKeys(text);  await alert.accept();
//Click the link to activate the alert driver.findElement(By.linkText("See a sample prompt")).click()  //Wait for the alert to be displayed and store it in a variable val alert = wait.until(ExpectedConditions.alertIsPresent())  //Type your message alert.sendKeys("Selenium")  //Press the OK button alert.accept()  

3 - 同cookies一起工作

Cookie是从网站发送并存储在您的计算机中的一小段数据. Cookies主要用于识别用户并加载存储的信息.

WebDriver API提供了一种使用内置的方法与Cookie进行交互:

这个方法常常用于将cookie添加到当前访问的上下文中. 添加Cookie仅接受一组已定义的可序列化JSON对象. 这里 是一个链接, 用于描述可接受的JSON键值的列表

首先, 您需要位于有效Cookie的域上. 如果您在开始与网站进行交互之前尝试预设cookie, 并且您的首页很大或需要一段时间才能加载完毕, 则可以选择在网站上找到一个较小的页面 (通常404页很小, 例如 http://example.com/some404page)

@Test  public void addCookie() {  driver.get("https://www.selenium.dev/selenium/web/blank.html");
 driver = webdriver.Chrome()  driver.get("http://www.example.com")   # Adds the cookie into current browser context  driver.add_cookie({"name": "key", "value": "value"})
 driver.Url="https://www.selenium.dev/selenium/web/blank.html";  // Add cookie into current browser context  driver.Manage().Cookies.AddCookie(new Cookie("key", "value"));
 driver.navigate.to 'https://www.selenium.dev/selenium/web/blank.html'  # Add cookie into current browser context  driver.manage.add_cookie(name: 'key', value: 'value')
 await driver.get('https://www.selenium.dev/selenium/web/blank.html');
import org.openqa.selenium.Cookie import org.openqa.selenium.chrome.ChromeDriver  fun main() {  val driver = ChromeDriver()  try {  driver.get("https://example.com")   // Adds the cookie into current browser context  driver.manage().addCookie(Cookie("key", "value"))  } finally {  driver.quit()  } }  

此方法返回与cookie名称匹配的序列化cookie数据中所有关联的cookie.

 public void getNamedCookie() {   driver.get("https://www.selenium.dev/selenium/web/blank.html");  // Add cookie into current browser context  driver.manage().addCookie(new Cookie("foo", "bar"));
 driver = webdriver.Chrome()  driver.get("http://www.example.com")   # Adds the cookie into current browser context  driver.add_cookie({"name": "foo", "value": "bar"})   # Get cookie details with named cookie 'foo'  print(driver.get_cookie("foo"))
 driver.Url = "https://www.selenium.dev/selenium/web/blank.html";  // Add cookie into current browser context  driver.Manage().Cookies.AddCookie(new Cookie("foo", "bar"));  // Get cookie details with named cookie 'foo'  Cookie cookie = driver.Manage().Cookies.GetCookieNamed("foo");
 driver.navigate.to 'https://www.selenium.dev/selenium/web/blank.html'  # Add cookie into current browser context  driver.manage.add_cookie(name: 'foo', value: 'bar')  # Get cookie details with named cookie 'foo'  cookie = driver.manage.cookie_named('foo')
 // set a cookie on the current domain  await driver.manage().addCookie({ name: 'foo', value: 'bar' });   // Get cookie details with named cookie 'foo' 
import org.openqa.selenium.Cookie import org.openqa.selenium.chrome.ChromeDriver  fun main() {  val driver = ChromeDriver()  try {  driver.get("https://example.com")  driver.manage().addCookie(Cookie("foo", "bar"))   // Get cookie details with named cookie 'foo'  val cookie = driver.manage().getCookieNamed("foo")  println(cookie)  } finally {  driver.quit()  } }  

获取全部 Cookies

此方法会针对当前访问上下文返回“成功的序列化cookie数据”. 如果浏览器不再可用, 则返回错误.

 public void getAllCookies() {   driver.get("https://www.selenium.dev/selenium/web/blank.html");  // Add cookies into current browser context  driver.manage().addCookie(new Cookie("test1", "cookie1"));  driver.manage().addCookie(new Cookie("test2", "cookie2"));  // Get cookies  Set<Cookie> cookies = driver.manage().getCookies();  for (Cookie cookie : cookies) {  if (cookie.getName().equals("test1")) {  Assertions.assertEquals(cookie.getValue(), "cookie1");  }   if (cookie.getName().equals("test2")) {  Assertions.assertEquals(cookie.getValue(), "cookie2");
 driver = webdriver.Chrome()   driver.get("http://www.example.com")   driver.add_cookie({"name": "test1", "value": "cookie1"})  driver.add_cookie({"name": "test2", "value": "cookie2"})   # Get all available cookies  print(driver.get_cookies())
 driver.Url = "https://www.selenium.dev/selenium/web/blank.html";  // Add cookies into current browser context  driver.Manage().Cookies.AddCookie(new Cookie("test1", "cookie1"));  driver.Manage().Cookies.AddCookie(new Cookie("test2", "cookie2"));  // Get cookies  var cookies = driver.Manage().Cookies.AllCookies;  foreach (var cookie in cookies){  if (cookie.Name.Equals("test1")){  Assert.AreEqual("cookie1", cookie.Value);  }  if (cookie.Name.Equals("test2")){  Assert.AreEqual("cookie2", cookie.Value);  }  }
 driver.navigate.to 'https://www.selenium.dev/selenium/web/blank.html'  # Add cookies into current browser context  driver.manage.add_cookie(name: 'test1', value: 'cookie1')  driver.manage.add_cookie(name: 'test2', value: 'cookie2')  # Get cookies  cookies = driver.manage.all_cookies
 await driver.manage().addCookie({ name: 'test2', value: 'cookie2' });   // Get all Available cookies 
import org.openqa.selenium.Cookie import org.openqa.selenium.chrome.ChromeDriver  fun main() {  val driver = ChromeDriver()  try {  driver.get("https://example.com")  driver.manage().addCookie(Cookie("test1", "cookie1"))  driver.manage().addCookie(Cookie("test2", "cookie2"))   // Get All available cookies  val cookies = driver.manage().cookies  println(cookies)  } finally {  driver.quit()  } }  

此方法删除与提供的cookie名称匹配的cookie数据.

 public void deleteCookieNamed() {   driver.get("https://www.selenium.dev/selenium/web/blank.html");  driver.manage().addCookie(new Cookie("test1", "cookie1"));
 driver = webdriver.Chrome()   driver.get("http://www.example.com")   driver.add_cookie({"name": "test1", "value": "cookie1"})  driver.add_cookie({"name": "test2", "value": "cookie2"})   # Delete cookie with name 'test1'  driver.delete_cookie("test1")
 driver.Url = "https://www.selenium.dev/selenium/web/blank.html";  driver.Manage().Cookies.AddCookie(new Cookie("test1", "cookie1"));  // delete cookie named  driver.Manage().Cookies.DeleteCookieNamed("test1");
 driver.navigate.to 'https://www.selenium.dev/selenium/web/blank.html'  driver.manage.add_cookie(name: 'test1', value: 'cookie1')  # Delete cookie named  driver.manage.delete_cookie('test1')
 await driver.manage().addCookie({ name: 'test1', value: 'cookie1' });  await driver.manage().addCookie({ name: 'test2', value: 'cookie2' });
import org.openqa.selenium.Cookie import org.openqa.selenium.chrome.ChromeDriver  fun main() {  val driver = ChromeDriver()  try {  driver.get("https://example.com")  driver.manage().addCookie(Cookie("test1", "cookie1"))  val cookie1 = Cookie("test2", "cookie2")  driver.manage().addCookie(cookie1)   // delete a cookie with name 'test1'  driver.manage().deleteCookieNamed("test1")   // delete cookie by passing cookie object of current browsing context.  driver.manage().deleteCookie(cookie1)  } finally {  driver.quit()  } }  

删除所有 Cookies

此方法删除当前访问上下文的所有cookie.

 public void deleteAllCookies() {   driver.get("https://www.selenium.dev/selenium/web/blank.html");  // Add cookies into current browser context  driver.manage().addCookie(new Cookie("test1", "cookie1"));  driver.manage().addCookie(new Cookie("test2", "cookie2"));
 driver = webdriver.Chrome()   driver.get("http://www.example.com")   driver.add_cookie({"name": "test1", "value": "cookie1"})  driver.add_cookie({"name": "test2", "value": "cookie2"})   # Delete all cookies  driver.delete_all_cookies()
 driver.Url = "https://www.selenium.dev/selenium/web/blank.html";  // Add cookies into current browser context  driver.Manage().Cookies.AddCookie(new Cookie("test1", "cookie1"));  driver.Manage().Cookies.AddCookie(new Cookie("test2", "cookie2"));  // Delete All cookies  driver.Manage().Cookies.DeleteAllCookies();
 driver.navigate.to 'https://www.selenium.dev/selenium/web/blank.html'  # Add cookies into current browser context  driver.manage.add_cookie(name: 'test1', value: 'cookie1')  driver.manage.add_cookie(name: 'test2', value: 'cookie2')  # Delete All cookies  driver.manage.delete_all_cookies
 await driver.manage().addCookie({ name: 'test1', value: 'cookie1' });  await driver.manage().addCookie({ name: 'test2', value: 'cookie2' });
import org.openqa.selenium.Cookie import org.openqa.selenium.chrome.ChromeDriver  fun main() {  val driver = ChromeDriver()  try {  driver.get("https://example.com")  driver.manage().addCookie(Cookie("test1", "cookie1"))  driver.manage().addCookie(Cookie("test2", "cookie2"))   // deletes all cookies  driver.manage().deleteAllCookies()  } finally {  driver.quit()  } }  

Same-Site Cookie属性

此属性允许用户引导浏览器控制cookie, 是否与第三方站点发起的请求一起发送. 引入其是为了防止CSRF(跨站请求伪造)攻击.

Same-Site cookie属性接受以下两种参数作为指令

Strict:

当sameSite属性设置为 Strict, cookie不会与来自第三方网站的请求一起发送.

Lax:

当您将cookie sameSite属性设置为 Lax, cookie将与第三方网站发起的GET请求一起发送.

注意: 到目前为止, 此功能已在Chrome(80+版本), Firefox(79+版本)中提供, 并适用于Selenium 4以及更高版本.

 @Test  public void sameSiteCookie() {  driver.get("http://www.example.com");   Cookie cookie = new Cookie.Builder("key", "value").sameSite("Strict").build();  Cookie cookie1 = new Cookie.Builder("key", "value").sameSite("Lax").build();   driver.manage().addCookie(cookie);  driver.manage().addCookie(cookie1); 
 driver = webdriver.Chrome()   driver.get("http://www.example.com")   # Adds the cookie into current browser context with sameSite 'Strict' (or) 'Lax'  driver.add_cookie({"name": "foo", "value": "value", "sameSite": "Strict"})  driver.add_cookie({"name": "foo1", "value": "value", "sameSite": "Lax"})   cookie1 = driver.get_cookie("foo")  cookie2 = driver.get_cookie("foo1")   print(cookie1)  print(cookie2)
using OpenQA.Selenium; using OpenQA.Selenium.Chrome;  namespace SameSiteCookie {  class SameSiteCookie {  static void Main(string[] args) {  IWebDriver driver = new ChromeDriver();  try {  driver.Navigate().GoToUrl("http://www.example.com");   var cookie1Dictionary = new System.Collections.Generic.Dictionary<string, object>() {  { "name", "test1" }, { "value", "cookie1" }, { "sameSite", "Strict" } };  var cookie1 = Cookie.FromDictionary(cookie1Dictionary);   var cookie2Dictionary = new System.Collections.Generic.Dictionary<string, object>() {  { "name", "test2" }, { "value", "cookie2" }, { "sameSite", "Lax" } };  var cookie2 = Cookie.FromDictionary(cookie2Dictionary);   driver.Manage().Cookies.AddCookie(cookie1);  driver.Manage().Cookies.AddCookie(cookie2);   System.Console.WriteLine(cookie1.SameSite);  System.Console.WriteLine(cookie2.SameSite);  } finally {  driver.Quit();  }  }  } }  
require 'selenium-webdriver' driver = Selenium::WebDriver.for :chrome  begin  driver.get 'https://www.example.com'  # Adds the cookie into current browser context with sameSite 'Strict' (or) 'Lax'  driver.manage.add_cookie(name: "foo", value: "bar", same_site: "Strict")  driver.manage.add_cookie(name: "foo1", value: "bar", same_site: "Lax")  puts driver.manage.cookie_named('foo')  puts driver.manage.cookie_named('foo1') ensure  driver.quit end  
 it('Create cookies with sameSite', async function() {  await driver.get('https://www.selenium.dev/selenium/web/blank.html'); 
import org.openqa.selenium.Cookie import org.openqa.selenium.chrome.ChromeDriver  fun main() {  val driver = ChromeDriver()  try {  driver.get("http://www.example.com")  val cookie = Cookie.Builder("key", "value").sameSite("Strict").build()  val cookie1 = Cookie.Builder("key", "value").sameSite("Lax").build()  driver.manage().addCookie(cookie)  driver.manage().addCookie(cookie1)  println(cookie.getSameSite())  println(cookie1.getSameSite())  } finally {  driver.quit()  } }  

4 - 与IFrames和frames一起工作

框架是一种现在已被弃用的方法,用于从同一域中的多个文档构建站点布局。除非你使用的是 HTML5 之前的 webapp,否则你不太可能与他们合作。内嵌框架允许插入来自完全不同领域的文档,并且仍然经常使用。

如果您需要使用框架或 iframe, WebDriver 允许您以相同的方式使用它们。考虑 iframe 中的一个按钮。 如果我们使用浏览器开发工具检查元素,我们可能会看到以下内容:

<div id="modal">  <iframe id="buttonframe"name="myframe"src="https://seleniumhq.github.io">  <button>Click here</button>  </iframe> </div> 

如果不是 iframe,我们可能会使用如下方式点击按钮:

// 这不会工作 driver.findElement(By.tagName("button")).click();
 # 这不会工作 driver.find_element(By.TAG_NAME, 'button').click()
// 这不会工作 driver.FindElement(By.TagName("button")).Click();
 # 这不会工作 driver.find_element(:tag_name,'button').click
// 这不会工作 await driver.findElement(By.css('button')).click();
// 这不会工作 driver.findElement(By.tagName("button")).click()

但是,如果 iframe 之外没有按钮,那么您可能会得到一个 no such element 无此元素 的错误。 这是因为 Selenium 只知道顶层文档中的元素。为了与按钮进行交互,我们需要首先切换到框架, 这与切换窗口的方式类似。WebDriver 提供了三种切换到帧的方法。

使用 WebElement

使用 WebElement 进行切换是最灵活的选择。您可以使用首选的选择器找到框架并切换到它。

 //switch To IFrame using Web Element  WebElement iframe = driver.findElement(By.id("iframe1"));  //Switch to the frame  driver.switchTo().frame(iframe);  assertEquals(true, driver.getPageSource().contains("We Leave From Here"));  //Now we can type text into email field  WebElement emailE = driver.findElement(By.id("email"));  emailE.sendKeys("admin@selenium.dev");  emailE.clear();
# --- Switch to iframe using WebElement --- iframe = driver.find_element(By.ID, "iframe1") driver.switch_to.frame(iframe) assert "We Leave From Here" in driver.page_source  email_element = driver.find_element(By.ID, "email") email_element.send_keys("admin@selenium.dev") email_element.clear() driver.switch_to.default_content()
 //switch To IFrame using Web Element  IWebElement iframe = driver.FindElement(By.Id("iframe1"));  //Switch to the frame  driver.SwitchTo().Frame(iframe);  Assert.AreEqual(true, driver.PageSource.Contains("We Leave From Here"));  //Now we can type text into email field  IWebElement emailE = driver.FindElement(By.Id("email"));  emailE.SendKeys("admin@selenium.dev");  emailE.Clear();
 iframe = driver.find_element(:id, 'iframe1')  driver.switch_to.frame(iframe)  expect(driver.page_source).to include('We Leave From Here')   email_element = driver.find_element(:id, 'email')  email_element.send_keys('admin@selenium.dev')  email_element.clear  driver.switch_to.default_content
// 存储网页元素 const iframe = driver.findElement(By.css('#modal> iframe'));  // 切换到 frame await driver.switchTo().frame(iframe);  // 现在可以点击按钮 await driver.findElement(By.css('button')).click();
// 存储网页元素 val iframe = driver.findElement(By.cssSelector("#modal>iframe"))  // 切换到 frame driver.switchTo().frame(iframe)  // 现在可以点击按钮 driver.findElement(By.tagName("button")).click()

使用 name 或 id

如果您的 frame 或 iframe 具有 id 或 name 属性,则可以使用该属性。如果名称或 id 在页面上不是唯一的, 那么将切换到找到的第一个。

 //switch To IFrame using name or id  WebElement iframe1=driver.findElement(By.name("iframe1-name"));  //Switch to the frame  driver.switchTo().frame(iframe1);  assertEquals(true, driver.getPageSource().contains("We Leave From Here"));  WebElement email = driver.findElement(By.id("email"));  //Now we can type text into email field  email.sendKeys("admin@selenium.dev");  email.clear();
# --- Switch to iframe using name or ID --- iframe1=driver.find_element(By.NAME, "iframe1-name") # (This line doesn't switch, just locates) driver.switch_to.frame(iframe1) assert "We Leave From Here" in driver.page_source  email = driver.find_element(By.ID, "email") email.send_keys("admin@selenium.dev") email.clear() driver.switch_to.default_content()
 //switch To IFrame using name or id  IWebElement iframe1=driver.FindElement(By.Name("iframe1-name"));  //Switch to the frame  driver.SwitchTo().Frame(iframe1);  Assert.AreEqual(true, driver.PageSource.Contains("We Leave From Here"));  IWebElement email = driver.FindElement(By.Id("email"));  //Now we can type text into email field  email.SendKeys("admin@selenium.dev");  email.Clear();
 iframe1 = driver.find_element(:name, 'iframe1-name')  driver.switch_to.frame(iframe1)  expect(driver.page_source).to include('We Leave From Here')   email = driver.find_element(:id, 'email')  email.send_keys('admin@selenium.dev')  email.clear  driver.switch_to.default_content
// 使用 ID await driver.switchTo().frame('buttonframe');  // 或者使用 name 代替 await driver.switchTo().frame('myframe');  // 现在可以点击按钮 await driver.findElement(By.css('button')).click();
// 使用 ID driver.switchTo().frame("buttonframe")  // 或者使用 name 代替 driver.switchTo().frame("myframe")  // 现在可以点击按钮 driver.findElement(By.tagName("button")).click()

使用索引

还可以使用frame的索引, 例如可以使用JavaScript中的 window.frames 进行查询.

 //switch To IFrame using index  driver.switchTo().frame(0);
driver.switch_to.frame(0) assert "We Leave From Here" in driver.page_source
 //switch To IFrame using index  driver.SwitchTo().Frame(0);
 driver.switch_to.frame(0)  expect(driver.page_source).to include('We Leave From Here')
// 切换到第 2 个框架 await driver.switchTo().frame(1);
// 切换到第 2 个框架 driver.switchTo().frame(1)

离开框架

离开 iframe 或 frameset,切换回默认内容,如下所示:

 //leave frame  driver.switchTo().defaultContent();
driver.switch_to.default_content() assert "This page has iframes" in driver.page_source
 //leave frame  driver.SwitchTo().DefaultContent();
 driver.switch_to.default_content  expect(driver.page_source).to include('This page has iframes')
// 回到顶层 await driver.switchTo().defaultContent();
// 回到顶层 driver.switchTo().defaultContent()

5 - 打印页面

无论是共享信息还是维护档案,打印网页都是一项常见任务。 Selenium 通过其 PrintOptions、PrintsPage 和 browsingContext 类简化了这一过程,这些类为网页自动打印提供了灵活直观的接口。 这些类使得用户可以配置打印首选项,如页面布局、页边距和缩放比例,以确保输出满足特定要求。

配置

方向

通过 getOrientation()setOrientation() 方法,可以获取/设置页面方向(PORTRAITLANDSCAPE)。

 driver.get("https://www.selenium.dev/");  PrintOptions printOptions = new PrintOptions();  printOptions.setOrientation(PrintOptions.Orientation.LANDSCAPE);  PrintOptions.Orientation current_orientation = printOptions.getOrientation();
 public void TestOrientation()  {  IWebDriver driver = new ChromeDriver();  driver.Navigate().GoToUrl("https://selenium.dev");  PrintOptions printOptions = new PrintOptions();  printOptions.Orientation = PrintOrientation.Landscape;  PrintOrientation currentOrientation = printOptions.Orientation;  driver.Quit();
 driver.get("https://www.selenium.dev/")  print_options = PrintOptions()  print_options.orientation = "landscape" ## landscape or portrait

范围

通过 getPageRanges()setPageRanges() 方法,可以获取设置要打印页面的范围(如 “2-4”)。

 driver.get("https://www.selenium.dev/");  PrintOptions printOptions = new PrintOptions();  printOptions.setPageRanges("1-2");  String[] current_range = printOptions.getPageRanges();
 [TestMethod]  public void TestRange()  {  IWebDriver driver = new ChromeDriver();  driver.Navigate().GoToUrl("https://selenium.dev");  PrintOptions printOptions = new PrintOptions();  printOptions.AddPageRangeToPrint("1-3"); // add range of pages  printOptions.AddPageToPrint(5); // add individual page
 driver.get("https://www.selenium.dev/")  print_options = PrintOptions()  print_options.page_ranges = ["1, 2, 3"] ## ["1", "2", "3"] or ["1-3"]

尺寸

通过 getPageSize()setPageSize() 方法,可以获取/设置要打印页面的纸张尺寸(如"A0"、“A6”、“Legal”、“Tabloid” 等)。

 driver.get("https://www.selenium.dev/");  PrintOptions printOptions = new PrintOptions();  printOptions.setPageSize(new PageSize(27.94, 21.59)); // A4 size in cm  double currentHeight = printOptions.getPageSize().getHeight(); // use getWidth() to retrieve width
  [TestMethod]  public void TestSize()  {  IWebDriver driver = new ChromeDriver();  driver.Navigate().GoToUrl("https://www.selenium.dev/");  PrintOptions printOptions = new PrintOptions();
 driver.get("https://www.selenium.dev/")  print_options = PrintOptions()  print_options.page_height = 27.94 # Use page_width to assign width

边距

通过 getPageMargin()setPageMargin() 方法,可以获取/设置要打印页面的边距大小(也就是上、下、左右边距)。

 driver.get("https://www.selenium.dev/");  PrintOptions printOptions = new PrintOptions();  PageMargin margins = new PageMargin(1.0,1.0,1.0,1.0);  printOptions.setPageMargin(margins);  double topMargin = margins.getTop();  double bottomMargin = margins.getBottom();  double leftMargin = margins.getLeft();  double rightMargin = margins.getRight();
 driver.Quit();  }   [TestMethod]  public void TestMargins()  {  IWebDriver driver = new ChromeDriver();
 driver.get("https://www.selenium.dev/")  print_options = PrintOptions()  print_options.margin_top = 10  print_options.margin_bottom = 10  print_options.margin_left = 10  print_options.margin_right = 10

缩放

通过 getScale()setScale() 方法,可以获取/设置要打印页面的缩放尺寸(如 1.0 为 100% 或默认缩放,0.25 为 25% 等)。

 {  driver.get("https://www.selenium.dev/");  PrintOptions printOptions = new PrintOptions();  printOptions.setScale(.50);  double current_scale = printOptions.getScale();
 driver.Quit();  }    [TestMethod]  public void TestScale()  {  IWebDriver driver = new ChromeDriver();
 driver.get("https://www.selenium.dev/")  print_options = PrintOptions()  print_options.scale = 0.5 ## 0.1 to 2.0  current_scale = print_options.scale

背景

通过 getBackground()setBackground() 方法,可以获取/设置背景色和图片出现,其为布尔值 truefalse

 driver.get("https://www.selenium.dev/");  PrintOptions printOptions = new PrintOptions();  printOptions.setBackground(true);  boolean current_background = printOptions.getBackground();
 }   [TestMethod]  public void TestBackgrounds()  {  IWebDriver driver = new ChromeDriver();  driver.Navigate().GoToUrl("https://www.selenium.dev/");  PrintOptions printOptions = new PrintOptions();
 driver.get("https://www.selenium.dev/")  print_options = PrintOptions()  print_options.background = True ## True or False

缩放至合适大小

通过 getShrinkToFit()setShrinkToFit() 方法,可以获取/设置页面是否会根据页面内容缩小,其为布尔值 truefalse

 driver.get("https://www.selenium.dev/");  PrintOptions printOptions = new PrintOptions();  printOptions.setShrinkToFit(true);  boolean current_shrink_to_fit = printOptions.getShrinkToFit();
 printOptions.ScaleFactor = 0.5;  double currentScale = printOptions.ScaleFactor;  driver.Quit();  }   [TestMethod]  public void TestShrinkToFit()  {
 driver.get("https://www.selenium.dev/")  print_options = PrintOptions()  print_options.shrink_to_fit = True ## True or False

打印

配置好打印选项后,就可以打印页面了。为此,您可以调用打印功能,生成网页的 PDF 表示形式。 生成的 PDF 文件可以保存到本地存储器中,以便进一步使用或分发。 使用 PrintsPage() 时,打印命令将以 base64 编码格式返回 PDF 数据,该格式可以解码并写入所需位置的文件,而使用 BrowsingContext() 时将返回字符串。

目前可能有多种实现方式,这取决于您所选择的语言。例如,Java 可以使用 BrowingContext()PrintsPage() 进行打印。两者都将 PrintOptions() 对象作为一个参数。

注意:BrowsingContext() 是 Selenium BiDi 实现的一部分。为启用 BiDi,请参见启用 Bidi

PrintsPage()

 driver.get("https://www.selenium.dev/");  PrintsPage printer = (PrintsPage) driver;  PrintOptions printOptions = new PrintOptions();  Pdf printedPage = printer.print(printOptions);  Assertions.assertNotNull(printedPage);

BrowsingContext()

 BrowsingContext browsingContext = new BrowsingContext(driver, driver.getWindowHandle());  driver.get("https://www.selenium.dev/selenium/web/formPage.html");  PrintOptions printOptions = new PrintOptions();  String printPage = browsingContext.print(printOptions);  Assertions.assertTrue(printPage.length() > 0);
 PrintOptions printOptions = new PrintOptions();  printOptions.ShrinkToFit = true;  bool currentShrinkToFit = printOptions.ShrinkToFit;  driver.Quit();  }   [TestMethod]  public void PrintWithPrintsPageTest()

print_page()

 driver.get("https://www.selenium.dev/")  print_options = PrintOptions()  pdf = driver.print_page(print_options)

6 - 同窗口和标签一起工作

窗口和标签页

WebDriver 没有区分窗口和标签页。如果你的站点打开了一个新标签页或窗口,Selenium 将允许您使用窗口句柄来处理它。 每个窗口都有一个唯一的标识符,该标识符在单个会话中保持持久性。你可以使用以下方法获得当前窗口的窗口句柄:

 // Navigate to Url  driver.get("https://www.selenium.dev/selenium/web/window_switching_tests/page_with_frame.html");  //fetch handle of this  String currHandle=driver.getWindowHandle();  assertNotNull(currHandle);
driver.current_window_handle
 // Navigate to Url  driver.Url="https://www.selenium.dev/selenium/web/window_switching_tests/page_with_frame.html";  //fetch handle of this  String currHandle = driver.CurrentWindowHandle;  Assert.IsNotNull(currHandle);
driver.window_handle
await driver.getWindowHandle();
driver.windowHandle

切换窗口或标签页

单击在 <a href=“https://seleniumhq.github.io"target="_blank”>新窗口 中打开链接, 则屏幕会聚焦在新窗口或新标签页上,但 WebDriver 不知道操作系统认为哪个窗口是活动的。 要使用新窗口,您需要切换到它。 如果只有两个选项卡或窗口被打开,并且你知道从哪个窗口开始, 则你可以遍历 WebDriver, 通过排除法可以看到两个窗口或选项卡,然后切换到你需要的窗口或选项卡。

不过,Selenium 4 提供了一个新的 api NewWindow 它创建一个新选项卡 (或) 新窗口并自动切换到它。

 //click on link to open a new window  driver.findElement(By.linkText("Open new window")).click();  //fetch handles of all windows, there will be two, [0]- default, [1] - new window  Object[] windowHandles=driver.getWindowHandles().toArray();  driver.switchTo().window((String) windowHandles[1]);  //assert on title of new window  String title=driver.getTitle();  assertEquals("Simple Page",title);
from selenium import webdriver from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC   # 启动驱动程序 with webdriver.Firefox() as driver:  # 打开网址 driver.get("https://seleniumhq.github.io")   # 设置等待  wait = WebDriverWait(driver, 10)   # 存储原始窗口的 ID  original_window = driver.current_window_handle   # 检查一下,我们还没有打开其他的窗口  assert len(driver.window_handles) == 1   # 单击在新窗口中打开的链接  driver.find_element(By.LINK_TEXT, "new window").click()   # 等待新窗口或标签页  wait.until(EC.number_of_windows_to_be(2))   # 循环执行,直到找到一个新的窗口句柄  for window_handle in driver.window_handles:  if window_handle != original_window:  driver.switch_to.window(window_handle)  break   # 等待新标签页完成加载内容  wait.until(EC.title_is("SeleniumHQ Browser Automation"))
 //click on link to open a new window  driver.FindElement(By.LinkText("Open new window")).Click();  //fetch handles of all windows, there will be two, [0]- default, [1] - new window  IList<string> windowHandles = new List<string>(driver.WindowHandles);  driver.SwitchTo().Window(windowHandles[1]);  //assert on title of new window  String title = driver.Title;  Assert.AreEqual("Simple Page", title);
 # 存储原始窗口的 ID original_window = driver.window_handle   #检查一下,我们还没有打开其他的窗口 assert(driver.window_handles.length == 1,'Expected one window')   #点击在新窗口中打开的链接 driver.find_element(link:'new window').click   #等待新窗口或标签页 wait.until {driver.window_handles.length == 2}   #循环执行,直到找到一个新的窗口句柄 driver.window_handles.each do |handle| if handle != original_window driver.switch_to.window handle break end end   #等待新标签页完成加载内容 wait.until {driver.title =='Selenium documentation'}
// 存储原始窗口的 ID const originalWindow = await driver.getWindowHandle();  // 检查一下,我们还没有打开其他的窗口 assert((await driver.getAllWindowHandles()).length === 1);  // 点击在新窗口中打开的链接 await driver.findElement(By.linkText('new window')).click();  // 等待新窗口或标签页 await driver.wait(async () => (await driver.getAllWindowHandles()).length === 2, 10000 );  // 循环执行,直到找到一个新的窗口句柄 const windows = await driver.getAllWindowHandles(); windows.forEach(async handle => {if (handle !== originalWindow) {await driver.switchTo().window(handle); } });  // 等待新标签页完成加载内容 await driver.wait(until.titleIs('Selenium documentation'), 10000);
// 存储原始窗口的 ID val originalWindow = driver.getWindowHandle()  // 检查一下,我们还没有打开其他的窗口 assert(driver.getWindowHandles().size() === 1)  // 点击在新窗口中打开的链接 driver.findElement(By.linkText("new window")).click()  // 等待新窗口或标签页 wait.until(numberOfWindowsToBe(2))  // 循环执行,直到找到一个新的窗口句柄 for (windowHandle in driver.getWindowHandles()) { if (!originalWindow.contentEquals(windowHandle)) { driver.switchTo().window(windowHandle) break } }  // 等待新标签页完成加载内容 wait.until(titleIs("Selenium documentation"))

关闭窗口或标签页

当你完成了一个窗口或标签页的工作时,_并且_它不是浏览器中最后一个打开的窗口或标签页时,你应该关闭它并切换回你之前使用的窗口。 假设您遵循了前一节中的代码示例,您将把前一个窗口句柄存储在一个变量中。把这些放在一起,你会得到:

 //closing current window  driver.close();  //Switch back to the old tab or window  driver.switchTo().window((String) windowHandles[0]);
 #关闭标签页或窗口 driver.close()   #切回到之前的标签页或窗口 driver.switch_to.window(original_window)
 //closing current window  driver.Close();  //Switch back to the old tab or window  driver.SwitchTo().Window(windowHandles[0]);
 #关闭标签页或窗口 driver.close   #切回到之前的标签页或窗口 driver.switch_to.window original_window
//关闭标签页或窗口 await driver.close();  //切回到之前的标签页或窗口 await driver.switchTo().window(originalWindow);
//关闭标签页或窗口 driver.close()  //切回到之前的标签页或窗口 driver.switchTo().window(originalWindow)

如果在关闭一个窗口后忘记切换回另一个窗口句柄,WebDriver 将在当前关闭的页面上执行,并触发一个 No Such Window Exception 无此窗口异常。必须切换回有效的窗口句柄才能继续执行。

创建新窗口(或)新标签页并且切换

创建一个新窗口 (或) 标签页,屏幕焦点将聚焦在新窗口或标签在上。您不需要切换到新窗口 (或) 标签页。如果除了新窗口之外, 您打开了两个以上的窗口 (或) 标签页,您可以通过遍历 WebDriver 看到两个窗口或选项卡,并切换到非原始窗口。

注意: 该特性适用于 Selenium 4 及其后续版本。

 //Opens a new tab and switches to new tab  driver.switchTo().newWindow(WindowType.TAB);  assertEquals("",driver.getTitle());   //Opens a new window and switches to new window  driver.switchTo().newWindow(WindowType.WINDOW);  assertEquals("",driver.getTitle());
 # 打开新标签页并切换到新标签页 driver.switch_to.new_window('tab')   # 打开一个新窗口并切换到新窗口 driver.switch_to.new_window('window')
 //Opens a new tab and switches to new tab  driver.SwitchTo().NewWindow(WindowType.Tab);  Assert.AreEqual("", driver.Title);   //Opens a new window and switches to new window  driver.SwitchTo().NewWindow(WindowType.Window);  Assert.AreEqual("", driver.Title);

打开新标签页并切换到新标签页

 driver.switch_to.new_window(:tab)

打开一个新窗口并切换到新窗口

 driver.switch_to.new_window(:window)
// 打开新标签页并切换到新标签页
 await driver.switchTo().newWindow('tab');
// 打开一个新窗口并切换到新窗口
 await driver.switchTo().newWindow('window');
// 打开新标签页并切换到新标签页 driver.switchTo().newWindow(WindowType.TAB)  // 打开一个新窗口并切换到新窗口 driver.switchTo().newWindow(WindowType.WINDOW)

在会话结束时退出浏览器

当你完成了浏览器会话,你应该调用 quit 退出,而不是 close 关闭:

 //quitting driver  driver.quit(); //close all windows
driver.quit()
 //quitting driver  driver.Quit(); //close all windows
driver.quit
await driver.quit();
driver.quit()

  • 退出将会
    • 关闭所有与 WebDriver 会话相关的窗口和选项卡
    • 结束浏览器进程
    • 结束后台驱动进程
    • 通知 Selenium Grid 浏览器不再使用,以便可以由另一个会话使用它(如果您正在使用 Selenium Grid)

调用 quit() 失败将留下额外的后台进程和端口运行在机器上,这可能在以后导致一些问题。

有的测试框架提供了一些方法和注释,您可以在测试结束时放入 teardown() 方法中。

/** * 使用 JUnit 的例子 * https://junit.org/junit5/docs/current/api/org/junit/jupiter/api/AfterAll.html */ @AfterAll public static void tearDown() {  driver.quit(); }
 # unittest teardown  # https://docs.python.org/3/library/unittest.html?highlight=teardown#unittest.TestCase.tearDown def tearDown(self): self.driver.quit()
/* 使用 Visual Studio 的 UnitTesting 的例子 https://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.aspx */ [TestCleanup] public void TearDown() {driver.Quit(); }
 # UnitTest Teardown  # https://www.rubydoc.info/github/test-unit/test-unit/Test/Unit/TestCase def teardown @driver.quit end
/** * 使用 Mocha 的例子 * https://mochajs.org/#hooks  */  after('Tear down', async function () {await driver.quit();  });  
/** * 使用 JUnit 的例子 * https://junit.org/junit5/docs/current/api/org/junit/jupiter/api/AfterAll.html */ @AfterAll fun tearDown() { driver.quit() }

如果不在测试上下文中运行 WebDriver,您可以考虑使用 try / finally,这是大多数语言都提供的, 这样一个异常处理仍然可以清理 WebDriver 会话。

try {  //WebDriver 代码… } finally {  driver.quit(); }
try:  #WebDriver 代码… finally: driver.quit()
try {//WebDriver 代码…} finally {driver.Quit(); }
begin  #WebDriver 代码… ensure driver.quit end
try {//WebDriver 代码…} finally {await driver.quit(); }
try {//WebDriver 代码…} finally {driver.quit() }

Python 的 WebDriver 现在支持 Python 上下文管理器,当使用 with 关键字时,可以在执行结束时自动退出驱动程序。

with webdriver.Firefox() as driver:  # WebDriver 代码…  # 在此缩进位置后 WebDriver 会自动退出 

窗口管理

屏幕分辨率会影响 web 应用程序的呈现方式,因此 WebDriver 提供了移动和调整浏览器窗口大小的机制。

获取窗口大小

获取浏览器窗口的大小(以像素为单位)。

// 分别获取每个尺寸 int width = driver.manage().window().getSize().getWidth(); int height = driver.manage().window().getSize().getHeight();  // 或者存储尺寸并在以后查询它们 Dimension size = driver.manage().window().getSize(); int width1 = size.getWidth(); int height1 = size.getHeight();
 # 分别获取每个尺寸 width = driver.get_window_size().get("width") height = driver.get_window_size().get("height")   # 或者存储尺寸并在以后查询它们 size = driver.get_window_size() width1 = size.get("width") height1 = size.get("height")
// 分别获取每个尺寸 int width = driver.Manage().Window.Size.Width; int height = driver.Manage().Window.Size.Height;  // 或者存储尺寸并在以后查询它们 System.Drawing.Size size = driver.Manage().Window.Size; int width1 = size.Width; int height1 = size.Height;
 # 分别获取每个尺寸 width = driver.manage.window.size.width height = driver.manage.window.size.height   # 或者存储尺寸并在以后查询它们 size = driver.manage.window.size width1 = size.width height1 = size.height
分别获取每个尺寸
 const { width, height } = await driver.manage().window().getRect();
或者存储尺寸并在以后查询它们
 const rect = await driver.manage().window().getRect();  const windowWidth = rect.width;  const windowHeight = rect.height;
// 分别获取每个尺寸 val width = driver.manage().window().size.width val height = driver.manage().window().size.height  // 或者存储尺寸并在以后查询它们 val size = driver.manage().window().size val width1 = size.width val height1 = size.height

设置窗口大小

恢复窗口并设置窗口大小。

driver.manage().window().setSize(new Dimension(1024, 768));
driver.set_window_size(1024, 768)
driver.Manage().Window.Size = new Size(1024, 768);
driver.manage.window.resize_to(1024,768)
await driver.manage().window().setRect({width: 1024, height: 768});
driver.manage().window().size = Dimension(1024, 768)

得到窗口的位置

获取浏览器窗口左上角的坐标。

// 分别获取每个尺寸 int x = driver.manage().window().getPosition().getX(); int y = driver.manage().window().getPosition().getY();  // 或者存储尺寸并在以后查询它们 Point position = driver.manage().window().getPosition(); int x1 = position.getX(); int y1 = position.getY();
 # 分别获取每个尺寸 x = driver.get_window_position().get('x') y = driver.get_window_position().get('y')   # 或者存储尺寸并在以后查询它们 position = driver.get_window_position() x1 = position.get('x') y1 = position.get('y')
// 分别获取每个尺寸 int x = driver.Manage().Window.Position.X; int y = driver.Manage().Window.Position.Y;  // 或者存储尺寸并在以后查询它们 Point position = driver.Manage().Window.Position; int x1 = position.X; int y1 = position.Y;
 #Access each dimension individually x = driver.manage.window.position.x y = driver.manage.window.position.y   # Or store the dimensions and query them later rect = driver.manage.window.rect x1 = rect.x y1 = rect.y
分别获取每个尺寸
 const { x, y } = await driver.manage().window().getRect();
或者存储尺寸并在以后查询它们
 const rect = await driver.manage().window().getRect();  const x1 = rect.x;  const y1 = rect.y;
// 分别获取每个尺寸 val x = driver.manage().window().position.x val y = driver.manage().window().position.y  // 或者存储尺寸并在以后查询它们 val position = driver.manage().window().position val x1 = position.x val y1 = position.y

设置窗口位置

将窗口移动到设定的位置。

// 将窗口移动到主显示器的左上角 driver.manage().window().setPosition(new Point(0, 0));
 # 将窗口移动到主显示器的左上角 driver.set_window_position(0, 0)
// 将窗口移动到主显示器的左上角 driver.Manage().Window.Position = new Point(0, 0);
driver.manage.window.move_to(0,0)
// 将窗口移动到主显示器的左上角 await driver.manage().window().setRect({x: 0, y: 0});
// 将窗口移动到主显示器的左上角 driver.manage().window().position = Point(0,0)

最大化窗口

扩大窗口。对于大多数操作系统,窗口将填满屏幕,而不会阻挡操作系统自己的菜单和工具栏。

driver.manage().window().maximize();
driver.maximize_window()
driver.Manage().Window.Maximize();
driver.manage.window.maximize
await driver.manage().window().maximize();
driver.manage().window().maximize()

最小化窗口

最小化当前浏览上下文的窗口. 这种命令的精准行为将作用于各个特定的窗口管理器.

最小化窗口通常将窗口隐藏在系统托盘中.

注意: 此功能适用于Selenium 4以及更高版本.

driver.manage().window().minimize();
driver.minimize_window()
driver.Manage().Window.Minimize();
driver.manage.window.minimize
await driver.manage().window().minimize();
driver.manage().window().minimize()

全屏窗口

填充整个屏幕,类似于在大多数浏览器中按下 F11。

driver.manage().window().fullscreen();
driver.fullscreen_window()
driver.Manage().Window.FullScreen();
driver.manage.window.full_screen
await driver.manage().window().fullscreen();
driver.manage().window().fullscreen()

屏幕截图

用于捕获当前浏览上下文的屏幕截图. WebDriver端点 屏幕截图 返回以Base64格式编码的屏幕截图.

import org.apache.commons.io.FileUtils; import org.openqa.selenium.chrome.ChromeDriver; import java.io.*; import org.openqa.selenium.*;  public class SeleniumTakeScreenshot { public static void main(String args[]) throws IOException { WebDriver driver = new ChromeDriver(); driver.get("http://www.example.com"); File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE); FileUtils.copyFile(scrFile, new File("./image.png")); driver.quit(); } }
from selenium import webdriver  driver = webdriver.Chrome()   # Navigate to url driver.get("http://www.example.com")   # Returns and base64 encoded string into image driver.save_screenshot('./image.png')  driver.quit()
using OpenQA.Selenium; using OpenQA.Selenium.Chrome; using OpenQA.Selenium.Support.UI;   var driver = new ChromeDriver();  driver.Navigate().GoToUrl("http://www.example.com");  Screenshot screenshot = (driver as ITakesScreenshot).GetScreenshot();  screenshot.SaveAsFile("screenshot.png", ScreenshotImageFormat.Png); // Format values are Bmp, Gif, Jpeg, Png, Tiff
require 'selenium-webdriver' driver = Selenium::WebDriver.for :chrome  begin driver.get 'https://example.com/'   # Takes and Stores the screenshot in specified path driver.save_screenshot('./image.png')  end
 // Captures the screenshot  let encodedString = await driver.takeScreenshot();  // save screenshot as below  // await fs.writeFileSync('./image.png', encodedString, 'base64'); 
import com.oracle.tools.packager.IOUtils.copyFile import org.openqa.selenium.* import org.openqa.selenium.chrome.ChromeDriver import java.io.File  fun main(){ val driver = ChromeDriver() driver.get("https://www.example.com") val scrFile = (driver as TakesScreenshot).getScreenshotAs<File>(OutputType.FILE) copyFile(scrFile, File("./image.png")) driver.quit() }

元素屏幕截图

用于捕获当前浏览上下文的元素的屏幕截图. WebDriver端点 屏幕截图 返回以Base64格式编码的屏幕截图.

import org.apache.commons.io.FileUtils; import org.openqa.selenium.*; import org.openqa.selenium.chrome.ChromeDriver; import java.io.File; import java.io.IOException;  public class SeleniumelementTakeScreenshot { public static void main(String args[]) throws IOException { WebDriver driver = new ChromeDriver(); driver.get("https://www.example.com"); WebElement element = driver.findElement(By.cssSelector("h1")); File scrFile = element.getScreenshotAs(OutputType.FILE); FileUtils.copyFile(scrFile, new File("./image.png")); driver.quit(); } }
from selenium import webdriver from selenium.webdriver.common.by import By  driver = webdriver.Chrome()   # Navigate to url driver.get("http://www.example.com")  ele = driver.find_element(By.CSS_SELECTOR, 'h1')   # Returns and base64 encoded string into image ele.screenshot('./image.png')  driver.quit()
using OpenQA.Selenium; using OpenQA.Selenium.Chrome; using OpenQA.Selenium.Support.UI;   // Webdriver  var driver = new ChromeDriver();  driver.Navigate().GoToUrl("http://www.example.com");   // Fetch element using FindElement  var webElement = driver.FindElement(By.CssSelector("h1"));   // Screenshot for the element  var elementScreenshot = (webElement as ITakesScreenshot).GetScreenshot();  elementScreenshot.SaveAsFile("screenshot_of_element.png");
 # Works with Selenium4-alpha7 Ruby bindings and above require 'selenium-webdriver' driver = Selenium::WebDriver.for :chrome  begin driver.get 'https://example.com/' ele = driver.find_element(:css, 'h1')   # Takes and Stores the element screenshot in specified path ele.save_screenshot('./image.jpg') end
 let header = await driver.findElement(By.css('h1'));  // Captures the element screenshot  let encodedString = await header.takeScreenshot(true);  // save screenshot as below  // await fs.writeFileSync('./image.png', encodedString, 'base64'); 
import org.apache.commons.io.FileUtils import org.openqa.selenium.chrome.ChromeDriver import org.openqa.selenium.* import java.io.File  fun main() { val driver = ChromeDriver() driver.get("https://www.example.com") val element = driver.findElement(By.cssSelector("h1")) val scrFile: File = element.getScreenshotAs(OutputType.FILE) FileUtils.copyFile(scrFile, File("./image.png")) driver.quit() }

执行脚本

在当前frame或者窗口的上下文中,执行JavaScript代码片段.

//Creating the JavascriptExecutor interface object by Type casting JavascriptExecutor js = (JavascriptExecutor)driver; //Button Element WebElement button =driver.findElement(By.name("btnLogin")); //Executing JavaScript to click on element js.executeScript("arguments[0].click();", button); //Get return value from script String text = (String) js.executeScript("return arguments[0].innerText", button); //Executing JavaScript directly js.executeScript("console.log('hello world')");
 # Stores the header element header = driver.find_element(By.CSS_SELECTOR, "h1")   # Executing JavaScript to capture innerText of header element driver.execute_script('return arguments[0].innerText', header)
//creating Chromedriver instance IWebDriver driver = new ChromeDriver(); //Creating the JavascriptExecutor interface object by Type casting IJavaScriptExecutor js = (IJavaScriptExecutor) driver; //Button Element IWebElement button = driver.FindElement(By.Name("btnLogin")); //Executing JavaScript to click on element js.ExecuteScript("arguments[0].click();", button); //Get return value from script String text = (String)js.ExecuteScript("return arguments[0].innerText", button); //Executing JavaScript directly js.ExecuteScript("console.log('hello world')");
 # Stores the header element header = driver.find_element(css: 'h1')   # Get return value from script result = driver.execute_script("return arguments[0].innerText", header)   # Executing JavaScript directly driver.execute_script("alert('hello world')")
 // Stores the header element  let header = await driver.findElement(By.css('h1'));   // Executing JavaScript to capture innerText of header element  let text = await driver.executeScript('return arguments[0].innerText', header);
// Stores the header element val header = driver.findElement(By.cssSelector("h1"))  // Get return value from script val result = driver.executeScript("return arguments[0].innerText", header)  // Executing JavaScript directly driver.executeScript("alert('hello world')")

打印页面

打印当前浏览器内的页面

注意: 此功能需要无头模式下的Chromium浏览器

import org.openqa.selenium.print.PrintOptions;  driver.get("https://www.selenium.dev"); printer = (PrintsPage) driver;  PrintOptions printOptions = new PrintOptions(); printOptions.setPageRanges("1-2");  Pdf pdf = printer.print(printOptions); String content = pdf.getContent();
from selenium.webdriver.common.print_page_options import PrintOptions   print_options = PrintOptions()  print_options.page_ranges = ['1-2']   driver.get("printPage.html")   base64code = driver.print_page(print_options)
// code sample not available please raise a PR
driver.navigate_to 'https://www.selenium.dev'   base64encodedContent = driver.print_page(orientation: 'landscape')
 await driver.get('https://www.selenium.dev/selenium/web/alerts.html');  let base64 = await driver.printPage({pageRanges: ["1-2"]});  // page can be saved as a PDF as below  // await fs.writeFileSync('./test.pdf', base64, 'base64'); 
driver.get("https://www.selenium.dev") val printer = driver as PrintsPage  val printOptions = PrintOptions() printOptions.setPageRanges("1-2")  val pdf: Pdf = printer.print(printOptions) val content = pdf.content

7 - 虚拟身份验证器

一种Web身份验证器模型的表示形式.

Web 应用程序可以启用基于公钥的身份验证机制(称为 Web 身份验证)以无密码方式对用户进行身份验证。 Web 身份验证 定义了允许用户创建公钥凭据并将其注册到身份验证器的 API。 身份验证器可以是硬件设备或软件实体,用于存储用户的公钥凭证并根据请求检索它们。

顾名思义,虚拟身份验证器模拟此类身份验证器进行测试。

虚拟身份验证器选项

虚拟身份验证器具有 一组属性。 这些属性在 Selenium 绑定中映射为 VirtualAuthenticatorOptions。

 public void testVirtualOptions() {  VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions()  .setIsUserVerified(true)  .setHasUserVerification(true)  .setIsUserConsenting(true)  .setTransport(VirtualAuthenticatorOptions.Transport.USB)  .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F)
 // Create virtual authenticator options  VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions()  .SetIsUserVerified(true)  .SetHasUserVerification(true)  .SetIsUserConsenting(true)  .SetTransport(VirtualAuthenticatorOptions.Transport.USB)  .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F)  .SetHasResidentKey(false);
 options = VirtualAuthenticatorOptions()  options.is_user_verified = True  options.has_user_verification = True  options.is_user_consenting = True  options.transport = VirtualAuthenticatorOptions.Transport.USB  options.protocol = VirtualAuthenticatorOptions.Protocol.U2F  options.has_resident_key = False
 options.setHasUserVerification(true);  options.setIsUserConsenting(true);  options.setTransport(Transport['USB']);  options.setProtocol(Protocol['U2F']);  options.setHasResidentKey(false);   assert(Object.keys(options).length === 6);

添加虚拟身份验证器

它使用提供的属性创建一个新的虚拟身份验证器。

 public void testCreateAuthenticator() {  VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions()  .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F)  .setHasResidentKey(false);   VirtualAuthenticator authenticator =
 // Create virtual authenticator options  VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions()  .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F)  .SetHasResidentKey(false);   // Register a virtual authenticator  ((WebDriver)driver).AddVirtualAuthenticator(options);   List<Credential> credentialList = ((WebDriver)driver).GetCredentials();
 options = VirtualAuthenticatorOptions()  options.protocol = VirtualAuthenticatorOptions.Protocol.U2F  options.has_resident_key = False   # Register a virtual authenticator  driver.add_virtual_authenticator(options)
 options.setProtocol(Protocol['U2F']);  options.setHasResidentKey(false);   // Register a virtual authenticator  await driver.addVirtualAuthenticator(options);

删除虚拟身份验证器

删除之前添加的虚拟身份验证器。

 VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions()  .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F)  .SetHasResidentKey(false);   String virtualAuthenticatorId = ((WebDriver)driver).AddVirtualAuthenticator(options);   ((WebDriver)driver).RemoveVirtualAuthenticator(virtualAuthenticatorId);
 options = VirtualAuthenticatorOptions()   # Register a virtual authenticator  driver.add_virtual_authenticator(options)   # Remove virtual authenticator  driver.remove_virtual_authenticator()
 await driver.addVirtualAuthenticator(options);  await driver.removeVirtualAuthenticator();

创建永久凭据

使用给定的所需凭据 参数 创建一个永久(有状态的)凭据。

  byte[] credentialId = {1, 2, 3, 4};  byte[] userHandle = {1};  Credential residentCredential = Credential.createResidentCredential(
 byte[] credentialId = { 1, 2, 3, 4 };  byte[] userHandle = { 1 };   Credential residentCredential = Credential.CreateResidentCredential(  credentialId, "localhost", base64EncodedPK, userHandle, 0);
 # parameters for Resident Credential  credential_id = bytearray({1, 2, 3, 4})  rp_id = "localhost"  user_handle = bytearray({1})  privatekey = urlsafe_b64decode(BASE64__ENCODED_PK)  sign_count = 0   # create a resident credential using above parameters  resident_credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count)
 options.setProtocol(Protocol['CTAP2']);  options.setHasResidentKey(true);  options.setHasUserVerification(true);  options.setIsUserVerified(true);   await driver.addVirtualAuthenticator(options);   let residentCredential = new Credential().createResidentCredential(  new Uint8Array([1, 2, 3, 4]),  'localhost',  new Uint8Array([1]),  Buffer.from(BASE64_ENCODED_PK, 'base64').toString('binary'),  0);   await driver.addCredential(residentCredential);

创建临时凭据

使用给定的所需凭据 参数 创建一个常驻(无状态)凭据。

  byte[] credentialId = {1, 2, 3, 4};  Credential nonResidentCredential = Credential.createNonResidentCredential(
 byte[] credentialId = { 1, 2, 3, 4 };   Credential nonResidentCredential = Credential.CreateNonResidentCredential(  credentialId, "localhost", base64EncodedEC256PK, 0);
 # parameters for Non Resident Credential  credential_id = bytearray({1, 2, 3, 4})  rp_id = "localhost"  privatekey = urlsafe_b64decode(BASE64__ENCODED_PK)  sign_count = 0   # create a non resident credential using above parameters  credential = Credential.create_non_resident_credential(credential_id, rp_id, privatekey, sign_count)
 let nonResidentCredential = new Credential().createNonResidentCredential(  new Uint8Array([1, 2, 3, 4]),  'localhost',  Buffer.from(base64EncodedPK, 'base64').toString('binary'),  0);

添加凭据

向身份验证器注册凭据。

 public void testCreateAndAddNonResidentialKey() {  VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions()  .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F)  .setHasResidentKey(false);   VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options);   byte[] credentialId = {1, 2, 3, 4};  Credential nonResidentCredential = Credential.createNonResidentCredential(  credentialId, "localhost", ec256PrivateKey, /*signCount=*/0);
 VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions()  .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F)  .SetHasResidentKey(false);   ((WebDriver)driver).AddVirtualAuthenticator(options);   byte[] credentialId = { 1, 2, 3, 4 };   Credential nonResidentCredential = Credential.CreateNonResidentCredential(  credentialId, "localhost", base64EncodedEC256PK, 0);   ((WebDriver)driver).AddCredential(nonResidentCredential);
 driver.add_credential(credential)
 options.setProtocol(Protocol['U2F']);  options.setHasResidentKey(false);   await driver.addVirtualAuthenticator(options);   let nonResidentCredential = new Credential().createNonResidentCredential(  new Uint8Array([1, 2, 3, 4]),  'localhost',  Buffer.from(base64EncodedPK, 'base64').toString('binary'),  0);   await driver.addCredential(nonResidentCredential);

获取凭据

返回身份验证者拥有的凭据列表。

 public void testGetCredential() {  VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions()  .setProtocol(VirtualAuthenticatorOptions.Protocol.CTAP2)  .setHasResidentKey(true)  .setHasUserVerification(true)  .setIsUserVerified(true);  VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options);   byte[] credentialId = {1, 2, 3, 4};  byte[] userHandle = {1};  Credential residentCredential = Credential.createResidentCredential(  credentialId, "localhost", rsaPrivateKey, userHandle, /*signCount=*/0);   authenticator.addCredential(residentCredential); 
 VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions()  .SetProtocol(Protocol.CTAP2)  .SetHasResidentKey(true)  .SetHasUserVerification(true)  .SetIsUserVerified(true);   ((WebDriver)driver).AddVirtualAuthenticator(options);   byte[] credentialId = { 1, 2, 3, 4 };  byte[] userHandle = { 1 };   Credential residentCredential = Credential.CreateResidentCredential(  credentialId, "localhost", base64EncodedPK, userHandle, 0);   ((WebDriver)driver).AddCredential(residentCredential);   List<Credential> credentialList = ((WebDriver)driver).GetCredentials();
 credential_list = driver.get_credentials()
 options.setProtocol(Protocol['CTAP2']);  options.setHasResidentKey(true);  options.setHasUserVerification(true);  options.setIsUserVerified(true);   await driver.addVirtualAuthenticator(options);   let residentCredential = new Credential().createResidentCredential(  new Uint8Array([1, 2, 3, 4]),  'localhost',  new Uint8Array([1]),  Buffer.from(BASE64_ENCODED_PK, 'base64').toString('binary'),  0);   await driver.addCredential(residentCredential);   let credentialList = await driver.getCredentials();

删除凭据

根据传递的凭据ID从身份验证器中删除凭据。

 ((WebDriver)driver).AddVirtualAuthenticator(new VirtualAuthenticatorOptions());   byte[] credentialId = { 1, 2, 3, 4 };   Credential nonResidentCredential = Credential.CreateNonResidentCredential(  credentialId, "localhost", base64EncodedEC256PK, 0);   ((WebDriver)driver).AddCredential(nonResidentCredential);   ((WebDriver)driver).RemoveCredential(credentialId);
 public void testRemoveCredential() {  VirtualAuthenticator authenticator =  ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(new VirtualAuthenticatorOptions());   byte[] credentialId = {1, 2, 3, 4};  Credential credential = Credential.createNonResidentCredential(  credentialId, "localhost", rsaPrivateKey, 0);   authenticator.addCredential(credential); 
 driver.remove_credential(credential.id)

删除所有凭据

从身份验证器中删除所有凭据。

 public void testRemoveAllCredentials() {  VirtualAuthenticator authenticator =  ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(new VirtualAuthenticatorOptions());   byte[] credentialId = {1, 2, 3, 4};  Credential residentCredential = Credential.createNonResidentCredential(  credentialId, "localhost", rsaPrivateKey, /*signCount=*/0);   authenticator.addCredential(residentCredential); 
 ((WebDriver)driver).AddVirtualAuthenticator(new VirtualAuthenticatorOptions());   byte[] credentialId = { 1, 2, 3, 4 };   Credential nonResidentCredential = Credential.CreateNonResidentCredential(  credentialId, "localhost", base64EncodedEC256PK, 0);   ((WebDriver)driver).AddCredential(nonResidentCredential);   ((WebDriver)driver).RemoveAllCredentials();
 driver.remove_all_credentials()
 await driver.addVirtualAuthenticator(options);   let nonResidentCredential = new Credential().createNonResidentCredential(  new Uint8Array([1, 2, 3, 4]),  'localhost',  Buffer.from(BASE64_ENCODED_PK, 'base64').toString('binary'),  0);   await driver.addCredential(nonResidentCredential);  await driver.removeAllCredentials();

设置用户验证状态

设置身份验证器是模拟用户验证成功还是失败。

 public void testSetUserVerified() {  VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions()
 VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions()  .SetIsUserVerified(true);
 # Create virtual authenticator options  options = VirtualAuthenticatorOptions()  options.is_user_verified = True
 options.setIsUserVerified(true);