Jest Traversy Tutorial
Local folder:
E:\NMS\CURSOS\SMALL-TUTORIALS\jest-tutorial-traversy
Youtube tutorial link:
https://www.youtube.com/watch?v=7r4xVDI2vho
Github link of tutorial:
https://github.com/bradtraversy/jest_testing_basics
Installation
npm init -y
npm i -D jest
# for systax highlighting in vscode (type adquisition)
# https://stackoverflow.com/questions/42024526/vscode-automatic-type-acquisition-for-jest
npm install -D @types/jest
In package.json
"scripts": {
"test": "jest"
},
How to run tests
npm test
Example functions.test.js
const functions = require('./functions');
// to run functions before of after
// beforeEach(() => initDatabase());
// afterEach(() => closeDatabase());
// beforeAll(() => initDatabase());
// afterAll(() => closeDatabase());
//toBe
test('Adds 2 + 2 = 4', ()=> {
expect(functions.add(2,2)).toBe(4);
});
//to not.toBe
test('Adds 2 + 2 not equal to 5', ()=> {
expect(functions.add(2,2)).not.toBe(5);
});
// toBeFalsy
test('is 0 falsy?', ()=> {
expect(0).toBeFalsy();
}); //Answer is yes
// toEqual
test('User should be Brad Traversy object', () => {
expect(functions.createUser()).toEqual({
firstName: 'Brad',
lastName: 'Traversy'
});
});
// Async Await
test('User fetched name should be Leanne Graham', async () => {
// expect.assertions(1);
const data = await functions.fetchUser();
expect(data.name).toEqual('Leanne Graham');
});
// CHECK FOR TRUTHY & FALSY VALUES
// toBeEqual
// toBeNull matches only null
// toBeUndefined matches only undefined
// toBeDefined is the opposite of toBeUndefined
// toBeTruthy matches anything that an if statement treats as true
// toBeFalsy matches anything that an if statement treats as false
Example functions.js
const axios = require('axios');
const functions = {
add: (num1, num2) => num1 + num2,
isNull: () => null,
checkValue: x => x,
createUser: () => {
const user = { firstName: 'Brad' };
user['lastName'] = 'Traversy';
return user;
},
fetchUser: () =>
axios
.get('https://jsonplaceholder.typicode.com/users/1')
.then(res => res.data)
.catch(err => 'error')
};
module.exports = functions;
Mocks and async functions
In order of getting testing results that are independent of the API's we use, we can use mocks.
For that, we can create a __mocks__
folder that we can call using jest.mock('./mymodule')
.
An entire module is substituted. When using global package such as axios
. You dont need to call jest.mock('axios')
, it is done automatically if you place the axios.js
file in the __mocks__
folder.
__mocks__/async.js
:
const fetchUser = () => {
console.log("Using mock function for fetchData")
return Promise.resolve({name:"Leanne Graham"});
}
exports.fetchUser = fetchUser;
async.js
const axios = require('axios');
const fetchUser = () =>{
console.log('Fetching data with axios...')
return axios
.get('https://jsonplaceholder.typicode.com/users/1')
.then(res => res.data)
.catch(err => 'error')
}
exports.fetchUser = fetchUser;
async.test.js
jest.mock('./async')
const {fetchUser} = require('./async');
// Async Await using mock
test('User fetched name should be Leanne Graham', async () => {
const data = await fetchUser();
expect(data.name).toEqual('Leanne Graham');
});
More code in: https://github.com/academind/js-testing-introduction/tree/async-code
Firebase Functions Unit Testing with Jest
Youtube video:
https://www.youtube.com/watch?v=8IoCPZJ-zwA
Github example:
https://github.com/ssagga/firebase-emulators-testing-with-jest/tree/master/functions
Documentation:
https://firebase.google.com/docs/rules/unit-tests
Local example:
E:\NMS\PROGRAMACION_NMS\CENTRALHUB\CH_SCRAPER\APPSEARCH_FIRESTORE_FUNCTIONS\functions
Example Folder Structure:
myapp
├── node_modules
├── firebase.json
├── firestore.indexes.json
├── firestore.rules
├── functions
│ ├── node_modules
│ ├── index.js
│ ├── jest.config.js
│ ├── jsconfig.json
│ ├── package-lock.json
│ ├── package.json
│ ├── src
│ │ ├── tests
│ │ │ └── mymodule.test.js
│ │ ├── change_appsearch.js
│ │ ├── change_firestore.js
│ │ ├── testCollectionTriggers.js
│ │ └── testing.js
│ └── ui-debug.log
├── package-lock.json
├── package.json
└── ui-debug.log
To run:
#in one terminal
firebase emulators:start
#in a different terminal
cd functions
jest
functions/jest.config.js
module.exports = {
testRegex: 'src(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$',
testPathIgnorePatterns: ['lib/', 'node_modules/'],
moduleFileExtensions: ['js','ts','tsx','jsx','json','node'],
testEnvironment: 'node',
rootDir: 'src'
}
functions/jsconfig.json
{
"typeAcquisition": {
"include": [
"jest"
]
}
}
To run tests sequentially instead of in parallel use jest --runInBand
. It is necessary when running firestore test to prevent one test to influence the other.
functions/package.json
"scripts": {
...
"test": "jest '\\__tests__\\.*.test.js' --runInBand"
},
functions/src/__tests__/mymodule.test.js
const firebase = require('@firebase/testing')
const admin = require('firebase-admin')
test('Should be 1', ()=> {
expect(1).toBe(1);
})
const projectId = "rich-meridian-274818"
process.env.GCLOUD_PROJECT = projectId
process.env.FIRESTORE_EMULATOR_HOST = "localhost:8080";
let app = admin.initializeApp({projectId})
let db = firebase.firestore(app)
beforeAll(async ()=>{
await firebase.clearFirestoreData({projectId});
})
// When Document written to '/TestCollection/{DocumentId}' , trigger function to copy it to '/Copies/{DocumentId}
test("Expect to find a copy in 'Copies' Collection", async ()=>{
const testDoc = {
name: 'Samer',
age: 21,
city: 'Riyadh'
}
const ref = db.collection('TestCollection').doc()
await ref.set(testDoc)
const copyId = ref.id
const copyRef = db.collection('Copies').doc(copyId)
await new Promise((r)=>setTimeout(r, 3000))
const copyDoc = await copyRef.get()
expect(copyDoc.data()).toStrictEqual(testDoc)
})
onCreate function:
const functions = require('firebase-functions');
const admin = require("firebase-admin")
// admin.initializeApp(); //initialized in index.js
const db = admin.firestore()
exports.onCreate = functions.firestore.document('TestCollection/{docId}').onCreate(async (snapshot)=>{
const data = snapshot.data()
const docId = snapshot.id
const copyRef = db.collection('Copies').doc(docId)
await copyRef.set(data)
})
Top comments (0)