회사 프로젝트 유닛 테스트 코드 작성 중 UI 검사 및 DOM 접근을 통한 테스팅이 필요하였다.
react에서 웹팩을 통해 설치 시 기본 모듈에 탑재된 react-testing-libray를 통해
Behavior Driven Test(행위 주도 테스트) 사용자 관점의 테스트를 jest와 testing-library를 혼합하기로 하였다.
input onChagne 이벤트 검사하기
describe("Input 입력 컴포넌트 테스트 시작", () => {
const { getByTestId } = render(
<InputLoginBox
/>
);
const inputEmailElement = getByTestId("Input_Email");
const inputPwElement = getByTestId("Input_Password");
it("이메일 텍스트 onChange 이벤트 동작 테스트", () => {
fireEvent.change(inputEmailElement, {
target: { value: "caiforniaLuv@gmail.com" },
});
expect(inputEmailElement.value).toBe("caiforniaLuv@gmail.com");
});
it("패스워드 텍스트 onChange 이벤트 동작 테스트", () => {
fireEvent.change(inputPwElement, {
target: { value: "1q2w3e4r@@" },
});
expect(inputPwElement.value).toBe("1q2w3e4r@@");
});
fireEvent
라는 메서드는 react-testing-library에서 DOM 이벤트 핸들러를 직접 조작할 수 있게 해당 이벤트 트리거를 실행 하는 메서드이다.
getByTestId
메서드를 활영하여 input 엘리먼트를 확인하게 되어 해당 메서드의 변수를 onChange 트리거를 발동시켜 결과값(toBe)과 비교를 한다.
test 시나리오
-
해당 입력창 component에서 onChange(키보드 타이핑) 이벤트가 작동되는지 판별하는 Test이다.
-
만일 입력이 실패될 경우 onChange 이벤트가 작동되지 않는 관계로 해당 코드의 오류가 발생된 것으로 판단할 수 있다.
form onSubmit 함수 호출 확인하기
it("form submit 함수 실행 테스트", async () => {
const { getByTestId } = render(<Login />);
// 이메일, 패스워드 input 엘리먼트 접근
const inputEmailElement = getByTestId("Input_Email");
const inputPwElement = getByTestId("Input_Password");
// 이메일 text onChange 이벤트 발동
fireEvent.change(inputEmailElement, {
target: { value: "caiforniaLuv@gmail.m" },
});
// 패스워드 text onChange 이벤트 발동
fireEvent.change(inputPwElement, {
target: { value: "1q2w3e4r@@" },
});
// onChange 이벤트 후 문자열 있는지 없는지 판별
const typeBoolean = inputEmailElement.value && inputPwElement.value;
// form submit 액션으로 호출되어야 할 Rest API 함수
const handleLogin = jest.fn(() => {
if (typeBoolean) {
return "Axios starts";
}
});
// form 엘리먼트
const formLoginElement = getByTestId("form_login");
// form 엘리먼트의 onSubmit 클릭
fireEvent.submit(formLoginElement, {
onsubmit: typeBoolean ? handleLogin() : null,
});
// haldleLogin 함수 호출 확인 test
expect(handleLogin).toHaveBeenCalled();
});
onSubmit 이벤트 핸들러를 트리거할 경우 handleLogin 함수가 호출되어 서버에 전송되는 로직을 테스트하여야 한다.
Jest 검증 메서드 문법 중 toHaveBeenCalled
함수 호출이 되었는지 검증할 수 있도록 테스트 코드르 설계하였다.
test 시나리오
-
로그인 버튼은 Email과 Password String 값이 존재해야만 활성화가 되어 클릭 이벤트가 작동된다.
-
만일 Email과 Password 값이 없을 경우 버튼은 비활성화가 되어 클릭 이벤트가 차단되어야 한다. (테스트 오류 발생)
form onSubmit 함수 호출 후 실패 문구 Text 및 Color 검사하기
it("form submit 실패시 발생하는 텍스트 문구 테스트", async () => {
const user = {
email: "caiforniaLuv@gmail.com",
password: "1q2w3e4r@@",
};
const statusType = {
fail_msg400: "비밀번호가 올바르지 않습니다.",
fail_msg404: "존재하지 않는 email입니다.",
};
const { getByTestId } = render(<Login />);
// 이메일, 패스워드 input 엘리먼트 접근
const inputEmailElement = getByTestId("Input_Email");
const inputPwElement = getByTestId("Input_Password");
// form 엘리먼트
const formLoginElement = getByTestId("form_login");
// 이메일 text onChange 이벤트 발동
fireEvent.change(inputEmailElement, {
target: { value: "caiforniaLuv@gmail.com" },
});
// 패스워드 text onChange 이벤트 발동
fireEvent.change(inputPwElement, {
target: { value: "1q2w3e4r@@" },
});
// 이메일, 비밀번호 공백 판별
const typeBoolean = inputEmailElement.value && inputPwElement.value;
// 로그인 버튼 클릭 후 이메일, 비밀번호 작성한 값에 따라 상태코드 전달
const loginCheck = (email, password) => {
if (email === user.email && password === user.password) {
return true;
} else if (email !== user.email && password === user.password) {
return 404;
} else if (email === user.email && password !== user.password) {
return 400;
} else {
return 0;
}
};
const handleLogin = jest.fn(() => {
if (loginCheck(inputEmailElement.value, inputPwElement.value) === true) {
return 200;
} else {
return loginCheck(inputEmailElement.value, inputPwElement.value);
}
});
// 로그인 버튼 클릭 함수 (직접 호출하여 리턴값 변수에 저장 필요)
var login_test = handleLogin();
// 로그인 버튼 클릭 이벤트 발생
fireEvent.click(formLoginElement, {
onsubmit: typeBoolean ? handleLogin() : null,
});
// 클릭 이벤트 확인 test
expect(handleLogin).toHaveBeenCalled();
render(<LoginFail loginStatus={login_test} loginList={statusType} />);
// 오류 문구 DOM 접근 함수
const result = (id) => {
const failElement = getByTestId(id);
// 텍스트 color 확인 test
expect(failElement).toHaveStyle({ color: "#c00a21" });
return failElement;
};
// 로그인 클릭 결과에 따른 상태코드 판별
if (login_test === 200) {
expect(null).toBe(null);
} else if (login_test === 404) {
// 이메일 틀릴 경우 텍스트 결과 확인 test
expect(result("Login_Fail_404")).toHaveTextContent(
"존재하지 않는 email입니다."
);
} else if (login_test === 400) {
// 비밀번호 틀릴 경우 텍스트 결과 확인 test
expect(result("Login_Fail_400")).toHaveTextContent(
"비밀번호가 올바르지 않습니다."
);
}
test 시나리오 1
-
로그인 입력창에 이미 존재하는 이메일을 전송할 경우 404 상태 코드 전송된다.
-
비밀번호가 옳지 않을 경우 400 상태 코드 전송된다.
test 시나리오 2
-
로그인 하단 Text의 color가 #c00a1(브라우저 DOM에선 rgb code로 변환)
-
만일 color를 다른 code로 작성할 경우 테스트 오류가 발생한다.