<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Zeeaan Haral</title>
    <description>The latest articles on DEV Community by Zeeaan Haral (@zeeaan_haral).</description>
    <link>https://dev.to/zeeaan_haral</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3964403%2Fa461d02f-429d-49fc-91bf-ad78642e4917.jpg</url>
      <title>DEV Community: Zeeaan Haral</title>
      <link>https://dev.to/zeeaan_haral</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zeeaan_haral"/>
    <language>en</language>
    <item>
      <title>I Built 3 Playwright Frameworks So You Can Learn What Actually Scales</title>
      <dc:creator>Zeeaan Haral</dc:creator>
      <pubDate>Tue, 02 Jun 2026 11:14:20 +0000</pubDate>
      <link>https://dev.to/zeeaan_haral/i-built-the-playwright-best-practices-repo-i-wish-existed-when-i-started-48do</link>
      <guid>https://dev.to/zeeaan_haral/i-built-the-playwright-best-practices-repo-i-wish-existed-when-i-started-48do</guid>
      <description>&lt;h2&gt;
  
  
  From Script‑Based to Enterprise Playwright: Frameworks That Actually Scale
&lt;/h2&gt;

&lt;p&gt;When I started learning Playwright, every article told me the same things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“Use Page Object Model”&lt;/li&gt;
&lt;li&gt;“Create fixtures”&lt;/li&gt;
&lt;li&gt;“Don’t use &lt;code&gt;waitForTimeout&lt;/code&gt;”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Nobody showed me:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What a real project should look like&lt;/li&gt;
&lt;li&gt;How folders should be organized&lt;/li&gt;
&lt;li&gt;When POM becomes too big&lt;/li&gt;
&lt;li&gt;How teams handle authentication cleanly&lt;/li&gt;
&lt;li&gt;Why tests become flaky (and how to &lt;em&gt;actually&lt;/em&gt; fix them)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I learned by making mistakes.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Lots of mistakes.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After months of trial and error – and building automation frameworks from scratch at my job – I decided to document everything that worked. Not as a collection of tips, but as &lt;strong&gt;complete, runnable frameworks&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That’s why I built &lt;strong&gt;&lt;a href="https://github.com/ZeeaanNawazHarall/playwright-best-practices" rel="noopener noreferrer"&gt;playwright-best-practices&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What makes this different from most Playwright repositories
&lt;/h2&gt;

&lt;p&gt;Most GitHub repos show you &lt;strong&gt;one&lt;/strong&gt; “perfect” architecture. You clone it, run it, and… you don’t know why it’s built that way.&lt;/p&gt;

&lt;p&gt;This repo shows you the &lt;strong&gt;evolution&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;Script‑based (no patterns)&lt;br&gt;
↓&lt;br&gt;
Simple Page Object Model&lt;br&gt;
↓&lt;br&gt;
Advanced POM (layered architecture)&lt;/p&gt;

&lt;p&gt;You can compare each approach side‑by‑side and understand &lt;strong&gt;when&lt;/strong&gt; complexity becomes worthwhile.&lt;/p&gt;




&lt;h2&gt;
  
  
  What’s inside (no fluff, no guessing)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv080ns4cqzf5ypcrlpus.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv080ns4cqzf5ypcrlpus.png" alt="Repo Folder tree" width="800" height="521"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Three runnable frameworks (clone and &lt;code&gt;npm test&lt;/code&gt;)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Framework&lt;/th&gt;
&lt;th&gt;What it teaches&lt;/th&gt;
&lt;th&gt;Best for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;01-script-based&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Raw, inline interactions – the “I just need it to run” baseline&lt;/td&gt;
&lt;td&gt;Understanding the pain that patterns solve&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;02-simple-pom&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Classic Page Object Model – locators + actions in one class&lt;/td&gt;
&lt;td&gt;Most teams (80% of use cases)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;03-advanced-pom&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Separate layers: locators, actions, assertions&lt;/td&gt;
&lt;td&gt;Large suites where simple POM becomes a 1000‑line monster&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  One documentation folder (anti‑patterns)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Folder&lt;/th&gt;
&lt;th&gt;What it is&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;04-anti-pattern-lab&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Not runnable&lt;/strong&gt; – a written guide of common mistakes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;Why no runnable anti‑pattern code? Because broken examples can be confusing if they don’t fail clearly. Instead, I documented them – so you can recognize the smell before it infects your suite.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Additional production‑ready goodies
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Worker‑scoped login fixture&lt;/strong&gt; – one login for the whole suite&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Environment‑based credentials&lt;/strong&gt; – clean &lt;code&gt;.env&lt;/code&gt; example&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Actions + Jenkins CI configs&lt;/strong&gt; – ready to drop into your project&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flaky test strategies&lt;/strong&gt; – not just retries, but structural fixes&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Advanced POM explained (because it’s often misunderstood)
&lt;/h2&gt;

