Skip to content

Commit 6a6644e

Browse files
committed
Completed sample code
1 parent 06596e2 commit 6a6644e

File tree

1 file changed

+106
-212
lines changed

1 file changed

+106
-212
lines changed

src/test/java/com/serenitydojo/playwright/PlaywrightPageObjectTest.java

Lines changed: 106 additions & 212 deletions
Original file line numberDiff line numberDiff line change
@@ -59,109 +59,28 @@ class WhenSearchingProductsByKeyword {
5959
@DisplayName("Without Page Objects")
6060
@Test
6161
void withoutPageObjects() {
62-
page.getByPlaceholder("Search").fill("tape");
63-
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Search")).click();
6462
page.waitForResponse("**/products/search?q=tape", () -> {
63+
page.getByPlaceholder("Search").fill("tape");
64+
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Search")).click();
6565
});
66-
67-
assertThat(page.getByTestId("product-name")).hasCount(3);
68-
Assertions.assertThat(page.getByTestId("product-name").allInnerTexts())
66+
List<String> matchingProducts = page.getByTestId("product-name").allInnerTexts();
67+
Assertions.assertThat(matchingProducts)
6968
.contains("Tape Measure 7.5m", "Measuring Tape", "Tape Measure 5m");
7069

7170
}
7271

73-
static class SearchComponent {
74-
75-
private final Page page;
76-
77-
public SearchComponent(Page page) {
78-
this.page = page;
79-
}
80-
81-
private Locator searchField() {
82-
return page.getByTestId("search-query");
83-
}
84-
85-
private Locator searchButton() {
86-
return page.getByTestId("search-submit");
87-
}
88-
89-
void searchByKeyword(String keyword) {
90-
page.waitForResponse(
91-
"**/products/search*",
92-
() -> {
93-
searchField().fill(keyword);
94-
searchButton().click();
95-
}
96-
);
97-
}
98-
}
99-
100-
record ProductItem(String name, String image, double price) {
101-
}
102-
103-
;
104-
105-
static class ProductList {
106-
private final Page page;
107-
108-
public ProductList(Page page) {
109-
this.page = page;
110-
}
111-
112-
private Locator getProductCards() {
113-
return page.locator(".card");
114-
}
115-
116-
private double extractPrice(Locator priceElement) {
117-
return Double.parseDouble(
118-
priceElement.textContent()
119-
.trim()
120-
.replace("$", "")
121-
);
122-
}
123-
124-
public List<ProductItem> getProducts() {
125-
return getProductCards()
126-
.all()
127-
.stream()
128-
.map(card -> new ProductItem(
129-
card.getByTestId("product-name").innerText(),
130-
card.locator(".card-img-top").getAttribute("src"),
131-
extractPrice(card.getByTestId("product-price"))
132-
))
133-
.toList();
134-
}
135-
136-
public void viewProduct(String productName) {
137-
page.locator(".card").getByText(productName).click();
138-
}
139-
}
140-
72+
@DisplayName("With Page Objects")
14173
@Test
14274
void withPageObjects() {
14375
SearchComponent searchComponent = new SearchComponent(page);
14476
ProductList productList = new ProductList(page);
14577

146-
searchComponent.searchByKeyword("Tape");
147-
List<ProductItem> matchingProducts = productList.getProducts();
78+
searchComponent.searchBy("tape");
14879

149-
Assertions.assertThat(matchingProducts)
150-
.as("Should find correct number of tape measures")
151-
.hasSize(3);
80+
var matchingProducts = productList.getProductNames();
15281

153-
Assertions.assertThat(matchingProducts)
154-
.as("All products should have valid prices")
155-
.allMatch(product -> product.price() > 0.0);
82+
Assertions.assertThat(matchingProducts).contains("Tape Measure 7.5m", "Measuring Tape", "Tape Measure 5m");
15683

157-
Assertions.assertThat(matchingProducts)
158-
.extracting(ProductItem::name)
159-
.as("Should find all tape measure products")
160-
.containsExactlyInAnyOrder(
161-
"Tape Measure 7.5m",
162-
"Measuring Tape",
163-
"Tape Measure 5m"
164-
);
16584
}
16685
}
16786

