@@ -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