- 사용자는 이메일과 비밀번호를 사용해서 회원 가입 한다.
- 이미 사용 중인 이메일로 가입을 시도하면 에러 메시지를 보여 준다.
Cypress를 이용하여 위 두 가지의 상황으로 회원 가입
테스트 코드를 작성하려고 했는데 문제가 발생했다.
input type을 하다가 자꾸만 로그 중간에 (new url) http://localhost:5173/
이 뜨면서 메인 화면으로 이동하였고, input을 찾을 수 없다면서 오류가 떴다.
문제의 원인은 1번 상황을 테스트 할 때 회원 가입 후 자동으로 로그인이 되면서, 두 번째 테스트에서 /signup 페이지로 접속하면 이미 로그인된 상태로 간주되어 메인 페이지로 리다이렉트되었기 때문이었다. 첫 번째 테스트의 로그인 상태가 두 번째 테스트에 영향을 미치게 된 것이다.
이 문제를 해결하기 위해서는 두 가지 방법이 있을 것 같았다.
- 파일 나누어 독립적인 테스트로 실행하기
- 로그아웃 명령 추가로 구현하여 한 파일에서 테스트하기
1번을 선택하면 추가 구현을 하지 않아도 되어서 더 간편할 것 같았지만, 나는 실행 효율성을 위하여 2번 방법을 선택했다.
로그인 상태인지 확인하고 로그인 상태인 상태일 땐 로그아웃을 시켜 주어 회원 가입을 할 수 있게 코드를 추가해 주어야 했다.
// cypress/support/index.ts
import { initializeApp } from 'firebase/app';
const firebaseConfig = {
apiKey: Cypress.env('FIREBASE_API_KEY'),
authDomain: Cypress.env('FIREBASE_AUTH_DOMAIN'),
projectId: Cypress.env('FIREBASE_PROJECT_ID'),
storageBucket: Cypress.env('FIREBASE_STORAGE_BUCKET'),
messagingSenderId: Cypress.env('FIREBASE_MESSAGING_SENDER_ID'),
appId: Cypress.env('FIREBASE_APP_ID'),
};
export const app = initializeApp(firebaseConfig);
// cypress/support/commands.ts
/// <reference types="cypress" />
import { getAuth, signOut } from 'firebase/auth';
import { app } from './index.ts';
Cypress.Commands.add('firebaseLogout', () => {
const auth = getAuth(app);
return signOut(auth);
});
// cypress/support/cypress.d.ts
declare namespace Cypress {
interface Chainable {
firebaseLogout(): Promise<void>;
}
}
cypress에서 쓰이는 env 파일은 프로젝트 루트 폴더(기존 .env 파일이랑 같은 위치)에 위치해야 적용된다!
const { user } = require('../fixtures/user');
describe('회원가입 테스트', () => {
const { buyer } = user;
beforeEach(() => {
// Given - 회원가입 페이지로 접속한다.
cy.visit('/signup');
cy.get('input[name="userType"]').as('userTypeInput');
cy.get('input[name="email"]').as('emailInput');
cy.get('input[name="nickname"]').as('nicknameInput');
cy.get('input[name="password"]').as('passwordInput').should('be.visible');
cy.get('input[name="passwordConfirm"]').as('passwordConfirmInput');
cy.get('input[name="phone"]').as('phoneInput');
cy.get('[data-cy="signup-button"]')
.as('signupButton')
.should('be.disabled');
});
it('사용자는 이메일과 비밀번호를 사용해서 회원가입 한다.', () => {
// When - 사용자 유형, 이메일, 닉네임, 비밀번호, 비밀번호 확인, 전화번호를 입력하고 회원가입 버튼을 클릭한다.
cy.get('@userTypeInput').check(buyer.userType);
cy.get('@emailInput').type(buyer.email);
cy.get('@nicknameInput').type(buyer.nickname);
cy.get('@passwordInput').type(buyer.password);
cy.get('@passwordConfirmInput').type(buyer.password);
cy.get('@phoneInput').type(buyer.phone);
cy.get('@signupButton').should('not.be.disabled');
cy.get('@signupButton').click();
// Then - 회원가입이 완료되고 메인 페이지로 이동한다.
cy.url().should('eq', `${Cypress.config().baseUrl}/`);
cy.get('[data-cy="alert-dialog-title"]').should('contain', '환영합니다!');
});
it('이미 사용 중인 이메일로 가입을 시도하면 에러 메시지를 보여 준다.', () => {
// When - 이미 사용 중인 이메일로 회원가입을 시도한다.
cy.get('@userTypeInput').check(buyer.userType);
cy.get('@emailInput').type('test@test.com');
cy.get('@nicknameInput').type(buyer.nickname);
cy.get('@passwordInput').type(buyer.password);
cy.get('@passwordConfirmInput').type(buyer.password);
cy.get('@phoneInput').type(buyer.phone);
cy.get('@signupButton').should('not.be.disabled');
cy.get('@signupButton').click();
// Then - 에러 메시지를 보여 준다.
cy.get('[data-cy="alert-dialog-title"]').should(
'contain',
'다시 시도해 주세요.',
);
});
afterEach(() => {
cy.firebaseLogout();
});
});