Home » Enterprise Java » TestNG » TestNG Selenium Integration Example

About Ram Mokkapaty

Ram Mokkapaty
Ram holds a master's degree in Machine Design from IT B.H.U. His expertise lies in test driven development and re-factoring. He is passionate about open source technologies and actively blogs on various java and open-source technologies like spring. He works as a principal Engineer in the logistics domain.

TestNG Selenium Integration Example

In this article, I am going to show you an example of TestNG and Selenium integration. Let me first brief you on TestNG and Selenium.

TestNG is an annotation based testing framework which allows you to create configurable test suites where each suite contains one or more tests. A test in turn is composed of one more test classes.

Selenium is used in automating web applications for testing purposes. Unlike HtmlUnit, it uses actual browser to execute its tests.

Let’s start with the setup:

  • Since the example is about TestNG and Selenium integration, we will simplify our setup by using Maven as our build tool.
  • TestNG Maven Project Example will guide you on how to setup a Maven based project and run the TestNG tests.
  • Our examples will be based on Chrome and Firefox, so make sure both are installed in your machine.
  • The browser drivers will be automatically downloaded as a result of the dependencies being added to the maven project file pom.xml.
  • In case of chrome, we also need to download chromedriver.exe. This acts as a bridge between chrome and the driver.
  • I have used Eclipse as the IDE, version Luna 4.4.1.

1. TestNG and Selenium Dependencies

Since our project is dependent on TestNG and selenium, we need to add their dependencies in Maven’s pom.xml file. For TestNG, we need to add org.testng package and for selenium, we need to add org.seleniumhq.selenium. Once saved, it will download Selenium 2.0 java client library and all its dependencies.

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.javacodegeeks.testng.spring</groupId>
	<artifactId>testNGSpring</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<dependencies>
		<dependency>
			<groupId>org.seleniumhq.selenium</groupId>
			<artifactId>selenium-java</artifactId>
			<version>2.45.0</version>
		</dependency>
		<dependency>
			<groupId>org.testng</groupId>
			<artifactId>testng</artifactId>
			<version>6.8.8</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<properties>
		<spring.version>4.1.5.RELEASE</spring.version>
	</properties>
</project>

2. TestNG Selenium Simple Search Example

Selenium provides WebDriver as its API for automating web application testing. WebDriver drives the browser directly using each browser’s built-in support for automation.

In this example, we will use the WebDriver to open google and search for TestNG.

WebDriver is an interface so we still need to an implementation to run the test on an actual browser. We will select the implementation based on the browser used. For example, if we are using firefox, we will use FirefoxDriver. If it is chrome, we will use ChromeDriver. Since ChromeDriver works with Chrome through the chromedriver.exe, we need to make sure that the binary be placed somewhere on your system’s path.

Points to be noted regarding the test class:

  1. In @BeforeSuite method, initDriver(), we create the driver.
  2. searchTestNGInGoogle() is our test method.
  3. We call driver.navigate().to(url) to open the url.
  4. Once the site is open, we need to get a handle on the search field so that we can type in the text to be searched.
  5. When we call driver.findElement(By.name("q")), the WebDriver locates the search field using matching name attribute.
  6. Next, we call element.sendKeys("TestNG") to type in the text “TestNG” in the search field.
  7. The search is submitted on calling element.submit().
  8. Finally, we wait for the results to be returned.
  9. In @AfterSuite method, quitDriver(), we call driver.quit() to close the browser session.

TestNGSeleniumSimpleSearchExample:

package com.javacodegeeks.testng.selenium;

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.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Test;

public class TestNGSeleniumSimpleSearchExample {
	private WebDriver driver;

	@BeforeSuite
	public void initDriver() throws Exception {
		System.out.println("You are testing in firefox");
		driver = new FirefoxDriver();
	}

	@Test
	public void searchTestNGInGoogle() {
		final String searchKey = "TestNG";
		System.out.println("Search " + searchKey + " in google");
		driver.navigate().to("http://www.google.com");
		WebElement element = driver.findElement(By.name("q"));
		System.out.println("Enter " + searchKey);
		element.sendKeys(searchKey);
		System.out.println("submit");
		element.submit();
		(new WebDriverWait(driver, 10)).until(new ExpectedCondition() {
			public Boolean apply(WebDriver d) {
				return d.getTitle().toLowerCase()
						.startsWith(searchKey.toLowerCase());
			}
		});
		System.out.println("Got " + searchKey + " results");
	}

