Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -166,4 +166,13 @@ cython_debug/
/service/user_account.json
/service/models

secrets/
secrets/


# test-automation-ignore -files
com.hybrid.joshsoftware.lingoai/target/
com.hybrid.joshsoftware.lingoai/Reports/
com.hybrid.joshsoftware.lingoai/test-output/
com.hybrid.joshsoftware.lingoai/.settings/
com.hybrid.joshsoftware.lingoai/.classpath
com.hybrid.joshsoftware.lingoai/.project
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
appUrl = https://thelingo.co.in/signin
headless = false
Binary file not shown.
Binary file not shown.
20 changes: 20 additions & 0 deletions com.hybrid.joshsoftware.lingoai/XMLFiles/e2e.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="Suite">
<listeners>

<listener class-name="Listeners.MyTestNGListener"></listener>

<listener class-name="com.aventstack.chaintest.plugins.ChainTestListener"></listener>


</listeners>

<test thread-count="5" name="Test">
<parameter name="browser_name" value="Chrome" />
<classes>
<class name="testcases.LingoAILogin" />
<class name="testcases.ProfileIcon" />
</classes>
</test>
</suite>
41 changes: 41 additions & 0 deletions com.hybrid.joshsoftware.lingoai/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.hybrid.joshsoftware.lingoai</groupId>
<artifactId>com.hybrid.joshsoftware.lingoai</artifactId>
<version>0.0.1-SNAPSHOT</version>

<dependencies>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.29.0</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.testng/testng -->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.10.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.4.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.4.0</version>
</dependency>

<dependency>
<groupId>com.aventstack</groupId>
<artifactId>chaintest-testng</artifactId>
<version>1.0.12 </version>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package BaseClass;

import org.openqa.selenium.WebDriver;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;

import com.aventstack.chaintest.plugins.ChainTestListener;

import Helper.BrowserFactory;
import Helper.ConfigUtility;

