<?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: Jalal Maskoun</title>
    <description>The latest articles on DEV Community by Jalal Maskoun (@jalal246).</description>
    <link>https://dev.to/jalal246</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F126717%2Fb2192225-a47b-462a-8d40-c1a7762b1713.jpeg</url>
      <title>DEV Community: Jalal Maskoun</title>
      <link>https://dev.to/jalal246</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jalal246"/>
    <language>en</language>
    <item>
      <title>The Old Business Model of Knowledge Work Is Dead</title>
      <dc:creator>Jalal Maskoun</dc:creator>
      <pubDate>Thu, 10 Sep 2026 20:12:59 +0000</pubDate>
      <link>https://dev.to/jalal246/the-old-business-model-of-knowledge-work-is-dead-14m1</link>
      <guid>https://dev.to/jalal246/the-old-business-model-of-knowledge-work-is-dead-14m1</guid>
      <description>&lt;p&gt;I think Anthropic is right about something that most people still don't want to talk about.&lt;/p&gt;

&lt;p&gt;Even if the AI race stopped today, the old business model of knowledge work is already dead.&lt;/p&gt;

&lt;p&gt;For decades, we built an economy around people getting paid for what they know. You studied a domain. You became an expert. You sold that knowledge for an hourly rate or a salary. &lt;/p&gt;

&lt;p&gt;But what happens when knowledge becomes extremely cheap to produce?&lt;/p&gt;

&lt;p&gt;And it is not just cheap. It is becoming &lt;strong&gt;autonomous&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;That is the part we are heavily underestimating. This isn't just a software engineering problem. It is not even really an AI problem. It is a fundamental economic problem.&lt;/p&gt;

&lt;p&gt;This wave will eventually hit almost every knowledge-based career: lawyers, accountants, analysts, consultants, designers, marketers, developers, finance, operations, and a huge part of the traditional 9–5 office economy. Some jobs will disappear entirely. Many will mutate. New ones will emerge. &lt;/p&gt;

&lt;p&gt;Pretending the economic structure stays the same doesn't make much sense. &lt;/p&gt;

&lt;h3&gt;
  
  
  The Decision We Have to Make
&lt;/h3&gt;

&lt;p&gt;This is where the MENA region has a critical choice in front of it. &lt;/p&gt;

&lt;p&gt;We can wait for AGI to arrive and then import whatever economic transformation happens somewhere else. Or we can start the transformation now.&lt;/p&gt;

&lt;p&gt;I am not talking about the superficial approach of &lt;em&gt;"let's add an AI wrapper to our existing software."&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;I am talking about &lt;strong&gt;agentic transformation&lt;/strong&gt; across entire industries. Redesigning how companies operate from the ground up, how services are delivered, and how knowledge work is actually produced.&lt;/p&gt;

&lt;p&gt;There are two distinct reasons to do this right now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Preparation:&lt;/strong&gt; We will be structurally prepared when AGI-level systems actually arrive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Market Creation:&lt;/strong&gt; We can create an entirely new market around that transformation. We can give our own knowledge workers a chance to build the new economy, rather than watching imported solutions quietly eliminate the old one. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because if we wait until the technology is completely mature, the transition will already be decided for us.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Uncomfortable Reality
&lt;/h3&gt;

&lt;p&gt;I don't know exactly what the end state looks like. Nobody does. &lt;/p&gt;

&lt;p&gt;But one thing is becoming increasingly difficult to argue against: The 9–5 knowledge economy as we know it is coming to an end.&lt;/p&gt;

&lt;p&gt;The only question left is whether we actively shape what replaces it, or simply deal with whatever arrives.&lt;/p&gt;




</description>
      <category>ai</category>
      <category>futureofwork</category>
      <category>techleadership</category>
      <category>startup</category>
    </item>
    <item>
      <title>The End of Code as the Final Product (The Agentic Shift)</title>
      <dc:creator>Jalal Maskoun</dc:creator>
      <pubDate>Fri, 04 Sep 2026 19:52:13 +0000</pubDate>
      <link>https://dev.to/jalal246/the-end-of-code-as-the-final-product-the-agentic-shift-okk</link>
      <guid>https://dev.to/jalal246/the-end-of-code-as-the-final-product-the-agentic-shift-okk</guid>
      <description>&lt;p&gt;We keep talking about AI as a "coding assistant." I think that framing is already becoming outdated.&lt;/p&gt;

&lt;p&gt;A recent paper, &lt;em&gt;Agentic Software: How AI Agents Are Restructuring the Software Paradigm&lt;/em&gt; by Zhenfeng Cao, makes a much bigger argument: &lt;strong&gt;AI agents may fundamentally change what we mean by software.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For about 50 years, the basic software engineering model was:&lt;br&gt;
&lt;em&gt;Humans write code&lt;/em&gt; → &lt;em&gt;code contains the logic&lt;/em&gt; → &lt;em&gt;machines execute it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Agentic software flips that model entirely. Instead:&lt;br&gt;
&lt;em&gt;Humans define intent&lt;/em&gt; → &lt;em&gt;agents reason&lt;/em&gt; → &lt;em&gt;agents generate/use code&lt;/em&gt; → &lt;em&gt;systems execute&lt;/em&gt; → &lt;em&gt;outcomes are evaluated.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The code is no longer necessarily the product.&lt;/strong&gt; It can become an ephemeral tool used by the agent to accomplish a goal.&lt;/p&gt;