	@AfterSuite
	public void quitDriver() throws Exception {
		driver.quit();
	}
}

testngSimpleSearch.xml:

<?xml version="1.0" encoding="UTF-8"?>
<suite name="TestNgSeleniumSuite" parallel="false">
	<test name="TestNgSeleniumTest">
		<classes>
			<class
				name="com.javacodegeeks.testng.selenium.TestNGSeleniumSimpleSearchExample" />
		</classes>
	</test>
</suite>

Output:

[TestNG] Running:
  C:\javacodegeeks_ws\testNGSelenium\src\test\resources\com\javacodegeeks\testng\selenium\testngSimpleSearch.xml

You are testing in firefox
Search TestNG in google
Enter TestNG
submit
Got TestNG results

===============================================
TestNgSeleniumSuite
Total tests run: 1, Failures: 0, Skips: 0
===============================================

3. WebDriver Injection using spring

Instead of creating the WebDriver ourselves, we can inject the implementation using the spring’s dependency injection. Here we will modify our previous example by using spring to inject the driver.

Since we are going to rely on spring, we need to add spring-context and spring-test to our dependencies in pom.xml.

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.javacodegeeks.testng.spring</groupId>
	<artifactId>testNGSpring</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<dependencies>
		<dependency>
			<groupId>org.seleniumhq.selenium</groupId>
			<artifactId>selenium-java</artifactId>
			<version>2.45.0</version>
		</dependency>
		<dependency>
			<groupId>org.testng</groupId>
			<artifactId>testng</artifactId>
			<version>6.8.8</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>${spring.version}</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<properties>
		<spring.version>4.1.5.RELEASE</spring.version>
	</properties>
</project>

The below context file contains the driver bean definition. The class attribute points to org.openqa.selenium.firefox.FirefoxDriver.

driver_context.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
				http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
	<bean id="driver" class="org.openqa.selenium.firefox.FirefoxDriver" />
</beans>

The below test class, does exactly what the previous one did, the only change is that the driver is injected through spring’s annotation @ContextConfiguration. Its value contains the location path to the context file driver_context.xml. The driver member is anootated with @Autowired so that the spring can inject the implementation.

Since we are going to rely on TestNG-spring integration framework, test class TestNGSeleniumDriverInjectionExample extends AbstractTestNGSpringContextTests.

TestNGSeleniumDriverInjectionExample:

package com.javacodegeeks.testng.selenium;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;


@ContextConfiguration("driver_context.xml")
public class TestNGSeleniumDriverInjectionExample extends AbstractTestNGSpringContextTests {
	@Autowired
	private WebDriver driver;
	
	@BeforeClass
	public void printBrowserUsed() {
		System.out.println("Driver used is: " + driver);
	}

	@Test
	public void searchTestNGInGoogle() {
		final String searchKey = "TestNG";
		System.out.println("Search " + searchKey + " in google");
		driver.navigate().to("http://www.google.com");
		WebElement element = driver.findElement(By.name("q"));
		System.out.println("Enter " + searchKey);
		element.sendKeys(searchKey);
		System.out.println("submit");
		element.submit();
		(new WebDriverWait(driver, 10)).until(new ExpectedCondition() {
			public Boolean apply(WebDriver d) {
				return d.getTitle().toLowerCase()
						.startsWith(searchKey.toLowerCase());
			}
		});
		System.out.println("Got " + searchKey + " results");
	}

	@AfterSuite
	public void quitDriver() throws Exception {
		driver.quit();
	}
}

testngDriverInjection.xml:

<?xml version="1.0" encoding="UTF-8"?>
<suite name="TestNgSeleniumSuite" parallel="false">
	<test name="TestNgSeleniumTest">
		<classes>
			<class
				name="com.javacodegeeks.testng.selenium.TestNGSeleniumDriverInjectionExample" />
		</classes>
	</test>
</suite>

Output:

[TestNG] Running:
  C:\javacodegeeks_ws\testNGSelenium\src\test\resources\com\javacodegeeks\testng\selenium\testngDriverInjection.xml

