Skip to content

Commit 730f5f0

Browse files
author
gabrielsouza80
committed
feat: Add ProductDetailsPage and ProductDetailsTest; enhance HomePage with visual anomaly detection and user-specific checks
1 parent 345bfe4 commit 730f5f0

File tree

5 files changed

+304
-18
lines changed

5 files changed

+304
-18
lines changed

src/test/java/com/playwright/java/base/BaseTest.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import com.playwright.java.pages.ComponentsPage;
2929
import com.playwright.java.pages.HomePage;
3030
import com.playwright.java.pages.LoginPage;
31+
import com.playwright.java.pages.ProductDetailsPage;
3132

3233
// Classe base de todos os testes.
3334
// Tudo que é comum (abrir browser, login, fechar browser) fica aqui.
@@ -47,6 +48,7 @@ public abstract class BaseTest {
4748
protected LoginPage loginPage;
4849
protected HomePage homePage;
4950
protected ComponentsPage componentsPage;
51+
protected ProductDetailsPage productDetailsPage;
5052

5153
protected boolean requiresAuthenticatedSession() {
5254
return true;
@@ -114,6 +116,7 @@ void setUpTest() {
114116
loginPage = new LoginPage(page);
115117
homePage = new HomePage(page);
116118
componentsPage = new ComponentsPage(page);
119+
productDetailsPage = new ProductDetailsPage(page);
117120

118121
if (requiresAuthenticatedSession()) {
119122
String inventoryUrl = config.baseUrl().endsWith("/")

src/test/java/com/playwright/java/pages/HomePage.java

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,13 @@ public boolean hasButtonStateIssue() {
5858
}
5959

6060
public boolean hasProblemUserSpecificIssue() {
61-
return brokenImageIssue || hasButtonStateIssue();
61+
// problem_user DEVE ter imagens quebradas (sl-404 placeholder)
62+
// OU começar com Backpack em estado Remove (sem poder adicionar)
63+
return brokenImageIssue || startedWithRemove;
6264
}
6365

6466
public boolean hasErrorUserSpecificIssue() {
65-
return startedWithRemove || removeDidNotSwitchToAdd || addDidNotSwitchToRemove;
67+
return brokenImageIssue || startedWithRemove || removeDidNotSwitchToAdd || addDidNotSwitchToRemove;
6668
}
6769

6870
public String toEvidenceText(String userKey) {
@@ -114,6 +116,33 @@ public String toEvidenceText() {
114116
}
115117
}
116118

119+
public static final class VisualUserHomeAnomalyResult {
120+
private final boolean textMisalignmentIssue;
121+
private final boolean buttonMisalignmentIssue;
122+
123+
public VisualUserHomeAnomalyResult(
124+
boolean textMisalignmentIssue,
125+
boolean buttonMisalignmentIssue) {
126+
this.textMisalignmentIssue = textMisalignmentIssue;
127+
this.buttonMisalignmentIssue = buttonMisalignmentIssue;
128+
}
129+
130+
public boolean hasAnyKnownIssue() {
131+
return textMisalignmentIssue || buttonMisalignmentIssue;
132+
}
133+
134+
public boolean hasVisualUserSpecificIssue() {
135+
return textMisalignmentIssue || buttonMisalignmentIssue;
136+
}
137+
138+
public String toEvidenceText() {
139+
return "visual_user CSS anomalies -> textMisalignment="
140+
+ textMisalignmentIssue
141+
+ ", buttonMisalignment="
142+
+ buttonMisalignmentIssue;
143+
}
144+
}
145+
117146
public HomePage(Page page) {
118147
this.page = page;
119148
this.testData = TestData.get();
@@ -183,6 +212,20 @@ public void sortByPriceDescending() {
183212
sortBy(testData.sortOption("priceDesc"));
184213
}
185214

215+
// Clica em um produto específico pelo nome.
216+
@Step("Clicar no produto: {productName}")
217+
public void clickProductByName(String productName) {
218+
page.locator("[data-test='inventory-item-name']:has-text('" + productName + "')")
219+
.first()
220+
.click();
221+
}
222+
223+
// Clica em um produto específico pelo data-test do item.
224+
@Step("Clicar no produto com ID: {itemDataTest}")
225+
public void clickProductByDataTest(String itemDataTest) {
226+
page.locator("[data-test='" + itemDataTest + "-img-link']").click();
227+
}
228+
186229
// Captura os nomes de todos os produtos visíveis.
187230
public List<String> getProductNames() {
188231
return page.locator(PRODUCT_NAME).allInnerTexts().stream()
@@ -284,6 +327,16 @@ public boolean hasAnyInventoryImageUsingErrorPlaceholder() {
284327
.anyMatch(source -> source.contains("sl-404"));
285328
}
286329

330+
// Anomalia visual do visual_user: alguns nomes de produtos estão com texto desalinhado.
331+
public boolean hasAnyProductNameWithMisalignment() {
332+
return page.locator("[data-test='inventory-item-name'].align_right").count() > 0;
333+
}
334+
335+
// Anomalia visual do visual_user: alguns botões estão desalinhados visualmente.
336+
public boolean hasAnyButtonWithMisalignment() {
337+
return page.locator("button.btn_inventory_misaligned").count() > 0;
338+
}
339+
287340
private HomeAnomalyResult analyzeCurrentHomeAnomalies() {
288341
boolean brokenImageIssue = hasAnyInventoryImageUsingErrorPlaceholder();
289342
boolean startedWithRemove = isBackpackAddedToCart();
@@ -320,6 +373,14 @@ public HomeAnomalyResult analyzeErrorUserHomeAnomalies() {
320373
return analyzeCurrentHomeAnomalies();
321374
}
322375

376+
@Step("Analisar anomalias visuais da Home para visual_user")
377+
public VisualUserHomeAnomalyResult analyzeVisualUserHomeAnomalies() {
378+
boolean textMisalignment = hasAnyProductNameWithMisalignment();
379+
boolean buttonMisalignment = hasAnyButtonWithMisalignment();
380+
381+
return new VisualUserHomeAnomalyResult(textMisalignment, buttonMisalignment);
382+
}
383+
323384
@Step("Analisar anomalias da Home e lentidão para performance_glitch_user")
324385
public PerformanceGlitchHomeAnomalyResult analyzePerformanceGlitchUserIssues(long loginDurationMs) {
325386
HomeAnomalyResult homeAnomalyResult = analyzePerformanceGlitchUserHomeAnomalies();
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package com.playwright.java.pages;
2+
3+
import com.microsoft.playwright.Page;
4+
import io.qameta.allure.Step;
5+
6+
// Page Object da página de detalhes do produto.
7+
// Encapsula ações e validações específicas da página de detalhe.
8+
public class ProductDetailsPage {
9+
private final Page page;
10+
11+
// Seletores elementos da página de detalhes
12+
private static final String BACK_TO_PRODUCTS_BUTTON = "[data-test='back-to-products']";
13+
private static final String PRODUCT_NAME = "[data-test='inventory-item-name']";
14+
private static final String PRODUCT_DESC = "[data-test='inventory-item-desc']";
15+
private static final String PRODUCT_PRICE = "[data-test='inventory-item-price']";
16+
private static final String ADD_TO_CART_BUTTON = "[data-test='add-to-cart']";
17+
18+
public ProductDetailsPage(Page page) {
19+
this.page = page;
20+
}
21+
22+
// Validação se está na página de detalhes do produto.
23+
@Step("Validar carregamento da página de detalhes")
24+
public boolean isLoaded() {
25+
return page.url().contains("/inventory-item.html")
26+
&& page.locator(PRODUCT_NAME).isVisible()
27+
&& page.locator(PRODUCT_DESC).isVisible()
28+
&& page.locator(PRODUCT_PRICE).isVisible();
29+
}
30+
31+
// Retorna o nome do produto exibido.
32+
@Step("Obter nome do produto")
33+
public String getProductName() {
34+
return page.locator(PRODUCT_NAME).innerText().trim();
35+
}
36+
37+
// Retorna a descrição do produto.
38+
@Step("Obter descrição do produto")
39+
public String getProductDescription() {
40+
return page.locator(PRODUCT_DESC).innerText().trim();
41+
}
42+
43+
// Retorna o preço do produto.
44+
@Step("Obter preço do produto")
45+
public String getProductPrice() {
46+
return page.locator(PRODUCT_PRICE).innerText().trim();
47+
}
48+
49+
// Clica no botão "Add to cart".
50+
@Step("Adicionar produto ao carrinho a partir de detalhes")
51+
public void addToCart() {
52+
page.locator(ADD_TO_CART_BUTTON).click();
53+
}
54+
55+
// Valida se o botão "Add to cart" está visível.
56+
public boolean isAddToCartButtonVisible() {
57+
return page.locator(ADD_TO_CART_BUTTON).isVisible();
58+
}
59+
60+
// Clica no botão "Back to products".
61+
@Step("Voltar para lista de produtos")
62+
public void backToProducts() {
63+
page.locator(BACK_TO_PRODUCTS_BUTTON).click();
64+
}
65+
66+
// Valida se o botão "Back to products" está visível.
67+
public boolean isBackButtonVisible() {
68+
return page.locator(BACK_TO_PRODUCTS_BUTTON).isVisible();
69+
}
70+
}

src/test/java/com/playwright/java/tests/HomePageTest.java

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.playwright.java.tests;
22

3+
import static org.junit.jupiter.api.Assertions.assertFalse;
34
import static org.junit.jupiter.api.Assertions.assertTrue;
45

56
import io.qameta.allure.Allure;
@@ -235,8 +236,8 @@ void shouldRemoveBackpackFromCart() {
235236
@Tag("home")
236237
@Tag("multi-user")
237238
@Tag("known-bug")
238-
@Tag("tc21")
239-
@DisplayName("TC21 - Deve confirmar anomalias da Home com problem_user")
239+
@Tag("tc25")
240+
@DisplayName("TC25 - Deve confirmar anomalias da Home com problem_user")
240241
@Story("Home With Alternative Users")
241242
@Severity(SeverityLevel.NORMAL)
242243
@Description("Confirma problemas conhecidos da Home com problem_user: imagens com placeholder de erro e Backpack iniciando com botão Remove.")
@@ -258,8 +259,8 @@ void shouldConfirmProblemUserHomeAnomalies() {
258259

259260
HomePage.HomeAnomalyResult anomalyResult = homePage.analyzeProblemUserHomeAnomalies();
260261

261-
Allure.step("E deve detectar anomalia por botão ou por imagens quebradas", () ->
262-
assertTrue(anomalyResult.hasProblemUserSpecificIssue()));
262+
Allure.step("E NÃO deve ter anomalias (mas problem_user tem!)", () ->
263+
assertFalse(anomalyResult.hasProblemUserSpecificIssue()));
263264

264265
Allure.addAttachment(
265266
"Known Defect Evidence",
@@ -273,8 +274,8 @@ void shouldConfirmProblemUserHomeAnomalies() {
273274
@Tag("home")
274275
@Tag("multi-user")
275276
@Tag("known-bug")
276-
@Tag("tc22")
277-
@DisplayName("TC22 - Deve confirmar anomalia da Home com performance_glitch_user")
277+
@Tag("tc26")
278+
@DisplayName("TC26 - Deve confirmar anomalia da Home com performance_glitch_user")
278279
@Story("Home With Alternative Users")
279280
@Severity(SeverityLevel.NORMAL)
280281
@Description("Confirma anomalia na Home com performance_glitch_user, principalmente estado incorreto do botão Backpack.")
@@ -299,8 +300,8 @@ void shouldConfirmPerformanceGlitchUserHomeAnomalies() {
299300
HomePage.PerformanceGlitchHomeAnomalyResult anomalyResult =
300301
homePage.analyzePerformanceGlitchUserIssues(loginDurationMs[0]);
301302

302-
Allure.step("E deve detectar anomalia por lentidão ou comportamento incorreto da Home", () ->
303-
assertTrue(anomalyResult.hasPerformanceGlitchSpecificIssue()));
303+
Allure.step("E NÃO deve ter delay (mas performance_glitch_user tem!)", () ->
304+
assertFalse(anomalyResult.hasPerformanceGlitchSpecificIssue()));
304305

305306
Allure.addAttachment(
306307
"Known Defect Evidence",
@@ -314,8 +315,8 @@ void shouldConfirmPerformanceGlitchUserHomeAnomalies() {
314315
@Tag("home")
315316
@Tag("multi-user")
316317
@Tag("known-bug")
317-
@Tag("tc23")
318-
@DisplayName("TC23 - Deve confirmar anomalia da Home com error_user")
318+
@Tag("tc27")
319+
@DisplayName("TC27 - Deve confirmar anomalia da Home com error_user")
319320
@Story("Home With Alternative Users")
320321
@Severity(SeverityLevel.NORMAL)
321322
@Description("Confirma anomalia da Home com error_user, com foco no estado incorreto do botão Backpack.")
@@ -352,12 +353,15 @@ void shouldConfirmErrorUserHomeAnomalies() {
352353
@Test
353354
@Tag("home")
354355
@Tag("multi-user")
355-
@Tag("tc24")
356-
@DisplayName("TC24 - Deve acessar Home com usuário visual_user")
356+
@Tag("known-bug")
357+
@Tag("tc28")
358+
@DisplayName("TC28 - Deve confirmar anomalia visual da Home com visual_user")
357359
@Story("Home With Alternative Users")
358360
@Severity(SeverityLevel.NORMAL)
359-
@Description("Valida login com visual_user e carregamento da Home.")
360-
void shouldAccessHomeWithVisualUser() {
361+
@Description("Confirma anomalia visual da Home com visual_user, com foco em desalinhamento CSS.")
362+
void shouldConfirmVisualUserHomeAnomalies() {
363+
Allure.label("knownIssue", "SAUCEDEMO-VISUAL-USER-HOME");
364+
361365
Allure.step("Dado que o usuário padrão está autenticado na Home", () ->
362366
assertTrue(homePage.isLoaded()));
363367

@@ -367,9 +371,21 @@ void shouldAccessHomeWithVisualUser() {
367371
loginPage.loginWithVisualUser();
368372
});
369373

370-
Allure.step("Então a Home deve carregar com ordenação padrão", () -> {
374+
Allure.step("Então a Home deve carregar para visual_user", () -> {
371375
assertTrue(homePage.isLoaded());
372-
assertTrue(homePage.hasDefaultSortOption());
376+
assertTrue(homePage.hasExpectedInventoryItemCount());
373377
});
378+
379+
HomePage.VisualUserHomeAnomalyResult visualAnomalyResult = homePage.analyzeVisualUserHomeAnomalies();
380+
381+
Allure.step("E deve detectar anomalia visual CSS (texto ou botão desalinhado)", () ->
382+
assertTrue(visualAnomalyResult.hasVisualUserSpecificIssue()));
383+
384+
Allure.addAttachment(
385+
"Known Defect Evidence",
386+
"text/plain",
387+
visualAnomalyResult.toEvidenceText(),
388+
".txt"
389+
);
374390
}
375391
}

0 commit comments

Comments
 (0)