[BE-55] 단계 1 통합 · E2E 시나리오 테스트
작업 내용 (설계 의도)
근거 TDD: 20260808-지원관리-확장-tdd.md — “Testing Plan 시나리오 E2E”, “Release Scenario 1단계”
변경 사항
단계 1의 완료 판정 기준(PRD Milestones: “인증 없이 API 호출 시 401, 웹훅 경로만 터널로 접근 가능, 관리 상태 3종 CRUD·교차 회사 목록 API·대시보드 3요소·담당자 CRUD가 실 DB로 동작”)을 실 DB(Testcontainers MySQL) 기반 시나리오 테스트 1본으로 검증합니다.
- 기존
RecruitmentE2EScenarioTest·ScenarioFixtures패턴을 따라Stage1ManagementScenarioTest를 신설합니다. 기존 시나리오 파일을 수정하지 않습니다(Single Writer). - 시나리오: 로그인 → 공고 수집(픽스처) → dedup 배치로 그룹 생성 → 관리 상태
INTERESTED저장 → 교차 목록에서 필터 조회 → 지원 생성 → 관리 상태 자동 복구 확인 → 대시보드에 카드 노출 → 담당자 등록 → 로그아웃 후 401. - 피처 플래그 전환 순서까지 검증합니다 — 플래그 OFF 상태에서 기존 API가 그대로 동작하는지, ON 전환 후 신규 기능이 열리는지를 같은 테스트에서 확인합니다. Release Scenario 1-6~1-9의 무중단 전환이 실제로 성립하는지 보는 것이 목적입니다.
- 인증 ON이 터널 ON보다 먼저라는 순서 제약을 문서(릴리즈 체크리스트)로 남깁니다 — 순서가 뒤집히면 무인증으로 인터넷에 노출됩니다.
- 전 wave 티켓의 회귀(기존 FR-1~69 경로)가 깨지지 않았는지 확인합니다.
의존
- BE-46, BE-47, BE-48, BE-49, BE-50, BE-51, BE-52, BE-53, BE-54 (단계 1 전량 — BE-52·53·54 머지 완료가 착수 전제)
다이어그램
처리 흐름
sequenceDiagram participant T as Stage1ScenarioTest participant Auth as AuthApi participant Dedup as DedupBatch participant Watch as WatchStateApi participant List as JobPostingApi participant App as ApplicationApi participant Dash as DashboardApi T->>Auth: POST /api/auth/login T->>Dedup: 08:30 배치 실행 → 그룹 생성 T->>Watch: PUT watch-state (INTERESTED) T->>List: GET /api/job-postings?watchStatus=INTERESTED T->>Watch: PUT watch-state (EXCLUDED) T->>App: POST /api/applications T->>Watch: GET watch-state → INTERESTED 복구 확인 T->>Dash: GET /api/dashboard → 카드 노출 확인 T->>Auth: POST /api/auth/logout T->>List: GET /api/job-postings → 401
클래스 의존
flowchart LR subgraph Test["src/test scenario"] Scenario[Stage1ManagementScenarioTest] Fixture[Stage1ScenarioFixtures] end subgraph Api["presentation"] AuthApi[AuthApiController] WatchApi[WatchStateApiController] PostApi[JobPostingApiController] AppApi[ApplicationApiController] DashApi[DashboardApiController] end Scenario --> Fixture Scenario --> AuthApi Scenario --> WatchApi Scenario --> PostApi Scenario --> AppApi Scenario --> DashApi
테스트 케이스
- 로그인부터 로그아웃까지 전 흐름이 실 DB로 1회 왕복 성공한다
- 인증 없이
/api/job-postings를 호출하면 401이다 - 웹훅 경로는 인증 없이 접근된다
EXCLUDED로 저장한 공고에 지원하면 관리 상태가INTERESTED로 복구된다 (비동기 리스너 — Awaitility로 대기)- 교차 목록의 관리 상태·플랫폼 필터가 시나리오 데이터에서 기대대로 동작한다
- 대시보드 3요소가 시나리오 지원 건을 반영한다
- 담당자를 등록하면 조회된다
auth.required플래그 OFF 상태에서는 인증 없이 전 API가 동작한다 (무중단 전환 검증)- 플래그 OFF 구간에서
GET /api/auth/session이authRequired: false를 반환해 FE 게이트가 우회된다 (C-4) - 플래그 ON 전환 후 같은 요청이 401로 바뀐다 (배포 1-8 → 1-9 창 검증)
- dedup 배치 실행 전 공고에
PUT /api/job-postings/{id}/watch-state로 관리 상태를 저장하면 단독 그룹이 생성된다 (C-1) - 이후 dedup 배치를 돌려도 그 그룹 id와 관리 상태가 유지된다 (정체성 승계)
- 공고 상세 응답에
dedupGroupId·watchState가 포함된다 (C-1) - 교차 목록
companyId필터가 동작한다 (C-3) watchlist.management플래그 OFF 상태에서 관리 상태 API가 409를 반환한다
wave 3 산출물 검증 (BE-52·53·54 병합 후)
-
[병합 정합] BE-52의
WatchStateDomainService.findAllBy와 BE-53의restoreOnApplied·revertOnApplicationRemoved가 같은 파일에 공존한 상태에서 둘 다 정상 동작한다 (두 브랜치가 병렬 추가 → 리베이스로 합쳐진 지점) -
교차 목록
tag필터가 동작하고watchedOnly를 함의한다 (D) -
sort=PRIORITY_DESC+watchedOnly=false면 400JOB_POSTING_SORT_NOT_APPLICABLE이다 (C-6) -
관리 상태 그룹이 상한을 넘으면 400
WATCH_STATE_FILTER_LIMIT_EXCEEDED이고actualCount·limit이 응답에 담긴다 (A) -
matchedOnly=true면 400JOB_POSTING_FILTER_NOT_SUPPORTED다 — 조용히 무시되어 전체 목록이 200으로 돌아오지 않는다 -
관리 상태가 없는 그룹 조회는 200 +
watchState: null(미분류)이고,watchlist.managementOFF는 409FEATURE_DISABLED로 구분된다 (C) -
플래그 OFF + 관리 상태 파라미터 미지정이면 교차 목록이 200이고 관리 상태 필드만 null로 강등된다 (Release 1-7 이전 구간 보장)
-
지원을 철회하면 관리 상태가 이력 기준 직전 상태로 복귀한다 (FR-75 ②)
-
태그가 등록된 관리 상태에 복구가 일어나도 태그 유니크 위반 없이 커밋되고 태그가 증식하지 않는다 (BE-50에서 실 DB로 드러난 결함의 E2E 회귀 가드)
-
POST /api/operations/backfills/posting-platform을 두 번 실행하면 두 번째 처리 건수가 0이다 (멱등) -
백필 후
platform IS NULL AND posting_origin='COLLECTED'건수가 0이다 -
GET /api/operations/webhook-receipts가 사유 코드 필터·days범위로 조회된다 -
GET /api/operations/tunnel-status가 호스트명 미설정 시 예외 없이reachable=false를 반환한다 -
/api/health-probe가 인증 없이 204를 반환하고 본문이 비어 있다 -
기존 FR-1~69 경로(회사 등록·수집·매칭·알림)가 회귀 없이 동작한다