- Published on
How to prepare a GatsbyJS blog for testing with Cypress
- Authors
- Name
- Łukasz Woźniak
It's not a good idea to use your original posts in end-to-end testing. Tests can become sensitive to change (when you decide to edit your post, e.g. change some tag or fix description typo).
Especially during working on a new layout - it is worth testing blog post details (like title, tags, or date) on both - list (/blog
) and post (/blog/[slug]
) pages, navigation between posts, tags logic and more!
Here I will describe how to mock blog posts to provide post-edit insensitive tests.
At the end of this post, I'll link a repository with an example based on Gatsby's blog starter.
Setup Cypress
Add Cypress as a devDependency
to your GatsbyJS project:
npm i cypress --save-dev
Create cypress.json
file in the project directory (at the same level as package.json
) with the following content (we will use port 3030):
{
"baseUrl": "http://localhost:3030/"
}
Create a cypress
directory containing the following structure (note: blog
dir should have the same structure as your original content/blog
directory):
.
├── cypress
│ ├── fixtures
│ │ ├── post.json # file with assertion of post data
│ │ └── blog # mock of posts
│ │ │ └── ... # clone of content/blog structure
│ └── integration # dir with tests to run by cypress
│ ├── [your-test].spec.js
│ └── ...
Prepare post fixtures:
Install cross-env
:
npm i cross-env --save-dev
Then add the GATSBY_TEST=cypress
flag (you can name it whatever you want) and command to open cypress in package.json
scripts:
"scripts": {
"develop": "gatsby develop",
+ "develop:test": "cross-env GATSBY_TEST=cypress gatsby develop --port=3030",
+ "cypress:open": "cypress open"
In the gatsby-config.js
file find code responsible for the copying of blog posts from content/blog
and use the GATSBY_TEST
flag:
depending on
npm run develop
command different.md
post files will be copied.
{
resolve: "gatsby-source-filesystem",
options: {
+ path: process.env.GATSBY_TEST === "cypress"
+ ? `${__dirname}/cypress/fixtures/blog`
+ : `${__dirname}/content/blog`,
- path: "${__dirname}/content/blog",
name: "blog"
},
},
Write test
This is an example of a test that checks if a post is displayed in the post list:
describe('Blog post display every detail on list', async () => {
let postFixture
before(() => {
cy.fixture('blog/post').then((post) => {
postFixture = post
})
})
beforeEach(() => {
cy.visit('/')
})
it('Title is displayed', () => {
const { title } = postFixture
cy.get(`*[data-cy="${title}-title"]`).should('contain.text', title)
})
it('Date is displayed', () => {
const { title, date } = postFixture
cy.get(`*[data-cy="${title}-date"]`).should('contain.text', date)
})
})
According to the Cypress documentation, the test uses
data-cy
attribute to locate the element in DOM.
The test uses the postFixture
variable that is loaded from the /cypress/fixtures/blog/post.json
file. The file contains expected values of tests for easier editing and reusing these values (there is a few test files that are using the same expected values):
{
"title": "Test post 2",
"date": "February 25, 2021"
}
Automate your tests
Below there is an example of a configuration file to run e2e tests on every push or pull request to master
and develop
branches:
name: End-to-end tests
on:
push:
branches: [master, develop]
pull_request:
branches: [master, develop]
jobs:
cypress-run:
runs-on: ubuntu-18.04
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Cypress run
uses: cypress-io/github-action@v2
with:
browser: chrome
start: npm run develop:test
wait-on: http://localhost:3030
Repository with working example.