mingg IT

[Cypress] commands.ts 이용해서 utils 함수 만들기 (ex 로그인) 본문

FrontEnd

[Cypress] commands.ts 이용해서 utils 함수 만들기 (ex 로그인)

mingg123 2023. 2. 17. 17:32

cypress내 cy.visit 함수를 이용하면서 사전작업이 필요한 경우가 있다.

 
예를 들면, 로그인 이후에 해당 페이지를 접속할 수 있다는 둥..
 
이런 작업을 나는 처음에 Login.cy.ts에서 loginForTest() 함수를 만들었다.

Login.cy.ts

const id = 'id';
const password = 'password';

export function loginForTest() {
	const idTextField = cy.get('[data-cy="loginIdTextField"]').should('exist').type(id);
	const pwTextField = cy.get('[data-cy="loginPWTextField"]').should('exist').type(password);

	const loginBtn = cy.get('[data-cy="vaunceAppLoginBtn"]').should('exist').click();
}


describe('vaunce-app login', () => {
	beforeEach(() => cy.visit('/members/login'));

	it('Login Page Rendering', () => {
		cy.contains('LOGIN');
		loginForTest();
	});

});

loginForTest는 로그인 기능을 하는 테스트 코드이다. 
 
 
그러고 이제 테스트할 페이지의 테스트코드에서 해당 함수를 불러와주었다. 
(beforeEach에서 사용한 이유는 로그인작업이 선행되어야 하기 때문이다.)

Register.cy.ts

import { loginForTest } from './Login.cy';
describe('vaunce-app', () => {
	beforeEach(() => {
		loginForTest();
		cy.visit('/newRegister_stepOne');
	});

	it('should display welcome message', () => {
	});
});

 

우선 두 가지 문제가 발생했다.

 
첫 번째 문제는 loginForTest함수를 불러왔더니, Login.cy의 테스트까지 Register.cy.ts에서 진행되는 것이다.
보면 vaunce-app login은 Login.cy에 적은 부분인데 저 부분까지 함께 테스트가 돌아간다. 
 
알다시피 Cypress가 빠른 편은 아니다. 불필요하게 테스트를 여러 번 하고 싶지 않아서 내가 원했던 상황은 아니었다.
 
두 번째 문제는 에러로그와 마찬가지로 로그인 쪽 TextField를 찾을 수 없다는 것이다. 아마 beforeEach에서 비동기로 돌면서 발생한 문제라고 추측된다(?)
 

해결 방법 

해결법을 고민하던 와중에 commands.ts 파일을 발견했다.

느낌이 Cypress에서 사용할 커스텀한 명령어를 만들 수 있는 파일 같다.

declare namespace Cypress {
	// eslint-disable-next-line @typescript-eslint/no-unused-vars
	interface Chainable<Subject> {
		login(email: string, password: string): Chainable<string>;
	}
}

//
// -- This is a parent command --
Cypress.Commands.add('login', (email, password) => {
	let logInformData = new FormData();
	logInformData.append('id', email);
	logInformData.append('password', password);
	logInformData.append('auto', 'false');

	cy.request({
		method: 'POST',
		url: 'https://localhost:80/api/v1/auth/app-login',
		body: { id: email, password: password, auto: false },
	}).then(({ body }) => {
		const data = body.body.vo;
		const { token, id, isJoined, refreshToken, is_join_completed } = data;
		localStorage.setItem('accessToken', token);
	});
});

이런 식으로 수정을 해준다.
 
함수이름은 login이고 email, password 파라미터를 받아온다.
그러고 실제 로그인 API를 호출해 주고, accesToken을 로컬스토리지에 저장해 준다.
(기존 로그인 코드가 이렇다.. 본인 코드에 맞게 구현하면 된다.)
 
이후 에러가 났었던 Register.cy.ts에서 아래처럼 사용해 준다.

const email = 'email';
const password = 'password';

// 로그인 한 적 없는 첫 방문일 경우
describe('vaunce-app', () => {
	beforeEach(() => {
		cy.login(email, password);
		cy.visit('/newRegister_stepOne');
	});

	it('should display welcome message', () => {
	});
});

 
짠.
 
해당 페이지를 테스트하기 전에 사전작업을 할 경우 commands.ts에 공통함수를 만들어서 사용하면 좋다.
빠르게 해결할 방법도 있지만.. (로그인 로직을 타지 말고 env에 accesToken을 저장해 두고, 호출한다는 둥.. ) 
 
그러면 accesToken의 값 만료되는 부분도 내가 관리를 해줘야 해서 매우 귀찮다..
물론 email, password를 관리해 주어야 하긴 하지만.. 
 
여튼 좀 더 좋은 방법을 찾으려고 삽질을 오래 했다. 그래도 굳굳 

Comments