Skip to content

Using Cypress with Cucumber in a React Application

Using Cypress with Cucumber in a React Application

Introduction

We are going to be learning how to integrate Cypress with Cucumber in a React application. Cypress is the premier end-to-end testing platform to allow you to test user interactions, and end-to-end flows in your application.

What is Cucumber?

Cucumber logo

Cucumber creates a layer of abstraction that allows for better communication between business and technical folks, and facilitates the use of Behavior Driven Development (BDD). One of the additional benefits is that it essentially creates documentation, which stays up to date and is easy to share. Cucumber is built to support Behavior Drive Development (BDD). If you are unfamiliar with Behavior Driven Development, you can read Cucumber’s guide on it here: https://cucumber.io/docs/bdd/

Learn more about Cucumber in general here: https://cucumber.io/docs/guides/overview/

What is Gherkin?

In the simplest terms, Gherkin is a set of grammar rules that structure plain text for Cucumber to understand and process.

Learn more here: https://cucumber.io/docs/gherkin/

Setup

Steps

- Clone a React app to test against. Here is a link to a photo viewer and search app which we will be using:

https://github.com/Yog9/SnapShot

You will need to clone the app and get it running before we can move on to next steps. Below is a screenshot of the working app:

SnapShot app screenshot

- Add Cypress as a dev dependency within your application. Install Cypress npm i cypress --save-dev. Once you have completed this step, you should see "cypress": "^10.11.0", or something similar in the devDependencies section of your package.json file.

- Open and run Cypress to install it using the binary. You do this by typing the command npx cypress open in your terminal. If it's your first time running this command within your application, Cypress will prompt you to install some example tests and other helper files, and guide you through a basic configuration necessary for Cypress to operate within your application.

Cypress 1
Cypress 2
Cypress 3
Cypress 4
Cypress 5
Cypress 6

- Add the cypress-cucumber-preprocessor package to your project. This package was originally maintained by BrainFamily, but was recently taken over by Badeball. You can find it here:

https://www.npmjs.com/package/@badeball/cypress-cucumber-preprocessor

Use the command npm install --save-dev @badeball/cypress-cucumber-preprocessor

You can find the quick start guide here:

https://github.com/badeball/cypress-cucumber-preprocessor/blob/a2702f5ce247c96269a0432358ed919b596a4dbb/docs/quick-start.md

- Add @bahmutov/cypress-esbuild-preprocessor esbuild https://github.com/bahmutov/cypress-esbuild-preprocessor. Use the command npm i -D @bahmutov/cypress-esbuild-preprocessor esbuild. This should result in "esbuild": "^0.15.13" as well as "@bahmutov/cypress-esbuild-preprocessor": "^2.1.5" becoming part of the devDependencies in your package.json file.

Add cypress/webpack-preprocessor to your project. Use the command npm i --save-dev @cypress/webpack-preprocessor to add this package. The devDependencies section of your package.json file should now include, "@cypress/webpack-preprocessor": "^5.15.3" if done correctly.

- Configure cypress.config.ts file. Configure specPattern with "**/*.feature" and setupNodeEvents. Here is my file:

const { defineConfig } = require("cypress");
const createBundler = require("@bahmutov/cypress-esbuild-preprocessor");
const addCucumberPreprocessorPlugin =
  require("@badeball/cypress-cucumber-preprocessor").addCucumberPreprocessorPlugin;
const createEsbuildPlugin =
  require("@badeball/cypress-cucumber-preprocessor/esbuild").createEsbuildPlugin;

module.exports = defineConfig({
  e2e: {
    async setupNodeEvents(on, config) {
      const bundler = createBundler({
        plugins: [createEsbuildPlugin(config)],
      });

      on("file:preprocessor", bundler);
      await addCucumberPreprocessorPlugin(on, config);

      return config;
    },
    specPattern: "cypress/e2e/features/*.feature",
    baseUrl: "http://localhost:3000/SnapShot#/SnapScout/",
    chromeWebSecurity: false,
  },
});

Additionally, you will want to generate a cypress-cucumber-preprocessorrc.json file at the root level of your project in order to handle some additional configuration settings. My file contents are below:

