<?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: Tymoteusz Stępień</title>
    <description>The latest articles on DEV Community by Tymoteusz Stępień (@inanoniloquent).</description>
    <link>https://dev.to/inanoniloquent</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%2F1035846%2F078f2ba3-6fe3-4ee4-a950-e888b316d370.jpeg</url>
      <title>DEV Community: Tymoteusz Stępień</title>
      <link>https://dev.to/inanoniloquent</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/inanoniloquent"/>
    <language>en</language>
    <item>
      <title>Turning testing frameworks "post-it notes" into a Testing Arsenal</title>
      <dc:creator>Tymoteusz Stępień</dc:creator>
      <pubDate>Fri, 14 Mar 2025 19:56:08 +0000</pubDate>
      <link>https://dev.to/inanoniloquent/turning-testing-frameworks-post-it-notes-into-a-testing-arsenal-4m0b</link>
      <guid>https://dev.to/inanoniloquent/turning-testing-frameworks-post-it-notes-into-a-testing-arsenal-4m0b</guid>
      <description>&lt;p&gt;My testing notes were living their best life... scattered across post-its everywhere 🙈 Finally got my act together and created Testing Arsenal - just a collection of testing patterns that work with literally ANY framework (and saved my back few times)!&lt;/p&gt;

&lt;p&gt;Sure, you'll spot some Playwright/Cypress vibes in the examples, but these tricks work whether you're team pytest, Catch2, or whatever else you're into.&lt;/p&gt;