public class BaseClass {

public WebDriver driver;

// @Parameters({"browser_name"})
@BeforeClass
public void startBrowser() {

ChainTestListener.log(" *** Instantiating Browser *** ");

driver = BrowserFactory.startBrowser("Chrome", ConfigUtility.getProperty("appUrl"),
ConfigUtility.getProperty("headless"));

}

@AfterClass
public void tearDown() {
ChainTestListener.log("LOG INFO: CLOSING BROWSER");
if (driver != null) {
driver.quit();
ChainTestListener.log("LOG INFO: BROWSER CLOSED");
} else {
System.out.println("LOG INFO: BROWSER NOT INITIATED ");
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package Helper;

import java.time.Duration;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;

import com.aventstack.chaintest.plugins.ChainTestListener;

public class BrowserFactory {

static WebDriver driver;

// Initializing driver for screenshot in listener during failure
public static WebDriver getDriver() {
return driver;
}

public static WebDriver startBrowser(String browser, String appUrl) {
if (browser.equalsIgnoreCase("Chrome")) {
driver = new ChromeDriver();
} else if (browser.equalsIgnoreCase("Firefox")) {
driver = new FirefoxDriver();
}

else if (browser.equalsIgnoreCase("Edge")) {
driver = new EdgeDriver();
} else {
System.out.println("We only support CHROME, FIREFOX, EDGE Browser");
System.out.println("Starting Default Browser");
driver = new ChromeDriver();
}
driver.manage().window().maximize();
driver.manage().timeouts().pageLoadTimeout(Duration.ofSeconds(60));
driver.get(appUrl);
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
return driver;
}

public static WebDriver startBrowser(String browser, String appUrl, String headless) {

if (browser.equalsIgnoreCase("Chrome")) {

if (headless.equalsIgnoreCase("true")) {
ChainTestListener.log("LOG INFO: CHROME BROWSER Initialized In HEADLESS");
ChromeOptions options = new ChromeOptions();
options.addArguments("headless");
driver = new ChromeDriver(options);
}

else {
ChainTestListener.log("LOG INFO: Chrome Browser Initialized ");
driver = new ChromeDriver();
}
}

else if (browser.equalsIgnoreCase("Firefox")) {
ChainTestListener.log("LOG INFO: FireFox Browser Initialized ");
driver = new FirefoxDriver();
} else if (browser.equalsIgnoreCase("Edge")) {
ChainTestListener.log("LOG INFO: Edge Browser Initialized ");
driver = new EdgeDriver();
}

else {
ChainTestListener.log("LOG INFO: Sorry We Only support 'CHROME', 'FIREFOX', 'EDGE' ");
ChainTestListener.log("LOG INFO: Initializing Chrome Browser");
driver = new ChromeDriver();
}

driver.manage().window().maximize();
driver.manage().timeouts().pageLoadTimeout(Duration.ofSeconds(60));
ChainTestListener.log("LOG INFO: Launching Lingo AI URL");
driver.get(appUrl);
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
return driver;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package Helper;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;

public class ConfigUtility {

public static String getProperty(String key) {
Properties prop = null;

try {

prop = new Properties();
prop.load(
new FileInputStream(new File(System.getProperty("user.dir") + "/Configuration/lingo.properties")));
} catch (FileNotFoundException e) {
System.out.println("File Not Found " + e.getMessage());
} catch (IOException e) {
System.out.println("Issue On loading " + e.getMessage());
}
return prop.getProperty(key);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package Helper;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class DateUtility {

public static String getDate() {
LocalDate today = LocalDate.now(); // gets current date

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd MMM yyyy");
String formattedDate = today.format(formatter);

return formattedDate; // e.g., 22 July 2025
}

}
123 changes: 123 additions & 0 deletions com.hybrid.joshsoftware.lingoai/src/main/java/Helper/Utility.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package Helper;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;

import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

public class Utility {

public static String getScreenshot(WebDriver driver) {
TakesScreenshot ts = (TakesScreenshot) driver;
return ts.getScreenshotAs(OutputType.BASE64);
}

public static String getTitle(WebDriver driver) {
return driver.getTitle();
}

public static boolean isCurrentUrlMatch(WebDriver driver, String url) {

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
return wait.until(ExpectedConditions.urlContains(url));

}

public static void pause(int millisec) {
try {
Thread.sleep(millisec);
} catch (InterruptedException e) {
System.out.println(e.getMessage());

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improper InterruptedException handling in pause method

The pause method catches InterruptedException but only prints the message without restoring the interrupt status. This breaks proper thread interruption handling. Add Thread.currentThread().interrupt() after logging to restore the interrupt status.

Code suggestion
Check the AI-generated fix before applying
Suggested change
System.out.println(e.getMessage());
System.out.println(e.getMessage());
Thread.currentThread().interrupt();

Code Review Run #09aa03


Should Bito avoid suggestions like this for future reviews? (Manage Rules)

  • Yes, avoid them

}
}

public static boolean checkElementInvisibility(WebDriver driver, By locator) {
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
return wait.until(ExpectedConditions.invisibilityOfElementLocated(locator));

}

public static WebElement checkElement(WebDriver driver, By locator) {
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(300));

WebElement ele = wait.until(ExpectedConditions.elementToBeClickable(locator));

Utility.highlightElement(driver, ele);

return ele;

}

// public static WebElement checkElementVisibility(WebDriver driver, By locator) {
// WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(60));
//
// WebElement ele = wait.until(ExpectedConditions.visibilityOfElementLocated(locator));
//
// Utility.highlightElement(driver, ele);
//
// return ele;
//
// }

public static List<WebElement> checkListElementPresence(WebDriver driver, By locator) {
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(60));
return wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(locator));
}

public static void highlightElement(WebDriver driver, WebElement element) {
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("arguments[0].setAttribute('style','background:yellow;border: 2px solid red;');", element);
pause(500);
js.executeScript("arguments[0].setAttribute('style','border: solid 2px white');", element);
}

public static void typeonElement(WebDriver driver, By locator, String textToType) {
// System.out.println(textToType);

Utility.checkElement(driver, locator).sendKeys(textToType);
}

public static void clickOnElement(WebDriver driver, By locator) {
Utility.checkElement(driver, locator).click();
}

public static String getElementText(WebDriver driver, By locator) {
System.out.println(driver.findElement(locator).getText());
return Utility.checkElement(driver, locator).getText();
Comment on lines +93 to +94

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate element lookups causing race conditions

The getElementText method performs duplicate element lookups which can cause race conditions. It calls driver.findElement(locator).getText() for logging, then Utility.checkElement(driver, locator).getText() for the return value. This could lead to stale element references if the DOM changes between calls. Store the element text in a variable and use it for both logging and return.

Code suggestion
Check the AI-generated fix before applying
Suggested change
System.out.println(driver.findElement(locator).getText());
return Utility.checkElement(driver, locator).getText();
String elementText = Utility.checkElement(driver, locator).getText();
System.out.println(elementText);
return elementText;

Code Review Run #09aa03


Should Bito avoid suggestions like this for future reviews? (Manage Rules)

  • Yes, avoid them

}

public static boolean isElementDisplayed(WebDriver driver, By locator) {
return Utility.checkElement(driver, locator).isDisplayed();
}

public static List<WebElement> getActualList(WebDriver driver, By locator) {
return driver.findElements(locator);
}

public static List<String> getMenuList(WebDriver driver, int size, By locator) {
List<String> actual_list = new ArrayList<String>();
List<WebElement> list_webElement = Utility.getActualList(driver, locator);

if (list_webElement.size() == size) {
for (WebElement webElement : list_webElement) {
String str = webElement.getText();

actual_list.add(str);
}

} else {
System.out.println("List Count Mismatch");
}

return actual_list;
}

}
Loading