-
Notifications
You must be signed in to change notification settings - Fork 16
feat/CUS-9392-Added class Lighthouse Audit and Report Upload to Testsigma Upload Section #288
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughThis PR introduces a new Testsigma addon project that integrates Google Lighthouse audits with Testsigma. The addon orchestrates a Lighthouse audit via PageSpeed API, extracts performance metrics, generates an HTML report through Lighthouse Viewer, and uploads the report to Testsigma. Changes
Sequence Diagram(s)sequenceDiagram
participant User as Testsigma Test
participant Addon as RunLighthouseAuditAndUploadReport
participant PageSpeed as Google PageSpeed API
participant Viewer as Lighthouse Viewer
participant Upload as Testsigma Upload
participant Runtime as Runtime Data
participant FileSystem as File System
User->>Addon: execute()
Addon->>PageSpeed: POST audit request<br/>(target URL + strategy)
activate PageSpeed
PageSpeed-->>Addon: Lighthouse JSON result
deactivate PageSpeed
Addon->>Addon: Parse scores<br/>(performance, accessibility, best-practices)
Addon->>Runtime: Store audit scores
Addon->>FileSystem: Write JSON to temp file
Addon->>Viewer: POST JSON to generate<br/>HTML report
activate Viewer
Viewer-->>Addon: HTML page source
deactivate Viewer
Addon->>FileSystem: Write HTML to temp file
Addon->>Upload: Multipart POST<br/>(HTML report + metadata)
activate Upload
alt Upload Successful
Upload-->>Addon: Success response
Addon-->>User: Result.SUCCESS
else Upload Failed
Upload-->>Addon: Error response
Addon-->>User: Result.FAILED
end
deactivate Upload
Addon->>FileSystem: Cleanup temp files
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Areas requiring extra attention:
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
🧹 Nitpick comments (6)
run_lighthouse_audit_and_upload_report_to_testsigma_uploads/src/main/java/com/testsigma/addons/web/RunLighthouseAuditAndUploadReport.java (4)
74-77: Consider sharing the OkHttpClient instance.Creating a new
OkHttpClientper action instance is wasteful since OkHttp is designed for connection pooling and reuse. For an addon that may be called multiple times, consider making thisstaticor using a singleton pattern.- private final OkHttpClient client = new OkHttpClient.Builder() + private static final OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(Duration.ofSeconds(60)) .readTimeout(Duration.ofSeconds(60)) .build();
122-132: Consider truncating error response body.If the Google API returns a large error response, including the entire body in the exception message could clutter logs. Consider truncating it.
try (Response response = client.newCall(request).execute()) { String body = response.body() != null ? response.body().string() : ""; if (!response.isSuccessful()) { - throw new RuntimeException("Google API error (" + response.code() + "): " + body); + String truncatedBody = body.length() > 500 ? body.substring(0, 500) + "..." : body; + throw new RuntimeException("Google API error (" + response.code() + "): " + truncatedBody); } return new JSONObject(body); }
207-211: Include response body in upload error for debugging.When the upload fails, only the status code is reported. Including the response body would help diagnose issues like authentication failures or validation errors.
try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { - throw new RuntimeException("Upload failed: " + response.code()); + String errorBody = response.body() != null ? response.body().string() : ""; + throw new RuntimeException("Upload failed (" + response.code() + "): " + errorBody); } }
214-220: Specify explicit charset for file writing.
FileWriteruses the platform's default charset, which may vary. Since the content includes JSON and HTML that may contain special characters, explicitly use UTF-8 for consistency.private File writeTempFile(String name, String ext, String content) throws IOException { File file = File.createTempFile(name, ext); - try (FileWriter writer = new FileWriter(file)) { + try (FileWriter writer = new FileWriter(file, StandardCharsets.UTF_8)) { writer.write(content); } return file; }run_lighthouse_audit_and_upload_report_to_testsigma_uploads/pom.xml (2)
18-18: Unused property: remove or utilize.The
testsigma.addon.maven.pluginproperty is defined but never referenced in the build configuration.Apply this diff to remove the unused property:
<maven.source.plugin.version>3.2.1</maven.source.plugin.version> <lombok.version>1.18.30</lombok.version> - - <testsigma.addon.maven.plugin>1.0.0</testsigma.addon.maven.plugin> </properties>
84-96: Consider configuring the Maven Shade Plugin for better dependency management.The Maven Shade Plugin is configured with minimal settings. For production addons, consider adding transformers to merge service files and filters to exclude unnecessary dependencies, which can reduce JAR size and prevent classpath conflicts.
Example configuration:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.2.4</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"/> </transformers> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>META-INF/*.SF</exclude> <exclude>META-INF/*.DSA</exclude> <exclude>META-INF/*.RSA</exclude> </excludes> </filter> </filters> </configuration> </execution> </executions> </plugin>
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
run_lighthouse_audit_and_upload_report_to_testsigma_uploads/pom.xml(1 hunks)run_lighthouse_audit_and_upload_report_to_testsigma_uploads/src/main/java/com/testsigma/addons/web/RunLighthouseAuditAndUploadReport.java(1 hunks)run_lighthouse_audit_and_upload_report_to_testsigma_uploads/src/main/resources/testsigma-sdk.properties(1 hunks)
🧰 Additional context used
🪛 Gitleaks (8.30.0)
run_lighthouse_audit_and_upload_report_to_testsigma_uploads/src/main/resources/testsigma-sdk.properties
[high] 1-1: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.
(jwt)
🪛 OSV Scanner (2.3.0)
run_lighthouse_audit_and_upload_report_to_testsigma_uploads/pom.xml
[HIGH] 1-1: org.json:json 20230227: Java: DoS Vulnerability in JSON-JAVA
[HIGH] 1-1: org.testng:testng 6.14.3: TestNG is vulnerable to Path Traversal
🔇 Additional comments (5)
run_lighthouse_audit_and_upload_report_to_testsigma_uploads/src/main/java/com/testsigma/addons/web/RunLighthouseAuditAndUploadReport.java (3)
23-30: LGTM!The class declaration with
@Dataand@Actionannotations is properly configured. The action text is descriptive and the application type correctly identifies this as a web action.
79-109: LGTM!The
execute()method is well-structured with proper try-catch-finally pattern. Temporary file cleanup in the finally block ensures resources are released even on failure.
151-155: LGTM!Score storage with null-safe runtime data handling is properly implemented.
run_lighthouse_audit_and_upload_report_to_testsigma_uploads/pom.xml (1)
42-46: Security vulnerability: TestNG 6.14.3 has a Path Traversal flaw.TestNG 6.14.3 is over six years old and likely contains known security vulnerabilities. The specific vulnerability referenced (GHSA-rc2q-x9mf-w3vf) requires verification, but upgrading to a more recent TestNG version is strongly recommended.
Upgrade to TestNG 7.5.1 or later to address known security issues.
run_lighthouse_audit_and_upload_report_to_testsigma_uploads/src/main/resources/testsigma-sdk.properties (1)
1-1: Hardcoded JWT in properties file is part of a repository-wide pattern across 180+ addons—requires clarification on credential policy.This JWT token is hardcoded in the properties file, which is packaged into distributions and already visible in the public GitHub repository. However, this is not an isolated issue: every addon in this repository (~180+) follows the identical pattern with different JWT tokens per addon (each with different uniqueIds), suggesting this may be an intentional test credential design rather than accidental exposure.
Before taking action:
- Clarify whether these are intentional test/dummy credentials or production secrets
- Determine if Testsigma has an established credential management policy for community addons
- Decide whether to address this as a repository-wide issue rather than per-addon fixes
If these are test credentials and the pattern is intentional, document that explicitly. If they are real credentials, this requires coordinated remediation across all addons and a policy change for credential handling in future addon development.
| <dependency> | ||
| <groupId>org.junit.jupiter</groupId> | ||
| <artifactId>junit-jupiter-api</artifactId> | ||
| <version>${junit.jupiter.version}</version> | ||
| <scope>test</scope> | ||
| </dependency> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Milestone version of JUnit may cause stability issues.
The junit-jupiter-api dependency uses version 5.8.0-M1, which is a milestone (pre-release) version and may not be suitable for production use.
Apply this diff to use a stable release:
- <junit.jupiter.version>5.8.0-M1</junit.jupiter.version>
+ <junit.jupiter.version>5.10.5</junit.jupiter.version>Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In run_lighthouse_audit_and_upload_report_to_testsigma_uploads/pom.xml around
lines 36 to 41, the junit-jupiter-api dependency is using a milestone
pre-release version (5.8.0-M1); change it to a stable release by updating the
version reference (replace the milestone with a stable version such as 5.8.2 or
another current stable release) and, if the version comes from a property (e.g.
${junit.jupiter.version}), update that property accordingly so the pom
references a non-milestone, supported JUnit 5 release.
| <dependency> | ||
| <groupId>org.seleniumhq.selenium</groupId> | ||
| <artifactId>selenium-java</artifactId> | ||
| <version>4.33.0</version> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update dependencies to latest secure versions.
The project is using significantly outdated dependencies. Selenium should be upgraded from 4.33.0 to at least 4.38.0 (latest as of October 2025). Jackson-annotations 2.13.0 should be upgraded to 2.20 or migrate to Jackson 3.0.0. OkHttp 4.12.0 should be upgraded to address known security patterns in newer versions, with 5.3.0 being the current stable release.
| <dependency> | ||
| <groupId>org.json</groupId> | ||
| <artifactId>json</artifactId> | ||
| <version>20230227</version> | ||
| </dependency> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
find . -name "pom.xml" -type f -exec grep -l "org.json" {} \;Repository: testsigmahq/testsigma-addons
Length of output: 311
Update org.json dependency due to DoS vulnerability
org.json:json version 20230227 contains CVE-2023-5072 (GHSA-rm7j-f5g5-27vv). This vulnerability was fixed in version 20231013. Update to 20250517 or a later stable release.
🤖 Prompt for AI Agents
In run_lighthouse_audit_and_upload_report_to_testsigma_uploads/pom.xml around
lines 69 to 73, the org.json:json dependency is pinned to 20230227 which
contains CVE-2023-5072; update the <version> element to a patched release (at
least 20231013, preferably 20250517 or later) to remediate the DoS
vulnerability, then run mvn -U clean install or update your dependency lock to
ensure the new version is resolved and rebuild to verify no dependency
conflicts.
| private String buildLighthouseApiUrl() { | ||
| String encodedUrl = URLEncoder.encode(targetUrl.getValue().toString(), StandardCharsets.UTF_8); | ||
| String strat = strategy.getValue().toString().toLowerCase(); | ||
|
|
||
| return String.format( | ||
| "https://www.googleapis.com/pagespeedonline/v5/runPagespeed" + | ||
| "?url=%s&strategy=%s&category=performance&category=accessibility&category=best-practices&key=%s", | ||
| encodedUrl, strat, apiKey.getValue().toString() | ||
| ); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
API key may be exposed in logs or error messages.
The Google API key is embedded directly in the URL. If this URL is logged or included in an exception message, the API key could be leaked to logs, monitoring systems, or error reports.
Consider sanitizing the URL before including it in any error messages, or use a more secure method to pass the API key if the PageSpeed API supports it.
private String buildLighthouseApiUrl() {
String encodedUrl = URLEncoder.encode(targetUrl.getValue().toString(), StandardCharsets.UTF_8);
String strat = strategy.getValue().toString().toLowerCase();
- return String.format(
+ String apiKeyValue = apiKey.getValue().toString();
+ if (apiKeyValue == null || apiKeyValue.trim().isEmpty()) {
+ throw new IllegalArgumentException("Google API key is required");
+ }
+ return String.format(
"https://www.googleapis.com/pagespeedonline/v5/runPagespeed" +
"?url=%s&strategy=%s&category=performance&category=accessibility&category=best-practices&key=%s",
- encodedUrl, strat, apiKey.getValue().toString()
+ encodedUrl, strat, apiKeyValue
);
}Additionally, consider wrapping the callGoogleApi call to avoid leaking the key in exception messages:
try {
JSONObject lighthouseJson = callGoogleApi(apiUrl);
} catch (Exception e) {
// Re-throw with sanitized message (no URL containing API key)
throw new RuntimeException("Failed to call Google PageSpeed API: " + e.getMessage());
}🤖 Prompt for AI Agents
In
run_lighthouse_audit_and_upload_report_to_testsigma_uploads/src/main/java/com/testsigma/addons/web/RunLighthouseAuditAndUploadReport.java
around lines 111-120, the constructed URL contains the API key which may be
leaked via logs or exception messages; change the code to stop embedding the key
into any string that might be logged: keep a method that builds the base API URL
without the key for logging/exception contexts and append the key only at the
point of making the HTTP request (preferably passing the key in a non-logged
header or request body if the PageSpeed API supports it, otherwise append it
right before the request and avoid logging the full URL). Also wrap the
callGoogleApi invocation in a try/catch, and rethrow or log only a sanitized
error message that does not include the URL or apiKey value (e.g., "Failed to
call PageSpeed API" + e.getMessage()) so the key never appears in logs or
exception text.
| private Map<String, Integer> extractScores(JSONObject json) { | ||
| JSONObject categories = json | ||
| .getJSONObject("lighthouseResult") | ||
| .getJSONObject("categories"); | ||
|
|
||
| Map<String, Integer> scores = new HashMap<>(); | ||
| scores.put("performance", getScore(categories, "performance")); | ||
| scores.put("accessibility", getScore(categories, "accessibility")); | ||
| scores.put("best-practices", getScore(categories, "best-practices")); | ||
| return scores; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add defensive checks for JSON structure.
The method assumes lighthouseResult and categories keys exist. If the API response structure changes or contains an error object instead, this will throw an unhelpful JSONException.
private Map<String, Integer> extractScores(JSONObject json) {
+ if (!json.has("lighthouseResult")) {
+ throw new RuntimeException("Invalid API response: missing 'lighthouseResult'");
+ }
+ JSONObject lighthouseResult = json.getJSONObject("lighthouseResult");
+ if (!lighthouseResult.has("categories")) {
+ throw new RuntimeException("Invalid API response: missing 'categories'");
+ }
- JSONObject categories = json
- .getJSONObject("lighthouseResult")
- .getJSONObject("categories");
+ JSONObject categories = lighthouseResult.getJSONObject("categories");
Map<String, Integer> scores = new HashMap<>();
scores.put("performance", getScore(categories, "performance"));
scores.put("accessibility", getScore(categories, "accessibility"));
scores.put("best-practices", getScore(categories, "best-practices"));
return scores;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| private Map<String, Integer> extractScores(JSONObject json) { | |
| JSONObject categories = json | |
| .getJSONObject("lighthouseResult") | |
| .getJSONObject("categories"); | |
| Map<String, Integer> scores = new HashMap<>(); | |
| scores.put("performance", getScore(categories, "performance")); | |
| scores.put("accessibility", getScore(categories, "accessibility")); | |
| scores.put("best-practices", getScore(categories, "best-practices")); | |
| return scores; | |
| } | |
| private Map<String, Integer> extractScores(JSONObject json) { | |
| if (!json.has("lighthouseResult")) { | |
| throw new RuntimeException("Invalid API response: missing 'lighthouseResult'"); | |
| } | |
| JSONObject lighthouseResult = json.getJSONObject("lighthouseResult"); | |
| if (!lighthouseResult.has("categories")) { | |
| throw new RuntimeException("Invalid API response: missing 'categories'"); | |
| } | |
| JSONObject categories = lighthouseResult.getJSONObject("categories"); | |
| Map<String, Integer> scores = new HashMap<>(); | |
| scores.put("performance", getScore(categories, "performance")); | |
| scores.put("accessibility", getScore(categories, "accessibility")); | |
| scores.put("best-practices", getScore(categories, "best-practices")); | |
| return scores; | |
| } |
🤖 Prompt for AI Agents
In
run_lighthouse_audit_and_upload_report_to_testsigma_uploads/src/main/java/com/testsigma/addons/web/RunLighthouseAuditAndUploadReport.java
around lines 134 to 144, the method extractScores assumes the JSON contains
"lighthouseResult" and "categories" and will throw JSONException if those keys
are missing or not objects; update the method to defensively check for these
keys (use has/optJSONObject or check for null and instance types), return an
empty map or throw a clear, descriptive exception when the expected structure is
missing, and ensure downstream calls to getScore are only made when categories
is valid (or have getScore handle missing category gracefully); also consider
logging the unexpected JSON shape for debugging.
| new WebDriverWait(driver, Duration.ofSeconds(60)) | ||
| .until(ExpectedConditions.presenceOfElementLocated( | ||
| By.xpath("//div[contains(@class,'lh-report')]"))); | ||
|
|
||
| Thread.sleep(1500); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Replace Thread.sleep with explicit wait condition.
Using Thread.sleep(1500) after the WebDriverWait is a brittle approach. The WebDriverWait already confirms the report element is present. If additional stabilization is needed, use another explicit wait for a specific condition (e.g., waiting for JavaScript to finish or a specific element state).
new WebDriverWait(driver, Duration.ofSeconds(60))
.until(ExpectedConditions.presenceOfElementLocated(
By.xpath("//div[contains(@class,'lh-report')]")));
- Thread.sleep(1500);
+ // Wait for report to fully render
+ new WebDriverWait(driver, Duration.ofSeconds(10))
+ .until(ExpectedConditions.visibilityOfElementLocated(
+ By.xpath("//div[contains(@class,'lh-report')]")));🤖 Prompt for AI Agents
In
run_lighthouse_audit_and_upload_report_to_testsigma_uploads/src/main/java/com/testsigma/addons/web/RunLighthouseAuditAndUploadReport.java
around lines 170-174, remove the Thread.sleep(1500) and replace it with an
explicit wait that ensures the page/report is stabilized (for example, wait
until the report element is visible/interactive or until document.readyState ==
"complete" or until a loading spinner disappears). Use WebDriverWait with an
appropriate ExpectedCondition such as visibilityOfElementLocated,
elementToBeClickable on the lh-report element, or a JavascriptExecutor check for
readyState, and then proceed; do not use Thread.sleep.
Publish this addon as public
Addon Name: Run Lighthouse Audit and Upload Report to Testsigma Uploads
Jarvis Link: https://jarvis.testsigma.com/ui/tenants/3072/addons
Jira : https://testsigma.atlassian.net/browse/CUS-9392
Added class Lighthouse Audit and Report Upload to Testsigma Upload Section
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.