&lt;p&gt;It's got all the good stuff:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API testing hacks&lt;/li&gt;
&lt;li&gt;Test data tricks&lt;/li&gt;
&lt;li&gt;Auth shortcuts&lt;/li&gt;
&lt;li&gt;more!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Still working on it (aren't we all working on ourselves? lol), but wanted to share early. Check it out, you can edit it, share your thoughts, maybe just argue it has no sense!&lt;/p&gt;

&lt;p&gt;Link: &lt;a href="https://github.com/403-html/testing-arsenal" rel="noopener noreferrer"&gt;https://github.com/403-html/testing-arsenal&lt;/a&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>architecture</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>The QA architecture handbook: Guide for building a quality-first culture</title>
      <dc:creator>Tymoteusz Stępień</dc:creator>
      <pubDate>Mon, 26 Aug 2024 15:43:44 +0000</pubDate>
      <link>https://dev.to/inanoniloquent/the-qa-architecture-handbook-guide-for-building-a-quality-first-culture-1bgm</link>
      <guid>https://dev.to/inanoniloquent/the-qa-architecture-handbook-guide-for-building-a-quality-first-culture-1bgm</guid>
      <description>&lt;p&gt;Hey! I recently (literally last weekend 🤠) created a GitHub repository focused on building a quality-first culture within organizations.&lt;/p&gt;

&lt;p&gt;Short background on why:&lt;br&gt;
After participating in several recruitment interviews where some of them were cool, and I could learn a lot from those teams (in addition to bringing the experience I already have), but also there were some teams not so well prepared in terms of quality (where there is/was a lot to improve), I was inspired to share (and create platform for it) some insights and best practices for establishing a robust QA architecture.&lt;/p&gt;

&lt;p&gt;Main:&lt;br&gt;
This repository (&lt;a href="https://github.com/403-html/the-qa-architecture-handbook" rel="noopener noreferrer"&gt;https://github.com/403-html/the-qa-architecture-handbook&lt;/a&gt;), is designed to be a collaborative resource for anyone looking to learn about or improve QA processes. It covers topics like fostering a quality-first mindset, implementing continuous monitoring, and leveraging automation and testing with users. It's not for personal QA development (for this, you can utilize QA Roadmap – &lt;a href="https://roadmap.sh/qa" rel="noopener noreferrer"&gt;https://roadmap.sh/qa&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Whether you're just starting to develop your QA strategy, or you're looking to brush up your existing practices, I believe this handbook can be a valuable resource. I encourage you to check it out and contribute your own experiences and insights (whether it's adding something new, providing feedback, or just straight up "this is bs" – let's talk about it) – let's work together to build a stronger QA community.&lt;/p&gt;

</description>
      <category>qa</category>
      <category>tutorial</category>
      <category>news</category>
      <category>testing</category>
    </item>
    <item>
      <title>EVRTN - web3 stack, for everything you may need</title>
      <dc:creator>Tymoteusz Stępień</dc:creator>
      <pubDate>Fri, 15 Dec 2023 22:43:20 +0000</pubDate>
      <link>https://dev.to/inanoniloquent/evrtn-web3-stack-for-everything-you-may-need-1kaa</link>
      <guid>https://dev.to/inanoniloquent/evrtn-web3-stack-for-everything-you-may-need-1kaa</guid>
      <description>&lt;h2&gt;
  
  
  Preamble
&lt;/h2&gt;

&lt;p&gt;As a developer, aspiring to gain some web3 code knowledge, I started side project meant to teach me how to move around blockchain realm. But although there were many technologies present, none of them seemed to work well together. I made the decision to press ahead, fusing the best available technology I know into a logical structure. Here comes &lt;strong&gt;EVRTN&lt;/strong&gt;, a fusion of Node.js, TypeScript-powered React, Ethereum, and smart contract language - Vyper. It's a unified approach to creating decentralized apps (dApps), not &lt;em&gt;just&lt;/em&gt; a stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  So what's in there?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Ethereum: The backbone of blockchain
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://ethereum.org/en/" rel="noopener noreferrer"&gt;&lt;strong&gt;Ethereum&lt;/strong&gt;&lt;/a&gt; is at the center of EVRTN and is most likely the most popular blockchain platform worldwide based on its widespread usage. In order to implement smart contracts and create dApps, Ethereum's strong ecosystem provides the flexibility and security required. It is the best choice for the core of our framework due to its broad adoption and encouraging community.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vyper: Secure and simple smart contracts
&lt;/h3&gt;

&lt;p&gt;Moving up the stack, we have &lt;a href="https://docs.vyperlang.org/en/stable/" rel="noopener noreferrer"&gt;&lt;strong&gt;Vyper&lt;/strong&gt;&lt;/a&gt;, which is a practical smart contract writing alternative to Solidity, which is infamous for its quirks. Because Vyper's syntax is similar to that of Python, it is easier to understand and use, which lowers the learning curve considerably. Vyper is perfectly aligned with Ethereum to enable a more safe and efficient development process by putting security and simplicity first.&lt;/p&gt;

&lt;h3&gt;
  
  
  React and TypeScript: A frontend power duo
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.typescriptlang.org/" rel="noopener noreferrer"&gt;&lt;strong&gt;TypeScript&lt;/strong&gt;&lt;/a&gt; and &lt;a href="https://react.dev/" rel="noopener noreferrer"&gt;&lt;strong&gt;React&lt;/strong&gt;&lt;/a&gt;, two of the most effective and versatile frontend technologies, combine to form EVRTN's frontend team. Building dependable, scalable user interfaces with type safety and user-friendly codebase management is made possible by this combination. React and TypeScript work well together to improve the development experience and make it simpler to create responsive and dynamic dApps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Node.js: The backend enabler
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://nodejs.org/en" rel="noopener noreferrer"&gt;&lt;strong&gt;Node.js&lt;/strong&gt;&lt;/a&gt; rounds out the stack. Node.js supports extra backend operations, such as masking certain backend work, leveraging secrets to connect to blockchain, or just giving simplified API, while Ethereum and Vyper handle the blockchain and smart contract features. It offers an environment that is both scalable and efficient for server-side logic, API integrations, and other uses, and it connects with the other technologies with ease.&lt;/p&gt;

&lt;h2&gt;
  
  
  Postamble
&lt;/h2&gt;

&lt;p&gt;So... will you give it a whip? Of course it can take anything in there, as it's flexible framework. You can build it with &lt;a href="https://v2.vitejs.dev/" rel="noopener noreferrer"&gt;Vite&lt;/a&gt;, or just &lt;a href="https://esbuild.github.io/" rel="noopener noreferrer"&gt;esbuild&lt;/a&gt;. You want your frontend to shine? There are tons of options to choose from - all of them will work here.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>programming</category>
      <category>webdev</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Cypress vs. Sorry-Cypress - Decoding the Drama</title>
      <dc:creator>Tymoteusz Stępień</dc:creator>
      <pubDate>Wed, 08 Nov 2023 11:52:14 +0000</pubDate>
      <link>https://dev.to/inanoniloquent/cypress-vs-sorry-cypress-decoding-the-drama-4an4</link>
      <guid>https://dev.to/inanoniloquent/cypress-vs-sorry-cypress-decoding-the-drama-4an4</guid>
      <description>&lt;p&gt;As a long-time Cypress user, I'll be honest - the latest update from Cypress in &lt;a href="https://www.cypress.io/blog/2023/11/07/update-defense-intellectual-property" rel="noopener noreferrer"&gt;this post&lt;/a&gt; is the most chaotic post I've seen in years. Trying to "defend" some actions which shouldn't take place in the first place. Let's dive in into this a bit more.&lt;/p&gt;

&lt;p&gt;Also... blocking previous version, like month-two after first blockage? Do it in one batch at least. Have balls to do it, it's part of your statement, that's for "our" good.&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;As we enter the waters of the Cypress vs. Sorry-Cypress dispute, we start on a trip that necessitates a thorough examination of both technical viewpoints and legal complexities. However, let us be clear from the start: utilizing Cypress' reports under the MIT license is fully within the established conventions of the open-source community, and prohibiting commercial use in places other than "yours" undermines the spirit of it. So we can skip half of the post of Cypress team.&lt;/p&gt;

&lt;h1&gt;
  
  
  Trademark and Naming
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;edit: btw... they for quite some time already use name Currents (year or so?), and Sorry-Cypress for self-host dashboard, but Currents is name for hosted by them dashboard solution&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Sorry-Cypress, which inappropriately uses our company name in their product&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In a world where the term "Cypress" &lt;a href="https://uspto.report/TM/97870603" rel="noopener noreferrer"&gt;is not registered trademark&lt;/a&gt; (as of 8th Nov 2023), how we can talk about "theft" or "misappropriation"? It is time to recognize that their use extends outside the domain of exclusive ownership. In the technology industry, similar names coexist happily, suggesting an unwritten consensus on the vast technological environment.&lt;/p&gt;

&lt;p&gt;Instances such as "k3s" (wrapping what Kubernetes does, but make it easier to chew) cheekily nodding at "k8s" (Kubernetes) or the symbiotic relationship between "preact" and "react" demonstrate that coexistence is possible without igniting conflict. Or consider the famous Pizza Hot... oh wait.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F702c3vbe5di8si69vruk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F702c3vbe5di8si69vruk.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When the community surfaced the concern of using our brand name and violating our terms of service, Sorry-Cypress publicly acknowledged the source of confusion. Sorry-Cypress justified their rationale that using our product name benefited from greater "discoverability" because it uses “Cypress” in its name and it enables improved “SEO ranking”.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And that's exactly what they decided to do. They kept the name because there were no further comments or suggestions, even from the Cypress team, to change it. The maintainer could feel like he was in agreement with user who opened the "issue". There was no pressure, no alteration, just a straightforward decision. As promised, a separate brand was later established - Currents. It was explicitly mentioned that this was primarily to address potential trademark concerns (which, as I mentioned earlier, Cypress &lt;strong&gt;still&lt;/strong&gt; lacks), rather than Terms of Service (trademark takes precedence over TOS in this case). He even emphasized that it was initially created as a temporary placeholder, and he doesn't see any issue with changing it - this comment and decision was made &lt;strong&gt;two years ago&lt;/strong&gt;... I'll repeat it in case you missed that...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;T W O     Y E A R S&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Didn't the Cypress team make any effort to communicate with the author(s) about this for two years? Really?&lt;/p&gt;

&lt;p&gt;It appears evident that the Cypress team made significant efforts to find a rationale (but not rational) for obstructing the CI processes of numerous companies now. Is the naming of the tool truly the crux of the matter? Or maybe when they've seen users fleeing from them to Currents? Could this not have been addressed through inter-company discussions, or legal proceedings if it's genuinely constituted legal issue? Why burden customers and users with this?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;To sum this up&lt;/strong&gt;: If Cypress' team believes there is a legal issue, &lt;strong&gt;going to court is a potential option&lt;/strong&gt;. However, fighting with their own users is not a long-term solution. Outperforming the competition through innovation and quality should be the goal. If you can't do it, and you block competition through your MIT licensed software... is not a good PR move. Just saying. Stop pretending it's for "good of users". &lt;strong&gt;Competition in the market is good for users. Forcing the use of one tool is not.&lt;/strong&gt; Basics of economics.&lt;/p&gt;

&lt;h1&gt;
  
  
  Pricing and Design
&lt;/h1&gt;

&lt;p&gt;While Cypress deserves kudos for pioneering a well-designed dashboard, it's crucial to recognize that being the first doesn't negate others from drawing inspiration and pushing innovation. It's like one car model taking cues from another, both embodying the essence of an automobile but distinct in their design, features, and user experience. Example? Hyundai Sonata and Kia Optima. They literally look the same on one side.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F6uhkcq9u6ofzo83azddy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F6uhkcq9u6ofzo83azddy.png" alt="Hyundai Sonata and Kia Optima"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(&lt;em&gt;edit: Here was example of Toyota 86 and Subaru BRZ, but apparently they had agreements, so I found other one, who doesn't have one, just use same common base. Thanks motorsport geeks.&lt;/em&gt;)&lt;/p&gt;

&lt;p&gt;Let's take a hard look at the pricing tactics and layouts of both Cypress Dashboard and Currents Dashboard. It is critical to distinguish between design decisions based on industry best practices and obvious imitation. A sleek, user-friendly pricing structure isn't an imitation - it's a testament of a good design. It is only reasonable for companies in the same industry to use comparable techniques.&lt;/p&gt;

&lt;p&gt;Moreover, when two services offer akin functionalities, it's hardly surprising that they might employ parallel terminology. This isn't mimicry—it's adherence to established industry standards.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Currents.dev describes their services as “a drop-in replacement for Cypress Dashboard”, which in our opinion, is a disturbingly similar version of the Cypress Cloud.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No sh*t, both provides dashboard to track e2e tests reports.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We have observed patterns of replicating the user experience, feature release timing, product feature names, marketing language, documentation, and pricing value metrics that go beyond simple derivatives of the work done by Cypress.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nice, as user of Currents' dashboard... I requested few features there, all were added. You don't have them for sure, as we decided to not use Cypress dashboard, too expensive for what it provide. Also... do you know like... competition? If one company adds something new, in the same field of work of other, then other tries to speed up development and add something similar.&lt;/p&gt;

&lt;h1&gt;
  
  
  Mocking with tool name, market dynamics, affordability
&lt;/h1&gt;

&lt;p&gt;Rather than receiving criticism, Currents deserves praise for openly positioning itself as a more economical option. As mentioned earlier, the act of mocking is considered commonplace. It's ironic how Currents (with its Sorry-Cypress'  tool) has now become synonymous with improvement — they've developed a better dashboard. Embodying the phrase "Sorry Cypress, we've enhanced it." sounds fitting. Have you ever heard of effective marketing?&lt;/p&gt;

