[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본으로 검증합니다.

  1. 기존 RecruitmentE2EScenarioTest·ScenarioFixtures 패턴을 따라 Stage1ManagementScenarioTest를 신설합니다. 기존 시나리오 파일을 수정하지 않습니다(Single Writer).
  2. 시나리오: 로그인 → 공고 수집(픽스처) → dedup 배치로 그룹 생성 → 관리 상태 INTERESTED 저장 → 교차 목록에서 필터 조회 → 지원 생성 → 관리 상태 자동 복구 확인 → 대시보드에 카드 노출 → 담당자 등록 → 로그아웃 후 401.
  3. 피처 플래그 전환 순서까지 검증합니다 — 플래그 OFF 상태에서 기존 API가 그대로 동작하는지, ON 전환 후 신규 기능이 열리는지를 같은 테스트에서 확인합니다. Release Scenario 1-6~1-9의 무중단 전환이 실제로 성립하는지 보는 것이 목적입니다.
  4. 인증 ON이 터널 ON보다 먼저라는 순서 제약을 문서(릴리즈 체크리스트)로 남깁니다 — 순서가 뒤집히면 무인증으로 인터넷에 노출됩니다.
  5. 전 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/sessionauthRequired: 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면 400 JOB_POSTING_SORT_NOT_APPLICABLE이다 (C-6)

  • 관리 상태 그룹이 상한을 넘으면 400 WATCH_STATE_FILTER_LIMIT_EXCEEDED이고 actualCount·limit이 응답에 담긴다 (A)

  • matchedOnly=true면 400 JOB_POSTING_FILTER_NOT_SUPPORTED다 — 조용히 무시되어 전체 목록이 200으로 돌아오지 않는다

  • 관리 상태가 없는 그룹 조회는 200 + watchState: null(미분류)이고, watchlist.management OFF는 409 FEATURE_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 경로(회사 등록·수집·매칭·알림)가 회귀 없이 동작한다