@@ -171,177 +90,152 @@ class WhenAddingItemsToTheCart {
17190
@DisplayName("Without Page Objects")
17291
@Test
17392
void withoutPageObjects() {
174-
page.getByPlaceholder("Search").fill("pliers");
175-
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Search")).click();
93+
// Search for pliers
17694
page.waitForResponse("**/products/search?q=pliers", () -> {
95+
page.getByPlaceholder("Search").fill("pliers");
96+
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Search")).click();
17797
});
98+
// Show details page
17899
page.locator(".card").getByText("Combination Pliers").click();
100+
101+
// Increase cart quanity
179102
page.getByTestId("increase-quantity").click();
180103
page.getByTestId("increase-quantity").click();
104+
// Add to cart
181105
page.getByText("Add to cart").click();
182106
page.waitForCondition(() -> page.getByTestId("cart-quantity").textContent().equals("3"));
107+
108+
// Open the cart
183109
page.getByTestId("nav-cart").click();
184110

111+
// check cart contents
185112
assertThat(page.locator(".product-title").getByText("Combination Pliers")).isVisible();
186113
assertThat(page.getByTestId("cart-quantity").getByText("3")).isVisible();
187114
}
188115

189-
@DisplayName("With Page Objects")
190116
@Test
191117
void withPageObjects() {
192-
WhenSearchingProductsByKeyword.SearchComponent searchComponent = new WhenSearchingProductsByKeyword.SearchComponent(page);
193-
WhenSearchingProductsByKeyword.ProductList productList = new WhenSearchingProductsByKeyword.ProductList(page);
118+
SearchComponent searchComponent = new SearchComponent(page);
119+
ProductList productList = new ProductList(page);
194120
ProductDetails productDetails = new ProductDetails(page);
195121
NavBar navBar = new NavBar(page);
196122
CheckoutCart checkoutCart = new CheckoutCart(page);
197123

198-
searchComponent.searchByKeyword("pliers");
199-
productList.viewProduct("Combination Pliers");
124+
searchComponent.searchBy("pliers");
125+
productList.viewProductDetails("Combination Pliers");
200126

127+
productDetails.increaseQuanityBy(2);
201128
productDetails.addToCart();
202-
navBar.openCart();
203-
204-
List<CheckoutItem> checkoutItems = checkoutCart.getCheckoutItems();
205-
206-
Assertions.assertThat(checkoutItems).hasSize(1);
207-
Assertions.assertThat(checkoutItems.get(0).title()).contains("Combination Pliers");
208-
Assertions.assertThat(checkoutItems.get(0).quantity()).isEqualTo(1);
209129

210-
}
211-
212-
@DisplayName("With Page Objects and multiple items")
213-
@Test
214-
void withPageObjectsAndMultipleItems() {
215-
WhenSearchingProductsByKeyword.SearchComponent searchComponent = new WhenSearchingProductsByKeyword.SearchComponent(page);
216-
WhenSearchingProductsByKeyword.ProductList productList = new WhenSearchingProductsByKeyword.ProductList(page);
217-
ProductDetails productDetails = new ProductDetails(page);
218-
NavBar navBar = new NavBar(page);
219-
CheckoutCart checkoutCart = new CheckoutCart(page);
220-
221-
searchComponent.searchByKeyword("pliers");
222-
productList.viewProduct("Combination Pliers");
223-
224-
productDetails.increaseQuantityBy(2);
225-
productDetails.addToCart();
226130
navBar.openCart();
227131

228-
List<CheckoutItem> checkoutItems = checkoutCart.getCheckoutItems();
132+
List<CartLineItem> lineItems = checkoutCart.getLineItems();
229133

230-
Assertions.assertThat(checkoutItems).hasSize(1);
231-
Assertions.assertThat(checkoutItems.get(0).title()).contains("Combination Pliers");
232-
Assertions.assertThat(checkoutItems.get(0).quantity()).isEqualTo(3);
134+
Assertions.assertThat(lineItems)
135+
.hasSize(1)
136+
.first()
137+
.satisfies(item -> {
138+
Assertions.assertThat(item.title()).contains("Combination Pliers");
139+
Assertions.assertThat(item.quantity()).isEqualTo(3);
140+
Assertions.assertThat(item.total()).isEqualTo(item.quantity() * item.price());
141+
});
233142
}
143+
}
234144