{
  "json": {
    "enabled": false,
    "output": "jsonlogs/log.json",
    "formatter": "cucumber-json-formatter.exe"
  },
  "messages": {
    "enabled": false,
    "output": "jsonlogs/messages.ndjson"
  },
  "html": {
    "enabled": false
  },
  "stepDefinitions": [
    "[filepath]/**/*.{js,ts}",
    "[filepath].{js,ts}",
    "cypress/e2e/step_definitions/*.{js,ts}",
    "[filepath]\\***.{js,ts}",
    "[filepath].{js,ts}",
    "cypress\\e2e\\step_definitions\\*.{js,ts}"
  ]
}

Organize your files. There are multiple ways to organize your feature files and step definition files. For the purposes of this tutorial, we will place our feature files in a cypress > e2e > features directory, and our step definition files in a cypress > e2e > step_definitions directory.

Let's Write Some Tests!!

Let's create a simple feature file with some basic scenarios and test steps for this application. Here is a start in app.feature!

Feature: Snapshot website test scenarios
  Scenario: visiting the home page - successful search
    Given I visit the home page
    Then the header should be visible
    Then I click in the text input
    Then I type birds into the search input and press search button
    Then I should see Birds Images in header
    Then I click the Food button and see Food header and 24 images
import { Given, Then } from "@badeball/cypress-cucumber-preprocessor";

Given("I visit the home page", () => {
  cy.visit("/");
});

Then("the header should be visible", () => {
  cy.get("h1").should("be.visible");
});

Then("I click in the text input", () => {
  cy.get("input").click();
});

Then("I type birds into the search input and press search button", () => {
  cy.get("input").type("birds");
  cy.get(".search-button").click();
});

Then("I should see Birds Images in header", () => {
  cy.get(":nth-child(24) > img").should("be.visible");
});

Then("I click the Food button and see Food header and 24 images", () => {
  cy.get(":nth-child(4) > a").click({ force: true });
  cy.get(":nth-child(24) > img").should("be.visible");
});
Cypress test list screen
Running Test Screen

Summary

As you can see, setting up Cypress with Cucumber is a fairly straight-forward process. There are incredible benefits to using Cucumber with Cypress, particularly related to facilitating communication between non-technical and technical members of a development team, as well as creating ongoing project documentation, and an easy-to-understand guide for what your application or feature is doing.

This Dot Labs is a development consultancy that is trusted by top industry companies, including Stripe, Xero, Wikimedia, Docusign, and Twilio. This Dot takes a hands-on approach by providing tailored development strategies to help you approach your most pressing challenges with clarity and confidence. Whether it's bridging the gap between business and technology or modernizing legacy systems, you’ll find a breadth of experience and knowledge you need. Check out how This Dot Labs can empower your tech journey.

You might also like

State of React Ecosystem Wrap-Up January 2023 cover image

State of React Ecosystem Wrap-Up January 2023