Driver used is: FirefoxDriver: firefox on WINDOWS (441cda6b-9e73-4594-b4e8-7134a1623c7d)
Search TestNG in google
Enter TestNG
submit
Got TestNG results

===============================================
TestNgSeleniumSuite
Total tests run: 1, Failures: 0, Skips: 0
===============================================

4. TestNG Selenium Data-Driven Testing Example

Suppose we want to do multiple searches in google by using our search method, we would want to pass in different search strings each time we call the method. In this example, I will demonstrate data-driven testing to do multiple searches in google.

We will modify our example further and introduce a parameter to our search method. Since we will be searching multiple times, we will keep the search method name generic, call it searchGoogle(). We will provide the data using a @DataProvider method called searchStrings() which returns “TestNG” and “Selenium” as the search keywords. The @Test annotation is modified to include searchGoogle as the dataProvider.

TestNGSeleniumDataDrivenSearchExample:

package com.javacodegeeks.testng.selenium;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

@ContextConfiguration("driver_context.xml")
public class TestNGSeleniumDataDrivenSearchExample extends
		AbstractTestNGSpringContextTests {
	private WebDriver driver;

	@BeforeClass
	public void printBrowserUsed() {
		System.out.println("Driver used is: " + driver);
	}

	@Test(dataProvider = "searchStrings")
	public void searchGoogle(final String searchKey) {
		System.out.println("Search " + searchKey + " in google");
		driver.navigate().to("http://www.google.com");
		WebElement element = driver.findElement(By.name("q"));
		System.out.println("Enter " + searchKey);
		element.sendKeys(searchKey);
		System.out.println("submit");
		element.submit();
		(new WebDriverWait(driver, 10)).until(new ExpectedCondition() {
			public Boolean apply(WebDriver d) {
				return d.getTitle().toLowerCase()
						.startsWith(searchKey.toLowerCase());
			}
		});
		System.out.println("Got " + searchKey + " results");
	}

	@DataProvider
	private Object[][] searchStrings() {
		return new Object[][] { { "TestNG" }, { "Selenium" } };
	}

	@AfterSuite
	public void quitDriver() throws Exception {
		driver.quit();
	}
}

testngDataDrivenSearch.xml:

<?xml version="1.0" encoding="UTF-8"?>
<suite name="TestNgSeleniumSuite" parallel="false">
	<parameter name="browser" value="chrome"></parameter>
	<parameter name="driverPath" value="c://selenium/chromedriver.exe"></parameter>
	<test name="TestNgSeleniumTest">
		<classes>
			<class
				name="com.javacodegeeks.testng.selenium.TestNGSeleniumDataDrivenSearchExample" />
		</classes>
	</test>
</suite>

Now when we run the test, it runs twice, once for “TestNG” and then for “Selenium”.

Output:

[TestNG] Running:
  C:\javacodegeeks_ws\testNGSelenium\src\test\resources\com\javacodegeeks\testng\selenium\testngDataDrivenSearch.xml

Driver used is: FirefoxDriver: firefox on WINDOWS (ab3f6869-6669-4ccf-8e8f-9479f35aa790)
Search TestNG in google
Enter TestNG
submit
Got TestNG results
Search Selenium in google
Enter Selenium
submit
Got Selenium results

===============================================
TestNgSeleniumSuite
Total tests run: 2, Failures: 0, Skips: 0
===============================================

5. TestNG Selenium Multiple Browser Example

Now suppose, we want to run our test on multiple browsers, all we need to do is parameterize our initDriver() method and pass it the name of the browser on which we want to run our test.

Based on the browser, we will create either ChromeDriver or FirefixDriver. We will pass the browser name through testng.xml.

TestNGSeleniumBrowserCfgExample:

package com.javacodegeeks.testng.selenium;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Optional;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

public class TestNGSeleniumBrowserCfgExample {
	private WebDriver driver;	

	@Parameters({"browser", "driverPath"})
	@BeforeTest
	public void initDriver(String browser, @Optional("") String driverPath) throws Exception {
		System.out.println("You are testing on browser " + browser);
		browser = browser.toLowerCase();
		if (!driverPath.equals("")) {
			System.setProperty("webdriver.chrome.driver", driverPath);
		}
		if (browser.equals("chrome")) {			
			driver = new ChromeDriver();
		} else if (browser.equals("firefox")) {
			driver = new FirefoxDriver();
		} else {
			throw new RuntimeException("Please create a driver for " + browser);
		}
	}

	@Test(dataProvider = "searchStrings")
	public void searchGoogle(final String searchKey) {
		System.out.println("Search " + searchKey + " in google");
		driver.navigate().to("http://www.google.com");		
		WebElement element = driver.findElement(By.name("q"));
		System.out.println("Enter " + searchKey);
		element.sendKeys(searchKey);
		System.out.println("submit");
		element.submit();
		 (new WebDriverWait(driver, 10)).until(new ExpectedCondition() {
	            public Boolean apply(WebDriver d) {
	                return d.getTitle().toLowerCase().startsWith(searchKey.toLowerCase());
	            }
	        });
		System.out.println("Got " + searchKey + " results");
	}

	@DataProvider
	private Object[][] searchStrings() {
		return new Object[][] { { "TestNG" }, { "Selenium" } };
	}

	@AfterTest
	public void quitDriver() throws Exception {
		driver.quit();
	}	
}

testng.xml will have two tests and both the tests will run the same test class. We want TestNgSeleniumChromeTest to run on a chrome browser so we have set the browser parameter to chrome. Likewise, we want TestNgSeleniumFirefoxTest to run on a firefox browser so the browser is set to value firefox.

testngBrowserConfigurable.xml:

<?xml version="1.0" encoding="UTF-8"?>
<suite name="TestNgSeleniumSuite" parallel="false">
	<test name="TestNgSeleniumChromeTest">
		<parameter name="browser" value="chrome"></parameter>
		<parameter name="driverPath" value="c://selenium/chromedriver.exe"></parameter>
		<classes>
			<class
				name="com.javacodegeeks.testng.selenium.TestNGSeleniumBrowserCfgExample" />
		</classes>
	</test>

	<test name="TestNgSeleniumFirefoxTest">
		<parameter name="browser" value="firefox"></parameter>
		<classes>
			<class
				name="com.javacodegeeks.testng.selenium.TestNGSeleniumBrowserCfgExample" />
		</classes>
	</test>
</suite>

As you can see below, the test runs for both the browsers.

Output:

[TestNG] Running:
  C:\javacodegeeks_ws\testNGSelenium\src\test\resources\com\javacodegeeks\testng\spring\testngBrowserConfigurable.xml

You are testing on browser chrome
Starting ChromeDriver 2.14.313457 (3d645c400edf2e2c500566c9aa096063e707c9cf) on port 7342
Only local connections are allowed.
Search TestNG in google
Enter TestNG
submit
Got TestNG results
Search Selenium in google
Enter Selenium
submit
Got Selenium results
You are testing on browser firefox
Search TestNG in google
Enter TestNG
submit
Got TestNG results
Search Selenium in google
Enter Selenium
submit
Got Selenium results

===============================================
TestNgSeleniumSuite
Total tests run: 4, Failures: 0, Skips: 0
===============================================

6. TestNG Selenium dependency based tests

Suppose you want to run some tests only after a page is loaded, you can make sure this happens by making the tests depend on the method that is responsible for loading the page.

In the below example, we open http://examples.javacodegeeks.com/ and then search for TestNG articles. Once the page is loaded, we search for article called ‘TestNG Maven Project Example’ and click on it.

There are two aspects to this scenario, the first one deals with searching TestNG articles and the second one, which is about clicking an article from the search results comes into picture only after the search results are returned.

In the below class, test clickOnJCGTestNGArticle() is about clicking on ‘TestNG Maven Project Example’ article whereas searchTestNGInJCG() is about searching TestNG in Java Code Geeks. Since clickOnJCGTestNGArticle() depends on test searchTestNGInJCG(), we modify @Test annotation and set the dependsOnMethod attribute to searchTestNGInJCG.

TestNGSeleniumDependentMethodExample:

package com.javacodegeeks.testng.selenium;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;


@ContextConfiguration("driver_context.xml")
public class TestNGSeleniumDependentMethodExample extends AbstractTestNGSpringContextTests {
	@Autowired
	private WebDriver driver;

	@BeforeClass
	public void printBrowserUsed() {
		System.out.println("Driver used is: " + driver);
	}
	
	@Test(dependsOnMethods="searchTestNGInJCG")
	public void clickOnJCGTestNGArticle() {
		System.out.println("You are in page " + driver.getTitle());
		(new WebDriverWait(driver, 10)).until(new ExpectedCondition() {
			public Boolean apply(WebDriver d) {
				WebElement link = driver.findElement(By.linkText("TestNG Maven Project Example"));
				if (link != null) {
					System.out.println("Going to click on '" + link.getText() + "'");
					link.click();
				}
				return link != null;
			}
		});
		assertPageTitle("TestNG Maven Project Example");
	}

	@Test
	public void searchTestNGInJCG() {
		final String searchKey = "TestNG";
		System.out.println("Search " + searchKey + " in JCG");
		driver.navigate().to("http://examples.javacodegeeks.com/");
		(new WebDriverWait(driver, 10)).until(new ExpectedCondition() {
			public Boolean apply(WebDriver d) {
				WebElement popup = d.findElement(By.linkText("Close this popup"));
				if (popup != null) {
					System.out.println("Found popup, close it");
					popup.click();
				}
				return popup != null;
			}
		});
		WebElement element = driver.findElement(By.name("s"));
		System.out.println("Enter " + searchKey);
		element.sendKeys(searchKey);
		System.out.println("submit");		
		element.submit();
		assertPageTitle("You searched for " + searchKey);
		System.out.println("Got " + searchKey + " results");
	}
	
	private void assertPageTitle(final String title) {
		(new WebDriverWait(driver, 10)).until(new ExpectedCondition() {
			public Boolean apply(WebDriver d) {
				System.out.println("TITLE: " + d.getTitle());
				return d.getTitle().toLowerCase()
						.startsWith(title.toLowerCase());
			}
		});
	}

	@AfterSuite
	public void quitDriver() throws Exception {
		driver.quit();
	}
}

testngDependencyTests.xml:

<?xml version="1.0" encoding="UTF-8"?>
<suite name="TestNgSeleniumSuite" parallel="false">
	<test name="TestNgSeleniumTest">
		<classes>
			<class
				name="com.javacodegeeks.testng.selenium.TestNGSeleniumDependentMethodExample" />
		</classes>
	</test>
</suite>

From the below output, you can see ‘TestNG’ articles are searched first and then article ‘TestNG Maven Project Example’ is clicked upon.

Output:

[TestNG] Running:
  C:\javacodegeeks_ws\testNGSelenium\src\test\resources\com\javacodegeeks\testng\selenium\testngDependencyTests.xml

Driver used is: FirefoxDriver: firefox on WINDOWS (07d0226b-8d03-4ec1-8a62-fb7ae09546be)
Search TestNG in JCG
Found popup, close it
Enter TestNG
submit
TITLE: You searched for TestNG | Examples Java Code Geeks
Got TestNG results
You are in page You searched for TestNG | Examples Java Code Geeks
Going to click on 'TestNG Maven Project Example'
TITLE: TestNG Maven Project Example | Examples Java Code Geeks

===============================================
TestNgSeleniumSuite
Total tests run: 2, Failures: 0, Skips: 0
===============================================

Download the Eclipse Project

In this article, I have shown you some examples of TestNG and Selenium integration.

Download
You can download the full source code of this example here: testNGSelenium.zip
(No Ratings Yet)
2 Comments Views Tweet it!

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you our best selling eBooks for FREE!

 

1. JPA Mini Book

2. JVM Troubleshooting Guide

3. JUnit Tutorial for Unit Testing

4. Java Annotations Tutorial

5. Java Interview Questions

6. Spring Interview Questions

7. Android UI Design

 

and many more ....

 

Receive Java & Developer job alerts in your Area

 

2
Leave a Reply

avatar
1 Comment threads
1 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
2 Comment authors
Ngoc Mai Lepradeep Recent comment authors
  Subscribe  
newest oldest most voted
Notify of
pradeep
Guest
pradeep

Worked well with Chrome but not Firefox. It looks not compatible with Firefox version 56.0(64-bit). Which version of Firefox should be used?

Ngoc Mai Le
Guest
Ngoc Mai Le

It works well if you have version 47.0.1 of Firefox