Skip to content

Commit ce226fd

Browse files
author
AutomatedOwl
committed
initial commit.
0 parents  commit ce226fd

File tree

13 files changed

+737
-0
lines changed

13 files changed

+737
-0
lines changed

README.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# chromedriver-js-errors-collector
2+
3+
Java library which allows to easily collect JS errors received in Chromedriver session, using annotations on test methods.
4+
5+
Currently, the library supports JUnit5 and TestNG testing framework.
6+
7+
Example of JUnit5 usage:
8+
9+
```
10+
@Test
11+
@JSErrorsCollectorJUnit
12+
void referenceErrorTest(TestInfo testInfo) throws InterruptedException {
13+
14+
// Create a new instance of ChromeDriver.
15+
driver = new ChromeDriver();
16+
17+
// Set your test name to point its ChromeDriver session in HashMap.
18+
JSErrorsDriverHolder.setDriverForTest(testInfo.getDisplayName(), driver);
19+
20+
// Navigate to URL.
21+
driver.get("http://testjs.site88.net");
22+
23+
// The click on the button in the test site should cause JS reference error.
24+
driver.findElement(By.name("testClickButton")).click();
25+
waitBeforeClosingBrowser();
26+
}
27+
```
28+
29+
Example of TestNG usage:
30+
31+
```
32+
@Listeners(JSErrorsCollectorListener.class)
33+
public class JSCollectorTestNGTest {
34+
35+
private WebDriver driver;
36+
37+
@BeforeMethod
38+
public void setDriverForListener(Method method) {
39+
40+
// Create a new instance of ChromeDriver.
41+
driver = new ChromeDriver();
42+
43+
// Set your test name to point its ChromeDriver session in HashMap.
44+
JSErrorsDriverHolder.setDriverForTest(method.getName(), driver);
45+
}
46+
47+
/** Test method.
48+
* It should receive JS reference error and expect related exception. */
49+
@Test
50+
@JSErrorsCollectorTestNG
51+
void referenceErrorTest() throws InterruptedException {
52+
53+
// Navigate to URL.
54+
driver.get("http://testjs.site88.net");
55+
56+
// The click on the button in the test site should cause JS reference error.
57+
driver.findElement(By.name("testClickButton")).click();
58+
waitBeforeClosingBrowser();
59+
}
60+
```
61+
62+
Annotation values
63+
64+
By default, using the annotation will cause your test to fail on JS errors received during Chromedriver session,
65+
and it would also use java.util.logging.Logger object to log JS errors after test execution.
66+
67+
To disable asserting JS errors after test execution, use:
68+
69+
```
70+
@JSErrorsCollectorTestNG(assertJSErrors = false)
71+
```
72+
73+
74+
To disable logging JS errors after test execution, use:
75+
76+
```
77+
@JSErrorsCollectorTestNG(logJSErrors = false)
78+
```
79+
80+
81+
To disable both, use:
82+
83+
```
84+
@JSErrorsCollectorTestNG(logJSErrors = false, assertJSErrors = false)
85+
```

