사진에서 처럼 await has no effect
라고 되어있으면서 await를 없애면 event가 먹히지 않는다... 아무것도 입력되지 않은것으로 나온다. await를 입력하자...(진짜 이것때문에 1시간이상을 헤맸다... jest 일해라...)
Use .toHaveBeenCalledWith
to ensure that a mock function was called with specific arguments.
it('test',()=>{
const signInWithEmailAndPassword: jest.fn(()=> (Promise.resolve("successfully signed in")))
// signInWithEmailAndPassword has been called with arguments passed as value.
fireEvent.change(getByPlaceholderText('Email address'), {target: { value: 'karl@gmail.com' }});
fireEvent.change(getByPlaceholderText('Password'), { target: { value: 'password' } });
fireEvent.submit(getByTestId('login'));
expect(signInWithEmailAndPassword).toHaveBeenCalledWith("karl@gmail.com","password")
})
// signup.test.js
expect(doc).toHaveBeenCalled(); // 0
가 분명 1이상이 되어야 하는데 0이 나왔다. 즉 함수가 호출 되지 않았다는 거다.
이유를 알아보니 Signup.js에서 doc앞에 에러가 나서 그런것이었다.
// Signup.js
console.log('before newUsers');
const newUsers = {
userId: createdUserResult.user.uid,
username: username.toLowerCase(),
fullName,
emailAddress: emailAddress.toLocaleLowerCase(),
following: ['2'],
followers: [],
dateCreated: Date.now(),
photoURL,
};
console.log('after newUsers');
const userRef = doc(db, 'users', username);
알아보니 before은 찍히는 데 after는 안찍힌다. 알아보니 createdUserResult에서 에러가 났던것.
createdUserResult를 mock할때 obj가 아닌 string을 리턴했기 떄문.. {user:{uid:'uid'}}
를 리턴해주는 걸로 mock을 하니 잘 작동함.
아무리 이것저것 시도해봐도 useNavigate를 mocking하는 과정에서 에러가 났다...
import * ROUTES from '../../constants/route'
// first try
jest.mock('react-router-dom', () => {
// Require the original module to not be mocked...
return {
__esModule: true,
...jest.requireActual('react-router-dom');,
// add your noops here
useNavigate: jest.fn(() => 'bar')
};
});
// second try
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom');,
useNavigate: jest.fn(() => jest.fn),
}))
// third try
var mockUseNavigate = jest.fn()
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom');,
useNavigate: mockUseNavigate,
}))
// fourth try
import {useNavigate} from 'react-router-dom'
jest.mock('react-router-dom')
it('sign up',() =>{
useNavigate.mockImplementation(()=>jest.fn())
})
expect(useNavigate).toHaveBeenCalledWith(ROUTES.DASHBOARD)
// fifth try
const mockUseNavigate = jest.fn();
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useNavigate: jest.fn(() => mockUseNavigate),
}));
위의 것을 전부 시도해보았지만 0 arugmnets passed
라거나 TypeError: (0 , _reactRouterDom.useNavigate) is not a function
라거나 Number of calls: 0
라는 에러가 떴다.
그러다가.. stackoverflow에서 어떤 글의 제목을 보았다. react jest can't mock useNavigate
과연...!!
찾았다 해답을!
const mockUseNavigate = jest.fn();
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useNavigate: () => mockUseNavigate,
}));
// Signup.js
const navigate = useNavigate();
navigate(ROUTES.DASHBOARD);
그렇다 useNavigate 자체는 일반 함수가 되어야한다. 근데 일반함수가 아닌 jest.fn() 이더라도 정상작동해야하는게 상식적으로 맞는것같은데... 그냥 호출하는 함수는 일반함수가 되어야하나보다..
그리고 검색할때 jest mock useNavigate
요렇게만이라도 검색했으면 찾을 수 있었을텐데.. 검색을 좀더 정확하고 심플하게 하도록 연습해보자!
또한 requireActual
api로 어떤 파일안에 export된 수많은 함수중 특정 함수 하나만 mocking 할 수 있다.(ex> useUserStore만 ./src/store에서 모킹)
아래 글도 참고.
mock only one function from module
그러나 waitfor안에서는 찾을 수 있다. 그러나 waitfor안에서 조차 찾을 수 없는 것이 viewmore와 suggested profile follow 버튼이었다.
rendering은 잘 된다. fixture도 잘 넘어온다... 왜그럴까??... karl은 어떻게 했을까??
suggested profile 같은 경우는 아무래도 로딩 시간이 길어서 못찾은거 같다. 로딩되는 도중에 찾으려고 하니 못찾았던게 아닌가 생각이 든다.
그래서 suggested profile을 waitFor
api안에다가 넣고 fireEvent에다가 await
를 추가하니 suggested profile follow버튼을 테스팅 할 수 있었다.
await waitFor(async () => {
const follow = getByTestId('suggested-profile-utH4EadD3gBUbQkdG6Da');
fireEvent.click(follow);
});
그런데 그뒤에 expect(follow).tobeFalsy()
를 하려고하니 follow를 찾을 수 없다는 에러가 떴다... click하면 당연히 follow가 없어지니 falsy가 되어버리는 줄 알았는데 아예 없으니깐 에러가 나나보다.
그래서 queryselector
를 이용하기로 했다.
await waitFor(async () => {
const follow = getByTestId('suggested-profile-utH4EadD3gBUbQkdG6Da');
fireEvent.click(follow);
const followEle = container.querySelector(
'[data-testid="suggested-profile-utH4EadD3gBUbQkdG6Da"]'
);
expect(followEle).toBeFalsy();
});
그랬더니 또 follow를 찾을 수 가 없다고 한다. 그래서 또다시 기다렸다가 다시 찾아야 되나 싶어서 waitFor를 한번더 사용하였다.
await waitFor(() => {
const follow = getByTestId('suggested-profile-utH4EadD3gBUbQkdG6Da');
fireEvent.click(follow);
const followEle = container.querySelector(
'[data-testid="suggested-profile-utH4EadD3gBUbQkdG6Da"]'
);
expect(followEle).toBeFalsy();
});
await waitFor(() => {
const follow = container.querySelector(
'[data-testid="suggested-profile-utH4EadD3gBUbQkdG6Da"]'
);
expect(follow).toBeFalsy();
});
이러니깐 잘 된다!
dashboard를 테스팅하던 도중 갑자기 속도가 엄청나게 느려지는게 아닌가?... 이것 저것 시도해본 결과 역시나 mock이랑 render를 act안에다가 실행해서 그랬다... act바깥으로 빼내자!
감사합니다. 저도 await 추가하니 해결되네요 !