簡體   English   中英

如何在 Firebase Auth onAuthStateChanged 中測試 setState

[英]How to test setState inside Firebase Auth onAuthStateChanged

我已經在AuthStateChanged上模擬了Firebase,所以測試工作完美,但我有這個用例,其中設置了用戶:

const [isSignedIn, setIsSignedIn] = useState<boolean>(false);
const [displayName, setDisplayName] = useState<string | null>('');
const auth = getAuth();
onAuthStateChanged(auth, (user) => {
console.log('OnAuthStateChanged USER', user);
if (user) {
  setDisplayName(user.email);
  setIsSignedIn(true);
} else {
  setIsSignedIn(false);
  setDisplayName('');
}

我知道您可以輕松地模擬它返回的內容,但如果可能的話,我不知道如何處理 function 的“內部”。

我需要專門設置 state,因為 DrawerNavigator 將根據用戶是否登錄顯示不同的選項:

 {isSignedIn && (
      <>
        <Drawer.Screen name='Dashboard' component={Dashboard} />
      </>
    )}
    {!isSignedIn && (
      <>
        <Drawer.Screen name='Welcome' component={Welcome} />
        <Drawer.Screen name='CreateAccount' component={CreateAccount} />
        <Drawer.Screen name='Login' component={Login} />
      </>
    )}

我可以測試功能,但只能在默認的 state 上進行測試,因為它已初始化,我怎樣才能使它工作? 或者我設置 state 的方式是否有任何其他變化,可以在其中進行測試?

這也是我現在的 mocking firebase/auth 模塊:

/**
* Firebase
*/
jest.mock('firebase/auth', () => {
   return {
     getAuth: () => jest.fn(),
     onAuthStateChanged: () => jest.fn(),
   };
});

假設您要模擬登錄用戶時發生的延遲:

  • 無論是否有用戶,您都必須調用作為參數傳遞給onAuthStateChanged的回調。
  • 傳入的FirebaseAuth實例的currentUser屬性應該同時更新。

下面的模擬假設您一次不使用多個應用程序。 如果是這樣,則必須實現獲取特定的應用程序實例。

/**
* Firebase Auth Module
*/
jest.mock('firebase/auth', () => {
   const authInstance = {
     // while handshaking with the Firebase Auth servers, currentUser
     // is null, regardless if someone is logged in or not.
     currentUser: null
   };

   const mockedUserInfo = Object.freeze({ // force read-only
     // mocked user info here - display name, email, etc
     email: 'example@example.com'
   });
   
   // container for attached callbacks and state variables
   const authChangeCallbacks = [];
   let authCurrentUserInfo = mockedUserInfo;
   let authTimer = null;
   let authTimerCompleted = false;

   // invoke all callbacks with current data
   const fireOnChangeCallbacks = () => {
     authMock.currentUser = authCurrentUserInfo;
     callbacks.forEach((cb) => {
       try {
         cb(mockedUserInfo)); // invoke any active listeners
       } catch (err) {
         console.error('Error invoking callback', err);
       }
     });
     authTimerCompleted = true;
   }

   authInstance.signOut = () => { // signInWithX will look similar to this
     authCurrentUserInfo = null;
     fireOnChangeCallbacks();
   };

   return {
     getAuth: jest.fn(() => authInstance),
     onAuthStateChanged: jest.fn((authMock, onChangeCallback) => {
       if (!authTimer) {
         // increase this delay to emulate slower connections
         authTimer = setTimeout(fireOnChangeCallbacks, 2000);
       }

       callbacks.push(onChangeCallback);
       const unsubscriber = () => {
         const foundIndex = callbacks.indexOf(onChangeCallback);
         if (foundIndex > -1) callbacks.splice(foundIndex, 1);
       }

       if (authTimerCompleted) {
         // auth is "resolved" already, fire callback immediately
         onChangeCallback(mockedUserInfo);
       }

       return unsubscriber;
     })
   };
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM