Skip to content

Commit 8f512f2

Browse files
authored
Merge pull request #1 from patrickduong/myda_11May2025_add_new_test_features
upgrade chrome Driver 136 update selenium to 4.22.0 update webDriverManager 5.8.0 update readme file Add 2 new test cases for shopping cart feature Add default run for browser always firefox - for skip issue on chrome
2 parents 7426907 + c439351 commit 8f512f2

File tree

15 files changed

+230
-37
lines changed

15 files changed

+230
-37
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,7 @@ replay_pid*
2525

2626
/shelf/
2727
/workspace.xml
28+
/build
29+
/target
2830
.gradle
2931
.idea

README.md

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
# saucedemo_Test
1+
# sauceDemo_Test
22

33
## Preface:
4-
54
+ This project is a basic test framework for UI automation using cucumber, selenium and build tool gradle
65
+ You should be familiar with Java programming language (intermediate level)
76
+ Knowledge should know
@@ -13,6 +12,8 @@
1312
+ Setup Java SDK version: 1.8+ or later (default build is version 15)
1413
+ Plugins: See the build.gradle for dependencies installation
1514
+ Selenium usage should be familiar with @findby: https://www.selenium.dev/selenium/docs/api/java/org/openqa/selenium/support/FindBy.html
15+
+ First use framework please run gradle build test for download all required dependencies.
16+
+ Recommendation for using intelliJ IDE for install Java and manage lib
1617

1718
## Test Execution Flow
1819
1. Start the browser-driver base on defined properties in gradle.properties via build.gradle run (run with gradle)
@@ -22,6 +23,19 @@
2223
+ Default generating 3 types html, json and xml (for later use with other report plugins) - see at target/cucumber-reports
2324
+ I include the plugin called spacialcircumstances.gradle-cucumber-reporting that will generate report at target/cucumber-html-report (base on the Cucumber_report.json above)
2425

26+
## To use the framework
27+
1. Please install any items mentioned at Prerequisites
28+
2. For executing using cli - set the default approach 1 for using firefox only
29+
- Open terminal type ```gradle clean test```
30+
- Wait until the execution done then click on the link ```~/target/cucumber-html-reports/overview-features.html```
31+
- It should display the report result
32+
3. For executing single feature file just select the feature file then run
33+
34+
2535
## NOTE
2636
+ Feel free to update and customise this template base your own knowledge
27-
+ This test project has promblem with check page title when running directly with gradle.build or via cli. Temporary commented a step in feature file.
37+
+ This test project has problem with check page title when running directly with gradle.build or via cli. Temporary commented a step in feature file.
38+
+ The web app has issue with Chrome browser that need to handle popup will need to handle later
39+
+ Please upgrade chrome driver and firefox driver to latest as link below (choose the correct driver that support CPU type)
40+
+ https://googlechromelabs.github.io/chrome-for-testing/
41+
+ https://github.com/mozilla/geckodriver/releases

build.gradle

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ java {
1212
ext {
1313
cucumberVersion = '7.11.2'
1414
junitbomVersion = '5.9.2'
15-
seleniumJavaVersion = '4.1.2'
15+
seleniumJavaVersion = '4.22.0'
1616
junitvintageengineVersion = '5.7.2'
1717
hamcrestVersion = '2.2'
18-
webdrivermanagerVersion = '5.3.2'
18+
webdrivermanagerVersion = '5.8.0'
1919
}
2020

2121
repositories {
@@ -48,17 +48,17 @@ cucumberReports {
4848
//please use only 1 approach below and comment the unused
4949

5050
//approach_1: set override the os and driver
51-
//tasks.withType(Test).configureEach {
52-
// systemProperties = [
53-
// defaultos : System.getProperty('defaultos', 'mac'),
54-
// defaultbrowserdriver: System.getProperty('defaultbrowserdriver', 'firefox')
55-
// ]
56-
//}
51+
tasks.withType(Test).configureEach {
52+
systemProperties = [
53+
defaultos : System.getProperty('defaultos', 'mac'),
54+
defaultbrowserdriver: System.getProperty('defaultbrowserdriver', 'firefox')
55+
]
56+
}
5757

5858
//approach_2: read from gradle.properties
59-
tasks.register('uiTest', Test) {
60-
systemProperties project.properties.subMap(["defaultos", "defaultbrowserdriver"])
61-
}
59+
//tasks.register('uiTest', Test) {
60+
// systemProperties project.properties.subMap(["defaultos", "defaultbrowserdriver"])
61+
//}
6262

6363
//run with gradle cli: open terminal
6464
// gradle uiTest -Pdefaultos=mac -Pdefaultbrowserdriver=firefox

gradle.properties

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,8 @@
22
#set to all will show all the warning
33
org.gradle.warning.mode=none
44
systemProp.defaultos=mac
5-
systemProp.defaultbrowserdriver=chrome
5+
systemProp.defaultbrowserdriver=firefox
6+
# Gradle properties
7+
org.gradle.parallel=false
8+
org.gradle.caching=false
9+
org.gradle.jvmargs=-Duser.language=en -Duser.country=US -Dfile.encoding=UTF-8

settings.gradle

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,3 @@
1010
rootProject.name = 'saucedemo'
1111
println System.getProperty("defaultos")
1212
println System.getProperty("defaultbrowserdriver")
13-
include 'app'
-1.27 MB
Binary file not shown.
5.89 MB
Binary file not shown.

src/test/java/cucumber/ScenarioContextUI.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,13 @@ public ScenarioReport getReport() {
3030

3131

3232
private WebDriver getFreshWebdriver() {
33-
//temporary hardcoded with mac and chrome when running with feature file
34-
DEFAULT_OS = System.getProperty("defaultos","mac");
35-
DEFAULT_DRIVER = System.getProperty("defaultbrowserdriver","chrome");
33+
//temporary hardcoded value running with feature file
34+
System.setProperty("defaultos","mac");
35+
System.setProperty("defaultbrowserdriver","firefox");
36+
37+
DEFAULT_OS = System.getProperty("defaultos");
38+
DEFAULT_DRIVER = System.getProperty("defaultbrowserdriver");
39+
3640
//cannot pass gradle properties via variables always return null
3741
System.out.println("********DEFAULT_OS: " + System.getProperty("defaultos") + "***");
3842
System.out.println("********DEFAULT_DRIVER: " + System.getProperty("defaultbrowserdriver") + "***");

src/test/java/pages/CartPage.java

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package pages;
2+
3+
import org.openqa.selenium.By;
4+
import org.openqa.selenium.WebDriver;
5+
import org.openqa.selenium.WebElement;
6+
7+
import java.util.ArrayList;
8+
import java.util.List;
9+
10+
public class CartPage extends BasePage {
11+
12+
public CartPage(final WebDriver driver) {
13+
super(driver);
14+
}
15+
16+
private final By cartItemsLocator = By.cssSelector("div.cart_list div.cart_item");
17+
18+
// private final By continueShopButtonLocator = By.cssSelector("[data-test='continue-shopping']");
19+
// private final By checkOutButtonLocator = By.cssSelector("[data-test='checkout']");
20+
21+
public static class CartItem {
22+
public final String name;
23+
public final String price;
24+
public final int quantity;
25+
26+
public CartItem(String name, String price, int quantity) {
27+
this.name = name;
28+
this.price = price;
29+
this.quantity = quantity;
30+
}
31+
}
32+
33+
public List<CartItem> getAllCartItems() {
34+
List<CartItem> items = new ArrayList<>();
35+
List<WebElement> elements = driver.findElements(cartItemsLocator);
36+
37+
for (WebElement el : elements) {
38+
String qtyText = el.findElement(By.cssSelector("[data-test='item-quantity']")).getText().trim();
39+
int quantity = Integer.parseInt(qtyText);
40+
String name = el.findElement(By.cssSelector("[data-test='inventory-item-name']")).getText().trim();
41+
String price = el.findElement(By.cssSelector("[data-test='inventory-item-price']")).getText().trim();
42+
43+
items.add(new CartItem(name, price, quantity));
44+
}
45+
return items;
46+
}
47+
48+
public boolean isItemInCart(String expectedName, String expectedPrice, int expectedQuantity) {
49+
return getAllCartItems().stream().anyMatch(item ->
50+
item.name.equals(expectedName) &&
51+
item.price.equals(expectedPrice) &&
52+
item.quantity == expectedQuantity
53+
);
54+
}
55+
56+
public void verifyItemPresent(String expectedName, String expectedPrice, int expectedQuantity) {
57+
if (!isItemInCart(expectedName, expectedPrice, expectedQuantity)) {
58+
throw new AssertionError(
59+
String.format("Cart does not contain item [%s, %s, qty=%d]",
60+
expectedName, expectedPrice, expectedQuantity));
61+
}
62+
}
63+
64+
}

src/test/java/pages/InventoryPage.java

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package pages;
22

3+
import org.openqa.selenium.By;
34
import org.openqa.selenium.WebDriver;
45
import org.openqa.selenium.WebElement;
56
import org.openqa.selenium.support.FindBy;
@@ -14,11 +15,53 @@ public class InventoryPage extends BasePage {
1415
@FindBy(className = "title")
1516
private WebElement inventoryTitle;
1617

17-
public InventoryPage(WebDriver driver) {
18+
public void addProductToCart(String productName, String productPrice) {
19+
// 1. Grab all product containers
20+
List<WebElement> items = driver.findElements(By.cssSelector("div.inventory_item"));
21+
22+
for (WebElement item : items) {
23+
// 2. Extract name and price from each container
24+
String name = item.findElement(By.cssSelector("[data-test='inventory-item-name']")).getText().trim();
25+
String price = item.findElement(By.cssSelector("[data-test='inventory-item-price']")).getText().trim();
26+
27+
// 3. If both match, locate the button
28+
if (name.equals(productName) && price.equals(productPrice)) {
29+
WebElement btn = item.findElement(By.cssSelector("button.btn_inventory"));
30+
String btnText = btn.getText().trim();
31+
32+
// 4. Only click if it's an 'Add to cart' button
33+
if (btnText.equalsIgnoreCase("Add to cart")) {
34+
btn.click();
35+
} else {
36+
// already in cart / says "Remove" — do nothing
37+
System.out.printf("Product '%s' already in cart (button shows '%s'), skipping click.%n",
38+
productName, btnText);
39+
}
40+
return; // done after handling the matched product
41+
}
42+
}
43+
44+
throw new RuntimeException(
45+
String.format("Product not found: name='%s', price='%s'", productName, productPrice)
46+
);
47+
}
48+
49+
public int getCartBadgeCount() {
50+
WebElement badge = driver.findElement(By.cssSelector("span[data-test='shopping-cart-badge']"));
51+
String text = badge.getText().trim();
52+
try {
53+
return Integer.parseInt(text);
54+
} catch (NumberFormatException e) {
55+
throw new RuntimeException("Cart badge did not contain a number: '" + text + "'", e);
56+
}
57+
}
58+
59+
60+
public InventoryPage(final WebDriver driver) {
1861
super(driver);
1962
}
2063

21-
public String getPageTitle(){
64+
public String getPageTitle() {
2265
return inventoryTitle.getText();
2366
}
2467

@@ -27,5 +70,4 @@ public int countTotalProductItem() {
2770
}
2871

2972

30-
3173
}

0 commit comments

Comments
 (0)