diff --git a/.github/workflows/js-examples.yml b/.github/workflows/js-examples.yml index 2003ee2a4ab6..1a0ec55f7d31 100644 --- a/.github/workflows/js-examples.yml +++ b/.github/workflows/js-examples.yml @@ -31,40 +31,6 @@ jobs: steps: - name: Checkout GitHub repo uses: actions/checkout@v4 - - name: Install Chrome for set binary test - uses: browser-actions/setup-chrome@v1 - with: - chrome-version: stable - id: setup-chrome - - name: Install Edge for set binary test - uses: browser-actions/setup-edge@v1 - with: - edge-version: stable - id: setup-edge - - name: Install Firefox for set binary test - if: matrix.os != 'windows' - uses: browser-actions/setup-firefox@v1 - with: - firefox-version: latest - id: setup-firefox - - name: Set ENV Windows - if: matrix.os == 'windows' - run: | - echo "CHROME_BIN=${{ steps.setup-chrome.outputs.chrome-path }}" >> $env:GITHUB_ENV - echo "EDGE_BIN=C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" >> $env:GITHUB_ENV - echo "FF_BIN=C:\Program Files (x86)\Mozilla Firefox\firefox-browser.exe" >> $env:GITHUB_ENV - - name: Set ENV Mac - if: matrix.os == 'macos' - run: | - echo "CHROME_BIN=${{ steps.setup-chrome.outputs.chrome-path }}" >> "$GITHUB_ENV" - echo "EDGE_BIN=/Users/runner/hostedtoolcache/msedge/stable/x64/Contents/MacOS/Microsoft Edge" >> "$GITHUB_ENV" - echo "FF_BIN=/Users/runner/hostedtoolcache/firefox/latest/x64/Contents/MacOS/firefox" >> "$GITHUB_ENV" - - name: Set ENV Linux - if: matrix.os == 'ubuntu' - run: | - echo "CHROME_BIN=${{ steps.setup-chrome.outputs.chrome-path }}" >> "$GITHUB_ENV" - echo "EDGE_BIN=/opt/hostedtoolcache/msedge/stable/x64/msedge" >> "$GITHUB_ENV" - echo "FF_BIN=/opt/hostedtoolcache/firefox/latest/x64/firefox" >> "$GITHUB_ENV" - name: Remove driver directories Windows if: matrix.os == 'windows' run: | @@ -119,7 +85,7 @@ jobs: uses: nick-invision/retry@v3.0.2 with: timeout_minutes: 20 - max_attempts: 3 + max_attempts: 2 command: | cd examples/javascript npm test diff --git a/.github/workflows/kotlin-examples.yml b/.github/workflows/kotlin-examples.yml index ce53e7052e6e..14183e2fa03b 100644 --- a/.github/workflows/kotlin-examples.yml +++ b/.github/workflows/kotlin-examples.yml @@ -30,40 +30,6 @@ jobs: steps: - name: Checkout GitHub repo uses: actions/checkout@v4 - - name: Install Chrome for set binary test - uses: browser-actions/setup-chrome@v1 - with: - chrome-version: stable - id: setup-chrome - - name: Install Edge for set binary test - uses: browser-actions/setup-edge@v1 - with: - edge-version: stable - id: setup-edge - - name: Install Firefox for set binary test - if: matrix.os != 'windows' - uses: browser-actions/setup-firefox@v1 - with: - firefox-version: latest - id: setup-firefox - - name: Set ENV Windows - if: matrix.os == 'windows' - run: | - echo "CHROME_BIN=${{ steps.setup-chrome.outputs.chrome-path }}" >> $env:GITHUB_ENV - echo "EDGE_BIN=C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" >> $env:GITHUB_ENV - echo "FF_BIN=C:\Program Files (x86)\Mozilla Firefox\firefox-browser.exe" >> $env:GITHUB_ENV - - name: Set ENV Mac - if: matrix.os == 'macos' - run: | - echo "CHROME_BIN=${{ steps.setup-chrome.outputs.chrome-path }}" >> "$GITHUB_ENV" - echo "EDGE_BIN=/Users/runner/hostedtoolcache/msedge/stable/x64/Contents/MacOS/Microsoft Edge" >> "$GITHUB_ENV" - echo "FF_BIN=/Users/runner/hostedtoolcache/firefox/latest/x64/Contents/MacOS/firefox" >> "$GITHUB_ENV" - - name: Set ENV Linux - if: matrix.os == 'ubuntu' - run: | - echo "CHROME_BIN=${{ steps.setup-chrome.outputs.chrome-path }}" >> "$GITHUB_ENV" - echo "EDGE_BIN=/opt/hostedtoolcache/msedge/stable/x64/msedge" >> "$GITHUB_ENV" - echo "FF_BIN=/opt/hostedtoolcache/firefox/latest/x64/firefox" >> "$GITHUB_ENV" - name: Remove driver directories Windows if: matrix.os == 'windows' run: | diff --git a/.github/workflows/link-check.yml b/.github/workflows/link-check.yml index ebba025a718e..79730502e408 100644 --- a/.github/workflows/link-check.yml +++ b/.github/workflows/link-check.yml @@ -27,7 +27,7 @@ jobs: - name: Setup Node uses: actions/setup-node@v4 with: - node-version: '18.14.2' + node-version: '22.17.0' cache: 'npm' # The action defaults to search for the dependency file (package-lock.json, # npm-shrinkwrap.json or yarn.lock) in the repository root, and uses its diff --git a/.github/workflows/ruby-examples.yml b/.github/workflows/ruby-examples.yml index eee3b46a192d..71857ffa68c6 100644 --- a/.github/workflows/ruby-examples.yml +++ b/.github/workflows/ruby-examples.yml @@ -41,13 +41,17 @@ jobs: if: matrix.os != 'windows' run: | sudo rm -rf $CHROMEWEBDRIVER $EDGEWEBDRIVER $GECKOWEBDRIVER - - name: Start Xvfb + - name: Setup Fluxbox and Xvfb if: matrix.os == 'ubuntu' - run: Xvfb :99 & + run: | + sudo apt-get -y install fluxbox libxss1 libappindicator3-1 libindicator7 + Xvfb :99 & + fluxbox -display :99 & + echo "DISPLAY=:99" >> "$GITHUB_ENV" - name: Set up Ruby uses: ruby/setup-ruby@v1 with: - ruby-version: 3.0 + ruby-version: 3.2 bundler-cache: true - name: Install Gems Nightly non-Windows if: matrix.release == 'nightly' && matrix.os != 'windows' @@ -83,11 +87,43 @@ jobs: with: distribution: 'temurin' java-version: 11 - - name: Run tests + - name: Run tests on Windows + if: matrix.os == 'windows' uses: nick-invision/retry@v3.0.2 with: timeout_minutes: 20 - max_attempts: 3 + max_attempts: 2 command: | cd examples/ruby bundle exec rspec + new_command_on_retry: | + cd examples/ruby; $env:DEBUG="true"; bundle exec rspec --only-failures --backtrace + - name: Run tests on ${{ matrix.os }} + if: matrix.os != 'windows' + uses: nick-invision/retry@v3.0.2 + with: + timeout_minutes: 20 + max_attempts: 2 + command: | + cd examples/ruby + bundle exec rspec + new_command_on_retry: | + cd examples/ruby + DEBUG=true bundle exec rspec --only-failures --backtrace + + lint: + runs-on: ubuntu-latest + steps: + - name: Checkout GitHub repo + uses: actions/checkout@v4 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: 3.2 + bundler-cache: true + - name: Install dependencies + working-directory: ./examples/ruby + run: bundle install + - name: Run RuboCop + working-directory: ./examples/ruby + run: bundle exec rubocop diff --git a/README.md b/README.md index 42fcd27a138a..b58633891dfa 100755 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ to use **[Hugo 0.125.4](https://github.com/gohugoio/hugo/releases/tag/v0.125.4)* Steps needed to have this working locally and work on it: -- Follow the [Install Hugo](https://www.docsy.dev/docs/get-started/other-options/#install-hugo) instructions from Docsy +- [Install Hugo](https://gohugo.io/installation/) and follow the [Get Started](https://www.docsy.dev/docs/get-started/) instructions from Docsy - [Install go](https://go.dev/doc/install) - Clone this repository - Run `cd website_and_docs` diff --git a/examples/dotnet/SeleniumDocs/BaseTest.cs b/examples/dotnet/SeleniumDocs/BaseTest.cs index 18c17c3bb3f0..90a42002130f 100644 --- a/examples/dotnet/SeleniumDocs/BaseTest.cs +++ b/examples/dotnet/SeleniumDocs/BaseTest.cs @@ -17,7 +17,7 @@ public class BaseTest protected IWebDriver driver; protected Uri GridUrl; private Process _webserverProcess; - private const string ServerJarName = "selenium-server-4.29.0.jar"; + private const string ServerJarName = "selenium-server-4.34.0.jar"; private static readonly string BaseDirectory = AppContext.BaseDirectory; private const string RelativePathToGrid = "../../../../../"; private readonly string _examplesDirectory = Path.GetFullPath(Path.Combine(BaseDirectory, RelativePathToGrid)); @@ -33,12 +33,18 @@ public void Cleanup() } } - protected void StartDriver(string browserVersion = "stable") + protected void StartDriver(string browserVersion = null) { - ChromeOptions options = new ChromeOptions + ChromeOptions options = new ChromeOptions(); + if (browserVersion != null) { - BrowserVersion = browserVersion - }; + options.BrowserVersion = browserVersion; + string userDataDir = System.IO.Path.Combine(System.IO.Path.GetTempPath(), System.IO.Path.GetRandomFileName()); + System.IO.Directory.CreateDirectory(userDataDir); + options.AddArgument($"--user-data-dir={userDataDir}"); + options.AddArgument("--no-sandbox"); + options.AddArgument("--disable-dev-shm-usage"); + } driver = new ChromeDriver(options); } @@ -111,4 +117,4 @@ private async Task EnsureGridIsRunningAsync() } } } -} \ No newline at end of file +} diff --git a/examples/dotnet/SeleniumDocs/BiDi/CDP/NetworkTest.cs b/examples/dotnet/SeleniumDocs/BiDi/CDP/NetworkTest.cs index b51b60d7d1b0..325092813e06 100644 --- a/examples/dotnet/SeleniumDocs/BiDi/CDP/NetworkTest.cs +++ b/examples/dotnet/SeleniumDocs/BiDi/CDP/NetworkTest.cs @@ -4,8 +4,8 @@ using OpenQA.Selenium; using OpenQA.Selenium.DevTools; using System.Linq; -using OpenQA.Selenium.DevTools.V132.Network; -using OpenQA.Selenium.DevTools.V132.Performance; +using OpenQA.Selenium.DevTools.V137.Network; +using OpenQA.Selenium.DevTools.V137.Performance; namespace SeleniumDocs.BiDi.CDP @@ -16,7 +16,7 @@ public class NetworkTest : BaseTest [TestInitialize] public void Startup() { - StartDriver("132"); + StartDriver("137"); } [TestMethod] @@ -109,9 +109,9 @@ public async Task PerformanceMetrics() driver.Url = "https://www.selenium.dev/selenium/web/frameset.html"; var session = ((IDevTools)driver).GetDevToolsSession(); - var domains = session.GetVersionSpecificDomains(); + var domains = session.GetVersionSpecificDomains(); - await domains.Performance.Enable(new OpenQA.Selenium.DevTools.V132.Performance.EnableCommandSettings()); + await domains.Performance.Enable(new OpenQA.Selenium.DevTools.V137.Performance.EnableCommandSettings()); var metricsResponse = await session.SendCommand( new GetMetricsCommandSettings() @@ -130,8 +130,8 @@ await session.SendCommand( public async Task SetCookie() { var session = ((IDevTools)driver).GetDevToolsSession(); - var domains = session.GetVersionSpecificDomains(); - await domains.Network.Enable(new OpenQA.Selenium.DevTools.V132.Network.EnableCommandSettings()); + var domains = session.GetVersionSpecificDomains(); + await domains.Network.Enable(new OpenQA.Selenium.DevTools.V137.Network.EnableCommandSettings()); var cookieCommandSettings = new SetCookieCommandSettings { @@ -148,4 +148,4 @@ public async Task SetCookie() } } -} \ No newline at end of file +} diff --git a/examples/dotnet/SeleniumDocs/Browsers/ChromeTest.cs b/examples/dotnet/SeleniumDocs/Browsers/ChromeTest.cs index 15b1cf9b6177..55c3f162c648 100644 --- a/examples/dotnet/SeleniumDocs/Browsers/ChromeTest.cs +++ b/examples/dotnet/SeleniumDocs/Browsers/ChromeTest.cs @@ -44,7 +44,12 @@ public void Arguments() [TestMethod] public void SetBrowserLocation() { + string userDataDir = System.IO.Path.Combine(System.IO.Path.GetTempPath(), System.IO.Path.GetRandomFileName()); + System.IO.Directory.CreateDirectory(userDataDir); var options = new ChromeOptions(); + options.AddArgument($"--user-data-dir={userDataDir}"); + options.AddArgument("--no-sandbox"); + options.AddArgument("--disable-dev-shm-usage"); options.BinaryLocation = GetChromeLocation(); @@ -59,6 +64,7 @@ public void InstallExtension() var extensionFilePath = Path.Combine(baseDir, "../../../Extensions/webextensions-selenium-example.crx"); options.AddExtension(extensionFilePath); + options.AddArgument("--disable-features=DisableLoadExtensionCommandLineSwitch"); driver = new ChromeDriver(options); @@ -117,7 +123,7 @@ public void LogsLevel() var service = ChromeDriverService.CreateDefaultService(); service.LogPath = GetLogLocation(); - // service.LogLevel = ChromiumDriverLogLevel.Debug + // service.LogLevel = ChromiumDriverLogLevel.Debug driver = new ChromeDriver(service); @@ -180,4 +186,4 @@ private static string GetChromeLocation() return new DriverFinder(options).GetBrowserPath(); } } -} \ No newline at end of file +} diff --git a/examples/dotnet/SeleniumDocs/Drivers/OptionsTest.cs b/examples/dotnet/SeleniumDocs/Drivers/OptionsTest.cs index 1a387cb13ba6..618e5361ecce 100644 --- a/examples/dotnet/SeleniumDocs/Drivers/OptionsTest.cs +++ b/examples/dotnet/SeleniumDocs/Drivers/OptionsTest.cs @@ -1,9 +1,57 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; +using OpenQA.Selenium; +using OpenQA.Selenium.Chrome; namespace SeleniumDocs.Drivers { [TestClass] public class OptionsTest : BaseTest { + [TestMethod] + public void SetPageLoadStrategyNormal() + { + ChromeOptions chromeOptions = new ChromeOptions(); + chromeOptions.PageLoadStrategy = PageLoadStrategy.Normal; + IWebDriver driver = new ChromeDriver(chromeOptions); + try + { + // Navigate to Url + driver.Navigate().GoToUrl("https://selenium.dev/"); + } + finally + { + driver.Quit(); + } + } + [TestMethod] + public void SetPageLoadStrategyEager() + { + var chromeOptions = new ChromeOptions(); + chromeOptions.PageLoadStrategy = PageLoadStrategy.Eager; + IWebDriver driver = new ChromeDriver(chromeOptions); + try + { + driver.Navigate().GoToUrl("https://selenium.dev/"); + } + finally + { + driver.Quit(); + } + } + [TestMethod] + public void SetPageLoadStrategyNone() + { + var chromeOptions = new ChromeOptions(); + chromeOptions.PageLoadStrategy = PageLoadStrategy.None; + IWebDriver driver = new ChromeDriver(chromeOptions); + try + { + driver.Navigate().GoToUrl("https://selenium.dev/"); + } + finally + { + driver.Quit(); + } + } } } \ No newline at end of file diff --git a/examples/dotnet/SeleniumDocs/Extensions/webextensions-selenium-example.crx b/examples/dotnet/SeleniumDocs/Extensions/webextensions-selenium-example.crx index 38b38003b7ec..941114eb446e 100644 Binary files a/examples/dotnet/SeleniumDocs/Extensions/webextensions-selenium-example.crx and b/examples/dotnet/SeleniumDocs/Extensions/webextensions-selenium-example.crx differ diff --git a/examples/dotnet/SeleniumDocs/Interactions/FramesTest.cs b/examples/dotnet/SeleniumDocs/Interactions/FramesTest.cs index 85f7573c883f..4a0daa471c5a 100644 --- a/examples/dotnet/SeleniumDocs/Interactions/FramesTest.cs +++ b/examples/dotnet/SeleniumDocs/Interactions/FramesTest.cs @@ -48,9 +48,9 @@ public void TestFrames() //switch To IFrame using name or id - driver.FindElement(By.Name("iframe1-name")); + IWebElement iframe1=driver.FindElement(By.Name("iframe1-name")); //Switch to the frame - driver.SwitchTo().Frame(iframe); + 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 diff --git a/examples/dotnet/SeleniumDocs/Interactions/PrintOptionsTest.cs b/examples/dotnet/SeleniumDocs/Interactions/PrintOptionsTest.cs index 927b34dff340..2229d2378f71 100644 --- a/examples/dotnet/SeleniumDocs/Interactions/PrintOptionsTest.cs +++ b/examples/dotnet/SeleniumDocs/Interactions/PrintOptionsTest.cs @@ -16,6 +16,7 @@ public void TestOrientation() PrintOptions printOptions = new PrintOptions(); printOptions.Orientation = PrintOrientation.Landscape; PrintOrientation currentOrientation = printOptions.Orientation; + driver.Quit(); } [TestMethod] @@ -26,7 +27,8 @@ public void TestRange() PrintOptions printOptions = new PrintOptions(); printOptions.AddPageRangeToPrint("1-3"); // add range of pages printOptions.AddPageToPrint(5); // add individual page - } + driver.Quit(); + } [TestMethod] public void TestSize() @@ -35,6 +37,7 @@ public void TestSize() driver.Navigate().GoToUrl("https://www.selenium.dev/"); PrintOptions printOptions = new PrintOptions(); PrintOptions.PageSize currentDimensions = printOptions.PageDimensions; + driver.Quit(); } [TestMethod] @@ -45,6 +48,7 @@ public void TestBackgrounds() PrintOptions printOptions = new PrintOptions(); printOptions.OutputBackgroundImages = true; bool currentBackgrounds = printOptions.OutputBackgroundImages; + driver.Quit(); } [TestMethod] @@ -54,6 +58,7 @@ public void TestMargins() driver.Navigate().GoToUrl("https://www.selenium.dev/"); PrintOptions printOptions = new PrintOptions(); PrintOptions.Margins currentMargins = printOptions.PageMargins; + driver.Quit(); } @@ -65,6 +70,7 @@ public void TestScale() PrintOptions printOptions = new PrintOptions(); printOptions.ScaleFactor = 0.5; double currentScale = printOptions.ScaleFactor; + driver.Quit(); } [TestMethod] @@ -75,16 +81,18 @@ public void TestShrinkToFit() PrintOptions printOptions = new PrintOptions(); printOptions.ShrinkToFit = true; bool currentShrinkToFit = printOptions.ShrinkToFit; + driver.Quit(); } [TestMethod] - public void PrintWithPrintsPageTest() + public void PrintWithPrintsPageTest() { WebDriver driver = new ChromeDriver(); driver.Navigate().GoToUrl("https://www.selenium.dev/"); PrintOptions printOptions = new PrintOptions(); PrintDocument printedPage = driver.Print(printOptions); Assert.IsTrue(printedPage.AsBase64EncodedString.StartsWith("JVBER")); + driver.Quit(); } } -} \ No newline at end of file +} diff --git a/examples/dotnet/SeleniumDocs/SeleniumDocs.csproj b/examples/dotnet/SeleniumDocs/SeleniumDocs.csproj index 264303d3d127..9b630acef30e 100644 --- a/examples/dotnet/SeleniumDocs/SeleniumDocs.csproj +++ b/examples/dotnet/SeleniumDocs/SeleniumDocs.csproj @@ -10,8 +10,8 @@ - - + + diff --git a/examples/dotnet/SeleniumDocs/SeleniumManager/UsageTest.cs b/examples/dotnet/SeleniumDocs/SeleniumManager/UsageTest.cs new file mode 100644 index 000000000000..b2a04500df76 --- /dev/null +++ b/examples/dotnet/SeleniumDocs/SeleniumManager/UsageTest.cs @@ -0,0 +1,20 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using OpenQA.Selenium.Chrome; + +namespace SeleniumDocs.SeleniumManagerTest +{ + [TestClass] + public class UsageTest + { + [TestMethod] + public void TestWithSeleniumManager() + { + // Before + // using var driver = new ChromeDriver("path/to/chromedriver"); + + // Now + using var driver = new ChromeDriver(); + driver.Navigate().GoToUrl("https://www.selenium.dev/documentation/selenium_manager/"); + } + } +} diff --git a/examples/java/build.gradle b/examples/java/build.gradle index cd41e4b42842..7f0e643f14a0 100644 --- a/examples/java/build.gradle +++ b/examples/java/build.gradle @@ -10,8 +10,8 @@ repositories { } dependencies { - testImplementation 'org.seleniumhq.selenium:selenium-java:4.29.0' - testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.12.0' + testImplementation 'org.seleniumhq.selenium:selenium-java:4.34.0' + testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.13.3' } test { diff --git a/examples/java/gradle/wrapper/gradle-wrapper.jar b/examples/java/gradle/wrapper/gradle-wrapper.jar index 9bbc975c742b..1b33c55baabb 100644 Binary files a/examples/java/gradle/wrapper/gradle-wrapper.jar and b/examples/java/gradle/wrapper/gradle-wrapper.jar differ diff --git a/examples/java/gradle/wrapper/gradle-wrapper.properties b/examples/java/gradle/wrapper/gradle-wrapper.properties index 37f853b1c84d..d4081da476bb 100644 --- a/examples/java/gradle/wrapper/gradle-wrapper.properties +++ b/examples/java/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/examples/java/gradlew b/examples/java/gradlew index faf93008b77e..23d15a936707 100755 --- a/examples/java/gradlew +++ b/examples/java/gradlew @@ -114,7 +114,7 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar +CLASSPATH="\\\"\\\"" # Determine the Java command to use to start the JVM. @@ -213,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/examples/java/gradlew.bat b/examples/java/gradlew.bat index 9b42019c7915..5eed7ee84528 100644 --- a/examples/java/gradlew.bat +++ b/examples/java/gradlew.bat @@ -70,11 +70,11 @@ goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar +set CLASSPATH= @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell diff --git a/examples/java/pom.xml b/examples/java/pom.xml index ca1ac5f7358c..898f27c657a4 100644 --- a/examples/java/pom.xml +++ b/examples/java/pom.xml @@ -13,7 +13,7 @@ 17 17 UTF-8 - 4.29.0 + 4.34.0 @@ -40,7 +40,7 @@ org.junit.jupiter junit-jupiter-engine - 5.12.0 + 5.13.3 test @@ -55,7 +55,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.5.2 + 3.5.3 diff --git a/examples/java/src/test/java/dev/selenium/bidi/cdp/CdpApiTest.java b/examples/java/src/test/java/dev/selenium/bidi/cdp/CdpApiTest.java index 79b94137deaf..3d1d24aaa7bf 100644 --- a/examples/java/src/test/java/dev/selenium/bidi/cdp/CdpApiTest.java +++ b/examples/java/src/test/java/dev/selenium/bidi/cdp/CdpApiTest.java @@ -16,9 +16,9 @@ import org.openqa.selenium.chrome.ChromeOptions; import org.openqa.selenium.devtools.DevTools; import org.openqa.selenium.devtools.HasDevTools; -import org.openqa.selenium.devtools.v131.browser.Browser; -import org.openqa.selenium.devtools.v131.network.Network; -import org.openqa.selenium.devtools.v131.network.model.Headers; +import org.openqa.selenium.devtools.v137.browser.Browser; +import org.openqa.selenium.devtools.v137.network.Network; +import org.openqa.selenium.devtools.v137.network.model.Headers; import org.openqa.selenium.support.ui.WebDriverWait; public class CdpApiTest extends BaseTest { @@ -27,7 +27,7 @@ public class CdpApiTest extends BaseTest { @BeforeEach public void createSession() { ChromeOptions options = getDefaultChromeOptions(); - options.setBrowserVersion("131"); + options.setBrowserVersion("136"); driver = new ChromeDriver(options); wait = new WebDriverWait(driver, Duration.ofSeconds(10)); } diff --git a/examples/java/src/test/java/dev/selenium/bidi/cdp/NetworkTest.java b/examples/java/src/test/java/dev/selenium/bidi/cdp/NetworkTest.java index d9fb6f454866..68e0cdcc15b6 100644 --- a/examples/java/src/test/java/dev/selenium/bidi/cdp/NetworkTest.java +++ b/examples/java/src/test/java/dev/selenium/bidi/cdp/NetworkTest.java @@ -21,10 +21,10 @@ import org.openqa.selenium.devtools.DevTools; import org.openqa.selenium.devtools.HasDevTools; import org.openqa.selenium.devtools.NetworkInterceptor; -import org.openqa.selenium.devtools.v131.browser.Browser; -import org.openqa.selenium.devtools.v131.network.Network; -import org.openqa.selenium.devtools.v131.performance.Performance; -import org.openqa.selenium.devtools.v131.performance.model.Metric; +import org.openqa.selenium.devtools.v137.browser.Browser; +import org.openqa.selenium.devtools.v137.network.Network; +import org.openqa.selenium.devtools.v137.performance.Performance; +import org.openqa.selenium.devtools.v137.performance.model.Metric; import org.openqa.selenium.remote.http.*; import org.openqa.selenium.support.ui.WebDriverWait; diff --git a/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java b/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java index 55e82ed2c20e..0637537d4deb 100644 --- a/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java +++ b/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java @@ -46,28 +46,12 @@ void testCreateAWindow() { Assertions.assertNotNull(browsingContext.getId()); } - @Test - void testCreateAWindowWithAReferenceContext() { - BrowsingContext - browsingContext = - new BrowsingContext(driver, WindowType.WINDOW, driver.getWindowHandle()); - Assertions.assertNotNull(browsingContext.getId()); - } - @Test void testCreateATab() { BrowsingContext browsingContext = new BrowsingContext(driver, WindowType.TAB); Assertions.assertNotNull(browsingContext.getId()); } - @Test - void testCreateATabWithAReferenceContext() { - BrowsingContext - browsingContext = - new BrowsingContext(driver, WindowType.TAB, driver.getWindowHandle()); - Assertions.assertNotNull(browsingContext.getId()); - } - @Test void testNavigateToAUrl() { BrowsingContext browsingContext = new BrowsingContext(driver, WindowType.TAB); diff --git a/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/user_context/MultipleInstanceParallelTest.java b/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/user_context/MultipleInstanceParallelTest.java new file mode 100644 index 000000000000..7f5b5a6ccc1d --- /dev/null +++ b/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/user_context/MultipleInstanceParallelTest.java @@ -0,0 +1,92 @@ +package dev.selenium.bidirectional.webdriver_bidi.user_context; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.firefox.FirefoxDriver; +import org.openqa.selenium.firefox.FirefoxOptions; + +class MultipleInstanceParallelTest { + + private WebDriver driver; + + @BeforeEach + public void setup() { + FirefoxOptions options = new FirefoxOptions(); + options.setCapability("webSocketUrl", true); + options.addArguments("-private"); + driver = new FirefoxDriver(options); + } + + @Test + void canSwitchToBlue() { + driver.get("https://www.selenium.dev/selenium/web/cookie-background.html"); + + WebElement body = driver.findElement(By.tagName("body")); + String bgColor = body.getCssValue("background-color"); + + String expectedColor = "rgb(255, 255, 255)"; + // Background color is white + Assertions.assertEquals(bgColor, expectedColor); + + driver.get("https://www.selenium.dev/selenium/web/cookie-background.html"); + + driver.findElement(By.id("blue-btn")).click(); + body = driver.findElement(By.tagName("body")); + bgColor = body.getCssValue("background-color"); + + expectedColor = "rgb(173, 216, 230)"; + // Background color is blue + Assertions.assertEquals(bgColor, expectedColor); + + System.out.println( + Thread.currentThread().getName() + " " + Thread.currentThread().getStackTrace()[1] + .getMethodName() + " => executed successfully"); + } + + @Test + void canSwitchToGreen() { + driver.get("https://www.selenium.dev/selenium/web/cookie-background.html"); + + WebElement body = driver.findElement(By.tagName("body")); + String bgColor = body.getCssValue("background-color"); + + String expectedColor = "rgb(255, 255, 255)"; + Assertions.assertEquals(bgColor, expectedColor); + + driver.findElement(By.id("green-btn")).click(); + body = driver.findElement(By.tagName("body")); + bgColor = body.getCssValue("background-color"); + + expectedColor = "rgb(144, 238, 144)"; + Assertions.assertEquals(bgColor, expectedColor); + + System.out.println( + Thread.currentThread().getName() + " " + Thread.currentThread().getStackTrace()[1] + .getMethodName() + " => executed successfully"); + } + + @Test + void canHaveTheDefaultBackgroundColor() { + driver.get("https://www.selenium.dev/selenium/web/cookie-background.html"); + + WebElement body = driver.findElement(By.tagName("body")); + String bgColor = body.getCssValue("background-color"); + + String expectedColor = "rgb(255, 255, 255)"; + Assertions.assertEquals(bgColor, expectedColor); + + System.out.println( + Thread.currentThread().getName() + " " + Thread.currentThread().getStackTrace()[1] + .getMethodName() + " => executed successfully"); + } + + @AfterEach + public void cleanup() { + driver.quit(); + } +} diff --git a/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/user_context/SingleInstanceCookieParallelTest.java b/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/user_context/SingleInstanceCookieParallelTest.java new file mode 100644 index 000000000000..a40a6da5a85c --- /dev/null +++ b/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/user_context/SingleInstanceCookieParallelTest.java @@ -0,0 +1,133 @@ +package dev.selenium.bidirectional.webdriver_bidi.user_context; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WindowType; +import org.openqa.selenium.bidi.browsingcontext.BrowsingContext; +import org.openqa.selenium.bidi.browsingcontext.CreateContextParameters; +import org.openqa.selenium.bidi.browsingcontext.Locator; +import org.openqa.selenium.bidi.browsingcontext.ReadinessState; +import org.openqa.selenium.bidi.module.Browser; +import org.openqa.selenium.bidi.module.Input; +import org.openqa.selenium.bidi.script.NodeProperties; +import org.openqa.selenium.bidi.script.RemoteValue; +import org.openqa.selenium.firefox.FirefoxDriver; +import org.openqa.selenium.firefox.FirefoxOptions; +import org.openqa.selenium.interactions.Actions; +import org.openqa.selenium.remote.RemoteWebElement; + +class SingleInstanceCookieParallelTest { + + private static WebDriver driver; + BrowsingContext context; + + @BeforeAll + public static void beforeAll() { + FirefoxOptions options = new FirefoxOptions(); + options.setCapability("webSocketUrl", true); + driver = new FirefoxDriver(options); + +// To use Grid uncomment the lines below + +// driver = new RemoteWebDriver( +// new URL("http://localhost:4444/"), +// options, false); +// +// Augmenter augmenter = new Augmenter(); +// driver = augmenter.augment(driver); + } + + @BeforeEach + public void setup() { + Browser browser = new Browser(driver); + String userContext = browser.createUserContext(); + + CreateContextParameters parameters = new CreateContextParameters(WindowType.TAB); + parameters.userContext(userContext); + + context = new BrowsingContext(driver, parameters); + } + + @Test + void canSwitchToBlue() { + context.navigate("https://www.selenium.dev/selenium/web/cookie-background.html", ReadinessState.COMPLETE); + + RemoteValue value = context.locateNode(Locator.xpath("/html/body/button[1]")); + + Input inputModule = new Input(driver); + Actions actions = new Actions(driver); + + RemoteWebElement element = new RemoteWebElement(); + element.setId(value.getSharedId().get()); + actions.moveToElement(element).click(); + + inputModule.perform(context.getId(), actions.getSequences()); + + value = context.locateNode(Locator.xpath("/html/body")); + + NodeProperties properties = (NodeProperties) value.getValue().get(); + String bgColor = properties.getAttributes().get().get("style"); + + Assertions.assertEquals(bgColor, "background-color: lightblue;"); + System.out.println( + Thread.currentThread().getName() + " " + Thread.currentThread().getStackTrace()[1] + .getMethodName() + " => executed successfully"); + } + + @Test + void canSwitchToGreen() { + context.navigate("https://www.selenium.dev/selenium/web/cookie-background.html", ReadinessState.COMPLETE); + + RemoteValue value = context.locateNode(Locator.xpath("/html/body")); + + NodeProperties properties = (NodeProperties) value.getValue().get(); + String bgColor = properties.getAttributes().get().get("style"); + + Assertions.assertEquals(bgColor, "background-color: white;"); + + value = context.locateNode(Locator.xpath("/html/body/button[2]")); + + Input inputModule = new Input(driver); + Actions actions = new Actions(driver); + + RemoteWebElement element = new RemoteWebElement(); + element.setId(value.getSharedId().get()); + actions.moveToElement(element).click(); + + inputModule.perform(context.getId(), actions.getSequences()); + + value = context.locateNode(Locator.xpath("/html/body")); + + properties = (NodeProperties) value.getValue().get(); + bgColor = properties.getAttributes().get().get("style"); + + Assertions.assertEquals(bgColor, "background-color: lightgreen;"); + System.out.println( + Thread.currentThread().getName() + " " + Thread.currentThread().getStackTrace()[1] + .getMethodName() + " => executed successfully"); + } + + @Test + void canHaveTheDefaultBackgroundColor() { + context.navigate("https://www.selenium.dev/selenium/web/cookie-background.html", ReadinessState.COMPLETE); + + RemoteValue value = context.locateNode(Locator.xpath("/html/body")); + + NodeProperties properties = (NodeProperties) value.getValue().get(); + String bgColor = properties.getAttributes().get().get("style"); + + Assertions.assertEquals(bgColor, "background-color: white;"); + System.out.println( + Thread.currentThread().getName() + " " + Thread.currentThread().getStackTrace()[1] + .getMethodName() + " => executed successfully"); + } + + @AfterAll + public static void cleanup() { + driver.quit(); + } +} diff --git a/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java b/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java index 0161c6ceec34..4ccd625f8a92 100644 --- a/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java +++ b/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java @@ -24,7 +24,6 @@ import org.openqa.selenium.logging.*; import org.openqa.selenium.remote.service.DriverFinder; - public class ChromeTest extends BaseTest { @AfterEach public void clearProperties() { @@ -63,6 +62,7 @@ public void extensionOptions() { File extensionFilePath = new File(path.toUri()); options.addExtensions(extensionFilePath); + options.addArguments("--disable-features=DisableLoadExtensionCommandLineSwitch"); driver = new ChromeDriver(options); driver.get("https://www.selenium.dev/selenium/web/blank.html"); diff --git a/examples/java/src/test/java/dev/selenium/browsers/FirefoxTest.java b/examples/java/src/test/java/dev/selenium/browsers/FirefoxTest.java index 28166e124804..c66400cce76c 100644 --- a/examples/java/src/test/java/dev/selenium/browsers/FirefoxTest.java +++ b/examples/java/src/test/java/dev/selenium/browsers/FirefoxTest.java @@ -192,7 +192,7 @@ public void fullPageScreenshot() throws Exception { @Test public void setContext() { - driver = startFirefoxDriver(); + driver = startFirefoxDriver(new FirefoxOptions().addArguments("-remote-allow-system-access")); ((HasContext) driver).setContext(FirefoxCommandContext.CHROME); driver.executeScript("console.log('Inside Chrome context');"); diff --git a/examples/java/src/test/java/dev/selenium/interactions/AlertsTest.java b/examples/java/src/test/java/dev/selenium/interactions/AlertsTest.java index 5b42e0299f12..62a82b39f510 100644 --- a/examples/java/src/test/java/dev/selenium/interactions/AlertsTest.java +++ b/examples/java/src/test/java/dev/selenium/interactions/AlertsTest.java @@ -30,64 +30,39 @@ public class AlertsTest extends BaseTest { @Test - public void testForAlerts() throws Exception { + public void testForAlerts() { ChromeOptions chromeOptions = getDefaultChromeOptions(); chromeOptions.addArguments("disable-search-engine-choice-screen"); WebDriver driver = new ChromeDriver(chromeOptions); driver.manage().timeouts().implicitlyWait(Duration.ofMillis(500)); - driver.manage().window().maximize(); - //Navigate to Url driver.get("https://www.selenium.dev/documentation/webdriver/interactions/alerts/"); - //Simple Alert - //Click the link to activate the alert JavascriptExecutor js = (JavascriptExecutor) driver; - //execute js for alert js.executeScript("alert('Sample Alert');"); WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(30)); - //Wait for the alert to be displayed and store it in a variable wait.until(ExpectedConditions.alertIsPresent()); Alert alert = driver.switchTo().alert(); - //Store the alert text in a variable and verify it - String text = alert.getText(); - assertEquals(text, "Sample Alert"); - //Press the OK button + assertEquals("Sample Alert", alert.getText()); alert.accept(); - //Confirm - //execute js for confirm js.executeScript("confirm('Are you sure?');"); - //Wait for the alert to be displayed wait = new WebDriverWait(driver, Duration.ofSeconds(30)); wait.until(ExpectedConditions.alertIsPresent()); - alert = driver.switchTo().alert(); - //Store the alert text in a variable and verify it - text = alert.getText(); - assertEquals(text, "Are you sure?"); - //Press the Cancel button + assertEquals("Are you sure?", alert.getText()); alert.dismiss(); - //Prompt - //execute js for prompt js.executeScript("prompt('What is your name?');"); - //Wait for the alert to be displayed and store it in a variable wait = new WebDriverWait(driver, Duration.ofSeconds(30)); wait.until(ExpectedConditions.alertIsPresent()); - alert = driver.switchTo().alert(); - //Store the alert text in a variable and verify it - text = alert.getText(); - assertEquals(text, "What is your name?"); - //Type your message + assertEquals("What is your name?", alert.getText()); alert.sendKeys("Selenium"); - //Press the OK button alert.accept(); - //quit the browser driver.quit(); } -} \ No newline at end of file +} diff --git a/examples/java/src/test/java/dev/selenium/interactions/FramesTest.java b/examples/java/src/test/java/dev/selenium/interactions/FramesTest.java index b6ff81ae052f..8a11a3e00df9 100644 --- a/examples/java/src/test/java/dev/selenium/interactions/FramesTest.java +++ b/examples/java/src/test/java/dev/selenium/interactions/FramesTest.java @@ -48,9 +48,9 @@ public void informationWithElements() { //switch To IFrame using name or id - driver.findElement(By.name("iframe1-name")); + WebElement iframe1=driver.findElement(By.name("iframe1-name")); //Switch to the frame - driver.switchTo().frame(iframe); + 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 diff --git a/examples/java/src/test/java/dev/selenium/interactions/VirtualAuthenticatorTest.java b/examples/java/src/test/java/dev/selenium/interactions/VirtualAuthenticatorTest.java index dde7477ebcc4..8ca29c32b68d 100644 --- a/examples/java/src/test/java/dev/selenium/interactions/VirtualAuthenticatorTest.java +++ b/examples/java/src/test/java/dev/selenium/interactions/VirtualAuthenticatorTest.java @@ -5,6 +5,7 @@ import java.util.Base64; import java.util.List; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.openqa.selenium.InvalidArgumentException; import org.openqa.selenium.virtualauthenticator.Credential; @@ -133,6 +134,7 @@ public void testAddResidentCredentialNotSupportedWhenAuthenticatorUsesU2FProtoco @Test + @Disabled("A fix was implemented and will be available in Selenium 4.34.") public void testCreateAndAddNonResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) diff --git a/examples/java/src/test/java/dev/selenium/selenium_manager/SeleniumManagerUsageDemo.java b/examples/java/src/test/java/dev/selenium/selenium_manager/SeleniumManagerUsageDemo.java index 857c4a746f3f..e830dca9c204 100644 --- a/examples/java/src/test/java/dev/selenium/selenium_manager/SeleniumManagerUsageDemo.java +++ b/examples/java/src/test/java/dev/selenium/selenium_manager/SeleniumManagerUsageDemo.java @@ -1,5 +1,6 @@ package dev.selenium.selenium_manager; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; @@ -7,6 +8,7 @@ public class SeleniumManagerUsageDemo { @Test + @Disabled("This test is just for demo purposes and should not be run in CI") public void testSetupWithoutManager() { System.setProperty("webdriver.chrome.driver", "/path/to/chromedriver"); WebDriver driver = new ChromeDriver(); @@ -20,5 +22,5 @@ public void testSetupWithManager() { driver.get("https://www.selenium.dev/documentation/selenium_manager/"); driver.quit(); } - + } diff --git a/examples/java/src/test/resources/extensions/webextensions-selenium-example.crx b/examples/java/src/test/resources/extensions/webextensions-selenium-example.crx index 38b38003b7ec..941114eb446e 100644 Binary files a/examples/java/src/test/resources/extensions/webextensions-selenium-example.crx and b/examples/java/src/test/resources/extensions/webextensions-selenium-example.crx differ diff --git a/examples/javascript/package-lock.json b/examples/javascript/package-lock.json index 282993925e2a..4e9642471324 100644 --- a/examples/javascript/package-lock.json +++ b/examples/javascript/package-lock.json @@ -10,10 +10,10 @@ "license": "Apache-2.0", "dependencies": { "assert": "2.1.0", - "selenium-webdriver": "4.29.0" + "selenium-webdriver": "4.34.0" }, "devDependencies": { - "mocha": "11.1.0" + "mocha": "11.7.1" } }, "node_modules/@bazel/runfiles": { @@ -128,15 +128,6 @@ "node": ">=14" } }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -161,19 +152,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -209,15 +187,6 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -227,19 +196,6 @@ "balanced-match": "^1.0.0" } }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", @@ -300,30 +256,19 @@ } }, "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "license": "MIT", "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "readdirp": "^4.0.1" }, "engines": { - "node": ">= 8.10.0" + "node": ">= 14.16.0" }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "funding": { + "url": "https://paulmillr.com/funding/" } }, "node_modules/cliui": { @@ -437,9 +382,9 @@ } }, "node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", "dev": true, "engines": { "node": ">=0.3.1" @@ -479,19 +424,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -541,20 +473,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -607,33 +525,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -746,18 +637,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", @@ -769,15 +648,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -801,18 +671,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-nan": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", @@ -828,16 +686,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, "node_modules/is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -972,15 +820,18 @@ "dev": true }, "node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/minipass": { @@ -993,29 +844,28 @@ } }, "node_modules/mocha": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.1.0.tgz", - "integrity": "sha512-8uJR5RTC2NgpY3GrYcgpZrsEd9zKbPDpob1RezyR2upGHRQtHWofmzTMzTMSV6dru3tj5Ukt0+Vnq1qhFEEwAg==", + "version": "11.7.1", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.1.tgz", + "integrity": "sha512-5EK+Cty6KheMS/YLPPMJC64g5V61gIR25KsRItHw6x4hEKT6Njp1n9LOlH4gpevuwMVS66SXaBBpg+RWZkza4A==", "dev": true, - "license": "MIT", "dependencies": { - "ansi-colors": "^4.1.3", "browser-stdout": "^1.3.1", - "chokidar": "^3.5.3", + "chokidar": "^4.0.1", "debug": "^4.3.5", - "diff": "^5.2.0", + "diff": "^7.0.0", "escape-string-regexp": "^4.0.0", "find-up": "^5.0.0", "glob": "^10.4.5", "he": "^1.2.0", "js-yaml": "^4.1.0", "log-symbols": "^4.1.0", - "minimatch": "^5.1.6", + "minimatch": "^9.0.5", "ms": "^2.1.3", + "picocolors": "^1.1.1", "serialize-javascript": "^6.0.2", "strip-json-comments": "^3.1.1", "supports-color": "^8.1.1", - "workerpool": "^6.5.1", + "workerpool": "^9.2.0", "yargs": "^17.7.2", "yargs-parser": "^21.1.1", "yargs-unparser": "^2.0.0" @@ -1040,15 +890,6 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/object-is": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", @@ -1164,17 +1005,12 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } + "license": "ISC" }, "node_modules/process-nextick-args": { "version": "2.0.1", @@ -1205,15 +1041,17 @@ } }, "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, + "license": "MIT", "engines": { - "node": ">=8.10.0" + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, "node_modules/require-directory": { @@ -1232,9 +1070,9 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "node_modules/selenium-webdriver": { - "version": "4.29.0", - "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.29.0.tgz", - "integrity": "sha512-8XPGtDoji5xk7ZUCzFT1rqHmCp67DCzESsttId7DzmrJmlTRmRLF6X918rbwclcH89amcBNM4zB3lVPj404I0g==", + "version": "4.34.0", + "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.34.0.tgz", + "integrity": "sha512-zGfQFcsASAv3KrYzYh+iw4fFqB7iZAgHW7BU6rRz7isK1i1X4x3LvjmZad4bUUgHDwTnAhlqTzDh21byB+zHMg==", "funding": [ { "type": "github", @@ -1249,10 +1087,10 @@ "@bazel/runfiles": "^6.3.1", "jszip": "^3.10.1", "tmp": "^0.2.3", - "ws": "^8.18.0" + "ws": "^8.18.2" }, "engines": { - "node": ">= 18.20.5" + "node": ">= 20.0.0" } }, "node_modules/serialize-javascript": { @@ -1413,19 +1251,6 @@ "node": ">=14.14" } }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, "node_modules/util": { "version": "0.12.5", "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", @@ -1478,9 +1303,9 @@ } }, "node_modules/workerpool": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", - "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.2.tgz", + "integrity": "sha512-Xz4Nm9c+LiBHhDR5bDLnNzmj6+5F+cyEAWPMkbs2awq/dYazR/efelZzUAjB/y3kNHL+uzkHvxVVpaOfGCPV7A==", "dev": true }, "node_modules/wrap-ansi": { @@ -1520,9 +1345,9 @@ } }, "node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "engines": { "node": ">=10.0.0" }, @@ -1684,12 +1509,6 @@ "dev": true, "optional": true }, - "ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true - }, "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -1705,16 +1524,6 @@ "color-convert": "^2.0.1" } }, - "anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -1744,12 +1553,6 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, "brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -1759,15 +1562,6 @@ "balanced-match": "^1.0.0" } }, - "braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "requires": { - "fill-range": "^7.1.1" - } - }, "browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", @@ -1812,19 +1606,12 @@ } }, "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "readdirp": "^4.0.1" } }, "cliui": { @@ -1905,9 +1692,9 @@ } }, "diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", "dev": true }, "eastasianwidth": { @@ -1934,15 +1721,6 @@ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true }, - "fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, "find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -1977,13 +1755,6 @@ "signal-exit": "^4.0.1" } }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, "function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -2018,26 +1789,6 @@ "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" - }, - "dependencies": { - "minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" } }, "gopd": { @@ -2113,26 +1864,11 @@ "has-tostringtag": "^1.0.0" } }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, "is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==" }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true - }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -2147,15 +1883,6 @@ "has-tostringtag": "^1.0.0" } }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, "is-nan": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", @@ -2165,12 +1892,6 @@ "define-properties": "^1.1.3" } }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, "is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -2270,9 +1991,9 @@ "dev": true }, "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "requires": { "brace-expansion": "^2.0.1" @@ -2285,28 +2006,28 @@ "dev": true }, "mocha": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.1.0.tgz", - "integrity": "sha512-8uJR5RTC2NgpY3GrYcgpZrsEd9zKbPDpob1RezyR2upGHRQtHWofmzTMzTMSV6dru3tj5Ukt0+Vnq1qhFEEwAg==", + "version": "11.7.1", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.1.tgz", + "integrity": "sha512-5EK+Cty6KheMS/YLPPMJC64g5V61gIR25KsRItHw6x4hEKT6Njp1n9LOlH4gpevuwMVS66SXaBBpg+RWZkza4A==", "dev": true, "requires": { - "ansi-colors": "^4.1.3", "browser-stdout": "^1.3.1", - "chokidar": "^3.5.3", + "chokidar": "^4.0.1", "debug": "^4.3.5", - "diff": "^5.2.0", + "diff": "^7.0.0", "escape-string-regexp": "^4.0.0", "find-up": "^5.0.0", "glob": "^10.4.5", "he": "^1.2.0", "js-yaml": "^4.1.0", "log-symbols": "^4.1.0", - "minimatch": "^5.1.6", + "minimatch": "^9.0.5", "ms": "^2.1.3", + "picocolors": "^1.1.1", "serialize-javascript": "^6.0.2", "strip-json-comments": "^3.1.1", "supports-color": "^8.1.1", - "workerpool": "^6.5.1", + "workerpool": "^9.2.0", "yargs": "^17.7.2", "yargs-parser": "^21.1.1", "yargs-unparser": "^2.0.0" @@ -2326,12 +2047,6 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, "object-is": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", @@ -2408,10 +2123,10 @@ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true }, "process-nextick-args": { @@ -2443,13 +2158,10 @@ } }, "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true }, "require-directory": { "version": "2.1.1", @@ -2463,14 +2175,14 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "selenium-webdriver": { - "version": "4.29.0", - "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.29.0.tgz", - "integrity": "sha512-8XPGtDoji5xk7ZUCzFT1rqHmCp67DCzESsttId7DzmrJmlTRmRLF6X918rbwclcH89amcBNM4zB3lVPj404I0g==", + "version": "4.34.0", + "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.34.0.tgz", + "integrity": "sha512-zGfQFcsASAv3KrYzYh+iw4fFqB7iZAgHW7BU6rRz7isK1i1X4x3LvjmZad4bUUgHDwTnAhlqTzDh21byB+zHMg==", "requires": { "@bazel/runfiles": "^6.3.1", "jszip": "^3.10.1", "tmp": "^0.2.3", - "ws": "^8.18.0" + "ws": "^8.18.2" } }, "serialize-javascript": { @@ -2587,15 +2299,6 @@ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==" }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, "util": { "version": "0.12.5", "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", @@ -2636,9 +2339,9 @@ } }, "workerpool": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", - "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.2.tgz", + "integrity": "sha512-Xz4Nm9c+LiBHhDR5bDLnNzmj6+5F+cyEAWPMkbs2awq/dYazR/efelZzUAjB/y3kNHL+uzkHvxVVpaOfGCPV7A==", "dev": true }, "wrap-ansi": { @@ -2664,9 +2367,9 @@ } }, "ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "requires": {} }, "y18n": { diff --git a/examples/javascript/package.json b/examples/javascript/package.json index 0713af445189..5f7acea8cb95 100644 --- a/examples/javascript/package.json +++ b/examples/javascript/package.json @@ -8,9 +8,9 @@ "license": "Apache-2.0", "dependencies": { "assert": "2.1.0", - "selenium-webdriver": "4.29.0" + "selenium-webdriver": "4.34.0" }, "devDependencies": { - "mocha": "11.1.0" + "mocha": "11.7.1" } } diff --git a/examples/javascript/test/actionsApi/mouse/moveByOffset.spec.js b/examples/javascript/test/actionsApi/mouse/moveByOffset.spec.js index f73986e81ec2..949fef61bc99 100644 --- a/examples/javascript/test/actionsApi/mouse/moveByOffset.spec.js +++ b/examples/javascript/test/actionsApi/mouse/moveByOffset.spec.js @@ -1,4 +1,4 @@ -const {By, Origin, Builder} = require('selenium-webdriver'); +const {By, Origin, Builder, until } = require('selenium-webdriver'); const assert = require('assert'); describe('Mouse move by offset', function () { @@ -16,7 +16,7 @@ describe('Mouse move by offset', function () { const actions = driver.actions({async: true}); await actions.move({x: 8, y: 0, origin: mouseTracker}).perform(); - await driver.sleep(500); + await driver.wait(until.elementTextContains(await driver.findElement(By.id('relative-location')), ","), 2000); let result = await driver.findElement(By.id('relative-location')).getText(); result = result.split(', '); assert.deepStrictEqual((Math.abs(parseInt(result[0]) - 100 - 8) < 2), true) diff --git a/examples/javascript/test/bidirectional/browsingContextInspector.spec.js b/examples/javascript/test/bidirectional/browsingContextInspector.spec.js index 045b464eb054..e7f7e9f4cab8 100644 --- a/examples/javascript/test/bidirectional/browsingContextInspector.spec.js +++ b/examples/javascript/test/bidirectional/browsingContextInspector.spec.js @@ -114,7 +114,7 @@ describe('Browsing Context Inspector', function () { assert.equal(contextInfo.id, windowHandle) assert.equal(contextInfo.url, 'about:blank') - assert.equal(contextInfo.children, null) + assert.equal(contextInfo.children.length, 0) assert.equal(contextInfo.parentBrowsingContext, null) }) }) diff --git a/examples/javascript/test/bidirectional/input.spec.js b/examples/javascript/test/bidirectional/input.spec.js index 40573bd15648..9dd2ca5a45f7 100644 --- a/examples/javascript/test/bidirectional/input.spec.js +++ b/examples/javascript/test/bidirectional/input.spec.js @@ -33,7 +33,7 @@ describe('Input module', function () { let resultElement = await driver.findElement(By.id('result')) await resultElement.getText().then(function (text) { - assert(text.includes('oquefort parmigiano cheddar')) + assert(text.includes('oquefort parmigiano cheddar'), `text is: ${text}`) }) }) diff --git a/examples/javascript/test/bidirectional/network_events.spec.js b/examples/javascript/test/bidirectional/network_events.spec.js index bade8719a2ef..f6141bfbaf23 100644 --- a/examples/javascript/test/bidirectional/network_events.spec.js +++ b/examples/javascript/test/bidirectional/network_events.spec.js @@ -1,6 +1,6 @@ const assert = require("assert"); const firefox = require('selenium-webdriver/firefox'); -const Network = require("selenium-webdriver/bidi/network"); +const { Network } = require("selenium-webdriver/bidi/network"); const {until, Builder} = require("selenium-webdriver"); @@ -20,17 +20,17 @@ describe('Network events', function () { }) it('can listen to event before request is sent', async function () { - let beforeRequestEvent = null + let beforeRequestEvent = [] const network = await Network(driver) await network.beforeRequestSent(function (event) { - beforeRequestEvent = event + beforeRequestEvent.push(event) }) await driver.get('https://www.selenium.dev/selenium/web/blank.html') - assert.equal(beforeRequestEvent.request.method, 'GET') - const url = beforeRequestEvent.request.url - assert.equal(url, await driver.getCurrentUrl()) + const currentUrl = await driver.getCurrentUrl() + const currentUrlFound = beforeRequestEvent.some(event => event.request.url.includes(currentUrl)) + assert(currentUrlFound, `${currentUrl} was not requested`) }) it('can request cookies', async function () { @@ -50,8 +50,6 @@ describe('Network events', function () { assert.equal(beforeRequestEvent.request.method, 'GET') assert.equal(beforeRequestEvent.request.cookies[0].name, 'north') assert.equal(beforeRequestEvent.request.cookies[0].value.value, 'biryani') - const url = beforeRequestEvent.request.url - assert.equal(url, await driver.getCurrentUrl()) await driver.manage().addCookie({ name: 'south', @@ -70,13 +68,14 @@ describe('Network events', function () { beforeRequestEvent.push(event) }) - await driver.get('http://www.selenium.dev/selenium/web/bidi/redirected_http_equiv.html') + await driver.get('https://www.selenium.dev/selenium/web/bidi/redirected_http_equiv.html') await driver.wait(until.urlContains('redirected.html'), 1000) assert.equal(beforeRequestEvent[0].request.method, 'GET') - assert(beforeRequestEvent[0].request.url.includes('redirected_http_equiv.html')) - assert.equal(beforeRequestEvent[2].request.method, 'GET') - assert(beforeRequestEvent[2].request.url.includes('redirected.html')) + let redirectedFound = beforeRequestEvent.some(event => event.request.url.includes('redirected.html')) + assert(redirectedFound, 'redirected.html was not requested') + redirectedFound = beforeRequestEvent.some(event => event.request.url.includes('redirected_http_equiv.html')) + assert(redirectedFound, 'redirected_http_equiv.html was not requested') }) it('can subscribe to response started', async function () { diff --git a/examples/javascript/test/drivers/service.spec.js b/examples/javascript/test/drivers/service.spec.js index f0772239eb68..c2983631fb43 100644 --- a/examples/javascript/test/drivers/service.spec.js +++ b/examples/javascript/test/drivers/service.spec.js @@ -1,53 +1,62 @@ +const fs = require('fs'); +const os = require('os'); +const path = require('path'); const Chrome = require('selenium-webdriver/chrome'); const {Browser, Builder} = require("selenium-webdriver"); const {getBinaryPaths} = require("selenium-webdriver/common/driverFinder"); -const options = new Chrome.Options(); describe('Service Test', function () { - it('Default service', async function () { - let service = new Chrome.ServiceBuilder() - - let driver = new Builder() - .forBrowser(Browser.CHROME) - .setChromeService(service) - .build(); + let driver; + let userDataDir; + let service; + let options; + + afterEach(async function () { + if (driver) { + await driver.quit(); + driver = null; + } + if (userDataDir) { + fs.rmSync(userDataDir, { recursive: true, force: true }); + userDataDir = null; + } + }); + it('Default service', async function () { + service = new Chrome.ServiceBuilder(); + driver = new Builder() + .forBrowser(Browser.CHROME) + .setChromeService(service) + .build(); await driver.get('https://www.selenium.dev/selenium/web/blank.html'); - await driver.quit(); }); it('Set Driver Location', async function () { - - let options = new Chrome.Options(); - options.setBrowserVersion("stable") - - let paths = getBinaryPaths(options) + options = new Chrome.Options(); + options.setBrowserVersion("stable"); + let paths = getBinaryPaths(options); let driverPath = paths.driverPath; let browserPath = paths.browserPath; - - options.setChromeBinaryPath(browserPath) - - let service = new Chrome.ServiceBuilder().setPath(driverPath) - - let driver = new Builder() - .forBrowser(Browser.CHROME) - .setChromeOptions(options) - .setChromeService(service) - .build(); - + options.setChromeBinaryPath(browserPath); + userDataDir = fs.mkdtempSync(path.join(os.tmpdir(), 'chrome-profile-')); + options.addArguments(`--user-data-dir=${userDataDir}`); + options.addArguments('--no-sandbox'); + options.addArguments('--disable-dev-shm-usage'); + service = new Chrome.ServiceBuilder(driverPath); + driver = new Builder() + .forBrowser(Browser.CHROME) + .setChromeOptions(options) + .setChromeService(service) + .build(); await driver.get('https://www.selenium.dev/selenium/web/blank.html'); - await driver.quit(); }); it('Set port', async function () { - let service = new Chrome.ServiceBuilder().setPort(1234) - - let driver = new Builder() - .forBrowser(Browser.CHROME) - .setChromeService(service) - .build(); - + service = new Chrome.ServiceBuilder().setPort(1234); + driver = new Builder() + .forBrowser(Browser.CHROME) + .setChromeService(service) + .build(); await driver.get('https://www.selenium.dev/selenium/web/blank.html'); - await driver.quit(); }); -}); \ No newline at end of file +}); diff --git a/examples/javascript/test/interactions/cookies.spec.js b/examples/javascript/test/interactions/cookies.spec.js index a954f39310c5..b16bb99ec756 100644 --- a/examples/javascript/test/interactions/cookies.spec.js +++ b/examples/javascript/test/interactions/cookies.spec.js @@ -1,5 +1,6 @@ const {Browser, Builder} = require("selenium-webdriver"); +const assert = require('assert') describe('Cookies', function() { @@ -36,7 +37,7 @@ describe('Cookies', function() { // Get cookie details with named cookie 'foo' await driver.manage().getCookie('foo').then(function(cookie) { - console.log('cookie details => ', cookie); + assert.equal(cookie.value, 'bar'); }); }); @@ -49,7 +50,7 @@ describe('Cookies', function() { // Get all Available cookies await driver.manage().getCookies().then(function(cookies) { - console.log('cookie details => ', cookies); + assert.equal(cookies.filter(cookie => cookie.name.startsWith('test')).length, 2); }); }); @@ -65,7 +66,7 @@ describe('Cookies', function() { // Get all Available cookies await driver.manage().getCookies().then(function(cookies) { - console.log('cookie details => ', cookies); + assert.equal(cookies.filter(cookie => cookie.name.startsWith('test')).length, 1); }); }); @@ -79,4 +80,4 @@ describe('Cookies', function() { // Delete all cookies await driver.manage().deleteAllCookies(); }); -}); \ No newline at end of file +}); diff --git a/examples/javascript/test/selenium_manager/usage.spec.js b/examples/javascript/test/selenium_manager/usage.spec.js new file mode 100644 index 000000000000..9ef17707aeb5 --- /dev/null +++ b/examples/javascript/test/selenium_manager/usage.spec.js @@ -0,0 +1,32 @@ +const Chrome = require('selenium-webdriver/chrome'); +const {Browser, Builder} = require("selenium-webdriver"); +const options = new Chrome.Options(); + +describe('Usage Test', function () { + it('Creates driver wit Selenium Manager', async function () { + + let driver = new Builder() + .forBrowser(Browser.CHROME) + .build(); + + await driver.get('https://www.selenium.dev/selenium/web/blank.html'); + await driver.quit(); + }); + + // it('Creates driver with Selenium Manager', async function () { + // let driverPath = '/path/to/chromedriver'; + // let browserPath = '/path/to/chrome'; + + // options.setChromeBinaryPath(browserPath) + + // let service = new Chrome.ServiceBuilder().setPath(driverPath) + + // let driver = new Builder() + // .forBrowser(Browser.CHROME) + // .setChromeService(service) + // .build(); + + // await driver.get('https://www.selenium.dev/selenium/web/blank.html'); + // await driver.quit(); + // }); +}); diff --git a/examples/kotlin/pom.xml b/examples/kotlin/pom.xml index b93b1150eebe..779df4b7f6ca 100644 --- a/examples/kotlin/pom.xml +++ b/examples/kotlin/pom.xml @@ -9,18 +9,17 @@ 1.0.0 - 2.1.0 + 2.2.0 2.0.17 - 1.5.17 + 1.5.18 - 5.12.0 - 5.2.3 + 5.13.3 - 3.5.2 + 3.5.3 - 1.8 - 4.29.0 + 11 + 4.34.0 ${java.version} ${java.version} diff --git a/examples/kotlin/src/test/kotlin/dev/selenium/BaseTest.kt b/examples/kotlin/src/test/kotlin/dev/selenium/BaseTest.kt index dfe1bcef70a5..feea0654aade 100644 --- a/examples/kotlin/src/test/kotlin/dev/selenium/BaseTest.kt +++ b/examples/kotlin/src/test/kotlin/dev/selenium/BaseTest.kt @@ -1,7 +1,6 @@ package dev.selenium; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; diff --git a/examples/kotlin/src/test/kotlin/dev/selenium/actions_api/ActionsTest.kt b/examples/kotlin/src/test/kotlin/dev/selenium/actions_api/ActionsTest.kt index 4ba3d47e178b..8ac7972e5af0 100644 --- a/examples/kotlin/src/test/kotlin/dev/selenium/actions_api/ActionsTest.kt +++ b/examples/kotlin/src/test/kotlin/dev/selenium/actions_api/ActionsTest.kt @@ -5,7 +5,6 @@ import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test import org.openqa.selenium.By import org.openqa.selenium.Keys -import org.openqa.selenium.WebElement import org.openqa.selenium.interactions.Actions import org.openqa.selenium.remote.RemoteWebDriver @@ -47,7 +46,7 @@ class ActionsTest : BaseTest() { (driver as RemoteWebDriver).resetInputState() actions.sendKeys("a").perform() - Assertions.assertEquals("A", clickable.getAttribute("value").get(0).toString()) - Assertions.assertEquals("a", clickable.getAttribute("value").get(1).toString()) + Assertions.assertEquals("A", clickable.getAttribute("value")!!.get(0).toString()) + Assertions.assertEquals("a", clickable.getAttribute("value")!!.get(1).toString()) } } diff --git a/examples/kotlin/src/test/kotlin/dev/selenium/actions_api/KeysTest.kt b/examples/kotlin/src/test/kotlin/dev/selenium/actions_api/KeysTest.kt index ebc0c5046d77..519e29215141 100644 --- a/examples/kotlin/src/test/kotlin/dev/selenium/actions_api/KeysTest.kt +++ b/examples/kotlin/src/test/kotlin/dev/selenium/actions_api/KeysTest.kt @@ -7,7 +7,6 @@ import org.openqa.selenium.By import org.openqa.selenium.HasCapabilities import org.openqa.selenium.Keys import org.openqa.selenium.Platform -import org.openqa.selenium.WebElement import org.openqa.selenium.interactions.Actions class KeysTest : BaseTest() { diff --git a/examples/kotlin/src/test/kotlin/dev/selenium/actions_api/MouseTest.kt b/examples/kotlin/src/test/kotlin/dev/selenium/actions_api/MouseTest.kt index 8281943430d8..36c929335712 100644 --- a/examples/kotlin/src/test/kotlin/dev/selenium/actions_api/MouseTest.kt +++ b/examples/kotlin/src/test/kotlin/dev/selenium/actions_api/MouseTest.kt @@ -4,8 +4,6 @@ import dev.selenium.BaseTest import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test import org.openqa.selenium.By -import org.openqa.selenium.Rectangle -import org.openqa.selenium.WebElement import org.openqa.selenium.interactions.Actions import org.openqa.selenium.interactions.PointerInput import org.openqa.selenium.interactions.Sequence @@ -37,7 +35,7 @@ class MouseTest : BaseTest() { .click(clickable) .perform() - Assertions.assertTrue(driver.getCurrentUrl().contains("resultPage.html")) + Assertions.assertTrue(driver.getCurrentUrl()!!.contains("resultPage.html")) } @Test diff --git a/examples/kotlin/src/test/kotlin/dev/selenium/actions_api/PenTest.kt b/examples/kotlin/src/test/kotlin/dev/selenium/actions_api/PenTest.kt index 00278b62b3d5..4b537d19768d 100644 --- a/examples/kotlin/src/test/kotlin/dev/selenium/actions_api/PenTest.kt +++ b/examples/kotlin/src/test/kotlin/dev/selenium/actions_api/PenTest.kt @@ -4,7 +4,6 @@ import dev.selenium.BaseTest import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test import org.openqa.selenium.By -import org.openqa.selenium.Rectangle import org.openqa.selenium.WebElement import org.openqa.selenium.interactions.Actions import org.openqa.selenium.interactions.PointerInput diff --git a/examples/kotlin/src/test/kotlin/dev/selenium/virtualauthenticator/VirtualAuthenticatorTest.kt b/examples/kotlin/src/test/kotlin/dev/selenium/virtualauthenticator/VirtualAuthenticatorTest.kt index 91af23d0733e..8985a829c227 100644 --- a/examples/kotlin/src/test/kotlin/dev/selenium/virtualauthenticator/VirtualAuthenticatorTest.kt +++ b/examples/kotlin/src/test/kotlin/dev/selenium/virtualauthenticator/VirtualAuthenticatorTest.kt @@ -4,6 +4,7 @@ import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test +import org.junit.jupiter.api.Disabled import org.openqa.selenium.InvalidArgumentException import org.openqa.selenium.WebDriver import org.openqa.selenium.chrome.ChromeDriver @@ -107,6 +108,7 @@ class VirtualAuthenticatorTest { } @Test + @Disabled("A fix was implemented and will be available in Selenium 4.34.") fun testCreateAndAddNonResidentialKey() { val options = VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) @@ -208,4 +210,4 @@ class VirtualAuthenticatorTest { ) ) } -} \ No newline at end of file +} diff --git a/examples/python/README.md b/examples/python/README.md index 2db5f25cb9a5..9650c07cbb5e 100644 --- a/examples/python/README.md +++ b/examples/python/README.md @@ -1,38 +1,61 @@ -# Running all tests from Selenium python example +# Running tests from Selenium Python examples -Follow these steps to run all test example from selenium python - -1. Clone this repository +#### 1. Clone this repository ``` git clone https://github.com/SeleniumHQ/seleniumhq.github.io.git ``` -2. Navigate to `python` directory +#### 2. Navigate to `python` directory ``` cd seleniumhq.github.io/examples/python ``` -3. Install dependencies using pip +#### 3. Create a virtual environment + +- On Windows: + +``` +py -m venv venv +venv\Scripts\activate +``` + +- On Linux/Mac: + +``` +python3 -m venv venv +source venv/bin/activate +``` + +#### 4. Install dependencies: ``` pip install -r requirements.txt ``` -> if you are on a different python version, for example python3.x you may have to replace `pip` with `pip3` -4. Run all tests +> for help, see: https://packaging.python.org/en/latest/tutorials/installing-packages + +#### 5. Run tests + +- Run all tests with the default Python interpreter: ``` pytest ``` -> Please keep some patience - If you are doing it for the first time, it will take a little while to verify and download the browser drivers +- Run all tests with every installed/supported Python interpreter: -## Execute a specific example -To run a specific Selenium Python example, use the following command: -```bash +``` +tox +``` + +> Please have some patience - If you are doing it for the first time, it will take a little while to download the browser drivers + +- Run a specific example: + +``` pytest path/to/test_script.py ``` -Make sure to replace `path/to/test_script.py` with the path and name of the example you want to run. \ No newline at end of file +> Make sure to replace `path/to/test_script.py` with the path and name of the example you want to run diff --git a/examples/python/requirements.txt b/examples/python/requirements.txt index f1afcbd854a6..d743af5a6005 100644 --- a/examples/python/requirements.txt +++ b/examples/python/requirements.txt @@ -1,7 +1,8 @@ -selenium==4.29.0 -pytest==8.3.5 -trio==0.29.0 +selenium==4.34.2 +pytest==8.4.1 +trio==0.30.0 pytest-trio==0.8.0 -pytest-rerunfailures==14.0 -flake8==7.1.2 -requests==2.32.3 +pytest-rerunfailures==15.1 +flake8==7.3.0 +requests==2.32.4 +tox==4.27.0 diff --git a/examples/python/tests/bidi/cdp/test_network.py b/examples/python/tests/bidi/cdp/test_network.py index 191d7a4a95ad..7cddde13be21 100644 --- a/examples/python/tests/bidi/cdp/test_network.py +++ b/examples/python/tests/bidi/cdp/test_network.py @@ -2,7 +2,7 @@ import pytest from selenium.webdriver.common.by import By -from selenium.webdriver.common.devtools.v131.network import Headers +from selenium.webdriver.common.devtools.v137.network import Headers @pytest.mark.trio diff --git a/examples/python/tests/browsers/test_firefox.py b/examples/python/tests/browsers/test_firefox.py index 5780e16106fd..20ff9beecec9 100644 --- a/examples/python/tests/browsers/test_firefox.py +++ b/examples/python/tests/browsers/test_firefox.py @@ -143,14 +143,17 @@ def test_full_page_screenshot(firefox_driver): driver.quit() -def test_set_context(firefox_driver): - driver = firefox_driver +def test_set_context(): + options = webdriver.FirefoxOptions() + options.add_argument("-remote-allow-system-access") + driver = webdriver.Firefox(options=options) with driver.context(driver.CONTEXT_CHROME): driver.execute_script("console.log('Inside Chrome context');") # Check if the context is back to content assert driver.execute("GET_CONTEXT")["value"] == "content" + driver.quit() def test_firefox_profile(): diff --git a/examples/python/tests/conftest.py b/examples/python/tests/conftest.py index 660ce87e396a..4102ea87f440 100644 --- a/examples/python/tests/conftest.py +++ b/examples/python/tests/conftest.py @@ -14,6 +14,12 @@ from selenium import webdriver +def pytest_configure(config): + config.addinivalue_line( + "markers", "driver_type(type): marks tests to use driver type ('bidi', 'firefox', etc)" + ) + + @pytest.fixture(scope='function') def driver(request): marker = request.node.get_closest_marker("driver_type") @@ -142,7 +148,7 @@ def server_old(request): os.path.abspath(__file__) ) ), - "selenium-server-4.29.0.jar", + "selenium-server-4.34.0.jar", ) def wait_for_server(url, timeout): @@ -200,7 +206,7 @@ def server(): ) ) ), - "selenium-server-4.29.0.jar", + "selenium-server-4.34.0.jar", ) args = [ @@ -273,7 +279,7 @@ def grid_server(): ) ) ), - "selenium-server-4.29.0.jar", + "selenium-server-4.34.0.jar", ) args = [ diff --git a/examples/python/tests/design_strategy/using_best_practice.py b/examples/python/tests/design_strategy/using_best_practice.py new file mode 100644 index 000000000000..29063b8f6a90 --- /dev/null +++ b/examples/python/tests/design_strategy/using_best_practice.py @@ -0,0 +1,266 @@ +""" +An example of `python + pytest + selenium` +which implemented "**Action Bot**, **Loadable Component** and **Page Object**". +""" + +import pytest +from selenium import webdriver +from selenium.common import ( + ElementNotInteractableException, + NoSuchElementException, + StaleElementReferenceException, +) +from selenium.webdriver import ActionChains +from selenium.webdriver.common.by import By +from selenium.webdriver.remote.webelement import WebElement +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.support.ui import WebDriverWait + + +@pytest.fixture(scope="function") +def chrome_driver(): + with webdriver.Chrome() as driver: + driver.set_window_size(1024, 768) + driver.implicitly_wait(0.5) + yield driver + + +class ActionBot: + def __init__(self, driver) -> None: + self.driver = driver + self.wait = WebDriverWait( + driver, + timeout=10, + poll_frequency=2, + ignored_exceptions=[ + NoSuchElementException, + StaleElementReferenceException, + ElementNotInteractableException, + ], + ) + + def element(self, locator: tuple) -> WebElement: + self.wait.until(lambda driver: driver.find_element(*locator)) + return self.driver.find_element(*locator) + + def elements(self, locator: tuple) -> list[WebElement]: + return self.driver.find_elements(*locator) + + def hover(self, locator: tuple) -> None: + element = self.element(locator) + ActionChains(self.driver).move_to_element(element).perform() + + def click(self, locator: tuple) -> None: + element = self.element(locator) + element.click() + + def type(self, locator: tuple, value: str) -> None: + element = self.element(locator) + element.clear() + element.send_keys(value) + + def text(self, locator: tuple) -> str: + element = self.element(locator) + return element.text + + +class LoadableComponent: + def load(self): + raise NotImplementedError("Subclasses must implement this method") + + def is_loaded(self): + raise NotImplementedError("Subclasses must implement this method") + + def get(self): + if not self.is_loaded(): + self.load() + if not self.is_loaded(): + raise Exception("Page not loaded properly.") + return self + + +class TodoPage(LoadableComponent): + url = "https://todomvc.com/examples/react/dist/" + + new_todo_by = (By.CSS_SELECTOR, "input.new-todo") + count_todo_left_by = (By.CSS_SELECTOR, "span.todo-count") + todo_items_by = (By.CSS_SELECTOR, "ul.todo-list>li") + + view_all_by = (By.LINK_TEXT, "All") + view_active_by = (By.LINK_TEXT, "Active") + view_completed_by = (By.LINK_TEXT, "Completed") + + toggle_all_by = (By.CSS_SELECTOR, "input.toggle-all") + clear_completed_by = (By.CSS_SELECTOR, "button.clear-completed") + + @staticmethod + def build_todo_by(s: str) -> tuple: + p = f"//li[.//label[contains(text(), '{s}')]]" + return By.XPATH, p + + @staticmethod + def build_todo_item_label_by(s: str) -> tuple: + p = f"//label[contains(text(), '{s}')]" + return By.XPATH, p + + @staticmethod + def build_todo_item_toggle_by(s: str) -> tuple: + by, using = TodoPage.build_todo_item_label_by(s) + p = f"{using}/../input[@class='toggle']" + return by, p + + @staticmethod + def build_todo_item_delete_by(s: str) -> tuple: + by, using = TodoPage.build_todo_item_label_by(s) + p = f"{using}/../button[@class='destroy']" + return by, p + + def build_count_todo_left(self, count: int) -> str: + if count == 1: + return "1 item left!" + else: + return f"{count} items left!" + + def __init__(self, driver): + self.driver = driver + self.bot = ActionBot(driver) + + def load(self): + self.driver.get(self.url) + + def is_loaded(self): + try: + WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located(self.new_todo_by)) + return True + except: + return False + + # business domain below + def count_todo_items_left(self) -> str: + return self.bot.text(self.count_todo_left_by) + + def todo_count(self) -> int: + return len(self.bot.elements(self.todo_items_by)) + + def new_todo(self, s: str): + self.bot.type(self.new_todo_by, s + "\n") + + def toggle_todo(self, s: str): + self.bot.click(self.build_todo_item_toggle_by(s)) + + def hover_todo(self, s: str) -> None: + self.bot.hover(self.build_todo_by(s)) + + def delete_todo(self, s: str): + self.hover_todo(s) + self.bot.click(self.build_todo_item_delete_by(s)) + + def clear_completed_todo(self): + self.bot.click(self.clear_completed_by) + + def toggle_all_todo(self): + self.bot.click(self.toggle_all_by) + + def view_all_todo(self): + self.bot.click(self.view_all_by) + + def view_active_todo(self): + self.bot.click(self.view_active_by) + + def view_completed_todo(self): + self.bot.click(self.view_completed_by) + + +@pytest.fixture +def page(chrome_driver) -> TodoPage: + driver = chrome_driver + return TodoPage(driver).get() + + +class TestTodoPage: + def test_new_todo(self, page: TodoPage): + assert page.todo_count() == 0 + page.new_todo("aaa") + assert page.count_todo_items_left() == page.build_count_todo_left(1) + + def test_todo_toggle(self, page: TodoPage): + s = "aaa" + page.new_todo(s) + assert page.count_todo_items_left() == page.build_count_todo_left(1) + + page.toggle_todo(s) + assert page.count_todo_items_left() == page.build_count_todo_left(0) + + page.toggle_todo(s) + assert page.count_todo_items_left() == page.build_count_todo_left(1) + + def test_todo_delete(self, page: TodoPage): + s1 = "aaa" + s2 = "bbb" + page.new_todo(s1) + page.new_todo(s2) + assert page.count_todo_items_left() == page.build_count_todo_left(2) + + page.delete_todo(s1) + assert page.count_todo_items_left() == page.build_count_todo_left(1) + + page.delete_todo(s2) + assert page.todo_count() == 0 + + def test_new_100_todo(self, page: TodoPage): + for i in range(100): + s = f"ToDo{i}" + page.new_todo(s) + assert page.count_todo_items_left() == page.build_count_todo_left(100) + + def test_toggle_all_todo(self, page: TodoPage): + for i in range(10): + s = f"ToDo{i}" + page.new_todo(s) + assert page.count_todo_items_left() == page.build_count_todo_left(10) + assert page.todo_count() == 10 + + page.toggle_all_todo() + assert page.count_todo_items_left() == page.build_count_todo_left(0) + assert page.todo_count() == 10 + + page.toggle_all_todo() + assert page.count_todo_items_left() == page.build_count_todo_left(10) + assert page.todo_count() == 10 + + def test_clear_completed_todo(self, page: TodoPage): + for i in range(10): + s = f"ToDo{i}" + page.new_todo(s) + assert page.count_todo_items_left() == page.build_count_todo_left(10) + assert page.todo_count() == 10 + + for i in range(5): + s = f"ToDo{i}" + page.toggle_todo(s) + assert page.count_todo_items_left() == page.build_count_todo_left(5) + assert page.todo_count() == 10 + + page.clear_completed_todo() + assert page.count_todo_items_left() == page.build_count_todo_left(5) + assert page.todo_count() == 5 + + def test_view_todo(self, page: TodoPage): + for i in range(10): + s = f"ToDo{i}" + page.new_todo(s) + for i in range(4): + s = f"ToDo{i}" + page.toggle_todo(s) + + page.view_all_todo() + assert page.count_todo_items_left() == page.build_count_todo_left(6) + assert page.todo_count() == 10 + + page.view_active_todo() + assert page.count_todo_items_left() == page.build_count_todo_left(6) + assert page.todo_count() == 6 + + page.view_completed_todo() + assert page.count_todo_items_left() == page.build_count_todo_left(6) + assert page.todo_count() == 4 diff --git a/examples/python/tests/interactions/test_cookies.py b/examples/python/tests/interactions/test_cookies.py index 779965a8a332..0b40e9045172 100644 --- a/examples/python/tests/interactions/test_cookies.py +++ b/examples/python/tests/interactions/test_cookies.py @@ -1,7 +1,7 @@ from selenium import webdriver -def add_cookie(): +def test_add_cookie(): driver = webdriver.Chrome() driver.get("http://www.example.com/") @@ -9,7 +9,7 @@ def add_cookie(): driver.add_cookie({"name": "key", "value": "value"}) -def get_named_cookie(): +def test_get_named_cookie(): driver = webdriver.Chrome() driver.get("http://www.example.com/") @@ -20,7 +20,7 @@ def get_named_cookie(): print(driver.get_cookie("foo")) -def get_all_cookies(): +def test_get_all_cookies(): driver = webdriver.Chrome() driver.get("http://www.example.com/") @@ -31,7 +31,7 @@ def get_all_cookies(): # Get all available cookies print(driver.get_cookies()) -def delete_cookie(): +def test_delete_cookie(): driver = webdriver.Chrome() driver.get("http://www.example.com/") @@ -43,7 +43,7 @@ def delete_cookie(): driver.delete_cookie("test1") -def delete_all_cookies(): +def test_delete_all_cookies(): driver = webdriver.Chrome() driver.get("http://www.example.com/") @@ -55,7 +55,7 @@ def delete_all_cookies(): driver.delete_all_cookies() -def same_side_cookie_attr(): +def test_same_side_cookie_attr(): driver = webdriver.Chrome() driver.get("http://www.example.com/") diff --git a/examples/python/tests/interactions/test_frames.py b/examples/python/tests/interactions/test_frames.py index 53b695b6fc83..3ce9d1a31923 100644 --- a/examples/python/tests/interactions/test_frames.py +++ b/examples/python/tests/interactions/test_frames.py @@ -1,2 +1,55 @@ +# Licensed to the Software Freedom Conservancy (SFC) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The SFC licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + from selenium import webdriver +from selenium.webdriver.common.by import By + +#set chrome and launch web page +driver = webdriver.Chrome() +driver.get("https://www.selenium.dev/selenium/web/iframes.html") + +# --- 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 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 index --- +driver.switch_to.frame(0) +assert "We Leave From Here" in driver.page_source + +# --- Final page content check --- +driver.switch_to.default_content() +assert "This page has iframes" in driver.page_source + +#quit the driver +driver.quit() +#demo code for conference diff --git a/examples/python/tests/support/test_expected_conditions.py b/examples/python/tests/support/test_expected_conditions.py index 53b695b6fc83..fb93f26b79cd 100644 --- a/examples/python/tests/support/test_expected_conditions.py +++ b/examples/python/tests/support/test_expected_conditions.py @@ -1,2 +1,18 @@ -from selenium import webdriver +from selenium.webdriver.common.by import By +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.support.wait import WebDriverWait +# Expected Conditions API Documentation: +# https://www.selenium.dev/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.expected_conditions.html + + +def test_expected_condition(driver): + driver.get("https://www.selenium.dev/selenium/web/dynamic.html") + revealed = driver.find_element(By.ID, "revealed") + driver.find_element(By.ID, "reveal").click() + + wait = WebDriverWait(driver, timeout=2) + wait.until(EC.visibility_of_element_located((By.ID, "revealed"))) + + revealed.send_keys("Displayed") + assert revealed.get_property("value") == "Displayed" diff --git a/examples/python/tox.ini b/examples/python/tox.ini new file mode 100644 index 000000000000..49c6f636bb75 --- /dev/null +++ b/examples/python/tox.ini @@ -0,0 +1,30 @@ +# Tox (https://tox.wiki/) is a tool for running tests in multiple +# virtualenvs. This configuration file will run the test suite on all +# supported python versions. To use it, run "tox" from this directory. +# +# For a specific environment, run: "tox -e " (i.e.: "tox -e py313") +# +# This tox configuration will skip any Python interpreters that can't be found. +# To manage multiple Python interpreters for covering all versions, you can use +# pyenv: https://github.com/pyenv/pyenv + + +[tox] +env_list = + py39 + py310 + py311 + py312 + py313 +skip_missing_interpreters = True + +[testenv] +description = run tests +passenv = * +deps = + -r requirements.txt +commands = + # "-vv" means extra verbose + # "-r fEsxXp" means show extra test summary info as specified by: + # (f)ailed, (E)rror, (s)kipped, (x)failed, (X)passed, (p)assed + pytest -vv -r fEsxXp {posargs:.} diff --git a/examples/ruby/.rubocop.yml b/examples/ruby/.rubocop.yml index b88b233a689b..492720f45e42 100644 --- a/examples/ruby/.rubocop.yml +++ b/examples/ruby/.rubocop.yml @@ -1,9 +1,10 @@ inherit_from: .rubocop_todo.yml -require: rubocop-rspec +plugins: + - rubocop-rspec AllCops: - TargetRubyVersion: 3.0 + TargetRubyVersion: 3.1 NewCops: enable SuggestExtensions: rubocop-rake: false diff --git a/examples/ruby/Gemfile b/examples/ruby/Gemfile index 17d408f72607..71ca26c768d1 100644 --- a/examples/ruby/Gemfile +++ b/examples/ruby/Gemfile @@ -7,5 +7,5 @@ gem 'rake', '~> 13.0' gem 'rspec', '~> 3.0' gem 'rubocop', '~> 1.35' gem 'rubocop-rspec', '~> 3.0' -gem 'selenium-devtools', '= 0.133.0' -gem 'selenium-webdriver', '= 4.29.1' +gem 'selenium-devtools', '= 0.138.0' +gem 'selenium-webdriver', '= 4.34.0' diff --git a/examples/ruby/Gemfile.lock b/examples/ruby/Gemfile.lock index 5c54339b78de..ff4552b2c53e 100644 --- a/examples/ruby/Gemfile.lock +++ b/examples/ruby/Gemfile.lock @@ -1,36 +1,37 @@ GEM remote: https://rubygems.org/ specs: - ast (2.4.2) - base64 (0.2.0) + ast (2.4.3) + base64 (0.3.0) diff-lcs (1.5.1) - json (2.10.1) - language_server-protocol (3.17.0.4) + json (2.12.2) + language_server-protocol (3.17.0.5) lint_roller (1.1.0) - logger (1.6.6) - parallel (1.26.3) - parser (3.3.7.1) + logger (1.7.0) + parallel (1.27.0) + parser (3.3.8.0) ast (~> 2.4.1) racc + prism (1.4.0) racc (1.8.1) rainbow (3.1.1) - rake (13.2.1) + rake (13.3.0) regexp_parser (2.10.0) rexml (3.4.1) - rspec (3.13.0) + rspec (3.13.1) rspec-core (~> 3.13.0) rspec-expectations (~> 3.13.0) rspec-mocks (~> 3.13.0) - rspec-core (3.13.0) + rspec-core (3.13.4) rspec-support (~> 3.13.0) - rspec-expectations (3.13.0) + rspec-expectations (3.13.5) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) - rspec-mocks (3.13.0) + rspec-mocks (3.13.5) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) - rspec-support (3.13.0) - rubocop (1.72.2) + rspec-support (3.13.4) + rubocop (1.78.0) json (~> 2.3) language_server-protocol (~> 3.17.0.2) lint_roller (~> 1.1.0) @@ -38,19 +39,20 @@ GEM parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 2.9.3, < 3.0) - rubocop-ast (>= 1.38.0, < 2.0) + rubocop-ast (>= 1.45.1, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 4.0) - rubocop-ast (1.38.0) - parser (>= 3.3.1.0) - rubocop-rspec (3.5.0) + rubocop-ast (1.45.1) + parser (>= 3.3.7.2) + prism (~> 1.4) + rubocop-rspec (3.6.0) lint_roller (~> 1.1) rubocop (~> 1.72, >= 1.72.1) ruby-progressbar (1.13.0) rubyzip (2.4.1) - selenium-devtools (0.133.0) + selenium-devtools (0.138.0) selenium-webdriver (~> 4.2) - selenium-webdriver (4.29.1) + selenium-webdriver (4.34.0) base64 (~> 0.2) logger (~> 1.4) rexml (~> 3.2, >= 3.2.5) @@ -63,6 +65,8 @@ PLATFORMS arm64-darwin-21 arm64-darwin-22 arm64-darwin-23 + arm64-darwin-24 + ruby x86_64-darwin-19 x86_64-darwin-20 x86_64-darwin-22 @@ -73,8 +77,8 @@ DEPENDENCIES rspec (~> 3.0) rubocop (~> 1.35) rubocop-rspec (~> 3.0) - selenium-devtools (= 0.133.0) - selenium-webdriver (= 4.29.1) + selenium-devtools (= 0.138.0) + selenium-webdriver (= 4.34.0) BUNDLED WITH 2.5.6 diff --git a/examples/ruby/spec/actions_api/keys_spec.rb b/examples/ruby/spec/actions_api/keys_spec.rb index 62acfb00e650..c6b97e41a4f1 100644 --- a/examples/ruby/spec/actions_api/keys_spec.rb +++ b/examples/ruby/spec/actions_api/keys_spec.rb @@ -56,8 +56,7 @@ expect(text_field.attribute('value')).to eq 'Selenium!' end - it 'copy and paste', except: {browser: :chrome, - reason: 'https://bugs.chromium.org/p/chromedriver/issues/detail?id=4264'} do + it 'copy and paste' do driver.get 'https://www.selenium.dev/selenium/web/single_text_input.html' wait.until { driver.find_element(id: 'textInput').attribute('autofocus') } diff --git a/examples/ruby/spec/bidi/logging_spec.rb b/examples/ruby/spec/bidi/logging_spec.rb index b07b93342628..df010daae8e3 100644 --- a/examples/ruby/spec/bidi/logging_spec.rb +++ b/examples/ruby/spec/bidi/logging_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' RSpec.describe 'Logging' do diff --git a/examples/ruby/spec/browsers/chrome_spec.rb b/examples/ruby/spec/browsers/chrome_spec.rb index c15f4d88a978..85312ea53d6f 100644 --- a/examples/ruby/spec/browsers/chrome_spec.rb +++ b/examples/ruby/spec/browsers/chrome_spec.rb @@ -20,7 +20,11 @@ end it 'sets location of binary' do + user_data_dir = Dir.mktmpdir('chrome-profile-') options = Selenium::WebDriver::Options.chrome + options.add_argument("--user-data-dir=#{user_data_dir}") + options.add_argument('--no-sandbox') + options.add_argument('--disable-dev-shm-usage') options.binary = chrome_location @@ -32,6 +36,7 @@ options = Selenium::WebDriver::Options.chrome options.add_extension(extension_file_path) + options.add_argument('--disable-features=DisableLoadExtensionCommandLineSwitch') @driver = Selenium::WebDriver.for :chrome, options: options @driver.get('https://www.selenium.dev/selenium/web/blank.html') @@ -131,7 +136,8 @@ 'offline' => false, 'latency' => 100, 'download_throughput' => 200, - 'upload_throughput' => 200) + 'upload_throughput' => 200 + ) end it 'gets the browser logs' do diff --git a/examples/ruby/spec/browsers/edge_spec.rb b/examples/ruby/spec/browsers/edge_spec.rb index 225f8c601c40..5820fab3e799 100644 --- a/examples/ruby/spec/browsers/edge_spec.rb +++ b/examples/ruby/spec/browsers/edge_spec.rb @@ -131,7 +131,8 @@ 'offline' => false, 'latency' => 100, 'download_throughput' => 200, - 'upload_throughput' => 200) + 'upload_throughput' => 200 + ) end it 'gets the browser logs' do @@ -164,6 +165,6 @@ def driver_finder def permission(name) @driver.execute_async_script('callback = arguments[arguments.length - 1];' \ - 'callback(navigator.permissions.query({name: arguments[0]}));', name)['state'] + 'callback(navigator.permissions.query({name: arguments[0]}));', name)['state'] end end diff --git a/examples/ruby/spec/browsers/firefox_spec.rb b/examples/ruby/spec/browsers/firefox_spec.rb index 16928c9aa5fc..7a56053e4838 100644 --- a/examples/ruby/spec/browsers/firefox_spec.rb +++ b/examples/ruby/spec/browsers/firefox_spec.rb @@ -89,7 +89,7 @@ describe 'Features' do let(:driver) { start_firefox } - it 'installs addon', :skip => "Skipping tests until Firefox 127 is released" do + it 'installs addon' do extension_file_path = File.expand_path('../spec_support/extensions/webextensions-selenium-example.xpi', __dir__) driver.install_addon(extension_file_path) @@ -99,7 +99,7 @@ expect(injected.text).to eq 'Content injected by webextensions-selenium-example' end - it 'uninstalls addon', :skip => "Skipping tests until Firefox 127 is released" do + it 'uninstalls addon' do extension_file_path = File.expand_path('../spec_support/extensions/webextensions-selenium-example.xpi', __dir__) extension_id = driver.install_addon(extension_file_path) @@ -109,7 +109,7 @@ expect(driver.find_elements(id: 'webextensions-selenium-example')).to be_empty end - it 'installs unsigned addon', :skip => "Skipping tests until Firefox 127 is released" do + it 'installs unsigned addon' do extension_dir_path = File.expand_path('../spec_support/extensions/webextensions-selenium-example/', __dir__) driver.install_addon(extension_dir_path, true) diff --git a/examples/ruby/spec/browsers/safari_spec.rb b/examples/ruby/spec/browsers/safari_spec.rb index a26006070148..64e89ee22926 100644 --- a/examples/ruby/spec/browsers/safari_spec.rb +++ b/examples/ruby/spec/browsers/safari_spec.rb @@ -2,6 +2,7 @@ require 'spec_helper' +# rubocop:disable RSpec/MultipleDescribes RSpec.describe 'Safari', exclusive: {platform: :macosx} do describe 'Options' do it 'basic options' do @@ -33,10 +34,12 @@ end end -RSpec.describe 'Safari Technology Preview', skip: "This test is being skipped as GitHub Actions have no support for Safari Technology Preview" do +RSpec.describe 'Safari Technology Preview', skip: 'This test is being skipped as GitHub Actions ' \ + 'have no support for Safari Technology Preview' do it 'sets the technology preview' do Selenium::WebDriver::Safari.technology_preview! local_driver = Selenium::WebDriver.for :safari expect(local_driver.capabilities.browser_name).to eq 'Safari Technology Preview' end -end \ No newline at end of file +end +# rubocop:enable RSpec/MultipleDescribes diff --git a/examples/ruby/spec/drivers/http_client_spec.rb b/examples/ruby/spec/drivers/http_client_spec.rb index 4a6b05d3b086..b8fdc6e9a675 100644 --- a/examples/ruby/spec/drivers/http_client_spec.rb +++ b/examples/ruby/spec/drivers/http_client_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' RSpec.describe 'HTTP Client' do diff --git a/examples/ruby/spec/drivers/remote_webdriver_spec.rb b/examples/ruby/spec/drivers/remote_webdriver_spec.rb index cc517c421330..d2d05c75c5d5 100644 --- a/examples/ruby/spec/drivers/remote_webdriver_spec.rb +++ b/examples/ruby/spec/drivers/remote_webdriver_spec.rb @@ -7,7 +7,7 @@ let(:target_directory) { File.join(Dir.tmpdir, SecureRandom.uuid) } let(:wait) { Selenium::WebDriver::Wait.new(timeout: 2) } let(:server) do - Selenium::Server.get(:latest, + Selenium::Server.new(File.expand_path(File.join('..', '..', '..', 'selenium-server-4.34.0.jar'), __dir__), background: true, args: %w[--selenium-manager true --enable-managed-downloads true]) end @@ -35,8 +35,8 @@ file_input.send_keys(upload_file) driver.find_element(id: 'file-submit').click - file_name = driver.find_element(id: 'uploaded-files') - expect(file_name.text).to eq 'selenium-snapshot.png' + wait.until { driver.find_element(id: 'uploaded-files') } + expect(driver.find_element(id: 'uploaded-files').text).to eq 'selenium-snapshot.png' end it 'downloads' do diff --git a/examples/ruby/spec/drivers/service_spec.rb b/examples/ruby/spec/drivers/service_spec.rb index c9d45a05a83f..2187a8319e1b 100644 --- a/examples/ruby/spec/drivers/service_spec.rb +++ b/examples/ruby/spec/drivers/service_spec.rb @@ -16,7 +16,11 @@ end it 'specifies driver location' do + user_data_dir = Dir.mktmpdir('chrome-profile-') options = Selenium::WebDriver::Options.chrome(binary: browser_path) + options.add_argument("--user-data-dir=#{user_data_dir}") + options.add_argument('--no-sandbox') + options.add_argument('--disable-dev-shm-usage') service = Selenium::WebDriver::Service.chrome service.executable_path = driver_path diff --git a/examples/ruby/spec/elements/finders_spec.rb b/examples/ruby/spec/elements/finders_spec.rb index f6523ea029fd..5c6aa67dc841 100644 --- a/examples/ruby/spec/elements/finders_spec.rb +++ b/examples/ruby/spec/elements/finders_spec.rb @@ -12,31 +12,31 @@ it 'uses a subset of the dom to find an element' do fruits = driver.find_element(id: 'fruits') - fruit = fruits.find_element(class: 'tomatoes') + fruits.find_element(class: 'tomatoes') end it 'uses an optimized locator' do - fruit = driver.find_element(css: '#fruits .tomatoes') + driver.find_element(css: '#fruits .tomatoes') end it 'finds all matching elements' do - plants = driver.find_elements(tag_name: 'li') + driver.find_elements(tag_name: 'li') end it 'gets an element from a collection' do - elements = driver.find_elements(:tag_name,'p') + elements = driver.find_elements(:tag_name, 'p') elements.each { |e| puts e.text } end it 'finds element from element' do - element = driver.find_element(:tag_name,'div') - elements = element.find_elements(:tag_name,'p') + element = driver.find_element(:tag_name, 'div') + elements = element.find_elements(:tag_name, 'p') elements.each { |e| puts e.text } end it 'find active element' do driver.find_element(css: '[name="q"]').send_keys('webElement') - attr = driver.switch_to.active_element.attribute('title') + driver.switch_to.active_element.attribute('title') end end end diff --git a/examples/ruby/spec/getting_started/using_selenium_spec.rb b/examples/ruby/spec/getting_started/using_selenium_spec.rb index 8e50e32f5f1c..f972389fca0b 100644 --- a/examples/ruby/spec/getting_started/using_selenium_spec.rb +++ b/examples/ruby/spec/getting_started/using_selenium_spec.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true + require 'spec_helper' require 'selenium-webdriver' - RSpec.describe 'Using Selenium' do before do @driver = Selenium::WebDriver.for :chrome diff --git a/examples/ruby/spec/hello/hello_selenium_spec.rb b/examples/ruby/spec/hello/hello_selenium.rb similarity index 79% rename from examples/ruby/spec/hello/hello_selenium_spec.rb rename to examples/ruby/spec/hello/hello_selenium.rb index c8078fe08a64..52b2d69d81f8 100644 --- a/examples/ruby/spec/hello/hello_selenium_spec.rb +++ b/examples/ruby/spec/hello/hello_selenium.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'selenium-webdriver' driver = Selenium::WebDriver.for :chrome diff --git a/examples/ruby/spec/interactions/browser_spec.rb b/examples/ruby/spec/interactions/browser_spec.rb index 8bc281c163aa..f404a6d9eee4 100644 --- a/examples/ruby/spec/interactions/browser_spec.rb +++ b/examples/ruby/spec/interactions/browser_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' RSpec.describe 'Browser' do diff --git a/examples/ruby/spec/interactions/cookies_spec.rb b/examples/ruby/spec/interactions/cookies_spec.rb index fe5b3dfc4235..b679a720ba20 100644 --- a/examples/ruby/spec/interactions/cookies_spec.rb +++ b/examples/ruby/spec/interactions/cookies_spec.rb @@ -4,4 +4,55 @@ RSpec.describe 'Cookies' do let(:driver) { start_session } + + it 'adds a cookie' do + 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') + # Verify cookie was added + expect(driver.manage.cookie_named('key')[:value]).to eq('value') + end + + it 'gets a named cookie' do + 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') + expect(cookie[:value]).to eq('bar') + end + + it 'gets all cookies' do + 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 + # Verify both cookies exist with correct values + test1_cookie = cookies.find { |c| c[:name] == 'test1' } + test2_cookie = cookies.find { |c| c[:name] == 'test2' } + expect(test1_cookie[:value]).to eq('cookie1') + expect(test2_cookie[:value]).to eq('cookie2') + end + + it 'deletes a cookie by name' do + 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') + # Verify cookie is deleted + expect { driver.manage.cookie_named('test1') }.to raise_error(Selenium::WebDriver::Error::NoSuchCookieError) + end + + it 'deletes all cookies' do + 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 + # Verify all cookies are deleted + expect(driver.manage.all_cookies.size).to eq(0) + end end diff --git a/examples/ruby/spec/interactions/frames_spec.rb b/examples/ruby/spec/interactions/frames_spec.rb index d7b27b174044..d8b3b0c3b3dc 100644 --- a/examples/ruby/spec/interactions/frames_spec.rb +++ b/examples/ruby/spec/interactions/frames_spec.rb @@ -1,7 +1,52 @@ +# Licensed to the Software Freedom Conservancy (SFC) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The SFC licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. # frozen_string_literal: true require 'spec_helper' RSpec.describe 'Frames' do let(:driver) { start_session } + + it 'performs iframe switching operations' do + driver.navigate.to 'https://www.selenium.dev/selenium/web/iframes.html' + # --- Switch to iframe using WebElement --- + 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 + + # --- Switch to iframe using name or ID --- + 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 + + # --- Switch to iframe using index --- + driver.switch_to.frame(0) + expect(driver.page_source).to include('We Leave From Here') + # --- Final page content check --- + driver.switch_to.default_content + expect(driver.page_source).to include('This page has iframes') + end end diff --git a/examples/ruby/spec/interactions/navigation_spec.rb b/examples/ruby/spec/interactions/navigation_spec.rb index 36c60e4ace26..badebb5bc0b6 100644 --- a/examples/ruby/spec/interactions/navigation_spec.rb +++ b/examples/ruby/spec/interactions/navigation_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' RSpec.describe 'Browser' do diff --git a/examples/ruby/spec/selenium_manager/usage.rb b/examples/ruby/spec/selenium_manager/usage.rb new file mode 100644 index 000000000000..bff0161ef79f --- /dev/null +++ b/examples/ruby/spec/selenium_manager/usage.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +require 'selenium-webdriver' + +def setup_without_selenium_manager + service = Selenium::WebDriver::Chrome::Service.new(path: '/path/to/chromedriver') + driver = Selenium::WebDriver.for(:chrome, service: service) + driver.get('https://www.selenium.dev/documentation/selenium_manager/') + driver.quit +end + +def setup_with_selenium_manager + driver = Selenium::WebDriver.for(:chrome) # Selenium Manager handles the driver automatically + driver.get('https://www.selenium.dev/documentation/selenium_manager/') + driver.quit +end diff --git a/examples/ruby/spec/spec_helper.rb b/examples/ruby/spec/spec_helper.rb index a79f81232d01..a68a4526f0be 100644 --- a/examples/ruby/spec/spec_helper.rb +++ b/examples/ruby/spec/spec_helper.rb @@ -9,13 +9,15 @@ # Disable RSpec exposing methods globally on `Module` and `main` config.disable_monkey_patching! + Dir.mktmpdir('tmp') + config.example_status_persistence_file_path = 'tmp/examples.txt' config.expect_with :rspec do |c| c.syntax = :expect end config.before do |example| - bug_tracker = 'https://gigithub.com/SeleniumHQ/seleniumhq.github.io/issues' + bug_tracker = 'https://github.com/SeleniumHQ/seleniumhq.github.io/issues' guards = Selenium::WebDriver::Support::Guards.new(example, bug_tracker: bug_tracker) guards.add_condition(:platform, Selenium::WebDriver::Platform.os) @@ -30,6 +32,7 @@ def start_session options = Selenium::WebDriver::Chrome::Options.new options.add_argument('disable-search-engine-choice-screen') + options.add_argument('--no-sandbox') @driver = Selenium::WebDriver.for(:chrome, options: options) end diff --git a/examples/ruby/spec/spec_support/extensions/webextensions-selenium-example.crx b/examples/ruby/spec/spec_support/extensions/webextensions-selenium-example.crx index 38b38003b7ec..941114eb446e 100644 Binary files a/examples/ruby/spec/spec_support/extensions/webextensions-selenium-example.crx and b/examples/ruby/spec/spec_support/extensions/webextensions-selenium-example.crx differ diff --git a/examples/ruby/spec/spec_support/extensions/webextensions-selenium-example/manifest.json b/examples/ruby/spec/spec_support/extensions/webextensions-selenium-example/manifest.json index a8b4fec6e60f..69e480dc60dd 100644 --- a/examples/ruby/spec/spec_support/extensions/webextensions-selenium-example/manifest.json +++ b/examples/ruby/spec/spec_support/extensions/webextensions-selenium-example/manifest.json @@ -14,9 +14,17 @@ ] } ], + "permissions": [ + "storage", + "scripting" + ], + "host_permissions": [ + "https://*/*", + "http://*/*" + ], "browser_specific_settings": { "gecko": { "id": "webextensions-selenium-example-v3@example.com" } } -} \ No newline at end of file +} diff --git a/examples/selenium-server-4.29.0.jar b/examples/selenium-server-4.34.0.jar similarity index 83% rename from examples/selenium-server-4.29.0.jar rename to examples/selenium-server-4.34.0.jar index 92c0d43e7b27..4e5bbd1dfcb4 100644 Binary files a/examples/selenium-server-4.29.0.jar and b/examples/selenium-server-4.34.0.jar differ diff --git a/scripts/release-updates.sh b/scripts/release-updates.sh index 927406e3af79..aa6fd79079e1 100755 --- a/scripts/release-updates.sh +++ b/scripts/release-updates.sh @@ -20,18 +20,19 @@ git add "$NEW_BLOG" sed -i '' "s/4\.$OLD_VERSION/4\.$NEW_VERSION/g" "$NEW_BLOG" +SINCE_COMMIT_DATE=$(gh api repos/seleniumhq/selenium/commits/selenium-4.${OLD_VERSION}.0 --jq '.commit.committer.date') +UNTIL_COMMIT_DATE=$(gh api repos/seleniumhq/selenium/commits/selenium-4.${NEW_VERSION}.0 --jq '.commit.committer.date') + echo "Selenium Contributors" -gh api --method GET /repos/seleniumhq/selenium/commits -f since=selenium-4.${OLD_VERSION}.0 -f per_page=1000 \ +gh api --method GET /repos/seleniumhq/selenium/commits -f since="$SINCE_COMMIT_DATE" -f until="$UNTIL_COMMIT_DATE" -f per_page=1000 \ --jq 'map(.author.login) | unique | sort | map("{{< gh-user \"https://api.github.com/users/" + . + "\" >}}") | .[]' -COMMIT_DATE=$(gh api repos/seleniumhq/selenium/commits/selenium-4.${OLD_VERSION}.0 --jq '.commit.committer.date') - echo echo "Docs Contributors" -gh api --method GET /repos/seleniumhq/seleniumhq.github.io/commits -f since="$COMMIT_DATE" -f per_page=1000 \ +gh api --method GET /repos/seleniumhq/seleniumhq.github.io/commits -f since="$SINCE_COMMIT_DATE" -f until="$UNTIL_COMMIT_DATE" -f per_page=1000 \ --jq 'map(.author.login) | unique | sort | map("{{< gh-user \"https://api.github.com/users/" + . + "\" >}}") | .[]' echo echo "Docker Contributors" -gh api --method GET /repos/seleniumhq/docker-selenium/commits -f since="$COMMIT_DATE" -f per_page=1000 \ +gh api --method GET /repos/seleniumhq/docker-selenium/commits -f since="$SINCE_COMMIT_DATE" -f until="$UNTIL_COMMIT_DATE" -f per_page=1000 \ --jq 'map(.author.login) | unique | sort | map("{{< gh-user \"https://api.github.com/users/" + . + "\" >}}") | .[]' diff --git a/website_and_docs/content/blog/2023/selenium-4-13-0-released.md b/website_and_docs/content/blog/2023/selenium-4-13-0-released.md index 8262674151b7..5b62b37f80f9 100644 --- a/website_and_docs/content/blog/2023/selenium-4-13-0-released.md +++ b/website_and_docs/content/blog/2023/selenium-4-13-0-released.md @@ -73,7 +73,6 @@ Please upgrade to at least Java 11.
-{{< gh-user "https://api.github.com/users/JefferyVin" >}} {{< gh-user "https://api.github.com/users/KrishnaSuravarapu" >}} {{< gh-user "https://api.github.com/users/Sean-Gomez" >}} {{< gh-user "https://api.github.com/users/manuelsblanco" >}} diff --git a/website_and_docs/content/blog/2024/selenium-4-22-released.md b/website_and_docs/content/blog/2024/selenium-4-22-released.md index 10987af8b08e..bcaa36af21a4 100644 --- a/website_and_docs/content/blog/2024/selenium-4-22-released.md +++ b/website_and_docs/content/blog/2024/selenium-4-22-released.md @@ -103,7 +103,6 @@ have rolled out in Ruby, Python and JavaScript {{< gh-user "https://api.github.com/users/alaahong" >}} {{< gh-user "https://api.github.com/users/aguspe" >}} {{< gh-user "https://api.github.com/users/digitalvoice-nz" >}} -{{< gh-user "https://api.github.com/users/josh-pinwheelapi" >}} {{< gh-user "https://api.github.com/users/pallavigitwork" >}} {{< gh-user "https://api.github.com/users/sangcnguyen" >}}
diff --git a/website_and_docs/content/blog/2024/selenium-community-live-episode1.md b/website_and_docs/content/blog/2024/selenium-community-live-episode1.md index 6e0069410d94..093a11ac81d6 100644 --- a/website_and_docs/content/blog/2024/selenium-community-live-episode1.md +++ b/website_and_docs/content/blog/2024/selenium-community-live-episode1.md @@ -4,7 +4,7 @@ linkTitle: "Selenium Community Live - Episode 1" date: 2024-12-25 tags: ["webinar", "meetup", "talks","community"] categories: ["webinar"] -author: Pallavi Sharma +author: Pallavi Sharma images: description: > Selenium Community Live - Episode 1 diff --git a/website_and_docs/content/blog/2024/selenium-milestone-20yrs-blog.md b/website_and_docs/content/blog/2024/selenium-milestone-20yrs-blog.md index f6f524595991..7a17c5ce33a0 100644 --- a/website_and_docs/content/blog/2024/selenium-milestone-20yrs-blog.md +++ b/website_and_docs/content/blog/2024/selenium-milestone-20yrs-blog.md @@ -4,7 +4,7 @@ linkTitle: "Celebrating 20 Years of Selenium" date: 2024-10-18 tags: ["webinar", "meetup", "talks"] categories: ["webinar"] -author: Pallavi Sharma +author: Pallavi Sharma images: - "/images/blog/2024/20-selenium" description: > @@ -40,7 +40,7 @@ This webinar is more than just a celebration—it’s a chance to learn from the Join Us in Celebrating Selenium’s Incredible Journey! For 20 years, Selenium has helped shape how we test, automate, and innovate on the web. This is your opportunity to celebrate that legacy and learn what the future holds for browser automation. We can’t wait to see you there! -Event Organizers - **Maaret**, **Diego**, and **Pallavi**. +Event Organizers - **Maaret**, **Diego**, and **Pallavi**. ## Watch the Recording of Our 20th Anniversary Event diff --git a/website_and_docs/content/blog/2025/lambdatest-selenium-partnership.md b/website_and_docs/content/blog/2025/lambdatest-selenium-partnership.md new file mode 100644 index 000000000000..82cd175c3244 --- /dev/null +++ b/website_and_docs/content/blog/2025/lambdatest-selenium-partnership.md @@ -0,0 +1,66 @@ +--- +title: "LambdaTest Becomes a Selenium Development Partner" +linkTitle: "LambdaTest Becomes a Selenium Development Partner" +date: 2025-04-10 +tags: ["selenium"] +categories: ["general"] +author: Sri Harsha [@harsha509](https://www.linkedin.com/in/sriharsha509/) +images: + - "/images/blog/2025/lambdatest-selenium-development-partner.png" +description: > + The Selenium Project is pleased to welcome LambdaTest as an official Development Partner. +--- + +We are excited to share that [LambdaTest](https://www.lambdatest.com) has joined as a development +partner for Selenium. This partnership highlights our shared commitment +to innovation, community engagement, and collaborative progress in the +test automation space. LambdaTest’s dedicated Open Source Program Office (OSPO) +is contributing valuable expertise and resources that will further enrich the Selenium ecosystem. + +## A Partnership Rooted in Open Source Values + +At the heart of Selenium lies a vibrant community dedicated to open +standards and continuous improvement. Our collaboration with LambdaTest +is designed to strengthen the community by channeling focused contributions +from their OSPO—improving tools, integrations, and documentation for +Selenium users around the world. + +## About LambdaTest + +[LambdaTest](https://www.lambdatest.com) is a platform that empowers businesses to +accelerate time to market through intelligent, cloud-based test authoring, +orchestration, and execution. With over 15,000 customers and 2.3 million+ +users across 130+ countries, LambdaTest is the trusted choice for modern software testing. + +## Key Points of the Partnership + +- **Open Source Integrity:** Selenium continues to flourish as a community-led project, embodying the true spirit of open source. +- **Dedicated OSPO Contributions:** The team at LambdaTest is actively enhancing Selenium by improving documentation, bolstering community support, and enabling better integrations. Their efforts are aimed at empowering the global Selenium user base. +- **Community-Focused Innovation:** By pooling our collective expertise, we are well-positioned to drive new solutions and elevate test automation practices to new heights. + +## What This Partnership Means for the Community + +The contributions from LambdaTest’s OSPO are set to bring +notable benefits to the broader testing landscape: + +- **Faster Development:** The infusion of dedicated engineering resources will accelerate the development of new features and improvements. +- **Improved Stability:** Increased efforts in testing and quality assurance will help quickly identify and resolve issues. +- **Better Documentation:** Enhanced documentation will make it easier for users to dive into Selenium and harness its advanced capabilities. +- **Enhanced Community Support:** LambdaTest will play an active role in organizing and sponsoring community events, fostering rich collaboration and knowledge sharing. + +## Looking Ahead + +This partnership is more than a technical alliance—it reaffirms our +belief in the power of community-led development. The proactive contributions +from LambdaTest’s OSPO will help create a more connected and empowered test +automation community. We invite you to join our upcoming workshops, webinars, +and discussion forums to see firsthand how these collaborative projects will +shape the future of open source test automation. + +Formalizing LambdaTest as a Selenium development partner is a milestone that +celebrates our commitment to innovation and community spirit. With the dedicated +efforts from LambdaTest’s OSPO, we continue our mission to enhance the +Selenium ecosystem for every developer and tester worldwide. + +Join us on this journey toward a future that is more resilient, +supportive, and inventive in the realm of test automation. diff --git a/website_and_docs/content/blog/2025/selenium-4-29-released.md b/website_and_docs/content/blog/2025/selenium-4-29-released.md index 278f97aeb2e0..92a32986dc91 100644 --- a/website_and_docs/content/blog/2025/selenium-4-29-released.md +++ b/website_and_docs/content/blog/2025/selenium-4-29-released.md @@ -62,6 +62,7 @@ Links to everything can be found on our [downloads page][downloads]. - Improved logging stability. ([#15257](https://github.com/SeleniumHQ/selenium/pull/15257)) ### **Docker Selenium** + - Publish Node/Standalone images with the latest Grid core version and browser backward versions - Update container environment to JDK21 ([#2642](https://github.com/SeleniumHQ/docker-selenium/pull/2642)) - Node base with share system certificate support ([#2653](https://github.com/SeleniumHQ/docker-selenium/pull/2653)) @@ -109,7 +110,6 @@ For a detailed look at all changes, check out the [release notes](https://github {{< gh-user "https://api.github.com/users/AndreyJVM" >}} {{< gh-user "https://api.github.com/users/Delta456" >}} {{< gh-user "https://api.github.com/users/alaahong" >}} -{{< gh-user "https://api.github.com/users/automatealchemist" >}} {{< gh-user "https://api.github.com/users/b2m" >}} {{< gh-user "https://api.github.com/users/pallavigitwork" >}}
diff --git a/website_and_docs/content/blog/2025/selenium-4-30-released.md b/website_and_docs/content/blog/2025/selenium-4-30-released.md new file mode 100644 index 000000000000..8c9c41880c27 --- /dev/null +++ b/website_and_docs/content/blog/2025/selenium-4-30-released.md @@ -0,0 +1,197 @@ +--- +title: "Selenium 4.30 Released!" +linkTitle: "Selenium 4.30 Released!" +date: 2025-03-21 +tags: [ "selenium" ] +categories: [ "releases" ] +author: Diego Molina [@diemol](https://www.diemol.com) +images: + - "/images/blog/2025/selenium_4.30.jpg" +description: > + Today we're happy to announce that Selenium 4.30 has been released! +--- + +We're very happy to announce the release of Selenium 4.30 for Javascript, Ruby, Python, .NET, Java +and the Grid! +This version brings key updates across the project, with improvements to the BiDi protocol, +extensive nullability work in .NET, better error handling, and various bug fixes. It’s a great +step forward as we continue strengthening Selenium’s stability, consistency, and support across +all supported languages. + +Links to all assets can be found on our [downloads page][downloads]. + + +--- + +## 🚀 Major Highlights + +- Continued enhancements to **BiDi (Bi-Directional Protocol)** support across Java, Ruby, .NET, JavaScript, and Python. +- Extensive **nullability annotations** added throughout the .NET bindings. +- Selenium Manager (Rust) now supports **nightly Grid builds**. +- Improvements to testing infrastructure and developer experience, including better packaging, linting, and platform support. +- Numerous bug fixes and refactors across the Grid, bindings, and devtools. + +--- + +## 🔹 Language-Specific Changes + +### **Java** + +- Implemented BiDi commands: `getBidiSessionStatus` and `Permissions`. +- Refined logger initialization. +- Removed deprecated, non-W3C compliant `NetworkConnection` interface. +- Added support for setting viewport and handling CDP warnings gracefully. + +### **Python** + +- Improved devtools test handling and documentation. +- Fixed packaging issues and test discovery for `pytest`. +- Added docstring updates for clarity and modernization. +- Replaced strings with `By` class attributes. +- Improved socket resource management and error handling. +- Updated `expected_conditions` type annotations. + +### **JavaScript** + +- Fixed BiDi tests for Chrome and Firefox on CI. +- Implemented BiDi `permissions` module commands. + +### **Ruby** + +- Fixed a compatibility issue with Ruby 3.1 ("no anonymous block parameter"). +- Added BiDi support for: + - Setting viewport + - Activating browser context + - Providing responses +- Added a `target_type` parameter to devtools. + +### **.NET** + +- Enabled **nullable reference types** across many components. +- Trimmed away CDP for **AOT** applications. +- Enhanced BiDi support including: + - `SetFiles` command + - Support for `UnhandledPromptBehavior` + - Event support like `OnNavigationCommitted` + - Encapsulation of the transport layer +- Improved `WebDriver`, `WebElement`, and capabilities types with nullability. +- Introduced `SystemClock` singleton. +- Revisited and fixed test execution on Windows/macOS. +- Removed obsoleted members for 4.30. + +### **Grid & Selenium Manager** + +- Added trace logging for session stop events in Grid. +- Improved configuration options for server timeouts and session handling. +- Added support in Selenium Manager (Rust) for **nightly Grid builds**. +- Enhanced ability to trace and view live sessions. + +### **Docker Selenium** + +- Helm config: Node Relay to extend autoscaling Grid with test cloud resources ([#2703](https://github.com/SeleniumHQ/docker-selenium/pull/2703)). +- Docker: Disable HeapDumpOnOutOfMemoryError by default ([#2708](https://github.com/SeleniumHQ/docker-selenium/pull/2708)) +- [See all changes](https://github.com/SeleniumHQ/docker-selenium/releases) + + +
+ +We thank all our contributors for their incredible efforts in making Selenium better with every +release. ❤️ + +For a detailed look at all changes, check out +the [release notes](https://github.com/SeleniumHQ/selenium/releases/tag/4.30). + +
+ +## Contributors + +**Special shout-out to everyone who helped the Selenium Team get this release out!** + +### [Selenium](https://github.com/SeleniumHQ/selenium) + +
+
+
+{{< gh-user "https://api.github.com/users/Delta456" >}} +{{< gh-user "https://api.github.com/users/FloKNetcare" >}} +{{< gh-user "https://api.github.com/users/ahalbrock" >}} +{{< gh-user "https://api.github.com/users/allrob23" >}} +{{< gh-user "https://api.github.com/users/jpawlyn" >}} +{{< gh-user "https://api.github.com/users/navin772" >}} +{{< gh-user "https://api.github.com/users/smortex" >}} +{{< gh-user "https://api.github.com/users/pallavigitwork" >}} +{{< gh-user "https://api.github.com/users/ahalbrock" >}} +
+
+
+ +### [Selenium Docs & Website](https://github.com/SeleniumHQ/seleniumhq.github.io) + +
+
+
+{{< gh-user "https://api.github.com/users/Delta456" >}} +{{< gh-user "https://api.github.com/users/WasiqB" >}} +{{< gh-user "https://api.github.com/users/alaahong" >}} +{{< gh-user "https://api.github.com/users/beinghumantester" >}} +{{< gh-user "https://api.github.com/users/franciscotrenco" >}} +{{< gh-user "https://api.github.com/users/pallavigitwork" >}} +
+
+
+ +### [Docker Selenium](https://github.com/SeleniumHQ/docker-selenium) + +
+
+
+{{< gh-user "https://api.github.com/users/VietND96" >}} +
+
+
+ +### [Selenium Team Members][team] + +**Thanks as well to all the team members who contributed to this release:** + +
+
+
+{{< gh-user "https://api.github.com/users/aguspe" >}} +{{< gh-user "https://api.github.com/users/AutomatedTester" >}} +{{< gh-user "https://api.github.com/users/bonigarcia" >}} +{{< gh-user "https://api.github.com/users/cgoldberg" >}} +{{< gh-user "https://api.github.com/users/diemol" >}} +{{< gh-user "https://api.github.com/users/harsha509" >}} +{{< gh-user "https://api.github.com/users/joerg1985" >}} +{{< gh-user "https://api.github.com/users/nvborisenko" >}} +{{< gh-user "https://api.github.com/users/p0deje" >}} +{{< gh-user "https://api.github.com/users/pujagani" >}} +{{< gh-user "https://api.github.com/users/RenderMichael" >}} +{{< gh-user "https://api.github.com/users/shbenzer" >}} +{{< gh-user "https://api.github.com/users/shs96c" >}} +{{< gh-user "https://api.github.com/users/titusfortner" >}} +{{< gh-user "https://api.github.com/users/VietND96" >}} +
+
+
+ + + +Stay tuned for updates by following SeleniumHQ on: + +- [Mastodon](https://mastodon.social/@seleniumHQ@fosstodon.org) +- [BlueSky](https://bsky.app/profile/seleniumconf.bsky.social) +- [LinkedIn](https://www.linkedin.com/company/selenium/) +- [Selenium Community YouTube Channel](https://www.youtube.com/@SeleniumHQProject/streams) +- [X (Formerly Twitter)](https://twitter.com/seleniumhq) + +Happy automating! + +[downloads]: /downloads + +[bindings]: /downloads#bindings + +[team]: /project/structure + +[BiDi]: https://github.com/w3c/webdriver-bidi diff --git a/website_and_docs/content/blog/2025/selenium-4-31-released.md b/website_and_docs/content/blog/2025/selenium-4-31-released.md new file mode 100644 index 000000000000..c4c1fa14db18 --- /dev/null +++ b/website_and_docs/content/blog/2025/selenium-4-31-released.md @@ -0,0 +1,175 @@ +--- +title: "Selenium 4.31 Released!" +linkTitle: "Selenium 4.31 Released!" +date: 2025-04-05 +tags: [ "selenium" ] +categories: [ "releases" ] +author: Diego Molina [@diemol](https://www.diemol.com) +images: + - "/images/blog/2025/selenium_4.31.jpg" +description: > + Today we're happy to announce that Selenium 4.31 has been released! +--- + +We’re excited to announce the release of **Selenium 4.31** for Javascript, Ruby, Python, .NET, Java +and the Grid! 🎉 +This release focuses on improvements across the board, including better BiDi protocol support, test +reliability, nullability enhancements, and cleanup of legacy code across languages. + +Links to all assets can be found on our [downloads page][downloads]. + + +--- + +## 🚀 Major Highlights + +- Continued work towards full BiDi support in all bindings +- Cleanup of unused legacy components (like `wgxpath`) +- Expanded test coverage and fixes for various environments (CI, RBE, MacOS) +- Improvements in documentation and development tooling + +--- + +## 🔹 Language-Specific Changes + +### **Java** + +- [Handle `getNamedCookie` and `deleteNamedCookie` for empty strings](https://github.com/SeleniumHQ/selenium/pull/15092) +- [Add nullness for AppCacheStatus, Credential, and Either](https://github.com/SeleniumHQ/selenium/pull/15119) +- [Add nullness for interactions](https://github.com/SeleniumHQ/selenium/pull/15118) +- [Enable Safari for CookieImplementationTest](https://github.com/SeleniumHQ/selenium/pull/15544) +- [Add test to add a cookie in a user context (BiDi)](https://github.com/SeleniumHQ/selenium/pull/15312) + +### **Python** + +- [Fix docstring issues that sphinx complains about](https://github.com/SeleniumHQ/selenium/pull/15466) +- [Only shutdown service if process not already terminated](https://github.com/SeleniumHQ/selenium/pull/15183) +- [Remove unused mocker arg in chrome options test](https://github.com/SeleniumHQ/selenium/pull/15540) +- [Fix driver class name in test fixtures](https://github.com/SeleniumHQ/selenium/pull/15550) + +### **JavaScript** + +- Fixed BiDi tests for Chrome and Firefox on CI. +- Implemented BiDi `permissions` module commands. + +### **Ruby** + +- [Fix BiDi test errors](https://github.com/SeleniumHQ/selenium/pull/15482) +- [Allow symbols again to be passed on `delete_cookie`](https://github.com/SeleniumHQ/selenium/pull/15519) + +### **.NET** + +- [Decouple nested BiDi types across multiple modules](https://github.com/SeleniumHQ/selenium/pulls?q=is%3Apr+author%3Anvborisenko+label%3Adotnet) +- [Fix null warnings in `RelativeBy` by sealing the type](https://github.com/SeleniumHQ/selenium/pull/15379) +- [Simplify conversion to `LocalValue`](https://github.com/SeleniumHQ/selenium/pull/15441) +- [Unify protected and internal Execute methods](https://github.com/SeleniumHQ/selenium/pull/15233) +- [Make `ContinueWithAuthCommand` closer to spec (breaking change)](https://github.com/SeleniumHQ/selenium/pull/15545) +- [Avoid intermediate JsonDocument allocation to improve performance](https://github.com/SeleniumHQ/selenium/pull/15555) + +### **Grid** + +- [Expose register status via Node status response](https://github.com/SeleniumHQ/selenium/pull/15448) +- [Add traces for event stop session in Node](https://github.com/SeleniumHQ/selenium/pull/15348) + +### **Docker Selenium** + +- Helm config: Add template for file browser video records service ([#2763](https://github.com/SeleniumHQ/docker-selenium/pull/2763)) +- Helm config: Strictly handle `basicAuth.enabled` in template ([#2760](https://github.com/SeleniumHQ/docker-selenium/pull/2760)) +- Selenium Grid Autoscaling in Kubernetes is expected working well with KEDA core v2.17.0. +- [See all changes](https://github.com/SeleniumHQ/docker-selenium/releases) + + +
+ +We thank all our contributors for their incredible efforts in making Selenium better with every +release. ❤️ + +For a detailed look at all changes, check out +the [release notes](https://github.com/SeleniumHQ/selenium/releases/tag/4.31). + +
+ +## Contributors + +**Special shout-out to everyone who helped the Selenium Team get this release out!** + +### [Selenium](https://github.com/SeleniumHQ/selenium) + +
+
+
+{{< gh-user "https://api.github.com/users/Delta456" >}} +{{< gh-user "https://api.github.com/users/PSandro" >}} +{{< gh-user "https://api.github.com/users/mk868" >}} +{{< gh-user "https://api.github.com/users/navin772" >}} +
+
+
+ +### [Selenium Docs & Website](https://github.com/SeleniumHQ/seleniumhq.github.io) + +
+
+
+{{< gh-user "https://api.github.com/users/alaahong" >}} +{{< gh-user "https://api.github.com/users/pallavigitwork" >}} +
+
+
+ +### [Docker Selenium](https://github.com/SeleniumHQ/docker-selenium) + +
+
+
+{{< gh-user "https://api.github.com/users/KenHuPricer" >}} +{{< gh-user "https://api.github.com/users/KyriosGN0" >}} +
+
+
+ +### [Selenium Team Members][team] + +**Thanks as well to all the team members who contributed to this release:** + +
+
+
+{{< gh-user "https://api.github.com/users/aguspe" >}} +{{< gh-user "https://api.github.com/users/AutomatedTester" >}} +{{< gh-user "https://api.github.com/users/bonigarcia" >}} +{{< gh-user "https://api.github.com/users/cgoldberg" >}} +{{< gh-user "https://api.github.com/users/diemol" >}} +{{< gh-user "https://api.github.com/users/harsha509" >}} +{{< gh-user "https://api.github.com/users/joerg1985" >}} +{{< gh-user "https://api.github.com/users/nvborisenko" >}} +{{< gh-user "https://api.github.com/users/p0deje" >}} +{{< gh-user "https://api.github.com/users/pujagani" >}} +{{< gh-user "https://api.github.com/users/RenderMichael" >}} +{{< gh-user "https://api.github.com/users/shbenzer" >}} +{{< gh-user "https://api.github.com/users/shs96c" >}} +{{< gh-user "https://api.github.com/users/titusfortner" >}} +{{< gh-user "https://api.github.com/users/VietND96" >}} +
+
+
+ + + +Stay tuned for updates by following SeleniumHQ on: + +- [Mastodon](https://mastodon.social/@seleniumHQ@fosstodon.org) +- [BlueSky](https://bsky.app/profile/seleniumconf.bsky.social) +- [LinkedIn](https://www.linkedin.com/company/selenium/) +- [Selenium Community YouTube Channel](https://www.youtube.com/@SeleniumHQProject/streams) +- [X (Formerly Twitter)](https://twitter.com/seleniumhq) + +Happy automating! + +[downloads]: /downloads + +[bindings]: /downloads#bindings + +[team]: /project/structure + +[BiDi]: https://github.com/w3c/webdriver-bidi diff --git a/website_and_docs/content/blog/2025/selenium-4-32-released.md b/website_and_docs/content/blog/2025/selenium-4-32-released.md new file mode 100644 index 000000000000..a02c31e01cad --- /dev/null +++ b/website_and_docs/content/blog/2025/selenium-4-32-released.md @@ -0,0 +1,180 @@ +--- +title: "Selenium 4.32 Released!" +linkTitle: "Selenium 4.32 Released!" +date: 2025-05-05 +tags: [ "selenium" ] +categories: [ "releases" ] +author: Diego Molina [@diemol](https://www.diemol.com) +images: + - "/images/blog/2025/selenium_4.32.jpg" +description: > + Today we're happy to announce that Selenium 4.32 has been released! +--- + +We’re excited to announce the release of **Selenium 4.32** for Javascript, Ruby, Python, .NET, Java +and the Grid! 🎉 +This release continues the focus on strengthening BiDi support across multiple bindings, improving +stability in tests, and refining documentation and developer experience. + +Links to all assets can be found on our [downloads page][downloads]. + + +--- + +## 🚀 Major Highlights + +- Enhanced **BiDi (Bi-Directional)** protocol support for Python, Java, Ruby, and .NET bindings +- Dozens of **bug fixes and stability improvements** in tests and documentation +- Selenium Grid now better handles **capabilities for mobile testing with Relay Nodes** +- New utility class in Python to manage a local Grid server +- Additional updates to support AOT compatibility and memory optimizations in .NET + +--- + +## 🔹 Language-Specific Changes + +### **Java** + +- BiDi improvements: `onNavigationCommitted`, `getClientWindows`, and Edge support [#15560](https://github.com/SeleniumHQ/selenium/pull/15560), [#15661](https://github.com/SeleniumHQ/selenium/pull/15661) +- BiDi tests enabled for Edge network module [#15654](https://github.com/SeleniumHQ/selenium/pull/15654) +- Set BiDi as active protocol for Remote Firefox [#15224](https://github.com/SeleniumHQ/selenium/pull/15224) +- Dependency versioning improvements via BOM [#15689](https://github.com/SeleniumHQ/selenium/pull/15689) + +### **Python** + +- Fixes to test args for `--headless` and `--bidi` [#15567](https://github.com/SeleniumHQ/selenium/pull/15567) +- Improvements in test coverage and cleanup [#15579](https://github.com/SeleniumHQ/selenium/pull/15579), [#15580](https://github.com/SeleniumHQ/selenium/pull/15580) +- FedCM state leak fix [#15583](https://github.com/SeleniumHQ/selenium/pull/15583) +- BiDi Network: intercepts and authentication implemented [#14592](https://github.com/SeleniumHQ/selenium/pull/14592) +- Implemented BiDi `browser`, `browsing_context`, and `log` modules [#15616](https://github.com/SeleniumHQ/selenium/pull/15616), [#15631](https://github.com/SeleniumHQ/selenium/pull/15631), [#15668](https://github.com/SeleniumHQ/selenium/pull/15668) +- Added `Server` utility class to manage Grid [#15666](https://github.com/SeleniumHQ/selenium/pull/15666) +- Modernized linting setup and doc publishing [#15614](https://github.com/SeleniumHQ/selenium/pull/15614) + +### **JavaScript** + +- [Set remote active protocol in Firefox to BiDi only](https://github.com/SeleniumHQ/selenium/commit/a1ff120a9fd69daeea6a51d41aee6beb83748895) + +### **Ruby** + +- Added `PrintOptions` support [#15158](https://github.com/SeleniumHQ/selenium/pull/15158) +- WebSocket port handling for Firefox [#15458](https://github.com/SeleniumHQ/selenium/pull/15458) +- BiDi `setViewport`, `activate`, and log support enhanced [#15290](https://github.com/SeleniumHQ/selenium/pull/15290), [#15365](https://github.com/SeleniumHQ/selenium/pull/15365) + + +### **.NET** + +- Extensive BiDi refactoring for better spec alignment and AOT compatibility [#15575](https://github.com/SeleniumHQ/selenium/pull/15575), [#15591](https://github.com/SeleniumHQ/selenium/pull/15591) +- Introduced strong typing for LocalValue conversions [#15532](https://github.com/SeleniumHQ/selenium/pull/15532) +- Refined network interception and error handling [#15603](https://github.com/SeleniumHQ/selenium/pull/15603), [#15521](https://github.com/SeleniumHQ/selenium/pull/15521) +- Websocket memory and platform detection improvements [#15640](https://github.com/SeleniumHQ/selenium/pull/15640), [#15649](https://github.com/SeleniumHQ/selenium/pull/15649) + +### **Grid** + +- Fixed Safari-specific capability prefix handling [#15574](https://github.com/SeleniumHQ/selenium/pull/15574) +- Improved handling of `browserName` for Relay Nodes in mobile [#15537](https://github.com/SeleniumHQ/selenium/pull/15537) + +### **Docker Selenium** + +- Docker: Init python venv with non-root user ([#2769](https://github.com/SeleniumHQ/docker-selenium/pull/2769)) +- Docker: Remove Hub GraphQL dependency from video recorder ([#2813](https://github.com/SeleniumHQ/docker-selenium/pull/2813)) +- Docker: Fluxbox not rendering Chinese characters via VNC view ([#2817](https://github.com/SeleniumHQ/docker-selenium/pull/2817)) +- [See all changes](https://github.com/SeleniumHQ/docker-selenium/releases) + + +
+ +We thank all our contributors for their incredible efforts in making Selenium better with every +release. ❤️ + +For a detailed look at all changes, check out +the [release notes](https://github.com/SeleniumHQ/selenium/releases/tag/4.32). + +
+ +## Contributors + +**Special shout-out to everyone who helped the Selenium Team get this release out!** + +### [Selenium](https://github.com/SeleniumHQ/selenium) + +
+
+
+{{< gh-user "https://api.github.com/users/Delta456" >}} +{{< gh-user "https://api.github.com/users/FFederi" >}} +{{< gh-user "https://api.github.com/users/navin772" >}} +{{< gh-user "https://api.github.com/users/yvsvarma" >}} +
+
+
+ +### [Selenium Docs & Website](https://github.com/SeleniumHQ/seleniumhq.github.io) + +
+
+
+{{< gh-user "https://api.github.com/users/HandyCC" >}} +{{< gh-user "https://api.github.com/users/Ozoniuss" >}} +{{< gh-user "https://api.github.com/users/alaahong" >}} +{{< gh-user "https://api.github.com/users/manoj9788" >}} +{{< gh-user "https://api.github.com/users/pallavigitwork" >}} +
+
+
+ +### [Docker Selenium](https://github.com/SeleniumHQ/docker-selenium) + +
+
+
+{{< gh-user "https://api.github.com/users/Trigtrig" >}} +{{< gh-user "https://api.github.com/users/lermit" >}} +
+
+
+ +### [Selenium Team Members][team] + +**Thanks as well to all the team members who contributed to this release:** + +
+
+
+{{< gh-user "https://api.github.com/users/aguspe" >}} +{{< gh-user "https://api.github.com/users/AutomatedTester" >}} +{{< gh-user "https://api.github.com/users/bonigarcia" >}} +{{< gh-user "https://api.github.com/users/cgoldberg" >}} +{{< gh-user "https://api.github.com/users/diemol" >}} +{{< gh-user "https://api.github.com/users/harsha509" >}} +{{< gh-user "https://api.github.com/users/joerg1985" >}} +{{< gh-user "https://api.github.com/users/nvborisenko" >}} +{{< gh-user "https://api.github.com/users/p0deje" >}} +{{< gh-user "https://api.github.com/users/pujagani" >}} +{{< gh-user "https://api.github.com/users/RenderMichael" >}} +{{< gh-user "https://api.github.com/users/shbenzer" >}} +{{< gh-user "https://api.github.com/users/shs96c" >}} +{{< gh-user "https://api.github.com/users/titusfortner" >}} +{{< gh-user "https://api.github.com/users/VietND96" >}} +
+
+
+ + + +Stay tuned for updates by following SeleniumHQ on: + +- [Mastodon](https://mastodon.social/@seleniumHQ@fosstodon.org) +- [BlueSky](https://bsky.app/profile/seleniumconf.bsky.social) +- [LinkedIn](https://www.linkedin.com/company/selenium/) +- [Selenium Community YouTube Channel](https://www.youtube.com/@SeleniumHQProject/streams) +- [X (Formerly Twitter)](https://twitter.com/seleniumhq) + +Happy automating! + +[downloads]: /downloads + +[bindings]: /downloads#bindings + +[team]: /project/structure + +[BiDi]: https://github.com/w3c/webdriver-bidi diff --git a/website_and_docs/content/blog/2025/selenium-4-33-released.md b/website_and_docs/content/blog/2025/selenium-4-33-released.md new file mode 100644 index 000000000000..d5f022ff40d1 --- /dev/null +++ b/website_and_docs/content/blog/2025/selenium-4-33-released.md @@ -0,0 +1,178 @@ +--- +title: "Selenium 4.33 Released!" +linkTitle: "Selenium 4.33 Released!" +date: 2025-05-25 +tags: [ "selenium" ] +categories: [ "releases" ] +author: Diego Molina [@diemol](https://www.diemol.com) +images: + - "/images/blog/2025/selenium_4.33.jpg" +description: > + Today we're happy to announce that Selenium 4.33 has been released! +--- + +We’re excited to announce the release of **Selenium 4.33** for Javascript, Ruby, Python, .NET, Java +and the Grid! 🎉 + +This release contains improvements, cleanups, and new features across all language bindings and the +Grid. This release continues our effort to modernize the codebase, improve developer experience, and +refine the project’s tooling and documentation. + +Links to all assets can be found on our [downloads page][downloads]. + + +--- + +## 🚀 Highlights + +- [9f3c923670](https://github.com/SeleniumHQ/selenium/commit/9f3c92367005f19fad2bc79c171e7250cce43da3) - Grid UI now includes live previews for each Node. +- [43e6bb970e](https://github.com/SeleniumHQ/selenium/commit/43e6bb970e65ec62692d6bf49962ea81e1103e78) - Python BiDi support expands with the new webExtension module. +- [ef05c15798](https://github.com/SeleniumHQ/selenium/commit/ef05c15798b22a3ade4bb1f111d3e1955988e267) - Java: Reverted deprecation notice for `getAttribute` after community feedback. +- [638621f4bc](https://github.com/SeleniumHQ/selenium/commit/638621f4bc3c632c5955fb4d056fd2f01b6cf835) - Java: Clean-up of deprecated timeout configuration methods. + +## 🔍 Changes by Component + +### Grid + +- [9f3c923670](https://github.com/SeleniumHQ/selenium/commit/9f3c92367005f19fad2bc79c171e7250cce43da3) - UI Overview is able to see live preview per Node +- [7401a3db93](https://github.com/SeleniumHQ/selenium/commit/7401a3db93a7b6cca6f4697c5d032196b2e7f661) - UI Sessions capability fields to display as additional columns + +### Python + +- [92db47fa2a](https://github.com/SeleniumHQ/selenium/commit/92db47fa2ad6b4f8baa70446b7c18e6c17966306) - Add missing modules to python API docs +- [4fc2582bf9](https://github.com/SeleniumHQ/selenium/commit/4fc2582bf96ecc2d0d0f4552c0c200a1d4e1e303) - Better error for downloads on local webdrivers +- [43e6bb970e](https://github.com/SeleniumHQ/selenium/commit/43e6bb970e65ec62692d6bf49962ea81e1103e78) - Add bidi webExtension module (#15749) + +### Rust + +- [7497552255](https://github.com/SeleniumHQ/selenium/commit/7497552255a2bef5a1d9883d7620de2e41c6b553) - Replace WMIC commands (deprecated) by WinAPI in Windows + +### Java + +- [ef05c15798](https://github.com/SeleniumHQ/selenium/commit/ef05c15798b22a3ade4bb1f111d3e1955988e267) - Reverting deprecation notice for `getAttribute`. +- [638621f4bc](https://github.com/SeleniumHQ/selenium/commit/638621f4bc3c632c5955fb4d056fd2f01b6cf835) - Removing deprecated `setScriptTimeout` and `pageLoadTimeout`. +- [fcf4c9d09e](https://github.com/SeleniumHQ/selenium/commit/fcf4c9d09ecd41223d185a0d9922f14f37f9d4f6) - Removing deprecated SlowLoadableComponent constructor. +- [1e65b7b49f](https://github.com/SeleniumHQ/selenium/commit/1e65b7b49f4c22e842b3620d9c5841961dfccc5e) - Removing deprecated NATIVE_EVENTS field. +- [f3f0cadedb](https://github.com/SeleniumHQ/selenium/commit/f3f0cadedbaef98cc224dc7c84f4d8720d115565) - Deprecating methods that use FirefoxBinary as well. + +### Ruby + +- [212fc8be35](https://github.com/SeleniumHQ/selenium/commit/212fc8be3566e333ee3823e153b770162c3902b8) - Upgrade to Ruby 3.2. +- [1e2945de78](https://github.com/SeleniumHQ/selenium/commit/1e2945de78c8005d96bad66af43a02b46bde3d20) - Let firefox choose the bidi port by default. + +### .NET + +- [212fc8be35](https://github.com/SeleniumHQ/selenium/commit/212fc8be3566e333ee3823e153b770162c3902b8) - Upgrade to Ruby 3.2. +- [1e2945de78](https://github.com/SeleniumHQ/selenium/commit/1e2945de78c8005d96bad66af43a02b46bde3d20) - Let firefox choose the bidi port by default. + +### JavaScript + +- [3ef1c25fe8](https://github.com/SeleniumHQ/selenium/commit/3ef1c25fe8eef39b195550f7b5bf76d38f4f42ca) - Chrome capabilities test passes now in RBE. + + +### Docker Selenium + +- K8s: Fix Helm chart template for deployment of video recording manager ([#2828](https://github.com/SeleniumHQ/docker-selenium/pull/2828), [#2831](https://github.com/SeleniumHQ/docker-selenium/pull/2831)). +- K8s: Node enable readiness probe checks status registered to Hub ([#2833](https://github.com/SeleniumHQ/docker-selenium/pull/2833)). +- K8s: Video recorder run as sidecar container is disabled by default ([#2843](https://github.com/SeleniumHQ/docker-selenium/pull/2843)). +- K8s: Fix chart template issue that might occur when using Helm version v3.18.0 ([365c106](https://github.com/SeleniumHQ/docker-selenium/commit/365c10659905e6ad5e7e972fcb54225dc2a8c928)). +- K8s: Update chart dependencies (KEDA core 2.17,1, and so on). +- [See all changes](https://github.com/SeleniumHQ/docker-selenium/releases) + + +
+ +We thank all our contributors for their incredible efforts in making Selenium better with every +release. ❤️ + +For a detailed look at all changes, check out +the [release notes](https://github.com/SeleniumHQ/selenium/releases/tag/selenium-4.33.0). + +
+ +## Contributors + +**Special shout-out to everyone who helped the Selenium Team get this release out!** + +### [Selenium](https://github.com/SeleniumHQ/selenium) + +
+
+
+{{< gh-user "https://api.github.com/users/DeflateAwning" >}} +{{< gh-user "https://api.github.com/users/Delta456" >}} +{{< gh-user "https://api.github.com/users/bandophahita" >}} +{{< gh-user "https://api.github.com/users/navin772" >}} +{{< gh-user "https://api.github.com/users/t7ru" >}} +{{< gh-user "https://api.github.com/users/tomhughes" >}} +
+
+
+ +### [Selenium Docs & Website](https://github.com/SeleniumHQ/seleniumhq.github.io) + +
+
+
+{{< gh-user "https://api.github.com/users/PeteSong" >}} +{{< gh-user "https://api.github.com/users/alaahong" >}} +{{< gh-user "https://api.github.com/users/pallavigitwork" >}} +
+
+
+ +### [Docker Selenium](https://github.com/SeleniumHQ/docker-selenium) + +
+
+
+{{< gh-user "https://api.github.com/users/alcpereira" >}} +
+
+
+ +### [Selenium Team Members][team] + +**Thanks as well to all the team members who contributed to this release:** + +
+
+
+{{< gh-user "https://api.github.com/users/aguspe" >}} +{{< gh-user "https://api.github.com/users/AutomatedTester" >}} +{{< gh-user "https://api.github.com/users/bonigarcia" >}} +{{< gh-user "https://api.github.com/users/cgoldberg" >}} +{{< gh-user "https://api.github.com/users/diemol" >}} +{{< gh-user "https://api.github.com/users/harsha509" >}} +{{< gh-user "https://api.github.com/users/joerg1985" >}} +{{< gh-user "https://api.github.com/users/nvborisenko" >}} +{{< gh-user "https://api.github.com/users/p0deje" >}} +{{< gh-user "https://api.github.com/users/pujagani" >}} +{{< gh-user "https://api.github.com/users/RenderMichael" >}} +{{< gh-user "https://api.github.com/users/shbenzer" >}} +{{< gh-user "https://api.github.com/users/shs96c" >}} +{{< gh-user "https://api.github.com/users/titusfortner" >}} +{{< gh-user "https://api.github.com/users/VietND96" >}} +
+
+
+ + + +Stay tuned for updates by following SeleniumHQ on: + +- [Mastodon](https://mastodon.social/@seleniumHQ@fosstodon.org) +- [BlueSky](https://bsky.app/profile/seleniumconf.bsky.social) +- [LinkedIn](https://www.linkedin.com/company/selenium/) +- [Selenium Community YouTube Channel](https://www.youtube.com/@SeleniumHQProject/streams) +- [X (Formerly Twitter)](https://twitter.com/seleniumhq) + +Happy automating! + +[downloads]: /downloads + +[bindings]: /downloads#bindings + +[team]: /project/structure + +[BiDi]: https://github.com/w3c/webdriver-bidi diff --git a/website_and_docs/content/blog/2025/selenium-appium-conference-2025.md b/website_and_docs/content/blog/2025/selenium-appium-conference-2025.md new file mode 100644 index 000000000000..6edaaba66946 --- /dev/null +++ b/website_and_docs/content/blog/2025/selenium-appium-conference-2025.md @@ -0,0 +1,39 @@ +--- +title: "Selenium Conference and Appium Conference 2025, Valencia Spain" +linkTitle: "Selenium Conference Appium Conference 2025 Valencia Spain" +date: 2025-04-21 +tags: ["conference", "selenium","appium", "web driver ecosystem", "valencia", "spain"] +categories: ["conference"] +author: Pallavi Sharma +images: +description: > + Selenium Conference and Appium Conference 2025, Valencia Spain +--- + +Selenium and Appium projects joined hands together for the 2025 annual conference of both, which was held from March 26th - March 28th in Valencia, Spain. The official web page of the conference can be found **here** + +The event took place at the beautiful venue of **Veles e Vents**. + +On March 26th, there were **Workshops**, which were enthusiastically attended by participants from across the globe. On the 26th March evening, the conference organised Speaker's Dinner, which provided a fun space to sit, talk and know other better. + +We are thankful to our esteemed speaker group, who joined us from all over the world and helped make the event a success. Details about the speakers for the event is available here - **Speakers of the Conference** + +The main event started from 27th of March and ran through 28th March evening. The event was attended by close to 400 global participants. We are thankful to each of them, for their presence which made the event worthwhile. + +Conference also provided scholarship to 4 people who were chosen after a tough selection process to attend the conference. We thank all our **Sponsors** who collaborated and helped make the event possible. + +The video recording, presentations and photographs from the main event can be found here - **Videos, Photos and More..** + +Conference, also ran Pre Conference webinars which helped showcase high rated talks which couldn't make it to the end program to the audience. The details of the same are available here - **Pre Conference Webinars** + +The conference program chair was **Diego Molina**. Diego helmed all the activities of the conference with great leadership and meticulous supervision. + +The conference was supported by a wide group of professionals who participated in volunteer capacity as reviewers and organizers of the event. +More details about them can be found here - **Organizers & Program Review Committee **. + +The entire event was professionally managed by the event organiser company **OneStic**. They ensured smooth flow of the event. Special mention to **Jesus Sanchez** for going out of the way to ensure everyone was well taken care of. + + +## Subscribe to Official Selenium Conference YouTube Channel +To explore more about our previous conferences and the next ones don't forget to subscribe to our official You Tube Channel **Selenium Conference Official YouTube Channel.** + diff --git a/website_and_docs/content/blog/2025/selenium-community-live-episode2.md b/website_and_docs/content/blog/2025/selenium-community-live-episode2.md index 773345c2e834..11fb566e2871 100644 --- a/website_and_docs/content/blog/2025/selenium-community-live-episode2.md +++ b/website_and_docs/content/blog/2025/selenium-community-live-episode2.md @@ -4,13 +4,13 @@ linkTitle: "Selenium Community Live - Episode 2" date: 2025-01-21 tags: ["webinar", "meetup", "talks","community"] categories: ["webinar"] -author: Pallavi Sharma +author: Pallavi Sharma images: description: > Selenium Community Live - Episode 2 --- -The second episode of Selenium Community Live happened on Jan 21st, 2025, with speaker **David Burns**, event hosted by **Pallavi Sharma** +The second episode of Selenium Community Live happened on Jan 21st, 2025, with speaker **David Burns**, event hosted by **Pallavi Sharma** You can watch the episode here- **Selenium Community Live - Episode 2** diff --git a/website_and_docs/content/blog/2025/selenium-community-live-episode4.md b/website_and_docs/content/blog/2025/selenium-community-live-episode4.md new file mode 100644 index 000000000000..9a5cb4bb6c3e --- /dev/null +++ b/website_and_docs/content/blog/2025/selenium-community-live-episode4.md @@ -0,0 +1,40 @@ +--- +title: "Selenium Community Live - Episode 4" +linkTitle: "Selenium Community Live - Episode 4" +date: 2025-03-19 +tags: ["webinar", "meetup", "talks","community"] +categories: ["webinar"] +author: Pallavi Sharma +images: +description: > + Selenium Community Live - Episode 4 +--- + +The fourth episode of Selenium Community Live happened on March 19th, 2025, with speaker **Michael Mintz**, event hosted by **Pallavi Sharma** + +You can watch the episode on YouTube here- **Episode 4 on YouTube** +or +You can watch the episode on LinkedIn here- **Episode 4 on LinkedIn** + +**Selenium Community Live - Episode 4** + +Michael Mintz is creator of Selenium Base, an all in one Browser Automation Framework, built over Selenium WebDriver Python bindings. The framework is well known and used +in the WebDriver Ecosystem community for testing, web scraping, web crawling and stealth purposes. +You can find out more about Selenium Base here - **Selenium Base** + + +**Meet the Speakers:** + +1. **Michael Mintz** + + +## Watch the Recording + +Couldn’t join us live? Watch the entire episode here - +📹 Recording Link: [Watch the Event Recording on YouTube](https://youtube.com/live/FSH712hhHvo?feature=share) + +To know more about Selenium Base, please follow the link +**Explore more on Selenium Base** + +In case you were wondering what happened to episode 3, it was cancelled but will be scheduled in coming weeks. Thank you! +Stay tuned as we bring the next! **Subscribe here to the Selenium HQ Official YouTube Channel.** diff --git a/website_and_docs/content/blog/2025/selenium-community-live-episode5.md b/website_and_docs/content/blog/2025/selenium-community-live-episode5.md new file mode 100644 index 000000000000..76aeb320a2ee --- /dev/null +++ b/website_and_docs/content/blog/2025/selenium-community-live-episode5.md @@ -0,0 +1,97 @@ +--- +title: "Selenium Community Live - Episode 5" +linkTitle: "Selenium Community Live - Episode 5" +date: 2025-05-05 +tags: ["webinar", "meetup", "talks","community"] +categories: ["webinar"] +author: Puja Jagani +images: +description: > + Selenium Community Live - Episode 5 +--- + +The fifth episode of Selenium Community Live happened on April 25th 2025. + +The event featured speakers **Ashley Hunsberger **, Director at NBCUniversal with close to 25 years of industry experience and a long-time friend of the Selenium, alongside **Puja Jagani**, Open Source Engineer & Developer Advocate at BrowserStack and member of the Selenium leadership(TLC and PLC). The event was hosted by +**Pallavi Sharma**, Founder 5 Elements Learning and a long-time Selenium Committer. + +The theme of the community event was "Beyond Code: Understanding Developer Satisfaction in Open Source Contributions". + +While many discussions around open source have happened that focus on code contributions and technical aspects, there is a vital human element involved, something that keeps the contributions rolling for decades, i.e. developer satisfaction. This community event was dedicated to discussing the human factor in open source contributions. The speakers shared their insights and experience on developer satisfaction in open source. + +### What motivates Open Source contributors? + +Ashley’s LinkedIn states that "My driving principle is simple: people first" and building on that, Ashley and Puja both highlight that open source is "by the community, for the community," where collaboration and human connections are foundational motivating factors for them. + +Ashley shares her journey with Selenium, highlighting how the warm, caring community has helped her build genuine friendships and good memories. + +"In the end, do people really remember what we build? They're going to remember how we made them feel." - Ashley Hunsberger + +She states that for her, a main motivational factor is community, and what she thinks drives people is the altruistic purpose of giving back to the community beyond their organisation and serving a great purpose. According to her, motivation drives behaviour, and if you have clear motivation, that will drive your place in the community in the long run. + +Beyond altruism, Puja thinks there is a diversity of motivators, emphasising that contributions extend far beyond code. Contributions might include: +- Helping with documentation +- Managing continuous integration (CI) pipelines +- Handling legal, and financial aspects, and other administrative aspects +- Organising conferences, community events, and meetups. + +These roles are often in the spotlight but critical to the health and growth of open source projects. A huge spectrum of motivators drives people’s behaviour and keeps the open source project breathing and growing. + +### No single factor that contributes to developer satisfaction + +Ashley brings a unique perspective to the idea that developer satisfaction can be understood through the lens of the Job Characteristics Model. This model outlines key aspects of work that lead to positive outcomes such as retention, motivation, and job satisfaction. + +Key factors include: +- Skill Variety: Open source contributors engage in a wide range of skills, from coding to release engineering, documentation, and advocacy. +- Task Identity: Contributors often see their work through from start to finish, building and shipping features that users directly benefit from. +- Task Significance: Understanding the impact and value of their contributions motivates developers to continue their work. +- Autonomy: Contributors enjoy flexibility in how, when, and where they contribute, within the project's guidelines. +- Feedback: Constructive feedback loops help contributors improve and feel connected to the community. + +These elements combine to foster long-term satisfaction. + +### The Evolution of Motivation in Open Source + +Puja shared her own journey with Selenium, from initially feeling nervous about contributing to becoming a part of the technical leadership. Initially, simple contributions like fixing a bug brought immense satisfaction. Over time, the motivation evolved to include community appreciation and the visible impact of her work on the end users of Selenium. She recounts a meaningful interaction at a recent conference where an attendee thanked her for contributing to Selenium, highlighting how such moments validate and inspire ongoing commitment. + +### Handling Conflict in Open Source + +Ashley and Puja acknowledged that interactions on platforms like GitHub or chat channels can include harsh or unexpected comments or the project itself can have some differences of opinion. And this could be largely due to the diverse background of people, any open source project experiences. This difference of opinion and thought diversity is what makes the group awesome, but certain situations need to be resolved with care. + +Ashley shares her first experience receiving a non-constructive code review and emphasises the importance of kindness and clarity in feedback: +"Be kind, but clear. Clear is kind. You don't have to be nice, but be clear about what happened, why, and how to improve." - Ashley Hunsberger + +Effective conflict resolution involves open questions, understanding the intent, and focusing on shared goals. It’s important to remember that conflicts are natural in any group, but they can be handled constructively with the key focus being on what is important for the situation. It is also essential to make sure an open source project has a code of conduct that is implemented in such situations and that the community is aware they have a safe space to report their issue and that they will be heard. + +### Inclusivity + +Ashley distinguishes between mentorship and sponsorship as two pillars of inclusion: +- Mentorship: Providing advice, guidance, and support to help someone grow and navigate the community. +- Sponsorship: Actively advocating for someone, opening doors, and recommending them for opportunities + +Ashley further discussed that inclusivity needs to be beyond code. Such as ensuring inclusive language and removing any barriers of entry for new contributors. The key focus should be on building an inclusive environment and creating a welcoming space for new contributors and the community. + +### Overcoming Impostor Syndrome + +Impostor syndrome is a common challenge for developers, especially when engaging in large, visible open-source projects. Ashley shares candidly about her struggles and offers practical advice when Pallavi asked her to share her insights on how to enable people to overcome impostor syndrome. Ashley shares the following +- Be kind to yourself and reframe negative thoughts. Add "yet" to statements like "I don’t know how to do this... yet." +- Recognise that many others share the same fears and questions. +- Build a support network of trusted friends, mentors, and peers who understand your journey. +- Use tools like worksheets to identify negative thinking patterns and consciously reframe them. +- Focus on facts about your skills and contributions rather than self-doubt. + +These strategies can help contributors maintain confidence in their open-source journey. + +Next they discussed how open source projects can help people, and here the importance of visibility and recognition in sustaining open source motivation was emphasised. Seeing the direct impact of one’s work, whether through download statistics, user feedback, or conference stories, reinforces the value of contributions. Whether you are a seasoned contributor or a newcomer, reflecting on the above areas can hopefully help you foster a more satisfying developer experience. + +Selenium is now entering its 21st year of existence, has had contributors spanning across various time zones, geographies and areas of expertise. With nearly 800 contributors over two decades, we take this moment to express gratitude to each of them. Through continuous feedback and meaningful interaction with the community, Selenium remains dedicated to work towards a healthier developer satisfaction. + +## Watch the Recording + +Couldn’t join us live? Watch the entire episode! + +You can watch the episode on YouTube here- **Episode 5 on YouTube** +or +you can watch the episode on LinkedIn here- **Episode 5 on LinkedIn**. + +Thank you! Stay tuned as we bring the next! Subscribe here to the Selenium HQ Official YouTube Channel. \ No newline at end of file diff --git a/website_and_docs/content/blog/2025/selenium-community-live-episode6.md b/website_and_docs/content/blog/2025/selenium-community-live-episode6.md new file mode 100644 index 000000000000..a1501f59e7e4 --- /dev/null +++ b/website_and_docs/content/blog/2025/selenium-community-live-episode6.md @@ -0,0 +1,39 @@ +--- +title: "Selenium Community Live - Episode 6" +linkTitle: "Selenium Community Live - Episode 6" +date: 2025-05-21 +tags: ["webinar", "meetup", "talks","community"] +categories: ["webinar"] +author: Pallavi Sharma +images: +description: > + Selenium Community Live - Episode 6 +--- + +The sixth episode of Selenium Community Live happened on May 21st, 2025, with speaker **Luke Hill**, event hosted by **Pallavi Sharma** + +You can watch the episode on YouTube here- **Episode 6 on YouTube** +or +You can watch the episode on LinkedIn here- **Episode 6 on LinkedIn** + +**Selenium Community Live - Episode 6** + +Luke Hill is a Lead QA Engineer at Dexters with extensive automation expertise across FinTech, E-Commerce, and Education sectors. A passionate open-source contributor, Luke owns site_prism (a Page Object Gem extending Capybara), serves on the Cucumber technical committee, and is a maintainer of Selenium. Known for his meticulous testing approach and ability to identify challenging edge cases, Luke consistently helps teams deliver more reliable code. His technical expertise in both frontend and backend testing makes him a valuable voice in the QA community. + +Luke GitHub Profile is here - **Luke's GitHub** + + +**Meet the Speakers:** + +1. **Luke Hill** + + +## Watch the Recording + +Couldn’t join us live? Watch the entire episode here - +📹 Recording Link: [Watch the Event Recording on YouTube](https://www.youtube.com/live/48g7sOBHEL0?feature=shared) + +To know more about Site Prism, please follow the link +**Site Prism** + +Stay tuned as we bring the next! **Subscribe here to the Selenium HQ Official YouTube Channel.** diff --git a/website_and_docs/content/blog/2025/selenium-community-live-episode7.md b/website_and_docs/content/blog/2025/selenium-community-live-episode7.md new file mode 100644 index 000000000000..8b9b9a0e1eb1 --- /dev/null +++ b/website_and_docs/content/blog/2025/selenium-community-live-episode7.md @@ -0,0 +1,36 @@ +--- +title: "Selenium Community Live - Episode 7" +linkTitle: "Selenium Community Live - Episode 7" +date: 2025-07-01 +tags: ["webinar", "meetup", "talks","community"] +categories: ["webinar"] +author: Pallavi Sharma +images: +description: > + Selenium Community Live - Episode 7 +--- + +The seventh episode of Selenium Community Live happened on June 19th, 2025, with speaker **Christian Bromann**, event was hosted by **Pallavi Sharma** + +You can watch the episode on YouTube here- **Episode 7 on YouTube** +or +You can watch the episode on LinkedIn here- **Episode 7 on LinkedIn** + +**Selenium Community Live - Episode 7** + +Christian Bromann is a seasoned software engineer currently working at OutSystems where he contributes to the StencilJS project, a popular web component framework. He's the driving force behind WebdriverIO, a leading test automation framework that has revolutionized browser testing for countless development teams worldwide. + +Christian's GitHub Profile is here - **GitHub Profile** + + +**Meet the Speakers:** + +1. **Christian Bromann** + + +## Watch the Recording + +Couldn’t join us live? Watch the entire episode here - +📹 Recording Link: [Watch the Event Recording on YouTube](https://www.youtube.com/live/zrQRWi9Gpdg) + +Stay tuned as we bring the next! **Subscribe here to the Selenium HQ Official YouTube Channel.** diff --git a/website_and_docs/content/documentation/_index.en.md b/website_and_docs/content/documentation/_index.en.md index 0313bb1f586b..136db40dc513 100755 --- a/website_and_docs/content/documentation/_index.en.md +++ b/website_and_docs/content/documentation/_index.en.md @@ -42,7 +42,7 @@ a browser. You can find a more comprehensive example in [Writing your first Sele {{< gh-codeblock path="/examples/dotnet/HelloSelenium.cs" >}} {{< /tab >}} {{< tab header="Ruby" >}} -{{< gh-codeblock path="/examples/ruby/spec/hello/hello_selenium_spec.rb" >}} +{{< gh-codeblock path="/examples/ruby/spec/hello/hello_selenium.rb" >}} {{< /tab >}} {{< tab header="JavaScript" >}} {{< gh-codeblock path="/examples/javascript/test/hello/helloSelenium.js" >}} diff --git a/website_and_docs/content/documentation/_index.ja.md b/website_and_docs/content/documentation/_index.ja.md index 794dacbe3419..1512d796ef18 100755 --- a/website_and_docs/content/documentation/_index.ja.md +++ b/website_and_docs/content/documentation/_index.ja.md @@ -29,7 +29,7 @@ Seleniumの中核は[WebDriver]({{< ref "webdriver.md" >}})であり、様々な {{< gh-codeblock path="/examples/dotnet/HelloSelenium.cs" >}} {{< /tab >}} {{< tab header="Ruby" >}} -{{< gh-codeblock path="/examples/ruby/spec/hello/hello_selenium_spec.rb" >}} +{{< gh-codeblock path="/examples/ruby/spec/hello/hello_selenium.rb" >}} {{< /tab >}} {{< tab header="JavaScript" >}} {{< gh-codeblock path="/examples/javascript/test/hello/helloSelenium.js" >}} diff --git a/website_and_docs/content/documentation/_index.pt-br.md b/website_and_docs/content/documentation/_index.pt-br.md index 9fdaeeb151d1..7d92d0f5eb8b 100755 --- a/website_and_docs/content/documentation/_index.pt-br.md +++ b/website_and_docs/content/documentation/_index.pt-br.md @@ -40,7 +40,7 @@ navegadores. Aqui está uma das instruções mais simples que você pode fazer: {{< gh-codeblock path="/examples/dotnet/HelloSelenium.cs" >}} {{< /tab >}} {{< tab header="Ruby" >}} -{{< gh-codeblock path="/examples/ruby/spec/hello/hello_selenium_spec.rb" >}} +{{< gh-codeblock path="/examples/ruby/spec/hello/hello_selenium.rb" >}} {{< /tab >}} {{< tab header="JavaScript" >}} {{< gh-codeblock path="/examples/javascript/test/hello/helloSelenium.js" >}} diff --git a/website_and_docs/content/documentation/_index.zh-cn.md b/website_and_docs/content/documentation/_index.zh-cn.md index a68a2a5cbb70..8049e83ad16d 100755 --- a/website_and_docs/content/documentation/_index.zh-cn.md +++ b/website_and_docs/content/documentation/_index.zh-cn.md @@ -34,7 +34,7 @@ Selenium 的核心是 [WebDriver]({{< ref "webdriver.md" >}}),这是一个编 {{< gh-codeblock path="/examples/dotnet/HelloSelenium.cs" >}} {{< /tab >}} {{< tab header="Ruby" >}} -{{< gh-codeblock path="/examples/ruby/spec/hello/hello_selenium_spec.rb" >}} +{{< gh-codeblock path="/examples/ruby/spec/hello/hello_selenium.rb" >}} {{< /tab >}} {{< tab header="JavaScript" >}} {{< gh-codeblock path="/examples/javascript/test/hello/helloSelenium.js" >}} diff --git a/website_and_docs/content/documentation/grid/advanced_features/endpoints.en.md b/website_and_docs/content/documentation/grid/advanced_features/endpoints.en.md index 7e902bc0e996..3d605084c87c 100644 --- a/website_and_docs/content/documentation/grid/advanced_features/endpoints.en.md +++ b/website_and_docs/content/documentation/grid/advanced_features/endpoints.en.md @@ -16,7 +16,7 @@ Grid status provides the current state of the Grid. It consists of details about For every Node, the status includes information regarding Node availability, sessions, and slots. ```shell -cURL GET 'http://localhost:4444/status' +curl --request GET 'http://localhost:4444/status' ``` ### Delete session @@ -25,7 +25,7 @@ Deleting the session terminates the WebDriver session, quits the driver and remo Any request using the removed session-id or reusing the driver instance will throw an error. ```shell -cURL --request DELETE 'http://localhost:4444/session/%3Csession-id%3E' +curl --request DELETE 'http://localhost:4444/session/%3Csession-id%3E' ``` ### Which URL should I use? @@ -42,7 +42,7 @@ Default URL for all the above modes is http://localhost:4444. ### Remove Node -To remove the Node from the Grid, use the cURL command enlisted below. +To remove the Node from the Grid, use the curl command enlisted below. It does not stop any ongoing session running on that Node. The Node continues running as it is unless explicitly killed. The Distributor is no longer aware of the Node and hence any matching new session request @@ -52,15 +52,15 @@ In the Standalone mode, the Distributor URL is the Standalone server address. In the Hub-Node mode, the Distributor URL is the Hub server address. ```shell -cURL --request DELETE 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E' --header 'X-REGISTRATION-SECRET: ' +curl --request DELETE 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E' --header 'X-REGISTRATION-SECRET: ' ``` In the fully distributed mode, the URL is the Router server address. ```shell -cURL --request DELETE 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E' --header 'X-REGISTRATION-SECRET: ' +curl --request DELETE 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E' --header 'X-REGISTRATION-SECRET: ' ``` If no registration secret has been configured while setting up the Grid, then use ```shell -cURL --request DELETE 'http:///se/grid/distributor/node/' --header 'X-REGISTRATION-SECRET;' +curl --request DELETE 'http:///se/grid/distributor/node/' --header 'X-REGISTRATION-SECRET;' ``` ### Drain Node @@ -73,15 +73,15 @@ In the Standalone mode, the Distributor URL is the Standalone server address. In the Hub-Node mode, the Distributor URL is the Hub server address. ```shell -cURL --request POST 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E/drain' --header 'X-REGISTRATION-SECRET: ' +curl --request POST 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E/drain' --header 'X-REGISTRATION-SECRET: ' ``` In the fully distributed mode, the URL is the Router server address. ```shell -cURL --request POST 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E/drain' --header 'X-REGISTRATION-SECRET: ' +curl --request POST 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E/drain' --header 'X-REGISTRATION-SECRET: ' ``` If no registration secret has been configured while setting up the Grid, then use ```shell -cURL --request POST 'http:///se/grid/distributor/node//drain' --header 'X-REGISTRATION-SECRET;' +curl --request POST 'http:///se/grid/distributor/node//drain' --header 'X-REGISTRATION-SECRET;' ``` ## Node @@ -94,37 +94,37 @@ In case of multiple Nodes, use [Grid status](#grid-status) to get all Node detai ### Status The Node status is essentially a health-check for the Node. -Distributor pings the node status are regular intervals and updates the Grid Model accordingly. +Distributor pings the node status at regular intervals and updates the Grid Model accordingly. The status includes information regarding availability, sessions, and slots. ```shell -cURL --request GET 'http://localhost:5555/status' +curl --request GET 'http://localhost:5555/status' ``` ### Drain Distributor passes the [drain](#drain-node) command to the appropriate node identified by the node-id. -To drain the Node directly, use the cuRL command enlisted below. +To drain the Node directly, use the curl command enlisted below. Both endpoints are valid and produce the same result. Drain finishes the ongoing sessions before stopping the Node. ```shell -cURL --request POST 'http://localhost:5555/se/grid/node/drain' --header 'X-REGISTRATION-SECRET: ' +curl --request POST 'http://localhost:5555/se/grid/node/drain' --header 'X-REGISTRATION-SECRET: ' ``` If no registration secret has been configured while setting up the Grid, then use ```shell -cURL --request POST 'http:///se/grid/node/drain' --header 'X-REGISTRATION-SECRET;' +curl --request POST 'http:///se/grid/node/drain' --header 'X-REGISTRATION-SECRET;' ``` ### Check session owner -To check if a session belongs to a Node, use the cURL command enlisted below. +To check if a session belongs to a Node, use the curl command enlisted below. ```shell -cURL --request GET 'http://localhost:5555/se/grid/node/owner/%3Csession-id%3E' --header 'X-REGISTRATION-SECRET: ' +curl --request GET 'http://localhost:5555/se/grid/node/owner/%3Csession-id%3E' --header 'X-REGISTRATION-SECRET: ' ``` If no registration secret has been configured while setting up the Grid, then use ```shell -cURL --request GET 'http:///se/grid/node/owner/' --header 'X-REGISTRATION-SECRET;' +curl --request GET 'http:///se/grid/node/owner/' --header 'X-REGISTRATION-SECRET;' ``` It will return true if the session belongs to the Node else it will return false. @@ -135,11 +135,11 @@ Deleting the session terminates the WebDriver session, quits the driver and remo Any request using the removed session-id or reusing the driver instance will throw an error. ```shell -cURL --request DELETE 'http://localhost:5555/se/grid/node/session/%3Csession-id%3E' --header 'X-REGISTRATION-SECRET: ' +curl --request DELETE 'http://localhost:5555/se/grid/node/session/%3Csession-id%3E' --header 'X-REGISTRATION-SECRET: ' ``` If no registration secret has been configured while setting up the Grid, then use ```shell -cURL --request DELETE 'http:///se/grid/node/session/' --header 'X-REGISTRATION-SECRET;' +curl --request DELETE 'http:///se/grid/node/session/' --header 'X-REGISTRATION-SECRET;' ``` ## New Session Queue @@ -147,7 +147,7 @@ cURL --request DELETE 'http:///se/grid/node/session/' --he ### Clear New Session Queue New Session Request Queue holds the new session requests. -To clear the queue, use the cURL command enlisted below. +To clear the queue, use the curl command enlisted below. Clearing the queue rejects all the requests in the queue. For each such request, the server returns an error response to the respective client. The result of the clear command is the total number of deleted requests. @@ -156,23 +156,23 @@ In the Standalone mode, the Queue URL is the Standalone server address. In the Hub-Node mode, the Queue URL is the Hub server address. ```shell -cURL --request DELETE 'http://localhost:4444/se/grid/newsessionqueue/queue' --header 'X-REGISTRATION-SECRET: ' +curl --request DELETE 'http://localhost:4444/se/grid/newsessionqueue/queue' --header 'X-REGISTRATION-SECRET: ' ``` In the fully distributed mode, the Queue URL is Router server address. ```shell -cURL --request DELETE 'http://localhost:4444/se/grid/newsessionqueue/queue' --header 'X-REGISTRATION-SECRET: ' +curl --request DELETE 'http://localhost:4444/se/grid/newsessionqueue/queue' --header 'X-REGISTRATION-SECRET: ' ``` If no registration secret has been configured while setting up the Grid, then use ```shell -cURL --request DELETE 'http:///se/grid/newsessionqueue/queue' --header 'X-REGISTRATION-SECRET;' +curl --request DELETE 'http:///se/grid/newsessionqueue/queue' --header 'X-REGISTRATION-SECRET;' ``` ### Get New Session Queue Requests New Session Request Queue holds the new session requests. -To get the current requests in the queue, use the cURL command enlisted below. +To get the current requests in the queue, use the curl command enlisted below. The response returns the total number of requests in the queue and the request payloads. In the Standalone mode, the Queue URL is the Standalone server address. @@ -180,9 +180,9 @@ In the Standalone mode, the Queue URL is the Standalone server address. In the Hub-Node mode, the Queue URL is the Hub server address. ```shell -cURL --request GET 'http://localhost:4444/se/grid/newsessionqueue/queue' +curl --request GET 'http://localhost:4444/se/grid/newsessionqueue/queue' ``` In the fully distributed mode, the Queue URL is Router server address. ```shell -cURL --request GET 'http://localhost:4444/se/grid/newsessionqueue/queue' +curl --request GET 'http://localhost:4444/se/grid/newsessionqueue/queue' diff --git a/website_and_docs/content/documentation/grid/advanced_features/endpoints.ja.md b/website_and_docs/content/documentation/grid/advanced_features/endpoints.ja.md index cfc12e26ed1e..5407895187d8 100644 --- a/website_and_docs/content/documentation/grid/advanced_features/endpoints.ja.md +++ b/website_and_docs/content/documentation/grid/advanced_features/endpoints.ja.md @@ -16,7 +16,7 @@ Grid ステータスは Grid の現在の状態を提供します。 登録さ 各ノードのステータスには、ノードの稼働状況、セッション、およびスロットに関する情報が含まれます。 ```shell -cURL GET 'http://localhost:4444/status' +curl --request GET 'http://localhost:4444/status' ``` ### セッションの削除 @@ -25,7 +25,7 @@ cURL GET 'http://localhost:4444/status' 削除されたセッション ID を使用するリクエストや、ドライバのインスタンスを再利用しようとすると、エラーとなります。 ```shell -cURL --request DELETE 'http://localhost:4444/session/%3Csession-id%3E' +curl --request DELETE 'http://localhost:4444/session/%3Csession-id%3E' ``` ### Which URL should I use? @@ -42,7 +42,7 @@ cURL --request DELETE 'http://localhost:4444/session/%3Csession-id%3E' ### ノード削除 -ノードを Grid から削除するには、以下の cURL コマンドを使用します。 +ノードを Grid から削除するには、以下の curl コマンドを使用します。 このコマンドは、そのノード上で実行中のセッションを停止させるものではありません。 ノードは明示的に強制終了されない限り、そのまま動作し続けます。 ディストリビューターはそのノードを認識しなくなるため、マッチする新しいセッションのリクエストは はその Node に転送されません。 @@ -52,19 +52,19 @@ cURL --request DELETE 'http://localhost:4444/session/%3Csession-id%3E' ハブ&ノードモードでは、ディストリビューターの URL は ハブのアドレスになります。 ```shell -cURL --request DELETE 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E' --header 'X-REGISTRATION-SECRET: ' +curl --request DELETE 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E' --header 'X-REGISTRATION-SECRET: ' ``` 完全分散モードでは、ディストリビューター URL は ディストリビューターのアドレスになります。 ```shell -cURL --request DELETE 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E' --header 'X-REGISTRATION-SECRET: ' +curl --request DELETE 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E' --header 'X-REGISTRATION-SECRET: ' ``` Grid の設定時に登録用の secret を設定していない場合は次のようにします: ```shell -cURL --request DELETE 'http:///se/grid/distributor/node/' --header 'X-REGISTRATION-SECRET;' +curl --request DELETE 'http:///se/grid/distributor/node/' --header 'X-REGISTRATION-SECRET;' ``` ### ノードのドレイン @@ -78,19 +78,19 @@ cURL --request DELETE 'http:///se/grid/distributor/node/' - ハブ&ノードモードでは、ディストリビューターの URL は ハブのアドレスになります。 ```shell -cURL --request POST 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E/drain' --header 'X-REGISTRATION-SECRET: ' +curl --request POST 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E/drain' --header 'X-REGISTRATION-SECRET: ' ``` 完全分散モードでは、ディストリビューター URL は ディストリビューターのアドレスになります。 ```shell -cURL --request POST 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E/drain' --header 'X-REGISTRATION-SECRET: ' +curl --request POST 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E/drain' --header 'X-REGISTRATION-SECRET: ' ``` Grid の設定時に登録用の secret を設定していない場合は次のようにします: ```shell -cURL --request POST 'http:///se/grid/distributor/node//drain' --header 'X-REGISTRATION-SECRET;' +curl --request POST 'http:///se/grid/distributor/node//drain' --header 'X-REGISTRATION-SECRET;' ``` ## ノード @@ -106,38 +106,38 @@ cURL --request POST 'http:///se/grid/distributor/node//drai ステータスには稼働状況、セッション、およびスロットに関する情報が含まれます。 ```shell -cURL --request GET 'http://localhost:5555/status' +curl --request GET 'http://localhost:5555/status' ``` ### ドレイン ディストリビューターは [ドレイン](#ノードのドレイン)コマンドを適切なノードに渡します。 -ノードを直接ドレインするには以下の cURL コマンドを使います。 +ノードを直接ドレインするには以下の curl コマンドを使います。 どちらのエンドポイントも有効であり、同じ結果になります。 ドレインは、ノードを停止する前に進行中のセッションを終了させます。 ```shell -cURL --request POST 'http://localhost:5555/se/grid/node/drain' --header 'X-REGISTRATION-SECRET: ' +curl --request POST 'http://localhost:5555/se/grid/node/drain' --header 'X-REGISTRATION-SECRET: ' ``` Grid の設定時に登録用の secret を設定していない場合は次のようにします: ```shell -cURL --request POST 'http:///se/grid/node/drain' --header 'X-REGISTRATION-SECRET;' +curl --request POST 'http:///se/grid/node/drain' --header 'X-REGISTRATION-SECRET;' ``` ### セッションオーナーのチェック -あるセッションがノードに属しているかどうかをチェックするには、以下の cURL コマンドを使います。 +あるセッションがノードに属しているかどうかをチェックするには、以下の curl コマンドを使います。 ```shell -cURL --request GET 'http://localhost:5555/se/grid/node/owner/%3Csession-id%3E' --header 'X-REGISTRATION-SECRET: ' +curl --request GET 'http://localhost:5555/se/grid/node/owner/%3Csession-id%3E' --header 'X-REGISTRATION-SECRET: ' ``` Grid の設定時に登録用の secret を設定していない場合は次のようにします: ```shell -cURL --request GET 'http:///se/grid/node/owner/' --header 'X-REGISTRATION-SECRET;' +curl --request GET 'http:///se/grid/node/owner/' --header 'X-REGISTRATION-SECRET;' ``` もしセッションがノードに属していたら true を返し、そうでなければ false が返ります。 @@ -148,13 +148,13 @@ cURL --request GET 'http:///se/grid/node/owner/' --header 削除されたセッション ID を使用するリクエストや、ドライバのインスタンスを再利用しようとすると、エラーとなります。 ```shell -cURL --request DELETE 'http://localhost:5555/se/grid/node/session/%3Csession-id%3E' --header 'X-REGISTRATION-SECRET: ' +curl --request DELETE 'http://localhost:5555/se/grid/node/session/%3Csession-id%3E' --header 'X-REGISTRATION-SECRET: ' ``` Grid の設定時に登録用の secret を設定していない場合は次のようにします: ```shell -cURL --request DELETE 'http:///se/grid/node/session/' --header 'X-REGISTRATION-SECRET;' +curl --request DELETE 'http:///se/grid/node/session/' --header 'X-REGISTRATION-SECRET;' ``` ## 新規セッションキュー @@ -162,7 +162,7 @@ cURL --request DELETE 'http:///se/grid/node/session/' --he ### 新規セッションキューのクリア 新規セッションキューには、新規セッションリクエストが格納されます。 -キューをクリアするには、以下に挙げる cURL コマンドを使用します。 +キューをクリアするには、以下に挙げる curl コマンドを使用します。 キューを消去すると、キューにあるすべてのリクエストを拒否します。 サーバーは各リクエストのそれぞれのクライアントにエラーレスポンスを返します。 クリアコマンドの結果は、削除されたリクエストの数です。 @@ -172,25 +172,25 @@ cURL --request DELETE 'http:///se/grid/node/session/' --he ハブ&ノードモードでは、キューの URL は ハブのアドレスになります。 ```shell -cURL --request DELETE 'http://localhost:4444/se/grid/newsessionqueue/queue' --header 'X-REGISTRATION-SECRET: ' +curl --request DELETE 'http://localhost:4444/se/grid/newsessionqueue/queue' --header 'X-REGISTRATION-SECRET: ' ``` 完全分散モードでは、キューの URL は 新規セッションキューのアドレスになります。 ```shell -cURL --request DELETE 'http://localhost:4444/se/grid/newsessionqueue/queue' --header 'X-REGISTRATION-SECRET: ' +curl --request DELETE 'http://localhost:4444/se/grid/newsessionqueue/queue' --header 'X-REGISTRATION-SECRET: ' ``` Grid の設定時に登録用の secret を設定していない場合は次のようにします: ```shell -cURL --request DELETE 'http:///se/grid/newsessionqueue/queue' --header 'X-REGISTRATION-SECRET;' +curl --request DELETE 'http:///se/grid/newsessionqueue/queue' --header 'X-REGISTRATION-SECRET;' ``` ### 新規セッションリクエストの取得 新規セッションキューには、新規セッションリクエストが格納されます。 -キューにある現在のリクエストを取得するには、以下に挙げる cURL コマンドを使用します。 +キューにある現在のリクエストを取得するには、以下に挙げる curl コマンドを使用します。 レスポンスはキュー内のリクエストの数とリクエストのペイロードを返します。 スタンドアロンモードでは、キューの URL はスタンドアロンサーバーのアドレスとなります。 @@ -198,11 +198,11 @@ cURL --request DELETE 'http:///se/grid/newsessionqueue/queue' --head ハブ&ノードモードでは、キューの URL は ハブのアドレスになります。 ```shell -cURL --request GET 'http://localhost:4444/se/grid/newsessionqueue/queue' +curl --request GET 'http://localhost:4444/se/grid/newsessionqueue/queue' ``` 完全分散モードでは、キューの URL は 新規セッションキューのアドレスになります。 ```shell -cURL --request GET 'http://localhost:4444/se/grid/newsessionqueue/queue' +curl --request GET 'http://localhost:4444/se/grid/newsessionqueue/queue' ``` diff --git a/website_and_docs/content/documentation/grid/advanced_features/endpoints.pt-br.md b/website_and_docs/content/documentation/grid/advanced_features/endpoints.pt-br.md index f1221a1af8dd..046e2ab41fb8 100644 --- a/website_and_docs/content/documentation/grid/advanced_features/endpoints.pt-br.md +++ b/website_and_docs/content/documentation/grid/advanced_features/endpoints.pt-br.md @@ -16,7 +16,7 @@ O status da Grid fornece o estado atual da grid. Consiste em detalhes sobre cada Para cada nó, o status inclui informações sobre a disponibilidade, sessões e slots do nó. ```shell -cURL GET 'http://localhost:4444/status' +curl --request GET 'http://localhost:4444/status' ``` ### Deletar sessão @@ -25,7 +25,7 @@ A exclusão da sessão encerra a sessão do WebDriver, fecha o driver e o remove Qualquer solicitação usando o id de sessão removido ou reutilizando a instância do driver gerará um erro. ```shell -cURL --request DELETE 'http://localhost:4444/session/%3Csession-id%3E' +curl --request DELETE 'http://localhost:4444/session/%3Csession-id%3E' ``` ### Which URL should I use? @@ -42,7 +42,7 @@ A URL padrão para todos os modos acima é http://localhost:4444. ### Remover Nó -Para remover o Nó da Grid, use o comando cURL listado abaixo. +Para remover o Nó da Grid, use o comando curl listado abaixo. Ele não interrompe nenhuma sessão em andamento em execução nesse nó. O Node continua rodando como está, a menos que seja explicitamente eliminado. O Distribuidor não está mais ciente do Nó e, portanto, qualquer solicitação de nova sessão correspondente @@ -52,15 +52,15 @@ No modo Standalone, a URL do distribuidor é o endereço do servidor Standalone. No modo Hub-Node, a URL do Distribuidor é o endereço do servidor Hub. ```shell -cURL --request DELETE 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E' --header 'X-REGISTRATION-SECRET: ' +curl --request DELETE 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E' --header 'X-REGISTRATION-SECRET: ' ``` No modo totalmente distribuído, a URL é o endereço do servidor Router. ```shell -cURL --request DELETE 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E' --header 'X-REGISTRATION-SECRET: ' +curl --request DELETE 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E' --header 'X-REGISTRATION-SECRET: ' ``` Se nenhum segredo de registro foi configurado durante a configuração da Grid, use ```shell -cURL --request DELETE 'http:///se/grid/distributor/node/' --header 'X-REGISTRATION-SECRET;' +curl --request DELETE 'http:///se/grid/distributor/node/' --header 'X-REGISTRATION-SECRET;' ``` ### Drenar Nó @@ -73,15 +73,15 @@ No modo Standalone, a URL do distribuidor é o endereço do servidor Standalone. No modo Hub-Node, a URL do Distribuidor é o endereço do servidor Hub. ```shell -cURL --request POST 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E/drain' --header 'X-REGISTRATION-SECRET: ' +curl --request POST 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E/drain' --header 'X-REGISTRATION-SECRET: ' ``` No modo totalmente distribuído, a URL é o endereço do servidor Router. ```shell -cURL --request POST 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E/drain' --header 'X-REGISTRATION-SECRET: ' +curl --request POST 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E/drain' --header 'X-REGISTRATION-SECRET: ' ``` Se nenhum segredo de registro foi configurado durante a configuração da Grid, use ```shell -cURL --request POST 'http:///se/grid/distributor/node//drain' --header 'X-REGISTRATION-SECRET;' +curl --request POST 'http:///se/grid/distributor/node//drain' --header 'X-REGISTRATION-SECRET;' ``` ## Nó @@ -97,33 +97,33 @@ O distribuidor executa ping no status do Nó em intervalos regulares e atualiza O status inclui informações sobre disponibilidade, sessões e slots. ```shell -cURL --request GET 'http://localhost:5555/status' +curl --request GET 'http://localhost:5555/status' ``` ### Drenagem O Distribuidor passa o comando [drain](# drain-node) para o Nó apropriado identificado pelo ID do Nó. -Para drenar o Nó diretamente, use o comando cuRL listado abaixo. +Para drenar o Nó diretamente, use o comando curl listado abaixo. Ambos as rotas são válidas e produzem o mesmo resultado. Drenar termina as sessões em andamento antes de interromper o Nó. ```shell -cURL --request POST 'http://localhost:5555/se/grid/node/drain' --header 'X-REGISTRATION-SECRET: ' +curl --request POST 'http://localhost:5555/se/grid/node/drain' --header 'X-REGISTRATION-SECRET: ' ``` Se nenhum segredo de registro foi configurado durante a configuração da Grid, use ```shell -cURL --request POST 'http:///se/grid/node/drain' --header 'X-REGISTRATION-SECRET;' +curl --request POST 'http:///se/grid/node/drain' --header 'X-REGISTRATION-SECRET;' ``` ### Checar dono da sessão -Para verificar se uma sessão pertence a um Nó, use o comando cURL listado abaixo. +Para verificar se uma sessão pertence a um Nó, use o comando curl listado abaixo. ```shell -cURL --request GET 'http://localhost:5555/se/grid/node/owner/%3Csession-id%3E' --header 'X-REGISTRATION-SECRET: ' +curl --request GET 'http://localhost:5555/se/grid/node/owner/%3Csession-id%3E' --header 'X-REGISTRATION-SECRET: ' ``` Se nenhum segredo de registro foi configurado durante a configuração da Grid, use ```shell -cURL --request GET 'http:///se/grid/node/owner/' --header 'X-REGISTRATION-SECRET;' +curl --request GET 'http:///se/grid/node/owner/' --header 'X-REGISTRATION-SECRET;' ``` Ele retornará true se a sessão pertencer ao Nó, caso contrário, retornará false. @@ -134,11 +134,11 @@ A exclusão da sessão encerra a sessão do WebDriver, fecha o driver e o remove Qualquer solicitação usando o id de sessão removido ou reutilizando a instância do driver gerará um erro. ```shell -cURL --request DELETE 'http://localhost:5555/se/grid/node/session/%3Csession-id%3E' --header 'X-REGISTRATION-SECRET: ' +curl --request DELETE 'http://localhost:5555/se/grid/node/session/%3Csession-id%3E' --header 'X-REGISTRATION-SECRET: ' ``` Se nenhum segredo de registro foi configurado durante a configuração da Grid, use ```shell -cURL --request DELETE 'http:///se/grid/node/session/' --header 'X-REGISTRATION-SECRET;' +curl --request DELETE 'http:///se/grid/node/session/' --header 'X-REGISTRATION-SECRET;' ``` ## Fila de Sessão @@ -146,7 +146,7 @@ cURL --request DELETE 'http:///se/grid/node/session/' --he ### Limpar a Fila de Sessão A Fila de Sessão contém as novas solicitações de sessão. -Para limpar a fila, use o comando cURL listado abaixo. +Para limpar a fila, use o comando curl listado abaixo. Limpar a fila rejeita todas as solicitações na fila. Para cada solicitação, o servidor retorna uma resposta de erro ao respectivo cliente. O resultado do comando clear é o número total de solicitações excluídas. @@ -155,31 +155,31 @@ No modo Standalone, a URL Queue é o endereço do servidor Standalone. No modo Hub-Node, a URL do enfileirador é o endereço do servidor Hub. ```shell -cURL --request DELETE 'http://localhost:4444/se/grid/newsessionqueue/queue' --header 'X-REGISTRATION-SECRET: ' +curl --request DELETE 'http://localhost:4444/se/grid/newsessionqueue/queue' --header 'X-REGISTRATION-SECRET: ' ``` No modo totalmente distribuído, a URL do enfileirador é o endereço do servidor do Enfileirador de Sessões. ```shell -cURL --request DELETE 'http://localhost:4444/se/grid/newsessionqueue/queue' --header 'X-REGISTRATION-SECRET: ' +curl --request DELETE 'http://localhost:4444/se/grid/newsessionqueue/queue' --header 'X-REGISTRATION-SECRET: ' ``` If no registration secret has been configured while setting up the Grid, then use ```shell -cURL --request DELETE 'http:///se/grid/newsessionqueue/queue' --header 'X-REGISTRATION-SECRET;' +curl --request DELETE 'http:///se/grid/newsessionqueue/queue' --header 'X-REGISTRATION-SECRET;' ``` ### Obter novos pedidos da Fila de Sessão Novos pedidos da Fila de Sessão contém os novos pedidos de sessão. -Para obter os pedidos na Fila, utiliza o comando cURL listado abaixo. +Para obter os pedidos na Fila, utiliza o comando curl listado abaixo. É retornado o número total de pedidos na Fila. No modo Standalone, a URL é a do servidor, em modo Grid, a URL será a do HUB. ```shell -cURL --request GET 'http://localhost:4444/se/grid/newsessionqueue/queue' +curl --request GET 'http://localhost:4444/se/grid/newsessionqueue/queue' ``` No modo totalmente distribuido, a URL da Fila é a porta do servidor de Fila. ```shell -cURL --request GET 'http://localhost:4444/se/grid/newsessionqueue/queue' +curl --request GET 'http://localhost:4444/se/grid/newsessionqueue/queue' diff --git a/website_and_docs/content/documentation/grid/advanced_features/endpoints.zh-cn.md b/website_and_docs/content/documentation/grid/advanced_features/endpoints.zh-cn.md index 226edffd2e4b..8e67ae00a270 100644 --- a/website_and_docs/content/documentation/grid/advanced_features/endpoints.zh-cn.md +++ b/website_and_docs/content/documentation/grid/advanced_features/endpoints.zh-cn.md @@ -18,22 +18,22 @@ Grid状态提供Grid的当前状态. 状态包括有关节点可用性、会话和插槽的信息. ```shell -cURL GET 'http://localhost:4444/status' +curl --request GET 'http://localhost:4444/status' ``` -### 检查会话所有者 +### 删除会话 -要检查会话是否属于某一节点, 请使用下面列出的cURL命令. +删除会话会终止 WebDriver 会话、退出驱动程序并将其从活动会话映射中删除。任何使用删除的会话标识或重新使用驱动程序实例的请求都会出错。 ```shell -cURL --request DELETE 'http://localhost:4444/session/%3Csession-id%3E' +curl --request DELETE 'http://localhost:4444/session/%3Csession-id%3E' ``` -### Which URL should I use? +### 我应该使用哪一个URL? -在独立模式下, Grid URL是独立服务器的地址. +在 Standalone 模式下, Grid URL是独立服务器的地址. -在集线器节点模式下, Grid URL是集线器服务器的地址. +在 Hub-Node 模式下, Grid URL是集线器服务器的地址. 在完全分布式模式下, Grid URL是路由服务器的地址. @@ -43,179 +43,137 @@ cURL --request DELETE 'http://localhost:4444/session/%3Csession-id%3E' ### 删除节点 -要从Grid中删除节点, -请使用下面列出的cURL命令. -它不会停止在该节点上运行的任何持续中的会话. -除非显式终止, 否则节点将继续按原样运行. -分发器不再知晓该节点, -因此任何匹配的新会话请求 -也不会转发到该节点. +要从网格中删除节点,请使用下面列出的 curl 命令。该命令不会停止正在该节点上运行的任何会话。除非显式终止, 否则节点将继续运行。分发器不再知道该节点,因此任何匹配的新会话请求都不会转发到该节点。 -在独立模式下, 分发器URL是独立服务器的地址. +在 Standalone 模式下,分发器 URL 是独立服务器地址。 -在集线器节点模式下, 分发器URL是集线器服务器的地址. +在 Hub-Node 模式下, 分发器 URL 是 Hub 服务器的地址。 ```shell -cURL --request DELETE 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E' --header 'X-REGISTRATION-SECRET: ' +curl --request DELETE 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E' --header 'X-REGISTRATION-SECRET: ' ``` -在完全分布式模式下, URL是分发器的地址. +在完全分布式模式下, URL是分发器的地址。 ```shell -cURL --request DELETE 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E' --header 'X-REGISTRATION-SECRET: ' +curl --request DELETE 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E' --header 'X-REGISTRATION-SECRET: ' ``` -如果在设置Grid时未配置注册密码, -则使用 +如果在设置Grid时未配置注册密码, 则使用 ```shell -cURL --request DELETE 'http:///se/grid/distributor/node/' --header 'X-REGISTRATION-SECRET;' +curl --request DELETE 'http:///se/grid/distributor/node/' --header 'X-REGISTRATION-SECRET;' ``` -### 放空节点 +### 释放节点 -节点放空命令用于优雅地关闭节点. -放空节点将在所有持续中的会话完成后停止节点. -但是, 它不接受任何新的会话请求. +节点释放命令用于优雅地关闭节点。在所有正在进行的会话结束后,会停止该节点。并且,它不会接受任何新的会话请求。 -在独立模式下, 分发器URL是独立服务器的地址. +在 Standalone 模式下,分发器 URL 是独立服务器地址。 -在集线器节点模式下, 分发器URL是集线器服务器的地址. +在 Hub-Node 模式下, 分发器 URL 是 Hub 服务器的地址。 ```shell -cURL --request POST 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E/drain' --header 'X-REGISTRATION-SECRET: ' +curl --request POST 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E/drain' --header 'X-REGISTRATION-SECRET: ' ``` -在完全分布式模式下, URL是分发服务器的地址. +在完全分布式模式下, URL是分发服务器的地址。 ```shell -cURL --request POST 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E/drain' --header 'X-REGISTRATION-SECRET: ' +curl --request POST 'http://localhost:4444/se/grid/distributor/node/%3Cnode-id%3E/drain' --header 'X-REGISTRATION-SECRET: ' ``` -如果在设置Grid时未配置注册密码, -则使用 +如果在设置Grid时未配置注册密码, 则使用 ```shell -cURL --request POST 'http:///se/grid/distributor/node//drain' --header 'X-REGISTRATION-SECRET;' +curl --request POST 'http:///se/grid/distributor/node//drain' --header 'X-REGISTRATION-SECRET;' ``` ## 节点 -本节中的端点适用于 -集线器节点模式和 -节点独立运行的完全分布式网格模式. -在一个节点的情况下, 默认节点的URL为 http://localhost:5555 . -如果有多个节点, -请使用 [Grid 状态](#grid-状态) 获取所有节点详细信息 -以及定位地址. +本节中的端点适用于 Hub-Node 模式和节点独立运行的完全分布式网格模式。在一个节点的情况下, 默认节点的URL为 http://localhost:5555 。 +如果有多个节点,请使用 [Grid 状态](#grid-状态) 获取所有节点的详细信息并查找节点地址。 ### 状态 -节点状态本质上是节点的运行状况检查. -分发器定期ping节点状态, -并相应地更新Grid模型. -状态包括相关的可用性, 会话和插槽的信息. +节点状态本质上是节点的健康检查。分发程序会定期 ping 节点状态,并相应地更新 Grid 模型。状态包括有关可用性、会话和插槽的信息。 ```shell -cURL --request GET 'http://localhost:5555/status' +curl --request GET 'http://localhost:5555/status' ``` -### 放空 +### 释放 -分发器将 [放空](#放空节点) 命令传递给 -由node-id标识的相应节点. -要直接放空节点, -请使用下面列出的cuRL命令. -两个端点都有效并产生相同的结果. -放空会等待持续中的会话完成后 -才停止节点. +分发器将 [释放](#释放节点) 命令传递给由node-id标识的相应节点。要直接释放节点,请使用下面列出的curl命令。 +两个端点都有效并产生相同的结果。释放会等待持续中的会话完成后才停止节点。 ```shell -cURL --request POST 'http://localhost:5555/se/grid/node/drain' --header 'X-REGISTRATION-SECRET: ' +curl --request POST 'http://localhost:5555/se/grid/node/drain' --header 'X-REGISTRATION-SECRET: ' ``` -如果在设置Grid时未配置注册密码, -则使用 +如果在设置Grid时未配置注册密码,则使用 ```shell -cURL --request POST 'http:///se/grid/node/drain' --header 'X-REGISTRATION-SECRET;' +curl --request POST 'http:///se/grid/node/drain' --header 'X-REGISTRATION-SECRET;' ``` ### 检查会话所有者 -要检查会话是否属于某一节点, 请使用下面列出的cURL命令. +要检查会话是否属于某一节点, 请使用下面列出的curl命令. ```shell -cURL --request GET 'http://localhost:5555/se/grid/node/owner/%3Csession-id%3E' --header 'X-REGISTRATION-SECRET: ' +curl --request GET 'http://localhost:5555/se/grid/node/owner/%3Csession-id%3E' --header 'X-REGISTRATION-SECRET: ' ``` -如果在设置Grid时未配置注册密码, -则使用 +如果在设置Grid时未配置注册密码, 则使用 ```shell -cURL --request GET 'http:///se/grid/node/owner/' --header 'X-REGISTRATION-SECRET;' +curl --request GET 'http:///se/grid/node/owner/' --header 'X-REGISTRATION-SECRET;' ``` 如果会话属于该节点, 则返回true, -否则返回false. +否则返回false。 ### 删除会话 -删除会话将终止WebDriver会话, -退出驱动程序 -并将其从活动会话集合中删除. -任何使用删除的会话id -或重用驱动程序实例的请求 -都将抛出错误. +删除会话会终止 WebDriver 会话、退出驱动程序并将其从活动会话映射中删除。任何使用删除的会话标识或重新使用驱动程序实例的请求都会出错。 ```shell -cURL --request DELETE 'http://localhost:5555/se/grid/node/session/%3Csession-id%3E' --header 'X-REGISTRATION-SECRET: ' +curl --request DELETE 'http://localhost:5555/se/grid/node/session/%3Csession-id%3E' --header 'X-REGISTRATION-SECRET: ' ``` -如果在设置Grid时未配置注册密码, -则使用 +如果在设置Grid时未配置注册密码, 则使用 ```shell -cURL --request DELETE 'http:///se/grid/node/session/' --header 'X-REGISTRATION-SECRET;' +curl --request DELETE 'http:///se/grid/node/session/' --header 'X-REGISTRATION-SECRET;' ``` ## 新会话队列 ### 清除新会话队列 -新会话请求队列保存新会话请求. -要清除队列, -请使用下面列出的cURL命令. -清除队列将拒绝队列中的所有请求. -对于每个这样的请求, -服务器都会向相应的客户端返回一个错误响应. -清除命令的返回结果是 -已删除请求的总数. +新会话请求队列保存新会话请求。要清除队列,请使用下面列出的 curl 命令。清除队列会拒绝队列中的所有请求。对于每个此类请求,服务器都会向相应的客户端返回错误响应。清除命令的结果是被删除请求的总数。 -在独立模式下, 队列URL是独立服务器的地址. -在集线器节点模式下, 队列URL是集线器服务器的地址. +在 Standalone 模式下, 队列URL是独立服务器的地址。 +在 Hub-Node 模式下, 队列URL是集线器服务器的地址。 ```shell -cURL --request DELETE 'http://localhost:4444/se/grid/newsessionqueue/queue' --header 'X-REGISTRATION-SECRET: ' +curl --request DELETE 'http://localhost:4444/se/grid/newsessionqueue/queue' --header 'X-REGISTRATION-SECRET: ' ``` 在完全分布式模式下, -队列URL是新会话队列服务器的地址. +队列URL是新会话队列服务器的地址。 ```shell -cURL --request DELETE 'http://localhost:4444/se/grid/newsessionqueue/queue' --header 'X-REGISTRATION-SECRET: ' +curl --request DELETE 'http://localhost:4444/se/grid/newsessionqueue/queue' --header 'X-REGISTRATION-SECRET: ' ``` -如果在设置Grid时未配置注册密码, -则使用 +如果在设置Grid时未配置注册密码, 则使用 ```shell -cURL --request DELETE 'http:///se/grid/newsessionqueue/queue' --header 'X-REGISTRATION-SECRET;' +curl --request DELETE 'http:///se/grid/newsessionqueue/queue' --header 'X-REGISTRATION-SECRET;' ``` ### 获取新会话队列请求 -New Session Request Queue holds the new session requests. -To get the current requests in the queue, use the cURL command enlisted below. -The response returns the total number of requests in the queue and the request payloads. -新会话请求队列保存新会话请求. +新会话请求队列保存新会话请求。 要获取队列中的当前请求, -请使用下面列出的cURL命令. -响应会返回队列中的请求总数以及请求内容. +请使用下面列出的curl命令。 +响应会返回队列中的请求总数以及请求内容。 -在独立模式下, 队列URL是独立服务器的地址. -在集线器节点模式下, 队列URL是集线器服务器的地址. +在 Standalone 模式下, 队列URL是独立服务器的地址。 +在 Hub-Node 模式下, 队列URL是集线器服务器的地址。 ```shell -cURL --request GET 'http://localhost:4444/se/grid/newsessionqueue/queue' +curl --request GET 'http://localhost:4444/se/grid/newsessionqueue/queue' ``` 在完全分布式模式下, -队列URL是新会话队列服务器的地址. +队列URL是新会话队列服务器的地址。 ```shell -cURL --request GET 'http://localhost:4444/se/grid/newsessionqueue/queue' +curl --request GET 'http://localhost:4444/se/grid/newsessionqueue/queue' diff --git a/website_and_docs/content/documentation/grid/applicability.zh-cn.md b/website_and_docs/content/documentation/grid/applicability.zh-cn.md index c6b1a8308afc..486c1be49754 100644 --- a/website_and_docs/content/documentation/grid/applicability.zh-cn.md +++ b/website_and_docs/content/documentation/grid/applicability.zh-cn.md @@ -3,46 +3,39 @@ title: "什么时候应该使用Grid" linkTitle: "适用性" weight: 4 description: > - Is Grid right for you? + Grid适合您吗? aliases: [ "/documentation/zh-cn/grid/when_to_use_grid/", "/zh-cn/documentation/grid/when_to_use_grid" ] --- -{{% pageinfo color="warning" %}} -

- - Page being translated from English to Chinese. - Do you speak Chinese? Help us to translate - it by sending us pull requests! -

-{{% /pageinfo %}} 什么情况下可以使用 `Selenium Grid` ? * 想要在不同的浏览器类型、浏览器版本和操作系统上并行运行测试时 * 想要缩短执行测试案例所需的时间 -`Selenium Grid` 可以并行地在多台计算机(称为节点)上运行测试案例。对于大型和长时间运行的测试案例,这可以节省几分钟、几小时甚至几天的时间。 +`Selenium Grid` 可以并行地在多台计算机(称为节点)上运行测试案例. 对于大型和长时间运行的测试案例,这可以节省几分钟、几小时甚至几天的时间. -这有效的缩短了测试结果的反馈时间,使得在测试的应用程序发生变化时能够更快地得到测试结果。 +这有效的缩短了测试结果的反馈时间,使得在测试的应用程序发生变化时能够更快地得到测试结果. -`Grid` 可以并行地运行测试,支持多种不同的浏览器类型,并且可以同时运行多个相同浏览器的实例。 +`Grid` 可以并行地运行测试,支持多种不同的浏览器类型,并且可以同时运行多个相同浏览器的实例. -举个例子,假设一个拥有六个节点的Grid。第一台计算机拥有Firefox的最新版本,第二台拥有Firefox的上一个版本,第三台运行最新版Chrome,而其余三台机器是Mac Mini,允许在最新版本的Safari上并行运行三个测试。 +举个例子,假设一个拥有六个节点的Grid. 第一台计算机拥有Firefox的最新版本,第二台拥有Firefox的上一个版本,第三台运行最新版Chrome,而其余三台机器是Mac Mini,允许在最新版本的Safari上并行运行三个测试. 执行时间可以用一个简单的公式来表示: ```测试次数 × 平均测试时间 / 节点数 = 总执行时间``` - 15 * 45s / 1 = 11m 15s // Without Grid - 15 * 45s / 5 = 2m 15s // Grid with 5 Nodes - 15 * 45s / 15 = 45s // Grid with 15 Nodes - 100 * 120s / 15 = 13m 20s // Would take over 3 hours without Grid + 15 * 45s / 1 = 11m 15s // 没有Grid + 15 * 45s / 5 = 2m 15s // 5节点的Grid + 15 * 45s / 15 = 45s // 15节点的Grid + 100 * 120s / 15 = 13m 20s // 如果没有Grid, 需要3个多小时 -在测试案例执行时,`Grid` 会按照测试配置将测试分配到相应的浏览器上运行。 +在测试案例执行时,`Grid` 会按照测试配置将测试分配到相应的浏览器上运行. -即使对于比较复杂的 `Selenium` 测试案例,这样的配置也可以极大地加快执行时间。 +即使对于比较复杂的 `Selenium` 测试案例,这样的配置也可以极大地加快执行时间. -`Selenium Grid` 是 `Selenium` 项目中的重要组成部分,由同一团队的核心Selenium开发人员并行维护。由于意识到测试执行速度的重要性,`Grid` 自设计之初就成为 `Selenium` 项目的关键部分。 +`Selenium Grid` 是 `Selenium` 项目中的重要组成部分,由同一团队的核心Selenium开发人员并行维护. +由于意识到测试执行速度的重要性,`Grid` 自设计之初就成为 `Selenium` 项目的关键部分. \ No newline at end of file diff --git a/website_and_docs/content/documentation/grid/components.ja.md b/website_and_docs/content/documentation/grid/components.ja.md index 46cd256d235f..881803b51fb5 100644 --- a/website_and_docs/content/documentation/grid/components.ja.md +++ b/website_and_docs/content/documentation/grid/components.ja.md @@ -1,5 +1,5 @@ --- -title: "Serenium Grid のコンポーネント" +title: "Selenium Grid のコンポーネント" linkTitle: "コンポーネント" weight: 6 description: > diff --git a/website_and_docs/content/documentation/grid/components.zh-cn.md b/website_and_docs/content/documentation/grid/components.zh-cn.md index 554b85f12adb..9ee6760d555f 100644 --- a/website_and_docs/content/documentation/grid/components.zh-cn.md +++ b/website_and_docs/content/documentation/grid/components.zh-cn.md @@ -10,14 +10,6 @@ aliases: [ ] --- -{{% pageinfo color="warning" %}} -

- - Page being translated from - English to Chinese. Do you speak Chinese? Help us to translate - it by sending us pull requests! -

-{{% /pageinfo %}} Selenium Grid 4 是对以前版本的彻底重写。除了对性能和标准合规性进行全面改进外,还分解了 `Grid` 的不同功能以反映更现代的计算和软件开发时代。 Selenium Grid 4 专为容器化和云分布式可扩展性而构建,是现代时代的全新解决方案。 diff --git a/website_and_docs/content/documentation/grid/configuration/cli_options.en.md b/website_and_docs/content/documentation/grid/configuration/cli_options.en.md index 0cc8e27016c9..075c1eb82db2 100644 --- a/website_and_docs/content/documentation/grid/configuration/cli_options.en.md +++ b/website_and_docs/content/documentation/grid/configuration/cli_options.en.md @@ -194,7 +194,7 @@ pull request updating this page. | `--http-logs` | boolean | `false` | Enable http logging. Tracing should be enabled to log http logs. | | `--log-encoding` | string | `UTF-8` | Log encoding | | `--log` | string | Windows path example :
`'\path\to\file\gridlog.log'`
or
`'C:\path\path\to\file\gridlog.log'`

Linux/Unix/MacOS path example :
`'/path/to/file/gridlog.log'` | File to write out logs. Ensure the file path is compatible with the operating system's file path. | -| `--log-level` | string | `“INFO”` | Log level. Default logging level is INFO. Log levels are described here https://docs.oracle.com/javase/7/docs/api/java/util/logging/Level.html | +| `--log-level` | string | `“INFO”` | Log level. Default logging level is INFO. Log levels are described here https://docs.oracle.com/en/java/javase/11/docs/api/java.logging/java/util/logging/Level.html | | `--plain-logs` | boolean | `true` | Use plain log lines | | `--structured-logs` | boolean | `false` | Use structured logs | | `--tracing` | boolean | `true` | Enable trace collection | diff --git a/website_and_docs/content/documentation/grid/configuration/cli_options.ja.md b/website_and_docs/content/documentation/grid/configuration/cli_options.ja.md index ccd9ae0b4278..b61aa761852b 100644 --- a/website_and_docs/content/documentation/grid/configuration/cli_options.ja.md +++ b/website_and_docs/content/documentation/grid/configuration/cli_options.ja.md @@ -193,7 +193,7 @@ Grid の設定には、さまざまなセクションが用意されています | `--http-logs` | boolean | `false` | http ログを有効にします。http ログを記録するには、トレースを有効にする必要があります。 | | `--log-encoding` | string | `UTF-8` | ログのエンコーディング。 | | `--log` | string | Windows パスの例:
`'\path\to\file\gridlog.log'`
or
`'C:\path\path\to\file\gridlog.log'`

Linux/Unix/MacOS パスの例:
`'/path/to/file/gridlog.log'` | ログを出力するファイル。OS のファイルパスと互換性があることを確認してください。 | -| `--log-level` | string | `“INFO”` | ログレベル。デフォルトは INFO です。 ログレベルはこちらを参照してください。 https://docs.oracle.com/javase/7/docs/api/java/util/logging/Level.html | +| `--log-level` | string | `“INFO”` | ログレベル。デフォルトは INFO です。 ログレベルはこちらを参照してください。 https://docs.oracle.com/en/java/javase/11/docs/api/java.logging/java/util/logging/Level.html | | `--plain-logs` | boolean | `true` | プレーンなログを使用します。 | | `--structured-logs` | boolean | `false` | 構造化ログを使用します。 | | `--tracing` | boolean | `true` | トレースを有効にします。 | diff --git a/website_and_docs/content/documentation/grid/configuration/cli_options.pt-br.md b/website_and_docs/content/documentation/grid/configuration/cli_options.pt-br.md index e179241b7dd9..0ca074b58e04 100644 --- a/website_and_docs/content/documentation/grid/configuration/cli_options.pt-br.md +++ b/website_and_docs/content/documentation/grid/configuration/cli_options.pt-br.md @@ -196,7 +196,7 @@ e esteja à vontade para nos enviar um pull request com alterações a esta pág | `--http-logs` | boolean | `false` | Enable http logging. Tracing should be enabled to log http logs. | | `--log-encoding` | string | `UTF-8` | Log encoding | | `--log` | string | Windows path example :
`'\path\to\file\gridlog.log'`
or
`'C:\path\path\to\file\gridlog.log'`

Linux/Unix/MacOS path example :
`'/path/to/file/gridlog.log'` | File to write out logs. Ensure the file path is compatible with the operating system's file path. | -| `--log-level` | string | `“INFO”` | Log level. Default logging level is INFO. Log levels are described here https://docs.oracle.com/javase/7/docs/api/java/util/logging/Level.html | +| `--log-level` | string | `“INFO”` | Log level. Default logging level is INFO. Log levels are described here https://docs.oracle.com/en/java/javase/11/docs/api/java.logging/java/util/logging/Level.html | | `--plain-logs` | boolean | `true` | Use plain log lines | | `--structured-logs` | boolean | `false` | Use structured logs | | `--tracing` | boolean | `true` | Enable trace collection | diff --git a/website_and_docs/content/documentation/grid/configuration/cli_options.zh-cn.md b/website_and_docs/content/documentation/grid/configuration/cli_options.zh-cn.md index 036bc920caba..27b92048a91b 100644 --- a/website_and_docs/content/documentation/grid/configuration/cli_options.zh-cn.md +++ b/website_and_docs/content/documentation/grid/configuration/cli_options.zh-cn.md @@ -203,7 +203,7 @@ pull request updating this page. | `--http-logs` | boolean | `false` | Enable http logging. Tracing should be enabled to log http logs. | | `--log-encoding` | string | `UTF-8` | Log encoding | | `--log` | string | Windows path example :
`'\path\to\file\gridlog.log'`
or
`'C:\path\path\to\file\gridlog.log'`

Linux/Unix/MacOS path example :
`'/path/to/file/gridlog.log'` | File to write out logs. Ensure the file path is compatible with the operating system's file path. | -| `--log-level` | string | `“INFO”` | Log level. Default logging level is INFO. Log levels are described here https://docs.oracle.com/javase/7/docs/api/java/util/logging/Level.html | +| `--log-level` | string | `“INFO”` | Log level. Default logging level is INFO. Log levels are described here https://docs.oracle.com/en/java/javase/11/docs/api/java.logging/java/util/logging/Level.html | | `--plain-logs` | boolean | `true` | Use plain log lines | | `--structured-logs` | boolean | `false` | Use structured logs | | `--tracing` | boolean | `true` | Enable trace collection | diff --git a/website_and_docs/content/documentation/grid/configuration/toml_options.zh-cn.md b/website_and_docs/content/documentation/grid/configuration/toml_options.zh-cn.md index 241731148561..ecda44aa766d 100644 --- a/website_and_docs/content/documentation/grid/configuration/toml_options.zh-cn.md +++ b/website_and_docs/content/documentation/grid/configuration/toml_options.zh-cn.md @@ -110,8 +110,8 @@ webdriver-executable = '/path/to/chromedriver/95/chromedriver' 则最多有2个并发会话. 原型配置需要映射一个Docker映像, Docker的守护进程需要通过http/tcp公开. -此外,可以通过 `devices` 属性定义在主机上可访问的哪些设备文件将在容器中可用。 -有关 docker 设备映射如何工作的更多信息,请参阅 [docker](https://docs.docker.com/engine/reference/commandline/run/#add-host-device-to-container---device) 文档。 +此外, 可以通过 `devices` 属性定义在主机上可访问的哪些设备文件将在容器中可用. +有关 docker 设备映射如何工作的更多信息, 请参阅 [docker](https://docs.docker.com/engine/reference/commandline/run/#add-host-device-to-container---device) 文档. ```toml [node] @@ -182,12 +182,11 @@ HttpCommandExecutor executor = new HttpCommandExecutor(clientConfig); RemoteWebDriver driver = new RemoteWebDriver(executor, new ChromeOptions()); ``` -In other languages, you can use the URL http://admin:myStrongPassword@localhost:4444 +在其他语言中, 您可以使用 URL http://admin:myStrongPassword@localhost:4444 -### Setting custom capabilities for matching specific Nodes +### 为匹配特定节点设置自定义功能 -**Important:** Custom capabilities need to be set in the configuration in all Nodes. They also -need to be included always in every session request. +**重要提示:** 自定义功能需要在所有节点的配置中进行设置. 并且在每次会话请求中都必须包含这些功能. ```toml [node] @@ -199,7 +198,7 @@ stereotype = '{"browserName": "firefox", "platformName": "macOS", "browserVersio max-sessions = 5 ``` -Here is a Java example showing how to match that Node +这里有一个 Java 示例, 展示了如何匹配那个节点 ```java FirefoxOptions options = new FirefoxOptions(); @@ -212,14 +211,16 @@ driver.get("https://selenium.dev/"); driver.quit(); ``` -### Enabling Managed downloads by the Node. +### 启用节点的托管下载功能. -The Node can be instructed to manage downloads automatically. This will cause the Node to save all files that were downloaded for a particular session into a temp directory, which can later be retrieved from the node. -To turn this capability on, use the below configuration: +节点可以被设置为自动管理下载. +这将导致节点会把特定会话中下载的所有文件保存到一个临时目录中, +之后可以从节点中获取这些文件. +要启用此功能, 请使用以下配置: ```toml [node] enable-managed-downloads = true ``` -Refer to the [CLI section]({{< ref "cli_options.md#enabling-managed-downloads-by-the-node" >}}) for a complete example. \ No newline at end of file +有关完整示例, 请参阅[CLI章节]({{< ref "cli_options.md#enabling-managed-downloads-by-the-node" >}}) . \ No newline at end of file diff --git a/website_and_docs/content/documentation/legacy/selenium_ide/_index.ja.md b/website_and_docs/content/documentation/legacy/selenium_ide/_index.ja.md index 387fad87d05f..dcef8026d4dd 100644 --- a/website_and_docs/content/documentation/legacy/selenium_ide/_index.ja.md +++ b/website_and_docs/content/documentation/legacy/selenium_ide/_index.ja.md @@ -664,7 +664,7 @@ id 属性に一致する要素がない場合には、name 属性を持つ要素 ### Nameによる特定 -name ロケータタイプは、nama 属性に一致する最初の要素を特定します。 +name ロケータタイプは、name 属性に一致する最初の要素を特定します。 1つの name 属性に対して、複数の要素が同じ値を持っている場合には、フィルタを使ってロケーションストラテジーの精度を高めることができます。 デフォルトのフィルタタイプは value です (value 属性に一致)。 diff --git a/website_and_docs/content/documentation/selenium_manager.en.md b/website_and_docs/content/documentation/selenium_manager.en.md index 0ae0bd890b8b..0387593248b1 100644 --- a/website_and_docs/content/documentation/selenium_manager.en.md +++ b/website_and_docs/content/documentation/selenium_manager.en.md @@ -221,9 +221,9 @@ INFO Browser path: C:\Users\boni\.cache\selenium\chrome\win64\117.0.5938.22\c {{< tabpane text=true >}} {{% tab header="Java" %}} **Previously** -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/selenium_manager/SeleniumManagerUsageDemo.java#L10-L15" >}} +{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/selenium_manager/SeleniumManagerUsageDemo.java#L12-L17" >}} **Selenium Manager** -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/selenium_manager/SeleniumManagerUsageDemo.java#L18-L22" >}} +{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/selenium_manager/SeleniumManagerUsageDemo.java#L20-L24" >}} {{< /tab >}} {{% tab header="Python" %}} **Previously** @@ -231,14 +231,20 @@ INFO Browser path: C:\Users\boni\.cache\selenium\chrome\win64\117.0.5938.22\c **Selenium Manager** {{< gh-codeblock path="examples/python/tests/selenium_manager/usage.py#L10-L12" >}} {{< /tab >}} -{{< tab header="CSharp" >}} -{{< badge-code >}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="examples/dotnet/SeleniumDocs/SeleniumManager/UsageTest.cs#L10-L18" >}} {{< /tab >}} -{{< tab header="Ruby" >}} -{{< badge-code >}} +{{% tab header="Ruby" %}} +**Previously** +{{< gh-codeblock path="examples/ruby/spec/selenium_manager/usage.rb#L5-L10" >}} +**Selenium Manager** +{{< gh-codeblock path="examples/ruby/spec/selenium_manager/usage.rb#L12-L16" >}} {{< /tab >}} -{{< tab header="JavaScript" >}} -{{< badge-code >}} +{{% tab header="JavaScript" %}} +**Previously** +{{< gh-codeblock path="examples/javascript/test/selenium_manager/usage.spec.js#L16-L31" >}} +**Selenium Manager** +{{< gh-codeblock path="examples/javascript/test/selenium_manager/usage.spec.js#L6-L14" >}} {{< /tab >}} {{< tab header="Kotlin" >}} {{< badge-code >}} @@ -344,7 +350,6 @@ The following environment variables are supported: * `SE_EDGEDRIVER` * `SE_GECKODRIVER` * `SE_IEDRIVER` -* `SE_SAFARIDRIVER` For example, to specify the path to the chromedriver, you can set the `SE_CHROMEDRIVER` environment variable to the path of the chromedriver executable. diff --git a/website_and_docs/content/documentation/selenium_manager.ja.md b/website_and_docs/content/documentation/selenium_manager.ja.md index f52274f03364..c59adc7c83f2 100644 --- a/website_and_docs/content/documentation/selenium_manager.ja.md +++ b/website_and_docs/content/documentation/selenium_manager.ja.md @@ -221,9 +221,9 @@ INFO Browser path: C:\Users\boni\.cache\selenium\chrome\win64\117.0.5938.22\c {{< tabpane text=true >}} {{% tab header="Java" %}} **Previously** -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/selenium_manager/SeleniumManagerUsageDemo.java#L10-L15" >}} +{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/selenium_manager/SeleniumManagerUsageDemo.java#L12-L17" >}} **Selenium Manager** -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/selenium_manager/SeleniumManagerUsageDemo.java#L18-L22" >}} +{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/selenium_manager/SeleniumManagerUsageDemo.java#L20-L24" >}} {{< /tab >}} {{% tab header="Python" %}} **Previously** @@ -231,14 +231,20 @@ INFO Browser path: C:\Users\boni\.cache\selenium\chrome\win64\117.0.5938.22\c **Selenium Manager** {{< gh-codeblock path="examples/python/tests/selenium_manager/usage.py#L10-L12" >}} {{< /tab >}} -{{< tab header="CSharp" >}} -{{< badge-code >}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="examples/dotnet/SeleniumDocs/SeleniumManager/UsageTest.cs#L10-L18" >}} {{< /tab >}} -{{< tab header="Ruby" >}} -{{< badge-code >}} +{{% tab header="Ruby" %}} +**Previously** +{{< gh-codeblock path="examples/ruby/spec/selenium_manager/usage.rb#L5-L10" >}} +**Selenium Manager** +{{< gh-codeblock path="examples/ruby/spec/selenium_manager/usage.rb#L12-L16" >}} {{< /tab >}} -{{< tab header="JavaScript" >}} -{{< badge-code >}} +{{% tab header="JavaScript" %}} +**Previously** +{{< gh-codeblock path="examples/javascript/test/selenium_manager/usage.spec.js#L16-L31" >}} +**Selenium Manager** +{{< gh-codeblock path="examples/javascript/test/selenium_manager/usage.spec.js#L6-L14" >}} {{< /tab >}} {{< tab header="Kotlin" >}} {{< badge-code >}} @@ -344,7 +350,6 @@ The following environment variables are supported: * `SE_EDGEDRIVER` * `SE_GECKODRIVER` * `SE_IEDRIVER` -* `SE_SAFARIDRIVER` For example, to specify the path to the chromedriver, you can set the `SE_CHROMEDRIVER` environment variable to the path of the chromedriver executable. diff --git a/website_and_docs/content/documentation/selenium_manager.pt-br.md b/website_and_docs/content/documentation/selenium_manager.pt-br.md index f52274f03364..c59adc7c83f2 100644 --- a/website_and_docs/content/documentation/selenium_manager.pt-br.md +++ b/website_and_docs/content/documentation/selenium_manager.pt-br.md @@ -221,9 +221,9 @@ INFO Browser path: C:\Users\boni\.cache\selenium\chrome\win64\117.0.5938.22\c {{< tabpane text=true >}} {{% tab header="Java" %}} **Previously** -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/selenium_manager/SeleniumManagerUsageDemo.java#L10-L15" >}} +{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/selenium_manager/SeleniumManagerUsageDemo.java#L12-L17" >}} **Selenium Manager** -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/selenium_manager/SeleniumManagerUsageDemo.java#L18-L22" >}} +{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/selenium_manager/SeleniumManagerUsageDemo.java#L20-L24" >}} {{< /tab >}} {{% tab header="Python" %}} **Previously** @@ -231,14 +231,20 @@ INFO Browser path: C:\Users\boni\.cache\selenium\chrome\win64\117.0.5938.22\c **Selenium Manager** {{< gh-codeblock path="examples/python/tests/selenium_manager/usage.py#L10-L12" >}} {{< /tab >}} -{{< tab header="CSharp" >}} -{{< badge-code >}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="examples/dotnet/SeleniumDocs/SeleniumManager/UsageTest.cs#L10-L18" >}} {{< /tab >}} -{{< tab header="Ruby" >}} -{{< badge-code >}} +{{% tab header="Ruby" %}} +**Previously** +{{< gh-codeblock path="examples/ruby/spec/selenium_manager/usage.rb#L5-L10" >}} +**Selenium Manager** +{{< gh-codeblock path="examples/ruby/spec/selenium_manager/usage.rb#L12-L16" >}} {{< /tab >}} -{{< tab header="JavaScript" >}} -{{< badge-code >}} +{{% tab header="JavaScript" %}} +**Previously** +{{< gh-codeblock path="examples/javascript/test/selenium_manager/usage.spec.js#L16-L31" >}} +**Selenium Manager** +{{< gh-codeblock path="examples/javascript/test/selenium_manager/usage.spec.js#L6-L14" >}} {{< /tab >}} {{< tab header="Kotlin" >}} {{< badge-code >}} @@ -344,7 +350,6 @@ The following environment variables are supported: * `SE_EDGEDRIVER` * `SE_GECKODRIVER` * `SE_IEDRIVER` -* `SE_SAFARIDRIVER` For example, to specify the path to the chromedriver, you can set the `SE_CHROMEDRIVER` environment variable to the path of the chromedriver executable. diff --git a/website_and_docs/content/documentation/selenium_manager.zh-cn.md b/website_and_docs/content/documentation/selenium_manager.zh-cn.md index f52274f03364..6c71645150dd 100644 --- a/website_and_docs/content/documentation/selenium_manager.zh-cn.md +++ b/website_and_docs/content/documentation/selenium_manager.zh-cn.md @@ -1,113 +1,188 @@ --- -title: "Selenium Manager (Beta)" +title: "Selenium Manager (测试版)" linkTitle: "Selenium Manager" weight: 3 description: > - Selenium Manager is a command-line tool implemented in Rust that provides automated driver and browser management for Selenium. Selenium bindings use this tool by default, so you do not need to download it or add anything to your code or do anything else to use it. + Selenium Manager 是一个用 Rust 语言实现的命令行工具, 为 Selenium 提供了自动化的驱动程序和浏览器管理功能. Selenium 默认绑定使用此工具, 因此您无需下载它, 也不需要在代码中添加任何内容或执行其他操作即可使用它. --- -## Motivation -***TL;DR:*** *Selenium Manager is the official driver manager of the Selenium project, and it is shipped out of the box with every Selenium release.* - -Selenium uses the native support implemented by each browser to carry out the automation process. For this reason, Selenium users need to place a component called _driver_ (chromedriver, geckodriver, msedgedriver, etc.) between the script using the Selenium API and the browser. For many years, managing these drivers was a manual process for Selenium users. This way, they had to download the required driver for a browser (chromedriver for Chrome, geckodriver for Firefox, etc.) and place it in the `PATH` or export the driver path as a system property (Java, JavaScript, etc.). But this process was cumbersome and led to maintainability issues. - -Let's consider an example. Imagine you manually downloaded the required chromedriver for driving your Chrome with Selenium. When you did this process, the stable version of Chrome was 113, so you downloaded chromedriver 113 and put it in your `PATH`. At that moment, your Selenium script executed correctly. But the *problem* is that Chrome is *evergreen*. This name refers to Chrome's ability to upgrade automatically and silently to the next stable version when available. This feature is excellent for end-users but potentially dangerous for browser automation. Let's go back to the example to discover it. Your local Chrome eventually updates to version 115. And that moment, your Selenium script is broken due to the incompatibility between the manually downloaded driver (113) and the Chrome version (115). Thus, your Selenium script fails with the following error message: *"session not created: This version of ChromeDriver only supports Chrome version 113"*. - -This problem is the primary reason for the existence of the so-called *driver managers* (such as [WebDriverManager](https://bonigarcia.dev/webdrivermanager/) for Java, -[webdriver-manager](https://pypi.org/project/webdriver-manager/) for Python, [webdriver-manager](https://www.npmjs.com/package/webdriver-manager) for JavaScript, [WebDriverManager.Net](https://github.com/rosolko/WebDriverManager.Net) for C#, and [webdrivers](https://github.com/titusfortner/webdrivers) for Ruby). All these projects were an inspiration and a clear sign that the community needed this feature to be built in Selenium. Thus, the Selenium project has created *Selenium Manager*, the official driver manager for Selenium, shipped out of the box with each Selenium release as of version 4.6. - -## Usage -***TL;DR:*** *Selenium Manager is used by the Selenium bindings when the drivers (chromedriver, geckodriver, etc.) are unavailable.* - -Driver management through Selenium Manager is *opt-in* for the Selenium bindings. Thus, users can continue managing their drivers manually (putting the driver in the `PATH` or using system properties) or rely on a third-party *driver manager* to do it automatically. Selenium Manager only operates as a fallback: if no driver is provided, Selenium Manager will come to the rescue. - -Selenium Manager is a CLI (command line interface) tool implemented in Rust to allow cross-platform execution and compiled for Windows, Linux, and macOS. The Selenium Manager binaries are shipped with each Selenium release. This way, each Selenium binding language invokes Selenium Manager to carry out the automated driver and browser management explained in the following sections. - -## Automated driver management -***TL;DR:*** *Selenium Manager automatically discovers, downloads, and caches the drivers required by Selenium when these drivers are unavailable.* - -The primary feature of Selenium Manager is called *automated driver management*. Let's consider an example to understand it. Suppose we want to driver Chrome with Selenium (see the doc about how to [start a session with Selenium](https://www.selenium.dev/documentation/webdriver/getting_started/first_script/#1-start-the-session)). Before the session begins, and when the driver is unavailable, Selenium Manager manages chromedriver for us. We use the term *management* for this feature (and not just *download*) since this process is broader and implies different steps: - -1. Browser version discovery. Selenium Manager discovers the browser version (e.g., Chrome, Firefox, Edge) installed in the machine that executes Selenium. This step uses shell commands (e.g., `google-chrome --version`). -2. Driver version discovery. With the discovered browser version, the proper driver version is resolved. For this step, the online metadata/endpoints maintained by the browser vendors (e.g., [chromedriver](https://chromedriver.chromium.org/downloads), [geckodriver](https://github.com/mozilla/geckodriver/releases), or [msedgedriver](https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/)) are used. -3. Driver download. The driver URL is obtained with the resolved driver version; with that URL, the driver artifact is downloaded, uncompressed, and stored locally. -4. Driver cache. Uncompressed driver binaries are stored in a local cache folder (`~/.cache/selenium`). The next time the same driver is required, it will be used from there if the driver is already in the cache. - -## Automated browser management -***TL;DR:*** *Selenium Manager automatically discovers, downloads, and caches the browsers driven with Selenium (Chrome, Firefox, and Edge) when these browsers are not installed in the local system.* - -As of Selenium 4.11.0, Selenium Manager also implements *automated browser management*. With this feature, Selenium Manager allows us to discover, download, and cache the different browser releases, making them seamlessly available for Selenium. Internally, Selenium Manager uses an equivalent management procedure explained in the section before, but this time, for browser releases. - -The browser automatically managed by Selenium Manager are: - -- Chrome. Based on [Chrome for Testing (CfT)](https://googlechromelabs.github.io/chrome-for-testing/), as of Selenium 4.11.0. -- Firefox. Based on [public Firefox releases](https://ftp.mozilla.org/pub/firefox/releases/), as of Selenium 4.12.0. -- Edge. Based on [Edge downloads](https://www.microsoft.com/en-us/edge/download), as of Selenium 4.14.0. - -Let's consider again the typical example of driving Chrome with Selenium. And this time, suppose Chrome is not installed on the local machine when [starting a new session](https://www.selenium.dev/documentation/webdriver/getting_started/first_script/#1-start-the-session)). In that case, the current stable CfT release will be discovered, downloaded, and cached (in `~/.cache/selenium/chrome`) by Selenium Manager. - -But there is more. In addition to the stable browser version, Selenium Manager also allows downloading older browser versions (in the case of CfT, starting in version 113, the first version published as CfT). To set a browser version with Selenium, we use a browser option called [browserVersion](https://www.selenium.dev/documentation/webdriver/drivers/options/#browserversion). - -Let's consider another simple example. Suppose we set `browserVersion` to `114` using [Chrome options](https://www.selenium.dev/documentation/webdriver/browsers/chrome/). In this case, Selenium Manager will check if Chrome 114 is already installed. If it is, it will be used. If not, Selenium Manager will manage (i.e., discover, download, and cache) CfT 114. And in either case, the chromedriver is also managed. Finally, Selenium will start Chrome to be driven programmatically, as usual. - -But there is even more. In addition to fixed browser versions (e.g., `113`, `114`, `115`, etc.), we can use the following labels for `browserVersion`: - -- `stable`: Current CfT version. -- `beta`: Next version to stable. -- `dev`: Version in development at this moment. -- `canary`: Nightly build for developers. -- `esr`: Extended Support Release (only for Firefox). - -When these labels are specified, Selenium Manager first checks if a given browser is already installed (`beta`, `dev`, etc.), and when it is not detected, the browser is automatically managed. - -### Edge in Windows -Automated Edge management by Selenium Manager in Windows is different from other browsers. Both Chrome and Firefox (and Edge in macOS and Linux) are downloaded automatically to the local cache (`~/.cache/selenium`) by Selenium Manager. Nevertheless, the same cannot be done for Edge in Windows. The reason is that the Edge installer for Windows is distributed as a Microsoft Installer (MSI) file, designed to be executed with administrator rights. This way, when Edge is attempted to be installed with Selenium Manager in Windows with a non-administrator session, a warning message will be displayed by Selenium Manager as follows: +## 动机 +***简而言之:*** +*Selenium Manager 是 Selenium 项目的官方驱动程序管理器, 并且在每次 Selenium 发布时都会随附提供.* + +Selenium 利用每个浏览器实现的原生支持来执行自动化流程. +因此, Selenium 用户需要在使用 Selenium API 的脚本和浏览器之间放置一个名为 _驱动程序_(如 chromedriver、geckodriver、msedgedriver 等)的组件. +多年来, 管理这些驱动程序, 对Selenium 用户来说, 一直是个繁琐手动过程. +他们必须下载浏览器所需的驱动程序(如 Chrome 的 chromedriver、Firefox 的 geckodriver 等), +并将其放置在 `PATH` 中或以系统属性的形式导出驱动程序路径(如 Java、JavaScript 等). +但这种过程很麻烦, 导致了可维护性问题. + +让我们来看一个例子. +假设您手动下载了用于通过 Selenium 驱动 Chrome 的所需 chromedriver. +在执行此操作时, Chrome 的稳定版本是 113, +所以您下载了 chromedriver 113 并将其放在您的 `PATH` 中. +此时, 您的 Selenium 脚本执行正确. 但 *问题* 在于 Chrome 是 *保持更新* 的. +这指的是 Chrome 能够在有新版本可用时自动且静默地升级到下一个稳定版本. +此功能对终端用户来说很棒, 但对浏览器自动化来说可能很危险. +让我们回到这个例子来明确这一点. +当您本地的 Chrome 最终更新到了 115 版本. +此时, 由于手动下载的驱动程序(113 版)与 Chrome 版本(115 版)不兼容, +您的 Selenium 脚本出错了. +因此, 您的 Selenium 脚本会因以下错误消息而失败: +*“会话无法创建: 此版本的 ChromeDriver 仅支持 Chrome 版本 113”*. + + +这个问题是所谓的驱动管理器(例如 Java 的 [WebDriverManager](https://bonigarcia.dev/webdrivermanager/) 、 +Python 的 [webdriver-manager](https://pypi.org/project/webdriver-manager/) 、 +JavaScript 的 [webdriver-manager](https://www.npmjs.com/package/webdriver-manager) 、 +C# 的 [WebDriverManager.Net](https://github.com/rosolko/WebDriverManager.Net) 以及 Ruby 的 [webdrivers](https://github.com/titusfortner/webdrivers) +存在的主要原因. +所有这些项目都是一种启示, +也清楚地表明社区需要将此功能内置到 Selenium 中. +因此, Selenium 项目创建了 *Selenium Manager*, +这是 Selenium 的官方驱动管理器, 从 4.6 版本开始, 它随每个 Selenium 发行版一起提供. + + +## 用法 +***简而言之:*** +*当驱动程序(如 ChromeDriver、GeckoDriver 等)不可用时, Selenium 绑定会使用 Selenium Manager.* + +通过 Selenium Manager 进行驱动程序管理是 Selenium 绑定的 *可选功能* . +因此, 用户可以继续手动管理其驱动程序(将驱动程序放在 `PATH` 中或使用系统属性), +也可以依靠第三方 *驱动程序管理器* 自动完成. +Selenium Manager 仅作为备用方案: +如果未提供驱动程序, Selenium Manager 将会介入. + +Selenium Manager 是一个用 Rust 语言实现的命令行界面(CLI)工具, +可于 Windows、Linux 和 macOS 等多种操作系统上跨平台运行. +Selenium Manager 的二进制文件随每个 Selenium 版本一起发布. +这样, 每个 Selenium 绑定语言都会调用 Selenium Manager 来执行以下各节中所述的自动化驱动程序和浏览器管理. + +## Automated driver management 自动驱动管理 +***简而言之:*** +*当所需驱动程序不可用时, Selenium Manager 会自动寻找、下载并缓存 Selenium 所需的驱动程序.* + +Selenium Manager 的主要特性被称为 *自动驱动管理* . +让我们通过一个例子来理解它. 假设我们想用 Selenium 驱动 Chrome(请参阅关于如何[使用Selenium启动会话](https://www.selenium.dev/documentation/webdriver/getting_started/first_script/#1-start-the-session)的文档). +在会话开始之前, 如果驱动程序不可用, Selenium Manager 会为我们管理 chromedriver. +我们用 *管理* 这个词来描述此功能(而不仅仅是 *下载* ), 因为这个过程更广泛, 包含不同的步骤: + +1. 探索浏览器版本. Selenium Manager 会发现执行 Selenium 的机器上安装的浏览器版本(例如, Chrome、Firefox、Edge). 此步骤使用 shell 命令(例如, `google-chrome --version` ). +2. 寻找驱动程序版本. 通过探索过的浏览器版本, 确定合适的驱动程序版本. 在此步骤中, 使用由浏览器供应商维护的在线元数据/端点(例如, [chromedriver](https://chromedriver.chromium.org/downloads), [geckodriver](https://github.com/mozilla/geckodriver/releases), 或 [msedgedriver](https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/)). +3. 驱动下载. 通过解析出的驱动程序版本获取驱动程序的 URL;利用该 URL 下载驱动程序文件, 解压后将其存储在本地. +4. 驱动程序缓存. 未压缩的驱动程序二进制文件存储在本地缓存文件夹( `~/.cache/selenium` )中. 下次需要相同的驱动程序时, 如果该驱动程序已在缓存中, 则将从那里使用. + + +## 自动化浏览器管理 +***简而言之:*** +*当本地系统未安装 Selenium 驱动的浏览器(Chrome、Firefox 和 Edge)时, Selenium Manager 会自动发现、下载并缓存这些浏览器.* + +从 Selenium 4.11.0 版本开始, Selenium Manager 还实现了 *自动浏览器管理*. +借助此功能, Selenium Manager 能够发现、下载并缓存不同浏览器的版本, +使其能够无缝地供 Selenium 使用. +在内部, Selenium Manager 使用了与前一节所述类似的管理流程, 但这次是针对浏览器版本的. + +Selenium Manager 自动管理的浏览器有: + +- Chrome浏览器, 基于 [Chrome for Testing (CfT)](https://googlechromelabs.github.io/chrome-for-testing/), 自 Selenium 4.11.0 版本起. +- 火狐浏览器. 基于[public Firefox releases](https://ftp.mozilla.org/pub/firefox/releases/), 自 Selenium 4.12.0 版本. +- Edge浏览器, 基于 [Edge downloads](https://www.microsoft.com/en-us/edge/download), 自 Selenium 4.14.0 版本. + +让我们再次考虑用 Selenium 驱动 Chrome 的典型示例. +这一次, 假设在[启动新会话](https://www.selenium.dev/documentation/webdriver/getting_started/first_script/#1-start-the-session)时本地机器上未安装 Chrome. +在这种情况下, Selenium Manager会发现、下载并缓存当前的稳定版 Chrome 浏览器(在 `~/.cache/selenium/chrome` 中). + +但不仅如此. 除了稳定的浏览器版本, +Selenium Manager 还允许下载旧版浏览器(对于 Chrome for Testing 而言, +从 113 版本开始, 这是作为 Chrome for Testing 发布的第一个版本). +要使用 Selenium 设置浏览器版本, 我们使用一个名为 [browserVersion](https://www.selenium.dev/documentation/webdriver/drivers/options/#browserversion) 的浏览器选项. + +让我们考虑另一个简单的例子. +假设我们使用 [Chrome options](https://www.selenium.dev/documentation/webdriver/browsers/chrome/) 将 `browserVersion` 设置为 `114` . +在这种情况下, Selenium Manager会检查是否已安装 Chrome 114 版本. +如果已安装, 就会使用它. 如果没有安装, Selenium Manager会进行管理(即发现、下载并缓存)Chrome 114 版本. +无论哪种情况, chromedriver 也会被管理. 最后, Selenium 会像往常一样启动 Chrome 以实现程序化驱动. + +但还有更多. 除了固定的浏览器版本(例如, `113`, `114`, `115` 等), +我们还可以为 `browserVersion` 使用以下标签: + +- `stable`: 当前 CfT 版本. +- `beta`: 下一个稳定版. +- `dev`: 当前正在开发的版本. +- `canary`: 面向开发者的夜间构建版本. +- `esr`: 扩展支持版本(仅适用于 Firefox 浏览器). + +当指定了这些标签时, Selenium Manager首先会检查给定的浏览器是否已安装( `beta`, `dev` 等), +如果未检测到, 则会自动管理该浏览器. + +### Windows中的Edge + +在 Windows 系统中, Selenium Manager 对 Edge 的自动化边缘管理与其他浏览器有所不同. +对于 Chrome 和 Firefox(以及 macOS 和 Linux 系统中的 Edge), +Selenium Manager 会自动将其下载到本地缓存( `~/.cache/selenium` ). +然而, 在 Windows 系统中, Edge 却无法实现同样的操作. +原因在于 Windows 版本的 Edge 安装程序是以微软安装程序(MSI)文件的形式分发的, +需要以管理员权限执行. +因此, 当在 Windows 系统中使用非管理员权限会话通过 Selenium Manager 安装 Edge 时, +Selenium Manager 会显示如下警告信息: ``` edge can only be installed in Windows with administrator permissions ``` -Therefore, administrator permissions are required to install Edge in Windows automatically through Selenium Manager, and Edge is eventually installed in the usual program files folder (e.g., `C:\Program Files (x86)\Microsoft\Edge`). +因此, 通过 Selenium Manager 在 Windows 系统中自动安装 Edge 浏览器需要管理员权限, +并且 Edge 最终会被安装在通常的程序文件夹中(例如 `C:\Program Files (x86)\Microsoft\Edge` ). -## Data collection -Selenium Manager will report anonymised usage [statistics](https://plausible.io/privacy-focused-web-analytics) to [Plausible](https://plausible.io/manager.selenium.dev). This allows the Selenium team to understand more about how Selenium is being used so that we can better focus our development efforts. The data being collected is: +## 数据收集 +Selenium Manager会向 [Plausible](https://plausible.io/manager.selenium.dev) 报送匿名使用[statistics](https://plausible.io/privacy-focused-web-analytics) 数据. +这能让 Selenium 团队更深入地了解 Selenium 的使用情况, +从而更好地集中我们的开发精力. 所收集的数据包括: -| Data | Purpose | -| -----|---------| -| Selenium version | This allows the Selenium developers to safely deprecate and remove features, as well as determine which new features may be available to you | -| Language binding | Programming language used to execute Selenium scripts (Java, JavaScript, Python, .Net, Ruby) | -| OS and architecture Selenium Manager is running on | The Selenium developers can use this information to help prioritise bug reports, and to identify if there are systemic OS-related issues | -| Browser and browser version | Helping for prioritising bug reports | -| Rough geolocation | Derived from the IP address you connect from. This is useful for determining where we need to focus our documentation efforts | +| Data | Purpose | +|-------------------------------|---------| +| Selenium 版本 | 这使得 Selenium 开发人员能够安全地弃用和移除功能, 并确定哪些新功能可能对您可用. | +| 语言绑定 | 用于执行 Selenium 脚本的编程语言(Java、JavaScript、Python、.Net、Ruby)| +| Selenium Manager 正在运行的操作系统和架构 | Selenium 开发人员可以利用这些信息来帮助确定错误报告的优先级, 并识别是否存在系统性的与操作系统相关的故障. | +| 浏览器及浏览器版本 | 协助确定错误报告的优先级 | +| 大致地理位置 | 根据您连接的 IP 地址得出. 这有助于我们确定需要在哪些地区集中文档编写工作. | -Selenium Manager sends these data to Plausible once a day. This period is based on the TTL value (see [configuration](https://www.selenium.dev/documentation/selenium_manager/#configuration)). +Selenium Manager 每天会将这些数据发送给 Plausible 一次. +此周期基于 TTL 值(请参阅[configuration](https://www.selenium.dev/documentation/selenium_manager/#configuration)). -### Opting out of data collection -**Data collection is on by default.** To disable it, set the `SE_AVOID_STATS` environment variable to `true`. You may also disable data collection in the configuration file (see below) by setting `avoid-stats = true`. +### 选择退出数据收集 +**默认情况下会收集数据.** 若要禁用数据收集, 请将 `SE_AVOID_STATS` 环境变量设置 `true`. +您也可以在配置文件中(见下文)通过设置 `avoid-stats = true` 来禁用数据收集. -## Configuration -***TL;DR:*** *Selenium Manager should work silently and transparently for most users. Nevertheless, there are scenarios (e.g., to specify a custom cache path or setup globally a proxy) where custom configuration can be required.* +## 配置 +***简而言之:*** +*对于大多数用户而言, Selenium Manager 应该能静默且透明地运行. 不过, 在某些场景下(例如指定自定义缓存路径或全局设置代理), 可能需要自定义配置.* -Selenium Manager is a CLI tool. Therefore, under the hood, the Selenium bindings call Selenium Manager by invoking shell commands. Like any other CLI tool, arguments can be used to specify specific capabilities in Selenium Manager. The different arguments supported by Selenium Manager can be checked by running the following command: +Selenium Manager 是一个命令行界面(CLI)工具. +因此, 在底层, Selenium 绑定通过调用 shell 命令来调用 Selenium Manager. +和任何其他 CLI 工具一样, 可以使用参数来指定 Selenium Manager 中的特定功能. +要查看 Selenium Manager 支持的不同参数, 可以运行以下命令: ``` $ ./selenium-manager --help ``` -In addition to CLI arguments, Selenium Manager allows two additional mechanisms for configuration: +除了命令行参数之外, Selenium Manager 还支持两种额外的配置机制: -- Configuration file. Selenium Manager uses a file called `se-config.toml` located in the Selenium cache (by default, at `~/.cache/selenium`) for custom configuration values. This TOML file contains a key-value collection used for custom configuration. -- Environmental variables. Each configuration key has its equivalence in environmental variables by converting each key name to uppercase, replacing the dash symbol (`-`) with an underscore (`_`), and adding the prefix `SE_`. +- 配置文件. Selenium Manager使用位于 Selenium 缓存中的一个名为 `se-config.toml` 的文件(默认情况下位于 `~/.cache/selenium` )来存储自定义配置值. 此 TOML 文件包含用于自定义配置的键值集合. +- 环境变量. 每个配置键在环境变量中都有对应的等效项, 方法是将每个键名转换为大写, 将破折号(`-`)替换为下划线(`_`), 并在前面加上前缀`SE_`. -The configuration file is honored by Selenium Manager when it is present, and the corresponding CLI parameter is not specified. Besides, the environmental variables are used when neither of the previous options (CLI arguments and configuration file) is specified. In other words, the order of preference for Selenium Manager custom configuration is as follows: +当存在配置文件且未指定相应的命令行参数时, Selenium Manager 会遵循该配置文件. +此外, 如果既未指定命令行参数也未提供配置文件, 则会使用环境变量. 换句话说, Selenium Manager 自定义配置的优先级顺序如下: -1. CLI arguments. -2. Configuration file. -3. Environment variables. +1. CLI参数. +2. 配置文件. +3. 环境变量. -Notice that the Selenium bindings use the CLI arguments to specify configuration values, which in turn, are defined in each binding using [browser options](https://www.selenium.dev/documentation/webdriver/drivers/options/). +请注意, Selenium 绑定使用命令行参数来指定配置值, +而这些配置值又在每个绑定中通过[browser options](https://www.selenium.dev/documentation/webdriver/drivers/options/)来定义. + +下表总结了 Selenium Manager 支持的所有参数及其在配置文件和环境变量中的对应键. -The following table summarizes all the supported arguments supported by Selenium Manager and their correspondence key in the configuration file and environment variables. | CLI argument| Configuration file | Env variable | Description | |-------------|--------------------|--------------|-------------| @@ -133,54 +208,80 @@ The following table summarizes all the supported arguments supported by Selenium |`--language-binding `|`language-binding = "LANGUAGE"`|`SE_LANGUAGE_BINDING=LANGUAGE`|Language that invokes Selenium Manager (e.g., Java, JavaScript, Python, DotNet, Ruby)| |`--avoid-stats`|`avoid-stats = true`|`SE_AVOID_STATS=true`|Avoid sends usage statistics to plausible.io. Default: `false`| -In addition to the configuration keys specified in the table before, there are some special cases, namely: +除了前面表格中指定的配置键之外, 还有一些特殊情况, 即: -- Browser version. In addition to `browser-version`, we can use the specific configuration keys to specify custom versions per supported browser. This way, the keys `chrome-version`, `firefox-version`, `edge-version`, etc., are supported. The same applies to environment variables (i.e., `SE_CHROME_VERSION`, `SE_FIREFOX_VERSION`, `SE_EDGE_VERSION`, etc.). -- Driver version. Following the same pattern, we can use `chromedriver-version`, `geckodriver-version`, `msedgedriver-version`, etc. (in the configuration file), and `SE_CHROMEDRIVER_VERSION`, `SE_GECKODRIVER_VERSION`, `SE_MSEDGEDRIVER_VERSION`, etc. (as environment variables). -- Browser path. Following the same pattern, we can use `chrome-path`, `firefox-path`, `edge-path`, etc. (in the configuration file), and `SE_CHROME_PATH`, `SE_FIREFOX_PATH`, `SE_EDGE_PATH`, etc. (as environment variables). The Selenium bindings also allow to specify a custom location of the browser path using options, namely: [Chrome](https://www.selenium.dev/documentation/webdriver/browsers/chrome/#start-browser-in-a-specified-location)), [Edge](https://www.selenium.dev/documentation/webdriver/browsers/edge/#start-browser-in-a-specified-location), or [Firefox](https://www.selenium.dev/documentation/webdriver/browsers/firefox/#start-browser-in-a-specified-location). -- Driver mirror. Following the same pattern, we can use `chromedriver-mirror-url`, `geckodriver-mirror-url`, `msedgedriver-mirror-url`, etc. (in the configuration file), and `SE_CHROMEDRIVER_MIRROR_URL`, `SE_GECKODRIVER_MIRROR_URL`, `SE_MSEDGEDRIVER_MIRROR_URL`, etc. (as environment variables). -- Browser mirror. Following the same pattern, we can use `chrome-mirror-url`, `firefox-mirror-url`, `edge-mirror-url`, etc. (in the configuration file), and `SE_CHROME_MIRROR_URL`, `SE_FIREFOX_MIRROR_URL`, `SE_EDGE_MIRROR_URL`, etc. (as environment variables). +- 浏览器版本. 除了 `browser-version` 之外, 我们还可以使用特定的配置键为每个受支持的浏览器指定自定义版本. 这样, 键 `chrome-version`, `firefox-version`, `edge-version` 等就得到了支持. 环境变量(即 `SE_CHROME_VERSION`, `SE_FIREFOX_VERSION`, `SE_EDGE_VERSION` 等)也是如此. +- 驱动程序版本. 遵循相同的模式, 我们可以在配置文件中使用 `chromedriver-version`, `geckodriver-version`, `msedgedriver-version`等, 在环境变量中使用 `SE_CHROMEDRIVER_VERSION`, `SE_GECKODRIVER_VERSION`, `SE_MSEDGEDRIVER_VERSION` 等. +- 浏览器路径. 遵循相同的模式, 我们可以在配置文件中使用 `chrome-path`, `firefox-path`, `edge-path` 等, 在环境变量中使用 `SE_CHROME_PATH`, `SE_FIREFOX_PATH`, `SE_EDGE_PATH`等. Selenium 绑定还允许使用选项指定浏览器路径的自定义位置, 例如: Chrome、Edge 或 Firefox. +- 驱动镜像. 遵循同样的模式, 我们可以在配置文件中使用 `chromedriver-mirror-url`, `geckodriver-mirror-url`, `msedgedriver-mirror-url` 等, 在环境变量中使用 `SE_CHROMEDRIVER_MIRROR_URL`, `SE_GECKODRIVER_MIRROR_URL`, `SE_MSEDGEDRIVER_MIRROR_URL` 等. +- 浏览器镜像. 遵循同样的模式, 我们可以在配置文件中使用 `chrome-mirror-url`, `firefox-mirror-url`, `edge-mirror-url` 等, 在环境变量中使用 `SE_CHROME_MIRROR_URL`, `SE_FIREFOX_MIRROR_URL`, `SE_EDGE_MIRROR_URL` 等. -### se-config.toml Example +### se-config.toml 示例 {{< tabpane text=true >}} {{< tab header="se-config.toml" >}} {{< gh-codeblock path="examples/python/tests/selenium_manager/example_se-config.toml#L1-L21" >}} {{< /tab >}} {{< /tabpane >}} -## Caching -***TL;DR:*** *The drivers and browsers managed by Selenium Manager are stored in a local folder (`~/.cache/selenium`).* +## 缓存 +***简而言之:*** +*由 Selenium Manager 管理的驱动程序和浏览器会存储在本地文件夹(`~/.cache/selenium` )中.* -The cache in Selenium Manager is a local folder (`~/.cache/selenium` by default) in which the downloaded assets (drivers and browsers) are stored. For the sake of performance, when a driver or browser is already in the cache (i.e., there is a *cache hint*), Selenium Manager uses it from there. +Selenium Manager中的缓存是一个本地文件夹(默认为 `~/.cache/selenium` ), 用于存储下载的资源(驱动程序和浏览器). +为了提高性能, 当驱动程序或浏览器已存在于缓存中(即存在 *缓存* 提示)时, Selenium Manager会从那里使用它们. -In addition to the downloaded drivers and browsers, two additional files live in the cache's root: +除了已下载的驱动程序和浏览器之外, 缓存根目录中还有两个额外的文件: -- Configuration file (`se-config.toml`). This file is optional and, as explained in the previous section, allows to store custom configuration values for Selenium Manager. This file is maintained by the end-user and read by Selenium Manager. -- Metadata file (`se-metadata.json`). This file contains versions discovered by Selenium Manger making network requests (e.g., using the [CfT JSON endpoints](https://github.com/GoogleChromeLabs/chrome-for-testing#json-api-endpoints)) and the time-to-live (TTL) in which they are valid. Selenium Manager automatically maintains this file. +- 配置文件( `se-config.toml` ). 此文件是可选的, 正如前一节所述, 它允许为 Selenium Manager 存储自定义配置值. 此文件由最终用户维护, 并由 Selenium Manager 读取. +- 元数据文件( `se-metadata.json` ). 此文件包含由 Selenium Manager通过网络请求(例如, 使用 [CfT JSON endpoints](https://github.com/GoogleChromeLabs/chrome-for-testing#json-api-endpoints))发现的版本以及它们有效的生存时间(TTL). Selenium Manager会自动维护此文件. -The TTL in Selenium Manager is inspired by the TTL for DNS, a well-known mechanism that refers to how long some values are cached before they are automatically refreshed. In the case of Selenium Manager, these values are the versions found by making network requests for driver and browser version discovery. By default, the TTL is `3600` seconds (i.e., 1 hour) and can be tuned using configuration values or disabled by setting this configuration value to `0`. +Selenium Manager 中的生存时间(TTL)借鉴了 DNS 的 TTL 机制, 这是一种广为人知的机制, +指的是某些值在被自动刷新之前被缓存的时长. +对于 Selenium Manager 而言, 这些值是通过网络请求获取的驱动程序和浏览器版本发现的结果. +默认情况下, TTL 为 3600 秒(即 1 小时), 并且可以通过配置值进行调整, 或者将其设置为 0 来禁用此功能. -The TTL mechanism is a way to improve the overall performance of Selenium. It is based on the fact that the discovered driver and browser versions (e.g., the proper chromedriver version for Chrome 115 is 115.0.5790.170) will likely remain the same in the short term. Therefore, the discovered versions are written in the metadata file and read from there instead of making the same consecutive network request. This way, during the driver version discovery (step 2 of the automated driver management process previously introduced), Selenium Manager first reads the file metadata. When a *fresh* resolution (i.e., a driver/browser version valid during a TTL) is found, that version is used (saving some time in making a new network request). If not found or the TTL has expired, a network request is made, and the result is stored in the metadata file. +TTL 机制是一种提升 Selenium 总体性能的方法. +它基于这样一个事实: 在短期内, 发现的驱动程序和浏览器版本(例如, 适用于 Chrome 115 的正确 chromedriver 版本是 115.0.5790.170)很可能保持不变. +因此, 发现的版本会被写入元数据文件, 并从那里读取, 而不是连续进行相同的网络请求. +这样, 在驱动程序版本发现过程中(之前介绍的自动化驱动程序管理流程的第 2 步), +Selenium Manager 首先读取元数据文件. 如果找到新的解决方案(即在 TTL 期间有效的驱动程序/浏览器版本), +则使用该版本(节省了进行新网络请求的时间). +如果未找到或 TTL 已过期, 则会进行网络请求, 并将结果存储在元数据文件中. -Let's consider an example. A Selenium binding asks Selenium Manager to resolve chromedriver. Selenium Manager detects that Chrome 115 is installed, so it makes a network request to the CfT endpoints to discover the proper chromedriver version (115.0.5790.170, at that moment). This version is stored in the metadata file and considered valid during the next hour (TTL). If Selenium Manager is asked to resolve chromedriver during that time (which is likely to happen in the execution of a test suite), the chromedriver version is discovered by reading the metadata file instead of making a new request to the CfT endpoints. After one hour, the chromedriver version stored in the cache will be considered as *stale*, and Selenium Manager will refresh it by making a new network request to the corresponding endpoint. +我们来看一个例子. +一个 Selenium 绑定请求 Selenium Manager解析 chromedriver. +Selenium Manager检测到已安装 Chrome 115 版本, +于是向 CfT 端点发出网络请求以确定合适的 chromedriver 版本(当时为 115.0.5790.170). +此版本会被存储在元数据文件中, 并在接下来的一小时内(TTL)被视为有效. +如果在此期间(在执行测试套件时很可能发生)再次请求 Selenium Manager解析 chromedriver, +那么将通过读取元数据文件来获取 chromedriver 版本, 而无需向 CfT 端点发出新的请求. 一小时后, +缓存中存储的 chromedriver 版本将被视为过期, Selenium Manager会通过向相应端点发出新的网络请求来刷新它. Selenium Manager includes two additional arguments two handle the cache, namely: +Selenium Manager包含两个用于处理缓存的附加参数, 分别是: -- `--clear-cache`: To remove the cache folder (equivalent to the environment variable `SE_CLEAR_CACHE=true`). -- `--clear-metadata`: To remove the metadata file (equivalent to the environment variable `SE_CLEAR_METADATA=true`). +- `--clear-cache`: 要删除缓存文件夹(相当于环境变量 `SE_CLEAR_CACHE=true` ). +- `--clear-metadata` : 删除元数据文件(相当于环境变量 `SE_CLEAR_METADATA=true` ). -## Versioning -Selenium Manager follows the same versioning schema as Selenium. Nevertheless, we use the major version 0 for Selenium Manager releases because it is still in beta. For example, the Selenium Manager binaries shipped with Selenium 4.12.0 corresponds to version 0.4.12. +## 版本控制 +Selenium Manager 采用与 Selenium 相同的版本命名规则. +不过, 由于 Selenium Manager 仍处于测试阶段, 因此其主版本号为 0. +例如, 与 Selenium 4.12.0 一同发布的 Selenium Manager 二进制文件对应的是 0.4.12 版本. -## Getting Selenium Manager -For most users, direct interaction with Selenium Manager is not required since the Selenium bindings use it internally. Nevertheless, if you want to *play* with Selenium Manager or use it for your use case involving driver or browser management, you can get the Selenium Manager binaries in different ways: +## 获取 Selenium Manager +对于大多数用户而言, 由于 Selenium 绑定会在内部使用 Selenium Manager, +所以无需直接与之交互. +不过, 如果您想试用 Selenium Manager 或将其用于涉及驱动程序或浏览器管理的用例, +可以通过多种方式获取 Selenium Manager 的二进制文件 -- From the Selenium repository. The Selenium Manager source code is stored in the main Selenium repo under the folder [rust](https://github.com/SeleniumHQ/selenium/tree/trunk/rust). Moreover, you can find the compiled versions for Windows, Linux, and macOS in the [Selenium Manager Artifacts](https://github.com/SeleniumHQ/selenium_manager_artifacts) repo. The stable Selenium Manager binaries (i.e., those distributed in the latest stable Selenium version) are linked in this [file](https://github.com/SeleniumHQ/selenium/blob/trunk/common/selenium_manager.bzl). -- From the build workflow. Selenium Manager is compiled using a [GitHub Actions workflow](https://github.com/SeleniumHQ/selenium/actions/workflows/ci-rust.yml). This workflow creates binaries for Windows, Linux, and macOS. You can download these binaries from these workflow executions. -- From the cache. As of version 4.15.0 of the Selenium Java bindings, the Selenium Manager binary is extracted and copied to the cache folder. For instance, the Selenium Manager binary shipped with Selenium 4.15.0 is stored in the folder `~/.cache/selenium/manager/0.4.15`). +- Selenium Manager的源代码存储在 Selenium 主仓库的 [rust](https://github.com/SeleniumHQ/selenium/tree/trunk/rust) 文件夹中. 此外, 您可以在 [Selenium Manager Artifacts](https://github.com/SeleniumHQ/selenium_manager_artifacts) 仓库中找到适用于 Windows、Linux 和 macOS 的编译版本. 此文件中链接了稳定版的 Selenium Manager二进制[file](https://github.com/SeleniumHQ/selenium/blob/trunk/common/selenium_manager.bzl)(即在最新稳定版 Selenium 中分发的那些). +- 在构建工作流中, Selenium Manager 是通过 [GitHub Actions workflow](https://github.com/SeleniumHQ/selenium/actions/workflows/ci-rust.yml)进行编译的. 此工作流会为 Windows、Linux 和 macOS 创建二进制文件. 您可以从这些工作流执行中下载这些二进制文件. +- 在缓存中. 自 Selenium Java 绑定的 4.15.0 版本起, Selenium Manager 二进制文件会被提取并复制到缓存文件夹中. 例如, 与 Selenium 4.15.0 一同提供的 Selenium Manager 二进制文件会存储在文件夹 `~/.cache/selenium/manager/0.4.15` 中. -## Examples -Let's consider a typical example: we want to manage chromedriver automatically. For that, we invoke Selenium Manager as follows (notice that the flag `--debug` is optional, but it helps us to understand what Selenium Manager is doing): +## 例子 +让我们来看一个典型的例子: 我们想要自动管理 chromedriver. +为此, 我们像下面这样调用 Selenium Manager +(请注意, 标志 `--debug` 是可选的, 但它有助于我们理解 Selenium Manager 正在做什么): ``` $ ./selenium-manager --browser chrome --debug @@ -196,9 +297,14 @@ INFO Driver path: C:\Users\boni\.cache\selenium\chromedriver\win64\116.0.5845 INFO Browser path: C:\Program Files\Google\Chrome\Application\chrome.exe ``` -In this case, the local Chrome (in Windows) is detected by Selenium Manager. Then, using its version and the CfT endpoints, the proper chromedriver version (115, in this example) is downloaded to the local cache. Finally, Selenium Manager provides two results: i) the driver path (downloaded) and ii) the browser path (local). +在这种情况下, Selenium Manager会检测到本地的 Chrome(在 Windows 系统中). +然后, 根据其版本和 CfT 端点, 会将合适的 chromedriver 版本(在此示例中为 115 版)下载到本地缓存. +最后, Selenium Manager提供两个结果: +i)驱动程序路径(已下载)和 ii)浏览器路径(本地). -Let's consider another example. Now we want to use Chrome beta. Therefore, we invoke Selenium Manager specifying that version label as follows (notice that the CfT beta is discovered, downloaded, and stored in the local cache): +让我们再来看一个例子. 现在我们想要使用 Chrome 测试版. +因此, 我们调用 Selenium Manager并指定该版本标签, +如下所示(请注意, CfT 测试版会被发现、下载并存储在本地缓存中): ``` $ ./selenium-manager --browser chrome --browser-version beta --debug @@ -216,14 +322,14 @@ INFO Driver path: C:\Users\boni\.cache\selenium\chromedriver\win64\117.0.5938 INFO Browser path: C:\Users\boni\.cache\selenium\chrome\win64\117.0.5938.22\chrome.exe ``` -### Implementing Selenium Manager in Your Scripts +### 在您的脚本中实现 Selenium Manager {{< tabpane text=true >}} {{% tab header="Java" %}} **Previously** -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/selenium_manager/SeleniumManagerUsageDemo.java#L10-L15" >}} +{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/selenium_manager/SeleniumManagerUsageDemo.java#L12-L17" >}} **Selenium Manager** -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/selenium_manager/SeleniumManagerUsageDemo.java#L18-L22" >}} +{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/selenium_manager/SeleniumManagerUsageDemo.java#L20-L24" >}} {{< /tab >}} {{% tab header="Python" %}} **Previously** @@ -231,14 +337,20 @@ INFO Browser path: C:\Users\boni\.cache\selenium\chrome\win64\117.0.5938.22\c **Selenium Manager** {{< gh-codeblock path="examples/python/tests/selenium_manager/usage.py#L10-L12" >}} {{< /tab >}} -{{< tab header="CSharp" >}} -{{< badge-code >}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="examples/dotnet/SeleniumDocs/SeleniumManager/UsageTest.cs#L10-L18" >}} {{< /tab >}} -{{< tab header="Ruby" >}} -{{< badge-code >}} +{{% tab header="Ruby" %}} +**Previously** +{{< gh-codeblock path="examples/ruby/spec/selenium_manager/usage.rb#L5-L10" >}} +**Selenium Manager** +{{< gh-codeblock path="examples/ruby/spec/selenium_manager/usage.rb#L12-L16" >}} {{< /tab >}} -{{< tab header="JavaScript" >}} -{{< badge-code >}} +{{% tab header="JavaScript" %}} +**Previously** +{{< gh-codeblock path="examples/javascript/test/selenium_manager/usage.spec.js#L16-L31" >}} +**Selenium Manager** +{{< gh-codeblock path="examples/javascript/test/selenium_manager/usage.spec.js#L6-L14" >}} {{< /tab >}} {{< tab header="Kotlin" >}} {{< badge-code >}} @@ -246,22 +358,27 @@ INFO Browser path: C:\Users\boni\.cache\selenium\chrome\win64\117.0.5938.22\c {{< /tabpane >}} ## Selenium Grid -Selenium Manager allows you to configure the drivers automatically when setting up Selenium Grid. To that aim, you need to include the argument `--selenium-manager true` in the command to start Selenium Grid. For more details, visit the [Selenium Grid starting page](https://www.selenium.dev/documentation/grid/getting_started/). +Selenium Manager 可让您在设置 Selenium Grid 时自动配置驱动程序. +为此, 您需要在启动 Selenium Grid 的命令中包含 `--selenium-manager true` 参数. +更多详情, 请访问 [Selenium Grid starting page](https://www.selenium.dev/documentation/grid/getting_started/). -Moreover, Selenium Manager also allows managing Selenium Grid releases automatically. For that, the argument `--grid` is used as follows: +此外, Selenium Manager 还允许自动管理 Selenium Grid 的版本. 为此, 使用如下参数 `--grid` : ``` $ ./selenium-manager --grid ``` -After this command, Selenium Manager discovers the latest version of Selenium Grid, storing the `selenium-server.jar` in the local cache. +执行此命令后, Selenium Manager会发现 Selenium Grid 的最新版本, +并将 `selenium-server.jar` 存储在本地缓存中. -Optionally, the argument `--grid` allows to specify a Selenium Grid version (`--grid `). +可选地, 参数 `--grid` 允许指定 Selenium Grid 版本( `--grid ` ). -## Known Limitations +## 已知的限制 -### Connectivity issues -Selenium Manager requests remote endpoints (like Chrome for Testing (CfT), among others) to discover and download drivers and browsers from online repositories. When this operation is done in a corporate environment with a proxy or firewall, it might lead to connectivity problems like the following: +### 连接问题 +Selenium Manager会请求远程端点(例如 Chrome 测试版(CfT)等) +从在线存储库中发现并下载驱动程序和浏览器. +当在具有代理或防火墙的企业环境中执行此操作时, 可能会导致以下连接问题: ``` error sending request for url (https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json) @@ -275,98 +392,107 @@ error trying to connect: dns error: failed to lookup address information error trying to connect: An existing connection was forcibly closed by the remote host. (os error 10054) ``` -When that happens, consider the following solutions: +当这种情况发生时, 请考虑以下解决方案: + +- 使用 Selenium 的代理功能(请参阅[documentation](https://www.selenium.dev/documentation/webdriver/drivers/options/#proxy)). 或者, 使用环境变量 `SE_PROXY` 来设置代理 URL, 或者使用配置文件(请参阅 [configuration](https://www.selenium.dev/documentation/selenium_manager/#configuration) ). +- 检查您的网络设置, 以启用 Selenium Manager所需的远程请求和下载. + +### 自定义包管理器 +如果您正在使用需要特定驱动程序的 Linux 软件包管理器(如 Anaconda、snap 等)来运行您的浏览器, +您可能需要指定[driver location](https://www.selenium.dev/documentation/webdriver/drivers/service/#driver-location)、[browser location](https://www.selenium.dev/documentation/webdriver/browsers/chrome/#start-browser-in-a-specified-location), +或者两者都需要, 具体取决于管理器的要求. + + -- Use the proxy capabilities of Selenium (see [documentation](https://www.selenium.dev/documentation/webdriver/drivers/options/#proxy)). Alternatively, use the environment variable `SE_PROXY` to set the proxy URL or use the configuration file (see [configuration](https://www.selenium.dev/documentation/selenium_manager/#configuration)). -- Review your network setup to enable the remote requests and downloads required by Selenium Manager. +### 备选架构 +Selenium 支持由谷歌 Chrome for Testing 管理的所有五种架构, +以及为微软 Edge 提供的所有六种驱动程序. -### Custom package managers -If you are using a Linux package manager (Anaconda, snap, etc) that requires a specific driver be used for your browsers, -you'll need to either specify the -[driver location](https://www.selenium.dev/documentation/webdriver/drivers/service/#driver-location), -the [browser location](https://www.selenium.dev/documentation/webdriver/browsers/chrome/#start-browser-in-a-specified-location), -or both, depending on the requirements. +Selenium 绑定的每次发布都包含三个独立的 Selenium Manager 二进制文件, +分别适用于 Linux、Windows 和 Mac 系统. -### Alternative architectures -Selenium supports all five architectures managed by Google's Chrome for Testing, and all six drivers provided for Microsoft Edge. +* Mac 版本支持 x64 和 aarch64(英特尔和苹果)架构. +* Windows 版本应适用于 x86 和 x64(32 位和 64 位操作系统). +* Linux 版本仅经过验证可在 x64 系统上运行 -Each release of the Selenium bindings comes with three separate Selenium Manager binaries — one for Linux, Windows, and Mac. -* The Mac version supports both x64 and aarch64 (Intel and Apple). -* The Windows version should work for both x86 and x64 (32-bit and 64-bit OS). -* The Linux version has only been verified to work for x64. +不支持更多架构的原因: -Reasons for not supporting more architectures: -1. Neither Chrome for Testing nor Microsoft Edge supports additional architectures, so Selenium Manager would need to -manage something unofficial for it to work. -2. We currently build the binaries from existing GitHub actions runners, which do not support these architectures -3. Any additional architectures would get distributed with all Selenium releases, increasing the total build size +1. 无论是 Chrome for Testing 还是 Microsoft Edge 都不支持其他架构, 因此 Selenium Manager 需要管理一些非官方的东西才能使其正常工作. +2. 我们目前从现有的 GitHub 操作运行器构建二进制文件, 这些运行器不支持这些架构. +3. 任何额外的架构都会随所有 Selenium 版本一起分发, 从而增加总的构建大小. -If you are running Linux on arm64/aarch64, 32-bit architecture, or a Raspberry Pi, Selenium Manager will not work for you. -The biggest issue for people is that they used to get custom-built drivers and put them on PATH and have them work. -Now that Selenium Manager is responsible for locating drivers on PATH, this approach no longer works, and users -need to use a `Service` class and [set the location directly](https://www.selenium.dev/documentation/webdriver/drivers/service/#driver-location). -There are a number of advantages to having Selenium Manager look for drivers on PATH instead of managing that logic -in each of the bindings, so that's currently a trade-off we are comfortable with. +如果您在 arm64/aarch64、32 位架构或树莓派上运行 Linux, Selenium Manager 将无法为您服务. +对于用户来说, 最大的问题在于他们过去常常获取自定义构建的驱动程序并将其放在 PATH 上, 然后就能正常工作. +现在由于 Selenium Manager 负责在 PATH 上查找驱动程序, +这种方法不再奏效, 用户需要使用 `Service` 类并[直接设置位置](https://www.selenium.dev/documentation/webdriver/drivers/service/#driver-location) . +让 Selenium Manager 在 PATH 上查找驱动程序而不是在每个绑定中管理该逻辑, 有诸多优势, 所以目前这是我们愿意接受的权衡. -However, as of Selenium 4.13.0, the Selenium bindings allow locating the Selenium Manager binary using an environment variable called `SE_MANAGER_PATH`. If this variable is set, the bindings will use its value as the Selenium Manager path in the local filesystem. This feature will allow users to provide a custom compilation of Selenium Manager, for instance, if the default binaries (compiled for Windows, Linux, and macOS) are incompatible with a given system (e.g., ARM64 in Linux). +然而, 从 Selenium 4.13.0 版本开始, +Selenium 绑定允许通过一个名为 `SE_MANAGER_PATH` 的环境变量来定位 Selenium Manager 二进制文件. +如果设置了此变量, 绑定将使用其值作为本地文件系统中的 Selenium Manager 路径. +此功能将允许用户提供自定义编译的 Selenium Manager, +例如, 如果默认的二进制文件(针对 Windows、Linux 和 macOS 编译)与给定系统(例如 Linux 中的 ARM64)不兼容. -### Browser dependencies -When automatically managing browsers in Linux, Selenium Manager relies on the releases published by the browser vendors (i.e., Chrome, Firefox, and Edge). These releases are portable in most cases. Nevertheless, there might be cases in which existing libraries are required. In Linux, this problem might be experienced when trying to run Firefox, e.g., as follows: +### 浏览器依赖 +在 Linux 系统中自动管理浏览器时, Selenium Manager 依赖于浏览器供应商(例如 Chrome、Firefox 和 Edge)发布的版本. +这些版本在大多数情况下都是可移植的. +然而, 在某些情况下可能需要现有的库. +在 Linux 中, 尝试运行 Firefox 时可能会遇到此问题, 例如: ``` libdbus-glib-1.so.2: cannot open shared object file: No such file or directory Couldn't load XPCOM. ``` -If that happens, the solution is to install that library, for instance, as follows: +如果出现这种情况, 解决办法是安装相应的库, 例如, 可以按如下方式操作: ``` sudo apt-get install libdbus-glib-1-2 ``` -A similar issue might happen when trying to execute Chrome for Testing in Linux: +在 Linux 系统中尝试执行 Chrome for Testing 时可能会出现类似的问题: ``` error while loading shared libraries: libatk-1.0.so.0: cannot open shared object file: No such file or directory ``` -In this case, the library to be installed is the following: +在这种情况下, 要安装的库是以下这个: ``` sudo apt-get install libatk-bridge2.0-0 ``` -### Using an environment variable for the driver path -It's possible to use an environment variable to specify the driver path without using Selenium Manager. -The following environment variables are supported: +### 使用环境变量来指定驱动程序路径 +可以使用环境变量来指定驱动程序路径, 而无需使用 Selenium Manager. +支持以下环境变量: * `SE_CHROMEDRIVER` * `SE_EDGEDRIVER` * `SE_GECKODRIVER` * `SE_IEDRIVER` -* `SE_SAFARIDRIVER` -For example, to specify the path to the chromedriver, -you can set the `SE_CHROMEDRIVER` environment variable to the path of the chromedriver executable. -The following bindings allow you to specify the driver path using an environment variable: +例如, 要指定 chromedriver 的路径, +您可以将 `SE_CHROMEDRIVER` 环境变量设置为 chromedriver 可执行文件的路径. +以下绑定允许您使用环境变量指定驱动程序路径: * Ruby * Java * Python -This feature is available in the Selenium Ruby binding starting from version 4.25.0 and in the Python binding from version 4.26.0. +此功能从 Selenium Ruby 绑定的 4.25.0 版本以及 Python 绑定的 4.26.0 版本开始可用. -## Building a Custom Selenium Manager -In order to build your own custom Selenium Manager that works in an architecture we don't currently support, you can -utilize the following steps: +## 构建自定义 Selenium Manager +若要构建适用于我们当前不支持的架构的自定义 Selenium Manager, +您可以按照以下步骤操作: -1. Install Rust Dev Environment -2. clone Selenium onto your local machine `git clone https://github.com/SeleniumHQ/selenium.git --depth 1` -3. Navigate into your clone `cd selenium/rust` -4. Build selenium `cargo build --release` -5. Set the following environment variable for the driver path `SE_MANAGER_PATH=~/selenium/rust/target/release/selenium-manager` -6. Put the driver you want in a location on your system PATH -7. Selenium will now use the built Selenium Manager to locate the manually downloaded driver on PATH +2. 安装 Rust 开发环境 +3. 将 Selenium 克隆到您的本地机器上 `git clone https://github.com/SeleniumHQ/selenium.git --depth 1` +4. 进入您的下载目录 `cd selenium/rust` +5. 构建 Selenium `cargo build --release` +6. 设置以下环境变量以指定驱动程序路径 `SE_MANAGER_PATH=~/selenium/rust/target/release/selenium-manager` +7. 将您想要的驱动程序放在系统路径中的某个位置. +8. Selenium 现在将使用内置的 Selenium Manager在 PATH 中定位手动下载的驱动程序. -## Roadmap -You can trace the work in progress in the [Selenium Manager project dashboard](https://github.com/orgs/SeleniumHQ/projects/5). Moreover, you can check the new features shipped with each Selenium Manager release in its [changelog file](https://github.com/SeleniumHQ/selenium/blob/trunk/rust/CHANGELOG.md). +## 路线图 +您可以在 [Selenium Manager project dashboard](https://github.com/orgs/SeleniumHQ/projects/5) 中追踪正在进行的工作. +此外, 您还可以在每个 Selenium Manager 版本的[changelog file](https://github.com/SeleniumHQ/selenium/blob/trunk/rust/CHANGELOG.md) 中查看随版本发布的新增功能. diff --git a/website_and_docs/content/documentation/test_practices/design_strategies.en.md b/website_and_docs/content/documentation/test_practices/design_strategies.en.md index 6db4fe03c094..517b7f0e20a3 100644 --- a/website_and_docs/content/documentation/test_practices/design_strategies.en.md +++ b/website_and_docs/content/documentation/test_practices/design_strategies.en.md @@ -442,3 +442,128 @@ public class ActionBot { ``` Once these abstractions have been built and duplication in your tests identified, it's possible to layer PageObjects on top of bots. + +## Example + +{{< tabpane text=true >}} +{{< tab header="Python" >}} + +An example of `python + pytest + selenium` which implemented "**Action Bot**, **Loadable Component** and **Page Object**". + +A `pytest` fixture `chrome_driver`. + +{{< gh-codeblock path="/examples/python/tests/design_strategy/using_best_practice.py#L6-L26" >}} +{{< /tab >}} +{{< tab header="Java" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="CSharp" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Ruby" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="JavaScript" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Kotlin" >}} +{{< badge-code >}} +{{< /tab >}} +{{< /tabpane >}} + + +"**Action Bot**" implementation. + +{{< tabpane text=true >}} +{{< tab header="Python" >}} +{{< gh-codeblock path="/examples/python/tests/design_strategy/using_best_practice.py#L28-L65" >}} +{{< /tab >}} +{{< tab header="Java" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="CSharp" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Ruby" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="JavaScript" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Kotlin" >}} +{{< badge-code >}} +{{< /tab >}} +{{< /tabpane >}} + + +"**Loadable Component** definition. + +{{< tabpane text=true >}} +{{< tab header="Python" >}} +{{< gh-codeblock path="/examples/python/tests/design_strategy/using_best_practice.py#L67-L80" >}} +{{< /tab >}} +{{< tab header="Java" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="CSharp" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Ruby" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="JavaScript" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Kotlin" >}} +{{< badge-code >}} +{{< /tab >}} +{{< /tabpane >}} + + +"**Loadable Component** and **Page Object**" implementation. + +{{< tabpane text=true >}} +{{< tab header="Python" >}} +{{< gh-codeblock path="/examples/python/tests/design_strategy/using_best_practice.py#L82-L172" >}} +{{< /tab >}} +{{< tab header="Java" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="CSharp" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Ruby" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="JavaScript" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Kotlin" >}} +{{< badge-code >}} +{{< /tab >}} +{{< /tabpane >}} + +Test cases implementation. + +{{< tabpane text=true >}} +{{< tab header="Python" >}} +Test cases implementation with `pytest`. + +{{< gh-codeblock path="/examples/python/tests/design_strategy/using_best_practice.py#L174-L240" >}} +{{< /tab >}} +{{< tab header="Java" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="CSharp" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Ruby" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="JavaScript" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Kotlin" >}} +{{< badge-code >}} +{{< /tab >}} +{{< /tabpane >}} diff --git a/website_and_docs/content/documentation/test_practices/design_strategies.ja.md b/website_and_docs/content/documentation/test_practices/design_strategies.ja.md index 34dfec87e6bf..c351cc2a5cfe 100644 --- a/website_and_docs/content/documentation/test_practices/design_strategies.ja.md +++ b/website_and_docs/content/documentation/test_practices/design_strategies.ja.md @@ -434,3 +434,129 @@ public class ActionBot { ``` これらの抽象化が構築され、テストでの重複が特定されると、ボットの上にPageObjectsを階層化することができます。 + +## Example + +{{< tabpane text=true >}} +{{< tab header="Python" >}} + +**Action Bot**、**Loadable Component**、および **Page Object** を実装した `python + pytest + selenium` の例です。 + +A `pytest` fixture `chrome_driver`. + +{{< gh-codeblock path="/examples/python/tests/design_strategy/using_best_practice.py#L6-L26" >}} +{{< /tab >}} +{{< tab header="Java" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="CSharp" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Ruby" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="JavaScript" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Kotlin" >}} +{{< badge-code >}} +{{< /tab >}} +{{< /tabpane >}} + + +"**Action Bot**" implementation. + +{{< tabpane text=true >}} +{{< tab header="Python" >}} +{{< gh-codeblock path="/examples/python/tests/design_strategy/using_best_practice.py#L28-L65" >}} +{{< /tab >}} +{{< tab header="Java" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="CSharp" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Ruby" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="JavaScript" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Kotlin" >}} +{{< badge-code >}} +{{< /tab >}} +{{< /tabpane >}} + + +"**Loadable Component** definition. + +{{< tabpane text=true >}} +{{< tab header="Python" >}} +{{< gh-codeblock path="/examples/python/tests/design_strategy/using_best_practice.py#L67-L80" >}} +{{< /tab >}} +{{< tab header="Java" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="CSharp" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Ruby" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="JavaScript" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Kotlin" >}} +{{< badge-code >}} +{{< /tab >}} +{{< /tabpane >}} + + +"**Loadable Component** and **Page Object**" implementation. + +{{< tabpane text=true >}} +{{< tab header="Python" >}} +{{< gh-codeblock path="/examples/python/tests/design_strategy/using_best_practice.py#L82-L172" >}} +{{< /tab >}} +{{< tab header="Java" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="CSharp" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Ruby" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="JavaScript" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Kotlin" >}} +{{< badge-code >}} +{{< /tab >}} +{{< /tabpane >}} + +Test cases implementation. + +{{< tabpane text=true >}} +{{< tab header="Python" >}} + +Test cases implementation with `pytest`. + +{{< gh-codeblock path="/examples/python/tests/design_strategy/using_best_practice.py#L174-L240" >}} +{{< /tab >}} +{{< tab header="Java" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="CSharp" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Ruby" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="JavaScript" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Kotlin" >}} +{{< badge-code >}} +{{< /tab >}} +{{< /tabpane >}} diff --git a/website_and_docs/content/documentation/test_practices/design_strategies.pt-br.md b/website_and_docs/content/documentation/test_practices/design_strategies.pt-br.md index ff0c94c48c00..d45d25e41114 100644 --- a/website_and_docs/content/documentation/test_practices/design_strategies.pt-br.md +++ b/website_and_docs/content/documentation/test_practices/design_strategies.pt-br.md @@ -441,3 +441,128 @@ public class ActionBot { ``` Once these abstractions have been built and duplication in your tests identified, it's possible to layer PageObjects on top of bots. + + +## Example + +{{< tabpane text=true >}} +{{< tab header="Python" >}} +An example of `python + pytest + selenium` which implemented "**Action Bot**, **Loadable Component** and **Page Object**". + +A `pytest` fixture `chrome_driver`. + +{{< gh-codeblock path="/examples/python/tests/design_strategy/using_best_practice.py#L6-L26" >}} +{{< /tab >}} +{{< tab header="Java" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="CSharp" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Ruby" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="JavaScript" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Kotlin" >}} +{{< badge-code >}} +{{< /tab >}} +{{< /tabpane >}} + + +"**Action Bot**" implementation. + +{{< tabpane text=true >}} +{{< tab header="Python" >}} +{{< gh-codeblock path="/examples/python/tests/design_strategy/using_best_practice.py#L28-L65" >}} +{{< /tab >}} +{{< tab header="Java" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="CSharp" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Ruby" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="JavaScript" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Kotlin" >}} +{{< badge-code >}} +{{< /tab >}} +{{< /tabpane >}} + + +"**Loadable Component** definition. + +{{< tabpane text=true >}} +{{< tab header="Python" >}} +{{< gh-codeblock path="/examples/python/tests/design_strategy/using_best_practice.py#L67-L80" >}} +{{< /tab >}} +{{< tab header="Java" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="CSharp" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Ruby" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="JavaScript" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Kotlin" >}} +{{< badge-code >}} +{{< /tab >}} +{{< /tabpane >}} + + +"**Loadable Component** and **Page Object**" implementation. + +{{< tabpane text=true >}} +{{< tab header="Python" >}} +{{< gh-codeblock path="/examples/python/tests/design_strategy/using_best_practice.py#L82-L172" >}} +{{< /tab >}} +{{< tab header="Java" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="CSharp" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Ruby" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="JavaScript" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Kotlin" >}} +{{< badge-code >}} +{{< /tab >}} +{{< /tabpane >}} + +Test cases implementation. + +{{< tabpane text=true >}} +{{< tab header="Python" >}} +Test cases implementation with `pytest`. + +{{< gh-codeblock path="/examples/python/tests/design_strategy/using_best_practice.py#L174-L240" >}} +{{< /tab >}} +{{< tab header="Java" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="CSharp" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Ruby" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="JavaScript" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Kotlin" >}} +{{< badge-code >}} +{{< /tab >}} +{{< /tabpane >}} diff --git a/website_and_docs/content/documentation/test_practices/design_strategies.zh-cn.md b/website_and_docs/content/documentation/test_practices/design_strategies.zh-cn.md index 9326b0fa8f55..0d379b4b4a36 100644 --- a/website_and_docs/content/documentation/test_practices/design_strategies.zh-cn.md +++ b/website_and_docs/content/documentation/test_practices/design_strategies.zh-cn.md @@ -456,3 +456,128 @@ public class ActionBot { Once these abstractions have been built and duplication in your tests identified, it's possible to layer PageObjects on top of bots. + + +## Example + +{{< tabpane text=true >}} +{{< tab header="Python" >}} +一个用例 使用 `python + pytest + selenium` 实现了设计策略 "**Action Bot**, **Loadable Component** 和 **Page Object**". + +A `pytest` fixture `chrome_driver`. + +{{< gh-codeblock path="/examples/python/tests/design_strategy/using_best_practice.py#L6-L26" >}} +{{< /tab >}} +{{< tab header="Java" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="CSharp" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Ruby" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="JavaScript" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Kotlin" >}} +{{< badge-code >}} +{{< /tab >}} +{{< /tabpane >}} + + +"**Action Bot**" implementation. + +{{< tabpane text=true >}} +{{< tab header="Python" >}} +{{< gh-codeblock path="/examples/python/tests/design_strategy/using_best_practice.py#L28-L65" >}} +{{< /tab >}} +{{< tab header="Java" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="CSharp" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Ruby" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="JavaScript" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Kotlin" >}} +{{< badge-code >}} +{{< /tab >}} +{{< /tabpane >}} + + +"**Loadable Component** definition. + +{{< tabpane text=true >}} +{{< tab header="Python" >}} +{{< gh-codeblock path="/examples/python/tests/design_strategy/using_best_practice.py#L67-L80" >}} +{{< /tab >}} +{{< tab header="Java" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="CSharp" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Ruby" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="JavaScript" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Kotlin" >}} +{{< badge-code >}} +{{< /tab >}} +{{< /tabpane >}} + + +"**Loadable Component** and **Page Object**" implementation. + +{{< tabpane text=true >}} +{{< tab header="Python" >}} +{{< gh-codeblock path="/examples/python/tests/design_strategy/using_best_practice.py#L82-L172" >}} +{{< /tab >}} +{{< tab header="Java" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="CSharp" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Ruby" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="JavaScript" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Kotlin" >}} +{{< badge-code >}} +{{< /tab >}} +{{< /tabpane >}} + +Test cases implementation. + +{{< tabpane text=true >}} +{{< tab header="Python" >}} +Test cases implementation with `pytest`. + +{{< gh-codeblock path="/examples/python/tests/design_strategy/using_best_practice.py#L174-L240" >}} +{{< /tab >}} +{{< tab header="Java" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="CSharp" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Ruby" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="JavaScript" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Kotlin" >}} +{{< badge-code >}} +{{< /tab >}} +{{< /tabpane >}} diff --git a/website_and_docs/content/documentation/test_practices/discouraged/file_downloads.en.md b/website_and_docs/content/documentation/test_practices/discouraged/file_downloads.en.md index c8c0fc639813..78a686b2125c 100644 --- a/website_and_docs/content/documentation/test_practices/discouraged/file_downloads.en.md +++ b/website_and_docs/content/documentation/test_practices/discouraged/file_downloads.en.md @@ -17,7 +17,7 @@ of emulating user interaction with the web platform. Instead, find the link using Selenium (and any required cookies) and pass it to a HTTP request library like -[libcurl](//curl.haxx.se/libcurl/). +[curl](https:////curl.se/). The [HtmlUnit driver](https://github.com/SeleniumHQ/htmlunit-driver) can download attachments by accessing them as input streams by implementing the diff --git a/website_and_docs/content/documentation/test_practices/discouraged/file_downloads.ja.md b/website_and_docs/content/documentation/test_practices/discouraged/file_downloads.ja.md index d0e6f03c10de..2f2b4ab54c0d 100644 --- a/website_and_docs/content/documentation/test_practices/discouraged/file_downloads.ja.md +++ b/website_and_docs/content/documentation/test_practices/discouraged/file_downloads.ja.md @@ -11,7 +11,7 @@ aliases: [ Seleniumの管理下にあるブラウザーでリンクをクリックしてダウンロードを開始することは可能ですが、APIはダウンロードの進行状況を公開しないため、ダウンロードしたファイルのテストには理想的ではありません。 これは、ファイルのダウンロードは、Webプラットフォームとのユーザーインタラクションをエミュレートする重要な側面とは見なされないためです。 -代わりに、Selenium(および必要なCookie)を使用してリンクを見つけ、 [libcurl](//curl.haxx.se/libcurl/) などのHTTPリクエストライブラリに渡します。 +代わりに、Selenium(および必要なCookie)を使用してリンクを見つけ、 [curl](https://curl.se/) などのHTTPリクエストライブラリに渡します。 [HtmlUnitドライバー](https://github.com/SeleniumHQ/htmlunit-driver)は、 [AttachmentHandler](https://htmlunit.sourceforge.io/apidocs/com/gargoylesoftware/htmlunit/attachment/AttachmentHandler.html) インターフェイスを実装することで、 diff --git a/website_and_docs/content/documentation/test_practices/discouraged/file_downloads.pt-br.md b/website_and_docs/content/documentation/test_practices/discouraged/file_downloads.pt-br.md index 6d3d3080c005..3cc5f0a5be91 100644 --- a/website_and_docs/content/documentation/test_practices/discouraged/file_downloads.pt-br.md +++ b/website_and_docs/content/documentation/test_practices/discouraged/file_downloads.pt-br.md @@ -17,7 +17,7 @@ de emular a interação do usuário com a plataforma da web. Em vez disso, encontre o link usando Selenium (e todos os cookies necessários) e passe este cookie para uma biblioteca de solicitação HTTP como -[libcurl](//curl.haxx.se/libcurl/). +[curl](https://curl.se/). O [driver HtmlUnit](https://github.com/SeleniumHQ/htmlunit-driver) pode baixar anexos acessando-os como fluxos de entrada, implementando o diff --git a/website_and_docs/content/documentation/test_practices/discouraged/file_downloads.zh-cn.md b/website_and_docs/content/documentation/test_practices/discouraged/file_downloads.zh-cn.md index 2b1fd1c792a6..47b28975a66b 100644 --- a/website_and_docs/content/documentation/test_practices/discouraged/file_downloads.zh-cn.md +++ b/website_and_docs/content/documentation/test_practices/discouraged/file_downloads.zh-cn.md @@ -10,7 +10,7 @@ aliases: [ 虽然可以通过在Selenium的控制下单击浏览器的链接来开始下载, 但是API并不会暴露下载进度, 因此这是一种不理想的测试下载文件的方式. -因为下载文件并非模拟用户与Web平台交互的重要方面. 取而代之的是, 应使用Selenium(以及任何必要的cookie)查找链接, 并将其传递给例如[libcurl](//curl.haxx.se/libcurl/)这样的HTTP请求库. +因为下载文件并非模拟用户与Web平台交互的重要方面. 取而代之的是, 应使用Selenium(以及任何必要的cookie)查找链接, 并将其传递给例如[curl](//curl.se/)这样的HTTP请求库. [HtmlUnit driver](https://github.com/SeleniumHQ/htmlunit-driver) diff --git a/website_and_docs/content/documentation/test_practices/discouraged/link_spidering.en.md b/website_and_docs/content/documentation/test_practices/discouraged/link_spidering.en.md index f2467d933a5b..59d35eb79f32 100644 --- a/website_and_docs/content/documentation/test_practices/discouraged/link_spidering.en.md +++ b/website_and_docs/content/documentation/test_practices/discouraged/link_spidering.en.md @@ -18,7 +18,7 @@ just to get to the page and traverse through the DOM. Instead of using WebDriver for this, you could save a ton of time -by executing a [curl](//curl.haxx.se/) command, +by executing a [curl](https://curl.se/) command, or using a library such as BeautifulSoup since these methods do not rely on creating a browser and navigating to a page. diff --git a/website_and_docs/content/documentation/test_practices/discouraged/link_spidering.ja.md b/website_and_docs/content/documentation/test_practices/discouraged/link_spidering.ja.md index 58b8b20f4a89..b4a6254ba37b 100644 --- a/website_and_docs/content/documentation/test_practices/discouraged/link_spidering.ja.md +++ b/website_and_docs/content/documentation/test_practices/discouraged/link_spidering.ja.md @@ -12,5 +12,5 @@ aliases: [ WebDriverを使用してリンクをスパイダーすることは、実行できないためではなく、最も理想的なツールではないため明らかに推奨される方法ではありません。 WebDriverの起動には時間が必要であり、テストの記述方法によっては、ページに到達してDOMを通過するために数秒から1分かかる場合があります。 -このためにWebDriverを使用する代わりに、[curl](//curl.haxx.se/) コマンドを実行するか、BeautifulSoupなどのライブラリを使用することにより、これらの方法はブラウザーの作成やページへの移動に依存しないため、時間を大幅に節約できます。 +このためにWebDriverを使用する代わりに、[curl](https://curl.se/) コマンドを実行するか、BeautifulSoupなどのライブラリを使用することにより、これらの方法はブラウザーの作成やページへの移動に依存しないため、時間を大幅に節約できます。 このタスクにWebDriverを使用しないことで、時間を大幅に節約できます。 diff --git a/website_and_docs/content/documentation/test_practices/discouraged/link_spidering.pt-br.md b/website_and_docs/content/documentation/test_practices/discouraged/link_spidering.pt-br.md index 8bb2ce6008af..810fa6de0b31 100644 --- a/website_and_docs/content/documentation/test_practices/discouraged/link_spidering.pt-br.md +++ b/website_and_docs/content/documentation/test_practices/discouraged/link_spidering.pt-br.md @@ -18,7 +18,7 @@ apenas para chegar à página e atravessar o DOM. Em vez de usar o WebDriver para isso, você poderia economizar muito tempo -executando um comando [curl](//curl.haxx.se/), +executando um comando [curl](https://curl.se/), ou usando uma biblioteca como BeautifulSoup uma vez que esses métodos não dependem em criar um navegador e navegar para uma página. diff --git a/website_and_docs/content/documentation/test_practices/discouraged/link_spidering.zh-cn.md b/website_and_docs/content/documentation/test_practices/discouraged/link_spidering.zh-cn.md index ac30f3efb1b5..0f0be9f539cf 100644 --- a/website_and_docs/content/documentation/test_practices/discouraged/link_spidering.zh-cn.md +++ b/website_and_docs/content/documentation/test_practices/discouraged/link_spidering.zh-cn.md @@ -14,7 +14,7 @@ WebDriver需要一些时间来启动,并且可能要花几秒钟到一分钟 具体取决于测试的编写方式,仅仅是为了获取页面并遍历DOM. 除了使用WebDriver之外, -您还可以通过执行 [curl](//curl.haxx.se/) 命令或 +您还可以通过执行 [curl](https://curl.se/) 命令或 使用诸如BeautifulSoup之类的库来节省大量时间, 因为这些方法不依赖于创建浏览器和导航至页面. 通过不使用WebDriver可以节省大量时间. diff --git a/website_and_docs/content/documentation/webdriver/bidi/logging.zh-cn.md b/website_and_docs/content/documentation/webdriver/bidi/logging.zh-cn.md index 8109898135fd..682b8dc2f866 100644 --- a/website_and_docs/content/documentation/webdriver/bidi/logging.zh-cn.md +++ b/website_and_docs/content/documentation/webdriver/bidi/logging.zh-cn.md @@ -1,24 +1,26 @@ --- -title: "WebDriver BiDi Logging Features" -linkTitle: "Logging" +title: "WebDriver BiDi 日志功能" +linkTitle: "日志" weight: 1 description: > - These features are related to logging. Because "logging" can refer to so many - different things, these methods are made available via a "script" namespace. + 这些功能与日志记录有关。 + 由于"logging"可以指代许多不同的事物, + 因此这些方法通过"script"命名空间提供. aliases: [ "/documentation/zh-cn/webdriver/bidirectional/bidirectional_w3c/log", "/documentation/webdriver/bidirectional/webdriver_bidi/log" ] --- -Remember that to use WebDriver BiDi, you must enable it in Options. -For more details, see [Enabling BiDi]({{< ref "BiDi" >}}) +请记住, 要使用 WebDriver BiDi, +您必须在选项中启用它. +更多详情, 请参阅 [启用 BiDi]({{< ref "BiDi" >}}) . -## Console Message Handlers +## 控制台消息处理程序 -Record or take actions on `console.log` events. +记录或对 `console.log` 事件采取行动. -### Add Handler +### 添加处理程序 {{< tabpane text=true >}} {{< tab header="Java" >}} @@ -41,9 +43,9 @@ Record or take actions on `console.log` events. {{< /tab >}} {{< /tabpane >}} -### Remove Handler +### 删除处理程序 -You need to store the ID returned when adding the handler to delete it. +您需要存储添加处理程序时返回的 ID 以便将其删除. {{< tabpane text=true >}} {{< tab header="Java" >}} @@ -66,11 +68,11 @@ You need to store the ID returned when adding the handler to delete it. {{< /tab >}} {{< /tabpane >}} -## JavaScript Exception Handlers +## JavaScript 异常处理程序 -Record or take actions on JavaScript exception events. +记录或对 JavaScript 异常事件采取行动. -### Add Handler +### 添加处理程序 {{< tabpane text=true >}} {{< tab header="Java" >}} @@ -93,9 +95,9 @@ Record or take actions on JavaScript exception events. {{< /tab >}} {{< /tabpane >}} -### Remove Handler +### 删除处理程序 -You need to store the ID returned when adding the handler to delete it. +您需要存储添加处理程序时返回的 ID 以便将其删除. {{< tabpane text=true >}} {{< tab header="Java" >}} diff --git a/website_and_docs/content/documentation/webdriver/bidi/w3c/network.en.md b/website_and_docs/content/documentation/webdriver/bidi/w3c/network.en.md index 9436128ed9d5..b4310a46c3d1 100644 --- a/website_and_docs/content/documentation/webdriver/bidi/w3c/network.en.md +++ b/website_and_docs/content/documentation/webdriver/bidi/w3c/network.en.md @@ -158,7 +158,7 @@ This section contains the APIs related to network events. {{< /tab >}} {{< tab header="JavaScript" >}} {{< badge-version version="4.18" >}} -{{< gh-codeblock path="/examples/javascript/test/bidirectional/network_events.spec.js#L83-L89" >}} +{{< gh-codeblock path="/examples/javascript/test/bidirectional/network_events.spec.js#L82-L88" >}} {{< /tab >}} {{< tab header="Kotlin" >}} {{< badge-code >}} @@ -177,7 +177,7 @@ This section contains the APIs related to network events. {{< /tab >}} {{< tab header="JavaScript" >}} {{< badge-version version="4.18" >}} -{{< gh-codeblock path="/examples/javascript/test/bidirectional/network_events.spec.js#L97-L103" >}} +{{< gh-codeblock path="/examples/javascript/test/bidirectional/network_events.spec.js#L96-L102" >}} {{< /tab >}} {{< tab header="Kotlin" >}} {{< badge-code >}} diff --git a/website_and_docs/content/documentation/webdriver/bidi/w3c/network.ja.md b/website_and_docs/content/documentation/webdriver/bidi/w3c/network.ja.md index da763f879083..b8b76a827b99 100644 --- a/website_and_docs/content/documentation/webdriver/bidi/w3c/network.ja.md +++ b/website_and_docs/content/documentation/webdriver/bidi/w3c/network.ja.md @@ -168,7 +168,7 @@ This section contains the APIs related to network events. {{< /tab >}} {{< tab header="JavaScript" >}} {{< badge-version version="4.18" >}} -{{< gh-codeblock path="/examples/javascript/test/bidirectional/network_events.spec.js#L83-L89" >}} +{{< gh-codeblock path="/examples/javascript/test/bidirectional/network_events.spec.js#L82-L88" >}} {{< /tab >}} {{< tab header="Kotlin" >}} {{< badge-code >}} @@ -187,7 +187,7 @@ This section contains the APIs related to network events. {{< /tab >}} {{< tab header="JavaScript" >}} {{< badge-version version="4.18" >}} -{{< gh-codeblock path="/examples/javascript/test/bidirectional/network_events.spec.js#L97-L103" >}} +{{< gh-codeblock path="/examples/javascript/test/bidirectional/network_events.spec.js#L96-L102" >}} {{< /tab >}} {{< tab header="Kotlin" >}} {{< badge-code >}} diff --git a/website_and_docs/content/documentation/webdriver/bidi/w3c/network.pt-br.md b/website_and_docs/content/documentation/webdriver/bidi/w3c/network.pt-br.md index 87dfd0a4c669..ce3f5d5508e5 100644 --- a/website_and_docs/content/documentation/webdriver/bidi/w3c/network.pt-br.md +++ b/website_and_docs/content/documentation/webdriver/bidi/w3c/network.pt-br.md @@ -168,7 +168,7 @@ This section contains the APIs related to network events. {{< /tab >}} {{< tab header="JavaScript" >}} {{< badge-version version="4.18" >}} -{{< gh-codeblock path="/examples/javascript/test/bidirectional/network_events.spec.js#L83-L89" >}} +{{< gh-codeblock path="/examples/javascript/test/bidirectional/network_events.spec.js#L82-L88" >}} {{< /tab >}} {{< tab header="Kotlin" >}} {{< badge-code >}} @@ -187,7 +187,7 @@ This section contains the APIs related to network events. {{< /tab >}} {{< tab header="JavaScript" >}} {{< badge-version version="4.18" >}} -{{< gh-codeblock path="/examples/javascript/test/bidirectional/network_events.spec.js#L97-L103" >}} +{{< gh-codeblock path="/examples/javascript/test/bidirectional/network_events.spec.js#L96-L102" >}} {{< /tab >}} {{< tab header="Kotlin" >}} {{< badge-code >}} diff --git a/website_and_docs/content/documentation/webdriver/bidi/w3c/network.zh-cn.md b/website_and_docs/content/documentation/webdriver/bidi/w3c/network.zh-cn.md index 5c8e6c670e6d..7788c2d76396 100644 --- a/website_and_docs/content/documentation/webdriver/bidi/w3c/network.zh-cn.md +++ b/website_and_docs/content/documentation/webdriver/bidi/w3c/network.zh-cn.md @@ -168,7 +168,7 @@ This section contains the APIs related to network events. {{< /tab >}} {{< tab header="JavaScript" >}} {{< badge-version version="4.18" >}} -{{< gh-codeblock path="/examples/javascript/test/bidirectional/network_events.spec.js#L83-L89" >}} +{{< gh-codeblock path="/examples/javascript/test/bidirectional/network_events.spec.js#L82-L88" >}} {{< /tab >}} {{< tab header="Kotlin" >}} {{< badge-code >}} @@ -187,7 +187,7 @@ This section contains the APIs related to network events. {{< /tab >}} {{< tab header="JavaScript" >}} {{< badge-version version="4.18" >}} -{{< gh-codeblock path="/examples/javascript/test/bidirectional/network_events.spec.js#L97-L103" >}} +{{< gh-codeblock path="/examples/javascript/test/bidirectional/network_events.spec.js#L96-L102" >}} {{< /tab >}} {{< tab header="Kotlin" >}} {{< badge-code >}} @@ -210,4 +210,4 @@ This section contains the APIs related to network events. {{< tab header="Kotlin" >}} {{< badge-code >}} {{< /tab >}} -{{< /tabpane >}} \ No newline at end of file +{{< /tabpane >}} diff --git a/website_and_docs/content/documentation/webdriver/browsers/chrome.en.md b/website_and_docs/content/documentation/webdriver/browsers/chrome.en.md index 224c8bcbd3b5..2508b7391598 100644 --- a/website_and_docs/content/documentation/webdriver/browsers/chrome.en.md +++ b/website_and_docs/content/documentation/webdriver/browsers/chrome.en.md @@ -23,7 +23,7 @@ Starting a Chrome session with basic defined options looks like this: {{< tabpane text=true >}} {{< tab header="Java" >}} -{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L37-L38" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L36-L37" >}} {{< /tab >}} {{% tab header="Python" %}} {{< gh-codeblock path="/examples/python/tests/browsers/test_chrome.py#L9-L10" >}} @@ -55,7 +55,7 @@ Add an argument to options: {{< tabpane text=true >}} {{< tab header="Java" >}} -{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L45" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L44" >}} {{< /tab >}} {{% tab header="Python" %}} {{< gh-codeblock path="/examples/python/tests/browsers/test_chrome.py#L18" >}} @@ -83,7 +83,7 @@ Add a browser location to options: {{< tabpane text=true >}} {{< tab header="Java" >}} -{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L54" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L53" >}} {{< /tab >}} {{% tab header="Python" %}} {{< gh-codeblock path="/examples/python/tests/browsers/test_chrome.py#L29">}} @@ -92,7 +92,7 @@ Add a browser location to options: {{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Browsers/ChromeTest.cs#L49" >}} {{< /tab >}} {{< tab header="Ruby" >}} -{{< gh-codeblock path="/examples/ruby/spec/browsers/chrome_spec.rb#L25" >}} +{{< gh-codeblock path="/examples/ruby/spec/browsers/chrome_spec.rb#L29" >}} {{< /tab >}} {{< tab header="JavaScript" >}} {{< gh-codeblock path="/examples/javascript/test/browser/chromeSpecificCaps.spec.js#L41-L44">}} @@ -112,16 +112,16 @@ Add an extension to options: {{< tabpane text=true >}} {{< tab header="Java" >}} -{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L65" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L64" >}} {{< /tab >}} {{% tab header="Python" %}} {{< gh-codeblock path="/examples/python/tests/browsers/test_chrome.py#L40">}} {{% /tab %}} {{< tab header="CSharp" >}} -{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Browsers/ChromeTest.cs#L61" >}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Browsers/ChromeTest.cs#L62-67" >}} {{< /tab >}} {{< tab header="Ruby" >}} -{{< gh-codeblock path="/examples/ruby/spec/browsers/chrome_spec.rb#L34" >}} +{{< gh-codeblock path="/examples/ruby/spec/browsers/chrome_spec.rb#L38" >}} {{< /tab >}} {{< tab header="JavaScript" >}} {{< gh-codeblock path="/examples/javascript/test/browser/chromeSpecificCaps.spec.js#L62-L66">}} @@ -147,7 +147,7 @@ so long as the quit command is not sent to the driver. **Note**: This is already the default behavior in .NET. {{% /tab %}} {{< tab header="Ruby" >}} -{{< gh-codeblock path="/examples/ruby/spec/browsers/chrome_spec.rb#L45" >}} +{{< gh-codeblock path="/examples/ruby/spec/browsers/chrome_spec.rb#L49" >}} {{< /tab >}} {{< tab header="JavaScript" >}} {{< gh-codeblock path="/examples/javascript/test/browser/chromeSpecificCaps.spec.js#L29-L32">}} @@ -175,10 +175,10 @@ Set excluded arguments on options: {{< gh-codeblock path="/examples/python/tests/browsers/test_chrome.py#L62" >}} {{% /tab %}} {{< tab header="CSharp" >}} -{{< gh-codeblock path="examples/dotnet/SeleniumDocs/Browsers/ChromeTest.cs#L76" >}} +{{< gh-codeblock path="examples/dotnet/SeleniumDocs/Browsers/ChromeTest.cs#L82" >}} {{< /tab >}} {{< tab header="Ruby" >}} -{{< gh-codeblock path="/examples/ruby/spec/browsers/chrome_spec.rb#L53" >}} +{{< gh-codeblock path="/examples/ruby/spec/browsers/chrome_spec.rb#L57" >}} {{< /tab >}} {{< tab header="JavaScript" >}} {{< gh-codeblock path="/examples/javascript/test/browser/chromeSpecificCaps.spec.js#L19-L22">}} @@ -219,7 +219,7 @@ Property value: String representing path to log file {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-version version="4.10" >}} -{{< gh-codeblock path="examples/ruby/spec/browsers/chrome_spec.rb#L67" >}} +{{< gh-codeblock path="examples/ruby/spec/browsers/chrome_spec.rb#L71" >}} {{< /tab >}} {{< tab header="JavaScript" >}} {{< badge-code >}} @@ -251,7 +251,7 @@ Property value: `DriverService.LOG_STDOUT` or `DriverService.LOG_STDERR` {{% tab header="Ruby" %}} `$stdout` and `$stderr` are both valid values {{< badge-version version="4.10" >}} -{{< gh-codeblock path="examples/ruby/spec/browsers/chrome_spec.rb#L76" >}} +{{< gh-codeblock path="examples/ruby/spec/browsers/chrome_spec.rb#L80" >}} {{% /tab %}} {{< tab header="JavaScript" >}} {{< badge-code >}} @@ -283,7 +283,7 @@ Property value: String representation of `ChromiumDriverLogLevel` enum {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-version version="4.10" >}} -{{< gh-codeblock path="examples/ruby/spec/browsers/chrome_spec.rb#L87" >}} +{{< gh-codeblock path="examples/ruby/spec/browsers/chrome_spec.rb#L91" >}} {{< /tab >}} {{< tab header="JavaScript" >}} {{< badge-code >}} @@ -317,7 +317,7 @@ Property value: `"true"` or `"false"` {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/ruby/spec/browsers/chrome_spec.rb#L97-L98" >}} +{{< gh-codeblock path="examples/ruby/spec/browsers/chrome_spec.rb#L101-L102" >}} {{< /tab >}} {{< tab header="JavaScript" >}} {{< badge-code >}} @@ -350,7 +350,7 @@ Property value: `"true"` or `"false"` {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/ruby/spec/browsers/chrome_spec.rb#L108" >}} +{{< gh-codeblock path="examples/ruby/spec/browsers/chrome_spec.rb#L112" >}} {{< /tab >}} {{< tab header="JavaScript" >}} {{< badge-code >}} @@ -379,7 +379,7 @@ You can drive Chrome Cast devices, including sharing tabs {{< badge-code >}} {{< /tab >}} {{< tab header="Ruby" >}} -{{< gh-codeblock path="/examples/ruby/spec/browsers/chrome_spec.rb#L119-L124" >}} +{{< gh-codeblock path="/examples/ruby/spec/browsers/chrome_spec.rb#L123-L128" >}} {{< /tab >}} {{< tab header="JavaScript" >}} {{< badge-code >}} @@ -405,7 +405,7 @@ You can simulate various network conditions. {{< badge-code >}} {{< /tab >}} {{< tab header="Ruby" >}} -{{< gh-codeblock path="/examples/ruby/spec/browsers/chrome_spec.rb#L129" >}} +{{< gh-codeblock path="/examples/ruby/spec/browsers/chrome_spec.rb#L133" >}} {{< /tab >}} {{< tab header="JavaScript" >}} {{< badge-code >}} @@ -428,7 +428,7 @@ You can simulate various network conditions. {{< badge-code >}} {{< /tab >}} {{< tab header="Ruby" >}} -{{< gh-codeblock path="/examples/ruby/spec/browsers/chrome_spec.rb#L141" >}} +{{< gh-codeblock path="/examples/ruby/spec/browsers/chrome_spec.rb#L145" >}} {{< /tab >}} {{< tab header="JavaScript" >}} {{< badge-code >}} @@ -451,7 +451,7 @@ You can simulate various network conditions. {{< badge-code >}} {{< /tab >}} {{< tab header="Ruby" >}} -{{< gh-codeblock path="/examples/ruby/spec/browsers/chrome_spec.rb#L149-L150" >}} +{{< gh-codeblock path="/examples/ruby/spec/browsers/chrome_spec.rb#L153-L154" >}} {{< /tab >}} {{< tab header="JavaScript" >}} {{< badge-code >}} diff --git a/website_and_docs/content/documentation/webdriver/browsers/chrome.ja.md b/website_and_docs/content/documentation/webdriver/browsers/chrome.ja.md index 2949c39cf827..192f69d711fe 100644 --- a/website_and_docs/content/documentation/webdriver/browsers/chrome.ja.md +++ b/website_and_docs/content/documentation/webdriver/browsers/chrome.ja.md @@ -22,7 +22,7 @@ ChromeおよびChromiumに特有の機能は、Googleの [Capabilities & ChromeO {{< tabpane text=true >}} {{< tab header="Java" >}} -{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L37-L38" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L36-L37" >}} {{< /tab >}} {{% tab header="Python" %}} {{< gh-codeblock path="/examples/python/tests/browsers/test_chrome.py#L9-L10" >}} @@ -54,7 +54,7 @@ ChromeおよびChromiumに特有の機能は、Googleの [Capabilities & ChromeO {{< tabpane text=true >}} {{< tab header="Java" >}} -{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L45" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L44" >}} {{< /tab >}} {{% tab header="Python" %}} {{< gh-codeblock path="/examples/python/tests/browsers/test_chrome.py#L18" >}} @@ -82,7 +82,7 @@ ChromeおよびChromiumに特有の機能は、Googleの [Capabilities & ChromeO {{< tabpane text=true >}} {{< tab header="Java" >}} -{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L54" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L53" >}} {{< /tab >}} {{% tab header="Python" %}} {{< gh-codeblock path="/examples/python/tests/browsers/test_chrome.py#L29">}} @@ -91,7 +91,7 @@ ChromeおよびChromiumに特有の機能は、Googleの [Capabilities & ChromeO {{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Browsers/ChromeTest.cs#L49" >}} {{< /tab >}} {{< tab header="Ruby" >}} -{{< gh-codeblock path="/examples/ruby/spec/browsers/chrome_spec.rb#L25" >}} +{{< gh-codeblock path="/examples/ruby/spec/browsers/chrome_spec.rb#L27" >}} {{< /tab >}} {{< tab header="JavaScript" >}} {{< gh-codeblock path="/examples/javascript/test/browser/chromeSpecificCaps.spec.js#L41-L44">}} @@ -111,16 +111,16 @@ The `extensions` パラメータはcrxファイルを受け入れます。解凍 {{< tabpane text=true >}} {{< tab header="Java" >}} -{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L65" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L64" >}} {{< /tab >}} {{% tab header="Python" %}} {{< gh-codeblock path="/examples/python/tests/browsers/test_chrome.py#L40">}} {{% /tab %}} {{< tab header="CSharp" >}} -{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Browsers/ChromeTest.cs#L61" >}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Browsers/ChromeTest.cs#L62-67" >}} {{< /tab >}} {{< tab header="Ruby" >}} -{{< gh-codeblock path="/examples/ruby/spec/browsers/chrome_spec.rb#L34" >}} +{{< gh-codeblock path="/examples/ruby/spec/browsers/chrome_spec.rb#L36" >}} {{< /tab >}} {{< tab header="JavaScript" >}} {{< gh-codeblock path="/examples/javascript/test/browser/chromeSpecificCaps.spec.js#L62-L66">}} @@ -174,7 +174,7 @@ Chrome はさまざまな引数を追加します。 {{< gh-codeblock path="/examples/python/tests/browsers/test_chrome.py#L62" >}} {{% /tab %}} {{< tab header="CSharp" >}} -{{< gh-codeblock path="examples/dotnet/SeleniumDocs/Browsers/ChromeTest.cs#L76" >}} +{{< gh-codeblock path="examples/dotnet/SeleniumDocs/Browsers/ChromeTest.cs#L82" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< gh-codeblock path="/examples/ruby/spec/browsers/chrome_spec.rb#L53" >}} diff --git a/website_and_docs/content/documentation/webdriver/browsers/chrome.pt-br.md b/website_and_docs/content/documentation/webdriver/browsers/chrome.pt-br.md index ad5a7234b3d0..c490f626dc49 100644 --- a/website_and_docs/content/documentation/webdriver/browsers/chrome.pt-br.md +++ b/website_and_docs/content/documentation/webdriver/browsers/chrome.pt-br.md @@ -21,7 +21,7 @@ Este é um exemplo de como iniciar uma sessão Chrome com um conjunto de opçõe {{< tabpane text=true >}} {{< tab header="Java" >}} -{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L37-L38" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L36-L37" >}} {{< /tab >}} {{% tab header="Python" %}} {{< gh-codeblock path="/examples/python/tests/browsers/test_chrome.py#L9-L10" >}} @@ -55,7 +55,7 @@ Add an argument to options: {{< tabpane text=true >}} {{< tab header="Java" >}} -{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L45" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L44" >}} {{< /tab >}} {{% tab header="Python" %}} {{< gh-codeblock path="/examples/python/tests/browsers/test_chrome.py#L18" >}} @@ -80,7 +80,7 @@ Adicionar uma localização: {{< tabpane text=true >}} {{< tab header="Java" >}} -{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L54" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L53" >}} {{< /tab >}} {{% tab header="Python" %}} {{< gh-codeblock path="/examples/python/tests/browsers/test_chrome.py#L29">}} @@ -111,13 +111,13 @@ Adicionar uma extensão: {{< tabpane text=true >}} {{< tab header="Java" >}} -{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L65" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L64" >}} {{< /tab >}} {{% tab header="Python" %}} {{< gh-codeblock path="/examples/python/tests/browsers/test_chrome.py#L40">}} {{% /tab %}} {{< tab header="CSharp" >}} -{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Browsers/ChromeTest.cs#L61" >}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Browsers/ChromeTest.cs#L62-67">}} {{< /tab >}} {{< tab header="Ruby" >}} {{< gh-codeblock path="/examples/ruby/spec/browsers/chrome_spec.rb#L34" >}} @@ -176,7 +176,7 @@ Exclua parametros: {{< gh-codeblock path="/examples/python/tests/browsers/test_chrome.py#L62" >}} {{% /tab %}} {{< tab header="CSharp" >}} -{{< gh-codeblock path="examples/dotnet/SeleniumDocs/Browsers/ChromeTest.cs#L76" >}} +{{< gh-codeblock path="examples/dotnet/SeleniumDocs/Browsers/ChromeTest.cs#L82" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< gh-codeblock path="/examples/ruby/spec/browsers/chrome_spec.rb#L53" >}} diff --git a/website_and_docs/content/documentation/webdriver/browsers/chrome.zh-cn.md b/website_and_docs/content/documentation/webdriver/browsers/chrome.zh-cn.md index 44882a2a3f57..6c246ad2cb74 100644 --- a/website_and_docs/content/documentation/webdriver/browsers/chrome.zh-cn.md +++ b/website_and_docs/content/documentation/webdriver/browsers/chrome.zh-cn.md @@ -21,7 +21,7 @@ Chrome浏览器的特有功能可以在谷歌的页面找到: [Capabilities & Ch {{< tabpane text=true >}} {{< tab header="Java" >}} -{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L37-L38" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L36-L37" >}} {{< /tab >}} {{% tab header="Python" %}} {{< gh-codeblock path="/examples/python/tests/browsers/test_chrome.py#L9-L10" >}} @@ -55,7 +55,7 @@ Chrome浏览器的特有功能可以在谷歌的页面找到: [Capabilities & Ch {{< tabpane text=true >}} {{< tab header="Java" >}} -{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L45" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L44" >}} {{< /tab >}} {{% tab header="Python" %}} {{< gh-codeblock path="/examples/python/tests/browsers/test_chrome.py#L18" >}} @@ -82,7 +82,7 @@ Chrome浏览器的特有功能可以在谷歌的页面找到: [Capabilities & Ch {{< tabpane text=true >}} {{< tab header="Java" >}} -{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L54" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L53" >}} {{< /tab >}} {{% tab header="Python" %}} {{< gh-codeblock path="/examples/python/tests/browsers/test_chrome.py#L29">}} @@ -111,13 +111,13 @@ Chrome浏览器的特有功能可以在谷歌的页面找到: [Capabilities & Ch {{< tabpane text=true >}} {{< tab header="Java" >}} -{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L65" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java#L64" >}} {{< /tab >}} {{% tab header="Python" %}} {{< gh-codeblock path="/examples/python/tests/browsers/test_chrome.py#L40">}} {{% /tab %}} {{< tab header="CSharp" >}} -{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Browsers/ChromeTest.cs#L61" >}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Browsers/ChromeTest.cs#L62-67" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< gh-codeblock path="/examples/ruby/spec/browsers/chrome_spec.rb#L34" >}} @@ -174,7 +174,7 @@ Chrome 添加了各种参数,如果你不希望添加某些参数,可以将 {{< gh-codeblock path="/examples/python/tests/browsers/test_chrome.py#L62" >}} {{% /tab %}} {{< tab header="CSharp" >}} -{{< gh-codeblock path="examples/dotnet/SeleniumDocs/Browsers/ChromeTest.cs#L76" >}} +{{< gh-codeblock path="examples/dotnet/SeleniumDocs/Browsers/ChromeTest.cs#L82" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< gh-codeblock path="/examples/ruby/spec/browsers/chrome_spec.rb#L53" >}} diff --git a/website_and_docs/content/documentation/webdriver/browsers/firefox.en.md b/website_and_docs/content/documentation/webdriver/browsers/firefox.en.md index e38174e824e5..6dd175d6c3c1 100644 --- a/website_and_docs/content/documentation/webdriver/browsers/firefox.en.md +++ b/website_and_docs/content/documentation/webdriver/browsers/firefox.en.md @@ -106,7 +106,7 @@ There are several ways to work with Firefox profiles. {{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/FirefoxTest.java#L211-L216" >}} {{< /tab >}} {{< tab header="Python" text=true >}} -{{< gh-codeblock path="/examples/python/tests/browsers/test_firefox.py#L157-L165" >}} +{{< gh-codeblock path="/examples/python/tests/browsers/test_firefox.py#L160-L168" >}} {{< /tab >}} {{< tab header="CSharp" >}} var options = new FirefoxOptions(); @@ -135,7 +135,16 @@ options.profile = FirefoxProfile() driver = FirefoxDriver(options) {{< /tab >}} {{< /tabpane >}} +**Note**: Whether you create an empty `FirefoxProfile` or point it to the directory of your own profile, Selenium +will create a temporary directory to store either the data of the new profile or a copy of your existing one. Every +time you run your program, a different temporary directory will be created. These directories are not cleaned up +explicitly by Selenium, they should eventually get removed by the operating system. However, if you want to remove +the copy manually (e.g. if your profile is large in size), the path of the copy is exposed by the `FirefoxProfile` +object. Check the language specific implementation to see how to retrieve that location. +If you want to use an existing Firefox profile, you can pass in the path to that profile. Please refer to the official +[Firefox documentation](https://support.mozilla.org/en-US/kb/profiles-where-firefox-stores-user-data#w_how-do-i-find-my-profile) +for instructions on how to find the directory of your profile. ## Service @@ -436,7 +445,7 @@ please refer to the {{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/FirefoxTest.java#L197-L198" >}} {{< /tab >}} {{< tab header="Python" >}} -{{< gh-codeblock path="/examples/python/tests/browsers/test_firefox.py#L149-L150" >}} +{{< gh-codeblock path="/examples/python/tests/browsers/test_firefox.py#L151-L152" >}} {{< /tab >}} {{< tab header="CSharp" >}} {{< badge-code >}} @@ -451,3 +460,5 @@ please refer to the {{< badge-code >}} {{< /tab >}} {{< /tabpane >}} + +**Note**: As of Firefox 138, geckodriver needs to be started with the argument `--allow-system-access` to switch the context to `CHROME`. diff --git a/website_and_docs/content/documentation/webdriver/browsers/firefox.ja.md b/website_and_docs/content/documentation/webdriver/browsers/firefox.ja.md index 664ab91d6bf6..5713931b1f32 100644 --- a/website_and_docs/content/documentation/webdriver/browsers/firefox.ja.md +++ b/website_and_docs/content/documentation/webdriver/browsers/firefox.ja.md @@ -110,7 +110,7 @@ Firefoxプロファイルを操作するにはいくつかの方法がありま {{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/FirefoxTest.java#L211-L216" >}} {{< /tab >}} {{< tab header="Python" text=true >}} -{{< gh-codeblock path="/examples/python/tests/browsers/test_firefox.py#L157-L165" >}} +{{< gh-codeblock path="/examples/python/tests/browsers/test_firefox.py#L160-L168" >}} {{< /tab >}} {{< tab header="CSharp" >}} var options = new FirefoxOptions(); @@ -141,6 +141,16 @@ driver = RemoteWebDriver(options) {{< /tabpane >}}
+**Note**: Whether you create an empty `FirefoxProfile` or point it to the directory of your own profile, Selenium +will create a temporary directory to store either the data of the new profile or a copy of your existing one. Every +time you run your program, a different temporary directory will be created. These directories are not cleaned up +explicitly by Selenium, they should eventually get removed by the operating system. However, if you want to remove +the copy manually (e.g. if your profile is large in size), the path of the copy is exposed by the `FirefoxProfile` +object. Check the language specific implementation to see how to retrieve that location. + +If you want to use an existing Firefox profile, you can pass in the path to that profile. Please refer to the official +[Firefox documentation](https://support.mozilla.org/en-US/kb/profiles-where-firefox-stores-user-data#w_how-do-i-find-my-profile) +for instructions on how to find the directory of your profile. ## サービス @@ -432,7 +442,7 @@ IDはアドオンインストール時の戻り値から取得できます。 {{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/FirefoxTest.java#L197-L198" >}} {{< /tab >}} {{< tab header="Python" >}} -{{< gh-codeblock path="/examples/python/tests/browsers/test_firefox.py#L149-L150" >}} +{{< gh-codeblock path="/examples/python/tests/browsers/test_firefox.py#L151-L152" >}} {{< /tab >}} {{< tab header="CSharp" >}} {{< badge-code >}} @@ -447,3 +457,5 @@ IDはアドオンインストール時の戻り値から取得できます。 {{< badge-code >}} {{< /tab >}} {{< /tabpane >}} + +**Note**: As of Firefox 138, geckodriver needs to be started with the argument `--allow-system-access` to switch the context to `CHROME`. diff --git a/website_and_docs/content/documentation/webdriver/browsers/firefox.pt-br.md b/website_and_docs/content/documentation/webdriver/browsers/firefox.pt-br.md index 0603016ae1d2..f582ca55e06e 100644 --- a/website_and_docs/content/documentation/webdriver/browsers/firefox.pt-br.md +++ b/website_and_docs/content/documentation/webdriver/browsers/firefox.pt-br.md @@ -109,7 +109,7 @@ Existem várias formas de trabalhar com perfis Firefox {{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/FirefoxTest.java#L211-L216" >}} {{< /tab >}} {{< tab header="Python" text=true >}} -{{< gh-codeblock path="/examples/python/tests/browsers/test_firefox.py#L157-L165" >}} +{{< gh-codeblock path="/examples/python/tests/browsers/test_firefox.py#L160-L168" >}} {{< /tab >}} {{< tab header="CSharp" >}} var options = new FirefoxOptions(); @@ -140,6 +140,16 @@ driver = RemoteWebDriver(options) {{< /tabpane >}} +**Note**: Whether you create an empty `FirefoxProfile` or point it to the directory of your own profile, Selenium +will create a temporary directory to store either the data of the new profile or a copy of your existing one. Every +time you run your program, a different temporary directory will be created. These directories are not cleaned up +explicitly by Selenium, they should eventually get removed by the operating system. However, if you want to remove +the copy manually (e.g. if your profile is large in size), the path of the copy is exposed by the `FirefoxProfile` +object. Check the language specific implementation to see how to retrieve that location. + +If you want to use an existing Firefox profile, you can pass in the path to that profile. Please refer to the official +[Firefox documentation](https://support.mozilla.org/en-US/kb/profiles-where-firefox-stores-user-data#w_how-do-i-find-my-profile) +for instructions on how to find the directory of your profile. ## Service @@ -441,7 +451,7 @@ please refer to the {{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/FirefoxTest.java#L197-L198" >}} {{< /tab >}} {{< tab header="Python" >}} -{{< gh-codeblock path="/examples/python/tests/browsers/test_firefox.py#L149-L150" >}} +{{< gh-codeblock path="/examples/python/tests/browsers/test_firefox.py#L151-L152" >}} {{< /tab >}} {{< tab header="CSharp" >}} {{< badge-code >}} @@ -456,3 +466,5 @@ please refer to the {{< badge-code >}} {{< /tab >}} {{< /tabpane >}} + +**Note**: As of Firefox 138, geckodriver needs to be started with the argument `--allow-system-access` to switch the context to `CHROME`. diff --git a/website_and_docs/content/documentation/webdriver/browsers/firefox.zh-cn.md b/website_and_docs/content/documentation/webdriver/browsers/firefox.zh-cn.md index d1384cebc591..4376fea4bb62 100644 --- a/website_and_docs/content/documentation/webdriver/browsers/firefox.zh-cn.md +++ b/website_and_docs/content/documentation/webdriver/browsers/firefox.zh-cn.md @@ -108,7 +108,7 @@ There are several ways to work with Firefox profiles {{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/FirefoxTest.java#L211-L216" >}} {{< /tab >}} {{< tab header="Python" text=true >}} -{{< gh-codeblock path="/examples/python/tests/browsers/test_firefox.py#L157-L165" >}} +{{< gh-codeblock path="/examples/python/tests/browsers/test_firefox.py#L160-L168" >}} {{< /tab >}} {{< tab header="CSharp" >}} var options = new FirefoxOptions(); @@ -139,6 +139,16 @@ driver = RemoteWebDriver(options) {{< /tabpane >}} +**Note**: Whether you create an empty `FirefoxProfile` or point it to the directory of your own profile, Selenium +will create a temporary directory to store either the data of the new profile or a copy of your existing one. Every +time you run your program, a different temporary directory will be created. These directories are not cleaned up +explicitly by Selenium, they should eventually get removed by the operating system. However, if you want to remove +the copy manually (e.g. if your profile is large in size), the path of the copy is exposed by the `FirefoxProfile` +object. Check the language specific implementation to see how to retrieve that location. + +If you want to use an existing Firefox profile, you can pass in the path to that profile. Please refer to the official +[Firefox documentation](https://support.mozilla.org/en-US/kb/profiles-where-firefox-stores-user-data#w_how-do-i-find-my-profile) +for instructions on how to find the directory of your profile. ## Service @@ -438,7 +448,7 @@ please refer to the {{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/browsers/FirefoxTest.java#L197-L198" >}} {{< /tab >}} {{< tab header="Python" >}} -{{< gh-codeblock path="/examples/python/tests/browsers/test_firefox.py#L149-L150" >}} +{{< gh-codeblock path="/examples/python/tests/browsers/test_firefox.py#L151-L152" >}} {{< /tab >}} {{< tab header="CSharp" >}} {{< badge-code >}} @@ -453,3 +463,5 @@ please refer to the {{< badge-code >}} {{< /tab >}} {{< /tabpane >}} + +**Note**: As of Firefox 138, geckodriver needs to be started with the argument `--allow-system-access` to switch the context to `CHROME`. diff --git a/website_and_docs/content/documentation/webdriver/drivers/_index.en.md b/website_and_docs/content/documentation/webdriver/drivers/_index.en.md index 991bdc15fc56..5910e580f9e8 100644 --- a/website_and_docs/content/documentation/webdriver/drivers/_index.en.md +++ b/website_and_docs/content/documentation/webdriver/drivers/_index.en.md @@ -41,7 +41,7 @@ on the local machine. {{< gh-codeblock path="examples/ruby/spec/drivers/options_spec.rb#L14" >}} {{< /tab >}} {{< tab header="JavaScript" >}} -{{< gh-codeblock path="examples/javascript/test/drivers/service.spec.js#L32-L36" >}} +{{< gh-codeblock path="examples/javascript/test/drivers/service.spec.js#L46-L50" >}} {{< /tab >}} {{< tab header="Kotlin" >}} {{< badge-code >}} diff --git a/website_and_docs/content/documentation/webdriver/drivers/_index.ja.md b/website_and_docs/content/documentation/webdriver/drivers/_index.ja.md index b7602f6e607d..971b46385859 100644 --- a/website_and_docs/content/documentation/webdriver/drivers/_index.ja.md +++ b/website_and_docs/content/documentation/webdriver/drivers/_index.ja.md @@ -38,7 +38,7 @@ weight: 3 {{< gh-codeblock path="examples/ruby/spec/drivers/options_spec.rb#L14" >}} {{< /tab >}} {{< tab header="JavaScript" >}} -{{< gh-codeblock path="examples/javascript/test/drivers/service.spec.js#L32-L36" >}} +{{< gh-codeblock path="examples/javascript/test/drivers/service.spec.js#L46-L50" >}} {{< /tab >}} {{< tab header="Kotlin" >}} {{< badge-code >}} diff --git a/website_and_docs/content/documentation/webdriver/drivers/_index.pt-br.md b/website_and_docs/content/documentation/webdriver/drivers/_index.pt-br.md index e5e3beae0541..5c7e5072d964 100644 --- a/website_and_docs/content/documentation/webdriver/drivers/_index.pt-br.md +++ b/website_and_docs/content/documentation/webdriver/drivers/_index.pt-br.md @@ -41,7 +41,7 @@ on the local machine. {{< gh-codeblock path="examples/ruby/spec/drivers/options_spec.rb#L14" >}} {{< /tab >}} {{< tab header="JavaScript" >}} -{{< gh-codeblock path="examples/javascript/test/drivers/service.spec.js#L32-L36" >}} +{{< gh-codeblock path="examples/javascript/test/drivers/service.spec.js#L46-L50" >}} {{< /tab >}} {{< tab header="Kotlin" >}} {{< badge-code >}} diff --git a/website_and_docs/content/documentation/webdriver/drivers/_index.zh-cn.md b/website_and_docs/content/documentation/webdriver/drivers/_index.zh-cn.md index 09d36622ecbe..29a474db7c0a 100644 --- a/website_and_docs/content/documentation/webdriver/drivers/_index.zh-cn.md +++ b/website_and_docs/content/documentation/webdriver/drivers/_index.zh-cn.md @@ -39,7 +39,7 @@ weight: 3 {{< gh-codeblock path="examples/ruby/spec/drivers/options_spec.rb#L14" >}} {{< /tab >}} {{< tab header="JavaScript" >}} -{{< gh-codeblock path="examples/javascript/test/drivers/service.spec.js#L32-L36" >}} +{{< gh-codeblock path="examples/javascript/test/drivers/service.spec.js#L46-L50" >}} {{< /tab >}} {{< tab header="Kotlin" >}} {{< badge-code >}} diff --git a/website_and_docs/content/documentation/webdriver/drivers/options.en.md b/website_and_docs/content/documentation/webdriver/drivers/options.en.md index 3bd3b64f5795..b46d7d214d8f 100644 --- a/website_and_docs/content/documentation/webdriver/drivers/options.en.md +++ b/website_and_docs/content/documentation/webdriver/drivers/options.en.md @@ -119,24 +119,8 @@ event fire is returned. {{< tab header="Python" text=true >}} {{< gh-codeblock path="/examples/python/tests/drivers/test_options.py#L7-9">}} {{< /tab >}} -{{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; - -namespace pageLoadStrategy { - class pageLoadStrategy { - public static void Main(string[] args) { - var chromeOptions = new ChromeOptions(); - chromeOptions.PageLoadStrategy = PageLoadStrategy.Normal; - IWebDriver driver = new ChromeDriver(chromeOptions); - try { - driver.Navigate().GoToUrl("https://example.com/"); - } finally { - driver.Quit(); - } - } - } -} +{{< tab header="CSharp" text=true >}} +{{< gh-codeblock path="examples/dotnet/SeleniumDocs/Drivers/OptionsTest.cs#L13-14" >}} {{< /tab >}} {{< tab header="Ruby" text=true >}} {{< gh-codeblock path="/examples/ruby/spec/drivers/options_spec.rb#L11-L12">}} @@ -176,24 +160,8 @@ event fire is returned. {{< tab header="Python" text=true >}} {{< gh-codeblock path="/examples/python/tests/drivers/test_options.py#L15-L17">}} {{< /tab >}} -{{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; - -namespace pageLoadStrategy { - class pageLoadStrategy { - public static void Main(string[] args) { - var chromeOptions = new ChromeOptions(); - chromeOptions.PageLoadStrategy = PageLoadStrategy.Eager; - IWebDriver driver = new ChromeDriver(chromeOptions); - try { - driver.Navigate().GoToUrl("https://example.com/"); - } finally { - driver.Quit(); - } - } - } -} +{{< tab header="CSharp" text=true >}} +{{< gh-codeblock path="examples/dotnet/SeleniumDocs/Drivers/OptionsTest.cs#L29-30" >}} {{< /tab >}} {{< tab header="Ruby" text=true >}} {{< gh-codeblock path="/examples/ruby/spec/drivers/options_spec.rb#L20-L21">}} @@ -232,24 +200,8 @@ WebDriver only waits until the initial page is downloaded. {{< tab header="Python" text=true >}} {{< gh-codeblock path="/examples/python/tests/drivers/test_options.py#L23-L25">}} {{< /tab >}} -{{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; - -namespace pageLoadStrategy { - class pageLoadStrategy { - public static void Main(string[] args) { - var chromeOptions = new ChromeOptions(); - chromeOptions.PageLoadStrategy = PageLoadStrategy.None; - IWebDriver driver = new ChromeDriver(chromeOptions); - try { - driver.Navigate().GoToUrl("https://example.com/"); - } finally { - driver.Quit(); - } - } - } -} +{{< tab header="CSharp" text=true >}} +{{< gh-codeblock path="examples/dotnet/SeleniumDocs/Drivers/OptionsTest.cs#L41-42" >}} {{< /tab >}} {{< tab header="Ruby" text=true >}} {{< gh-codeblock path="/examples/ruby/spec/drivers/options_spec.rb#L29-L30">}} diff --git a/website_and_docs/content/documentation/webdriver/drivers/options.ja.md b/website_and_docs/content/documentation/webdriver/drivers/options.ja.md index a46cf6bacc84..08bd6810f29d 100644 --- a/website_and_docs/content/documentation/webdriver/drivers/options.ja.md +++ b/website_and_docs/content/documentation/webdriver/drivers/options.ja.md @@ -115,24 +115,8 @@ WebDriver は [load](https://developer.mozilla.org/ja/docs/Web/API/Window/load_e {{< tab header="Python" text=true >}} {{< gh-codeblock path="/examples/python/tests/drivers/test_options.py#L7-9">}} {{< /tab >}} -{{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; - -namespace pageLoadStrategy { - class pageLoadStrategy { - public static void Main(string[] args) { - var chromeOptions = new ChromeOptions(); - chromeOptions.PageLoadStrategy = PageLoadStrategy.Normal; - IWebDriver driver = new ChromeDriver(chromeOptions); - try { - driver.Navigate().GoToUrl("https://example.com/"); - } finally { - driver.Quit(); - } - } - } -} +{{< tab header="CSharp" text=true >}} +{{< gh-codeblock path="examples/dotnet/SeleniumDocs/Drivers/OptionsTest.cs#L13-14" >}} {{< /tab >}} {{< tab header="Ruby" text=true >}} {{< gh-codeblock path="/examples/ruby/spec/drivers/options_spec.rb#L11-L12">}} @@ -171,24 +155,8 @@ WebDriver は、[DOMContentLoaded](https://developer.mozilla.org/ja/docs/Web/API {{< tab header="Python" text=true >}} {{< gh-codeblock path="/examples/python/tests/drivers/test_options.py#L15-L17">}} {{< /tab >}} -{{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; - -namespace pageLoadStrategy { - class pageLoadStrategy { - public static void Main(string[] args) { - var chromeOptions = new ChromeOptions(); - chromeOptions.PageLoadStrategy = PageLoadStrategy.Eager; - IWebDriver driver = new ChromeDriver(chromeOptions); - try { - driver.Navigate().GoToUrl("https://example.com/"); - } finally { - driver.Quit(); - } - } - } -} +{{< tab header="CSharp" text=true >}} +{{< gh-codeblock path="examples/dotnet/SeleniumDocs/Drivers/OptionsTest.cs#L29-30" >}} {{< /tab >}} {{< tab header="Ruby" text=true >}} {{< gh-codeblock path="/examples/ruby/spec/drivers/options_spec.rb#L20-L21">}} @@ -226,24 +194,8 @@ WebDriver は、最初のページがダウンロードされるまで待機し {{< tab header="Python" text=true >}} {{< gh-codeblock path="/examples/python/tests/drivers/test_options.py#L23-L25">}} {{< /tab >}} -{{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; - -namespace pageLoadStrategy { - class pageLoadStrategy { - public static void Main(string[] args) { - var chromeOptions = new ChromeOptions(); - chromeOptions.PageLoadStrategy = PageLoadStrategy.None; - IWebDriver driver = new ChromeDriver(chromeOptions); - try { - driver.Navigate().GoToUrl("https://example.com/"); - } finally { - driver.Quit(); - } - } - } -} +{{< tab header="CSharp" text=true >}} +{{< gh-codeblock path="examples/dotnet/SeleniumDocs/Drivers/OptionsTest.cs#L41-42" >}} {{< /tab >}} {{< tab header="Ruby" text=true >}} {{< gh-codeblock path="/examples/ruby/spec/drivers/options_spec.rb#L29-L30">}} diff --git a/website_and_docs/content/documentation/webdriver/drivers/options.pt-br.md b/website_and_docs/content/documentation/webdriver/drivers/options.pt-br.md index 574b772527ec..8f6d943358c3 100644 --- a/website_and_docs/content/documentation/webdriver/drivers/options.pt-br.md +++ b/website_and_docs/content/documentation/webdriver/drivers/options.pt-br.md @@ -131,25 +131,8 @@ event fire is returned. {{< /tab >}} {{< tab header="Python" text=true >}} {{< gh-codeblock path="/examples/python/tests/drivers/test_options.py#L7-9">}} -{{< /tab >}} -{{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; - -namespace pageLoadStrategy { - class pageLoadStrategy { - public static void Main(string[] args) { - var chromeOptions = new ChromeOptions(); - chromeOptions.PageLoadStrategy = PageLoadStrategy.Normal; - IWebDriver driver = new ChromeDriver(chromeOptions); - try { - driver.Navigate().GoToUrl("https://example.com/"); - } finally { - driver.Quit(); - } - } - } -} +{{< /tab >}}{{< tab header="CSharp" text=true >}} +{{< gh-codeblock path="examples/dotnet/SeleniumDocs/Drivers/OptionsTest.cs#L13-14" >}} {{< /tab >}} {{< tab header="Ruby" text=true >}} {{< gh-codeblock path="/examples/ruby/spec/drivers/options_spec.rb#L11-L12">}} @@ -188,24 +171,8 @@ event fire is returned. {{< tab header="Python" text=true >}} {{< gh-codeblock path="/examples/python/tests/drivers/test_options.py#L15-L17">}} {{< /tab >}} -{{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; - -namespace pageLoadStrategy { - class pageLoadStrategy { - public static void Main(string[] args) { - var chromeOptions = new ChromeOptions(); - chromeOptions.PageLoadStrategy = PageLoadStrategy.Eager; - IWebDriver driver = new ChromeDriver(chromeOptions); - try { - driver.Navigate().GoToUrl("https://example.com/"); - } finally { - driver.Quit(); - } - } - } -} +{{< tab header="CSharp" text=true >}} +{{< gh-codeblock path="examples/dotnet/SeleniumDocs/Drivers/OptionsTest.cs#L29-30" >}} {{< /tab >}} {{< tab header="Ruby" text=true >}} {{< gh-codeblock path="/examples/ruby/spec/drivers/options_spec.rb#L20-L21">}} @@ -243,24 +210,8 @@ WebDriver only waits until the initial page is downloaded. {{< tab header="Python" text=true >}} {{< gh-codeblock path="/examples/python/tests/drivers/test_options.py#L23-L25">}} {{< /tab >}} -{{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; - -namespace pageLoadStrategy { - class pageLoadStrategy { - public static void Main(string[] args) { - var chromeOptions = new ChromeOptions(); - chromeOptions.PageLoadStrategy = PageLoadStrategy.None; - IWebDriver driver = new ChromeDriver(chromeOptions); - try { - driver.Navigate().GoToUrl("https://example.com/"); - } finally { - driver.Quit(); - } - } - } -} +{{< tab header="CSharp" text=true >}} +{{< gh-codeblock path="examples/dotnet/SeleniumDocs/Drivers/OptionsTest.cs#L41-42" >}} {{< /tab >}} {{< tab header="Ruby" text=true >}} {{< gh-codeblock path="/examples/ruby/spec/drivers/options_spec.rb#L29-L30">}} diff --git a/website_and_docs/content/documentation/webdriver/drivers/options.zh-cn.md b/website_and_docs/content/documentation/webdriver/drivers/options.zh-cn.md index 035ae4883aae..01bae2762c1b 100644 --- a/website_and_docs/content/documentation/webdriver/drivers/options.zh-cn.md +++ b/website_and_docs/content/documentation/webdriver/drivers/options.zh-cn.md @@ -127,25 +127,8 @@ WebDriver一直等到 [load](https://developer.mozilla.org/en-US/docs/Web/API/Wi {{< /tab >}} {{< tab header="Python" text=true >}} {{< gh-codeblock path="/examples/python/tests/drivers/test_options.py#L7-9">}} -{{< /tab >}} -{{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; - -namespace pageLoadStrategy { - class pageLoadStrategy { - public static void Main(string[] args) { - var chromeOptions = new ChromeOptions(); - chromeOptions.PageLoadStrategy = PageLoadStrategy.Normal; - IWebDriver driver = new ChromeDriver(chromeOptions); - try { - driver.Navigate().GoToUrl("https://example.com/"); - } finally { - driver.Quit(); - } - } - } -} +{{< /tab >}}{{< tab header="CSharp" text=true >}} +{{< gh-codeblock path="examples/dotnet/SeleniumDocs/Drivers/OptionsTest.cs#L13-14" >}} {{< /tab >}} {{< tab header="Ruby" text=true >}} {{< gh-codeblock path="/examples/ruby/spec/drivers/options_spec.rb#L11-L12">}} @@ -184,24 +167,8 @@ WebDriver一直等到 [DOMContentLoaded](https://developer.mozilla.org/en-US/doc {{< tab header="Python" text=true >}} {{< gh-codeblock path="/examples/python/tests/drivers/test_options.py#L15-L17">}} {{< /tab >}} -{{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; - -namespace pageLoadStrategy { - class pageLoadStrategy { - public static void Main(string[] args) { - var chromeOptions = new ChromeOptions(); - chromeOptions.PageLoadStrategy = PageLoadStrategy.Eager; - IWebDriver driver = new ChromeDriver(chromeOptions); - try { - driver.Navigate().GoToUrl("https://example.com/"); - } finally { - driver.Quit(); - } - } - } -} +{{< tab header="CSharp" text=true >}} +{{< gh-codeblock path="examples/dotnet/SeleniumDocs/Drivers/OptionsTest.cs#L29-30" >}} {{< /tab >}} {{< tab header="Ruby" text=true >}} {{< gh-codeblock path="/examples/ruby/spec/drivers/options_spec.rb#L20-L21">}} @@ -239,24 +206,8 @@ WebDriver 仅等待初始页面已下载. {{< tab header="Python" text=true >}} {{< gh-codeblock path="/examples/python/tests/drivers/test_options.py#L23-L25">}} {{< /tab >}} -{{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; - -namespace pageLoadStrategy { - class pageLoadStrategy { - public static void Main(string[] args) { - var chromeOptions = new ChromeOptions(); - chromeOptions.PageLoadStrategy = PageLoadStrategy.None; - IWebDriver driver = new ChromeDriver(chromeOptions); - try { - driver.Navigate().GoToUrl("https://example.com/"); - } finally { - driver.Quit(); - } - } - } -} +{{< tab header="CSharp" text=true >}} +{{< gh-codeblock path="examples/dotnet/SeleniumDocs/Drivers/OptionsTest.cs#L41-42" >}} {{< /tab >}} {{< tab header="Ruby" text=true >}} {{< gh-codeblock path="/examples/ruby/spec/drivers/options_spec.rb#L29-L30">}} diff --git a/website_and_docs/content/documentation/webdriver/drivers/service.en.md b/website_and_docs/content/documentation/webdriver/drivers/service.en.md index 91328afaf977..f1075084ec8a 100644 --- a/website_and_docs/content/documentation/webdriver/drivers/service.en.md +++ b/website_and_docs/content/documentation/webdriver/drivers/service.en.md @@ -61,7 +61,7 @@ If you cannot update Selenium or have an advanced use case, here is how to speci {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/ruby/spec/drivers/service_spec.rb#L22" >}} +{{< gh-codeblock path="examples/ruby/spec/drivers/service_spec.rb#L26" >}} {{< /tab >}} {{< tab header="JavaScript" >}} {{< badge-code >}} @@ -88,7 +88,7 @@ If you want the driver to run on a specific port, you may specify it as follows: {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/ruby/spec/drivers/service_spec.rb#L29" >}} +{{< gh-codeblock path="examples/ruby/spec/drivers/service_spec.rb#L33" >}} {{< /tab >}} {{< tab header="JavaScript" >}} {{< badge-code >}} diff --git a/website_and_docs/content/documentation/webdriver/drivers/service.ja.md b/website_and_docs/content/documentation/webdriver/drivers/service.ja.md index 7071298fb0d5..2d7847da49b3 100644 --- a/website_and_docs/content/documentation/webdriver/drivers/service.ja.md +++ b/website_and_docs/content/documentation/webdriver/drivers/service.ja.md @@ -52,7 +52,7 @@ weight: 3 {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/ruby/spec/drivers/service_spec.rb#L22" >}} +{{< gh-codeblock path="examples/ruby/spec/drivers/service_spec.rb#L26" >}} {{< /tab >}} {{< tab header="JavaScript" >}} {{< badge-code >}} @@ -79,7 +79,7 @@ weight: 3 {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/ruby/spec/drivers/service_spec.rb#L29" >}} +{{< gh-codeblock path="examples/ruby/spec/drivers/service_spec.rb#L33" >}} {{< /tab >}} {{< tab header="JavaScript" >}} {{< badge-code >}} diff --git a/website_and_docs/content/documentation/webdriver/drivers/service.pt-br.md b/website_and_docs/content/documentation/webdriver/drivers/service.pt-br.md index 0d5844d709a4..cf40dc6a42ac 100644 --- a/website_and_docs/content/documentation/webdriver/drivers/service.pt-br.md +++ b/website_and_docs/content/documentation/webdriver/drivers/service.pt-br.md @@ -57,7 +57,7 @@ If you can not update Selenium or have an advanced use case here is how to speci {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/ruby/spec/drivers/service_spec.rb#L22" >}} +{{< gh-codeblock path="examples/ruby/spec/drivers/service_spec.rb#L26" >}} {{< /tab >}} {{< tab header="JavaScript" >}} {{< badge-code >}} @@ -84,7 +84,7 @@ If you want the driver to run on a specific port, you may specify it as follows: {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/ruby/spec/drivers/service_spec.rb#L29" >}} +{{< gh-codeblock path="examples/ruby/spec/drivers/service_spec.rb#L33" >}} {{< /tab >}} {{< tab header="JavaScript" >}} {{< badge-code >}} diff --git a/website_and_docs/content/documentation/webdriver/drivers/service.zh-cn.md b/website_and_docs/content/documentation/webdriver/drivers/service.zh-cn.md index 23429833aba5..78f98145aaba 100644 --- a/website_and_docs/content/documentation/webdriver/drivers/service.zh-cn.md +++ b/website_and_docs/content/documentation/webdriver/drivers/service.zh-cn.md @@ -59,7 +59,7 @@ weight: 3 {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/ruby/spec/drivers/service_spec.rb#L22" >}} +{{< gh-codeblock path="examples/ruby/spec/drivers/service_spec.rb#L26" >}} {{< /tab >}} {{< tab header="JavaScript" >}} {{< badge-code >}} @@ -87,7 +87,7 @@ weight: 3 {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/ruby/spec/drivers/service_spec.rb#L29" >}} +{{< gh-codeblock path="examples/ruby/spec/drivers/service_spec.rb#L33" >}} {{< /tab >}} {{< tab header="JavaScript" >}} {{< badge-code >}} diff --git a/website_and_docs/content/documentation/webdriver/getting_started/install_library.en.md b/website_and_docs/content/documentation/webdriver/getting_started/install_library.en.md index c1fda4c5d1a4..8584b09a26ca 100644 --- a/website_and_docs/content/documentation/webdriver/getting_started/install_library.en.md +++ b/website_and_docs/content/documentation/webdriver/getting_started/install_library.en.md @@ -37,7 +37,7 @@ Specify the dependency in the project `build.gradle` file as `testImplementation {{% /tab %}} {{% tab header="Python" %}} The minimum supported Python version for each Selenium version can be found -in `Supported Python Versions` on [PyPi](https://pypi.org/project/selenium/) +in "Supported Python Versions" on [PyPi](https://pypi.org/project/selenium/). There are a couple different ways to install Selenium. @@ -50,11 +50,11 @@ pip install selenium ### Download -Alternatively you can download the [PyPI source archive](https://pypi.org/project/selenium/#files) -(selenium-x.x.x.tar.gz) and install it using _setup.py_: +Alternatively you can download the [PyPI Built Distribution](https://pypi.org/project/selenium/#files) +(selenium-x.x.x.-py3-none-any.whl) and install it using _pip_: ```shell -python setup.py install +pip install selenium-x.x.x.-py3-none-any.whl ```
diff --git a/website_and_docs/content/documentation/webdriver/getting_started/install_library.ja.md b/website_and_docs/content/documentation/webdriver/getting_started/install_library.ja.md index cc266706a996..0f2c95dc2fd1 100644 --- a/website_and_docs/content/documentation/webdriver/getting_started/install_library.ja.md +++ b/website_and_docs/content/documentation/webdriver/getting_started/install_library.ja.md @@ -48,10 +48,10 @@ pip install selenium ### ダウンロード または、ダウンロードすることもできます[PyPI ソースアーカイブ](https://pypi.org/project/selenium/#files) -(selenium-x.x.x.tar.gz) を使用してインストールします _setup.py_ +(selenium-x.x.x.-py3-none-any.whl) を使用してインストールします _pip_: ```shell -python setup.py install +pip install selenium-x.x.x.-py3-none-any.whl ```
diff --git a/website_and_docs/content/documentation/webdriver/getting_started/install_library.pt-br.md b/website_and_docs/content/documentation/webdriver/getting_started/install_library.pt-br.md index 02456646fb26..3e0a116d3fd5 100644 --- a/website_and_docs/content/documentation/webdriver/getting_started/install_library.pt-br.md +++ b/website_and_docs/content/documentation/webdriver/getting_started/install_library.pt-br.md @@ -37,7 +37,7 @@ Especifique a dependência no `build.gradle` do seu projeto como `testImplementa {{% /tab %}} {{% tab header="Python" %}} A mínima versão suportada do Python para cada versão do Selenium pode ser encontrada -em `Supported Python Versions` no [PyPi](https://pypi.org/project/selenium/) +em "Supported Python Versions" no [PyPi](https://pypi.org/project/selenium/). Existe muitas formas diferentes de instalar Selenium. @@ -51,10 +51,10 @@ pip install selenium ### Download Como uma alternativa você pode baixar o [código fonte PyPI](https://pypi.org/project/selenium/#files) -(selenium-x.x.x.tar.gz) e instalar usando _setup.py_: +(selenium-x.x.x.-py3-none-any.whl) e instalar usando _pip_: ```shell -python setup.py install +pip install selenium-x.x.x.-py3-none-any.whl ```
diff --git a/website_and_docs/content/documentation/webdriver/getting_started/install_library.zh-cn.md b/website_and_docs/content/documentation/webdriver/getting_started/install_library.zh-cn.md index 3a3932a94a3a..2b3335bafc75 100644 --- a/website_and_docs/content/documentation/webdriver/getting_started/install_library.zh-cn.md +++ b/website_and_docs/content/documentation/webdriver/getting_started/install_library.zh-cn.md @@ -48,11 +48,11 @@ pip install selenium ### 下载 -此外你可以从这里下载 [PyPI source archive](https://pypi.org/project/selenium/#files) -(selenium-x.x.x.tar.gz) 并通过: _setup.py_ 文件安装: +此外你可以从这里下载 [PyPI Built Distribution](https://pypi.org/project/selenium/#files) +(selenium-x.x.x.-py3-none-any.whl) 并通过: _pip_ 文件安装: ```shell -python setup.py install +pip install selenium-x.x.x.-py3-none-any.whl ```
diff --git a/website_and_docs/content/documentation/webdriver/getting_started/using_selenium.en.md b/website_and_docs/content/documentation/webdriver/getting_started/using_selenium.en.md index 00dabca65ca1..f2641c0136b7 100644 --- a/website_and_docs/content/documentation/webdriver/getting_started/using_selenium.en.md +++ b/website_and_docs/content/documentation/webdriver/getting_started/using_selenium.en.md @@ -198,7 +198,7 @@ In your project's `package.json`, add requirement to `dependencies`: ### Tear Down -{{< gh-codeblock path="examples/ruby/spec/spec_helper.rb#L28" >}} +{{< gh-codeblock path="examples/ruby/spec/spec_helper.rb#L30" >}} {{% /tab %}} {{< tab header="JavaScript" >}} diff --git a/website_and_docs/content/documentation/webdriver/getting_started/using_selenium.ja.md b/website_and_docs/content/documentation/webdriver/getting_started/using_selenium.ja.md index 5f8c05ad8ef9..e69f82b69732 100644 --- a/website_and_docs/content/documentation/webdriver/getting_started/using_selenium.ja.md +++ b/website_and_docs/content/documentation/webdriver/getting_started/using_selenium.ja.md @@ -188,7 +188,7 @@ Seleniumコードの使用方法に関係なく、優れた統合開発環境が ### 取り壊す -{{< gh-codeblock path="examples/ruby/spec/spec_helper.rb#L28" >}} +{{< gh-codeblock path="examples/ruby/spec/spec_helper.rb#L30" >}} {{% /tab %}} {{< tab header="JavaScript" >}} diff --git a/website_and_docs/content/documentation/webdriver/getting_started/using_selenium.pt-br.md b/website_and_docs/content/documentation/webdriver/getting_started/using_selenium.pt-br.md index e4bc9a7ac093..8281f5211e32 100644 --- a/website_and_docs/content/documentation/webdriver/getting_started/using_selenium.pt-br.md +++ b/website_and_docs/content/documentation/webdriver/getting_started/using_selenium.pt-br.md @@ -192,7 +192,7 @@ In your project's `package.json`, adicionar requisito às `dependências`: ### Tear Down -{{< gh-codeblock path="examples/ruby/spec/spec_helper.rb#L28" >}} +{{< gh-codeblock path="examples/ruby/spec/spec_helper.rb#L30" >}} {{% /tab %}} {{< tab header="JavaScript" >}} diff --git a/website_and_docs/content/documentation/webdriver/getting_started/using_selenium.zh-cn.md b/website_and_docs/content/documentation/webdriver/getting_started/using_selenium.zh-cn.md index e3da22cd5f85..f7f1c09a37fb 100644 --- a/website_and_docs/content/documentation/webdriver/getting_started/using_selenium.zh-cn.md +++ b/website_and_docs/content/documentation/webdriver/getting_started/using_selenium.zh-cn.md @@ -6,7 +6,8 @@ description: > 使用IDE和Test Runner库组织Selenium的执行 --- -如果你不仅仅只是想执行一小撮的一次性脚本,你需要能组织和安排好你的代码。这一页会启发你如何真正地使用 Selenium 代码做高效的事情。 +如果你不仅仅只是想执行一小撮的一次性脚本,你需要能组织并编排好你的代码。 +本章会启发你如何真正地使用 Selenium 代码做高效的事情。 ## 常见用法 @@ -14,15 +15,19 @@ description: > ### 重复性任务 -有时候你需要往网站记录日志或者下载一些东西,或者提交一个表单,你可以在预设的时间创建一个 Selenium 脚本去执行一个服务。 +有时候你需要往网站记录日志或者下载一些东西,或者提交一个表单, +你可以在预设的时间创建一个 Selenium 脚本去执行一个服务。 ### 网页爬虫 -你是否期望从一个不提供 API 的网站收集数据?Selenium 可以满足你,但是请确保你了解该网站的服务条例,因为有些网站不允许你这样做,甚至有些网站会屏蔽 Selenium。 +你是否期望从一个不提供 API 的网站收集数据?Selenium 可以满足你, +但是请确保你了解该网站的服务条例, +因为有些网站不允许你这样做,甚至有些网站会屏蔽 Selenium。 ### 测试 -使用 Selenium 做测试需要在 Selenium 执行操作后进行断言,所以一个好的断言类库是很有必要的。至于组织测试用例结构的一些额外特性则需要[Test Runner](#test-runner)来完成。 +使用 Selenium 做测试需要在 Selenium 执行操作后进行断言,所以一个好的断言类库是很有必要的。 +至于组织测试用例结构的一些额外特性则需要[Test Runner](#test-runner)来完成。 ## IDEs @@ -38,18 +43,21 @@ description: > ## Test Runner -即使不使用 Selenium 做测试,如果你有高级用例,使用一个 test runner 去更好地组织你的代码是很有意义的。学会使用 before/after hooks 和分组执行或者并行执行将会非常有用。 +即使不使用 Selenium 做测试,如果你有高级用例,使用一个 test runner 去更好地组织你的代码是很有意义的。 +学会使用 before/after hooks 和分组执行或者并行执行将会非常有用。 -### 待选 +### 候选 有非常多不同的 test runner 可供选择。 -这个教程中所有使用到 test runner 的代码示例都可以在我们的示例目录中找到(或者正在被迁移过去),而且这些示例在每一次发版都会被执行,以确保代码是正确的和最新的。下面是一份包含对应链接的 test runner 清单,其中第一项是被这个仓库和本页所有用例所使用的。 +这个教程中所有使用到 test runner 的代码示例都可以在我们的示例目录中找到(或者正在被迁移过去), +而且这些示例在每一次发版都会被执行,以确保代码是正确的和最新的。 +下面是一份包含对应链接的 test runner 清单,其中第一项是被这个仓库和本页所有用例所使用的。 {{< tabpane text=true >}} {{% tab header="Java" %}} -- [JUnit](https://junit.org/junit5/) - 个广泛使用的用于基于 Java 的 Selenium 测试的测试框架。 +- [JUnit](https://junit.org/junit5/) - 一个广泛使用的用于基于 Java 的 Selenium 测试的测试框架。 - [TestNG](https://testng.org/) - 提供诸如并行测试执行和参数化测试等额外功能。 {{% /tab %}} @@ -78,14 +86,15 @@ description: > {{% /tab %}} {{% tab header="Kotlin" %}} -- [Kotest](https://kotest.io/) - 个灵活且全面的测试框架,专为 Kotlin 设计。 -- [JUnit5](https://junit.org/junit5/) -标准的 Java 测试框架,完全兼容 Kotlin。 +- [Kotest](https://kotest.io/) - 一个灵活且全面的测试框架,专为 Kotlin 设计。 +- [JUnit5](https://junit.org/junit5/) - 标准的 Java 测试框架,完全兼容 Kotlin。 {{% /tab %}} {{< /tabpane >}} ### 安装 -在[安装 Selenium 类库]({{< ref "install_library.md" >}})一节中详细说明了需要哪些东西。这里的代码只展示在我们的文档示例项目中用到的示例。 +在[安装 Selenium 类库]({{< ref "install_library.md" >}})一节中详细说明了需要哪些东西。 +这里的代码只展示在我们的文档示例项目中用到的示例。 {{< tabpane text=true >}} {{% tab header="Java" %}} @@ -176,7 +185,7 @@ In your project's `package.json`, add requirement to `dependencies`: ### Tear Down -{{< gh-codeblock path="examples/ruby/spec/spec_helper.rb#L28" >}} +{{< gh-codeblock path="examples/ruby/spec/spec_helper.rb#L30" >}} {{% /tab %}} {{< tab header="JavaScript" >}} @@ -242,7 +251,8 @@ npx mocha runningTests.spec.js ### 示例 -在[第一个脚本]({{< ref "first_script.md" >}})一节中,我们了解了 Selenium 脚本的每一个组件。这里是使用 test runner 重新组织那个脚本的一个示例: +在[第一个脚本]({{< ref "first_script.md" >}})一节中,我们了解了 Selenium 脚本的每一个组件。 +这里是使用 test runner 重新组织那个脚本的一个示例: {{< tabpane text=true >}} {{< tab header="Java" >}} @@ -267,6 +277,7 @@ npx mocha runningTests.spec.js ## 下一步 -使用你目前所学到的知识建立你自己的 Selenium 代码吧! +使用你目前所学到的知识构建你自己的 Selenium 代码吧! -想要了解更多的功能特性,请继续阅读我们接下来的[WebDriver 教程]({{< ref "/documentation/webdriver/" >}}) +想要了解更多的功能特性, +请继续阅读我们接下来的[WebDriver 教程]({{< ref "/documentation/webdriver/" >}}) diff --git a/website_and_docs/content/documentation/webdriver/interactions/alerts.en.md b/website_and_docs/content/documentation/webdriver/interactions/alerts.en.md index 8ddf4967592e..c5c420273a5b 100644 --- a/website_and_docs/content/documentation/webdriver/interactions/alerts.en.md +++ b/website_and_docs/content/documentation/webdriver/interactions/alerts.en.md @@ -26,7 +26,7 @@ alerts. {{< tabpane langEqualsHeader=true >}} {{< tab header="Java" text=true >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/AlertsTest.java#L51-L57" >}} +{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/AlertsTest.java#L45-L49" >}} {{< /tab >}} {{< tab header="Python" text=true >}} @@ -77,7 +77,7 @@ This example also shows a different approach to storing an alert: {{< tabpane langEqualsHeader=true >}} {{< tab header="Java" text=true >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/AlertsTest.java#L66-L72" >}} +{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/AlertsTest.java#L55-L57" >}} {{< /tab >}} {{< tab header="Python" text=true >}} @@ -136,7 +136,7 @@ See a sample prompt. {{< tabpane langEqualsHeader=true >}} {{< tab header="Java" text=true >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/AlertsTest.java#L80-L88" >}} +{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/AlertsTest.java#L62-L65" >}} {{< /tab >}} {{< tab header="Python" text=true >}} diff --git a/website_and_docs/content/documentation/webdriver/interactions/alerts.ja.md b/website_and_docs/content/documentation/webdriver/interactions/alerts.ja.md index eed2c39bda59..3c83e07d4ab0 100644 --- a/website_and_docs/content/documentation/webdriver/interactions/alerts.ja.md +++ b/website_and_docs/content/documentation/webdriver/interactions/alerts.ja.md @@ -22,7 +22,7 @@ WebDriverはポップアップからテキストを取得し、これらのア {{< tabpane langEqualsHeader=true >}} {{< tab header="Java" text=true >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/AlertsTest.java#L51-L57" >}} +{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/AlertsTest.java#L45-L49" >}} {{< /tab >}} {{< tab header="Python" text=true >}} @@ -72,7 +72,7 @@ alert.accept() {{< tabpane langEqualsHeader=true >}} {{< tab header="Java" text=true >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/AlertsTest.java#L66-L72" >}} +{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/AlertsTest.java#L55-L57" >}} {{< /tab >}} {{< tab header="Python" text=true >}} @@ -129,7 +129,7 @@ alert.dismiss() {{< tabpane langEqualsHeader=true >}} {{< tab header="Java" text=true >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/AlertsTest.java#L80-L88" >}} +{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/AlertsTest.java#L62-L65" >}} {{< /tab >}} {{< tab header="Python" text=true >}} diff --git a/website_and_docs/content/documentation/webdriver/interactions/alerts.pt-br.md b/website_and_docs/content/documentation/webdriver/interactions/alerts.pt-br.md index e741c7e2ab78..193569d8021e 100644 --- a/website_and_docs/content/documentation/webdriver/interactions/alerts.pt-br.md +++ b/website_and_docs/content/documentation/webdriver/interactions/alerts.pt-br.md @@ -26,7 +26,7 @@ alertas. {{< tabpane langEqualsHeader=true >}} {{< tab header="Java" text=true >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/AlertsTest.java#L51-L57" >}} +{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/AlertsTest.java#L45-L49" >}} {{< /tab >}} {{< tab header="Python" text=true >}} {{< gh-codeblock path="examples/python/tests/interactions/test_alerts.py#L12-L18" >}} @@ -63,7 +63,7 @@ Este exemplo também mostra uma abordagem diferente para armazenar um alerta: {{< tabpane langEqualsHeader=true >}} {{< tab header="Java" text=true >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/AlertsTest.java#L66-L72" >}} +{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/AlertsTest.java#L55-L57" >}} {{< /tab >}} {{< tab header="Python" text=true >}} @@ -122,7 +122,7 @@ Veja um exemplo de prompt . {{< tabpane langEqualsHeader=true >}} {{< tab header="Java" text=true >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/AlertsTest.java#L80-L88" >}} +{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/AlertsTest.java#L62-L65" >}} {{< /tab >}} {{< tab header="Python" text=true >}} diff --git a/website_and_docs/content/documentation/webdriver/interactions/alerts.zh-cn.md b/website_and_docs/content/documentation/webdriver/interactions/alerts.zh-cn.md index b7986383e8f3..6409b40dd12e 100644 --- a/website_and_docs/content/documentation/webdriver/interactions/alerts.zh-cn.md +++ b/website_and_docs/content/documentation/webdriver/interactions/alerts.zh-cn.md @@ -19,7 +19,7 @@ WebDriver可以从弹窗获取文本并接受或关闭这些警告. {{< tabpane langEqualsHeader=true >}} {{< tab header="Java" text=true >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/AlertsTest.java#L51-L57" >}} +{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/AlertsTest.java#L45-L49" >}} {{< /tab >}} {{< tab header="Python" text=true >}} @@ -68,7 +68,7 @@ alert.accept() {{< tabpane langEqualsHeader=true >}} {{< tab header="Java" text=true >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/AlertsTest.java#L66-L72" >}} +{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/AlertsTest.java#L55-L57" >}} {{< /tab >}} {{< tab header="Python" text=true >}} @@ -124,7 +124,7 @@ alert.dismiss() {{< tabpane langEqualsHeader=true >}} {{< tab header="Java" text=true >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/AlertsTest.java#L80-L88" >}} +{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/AlertsTest.java#L62-L65" >}} {{< /tab >}} {{< tab header="Python" text=true >}} diff --git a/website_and_docs/content/documentation/webdriver/interactions/cookies.en.md b/website_and_docs/content/documentation/webdriver/interactions/cookies.en.md index 2565a731e51e..ba057000f599 100644 --- a/website_and_docs/content/documentation/webdriver/interactions/cookies.en.md +++ b/website_and_docs/content/documentation/webdriver/interactions/cookies.en.md @@ -36,18 +36,8 @@ e.g. http://example.com/some404page) {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/CookiesTest.cs#L32-L34" >}} {{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - driver.get 'https://www.example.com/' - - # Adds the cookie into current browser context - driver.manage.add_cookie(name: "key", value: "value") -ensure - driver.quit -end +{{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/cookies_spec.rb#L9-L11" >}} {{< /tab >}} {{< tab header="JavaScript" text=true >}} {{< gh-codeblock path="/examples/javascript/test/interactions/cookies.spec.js#L18">}} @@ -85,19 +75,8 @@ It returns the serialized cookie data matching with the cookie name among all as {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/CookiesTest.cs#L40-L44" >}} {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - driver.get 'https://www.example.com/' - driver.manage.add_cookie(name: "foo", value: "bar") - - # Get cookie details with named cookie 'foo' - puts driver.manage.cookie_named('foo') -ensure - driver.quit -end + {{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/cookies_spec.rb#L17-L21" >}} {{< /tab >}} {{< tab header="JavaScript" text=true >}} {{< gh-codeblock path="/examples/javascript/test/interactions/cookies.spec.js#L35-L38">}} @@ -138,20 +117,8 @@ If browser is no longer available it returns error. {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/CookiesTest.cs#L51-L64" >}} {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - driver.get 'https://www.example.com/' - driver.manage.add_cookie(name: "test1", value: "cookie1") - driver.manage.add_cookie(name: "test2", value: "cookie2") - - # Get all available cookies - puts driver.manage.all_cookies -ensure - driver.quit -end + {{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/cookies_spec.rb#L26-L31" >}} {{< /tab >}} {{< tab header="JavaScript" text=true >}} {{< gh-codeblock path="/examples/javascript/test/interactions/cookies.spec.js#L49-L51">}} @@ -193,20 +160,8 @@ It deletes the cookie data matching with the provided cookie name. {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/CookiesTest.cs#L70-L73" >}} {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - driver.get 'https://www.example.com/' - driver.manage.add_cookie(name: "test1", value: "cookie1") - driver.manage.add_cookie(name: "test2", value: "cookie2") - - # delete a cookie with name 'test1' - driver.manage.delete_cookie('test1') -ensure - driver.quit -end + {{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/cookies_spec.rb#L40-L43" >}} {{< /tab >}} {{< tab header="JavaScript" text=true >}} {{< gh-codeblock path="/examples/javascript/test/interactions/cookies.spec.js#L61-L62">}} @@ -251,20 +206,8 @@ It deletes all the cookies of the current browsing context. {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/CookiesTest.cs#L92-L97" >}} {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - driver.get 'https://www.example.com/' - driver.manage.add_cookie(name: "test1", value: "cookie1") - driver.manage.add_cookie(name: "test2", value: "cookie2") - - # deletes all cookies - driver.manage.delete_all_cookies -ensure - driver.quit -end + {{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/cookies_spec.rb#L49-L54" >}} {{< /tab >}} {{< tab header="JavaScript" text=true >}} {{< gh-codeblock path="/examples/javascript/test/interactions/cookies.spec.js#L77-L78">}} diff --git a/website_and_docs/content/documentation/webdriver/interactions/cookies.ja.md b/website_and_docs/content/documentation/webdriver/interactions/cookies.ja.md index 9a8be028f39f..74dca2e6b13d 100644 --- a/website_and_docs/content/documentation/webdriver/interactions/cookies.ja.md +++ b/website_and_docs/content/documentation/webdriver/interactions/cookies.ja.md @@ -33,18 +33,8 @@ Cookieの追加では、一連の定義済みのシリアル化可能なJSONオ {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/CookiesTest.cs#L32-L34" >}} {{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - driver.get 'https://www.example.com/' - - # Adds the cookie into current browser context - driver.manage.add_cookie(name: "key", value: "value") -ensure - driver.quit -end +{{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/cookies_spec.rb#L9-L11" >}} {{< /tab >}} {{< tab header="JavaScript" text=true >}} {{< gh-codeblock path="/examples/javascript/test/interactions/cookies.spec.js#L18">}} @@ -81,19 +71,8 @@ fun main() { {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/CookiesTest.cs#L40-L44" >}} {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - driver.get 'https://www.example.com/' - driver.manage.add_cookie(name: "foo", value: "bar") - - # Get cookie details with named cookie 'foo' - puts driver.manage.cookie_named('foo') -ensure - driver.quit -end + {{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/cookies_spec.rb#L17-L21" >}} {{< /tab >}} {{< tab header="JavaScript" text=true >}} {{< gh-codeblock path="/examples/javascript/test/interactions/cookies.spec.js#L35-L38">}} @@ -133,20 +112,8 @@ fun main() { {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/CookiesTest.cs#L51-L64" >}} {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - driver.get 'https://www.example.com/' - driver.manage.add_cookie(name: "test1", value: "cookie1") - driver.manage.add_cookie(name: "test2", value: "cookie2") - - # Get all available cookies - puts driver.manage.all_cookies -ensure - driver.quit -end + {{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/cookies_spec.rb#L26-L31" >}} {{< /tab >}} {{< tab header="JavaScript" text=true >}} {{< gh-codeblock path="/examples/javascript/test/interactions/cookies.spec.js#L49-L51">}} @@ -187,20 +154,8 @@ fun main() { {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/CookiesTest.cs#L70-L73" >}} {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - driver.get 'https://www.example.com/' - driver.manage.add_cookie(name: "test1", value: "cookie1") - driver.manage.add_cookie(name: "test2", value: "cookie2") - - # delete a cookie with name 'test1' - driver.manage.delete_cookie('test1') -ensure - driver.quit -end + {{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/cookies_spec.rb#L40-L43" >}} {{< /tab >}} {{< tab header="JavaScript" text=true >}} {{< gh-codeblock path="/examples/javascript/test/interactions/cookies.spec.js#L61-L62">}} @@ -244,20 +199,8 @@ fun main() { {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/CookiesTest.cs#L92-L97" >}} {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - driver.get 'https://www.example.com/' - driver.manage.add_cookie(name: "test1", value: "cookie1") - driver.manage.add_cookie(name: "test2", value: "cookie2") - - # deletes all cookies - driver.manage.delete_all_cookies -ensure - driver.quit -end + {{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/cookies_spec.rb#L49-L54" >}} {{< /tab >}} {{< tab header="JavaScript" text=true >}} {{< gh-codeblock path="/examples/javascript/test/interactions/cookies.spec.js#L77-L78">}} diff --git a/website_and_docs/content/documentation/webdriver/interactions/cookies.pt-br.md b/website_and_docs/content/documentation/webdriver/interactions/cookies.pt-br.md index 63d69e63ea17..b080164a06d9 100644 --- a/website_and_docs/content/documentation/webdriver/interactions/cookies.pt-br.md +++ b/website_and_docs/content/documentation/webdriver/interactions/cookies.pt-br.md @@ -35,18 +35,8 @@ por exemplo http://example.com/some404page) {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/CookiesTest.cs#L32-L34" >}} {{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - driver.get 'https://www.example.com/' - - # Adds the cookie into current browser context - driver.manage.add_cookie(name: "key", value: "value") -ensure - driver.quit -end +{{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/cookies_spec.rb#L9-L11" >}} {{< /tab >}} {{< tab header="JavaScript" text=true >}} {{< gh-codeblock path="/examples/javascript/test/interactions/cookies.spec.js#L18">}} @@ -83,19 +73,8 @@ Retorna os dados do cookie serializado correspondentes ao nome do cookie entre t {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/CookiesTest.cs#L40-L44" >}} {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - driver.get 'https://www.example.com/' - driver.manage.add_cookie(name: "foo", value: "bar") - - # Get cookie details with named cookie 'foo' - puts driver.manage.cookie_named('foo') -ensure - driver.quit -end + {{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/cookies_spec.rb#L17-L21" >}} {{< /tab >}} {{< tab header="JavaScript" text=true >}} {{< gh-codeblock path="/examples/javascript/test/interactions/cookies.spec.js#L35-L38">}} @@ -135,20 +114,8 @@ Se o navegador não estiver mais disponível, ele retornará um erro. {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/CookiesTest.cs#L51-L64" >}} {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - driver.get 'https://www.example.com/' - driver.manage.add_cookie(name: "test1", value: "cookie1") - driver.manage.add_cookie(name: "test2", value: "cookie2") - - # Get all available cookies - puts driver.manage.all_cookies -ensure - driver.quit -end + {{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/cookies_spec.rb#L26-L31" >}} {{< /tab >}} {{< tab header="JavaScript" text=true >}} {{< gh-codeblock path="/examples/javascript/test/interactions/cookies.spec.js#L49-L51">}} @@ -189,20 +156,8 @@ Exclui os dados do cookie que correspondem ao nome do cookie fornecido. {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/CookiesTest.cs#L70-L73" >}} {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - driver.get 'https://www.example.com/' - driver.manage.add_cookie(name: "test1", value: "cookie1") - driver.manage.add_cookie(name: "test2", value: "cookie2") - - # delete a cookie with name 'test1' - driver.manage.delete_cookie('test1') -ensure - driver.quit -end + {{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/cookies_spec.rb#L40-L43" >}} {{< /tab >}} {{< tab header="JavaScript" text=true >}} {{< gh-codeblock path="/examples/javascript/test/interactions/cookies.spec.js#L61-L62">}} @@ -246,20 +201,8 @@ Exclui todos os cookies do contexto de navegação atual. {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/CookiesTest.cs#L92-L97" >}} {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - driver.get 'https://www.example.com/' - driver.manage.add_cookie(name: "test1", value: "cookie1") - driver.manage.add_cookie(name: "test2", value: "cookie2") - - # deletes all cookies - driver.manage.delete_all_cookies -ensure - driver.quit -end + {{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/cookies_spec.rb#L49-L54" >}} {{< /tab >}} {{< tab header="JavaScript" text=true >}} {{< gh-codeblock path="/examples/javascript/test/interactions/cookies.spec.js#L77-L78">}} diff --git a/website_and_docs/content/documentation/webdriver/interactions/cookies.zh-cn.md b/website_and_docs/content/documentation/webdriver/interactions/cookies.zh-cn.md index 2a60ccdd93a9..1f3515009759 100644 --- a/website_and_docs/content/documentation/webdriver/interactions/cookies.zh-cn.md +++ b/website_and_docs/content/documentation/webdriver/interactions/cookies.zh-cn.md @@ -31,18 +31,8 @@ WebDriver API提供了一种使用内置的方法与Cookie进行交互: {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/CookiesTest.cs#L32-L34" >}} {{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - driver.get 'https://www.example.com/' - - # Adds the cookie into current browser context - driver.manage.add_cookie(name: "key", value: "value") -ensure - driver.quit -end +{{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/cookies_spec.rb#L9-L11" >}} {{< /tab >}} {{< tab header="JavaScript" text=true >}} {{< gh-codeblock path="/examples/javascript/test/interactions/cookies.spec.js#L18">}} @@ -79,20 +69,11 @@ fun main() { {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/CookiesTest.cs#L40-L44" >}} {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - driver.get 'https://www.example.com/' - driver.manage.add_cookie(name: "foo", value: "bar") - - # Get cookie details with named cookie 'foo' - puts driver.manage.cookie_named('foo') -ensure - driver.quit -end + + {{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/cookies_spec.rb#L17-L21" >}} {{< /tab >}} + {{< tab header="JavaScript" text=true >}} {{< gh-codeblock path="/examples/javascript/test/interactions/cookies.spec.js#L35-L38">}} {{< /tab >}} @@ -130,21 +111,11 @@ fun main() { {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/CookiesTest.cs#L51-L64" >}} {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome -begin - driver.get 'https://www.example.com/' - driver.manage.add_cookie(name: "test1", value: "cookie1") - driver.manage.add_cookie(name: "test2", value: "cookie2") +{{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/cookies_spec.rb#L26-L31" >}} +{{< /tab >}} - # Get all available cookies - puts driver.manage.all_cookies -ensure - driver.quit -end - {{< /tab >}} {{< tab header="JavaScript" text=true >}} {{< gh-codeblock path="/examples/javascript/test/interactions/cookies.spec.js#L49-L51">}} {{< /tab >}} @@ -184,21 +155,11 @@ fun main() { {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/CookiesTest.cs#L70-L73" >}} {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome -begin - driver.get 'https://www.example.com/' - driver.manage.add_cookie(name: "test1", value: "cookie1") - driver.manage.add_cookie(name: "test2", value: "cookie2") +{{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/cookies_spec.rb#L40-L43" >}} +{{< /tab >}} - # delete a cookie with name 'test1' - driver.manage.delete_cookie('test1') -ensure - driver.quit -end - {{< /tab >}} {{< tab header="JavaScript" text=true >}} {{< gh-codeblock path="/examples/javascript/test/interactions/cookies.spec.js#L61-L62">}} {{< /tab >}} @@ -241,21 +202,11 @@ fun main() { {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/CookiesTest.cs#L92-L97" >}} {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :chrome - -begin - driver.get 'https://www.example.com/' - driver.manage.add_cookie(name: "test1", value: "cookie1") - driver.manage.add_cookie(name: "test2", value: "cookie2") - - # deletes all cookies - driver.manage.delete_all_cookies -ensure - driver.quit -end + + {{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/cookies_spec.rb#L49-L54" >}} {{< /tab >}} + {{< tab header="JavaScript" text=true >}} {{< gh-codeblock path="/examples/javascript/test/interactions/cookies.spec.js#L77-L78">}} {{< /tab >}} diff --git a/website_and_docs/content/documentation/webdriver/interactions/frames.en.md b/website_and_docs/content/documentation/webdriver/interactions/frames.en.md index 4c02033c24c7..a4bbbd892746 100644 --- a/website_and_docs/content/documentation/webdriver/interactions/frames.en.md +++ b/website_and_docs/content/documentation/webdriver/interactions/frames.en.md @@ -75,29 +75,22 @@ find the frame using your preferred selector and switch to it. {{< tab header="Java" text=true >}} {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/FramesTest.java#L38-L46" >}} {{< /tab >}} - {{< tab header="Python" >}} - # Store iframe web element -iframe = driver.find_element(By.CSS_SELECTOR, "#modal > iframe") - - # switch to selected iframe -driver.switch_to.frame(iframe) - - # Now click on button -driver.find_element(By.TAG_NAME, 'button').click() - {{< /tab >}} + + {{< tab header="Python" text=true >}} +{{< gh-codeblock path="examples/python/tests/interactions/test_frames.py#L24-L32" >}} +{{< /tab >}} + + {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/FramesTest.cs#L38-L46" >}} {{< /tab >}} - {{< tab header="Ruby" >}} - # Store iframe web element -iframe = driver.find_element(:css,'#modal > iframe') + + +{{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/frames_spec.rb#L26-L33" >}} +{{< /tab >}} - # Switch to the frame -driver.switch_to.frame iframe - # Now, Click on the button -driver.find_element(:tag_name,'button').click - {{< /tab >}} {{< tab header="JavaScript" >}} // Store the web element const iframe = driver.findElement(By.css('#modal > iframe')); @@ -130,23 +123,20 @@ one found will be switched to. {{< tab header="Java" text=true >}} {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/FramesTest.java#L50-L58" >}} {{< /tab >}} - {{< tab header="Python" >}} - # Switch frame by id -driver.switch_to.frame('buttonframe') - - # Now, Click on the button -driver.find_element(By.TAG_NAME, 'button').click() - {{< /tab >}} + +{{< tab header="Python" text=true >}} +{{< gh-codeblock path="examples/python/tests/interactions/test_frames.py#L34-L42" >}} +{{< /tab >}} + {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/FramesTest.cs#L50-L58" >}} {{< /tab >}} - {{< tab header="Ruby" >}} - # Switch by ID -driver.switch_to.frame 'buttonframe' + + +{{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/frames_spec.rb#L36-L43" >}} +{{< /tab >}} - # Now, Click on the button -driver.find_element(:tag_name,'button').click - {{< /tab >}} {{< tab header="JavaScript" >}} // Using the ID await driver.switchTo().frame('buttonframe'); @@ -180,14 +170,25 @@ queried using _window.frames_ in JavaScript. {{< tab header="Java" text=true >}} {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/FramesTest.java#L62-L63" >}} {{< /tab >}} + +{{< tab header="Python" text=true >}} +{{< gh-codeblock path="examples/python/tests/interactions/test_frames.py#L45-L46" >}} +{{< /tab >}} + + + - {{< tab header="Ruby" >}} - # Switch to the second frame -driver.switch_to.frame(1) - {{< /tab >}} {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/FramesTest.cs#L62-L63" >}} {{< /tab >}} + +{{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/frames_spec.rb#L46-L47" >}} +{{< /tab >}} + + + + {{< tab header="JavaScript" >}} // Switches to the second frame await driver.switchTo().frame(1); @@ -210,17 +211,20 @@ like so: {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/FramesTest.java#L66-L67" >}} {{< /tab >}} - {{< tab header="Python" >}} - # switch back to default content -driver.switch_to.default_content() - {{< /tab >}} + {{< tab header="Python" text=true >}} +{{< gh-codeblock path="examples/python/tests/interactions/test_frames.py#L49-L50" >}} +{{< /tab >}} + + {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/FramesTest.cs#L66-L67" >}} {{< /tab >}} - {{< tab header="Ruby" >}} - # Return to the top level -driver.switch_to.default_content - {{< /tab >}} + + +{{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/frames_spec.rb#L49-L50" >}} +{{< /tab >}} + {{< tab header="JavaScript" >}} // Return to the top level await driver.switchTo().defaultContent(); diff --git a/website_and_docs/content/documentation/webdriver/interactions/frames.ja.md b/website_and_docs/content/documentation/webdriver/interactions/frames.ja.md index 97ae27619657..d5e97d641d7c 100644 --- a/website_and_docs/content/documentation/webdriver/interactions/frames.ja.md +++ b/website_and_docs/content/documentation/webdriver/interactions/frames.ja.md @@ -64,29 +64,21 @@ WebElementを使用した切り替えは、最も柔軟なオプションです {{< tab header="Java" text=true >}} {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/FramesTest.java#L38-L46" >}} {{< /tab >}} - {{< tab header="Python" >}} - # Store iframe web element -iframe = driver.find_element(By.CSS_SELECTOR, "#modal > iframe") - - # switch to selected iframe -driver.switch_to.frame(iframe) - - # Now click on button -driver.find_element(By.TAG_NAME, 'button').click() - {{< /tab >}} + {{< tab header="Python" text=true >}} +{{< gh-codeblock path="examples/python/tests/interactions/test_frames.py#L24-L32" >}} +{{< /tab >}} + {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/FramesTest.cs#L38-L46" >}} {{< /tab >}} - {{< tab header="Ruby" >}} - # Store iframe web element -iframe = driver.find_element(:css,'#modal > iframe') + + +{{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/frames_spec.rb#L26-L36" >}} +{{< /tab >}} + - # Switch to the frame -driver.switch_to.frame iframe - # Now, Click on the button -driver.find_element(:tag_name,'button').click - {{< /tab >}} {{< tab header="JavaScript" >}} // Store the web element const iframe = driver.findElement(By.css('#modal > iframe')); @@ -118,16 +110,21 @@ FrameまたはiFrameにidまたはname属性がある場合、代わりにこれ {{< tab header="Java" text=true >}} {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/FramesTest.java#L50-L58" >}} {{< /tab >}} - {{< tab header="Python" >}} - # Switch frame by id -driver.switch_to.frame('buttonframe') - - # Now, Click on the button -driver.find_element(By.TAG_NAME, 'button').click() - {{< /tab >}} + +{{< tab header="Python" text=true >}} +{{< gh-codeblock path="examples/python/tests/interactions/test_frames.py#L34-L42" >}} +{{< /tab >}} + {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/FramesTest.cs#L50-L58" >}} {{< /tab >}} + + +{{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/frames_spec.rb#L36-L43" >}} +{{< /tab >}} + + {{< tab header="JavaScript" >}} // Using the ID await driver.switchTo().frame('buttonframe'); @@ -138,6 +135,8 @@ await driver.switchTo().frame('myframe'); // Now we can click the button await driver.findElement(By.css('button')).click(); {{< /tab >}} + + {{< tab header="Kotlin" >}} //Using the ID driver.switchTo().frame("buttonframe") @@ -155,31 +154,29 @@ driver.findElement(By.tagName("button")).click() JavaScriptの _window.frames_ を使用して照会できるように、Frameのインデックスを使用することもできます。 {{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" text=true >}} +{{< tab header="Java" text=true >}} {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/FramesTest.java#L62-L63" >}} - {{< /tab >}} - {{< tab header="Ruby" >}} - # Switch to the second frame -driver.switch_to.frame(1) - {{< /tab >}} - {{< tab header="CSharp" text=true >}} +{{< /tab >}} +{{< tab header="Python" text=true >}} +{{< gh-codeblock path="examples/python/tests/interactions/test_frames.py#L45-L46" >}} +{{< /tab >}} +{ +{{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/FramesTest.cs#L62-L63" >}} {{< /tab >}} - {{< tab header="Python" >}} - # switching to second iframe based on index -iframe = driver.find_elements(By.TAG_NAME,'iframe')[1] - # switch to selected iframe -driver.switch_to.frame(iframe) - {{< /tab >}} - {{< tab header="JavaScript" >}} +{{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/frames_spec.rb#L46-L47" >}} +{{< /tab >}} + +{{< tab header="JavaScript" >}} // Switches to the second frame await driver.switchTo().frame(1); - {{< /tab >}} - {{< tab header="Kotlin" >}} +{{< /tab >}} +{{< tab header="Kotlin" >}} // Switches to the second frame driver.switchTo().frame(1) - {{< /tab >}} +{{< /tab >}} {{< /tabpane >}} @@ -198,10 +195,11 @@ driver.switch_to.default_content() {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/FramesTest.cs#L66-L67" >}} {{< /tab >}} - {{< tab header="Ruby" >}} - # Return to the top level -driver.switch_to.default_content - {{< /tab >}} + + {{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/frames_spec.rb#L49-L50" >}} +{{< /tab >}} + {{< tab header="JavaScript" >}} // Return to the top level await driver.switchTo().defaultContent(); diff --git a/website_and_docs/content/documentation/webdriver/interactions/frames.pt-br.md b/website_and_docs/content/documentation/webdriver/interactions/frames.pt-br.md index 0fd61db35931..1a0d86257b61 100644 --- a/website_and_docs/content/documentation/webdriver/interactions/frames.pt-br.md +++ b/website_and_docs/content/documentation/webdriver/interactions/frames.pt-br.md @@ -72,29 +72,18 @@ encontrar o quadro usando seu seletor preferido e mudar para ele. {{< tab header="Java" text=true >}} {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/FramesTest.java#L38-L46" >}} {{< /tab >}} - {{< tab header="Python" >}} - # Store iframe web element -iframe = driver.find_element(By.CSS_SELECTOR, "#modal > iframe") - - # switch to selected iframe -driver.switch_to.frame(iframe) - - # Now click on button -driver.find_element(By.TAG_NAME, 'button').click() - {{< /tab >}} + {{< tab header="Python" text=true >}} +{{< gh-codeblock path="examples/python/tests/interactions/test_frames.py#L24-L32" >}} +{{< /tab >}} {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/FramesTest.cs#L38-L46" >}} {{< /tab >}} - {{< tab header="Ruby" >}} - # Store iframe web element -iframe = driver.find_element(:css,'#modal > iframe') + +{{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/frames_spec.rb#L26-L33" >}} +{{< /tab >}} - # Switch to the frame -driver.switch_to.frame iframe - # Now, Click on the button -driver.find_element(:tag_name,'button').click - {{< /tab >}} {{< tab header="JavaScript" >}} // Store the web element const iframe = driver.findElement(By.css('#modal > iframe')); @@ -126,23 +115,22 @@ primeiro encontrado será utilizado. {{< tab header="Java" text=true >}} {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/FramesTest.java#L50-L58" >}} {{< /tab >}} - {{< tab header="Python" >}} - # Switch frame by id -driver.switch_to.frame('buttonframe') - # Now, Click on the button -driver.find_element(By.TAG_NAME, 'button').click() - {{< /tab >}} +{{< tab header="Python" text=true >}} +{{< gh-codeblock path="examples/python/tests/interactions/test_frames.py#L34-L42" >}} +{{< /tab >}} + {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/FramesTest.cs#L50-L58" >}} {{< /tab >}} - {{< tab header="Ruby" >}} - # Switch by ID -driver.switch_to.frame 'buttonframe' + + +{{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/frames_spec.rb#L36-L43" >}} +{{< /tab >}} + + - # Now, Click on the button -driver.find_element(:tag_name,'button').click - {{< /tab >}} {{< tab header="JavaScript" >}} // Using the ID await driver.switchTo().frame('buttonframe'); @@ -171,31 +159,30 @@ Também é possível usar o índice do frame, podendo ser consultado usando _window.frames_ em JavaScript. {{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" text=true >}} +{{< tab header="Java" text=true >}} {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/FramesTest.java#L62-L63" >}} - {{< /tab >}} - {{< tab header="Ruby" >}} - # Switch to the second frame -driver.switch_to.frame(1) - {{< /tab >}} - {{< tab header="CSharp" text=true >}} +{{< /tab >}} +{{< tab header="Python" text=true >}} +{{< gh-codeblock path="examples/python/tests/interactions/test_frames.py#L45-L46" >}} +{{< /tab >}} + +{{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/FramesTest.cs#L62-L63" >}} {{< /tab >}} - {{< tab header="Python" >}} - # switching to second iframe based on index -iframe = driver.find_elements(By.TAG_NAME,'iframe')[1] - # switch to selected iframe -driver.switch_to.frame(iframe) - {{< /tab >}} - {{< tab header="JavaScript" >}} +{{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/frames_spec.rb#L46-L47" >}} +{{< /tab >}} + + +{{< tab header="JavaScript" >}} // Switches to the second frame await driver.switchTo().frame(1); - {{< /tab >}} - {{< tab header="Kotlin" >}} +{{< /tab >}} +{{< tab header="Kotlin" >}} // Switches to the second frame driver.switchTo().frame(1) - {{< /tab >}} +{{< /tab >}} {{< /tabpane >}} @@ -205,26 +192,27 @@ Para deixar um iframe ou frameset, volte para o conteúdo padrão como a seguir: {{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" text=true >}} +{{< tab header="Java" text=true >}} {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/FramesTest.java#L66-L67" >}} - {{< /tab >}} - {{< tab header="Python" >}} - # switch back to default content -driver.switch_to.default_content() - {{< /tab >}} - {{< tab header="CSharp" text=true >}} +{{< /tab >}} +{{< tab header="Python" text=true >}} +{{< gh-codeblock path="examples/python/tests/interactions/test_frames.py#L49-L50" >}} +{{< /tab >}} +{{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/FramesTest.cs#L66-L67" >}} {{< /tab >}} - {{< tab header="Ruby" >}} - # Return to the top level -driver.switch_to.default_content - {{< /tab >}} - {{< tab header="JavaScript" >}} + + {{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/frames_spec.rb#L49-L50" >}} +{{< /tab >}} + + +{{< tab header="JavaScript" >}} // Return to the top level await driver.switchTo().defaultContent(); - {{< /tab >}} - {{< tab header="Kotlin" >}} +{{< /tab >}} +{{< tab header="Kotlin" >}} // Return to the top level driver.switchTo().defaultContent() - {{< /tab >}} +{{< /tab >}} {{< /tabpane >}} diff --git a/website_and_docs/content/documentation/webdriver/interactions/frames.zh-cn.md b/website_and_docs/content/documentation/webdriver/interactions/frames.zh-cn.md index af55faf58226..867c7d729a1e 100644 --- a/website_and_docs/content/documentation/webdriver/interactions/frames.zh-cn.md +++ b/website_and_docs/content/documentation/webdriver/interactions/frames.zh-cn.md @@ -65,29 +65,19 @@ driver.findElement(By.tagName("button")).click() {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/FramesTest.java#L38-L46" >}} {{< /tab >}} -{{< tab header="Python" >}} - # 存储网页元素 -iframe = driver.find_element(By.CSS_SELECTOR, "#modal > iframe") - - # 切换到选择的 iframe -driver.switch_to.frame(iframe) - - # 单击按钮 -driver.find_element(By.TAG_NAME, 'button').click() + {{< tab header="Python" text=true >}} +{{< gh-codeblock path="examples/python/tests/interactions/test_frames.py#L24-L32" >}} {{< /tab >}} + {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/FramesTest.cs#L38-L46" >}} {{< /tab >}} -{{< tab header="Ruby" >}} - # Store iframe web element -iframe = driver.find_element(:css,'#modal> iframe') - # 切换到 frame -driver.switch_to.frame iframe - - # 单击按钮 -driver.find_element(:tag_name,'button').click +{{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/frames_spec.rb#L26-L33" >}} {{< /tab >}} + + {{< tab header="JavaScript" >}} // 存储网页元素 const iframe = driver.findElement(By.css('#modal> iframe')); @@ -119,23 +109,21 @@ driver.findElement(By.tagName("button")).click() {{< tab header="Java" text=true >}} {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/FramesTest.java#L50-L58" >}} {{< /tab >}} -{{< tab header="Python" >}} - # 通过 id 切换框架 -driver.switch_to.frame('buttonframe') - - # 单击按钮 -driver.find_element(By.TAG_NAME, 'button').click() + +{{< tab header="Python" text=true >}} +{{< gh-codeblock path="examples/python/tests/interactions/test_frames.py#L34-L42" >}} {{< /tab >}} - {{< tab header="CSharp" text=true >}} + + {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/FramesTest.cs#L50-L58" >}} {{< /tab >}} -{{< tab header="Ruby" >}} - # Switch by ID -driver.switch_to.frame 'buttonframe' - # 单击按钮 -driver.find_element(:tag_name,'button').click + +{{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/frames_spec.rb#L36-L43" >}} {{< /tab >}} + + {{< tab header="JavaScript" >}} // 使用 ID await driver.switchTo().frame('buttonframe'); @@ -168,20 +156,21 @@ _window.frames_ 进行查询. {{< tab header="Java" text=true >}} {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/FramesTest.java#L62-L63" >}} {{< /tab >}} -{{< tab header="Ruby" >}} - # 切换到第 2 个框架 -driver.switch_to.frame(1) + + {{< tab header="Python" text=true >}} +{{< gh-codeblock path="examples/python/tests/interactions/test_frames.py#L45-L46" >}} {{< /tab >}} + + + {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/FramesTest.cs#L62-L63" >}} {{< /tab >}} -{{< tab header="Python" >}} - # 基于索引切换到第 2 个 iframe -iframe = driver.find_elements(By.TAG_NAME,'iframe')[1] - # 切换到选择的 iframe -driver.switch_to.frame(iframe) +{{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/frames_spec.rb#L46-L47" >}} {{< /tab >}} + {{< tab header="JavaScript" >}} // 切换到第 2 个框架 await driver.switchTo().frame(1); @@ -201,17 +190,18 @@ driver.switchTo().frame(1) {{< tab header="Java" text=true >}} {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/interactions/FramesTest.java#L66-L67" >}} {{< /tab >}} -{{< tab header="Python" >}} - # 切回到默认内容 -driver.switch_to.default_content() + {{< tab header="Python" text=true >}} +{{< gh-codeblock path="examples/python/tests/interactions/test_frames.py#L49-L50" >}} {{< /tab >}} {{< tab header="CSharp" text=true >}} {{< gh-codeblock path="examples/dotnet/SeleniumDocs/Interactions/FramesTest.cs#L66-L67" >}} {{< /tab >}} -{{< tab header="Ruby" >}} - # 回到顶层 -driver.switch_to.default_content + + {{< tab header="Ruby" text=true >}} +{{< gh-codeblock path="examples/ruby/spec/interactions/frames_spec.rb#L49-L50" >}} {{< /tab >}} + + {{< tab header="JavaScript" >}} // 回到顶层 await driver.switchTo().defaultContent(); diff --git a/website_and_docs/content/documentation/webdriver/support_features/expected_conditions.en.md b/website_and_docs/content/documentation/webdriver/support_features/expected_conditions.en.md index 729ccb3908a1..ae8d70bcab8e 100644 --- a/website_and_docs/content/documentation/webdriver/support_features/expected_conditions.en.md +++ b/website_and_docs/content/documentation/webdriver/support_features/expected_conditions.en.md @@ -24,10 +24,9 @@ These methods can include conditions such as: [Expected Conditions Documentation](https://www.selenium.dev/selenium/docs/api/java/org/openqa/selenium/support/ui/ExpectedConditions.html) {{< badge-code >}} {{% /tab %}} -{{< tab header="Python" >}} -[Expected Conditions Documentation](https://www.selenium.dev/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.expected_conditions.html) -{{< badge-code >}} -{{< /tab >}} +{{% tab header="Python" %}} +{{< gh-codeblock path="examples/python/tests/support/test_expected_conditions.py#L14-L15" >}} +{{% /tab %}} {{< tab header="CSharp" >}} .NET stopped supporting Expected Conditions in Selenium 4 to minimize maintenance hassle and redundancy. {{< /tab >}} diff --git a/website_and_docs/content/documentation/webdriver/support_features/expected_conditions.ja.md b/website_and_docs/content/documentation/webdriver/support_features/expected_conditions.ja.md index 729ccb3908a1..ae8d70bcab8e 100644 --- a/website_and_docs/content/documentation/webdriver/support_features/expected_conditions.ja.md +++ b/website_and_docs/content/documentation/webdriver/support_features/expected_conditions.ja.md @@ -24,10 +24,9 @@ These methods can include conditions such as: [Expected Conditions Documentation](https://www.selenium.dev/selenium/docs/api/java/org/openqa/selenium/support/ui/ExpectedConditions.html) {{< badge-code >}} {{% /tab %}} -{{< tab header="Python" >}} -[Expected Conditions Documentation](https://www.selenium.dev/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.expected_conditions.html) -{{< badge-code >}} -{{< /tab >}} +{{% tab header="Python" %}} +{{< gh-codeblock path="examples/python/tests/support/test_expected_conditions.py#L14-L15" >}} +{{% /tab %}} {{< tab header="CSharp" >}} .NET stopped supporting Expected Conditions in Selenium 4 to minimize maintenance hassle and redundancy. {{< /tab >}} diff --git a/website_and_docs/content/documentation/webdriver/support_features/expected_conditions.pt-br.md b/website_and_docs/content/documentation/webdriver/support_features/expected_conditions.pt-br.md index 298cbe838688..2c2a3f75d80b 100644 --- a/website_and_docs/content/documentation/webdriver/support_features/expected_conditions.pt-br.md +++ b/website_and_docs/content/documentation/webdriver/support_features/expected_conditions.pt-br.md @@ -24,10 +24,9 @@ These methods can include conditions such as: [Expected Conditions Documentation](https://www.selenium.dev/selenium/docs/api/java/org/openqa/selenium/support/ui/ExpectedConditions.html) {{< badge-code >}} {{% /tab %}} -{{< tab header="Python" >}} -[Expected Conditions Documentation](https://www.selenium.dev/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.expected_conditions.html) -{{< badge-code >}} -{{< /tab >}} +{{% tab header="Python" %}} +{{< gh-codeblock path="examples/python/tests/support/test_expected_conditions.py#L14-L15" >}} +{{% /tab %}} {{< tab header="CSharp" >}} .NET stopped supporting Expected Conditions in Selenium 4 to minimize maintenance hassle and redundancy. {{< /tab >}} diff --git a/website_and_docs/content/documentation/webdriver/support_features/expected_conditions.zh-cn.md b/website_and_docs/content/documentation/webdriver/support_features/expected_conditions.zh-cn.md index f9ce68fb0c46..f25b9d5e5215 100644 --- a/website_and_docs/content/documentation/webdriver/support_features/expected_conditions.zh-cn.md +++ b/website_and_docs/content/documentation/webdriver/support_features/expected_conditions.zh-cn.md @@ -24,10 +24,9 @@ description: > [Expected Conditions Documentation](https://www.selenium.dev/selenium/docs/api/java/org/openqa/selenium/support/ui/ExpectedConditions.html) {{< badge-code >}} {{% /tab %}} -{{< tab header="Python" >}} -[Expected Conditions Documentation](https://www.selenium.dev/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.expected_conditions.html) -{{< badge-code >}} -{{< /tab >}} +{{% tab header="Python" %}} +{{< gh-codeblock path="examples/python/tests/support/test_expected_conditions.py#L14-L15" >}} +{{% /tab %}} {{< tab header="CSharp" >}} .NET stopped supporting Expected Conditions in Selenium 4 to minimize maintenance hassle and redundancy. {{< /tab >}} diff --git a/website_and_docs/content/documentation/webdriver/troubleshooting/errors/_index.en.md b/website_and_docs/content/documentation/webdriver/troubleshooting/errors/_index.en.md index c29b50e2ea8b..d2bb6821ae27 100644 --- a/website_and_docs/content/documentation/webdriver/troubleshooting/errors/_index.en.md +++ b/website_and_docs/content/documentation/webdriver/troubleshooting/errors/_index.en.md @@ -179,3 +179,19 @@ This exception occurs when Selenium tries to interact with an element that is no 2. Ensure locators uniquely identify the intended element to avoid incorrect matches. 3. Check if the element is visible on the page before interacting with it. Use scrolling to bring the element into view, if required. 4. Use explicit waits to ensure the element is interactable before performing actions. + +## ElementNotVisibleException + +This exception is thrown when the element you are trying to interact with _is_ present in the DOM, but is not visible. + +### Likely Cause + +This can occur in several situations: +* Another element is blocking your intended element +* The element is disabled/invisible to the user + +### Possible Solutions + +This issue cannot always be resolved on the user's end, however when it can it is usually solved by the following: +using an explicit wait, or interacting with the page in such a way to make the element visible +(scrolling, clicking a button, etc.) diff --git a/website_and_docs/content/documentation/webdriver/troubleshooting/errors/_index.ja.md b/website_and_docs/content/documentation/webdriver/troubleshooting/errors/_index.ja.md index e07e2ee97d2c..3a61c2ce3147 100644 --- a/website_and_docs/content/documentation/webdriver/troubleshooting/errors/_index.ja.md +++ b/website_and_docs/content/documentation/webdriver/troubleshooting/errors/_index.ja.md @@ -175,3 +175,20 @@ This exception occurs when Selenium tries to interact with an element that is no 2. Ensure locators uniquely identify the intended element to avoid incorrect matches. 3. Check if the element is visible on the page before interacting with it. Use scrolling to bring the element into view, if required. 4. Use explicit waits to ensure the element is interactable before performing actions. + +## ElementNotVisibleException + +This exception is thrown when the element you are trying to interact with _is_ present in the DOM, but is not visible. + +### Likely Cause + +This can occur in several situations: +* Another element is blocking your intended element +* The element is disabled/invisible to the user + +### Possible Solutions + +This issue cannot always be resolved on the user's end, however when it can it is usually solved by the following: +using an explicit wait, or interacting with the page in such a way to make the element visible +(scrolling, clicking a button, etc.) + diff --git a/website_and_docs/content/documentation/webdriver/troubleshooting/errors/_index.pt-br.md b/website_and_docs/content/documentation/webdriver/troubleshooting/errors/_index.pt-br.md index c589a269edd0..31109672a38b 100644 --- a/website_and_docs/content/documentation/webdriver/troubleshooting/errors/_index.pt-br.md +++ b/website_and_docs/content/documentation/webdriver/troubleshooting/errors/_index.pt-br.md @@ -175,3 +175,19 @@ This exception occurs when Selenium tries to interact with an element that is no 2. Ensure locators uniquely identify the intended element to avoid incorrect matches. 3. Check if the element is visible on the page before interacting with it. Use scrolling to bring the element into view, if required. 4. Use explicit waits to ensure the element is interactable before performing actions. + +## ElementNotVisibleException + +This exception is thrown when the element you are trying to interact with _is_ present in the DOM, but is not visible. + +### Likely Cause + +This can occur in several situations: +* Another element is blocking your intended element +* The element is disabled/invisible to the user + +### Possible Solutions + +This issue cannot always be resolved on the user's end, however when it can it is usually solved by the following: +using an explicit wait, or interacting with the page in such a way to make the element visible +(scrolling, clicking a button, etc.) diff --git a/website_and_docs/content/documentation/webdriver/troubleshooting/errors/_index.zh-cn.md b/website_and_docs/content/documentation/webdriver/troubleshooting/errors/_index.zh-cn.md index 5818b46d6a08..a2704257f470 100644 --- a/website_and_docs/content/documentation/webdriver/troubleshooting/errors/_index.zh-cn.md +++ b/website_and_docs/content/documentation/webdriver/troubleshooting/errors/_index.zh-cn.md @@ -178,3 +178,19 @@ Actions class with `Actions.moveToElement(element)`. 2. 确保定位器唯一标识目标元素,以避免错误匹配。 3. 在与元素交互之前,检查其是否在页面上可见。如果需要,将元素滚动到视图中。 4. 使用显式等待以确保元素在执行操作前可交互。 + +## ElementNotVisibleException + +This exception is thrown when the element you are trying to interact with _is_ present in the DOM, but is not visible. + +### Likely Cause + +This can occur in several situations: +* Another element is blocking your intended element +* The element is disabled/invisible to the user + +### Possible Solutions + +This issue cannot always be resolved on the user's end, however when it can it is usually solved by the following: +using an explicit wait, or interacting with the page in such a way to make the element visible +(scrolling, clicking a button, etc.) diff --git a/website_and_docs/content/documentation/webdriver/waits.zh-cn.md b/website_and_docs/content/documentation/webdriver/waits.zh-cn.md index 6f9de8e6dd54..ffedafd6de0a 100644 --- a/website_and_docs/content/documentation/webdriver/waits.zh-cn.md +++ b/website_and_docs/content/documentation/webdriver/waits.zh-cn.md @@ -1,69 +1,79 @@ --- -title: "等待" +title: "等待策略" linkTitle: "等待" weight: 6 aliases: ["/documentation/zh-cn/webdriver/waits/"] --- -Perhaps the most common challenge for browser automation is ensuring -that the web application is in a state to execute a particular -Selenium command as desired. The processes often end up in -a _race condition_ where sometimes the browser gets into the right -state first (things work as intended) and sometimes the Selenium code -executes first (things do not work as intended). This is one of the -primary causes of _flaky tests_. - -All navigation commands wait for a specific `readyState` value -based on the [page load strategy]({{< ref "drivers/options#pageloadstrategy" >}}) (the -default value to wait for is `"complete"`) before the driver returns control to the code. -The `readyState` only concerns itself with loading assets defined in the HTML, -but loaded JavaScript assets often result in changes to the site, -and elements that need to be interacted with may not yet be on the page -when the code is ready to execute the next Selenium command. - -Similarly, in a lot of single page applications, elements get dynamically -added to a page or change visibility based on a click. -An element must be both present and -[displayed]({{< ref "elements/information/#is-displayed" >}}) on the page -in order for Selenium to interact with it. - -Take this page for example: https://www.selenium.dev/selenium/web/dynamic.html -When the "Add a box!" button is clicked, a "div" element that does not exist is created. -When the "Reveal a new input" button is clicked, a hidden text field element is displayed. -In both cases the transition takes a couple seconds. -If the Selenium code is to click one of these buttons and interact with the resulting element, -it will do so before that element is ready and fail. - -The first solution many people turn to is adding a sleep statement to -pause the code execution for a set period of time. -Because the code can't know exactly how long it needs to wait, this -can fail when it doesn't sleep long enough. Alternately, if the value is set too high -and a sleep statement is added in every place it is needed, the duration of -the session can become prohibitive. - -Selenium provides two different mechanisms for synchronization that are better. - - -## Implicit waits -Selenium has a built-in way to automatically wait for elements called an _implicit wait_. -An implicit wait value can be set either with the [timeouts]({{< ref "drivers/options#timeouts" >}}) -capability in the browser options, or with a driver method (as shown below). - -This is a global setting that applies to every element location call for the entire session. -The default value is `0`, which means that if the element is not found, it will -immediately return an error. If an implicit wait is set, the driver will wait for the -duration of the provided value before returning the error. Note that as soon as the -element is located, the driver will return the element reference and the code will continue executing, -so a larger implicit wait value won't necessarily increase the duration of the session. - -*Warning:* -Do not mix implicit and explicit waits. -Doing so can cause unpredictable wait times. -For example, setting an implicit wait of 10 seconds -and an explicit wait of 15 seconds -could cause a timeout to occur after 20 seconds. - -Solving our example with an implicit wait looks like this: + +或许浏览器自动化面临的最常见挑战在于, +确保网络应用程序处于能够按预期执行特定 Selenium 命令的状态. +这些过程常常陷入一种 _竞态条件_ , +有时浏览器会先达到正确状态 (一切按预期运行) , +有时 Selenium 代码会先执行 (一切未按预期运行) . +这是导致 _不稳定测试_ 的主要原因之一. + + +所有导航命令都会等待特定基于 [页面加载策略]({{< ref "drivers/options#pageloadstrategy">}}) 的值 `readyState` + (默认等待的值为 `"complete"` ) , +然后驱动程序才会将控制权交还给代码. +`readyState` 仅关注 HTML 中定义的资源加载, +但加载的 JavaScript 资源常常会导致网站发生变化, +而当代码准备执行下一个 Selenium 命令时, +需要交互的元素可能尚未出现在页面上. + + +同样, 在许多单页应用程序中, +元素会根据点击操作动态添加到页面上或改变可见性. +对于 Selenium 能够与之交互, +该元素必须既存在于页面上又处于[displayed]({{< ref "elements/information/#is-displayed">}}) 状态. + + +以这个页面为例: https://www.selenium.dev/selenium/web/dynamic.html +当点击 "Add a box!" 按钮时, +会创建一个原本不存在的 "div" 元素. +当点击 "Reveal a new input" 按钮时, +一个隐藏的文本字段元素会被显示出来. +在这两种情况下, 过渡都需要几秒钟. +如果 Selenium 代码要点击其中一个按钮并与生成的元素进行交互, +它会在该元素准备好之前就执行操作, 从而导致失败. + + +许多人首先想到的解决办法是在代码中添加一个睡眠语句, +让代码暂停执行一段设定的时间. +由于代码无法确切知道需要等待多久, +如果设置的睡眠时间不够长, +这种方法可能会失败. +相反, 如果睡眠时间设置得过高, 并且在每个需要的地方都添加睡眠语句, +那么会话的持续时间可能会变得难以接受. + +Selenium 提供了更好的两种不同的同步机制, + + +## 隐式等待 +Selenium 内置了一种自动等待元素出现的方式, 称为 _隐式等待_ . +隐式等待的值可以通过浏览器选项中的 [timeouts]({{< ref "drivers/options#timeouts">}}) 设置来设定, +也可以通过驱动程序的方法来设定 (如下所示) . + +这是一个全局设置, 适用于整个会话期间的每个元素定位调用. +默认值为 `0` , +这意味着如果未找到元素, +将立即返回错误. +如果设置了隐式等待, +驱动程序将在返回错误之前等待所提供的时长. +请注意, 一旦定位到元素, +驱动程序将返回元素引用, +代码将继续执行, +因此较大的隐式等待值不一定增加会话的持续时间. + +*警告:* +请勿混合使用隐式等待和显式等待. +这样做可能会导致等待时间不可预测. +例如, 设置 10 秒的隐式等待和 15 秒的显式等待, +可能会导致在 20 秒后发生超时. + +使用隐式等待解决我们的示例代码如下: + {{< tabpane text=true >}} {{< tab header="Java" >}} @@ -86,15 +96,20 @@ Solving our example with an implicit wait looks like this: {{< /tab >}} {{< /tabpane >}} -## Explicit waits -_Explicit waits_ are loops added to the code that poll the application -for a specific condition to evaluate as true before it exits the loop and -continues to the next command in the code. If the condition is not met before a designated timeout value, -the code will give a timeout error. Since there are many ways for the application not to be in the desired state, -explicit waits are a great choice to specify the exact condition to wait for -in each place it is needed. -Another nice feature is that, by default, the Selenium Wait class automatically waits for the designated element to exist. + +## 显式等待 + +_显式等待_ 是在代码中添加的, 用于轮询应用程序的循环, +直到特定条件评估为真时, 才退出循环并继续执行代码中的下一个命令. +如果在指定的超时值之前条件未满足, +代码将给出超时错误. +由于应用程序未处于所需状态的方式有很多, +因此显式等待是为每个需要等待的地方指定确切等待条件的绝佳选择. +另一个不错的特性是, 默认情况下, +Selenium 等待类会自动等待指定的元素存在. + + {{< tabpane text=true >}} {{% tab header="Java" %}} @@ -122,23 +137,28 @@ JavaScript also supports [Expected Conditions]({{< ref "support_features/expecte {{< /tab >}} {{< /tabpane >}} -### Customization -The Wait class can be instantiated with various parameters that will change how the conditions are evaluated. -This can include: -* Changing how often the code is evaluated (polling interval) -* Specifying which exceptions should be handled automatically -* Changing the total timeout length -* Customizing the timeout message +### 定制 + +Wait 类可以通过各种参数进行实例化, +这些参数会改变条件的评估方式. + +这可以包括: +* 更改代码的评估频率 (轮询间隔) +* 指定哪些异常应自动处理 +* 更改总超时时长 +* 自定义超时消息 + +例如, 如果默认情况下对 _元素不可交互_ 错误进行重试, +那么我们可以在执行中的代码里的某个方法内添加一个操作 + (我们只需要确保代码在成功时返回 `true` 即可): + -For instance, if the _element not interactable_ error is retried by default, then we can -add an action on a method inside the code getting executed (we just need to -make sure that the code returns `true` when it is successful): {{< tabpane text=true >}} {{% tab header="Java" %}} -The easiest way to customize Waits in Java is to use the `FluentWait` class: +The easiest way to customize Waits in Java is to use the `FluentWait` class: {{< gh-codeblock path="examples/java/src/test/java/dev/selenium/waits/WaitsTest.java#L82-L92" >}} {{% /tab %}} {{< tab header="Python" >}} @@ -157,3 +177,4 @@ The easiest way to customize Waits in Java is to use the `FluentWait` class: {{< badge-code >}} {{< /tab >}} {{< /tabpane >}} + diff --git a/website_and_docs/content/events/_index.html b/website_and_docs/content/events/_index.html index 7d8af1562859..c4a78af2507b 100644 --- a/website_and_docs/content/events/_index.html +++ b/website_and_docs/content/events/_index.html @@ -45,21 +45,28 @@

Selenium Meetups

Selenium Conference

- The next flagship Selenium conference will be held together - with Appium conference. It will be an in-person event + The last flagship Selenium conference was held together + with Appium conference. It was an in-person event and was held in Valencia, Spain on March 26-28, 2025. The Selenium Conference - and Appium Conference brings together Selenium and Appium developers & enthusiasts + and Appium Conference brought together Selenium and Appium developers & enthusiasts from around the world to share ideas, socialize, and work together on advancing the present and future success of the project.

diff --git a/website_and_docs/content/project/structure/_index.html b/website_and_docs/content/project/structure/_index.html index 17a02ee42eaf..fd4f8e9a208d 100644 --- a/website_and_docs/content/project/structure/_index.html +++ b/website_and_docs/content/project/structure/_index.html @@ -23,13 +23,13 @@

Structure

Project Leadership Committee

- {{< gh-user "https://api.github.com/users/manoj9788" >}} {{< gh-user "https://api.github.com/users/AutomatedTester" >}} - {{< gh-user "https://api.github.com/users/mmerrell" >}} + {{< gh-user "https://api.github.com/users/janetmoreno" >}} + {{< gh-user "https://api.github.com/users/jason-baum" >}} {{< gh-user "https://api.github.com/users/maaretp" >}} + {{< gh-user "https://api.github.com/users/manoj9788" >}} {{< gh-user "https://api.github.com/users/pujagani" >}} - {{< gh-user "https://api.github.com/users/janetmoreno" >}}
@@ -66,6 +66,7 @@

Selenium Committers

{{< gh-user "https://api.github.com/users/corevo" >}} {{< gh-user "https://api.github.com/users/davehunt" >}} {{< gh-user "https://api.github.com/users/ddavison" >}} + {{< gh-user "https://api.github.com/users/Delta456" >}} {{< gh-user "https://api.github.com/users/dfabulich" >}} {{< gh-user "https://api.github.com/users/diemol" >}} {{< gh-user "https://api.github.com/users/DominikDary" >}} @@ -87,6 +88,7 @@

Selenium Committers

{{< gh-user "https://api.github.com/users/luke-hill" >}} {{< gh-user "https://api.github.com/users/mach6" >}} {{< gh-user "https://api.github.com/users/mtscout6" >}} + {{< gh-user "https://api.github.com/users/navin772" >}} {{< gh-user "https://api.github.com/users/nirvdrum" >}} {{< gh-user "https://api.github.com/users/nvborisenko" >}} {{< gh-user "https://api.github.com/users/paul-hammant" >}} @@ -95,7 +97,7 @@

Selenium Committers

{{< gh-user "https://api.github.com/users/santiycr" >}} {{< gh-user "https://api.github.com/users/sevaseva" >}} {{< gh-user "https://api.github.com/users/shbenzer" >}} - {{< gh-user "https://api.github.com/users/shs96c" >}} + {{< gh-user "https://api.github.com/users/shs96c" >}} {{< gh-user "https://api.github.com/users/symonk" >}} {{< gh-user "https://api.github.com/users/TamsilAmani" >}} {{< gh-user "https://api.github.com/users/titusfortner" >}} @@ -154,8 +156,14 @@

Selenium Triagers

{{< gh-user "https://api.github.com/users/raju249" >}} {{< gh-user "https://api.github.com/users/SalmonMode" >}} {{< gh-user "https://api.github.com/users/toddtarsi" >}} - {{< gh-user "https://api.github.com/users/navin772" >}} - {{< gh-user "https://api.github.com/users/Delta456" >}} + {{< gh-user "https://api.github.com/users/navin772" >}} + {{< gh-user "https://api.github.com/users/Delta456" >}} +
+ +
+

Conference Committee

+
+ {{< gh-user "https://api.github.com/users/mmerrell" >}}
diff --git a/website_and_docs/content/sponsor/_index.html b/website_and_docs/content/sponsor/_index.html index 544ebac3a017..f920ad3e0f75 100644 --- a/website_and_docs/content/sponsor/_index.html +++ b/website_and_docs/content/sponsor/_index.html @@ -52,7 +52,8 @@

General Benefits

  • Our website is the first place people learn about Selenium. By having a link to your - website, you will be seen as a supporter of the Selenium project that our users adore.
  • + website, you will be seen as a supporter of the Selenium project that our users adore. +
  • Contributions are tax-deductible.
  • @@ -64,7 +65,6 @@

    General Benefits

    Check the Sponsorship Levels for more benefits. -

    @@ -115,7 +115,7 @@

    Sponsorship Levels

    needs to be actively contributing to the project.
  • - Currently limited to 2 companies but reviewed yearly. + Currently limited to 3 companies but reviewed yearly.
  • Special mention at Selenium events
  • diff --git a/website_and_docs/content/support/_index.html b/website_and_docs/content/support/_index.html index f9c8e619a3d1..faf929c73b8f 100644 --- a/website_and_docs/content/support/_index.html +++ b/website_and_docs/content/support/_index.html @@ -61,7 +61,7 @@

    Chat Room

    Another option, if you prefer, is to use the - + Selenium Slack channel .

    diff --git a/website_and_docs/data/sponsors.yml b/website_and_docs/data/sponsors.yml index c6d90da9c270..5c7664296af5 100644 --- a/website_and_docs/data/sponsors.yml +++ b/website_and_docs/data/sponsors.yml @@ -9,6 +9,10 @@ development: - logo: "/images/sponsors/saucelabs.png" url: "https://saucelabs.com/resources/topic-hub/selenium?utm_source=selenium&utm_medium=website&utm_campaign=selenium-sponsorship-fy25" name: "Sauce Labs" + # Sponsorship renewed October 16, 2024. Renewed again on April 8, 2025, under the "Development" level + - logo: "/images/sponsors/lambda-test.png" + url: "https://www.lambdatest.com/selenium-automation?utm_source=selenium&utm_medium=open-source-sponsor&utm_campaign=nov_14&utm_term=sk&utm_content=web" + name: "LambdaTest" selenium: # Set to false if no items are present @@ -22,10 +26,6 @@ selenium: - logo: "/images/sponsors/applitools.png" url: "https://applitools.com/" name: "Applitools" - # Sponsorship renewed October 16, 2024. - - logo: "/images/sponsors/lambda-test.png" - url: "https://www.lambdatest.com/selenium-automation?utm_source=selenium&utm_medium=open-source-sponsor&utm_campaign=nov_14&utm_term=sk&utm_content=web" - name: "LambdaTest" # Sponsorship start date: June 24, 2015, updated July 2023 (only logo, not the agreement) # - logo: "/images/sponsors/Digital.ai.jpg" # url: "http://bit.ly/36uZ7ad" @@ -87,6 +87,10 @@ bronze: # Set to false if no items are present enable: true item: + # Sponsorship renewal date: Apr 12, 2026 + - logo: "/images/sponsors/kualtee.png" + url: "http://www.kualitee.com/?utm_source=selenium&utm_medium=website&utm_campaign=seleniumpartnership" + name: "Kualitee" # Sponsorship renewal date: Feb 4, 2025 - logo: "/images/sponsors/alpi.jpg" url: "http://www.alpi.com/courses-opensource/index.cfm" @@ -115,6 +119,10 @@ bronze: - logo: "/images/sponsors/mailsac-logo.png" url: "https://mailsac.com/?utm_source=selenium&utm_medium=ads&utm_campaign=selenium-sponsor&utm_content=logolink" name: "Mailsac - Receive test emails with confidence" + # Sponsorship start date: June 02, 2025 + - logo: "/images/sponsors/Jetify-Wordmark.svg" + url: "https://www.jetify.com/" + name: "AI Automation Agency" # Sponsorship start date: Mar 20, 2023 # - logo: "/images/sponsors/kiwiqa-logo.png" # url: "https://www.kiwiqa.com/" diff --git a/website_and_docs/hugo.toml b/website_and_docs/hugo.toml index fa46c474e1e2..b3bcfd2b27d4 100644 --- a/website_and_docs/hugo.toml +++ b/website_and_docs/hugo.toml @@ -219,7 +219,7 @@ enable = false desc = "Follow us on X to get the latest news!" [[params.links.user]] name = "Selenium Community YouTube Channel" - url = "https://www.youtube.com/@SeleniumHQProject/streams" + url = "https://www.youtube.com/@SeleniumHQProject/" icon = "fab fa-youtube" desc = "Check all the Community talks!" # Developer relevant links. These will show up on right side of footer and in the community page if you have one. @@ -258,7 +258,7 @@ enable = false desc = "Development takes place here!" [[params.links.developer]] name = "Slack" - url = "https://join.slack.com/t/seleniumhq/shared_invite/zt-2stlcmc6b-Hww~3r3yAzquhSq4riOFxA" + url = "https://inviter.co/seleniumhq" icon = "fab fa-slack" desc = "Chat with other project developers and users in Slack" [[params.links.developer]] diff --git a/website_and_docs/layouts/downloads/list.html b/website_and_docs/layouts/downloads/list.html index 119d236986c4..ce2ee8be22e3 100644 --- a/website_and_docs/layouts/downloads/list.html +++ b/website_and_docs/layouts/downloads/list.html @@ -25,18 +25,18 @@

    Latest stable version - 4.29.0 + 4.34.0

    - To use the Selenium Server in a Grid configuration see the + To use the Selenium Server in a Grid configuration, see the documentation.

    - To run the Grid with popular browsers using Docker see the + To run the Grid with popular browsers using Docker, see the repository.

    - To deploy the Grid to Kubernetes cluster see the Helm chart + To deploy the Grid to Kubernetes cluster, see the Helm chart configuration.

    @@ -115,7 +115,7 @@

    C# NuGet

    - Nuget latest release is 4.29.0 Released on February 20, 2025. + Nuget latest release is 4.34.0 Released on June 29, 2025.

    • diff --git a/website_and_docs/layouts/partials/announcement-banner.html b/website_and_docs/layouts/partials/announcement-banner.html index 9bcd5cadfdbd..4dafa09b324e 100644 --- a/website_and_docs/layouts/partials/announcement-banner.html +++ b/website_and_docs/layouts/partials/announcement-banner.html @@ -4,16 +4,12 @@
      - +
      diff --git a/website_and_docs/layouts/partials/hooks/body-end.html b/website_and_docs/layouts/partials/hooks/body-end.html new file mode 100644 index 000000000000..0652394a4259 --- /dev/null +++ b/website_and_docs/layouts/partials/hooks/body-end.html @@ -0,0 +1,29 @@ +{{ if or .Site.Params.search.algolia .Site.Params.algolia_docsearch }} + +{{ end }} diff --git a/website_and_docs/layouts/partials/hooks/head-end.html b/website_and_docs/layouts/partials/hooks/head-end.html index a22bf871d042..2dcc8e6d4f19 100644 --- a/website_and_docs/layouts/partials/hooks/head-end.html +++ b/website_and_docs/layouts/partials/hooks/head-end.html @@ -1,3 +1,6 @@ {{ with .Site.Params.plausible_analytics }} {{ end }} +{{ if or .Site.Params.search.algolia .Site.Params.algolia_docsearch }} + +{{ end }} diff --git a/website_and_docs/layouts/partials/selenium-clients-and-webdriver-bindings.html b/website_and_docs/layouts/partials/selenium-clients-and-webdriver-bindings.html index 110ea411129d..b7f059d0b12d 100644 --- a/website_and_docs/layouts/partials/selenium-clients-and-webdriver-bindings.html +++ b/website_and_docs/layouts/partials/selenium-clients-and-webdriver-bindings.html @@ -27,7 +27,7 @@

      Selenium Clients and WebDriver Language Bin

      Stable: - 4.29.0 (February 20, 2025) + 4.34.0 (June 29, 2025)

      @@ -54,8 +54,8 @@

      Selenium Clients and WebDriver Language Bin

      Stable: - - 4.29.0 (February 20, 2025) + + 4.34.0 (June 29, 2025)

      @@ -82,8 +82,8 @@

      Selenium Clients and WebDriver Language Bin

      Stable: - - 4.29.0 (February 20, 2025) + + 4.34.0 (June 29, 2025)

      @@ -111,7 +111,7 @@

      Selenium Clients and WebDriver Language Bin

      Stable: - 4.29.0 (February 20, 2024) + 4.34.0 (June 29, 2024)

      @@ -139,11 +139,11 @@

      Selenium Clients and WebDriver Language Bin

      Stable: - 4.29.0 (February 20, 2025) + 4.34.0 (June 29, 2025)

      - + Changelog

      diff --git a/website_and_docs/layouts/shortcodes/gh-codeblock.html b/website_and_docs/layouts/shortcodes/gh-codeblock.html index ca3073301620..1db52648f837 100644 --- a/website_and_docs/layouts/shortcodes/gh-codeblock.html +++ b/website_and_docs/layouts/shortcodes/gh-codeblock.html @@ -6,21 +6,22 @@ {{ $defaultBranchFromEnv := (getenv "SELENIUM_EXAMPLES_BRANCH") }} {{ if $defaultBranchFromEnv }} - {{ $branch = $defaultBranchFromEnv }} +{{ $branch = $defaultBranchFromEnv }} {{ end }} {{ $defaultOrgFromEnv := (getenv "SELENIUM_EXAMPLES_ORG") }} {{ if $defaultOrgFromEnv }} - {{ $org = $defaultOrgFromEnv }} +{{ $org = $defaultOrgFromEnv }} {{ end }} {{ $defaultRepoFromEnv := (getenv "SELENIUM_EXAMPLES_REPO") }} {{ if $defaultRepoFromEnv }} - {{ $repo = $defaultRepoFromEnv }} +{{ $repo = $defaultRepoFromEnv }} {{ end }} {{ $fullPath := .Get "path" }} {{ $path := index (split $fullPath "#") 0 }} +{{ $hasFragment := in $fullPath "#" }} {{ $apiUrl := printf "%s/%s/%s/contents%s?ref=%s" $apiBaseUrl $org $repo $path $branch }} {{ $webUrl := printf "%s/%s/%s/blob/%s/%s" $webBaseUrl $org $repo $branch $fullPath }} @@ -30,34 +31,148 @@ {{ $githubToken := (getenv "SELENIUM_CI_TOKEN") }} {{ if $githubToken }} - {{ $toReplace := printf "://%s@" $githubToken }} - {{ $tokenInUrl := cond (eq $githubToken "") "://" $toReplace }} - {{ $apiUrlWithToken := replace $apiUrl "://" $tokenInUrl }} - - {{ $apiResults := getJSON $apiUrlWithToken }} - {{ $content := base64Decode $apiResults.content }} - {{ $codeSnippet := $content }} - - {{ $parsedApiUrl := urls.Parse $webUrl }} - {{ with $parsedApiUrl.Fragment }} - {{ $codeLines := split $parsedApiUrl.Fragment "-" }} - {{ $fromLine := sub (int (replace (index $codeLines 0) "L" "")) 1 }} - {{ $toLine := int (cond (eq (len $codeLines) 1) (replace (index $codeLines 0) "L" "") (replace (index $codeLines 1) "L" "")) }} - {{ $numOfLines := cond (eq (sub $toLine $fromLine) 0) 1 (sub $toLine $fromLine) }} - {{ $splitContent := split $content "\n" }} - {{ $codeSnippet = delimit (first $numOfLines (after $fromLine $splitContent)) "\n" }} - {{ end }} - - {{ highlight $codeSnippet $language }} - -
      +{{ $toReplace := printf "://%s@" $githubToken }} +{{ $tokenInUrl := cond (eq $githubToken "") "://" $toReplace }} +{{ $apiUrlWithToken := replace $apiUrl "://" $tokenInUrl }} + +{{ $apiResults := getJSON $apiUrlWithToken }} +{{ $content := base64Decode $apiResults.content }} +{{ $codeSnippet := $content }} + +{{ $parsedApiUrl := urls.Parse $webUrl }} +{{ with $parsedApiUrl.Fragment }} +{{ $codeLines := split $parsedApiUrl.Fragment "-" }} +{{ $fromLine := sub (int (replace (index $codeLines 0) "L" "")) 1 }} +{{ $toLine := int (cond (eq (len $codeLines) 1) (replace (index $codeLines 0) "L" "") (replace (index $codeLines 1) "L" "")) }} +{{ $numOfLines := cond (eq (sub $toLine $fromLine) 0) 1 (sub $toLine $fromLine) }} +{{ $splitContent := split $content "\n" }} +{{ $codeSnippet = delimit (first $numOfLines (after $fromLine $splitContent)) "\n" }} +{{ end }} + +{{ highlight $codeSnippet $language }} + + + +{{ if $hasFragment }} +{{ $uniqueId := md5 $path }} + + + + + +{{ else }} + -{{ else }} - {{ partial "github-content.html" }} +
      {{ end }} - +{{ else }} +{{ partial "github-content.html" }} +{{ end }} diff --git a/website_and_docs/package-lock.json b/website_and_docs/package-lock.json index 74955c2f9e78..cf8a6b257f44 100644 --- a/website_and_docs/package-lock.json +++ b/website_and_docs/package-lock.json @@ -10,51 +10,8 @@ "license": "Apache-2.0", "dependencies": { "autoprefixer": "^10.4.21", - "postcss": "^8.5.3", - "postcss-cli": "^11.0.0" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@sindresorhus/merge-streams": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", - "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "postcss": "^8.5.4", + "postcss-cli": "^11.0.1" } }, "node_modules/ansi-regex": { @@ -256,11 +213,12 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/dependency-graph": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz", - "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-1.0.0.tgz", + "integrity": "sha512-cW3gggJ28HZ/LExwxP2B++aiKxhJXMSIt9K48FOXQkm+vuG5gyatXnLsONRJdzO/7VfjDIiaOOa/bs4l464Lwg==", + "license": "MIT", "engines": { - "node": ">= 0.6.0" + "node": ">=4" } }, "node_modules/electron-to-chromium": { @@ -283,29 +241,6 @@ "node": ">=6" } }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dependencies": { - "reusify": "^1.0.4" - } - }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -364,17 +299,6 @@ "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/get-stdin": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", - "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -386,38 +310,11 @@ "node": ">= 6" } }, - "node_modules/globby": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.1.tgz", - "integrity": "sha512-jOMLD2Z7MAhyG8aJpNOpmziMOP4rPLcc95oQPKXBazW82z+CEgPFBQvEpRUa1KeIMUJo4Wsm+q6uzO/Q/4BksQ==", - "dependencies": { - "@sindresorhus/merge-streams": "^2.1.0", - "fast-glob": "^3.3.2", - "ignore": "^5.2.4", - "path-type": "^5.0.0", - "slash": "^5.1.0", - "unicorn-magic": "^0.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, - "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "engines": { - "node": ">= 4" - } - }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -487,30 +384,10 @@ "url": "https://github.com/sponsors/antonk52" } }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, "node_modules/nanoid": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", - "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "funding": [ { "type": "github", @@ -546,17 +423,6 @@ "node": ">=0.10.0" } }, - "node_modules/path-type": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", - "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -583,9 +449,9 @@ } }, "node_modules/postcss": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", - "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "funding": [ { "type": "opencollective", @@ -601,7 +467,7 @@ } ], "dependencies": { - "nanoid": "^3.3.8", + "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -610,21 +476,21 @@ } }, "node_modules/postcss-cli": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/postcss-cli/-/postcss-cli-11.0.0.tgz", - "integrity": "sha512-xMITAI7M0u1yolVcXJ9XTZiO9aO49mcoKQy6pCDFdMh9kGqhzLVpWxeD/32M/QBmkhcGypZFFOLNLmIW4Pg4RA==", + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/postcss-cli/-/postcss-cli-11.0.1.tgz", + "integrity": "sha512-0UnkNPSayHKRe/tc2YGW6XnSqqOA9eqpiRMgRlV1S6HdGi16vwJBx7lviARzbV1HpQHqLLRH3o8vTcB0cLc+5g==", + "license": "MIT", "dependencies": { "chokidar": "^3.3.0", - "dependency-graph": "^0.11.0", + "dependency-graph": "^1.0.0", "fs-extra": "^11.0.0", - "get-stdin": "^9.0.0", - "globby": "^14.0.0", "picocolors": "^1.0.0", "postcss-load-config": "^5.0.0", "postcss-reporter": "^7.0.0", "pretty-hrtime": "^1.0.3", "read-cache": "^1.0.0", "slash": "^5.0.0", + "tinyglobby": "^0.2.12", "yargs": "^17.0.0" }, "bin": { @@ -703,25 +569,6 @@ "node": ">= 0.8" } }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -749,41 +596,11 @@ "node": ">=0.10.0" } }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, "node_modules/slash": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "license": "MIT", "engines": { "node": ">=14.16" }, @@ -828,6 +645,48 @@ "resolved": "https://registry.npmjs.org/thenby/-/thenby-1.3.4.tgz", "integrity": "sha512-89Gi5raiWA3QZ4b2ePcEwswC3me9JIg+ToSgtE0JWeCynLnLxNr/f9G+xfo9K+Oj4AFdom8YNJjibIARTJmapQ==" }, + "node_modules/tinyglobby": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.12.tgz", + "integrity": "sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==", + "license": "MIT", + "dependencies": { + "fdir": "^6.4.3", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz", + "integrity": "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==", + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -840,17 +699,6 @@ "node": ">=8.0" } }, - "node_modules/unicorn-magic": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", - "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", @@ -951,34 +799,6 @@ } }, "dependencies": { - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@sindresorhus/merge-streams": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", - "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==" - }, "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -1082,9 +902,9 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "dependency-graph": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz", - "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-1.0.0.tgz", + "integrity": "sha512-cW3gggJ28HZ/LExwxP2B++aiKxhJXMSIt9K48FOXQkm+vuG5gyatXnLsONRJdzO/7VfjDIiaOOa/bs4l464Lwg==" }, "electron-to-chromium": { "version": "1.5.113", @@ -1101,26 +921,6 @@ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==" }, - "fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - } - }, - "fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "requires": { - "reusify": "^1.0.4" - } - }, "fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -1155,11 +955,6 @@ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, - "get-stdin": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", - "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==" - }, "glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -1168,29 +963,11 @@ "is-glob": "^4.0.1" } }, - "globby": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.1.tgz", - "integrity": "sha512-jOMLD2Z7MAhyG8aJpNOpmziMOP4rPLcc95oQPKXBazW82z+CEgPFBQvEpRUa1KeIMUJo4Wsm+q6uzO/Q/4BksQ==", - "requires": { - "@sindresorhus/merge-streams": "^2.1.0", - "fast-glob": "^3.3.2", - "ignore": "^5.2.4", - "path-type": "^5.0.0", - "slash": "^5.1.0", - "unicorn-magic": "^0.1.0" - } - }, "graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, - "ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==" - }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -1236,24 +1013,10 @@ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz", "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==" }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" - }, - "micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "requires": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - } - }, "nanoid": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", - "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==" + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==" }, "node-releases": { "version": "2.0.19", @@ -1270,11 +1033,6 @@ "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==" }, - "path-type": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", - "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==" - }, "picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -1291,31 +1049,30 @@ "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==" }, "postcss": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", - "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "requires": { - "nanoid": "^3.3.8", + "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "postcss-cli": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/postcss-cli/-/postcss-cli-11.0.0.tgz", - "integrity": "sha512-xMITAI7M0u1yolVcXJ9XTZiO9aO49mcoKQy6pCDFdMh9kGqhzLVpWxeD/32M/QBmkhcGypZFFOLNLmIW4Pg4RA==", + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/postcss-cli/-/postcss-cli-11.0.1.tgz", + "integrity": "sha512-0UnkNPSayHKRe/tc2YGW6XnSqqOA9eqpiRMgRlV1S6HdGi16vwJBx7lviARzbV1HpQHqLLRH3o8vTcB0cLc+5g==", "requires": { "chokidar": "^3.3.0", - "dependency-graph": "^0.11.0", + "dependency-graph": "^1.0.0", "fs-extra": "^11.0.0", - "get-stdin": "^9.0.0", - "globby": "^14.0.0", "picocolors": "^1.0.0", "postcss-load-config": "^5.0.0", "postcss-reporter": "^7.0.0", "pretty-hrtime": "^1.0.3", "read-cache": "^1.0.0", "slash": "^5.0.0", + "tinyglobby": "^0.2.12", "yargs": "^17.0.0" } }, @@ -1347,11 +1104,6 @@ "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==" }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" - }, "read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -1373,19 +1125,6 @@ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "requires": { - "queue-microtask": "^1.2.2" - } - }, "slash": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", @@ -1419,6 +1158,28 @@ "resolved": "https://registry.npmjs.org/thenby/-/thenby-1.3.4.tgz", "integrity": "sha512-89Gi5raiWA3QZ4b2ePcEwswC3me9JIg+ToSgtE0JWeCynLnLxNr/f9G+xfo9K+Oj4AFdom8YNJjibIARTJmapQ==" }, + "tinyglobby": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.12.tgz", + "integrity": "sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==", + "requires": { + "fdir": "^6.4.3", + "picomatch": "^4.0.2" + }, + "dependencies": { + "fdir": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz", + "integrity": "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==", + "requires": {} + }, + "picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==" + } + } + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -1427,11 +1188,6 @@ "is-number": "^7.0.0" } }, - "unicorn-magic": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", - "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==" - }, "universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", diff --git a/website_and_docs/package.json b/website_and_docs/package.json index f089c34c9a40..86efb58fae8b 100644 --- a/website_and_docs/package.json +++ b/website_and_docs/package.json @@ -10,7 +10,7 @@ "license": "Apache-2.0", "dependencies": { "autoprefixer": "^10.4.21", - "postcss": "^8.5.3", - "postcss-cli": "^11.0.0" + "postcss": "^8.5.4", + "postcss-cli": "^11.0.1" } } diff --git a/website_and_docs/static/images/blog/2025/lambdatest-selenium-development-partner.png b/website_and_docs/static/images/blog/2025/lambdatest-selenium-development-partner.png new file mode 100644 index 000000000000..712d0245cef7 Binary files /dev/null and b/website_and_docs/static/images/blog/2025/lambdatest-selenium-development-partner.png differ diff --git a/website_and_docs/static/images/blog/2025/selenium_4.30.jpg b/website_and_docs/static/images/blog/2025/selenium_4.30.jpg new file mode 100644 index 000000000000..e4a948f087d3 Binary files /dev/null and b/website_and_docs/static/images/blog/2025/selenium_4.30.jpg differ diff --git a/website_and_docs/static/images/blog/2025/selenium_4.31.jpg b/website_and_docs/static/images/blog/2025/selenium_4.31.jpg new file mode 100644 index 000000000000..a8374b70e789 Binary files /dev/null and b/website_and_docs/static/images/blog/2025/selenium_4.31.jpg differ diff --git a/website_and_docs/static/images/blog/2025/selenium_4.32.jpg b/website_and_docs/static/images/blog/2025/selenium_4.32.jpg new file mode 100644 index 000000000000..1f24f76ff216 Binary files /dev/null and b/website_and_docs/static/images/blog/2025/selenium_4.32.jpg differ diff --git a/website_and_docs/static/images/blog/2025/selenium_4.33.jpg b/website_and_docs/static/images/blog/2025/selenium_4.33.jpg new file mode 100644 index 000000000000..0da5201b9f8e Binary files /dev/null and b/website_and_docs/static/images/blog/2025/selenium_4.33.jpg differ diff --git a/website_and_docs/static/images/sponsors/Jetify-Wordmark.svg b/website_and_docs/static/images/sponsors/Jetify-Wordmark.svg new file mode 100644 index 000000000000..d4ce744d077f --- /dev/null +++ b/website_and_docs/static/images/sponsors/Jetify-Wordmark.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/website_and_docs/static/images/sponsors/kualtee.png b/website_and_docs/static/images/sponsors/kualtee.png new file mode 100644 index 000000000000..e38fc42c8bc3 Binary files /dev/null and b/website_and_docs/static/images/sponsors/kualtee.png differ diff --git a/website_and_docs/static/js/docsearch-fix.js b/website_and_docs/static/js/docsearch-fix.js new file mode 100644 index 000000000000..230a7b607984 --- /dev/null +++ b/website_and_docs/static/js/docsearch-fix.js @@ -0,0 +1,25 @@ +let originalDocsearch = null; + +Object.defineProperty(window, 'docsearch', { + get: function() { + return function(config) { + if (originalDocsearch) { + try { + const container = typeof config.container === 'string' + ? document.querySelector(config.container) + : config.container; + + if (container) { + return originalDocsearch(config); + } + } catch (error) { + // Silently ignore errors + } + } + }; + }, + set: function(value) { + originalDocsearch = value; + }, + configurable: true +});