&lt;p&gt;That points to an interesting evolution in software delivery:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Licensed software:&lt;/strong&gt; You received the software and managed much of the surrounding infrastructure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SaaS:&lt;/strong&gt; The vendor took over infrastructure and operational complexity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent-as-a-Service (AaaS):&lt;/strong&gt; The system increasingly takes on part of the decision-making and execution complexity itself.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that changes software engineering at a much deeper level than AI writing code faster.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Core Object of Engineering is Shifting:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;From the code itself&lt;/strong&gt; → To the autonomous system around it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;From explicitly encoding every rule&lt;/strong&gt; → To designing how models reason and act.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;From writing every instruction&lt;/strong&gt; → To defining intent, constraints, evaluation, and outcomes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;From code author&lt;/strong&gt; → To system architect and outcome auditor.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This creates a very different engineering discipline. &lt;/p&gt;

&lt;p&gt;The hard problem may no longer be: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"How do I write the code?" &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is becoming: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"How do I design a system that can reason, act, recover from failure, and remain trustworthy?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Architecture, observability, evaluation, security, human oversight, and system design may matter even more, not less, as the amount of code humans write directly continues to decline.&lt;/p&gt;

&lt;p&gt;If AI-generated code becomes a mere implementation detail, what becomes the most valuable skill for a software engineer?&lt;/p&gt;




&lt;p&gt;&lt;a href="https://www.linkedin.com/in/jalal-again/" rel="noopener noreferrer"&gt;Read the original discussion and share your thoughts on LinkedIn&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>softwareengineering</category>
      <category>architecture</category>
      <category>startup</category>
    </item>
    <item>
      <title>The Org Chart Is About to Become Obsolete</title>
      <dc:creator>Jalal Maskoun</dc:creator>
      <pubDate>Thu, 03 Sep 2026 20:20:00 +0000</pubDate>
      <link>https://dev.to/jalal246/the-org-chart-is-about-to-become-obsolete-5bd</link>
      <guid>https://dev.to/jalal246/the-org-chart-is-about-to-become-obsolete-5bd</guid>
      <description>&lt;p&gt;The org chart is about to become obsolete.&lt;/p&gt;

&lt;p&gt;Not because companies will stop needing people. &lt;/p&gt;

&lt;p&gt;Because companies will stop needing as many people to coordinate the work.&lt;/p&gt;

&lt;p&gt;For decades, scaling a company meant scaling management. More employees led to more managers, more coordinators, more meetings, more reporting, and more bureaucracy. &lt;/p&gt;

&lt;p&gt;That model made sense when coordination required humans. It makes far less sense when AI agents can coordinate continuously.&lt;/p&gt;

&lt;p&gt;Imagine an enterprise where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HR agents handle recruiting workflows, compensation administration, compliance, and employee requests.&lt;/li&gt;
&lt;li&gt;Operations agents monitor execution, SLAs, bottlenecks, and resource allocation in real time.&lt;/li&gt;
&lt;li&gt;Finance agents reconcile transactions, flag anomalies, forecast cash needs, and initiate routine workflows.&lt;/li&gt;
&lt;li&gt;Cross-functional agent swarms coordinate execution without waiting for a weekly status meeting.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The biggest impact of AI may not be replacing individual jobs. It may be removing entire layers of organizational coordination.&lt;/p&gt;

&lt;p&gt;That changes what the company itself looks like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Middle-management layers shrink.&lt;/li&gt;
&lt;li&gt;Administrative coordination collapses.&lt;/li&gt;
&lt;li&gt;Status meetings disappear.&lt;/li&gt;
&lt;li&gt;White-collar roles built primarily around moving information between humans become increasingly difficult to justify.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The human role shifts from &lt;em&gt;“Manage the work”&lt;/em&gt; to &lt;em&gt;“Design, supervise, and improve the system that does the work.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There’s an even bigger implication for finance. Today, companies carry enormous fixed costs in the form of salaries and headcount. Tomorrow, more of that operating model could become variable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Payroll&lt;/strong&gt; → Compute&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Headcount&lt;/strong&gt; → Agents&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Management layers&lt;/strong&gt; → Orchestration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Status reports&lt;/strong&gt; → Real-time system telemetry&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This doesn't mean the office disappears. It means the architecture of the office changes.&lt;/p&gt;

