Turn off your browser and try red, green & refactor pattern (part 3)
Since we added the home page let's add some extra routes for About
and Contact
pages. Don't forget, tests always come first:
describe('a user who visits about page under url "/about"', () => {
it('should be able to see About headline and the url should equal with "/about"', () => {
cy.visit('/about');
cy.contains('h1', 'About');
cy.url().should('include', '/about');
});
});
describe('a user who visits contact page under url "/contact"', () => {
it('should be able to see About headline and the url should equal with "/contact"', () => {
cy.visit('/contact');
cy.contains('h1', 'Contact');
cy.url().should('include', '/contact');
});
});
As you guessed, both failed:
Time to make them green by adding some extra routes and views accordingly:
const express = require('express');
const router = express.Router();
router.get('/', function(req, res, next) {
res.render('index', { title: 'Home' });
});
router.get('/about', function(req, res, next) {
res.render('about', { title: 'About' });
});
router.get('/contact', function(req, res, next) {
res.render('contact', { title: 'Contact' });
});
module.exports = router;
So they pass:
One more for our example. Can we navigate from home page to about and contact page? Time for some extra test cases:
describe('a user who is in home page', () => {
it('should be able to navigate to about page after clicking the about link in navbar', () => {
cy.visit('/');
cy.get('nav a').contains('About').click();
cy.contains('h1', 'About');
cy.url().should('include', '/about');
});
it('should be able to navigate to contact page after clicking the contact link in navbar', () => {
cy.visit('/');
cy.get('nav a').contains('Contact').click();
cy.contains('h1', 'Contact');
cy.url().should('include', '/contact');
});
});
Both fail of course since we haven't created the navigation menu yet:
Time to add the navigation menu in the header:
<ul class="hidden sm:flex items-center justify-between">
<li class="ml-4">
<a href="/about" class="inline-block p-4 hover:bg-gray-100">About</a>
</li>
<li class="ml-4">
<a href="/contact" class="inline-block p-4 hover:bg-gray-100">Contact</a>
</li>
</ul>
These help our test cases to become green:
A last one. Can we navigate to About
and Contact
pages from Home
page while using a mobile device? Do we have a mobile menu in place? No we don't. Let's create it then but first we need to create the appropriate test cases:
describe('a user who is in home page and uses a mobile device', () => {
beforeEach(() => {
cy.viewport('iphone-x');
});
it('should be able to navigate to about page after clicking the about link in mobile menu', () => {
cy.visit('/');
cy.get('[aria-label="mobile-toggle"]').click();
cy.get('[data-test="mobile-menu"] a').contains('About').click();
cy.contains('h1', 'About');
cy.url().should('include', '/about');
});
it('should be able to navigate to contact page after clicking the about link in mobile menu', () => {
cy.visit('/');
cy.get('[aria-label="mobile-toggle"]').click();
cy.get('[data-test="mobile-menu"] a').contains('Contact').click();
cy.contains('h1', 'Contact');
cy.url().should('include', '/contact');
});
});
These will fail of course:
Notice that we asked Cypress
to use an iPhoneX viewport, so that these test cases will use the mobile version of our application. This gives us enormous flexibility obviously.
Time to add that mobile menu in place:
<div data-test="mobile-menu" x-data="{ open: false }" class="block sm:hidden">
<button
@click="open = true"
aria-label="mobile-toggle"
class="flex items-center py-4 text-gray-500 hover:text-gray-800 hover:border-teal-500 appearance-none focus:outline-none"
>
<svg
class="fill-current h-4 w-4"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<title>Menu</title>
<path d="M0 3h20v2H0V3zm0 6h20v2H0V9zm0 6h20v2H0v-2z" />
</svg>
</button>
<ul
x-show="open"
@click.away="open = false"
class="absolute top-auto left-0 w-full shadow py-2 z-10 bg-white"
>
<li>
<a href="/about" class="block px-4 py-2 hover:bg-gray-100">About</a>
</li>
<li>
<a href="/contact" class="block px-4 py-2 hover:bg-gray-100">Contact</a>
</li>
</ul>
</div>
If you are wondering what are these x-something
directives, these are directives provided by AlpineJS
. I highly recommend to use this framework, because of its simplicity especially when it comes about such simple webpages and applications like the one we are building here.
In order to bring AlpineJS
into the game, we need to add a script tag in head
section from a CDN. Nothing more. It actually takes care of the rest since it initializes on its own. Pretty cool, right?
As expected, our tests now are passing:
Pretty awesome, right? ๐
You can find the actual codebase of this application here
You can read more about Cypress here
You can read more about AlpineJS here
Move on with part 4 here
Did you miss part 2? You can find it here
In case you want to take it from the very start, check part 1 here
Did you like this one?
I hope you really did...
Newsletter
Get notified about latest posts and updates once a week!!
You liked it?