admin管理员组

文章数量:1302374

I need help resolving error when running unit tests on a hook being used to retrieve user data.

TypeError: _app.default.auth is not a function

  10 |       setUserId(storedUserId);
  11 |     } else {
> 12 |       const unsubscribe = firebase.auth().onAuthStateChanged((user) => {

I'm only getting the above error when running unit tests for a hook I created to retrieve user info from storage or Firebase. This hook looks in storage and then Firebase if storage === null.

import { useEffect, useState } from "react";
import useGetUserId from "./useGetUserId";

import { app } from "../environments/environment";
import { doc, getDoc, getFirestore } from "firebase/firestore";

const useGetUserProfile = () => {
  type profile = {
    email: string;
    username: string;
    userBio: string;
    dob: Date;
    gender: string;
    sexo: string;
    education: string;
    drinkingHabits: string;
    smokingHabits: string;
  };

  const db = getFirestore(app);
  const userId: string | null = useGetUserId();
  const [isLoading, setIsLoading] = useState(true);
  const [userProfile, setUserProfile] = useState<any | null>(null);

  useEffect(() => {
    const userProfile = async () => {
      setIsLoading(true);
      try {
        const userRef = localStorage.getItem("PROFILE_INFO");
        if (userRef) {
          const profile: profile = JSON.parse(userRef);
          setUserProfile(profile);
        } else {
          if (userId) {
            const id = JSON.parse(userId);
            const userRef = await getDoc(doc(db, "users", id.user.uid));
            if (userRef.exists()) {
              const profile = userRef.data();
              setUserProfile(profile);
            }
          }
        }
      } catch (error) {
        console.log("error", error);
      } finally {
        setIsLoading(false);
      }
    };
    userProfile();
  }, [setUserProfile]);
  return {
    isLoading,
    userProfile, setUserProfile
  };
};

export default useGetUserProfile;
// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
// This file can be replaced during build by using the `fileReplacements` array.
// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
// The list of file replacements can be found in `angular.json`.

export const firebaseConfig = {
//config properties
};

// Initialize Firebase
export const app = initializeApp(firebaseConfig);

// Initialize Firebase Authentication and get a reference to the service
export const auth = getAuth(app);

And unit test:

// Mocking Firebase Firestore methods
jest.mock('firebase/firestore', () => ({
  getFirestore: jest.fn(),
  doc: jest.fn(),
  getDoc: jest.fn(),
}));

// Mocking localStorage
beforeEach(() => {
  jest.spyOn(Storage.prototype, 'getItem').mockImplementation(() => null); // Reset localStorage
});

describe('useGetUserProfile', () => {
  it.only('should get user profile from localStorage if available', async () => {
    // Mock localStorage with a mock profile
    const mockProfile = {
      email: '[email protected]',
      username: 'testuser',
      userBio: 'Bio info',
      dob: new Date('1990-01-01'),
      gender: 'Male',
      sexo: 'M',
      education: 'Bachelor',
      drinkingHabits: 'Occasionally',
      smokingHabits: 'Non-smoker',
    };
    jest.spyOn(Storage.prototype, 'getItem').mockImplementationOnce(() => JSON.stringify(mockProfile));

    const { result } = renderHook(() => useGetUserProfile());

    expect(result.current.userProfile).toEqual(mockProfile);
  });

I'm only getting the error when running the unit test, I think there must be an error on how I set up my Firebase config, but I'm not sure.

The actual error is it's displaying is in a separte hook that gets the UserId, however the unit tests for that hook is not failing.

Here's the actual line of code that's causing errors in a separate Hook's unit test.

  useEffect(() => {
    const storedUserId = localStorage.getItem("USER_CREDENTIALS");
    if (storedUserId) {
      setUserId(storedUserId);
    } else {
      const unsubscribe = firebase.auth().onAuthStateChanged((user) => {
        if (user) {
          const uid = user.uid;
          localStorage.setItem("USER_CREDENTIALS", uid);
          setUserId(uid);
        }
      });

      return () => unsubscribe();
    }
  }, [userId]);

  return userId;
};

I need help resolving error when running unit tests on a hook being used to retrieve user data.

TypeError: _app.default.auth is not a function

  10 |       setUserId(storedUserId);
  11 |     } else {
> 12 |       const unsubscribe = firebase.auth().onAuthStateChanged((user) => {

I'm only getting the above error when running unit tests for a hook I created to retrieve user info from storage or Firebase. This hook looks in storage and then Firebase if storage === null.

import { useEffect, useState } from "react";
import useGetUserId from "./useGetUserId";

import { app } from "../environments/environment";
import { doc, getDoc, getFirestore } from "firebase/firestore";

const useGetUserProfile = () => {
  type profile = {
    email: string;
    username: string;
    userBio: string;
    dob: Date;
    gender: string;
    sexo: string;
    education: string;
    drinkingHabits: string;
    smokingHabits: string;
  };

  const db = getFirestore(app);
  const userId: string | null = useGetUserId();
  const [isLoading, setIsLoading] = useState(true);
  const [userProfile, setUserProfile] = useState<any | null>(null);

  useEffect(() => {
    const userProfile = async () => {
      setIsLoading(true);
      try {
        const userRef = localStorage.getItem("PROFILE_INFO");
        if (userRef) {
          const profile: profile = JSON.parse(userRef);
          setUserProfile(profile);
        } else {
          if (userId) {
            const id = JSON.parse(userId);
            const userRef = await getDoc(doc(db, "users", id.user.uid));
            if (userRef.exists()) {
              const profile = userRef.data();
              setUserProfile(profile);
            }
          }
        }
      } catch (error) {
        console.log("error", error);
      } finally {
        setIsLoading(false);
      }
    };
    userProfile();
  }, [setUserProfile]);
  return {
    isLoading,
    userProfile, setUserProfile
  };
};

export default useGetUserProfile;
// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
// This file can be replaced during build by using the `fileReplacements` array.
// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
// The list of file replacements can be found in `angular.json`.

export const firebaseConfig = {
//config properties
};

// Initialize Firebase
export const app = initializeApp(firebaseConfig);

// Initialize Firebase Authentication and get a reference to the service
export const auth = getAuth(app);

And unit test:

// Mocking Firebase Firestore methods
jest.mock('firebase/firestore', () => ({
  getFirestore: jest.fn(),
  doc: jest.fn(),
  getDoc: jest.fn(),
}));

// Mocking localStorage
beforeEach(() => {
  jest.spyOn(Storage.prototype, 'getItem').mockImplementation(() => null); // Reset localStorage
});

describe('useGetUserProfile', () => {
  it.only('should get user profile from localStorage if available', async () => {
    // Mock localStorage with a mock profile
    const mockProfile = {
      email: '[email protected]',
      username: 'testuser',
      userBio: 'Bio info',
      dob: new Date('1990-01-01'),
      gender: 'Male',
      sexo: 'M',
      education: 'Bachelor',
      drinkingHabits: 'Occasionally',
      smokingHabits: 'Non-smoker',
    };
    jest.spyOn(Storage.prototype, 'getItem').mockImplementationOnce(() => JSON.stringify(mockProfile));

    const { result } = renderHook(() => useGetUserProfile());

    expect(result.current.userProfile).toEqual(mockProfile);
  });

I'm only getting the error when running the unit test, I think there must be an error on how I set up my Firebase config, but I'm not sure.

The actual error is it's displaying is in a separte hook that gets the UserId, however the unit tests for that hook is not failing.

Here's the actual line of code that's causing errors in a separate Hook's unit test.

  useEffect(() => {
    const storedUserId = localStorage.getItem("USER_CREDENTIALS");
    if (storedUserId) {
      setUserId(storedUserId);
    } else {
      const unsubscribe = firebase.auth().onAuthStateChanged((user) => {
        if (user) {
          const uid = user.uid;
          localStorage.setItem("USER_CREDENTIALS", uid);
          setUserId(uid);
        }
      });

      return () => unsubscribe();
    }
  }, [userId]);

  return userId;
};
Share edited Feb 10 at 23:46 Drew Reese 203k18 gold badges239 silver badges271 bronze badges asked Feb 10 at 21:34 D.HodgesD.Hodges 2,1074 gold badges26 silver badges59 bronze badges 2
  • firebase.auth().onAuthStateChanged does not appear in any of the code samples you have shared here. Please track it down in your code base and include it here (searching the text createContext( is a good starting point). It is likely contained in one of your project's authentication contexts (typically called AuthContext). Ultimately, this error is because that context file is using the legacy SDK syntax rather than the modern one (using getAuth(), etc.). – samthecodingman Commented Feb 10 at 22:22
  • Thanks @samthecodingman I just updated it. It's weird that the error is referencing a separate hook where the unit tests are actually working – D.Hodges Commented Feb 10 at 22:28
Add a comment  | 

1 Answer 1

Reset to default 1

Based on the code you provided, as long as local storage contains an entry for "USER_CREDENTIALS", the logic that is throwing the error is skipped entirely.

When you mock localStorage.getItem() to always return null, you now cause the faulty logic to execute.

useEffect(() => {
  const storedUserId = localStorage.getItem("USER_CREDENTIALS");
  if (storedUserId) { // this becomes null
    setUserId(storedUserId);
  } else { // this block gets executed
    const unsubscribe = firebase.auth().onAuthStateChanged((user) => { // this line throws the error
      if (user) {
        const uid = user.uid;
        localStorage.setItem("USER_CREDENTIALS", uid);
        setUserId(uid);
      }
    });
    return () => unsubscribe();
  }
}, [userId]);

To update this legacy logic to the new syntax, you'd use the following:

import { getAuth, onAuthStateChanged } from "firebase/auth";

useEffect(() => {
  const storedUserId = localStorage.getItem("USER_CREDENTIALS");
  if (storedUserId) {
    setUserId(storedUserId);
  } else {
    const unsubscribe = onAuthStateChanged(getAuth(), (user) => { // line updated to new syntax
      if (user) {
        const uid = user.uid;
        localStorage.setItem("USER_CREDENTIALS", uid);
        setUserId(uid);
      }
    });
    return () => unsubscribe();
  }
}, [userId]);

本文标签: reactjsHow do I resolve TypeError appdefaultauth is not a function errorStack Overflow