&lt;p&gt;If you're building a company today, the strategic question is no longer: &lt;em&gt;“Who should we hire next?”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It is: &lt;em&gt;“Should this role exist as a human role at all?”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That is a much more uncomfortable question. And probably the most important one.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://www.linkedin.com/in/jalal-again/" rel="noopener noreferrer"&gt;Read the original discussion and share your thoughts on LinkedIn&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>management</category>
      <category>startup</category>
      <category>futureofwork</category>
    </item>
    <item>
      <title>The Only AI Advantage That Can't Be Subscribed</title>
      <dc:creator>Jalal Maskoun</dc:creator>
      <pubDate>Thu, 03 Sep 2026 19:41:17 +0000</pubDate>
      <link>https://dev.to/jalal246/the-only-ai-advantage-that-cant-be-subscribed-4m75</link>
      <guid>https://dev.to/jalal246/the-only-ai-advantage-that-cant-be-subscribed-4m75</guid>
      <description>&lt;p&gt;In two years, every company will say "we use AI." That's not a prediction; it's already happening.&lt;/p&gt;

&lt;p&gt;Which means "we use AI" isn't an advantage anymore. The model isn't your edge. Anyone can call the same tool you're calling.&lt;/p&gt;

&lt;p&gt;The real edge is what you know that the AI doesn't: your customers, your failures, the messy details only you've lived through. Feed that in, and AI becomes powerful. Skip it, and you're just borrowing someone else's brain.&lt;/p&gt;

&lt;p&gt;So the only question worth asking is: what do we know that no model does, and are we actually using it, or is it still stuck in someone's head?&lt;/p&gt;

&lt;p&gt;That's the edge. Everything else is a subscription.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://www.linkedin.com/in/jalal-again/" rel="noopener noreferrer"&gt;Read the original discussion and share your thoughts on LinkedIn&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>startup</category>
      <category>strategy</category>
      <category>productdesign</category>
    </item>
    <item>
      <title>The Return of the Super App</title>
      <dc:creator>Jalal Maskoun</dc:creator>
      <pubDate>Wed, 02 Sep 2026 20:37:14 +0000</pubDate>
      <link>https://dev.to/jalal246/the-return-of-the-super-app-58e2</link>
      <guid>https://dev.to/jalal246/the-return-of-the-super-app-58e2</guid>
      <description>&lt;p&gt;Super apps were always the right idea. The timing was just wrong.&lt;/p&gt;

&lt;p&gt;For years, the barrier wasn't strategy. It was the interface. You can't group twenty services into one app without burying the user in menus, tabs, and onboarding flows nobody finishes.&lt;/p&gt;

&lt;p&gt;That barrier is gone.&lt;/p&gt;

&lt;p&gt;When your app can talk to the user and then execute, you don't need twenty screens for twenty services. You need one conversation. The interface shrinks. The service layer expands. Complexity moves from the user's screen to the model's reasoning; where it belongs.&lt;/p&gt;

&lt;p&gt;This is the moment super apps stop being a distribution problem and start being an execution problem. The companies that win this won't be the ones with the most features. They'll be the ones with the fewest screens standing between a user and what they actually need done.&lt;/p&gt;

&lt;p&gt;If you're still designing for more screens, you're designing for the last decade.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://www.linkedin.com/in/jalal-again/" rel="noopener noreferrer"&gt;Read the original discussion and share your thoughts on LinkedIn&lt;/a&gt;&lt;/p&gt;

</description>
      <category>productdesign</category>
      <category>superapps</category>
      <category>ai</category>
      <category>startup</category>
    </item>
    <item>
      <title>Infinite Scroll Was Never a Feature</title>
      <dc:creator>Jalal Maskoun</dc:creator>
      <pubDate>Wed, 02 Sep 2026 20:36:10 +0000</pubDate>
      <link>https://dev.to/jalal246/infinite-scroll-was-never-a-feature-470c</link>
      <guid>https://dev.to/jalal246/infinite-scroll-was-never-a-feature-470c</guid>
      <description>&lt;p&gt;Every browse-and-filter interface was a workaround, not a feature.&lt;/p&gt;

&lt;p&gt;Users were never asking for infinite scroll. They were asking for the thing they wanted. We gave them raw data and filters because the system couldn't understand the request; it could only display rows and let the user run their own query, manually, with their thumb.&lt;/p&gt;

&lt;p&gt;That workaround is over.&lt;/p&gt;

&lt;p&gt;Users already know what they want. They don't want to browse fifty options ranked by relevance score. They want the three that actually fit. AI models can finally take a real request and return a real answer, instead of a dataset dressed up as a decision.&lt;/p&gt;

&lt;p&gt;The products that win next will stop asking users to do the filtering themselves. They'll do it for them and only show up when the match is right.&lt;/p&gt;

&lt;p&gt;Infinite scroll wasn't a design choice. It was a limitation we mistook for a feature. &lt;/p&gt;

&lt;p&gt;Time to build like the limitation is gone.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://www.linkedin.com/in/jalal-again/" rel="noopener noreferrer"&gt;Read the original discussion and share your thoughts on LinkedIn&lt;/a&gt;&lt;/p&gt;

</description>
      <category>productdesign</category>
      <category>ai</category>
      <category>ux</category>
      <category>startup</category>
    </item>
    <item>
      <title>The "Delete" Mindset: Why Most AI Strategies Fail Founders</title>
      <dc:creator>Jalal Maskoun</dc:creator>
      <pubDate>Wed, 02 Sep 2026 20:34:16 +0000</pubDate>
      <link>https://dev.to/jalal246/the-delete-mindset-why-most-ai-strategies-fail-founders-1aep</link>
      <guid>https://dev.to/jalal246/the-delete-mindset-why-most-ai-strategies-fail-founders-1aep</guid>
      <description>&lt;p&gt;Most "AI strategy" in businesses right now is just adding a chatbot to something that was already broken.&lt;/p&gt;

&lt;p&gt;That's not strategy. That's decoration.&lt;/p&gt;

&lt;p&gt;The real question every CEO should be asking isn't "where can we add AI"; it's "which slow, manual decision in this company should no longer exist." &lt;/p&gt;

&lt;p&gt;Approvals that take a week. Reports someone builds by hand every Monday. Customer answers that sit in a queue for a human to type out.&lt;/p&gt;

&lt;p&gt;AI doesn't make those faster. It makes them unnecessary.&lt;/p&gt;

&lt;p&gt;The companies that win the next 5 years won't be the ones with the most AI tools bolted on. They'll be the ones who deleted the most steps.&lt;/p&gt;

&lt;p&gt;What's one process in your business that should disappear? Not speed up, but disappear?&lt;/p&gt;




&lt;p&gt;&lt;a href="https://www.linkedin.com/in/jalal-again/" rel="noopener noreferrer"&gt;Read the original discussion and share your thoughts on LinkedIn&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>leadership</category>
      <category>startup</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Your AI Strategy Is Just Decoration</title>
      <dc:creator>Jalal Maskoun</dc:creator>
      <pubDate>Wed, 02 Sep 2026 20:32:16 +0000</pubDate>
      <link>https://dev.to/jalal246/your-ai-strategy-is-just-decoration-261</link>
      <guid>https://dev.to/jalal246/your-ai-strategy-is-just-decoration-261</guid>
      <description>&lt;p&gt;Most "AI strategy" in businesses right now is just adding a chatbot to something that was already broken.&lt;/p&gt;

&lt;p&gt;That's not strategy. That's decoration.&lt;/p&gt;

&lt;p&gt;The real question every CEO should be asking isn't "where can we add AI"; it's "which slow, manual decision in this company should no longer exist."&lt;/p&gt;

&lt;p&gt;Approvals that take a week. Reports someone builds by hand every Monday. Customer answers that sit in a queue for a human to type out.&lt;/p&gt;

&lt;p&gt;AI doesn't make those faster. It makes them unnecessary.&lt;/p&gt;

&lt;p&gt;The companies that win the next 5 years won't be the ones with the most AI tools bolted on. They'll be the ones who deleted the most steps.&lt;/p&gt;

&lt;p&gt;What's one process in your business that should disappear? Not speed up, but disappear?&lt;/p&gt;




&lt;p&gt;&lt;a href="https://www.linkedin.com/in/jalal-again/" rel="noopener noreferrer"&gt;Read the original discussion and share your thoughts on LinkedIn&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>leadership</category>
      <category>startup</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Your AI Strategy Is Just an IT Request</title>
      <dc:creator>Jalal Maskoun</dc:creator>
      <pubDate>Wed, 02 Sep 2026 20:30:29 +0000</pubDate>
      <link>https://dev.to/jalal246/your-ai-strategy-is-just-an-it-request-3o2n</link>
      <guid>https://dev.to/jalal246/your-ai-strategy-is-just-an-it-request-3o2n</guid>
      <description>&lt;p&gt;If your AI strategy sits with your IT department, you don't have an AI strategy. You have a technology project. And that's a dangerous distinction.&lt;/p&gt;

&lt;p&gt;100 years ago, carriage companies didn't lose because they built bad carriages. They lost because they misunderstood what the automobile was. They thought the new technology was simply a better version of what they already sold. It wasn't. It changed the entire operating system of the economy.&lt;/p&gt;

&lt;p&gt;AI is doing the same thing to business.&lt;/p&gt;

&lt;p&gt;Yet most companies are still asking: "Where can we use AI?" That's the wrong question.&lt;/p&gt;

&lt;p&gt;The question is: "If we were building this company today, what would we design differently because AI exists?"&lt;/p&gt;

&lt;p&gt;That's a CEO question. Not an IT question. Because the real opportunity isn't adding a chatbot.&lt;/p&gt;