&lt;p&gt;It is standard industry practice to accommodate a wide range of budgets and needs. And Cypress team made nice design to accommodate this. So if Currents wants to claim to be a 'drop-in replacement for Cypress Dashboard' and carve out a niche and cater to a specific demographic... they had managed to provide a more cost-effective option. And they did. That's what's hurting Cypress team the most.&lt;/p&gt;

&lt;p&gt;They expressly highlight their independence from the Cypress team (FAQ and landing page on their site), emphasizing their offer of a less expensive dashboard than Cypress Dashboard. Competition is the standard in business; those that are unable to compete often risk obsolescence. Doing this by blocking physically other company sucks.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Legal Arena
&lt;/h1&gt;

&lt;p&gt;While we dissect the technical and competitive realms, let's not sidestep the legal battleground. Cypress' strategic choice to engage in the open market discussion, rather than resorting to legal (or inter-company) action, is a tacit admission that this isn't solely a legal wrangle. This approach, while astute from a business standpoint, carries ramifications for users. So better move this to court room, and after decision share with us that you won.&lt;/p&gt;

&lt;p&gt;Edit: I have to add something. Small kudos, that they don't hide it's about Currents, and their Sorry-Cypress' tool (and Currents dashboard). At first they said "3rd party plugins" but everyone knew what's poppin'.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>opensource</category>
      <category>testing</category>
    </item>
    <item>
      <title>Reality Check: Cypress' Actions Speak Louder than Words</title>
      <dc:creator>Tymoteusz Stępień</dc:creator>
      <pubDate>Thu, 28 Sep 2023 06:35:37 +0000</pubDate>
      <link>https://dev.to/inanoniloquent/reality-check-cypress-actions-speak-louder-than-words-3c6b</link>
      <guid>https://dev.to/inanoniloquent/reality-check-cypress-actions-speak-louder-than-words-3c6b</guid>
      <description>&lt;p&gt;There comes a point where you have to confront reality, and you can't be a fanboy without examining some things with clarity. Recently, Cypress published a &lt;a href="https://www.cypress.io/blog/2023/09/25/defense-intellectual-property/" rel="noopener noreferrer"&gt;blog post&lt;/a&gt; that left me with jaw dropped, unable to square their professed principles with their actual actions.&lt;/p&gt;

