This article outlines the process of creating a Next.js app, setting up Cypress headless testing and running the build and testing in Azure.
In this article
Create a Next app – Create a next app using default settings.
Adding Cypress.js for testing – Adding integrated testing to the next app codebase
Running Cypress in headless – Running UI tests without launching UI
Pushing code to an Azure Repository – Adding new code to a fresh repo
Run pipeline on Pull Request – Protecting master from direct pushes, block PR merges in the event of build & test failures.
Create a Next app
- Install node.js
- Open your command line
- Enter the following command:
npx create-next-app@latest
This will create the next app and install any dependencies. The first part of this process will ask you a number of questions, aside from the ‘What is your project named?’ question, you can hit enter for the remaining settings to use the recommending settings:
- cd into the project directory:
cd next_app
From here, you have 2 main options:
1) Run the app in dev mode:
npm run dev
This will launch the app in dev mode, with hot-code reloading and error reporting. This is where the development will take place ;).
2) Build and run the app in production mode:
Before running the app in production mode, the 1st step is the build the app:
npm run build
Then we can run the app:
npm run start
Either way you’ll see the following:
Adding Cypress.js for testing
The next step is to add Cypress.js to our app, so that we can run headless automated tests when PR’s are created in Azure Repos.
- Add cypress as a dev dependency:
npm install cypress start-server-and-test --save-dev
This will install cypress, the ‘start-server-and-test‘ part allows for local running of the app before starting the tests. When we come to run this in an Azure Pipeline, the pipeline environment is local by context (rather than deploying to a production like URL and running tests after a deploy).
- Add scripts to package.json:
Its time to open the project folder in whatever IDE you prefer (I’m using VSCODE in this example). Open the package.json file in the root of the project:
Within the scripts section, add the following commands:
"cy:open-only": "cypress open",
"cy:run-only": "cypress run",
"cy:open": "start-server-and-test dev 3000 cy:open-only",
"cy:run": "start-server-and-test dev 3000 cy:run-only"
Your package.json should now look like this:
- Setup basic Cypress framework:
You may have noticed when you opened the project in an IDE that there doesn’t seem to be any cypress related folders? These will be automatically created, once we run cypress for the 1st time.
In the command line enter the following command:
(by this point I have switched to the integrated terminal in VSCODE – Terminal > New Terminal)
npm run cy:open-only
This will launch cypress for the 1st time:
Click ‘E2E Testing’, the next screen will confirm that the file structure has been created:
Click the ‘Continue’ button.
If you encounter a ‘TSError’ like he following, we will fix that in the next step, if not then skip the next step.
- Fixing the TSError, invalid config file
If you encounter the below error, please follow on:
To fix this error, open your ‘tsconfig.json‘ file, and change the value of ‘moduleResolution‘ from ‘bundler‘ to ‘node‘:
Go back to Cypress and click the ‘Try again‘ button, the problem should now be resolved and you will be asked to confirm which browser you’d like to use:
As we are aiming to exclusively headless within Azure, I’m not going to dig any deeper into browser testing, we’ll move on to writing a basic test.
Running Cypress in Headless
In our setup, firing up the next app and running the tests headless is a simple as 1 command:
npm run cy:run
If we were to run this right now, we would see an error if that the tests cant run because no spec files have been found. So lets create one:
Open the cypress folder in your project and add a new folder called ‘e2e’:
In that folder create a JavaScript file, we’ll call it next_app.cy.js:
Within this file we’ll create our basic test:
Describe the test:
describe('Next app landing page', () => {})
Specify what you are expecting:
describe('Next app landing page', () => {
it('contains expected content', () => {})
})
Write the step that will visit the URL and verify the expectation:
describe('Next app landing page', () => {
it('contains expected content', () => {
cy.visit('/')
cy.get('code.font-mono').should('contain', 'app/page.tsx')
})
})
The last thing we need to do is specify our baseUrl, in the example above you can see that we’re visiting ‘/’, this gets appended to the baseUrl we set in cypress.config.js:
If we now run the tests again using the command:
npm run cy:run
The app gets built, deployed to localhost and then cypress headless tests run, verifying the simple test we’ve written:
Pushing code to an Azure Repository
Now that our next app is set up, we’ve integrate cypress, and added a basic test, we can push the project code to a new Azure repo.
Open Azure, and in the left menu click ‘Repos’:
Then from the top menu, click ‘New repository‘:
Give your repo a name, and deselect ‘Add a README’ (one was added automatically when we set up next) then click on the ‘Create‘ button:
From the next page, copy the code in ‘Push an existing repository from command line’:
Paste this into your command line and hit enter:
After this, and just to make sure everything is included, run the following:
git add .
git commit -m 'Make sure its all there'
git push origin master
That’s it! our code is now stored on Azure.
Creating a build pipeline
Now that our code is in Azure, we can set up a build pipeline. But before we do that, we can prep our project with a yaml file that will be used to specify the pipeline parameters and commands.
Let’s create a new yaml file in the root of our project:
And add the following:
trigger:
branches:
include:
- master
pool:
vmImage: ubuntu-latest
jobs:
- job: Next_Cypress_Headless
steps:
- script: |
npm install
npm run cy:run
displayName: 'Cypress (Headless, Js)'
And push this up to the repository:
git add .
git commit -m 'Adds pipeline YAML'
git push origin master
Now back in Azure, click on ‘Pipelines’ in the navigation:
Then ‘New pipeline’ in the top right:
Select ‘Azure Repos Git’ when asked for the project location:
On the next step, choose our new project for the list:
On the next step (Configure your pipeline), select ‘Existing Azure Pipelines YAML file’:
Select the YAML file we just pushed up, and click ‘Continue‘:
You will then see the YAML file, giving the chance the review:
Click ‘Run’ in the top right:
The pipeline will run, and will be all green :):
Run Pipeline on PR
So far we have set the pipeline up to run when any changes to master take place, we did this in the YAML here:
trigger:
branches:
include:
- master
However its much more important to catch any issues before that merge takes place, we want to trigger the pipeline when a PR is raised, and use the branch in the PR to run the tests.
This will detect any pull requests where master is the target branch. We do this using build validation.
- In the main Azure menu, click on Repos > Branches:
- Click the menu (…) button on the master branch and select ‘Branch policies’
- Click the ‘+’ button on ‘Build Validation’:
- Select the pipeline from the ‘Build pipeline’ dropdown, and enter a display name in the last field:
An important setting here is the ‘Policy Requirement’ options, by setting this to ‘Required’, a PR won’t be able to merge into the master branch if the pipeline fails.
- Click ‘Save’
Master protection
In addition to pipeline triggers, our previous settings have added a layer of protection to our master branch, if we make a change and try to push directly to master, we get the following error:
Raising a PR to trigger the pipeline
The last thing we need to do to make sure this all works is to raise a PR for our next app.
- Create a new branch
git checkout -b copy-change
- Open app/page.tsx, on line 50 change Docs{‘ ‘} to Documents{‘ ‘}
- Commit the change
git add .
git commit -m 'Simple copy change'
git push origin copy-change
- Raise a PR in Azure to merge the changes into master (repos > pull requests).
- The PR will trigger the build, and display the status of the build:
Only if/when the build succeeds, can the PR be merged.