In this State of React Ecosystem event, our panelists discussed the React Roadmap, Best Practices, Redux, Styling Libraries and techniques, Nextjs, and community initiatives! In this wrap-up, we will take a deeper look into these latest developments and explore what is on the horizon for React. You can watch the full State of React Ecosystem event on the This Dot Media YouTube Channel. Here is a complete list of the host and panelists that participated in this online event. Hosts__ - Tracy Lee, CEO, This Dot Labs, @ladyleet - Adam L. Barrett, Senior Software Engineer, This Dot, @adamlbarrett Panelists__ - Mark Erikson, Senior Front-End Engineer, Replay, Redux maintainer @acemarke - Tanner Linsley, VP of UI/UX, nozzle.io, TanStack Creator, @tannerlinsley - Dominik Dorfmeister, TanStack Query Maintainer, @TkDodo - Ben Ilegbodu, Frontend Architect, Stitch Fix, @benmvp - Chantastic, DX Engineer, Chromatic, @chantastic - Kathleen McMahon, Senior Design Systems Engineer, Northwestern Mutual, @resource11 Updates from Panelists and what they are currently working on The event started off with great conversation by getting updates, from our panelists, on what they are currently working on. Mark Erikson__ was first, and he talked about how Redux Toolkit 1.9 was shipped back in November 2022. It had new options for RTK Query as well as forms improvements by optimizing the internals. Redux Toolkit 2.0 is currently being developed! It will have breaking changes, and there are some big things coming with the release including modernizing the build output, and updating the package to be fully es module format package defined, and much more! Redux Toolkit 2.0 alpha 1 has already been shipped, and he is asking for users to try it out, and give feedback. Kathleen McMahon__ was next, and talked about how she has been with Nortwestern Mutual and is currently working on standing up their design tokens system as part of the Lunar Design system. She has been enjoying the work of trying to get things into a very big Enterprise level system. She also got the opportunity to give a couple talks last fall at React Brussels and React Verona where she talked about feature flagging, accessibility, and how to make some widgets accessible. She will be giving a similar talk at React Miami. Tanner Linsley__ gave a quick update that he is currently working on Type Safe Routing and has been for over a year learning about the intricacies of how all of that works with type safe everything. He mentioned that there is also going to be a lot of new TanStack packages to play around with. He has also been recently trying to rebuild all the reactivity engine using SolidJS, and he is working on some smaller libraries at TanStack that are going to be headless. Dominik Dorfmeister__ gave an update about what is coming for TanStack Query. In a recent update, they added a Svelte query adapter for TanStack Query. They have pretty much completed the cycle of having one adapter for all the major frameworks. He takes time to share a video that shows Astro with the same query client shared with four different components with each one in a different framework. It shows what you can do when everything works together with the same query client. He also goes over the roadmap for getting to TanStack Query v5 with it hopefully coming out sometime this year. Ben Ilegbodu__ is a Frontend Architect at Stitch Fix on the frontend platform team. He is part of a team that builds out all the platforms and design systems that other teams use to build a site. He has been helping build out the design system using React while documenting in Storybook. He also talks about how the team has been building a development platform for all the teams to build their apps. They are in the process of moving from Rails to NextJS using a wrapper. He finishes up by talking about working on a monorepo for all of their libraries. Chantastic__ talks about how he has been trying to do a little more with Youtube this year. He works at Chromatic which is a company that maintains StorybookJS. They are all working to get to Storybook day which is March 14, 2023. It’s an event that is going to be going over everything that is happening with Storybook 7. This concluded introduction as the event moved into general questions for the panel. Panel Questions Adam got the conversation going to this next part of the event by asking right if React is dying? The panelists got on this topic and maintained it throughout the rest of the event. Each panelist took the time to explain how it is either frustrating or misunderstood. There is still growth and evolution within the React ecosystem. With new frameworks and libraries comes a betterment for the community as a whole. They also brought up how the same sorts of things were said about other frameworks like Angular. Overall, there was agreement that React is not dead, but in a time where it is growing to be a better product overall. Conclusion The one question that was asked helped bring out an incredible conversation on where React is and where it is going. It is always good to continue to have these discussions in order to stay current or talk about what needs to be done to keep things moving forward for the future of the library. You can watch the full State of React Ecosystem event on the This Dot Media Youtube Channel....

How to Integrate Mailchimp Forms in a React Project cover image

How to Integrate Mailchimp Forms in a React Project

