From c1fea2c2bca8bbaac8eeeb773ab574841970d82b Mon Sep 17 00:00:00 2001 From: BrunoTiptc Date: Sat, 11 Apr 2026 19:42:54 -0300 Subject: [PATCH 1/3] fix: stabilize contact tests (selectors, navigation and validation events) --- tests/contact/contact.nofixture.spec.ts | 37 ++++++++--- tests/contact/contact.spec.ts | 36 +++++++--- tests/debug-qa/INDEX.md | 42 ++++++++++++ tests/debug-qa/README.md | 35 ++++++++++ tests/debug-qa/debug-submit.spec.ts | 43 ++++++++++++ tests/debug-qa/inspeciona-select.spec.ts | 22 +++++++ tests/debug-qa/inspect-thanks.spec.ts | 40 +++++++++++ tests/debug-qa/inspect.spec.ts | 44 +++++++++++++ tests/debug-qa/test-all-options.spec.ts | 52 +++++++++++++++ tests/debug-qa/test-multiplos-eventos.spec.ts | 66 +++++++++++++++++++ 10 files changed, 397 insertions(+), 20 deletions(-) create mode 100644 tests/debug-qa/INDEX.md create mode 100644 tests/debug-qa/README.md create mode 100644 tests/debug-qa/debug-submit.spec.ts create mode 100644 tests/debug-qa/inspeciona-select.spec.ts create mode 100644 tests/debug-qa/inspect-thanks.spec.ts create mode 100644 tests/debug-qa/inspect.spec.ts create mode 100644 tests/debug-qa/test-all-options.spec.ts create mode 100644 tests/debug-qa/test-multiplos-eventos.spec.ts diff --git a/tests/contact/contact.nofixture.spec.ts b/tests/contact/contact.nofixture.spec.ts index 0d5095d..8bbb594 100644 --- a/tests/contact/contact.nofixture.spec.ts +++ b/tests/contact/contact.nofixture.spec.ts @@ -1,16 +1,33 @@ import { test, expect } from "@playwright/test"; -test("Home Page Tests", async ({ page }) => { - await page.goto(""); +test("Contact form without fixture", async ({ page }) => { + const baseURL = "https://practicesoftwaretesting.com"; + await page.goto(baseURL); + await page.waitForLoadState('load'); - await page.getByTestId("nav-contact").click(); - await page.getByTestId("first-name").fill("Test"); - await page.getByTestId("last-name").fill("Mctester"); - await page.getByTestId("email").fill("asf@asdf.com"); - await page.getByTestId("subject").selectOption("payments"); - await page.getByTestId("message").fill("test".repeat(40)); - await page.getByTestId("contact-submit").click(); - await expect(page.locator(".alert-success")).toHaveText( + // Navigate to contact using accessible selector + await page.getByRole('link', { name: /contact/i }).click(); + await page.waitForLoadState('networkidle'); + + // Fill form using ID selectors (discovered via inspection) + await page.locator('#first_name').fill('Test'); + await page.locator('#last_name').fill('Mctester'); + await page.locator('#email').fill('asf@asdf.com'); + + // Select and dispatch multiple events to trigger validation + const subjectSelect = page.locator('#subject'); + await subjectSelect.selectOption({ label: 'Payments' }); + await subjectSelect.dispatchEvent('change'); + await subjectSelect.dispatchEvent('blur'); + await subjectSelect.dispatchEvent('input'); + + await page.locator('#message').fill('test'.repeat(40)); + + // Submit using submit input + await page.locator('input[type="submit"]').click(); + + // Verify success message + await expect(page.locator(".alert")).toContainText( "Thanks for your message! We will contact you shortly." ); }); diff --git a/tests/contact/contact.spec.ts b/tests/contact/contact.spec.ts index 89f5ba6..34da073 100644 --- a/tests/contact/contact.spec.ts +++ b/tests/contact/contact.spec.ts @@ -1,18 +1,34 @@ import { test } from "@fixtures/modifiedGoto"; import { expect } from "@playwright/test"; -test("Home Page Tests", async ({ page }) => { - await page.goto("/"); +test("Contact form with fixture", async ({ page }) => { + await page.goto("https://practicesoftwaretesting.com"); + await page.waitForLoadState('load'); expect(page.url()).toContain("?UTM_SOURCE=playwright"); - await page.getByTestId("nav-contact").click(); - await page.getByTestId("first-name").fill("Test"); - await page.getByTestId("last-name").fill("Mctester"); - await page.getByTestId("email").fill("asf@asdf.com"); - await page.getByTestId("subject").selectOption("payments"); - await page.getByTestId("message").fill("test".repeat(40)); - await page.getByTestId("contact-submit").click(); - await expect(page.locator(".alert-success")).toHaveText( + // Navigate to contact using accessible selector + await page.getByRole('link', { name: /contact/i }).click(); + await page.waitForLoadState('load'); + + // Fill form using ID selectors (discovered via inspection) + await page.locator('#first_name').fill('Test'); + await page.locator('#last_name').fill('Mctester'); + await page.locator('#email').fill('asf@asdf.com'); + + // Select and dispatch multiple events to trigger validation + const subjectSelect = page.locator('#subject'); + await subjectSelect.selectOption({ label: 'Payments' }); + await subjectSelect.dispatchEvent('change'); + await subjectSelect.dispatchEvent('blur'); + await subjectSelect.dispatchEvent('input'); + + await page.locator('#message').fill('test'.repeat(40)); + + // Submit using submit input + await page.locator('input[type="submit"]').click(); + + // Verify success message + await expect(page.locator(".alert")).toContainText( "Thanks for your message! We will contact you shortly." ); }); diff --git a/tests/debug-qa/INDEX.md b/tests/debug-qa/INDEX.md new file mode 100644 index 0000000..cfa2462 --- /dev/null +++ b/tests/debug-qa/INDEX.md @@ -0,0 +1,42 @@ +# 🧪 QA Debug Tests - Investigação do Select Subject + +## Descrição +Arquivos de debug criados durante investigação do problema com o campo Subject do formulário de contato. + +**Problema identificado:** O campo Subject retorna erro "Subject is required" mesmo após selectOption() ser executado com sucesso. + +## Arquivos + +### inspect.spec.ts +Inspeciona a estrutura HTML da página de contato (labels, inputs, botões, etc) + +### debug-submit.spec.ts +Testa o fluxo de submit e verifica qual mensagem de alerta aparece após submeter + +### test-all-options.spec.ts +Tenta submeter o formulário com TODAS as 6 opções de Subject diferentes para encontrar qual funciona + +### inspeciona-select.spec.ts +Inspeciona o HTML exato do elemento SELECT para verificar se é real ou elemento customizado + const tagName = await subjectSelector.evaluate((el) => el.tagName); + console.log(`\nTag name: ${tagName}`); + + // Get HTML interno + const innerHTML = await subjectSelector.evaluate((el) => el.innerHTML); + console.log("\nInner HTML:"); + console.log(innerHTML.substring(0, 500)); +}); diff --git a/tests/debug-qa/inspect-thanks.spec.ts b/tests/debug-qa/inspect-thanks.spec.ts new file mode 100644 index 0000000..5aef5d9 --- /dev/null +++ b/tests/debug-qa/inspect-thanks.spec.ts @@ -0,0 +1,40 @@ +import { test } from "@playwright/test"; + +test("Inspect where the thank-you message appears", async ({ page }) => { + await page.goto("https://practicesoftwaretesting.com"); + await page.waitForLoadState("load"); + + await page.getByRole("link", { name: /contact/i }).click(); + await page.waitForLoadState("load"); + + await page.locator("#first_name").fill("Test"); + await page.locator("#last_name").fill("Mctester"); + await page.locator("#email").fill("test@example.com"); + const subjectSelect = page.locator("#subject"); + await subjectSelect.selectOption({ label: "Payments" }); + await subjectSelect.dispatchEvent("change"); + await subjectSelect.dispatchEvent("blur"); + await subjectSelect.dispatchEvent("input"); + await page.locator("#message").fill("test".repeat(40)); + + await page.locator("input[type=\"submit\"]").click(); + await page.waitForLoadState("load"); + await page.waitForTimeout(2000); + + console.log(`urlAfterSubmit=${page.url()}`); + const pageTitle = await page.title(); + console.log(`titleAfterSubmit=${pageTitle}`); + + const thanksCount = await page.locator('text=Thanks for your message').count(); + console.log(`thanksCount=${thanksCount}`); + + const thanksTexts = await page.locator('text=Thanks').allTextContents(); + console.log(`thanksTexts=${JSON.stringify(thanksTexts)}`); + + const thankElementHandle = await page.locator('text=Thanks for your message').first(); + const outerHTML = await thankElementHandle.evaluate((el: any) => el.outerHTML); + console.log(`outerHTML=${outerHTML}`); + + const body = await page.locator("body").innerText(); + console.log(`body starts with: ${body.slice(0, 400).replace(/\n/g, ' ')}...`); +}); \ No newline at end of file diff --git a/tests/debug-qa/inspect.spec.ts b/tests/debug-qa/inspect.spec.ts new file mode 100644 index 0000000..f602fd8 --- /dev/null +++ b/tests/debug-qa/inspect.spec.ts @@ -0,0 +1,44 @@ +import { test } from "@playwright/test"; + +test("Inspect Contact Page Structure", async ({ page }) => { + await page.goto("https://practicesoftwaretesting.com"); + await page.waitForLoadState("networkidle"); + + console.log("\n=== HOME PAGE ==="); + console.log("Procurando links/botões Contact..."); + + const contactElements = await page + .locator("a, button") + .filter({ hasText: /contact/i }) + .all(); + console.log(`✓ Encontrados ${contactElements.length} elementos com "contact"`); + + for (let i = 0; i < contactElements.length; i++) { + const elem = contactElements[i]; + const text = await elem.textContent(); + const tag = await elem.evaluate((el) => el.tagName); + const href = await elem.getAttribute("href"); + console.log(` [${i}] <${tag}> "${text?.trim()}" href="${href}"`); + } + + if (contactElements.length > 0) { + await contactElements[0].click(); + await page.waitForLoadState("networkidle"); + + console.log("\n=== CONTACT PAGE ==="); + + const labels = await page.locator("label").all(); + console.log(`✓ Encontrados ${labels.length} labels`); + + const inputs = await page.locator("input, textarea, select").all(); + console.log(`✓ Encontrados ${inputs.length} campos`); + + for (let i = 0; i < inputs.length; i++) { + const input = inputs[i]; + const tag = await input.evaluate((el) => el.tagName); + const id = await input.getAttribute("id"); + const type = await input.getAttribute("type"); + console.log(` [${i}] <${tag}> id="${id}" type="${type}"`); + } + } +}); diff --git a/tests/debug-qa/test-all-options.spec.ts b/tests/debug-qa/test-all-options.spec.ts new file mode 100644 index 0000000..8e0b7f0 --- /dev/null +++ b/tests/debug-qa/test-all-options.spec.ts @@ -0,0 +1,52 @@ +import { test } from "@playwright/test"; + +test("Test ALL subject options to find working one", async ({ page }) => { + const optionsToTest = [ + "Customer service", + "Webmaster", + "Return", + "Payments", + "Warranty", + "Status of my order", + ]; + + for (const option of optionsToTest) { + console.log(`\n🧪 Testing option: "${option}"`); + + await page.goto("https://practicesoftwaretesting.com/contact"); + await page.waitForLoadState("networkidle"); + + await page.locator("#first_name").fill("Test"); + await page.locator("#last_name").fill("User"); + await page.locator("#email").fill("test@example.com"); + + try { + await page.locator("#subject").selectOption({ label: option }); + const value = await page.locator("#subject").inputValue(); + console.log(` ✓ Selected: value="${value}"`); + } catch (e) { + console.log(` ✗ Could not select`); + continue; + } + + await page.locator("#subject").dispatchEvent("change"); + await page.locator("#message").fill("test message"); + + await page.locator('input[type="submit"]').click(); + await page.waitForLoadState("networkidle"); + await page.waitForTimeout(1000); + + const alerts = await page.locator(".alert").all(); + if (alerts.length > 0) { + const alertText = await alerts[0].textContent(); + if (alertText?.includes("Thanks")) { + console.log(` 🎉 SUCCESS! Alert: "${alertText?.trim()}"`); + return; + } else { + console.log(` ❌ Alert: "${alertText?.trim()}"`); + } + } + } + + console.log("\n🔴 None of the options worked!"); +}); diff --git a/tests/debug-qa/test-multiplos-eventos.spec.ts b/tests/debug-qa/test-multiplos-eventos.spec.ts new file mode 100644 index 0000000..1b25c2f --- /dev/null +++ b/tests/debug-qa/test-multiplos-eventos.spec.ts @@ -0,0 +1,66 @@ +import { test, expect } from "@playwright/test"; + +test("Contact form com múltiplos eventos após select", async ({ page }) => { + await page.goto("https://practicesoftwaretesting.com"); + await page.waitForLoadState("networkidle"); + + await page.getByRole("link", { name: /contact/i }).click(); + await page.waitForLoadState("networkidle"); + + console.log("\n📝 Fill form..."); + await page.locator("#first_name").fill("Test"); + await page.locator("#last_name").fill("Mctester"); + await page.locator("#email").fill("test@example.com"); + + const subjectSelect = page.locator("#subject"); + + // Check required attribute + const isRequired = await subjectSelect.evaluate( + (el: any) => el.hasAttribute("required") + ); + console.log(`Subject has required: ${isRequired}`); + + // Select option + await subjectSelect.selectOption({ label: "Payments" }); + const value1 = await subjectSelect.inputValue(); + console.log(`✓ After selectOption: value="${value1}"`); + + // Dispatch multiple events + console.log("🔄 Dispatching events: change, blur, input..."); + await subjectSelect.dispatchEvent("change"); + await subjectSelect.dispatchEvent("blur"); + await subjectSelect.dispatchEvent("input"); + + // Alternative: try to focus and trigger + await subjectSelect.focus(); + await page.waitForTimeout(100); + await subjectSelect.blur(); + + const value2 = await subjectSelect.inputValue(); + console.log(`✓ After all events: value="${value2}"`); + + await page.locator("#message").fill("test".repeat(40)); + + console.log("📮 Submitting..."); + await page.locator('input[type="submit"]').click(); + + await page.waitForLoadState("networkidle"); + await page.waitForTimeout(1500); + + // Check result + const alerts = await page.locator(".alert").all(); + console.log(`Found ${alerts.length} alerts`); + + for (const alert of alerts) { + const text = await alert.textContent(); + console.log(`Alert: "${text?.trim()}"`); + + if (text?.includes("Thanks")) { + console.log("🎉 SUCCESS!"); + expect(text).toContain("Thanks for your message"); + return; + } + } + + console.log("❌ Still failed"); +}); From 2a76ebdcec92c0ee8c9e0dc22dc543351fe45246 Mon Sep 17 00:00:00 2001 From: BrunoTiptc Date: Sat, 11 Apr 2026 19:46:40 -0300 Subject: [PATCH 2/3] fix: stabilize contact tests (selectors, navigation and validation events) --- tests/contact/contact.nofixture.spec.ts | 2 +- tests/contact/contact.spec.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/contact/contact.nofixture.spec.ts b/tests/contact/contact.nofixture.spec.ts index 8bbb594..d1585cf 100644 --- a/tests/contact/contact.nofixture.spec.ts +++ b/tests/contact/contact.nofixture.spec.ts @@ -27,7 +27,7 @@ test("Contact form without fixture", async ({ page }) => { await page.locator('input[type="submit"]').click(); // Verify success message - await expect(page.locator(".alert")).toContainText( + await expect(page.locator(".alert.alert-success")).toContainText( "Thanks for your message! We will contact you shortly." ); }); diff --git a/tests/contact/contact.spec.ts b/tests/contact/contact.spec.ts index 34da073..38483bc 100644 --- a/tests/contact/contact.spec.ts +++ b/tests/contact/contact.spec.ts @@ -28,7 +28,7 @@ test("Contact form with fixture", async ({ page }) => { await page.locator('input[type="submit"]').click(); // Verify success message - await expect(page.locator(".alert")).toContainText( + await expect(page.locator(".alert.alert-success")).toContainText( "Thanks for your message! We will contact you shortly." ); }); From ac9b85ade0abe8f8c9b8c99ce9b71dcf1305029e Mon Sep 17 00:00:00 2001 From: BrunoTiptc Date: Sat, 11 Apr 2026 19:49:33 -0300 Subject: [PATCH 3/3] fix: stabilize contact tests (selectors, navigation and validation events) --- tests/contact/contact.nofixture.spec.ts | 3 +- tests/contact/contact.spec.ts | 3 +- tests/debug-qa/inspect-with-fixture.spec.ts | 32 +++++++++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 tests/debug-qa/inspect-with-fixture.spec.ts diff --git a/tests/contact/contact.nofixture.spec.ts b/tests/contact/contact.nofixture.spec.ts index d1585cf..13382c1 100644 --- a/tests/contact/contact.nofixture.spec.ts +++ b/tests/contact/contact.nofixture.spec.ts @@ -25,7 +25,8 @@ test("Contact form without fixture", async ({ page }) => { // Submit using submit input await page.locator('input[type="submit"]').click(); - + await page.waitForSelector('.alert.alert-success', { timeout: 10000 }); + // Verify success message await expect(page.locator(".alert.alert-success")).toContainText( "Thanks for your message! We will contact you shortly." diff --git a/tests/contact/contact.spec.ts b/tests/contact/contact.spec.ts index 38483bc..8a1069f 100644 --- a/tests/contact/contact.spec.ts +++ b/tests/contact/contact.spec.ts @@ -26,7 +26,8 @@ test("Contact form with fixture", async ({ page }) => { // Submit using submit input await page.locator('input[type="submit"]').click(); - + await page.waitForSelector('.alert.alert-success', { timeout: 10000 }); + // Verify success message await expect(page.locator(".alert.alert-success")).toContainText( "Thanks for your message! We will contact you shortly." diff --git a/tests/debug-qa/inspect-with-fixture.spec.ts b/tests/debug-qa/inspect-with-fixture.spec.ts new file mode 100644 index 0000000..45478fe --- /dev/null +++ b/tests/debug-qa/inspect-with-fixture.spec.ts @@ -0,0 +1,32 @@ +import { test } from "@fixtures/modifiedGoto"; + +test("Inspect contact submit with modifiedGoto fixture", async ({ page }) => { + await page.goto("https://practicesoftwaretesting.com"); + await page.waitForLoadState("load"); + + await page.getByRole("link", { name: /contact/i }).click(); + await page.waitForLoadState("load"); + + await page.locator("#first_name").fill("Test"); + await page.locator("#last_name").fill("Mctester"); + await page.locator("#email").fill("test@example.com"); + + const subjectSelect = page.locator("#subject"); + await subjectSelect.selectOption({ label: "Payments" }); + await subjectSelect.dispatchEvent("change"); + await subjectSelect.dispatchEvent("blur"); + await subjectSelect.dispatchEvent("input"); + + await page.locator("#message").fill("test".repeat(40)); + await page.locator('input[type="submit"]').click(); + await page.waitForLoadState("load"); + await page.waitForTimeout(2000); + + console.log(`urlAfterSubmit=${page.url()}`); + const thanksCount = await page.locator('text=Thanks for your message').count(); + console.log(`thanksCount=${thanksCount}`); + const alertCount = await page.locator('.alert.alert-success').count(); + console.log(`alertCount=${alertCount}`); + const hasAlertText = await page.locator('.alert.alert-success', { hasText: 'Thanks for your message' }).count(); + console.log(`hasAlertText=${hasAlertText}`); +}); \ No newline at end of file