&lt;p&gt;It's rebuilding how work gets done.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sales:&lt;/strong&gt; Stop using AI to tell salespeople which leads to call. Build an AI sales agent that continuously monitors the market, identifies companies showing buying signals, researches the account, finds the right decision-makers, builds the business case, starts the conversation, follows up, handles objections, and books the meeting.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HR:&lt;/strong&gt; Stop using AI to rank CVs. Build an AI recruiting agent that understands the roles you need, searches talent pools, identifies potential candidates, reaches out, has the initial conversation, evaluates fit against your requirements, schedules interviews, and keeps candidates engaged throughout the process.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customer Service:&lt;/strong&gt; Stop using AI to answer support tickets. Build an AI service agent that understands the customer's problem, checks their history, investigates the issue across your systems, takes action, resolves the problem, processes the necessary changes, and escalates only when human judgment is actually required.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's the difference between using AI to automate tasks and using AI to redesign the company.&lt;/p&gt;

&lt;p&gt;The companies that win with AI won't necessarily be the ones with the most sophisticated models. They'll be the ones willing to question the way they've operated for the last 10, 20, or 30 years.&lt;/p&gt;

&lt;p&gt;Because AI doesn't just give you a faster way to do yesterday's work. It gives you permission to ask whether yesterday's work should exist at all.&lt;/p&gt;

&lt;p&gt;So here's the uncomfortable question for every CEO:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you had to rebuild your company from zero today, which department would look completely different?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's probably where your AI strategy should start.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://www.linkedin.com/in/jalal-again/" rel="noopener noreferrer"&gt;Read the original discussion and share your thoughts on LinkedIn&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>leadership</category>
      <category>business</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Introducing DFlex - A Modern Javascript Drag and Drop Library</title>
      <dc:creator>Jalal Maskoun</dc:creator>
      <pubDate>Fri, 10 Nov 2023 10:03:44 +0000</pubDate>
      <link>https://dev.to/jalal246/introducing-dflex-a-modern-javascript-drag-and-drop-library-26k0</link>
      <guid>https://dev.to/jalal246/introducing-dflex-a-modern-javascript-drag-and-drop-library-26k0</guid>
      <description>&lt;p&gt;I'm excited to announce the release of DFlex, a new Javascript library for building modern drag and drop interfaces. &lt;/p&gt;

&lt;p&gt;DFlex aims to make it easy to add natural dragging, dropping, and sorting interactions to your web apps. It is lightweight, dependency-free, and works across all modern browsers.&lt;/p&gt;

&lt;p&gt;Some key features of DFlex include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DOM Manipulation&lt;/strong&gt; - DFlex directly manipulates the DOM instead of reconstructing it like other libraries. This results in better performance and avoids layout shifts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Transformation Scheduler&lt;/strong&gt; - DFlex has its own scheduler and reconciler to transform elements. This prevents blocking and allows smooth, concurrent animations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Custom Events &amp;amp; Listeners&lt;/strong&gt; - DFlex provides custom events for dragging, interactivity, siblings, and more. It also has layout listeners to monitor state changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Modular Architecture&lt;/strong&gt; - DFlex is built with a modular architecture, including separate packages for the DOM generator, utilities, store, draggable, and more.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Framework Agnostic&lt;/strong&gt; - DFlex is framework agnostic and works with React, Vue, Angular, and vanilla JS.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Configurable&lt;/strong&gt; - Options like dragging threshold, restrictions, auto-scroll, and more can be configured per element.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I built DFlex to push drag and drop capabilities further and handle complex interfaces at scale without compromises. The project is MIT licensed and open source on &lt;a href="https://github.com/dflex-js/dflex" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Here is a simple DnD component using React and DFlex:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Simple DFlex DnD Component &lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;DnD&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@dflex/dnd&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;draggableInstance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;DFlexDnD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unregister&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onMouseDown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;draggableInstance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DnD&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientY&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onMouseMove&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;draggableInstance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;draggableInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dragAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onMouseUp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;draggableInstance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;draggableInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;endDragging&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nx"&gt;draggableInstance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;
      &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;onMouseDown&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onMouseDown&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;onMouseMove&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onMouseMove&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;onMouseUp&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onMouseUp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;  
    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;DFlexDnD&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;With just a few lines of code, we can add drag and drop capabilities to a component. The DFlex store manages registration, while the DnD instance handles the dragging logic.&lt;/p&gt;

&lt;p&gt;I'd love for you to check out the &lt;a href="https://www.dflex.dev" rel="noopener noreferrer"&gt;DFlex website&lt;/a&gt; to see examples and live demos. Let me know if you end up building something cool with DFlex! I'm always looking for feedback to help improve the library.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/dflex-js" rel="noopener noreferrer"&gt;
        dflex-js
      &lt;/a&gt; / &lt;a href="https://github.com/dflex-js/dflex" rel="noopener noreferrer"&gt;
        dflex
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      The sophisticated Drag and Drop library you've been waiting for 🥳
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;
  &lt;a href="https://www.dflex.dev/" rel="nofollow noopener noreferrer"&gt;
    &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fdflex-js%2Fdflex%2Fmaster%2FDFlex-readme.png" alt="DFlex is a Javascript library for modern Drag and Drop apps"&gt;
  &lt;/a&gt;