145+
class SearchComponent {
146+
private final Page page;
235147

236-
@DisplayName("With Page Objects and multiple products")
237-
@Test
238-
void withPageObjectsAndMultipleProducts() {
239-
WhenSearchingProductsByKeyword.SearchComponent searchComponent = new WhenSearchingProductsByKeyword.SearchComponent(page);
240-
WhenSearchingProductsByKeyword.ProductList productList = new WhenSearchingProductsByKeyword.ProductList(page);
241-
ProductDetails productDetails = new ProductDetails(page);
242-
NavBar navBar = new NavBar(page);
243-
CheckoutCart checkoutCart = new CheckoutCart(page);
244-
245-
searchComponent.searchByKeyword("pliers");
246-
productList.viewProduct("Combination Pliers");
247-
productDetails.addToCart();
248-
249-
navBar.openHomePage();
250-
;
251-
productList.viewProduct("Bolt Cutters");
252-
productDetails.addToCart();
253-
254-
navBar.openCart();
255-
256-
List<CheckoutItem> checkoutItems = checkoutCart.getCheckoutItems();
257-
258-
Assertions.assertThat(checkoutItems).hasSize(2);
148+
SearchComponent(Page page) {
149+
this.page = page;
259150
}
260151

152+
public void searchBy(String keyword) {
153+
page.waitForResponse("**/products/search?q=" + keyword, () -> {
154+
page.getByPlaceholder("Search").fill(keyword);
155+
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Search")).click();
156+
});
157+
}
158+
}
261159

262-
static class ProductDetails {
263-
private final Page page;
264-
265-
ProductDetails(Page page) {
266-
this.page = page;
267-
}
268-
269-
public void increaseQuantityBy(int increment) {
270-
for (int i = 0; i < increment; i++) {
271-
increaseQuantityButton().click();
272-
}
273-
}
160+
class ProductList {
161+
private final Page page;
274162

275-
public void addToCart() {
276-
page.waitForResponse(
277-
response -> response.url().contains("/carts/") && response.request().method().equals("POST"),
278-
() -> {
279-
addToCartButton().click();
280-
}
281-
);
282-
}
163+
ProductList(Page page) {
164+
this.page = page;
165+
}
283166

284-
private Locator increaseQuantityButton() {
285-
return page.getByTestId("increase-quantity");
286-
}
287167

288-
private Locator addToCartButton() {
289-
return page.getByText("Add to cart");
290-
}
168+
public List<String> getProductNames() {
169+
return page.getByTestId("product-name").allInnerTexts();
291170
}
292171

293-
static class NavBar {
294-
private final Page page;
172+
public void viewProductDetails(String productName) {
173+
page.locator(".card").getByText(productName).click();
174+
}
175+
}
295176

296-
NavBar(Page page) {
297-
this.page = page;
298-
}
177+
class ProductDetails {
178+
private final Page page;
299179

300-
public void openCart() {
301-
page.navigate("https://practicesoftwaretesting.com/checkout");
302-
page.waitForSelector(".product-title");
303-
}
180+
ProductDetails(Page page) {
181+
this.page = page;
182+
}
304183

305-
public void openHomePage() {
306-
page.navigate("https://practicesoftwaretesting.com");
184+
public void increaseQuanityBy(int increment) {
185+
for (int i = 1; i <= increment; i++) {
186+
page.getByTestId("increase-quantity").click();
307187
}
308188
}
309189

310-
static class CheckoutCart {
311-
private final Page page;
190+
public void addToCart() {
191+
page.waitForResponse(
192+
response -> response.url().contains("/carts") && response.request().method().equals("POST"),
193+
() -> {
194+
page.getByText("Add to cart").click();
195+
page.getByRole(AriaRole.ALERT).click();
196+
}
197+
);
198+
}
199+
}
312200

313-
CheckoutCart(Page page) {
314-
this.page = page;
315-
}
201+
class NavBar {
202+
private final Page page;
316203

317-
List<CheckoutItem> getCheckoutItems() {
318-
return page.locator("app-cart tbody tr")
319-
.all()
320-
.stream()
321-
.map(
322-
checkoutItemRow -> {
323-
List<Locator> itemRowCells = checkoutItemRow.locator("td").all();
324-
String title = stripBlankCharactersFrom(checkoutItemRow.locator(".product-title").innerText());
325-
String itemQuantity = checkoutItemRow.locator("td").all().get(1).locator("input").inputValue();
326-
int quantity = Integer.parseInt(itemQuantity);
327-
double itemPrice = extractPrice(itemRowCells.get(2).textContent());
328-
double totalPrice = extractPrice(itemRowCells.get(3).textContent());
329-
return new CheckoutItem(title, quantity, itemPrice, totalPrice);
330-
}
331-
).toList();
332-
}
204+
NavBar(Page page) {
205+
this.page = page;
206+
}
333207

334-
private String stripBlankCharactersFrom(String value) {
335-
return value.strip().replaceAll("\u00A0+$", "");
336-
}
208+
public void openCart() {
209+
page.getByTestId("nav-cart").click();
210+
}
211+
}
337212

338-
private double extractPrice(String priceValue) {
339-
return Double.parseDouble(priceValue.replace("$", ""));
340-
}
213+
record CartLineItem(String title, int quantity, double price, double total) {}
341214

215+
class CheckoutCart {
216+
private final Page page;
217+
CheckoutCart(Page page) {
218+
this.page = page;
342219
}
343220

344-
record CheckoutItem(String title, int quantity, double price, double total) {
221+
public List<CartLineItem> getLineItems() {
222+
page.locator("app-cart tbody tr").waitFor();
223+
return page.locator("app-cart tbody tr")
224+
.all()
225+
.stream()
226+
.map(
227+
row -> {
228+
String title = row.getByTestId("product-title").innerText();
229+
int quantity = Integer.parseInt(row.getByTestId("product-quantity").inputValue());
230+
double price = Double.parseDouble(price(row.getByTestId("product-price").innerText()));
231+
double linePrice = Double.parseDouble(price(row.getByTestId("line-price").innerText()));
232+
return new CartLineItem(title, quantity, price, linePrice);
233+
}
234+
).toList();
345235
}
346236
}
347-
}
237+
238+
private String price(String value) {
239+
return value.replace("$","");
240+
}
241+
}

0 commit comments

Comments
 (0)