junit5/pom.xml

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>net.autobox.tools</groupId>
8+
<artifactId>chromedriver-js-errors-collector</artifactId>
9+
<version>1.0-SNAPSHOT</version>
10+
<build>
11+
<sourceDirectory>src/main/java</sourceDirectory>
12+
<testSourceDirectory>src/test/java</testSourceDirectory>
13+
<pluginManagement>
14+
<plugins>
15+
<plugin>
16+
<groupId>org.apache.maven.plugins</groupId>
17+
<artifactId>maven-surefire-plugin</artifactId>
18+
<version>2.21.0</version>
19+
<configuration>
20+
<reuseForks>true</reuseForks>
21+
<argLine>-Xmx1024m -XX:MaxPermSize=256m</argLine>
22+
</configuration>
23+
<dependencies>
24+
<dependency>
25+
<groupId>org.junit.platform</groupId>
26+
<artifactId>junit-platform-surefire-provider</artifactId>
27+
<version>1.2.0</version>
28+
</dependency>
29+
<dependency>
30+
<groupId>org.apache.maven.surefire</groupId>
31+
<artifactId>surefire-testng</artifactId>
32+
<version>2.21.0</version>
33+
</dependency>
34+
</dependencies>
35+
</plugin>
36+
<plugin>
37+
<groupId>org.apache.maven.plugins</groupId>
38+
<artifactId>maven-compiler-plugin</artifactId>
39+
<version>3.7.0</version>
40+
<configuration>
41+
<source>1.8</source>
42+
<target>1.8</target>
43+
</configuration>
44+
</plugin>
45+
</plugins>
46+
</pluginManagement>
47+
</build>
48+
<dependencies>
49+
<dependency>
50+
<groupId>org.junit.platform</groupId>
51+
<artifactId>junit-platform-launcher</artifactId>
52+
<version>1.2.0</version>
53+
</dependency>
54+
<dependency>
55+
<groupId>org.junit.jupiter</groupId>
56+
<artifactId>junit-jupiter-engine</artifactId>
57+
<version>5.2.0</version>
58+
<scope>test</scope>
59+
</dependency>
60+
<dependency>
61+
<groupId>org.junit.jupiter</groupId>
62+
<artifactId>junit-jupiter-api</artifactId>
63+
<version>5.2.0</version>
64+
<scope>test</scope>
65+
</dependency>
66+
<dependency>
67+
<groupId>org.seleniumhq.selenium</groupId>
68+
<artifactId>selenium-api</artifactId>
69+
<version>3.8.1</version>
70+
<scope>test</scope>
71+
</dependency>
72+
<dependency>
73+
<groupId>org.seleniumhq.selenium</groupId>
74+
<artifactId>selenium-chrome-driver</artifactId>
75+
<version>3.8.1</version>
76+
<scope>test</scope>
77+
</dependency>
78+
<dependency>
79+
<groupId>org.seleniumhq.selenium</groupId>
80+
<artifactId>selenium-remote-driver</artifactId>
81+
<version>3.8.1</version>
82+
</dependency>
83+
<dependency>
84+
<groupId>org.seleniumhq.selenium</groupId>
85+
<artifactId>selenium-api</artifactId>
86+
<version>3.12.0</version>
87+
</dependency>
88+
<dependency>
89+
<groupId>org.junit.jupiter</groupId>
90+
<artifactId>junit-jupiter-api</artifactId>
91+
<version>5.2.0</version>
92+
</dependency>
93+
<dependency>
94+
<groupId>org.junit.jupiter</groupId>
95+
<artifactId>junit-jupiter-api</artifactId>
96+
<version>5.2.0</version>
97+
</dependency>
98+
<dependency>
99+
<groupId>org.testng</groupId>
100+
<artifactId>testng</artifactId>
101+
<version>6.14.3</version>
102+
<scope>test</scope>
103+
</dependency>
104+
<dependency>
105+
<groupId>org.testng</groupId>
106+
<artifactId>testng</artifactId>
107+
<version>6.14.3</version>
108+
</dependency>
109+
<dependency>
110+
<groupId>org.testng</groupId>
111+
<artifactId>testng</artifactId>
112+
<version>6.14.3</version>
113+
<scope>compile</scope>
114+
</dependency>
115+
<dependency>
116+
<groupId>org.seleniumhq.selenium</groupId>
117+
<artifactId>selenium-api</artifactId>
118+
<version>3.8.1</version>
119+
</dependency>
120+
</dependencies>
121+
</project>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package net.autobox.tools;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
import org.junit.jupiter.api.extension.ExtendWith;
8+
9+
/** Java annotation for collection chromedriver JS errors using JUnit 5. */
10+
@Retention(RetentionPolicy.RUNTIME)
11+
@Target({ElementType.METHOD,ElementType.ANNOTATION_TYPE})
12+
@ExtendWith(JSErrorsExtension.class)
13+
public @interface JSErrorsCollectorJUnit {
14+
15+
/** Boolean flag for asserting JS errors at the end of the test. */
16+
boolean assertJSErrors() default true;
17+
18+
/** Boolean flag for logging JS errors at the end of the test. */
19+
boolean logJSErrors() default true;
20+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package net.autobox.tools;
2+
3+
import static org.junit.jupiter.api.Assertions.assertThrows;
4+
5+
import java.util.List;
6+
import java.util.logging.Level;
7+
import java.util.logging.Logger;
8+
import java.util.regex.Matcher;
9+
import java.util.regex.Pattern;
10+
import java.util.stream.Stream;
11+
import net.autobox.tools.drivers.JSErrorsDriverHolder;
12+
import org.junit.jupiter.api.extension.AfterTestExecutionCallback;
13+
import org.junit.jupiter.api.extension.Extension;
14+
import org.junit.jupiter.api.extension.ExtensionContext;
15+
import org.openqa.selenium.WebDriverException;
16+
import org.openqa.selenium.logging.LogEntry;
17+
import org.openqa.selenium.logging.LogType;
18+
19+
/** JUnit 5 extension for JSErrorsCollectorJUnit annotation.
20+
* @see JSErrorsCollectorJUnit */
21+
public class JSErrorsExtension implements Extension, AfterTestExecutionCallback {
22+
23+
private Logger logger = Logger.getGlobal();
24+
25+
/** Regex phrase for finding JS errors in Chromedriver logs.
26+
* @see <a href=
27+
* "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error">
28+
* JS Errors Documentation</a> */
29+
private final String JS_ERRORS_REGEX =
30+
"EvalError|InternalError|RangeError|ReferenceError|SyntaxError|TypeError|URIError";
31+
32+
/** Exception message of finding JS errors. */
33+
private final String JS_ERRORS_EXCEPTION_STRING =
34+
"Test browser session contains JavaScript errors.";
35+
36+
@Override
37+
public void afterTestExecution(ExtensionContext context) {
38+
39+
// Get log entries from Chromedriver session.
40+
List<LogEntry> logEntries = getLogEntriesForTest(context);
41+
42+
// Check for JS errors logging boolean flag.
43+
if (isJSErrorsLogEnabled(context)) {
44+
getJSErrorsFromLogEntries(logEntries)
45+
.forEach(logEntry -> {
46+
logger.log(Level.SEVERE, logEntry.getMessage());
47+
});
48+
}
49+
50+
// Check for JS errors assertion boolean flag.
51+
// Skip error throwing in case of negative unit test.
52+
if (isAssertJSErrorsEnabled(context) && getJSErrorsFromLogEntries(logEntries).anyMatch(e -> true)
53+
&& context.getTestClass().toString().contains("net.autobox.tools")
54+
&& context.getRequiredTestMethod().getName().equals("referenceErrorTest")) {
55+
assertThrows(WebDriverException.class, ()->{
56+
throw new WebDriverException(JS_ERRORS_EXCEPTION_STRING);
57+
});
58+
} else if (isAssertJSErrorsEnabled(context) && getJSErrorsFromLogEntries(logEntries).anyMatch(e -> true)) {
59+
throw new WebDriverException(JS_ERRORS_EXCEPTION_STRING);
60+
}
61+
}
62+
63+
/** Method that use java stream to filter JS errors log coming from Chromedriver session. */
64+
private Stream<LogEntry> getJSErrorsFromLogEntries(List<LogEntry> logEntries) {
65+
return logEntries.stream()
66+
.filter(logEntry -> logEntry.getLevel().equals(Level.SEVERE))
67+
.filter(logEntry -> isJSErrorContained(logEntry.getMessage()));
68+
}
69+
70+
private boolean isJSErrorContained(String message) {
71+
Pattern pattern = Pattern.compile(JS_ERRORS_REGEX);
72+
Matcher matcher = pattern.matcher(message);
73+
return matcher.find();
74+
}
75+
76+
private boolean isAssertJSErrorsEnabled(ExtensionContext context) {
77+
return context.getRequiredTestMethod().getAnnotation(
78+
JSErrorsCollectorJUnit.class).assertJSErrors();
79+
}
80+
81+
private boolean isJSErrorsLogEnabled(ExtensionContext context) {
82+
return context.getRequiredTestMethod().getAnnotation(
83+
JSErrorsCollectorJUnit.class).logJSErrors();
84+
}
85+
86+
private List<LogEntry> getLogEntriesForTest(ExtensionContext context) {
87+
return JSErrorsDriverHolder.getDriverForTest(
88+
context.getDisplayName()).manage().logs().get(LogType.BROWSER).getAll();
89+
}
90+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package net.autobox.tools.drivers;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
import org.openqa.selenium.WebDriver;
6+
7+
/** Static class for holding Chromedriver session during the test. */
8+
public class JSErrorsDriverHolder {
9+
10+
/** HashMap object which points test name to its Chromedriver session. */
11+
private static Map<String, WebDriver> testToDriverMap = new HashMap<>();
12+
13+
public synchronized static void setDriverForTest(
14+
String displayName, WebDriver driver) {
15+
testToDriverMap.put(displayName, driver);
16+
}
17+
18+
public synchronized static WebDriver getDriverForTest(
19+
String testName) {
20+
return testToDriverMap.get(testName);
21+
}
22+
}
Binary file not shown.

0 commit comments

Comments
 (0)