DEV Community

Nestor Solalinde
Nestor Solalinde

Posted on • Originally published at 181.126.83.235 on

Javascript Unit Testing – Jest - Course Notes

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 
Enter fullscreen mode Exit fullscreen mode

In package.json

 "scripts": { "test": "jest" }, 
Enter fullscreen mode Exit fullscreen mode

How to run tests

npm test 
Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode

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; 
Enter fullscreen mode Exit fullscreen mode

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; 
Enter fullscreen mode Exit fullscreen mode

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; 
Enter fullscreen mode Exit fullscreen mode

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'); }); 
Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode

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' } 
Enter fullscreen mode Exit fullscreen mode

functions/jsconfig.json

{ "typeAcquisition": { "include": [ "jest" ] } } 
Enter fullscreen mode Exit fullscreen mode

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" }, 
Enter fullscreen mode Exit fullscreen mode

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) }) 
Enter fullscreen mode Exit fullscreen mode

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) }) 
Enter fullscreen mode Exit fullscreen mode

Top comments (0)