feat: 더미 데이터 시더 추가 및 회계 관련 마이그레이션
- DummyDataSeeder 및 개별 시더 추가 (Client, BadDebt, Deposit 등) - payments.paid_at nullable 마이그레이션 - subscriptions 취소 컬럼 추가 - clients 테이블 bad_debt 컬럼 제거 - PlanController, ClientService 수정 - 불필요한 claudedocs, flow-test 파일 정리
This commit is contained in:
@@ -1,172 +0,0 @@
|
||||
{
|
||||
"name": "ItemField is_active 컬럼 검증 테스트",
|
||||
"description": "item_fields 테이블에 추가된 is_active 컬럼의 기능을 검증합니다. 필드 생성 시 기본값(true), 수정, 조회 시 is_active 필드 포함 여부를 테스트합니다.",
|
||||
"version": "1.0",
|
||||
"config": {
|
||||
"baseUrl": "https://api.sam.kr/api/v1",
|
||||
"apiKey": "{{$env.FLOW_TESTER_API_KEY}}",
|
||||
"timeout": 30000,
|
||||
"stopOnFailure": true
|
||||
},
|
||||
"variables": {
|
||||
"user_id": "{{$env.FLOW_TESTER_USER_ID}}",
|
||||
"user_pwd": "{{$env.FLOW_TESTER_USER_PWD}}"
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
"id": "login",
|
||||
"name": "1. 로그인 - 인증 토큰 획득",
|
||||
"method": "POST",
|
||||
"endpoint": "/login",
|
||||
"body": {
|
||||
"user_id": "{{user_id}}",
|
||||
"user_pwd": "{{user_pwd}}"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.message": "로그인 성공",
|
||||
"$.access_token": "@isString"
|
||||
}
|
||||
},
|
||||
"extract": {
|
||||
"token": "$.access_token"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "get_fields_list",
|
||||
"name": "2. 필드 목록 조회 - is_active 필드 포함 확인",
|
||||
"method": "GET",
|
||||
"endpoint": "/item-master/fields",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data": "@isArray"
|
||||
}
|
||||
},
|
||||
"extract": {
|
||||
"existingFieldId": "$.data[0].id",
|
||||
"fieldCount": "$.data.length"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "create_field",
|
||||
"name": "3. 독립 필드 생성 - is_active 기본값 true 확인",
|
||||
"method": "POST",
|
||||
"endpoint": "/item-master/fields",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"body": {
|
||||
"field_name": "[테스트] is_active 검증 필드",
|
||||
"field_type": "textbox",
|
||||
"field_key": "test_is_active",
|
||||
"is_required": false,
|
||||
"placeholder": "is_active 기본값 테스트",
|
||||
"description": "API Flow Tester에서 생성한 테스트 필드"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200, 201],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data.id": "@isNumber",
|
||||
"$.data.field_name": "[테스트] is_active 검증 필드",
|
||||
"$.data.is_active": true
|
||||
}
|
||||
},
|
||||
"extract": {
|
||||
"newFieldId": "$.data.id"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "verify_field_created",
|
||||
"name": "4. 생성된 필드 상세 확인 - is_active=true",
|
||||
"method": "GET",
|
||||
"endpoint": "/item-master/fields",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true
|
||||
}
|
||||
},
|
||||
"extract": {
|
||||
"allFields": "$.data"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "update_field_inactive",
|
||||
"name": "5. 필드 비활성화 - is_active=false로 수정",
|
||||
"method": "PUT",
|
||||
"endpoint": "/item-master/fields/{{create_field.newFieldId}}",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"body": {
|
||||
"is_active": false
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data.is_active": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "verify_field_inactive",
|
||||
"name": "6. 비활성화 상태 확인",
|
||||
"method": "GET",
|
||||
"endpoint": "/item-master/fields",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "update_field_active",
|
||||
"name": "7. 필드 재활성화 - is_active=true로 수정",
|
||||
"method": "PUT",
|
||||
"endpoint": "/item-master/fields/{{create_field.newFieldId}}",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"body": {
|
||||
"is_active": true
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data.is_active": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "delete_test_field",
|
||||
"name": "8. 테스트 필드 삭제 (정리)",
|
||||
"method": "DELETE",
|
||||
"endpoint": "/item-master/fields/{{create_field.newFieldId}}",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,277 +0,0 @@
|
||||
{
|
||||
"name": "단가 관리 CRUD 테스트",
|
||||
"description": "단가(Pricing) API의 생성, 조회, 수정, 확정, 삭제 전체 플로우 테스트",
|
||||
"version": "1.0",
|
||||
"config": {
|
||||
"baseUrl": "",
|
||||
"timeout": 30000,
|
||||
"stopOnFailure": true
|
||||
},
|
||||
"variables": {
|
||||
"user_id": "{{$env.FLOW_TESTER_USER_ID}}",
|
||||
"user_pwd": "{{$env.FLOW_TESTER_USER_PWD}}"
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
"id": "login",
|
||||
"name": "로그인",
|
||||
"method": "POST",
|
||||
"endpoint": "/login",
|
||||
"body": {
|
||||
"user_id": "{{user_id}}",
|
||||
"user_pwd": "{{user_pwd}}"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.message": "로그인 성공",
|
||||
"$.access_token": "@isString"
|
||||
}
|
||||
},
|
||||
"extract": {
|
||||
"token": "$.access_token"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "list_prices",
|
||||
"name": "단가 목록 조회",
|
||||
"method": "GET",
|
||||
"endpoint": "/pricing",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"query": {
|
||||
"per_page": 10,
|
||||
"page": 1
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data.data": "@isArray"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "create_price",
|
||||
"name": "단가 생성 (MATERIAL)",
|
||||
"method": "POST",
|
||||
"endpoint": "/pricing",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"body": {
|
||||
"item_type_code": "MATERIAL",
|
||||
"item_id": 1,
|
||||
"client_group_id": null,
|
||||
"purchase_price": 10000,
|
||||
"processing_cost": 500,
|
||||
"loss_rate": 5,
|
||||
"margin_rate": 20,
|
||||
"sales_price": 12600,
|
||||
"rounding_rule": "round",
|
||||
"rounding_unit": 100,
|
||||
"supplier": "테스트 공급업체",
|
||||
"effective_from": "2025-01-01",
|
||||
"effective_to": "2025-12-31",
|
||||
"note": "API Flow 테스트용 단가",
|
||||
"status": "draft"
|
||||
},
|
||||
"expect": {
|
||||
"status": [201],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data.id": "@isNumber",
|
||||
"$.data.item_type_code": "MATERIAL",
|
||||
"$.data.purchase_price": 10000,
|
||||
"$.data.status": "draft"
|
||||
}
|
||||
},
|
||||
"extract": {
|
||||
"price_id": "$.data.id"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "show_price",
|
||||
"name": "생성된 단가 상세 조회",
|
||||
"method": "GET",
|
||||
"endpoint": "/pricing/{{create_price.price_id}}",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data.id": "{{create_price.price_id}}",
|
||||
"$.data.item_type_code": "MATERIAL",
|
||||
"$.data.supplier": "테스트 공급업체"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "update_price",
|
||||
"name": "단가 수정 (가격 변경)",
|
||||
"method": "PUT",
|
||||
"endpoint": "/pricing/{{create_price.price_id}}",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"body": {
|
||||
"purchase_price": 11000,
|
||||
"processing_cost": 600,
|
||||
"margin_rate": 25,
|
||||
"sales_price": 14500,
|
||||
"note": "단가 수정 테스트",
|
||||
"change_reason": "원가 인상으로 인한 가격 조정",
|
||||
"status": "active"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data.purchase_price": 11000,
|
||||
"$.data.processing_cost": 600,
|
||||
"$.data.status": "active"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "get_revisions",
|
||||
"name": "변경 이력 조회",
|
||||
"method": "GET",
|
||||
"endpoint": "/pricing/{{create_price.price_id}}/revisions",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data": "@isArray"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "get_cost",
|
||||
"name": "원가 조회 (receipt > standard 폴백)",
|
||||
"method": "GET",
|
||||
"endpoint": "/pricing/cost",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"query": {
|
||||
"item_type_code": "MATERIAL",
|
||||
"item_id": 1,
|
||||
"date": "2025-06-15"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data.item_type_code": "MATERIAL",
|
||||
"$.data.item_id": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "by_items",
|
||||
"name": "다중 품목 단가 조회",
|
||||
"method": "POST",
|
||||
"endpoint": "/pricing/by-items",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"body": {
|
||||
"items": [
|
||||
{
|
||||
"item_type_code": "MATERIAL",
|
||||
"item_id": 1
|
||||
}
|
||||
],
|
||||
"date": "2025-06-15"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data": "@isArray"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "create_price_for_finalize",
|
||||
"name": "확정 테스트용 단가 생성",
|
||||
"method": "POST",
|
||||
"endpoint": "/pricing",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"body": {
|
||||
"item_type_code": "PRODUCT",
|
||||
"item_id": 1,
|
||||
"purchase_price": 50000,
|
||||
"sales_price": 70000,
|
||||
"effective_from": "2025-01-01",
|
||||
"status": "active"
|
||||
},
|
||||
"expect": {
|
||||
"status": [201],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data.id": "@isNumber"
|
||||
}
|
||||
},
|
||||
"extract": {
|
||||
"finalize_price_id": "$.data.id"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "finalize_price",
|
||||
"name": "가격 확정 (불변 처리)",
|
||||
"method": "POST",
|
||||
"endpoint": "/pricing/{{create_price_for_finalize.finalize_price_id}}/finalize",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data.status": "finalized",
|
||||
"$.data.is_final": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "delete_price",
|
||||
"name": "단가 삭제 (soft delete)",
|
||||
"method": "DELETE",
|
||||
"endpoint": "/pricing/{{create_price.price_id}}",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "verify_deleted",
|
||||
"name": "삭제된 단가 조회 시 404 확인",
|
||||
"method": "GET",
|
||||
"endpoint": "/pricing/{{create_price.price_id}}",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"expect": {
|
||||
"status": [404],
|
||||
"jsonPath": {
|
||||
"$.success": false
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,227 +0,0 @@
|
||||
{
|
||||
"name": "Attendance API 근태관리 테스트",
|
||||
"description": "근태 CRUD, 출퇴근 기록, 월간 통계 테스트",
|
||||
"version": "1.0",
|
||||
"config": {
|
||||
"baseUrl": "",
|
||||
"timeout": 30000,
|
||||
"stopOnFailure": true
|
||||
},
|
||||
"variables": {
|
||||
"user_id": "{{$env.FLOW_TESTER_USER_ID}}",
|
||||
"user_pwd": "{{$env.FLOW_TESTER_USER_PWD}}",
|
||||
"test_date": "{{$date}}"
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
"id": "login",
|
||||
"name": "로그인",
|
||||
"method": "POST",
|
||||
"endpoint": "/login",
|
||||
"body": {
|
||||
"user_id": "{{user_id}}",
|
||||
"user_pwd": "{{user_pwd}}"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.message": "로그인 성공",
|
||||
"$.access_token": "@isString"
|
||||
}
|
||||
},
|
||||
"extract": {
|
||||
"token": "$.access_token",
|
||||
"current_user_id": "$.user.id"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "check_in",
|
||||
"name": "출근 기록",
|
||||
"method": "POST",
|
||||
"endpoint": "/attendances/check-in",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"body": {
|
||||
"check_in": "09:00:00",
|
||||
"gps_data": {
|
||||
"latitude": 37.5665,
|
||||
"longitude": 126.978,
|
||||
"accuracy": 10
|
||||
}
|
||||
},
|
||||
"expect": {
|
||||
"status": [200, 201],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data.id": "@isNumber",
|
||||
"$.data.status": "@isString"
|
||||
}
|
||||
},
|
||||
"extract": {
|
||||
"attendance_id": "$.data.id"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "show_attendance",
|
||||
"name": "근태 상세 조회",
|
||||
"method": "GET",
|
||||
"endpoint": "/attendances/{{check_in.attendance_id}}",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data.id": "{{check_in.attendance_id}}",
|
||||
"$.data.base_date": "@isString"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "check_out",
|
||||
"name": "퇴근 기록",
|
||||
"method": "POST",
|
||||
"endpoint": "/attendances/check-out",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"body": {
|
||||
"check_out": "18:00:00",
|
||||
"gps_data": {
|
||||
"latitude": 37.5665,
|
||||
"longitude": 126.978,
|
||||
"accuracy": 15
|
||||
}
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data.id": "@isNumber"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "list_attendances",
|
||||
"name": "근태 목록 조회",
|
||||
"method": "GET",
|
||||
"endpoint": "/attendances",
|
||||
"query": {
|
||||
"page": 1,
|
||||
"per_page": 10,
|
||||
"date": "{{test_date}}"
|
||||
},
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data.data": "@isArray"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "monthly_stats",
|
||||
"name": "월간 통계 조회",
|
||||
"method": "GET",
|
||||
"endpoint": "/attendances/monthly-stats",
|
||||
"query": {
|
||||
"year": 2025,
|
||||
"month": 12
|
||||
},
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "create_attendance",
|
||||
"name": "근태 수동 등록 (관리자)",
|
||||
"method": "POST",
|
||||
"endpoint": "/attendances",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"body": {
|
||||
"user_id": "{{login.current_user_id}}",
|
||||
"base_date": "2025-12-01",
|
||||
"status": "onTime",
|
||||
"json_details": {
|
||||
"check_in": "09:00:00",
|
||||
"check_out": "18:00:00",
|
||||
"work_minutes": 480
|
||||
},
|
||||
"remarks": "Flow Tester 테스트 데이터"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200, 201],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data.id": "@isNumber"
|
||||
}
|
||||
},
|
||||
"extract": {
|
||||
"manual_attendance_id": "$.data.id"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "update_attendance",
|
||||
"name": "근태 수정",
|
||||
"method": "PATCH",
|
||||
"endpoint": "/attendances/{{create_attendance.manual_attendance_id}}",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"body": {
|
||||
"status": "late",
|
||||
"remarks": "수정된 테스트 데이터"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data.status": "late"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "delete_manual_attendance",
|
||||
"name": "수동 등록 근태 삭제",
|
||||
"method": "DELETE",
|
||||
"endpoint": "/attendances/{{create_attendance.manual_attendance_id}}",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "delete_checkin_attendance",
|
||||
"name": "출퇴근 기록 삭제 (정리)",
|
||||
"method": "DELETE",
|
||||
"endpoint": "/attendances/{{check_in.attendance_id}}",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
{
|
||||
"name": "Department Tree API 테스트",
|
||||
"description": "부서 트리 조회 테스트",
|
||||
"version": "1.0",
|
||||
"config": {
|
||||
"baseUrl": "",
|
||||
"timeout": 30000,
|
||||
"stopOnFailure": true
|
||||
},
|
||||
"variables": {
|
||||
"user_id": "{{$env.FLOW_TESTER_USER_ID}}",
|
||||
"user_pwd": "{{$env.FLOW_TESTER_USER_PWD}}"
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
"id": "login",
|
||||
"name": "로그인",
|
||||
"method": "POST",
|
||||
"endpoint": "/login",
|
||||
"body": {
|
||||
"user_id": "{{user_id}}",
|
||||
"user_pwd": "{{user_pwd}}"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.message": "로그인 성공",
|
||||
"$.access_token": "@isString"
|
||||
}
|
||||
},
|
||||
"extract": {
|
||||
"token": "$.access_token"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "get_tree",
|
||||
"name": "부서 트리 조회",
|
||||
"method": "GET",
|
||||
"endpoint": "/departments/tree",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data": "@isArray"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "get_tree_with_users",
|
||||
"name": "부서 트리 조회 (사용자 포함)",
|
||||
"method": "GET",
|
||||
"endpoint": "/departments/tree",
|
||||
"query": {
|
||||
"with_users": true
|
||||
},
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data": "@isArray"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "list_departments",
|
||||
"name": "부서 목록 조회",
|
||||
"method": "GET",
|
||||
"endpoint": "/departments",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data": "@isArray"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,188 +0,0 @@
|
||||
{
|
||||
"name": "Employee API CRUD 테스트",
|
||||
"description": "사원 관리 API 전체 CRUD 및 계정 생성 테스트",
|
||||
"version": "1.0",
|
||||
"config": {
|
||||
"baseUrl": "",
|
||||
"timeout": 30000,
|
||||
"stopOnFailure": true
|
||||
},
|
||||
"variables": {
|
||||
"user_id": "{{$env.FLOW_TESTER_USER_ID}}",
|
||||
"user_pwd": "{{$env.FLOW_TESTER_USER_PWD}}",
|
||||
"test_email": "test.employee.{{$timestamp}}@example.com",
|
||||
"test_name": "테스트사원{{$random:4}}"
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
"id": "login",
|
||||
"name": "로그인",
|
||||
"method": "POST",
|
||||
"endpoint": "/login",
|
||||
"body": {
|
||||
"user_id": "{{user_id}}",
|
||||
"user_pwd": "{{user_pwd}}"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.message": "로그인 성공",
|
||||
"$.access_token": "@isString"
|
||||
}
|
||||
},
|
||||
"extract": {
|
||||
"token": "$.access_token",
|
||||
"current_user_id": "$.user.id"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "get_stats",
|
||||
"name": "사원 통계 조회",
|
||||
"method": "GET",
|
||||
"endpoint": "/employees/stats",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data.total": "@isNumber",
|
||||
"$.data.active": "@isNumber",
|
||||
"$.data.leave": "@isNumber",
|
||||
"$.data.resigned": "@isNumber"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "list_employees",
|
||||
"name": "사원 목록 조회",
|
||||
"method": "GET",
|
||||
"endpoint": "/employees",
|
||||
"query": {
|
||||
"page": 1,
|
||||
"per_page": 10
|
||||
},
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data.data": "@isArray"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "create_employee",
|
||||
"name": "사원 등록",
|
||||
"method": "POST",
|
||||
"endpoint": "/employees",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"body": {
|
||||
"name": "{{test_name}}",
|
||||
"email": "{{test_email}}",
|
||||
"phone": "010-1234-5678",
|
||||
"employee_number": "EMP{{$random:6}}",
|
||||
"employee_status": "active",
|
||||
"position": "사원",
|
||||
"hire_date": "{{$date}}",
|
||||
"json_extra": {
|
||||
"emergency_contact": "010-9999-8888",
|
||||
"address": "서울시 강남구"
|
||||
}
|
||||
},
|
||||
"expect": {
|
||||
"status": [200, 201],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data.id": "@isNumber",
|
||||
"$.data.user.name": "{{test_name}}"
|
||||
}
|
||||
},
|
||||
"extract": {
|
||||
"employee_id": "$.data.id",
|
||||
"user_id": "$.data.user_id"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "show_employee",
|
||||
"name": "사원 상세 조회",
|
||||
"method": "GET",
|
||||
"endpoint": "/employees/{{create_employee.employee_id}}",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data.id": "{{create_employee.employee_id}}",
|
||||
"$.data.employee_status": "active"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "update_employee",
|
||||
"name": "사원 정보 수정",
|
||||
"method": "PATCH",
|
||||
"endpoint": "/employees/{{create_employee.employee_id}}",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"body": {
|
||||
"position": "대리",
|
||||
"employee_status": "active",
|
||||
"json_extra": {
|
||||
"emergency_contact": "010-1111-2222",
|
||||
"address": "서울시 서초구",
|
||||
"skills": ["Laravel", "React"]
|
||||
}
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data.id": "@isNumber"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "list_filtered",
|
||||
"name": "사원 필터 조회 (재직자)",
|
||||
"method": "GET",
|
||||
"endpoint": "/employees",
|
||||
"query": {
|
||||
"status": "active",
|
||||
"q": "{{test_name}}"
|
||||
},
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "delete_employee",
|
||||
"name": "사원 삭제",
|
||||
"method": "DELETE",
|
||||
"endpoint": "/employees/{{create_employee.employee_id}}",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.token}}"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,926 +0,0 @@
|
||||
{
|
||||
"name": "사용자 초대 플로우 테스트",
|
||||
"description": "사용자 초대 전체 플로우 (발송/목록/수락/취소/재발송) 및 분기 상황 테스트",
|
||||
"version": "1.0",
|
||||
"config": {
|
||||
"baseUrl": "https://api.sam.kr/api/v1",
|
||||
"apiKey": "{{$env.FLOW_TESTER_API_KEY}}",
|
||||
"timeout": 30000,
|
||||
"stopOnFailure": false
|
||||
},
|
||||
"variables": {
|
||||
"user_id": "{{$env.FLOW_TESTER_USER_ID}}",
|
||||
"user_pwd": "{{$env.FLOW_TESTER_USER_PWD}}",
|
||||
"test_email_prefix": "flowtest",
|
||||
"test_domain": "example.com"
|
||||
},
|
||||
"setup": {
|
||||
"description": "테스트 전 초기화 - 기존 테스트 초대 정리는 수동으로 진행"
|
||||
},
|
||||
"flows": [
|
||||
{
|
||||
"id": "flow_1",
|
||||
"name": "🔴 P1: 기본 초대 플로우 (role=user)",
|
||||
"description": "일반 사용자 역할로 초대 발송 → 목록 확인 → 취소",
|
||||
"steps": [
|
||||
{
|
||||
"id": "login",
|
||||
"name": "로그인",
|
||||
"method": "POST",
|
||||
"endpoint": "/login",
|
||||
"body": {
|
||||
"user_id": "{{variables.user_id}}",
|
||||
"user_pwd": "{{variables.user_pwd}}"
|
||||
},
|
||||
"extract": {
|
||||
"accessToken": "$.access_token"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.access_token": "@isString"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "invite_user_role",
|
||||
"name": "초대 발송 (role=user)",
|
||||
"method": "POST",
|
||||
"endpoint": "/users/invite",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.accessToken}}"
|
||||
},
|
||||
"body": {
|
||||
"email": "{{variables.test_email_prefix}}_user_{{$timestamp}}@{{variables.test_domain}}",
|
||||
"role": "user",
|
||||
"message": "SAM 시스템에 합류해 주세요!"
|
||||
},
|
||||
"dependsOn": ["login"],
|
||||
"extract": {
|
||||
"invitationId": "$.data.id",
|
||||
"invitationToken": "$.data.token",
|
||||
"invitedEmail": "$.data.email"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data.status": "pending",
|
||||
"$.data.email": "@isString"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "list_invitations",
|
||||
"name": "초대 목록 조회",
|
||||
"method": "GET",
|
||||
"endpoint": "/users/invitations",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.accessToken}}"
|
||||
},
|
||||
"query": {
|
||||
"status": "pending",
|
||||
"per_page": 10
|
||||
},
|
||||
"dependsOn": ["invite_user_role"],
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data.data": "@isArray"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "cancel_invitation",
|
||||
"name": "초대 취소",
|
||||
"method": "DELETE",
|
||||
"endpoint": "/users/invitations/{{invite_user_role.invitationId}}",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.accessToken}}"
|
||||
},
|
||||
"dependsOn": ["list_invitations"],
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "flow_2",
|
||||
"name": "🔴 P1: 관리자 역할 초대 (role=admin)",
|
||||
"description": "관리자 역할로 초대 발송",
|
||||
"steps": [
|
||||
{
|
||||
"id": "login",
|
||||
"name": "로그인",
|
||||
"method": "POST",
|
||||
"endpoint": "/login",
|
||||
"body": {
|
||||
"user_id": "{{variables.user_id}}",
|
||||
"user_pwd": "{{variables.user_pwd}}"
|
||||
},
|
||||
"extract": {
|
||||
"accessToken": "$.access_token"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "invite_admin_role",
|
||||
"name": "초대 발송 (role=admin)",
|
||||
"method": "POST",
|
||||
"endpoint": "/users/invite",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.accessToken}}"
|
||||
},
|
||||
"body": {
|
||||
"email": "{{variables.test_email_prefix}}_admin_{{$timestamp}}@{{variables.test_domain}}",
|
||||
"role": "admin",
|
||||
"message": "관리자로 초대합니다."
|
||||
},
|
||||
"dependsOn": ["login"],
|
||||
"extract": {
|
||||
"invitationId": "$.data.id"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data.status": "pending"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "cleanup",
|
||||
"name": "초대 취소 (정리)",
|
||||
"method": "DELETE",
|
||||
"endpoint": "/users/invitations/{{invite_admin_role.invitationId}}",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.accessToken}}"
|
||||
},
|
||||
"dependsOn": ["invite_admin_role"],
|
||||
"expect": {
|
||||
"status": [200]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "flow_3",
|
||||
"name": "🔴 P1: 매니저 역할 초대 (role=manager)",
|
||||
"description": "매니저 역할로 초대 발송",
|
||||
"steps": [
|
||||
{
|
||||
"id": "login",
|
||||
"name": "로그인",
|
||||
"method": "POST",
|
||||
"endpoint": "/login",
|
||||
"body": {
|
||||
"user_id": "{{variables.user_id}}",
|
||||
"user_pwd": "{{variables.user_pwd}}"
|
||||
},
|
||||
"extract": {
|
||||
"accessToken": "$.access_token"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "invite_manager_role",
|
||||
"name": "초대 발송 (role=manager)",
|
||||
"method": "POST",
|
||||
"endpoint": "/users/invite",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.accessToken}}"
|
||||
},
|
||||
"body": {
|
||||
"email": "{{variables.test_email_prefix}}_manager_{{$timestamp}}@{{variables.test_domain}}",
|
||||
"role": "manager"
|
||||
},
|
||||
"dependsOn": ["login"],
|
||||
"extract": {
|
||||
"invitationId": "$.data.id"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data.status": "pending"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "cleanup",
|
||||
"name": "초대 취소 (정리)",
|
||||
"method": "DELETE",
|
||||
"endpoint": "/users/invitations/{{invite_manager_role.invitationId}}",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.accessToken}}"
|
||||
},
|
||||
"dependsOn": ["invite_manager_role"],
|
||||
"expect": {
|
||||
"status": [200]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "flow_4",
|
||||
"name": "🔴 P1: 초대 재발송 플로우",
|
||||
"description": "초대 발송 → 재발송 → 취소",
|
||||
"steps": [
|
||||
{
|
||||
"id": "login",
|
||||
"name": "로그인",
|
||||
"method": "POST",
|
||||
"endpoint": "/login",
|
||||
"body": {
|
||||
"user_id": "{{variables.user_id}}",
|
||||
"user_pwd": "{{variables.user_pwd}}"
|
||||
},
|
||||
"extract": {
|
||||
"accessToken": "$.access_token"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "invite",
|
||||
"name": "초대 발송",
|
||||
"method": "POST",
|
||||
"endpoint": "/users/invite",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.accessToken}}"
|
||||
},
|
||||
"body": {
|
||||
"email": "{{variables.test_email_prefix}}_resend_{{$timestamp}}@{{variables.test_domain}}",
|
||||
"role": "user"
|
||||
},
|
||||
"dependsOn": ["login"],
|
||||
"extract": {
|
||||
"invitationId": "$.data.id",
|
||||
"originalExpiresAt": "$.data.expires_at"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "resend",
|
||||
"name": "초대 재발송",
|
||||
"method": "POST",
|
||||
"endpoint": "/users/invitations/{{invite.invitationId}}/resend",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.accessToken}}"
|
||||
},
|
||||
"dependsOn": ["invite"],
|
||||
"extract": {
|
||||
"newExpiresAt": "$.data.expires_at"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data.status": "pending"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "cleanup",
|
||||
"name": "초대 취소 (정리)",
|
||||
"method": "DELETE",
|
||||
"endpoint": "/users/invitations/{{invite.invitationId}}",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.accessToken}}"
|
||||
},
|
||||
"dependsOn": ["resend"],
|
||||
"expect": {
|
||||
"status": [200]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "flow_5",
|
||||
"name": "🔴 P1: 에러 케이스 - 중복 이메일 초대",
|
||||
"description": "동일 이메일로 중복 초대 시도 (대기 중 초대 존재)",
|
||||
"steps": [
|
||||
{
|
||||
"id": "login",
|
||||
"name": "로그인",
|
||||
"method": "POST",
|
||||
"endpoint": "/login",
|
||||
"body": {
|
||||
"user_id": "{{variables.user_id}}",
|
||||
"user_pwd": "{{variables.user_pwd}}"
|
||||
},
|
||||
"extract": {
|
||||
"accessToken": "$.access_token"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "first_invite",
|
||||
"name": "첫 번째 초대 발송",
|
||||
"method": "POST",
|
||||
"endpoint": "/users/invite",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.accessToken}}"
|
||||
},
|
||||
"body": {
|
||||
"email": "{{variables.test_email_prefix}}_dup_{{$timestamp}}@{{variables.test_domain}}",
|
||||
"role": "user"
|
||||
},
|
||||
"dependsOn": ["login"],
|
||||
"extract": {
|
||||
"invitationId": "$.data.id",
|
||||
"testEmail": "$.data.email"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "duplicate_invite",
|
||||
"name": "중복 초대 발송 (실패 예상)",
|
||||
"method": "POST",
|
||||
"endpoint": "/users/invite",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.accessToken}}"
|
||||
},
|
||||
"body": {
|
||||
"email": "{{first_invite.testEmail}}",
|
||||
"role": "user"
|
||||
},
|
||||
"dependsOn": ["first_invite"],
|
||||
"expect": {
|
||||
"status": [400, 422],
|
||||
"jsonPath": {
|
||||
"$.success": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "cleanup",
|
||||
"name": "초대 취소 (정리)",
|
||||
"method": "DELETE",
|
||||
"endpoint": "/users/invitations/{{first_invite.invitationId}}",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.accessToken}}"
|
||||
},
|
||||
"dependsOn": ["duplicate_invite"],
|
||||
"expect": {
|
||||
"status": [200]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "flow_6",
|
||||
"name": "🟡 P2: 목록 필터링 - 상태별",
|
||||
"description": "초대 목록을 상태별로 필터링",
|
||||
"steps": [
|
||||
{
|
||||
"id": "login",
|
||||
"name": "로그인",
|
||||
"method": "POST",
|
||||
"endpoint": "/login",
|
||||
"body": {
|
||||
"user_id": "{{variables.user_id}}",
|
||||
"user_pwd": "{{variables.user_pwd}}"
|
||||
},
|
||||
"extract": {
|
||||
"accessToken": "$.access_token"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "list_pending",
|
||||
"name": "대기 중 목록 조회",
|
||||
"method": "GET",
|
||||
"endpoint": "/users/invitations",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.accessToken}}"
|
||||
},
|
||||
"query": {
|
||||
"status": "pending"
|
||||
},
|
||||
"dependsOn": ["login"],
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "list_accepted",
|
||||
"name": "수락된 목록 조회",
|
||||
"method": "GET",
|
||||
"endpoint": "/users/invitations",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.accessToken}}"
|
||||
},
|
||||
"query": {
|
||||
"status": "accepted"
|
||||
},
|
||||
"dependsOn": ["login"],
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "list_expired",
|
||||
"name": "만료된 목록 조회",
|
||||
"method": "GET",
|
||||
"endpoint": "/users/invitations",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.accessToken}}"
|
||||
},
|
||||
"query": {
|
||||
"status": "expired"
|
||||
},
|
||||
"dependsOn": ["login"],
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "list_cancelled",
|
||||
"name": "취소된 목록 조회",
|
||||
"method": "GET",
|
||||
"endpoint": "/users/invitations",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.accessToken}}"
|
||||
},
|
||||
"query": {
|
||||
"status": "cancelled"
|
||||
},
|
||||
"dependsOn": ["login"],
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "flow_7",
|
||||
"name": "🟡 P2: 목록 정렬 옵션",
|
||||
"description": "다양한 정렬 기준으로 목록 조회",
|
||||
"steps": [
|
||||
{
|
||||
"id": "login",
|
||||
"name": "로그인",
|
||||
"method": "POST",
|
||||
"endpoint": "/login",
|
||||
"body": {
|
||||
"user_id": "{{variables.user_id}}",
|
||||
"user_pwd": "{{variables.user_pwd}}"
|
||||
},
|
||||
"extract": {
|
||||
"accessToken": "$.access_token"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "sort_created_at_desc",
|
||||
"name": "생성일 내림차순",
|
||||
"method": "GET",
|
||||
"endpoint": "/users/invitations",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.accessToken}}"
|
||||
},
|
||||
"query": {
|
||||
"sort_by": "created_at",
|
||||
"sort_dir": "desc"
|
||||
},
|
||||
"dependsOn": ["login"],
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "sort_expires_at_asc",
|
||||
"name": "만료일 오름차순",
|
||||
"method": "GET",
|
||||
"endpoint": "/users/invitations",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.accessToken}}"
|
||||
},
|
||||
"query": {
|
||||
"sort_by": "expires_at",
|
||||
"sort_dir": "asc"
|
||||
},
|
||||
"dependsOn": ["login"],
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "sort_email_asc",
|
||||
"name": "이메일 오름차순",
|
||||
"method": "GET",
|
||||
"endpoint": "/users/invitations",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.accessToken}}"
|
||||
},
|
||||
"query": {
|
||||
"sort_by": "email",
|
||||
"sort_dir": "asc"
|
||||
},
|
||||
"dependsOn": ["login"],
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "flow_8",
|
||||
"name": "🟡 P2: 이메일 검색",
|
||||
"description": "이메일 키워드로 초대 검색",
|
||||
"steps": [
|
||||
{
|
||||
"id": "login",
|
||||
"name": "로그인",
|
||||
"method": "POST",
|
||||
"endpoint": "/login",
|
||||
"body": {
|
||||
"user_id": "{{variables.user_id}}",
|
||||
"user_pwd": "{{variables.user_pwd}}"
|
||||
},
|
||||
"extract": {
|
||||
"accessToken": "$.access_token"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "search_by_email",
|
||||
"name": "이메일 검색",
|
||||
"method": "GET",
|
||||
"endpoint": "/users/invitations",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.accessToken}}"
|
||||
},
|
||||
"query": {
|
||||
"search": "flowtest"
|
||||
},
|
||||
"dependsOn": ["login"],
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data.data": "@isArray"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "flow_9",
|
||||
"name": "🟢 P3: 만료 기간 지정 옵션",
|
||||
"description": "만료 기간을 명시적으로 지정하여 초대",
|
||||
"steps": [
|
||||
{
|
||||
"id": "login",
|
||||
"name": "로그인",
|
||||
"method": "POST",
|
||||
"endpoint": "/login",
|
||||
"body": {
|
||||
"user_id": "{{variables.user_id}}",
|
||||
"user_pwd": "{{variables.user_pwd}}"
|
||||
},
|
||||
"extract": {
|
||||
"accessToken": "$.access_token"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "invite_with_expires",
|
||||
"name": "14일 만료 기간으로 초대",
|
||||
"method": "POST",
|
||||
"endpoint": "/users/invite",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.accessToken}}"
|
||||
},
|
||||
"body": {
|
||||
"email": "{{variables.test_email_prefix}}_expires_{{$timestamp}}@{{variables.test_domain}}",
|
||||
"role": "user",
|
||||
"expires_days": 14
|
||||
},
|
||||
"dependsOn": ["login"],
|
||||
"extract": {
|
||||
"invitationId": "$.data.id"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data.expires_at": "@isString"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "cleanup",
|
||||
"name": "초대 취소 (정리)",
|
||||
"method": "DELETE",
|
||||
"endpoint": "/users/invitations/{{invite_with_expires.invitationId}}",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.accessToken}}"
|
||||
},
|
||||
"dependsOn": ["invite_with_expires"],
|
||||
"expect": {
|
||||
"status": [200]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "flow_10",
|
||||
"name": "🟢 P3: role_id로 초대 (숫자 ID 사용)",
|
||||
"description": "role 문자열 대신 role_id 숫자로 초대",
|
||||
"steps": [
|
||||
{
|
||||
"id": "login",
|
||||
"name": "로그인",
|
||||
"method": "POST",
|
||||
"endpoint": "/login",
|
||||
"body": {
|
||||
"user_id": "{{variables.user_id}}",
|
||||
"user_pwd": "{{variables.user_pwd}}"
|
||||
},
|
||||
"extract": {
|
||||
"accessToken": "$.access_token"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "invite_with_role_id",
|
||||
"name": "role_id=2로 초대",
|
||||
"method": "POST",
|
||||
"endpoint": "/users/invite",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.accessToken}}"
|
||||
},
|
||||
"body": {
|
||||
"email": "{{variables.test_email_prefix}}_roleid_{{$timestamp}}@{{variables.test_domain}}",
|
||||
"role_id": 2
|
||||
},
|
||||
"dependsOn": ["login"],
|
||||
"extract": {
|
||||
"invitationId": "$.data.id"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200],
|
||||
"jsonPath": {
|
||||
"$.success": true,
|
||||
"$.data.role_id": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "cleanup",
|
||||
"name": "초대 취소 (정리)",
|
||||
"method": "DELETE",
|
||||
"endpoint": "/users/invitations/{{invite_with_role_id.invitationId}}",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.accessToken}}"
|
||||
},
|
||||
"dependsOn": ["invite_with_role_id"],
|
||||
"expect": {
|
||||
"status": [200]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "flow_11",
|
||||
"name": "🔴 P1: 에러 케이스 - 잘못된 역할",
|
||||
"description": "존재하지 않는 role 값으로 초대 시도",
|
||||
"steps": [
|
||||
{
|
||||
"id": "login",
|
||||
"name": "로그인",
|
||||
"method": "POST",
|
||||
"endpoint": "/login",
|
||||
"body": {
|
||||
"user_id": "{{variables.user_id}}",
|
||||
"user_pwd": "{{variables.user_pwd}}"
|
||||
},
|
||||
"extract": {
|
||||
"accessToken": "$.access_token"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "invite_invalid_role",
|
||||
"name": "잘못된 role로 초대 (실패 예상)",
|
||||
"method": "POST",
|
||||
"endpoint": "/users/invite",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.accessToken}}"
|
||||
},
|
||||
"body": {
|
||||
"email": "{{variables.test_email_prefix}}_invalid_{{$timestamp}}@{{variables.test_domain}}",
|
||||
"role": "superadmin"
|
||||
},
|
||||
"dependsOn": ["login"],
|
||||
"expect": {
|
||||
"status": [400, 422],
|
||||
"jsonPath": {
|
||||
"$.success": false
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "flow_12",
|
||||
"name": "🔴 P1: 에러 케이스 - 이메일 형식 오류",
|
||||
"description": "잘못된 이메일 형식으로 초대 시도",
|
||||
"steps": [
|
||||
{
|
||||
"id": "login",
|
||||
"name": "로그인",
|
||||
"method": "POST",
|
||||
"endpoint": "/login",
|
||||
"body": {
|
||||
"user_id": "{{variables.user_id}}",
|
||||
"user_pwd": "{{variables.user_pwd}}"
|
||||
},
|
||||
"extract": {
|
||||
"accessToken": "$.access_token"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "invite_invalid_email",
|
||||
"name": "잘못된 이메일로 초대 (실패 예상)",
|
||||
"method": "POST",
|
||||
"endpoint": "/users/invite",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.accessToken}}"
|
||||
},
|
||||
"body": {
|
||||
"email": "invalid-email-format",
|
||||
"role": "user"
|
||||
},
|
||||
"dependsOn": ["login"],
|
||||
"expect": {
|
||||
"status": [422],
|
||||
"jsonPath": {
|
||||
"$.success": false
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "flow_13",
|
||||
"name": "🔴 P1: 에러 케이스 - 권한 없이 접근",
|
||||
"description": "인증 없이 초대 API 접근 시도",
|
||||
"steps": [
|
||||
{
|
||||
"id": "invite_no_auth",
|
||||
"name": "인증 없이 초대 시도 (실패 예상)",
|
||||
"method": "POST",
|
||||
"endpoint": "/users/invite",
|
||||
"body": {
|
||||
"email": "noauth@example.com",
|
||||
"role": "user"
|
||||
},
|
||||
"expect": {
|
||||
"status": [401],
|
||||
"jsonPath": {
|
||||
"$.success": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "list_no_auth",
|
||||
"name": "인증 없이 목록 조회 (실패 예상)",
|
||||
"method": "GET",
|
||||
"endpoint": "/users/invitations",
|
||||
"expect": {
|
||||
"status": [401],
|
||||
"jsonPath": {
|
||||
"$.success": false
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "flow_14",
|
||||
"name": "🔴 P1: 에러 케이스 - 존재하지 않는 초대 취소",
|
||||
"description": "존재하지 않는 초대 ID로 취소 시도",
|
||||
"steps": [
|
||||
{
|
||||
"id": "login",
|
||||
"name": "로그인",
|
||||
"method": "POST",
|
||||
"endpoint": "/login",
|
||||
"body": {
|
||||
"user_id": "{{variables.user_id}}",
|
||||
"user_pwd": "{{variables.user_pwd}}"
|
||||
},
|
||||
"extract": {
|
||||
"accessToken": "$.access_token"
|
||||
},
|
||||
"expect": {
|
||||
"status": [200]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "cancel_not_found",
|
||||
"name": "존재하지 않는 초대 취소 (실패 예상)",
|
||||
"method": "DELETE",
|
||||
"endpoint": "/users/invitations/999999",
|
||||
"headers": {
|
||||
"Authorization": "Bearer {{login.accessToken}}"
|
||||
},
|
||||
"dependsOn": ["login"],
|
||||
"expect": {
|
||||
"status": [404],
|
||||
"jsonPath": {
|
||||
"$.success": false
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"summary": {
|
||||
"total_flows": 14,
|
||||
"priority_breakdown": {
|
||||
"P1_critical": 8,
|
||||
"P2_important": 3,
|
||||
"P3_recommended": 3
|
||||
},
|
||||
"coverage": {
|
||||
"endpoints": [
|
||||
"POST /users/invite",
|
||||
"GET /users/invitations",
|
||||
"DELETE /users/invitations/{id}",
|
||||
"POST /users/invitations/{id}/resend"
|
||||
],
|
||||
"not_covered": [
|
||||
"POST /users/invitations/{token}/accept (별도 Flow 필요: 실제 이메일 수신 필요)"
|
||||
]
|
||||
},
|
||||
"branches_tested": {
|
||||
"role_types": ["admin", "manager", "user"],
|
||||
"role_methods": ["role (string)", "role_id (integer)"],
|
||||
"status_filters": ["pending", "accepted", "expired", "cancelled"],
|
||||
"sort_options": ["created_at", "expires_at", "email"],
|
||||
"error_cases": ["duplicate_email", "invalid_role", "invalid_email", "no_auth", "not_found"]
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user