-
Notifications
You must be signed in to change notification settings - Fork 16
[Cus-8162] Addon for iterating list and bulk check box actions. #246
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
WalkthroughIntroduces two new addon modules: Changes
Sequence Diagram(s)sequenceDiagram
participant Action as CheckAllCheckboxes<br/>(Android/iOS/Web)
participant CheckboxActions as CheckboxActions<br/>(Utility)
participant Driver as WebDriver<br/>(Platform-specific)
participant Element as WebElement<br/>(Checkbox)
Action->>CheckboxActions: checkAllEnabledCheckboxes(driver, logger)
CheckboxActions->>CheckboxActions: getPlatformType(driver)
CheckboxActions->>CheckboxActions: findCheckboxes(driver, platform-xpath)
loop For each checkbox element
CheckboxActions->>Element: isEnabled()?
alt Not Enabled
CheckboxActions->>CheckboxActions: Log: Skip disabled
else Enabled
CheckboxActions->>CheckboxActions: getCheckboxInfo(element)
CheckboxActions->>Element: isSelected()?
alt Not Selected (need to check)
CheckboxActions->>Element: click()
CheckboxActions->>CheckboxActions: Log: Checked
end
end
end
CheckboxActions->>CheckboxActions: Log: Summary (processed, skipped)
CheckboxActions->>Action: Return success
Action->>Action: setSuccessMessage()
Action->>Action: Return Result.SUCCESS
sequenceDiagram
participant Action as FetchCheckboxLabelAndStore<br/>(Android/iOS/Web)
participant Fetcher as CheckBoxLabelFetcher<br/>(Utility)
participant Driver as WebDriver<br/>(Platform-specific)
participant Element as WebElement<br/>(Checkbox)
Action->>Fetcher: getAllCheckboxLabels(driver, logger)
Fetcher->>Fetcher: getPlatformType(driver)
Fetcher->>Fetcher: findCheckboxes(driver, platform-xpath)
loop For each checkbox element
Fetcher->>Fetcher: extractLabel(element, platform)
alt Platform: Android
Fetcher->>Element: getAttribute("text")?
alt text exists
Fetcher->>Fetcher: Add to labels
else try content-desc
Fetcher->>Element: getAttribute("content-desc")
end
else Platform: iOS
Fetcher->>Element: getAttribute("label") / getAttribute("name")
else Platform: Web
Fetcher->>Element: Find ancestor label or label-for
end
end
Fetcher->>Fetcher: Join labels: comma-separated string
Fetcher->>Action: Return labels
Action->>Action: Create RunTimeData(variable_name, labels)
Action->>Action: setSuccessMessage()
Action->>Action: Return Result.SUCCESS
sequenceDiagram
participant Action as WhileLoopStringBySeparator<br/>(Any Platform)
participant Provider as RunTimeDataProvider
participant RTData as RunTimeData
Action->>Action: Read SEPARATOR, TEST-DATA, RUNTIME-VARIABLE
Action->>Action: Build index_key = RUNTIME-VARIABLE + "_TSIndex"
Action->>Provider: Get current index from index_key
alt Index not found
Action->>Action: Set current_index = 0
else Index found
Action->>Action: Set current_index = retrieved_index
end
Action->>Action: Split TEST-DATA by SEPARATOR
Action->>Action: Check: current_index < split_values.length?
alt Index out of bounds
Action->>Action: Log: No more values
Action->>Action: setErrorMessage("End of data")
Action->>Action: Return Result.FAILED
else Index valid
Action->>Action: current_value = split_values[current_index].trim()
Action->>RTData: Store(RUNTIME-VARIABLE, current_value)
Action->>Action: next_index = current_index + 1
Action->>RTData: Store(index_key, next_index)
Action->>Action: setSuccessMessage()
Action->>Action: Return Result.SUCCESS
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Warning Review ran into problems🔥 ProblemsGit: Failed to clone repository. Please run the 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: 14
🧹 Nitpick comments (24)
list_data_structure_actions/pom.xml (3)
74-86: Minimize shaded jar to reduce bloat and conflictsEnable minimizeJar and keep dependency-reduced-pom disabled (common for add-ons).
<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> + <createDependencyReducedPom>false</createDependencyReducedPom> + <minimizeJar>true</minimizeJar> + </configuration> </execution> </executions> </plugin>
18-18: Remove unused property or wire in the plugintestsigma.addon.maven.plugin is defined but unused. Either remove to avoid drift or use it.
- <testsigma.addon.maven.plugin>1.0.0</testsigma.addon.maven.plugin>
47-58: ---Versions verified as compatible; consider promoting to properties for consistency
Confirmed: org.seleniumhq.selenium:selenium-java 4.33.0 is published on Maven Central and compatible with io.appium:java-client 9.4.0 (Appium supports 4.26.0–4.33.0). Note: 4.37.0 is the latest stable 4.x, but your version is stable and within the compatibility range. Refactor to use Maven properties for easier version management and consistency across dependencies.
checkbox_actions/src/main/java/com/testsigma/addons/web/UnCheckAllCheckboxes.java (2)
14-16: Clarify action to “enabled checkboxes” and use error-level logging on failuresKeep user expectations aligned with behavior, and log failures at error level.
-@Action(actionText = "Uncheck all the checkboxes in the current page", - description = "Uncheck all the checkboxes in the current page", +@Action(actionText = "Uncheck all enabled checkboxes on the current page", + description = "Unchecks every enabled checkbox on the current page; disabled checkboxes are skipped", applicationType = ApplicationType.WEB) @@ - } catch (Exception e) { - setErrorMessage("An error occurred while unchecking all the checkboxes in the current page: " + e.getMessage()); - logger.info("An error occurred while unchecking all the checkboxes in the current page: " + ExceptionUtils.getStackTrace(e)); + } catch (Exception e) { + setErrorMessage("An error occurred while unchecking all the checkboxes in the current page: " + e.getMessage()); + logger.error("An error occurred while unchecking all the checkboxes in the current page: " + ExceptionUtils.getStackTrace(e)); return Result.FAILED; }Also applies to: 26-29, 22-25
17-17: Naming consistency: prefer “UncheckAllCheckboxes”Class name uses “UnCheck…”. Consider renaming to “UncheckAllCheckboxes” to match action text and other classes.
Please confirm if other modules use “Uncheck” vs “UnCheck”; we can submit a follow-up rename PR across platforms if desired.
checkbox_actions/src/main/java/com/testsigma/addons/android/CheckAllCheckboxes.java (1)
14-16: Tighten logging, types, and wordingUse error level on failures, prefer generics, and clarify action scope.
-@Action(actionText = "Check all the checkboxes in the current page", - description = "Check all the checkboxes in the current page", +@Action(actionText = "Check all enabled checkboxes on the current page", + description = "Checks every enabled checkbox on the current page; disabled checkboxes are skipped", applicationType = ApplicationType.ANDROID) @@ - AndroidDriver androidDriver = (AndroidDriver) this.driver; + AndroidDriver<?> androidDriver = (AndroidDriver<?>) this.driver; new CheckboxActions().checkAllEnabledCheckboxes(androidDriver, logger); @@ - logger.info("Error in CheckAllCheckboxes Android action: " + ExceptionUtils.getStackTrace(e)); + logger.error("Error in CheckAllCheckboxes Android action: " + ExceptionUtils.getStackTrace(e)); return Result.FAILED;Also applies to: 28-33, 23-25
checkbox_actions/src/main/java/com/testsigma/addons/ios/UnCheckAllCheckboxes.java (2)
14-16: Clarify wording and improve logging and typingAlign text with behavior, use error-level logging, and adopt generics.
-@Action(actionText = "Uncheck all the checkboxes in the current page", - description = "Uncheck all the checkboxes in the current page", +@Action(actionText = "Uncheck all enabled checkboxes on the current page", + description = "Unchecks every enabled checkbox on the current page; disabled checkboxes are skipped", applicationType = ApplicationType.IOS) @@ - IOSDriver iosDriver = (IOSDriver) this.driver; + IOSDriver<?> iosDriver = (IOSDriver<?>) this.driver; new CheckboxActions().unCheckAllEnabledCheckboxes(iosDriver, logger); @@ - logger.info("Error in UnCheckAllCheckboxes iOS action: " + ExceptionUtils.getStackTrace(e)); + logger.error("Error in UnCheckAllCheckboxes iOS action: " + ExceptionUtils.getStackTrace(e)); return Result.FAILED;Also applies to: 28-33, 23-26
17-17: Naming consistency: prefer “UncheckAllCheckboxes”Consider renaming class to “UncheckAllCheckboxes” for consistency.
checkbox_actions/src/main/java/com/testsigma/addons/web/CheckAllCheckboxes.java (1)
14-16: Clarify action scope and log failures at error levelMatch behavior (enabled only) and improve failure visibility.
-@Action(actionText = "Check all the checkboxes in the current page", - description = "Check all the checkboxes in the current page", +@Action(actionText = "Check all enabled checkboxes on the current page", + description = "Checks every enabled checkbox on the current page; disabled checkboxes are skipped", applicationType = ApplicationType.WEB) @@ - logger.info("Error in CheckAllCheckboxes Web action: " + ExceptionUtils.getStackTrace(e)); + logger.error("Error in CheckAllCheckboxes Web action: " + ExceptionUtils.getStackTrace(e)); return Result.FAILED;Also applies to: 26-31
checkbox_actions/src/main/java/com/testsigma/addons/android/UnCheckAllCheckboxes.java (2)
13-18: Avoid Lombok @DaTa here and consider consistent naming.This action has no own fields; @DaTa adds noisy toString/equals/hashCode. Also, consider renaming class to UncheckAllCheckboxes (lowercase “c”) to match the action text and typical naming.
21-33: Drop the AndroidDriver cast; pass WebDriver directly and improve error log level.CheckboxActions works with WebDriver and detects platform. Casting is redundant and can fail in mixed contexts. Also prefer error-level logging if Logger supports it.
- AndroidDriver androidDriver = (AndroidDriver) this.driver; - new CheckboxActions().unCheckAllEnabledCheckboxes(androidDriver, logger); + new CheckboxActions().unCheckAllEnabledCheckboxes(driver, logger); - logger.info("Error in UnCheckAllCheckboxes Android action: " + ExceptionUtils.getStackTrace(e)); + logger.info("Error in UnCheckAllCheckboxes Android action: " + ExceptionUtils.getStackTrace(e)); // consider logger.errorcheckbox_actions/src/main/java/com/testsigma/addons/ios/CheckAllCheckboxes.java (2)
13-18: Remove Lombok @DaTa; it’s unnecessary here.No fields on this class; @DaTa generates unused methods and noisy toString.
21-33: Avoid IOSDriver cast; delegate with WebDriver.Let CheckboxActions detect platform; also consider error-level logging for failures.
- IOSDriver iosDriver = (IOSDriver) this.driver; - new CheckboxActions().checkAllEnabledCheckboxes(iosDriver, logger); + new CheckboxActions().checkAllEnabledCheckboxes(driver, logger); - logger.info("Error in CheckAllCheckboxes iOS action: " + ExceptionUtils.getStackTrace(e)); + logger.info("Error in CheckAllCheckboxes iOS action: " + ExceptionUtils.getStackTrace(e)); // consider logger.errorcheckbox_actions/src/main/java/com/testsigma/addons/utils/CheckBoxLabelFetcher.java (3)
10-12: Deduplicate labels while preserving order.Prevent repeated labels by using a LinkedHashSet, then join once.
-import java.util.List; -import java.util.StringJoiner; +import java.util.List; +import java.util.LinkedHashSet; +import java.util.Set; @@ - StringJoiner labels = new StringJoiner(", "); - int processedCount = 0; + Set<String> labels = new LinkedHashSet<>(); + int processedCount = 0; @@ - String result = labels.toString(); + String result = String.join(", ", labels);Also applies to: 28-31, 49-51
143-164: Add web aria fallbacks for unlabeled inputs.Handle accessible naming when no association exists.
// Fallback to <label for="id"> association if ancestor label not found if (labelText.isEmpty()) { String id = checkbox.getAttribute("id"); if (id != null && !id.isEmpty()) { try { WebElement label = driver.findElement(By.xpath("//label[@for='" + id + "']")); labelText = label.getText().trim(); } catch (Exception ignored) { } } } + + // aria-label fallback + if (labelText.isEmpty()) { + String aria = checkbox.getAttribute("aria-label"); + if (aria != null && !aria.trim().isEmpty()) { + labelText = aria.trim(); + } + } + + // aria-labelledby fallback (first id) + if (labelText.isEmpty()) { + String labelledBy = checkbox.getAttribute("aria-labelledby"); + if (labelledBy != null && !labelledBy.trim().isEmpty()) { + String firstId = labelledBy.trim().split("\\s+")[0]; + try { + WebElement lbl = driver.findElement(By.id(firstId)); + labelText = lbl.getText().trim(); + } catch (Exception ignored) { } + } + }
69-81: Tighten iOS locators and avoid unlikely @type filter.The filter [@type='XCUIElementTypeButton'] is unusual; prefer class-based axes.
- return driver.findElements(By.xpath("//XCUIElementTypeSwitch | //XCUIElementTypeButton[@type='XCUIElementTypeButton'] | //input[@type='checkbox']")); + return driver.findElements(By.xpath("//XCUIElementTypeSwitch | //XCUIElementTypeButton | //input[@type='checkbox']"));Also consider that iOS “value” typically represents checked state (1/0) rather than a label; using it as a label is a last resort only.
Also applies to: 121-141
checkbox_actions/src/main/java/com/testsigma/addons/android/FetchCheckboxLabelAndStore.java (2)
16-18: Fix typo in user-facing text: “comma separated”.-@Action(actionText = "Fetch all checkboxes on the page and store the label in runtime variable runtime-variable in comma seperated format", - description = "Fetch all checkboxes on the page and store the label in runtime variable runtime-variable in comma seperated format", +@Action(actionText = "Fetch all checkboxes on the page and store the label in runtime variable runtime-variable in comma separated format", + description = "Fetch all checkboxes on the page and store the label in runtime variable runtime-variable in comma separated format", applicationType = ApplicationType.ANDROID)
33-35: Remove AndroidDriver cast; pass WebDriver.Fetcher accepts WebDriver and detects platform.
- AndroidDriver androidDriver = (AndroidDriver) this.driver; - String labels = new CheckBoxLabelFetcher().getAllCheckboxLabels(androidDriver, logger); + String labels = new CheckBoxLabelFetcher().getAllCheckboxLabels(driver, logger);checkbox_actions/src/main/java/com/testsigma/addons/web/FetchCheckboxLabelAndStore.java (1)
15-17: Correct “comma separated” typo in action text/description.-@Action(actionText = "Fetch all checkboxes on the page and store the label in runtime variable runtime-variable in comma seperated format", - description = "Fetch all checkboxes on the page and store the label in runtime variable runtime-variable in comma seperated format", +@Action(actionText = "Fetch all checkboxes on the page and store the label in runtime variable runtime-variable in comma separated format", + description = "Fetch all checkboxes on the page and store the label in runtime variable runtime-variable in comma separated format", applicationType = ApplicationType.WEB)checkbox_actions/src/main/java/com/testsigma/addons/ios/FetchCheckboxLabelAndStore.java (2)
16-18: Fix “comma separated” spelling.-@Action(actionText = "Fetch all checkboxes on the page and store the label in runtime variable runtime-variable in comma seperated format", - description = "Fetch all checkboxes on the page and store the label in runtime variable runtime-variable in comma seperated format", +@Action(actionText = "Fetch all checkboxes on the page and store the label in runtime variable runtime-variable in comma separated format", + description = "Fetch all checkboxes on the page and store the label in runtime variable runtime-variable in comma separated format", applicationType = ApplicationType.IOS)
33-35: Remove IOSDriver cast; use WebDriver.- IOSDriver iosDriver = (IOSDriver) this.driver; - String labels = new CheckBoxLabelFetcher().getAllCheckboxLabels(iosDriver, logger); + String labels = new CheckBoxLabelFetcher().getAllCheckboxLabels(driver, logger);checkbox_actions/src/main/java/com/testsigma/addons/utils/CheckboxActions.java (1)
89-92: Simplify iOS checkbox locator; drop unlikely @type filter.- return driver.findElements(By.xpath("//XCUIElementTypeSwitch | //XCUIElementTypeButton[@type='XCUIElementTypeButton'] | //input[@type='checkbox']")); + return driver.findElements(By.xpath("//XCUIElementTypeSwitch | //XCUIElementTypeButton | //input[@type='checkbox']"));checkbox_actions/pom.xml (2)
59-63: Update jackson-annotations to a recent stable version.jackson-annotations 2.13.0 is from 2021 and outdated. Consider updating to 2.17.x or 2.18.x to include security patches and improvements.
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> - <version>2.13.0</version> + <version>2.17.0</version> </dependency>
74-86: Consider configuring shade plugin to exclude or relocate common transitive dependencies.The maven-shade-plugin is configured without exclusions or relocation rules. This may cause classpath conflicts if consumers already have dependencies like commons-lang3, jackson, or lombok. Consider adding
<configuration>with<transformers>and/or<filters>to prevent shadowing critical transitive deps, or use relocation to avoid conflicts.For example:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.2.4</version> + <configuration> + <filters> + <filter> + <artifact>*:*</artifact> + <excludes> + <exclude>META-INF/**</exclude> + </excludes> + </filter> + </filters> + <transformers> + <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/> + </transformers> + </configuration> <executions> <execution> <phase>package</phase>
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (18)
checkbox_actions/pom.xml(1 hunks)checkbox_actions/src/main/java/com/testsigma/addons/android/CheckAllCheckboxes.java(1 hunks)checkbox_actions/src/main/java/com/testsigma/addons/android/FetchCheckboxLabelAndStore.java(1 hunks)checkbox_actions/src/main/java/com/testsigma/addons/android/UnCheckAllCheckboxes.java(1 hunks)checkbox_actions/src/main/java/com/testsigma/addons/ios/CheckAllCheckboxes.java(1 hunks)checkbox_actions/src/main/java/com/testsigma/addons/ios/FetchCheckboxLabelAndStore.java(1 hunks)checkbox_actions/src/main/java/com/testsigma/addons/ios/UnCheckAllCheckboxes.java(1 hunks)checkbox_actions/src/main/java/com/testsigma/addons/utils/CheckBoxLabelFetcher.java(1 hunks)checkbox_actions/src/main/java/com/testsigma/addons/utils/CheckboxActions.java(1 hunks)checkbox_actions/src/main/java/com/testsigma/addons/web/CheckAllCheckboxes.java(1 hunks)checkbox_actions/src/main/java/com/testsigma/addons/web/FetchCheckboxLabelAndStore.java(1 hunks)checkbox_actions/src/main/java/com/testsigma/addons/web/UnCheckAllCheckboxes.java(1 hunks)list_data_structure_actions/pom.xml(1 hunks)list_data_structure_actions/src/main/java/com/testsigma/addons/android/WhileLoopStringBySeparator.java(1 hunks)list_data_structure_actions/src/main/java/com/testsigma/addons/ios/WhileLoopStringBySeparator.java(1 hunks)list_data_structure_actions/src/main/java/com/testsigma/addons/mobileweb/WhileLoopStringBySeparator.java(1 hunks)list_data_structure_actions/src/main/java/com/testsigma/addons/web/WhileLoopStringBySeparator.java(1 hunks)list_data_structure_actions/src/main/java/com/testsigma/addons/windowsAdvanced/WhileLoopStringBySeparator.java(1 hunks)
🔇 Additional comments (3)
list_data_structure_actions/pom.xml (1)
16-18: Avoid milestone JUnit; pin a stable Jupiter version5.8.0-M1 is a pre-release. Prefer a stable 5.x. Align with the rest of the repo to reduce surprises.
list_data_structure_actions/src/main/java/com/testsigma/addons/android/WhileLoopStringBySeparator.java (1)
15-22: Android action registered as WEB and extends WebAction.This will register/run under Web, not Android. Adjust ApplicationType and base class (confirm exact class name in your SDK).
-@Action(actionText = "store the current iteration value using SEPARATOR separated values in TEST-DATA " + - "into a runtime variable RUNTIME-VARIABLE", - description = "Iterate SEPARATOR separated values in TEST-DATA and store current iteration value in RUNTIME-VARIABLE", - applicationType = ApplicationType.WEB, - actionType = StepActionType.WHILE_LOOP) -public class WhileLoopStringBySeparator extends WebAction { +@Action(actionText = "store the current iteration value using SEPARATOR separated values in TEST-DATA " + + "into a runtime variable RUNTIME-VARIABLE", + description = "Iterate SEPARATOR separated values in TEST-DATA and store current iteration value in RUNTIME-VARIABLE", + applicationType = ApplicationType.ANDROID, + actionType = StepActionType.WHILE_LOOP) +public class WhileLoopStringBySeparator extends AndroidAction {Add/adjust imports:
-import com.testsigma.sdk.WebAction; +import com.testsigma.sdk.AndroidAction;Please confirm the correct Android base class name in your SDK (e.g., AndroidAction vs AndroidMobileAction).
list_data_structure_actions/src/main/java/com/testsigma/addons/ios/WhileLoopStringBySeparator.java (1)
15-22: iOS action registered as WEB and extends WebAction.This will register/run under Web, not iOS. Adjust ApplicationType and base class (confirm exact class name).
-@Action(actionText = "store the current iteration value using SEPARATOR separated values in TEST-DATA " + - "into a runtime variable RUNTIME-VARIABLE", - description = "Iterate SEPARATOR separated values in TEST-DATA and store current iteration value " + - "in RUNTIME-VARIABLE", - applicationType = ApplicationType.WEB, - actionType = StepActionType.WHILE_LOOP) -public class WhileLoopStringBySeparator extends WebAction { +@Action(actionText = "store the current iteration value using SEPARATOR separated values in TEST-DATA " + + "into a runtime variable RUNTIME-VARIABLE", + description = "Iterate SEPARATOR separated values in TEST-DATA and store current iteration value " + + "in RUNTIME-VARIABLE", + applicationType = ApplicationType.IOS, + actionType = StepActionType.WHILE_LOOP) +public class WhileLoopStringBySeparator extends IOSAction {Imports:
-import com.testsigma.sdk.WebAction; +import com.testsigma.sdk.IOSAction;Please confirm the correct iOS base class name in your SDK.
| <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.
Replace pre-release JUnit version with a stable release.
junit-jupiter-api 5.8.0-M1 is a milestone release (marked -M1), not recommended for production. Use a stable final release like 5.8.0 or later.
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
- <version>${junit.jupiter.version}</version>
+ <version>5.11.0</version>
</dependency>Also update the property:
- <junit.jupiter.version>5.8.0-M1</junit.jupiter.version>
+ <junit.jupiter.version>5.11.0</junit.jupiter.version>📝 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.
| <dependency> | |
| <groupId>org.junit.jupiter</groupId> | |
| <artifactId>junit-jupiter-api</artifactId> | |
| <version>${junit.jupiter.version}</version> | |
| <scope>test</scope> | |
| </dependency> | |
| <dependency> | |
| <groupId>org.junit.jupiter</groupId> | |
| <artifactId>junit-jupiter-api</artifactId> | |
| <version>5.11.0</version> | |
| <scope>test</scope> | |
| </dependency> |
🤖 Prompt for AI Agents
In checkbox_actions/pom.xml around lines 36 to 41, the pom currently references
a pre-release JUnit (5.8.0-M1); update the junit-jupiter version to a stable
release by changing the junit.jupiter.version property to a final release (e.g.,
5.8.0 or later such as 5.8.2/5.9.x) and ensure the dependency uses that
property; remove the -M1 suffix from the property value so the dependency
resolves to the stable release.
| <dependency> | ||
| <groupId>org.testng</groupId> | ||
| <artifactId>testng</artifactId> | ||
| <version>6.14.3</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.
Update TestNG to a supported version; 6.14.3 is from 2018 and likely contains unpatched vulnerabilities.
TestNG 6.14.3 is severely outdated and may have known security issues. Upgrade to TestNG 7.x or later (e.g., 7.10.2).
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
- <version>6.14.3</version>
+ <version>7.10.2</version>
</dependency>📝 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.
| <dependency> | |
| <groupId>org.testng</groupId> | |
| <artifactId>testng</artifactId> | |
| <version>6.14.3</version> | |
| </dependency> | |
| <dependency> | |
| <groupId>org.testng</groupId> | |
| <artifactId>testng</artifactId> | |
| <version>7.10.2</version> | |
| </dependency> |
🤖 Prompt for AI Agents
In checkbox_actions/pom.xml around lines 42 to 46, the project depends on TestNG
6.14.3 which is outdated and may have security issues; update the dependency to
a supported 7.x release (for example 7.10.2) in the <dependency> section, run a
full build and test (mvn clean test) to catch any breaking changes, and if tests
fail adjust any TestNG API usages or test annotations to be compatible with
TestNG 7.x (and update Maven Surefire/Failsafe plugin versions if necessary).
| try { | ||
| String variableName = runtimeVariable.getValue().toString(); | ||
| logger.info("Starting to fetch checkbox labels on Android platform and store in variable: " + variableName); | ||
|
|
||
| AndroidDriver androidDriver = (AndroidDriver) this.driver; |
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.
Null/empty runtime-variable guard to avoid NPE.
runtimeVariable.getValue() can be null. Fail fast with a clear message.
- String variableName = runtimeVariable.getValue().toString();
+ if (runtimeVariable == null || runtimeVariable.getValue() == null ||
+ runtimeVariable.getValue().toString().trim().isEmpty()) {
+ setErrorMessage("Runtime variable name (runtime-variable) is required.");
+ return Result.FAILED;
+ }
+ String variableName = runtimeVariable.getValue().toString().trim();🤖 Prompt for AI Agents
In
checkbox_actions/src/main/java/com/testsigma/addons/android/FetchCheckboxLabelAndStore.java
around lines 29 to 33, guard against runtimeVariable or
runtimeVariable.getValue() being null before calling toString(); if either is
null (or the value's toString() is empty) log a clear error and fail fast by
throwing an exception or returning an appropriate failure result so you don't
get an NPE. Add an explicit null/empty check, craft a descriptive message
including the variable name/key, and ensure the method exits cleanly after
logging so downstream code (like casting driver) is not executed when the
runtime variable is invalid.
| try { | ||
| String variableName = runtimeVariable.getValue().toString(); | ||
| logger.info("Starting to fetch checkbox labels on iOS platform and store in variable: " + variableName); |
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 runtime-variable null/empty check.
- String variableName = runtimeVariable.getValue().toString();
+ if (runtimeVariable == null || runtimeVariable.getValue() == null ||
+ runtimeVariable.getValue().toString().trim().isEmpty()) {
+ setErrorMessage("Runtime variable name (runtime-variable) is required.");
+ return Result.FAILED;
+ }
+ String variableName = runtimeVariable.getValue().toString().trim();🤖 Prompt for AI Agents
In
checkbox_actions/src/main/java/com/testsigma/addons/ios/FetchCheckboxLabelAndStore.java
around lines 29 to 31, the code uses runtimeVariable.getValue() without checking
for null or empty, which can cause NullPointerException or store invalid data;
add a guard that verifies runtimeVariable is not null and
runtimeVariable.getValue() is not null and not an empty string before calling
toString() or using the value, and if the check fails log an error (or set an
appropriate failure status/exception) and return/throw early to avoid proceeding
with an invalid variable name.
| // Click only if current state does not match desired state | ||
| if (checkbox.isSelected() != check) { | ||
| checkbox.click(); | ||
| logger.info((check ? "Checked" : "Unchecked") + " checkbox: " + checkboxInfo); | ||
| processedCount++; | ||
| } else { | ||
| logger.info("Checkbox already in desired state: " + checkboxInfo); | ||
| skippedCount++; | ||
| } |
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.
Platform-specific checked-state detection is required (isSelected is wrong on mobile).
On Android/iOS, isSelected() often does not reflect “checked”. Use platform attributes instead to avoid flipping already-correct checkboxes.
- // Click only if current state does not match desired state
- if (checkbox.isSelected() != check) {
+ // Click only if current state does not match desired state
+ boolean current = isChecked(checkbox, platform);
+ if (current != check) {
checkbox.click();
logger.info((check ? "Checked" : "Unchecked") + " checkbox: " + checkboxInfo);
processedCount++;
} else {
logger.info("Checkbox already in desired state: " + checkboxInfo);
skippedCount++;
}Add helper:
@@
}
+ private boolean isChecked(WebElement checkbox, String platform) {
+ try {
+ switch (platform) {
+ case "Android":
+ String checked = checkbox.getAttribute("checked");
+ return "true".equalsIgnoreCase(checked);
+ case "iOS":
+ String value = checkbox.getAttribute("value");
+ return "1".equals(value) || "true".equalsIgnoreCase(value);
+ default:
+ return checkbox.isSelected();
+ }
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
private String getPlatformType(WebDriver driver) {Also applies to: 84-96
| String separatorValue = this.separator.getValue().toString(); | ||
| String inputValue = this.inputData.getValue().toString(); | ||
| String[] inputValues = inputValue.split(separatorValue); | ||
|
|
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
Same literal split + validation + parse hardening as other platforms.
Apply the same fix set (Pattern.quote, non-empty SEPARATOR, null checks, robust index parse).
@@
+import java.util.regex.Pattern;
@@
- String separatorValue = this.separator.getValue().toString();
- String inputValue = this.inputData.getValue().toString();
- String[] inputValues = inputValue.split(separatorValue);
+ if (separator == null || separator.getValue() == null) {
+ setErrorMessage("SEPARATOR is required");
+ return Result.FAILED;
+ }
+ if (inputData == null || inputData.getValue() == null) {
+ setErrorMessage("TEST-DATA is required");
+ return Result.FAILED;
+ }
+ String separatorValue = String.valueOf(this.separator.getValue());
+ if (separatorValue.isEmpty()) {
+ setErrorMessage("SEPARATOR cannot be empty");
+ return Result.FAILED;
+ }
+ String inputValue = String.valueOf(this.inputData.getValue());
+ String[] inputValues = inputValue.split(Pattern.quote(separatorValue), -1);
@@
- int currentIterationIndexValue;
- if (currentIterationIndexData != null) {
- currentIterationIndexValue = Integer.parseInt(currentIterationIndexData.toString());
- } else {
- logger.info("Current iteration index is null");
- currentIterationIndexValue = 0;
- }
+ int currentIterationIndexValue = 0;
+ if (currentIterationIndexData != null) {
+ try {
+ currentIterationIndexValue = Integer.parseInt(currentIterationIndexData.toString().trim());
+ } catch (NumberFormatException nfe) {
+ logger.warn("Invalid currentIterationIndexData '{}', defaulting to 0", currentIterationIndexData);
+ }
+ } else {
+ logger.info("Current iteration index is null; starting at 0");
+ }
+ if (currentIterationIndexValue < 0) {
+ logger.warn("Negative iteration index {}; clamping to 0", currentIterationIndexValue);
+ currentIterationIndexValue = 0;
+ }
@@
- logger.info("Stored next index" + indexedRuntimeVariableName + " = " + currentIterationIndexValue);
+ logger.info("Stored next index " + indexedRuntimeVariableName + " = " + currentIterationIndexValue);Also applies to: 63-71
🤖 Prompt for AI Agents
In
list_data_structure_actions/src/main/java/com/testsigma/addons/ios/WhileLoopStringBySeparator.java
around lines 51-54 (and also apply same changes to 63-71): the code currently
calls toString() on separator and inputData and uses String.split with the raw
separator, without null/empty checks or robust index parsing. Add null checks
for this.separator and this.inputData before calling getValue()/toString();
ensure separator is not empty (throw or handle invalid separator); use
java.util.regex.Pattern.quote(separator) when splitting to avoid regex
meta-characters; guard against empty input and zero-length split results; and
parse any numeric index values with Integer.parseInt inside a try/catch,
validating bounds before use. Ensure all of these validations are applied in
both the first block (lines ~51-54) and the other block (~63-71).
| String separatorValue = this.separator.getValue().toString(); | ||
| String inputValue = this.inputData.getValue().toString(); | ||
| String[] inputValues = inputValue.split(separatorValue); | ||
|
|
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.
Literal split and input/index hardening.
Same corrective changes as Web.
@@
+import java.util.regex.Pattern;
@@
- String separatorValue = this.separator.getValue().toString();
- String inputValue = this.inputData.getValue().toString();
- String[] inputValues = inputValue.split(separatorValue);
+ if (separator == null || separator.getValue() == null) {
+ setErrorMessage("SEPARATOR is required");
+ return Result.FAILED;
+ }
+ if (inputData == null || inputData.getValue() == null) {
+ setErrorMessage("TEST-DATA is required");
+ return Result.FAILED;
+ }
+ String separatorValue = String.valueOf(this.separator.getValue());
+ if (separatorValue.isEmpty()) {
+ setErrorMessage("SEPARATOR cannot be empty");
+ return Result.FAILED;
+ }
+ String inputValue = String.valueOf(this.inputData.getValue());
+ String[] inputValues = inputValue.split(Pattern.quote(separatorValue), -1);
@@
- int currentIterationIndexValue;
- if (currentIterationIndexData != null) {
- currentIterationIndexValue = Integer.parseInt(currentIterationIndexData.toString());
- } else {
- logger.info("Current iteration index is null");
- currentIterationIndexValue = 0;
- }
+ int currentIterationIndexValue = 0;
+ if (currentIterationIndexData != null) {
+ try {
+ currentIterationIndexValue = Integer.parseInt(currentIterationIndexData.toString().trim());
+ } catch (NumberFormatException nfe) {
+ logger.warn("Invalid currentIterationIndexData '{}', defaulting to 0", currentIterationIndexData);
+ }
+ } else {
+ logger.info("Current iteration index is null; starting at 0");
+ }
+ if (currentIterationIndexValue < 0) {
+ logger.warn("Negative iteration index {}; clamping to 0", currentIterationIndexValue);
+ currentIterationIndexValue = 0;
+ }
@@
- logger.info("Stored next index" + indexedRuntimeVariableName + " = " + currentIterationIndexValue);
+ logger.info("Stored next index " + indexedRuntimeVariableName + " = " + currentIterationIndexValue);Also applies to: 63-71
🤖 Prompt for AI Agents
In
list_data_structure_actions/src/main/java/com/testsigma/addons/mobileweb/WhileLoopStringBySeparator.java
around lines 51-54 (and also apply the same fixes to lines 63-71): harden input
and separator handling to avoid NPEs and incorrect splitting — replace direct
this.separator.getValue().toString() and this.inputData.getValue().toString()
with safe conversions (e.g., Objects.toString(value, "") or explicit null
checks), use Pattern.quote(separator) when calling split to treat the separator
as a literal, handle empty separators appropriately (avoid infinite split), use
split(..., -1) if trailing empty tokens must be preserved, and add bounds checks
before indexing into the resulting array (validate array length and the loop
index) so you never assume a non-null array or valid index.
| String separatorValue = this.separator.getValue().toString(); | ||
| String inputValue = this.inputData.getValue().toString(); | ||
| String[] inputValues = inputValue.split(separatorValue); | ||
|
|
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.
Make splitting literal-safe, validate inputs, and parse index robustly.
split(...) treats SEPARATOR as regex and will mis-split on chars like ".", "|", "+". Also add guards for empty/null inputs and safe index parsing with a negative-index clamp.
Apply:
@@
+import java.util.regex.Pattern;
@@
- String runtimeVariableName = runtimeVariable.getValue().toString();
+ // Validate inputs
+ if (runtimeVariable == null || runtimeVariable.getValue() == null ||
+ String.valueOf(runtimeVariable.getValue()).trim().isEmpty()) {
+ setErrorMessage("RUNTIME-VARIABLE is required and cannot be empty");
+ return Result.FAILED;
+ }
+ if (separator == null || separator.getValue() == null) {
+ setErrorMessage("SEPARATOR is required");
+ return Result.FAILED;
+ }
+ if (inputData == null || inputData.getValue() == null) {
+ setErrorMessage("TEST-DATA is required");
+ return Result.FAILED;
+ }
+
+ String runtimeVariableName = String.valueOf(runtimeVariable.getValue());
String indexedRuntimeVariableName = runtimeVariableName + "_TSIndex"; // variable to hold index value
- String separatorValue = this.separator.getValue().toString();
- String inputValue = this.inputData.getValue().toString();
- String[] inputValues = inputValue.split(separatorValue);
+ String separatorValue = String.valueOf(this.separator.getValue());
+ if (separatorValue.isEmpty()) {
+ setErrorMessage("SEPARATOR cannot be empty");
+ return Result.FAILED;
+ }
+ String inputValue = String.valueOf(this.inputData.getValue());
+ // Use literal split and preserve trailing empties to iterate consistently
+ String[] inputValues = inputValue.split(Pattern.quote(separatorValue), -1);
@@
- int currentIterationIndexValue;
- if (currentIterationIndexData != null) {
- currentIterationIndexValue = Integer.parseInt(currentIterationIndexData.toString());
- } else {
- logger.info("Current iteration index is null");
- currentIterationIndexValue = 0;
- }
+ int currentIterationIndexValue = 0;
+ if (currentIterationIndexData != null) {
+ try {
+ currentIterationIndexValue = Integer.parseInt(currentIterationIndexData.toString().trim());
+ } catch (NumberFormatException nfe) {
+ logger.warn("Invalid currentIterationIndexData '{}', defaulting to 0", currentIterationIndexData);
+ currentIterationIndexValue = 0;
+ }
+ } else {
+ logger.info("Current iteration index is null; starting at 0");
+ }
+ if (currentIterationIndexValue < 0) {
+ logger.warn("Negative iteration index {}; clamping to 0", currentIterationIndexValue);
+ currentIterationIndexValue = 0;
+ }
@@
- logger.info("Stored next index" + indexedRuntimeVariableName + " = " + currentIterationIndexValue);
+ logger.info("Stored next index " + indexedRuntimeVariableName + " = " + currentIterationIndexValue);Also applies to: 63-71
| @Action(actionText = "Iterate SEPARATOR separated values in TEST-DATA and store current iteration value in RUNTIME-VARIABLE", | ||
| description = "Iterate SEPARATOR separated values in TEST-DATA and store current iteration value in RUNTIME-VARIABLE", | ||
| displayName = "Store the current iteration value from string with separator SEPARATOR STRING-WITH-SEPARATOR RUNTIME-VARIABLE", | ||
| applicationType = ApplicationType.WINDOWS_ADVANCED, | ||
| actionType = StepActionType.WHILE_LOOP) |
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.
Unify TEST-DATA reference and clarify display name.
The field uses reference "STRING-WITH-SEPARATOR" but action text mentions "TEST-DATA". This inconsistency will confuse users and breaks cross-platform parity.
@@
-@Action(actionText = "Iterate SEPARATOR separated values in TEST-DATA and store current iteration value in RUNTIME-VARIABLE",
- description = "Iterate SEPARATOR separated values in TEST-DATA and store current iteration value in RUNTIME-VARIABLE",
- displayName = "Store the current iteration value from string with separator SEPARATOR STRING-WITH-SEPARATOR RUNTIME-VARIABLE",
+@Action(actionText = "Iterate SEPARATOR-separated values in TEST-DATA and store current iteration value in RUNTIME-VARIABLE",
+ description = "Iterate SEPARATOR-separated values in TEST-DATA and store current iteration value in RUNTIME-VARIABLE",
+ displayName = "Store current iteration from SEPARATOR-separated TEST-DATA into RUNTIME-VARIABLE",
applicationType = ApplicationType.WINDOWS_ADVANCED,
actionType = StepActionType.WHILE_LOOP)
@@
- @TestData(reference = "STRING-WITH-SEPARATOR")
+ @TestData(reference = "TEST-DATA")
private com.testsigma.sdk.TestData inputData;Also applies to: 23-25
🤖 Prompt for AI Agents
In
list_data_structure_actions/src/main/java/com/testsigma/addons/windowsAdvanced/WhileLoopStringBySeparator.java
around lines 13-17 and 23-25, the annotation and displayName use inconsistent
parameter names ("TEST-DATA" in actionText/description vs
"STRING-WITH-SEPARATOR" in the field), which is confusing and breaks parity;
update the actionText, description, and displayName to consistently reference
the same parameter name (choose either TEST-DATA or STRING-WITH-SEPARATOR) and
update any UI-facing displayName to clearly describe inputs as "SEPARATOR" and
the chosen data parameter (e.g., "Store the current iteration value from
TEST-DATA using separator SEPARATOR into RUNTIME-VARIABLE"), ensuring all
occurrences on the listed lines are changed to the unified name.
| String separatorValue = this.separator.getValue().toString(); | ||
| String inputValue = this.inputData.getValue().toString(); | ||
| String[] inputValues = inputValue.split(separatorValue); | ||
|
|
||
| // Get the current iteration index | ||
| Object currentIterationIndexData = null; | ||
| try { | ||
| currentIterationIndexData = currentIterationIndexProvider.getRuntimeData(indexedRuntimeVariableName); | ||
| } catch (Exception ex) { |
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.
Use literal split, validate inputs, and harden index parsing.
Same issues as Web: regex split, empty/null inputs, unsafe parse.
@@
+import java.util.regex.Pattern;
@@
- String runtimeVariableName = runtimeVariable.getValue().toString();
+ if (runtimeVariable == null || runtimeVariable.getValue() == null ||
+ String.valueOf(runtimeVariable.getValue()).trim().isEmpty()) {
+ setErrorMessage("RUNTIME-VARIABLE is required and cannot be empty");
+ return Result.FAILED;
+ }
+ if (separator == null || separator.getValue() == null) {
+ setErrorMessage("SEPARATOR is required");
+ return Result.FAILED;
+ }
+ if (inputData == null || inputData.getValue() == null) {
+ setErrorMessage("TEST-DATA is required");
+ return Result.FAILED;
+ }
+ String runtimeVariableName = String.valueOf(runtimeVariable.getValue());
String indexedRuntimeVariableName = runtimeVariableName + "_TSIndex"; // variable to hold index value
- String separatorValue = this.separator.getValue().toString();
- String inputValue = this.inputData.getValue().toString();
- String[] inputValues = inputValue.split(separatorValue);
+ String separatorValue = String.valueOf(this.separator.getValue());
+ if (separatorValue.isEmpty()) {
+ setErrorMessage("SEPARATOR cannot be empty");
+ return Result.FAILED;
+ }
+ String inputValue = String.valueOf(this.inputData.getValue());
+ String[] inputValues = inputValue.split(Pattern.quote(separatorValue), -1);
@@
- int currentIterationIndexValue;
- if (currentIterationIndexData != null) {
- currentIterationIndexValue = Integer.parseInt(currentIterationIndexData.toString());
- } else {
- logger.info("Current iteration index is null");
- currentIterationIndexValue = 0;
- }
+ int currentIterationIndexValue = 0;
+ if (currentIterationIndexData != null) {
+ try {
+ currentIterationIndexValue = Integer.parseInt(currentIterationIndexData.toString().trim());
+ } catch (NumberFormatException nfe) {
+ logger.warn("Invalid currentIterationIndexData '{}', defaulting to 0", currentIterationIndexData);
+ currentIterationIndexValue = 0;
+ }
+ } else {
+ logger.info("Current iteration index is null; starting at 0");
+ }
+ if (currentIterationIndexValue < 0) {
+ logger.warn("Negative iteration index {}; clamping to 0", currentIterationIndexValue);
+ currentIterationIndexValue = 0;
+ }
@@
- logger.info("Stored next index" + indexedRuntimeVariableName + " = " + currentIterationIndexValue);
+ logger.info("Stored next index " + indexedRuntimeVariableName + " = " + currentIterationIndexValue);Also applies to: 59-67
please review these addons and publish as PUBLIC
Addon name : List data structure actions
Addon name : Checkbox actions
Addon accont: https://jarvis.testsigma.com/ui/tenants/3072/addons
Jira: https://testsigma.atlassian.net/browse/CUS-8162
fix
Summary by CodeRabbit
Release Notes