&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;
  &lt;a href="https://github.com/dflex-js/dflex" rel="noopener noreferrer"&gt;
    &lt;img src="https://camo.githubusercontent.com/c62c084319ad07e0bfa69450e5ffc0f635363cd9221324566ee3a4faf1b0fe57/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f776f726b666c6f772f7374617475732f64666c65782d6a732f64666c65782f556e69742054657374" alt="Dflex build status"&gt;
  &lt;/a&gt;
  &lt;a href="https://github.com/dflex-js/dflex/pulls" rel="noopener noreferrer"&gt;
    &lt;img src="https://camo.githubusercontent.com/9aa2e0bf8f8ccacb3086155b34d6579cfb0d4e20baba2980bc2bb05ee4c59e61/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732d70722f64666c65782d6a732f64666c6578" alt="number of opened pull requests"&gt;
  &lt;/a&gt;
  &lt;a href="https://www.npmjs.com/package/@dflex/dnd" rel="nofollow noopener noreferrer"&gt;
    &lt;img src="https://camo.githubusercontent.com/fa7fcee2af252807fc7fb8b2380a37611c2e428ad34e4a7c9024c322e7b31047/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f4064666c65782f646e64" alt="DFlex last released version"&gt;
  &lt;/a&gt;
  &lt;a href="https://github.com/dflex-js/dflex/issues" rel="noopener noreferrer"&gt;
  &lt;img src="https://camo.githubusercontent.com/f93f4ae92078b8773d6e71f268652e1cb9af61f3f12402a4b017e4cf398a2217/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732f64666c65782d6a732f64666c6578" alt="number of opened issues"&gt;
  &lt;/a&gt;
  &lt;a href="https://github.com/dflex-js/dflex/pulls" rel="noopener noreferrer"&gt;
   &lt;img src="https://camo.githubusercontent.com/dd0b24c1e6776719edb2c273548a510d6490d8d25269a043dfabbd38419905da/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5052732d77656c636f6d652d627269676874677265656e2e737667" alt="Dflex welcomes pull request"&gt;
  &lt;/a&gt;
  &lt;a href="https://twitter.com/intent/follow?screen_name=dflex_js" rel="nofollow noopener noreferrer"&gt;
    &lt;img src="https://camo.githubusercontent.com/cddb43d2fce6053bfe0758b06831078fd43a04af343107df780b24535060bc23/68747470733a2f2f696d672e736869656c64732e696f2f747769747465722f75726c3f6c6162656c3d466f6c6c6f7725323025343064666c65785f6a73267374796c653d736f6369616c2675726c3d6874747073253341253246253246747769747465722e636f6d25324664666c65785f6a73" alt="Follow DFlex on twitter"&gt;
  &lt;/a&gt;
&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;DFlex&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;DFlex is a Javascript library for modern Drag and Drop apps. It's built
with vanilla Javascript and implemented an enhanced transformation mechanism to
manipulate DOM elements. It is by far the only Drag and Drop library on the
internet that manipulates the DOM instead of reconstructing it and has its own
scheduler and reconciler.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Features&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Dynamic architecture.&lt;/li&gt;
&lt;li&gt;Traverse DOM without calling browser API.&lt;/li&gt;
&lt;li&gt;Infinite DOM transformation instead of reconstructing the DOM tree with every interaction.&lt;/li&gt;
&lt;li&gt;Customized and enhanced reconciler targets only elements transformed from origin.&lt;/li&gt;
&lt;li&gt;Isolated from data flow with a scheduler prevents any blocking event.&lt;/li&gt;
&lt;li&gt;Prevent layout shift that happens with any Drag and Drop mechanism.&lt;/li&gt;
&lt;li&gt;Animated transformation with each interaction.&lt;/li&gt;
&lt;li&gt;Headless and compatible with any modern JS framework.&lt;/li&gt;
&lt;li&gt;Targeting each DOM element individually based on registration.&lt;/li&gt;
&lt;li&gt;Event driven and fully customized API.&lt;/li&gt;
&lt;li&gt;Extensible using its own matching algorithm instead of flat recursion algorithm(s).&lt;/li&gt;
&lt;li&gt;Support three different types…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/dflex-js/dflex" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>webdev</category>
      <category>opensource</category>
      <category>javascript</category>
    </item>
    <item>
      <title>To Puppeteer, or to Cypress</title>
      <dc:creator>Jalal Maskoun</dc:creator>
      <pubDate>Wed, 22 Jul 2020 20:21:46 +0000</pubDate>
      <link>https://dev.to/jalal246/to-puppeteer-or-to-cypress-4ccl</link>
      <guid>https://dev.to/jalal246/to-puppeteer-or-to-cypress-4ccl</guid>
      <description>&lt;p&gt;Working on a layout is not easy when there are too many possibilities and it gets more complicated if it's related to mouse direction. It's not just up and down, you literally need to test all horizontal and vertical possibilities. Imagine you also study elements getting effected by mouse movement, where things getting harder and harder. &lt;/p&gt;

