1"use strict";(globalThis.webpackChunkserenity_users_guide=globalThis.webpackChunkserenity_users_guide||[]).push([[3975],{7269(e,a,n){n.r(a),n.d(a,{assets:()=>l,contentTitle:()=>t,default:()=>p,frontMatter:()=>o,metadata:()=>s,toc:()=>d});const s=JSON.parse('{"id":"playwright/playwright_best_practices","title":"Mejores practicas","description":"Esta guia cubre las mejores practicas para escribir pruebas de Serenity Playwright mantenibles, confiables y eficientes.","source":"@site/i18n/es/docusaurus-plugin-content-docs/current/playwright/best-practices.md","sourceDirName":"playwright","slug":"/playwright/playwright_best_practices","permalink":"/es/docs/playwright/playwright_best_practices","draft":false,"unlisted":false,"editUrl":"https://github.com/serenity-bdd/serenity-bdd.github.io/blob/master/docs/playwright/best-practices.md","tags":[],"version":"current","sidebarPosition":6,"frontMatter":{"id":"playwright_best_practices","title":"Mejores practicas","sidebar_position":6},"sidebar":"tutorialSidebar","previous":{"title":"Configuracion","permalink":"/es/docs/playwright/playwright_configuration"},"next":{"title":"Tutorial: Probando TodoMVC","permalink":"/es/docs/playwright/playwright_tutorial_todomvc"}}');var r=n(4848),i=n(8453);const o={id:"playwright_best_practices",title:"Mejores practicas",sidebar_position:6},t="Mejores practicas",l={},d=[{value:"Arquitectura de pruebas",id:"arquitectura-de-pruebas",level:2},{value:"Sigue el patron de tres capas",id:"sigue-el-patron-de-tres-capas",level:3},{value:"Manten las pruebas enfocadas",id:"manten-las-pruebas-enfocadas",level:3},{value:"Gestion de navegadores",id:"gestion-de-navegadores",level:2},{value:"Comparte el navegador, aisla las paginas",id:"comparte-el-navegador-aisla-las-paginas",level:3},{value:"Usa contextos de navegador para aislamiento",id:"usa-contextos-de-navegador-para-aislamiento",level:3},{value:"Extrae la configuracion comun a una clase base",id:"extrae-la-configuracion-comun-a-una-clase-base",level:3},{value:"Estrategias de localizacion",id:"estrategias-de-localizacion",level:2},{value:"Prefiere localizadores resistentes",id:"prefiere-localizadores-resistentes",level:3},{value:"Evita localizadores fragiles",id:"evita-localizadores-fragiles",level:3},{value:"Usa localizadores encadenados para contexto",id:"usa-localizadores-encadenados-para-contexto",level:3},{value:"Estrategias de espera",id:"estrategias-de-espera",level:2},{value:"Confia en la espera automatica de Playwright",id:"confia-en-la-espera-automatica-de-playwright",level:3},{value:"Usa esperas explicitas cuando sea necesario",id:"usa-esperas-explicitas-cuando-sea-necesario",level:3},{value:"Manejo de errores",id:"manejo-de-errores",level:2},{value:"Proporciona aserciones claras",id:"proporciona-aserciones-claras",level:3},{value:"Maneja fallos esperados con elegancia",id:"maneja-fallos-esperados-con-elegancia",level:3},{value:"Consejos de rendimiento",id:"consejos-de-rendimiento",level:2},{value:"Usa modo headless en CI",id:"usa-modo-headless-en-ci",level:3},{value:"Minimiza los lanzamientos de navegador",id:"minimiza-los-lanzamientos-de-navegador",level:3},{value:"Usa simulacion de red para velocidad",id:"usa-simulacion-de-red-para-velocidad",level:3},{value:"Organizacion de pruebas",id:"organizacion-de-pruebas",level:2},{value:"Usa nombres de prueba descriptivos",id:"usa-nombres-de-prueba-descriptivos",level:3},{value:"Agrupa pruebas relacionadas",id:"agrupa-pruebas-relacionadas",level:3},{value:"Integracion CI/CD",id:"integracion-cicd",level:2},{value:"Configura para entornos CI",id:"configura-para-entornos-ci",level:3},{value:"Genera reportes en CI",id:"genera-reportes-en-ci",level:3},{value:"Errores comunes",id:"errores-comunes",level:2},{value:"Evita interdependencias entre pruebas",id:"evita-interdependencias-entre-pruebas",level:3},{value:"No ignores pruebas inestables",id:"no-ignores-pruebas-inestables",level:3},{value:"Limpia los datos de prueba",id:"limpia-los-datos-de-prueba",level:3}];function c(e){const a={code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(a.header,{children:(0,r.jsx)(a.h1,{id:"mejores-practicas",children:"Mejores practicas"})}),"\n",(0,r.jsx)(a.p,{children:"Esta guia cubre las mejores practicas para escribir pruebas de Serenity Playwright mantenibles, confiables y eficientes."}),"\n",(0,r.jsx)(a.h2,{id:"arquitectura-de-pruebas",children:"Arquitectura de pruebas"}),"\n",(0,r.jsx)(a.h3,{id:"sigue-el-patron-de-tres-capas",children:"Sigue el patron de tres capas"}),"\n",(0,r.jsx)(a.p,{children:"Siempre estructura tu codigo en tres capas:"}),"\n",(0,r.jsx)(a.pre,{children:(0,r.jsx)(a.code,{children:"Pruebas (escenarios de negocio)\n \u2514\u2500\u2500 Step Library (reportes con @Step)\n \u2514\u2500\u2500 Page Object (localizadores y acciones)\n"})}),"\n",(0,r.jsx)(a.p,{children:"Esta separacion proporciona:"}),"\n",(0,r.jsxs)(a.ul,{children:["\n",(0,r.jsxs)(a.li,{children:[(0,r.jsx)(a.strong,{children:"Mantenibilidad"})," - Los cambios en la UI solo afectan a los Page Object"]}),"\n",(0,r.jsxs)(a.li,{children:[(0,r.jsx)(a.strong,{children:"Legibilidad"})," - Las pruebas se leen como especificaciones"]}),"\n",(0,r.jsxs)(a.li,{children:[(0,r.jsx)(a.strong,{children:"Reusabilidad"})," - Los pasos y Page Object se pueden compartir"]}),"\n"]}),"\n",(0,r.jsx)(a.h3,{id:"manten-las-pruebas-enfocadas",children:"Manten las pruebas enfocadas"}),"\n",(0,r.jsx)(a.p,{children:"Cada prueba debe verificar un comportamiento especifico:"}),"\n",(0,r.jsx)(a.pre,{children:(0,r.jsx)(a.code,{className:"language-java",children:'// \u274c Mal: Probando demasiadas cosas\n@Test\nvoid testEverything() {\n login();\n searchForProduct();\n addToCart();\n checkout();\n verifyOrderConfirmation();\n logout();\n verifyLoggedOut();\n}\n\n// \u2705 Bien: Pruebas enfocadas\n@Test\nvoid shouldAddProductToCart() {\n // Given\n products.searchFor(page, "laptop");\n\n // When\n cart.addFirstResultToCart(page);\n\n // Then\n cart.verifyCartContains(page, "laptop");\n}\n\n@Test\nvoid shouldCompleteCheckout() {\n // Given\n cart.hasItemsInCart(page);\n\n // When\n checkout.completeOrder(page);\n\n // Then\n checkout.verifyOrderConfirmation(page);\n}\n'})}),"\n",(0,r.jsx)(a.h2,{id:"gestion-de-navegadores",children:"Gestion de navegadores"}),"\n",(0,r.jsx)(a.h3,{id:"comparte-el-navegador-aisla-las-paginas",children:"Comparte el navegador, aisla las paginas"}),"\n",(0,r.jsx)(a.p,{children:"Crea el navegador una vez por clase de prueba, pero crea una pagina nueva para cada prueba:"}),"\n",(0,r.jsx)(a.pre,{children:(0,r.jsx)(a.code,{className:"language-java",children:"@ExtendWith(SerenityJUnit5Extension.class)\nclass ProductTests {\n\n private static Playwright playwright;\n private static Browser browser;\n private Page page;\n\n @BeforeAll\n static void setupBrowser() {\n // Crear navegador una vez - operacion costosa\n playwright = Playwright.create();\n browser = playwright.chromium().launch(\n new BrowserType.Launc
1hOptions().setHeadless(true)\n );\n }\n\n @AfterAll\n static void closeBrowser() {\n // Cerrar navegador despues de todas las pruebas\n if (browser != null) browser.close();\n if (playwright != null) playwright.close();\n }\n\n @BeforeEach\n void setupPage() {\n // Pagina nueva para cada prueba - aislamiento de pruebas\n page = browser.newPage();\n PlaywrightSerenity.registerPage(page);\n }\n\n @AfterEach\n void closePage() {\n // Limpiar despues de cada prueba\n PlaywrightSerenity.unregisterPage(page);\n if (page != null) page.close();\n }\n}\n"})}),"\n",(0,r.jsx)(a.h3,{id:"usa-contextos-de-navegador-para-aislamiento",children:"Usa contextos de navegador para aislamiento"}),"\n",(0,r.jsx)(a.p,{children:"Para aislamiento completo de pruebas, usa contextos de navegador:"}),"\n",(0,r.jsx)(a.pre,{children:(0,r.jsx)(a.code,{className:"language-java",children:"@BeforeEach\nvoid setup() {\n // Cada contexto esta completamente aislado\n BrowserContext context = browser.newContext();\n page = context.newPage();\n PlaywrightSerenity.registerPage(page);\n}\n\n@AfterEach\nvoid cleanup() {\n PlaywrightSerenity.unregisterPage(page);\n BrowserContext context = page.context();\n page.close();\n context.close(); // Cierra todas las paginas y limpia cookies/storage\n}\n"})}),"\n",(0,r.jsx)(a.h3,{id:"extrae-la-configuracion-comun-a-una-clase-base",children:"Extrae la configuracion comun a una clase base"}),"\n",(0,r.jsx)(a.p,{children:"Para reducir codigo repetitivo entre clases de prueba, crea una clase base que maneje el ciclo de vida de Playwright:"}),"\n",(0,r.jsx)(a.pre,{children:(0,r.jsx)(a.code,{className:"language-java",children:"public abstract class SerenityPlaywrightTest {\n\n protected Playwright playwright;\n protected Browser browser;\n protected Page page;\n\n @BeforeEach\n void setUpPlaywright() {\n playwright = Playwright.create();\n browser = playwright.chromium().launch(\n new BrowserType.LaunchOptions().setHeadless(true)\n );\n page = browser.newPage();\n PlaywrightSerenity.registerPage(page);\n }\n\n @AfterEach\n void tearDownPlaywright() {\n PlaywrightSerenity.unregisterPage(page);\n if (page != null) page.close();\n if (browser != null) browser.close();\n if (playwright != null) playwright.close();\n }\n}\n"})}),"\n",(0,r.jsx)(a.p,{children:"Las clases de prueba entonces extienden esta base y solo conectan sus Step Library:"}),"\n",(0,r.jsx)(a.pre,{children:(0,r.jsx)(a.code,{className:"language-java",children:'@ExtendWith(SerenityJUnit5Extension.class)\n@DisplayName("When adding todos")\nclass WhenAddingTodosTest extends SerenityPlaywrightTest {\n\n @Steps\n TodoSteps todo;\n\n @BeforeEach\n void setUp() {\n todo.setPage(page); // Conectar Step Library a la pagina\n }\n\n @Test\n void shouldAddTodoItem() {\n todo.openApplication();\n todo.addTodo("Buy milk");\n\n assertThat(todo.visibleTodoCount()).isEqualTo(1);\n }\n}\n'})}),"\n",(0,r.jsx)(a.p,{children:"Este patron:"}),"\n",(0,r.jsxs)(a.ul,{children:["\n",(0,r.jsxs)(a.li,{children:[(0,r.jsx)(a.strong,{children:"Centraliza la gestion del ciclo de vida"})," - Los cambios en la configuracion del navegador solo necesitan hacerse en un lugar"]}),"\n",(0,r.jsxs)(a.li,{children:[(0,r.jsx)(a.strong,{children:"Asegura limpieza apropiada"}
1)," - La clase base garantiza que los recursos se liberen"]}),"\n",(0,r.jsxs)(a.li,{children:[(0,r.jsx)(a.strong,{children:"Reduce codigo repetitivo en clases de prueba"})," - Cada clase de prueba se enfoca en la logica de prueba"]}),"\n",(0,r.jsxs)(a.li,{children:[(0,r.jsxs)(a.strong,{children:["Hace la ",(0,r.jsx)(a.code,{children:"page"})," accesible"]})," - El campo protegido esta disponible para todas las subclases"]}),"\n"]}),"\n",(0,r.jsx)(a.h2,{id:"estrategias-de-localizacion",children:"Estrategias de localizacion"}),"\n",(0,r.jsx)(a.h3,{id:"prefiere-localizadores-resistentes",children:"Prefiere localizadores resistentes"}),"\n",(0,r.jsx)(a.p,{children:"Usa localizadores en este orden de preferencia:"}),"\n",(0,r.jsxs)(a.ol,{children:["\n",(0,r.jsxs)(a.li,{children:[(0,r.jsx)(a.strong,{children:"Basados en rol"})," - Mas resistentes, usan semantica de accesibilidad"]}),"\n",(0,r.jsxs)(a.li,{children:[(0,r.jsx)(a.strong,{children:"Basados en texto"})," - Buenos para texto visible al usuario"]}),"\n",(0,r.jsxs)(a.li,{children:[(0,r.jsx)(a.strong,{children:"Basados en etiqueta"})," - Buenos para campos de formulario"]}),"\n",(0,r.jsxs)(a.li,{children:[(0,r.jsx)(a.strong,{children:"Test ID"})," - Buenos para elementos sin significado semantico"]}),"\n",(0,r.jsxs)(a.li,{children:[(0,r.jsx)(a.strong,{children:"CSS/XPath"})," - Ultimo recurso"]}
1),"\n"]}),"\n",(0,r.jsx)(a.pre,{children:(0,r.jsx)(a.code,{className:"language-java",children:'// 1. Basado en rol (mejor)\npage.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Submit"));\n\n// 2. Basado en texto\npage.getByText("Add to Cart");\n\n// 3. Basado en etiqueta\npage.getByLabel("Email address");\n\n// 4. Test ID\npage.getByTestId("checkout-button");\n\n// 5. CSS (evitar si es posible)\npage.locator("button.submit-btn");\n'})}),"\n",(0,r.jsx)(a.h3,{id:"evita-localizadores-fragiles",children:"Evita localizadores fragiles"}),"\n",(0,r.jsx)(a.pre,{children:(0,r.jsx)(a.code,{className:"language-java",children:'// \u274c Localizadores fragiles\npage.locator("div:nth-child(3) > button");\npage.locator(".btn-primary");\npage.locator("//div[@class=\'container\']/form/button[2]");\n\n// \u2705 Localizadores resistentes\npage.getByRole(AriaRole.BUTTON, opts -> opts.setName("Place Order"));\npage.getByTestId("place-order-button");\n'})}),"\n",(0,r.jsx)(a.h3,{id:"usa-localizadores-encadenados-para-contexto",children:"Usa localizadores encadenados para contexto"}),"\n",(0,r.jsx)(a.p,{children:"Cuando el mismo tipo de elemento aparece multiples veces:"}),"\n",(0,r.jsx)(a.pre,{children:(0,r.jsx)(a.code,{className:"language-java",children:'// Encontrar el boton "Add" dentro de la primera tarjeta de producto\npage.locator("[data-testid=\'product-card\']").first()\n .getByRole(AriaRole.BUTTON, new GetByRoleOptions().setName("Add"));\n\n// Encontrar el campo email en la seccion de envio\npage.locator("#shipping-section")\n .getByLabel("Email");\n'})}),"\n",(0,r.jsx)(a.h2,{id:"estrategias-de-espera",children:"Estrategias de espera"}),"\n",(0,r.jsx)(a.h3,{id:"confia-en-la-espera-automatica-de-playwright",children:"Confia en la espera automatica de Playwright"}),"\n",(0,r.jsx)(a.p,{children:"Playwright espera automaticamente a que los elementos sean accionables. No agregues esperas innecesarias:"}),"\n",(0,r.jsx)(a.pre,{children:(0,r.jsx)(a.code,{className:"language-java",children:'// \u274c Innecesario - Playwright ya espera\nThread.sleep(2000);\npage.locator("#button").waitFor();\npage.locator("#button").click();\n\n// \u2705 Solo haz clic - Playwright espera automaticamente\npage.locator("#button").click();\n'})}),"\n",(0,r.jsx)(a.h3,{id:"usa-esperas-explicitas-cuando-sea-necesario",children:"Usa esperas explicitas cuando sea necesario"}),"\n",(0,r.jsx)(a.p,{children:"Para condiciones especificas, usa esperas explicitas:"}),"\n",(0,r.jsx)(a.pre,{children:(0,r.jsx)(a.code,{className:"language-java",children:'// Esperar a que la navegacion se complete\npage.waitForURL("**/checkout");\n\n// Esperar a que las peticiones de red terminen\npage.waitForLoadState(LoadState.NETWORKIDLE);\n\n// Esperar una condicion especifica\npage.waitForCondition(() -> getItemCount() >= 5);\n\n// Esperar a que un elemento se oculte\nloadingSpinner().waitFor(new WaitForOptions()\n .setState(WaitForSelectorState.HIDDEN));\n'})}),"\n",(0,r.jsx)(a.h2,{id:"manejo-de-errores",children:"Manejo de errores"}),"\n",(0,r.jsx)(a.h3,{id:"proporciona-aserciones-claras",children:"Proporciona aserciones claras"}),"\n",(0,r.jsx)(a.p,{children:"Usa mensajes de asercion descriptivos:"}),"\n",(0,r.jsx)(a.pre,{children:(0,r.jsx)(a.code,{className:"language-java",children:'@Step("Verify cart total is ${1}")\npublic void verifyCartTotal(Page page, BigDecimal expected) {\n BigDecimal actual = cartPage.getTotal();\n assertThat(actual)\n .as("Cart total should be $%s but was $%s", expected, actual)\n .isEqualByComparingTo(expected);\n}\n'})}),"\n",(0,r.jsx)(a.h3,{id:"maneja-fallos-esperados-con-elegancia",children:"Maneja fallos esperados con elegancia"}),"\n",(0,r.jsx)(a.pre,{children:(0,r.jsx)(a.code,{className:"language-java",children:'@Step("Verify error message is shown")\npublic void verifyErrorMessage(Page page, String expectedMessage) {\n Locator errorLocator = page.locator(".error-message");\n\n assertThat(errorLocator.isVisible())\n .as("Error message should be visible")\n .isTrue();\n\n assertThat(errorLocator.textContent())\n .as("Error message content")\n .contains(expectedMessage);\n}\n'})}),"\n",(0,r.jsx)(a.h2,{id:"consejos-de-rendimiento",children:"Consejos de rendimiento"}),"\n",(0,r.jsx)(a.h3,{id:"usa-modo-headless-en-ci",children:"Usa modo headless en CI"}),"\n",(0,r.jsx)(a.pre,{children:(0,r.jsx)(a.code,{className:"language-java",children:'boolean isCI = System.getenv("CI") != null;\nbrowser = playwright.chromium().launch(\n new BrowserType.Launc
1hOptions().setHeadless(isCI)\n);\n'})}),"\n",(0,r.jsx)(a.h3,{id:"minimiza-los-lanzamientos-de-navegador",children:"Minimiza los lanzamientos de navegador"}),"\n",(0,r.jsx)(a.p,{children:"Los lanzamientos de navegador son costosos. Comparte navegadores entre pruebas:"}),"\n",(0,r.jsx)(a.pre,{children:(0,r.jsx)(a.code,{className:"language-java",children:"// Un navegador por clase de prueba\n@BeforeAll\nstatic void launchBrowser() { ... }\n\n// NO: Un navegador por prueba\n@BeforeEach\nvoid launchBrowser() { ... } // \u274c Lento!\n"})}),"\n",(0,r.jsx)(a.h3,{id:"usa-simulacion-de-red-para-velocidad",children:"Usa simulacion de red para velocidad"}),"\n",(0,r.jsx)(a.p,{children:"Simula llamadas API lentas en las pruebas:"}),"\n",(0,r.jsx)(a.pre,{children:(0,r.jsx)(a.code,{className:"language-java",children:'@BeforeEach\nvoid setupMocks() {\n // Simular endpoint de API lento\n page.route("**/api/recommendations", route -> {\n route.fulfill(new FulfillOptions()\n .setStatus(200)\n .setBody("[]"));\n });\n}\n'})}),"\n",(0,r.jsx)(a.h2,{id:"organizacion-de-pruebas",children:"Organizacion de pruebas"}),"\n",(0,r.jsx)(a.h3,{id:"usa-nombres-de-prueba-descriptivos",children:"Usa nombres de prueba descriptivos"}),"\n",(0,r.jsx)(a.pre,{children:(0,r.jsx)(a.code,{className:"language-java",children:'@Test\n@DisplayName("Should display error when login fails with invalid password")\nvoid shouldDisplayErrorWhenLoginFailsWithInvalidPassword() {\n // ...\n}\n\n@Test\n@DisplayName("Should redirect to dashboard after successful login")\nvoid shouldRedirectToDashboardAfterSuccessfulLogin() {\n // ...\n}\n'})}),"\n",(0,r.jsx)(a.h3,{id:"agrupa-pruebas-relacionadas",children:"Agrupa pruebas relacionadas"}),"\n",(0,r.jsx)(a.pre,{children:(0,r.jsx)(a.code,{className:"language-java",children:'@Nested\n@DisplayName("When user is logged in")\nclass WhenLoggedIn {\n\n @BeforeEach\n void login() {\n auth.loginAs(page, testUser);\n }\n\n @Test\n void shouldDisplayWelcomeMessage() { ... }\n\n @Test\n void shouldShowOrderHistory() { ... }\n}\n\n@Nested\n@DisplayName("When user is not logged in")\nclass WhenNotLoggedIn {\n\n @Test\n void shouldShowLoginPrompt() { ... }\n\n @Test\n void shouldRedirectToLoginPage() { ... }\n}\n'})}),"\n",(0,r.jsx)(a.h2,{id:"integracion-cicd",children:"Integracion CI/CD"}),"\n",(0,r.jsx)(a.h3,{id:"configura-para-entornos-ci",children:"Configura para entornos CI"}),"\n",(0,r.jsx)(a.pre,{children:(0,r.jsx)(a.code,{className:"language-java",children:'@BeforeAll\nstatic void setup() {\n playwright = Playwright.create();\n\n BrowserType.LaunchOptions options = new BrowserType.LaunchOptions()\n .setHeadless(true)\n .setArgs(Arrays.asList(\n "--no-sandbox",\n "--disable-dev-shm-usage"\n ));\n\n browser = playwright.chromium().launch(options);\n}\n'})}),"\n",(0,r.jsx)(a.h3,{id:"genera-reportes-en-ci",children:"Genera reportes en CI"}),"\n",(0,r.jsx)(a.pre,{children:(0,r.jsx)(a.code,{className:"language-yaml",children:"# Ejemplo de GitHub Actions\n- name: Run Tests\n run: mvn verify\n\n- name: Upload Serenity Reports\n uses: actions/upload-artifact@v3\n if: always()\n with:\n name: serenity-reports\n path: target/site/serenity/\n"})}),"\n",(0,r.jsx)(a.h2,{id:"errores-comunes",children:"Errores comunes"}),"\n",(0,r.jsx)(a.h3,{id:"evita-interdependencias-entre-pruebas",children:"Evita interdependencias entre pruebas"}),"\n",(0,r.jsx)(a.pre,{children:(0,r.jsx)(a.code,{className:"language-java",children:"// \u274c Mal: Las pruebas dependen unas de otras\n@Test\n@Order(1)\nvoid createUser() {\n createdUserId = userService.create(user);\n}\n\n@Test\n@Order(2)\nvoid verifyUser() {\n userService.get(createdUserId); // Falla si la primera prueba falla\n}\n\n// \u2705 Bien: Cada prueba es independiente\n@Test\nvoid shouldCreateAndVerifyUser() {\n String userId = userService.create(user);\n User retrieved = userService.get(userId);\n assertThat(retrieved).isEqualTo(user);\n}\n"})}),"\n",(0,r.jsx)(a.h3,{id:"no-ignores-pruebas-inestables",children:"No ignores pruebas inestables"}),"\n",(0,r.jsx)(a.p,{children:"Aborda las pruebas inestables inmediatamente:"}),"\n",(0,r.jsx)(a.pre,{children:(0,r.jsx)(a.code,{className:"language-java",children:'// \u274c No hagas esto\n@Disabled("Flaky - investigate later")\n@Test\nvoid sometimesFailingTest() { ... }\n\n// \u2705 Arregla la causa raiz\n@Test\nvoid fixedTest() {\n // Espera una condicion especifica en lugar de sleep arbitrario\n page.waitForLoadState(LoadState.NETWORKIDLE);\n // Ahora realiza la asercion\n}\n'})}),"\n",(0,r.jsx)(a.h3,{id:"limpia-los-datos-de-prueba",children:"Limpia los datos de prueba"}),"\n",(0,r.jsx)(a.pre,{children:(0,r.jsx)(a.code,{className:"language-java",children:"@AfterEach\nvoid cleanup() {\
1n // Limpiar cualquier dato de prueba creado\n if (createdOrderId != null) {\n orderService.delete(createdOrderId);\n }\n}\n"})})]})}function p(e={}){const{wrapper:a}={...(0,i.R)(),...e.components};return a?(0,r.jsx)(a,{...e,children:(0,r.jsx)(c,{...e})}):c(e)}},8453(e,a,n){n.d(a,{R:()=>o,x:()=>t});var s=n(6540);const r={},i=s.createContext(r);function o(e){const a=s.useContext(i);return s.useMemo(function(){return"function"==typeof e?e(a):{...a,...e}},[a,e])}function t(e){let a;return a=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),s.createElement(i.Provider,{value:a},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.