How to test Firebase real-time database functions using Jest

Let's assume that you have a component that fetches a user from the Firebase real-time database using the .on() listener:

jsx
import React, { useEffect, useState } from 'react';
import firebase                       from './Firebase';

const Component = () => {
    
    const [user, setUser] = useState({});
    
    useEffect(() => {
        
        firebase.database().ref('user').on('value', snapshot => {
            
            if(snapshot.val()){
                
                setUser(snapshot.val());
                
            }
            
        });
        
    }, []);
    
    return(
        <React.Fragment>
            <div className = 'Name'>{user.name}</div>
            <div className = 'City'>{user.city}</div>
        </React.Fragment>
    );
    
}

export default Component;

If you want to test the component using Jest, you need to create a mock-up of the Firebase function:

javascript
it('Renders user data', () => {
    
    // Fake user to test using a mock-up
    let fakeUser = {
        
        name: 'Erik',
        city: 'Barcelona'
        
    }
    
    // Creating fake snapshot object
    let snapshot = {val: () => fakeUser};
    
    // As jest is trying to test the previous component
    // You need to create a fake snapshot.val() equal to fakeUser
    // You do it by creating a mock-up function
    jest.spyOn(firebase, 'database').mockImplementation(() => ({
        
        ref: jest.fn().mockReturnThis(),
        on:  jest.fn((event, callback) => callback(snapshot))
        
    }));
    
    // At his point you can render the component
    act(() => {
        
        render(<Component/>, container);
        
    });
    
    // Expected values to test
    expect(container.querySelector('.Name').textContent).toBe(fakeUser.name);
    expect(container.querySelector('.City').textContent).toBe(fakeUser.city);
    
});

If you take a look at a typical listener in Firebase:

javascript
firebase.database().ref().on(event, callback);
//-----[1]---------+
//                 +-[2]-+
//                       +--------[3]--------+

// To understand how to create the mock-up
// You can divide the listener into three parts:
// [1] spyOn(): Spy the function
// [2] mockReturnThis(): Chain the function
// [3] callback(snapshot): Execute callback, snapshot as argument

Hi, I'm Erik, an engineer from Barcelona. If you like the post or have any comments, say hi.