Adding Firefox Extensions With Selenium In Python
Modern browsers are equipped with all sorts of functionalities, i.e., from bookmarks to GPS location tracking, developer tools, and more. Almost all the modern web browsers have immense capabilities – Firefox has inbuilt screenshot capabilities, Opera has a free VPN, and Edge comes with in-built support for displaying ebooks with EPUB extension. Though browsers like Firefox, Chrome, and others are majorly used for web browsing, the fact is that Add Ons (or extensions) in Firefox provide additional power to the web browser! The same rule of thumb is also applicable to other browsers like Chrome, Edge, etc.
Additional add-ons, plugins, extensions are required to extend or customize browser functionalities, boost productivity, and suit specific requirements of users and developers. Test automation engineers that use Selenium test automation can also benefit from browser extensions like normal end-users. In fact, testers often need to automate the testing of these extensions itself 🙂
The catch is that the extensions installed on the Firefox browser present on the local machine will not be available when you fire up a Firefox instance using Gecko Driver and Selenium WebDriver. In this part of the Selenium Python tutorial, we deep dive into adding extensions in Firefox using Selenium WebDriver and Python.
What is Firefox WebExtensions API?
In Sept 2015, Mozilla started signing and validating every extension to ensure that the third-party extensions enable Firefox customization without sacrificing security or exposing users vulnerable to malware. Mozilla deprecated XPCOM and XUL-based add-ons and adapted a new extensions API (i.e., WebExtensions API).
New extensions API is compatible with the model used by Opera, Chrome, and other latest browsers. Thus, a Firefox extension developer can easily develop and manage cross-browser extensions.
What is XPI?
XPI is a cross-platform installer module file. It’s the same as zip files and can be accessed using any archive/compression program. XPI installation files are in use by Firefox, SeaMonkey, and Thunderbird. It is used for installing a web browser plugin, addons, extensions, etc.
XPI add ons can be installed by simply dragging and dropping into any open Firefox browser window. Mozilla uses XPInstall to read the installation instructions contained in the XPI file, which are later executed for the installation.
Chromium-based browsers like Chrome, Opera, and Edge use CRX files as extension installers. Safari uses SAFARIEXTZ. CRX files can’t be used to install extensions in Mozilla. XPIs can’t be used in Chromium-based browsers. However, the underlying API is the same for all these browsers, due to which maintenance of extensions is pretty easy.
How to add extensions in Firefox using Selenium WebDriver and Python?
Now that we have covered the fundamentals of extensions in Firefox, let’s look at how to add Firefox extensions using Selenium WebDriver and Python. Let’s look at the various approaches available to leverage Selenium and Firefox extensions for Selenium web automation.
Using install_addon API of Selenium WebDriver to add Firefox extensions using Python
The install_addon method of the Selenium WebDriver takes two input arguments – path to the desired Firefox extension and a Boolean value which indicates whether installation of the extension is temporary (or not).
Step 1 : Let’s download the XPIs of the target Firefox extensions.
You can point your cursor to the “ADD to Firefox button,” right-click and copy the XPI link. Then, open it in a new tab.
Alternatively, you can find a dedicated XPI download link by opening the extension’s landing page in a different browser than Firefox.
For demonstration, we’re downloading the following Firefox extensions – “VPN Master” and “Ghostery Privacy Ad Blocker.” The XPI downloader link for VPN Master is available below the green-colored button (visible in the below image) if opened using Chrome.
Step 2 : Here’s how the webdriver’s install_addon function is implemented for installing install the add-on in Mozilla:
def install_addon(self, path, temporary=None):
# Usage: driver.install_addon('/path/to/firebug.xpi')
# ‘self’ refers to the “Webdriver” class
# 'path' is absolute path to the addon that will be installed
payload = {"path": path}
if temporary:
payload["temporary"] = temporary
# The function returns an identifier of the installed addon.
# This identifier can later be used to uninstall installed addon.
return self.execute("INSTALL_ADDON", payload)["value"]
Now, let’s use this install_addon method to install the Ghostery Firefox extension temporarily.
Shown below is the Python implementation that uses Selenium WebDriver and install_addon method to install the Ghoserty plugin. The first two lines import the dependent libraries. I have added sufficient comments in the try, except, and finally python code block for easing the code walkthrough process.
Filename: FFExt.py
from selenium import webdriver
import time
try:
# Fire a remote Firefox instance using geckodriver.
# You need to have Geckodriver in the same directory as the automation testing script OR
# you need to add it in the "path" environment variable OR
# you need to know the full path to the geckodriver executable file and use it as:
# driver = webdriver.Firefox(executable_path=r'your\path\geckodriver.exe')
driver = webdriver.Firefox()
# path to your downloaded Firefox addon extension XPI file
extension_path = "G:\\jsalert\\vpnxpi\\ghostery_privacy_ad_blocker-8.5.5-an+fx.xpi"
# using webdriver's install_addon API to install the downloaded Firefox extension
driver.install_addon(extension_path, temporary=True)
# Opening the Firefox support page to verify that addon is installed
driver.get("about:support")
# xpath to the section on the support page that lists installed extension
addons = driver.find_element_by_xpath('//*[contains(text(),"Add-ons") and not(contains(text(),"with"))]')
# scrolling to the section on the support page that lists installed extension
driver.execute_script("arguments[0].scrollIntoView();", addons)
# introducing program halt time to view things, ideally remove this when performing test automation in the cloud using LambdaTest
print("Success. Yayy!!")
time.sleep(20)
except Exception as E:
print(E)
finally:
# exiting the fired Mozilla Firefox selenium webdriver instance
driver.quit()
# End Of Script
{"mode":"full","isActive":false}
Test Execution
Run the test by triggering the following command on the terminal:
python FFExt.py
Here is the execution output of the Firefox extension example that used Selenium WebDriver:
As seen from the execution snapshot, the Ghostery plugin icon appears at the top right corner. The Firefox extension installed using the install_addon method (of Selenium WebDriver) is enabled by default.
Let’s try this: Comment out the following line.
driver.install_addon(extension_path, temporary=True)
As seen in the below snapshot, the Ghostery extension is no longer a part of the installed extensions since it was installed temporarily.
Using PyTest to add Firefox extensions using Selenium and Python
PyTest is an open-source Python testing framework that is more extensively in place of the PyUnit framework. You can use PyTest for writing small tests and complex functional tests for python-based applications/libraries. On Github, PyTest clocks 7.4k+ stars. You can check out our existing blog for a quick recap on Selenium web automation in Python using PyTest.
File Name: FFExt.py
from selenium import webdriver
import time
import pytest
# Pytest fixture is used when before running the test you need to execute some code
@pytest.fixture
def FFExt():
driver = webdriver.Firefox()
extension_path = "G:\\jsalert\\vpnxpi\\ghostery_privacy_ad_blocker-8.5.5-an+fx.xpi"
driver.install_addon(extension_path, temporary=True)
driver.get("about:support")
addons = driver.find_element_by_xpath('//*[contains(text(),"Add-ons") and not(contains(text(),"with"))]')
driver.execute_script("arguments[0].scrollIntoView();", addons)
time.sleep(10)
addons1 = driver.find_elements_by_xpath('//*[contains(text(),"Add-ons") and not(contains(text(),"with"))]/following-sibling::*[1]/*[2]/*/*[1]')
# a list is created to return names of all the installed addons
addonsList = []
for addon in addons1:
addonsList.append(addon.text)
time.sleep(10)
driver.quit()
return addonsList
# This is the test function that will ASSERT whether addon is present in the list of installed add-ons returned by the FFExt function.
def test_addon(FFExt):
ghostery = "Ghostery – Privacy Ad Blocker"
assert ghostery in FFExt
{"mode":"full","isActive":false}
Run the test by triggering the following command on the terminal:
pytest FFExt.py
Here is the execution snapshot, which indicates that one test was successful.
Note: For every python project, pytest is the perfect choice for a reliable and maintainable testing architecture. For a quick overview on getting started with pytest, check out the video below from LambdaTest YouTube Channel.
Using pre-loaded Firefox extensions and FirefoxProfile in Selenium WebDriver
FirefoxProfile is a collection of settings, extensions, and customizations done on top of the Firefox browser. You can create several Firefox profiles to tailor-make the look & feel of the browser as per your preferences.
To add Firefox extensions in Selenium using FirefoxProfile, please follow the below-mentioned steps:
Step 1 : Create a Firefox profile. Before doing so, you need to close all the active Firefox windows.
Step 2 : Press “win + R” to open the Run dialog window. Type “firefox.exe -P” and press OK.
Step 3 : Now, click on the Create Profile button.
Step 4 : Click Next.
Step 5 : Enter a name for your new Firefox profile. Copy path to the destination folder (this will be required later). Click Finish to create the profile.
Step 6 : Launch Firefox with your newly created profile.
Step 7 : Add Ghostery Addon to this profile.
Now, let’s write a PyTest script to check if the Ghostery extension is installed when we launch the created Firefox profile in a remotely-controlled Firefox instance using Selenium Python.
Existing Firefox profile can be loaded in Selenium webdriver using:
webdriver.FirefoxProfile("\\path to the new Firefox profile’s folder")
Filename: FFExt_method_2.py
from selenium import webdriver
import time
import pytest
@pytest.fixture
def FFExt2():
# the value you pass to parameter should be the name of folder which represents your target Firefox profile, you created earlier
profile = webdriver.FirefoxProfile("G:\\7m1dwmtw.FFExt")
driver = webdriver.Firefox(profile)
time.sleep(5)
driver.get("about:support")
addons = driver.find_element_by_xpath('//*[contains(text(),"Add-ons") and not(contains(text(),"with"))]')
driver.execute_script("arguments[0].scrollIntoView();", addons)
addons1 = driver.find_elements_by_xpath('//*[contains(text(),"Add-ons") and not(contains(text(),"with"))]/following-sibling::*[1]/*[2]/*/*[1]')
addonsList = []
for addon in addons1:
addonsList.append(addon.text)
time.sleep(10)
driver.quit()
return addonsList
# this is the test function that will assert whether addon is present in the list of installed addons returned by FFExt function.
def test_addon(FFExt2):
ghostery = "Ghostery – Privacy Ad Blocker"
assert ghostery in FFExt2
{"mode":"full","isActive":false}
Run the following command on the terminal to trigger the test:
pytest FFExt_method_2.py
Here is the execution snapshot:
Conclusion:
Extensions, especially VPN extensions, are often required to test how your application would perform across different geographies. Also, if you’ve implemented an adBlocker detection technology in your web application, then you need to install adBlocker extensions to check if your adBlocker detection technology is effective.
In this part of the Selenium Python tutorial, we had a look at two different mechanisms to install addons in Selenium-controlled Firefox instances. Talking of extensions, we hope you already have LambdaTest chrome extension installed to test applications on the go. LambdaTest is a stellar tool for all your Selenium web automation requirements in the cloud. Do check out LT Browser and test applications across 50+ mobile screens.
Happy Testing!