&lt;p&gt;When I say “Advanced POM”, I don’t mean bigger. I mean &lt;strong&gt;separated responsibilities&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Responsibility&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Locators&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Store element selectors only&lt;/td&gt;
&lt;td&gt;&lt;code&gt;loginPage.emailInput&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Actions&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Perform business interactions&lt;/td&gt;
&lt;td&gt;&lt;code&gt;loginPage.loginWithCredentials()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This prevents your Page Objects from turning into 1000‑line files as your project grows. It also makes tests &lt;strong&gt;dramatically easier to refactor&lt;/strong&gt; – change a selector in one place, and everything updates.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lessons I learned building Playwright frameworks (the hard way)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Mistake #1: Putting assertions inside Page Objects
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Why it failed:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Page Objects became tied to specific test flows. Reusability dropped. Changing a button’s text broke unrelated tests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I do now:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Keep assertions in dedicated assertion classes or test files. Page Objects should only expose state and actions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mistake #2: Logging in before &lt;strong&gt;every&lt;/strong&gt; test
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Why it failed:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Test suite took 3x longer. Rate‑limiting kicked in. Flakiness spiked.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I do now:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Worker‑scoped login fixtures – one authentication per worker, shared across tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mistake #3: Using &lt;code&gt;waitForTimeout(5000)&lt;/code&gt; as a lazy fix
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Why it failed:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Tests became slow and still flaky – just slower flaky.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I do now:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;code&gt;waitForSelector&lt;/code&gt;, &lt;code&gt;waitForResponse&lt;/code&gt;, or auto‑waiting assertions. The repo has concrete examples.&lt;/p&gt;




&lt;h2&gt;
  
  
  Who should use this repository
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;Why it’s valuable&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Junior SDET&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Skip the painful trial‑and‑error phase – see what a real project looks like&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cypress → Playwright mover&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Understand Playwright’s different approach (fixtures, worker scope, trace viewer)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Team lead&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hand this to juniors as a reference architecture&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Anyone fighting flaky tests&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The anti‑pattern lab + flaky test strategies will save your weekends&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  How to use the repo (the way I intended)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clone it&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;code&gt;git clone https://github.com/ZeeaanNawazHarall/playwright-best-practices&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Run the script‑based framework&lt;/strong&gt; – feel the mess&lt;br&gt;&lt;br&gt;
&lt;code&gt;cd examples/script-framework &amp;amp;&amp;amp; npm install &amp;amp;&amp;amp; npx playwright test&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Run the simple POM&lt;/strong&gt; – see how much cleaner it gets  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Run the advanced POM&lt;/strong&gt; – understand how teams scale  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Read the anti‑pattern lab&lt;/strong&gt; – recognize mistakes you might be making right now  &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You’ll leave with a mental map of &lt;em&gt;why&lt;/em&gt; each pattern exists – not just copy‑pasted code.&lt;/p&gt;




&lt;h2&gt;
  
  
  A final honest note
&lt;/h2&gt;

&lt;p&gt;I’m not claiming this is the &lt;em&gt;only&lt;/em&gt; way. But these patterns come from real work at my job (AccuraSol). They saved my weekends, made my scripts stable, and helped me sleep better.&lt;/p&gt;

&lt;p&gt;I open‑sourced it because I remember being overwhelmed when I started. If this repo saves you one late night of debugging a flaky test, it’s done its job.&lt;/p&gt;




&lt;h2&gt;
  
  
  Repository link &amp;amp; call to action
&lt;/h2&gt;

&lt;p&gt;If you’re learning Playwright or mentoring junior automation engineers, check it out:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://github.com/ZeeaanNawazHarall/playwright-best-practices" rel="noopener noreferrer"&gt;github.com/ZeeaanNawazHarall/playwright-best-practices&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Feedback, issues, and pull requests are welcome.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Found a better pattern? Open a PR. Found a mistake? Tell me. Let’s make this the actual best‑practices repo, no gatekeeping.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;— Zeeaan&lt;/em&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;SDET @ AccuraSol&lt;/em&gt;&lt;/p&gt;

</description>
      <category>playwright</category>
      <category>testing</category>
      <category>bestpractices</category>
      <category>qa</category>
    </item>
  </channel>
</rss>