&lt;p&gt;In their statement, Cypress emphasizes their commitment to open source and the thriving community that has contributed to their success over the past 9 years. They highlight their desire to facilitate &lt;strong&gt;innovation and collective growth through collaboration&lt;/strong&gt;. Admirable, right?&lt;/p&gt;

&lt;p&gt;The latest decision to limit access to third-party plugins, including other dashboards, paints a starkly different picture. If you're integrated with third parties, you literally cannot perform your tests. They justify this decision by claiming to protect their intellectual property, a term that raises eyebrows considering that framework project is founded on the &lt;strong&gt;MIT license&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To be clear, an MIT license means that the code can be used, modified, and shared freely. It is a pillar of open source, cultivating a culture of collaboration and mutual benefit. So, how does the concept of "&lt;em&gt;intellectual property&lt;/em&gt;" come into the picture?&lt;/p&gt;

&lt;p&gt;The decision to restrict third-party products and services seems to be at odds with the very essence of open source. It not only stifles innovation but also hampers the diverse ways in which developers choose to integrate and display testing results.&lt;/p&gt;

&lt;p&gt;Cypress Cloud, their commercial product, undoubtedly plays a vital role in sustaining their community-focused model. However, it should not come at the cost of limiting users' choices and forcing them into a one-size-fits-all approach. If you can't build a more cost-effective and convenient dashboard tool, then why not cooperate with those who can?&lt;/p&gt;

&lt;p&gt;Fair competition and ethical business practices are laudable goals, but they must be manifested in actions, not just words. The current move raises questions about whether these principles are being applied consistently.&lt;/p&gt;

&lt;p&gt;Edit: I've recently learned that they permit a third-party dashboards, but it comes at a hefty price (5k$/year) for the connector. You can find more details &lt;a href="https://go.cypress.io/continue-recording-with-gateway-connector" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Could you please reaffirm that this isn't a money-making scheme, but rather a genuine effort to protect community rights and intellectual property? Lol.&lt;/p&gt;

</description>
      <category>cypress</category>
      <category>opensource</category>
      <category>testing</category>
      <category>programming</category>
    </item>
    <item>
      <title>Starting Your Test Automation Journey: A Guide for QAs with automation!</title>
      <dc:creator>Tymoteusz Stępień</dc:creator>
      <pubDate>Sat, 05 Aug 2023 18:27:17 +0000</pubDate>
      <link>https://dev.to/inanoniloquent/starting-your-test-automation-journey-a-guide-for-fresh-qa-professionals-4ggi</link>
      <guid>https://dev.to/inanoniloquent/starting-your-test-automation-journey-a-guide-for-fresh-qa-professionals-4ggi</guid>
      <description>&lt;p&gt;I want to provide something lighter but yet significant this month, especially for aspiring quality assurance professionals who want to start their test automation journey. This piece was inspired by a recent conversation I had, and even while it may not offer wholly fresh perspectives, it's important to be reminded of the essential stages to begin automated regression testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Steps for Aspiring QA Professionals in Test Automation
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Actual Projects&lt;/strong&gt;: When starting off, don't be discouraged by your lack of business experience. Accept open-source initiatives as your pals. Choose one that appeals to you, then add to it some automated tests. Present your work on websites like GitHub's personal README. Employers (more likely technical recruiters) value seeing real-world examples of your abilities and enthusiasm in action.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Code Reviews&lt;/strong&gt;: Code reviews are a good way to get advice from seasoned programmers. Discuss and solve issues with others on established open-source projects. Reviewers, who are frequently repository maintainers, will offer insightful criticism that will help you develop your coding techniques.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Programming Principles&lt;/strong&gt;: &lt;em&gt;Programming Principles&lt;/em&gt;: Get to know fundamental programming concepts like &lt;strong&gt;SOLID&lt;/strong&gt;, &lt;strong&gt;KISS&lt;/strong&gt;, and &lt;strong&gt;DRY&lt;/strong&gt;. Knowing these ideas makes you stand out as a conscientious coder. Use them to develop readable, maintainable, and well-organized code while writing automation scripts to impress potential employers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Practice, Practice, Practice&lt;/strong&gt;: Regression test automation and programming require a lot of practice. Use platforms for programming practice such as "Exercism.io," "Codewars," or "LeetCode" to take on different coding tasks. These websites include workouts to help you hone your abilities and discover frequently utilized coding patterns and automation methods.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Project Descriptions&lt;/strong&gt;: Don't forget to include detailed project descriptions in your resume and while exhibiting your work on websites like GitHub's PRs. Outline the goals of the project, the tools employed, and the difficulties you faced and how you handled them. For technical professions, it's essential to have excellent documentation and communication abilities.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Continuous Learning&lt;/strong&gt;: Accept lifelong learning to stay current with technology. Keep abreast on emerging test automation tools and frameworks. whenever possible, participate in webinars, workshops, and conferences. Being passionate about development and progress distinguishes you in the field.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Networking&lt;/strong&gt;: Create a network of experts and professionals in the field of test automation. Participate in discussions, connect with individuals, and join relevant online groups on sites like LinkedIn. Career advancement and possibilities might result through networking.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Regression test automation requires patience when first starting out, but retain a good attitude and keep going. Don't let rejections deter you; they are a necessary part of the trip. Although your professional path may take some unexpected detours, with perseverance and a growth mentality, you will succeed as a QA professional.&lt;/p&gt;

&lt;p&gt;So don't worry if there's no simple answer, as every career path is unique. Embrace the challenges and keep learning and improving along the way. Happy automating! 😊&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>career</category>
      <category>opensource</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>One moment, and all your problems are gone</title>
      <dc:creator>Tymoteusz Stępień</dc:creator>
      <pubDate>Sat, 08 Apr 2023 17:42:01 +0000</pubDate>
      <link>https://dev.to/inanoniloquent/one-moment-and-all-your-problems-are-gone-5d1p</link>
      <guid>https://dev.to/inanoniloquent/one-moment-and-all-your-problems-are-gone-5d1p</guid>
      <description>&lt;p&gt;Hello 🌎! Are you sick of having your Cypress tests fail at random? Do you find it difficult to keep up with the pace of development and achieve deadlines? Fear not, since today we'll be discussing a topic that could perhaps assist you with those issues: time management in Cypress.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Oh damn... next &lt;em&gt;agile&lt;/em&gt; or &lt;em&gt;scrum&lt;/em&gt; post? I can read few pages of manifesto myself...&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Before you start rolling your eyes and grumbling at the idea of another another time management post, please bear with me. This &lt;strong&gt;isn't&lt;/strong&gt; your normal "how to prioritize tasks" or "how to plan your day" advise. Instead, we'll get down to business with managing &lt;strong&gt;system time&lt;/strong&gt; in Cypress tests.&lt;/p&gt;

&lt;p&gt;So, why is time management sometimes vital in Cypress tests? For starters, time-related defects might be some of the most difficult to find and fix. They can also result in inconsistencies and flaky tests, which can be frustrating for both developers and QAs (and testers :troll-face:). Additionally, you may wish to simulate specific date and time settings in order to test certain functionality or edge cases after you fix some bug related to that.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;But how can we actually manage time in Cypress tests? Are we Doctor Strange with Time Stone?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's a great question! Although we might not have the Time Stone like Doctor Strange, we do have powerful tool at our disposal to manage time in Cypress tests. To control the system clock during your tests, one typical technique is to use the &lt;code&gt;cy.clock()&lt;/code&gt; command. Using &lt;code&gt;cy.clock()&lt;/code&gt; is fairly straightforward - simply call the command with a specific timestamp, and any subsequent time-related commands in your test will use that timestamp as the system clock. For example, you could set the system clock to a specific date and time in the past or future, and then test how your application behaves under those conditions.&lt;/p&gt;

&lt;p&gt;Of course, there are potential drawbacks to managing time with Cypress tests, as with any testing technique. It will add additional complexity to your tests and, if not done appropriately, can result in false positives or false negatives. That is why it's critical to assess the benefits and drawbacks and carefully consider whether time management is required for your specific tests.&lt;/p&gt;