&lt;p&gt;In the nutshell, I am a hard unit-test believer, but in this case, you definitely need to do testing and not a unit test we are talking here about an end-to-end test where you see elements moving virtually and experience each case individually.&lt;/p&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/jalal246/using-jest-puppeteer-with-monorepo-3kj2" class="crayons-story__hidden-navigation-link"&gt;Using unit and integration tests in Jest&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/jalal246" class="crayons-avatar  crayons-avatar--l  "&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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F126717%2Fb2192225-a47b-462a-8d40-c1a7762b1713.jpeg" alt="jalal246 profile" class="crayons-avatar__image" width="720" height="720"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/jalal246" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Jalal Maskoun
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Jalal Maskoun
                
                
              
              &lt;div id="story-author-preview-content-371364" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/jalal246" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F126717%2Fb2192225-a47b-462a-8d40-c1a7762b1713.jpeg" class="crayons-avatar__image" alt="" width="720" height="720"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Jalal Maskoun&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/jalal246/using-jest-puppeteer-with-monorepo-3kj2" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jun 27 '20&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/jalal246/using-jest-puppeteer-with-monorepo-3kj2" id="article-link-371364"&gt;
          Using unit and integration tests in Jest
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag crayons-tag--filled  " href="/t/showdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;showdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/javascript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;javascript&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/testing"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;testing&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/jalal246/using-jest-puppeteer-with-monorepo-3kj2" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;7&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/jalal246/using-jest-puppeteer-with-monorepo-3kj2#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              11&lt;span class="hidden s:inline"&gt;&amp;nbsp;comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            2 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


&lt;p&gt;The big question is how you do it, taking into consideration that your project already uses a unit test with Jest.&lt;/p&gt;




&lt;h3&gt;
  
  
  Puppeteer it
&lt;/h3&gt;

&lt;p&gt;The wise decision in my case is to use, Puppeteer. You integrate Puppeteer with Jest in &lt;code&gt;jest.integration.config.js&lt;/code&gt; a whole new config and start writing your first integration test.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;preset&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jest-puppeteer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything is &lt;code&gt;async&lt;/code&gt; in Puppeteer so you go by something like this to get your element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;waitForSelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#id-something&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I need to get element box size so I added:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;elmBox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;boundingBox&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;elmBox&lt;/span&gt;

&lt;span class="c1"&gt;// do something here...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You immediately start to notice that's Puppeteer is natural. I am not learning something new, it's easy to use and you supposedly can go further. Let's try mouse events.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// move the mouse to new coordinates &lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mouse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// triggers mouse down&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mouse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;down&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// move the mouse to new horizontal position&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mouse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// triggers mouse up&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mouse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;up&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Very easy. Very handy. Except there's a configuration related. you can't &lt;a href="https://github.com/smooth-code/jest-puppeteer/pull/276" rel="noopener noreferrer"&gt;keep the browser open&lt;/a&gt;, there's no time travel, and you can't repeat the test cases individually. So, if you test and develop by doing &lt;a href="https://en.wikipedia.org/wiki/Test-driven_development" rel="noopener noreferrer"&gt;TDD&lt;/a&gt; it's nearly impossible to actually see what's going on. You can slow down the test but if you running a server and you wait to browser to re-launch that's means waiting for infinity.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nl"&gt;devtools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="nx"&gt;slowMo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even with Puppeteer reaching version 5 there's a gap in its ecosystem. Because it's not a testing framework.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Puppeteer is a Node library which provides a high-level API to control Chrome or Chromium over the DevTools Protocol. &lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Trying Cypress
&lt;/h3&gt;

&lt;p&gt;The first issue with Cypress, that you need to start from scratch. A new assertion, a new testing framework, with a new structure. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Floh41p05j32tcb7ub2m2.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Floh41p05j32tcb7ub2m2.gif" alt="install cypress" width="602" height="265"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The installation includes examples that really help to know where you are going and what your test cases should look like. You use a chain of commands. You get something, trigger it, test it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#id-something&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;elm&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nx"&gt;elmBox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;elm&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;getBoundingClientRect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;elmBox&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cypress uses &lt;code&gt;trigger&lt;/code&gt; to trigger an event&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#id-something&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trigger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mousedown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;button&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trigger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mousemove&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;clientX&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;clientY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It uses a whole different approach but once you read it you easily get it. Until you start to use assertion.&lt;/p&gt;

&lt;p&gt;This is from Cypress documentation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.empty&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Login&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.visible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wrap&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;its&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;eq&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You take a deep breath and ask yourself, should I really have to learn this? Even something like &lt;code&gt;beforeAll&lt;/code&gt; in cypress is &lt;code&gt;before&lt;/code&gt;. So, you get the sense that whatever transition you make it's not going to be smooth as you expect. &lt;/p&gt;