Intro Today we will cover how to set up an email signup form using React and Mailchimp. This blog will be using the starter.dev cra-rxjs-styled-components template to expedite the process. This article assumes you have a basic understanding of React, and have set up a Mailchimp account. Here is the code repo if you want to review it while reading, or just skip ahead. We will start with setting up our React project using Starter.dev for simplicity, and then finish it up by integrating the two for our signup form. To start, we will be using the command yarn create @this-dot/starter --kit cra-rxjs-styled-components, which can be found here. We’ll go ahead, and give the project a name. I will be calling mine react-mailchimp. Now we will navigate into the project and do a yarn install. Then we can run yarn run dev to get it up and running locally on localhost:3000. This should have us load up on the React App, RxJS, and styled-components Starter kit page. With that all set, we’ll also need to install jsonp by using yarn add jsonp`. We’ll be using jsonp instead of fetch to avoid any CORS issues we may run into. This also makes for an easy and quick process by not relying on their API, which can’t be utilized by the client. Now that we have our project set up, we will go ahead and go and grab our form action URL from MailChimp. This can be found by going to your Audience > Signup Forms > Embedded Forms > Continue and then grabbing the form action URL found in the Embedded Form Code. We need to make a small change to the URL and swap /post? with /post-json?. We can now start setting up our form input, and our submit function. I will add a simple form input and follow it up, and a submit function. Inside the submit function, we will use our imported jsonp to invoke our action URL. ` import { useState } from 'react'; import jsonp from 'jsonp'; export const MailChimp = () => { const [email, setEmail] = useState(''); const onSubmit = (e: any) => { e.preventDefault(); const url = 'insert-mailchimp-action-url-here'; jsonp(${url}&EMAIL=${email}`, { param: 'c' }, (_: any, data: any) => { console.log('data', data); const { msg } = data; alert(msg); }); }; return ( Email setEmail(e.target.value)} > Submit ); }; ` We’ll also add a quick alert to let the user know that it was successful and that’s it! We’ve now successfully added the email to our MailChimp account. Conclusion Today, we covered how to integrate Mailchimp with a react app using the cra-rxjs-styled-components template from starter.dev. I highly recommend using starter.dev to get your project up and running quickly. Here is the code repo again for you to check out....

Effective Communication Strategies Within The Software Development Organization cover image

Effective Communication Strategies Within The Software Development Organization

Have you ever been in a situation where you thought you were communicating effectively, only to realize later that the other person misunderstood what you were saying? Have you ever communicated with someone only to hear that they felt you provided way too much detail, or that you didn’t provide nearly enough detail? Communication in the workplace is how ideas, updates, directions, etc are transferred to others. Each party in a software development organization has differing needs and expectations when it comes to workplace communication. By learning to tailor your communication to meet the needs of each stakeholder, you can become a more effective communicator and achieve greater success within your organization. The requirements of various parties that you interact with in the workplace can vary wildly depending on several factors. Your awareness of these individualized communication preferences and how you can give each party what they want and need will impact your effectiveness in your daily activities, your perception by others, and even your upward mobility within the organization. That's the power of communication, and why it's so important to master effective communication strategies in the workplace! In this article, we'll explore the different types of stakeholders in a software development organization, the communication strategies that work best for each group, and how effective communication can help you advance your career in the industry. We'll start by discussing the difference between “communication” and “effective communication”, before diving into the different types of stakeholders in a software development organization. Then, we'll explore the communication strategies that work best for each group, and provide actionable tips for improving your communication skills. Communication vs. Effective Communication When it comes to communication, it's important to remember that the intended message is only effective if it's received and understood by the recipient, regardless of their background or level of familiarity with the topic. Effective communication is about sharing thoughts, ideas, opinions, knowledge, and data in a way that ensures that the message is received and understood by the recipient. With effective communication, the sender and receiver leave the exchange feeling satisfied. There is a shared understanding of what was intended to be transmitted by the sender. Stakeholder Types In any organization, you have many different types of parties involved in a software project. Let's group the parties involved in software development into three categories for the sake of clarity: - Development Team__ - This consists of individual contributors, project managers, scrum masters, QA testers, UX designers, UI designers, architects, etc. - Product Team__ - The product team is made up of a diverse group of individuals, including product owners, business analysts, architects, and more. - Executive Team__ - CTO, CEO, etc. Each of these parties requires a different type of communication, a different level, and has different needs from your interactions to allow you to provide value from what you are saying and to for them view you as an effective communicator. Let’s talk a bit about what each of these parties needs, and how you can interact with them in the most meaningful way possible. Development Team This is the most detailed version of the interaction. This group needs to be communicated with on the level of individual tickets and the details of those tickets. When interacting with the development team, it's important to focus on the nitty-gritty details of each task, ensuring that everything is sorted through meticulously. With this group, we will sort through specific implementation details. An example of interaction with someone from this group might look like this, “I am currently working on ticket 473, and trying to get the checkbox to behave correctly during testing. I have no blockers currently.” Product Team This group will be communicated with at the level of features and larger increments of work such as project milestones. This group is interested in chunks of a project, milestones, progress on the overall initiative, etc. An example of interaction with someone from this group might look like this, “The team is wrapping up development of the new Project X User Interface and will be moving to the implementation of the functionality next”. Executive Team This group is interested in the conversation at the highest levels of abstraction. Generally, they will be more concerned with things at the overall project level. When updating the executive team, it's important to provide high-level updates that summarize progress and focus on next steps. For example, you might say, 'We're making great progress on Showcase X and are on track to complete it soon. Next, we'll be shifting our attention to project Y.' Types of Communication What are some of the types of communication? It’s a great question. When you begin to study various communication styles, you will read about different personality types, and how those personalities interact with the world around them. You might hear things like aggressive, passive-aggressive, passive, and assertive communication styles. While understanding these can help you communicate effectively, we will focus on how different roles in a company require different levels of detail and specificity in their interactions. Your Natural Communication Style We all have a natural way that we prefer to communicate. Some are very direct and assertive. We might tend to be very to the point, with no filler, no fluff. Others might naturally tend to be more verbose, to fill in lots of details and context and information. Some naturally meet somewhere in the middle on the spectrum of detail vs direct higher-level type of communication. There is no right or wrong answer, but you must be aware of your natural tendencies in conversation, and know how to use those effectively, or tailor your communication style to a specific situation or audience. Benefits of Tailored Communication What are the benefits of tailored communication? The primary benefits of tailoring your communication to different stakeholders are that you can provide each person with what they want and need in a way that resonates with them. For instance, I once had to adapt my communication style when working with a highly detail-oriented developer who preferred a more granular level of communication. This eases the amount of effort required by the other party to understand you, and allows them to be more effective in taking your message forward. It increases the perception of your effectiveness, and credibility in their eyes as well. If people know that you are someone who can communicate with multiple parties with varying interests and needs, and do so effectively, you will be trusted with more responsibility, and be given more opportunities. Using Effective Communication To Advance Your Career As you can see, developing effective communication skills is a powerful way to advance your career in the software development industry. How have you seen effective communication impact your work? People who are seen as effective communicators have staying power in an organization. They are viewed as competent and necessary. They are given positions of authority and trusted to get things done. I remember that, when I was just starting out in software development, I struggled to communicate effectively with stakeholders at different levels of the organization. But over time, I learned the value of tailoring my communication to each person's unique needs, and it has paid off in my career in countless ways. Basic Strategies For Improving Your Communication Know your audience__ When preparing for a presentation or conversation, it's essential to consider your audience and tailor your communication style to their needs. What are some strategies you use to ensure your message is received and understood? Write notes in advance, when possible__ Draw an outline or even the bulk of what you need to deliver before the time comes. Even if you don’t ultimately use these notes directly, preparing them will help you to distill your thoughts and clarify your message, as well as review that they have the appropriate amount of detail for the intended audience. Practice your delivery__ Though you will not always be giving a speech, talking through what you plan to say will help you to see gaps, smooth the flow, and make sure that you are comfortable with the material you will be presenting or communicating. Conclusion__ In this article, we learned about the importance of effective communication, strategies for improving your communication, and the direct and indirect positive impacts these improvements can have on your effectiveness and value in the organization. We explored various strategies and approaches to improve communication. Development in this area can yield amazing results for you as you make the investment to improve your skills. We hope you enjoyed this article, and found it helpful. If you have any questions please feel free to join the discussions going on at starter.dev or on our Discord....

Testing a Fastify app with the NodeJS test runner cover image

Testing a Fastify app with the NodeJS test runner

Introduction Node.js has shipped a built-in test runner for a couple of major versions. Since its release I haven’t heard much about it so I decided to try it out on a simple Fastify API server application that I was working on. It turns out, it’s pretty good! It’s also really nice to start testing a node application without dealing with the hassle of installing some additional dependencies and managing more configurations. Since it’s got my stamp of approval, why not write a post about it? In this post, we will hit the highlights of the testing API and write some basic but real-life tests for an API server. This server will be built with Fastify, a plugin-centric API framework. They have some good documentation on testing that should make this pretty easy. We’ll also add a SQL driver for the plugin we will test. Setup Let's set up our simple API server by creating a new project, adding our dependencies, and creating some files. Ensure you’re running node v20 or greater (Test runner is a stable API as of the 20 major releases) Overview `index.js` - node entry that initializes our Fastify app and listens for incoming http requests on port 3001 `app.js` - this file exports a function that creates and returns our Fastify application instance `sql-plugin.js` - a Fastify plugin that sets up and connects to a SQL driver and makes it available on our app instance Application Code A simple first test For our first test we will just test our servers index route. If you recall from the app.js` code above, our index route returns a 501 response for “not implemented”. In this test, we're using the createApp` function to create a new instance of our Fastify app, and then using the `inject` method from the Fastify API to make a request to the `/` route. We import our test utilities directly from the node. Notice we can pass async functions to our test to use async/await. Node’s assert API has been around for a long time, this is what we are using to make our test assertions. To run this test, we can use the following command: By default the Node.js test runner uses the TAP reporter. You can configure it using other reporters or even create your own custom reporters for it to use. Testing our SQL plugin Next, let's take a look at how to test our Fastify Postgres plugin. This one is a bit more involved and gives us an opportunity to use more of the test runner features. In this example, we are using a feature called Subtests. This simply means when nested tests inside of a top-level test. In our top-level test call, we get a test parameter t` that we call methods on in our nested test structure. In this example, we use `t.beforeEach` to create a new Fastify app instance for each test, and call the `test` method to register our nested tests. Along with `beforeEach` the other methods you might expect are also available: `afterEach`, `before`, `after`. Since we don’t want to connect to our Postgres database in our tests, we are using the available Mocking API to mock out the client. This was the API that I was most excited to see included in the Node Test Runner. After the basics, you almost always need to mock some functions, methods, or libraries in your tests. After trying this feature, it works easily and as expected, I was confident that I could get pretty far testing with the new Node.js core API’s. Since my plugin only uses the end method of the Postgres driver, it’s the only method I provide a mock function for. Our second test confirms that it gets called when our Fastify server is shutting down. Additional features A lot of other features that are common in other popular testing frameworks are also available. Test styles and methods Along with our basic test` based tests we used for our Fastify plugins - `test` also includes `skip`, `todo`, and `only` methods. They are for what you would expect based on the names, skipping or only running certain tests, and work-in-progress tests. If you prefer, you also have the option of using the describe` → `it` test syntax. They both come with the same methods as `test` and I think it really comes down to a matter of personal preference. Test coverage This might be the deal breaker for some since this feature is still experimental. As popular as test coverage reporting is, I expect this API to be finalized and become stable in an upcoming version. Since this isn’t something that’s being shipped for the end user though, I say go for it. What’s the worst that could happen really? Other CLI flags —watch` - https://nodejs.org/dist/latest-v20.x/docs/api/cli.html#--watch —test-name-pattern` - https://nodejs.org/dist/latest-v20.x/docs/api/cli.html#--test-name-pattern TypeScript support You can use a loader like you would for a regular node application to execute TypeScript files. Some popular examples are tsx` and `ts-node`. In practice, I found that this currently doesn’t work well since the test runner only looks for JS file types. After digging in I found that they added support to locate your test files via a glob string but it won’t be available until the next major version release. Conclusion The built-in test runner is a lot more comprehensive than I expected it to be. I was able to easily write some real-world tests for my application. If you don’t mind some of the features like coverage reporting being experimental, you can get pretty far without installing any additional dependencies. The biggest deal breaker on many projects at this point, in my opinion, is the lack of straightforward TypeScript support. This is the test command that I ended up with in my application: I’ll be honest, I stole this from a GitHub issue thread and I don’t know exactly how it works (but it does). If TypeScript is a requirement, maybe stick with Jest or Vitest for now 🙂...