์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- ๋ฐฑ์ค 2108 nodejs
- ๊ตฌ๋ฆํค ์ฑ๋ฆฐ์ง ํ๊ณ
- js ๊ฑฐ๋ฆฌ๋๊ธฐ ํ์ธํ๊ธฐ
- ์๋ฐ์คํฌ๋ฆฝํธ ์ค์ฝํ
- suspense ๋์์๋ฆฌ
- js ์ค์ฝํ
- ๋ฐฑ์ค 1339๋ฒ ์๋ฐ์คํฌ๋ฆฝํธ
- next13 emotion
- ์นด์นด์ค ์ฝํ
- ๊ตฌ๋ฆํค ์ฑ๋ฆฐ์ง
- ์ฌ์ฉ์ฑ ๊ฐ์
- emtion app router
- ๊ตฌ๋ฆํค
- ํ๋ก๊ทธ๋๋จธ์ค ๊ฑฐ๋ฆฌ๋๊ธฐ ํ์ธํ๊ธฐ
- emotion RSC
- js ๋ฌธ์์ด ์์ถ
- ๋ฐฑ์ค 1339๋ฒ nodejs
- app router emotion
- suspense ๋ณ๋ชฉํ์
- ์ต์ ๋์ฒด์ด๋
- ๋ฐฑ์ค 2108 ์๋ฐ์คํฌ๋ฆฝํธ
- ์ค์ฝํ
- ๋ฆฌ์กํธ์ฟผ๋ฆฌ suspense
- suspense react-query
- ํ๋ก๊ทธ๋๋จธ์ค ๋ฌธ์์ด ์์ถ
- ๋ฐฑ์ค 1339๋ฒ js
- js
- TypeError: createContext only works in Client Components. Add the "use client" directive at the top of the file to use it. Read more:
- suspense ๋น๋๊ธฐ
- ์๋ฐ์คํฌ๋ฆฝํธ ๋ฌธ์์ด ์์ถ
- Today
- Total
Lennon FE
[React] Cypress๋ก e2e ํ ์คํธ๋ฅผ ๊ตฌํํด๋ณด์ ๋ณธ๋ฌธ
Next.js๋ฅผ ํฌํจํ React ํ๋ก์ ํธ์์ Cypress๋ก e2e๋ฅผ ๊ตฌํํด ๋ด ์๋ค.
ํ๋ก์ ํธ์ Cypress๋ฅผ ์ค์นํด ์ค๋๋ค.
$ yarn add cypress --dev
or
$ npm install cypress --save-dev
Package.json์ ๊ฐ์ ์คํฌ๋ฆฝํธ๋ฅผ ์ถ๊ฐํด ์ค๋๋ค.
"scripts": {
...,
"test": "cypress open",
"cy:run": "cypress run"
},
ํฐ๋ฏธ๋์์ ๋ช ๋ น์ด๋ฅผ ์์ฑํด ๋ด ์๋ค
$ yarn test
or
$ npm run test
๊ทธ๋ผ ์๋์ ๊ฐ์ ํ๋ก๊ทธ๋จ์ด ์ผ์ง ๊ฒ๋๋ค!
์ฐ๋ฆฌ๋ e2e๋ฅผ ๊ตฌํํ ๊ฒ์ด๋๊น ์ฒซ ๋ฒ์งธ๋ฅผ ์ ํํ๊ณ ํ์ผ์ ์์ฑํด ์ค๋ค๋ ๊ฑฐ์ ๋์ํ๊ณ ๋์ด๊ฐ๋๋ค.
์ ๊ธฐ์ค Electron์ด ํธํด์ ์ ํํ์ฌ Start๋ฅผ ๋๋ฆ ๋๋ค.
โ๏ธ ์ด ๊ณผ์ ์์ ํฌ๋กฌ์ด๋ Electron์ ์ผ๋ฉด ๋น ํ๋ฉด(blank screen)์ด ๋จ๋ ๊ฒฝ์ฐ๊ฐ ์๋๋ฐ
์ฐธ๊ณ (https://github.com/cypress-io/cypress/issues/4131) ์ ๊ธ์์๋ ์น์์ผ ๋ฌธ์ , ํ๋ฌ๊ทธ์ธ ๋ฌธ์ ๋ฑ๋ฑ์ ์ธ๊ธํฉ๋๋ค.
์ ๋ ๊ณต์๋ฌธ์๋ง ๋ณด๊ณ ๋ฐ๋ผ ํ์ ๋ฟ์ธ๋ฐ ์ ๋ผ์ ๊ทผ๋ณธ์ ์ธ ํด๊ฒฐ ๋ฐฉ๋ฒ์ด ์๋๋ผ ์๊ฐํ์ต๋๋ค.
yarn test๋ฅผ ์คํํ ํฐ๋ฏธ๋์์ ์ค๋ฅ๊ฐ ํ๋๋ ์๋๋ฐ ํด๋น ํ์์ด ๊ณ์ ์ง์๋์์ง๋ง, ๋๋๊ฒ๋ ๋งฅ๋ถ ์ฌ๋ถํ ํ๋๊น ํด๊ฒฐ์ด ๋์ต๋๋ค.
โ ์ปดํจํฐ ์ฌ๋ถํ ์ ํ ๋ฒ ํด๋ณด์ธ์!
๋ค์ ์ฝ๋๋ก ๋์๊ฐ๋ด ์๋ค.
cypress.config.ts์ ์ ์ญ ํด๋์ cypress๊ฐ ์์ฑ๋์์ ๊ฒ๋๋ค.
์ ๋ ์๋์ ๊ฐ์ด ์์ฑํ์ต๋๋ค.
// cypress.config.ts
import { defineConfig } from 'cypress';
export default defineConfig({
projectId: process.env.CYPRESS_PROJECT_ID,
e2e: {
baseUrl: 'http://localhost:3000',
setupNodeEvents(on, config) {
// implement node event listeners here
}
},
chromeWebSecurity: false
});
cypress ํด๋ ๋ด๋ถ์ e2e ํด๋๋ฅผ ํ๋ ์์ฑํด์ฃผ์ธ์.
e2e ํด๋์์ ๊ฐ์ ํ ์คํธ ์ผ์ด์ค๋ค์ ์ง์ ํด ์ฃผ๋ฉด ๋ฉ๋๋ค.
// cypress/e2e/signIn.cy.ts
describe('SignIn', () => {
beforeEach(() => {
cy.visit('/auth/signIn');
});
it('should signIn successfully', () => {
cy.get('[type="text"]').type('test@test.com');
cy.get('[type="password"]').type('testUser123');
cy.contains('๋ก๊ทธ์ธ').click();
cy.url().should('include', '/main');
});
it('should navigate to sign up page successfully', () => {
cy.contains('ํ์๊ฐ์
').click();
cy.url().should('include', '/auth/signUp');
});
});
๊ฐ๋จํ๊ฒ ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํด ๋ณด์์ต๋๋ค.
cypress.config.ts์ baseUrl์ ์ง์ ํด ์ค์ pathname๋ง ์ง์ ํด ์ค๋ ๋์ํฉ๋๋ค.
beforeEach() ๋ด๋ถ์ ์ ์ํ ๊ฑด ํด๋น describe์ ์ ์๋ ํ ์คํธ ์ผ์ด์ค๋ค์ด ๋ชจ๋ ๊ณต์ ํ๋ค๊ณ ์๊ฐํ๋ฉด ๋ฉ๋๋ค.
์ฆ ๋ชจ๋ ์์ํ ๋ /auth/signIn์ ๋ฐฉ๋ฌธํ๊ฒ ์ฃ ?
ํด๋น ์ฝ๋๋ ์๋์ ๊ฐ์ด ์ค๋ณต ์ฝ๋๋ฅผ ์ค์ด๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
describe('invalid inputs', () => {
beforeEach(() => {
cy.get('[id="nickname"]').type('test');
cy.get('[id="email"]').type('test@naver.com');
cy.get('[id="password"]').type('testUser123');
cy.get('[id="password_check"]').type('testUser123');
});
it('should display an error message when nickname is too short', () => {
cy.get('[id="nickname"]').clear().type('h');
cy.contains('๊ฐ์
ํ๊ธฐ').should('be.disabled');
});
it('should display an error message when email is invalid', () => {
cy.get('[id="email"]').clear().type('testnaver.com');
cy.contains('๊ฐ์
ํ๊ธฐ').should('be.disabled');
});
it('should display an error message when password is too short', () => {
cy.get('[id="password"]').clear().type('1234');
cy.contains('๊ฐ์
ํ๊ธฐ').should('be.disabled');
});
it('should display an error message when match check password is not same', () => {
cy.get('[id="password_check"]').clear().type('testUser124');
cy.contains('๊ฐ์
ํ๊ธฐ').should('be.disabled');
});
});
๋ณธ์ธ์ด ํ์ํ ํ ์คํธ ์ผ์ด์ค๋ฅผ ์์ฑํ๊ณ ๋ค์ Cypress ํ๋ก๊ทธ๋จ์ผ๋ก ๊ฐ๋ณด๋ฉด
์๋์ ๊ฐ์ด E2E specs์ ์ ์ํ ํ ์คํธ๋ค์ด ์ ์๋์ด ์์ ๊ฑฐ์์.
์ฌ๊ธฐ์ ํด๋ฆญํ๋ฉด ์๋ ์์์ฒ๋ผ GUI๋ก ๋น๋์ค ๋ฐ ์ค๋ ์์ ๋ณด๋ฉด์ ๋ฐ๋ก ํ์ธํ ์ ์์ต๋๋ค.
CLI๋ก ํ๋ ค๋ฉด ์์์ ์ ์ํ cy:run ์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค.
$ yarn run cy:run -- --record --spec "cypress/e2e";
or
$ npm run cy:run -- --record --spec "cypress/e2e";
์ ๋ช ๋ น์ด๋ฅผ ์์ฑํ๋ฉด e2e ๋ด๋ถ์ ์๋ ๋ชจ๋ ํ ์คํธ๋ค์ ์๋ํ์ฌ ํฐ๋ฏธ๋์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํด ์ค๋๋ค.
๊ฐ์ธ์ ์ผ๋ก Cypress ํ๋ก๊ทธ๋จ์์ ์์ฑํ๋ ๊ฒ๋ณด๋จ ์ฝ๋๋ก ์์ฑํ๋ ๊ฒ ์ข์ ๊ฒ ๊ฐ์ต๋๋ค.
CLI์์ ํ ์คํธ๋ฅผ ์๋ํ๋ฉด Cypress์์ screenshots, videos ํด๋์ ๋ฐ์ดํฐ๋ค์ด ์์ด๋๋ฐ ๊นํ๋ธ์ ์ฌ๋ผ๊ฐ์ง ์๋๋ก
. gitignore์ ์ถ๊ฐํด ์ค์๋ค
# cypress video, screenshots
cypress/videos
cypress/screenshots
์๋ PR์ e2e ๊ด๋ จ ์ฝ๋๋ฅผ ์ ์ด๋์ ์ฐธ๊ณ ํ๋ฉด ์ข์ ๊ฒ ๊ฐ์ต๋๋ค.
https://github.com/Nimble-Meet/client/pull/28
feat(e2e): e2e test ๊ตฌํ by pmhxhsj · Pull Request #28 · Nimble-Meet/client
cypress๋ฅผ ์ด์ฉํด e2e ํ ์คํธ๋ฅผ ๊ตฌํํ์ต๋๋ค. โ๏ธ ์ถํ ์ปจ๋ฒค์ ํ๋ฆฝ ๋ฐ ํ ์คํธ ์ฝ๋ ๋ฆฌํฉํ ๋ง ํ merge ์์
github.com
'๐งโ๐ป Web > React' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Next.js 13] Emotion์ผ๋ก app router RSC๋ฅผ ๊ตฌ์ฑํด๋ณด์ (1) | 2023.07.17 |
---|---|
[React] ์ต์ ๋ ์ฒด์ด๋ (0) | 2022.07.21 |
[React] ๋น๋๊ธฐ useState ๋๊ธฐ๋ก ์ฒ๋ฆฌํ๊ธฐ (0) | 2022.06.30 |
[React] PostCSS์์ style๊ฐ์ root์ฒ๋ผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ (2) | 2022.05.21 |
[React] React Route์ ๋ํด ์์๋ณด์ (0) | 2022.05.19 |