DMF_Crawler/docs/research/_raw/tdd-red/playwright-best-practices.raw.html
Yun Chan 56a6e2da93 chore: 저장소 구조 정리 및 문서화, 첫 커밋
- src/dist 산출물 분리 원칙 정리(.gitignore, .gitattributes)
- 루트 및 주요 폴더(config/scripts/prompts/tests/src, 런타임 폴더 5종)에
  안내용 README.md 추가
- CHANGELOG.md, LICENSE, docs/ops/05-release-and-versioning.md 추가
- docs/README.md 문서 지도 갱신
2026-09-04 09:25:44 +09:00

110 lines
No EOL
123 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html><html lang=en dir=ltr class="docs-wrapper plugin-docs plugin-id-default docs-version-stable docs-doc-page docs-doc-id-best-practices" data-has-hydrated=false><head><meta charset=UTF-8><meta name=generator content="Docusaurus v3.10.1"><title data-rh=true>Best Practices | Playwright</title><meta data-rh=true name=viewport content="width=device-width, initial-scale=1.0"/><meta data-rh=true name=twitter:card content=summary_large_image /><meta data-rh=true property=og:image content=https://repository-images.githubusercontent.com/221981891/8c5c6942-c91f-4df1-825f-4cf474056bd7 /><meta data-rh=true name=twitter:image content=https://repository-images.githubusercontent.com/221981891/8c5c6942-c91f-4df1-825f-4cf474056bd7 /><meta data-rh=true property=og:url content=https://playwright.dev/docs/best-practices /><meta data-rh=true property=og:locale content=en /><meta data-rh=true name=docusaurus_locale content=en /><meta data-rh=true name=docsearch:language content=en /><meta data-rh=true name=docusaurus_version content=stable /><meta data-rh=true name=docusaurus_tag content=docs-default-stable /><meta data-rh=true name=docsearch:version content=stable /><meta data-rh=true name=docsearch:docusaurus_tag content=docs-default-stable /><meta data-rh=true property=og:title content="Best Practices | Playwright"/><meta data-rh=true name=description content=Introduction /><meta data-rh=true property=og:description content=Introduction /><link data-rh=true rel=icon href=/img/playwright-logo.ico /><link data-rh=true rel=canonical href=https://playwright.dev/docs/best-practices /><link data-rh=true rel=alternate href=https://playwright.dev/docs/best-practices hreflang=en /><link data-rh=true rel=alternate href=https://playwright.dev/docs/best-practices hreflang=x-default /><link data-rh=true rel=preconnect href=https://K09ICMCV6X-dsn.algolia.net crossorigin=anonymous /><script data-rh=true type=application/ld+json>{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","item":"https://playwright.dev/docs/best-practices","name":"Best Practices","position":1}]}</script><link rel=search type=application/opensearchdescription+xml title=Playwright href=/opensearch.xml><script src=/js/redirection.js></script><link rel=stylesheet href=/assets/css/styles.8ebb20b1.css /><script src=/assets/js/runtime~main.114724dc.js defer></script><script src=/assets/js/main.4d3217ee.js defer></script></head><body><svg style="display: none;"><defs>
<symbol id=theme-svg-external-link viewBox="0 0 24 24"><path fill=currentColor d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"/></symbol>
</defs></svg>
<script>!function(){var t=function(){try{return new URLSearchParams(window.location.search).get("docusaurus-theme")}catch(t){}}()||function(){try{return window.localStorage.getItem("theme-e2a")}catch(t){}}();document.documentElement.setAttribute("data-theme",t||(window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light")),document.documentElement.setAttribute("data-theme-choice",t||"system")}(),function(){try{for(var[t,e]of new URLSearchParams(window.location.search).entries())if(t.startsWith("docusaurus-data-")){var a=t.replace("docusaurus-data-","data-");document.documentElement.setAttribute(a,e)}}catch(t){}}()</script><div id=__docusaurus><div role=region aria-label="Skip to main content"><a class=skipToContent_fXgn href=#__docusaurus_skipToContent_fallback>Skip to main content</a></div><nav aria-label=Main class="theme-layout-navbar navbar navbar--fixed-top"><div class=navbar__inner><div class="theme-layout-navbar-left navbar__items"><button aria-label="Toggle navigation bar" aria-expanded=false class="navbar__toggle clean-btn" type=button><svg width=30 height=30 viewBox="0 0 30 30" aria-hidden=true><path stroke=currentColor stroke-linecap=round stroke-miterlimit=10 stroke-width=2 d="M4 7h22M4 15h22M4 23h22"/></svg></button><a class=navbar__brand href=/><div class=navbar__logo><img src=/img/playwright-logo.svg alt="Playwright logo" class="themedComponent_mlkZ themedComponent--light_NVdE"/><img src=/img/playwright-logo.svg alt="Playwright logo" class="themedComponent_mlkZ themedComponent--dark_xIcU"/></div><b class="navbar__title text--truncate">Playwright</b></a><a aria-current=page class="navbar__item navbar__link navbar__link--active" href=/docs/intro>Docs</a><a class="navbar__item navbar__link" href=/mcp/introduction>MCP</a><a class="navbar__item navbar__link" href=/agent-cli/introduction>CLI</a><a class="navbar__item navbar__link" href=/docs/api/class-playwright>API</a><div class="navbar__item dropdown dropdown--hoverable"><a href=# aria-haspopup=true aria-expanded=false role=button class=navbar__link>Node.js</a><ul class=dropdown__menu><li><a href=/docs/best-practices target=_self rel="noopener noreferrer" class="dropdown__link undefined dropdown__link--active" data-language-prefix=/>Node.js</a><li><a href=/python/docs/best-practices target=_self rel="noopener noreferrer" class=dropdown__link data-language-prefix=/python/>Python</a><li><a href=/java/docs/best-practices target=_self rel="noopener noreferrer" class=dropdown__link data-language-prefix=/java/>Java</a><li><a href=/dotnet/docs/best-practices target=_self rel="noopener noreferrer" class=dropdown__link data-language-prefix=/dotnet/>.NET</a></ul></div></div><div class="theme-layout-navbar-right navbar__items navbar__items--right"><a href=https://github.com/microsoft/playwright target=_blank rel="noopener noreferrer" class="navbar__item navbar__link header-github-link" aria-label="GitHub repository"></a><a href=https://aka.ms/playwright/discord target=_blank rel="noopener noreferrer" class="navbar__item navbar__link header-discord-link" aria-label="Discord server"></a><div class="toggle_vylO colorModeToggle_DEke"><button class="clean-btn toggleButton_gllP toggleButtonDisabled_aARS" type=button disabled title="system mode" aria-label="Switch between dark and light mode (currently system mode)"><svg viewBox="0 0 24 24" width=24 height=24 aria-hidden=true class="toggleIcon_g3eP lightToggleIcon_pyhR"><path fill=currentColor d="M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"/></svg><svg viewBox="0 0 24 24" width=24 height=24 aria-hidden=true class="toggleIcon_g3eP darkToggleIcon_wfgR"><path fill=currentColor d="M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"/></svg><svg viewBox="0 0 24 24" width=24 height=24 aria-hidden=true class="toggleIcon_g3eP systemToggleIcon_QzmC"><path fill=currentColor d="m12 21c4.971 0 9-4.029 9-9s-4.029-9-9-9-9 4.029-9 9 4.029 9 9 9zm4.95-13.95c1.313 1.313 2.05 3.093 2.05 4.95s-0.738 3.637-2.05 4.95c-1.313 1.313-3.093 2.05-4.95 2.05v-14c1.857 0 3.637 0.737 4.95 2.05z"/></svg></button></div><div class=navbarSearchContainer_Bca1><button type=button class="DocSearch DocSearch-Button" aria-label="Search (Meta+k)" aria-keyshortcuts=Meta+k><span class=DocSearch-Button-Container><svg width=20 height=20 class=DocSearch-Search-Icon viewBox="0 0 24 24" aria-hidden=true><circle cx=11 cy=11 r=8 stroke=currentColor fill=none stroke-width=1.4 /><path d="m21 21-4.3-4.3" stroke=currentColor fill=none stroke-linecap=round stroke-linejoin=round /></svg><span class=DocSearch-Button-Placeholder>Search</span></span><span class=DocSearch-Button-Keys></span></button></div></div></div><div role=presentation class=navbar-sidebar__backdrop></div></nav><div id=__docusaurus_skipToContent_fallback class="theme-layout-main main-wrapper mainWrapper_z2l0"><div class=docsWrapper_hBAB><button aria-label="Scroll back to top" class="clean-btn theme-back-to-top-button backToTopButton_sjWU" type=button></button><div class=docRoot_UBD9><aside class="theme-doc-sidebar-container docSidebarContainer_YfHR"><div class=sidebarViewport_aRkj><div class=sidebar_njMd><nav aria-label="Docs sidebar" class="menu thin-scrollbar menu_SIkG"><ul class="theme-doc-sidebar-menu menu__list"><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item"><div class=menu__list-item-collapsible><a class="categoryLink_byQd menu__link menu__link--sublist menu__link--sublist-caret" role=button aria-expanded=true href=/docs/intro><span title="Getting Started" class=categoryLinkLabel_W154>Getting Started</span></a></div><ul class=menu__list><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/intro><span title=Installation class=linkLabel_WmDU>Installation</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/writing-tests><span title="Writing tests" class=linkLabel_WmDU>Writing tests</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/codegen-intro><span title="Generating tests" class=linkLabel_WmDU>Generating tests</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/running-tests><span title="Running and debugging tests" class=linkLabel_WmDU>Running and debugging tests</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/trace-viewer-intro><span title="Trace viewer" class=linkLabel_WmDU>Trace viewer</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/ci-intro><span title="Setting up CI" class=linkLabel_WmDU>Setting up CI</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/getting-started-vscode><span title="VS Code" class=linkLabel_WmDU>VS Code</span></a></ul><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class=menu__link href=/docs/release-notes><span title="Release notes" class=linkLabel_WmDU>Release notes</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class=menu__link href=/docs/canary-releases><span title="Canary releases" class=linkLabel_WmDU>Canary releases</span></a><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item"><div class=menu__list-item-collapsible><a class="categoryLink_byQd menu__link menu__link--sublist menu__link--sublist-caret" role=button aria-expanded=true href=/docs/test-agents><span title="Playwright Test" class=categoryLinkLabel_W154>Playwright Test</span></a></div><ul class=menu__list><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/test-agents><span title=Agents class=linkLabel_WmDU>Agents</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/test-annotations><span title=Annotations class=linkLabel_WmDU>Annotations</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/test-cli><span title="Command line" class=linkLabel_WmDU>Command line</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/test-configuration><span title=Configuration class=linkLabel_WmDU>Configuration</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/test-use-options><span title="Configuration (use)" class=linkLabel_WmDU>Configuration (use)</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/emulation><span title=Emulation class=linkLabel_WmDU>Emulation</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/test-fixtures><span title=Fixtures class=linkLabel_WmDU>Fixtures</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/test-global-setup-teardown><span title="Global setup and teardown" class=linkLabel_WmDU>Global setup and teardown</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/test-parallel><span title=Parallelism class=linkLabel_WmDU>Parallelism</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/test-parameterize><span title="Parameterize tests" class=linkLabel_WmDU>Parameterize tests</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/test-projects><span title=Projects class=linkLabel_WmDU>Projects</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/test-reporters><span title=Reporters class=linkLabel_WmDU>Reporters</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/test-retries><span title=Retries class=linkLabel_WmDU>Retries</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/test-sharding><span title=Sharding class=linkLabel_WmDU>Sharding</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/test-timeouts><span title=Timeouts class=linkLabel_WmDU>Timeouts</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/test-typescript><span title=TypeScript class=linkLabel_WmDU>TypeScript</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/test-ui-mode><span title="UI Mode" class=linkLabel_WmDU>UI Mode</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/test-webserver><span title="Web server" class=linkLabel_WmDU>Web server</span></a></ul><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item"><div class=menu__list-item-collapsible><a class="categoryLink_byQd menu__link menu__link--sublist menu__link--sublist-caret menu__link--active" role=button aria-expanded=true href=/docs/library><span title=Guides class=categoryLinkLabel_W154>Guides</span></a></div><ul class=menu__list><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/library><span title=Library class=linkLabel_WmDU>Library</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/accessibility-testing><span title="Accessibility testing" class=linkLabel_WmDU>Accessibility testing</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/input><span title=Actions class=linkLabel_WmDU>Actions</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/test-assertions><span title=Assertions class=linkLabel_WmDU>Assertions</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/api-testing><span title="API testing" class=linkLabel_WmDU>API testing</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/auth><span title=Authentication class=linkLabel_WmDU>Authentication</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/actionability><span title=Auto-waiting class=linkLabel_WmDU>Auto-waiting</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link menu__link--active" aria-current=page tabindex=0 href=/docs/best-practices><span title="Best Practices" class=linkLabel_WmDU>Best Practices</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/browsers><span title=Browsers class=linkLabel_WmDU>Browsers</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/chrome-extensions><span title="Chrome extensions" class=linkLabel_WmDU>Chrome extensions</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/clock><span title=Clock class=linkLabel_WmDU>Clock</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/test-components><span title="Component testing" class=linkLabel_WmDU>Component testing</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/debug><span title="Debugging Tests" class=linkLabel_WmDU>Debugging Tests</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/dialogs><span title=Dialogs class=linkLabel_WmDU>Dialogs</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/downloads><span title=Downloads class=linkLabel_WmDU>Downloads</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/evaluating><span title="Evaluating JavaScript" class=linkLabel_WmDU>Evaluating JavaScript</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/events><span title=Events class=linkLabel_WmDU>Events</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/extensibility><span title=Extensibility class=linkLabel_WmDU>Extensibility</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/frames><span title=Frames class=linkLabel_WmDU>Frames</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/handles><span title=Handles class=linkLabel_WmDU>Handles</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/browser-contexts><span title=Isolation class=linkLabel_WmDU>Isolation</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/locators><span title=Locators class=linkLabel_WmDU>Locators</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/mock><span title="Mock APIs" class=linkLabel_WmDU>Mock APIs</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/mock-browser-apis><span title="Mock browser APIs" class=linkLabel_WmDU>Mock browser APIs</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/navigations><span title=Navigations class=linkLabel_WmDU>Navigations</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/network><span title=Network class=linkLabel_WmDU>Network</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/other-locators><span title="Other locators" class=linkLabel_WmDU>Other locators</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/pages><span title=Pages class=linkLabel_WmDU>Pages</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/pom><span title="Page object models" class=linkLabel_WmDU>Page object models</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/screenshots><span title=Screenshots class=linkLabel_WmDU>Screenshots</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/service-workers><span title="Service Workers" class=linkLabel_WmDU>Service Workers</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/aria-snapshots><span title="Snapshot testing" class=linkLabel_WmDU>Snapshot testing</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/codegen><span title="Test generator" class=linkLabel_WmDU>Test generator</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/touch-events><span title="Touch events (legacy)" class=linkLabel_WmDU>Touch events (legacy)</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/trace-viewer><span title="Trace viewer" class=linkLabel_WmDU>Trace viewer</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/videos><span title=Videos class=linkLabel_WmDU>Videos</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/test-snapshots><span title="Visual comparisons" class=linkLabel_WmDU>Visual comparisons</span></a><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class=menu__link tabindex=0 href=/docs/webview2><span title=WebView2 class=linkLabel_WmDU>WebView2</span></a></ul><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class=menu__list-item-collapsible><a class="categoryLink_byQd menu__link menu__link--sublist menu__link--sublist-caret" role=button aria-expanded=false href=/docs/protractor><span title=Migration class=categoryLinkLabel_W154>Migration</span></a></div><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class=menu__list-item-collapsible><a class="categoryLink_byQd menu__link menu__link--sublist menu__link--sublist-caret" role=button aria-expanded=false href=/docs/docker><span title=Integrations class=categoryLinkLabel_W154>Integrations</span></a></div><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class=menu__link href=/docs/languages><span title="Supported languages" class=linkLabel_WmDU>Supported languages</span></a></ul></nav></div></div></aside><main class=docMainContainer_TBSr><div class="container padding-top--md padding-bottom--lg"><div class=row><div class="col docItemCol_VOVn"><div class=docItemContainer_Djhp><article><nav class="theme-doc-breadcrumbs breadcrumbsContainer_Z_bl" aria-label=Breadcrumbs><ul class=breadcrumbs><li class=breadcrumbs__item><a aria-label="Home page" class=breadcrumbs__link href=/><svg viewBox="0 0 24 24" class=breadcrumbHomeIcon_YNFT><path d="M10 19v-5h4v5c0 .55.45 1 1 1h3c.55 0 1-.45 1-1v-7h1.7c.46 0 .68-.57.33-.87L12.67 3.6c-.38-.34-.96-.34-1.34 0l-8.36 7.53c-.34.3-.13.87.33.87H5v7c0 .55.45 1 1 1h3c.55 0 1-.45 1-1z" fill=currentColor /></svg></a><li class=breadcrumbs__item><span class=breadcrumbs__link>Guides</span><li class="breadcrumbs__item breadcrumbs__item--active"><span class=breadcrumbs__link>Best Practices</span></ul></nav><div class="tocCollapsible_ETCw theme-doc-toc-mobile tocMobile_ITEo"><button type=button class="clean-btn tocCollapsibleButton_TO0P">On this page</button></div><div class="theme-doc-markdown markdown"><header><h1>Best Practices</h1></header><h2 class="anchor anchorTargetStickyNavbar_Vzrq" id=introduction>Introduction<a href=#introduction class=hash-link aria-label="Direct link to Introduction" title="Direct link to Introduction" translate=no></a></h2>
<p>This guide should help you to make sure you are following our best practices and writing tests that are more resilient.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id=testing-philosophy>Testing philosophy<a href=#testing-philosophy class=hash-link aria-label="Direct link to Testing philosophy" title="Direct link to Testing philosophy" translate=no></a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id=test-user-visible-behavior>Test user-visible behavior<a href=#test-user-visible-behavior class=hash-link aria-label="Direct link to Test user-visible behavior" title="Direct link to Test user-visible behavior" translate=no></a></h3>
<p>Automated tests should verify that the application code works for the end users, and avoid relying on implementation details such as things which users will not typically use, see, or even know about such as the name of a function, whether something is an array, or the CSS class of some element. The end user will see or interact with what is rendered on the page, so your test should typically only see/interact with the same rendered output.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id=make-tests-as-isolated-as-possible>Make tests as isolated as possible<a href=#make-tests-as-isolated-as-possible class=hash-link aria-label="Direct link to Make tests as isolated as possible" title="Direct link to Make tests as isolated as possible" translate=no></a></h3>
<p>Each test should be completely isolated from another test and should run independently with its own local storage, session storage, data, cookies etc. <a class="" href=/docs/browser-contexts>Test isolation</a> improves reproducibility, makes debugging easier and prevents cascading test failures.</p>
<p>In order to avoid repetition for a particular part of your test you can use <a class="" href=/docs/api/class-test>before and after hooks</a>. Within your test file add a before hook to run a part of your test before each test such as going to a particular URL or logging in to a part of your app. This keeps your tests isolated as no test relies on another. However it is also ok to have a little duplication when tests are simple enough especially if it keeps your tests clearer and easier to read and maintain.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-js codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token keyword module" style=color:#C586C0>import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token imports"> test </span><span class="token imports punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"> </span><span class="token keyword module" style=color:#C586C0>from</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'@playwright/test'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain" style=display:inline-block></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain">test</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">beforeEach</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token keyword" style=color:#C586C0>async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token parameter punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token parameter" style=color:#9CDCFE> page </span><span class="token parameter punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(212, 212, 212)">=></span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"> </span><span class="token comment" style="color:rgb(106, 153, 85)">// Runs before each test and signs in each page.</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"> </span><span class="token keyword control-flow" style=color:#C586C0>await</span><span class="token plain"> page</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">goto</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">'https://github.com/login'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"> </span><span class="token keyword control-flow" style=color:#C586C0>await</span><span class="token plain"> page</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">getByLabel</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">'Username or email address'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">fill</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">'username'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"> </span><span class="token keyword control-flow" style=color:#C586C0>await</span><span class="token plain"> page</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">getByLabel</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">'Password'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">fill</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">'password'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"> </span><span class="token keyword control-flow" style=color:#C586C0>await</span><span class="token plain"> page</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">getByRole</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">'button'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property" style=color:#9CDCFE>name</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'Sign in'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">click</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain" style=display:inline-block></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"></span><span class="token function" style="color:rgb(220, 220, 170)">test</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">'first'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token keyword" style=color:#C586C0>async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token parameter punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token parameter" style=color:#9CDCFE> page </span><span class="token parameter punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(212, 212, 212)">=></span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"> </span><span class="token comment" style="color:rgb(106, 153, 85)">// page is signed in.</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain" style=display:inline-block></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"></span><span class="token function" style="color:rgb(220, 220, 170)">test</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">'second'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token keyword" style=color:#C586C0>async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token parameter punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token parameter" style=color:#9CDCFE> page </span><span class="token parameter punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(212, 212, 212)">=></span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"> </span><span class="token comment" style="color:rgb(106, 153, 85)">// page is signed in.</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><br/></div></code></pre></div></div>
<p>You can also reuse the signed-in state in the tests with <a class="" href=/docs/auth#basic-shared-account-in-all-tests>setup project</a>. That way you can log in only once and then skip the log in step for all of the tests.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id=avoid-testing-third-party-dependencies>Avoid testing third-party dependencies<a href=#avoid-testing-third-party-dependencies class=hash-link aria-label="Direct link to Avoid testing third-party dependencies" title="Direct link to Avoid testing third-party dependencies" translate=no></a></h3>
<p>Only test what you control. Don't try to test links to external sites or third party servers that you do not control. Not only is it time consuming and can slow down your tests but also you cannot control the content of the page you are linking to, or if there are cookie banners or overlay pages or anything else that might cause your test to fail.</p>
<p>Instead, use the <a class="" href=/docs/network#handle-requests>Playwright Network API</a> and guarantee the response needed.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-js codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token keyword control-flow" style=color:#C586C0>await</span><span class="token plain"> page</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">route</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">'**/api/fetch_data_third_party_dependency'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token parameter" style=color:#9CDCFE>route</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(212, 212, 212)">=></span><span class="token plain"> route</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">fulfill</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"> </span><span class="token literal-property property" style=color:#9CDCFE>status</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token number" style=color:#B5CEA8>200</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"> </span><span class="token literal-property property" style=color:#9CDCFE>body</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> testData</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"></span><span class="token keyword control-flow" style=color:#C586C0>await</span><span class="token plain"> page</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">goto</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">'https://example.com'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><br/></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id=testing-with-a-database>Testing with a database<a href=#testing-with-a-database class=hash-link aria-label="Direct link to Testing with a database" title="Direct link to Testing with a database" translate=no></a></h3>
<p>If working with a database then make sure you control the data. Test against a staging environment and make sure it doesn't change. For visual regression tests make sure the operating system and browser versions are the same.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id=best-practices>Best Practices<a href=#best-practices class=hash-link aria-label="Direct link to Best Practices" title="Direct link to Best Practices" translate=no></a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id=use-locators>Use locators<a href=#use-locators class=hash-link aria-label="Direct link to Use locators" title="Direct link to Use locators" translate=no></a></h3>
<p>In order to write end to end tests we need to first find elements on the webpage. We can do this by using Playwright's built in <a class="" href=/docs/locators>locators</a>. Locators come with auto waiting and retry-ability. Auto waiting means that Playwright performs a range of actionability checks on the elements, such as ensuring the element is visible and enabled before it performs the click. To make tests resilient, we recommend prioritizing user-facing attributes and explicit contracts.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-js codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token comment" style="color:rgb(106, 153, 85)">// 👍</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain">page</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">getByRole</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">'button'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property" style=color:#9CDCFE>name</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'submit'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><br/></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id=use-chaining-and-filtering>Use chaining and filtering<a href=#use-chaining-and-filtering class=hash-link aria-label="Direct link to Use chaining and filtering" title="Direct link to Use chaining and filtering" translate=no></a></h4>
<p>Locators can be <a class="" href=/docs/locators#matching-inside-a-locator>chained</a> to narrow down the search to a particular part of the page.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-js codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token keyword" style=color:#C586C0>const</span><span class="token plain"> product </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> page</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">getByRole</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">'listitem'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">filter</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property" style=color:#9CDCFE>hasText</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'Product 2'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><br/></div></code></pre></div></div>
<p>You can also <a class="" href=/docs/locators#filtering-locators>filter locators</a> by text or by another locator.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-js codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token keyword control-flow" style=color:#C586C0>await</span><span class="token plain"> page</span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">getByRole</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">'listitem'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">filter</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property" style=color:#9CDCFE>hasText</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'Product 2'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">getByRole</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">'button'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property" style=color:#9CDCFE>name</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'Add to cart'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">click</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><br/></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id=prefer-user-facing-attributes-to-xpath-or-css-selectors>Prefer user-facing attributes to XPath or CSS selectors<a href=#prefer-user-facing-attributes-to-xpath-or-css-selectors class=hash-link aria-label="Direct link to Prefer user-facing attributes to XPath or CSS selectors" title="Direct link to Prefer user-facing attributes to XPath or CSS selectors" translate=no></a></h4>
<p>Your DOM can easily change so having your tests depend on your DOM structure can lead to failing tests. For example consider selecting this button by its CSS classes. Should the designer change something then the class might change, thus breaking your test.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-js codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token comment" style="color:rgb(106, 153, 85)">// 👎</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain">page</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">locator</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">'button.buttonIcon.episode-actions-later'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><br/></div></code></pre></div></div>
<p>Use locators that are resilient to changes in the DOM.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-js codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token comment" style="color:rgb(106, 153, 85)">// 👍</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain">page</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">getByRole</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">'button'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property" style=color:#9CDCFE>name</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'submit'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><br/></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id=generate-locators>Generate locators<a href=#generate-locators class=hash-link aria-label="Direct link to Generate locators" title="Direct link to Generate locators" translate=no></a></h3>
<p>Playwright has a <a class="" href=/docs/codegen>test generator</a> that can generate tests and pick locators for you. It will look at your page and figure out the best locator, prioritizing role, text and test id locators. If the generator finds multiple elements matching the locator, it will improve the locator to make it resilient and uniquely identify the target element, so you don't have to worry about failing tests due to locators.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id=use-codegen-to-generate-locators>Use <code>codegen</code> to generate locators<a href=#use-codegen-to-generate-locators class=hash-link aria-label="Direct link to use-codegen-to-generate-locators" title="Direct link to use-codegen-to-generate-locators" translate=no></a></h4>
<p>To pick a locator run the <code>codegen</code> command followed by the URL that you would like to pick a locator from.</p>
<div class="theme-tabs-container tabs-container tabList__CuJ"><ul role=tablist aria-orientation=horizontal class=tabs><li role=tab tabindex=0 aria-selected=true class="tabs__item tabItem_LNqP tabs__item--active">npm<li role=tab tabindex=-1 aria-selected=false class="tabs__item tabItem_LNqP">yarn<li role=tab tabindex=-1 aria-selected=false class="tabs__item tabItem_LNqP">pnpm</ul><div class=margin-top--md><div role=tabpanel class=tabItem_Ymn6><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token plain">npx playwright codegen playwright.dev</span><br/></div></code></pre></div></div></div><div role=tabpanel class=tabItem_Ymn6 hidden><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token function" style="color:rgb(220, 220, 170)">yarn</span><span class="token plain"> playwright codegen playwright.dev</span><br/></div></code></pre></div></div></div><div role=tabpanel class=tabItem_Ymn6 hidden><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token function" style="color:rgb(220, 220, 170)">pnpm</span><span class="token plain"> </span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">exec</span><span class="token plain"> playwright codegen playwright.dev</span><br/></div></code></pre></div></div></div></div></div>
<p>This will open a new browser window as well as the Playwright inspector. To pick a locator first click on the 'Record' button to stop the recording. By default when you run the <code>codegen</code> command it will start a new recording. Once you stop the recording the 'Pick Locator' button will be available to click.</p>
<p>You can then hover over any element on your page in the browser window and see the locator highlighted below your cursor. Clicking on an element will add the locator into the Playwright inspector. You can either copy the locator and paste into your test file or continue to explore the locator by editing it in the Playwright Inspector, for example by modifying the text, and seeing the results in the browser window.</p>
<img height=1274 width=2788 alt="generating locators with codegen" loading=lazy src=https://user-images.githubusercontent.com/13063165/212103268-e7d8ee8b-d307-4cba-be13-831f3fbb1f40.png />
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id=use-the-vs-code-extension-to-generate-locators>Use the VS Code extension to generate locators<a href=#use-the-vs-code-extension-to-generate-locators class=hash-link aria-label="Direct link to Use the VS Code extension to generate locators" title="Direct link to Use the VS Code extension to generate locators" translate=no></a></h4>
<p>You can also use the <a class="" href=/docs/getting-started-vscode>VS Code Extension</a> to generate locators as well as record a test. The VS Code extension also gives you a great developer experience when writing, running, and debugging tests.</p>
<img height=1684 width=2788 alt="generating locators in vs code with codegen" loading=lazy src=https://user-images.githubusercontent.com/13063165/212269873-aca04043-16ce-4627-906f-7351d09740ab.png />
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id=use-web-first-assertions>Use web first assertions<a href=#use-web-first-assertions class=hash-link aria-label="Direct link to Use web first assertions" title="Direct link to Use web first assertions" translate=no></a></h3>
<p>Assertions are a way to verify that the expected result and the actual result matched or not. By using <a class="" href=/docs/test-assertions>web first assertions</a> Playwright will wait until the expected condition is met. For example, when testing an alert message, a test would click a button that makes a message appear and check that the alert message is there. If the alert message takes half a second to appear, assertions such as <code>toBeVisible()</code> will wait and retry if needed.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-js codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token comment" style="color:rgb(106, 153, 85)">// 👍</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"></span><span class="token keyword control-flow" style=color:#C586C0>await</span><span class="token plain"> </span><span class="token function" style="color:rgb(220, 220, 170)">expect</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">page</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">getByText</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">'welcome'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">toBeVisible</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain" style=display:inline-block></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)">// 👎</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"></span><span class="token function" style="color:rgb(220, 220, 170)">expect</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token keyword control-flow" style=color:#C586C0>await</span><span class="token plain"> page</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">getByText</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">'welcome'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">isVisible</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">toBe</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token boolean" style=color:#569CD6>true</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><br/></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id=dont-use-manual-assertions>Don't use manual assertions<a href=#dont-use-manual-assertions class=hash-link aria-label="Direct link to Don't use manual assertions" title="Direct link to Don't use manual assertions" translate=no></a></h4>
<p>Don't use manual assertions that are not awaiting the expect. In the code below the await is inside the expect rather than before it. When using assertions such as <code>isVisible()</code> the test won't wait a single second, it will just check the locator is there and return immediately.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-js codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token comment" style="color:rgb(106, 153, 85)">// 👎</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"></span><span class="token function" style="color:rgb(220, 220, 170)">expect</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token keyword control-flow" style=color:#C586C0>await</span><span class="token plain"> page</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">getByText</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">'welcome'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">isVisible</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">toBe</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token boolean" style=color:#569CD6>true</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><br/></div></code></pre></div></div>
<p>Use web first assertions such as <code>toBeVisible()</code> instead.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-js codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token comment" style="color:rgb(106, 153, 85)">// 👍</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"></span><span class="token keyword control-flow" style=color:#C586C0>await</span><span class="token plain"> </span><span class="token function" style="color:rgb(220, 220, 170)">expect</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">page</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">getByText</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">'welcome'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">toBeVisible</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><br/></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id=configure-debugging>Configure debugging<a href=#configure-debugging class=hash-link aria-label="Direct link to Configure debugging" title="Direct link to Configure debugging" translate=no></a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id=local-debugging>Local debugging<a href=#local-debugging class=hash-link aria-label="Direct link to Local debugging" title="Direct link to Local debugging" translate=no></a></h4>
<p>For local debugging we recommend you <a class="" href=/docs/getting-started-vscode#debugging-your-tests>debug your tests live in VS Code</a> by installing the <a class="" href=/docs/getting-started-vscode>VS Code extension</a>. You can run tests in debug mode by right-clicking on the line next to the test you want to run which will open a browser window and pause at where the breakpoint is set.</p>
<img height=1240 width=2676 alt="debugging tests in vscode" loading=lazy src=https://user-images.githubusercontent.com/13063165/212274675-5c6e1647-2aab-40fd-9804-8680c1ac2d16.png />
<p>You can live debug your test by clicking or editing the locators in your test in VS Code which will highlight this locator in the browser window as well as show you any other matching locators found on the page.</p>
<img height=1404 width=2788 alt="live debugging locators in vscode" loading=lazy src=https://user-images.githubusercontent.com/13063165/212273189-da271dc4-0f59-4138-92a8-10e719066cbe.png />
<p>You can also debug your tests with the Playwright inspector by running your tests with the <code>--debug</code> flag.</p>
<div class="theme-tabs-container tabs-container tabList__CuJ"><ul role=tablist aria-orientation=horizontal class=tabs><li role=tab tabindex=0 aria-selected=true class="tabs__item tabItem_LNqP tabs__item--active">npm<li role=tab tabindex=-1 aria-selected=false class="tabs__item tabItem_LNqP">yarn<li role=tab tabindex=-1 aria-selected=false class="tabs__item tabItem_LNqP">pnpm</ul><div class=margin-top--md><div role=tabpanel class=tabItem_Ymn6><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token plain">npx playwright </span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">test</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--debug</span><br/></div></code></pre></div></div></div><div role=tabpanel class=tabItem_Ymn6 hidden><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token function" style="color:rgb(220, 220, 170)">yarn</span><span class="token plain"> playwright </span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">test</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--debug</span><br/></div></code></pre></div></div></div><div role=tabpanel class=tabItem_Ymn6 hidden><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token function" style="color:rgb(220, 220, 170)">pnpm</span><span class="token plain"> </span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">exec</span><span class="token plain"> playwright </span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">test</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--debug</span><br/></div></code></pre></div></div></div></div></div>
<p>You can then step through your test, view actionability logs and edit the locator live and see it highlighted in the browser window. This will show you which locators match, how many of them there are.</p>
<img height=1736 width=2700 alt="debugging with the playwright inspector" loading=lazy src=https://user-images.githubusercontent.com/13063165/212276296-4f5b18e7-2bd7-4766-9aa5-783517bd4aa2.png />
<p>To debug a specific test add the name of the test file and the line number of the test followed by the <code>--debug</code> flag.</p>
<div class="theme-tabs-container tabs-container tabList__CuJ"><ul role=tablist aria-orientation=horizontal class=tabs><li role=tab tabindex=0 aria-selected=true class="tabs__item tabItem_LNqP tabs__item--active">npm<li role=tab tabindex=-1 aria-selected=false class="tabs__item tabItem_LNqP">yarn<li role=tab tabindex=-1 aria-selected=false class="tabs__item tabItem_LNqP">pnpm</ul><div class=margin-top--md><div role=tabpanel class=tabItem_Ymn6><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token plain">npx playwright </span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">test</span><span class="token plain"> example.spec.ts:9 </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--debug</span><br/></div></code></pre></div></div></div><div role=tabpanel class=tabItem_Ymn6 hidden><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token function" style="color:rgb(220, 220, 170)">yarn</span><span class="token plain"> playwright </span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">test</span><span class="token plain"> example.spec.ts:9 </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--debug</span><br/></div></code></pre></div></div></div><div role=tabpanel class=tabItem_Ymn6 hidden><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token function" style="color:rgb(220, 220, 170)">pnpm</span><span class="token plain"> </span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">exec</span><span class="token plain"> playwright </span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">test</span><span class="token plain"> example.spec.ts:9 </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--debug</span><br/></div></code></pre></div></div></div></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id=debugging-on-ci>Debugging on CI<a href=#debugging-on-ci class=hash-link aria-label="Direct link to Debugging on CI" title="Direct link to Debugging on CI" translate=no></a></h4>
<p>For CI failures, use the Playwright <a class="" href=/docs/trace-viewer>trace viewer</a> instead of videos and screenshots. The trace viewer gives you a full trace of your tests as a local Progressive Web App (PWA) that can easily be shared. With the trace viewer you can view the timeline, inspect DOM snapshots for each action using dev tools, view network requests and more.</p>
<img height=1920 width=3032 alt="playwrights trace viewer" loading=lazy src=https://user-images.githubusercontent.com/13063165/212277895-c63d94c2-bd06-4881-864e-62790a072ca3.png />
<p>Traces are configured in the Playwright config file and are set to run on CI on the first retry of a failed test. We don't recommend setting this to <code>on</code> so that traces are run on every test as it's very performance heavy. However you can run a trace locally when developing with the <code>--trace</code> flag.</p>
<div class="theme-tabs-container tabs-container tabList__CuJ"><ul role=tablist aria-orientation=horizontal class=tabs><li role=tab tabindex=0 aria-selected=true class="tabs__item tabItem_LNqP tabs__item--active">npm<li role=tab tabindex=-1 aria-selected=false class="tabs__item tabItem_LNqP">yarn<li role=tab tabindex=-1 aria-selected=false class="tabs__item tabItem_LNqP">pnpm</ul><div class=margin-top--md><div role=tabpanel class=tabItem_Ymn6><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token plain">npx playwright </span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">test</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--trace</span><span class="token plain"> on</span><br/></div></code></pre></div></div></div><div role=tabpanel class=tabItem_Ymn6 hidden><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token function" style="color:rgb(220, 220, 170)">yarn</span><span class="token plain"> playwright </span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">test</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--trace</span><span class="token plain"> on</span><br/></div></code></pre></div></div></div><div role=tabpanel class=tabItem_Ymn6 hidden><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token function" style="color:rgb(220, 220, 170)">pnpm</span><span class="token plain"> </span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">exec</span><span class="token plain"> playwright </span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">test</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--trace</span><span class="token plain"> on</span><br/></div></code></pre></div></div></div></div></div>
<p>Once you run this command your traces will be recorded for each test and can be viewed directly from the HTML report.</p>
<div class="theme-tabs-container tabs-container tabList__CuJ"><ul role=tablist aria-orientation=horizontal class=tabs><li role=tab tabindex=0 aria-selected=true class="tabs__item tabItem_LNqP tabs__item--active">npm<li role=tab tabindex=-1 aria-selected=false class="tabs__item tabItem_LNqP">yarn<li role=tab tabindex=-1 aria-selected=false class="tabs__item tabItem_LNqP">pnpm</ul><div class=margin-top--md><div role=tabpanel class=tabItem_Ymn6><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token plain">npx playwright show-report</span><br/></div></code></pre></div></div></div><div role=tabpanel class=tabItem_Ymn6 hidden><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token function" style="color:rgb(220, 220, 170)">yarn</span><span class="token plain"> playwright show-report</span><br/></div></code></pre></div></div></div><div role=tabpanel class=tabItem_Ymn6 hidden><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token function" style="color:rgb(220, 220, 170)">pnpm</span><span class="token plain"> </span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">exec</span><span class="token plain"> playwright show-report</span><br/></div></code></pre></div></div></div></div></div>
<img height=1920 width=3032 alt="Playwrights HTML report" loading=lazy src=https://user-images.githubusercontent.com/13063165/212279022-d929d4c0-2271-486a-a75f-166ac231d25f.png />
<p>Traces can be opened by clicking on the icon next to the test file name or by opening each of the test reports and scrolling down to the traces section.</p>
<img height=2242 width=3032 alt="Screenshot 2023-01-13 at 09 58 34" loading=lazy src=https://user-images.githubusercontent.com/13063165/212279699-c9eb134f-4f4e-4f19-805c-37596d3272a6.png />
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id=use-playwrights-tooling>Use Playwright's Tooling<a href=#use-playwrights-tooling class=hash-link aria-label="Direct link to Use Playwright's Tooling" title="Direct link to Use Playwright's Tooling" translate=no></a></h3>
<p>Playwright comes with a range of tooling to help you write tests.</p>
<ul>
<li class="">The <a class="" href=/docs/getting-started-vscode>VS Code extension</a> gives you a great developer experience when writing, running, and debugging tests.</li>
<li class="">The <a class="" href=/docs/codegen>test generator</a> can generate tests and pick locators for you.</li>
<li class="">The <a class="" href=/docs/trace-viewer>trace viewer</a> gives you a full trace of your tests as a local PWA that can easily be shared. With the trace viewer you can view the timeline, inspect DOM snapshots for each action, view network requests and more.</li>
<li class="">The <a class="" href=/docs/test-ui-mode>UI Mode</a> lets you explore, run and debug tests with a time travel experience complete with watch mode. All test files are loaded into the testing sidebar where you can expand each file and describe block to individually run, view, watch and debug each test.</li>
<li class=""><a class="" href=/docs/test-typescript>TypeScript</a> in Playwright works out of the box and gives you better IDE integrations. Your IDE will show you everything you can do and highlight when you do something wrong. No TypeScript experience is needed and it is not necessary for your code to be in TypeScript, all you need to do is create your tests with a <code>.ts</code> extension.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id=test-across-all-browsers>Test across all browsers<a href=#test-across-all-browsers class=hash-link aria-label="Direct link to Test across all browsers" title="Direct link to Test across all browsers" translate=no></a></h3>
<p>Playwright makes it easy to test your site across all <a class="" href=/docs/test-projects#configure-projects-for-multiple-browsers>browsers</a> no matter what platform you are on. Testing across all browsers ensures your app works for all users. In your config file you can set up projects adding the name and which browser or device to use.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockTitle_OeMC>playwright.config.ts</div><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-js codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token keyword module" style=color:#C586C0>import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token imports"> defineConfig</span><span class="token imports punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token imports"> devices </span><span class="token imports punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"> </span><span class="token keyword module" style=color:#C586C0>from</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'@playwright/test'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain" style=display:inline-block></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"></span><span class="token keyword module" style=color:#C586C0>export</span><span class="token plain"> </span><span class="token keyword module" style=color:#C586C0>default</span><span class="token plain"> </span><span class="token function" style="color:rgb(220, 220, 170)">defineConfig</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"> </span><span class="token literal-property property" style=color:#9CDCFE>projects</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"> </span><span class="token literal-property property" style=color:#9CDCFE>name</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'chromium'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"> </span><span class="token literal-property property" style=color:#9CDCFE>use</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token spread operator" style="color:rgb(212, 212, 212)">...</span><span class="token plain">devices</span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token string" style="color:rgb(206, 145, 120)">'Desktop Chrome'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"> </span><span class="token literal-property property" style=color:#9CDCFE>name</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'firefox'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"> </span><span class="token literal-property property" style=color:#9CDCFE>use</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token spread operator" style="color:rgb(212, 212, 212)">...</span><span class="token plain">devices</span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token string" style="color:rgb(206, 145, 120)">'Desktop Firefox'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"> </span><span class="token literal-property property" style=color:#9CDCFE>name</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'webkit'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"> </span><span class="token literal-property property" style=color:#9CDCFE>use</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token spread operator" style="color:rgb(212, 212, 212)">...</span><span class="token plain">devices</span><span class="token punctuation" style="color:rgb(212, 212, 212)">[</span><span class="token string" style="color:rgb(206, 145, 120)">'Desktop Safari'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">]</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><br/></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id=keep-your-playwright-dependency-up-to-date>Keep your Playwright dependency up to date<a href=#keep-your-playwright-dependency-up-to-date class=hash-link aria-label="Direct link to Keep your Playwright dependency up to date" title="Direct link to Keep your Playwright dependency up to date" translate=no></a></h3>
<p>By keeping your Playwright version up to date you will be able to test your app on the latest browser versions and catch failures before the latest browser version is released to the public.</p>
<div class="theme-tabs-container tabs-container tabList__CuJ"><ul role=tablist aria-orientation=horizontal class=tabs><li role=tab tabindex=0 aria-selected=true class="tabs__item tabItem_LNqP tabs__item--active">npm<li role=tab tabindex=-1 aria-selected=false class="tabs__item tabItem_LNqP">yarn<li role=tab tabindex=-1 aria-selected=false class="tabs__item tabItem_LNqP">pnpm</ul><div class=margin-top--md><div role=tabpanel class=tabItem_Ymn6><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token function" style="color:rgb(220, 220, 170)">npm</span><span class="token plain"> </span><span class="token function" style="color:rgb(220, 220, 170)">install</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">-D</span><span class="token plain"> @playwright/test@latest</span><br/></div></code></pre></div></div></div><div role=tabpanel class=tabItem_Ymn6 hidden><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token function" style="color:rgb(220, 220, 170)">yarn</span><span class="token plain"> </span><span class="token function" style="color:rgb(220, 220, 170)">add</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--dev</span><span class="token plain"> @playwright/test@latest</span><br/></div></code></pre></div></div></div><div role=tabpanel class=tabItem_Ymn6 hidden><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token function" style="color:rgb(220, 220, 170)">pnpm</span><span class="token plain"> </span><span class="token function" style="color:rgb(220, 220, 170)">install</span><span class="token plain"> --save-dev @playwright/test@latest</span><br/></div></code></pre></div></div></div></div></div>
<p>Check the <a class="" href=/docs/release-notes>release notes</a> to see what the latest version is and what changes have been released.</p>
<p>You can see what version of Playwright you have by running the following command.</p>
<div class="theme-tabs-container tabs-container tabList__CuJ"><ul role=tablist aria-orientation=horizontal class=tabs><li role=tab tabindex=0 aria-selected=true class="tabs__item tabItem_LNqP tabs__item--active">npm<li role=tab tabindex=-1 aria-selected=false class="tabs__item tabItem_LNqP">yarn<li role=tab tabindex=-1 aria-selected=false class="tabs__item tabItem_LNqP">pnpm</ul><div class=margin-top--md><div role=tabpanel class=tabItem_Ymn6><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token plain">npx playwright </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--version</span><br/></div></code></pre></div></div></div><div role=tabpanel class=tabItem_Ymn6 hidden><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token function" style="color:rgb(220, 220, 170)">yarn</span><span class="token plain"> playwright </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--version</span><br/></div></code></pre></div></div></div><div role=tabpanel class=tabItem_Ymn6 hidden><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token function" style="color:rgb(220, 220, 170)">pnpm</span><span class="token plain"> </span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">exec</span><span class="token plain"> playwright </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--version</span><br/></div></code></pre></div></div></div></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id=run-tests-on-ci>Run tests on CI<a href=#run-tests-on-ci class=hash-link aria-label="Direct link to Run tests on CI" title="Direct link to Run tests on CI" translate=no></a></h3>
<p>Setup CI/CD and run your tests frequently. The more often you run your tests the better. Ideally you should run your tests on each commit and pull request. Playwright comes with a <a class="" href=/docs/ci-intro>GitHub actions workflow</a> so that tests will run on CI for you with no setup required. Playwright can also be setup on the <a class="" href=/docs/ci>CI environment</a> of your choice.</p>
<p>Use Linux when running your tests on CI as it is cheaper. Developers can use whatever environment when running locally but use linux on CI. Consider setting up <a class="" href=/docs/test-sharding>Sharding</a> to make CI faster.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id=optimize-browser-downloads-on-ci>Optimize browser downloads on CI<a href=#optimize-browser-downloads-on-ci class=hash-link aria-label="Direct link to Optimize browser downloads on CI" title="Direct link to Optimize browser downloads on CI" translate=no></a></h4>
<p>Only install the browsers that you actually need, especially on CI. For example, if you're only testing with Chromium, install just Chromium.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockTitle_OeMC>.github/workflows/playwright.yml</div><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token comment" style="color:rgb(106, 153, 85)"># Instead of installing all browsers</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain">npx playwright </span><span class="token function" style="color:rgb(220, 220, 170)">install</span><span class="token plain"> --with-deps</span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain" style=display:inline-block></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)"># Install only Chromium</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain">npx playwright </span><span class="token function" style="color:rgb(220, 220, 170)">install</span><span class="token plain"> chromium --with-deps</span><br/></div></code></pre></div></div>
<p>This saves both download time and disk space on your CI machines.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id=lint-your-tests>Lint your tests<a href=#lint-your-tests class=hash-link aria-label="Direct link to Lint your tests" title="Direct link to Lint your tests" translate=no></a></h3>
<p>We recommend TypeScript and linting with ESLint for your tests to catch errors early. Use <a href=https://typescript-eslint.io/rules/no-floating-promises/ target=_blank rel="noopener noreferrer" class=""><code>@typescript-eslint/no-floating-promises</code></a> <a href=https://eslint.org target=_blank rel="noopener noreferrer" class="">ESLint</a> rule to make sure there are no missing awaits before the asynchronous calls to the Playwright API. On your CI you can run <code>tsc --noEmit</code> to ensure that functions are called with the right signature.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id=use-parallelism-and-sharding>Use parallelism and sharding<a href=#use-parallelism-and-sharding class=hash-link aria-label="Direct link to Use parallelism and sharding" title="Direct link to Use parallelism and sharding" translate=no></a></h3>
<p>Playwright runs tests in <a class="" href=/docs/test-parallel>parallel</a> by default. Tests in a single file are run in order, in the same worker process. If you have many independent tests in a single file, you might want to run them in parallel</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-js codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token keyword module" style=color:#C586C0>import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token imports"> test </span><span class="token imports punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token plain"> </span><span class="token keyword module" style=color:#C586C0>from</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'@playwright/test'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain" style=display:inline-block></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain">test</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token property-access">describe</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">configure</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property" style=color:#9CDCFE>mode</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'parallel'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain" style=display:inline-block></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"></span><span class="token function" style="color:rgb(220, 220, 170)">test</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">'runs in parallel 1'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token keyword" style=color:#C586C0>async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token parameter punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token parameter" style=color:#9CDCFE> page </span><span class="token parameter punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(212, 212, 212)">=></span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token comment" style="color:rgb(106, 153, 85)">/* ... */</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"></span><span class="token function" style="color:rgb(220, 220, 170)">test</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">'runs in parallel 2'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token keyword" style=color:#C586C0>async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token parameter punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token parameter" style=color:#9CDCFE> page </span><span class="token parameter punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(212, 212, 212)">=></span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token comment" style="color:rgb(106, 153, 85)">/* ... */</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><br/></div></code></pre></div></div>
<p>Playwright can <a class="" href=/docs/test-parallel#shard-tests-between-multiple-machines>shard</a> a test suite, so that it can be executed on multiple machines.</p>
<div class="theme-tabs-container tabs-container tabList__CuJ"><ul role=tablist aria-orientation=horizontal class=tabs><li role=tab tabindex=0 aria-selected=true class="tabs__item tabItem_LNqP tabs__item--active">npm<li role=tab tabindex=-1 aria-selected=false class="tabs__item tabItem_LNqP">yarn<li role=tab tabindex=-1 aria-selected=false class="tabs__item tabItem_LNqP">pnpm</ul><div class=margin-top--md><div role=tabpanel class=tabItem_Ymn6><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token plain">npx playwright </span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">test</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--shard</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token number" style=color:#B5CEA8>1</span><span class="token plain">/3</span><br/></div></code></pre></div></div></div><div role=tabpanel class=tabItem_Ymn6 hidden><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token function" style="color:rgb(220, 220, 170)">yarn</span><span class="token plain"> playwright </span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">test</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--shard</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token number" style=color:#B5CEA8>1</span><span class="token plain">/3</span><br/></div></code></pre></div></div></div><div role=tabpanel class=tabItem_Ymn6 hidden><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token function" style="color:rgb(220, 220, 170)">pnpm</span><span class="token plain"> </span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">exec</span><span class="token plain"> playwright </span><span class="token builtin class-name" style="color:rgb(78, 201, 176)">test</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(156, 220, 254)">--shard</span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token number" style=color:#B5CEA8>1</span><span class="token plain">/3</span><br/></div></code></pre></div></div></div></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id=productivity-tips>Productivity tips<a href=#productivity-tips class=hash-link aria-label="Direct link to Productivity tips" title="Direct link to Productivity tips" translate=no></a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id=use-soft-assertions>Use Soft assertions<a href=#use-soft-assertions class=hash-link aria-label="Direct link to Use Soft assertions" title="Direct link to Use Soft assertions" translate=no></a></h3>
<p>If your test fails, Playwright will give you an error message showing what part of the test failed which you can see either in VS Code, the terminal, the HTML report, or the trace viewer. However, you can also use <a class="" href=/docs/test-assertions#soft-assertions>soft assertions</a>. These do not immediately terminate the test execution, but rather compile and display a list of failed assertions once the test ended.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style=--prism-color:#D4D4D4;--prism-background-color:#212121><div class=codeBlockContent_QJqH><pre tabindex=0 class="prism-code language-js codeBlock_bY9V thin-scrollbar" style=color:#D4D4D4;background-color:#212121><code class=codeBlockLines_e6Vv><div class=token-line style=color:#D4D4D4><span class="token comment" style="color:rgb(106, 153, 85)">// Make a few checks that will not stop the test when failed...</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"></span><span class="token keyword control-flow" style=color:#C586C0>await</span><span class="token plain"> expect</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">soft</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">page</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">getByTestId</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">'status'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">toHaveText</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">'Success'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain" style=display:inline-block></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)">// ... and continue the test to check more things.</span><span class="token plain"></span><br/></div><div class=token-line style=color:#D4D4D4><span class="token plain"></span><span class="token keyword control-flow" style=color:#C586C0>await</span><span class="token plain"> page</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">getByRole</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token string" style="color:rgb(206, 145, 120)">'link'</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">{</span><span class="token plain"> </span><span class="token literal-property property" style=color:#9CDCFE>name</span><span class="token operator" style="color:rgb(212, 212, 212)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'next page'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">}</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token method function property-access" style="color:rgb(220, 220, 170)">click</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><br/></div></code></pre></div></div></div></article><nav class="docusaurus-mt-lg pagination-nav" aria-label="Docs pages"><a class="pagination-nav__link pagination-nav__link--prev" href=/docs/actionability><div class=pagination-nav__sublabel>Previous</div><div class=pagination-nav__label>Auto-waiting</div></a><a class="pagination-nav__link pagination-nav__link--next" href=/docs/browsers><div class=pagination-nav__sublabel>Next</div><div class=pagination-nav__label>Browsers</div></a></nav></div></div><div class="col col--3"><div class="tableOfContents_bqdL thin-scrollbar theme-doc-toc-desktop"><ul class="table-of-contents table-of-contents__left-border"><li><a href=#introduction class="table-of-contents__link toc-highlight">Introduction</a><li><a href=#testing-philosophy class="table-of-contents__link toc-highlight">Testing philosophy</a><ul><li><a href=#test-user-visible-behavior class="table-of-contents__link toc-highlight">Test user-visible behavior</a><li><a href=#make-tests-as-isolated-as-possible class="table-of-contents__link toc-highlight">Make tests as isolated as possible</a><li><a href=#avoid-testing-third-party-dependencies class="table-of-contents__link toc-highlight">Avoid testing third-party dependencies</a><li><a href=#testing-with-a-database class="table-of-contents__link toc-highlight">Testing with a database</a></ul><li><a href=#best-practices class="table-of-contents__link toc-highlight">Best Practices</a><ul><li><a href=#use-locators class="table-of-contents__link toc-highlight">Use locators</a><li><a href=#generate-locators class="table-of-contents__link toc-highlight">Generate locators</a><li><a href=#use-web-first-assertions class="table-of-contents__link toc-highlight">Use web first assertions</a><li><a href=#configure-debugging class="table-of-contents__link toc-highlight">Configure debugging</a><li><a href=#use-playwrights-tooling class="table-of-contents__link toc-highlight">Use Playwright's Tooling</a><li><a href=#test-across-all-browsers class="table-of-contents__link toc-highlight">Test across all browsers</a><li><a href=#keep-your-playwright-dependency-up-to-date class="table-of-contents__link toc-highlight">Keep your Playwright dependency up to date</a><li><a href=#run-tests-on-ci class="table-of-contents__link toc-highlight">Run tests on CI</a><li><a href=#lint-your-tests class="table-of-contents__link toc-highlight">Lint your tests</a><li><a href=#use-parallelism-and-sharding class="table-of-contents__link toc-highlight">Use parallelism and sharding</a></ul><li><a href=#productivity-tips class="table-of-contents__link toc-highlight">Productivity tips</a><ul><li><a href=#use-soft-assertions class="table-of-contents__link toc-highlight">Use Soft assertions</a></ul></ul></div></div></div></div></main></div></div></div><footer class="theme-layout-footer footer footer--dark"><div class="container container-fluid"><div class="row footer__links"><div class="theme-layout-footer-column col footer__col"><div class=footer__title>Learn</div><ul class="footer__items clean-list"><li class=footer__item><a class=footer__link-item href=/docs/intro>Getting started</a><li class=footer__item><a href=https://learn.microsoft.com/en-us/training/modules/build-with-playwright/ target=_blank rel="noopener noreferrer" class=footer__link-item>Playwright Training<svg width=13.5 height=13.5 aria-label="(opens in new tab)" class=iconExternalLink_nPIU><use href=#theme-svg-external-link /></svg></a><li class=footer__item><a class=footer__link-item href=/community/learn-videos>Learn Videos</a><li class=footer__item><a class=footer__link-item href=/community/feature-videos>Feature Videos</a></ul></div><div class="theme-layout-footer-column col footer__col"><div class=footer__title>Community</div><ul class="footer__items clean-list"><li class=footer__item><a href=https://stackoverflow.com/questions/tagged/playwright target=_blank rel="noopener noreferrer" class=footer__link-item>Stack Overflow<svg width=13.5 height=13.5 aria-label="(opens in new tab)" class=iconExternalLink_nPIU><use href=#theme-svg-external-link /></svg></a><li class=footer__item><a href=https://aka.ms/playwright/discord target=_blank rel="noopener noreferrer" class=footer__link-item>Discord<svg width=13.5 height=13.5 aria-label="(opens in new tab)" class=iconExternalLink_nPIU><use href=#theme-svg-external-link /></svg></a><li class=footer__item><a href=https://x.com/playwrightweb target=_blank rel="noopener noreferrer" class=footer__link-item>X<svg width=13.5 height=13.5 aria-label="(opens in new tab)" class=iconExternalLink_nPIU><use href=#theme-svg-external-link /></svg></a><li class=footer__item><a href=https://www.linkedin.com/company/playwrightweb target=_blank rel="noopener noreferrer" class=footer__link-item>LinkedIn<svg width=13.5 height=13.5 aria-label="(opens in new tab)" class=iconExternalLink_nPIU><use href=#theme-svg-external-link /></svg></a></ul></div><div class="theme-layout-footer-column col footer__col"><div class=footer__title>More</div><ul class="footer__items clean-list"><li class=footer__item><a href=https://github.com/microsoft/playwright target=_blank rel="noopener noreferrer" class=footer__link-item>GitHub<svg width=13.5 height=13.5 aria-label="(opens in new tab)" class=iconExternalLink_nPIU><use href=#theme-svg-external-link /></svg></a><li class=footer__item><a href=https://www.youtube.com/channel/UC46Zj8pDH5tDosqm1gd7WTg target=_blank rel="noopener noreferrer" class=footer__link-item>YouTube<svg width=13.5 height=13.5 aria-label="(opens in new tab)" class=iconExternalLink_nPIU><use href=#theme-svg-external-link /></svg></a><li class=footer__item><a href=https://dev.to/playwright target=_blank rel="noopener noreferrer" class=footer__link-item>Blog<svg width=13.5 height=13.5 aria-label="(opens in new tab)" class=iconExternalLink_nPIU><use href=#theme-svg-external-link /></svg></a><li class=footer__item><a class=footer__link-item href=/community/ambassadors>Ambassadors</a><li class=footer__item><a href="https://go.microsoft.com/fwlink/?LinkId=521839" target=_blank rel="noopener noreferrer" class=footer__link-item>Microsoft Privacy Statement<svg width=13.5 height=13.5 aria-label="(opens in new tab)" class=iconExternalLink_nPIU><use href=#theme-svg-external-link /></svg></a></ul></div></div><div class="footer__bottom text--center"><div class=footer__copyright>Copyright © 2026 Microsoft</div></div></div></footer></div></body>