&lt;p&gt;But your test runs with zero-config, with time travel, and yes you can repeat it forever. And it's super-fast.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjli1uoi14dmh9ze2jf17.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjli1uoi14dmh9ze2jf17.gif" alt="Cypress is fast" width="444" height="572"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, my problem is not with speediness. I need, at a certain point to be able to repeat the same test command.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmk9xkk5v2oubs62b99eg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmk9xkk5v2oubs62b99eg.gif" alt="repeate the test" width="761" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It turns out, Cypress automatically takes a screenshot for every command and you simply can highlight it forever which means a totally new debugging experience.&lt;/p&gt;




&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;When it comes to increasing productivity, end-to-end test can be the real solution. Forget about all articles tell you about the benefits of testing and why you should use e2e. I personally experienced a huge difference in fixing bugs saving hours of chasing needles in a haystack. &lt;/p&gt;

&lt;p&gt;Puppeteer can be a solution for expanding your test cases. But if you are using it with development, the answer is Cypress.&lt;/p&gt;

&lt;p&gt;Cypress is rich with examples, and a supportive community. It's designed for the end-to-end tests; therefore, you won't struggle using it. If you are familiar with &lt;a href="https://mochajs.org/" rel="noopener noreferrer"&gt;Mocha&lt;/a&gt; it won't take you a long time to get familiar with assertation. And it's amazing how you can use it even with no previous background about this type of testing. Most importantly, you immediately start experiencing the benefits of each test you write instead of figuring out how to configure it with your project.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>testing</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Using unit and integration tests in Jest</title>
      <dc:creator>Jalal Maskoun</dc:creator>
      <pubDate>Sat, 27 Jun 2020 16:42:16 +0000</pubDate>
      <link>https://dev.to/jalal246/using-jest-puppeteer-with-monorepo-3kj2</link>
      <guid>https://dev.to/jalal246/using-jest-puppeteer-with-monorepo-3kj2</guid>
      <description>&lt;p&gt;I was trying to use &lt;a href="https://github.com/smooth-code/jest-puppeteer" rel="noopener noreferrer"&gt;jest-puppeteer&lt;/a&gt; with monorepo project &lt;a href="https://github.com/jalal246/dflex" rel="noopener noreferrer"&gt;i'm working on&lt;/a&gt; in roadmap aiming to add integration tests using &lt;code&gt;puppeteer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And honestly, I didn't have any idea how to load different &lt;code&gt;jest.config.js&lt;/code&gt; for different packages I already have in the monorepo.&lt;/p&gt;




&lt;p&gt;In case anyone stuck in the same problem as me. The simple solution is to separate the unit test from an integration test. Obvious? didn't seem so for me.&lt;/p&gt;

&lt;p&gt;This "separation" should be reflected in the project structure, config files, and running scripts.&lt;/p&gt;

&lt;p&gt;Of course, the main problem I faced here, is dealing with the switching environment. I use &lt;code&gt;testEnvironment: "jsdom"&lt;/code&gt; and to run &lt;code&gt;puppeteer&lt;/code&gt; you have to remove any testing environment and use &lt;code&gt;preset: "jest-puppeteer"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Lesson 1: You can't run all tests at once.&lt;br&gt;
Lesson 2: It doesn't matter if you are using monorepo or not.&lt;/p&gt;

&lt;p&gt;So, I ended up with the following structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;myProj1/
  src/
  test/
    integration/
      myFrist.test.js
    foo.test.js
    bar.test.js
  package.json

myProj2/
  ...
myProj3/
  ...
jest.config.js
jest.integration.config.js
package.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What's in config files?&lt;/p&gt;

&lt;p&gt;Well, not much at all. &lt;/p&gt;

&lt;p&gt;In &lt;code&gt;jest.config.js&lt;/code&gt;, the main goal is to exclude the integration test.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;testEnvironment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jsdom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;testPathIgnorePatterns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;test/integration&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside &lt;code&gt;jest.integration.config.js&lt;/code&gt;, make sure to test only the integration files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;preset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jest-puppeteer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;testRegex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/integration/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And finally inside root &lt;code&gt;package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scripts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;test:unit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;test:e2e&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jest -c jest.integration.config.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;yarn test:unit &amp;amp;&amp;amp; yarn test:e2e&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using &lt;code&gt;jest -c&lt;/code&gt; to pass a custom config for Jest. Since I have &lt;code&gt;jest.config.js&lt;/code&gt; for the unit test there's no need to pass one, Jest will automatically read it. But that's not the case for &lt;code&gt;test:e2e&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Eventually, the &lt;code&gt;test&lt;/code&gt; script will run both integration and unit tests.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fiayi7goirfreyl2e9wsr.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fiayi7goirfreyl2e9wsr.gif" alt="show test" width="800" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>showdev</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