&lt;p&gt;So there you have it: a quick rundown of time management in Cypress testing. Keep an eye out for future chapters. Have fun playing with &lt;code&gt;cy.clock()&lt;/code&gt; then. Playing with new techniques and tools is the most important part of any "tutorial" (I'd call it more of an acknowledgment for a brilliant tool)!&lt;/p&gt;

</description>
      <category>cypress</category>
      <category>javascript</category>
      <category>qa</category>
      <category>codequality</category>
    </item>
    <item>
      <title>Actions sequence is great... but</title>
      <dc:creator>Tymoteusz Stępień</dc:creator>
      <pubDate>Wed, 08 Mar 2023 09:30:30 +0000</pubDate>
      <link>https://dev.to/inanoniloquent/actions-sequence-is-great-but-2o5h</link>
      <guid>https://dev.to/inanoniloquent/actions-sequence-is-great-but-2o5h</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Let's keep this introduction brief. I had a lot of things on my mind after reading this fantastic article by &lt;a href="https://www.linkedin.com/in/filip-hric/" rel="noopener noreferrer"&gt;Filip Hric&lt;/a&gt; about &lt;a href="https://filiphric.com/how-to-structure-a-big-project-in-cypress" rel="noopener noreferrer"&gt;how to structure a big project in Cypress&lt;/a&gt;.&lt;br&gt;
I concur with some, disagree with others. His article covers a lot of ground despite being very brief. Hence, I'd want to start with a topic that is important to me: his actions sequence methodology. I'm hoping that this article may serve as a dialogue opener in some way. So let's get started!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Beginning
&lt;/h2&gt;

&lt;p&gt;To begin with, let's address some fundamental questions regarding test writing, such as the available approaches, the separation of logic from pages, and the existence (if any) of "bad" techniques. Regarding the first question of whether we should divide our testing project into complex logic, while &lt;strong&gt;it's not mandatory&lt;/strong&gt;, it &lt;strong&gt;can greatly simplify&lt;/strong&gt; the lives of devs/QAs. Adopting a standard method for writing test logic is crucial for ease of writing, reading, and managing tests in the long run, especially for larger projects, as mentioned in Filip's article.&lt;/p&gt;

&lt;h3&gt;
  
  
  Methodologies / design patterns
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Ok, you convinced me. What I can do? What I can slap into project and what will work for me?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Numerous effective methods exist for organizing test logic (&lt;em&gt;I'm not referring to organizing tests or the file structure for helper methods; this can be covered in another article as it's also a rather big topic&lt;/em&gt;). The optimal technique relies on factors such as the project's pace, team size, and what works best for the team. However, industry consider the following recommendations as the "golden trio" of methodologies used to maintain tests.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;u&gt;Page object model (POM)&lt;/u&gt;
&lt;/h4&gt;

&lt;p&gt;Page Object Model (POM) is a design pattern used to organize and maintain test automation code. In this methodology, each page of the application under test is represented by a separate class or module containing all the necessary elements and methods to interact with that page.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;POM promotes reusability of code by keeping page-specific code separate from test code&lt;/li&gt;
&lt;li&gt;It makes tests more readable and easy to maintain by encapsulating page functionality into separate classes&lt;/li&gt;
&lt;li&gt;It helps in minimizing code duplication and improves test maintainability&lt;/li&gt;
&lt;li&gt;It enhances test scalability as new pages can be added to the framework with ease&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It may not be the best approach for small-scale applications with a limited number of pages, as its designed for large and complex applications&lt;/li&gt;
&lt;li&gt;This methodology can be memory (RAM) demanding in more complex test setups, because it loads entire page classes and init (so also store them in-memory)them during the test configuration phase&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;u&gt;App actions&lt;/u&gt;
&lt;/h4&gt;

&lt;p&gt;App Actions is a well-known Cypress design pattern that allows for the creation of tests at a higher degree of abstraction. Rather than engaging with specific components on a page, tests are built by describing a sequence of user activities that mimic user behavior from any point in the app. It's because it uses public app methods to configure tests to our specifications before the test is done. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;App Actions increase test code readability and maintainability by abstracting low-level UI interactions to independent methods&lt;/li&gt;
&lt;li&gt;Enables us to prepare the app for testing purposes&lt;/li&gt;
&lt;li&gt;It decreases the complexity of test code and makes tests less prone to failure due to small UI changes&lt;/li&gt;
&lt;li&gt;It saves time in test creation and debugging as tests can be written faster with less boilerplate code like in POM&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It requires a good understanding of the application's user flows and may be more challenging for new devs/QAs/testers to learn&lt;/li&gt;
&lt;li&gt;It requires a good knowledge how the app is built, and how to expose certain functionalities of the app. Or it needs assistance from the dev's team&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;u&gt;BDD via Cucumber&lt;/u&gt;
&lt;/h4&gt;

&lt;p&gt;Behavior Driven Development (BDD) is a software development methodology that emphasizes collaboration between developers, testers, and stakeholders. Cucumber is a popular BDD tool that enables writing tests in a natural language format that can be easily understood by non-technical stakeholders.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"BDD via Cucumber" promotes collaboration between different teams and improves communication between developers, QAs, testers, and stakeholders&lt;/li&gt;
&lt;li&gt;It improves test traceability and provides better coverage of requirements&lt;/li&gt;
&lt;li&gt;Easy to understand tests building blocks&lt;/li&gt;
&lt;li&gt;It helps in identifying defects early in the development cycle, as cases usually written much earlier than in other methodologies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It requires additional setup and configuration to use Cucumber with Cypress&lt;/li&gt;
&lt;li&gt;It may not be the best approach for small-scale applications with a limited number of stakeholders (burning resources)&lt;/li&gt;
&lt;li&gt;It may require additional effort to maintain test code as requirements change&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Hey, but Filip mentioned "actions sequence", where does it fit? It's not in your list. I thought it's main reason why this article even exists!&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As far as I understand Filip's article, he's writing about mix, of app actions with "native" BDD of Cypress, and idea of page object model. So we operate on certain page... with usage of native Cypress commands, in BDD manner.&lt;/p&gt;

&lt;h2&gt;
  
  
  Actions sequence is great... but
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;I was surprised that someone is doing actions sequence. I'm (with colleagues) already using it across projects, much before the article showed up.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But first of all, as before, let's dive into, what it exactly is, its advantages and disadvantages.&lt;/p&gt;

&lt;p&gt;Actions Sequence is a test automation methodology that combines the principles of BDD, Page Object Model, and App Actions. In this methodology, tests are written as a sequence of user actions that operate on a particular page/view, using the native JS/TS functions (unlike App Actions, which uses Cypress Commands). Unlike POM, this methodology doesn't define page objects as classes, but instead, it focuses on defining separate actions on pages/views that can be reused across tests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Actions Sequence improves test reusability and maintainability by abstracting page interactions into separate actions&lt;/li&gt;
&lt;li&gt;It promotes a high level of readability and maintainability of test code&lt;/li&gt;
&lt;li&gt;It saves time in test creation and debugging as tests can be written faster with less boilerplate code&lt;/li&gt;
&lt;li&gt;It combines the best of both worlds: BDD for &lt;em&gt;almost&lt;/em&gt; natural language test writing and App Actions for higher-level interaction with the UI&lt;/li&gt;
&lt;li&gt;Eliminates POM's memory issue (but does it really? I mean in terms of Filip's article... I'll write about it later in this article)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Test framework is much more modular.

&lt;ul&gt;
&lt;li&gt;There might be question "&lt;em&gt;Why it's a problem, doesn't it bring flexibility, so it's advantage?&lt;/em&gt;" - let me explain my thought process:&lt;/li&gt;
&lt;li&gt;Yes, a more modular test framework with different actions for pages/views can improve test reusability and make the test code more maintainable from a mid/senior standpoint.
It can also make the structure of the test framework easier to grasp and reduce code duplication.&lt;/li&gt;
&lt;li&gt;However, the modular nature of the framework, can be more challenging for newcomers and necessitate a higher level of understanding to navigate. They may be more comfortable with Cypress Commands than with designing different actions for pages/views. Maintaining the correct folder/file structure might sometimes be difficult for novice devs/QAs. &lt;strong&gt;This series is designed for beginners who wish to break out of their shells.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Increased likelihood of code duplication by dev/QA who don't understand the structure of the test framework&lt;/li&gt;

&lt;li&gt;It necessitates a thorough understanding of the application's user flows and may be more difficult for inexperienced testers to master&lt;/li&gt;

&lt;li&gt;It might not be the best solution for super small-scale applications with a modest number of pages&lt;/li&gt;

&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;If you think it's working (so it must be great), why you used "but" in article's title?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It wasn't "but" in meaning "I'm against it". It was because I work with such approach for some time, I think I may have some ideas and approaches which I think can be... filling out some gaps in such approach Filip showed up in his article.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Selecting elements&lt;/strong&gt;&lt;br&gt;
I &lt;strong&gt;strongly agree&lt;/strong&gt; that using the testing attribute, such as 'data-cy' in the article's example, is beneficial. However, I have a concern regarding repeating these attributes. It's possible that the author only intended to demonstrate the process and avoid delving into the selection process. Nevertheless, I recommend a personalized approach to selecting elements on the page by separating and customizing them. I have already detailed this process in a "how-to" article, which can be found &lt;a href="https://dev.to/inanoniloquent/selectors-and-locators-544c"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using Cypress Commands&lt;/strong&gt;&lt;br&gt;
As previously stated, this method has the benefit of being lightweight and using less RAM. However, the example provided by the author involves creating new Cypress Commands for every action, which I believe could result in even more memory usage than the Page Object Model.&lt;/p&gt;

&lt;p&gt;To illustrate, let's consider a scenario where we have two pages. With the current approach, all actions would be written as Cypress Commands. This means that when we want to test something on just one page, we end up loading the entire hefty Cypress API into memory, even though we only use a portion of it for the test (excluding the literal Cypress API operations). So, how would I go about it?&lt;/p&gt;

&lt;p&gt;Actions could be carried with using modular approaches. &lt;br&gt;
Instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// cypress/commands/actions.ts -&amp;gt; imported to cypress/commands/e2e.ts&lt;/span&gt;
&lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pickSidebarItem&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="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Settings&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Account&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;My profile&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Log out&lt;/span&gt;&lt;span class="dl"&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="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;[data-cy=hamburger-menu]&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;click&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;[data-cy=side-menu]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// cypress/e2e/app1/some-test.spec.ts&lt;/span&gt;
&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sample&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should pick sidebar item&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="o"&gt;=&amp;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;pickSidebarItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Settings&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;url&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="s2"&gt;include&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;/settings&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="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'd suggest such approach:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// cypress/e2e/app1/utils/actions.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pickSidebarItem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Settings&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Account&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;My profile&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Log out&lt;/span&gt;&lt;span class="dl"&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="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;[data-cy=hamburger-menu]&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;click&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;[data-cy=side-menu]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// cypress/e2e/app1/some-test.spec.ts&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;pickSidebarItem&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;utils/actions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sample&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should pick sidebar item&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;pickSidebarItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Settings&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;url&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="s2"&gt;include&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;/settings&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="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thanks to this we divided responsibilities of methods. Actions are kept close to app/page/view we test. Also from my point of view, Cypress Commands should expand usability of Cypress API (like new way of selecting elements), not adding specific interactions or steps that a user would take &lt;strong&gt;within an app&lt;/strong&gt; (or to setup tests for testing).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Clutter of Cypress namespace&lt;/strong&gt;&lt;br&gt;
This is something completely separate from the second point I made earlier. If we don't use Cypress Commands, we don't have to clutter up the Cypress namespace. But guess what? We can still make chainable methods (and give them types). Isn't that great?&lt;/p&gt;

&lt;p&gt;From this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// cypress/commands/actions.ts -&amp;gt; imported to cypress/commands/e2e.ts&lt;/span&gt;
&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="nb"&gt;global&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nx"&gt;Cypress&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Chainable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;addBoardApi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;addBoardApi&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="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Creates a new board using the API
 * @param name name of the board
 * @example
 * cy.addBoardApi('new board')
 *
 */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addBoardApi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Chainable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&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;return&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;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&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;/api/boards&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="nx"&gt;name&lt;/span&gt; &lt;span class="p"&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;body&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;log&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;board&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;to this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// cypress/e2e/app1/utils/actions.ts&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Creates a new board using the API
 * @param name name of the board
 * @example
 * addBoardApi('new board')
 *
 */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addBoardApi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Chainable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&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;return&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;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&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;/api/boards&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="nx"&gt;name&lt;/span&gt; &lt;span class="p"&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;body&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;log&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;board&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;So, to sum it up, Filip came up with this cool way to blend App Actions with native BDD from Cypress and the Page Object Model concept. It's pretty awesome, but there's room for customization to make it even better for our specific needs. So, what do you think? Do you have any ideas for how we could tweak it to make it work even better for us? Open to discussion!&lt;/p&gt;

</description>
      <category>cypress</category>
      <category>programming</category>
      <category>discuss</category>
      <category>testing</category>
    </item>
    <item>
      <title>Selectors and locators</title>
      <dc:creator>Tymoteusz Stępień</dc:creator>
      <pubDate>Thu, 02 Mar 2023 09:18:24 +0000</pubDate>
      <link>https://dev.to/inanoniloquent/selectors-and-locators-544c</link>
      <guid>https://dev.to/inanoniloquent/selectors-and-locators-544c</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;I must warn you that the piece that follows may not be the most content-rich you've ever read. Instead, it's more of a jumble of scattered notes that I'm leaving for my future self. Nonetheless, if you find something useful in these reflections, I'll consider this "project" a success.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Navigating through elements in browser's DOM while writing Cypress automated tests can be quite a challenging task, especially when it comes to selecting elements. Let me ask you something. How many times did you see, or even wrote by yourself (myself included!) such code?&lt;/p&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%2Fscg2owcglnydl2jccpm3.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%2Fscg2owcglnydl2jccpm3.png" alt="Brittle test code" width="800" height="607"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Something looks odd, isn't? For me it's lacking a proper and immutable way of selecting elements.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Why we should even care so much of "immutable way" of selecting elements? We just "clicking through" them, isn't? Just write and leave tactic.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Well... no, not really. Let me tell you why we should care:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Test stability&lt;/code&gt;: The goal of testing is to guarantee that the application is working properly. If the tests aren't stable, meaning they pass and fail without any modifications to the code, they aren't serving their objective. Utilizing immutable attributes ensures that the selector used to find the element in the DOM remains consistent and unchanged and it's independent of the element's content, even if the application's implementation changes.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Test maintainability&lt;/code&gt;: &lt;strong&gt;Tests aren't a one-time activity&lt;/strong&gt;, they need to be maintained as the application evolves. If the selectors used to find elements in the DOM aren't stable, then they will need to be updated every time the implementation of the application changes. Using immutable attributes ensures that selectors remain stable and tests don't need as much changes as with "quick selects of elements".&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Readability and clarity&lt;/code&gt;: Using attributes to pick elements in the DOM improves the readability and clarity of the test code. It explicitly states that the element is being chosen for testing reasons only, making the test's intent more clear.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Separation of objectives&lt;/code&gt;: Separating testing objectives from application implementation specifics is critical for test maintainability and readability. Using properties to identify DOM components allows for this separation of responsibilities and makes the tests less dependent on implementation details. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, it's just &lt;a href="https://docs.cypress.io/guides/references/best-practices#Selecting-Elements" rel="noopener noreferrer"&gt;a good and well known standard&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Ok... so I should just toss into implementation of component just test attribute, like &lt;code&gt;data-test-id&lt;/code&gt; with unique name for it, which will describe it?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yes!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;I have unit tests already, picking elements in them by &lt;code&gt;someTestId&lt;/code&gt; attribute. Should I change it to &lt;code&gt;data-test-id&lt;/code&gt;?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No need! You can reuse one pattern across all test levels which operates on app's DOM! I'll just use &lt;code&gt;data-test-id&lt;/code&gt; in this example.&lt;/p&gt;

&lt;p&gt;So what I'd change to above code? Where's area to expand our setup? Let's say I have 🪄 &lt;em&gt;a magical powers&lt;/em&gt; 🪄. This is our React app "so far". Nothing fancy, just list of movies categories.&lt;/p&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%2Fw0lux2h6twe2056ux877.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%2Fw0lux2h6twe2056ux877.png" alt="Simple categories app" width="800" height="1318"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First of all - each &lt;code&gt;Link&lt;/code&gt; is part of the bigger list of items. So I'd change implementation, and I'd add to all of these links attribute, describing what is the purpose of them.&lt;/p&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%2F9phqhqbxbes1o0aylx2o.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%2F9phqhqbxbes1o0aylx2o.png" alt="Added attributes" width="800" height="1199"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There might be questions:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Hey, should I keep attribute locator hardcoded like that? Also why not use something like &lt;code&gt;link.id&lt;/code&gt; to create a "uniquely unique" element for each link? That way, I could easily find the "Action" button I'm looking for in provided example above. What do you think?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Those are great questions! Let's start with the second one. While using &lt;code&gt;link.id&lt;/code&gt; (or any other unique way of describing attribute) to create a unique test attribute might seem like a good idea, it's important to remember that test attributes should reflect the purpose of the elements, not the details of a particular part of the app. For this purpose we write tests. By creating a test attribute that's tied to the implementation details of the app, you run the risk of making your tests more brittle and harder to maintain over time.&lt;/p&gt;

&lt;p&gt;Regarding first question, the answer is actually quite simple: you can hardcode your test attributes, but it's generally more beneficial to keep them separate and avoid hardcoding whenever possible. That's where a locators file comes in handy. By maintaining a separate file for your test attributes, you can easily manage them in one place and avoid cluttering your code with hardcoded values.&lt;/p&gt;

&lt;p&gt;So, let's create a locators file and add it to our code! This will make our test attributes more maintainable and easier to manage in the long run.&lt;/p&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%2Fe46d0phfqjyzrlr89n63.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%2Fe46d0phfqjyzrlr89n63.png" alt="Added locators to implementation code" width="800" height="1384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With such separation we added way of maintaining all locators in one place. So if we ever want to add any other element to our app, we'll be having all locators in one place.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Ok, ok, but we're here for Cypress. Not React course. Where's Cypress in this?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After we edited our implementation, it's time for Cypress. So now, we can add locator of our choice, and pick it in our test.&lt;/p&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%2F5f9yy7m6u9l4unhgf4ki.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%2F5f9yy7m6u9l4unhgf4ki.png" alt="Simple locator switch to new version in test" width="800" height="515"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Damn! So now I have to write such abominations over and over? It had to be breeze and make it easier for me!&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Don't worry. This is why we have &lt;a href="https://docs.cypress.io/api/cypress-api/custom-commands#docusaurus_skipToContent_fallback" rel="noopener noreferrer"&gt;Cypress Commands&lt;/a&gt;. Let's make this test suite to its final form. Ah, also we should split this &lt;code&gt;contains&lt;/code&gt; method. Because as mentioned above - we shouldn't keep implementation details with testing objectives. We should check if it's an &lt;code&gt;Action&lt;/code&gt; text and not base on it.&lt;/p&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%2F8udlewck2t27088nr74k.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%2F8udlewck2t27088nr74k.png" alt="Finished, polished test" width="800" height="812"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here we have it. We used custom command, which we can use across all of the tests, what's more - we have the same, non hardcoded locator to select proper element. As extra style points we did separation of objectives within the code, so now we &lt;strong&gt;test stuff&lt;/strong&gt;, and &lt;strong&gt;not rely on them&lt;/strong&gt; to test stuff.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>webdesign</category>
      <category>designagencies</category>
      <category>freelancing</category>
    </item>
  </channel>
</rss>
