diff --git a/cypress/e2e/Integration/LoginPage.cy.ts b/cypress/e2e/Integration/LoginPage.cy.ts index 0bd616c..6231147 100644 --- a/cypress/e2e/Integration/LoginPage.cy.ts +++ b/cypress/e2e/Integration/LoginPage.cy.ts @@ -1,6 +1,4 @@ -import { login } from '@/apis/PromotionAdmin/login'; import { MSG } from '@/constants/messages'; -import { PA_ROUTES } from '@/constants/routerConstants'; describe('로그인 통합 테스트', () => { beforeEach(() => { diff --git a/cypress/e2e/System/AboutPage/Introduction.cy.ts b/cypress/e2e/System/AboutPage/Introduction.cy.ts index 7d5a932..bebbf83 100644 --- a/cypress/e2e/System/AboutPage/Introduction.cy.ts +++ b/cypress/e2e/System/AboutPage/Introduction.cy.ts @@ -1,40 +1,13 @@ -import { aboutPageAttributes, dataEditCompanyPageAttributes } from '@/constants/dataCyAttributes'; -import { MSG } from '@/constants/messages'; -import { confirmAndCheckCompletion, login } from 'cypress/support/hooks'; +import { login, normalizeHtml } from 'cypress/support/hooks'; describe('1. 회사 소개를 관리한다', () => { beforeEach(() => { login(); - cy.intercept('GET', '/api/company/information', { - statusCode: 200, - body: { - code: 200, - status: 'OK', - message: '전체 회사 정보를 성공적으로 조회하였습니다.', - data: { - id: 1, - mainOverview: '
STUDIO EYE IS THE BEST NEW MEDIA
PRODUCTION BASED ON OTT & YOUTUBE
', - commitment: '우리는 급변하는 뉴 미디어 시대를 반영한 콘텐츠 제작을 위해 끊임없이 고민하고 변화합니다.
', - address: '서울시 성동구 광나루로 162 BS성수타워 5층', - addressEnglish: '5F 162, Gwangnaru-ro, Seongdong-gu, Seoul, Republic of Korea', - phone: '02-2038-2663', - fax: '02-2038-2663', - introduction: '초기 테스트 입력', - sloganImageFileName: null, - sloganImageUrl: null, - detailInformation: [ - { - id: 1, - key: '문의하기', - value: '사이트를 통해 간편하게 문의하세요.', - }, - ], - }, - }, - }).as('getCompanyInfo'); + cy.intercept('GET', '/api/company/information').as('getCompanyInfo'); + cy.visit('/promotion-admin/dataEdit/company'); + cy.wait('@getCompanyInfo', { timeout: 10000 }); cy.visit('/promotion-admin/dataEdit/company'); // 회사 정보 편집 페이지로 이동 - cy.wait('@getCompanyInfo', { timeout: 10000 }); }); it('PP에서 로그인 후 PA의 회사 정보 편집 페이지로 이동한다', () => { @@ -42,225 +15,99 @@ describe('1. 회사 소개를 관리한다', () => { cy.url().should('include', '/promotion-admin/dataEdit/company'); }); - // it('초기 회사 소개 텍스트를 생성하고 확인한다', () => { - // cy.fixture('AboutPage/introductionData.json').then((data) => { - // // 기본 데이터 입력 - // cy.get(`[data-cy="${aboutPageAttributes.CREATE_INTRO}"]`).type(data.initialIntroduction); - // cy.get(`[data-cy="${dataEditCompanyPageAttributes.SUBMIT_BUTTON}"]`).click(); - - // // 등록 확인 프롬프트 및 완료 메시지 확인 - // confirmAndCheckCompletion(MSG.CONFIRM_MSG.POST, MSG.ALERT_MSG.POST); // 메시지 확인 - - // cy.visit('/about'); - // cy.contains(data.initialIntroduction).should('exist'); - // }); - // }); - it('PA에서 회사 소개 텍스트를 수정하고 PP에서 변경된 내용을 확인한다', () => { - cy.fixture('AboutPage/introductionData.json').then((data) => { - // 수정 API 모킹 - cy.intercept('PUT', '/api/company/introduction', (req) => { - const expectedData = { - mainOverview: 'STUDIO EYE IS THE BEST NEW MEDIA
PRODUCTION BASED ON OTT & YOUTUBE
', - commitment: '우리는 급변하는 뉴 미디어 시대를 반영한 콘텐츠 제작을 위해 끊임없이 고민하고 변화합니다.
', - introduction: data.updatedIntroduction, - }; - - // HTML 태그와 줄바꿈을 제거하고 비교 - const stripHtml = (str: string) => str.replace(/<[^>]*>/g, '').trim(); - const normalizeText = (str: string) => str.replace(/\n/g, '').trim(); - chai - .expect(normalizeText(stripHtml(req.body.introduction))) - .to.include(normalizeText(stripHtml(expectedData.introduction))); - - req.reply({ - statusCode: 200, - body: { - message: 'Company Introduction updated successfully', - }, - }); - }).as('updateIntroduction'); - - // GET 요청에 대한 모킹 추가: 페이지 이동 후 확인을 위해 - cy.intercept('GET', '/api/company/information', { - statusCode: 200, - body: { - code: 200, - status: 'OK', - data: { - id: 1, - mainOverview: 'STUDIO EYE IS THE BEST NEW MEDIA
PRODUCTION BASED ON OTT & YOUTUBE
', - commitment: - '우리는 급변하는 뉴 미디어 시대를 반영한 콘텐츠 제작을 위해 끊임없이 고민하고 변화합니다.
', - address: '서울시 성동구 광나루로 162 BS성수타워 5층', - addressEnglish: '5F 162, Gwangnaru-ro, Seongdong-gu, Seoul, Republic of Korea', - phone: '02-2038-2663', - fax: '02-2038-2663', - introduction: data.updatedIntroduction, - sloganImageFileName: null, - sloganImageUrl: null, - detailInformation: [ - { - id: 1, - key: '문의하기', - value: '사이트를 통해 간편하게 문의하세요.', - }, - ], - }, - }, - }).as('getUpdatedCompanyInfo'); - - // MODIFY_INTRO_TITLE 요소가 존재하고 보이는지 확인 - cy.get('[data-cy="MODIFY_INTRO_TITLE"]', { timeout: 20000 }).should('exist').and('be.visible'); - - cy.log('MODIFY_INTRO_TITLE 요소 확인 완료'); - - // 수정하기 버튼 클릭 - cy.get(`[data-cy="dataEdit-Button"]`, { timeout: 20000 }) - .should('exist') - .and('be.visible') - .eq(2) // 세 번째 요소 선택 - .click({ force: true }); - - cy.log('수정하기 버튼 클릭 완료'); - - // 에디터가 존재하는지 확인 후 텍스트 입력 - cy.wait(1000); - cy.get('.ql-editor', { timeout: 20000 }) - .should('exist') - .and('be.visible') - .eq(2) // 세 번째 요소만 선택 - .invoke('html', ''); // 기존 내용 삭제 + // 기존 데이터 확인 + cy.wait('@getCompanyInfo').then((interception) => { + const response = interception.response?.body; + chai.expect(response).to.have.property('code', 200); + chai.expect(response.data).to.have.property('introduction'); + }); - cy.get('.ql-editor').eq(2).type(data.updatedIntroduction, { force: true }); + // 수정하기 버튼 클릭 + cy.get(`[data-cy="dataEdit-Button"]`).eq(2).click({ force: true }); - cy.log('텍스트 입력 완료'); + // 텍스트 입력 + cy.get('.ql-editor') + .eq(2) + .invoke('html', '') // 기존 내용 제거 + .type('수정된 회사 소개 텍스트
', { parseSpecialCharSequences: false, force: true }); - // "저장하기"라는 텍스트를 포함한 버튼 클릭 - cy.contains('button', '저장하기', { timeout: 20000 }).should('exist').and('be.visible').click({ force: true }); + // 요청 가로채기 및 확인 + cy.intercept('PUT', '/api/company/introduction').as('updateIntroduction'); + cy.contains('button', '저장하기').click({ force: true }); - // 모킹된 API 요청 대기 - cy.wait('@updateIntroduction'); + cy.wait('@updateIntroduction', { timeout: 10000 }).then((interception) => { + const request = interception.request?.body; - cy.log('저장하기 버튼 클릭 완료 및 API 호출 완료'); + // HTML 태그 제거 후 순수 텍스트 비교 + chai.expect(normalizeHtml(request.introduction)).to.equal('수정된 회사 소개 텍스트'); - // 수정된 내용 확인을 위한 GET 요청 대기 - cy.wait('@getUpdatedCompanyInfo'); + const response = interception.response?.body; + chai.expect(response.message).to.equal('회사 소개 정보를 성공적으로 수정했습니다.'); + }); - // 수정된 내용 확인 - cy.visit('/about'); + // 수정된 데이터 확인 + cy.intercept('GET', '/api/company/information').as('getUpdatedCompanyInfo'); + cy.wait('@getUpdatedCompanyInfo').then((interception) => { + const response = interception.response?.body; - // 수정된 내용 확인을 위해 페이지를 천천히 스크롤하며 요소 렌더링 확인 - cy.visit('/about'); - for (let i = 0; i < 8; i++) { - cy.scrollTo(0, i * 300, { duration: 500 }); - cy.wait(500); // 스크롤 후 대기 시간 추가 - } - cy.get('[data-cy="about-content"]').should('contain', data.updatedIntroduction); + // HTML 태그 제거 후 순수 텍스트 비교 + chai.expect(normalizeHtml(response.data.introduction)).to.equal('수정된 회사 소개 텍스트'); }); + + cy.visit('/about'); + cy.get('[data-cy="about-content"]').should('contain', '수정된 회사 소개 텍스트'); }); it('PA에서 회사 소개 텍스트를 삭제하고 PP에서 기본 데이터를 확인한다', () => { - cy.fixture('AboutPage/introductionData.json').then((data) => { - // API 요청 모킹 설정 - cy.intercept('PUT', '/api/company/introduction', (req) => { - const expectedData = { - mainOverview: 'STUDIO EYE IS THE BEST NEW MEDIA
PRODUCTION BASED ON OTT & YOUTUBE
', - commitment: '우리는 급변하는 뉴 미디어 시대를 반영한 콘텐츠 제작을 위해 끊임없이 고민하고 변화합니다.
', - introduction: '', // 삭제된 상태 - }; - - // HTML 태그와 줄바꿈을 제거하고 비교 - const stripHtml = (str: string) => str.replace(/<[^>]*>/g, '').trim(); - const normalizeText = (str: string) => str.replace(/\n/g, '').trim(); - chai - .expect(normalizeText(stripHtml(req.body.introduction))) - .to.include(normalizeText(stripHtml(expectedData.introduction))); + cy.fixture('AboutPage/introductionData.json').then(() => { + // 기존 데이터 가져오기 확인 + cy.wait('@getCompanyInfo').then((interception) => { + const response = interception.response?.body; + chai.expect(response).to.have.property('code', 200); + chai.expect(response.data).to.have.property('introduction'); + }); - req.reply({ - statusCode: 200, - body: {}, - }); - }).as('deleteIntroduction'); + // 수정하기 버튼 클릭 + cy.get(`[data-cy="dataEdit-Button"]`).eq(2).click({ force: true }); - // GET 요청에 대한 모킹 추가: 페이지 이동 후 확인을 위해 - cy.intercept('GET', '/api/company/information', { - statusCode: 200, - body: { - code: 200, - status: 'OK', - data: { - id: 1, - mainOverview: 'STUDIO EYE IS THE BEST NEW MEDIA
PRODUCTION BASED ON OTT & YOUTUBE
', - commitment: - '우리는 급변하는 뉴 미디어 시대를 반영한 콘텐츠 제작을 위해 끊임없이 고민하고 변화합니다.
', - address: '서울시 성동구 광나루로 162 BS성수타워 5층', - addressEnglish: '5F 162, Gwangnaru-ro, Seongdong-gu, Seoul, Republic of Korea', - phone: '02-2038-2663', - fax: '02-2038-2663', - introduction: - '2010년에 설립된 스튜디오 아이는 다양한 장르를 소화할 수 있는 PD들이 모여
클라이언트 맞춤형 콘텐츠 제작과 운영 대책 서비스를 제공하고 있으며
드라마 애니메이션 등을 전문으로 하는 여러 계열사들과도 협력하고 있습니다.
', - sloganImageFileName: null, - sloganImageUrl: null, - detailInformation: [ - { - id: 1, - key: '문의하기', - value: '사이트를 통해 간편하게 문의하세요.', - }, - ], - }, - }, - }).as('getUpdatedCompanyInfo'); + // 에디터에 빈값 입력 + cy.get('.ql-editor') + .eq(2) + .invoke('html', '') // 기존 내용 삭제 + .type('{selectall}{backspace}', { force: true }); // 모든 내용 지우기 - // MODIFY_INTRO_TITLE 요소가 존재하고 보이는지 확인 - cy.get('[data-cy="MODIFY_INTRO_TITLE"]', { timeout: 20000 }).should('exist').and('be.visible'); + // 저장하기 버튼 클릭 + cy.intercept('PUT', '/api/company/introduction').as('updateIntroduction'); + cy.contains('button', '저장하기').click({ force: true }); - cy.log('MODIFY_INTRO_TITLE 요소 확인 완료'); // 디버깅용 로그 + // 삭제 요청 확인 + cy.wait('@updateIntroduction', { timeout: 10000 }).then((interception) => { + const request = interception.request?.body; - // 수정하기 버튼 클릭 - cy.get(`[data-cy="dataEdit-Button"]`, { timeout: 20000 }) - .should('exist') - .and('be.visible') - .eq(2) // 세 번째 요소 선택 - .click({ force: true }); + // "STUDIO EYE IS THE BEST NEW MEDIA
PRODUCTION BASED ON OTT & YOUTUBE
', - commitment: '우리는 급변하는 뉴 미디어 시대를 반영한 콘텐츠 제작을 위해 끊임없이 고민하고 변화합니다.
', - address: '서울시 성동구 광나루로 162 BS성수타워 5층', - addressEnglish: '5F 162, Gwangnaru-ro, Seongdong-gu, Seoul, Republic of Korea', - phone: '02-2038-2663', - fax: '02-2038-2663', - introduction: '초기 테스트 입력', - sloganImageFileName: null, - sloganImageUrl: 'https://studio-eye-gold-bucket.s3.ap-northeast-2.amazonaws.com/Slogan.png', - detailInformation: [ - { - id: 1, - key: '문의하기', - value: '사이트를 통해 간편하게 문의하세요.', - }, - ], - }, - }, - }).as('getCompanyInfo'); + cy.intercept('GET', '/api/company/information').as('getCompanyInfo'); cy.visit('/promotion-admin/dataEdit/company'); // 회사 정보 편집 페이지로 이동 - cy.wait('@getCompanyInfo', { timeout: 10000 }); + cy.wait('@getCompanyInfo', { timeout: 10000 }).then((interception) => { + const response = interception.response?.body; + chai.expect(response).to.have.property('code', 200); + chai.expect(response.data).to.have.property('sloganImageUrl'); + }); + cy.intercept('PUT', '/api/company/slogan').as('updateSlogan'); }); it('PP에서 로그인 후 PA의 회사 정보 편집 페이지로 이동한다', () => { @@ -42,6 +20,9 @@ describe('2. 회사 슬로건을 관리한다.', () => { }); it('PA에서 회사 슬로건 이미지를 수정하고 PP에서 변경된 이미지를 확인한다', () => { + // PUT 요청 인터셉트 + cy.intercept('PUT', '/api/company/slogan').as('updateSlogan'); + // 두 번째 수정하기 버튼 클릭 cy.get(`[data-cy="dataEdit-Button"]`).eq(1).should('exist').and('be.visible').click({ force: true }); @@ -51,14 +32,13 @@ describe('2. 회사 슬로건을 관리한다.', () => { // 저장하기 버튼 클릭 cy.contains('button', '저장하기', { timeout: 20000 }).should('exist').and('be.visible').click({ force: true }); + // 저장 확인 알림 처리 + cy.on('window:confirm', (text) => { + return true; + }); + // /about 페이지 방문 후 변경된 슬로건 이미지 확인 cy.visit('/about'); - cy.wait(2000); // 이미지 반영을 기다리기 위한 추가 대기 시간 - - cy.get('img').then(($img) => { - const imgSrc = $img.attr('src'); - cy.log('Image src:', imgSrc); // 로그 출력 - chai.expect(imgSrc).to.contain('studioeyeyellow'); - }); + cy.get('[data-cy="mission-image"]').should('have.attr', 'src').and('contain', 'Slogan.png'); // 이미지 파일 이름에 "Slogan.png" 포함 확인 }); }); diff --git a/cypress/e2e/System/AboutPage/WhatWeDo.cy.ts b/cypress/e2e/System/AboutPage/WhatWeDo.cy.ts index 73619c3..3c90575 100644 --- a/cypress/e2e/System/AboutPage/WhatWeDo.cy.ts +++ b/cypress/e2e/System/AboutPage/WhatWeDo.cy.ts @@ -4,40 +4,8 @@ import { login } from 'cypress/support/hooks'; describe('3. WHAT WE DO를 관리한다', () => { beforeEach(() => { login(); - - cy.intercept('GET', `/api/company/information`, { - statusCode: 200, - body: { - code: 200, - status: 'OK', - message: '전체 회사 정보를 성공적으로 조회하였습니다.', - data: { - id: 9999, - mainOverview: '스튜디오 아이와 함께 영상물 퀄리티 UP
', - commitment: '최고의 경험을 선사하는 스튜디오 아이의 작업과 함께하세요.
', - address: '서울시 성동구 광나루로 162 BS성수타워 5층', - phone: '02-2038-2663', - detailInformation: [ - { - id: 5555, - key: 'MCN 2.0', - value: '뉴미디어 콘텐츠에 체화된 플래디만의 독보적인 제작 역량을 바탕으로 크리에이터와 함께 성장합니다', - }, - { - id: 6666, - key: 'Digital Operator', - value: '다양한 고객의 Youtube, Instagram, TikTok 채널을 운영 대행합니다', - }, - { - id: 7777, - key: 'PD Group', - value: '예능, 드라마, 다큐멘터리, 애니메이션까지 전 장르의 디지털 콘텐츠를 기획, 제작합니다', - }, - ], - }, - }, - }).as('getCompanyInfo'); - + cy.intercept('GET', `/api/company/information`).as('getCompanyInfo'); + cy.intercept('GET', '/api/company/detail').as('getDetailForEdit'); cy.visit('/promotion-admin/dataEdit/company'); cy.wait('@getCompanyInfo'); // 초기 데이터가 로드될 때까지 대기 }); @@ -47,65 +15,19 @@ describe('3. WHAT WE DO를 관리한다', () => { }); it('PA에서 기존에 존재하는 WHAT WE DO를 수정하고 PP에서 변경된 내용을 확인한다', () => { - // 수정하기 버튼 클릭 cy.get(`[data-cy="dataEdit-Button"]`, { timeout: 20000 }) .should('exist') .and('be.visible') .eq(3) .click({ force: true }); - // 수정 페이지에서 GET 요청 모킹 - cy.intercept('GET', '/api/company/detail', { - statusCode: 200, - body: { - code: 200, - status: 'OK', - message: '회사 상세 정보를 성공적으로 조회하였습니다.', - data: [ - { - id: 5555, - key: 'MCN 2.0', - value: '뉴미디어 콘텐츠에 체화된 플래디만의 독보적인 제작 역량을 바탕으로 크리에이터와 함께 성장합니다', - }, - { - id: 6666, - key: 'Digital Operator', - value: '다양한 고객의 Youtube, Instagram, TikTok 채널을 운영 대행합니다', - }, - { - id: 7777, - key: 'PD Group', - value: '예능, 드라마, 다큐멘터리, 애니메이션까지 전 장르의 디지털 콘텐츠를 기획, 제작합니다', - }, - ], - }, - }).as('getDetailForEdit'); - - // PUT 요청 모킹 - 세부 정보를 업데이트하는 API - cy.intercept('PUT', '/api/company/detail', (req) => { - const { detailInformation } = req.body; - detailInformation.forEach((detail: { key: string; value: string }, index: number) => { - // 공백과 개행 문자를 제거한 후 비교 - chai.expect(detail.key.trim()).to.equal(['MCN 2.0', 'Digital Operator', 'PD Group'][index].trim()); - chai - .expect(detail.value.replace(/\s+/g, ' ').trim()) - .to.equal( - [ - '정말로 다양하고 멋진 작업물을 문의해보세요', - '정말로 다양하고 멋진 다양한 고객의 Youtube, Instagram, TikTok 채널을 운영 대행합니다', - '예능, 드라마, 다큐멘터리, 애니메이션까지 전 장르의 디지털 콘텐츠를 기획, 제작합니다', - ][index] - .replace(/\s+/g, ' ') - .trim(), - ); - }); - req.reply({ - statusCode: 200, - body: {}, - }); - }).as('updateCompanyInfo'); + // 수정하기 버튼 클릭 후 요청 대기 + cy.wait('@getDetailForEdit', { timeout: 10000 }).then((interception) => { + const response = interception.response?.body; + chai.expect(response).to.have.property('code', 200); + chai.expect(response.data).to.be.an('array'); + }); - // 기존 Detail 수정 const updatedDetails = [ { key: 'MCN 2.0', @@ -120,188 +42,92 @@ describe('3. WHAT WE DO를 관리한다', () => { updatedDetails.forEach((detail, index) => { cy.get(`[data-cy="${aboutPageAttributes.DETAIL_KEY_INPUT}"]`) .eq(index) - .should('exist') // 존재 여부 확인 - .scrollIntoView() // 요소를 보이도록 스크롤 - .should('be.visible') // 보이는지 확인 - .clear({ force: true }) // 강제로 클리어 - .type(detail.key) // 새로운 키 입력 - .should('have.value', detail.key); // 입력된 값 확인 - - cy.wait(500); + .clear({ force: true }) + .type(detail.key, { force: true }); cy.get(`[data-cy="${aboutPageAttributes.DETAIL_VALUE_INPUT}"]`) .eq(index) - .should('exist') // 존재 여부 확인 - .scrollIntoView() // 요소를 보이도록 스크롤 - .should('be.visible') // 보이는지 확인 - .clear({ force: true }) // 강제로 클리어 - .type(detail.value) // 새로운 값 입력 - .should('have.value', detail.value); // 입력된 값 확인 + .clear({ force: true }) + .type(detail.value, { force: true }); }); - // "저장하기" 버튼 클릭 - cy.contains('button', '저장하기', { timeout: 20000 }).should('exist').and('be.visible').click({ force: true }); - cy.wait('@updateCompanyInfo'); // 업데이트 요청 대기 + // 저장하기 버튼 클릭 후 PUT 요청 가로채기 + cy.intercept('PUT', '/api/company/detail').as('updateCompanyInfo'); + cy.contains('button', '저장하기', { timeout: 20000 }).should('exist').click({ force: true }); - cy.visit('/about'); + cy.wait('@updateCompanyInfo', { timeout: 10000 }).then((interception) => { + const request = interception.request?.body; - // /about 페이지에서 수정된 항목 확인 - cy.intercept('GET', `/api/company/detail`, { - statusCode: 200, - body: { - code: 200, - status: 'OK', - message: '회사 상세 정보를 성공적으로 조회하였습니다.', - data: [ - { - id: 5555, - key: 'MCN 2.0', - value: '정말로 다양하고 멋진 작업물을 문의해보세요', - }, - { - id: 6666, - key: 'Digital Operator', - value: '정말로 다양하고 멋진 다양한 고객의 Youtube, Instagram, TikTok 채널을 운영 대행합니다', - }, - { - id: 7777, - key: 'PD Group', - value: '예능, 드라마, 다큐멘터리, 애니메이션까지 전 장르의 디지털 콘텐츠를 기획, 제작합니다', - }, - ], - }, - }).as('getUpdatedCompanyInfo'); + // 요청 데이터 검증 + const requestIncludesDetail = (detail: { key: any; value: any }) => + request.detailInformation.some( + (info: { key: any; value: any }) => info.key === detail.key && info.value === detail.value, + ); + updatedDetails.forEach((detail) => chai.expect(requestIncludesDetail(detail)).to.be.true); - cy.wait('@getUpdatedCompanyInfo'); + const response = interception.response?.body; + chai.expect(response).to.have.property('status', 'OK'); + chai.expect(response.message).to.equal('회사 5가지 상세 정보를 성공적으로 수정했습니다.'); + }); - // 변경된 내용 확인 - updatedDetails.forEach((detail) => { - cy.contains(detail.value, { timeout: 10000 }).should('exist'); // 업데이트된 내용 확인 + // /about 페이지로 이동하여 응답 데이터 확인 + cy.visit('/about'); + cy.intercept('GET', `/api/company/detail`).as('getUpdatedCompanyDetail'); // 경로 수정 + cy.wait('@getUpdatedCompanyDetail', { timeout: 10000 }).then((interception) => { + const response = interception.response?.body; + + // 응답 데이터 검증 + const responseIncludesDetail = (detail: { key: any; value: any }) => + response.data.some((info: { key: any; value: any }) => info.key === detail.key && info.value === detail.value); + updatedDetails.forEach((detail) => chai.expect(responseIncludesDetail(detail)).to.be.true); }); }); it('PA에서 기존에 존재하는 WHAT WE DO 항목을 삭제하고 PP에서 변경된 내용을 확인한다', () => { - // 수정하기 버튼 클릭 cy.get(`[data-cy="dataEdit-Button"]`, { timeout: 20000 }) .should('exist') .and('be.visible') .eq(3) .click({ force: true }); - // PUT 요청 모킹 - 세부 정보를 업데이트하는 API - cy.intercept('PUT', '/api/company/detail', (req) => { - const { detailInformation } = req.body; - detailInformation.forEach((detail: { key: string; value: string }, index: number) => { - chai.expect(detail.key.trim()).to.equal(['Digital Operator', 'PD Group'][index].trim()); - chai - .expect(detail.value.replace(/\s+/g, ' ').trim()) - .to.equal( - [ - '다양한 고객의 Youtube, Instagram, TikTok 채널을 운영 대행합니다', - '예능, 드라마, 다큐멘터리, 애니메이션까지 전 장르의 디지털 콘텐츠를 기획, 제작합니다', - ][index] - .replace(/\s+/g, ' ') - .trim(), - ); - }); - req.reply({ - statusCode: 200, - body: { - code: 200, - status: 'OK', - message: '세부 정보가 성공적으로 업데이트되었습니다.', - data: [ - { - id: 6666, - key: 'Digital Operator', - value: '다양한 고객의 Youtube, Instagram, TikTok 채널을 운영 대행합니다', - }, - { - id: 7777, - key: 'PD Group', - value: '예능, 드라마, 다큐멘터리, 애니메이션까지 전 장르의 디지털 콘텐츠를 기획, 제작합니다', - }, - ], - }, - }); - }).as('deleteCompanyInfo'); - - // 첫 번째 항목 삭제 - cy.get(`[data-cy="${aboutPageAttributes.DELETE_DETAIL}"]`).eq(0).click({ force: true }); // 첫 번째 삭제 버튼 클릭 - - // 프롬프트 창 자동 확인 처리 + cy.get(`[data-cy="${aboutPageAttributes.DELETE_DETAIL}"]`).first().click({ force: true }); cy.on('window:confirm', () => true); - cy.contains('button', '저장하기', { timeout: 20000 }).should('exist').and('be.visible').click({ force: true }); - - // 업데이트 요청 대기 - cy.wait('@deleteCompanyInfo'); + cy.intercept('PUT', '/api/company/detail').as('deleteCompanyInfo'); - // 로그는 체이닝과 분리하여 별도로 실행 - cy.log('저장하기 버튼 클릭 완료'); + cy.contains('button', '저장하기', { timeout: 20000 }).should('exist').click({ force: true }); - // /about 페이지에서 수정된 항목 확인 - cy.intercept('GET', `/api/company/information`, { - statusCode: 200, - body: { - code: 200, - status: 'OK', - message: '전체 회사 정보를 성공적으로 조회하였습니다.', - data: { - id: 9999, - mainOverview: '스튜디오 아이와 함께 영상물 퀄리티 UP
', - commitment: '최고의 경험을 선사하는 스튜디오 아이의 작업과 함께하세요.
', - address: '서울시 성동구 광나루로 162 BS성수타워 5층', - addressEnglish: '5F 162, Gwangnaru-ro, Seongdong-gu, Seoul, Republic of Korea', - phone: '02-2038-2663', - fax: '02-2038-2663', - introduction: '스튜디오 아이는 편집 및 애니메이팅을 하고 있는 영상 매체 작업 전문 기업입니다.
', - sloganImageFileName: 'Slogan.png', - sloganImageUrl: 'https://studio-eye-gold-bucket.s3.ap-northeast-2.amazonaws.com/Slogan.png', - detailInformation: [ - { - id: 6666, - key: 'Digital Operator', - value: '다양한 고객의 Youtube, Instagram, TikTok 채널을 운영 대행합니다', - }, - { - id: 7777, - key: 'PD Group', - value: '예능, 드라마, 다큐멘터리, 애니메이션까지 전 장르의 디지털 콘텐츠를 기획, 제작합니다', - }, - ], - }, - }, - }).as('getDeletedCompanyInfo'); + cy.wait('@deleteCompanyInfo').then((interception) => { + const request = interception.request?.body; + chai.expect(request.detailInformation).to.have.length.above(0); // 최소 1개 남아있음 + }); cy.visit('/about'); - cy.wait('@getDeletedCompanyInfo'); + cy.intercept('GET', `/api/company/information`).as('getDeletedCompanyInfo'); + + cy.wait('@getDeletedCompanyInfo').then((interception) => { + const response = interception.response?.body; + chai.expect(response.data.detailInformation).to.not.deep.include({ + key: 'MCN 2.0', + }); + }); cy.contains('MCN 2.0').should('not.exist'); }); - it('PA에서 WHAT WE DO 항목을 삭제할 때 최소 하나 이상 남아있어야 한다는 알림을 확인한다.', () => { - // 수정하기 버튼 클릭 + it('필수 예외) PA에서 WHAT WE DO 항목을 삭제할 때 최소 하나 이상 남아있어야 한다는 알림을 확인한다.', () => { cy.get(`[data-cy="dataEdit-Button"]`, { timeout: 20000 }) .should('exist') .and('be.visible') .eq(3) .click({ force: true }); - cy.get(`[data-cy="${aboutPageAttributes.DELETE_DETAIL}"]`, { timeout: 10000 }).should('exist'); + cy.get(`[data-cy="${aboutPageAttributes.DELETE_DETAIL}"]`).then(($buttons) => { if ($buttons.length === 1) { - // 항목이 하나만 남아있을 때 삭제 버튼 클릭 cy.wrap($buttons.eq(0)).click({ force: true }); - - // 프롬프트 창 자동 확인 처리 cy.on('window:confirm', () => true); - // 최소 1개 이상 등록되어 있어야 한다는 알림이 표시되는지 확인 cy.contains('최소 1개 이상은 등록되어 있어야 합니다.').should('be.visible'); - } else { - // 여러 개가 남아있을 때는 일반 삭제 시나리오 실행 - cy.wrap($buttons.eq(0)).click({ force: true }); - cy.on('window:confirm', () => true); } }); }); diff --git a/cypress/support/hooks.ts b/cypress/support/hooks.ts index 6ded828..95b04fb 100644 --- a/cypress/support/hooks.ts +++ b/cypress/support/hooks.ts @@ -23,3 +23,17 @@ export const confirmAndCheckCompletion = (confirmMessage: string, alertMessage: return true; // 알림 확인 }); }; + +// HTML 태그 제거 및 HTML 엔티티 디코딩 함수 +export const normalizeHtml = (html: string) => { + // HTML 엔티티 디코딩 + const textarea = document.createElement('textarea'); + textarea.innerHTML = html; + const decodedHtml = textarea.value; + + // 태그 제거 및 텍스트 정리 + return decodedHtml + .replace(/<[^>]*>/g, '') // HTML 태그 제거 + .replace(/\s+/g, ' ') // 공백 정리 + .trim(); // 앞뒤 공백 제거 +}; diff --git a/src/components/PromotionAdmin/Home/Graph/Graph.tsx b/src/components/PromotionAdmin/Home/Graph/Graph.tsx index 11b7faa..8412d1f 100644 --- a/src/components/PromotionAdmin/Home/Graph/Graph.tsx +++ b/src/components/PromotionAdmin/Home/Graph/Graph.tsx @@ -11,8 +11,8 @@ type Props = { title: string; processedData: { x: string; y: number }[]; data: ViewData[] | RequestData[]; - handleCategoryChange: (category:string)=>void; - handleStateChange: (state:string)=>void; + handleCategoryChange: (category: string) => void; + handleStateChange: (state: string) => void; handleStartDateChange: (newStartDate: dayjs.Dayjs | null) => void; handleEndDateChange: (newEndDate: dayjs.Dayjs | null) => void; category: string; @@ -24,10 +24,10 @@ type Props = { filter2: Option[]; }; -type Option={ - value:string; - label:string; -} +type Option = { + value: string; + label: string; +}; const Graph = ({ title, @@ -45,14 +45,14 @@ const Graph = ({ filter, filter2, }: Props) => { - const [showFilter2, setShowFilter2] = useState(false); - useEffect(()=>{ - if(division==='request'||category===MenuType.ARTWORK){ + const [showFilter2, setShowFilter2] = useState(false); + useEffect(() => { + if (division === 'request' || category === MenuType.ARTWORK) { setShowFilter2(true); - }else{ + } else { setShowFilter2(false); } - },[category]) + }, [category]); return (