-
Notifications
You must be signed in to change notification settings - Fork 1
Testing Guide
-
npm run jest_test
- run Jest tests -
npm run jest_coverage
- display Jest coverage -
npm run cypress_test
- run Cypress tests -
npm run cypress_start
- open Cypress UI -
npm i
- install dependencies -
npm run lint_test
- run the linter
- Check that you have npm installed
npm -v
- If not, install it: https://www.npmjs.com/get-npm
- Pull from
main
and check that you see a folder calledtesting
with 2 sub-folders:jest
andcypress
- You should see a number of tests already in the cypress folder:
test-pomo-finish.js
,test-pomo-info.js
,test-pomo-settings.js
,test-pomo-timer.js
- If you are working on finish, info, settings, or timer, add your tests to those above files
import { setDark, getDark } from '../../source/storage';
// in storage.js
function getDark() { return eval(localStorage.getItem('isDark')); }
function setDark(dark) { localStorage.setItem('isDark',dark); }
// in test-storage.js
test('setDark to be true', () => {
setDark(true);
expect(getDark()).toBe(true);
});
import * as storageObj from '../../source/storage';
// in storage.js
function getDark() { return eval(localStorage.getItem('isDark')); }
function setDark(dark) { localStorage.setItem('isDark',dark); }
// in test-storage.js
test('setDark to be true', () => {
storageObj.setDark(true);
expect(storageObj.getDark()).toBe(true);
});
Make sure that Cypress finds the correct index.html
path and can visit the site hosted by LiveServer.
describe("Open Page", () => {
it("Opens index.html", () => {
cy.visit('./source/index.html')
});
});
Finding a component that is a shadow DOM (like pomo-timer
):
describe('Find Timer Element with JS', () => {
it('Get element (\'Timer\')', () => {
cy.window().then((win) => {
expect(win.pomoTimer).to.exist;
});
});
});
Finding an element by type (e.g. 'p' is paragraph class):
-
Note: if this element belongs to a shadow DOM, make sure to include
{includeShadowDom: true}
describe('Find Elements', { includeShadowDom: true }, () => {
it('Get element X', () => {
cy.get('p');
});
});
Finding an element by ID (use a unique ID like timer-button
not button
):
-
Note: if this element belongs to a shadow DOM, make sure to include
{includeShadowDom: true}
describe('Find Elements', { includeShadowDom: true }, () => {
it('Get element X', () => {
cy.get('#id-name');
});
});
Finding an element by class:
-
Note: if this element belongs to a shadow DOM, make sure to include
{includeShadowDom: true}
describe('Find Elements', { includeShadowDom: true }, () => {
it('Get element X', () => {
cy.get('.class-name');
});
});
If working with a shadow DOM component, use cy.window
and win.component.function()
:
-
Note: if this element belongs to a shadow DOM, make sure to include
{includeShadowDom: true}
// function setTimer(min, mode) {}
it('Call setTimer() to set work mode', () => {
cy.window().then((win) => {
win.pomoTimer.setTimer(12, 'work');
});
});
If NOT working with shadow DOMs (e.g. storage.js
), use export
in the component JS file and import
in the Cypress test file:
// storage.js
export function helloWorld(hi) { return hi + " " + "World"; }
import { helloWorld } from '../../source/storage'
cy
.wrap({ hw: helloWorld })
.invoke('hw', 'Hello')
.should('be.eq', 'Hello World') // match
If working with shadow DOM (e.g. pomo-timer
) to check a this.variable
:
it('Check that total seconds is accurate', () => {
cy.window().then((win) => {
expect(win.pomoTimer.totalSeconds).to.eq(num * 60);
});
});
If NOT working with shadow DOMs (e.g. storage.js
):
// storage.js
let my_num = 0;
export function setNum(num) { my_num = num; }
export function getNum() { return my_num; }
import { setNum, getNum } from '../../source/storage'
cy
.wrap({ sn: setNum })
.invoke('sn', 10) // set
.wrap({ gn: getNum })
.invoke('gn')
.should('be.eq', 10) // get
Note: all of the following should be encapsulated with a test it()
and describe()
Basic example of adding and removing an event listener.
it('Basic Event Listener', () => {
const eventPromise = new Cypress.Promise((resolve) => {
cy.get('component-id').then(($el) => {
const eventFunction = (e) => {
$el[0].removeEventListener('event-name', eventFunction);
resolve();
};
$el[0].addEventListener('event-name', eventFunction);
});
});
cy.wrap(eventPromise);
});
Example of clicking button, waiting, and setting a function after event listened.
it('Set Timer for Long Break #1 after listening for Work #4 end', () => {
cy.get('#timer-button').click(); // do a button click then
cy.wait(15000); // wait for 2m
const eventPromise = new Cypress.Promise((resolve) => {
cy.get('#pomo-timer').then(($el) => {
const onFinish = (e) => {
$el[0].removeEventListener('timerFinish', onFinish);
$el[0].setTimer(1, 'long break'); // set the timer
resolve();
};
$el[0].addEventListener('timerFinish', onFinish);
});
});
cy.wrap(eventPromise);
});
Check text/labels by content
it('Mode should be \'Work\'', () => {
cy.get('#timer-mode').then(($el) => {
expect($el).to.contain('WORK');
});
});
Check text/labels by class changes
it('Mode should be \'Work\'', () => {
cy.get('#timer-mode').then(($el) => {
expect($el).to.have.attr('class', 'work');
});
});
Wait to do an action until text matches Note: you need to add a timeout to wait; for ex 30000 = fast 2m
it('When timer text is 00:00 ...', () => {
cy.get('#timer-text').contains('00:00', { timeout: 30500 }).then(($el) => {
// do action
});
});
To "click" a button:
it('Button toggles when Start clicked', () => {
cy.get('#timer-button').click();
cy.get('#timer-button').then(($el) => {
expect($el).to.have.attr('class', 'reset');
});
});
- Open VSCode in source folder
- Launch LiveServer with
index.html
file npm i
npm run cypress_start
-
Potential Errors:
- If your terminal cannot find
npm
, check that you have it installed withnpm -v
- If your terminal cannot find
cypress_start
, check that you have all the.json
files - If Cypress isn't showing the HTML timer but folders, re-open VSCode in the source folder (you have the wrong root)
- If your terminal cannot find
git push origin [branch-name]
- Open Actions
- Two things should be running:
Lint Code Base
andTest Code Base
- Once workflow is done, open up its
Test Code Base
run - Click
Test Code Base Run
(has a green check mark or red 'x') - Click
Run Jest and Cypress
- Scroll down and for your test you should see something like:
Running: test-pomo-info.js (2 of 4)
Open Page
✓ Opens index.html (158ms)
Find Info Elements
✓ Get element ('Info')
Check Initial State of Elements
✓ Check that element says Info
3 passing (221ms)
(Results)