Files
sam-manage/resources/views/dev-tools/flow-tester/run-detail.blade.php
hskwon 477779f3ac feat: FlowTester 환경변수 지원 및 결과 설명 UI 개선
- VariableBinder: setVariables()에서 {{$env.XXX}} 환경변수 치환 지원
- FlowExecutor: 스텝 실행 결과에 reason, description, expect 필드 추가
- buildResultReason(): 성공/실패 이유 자동 생성
  - 부정 테스트(400, 404 등) 시 예상대로 반환됨을 명시
  - 400: 유효성 검증 실패 확인
  - 404: 리소스 미존재 확인
  - 409: 충돌 상태 확인
  - 403: 권한 거부 확인
- run-detail.blade.php: 예상 상태코드, 이유, 스텝 설명 표시 UI
2025-12-04 13:28:22 +09:00

165 lines
8.8 KiB
PHP

@extends('layouts.app')
@section('title', '실행 상세 - #' . $run->id)
@section('content')
<!-- 페이지 헤더 -->
<div class="flex justify-between items-center mb-6">
<div class="flex items-center gap-4">
<a href="{{ route('dev-tools.flow-tester.history', $run->flow_id) }}"
class="p-2 text-gray-600 hover:bg-gray-100 rounded-lg transition">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
</svg>
</a>
<div>
<h1 class="text-2xl font-bold text-gray-800">실행 상세 #{{ $run->id }}</h1>
<p class="text-sm text-gray-500">{{ $run->flow->name }}</p>
</div>
</div>
<span class="px-3 py-1 text-sm font-medium rounded {{ $run->status_color }}">
{{ $run->status_label }}
</span>
</div>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
<!-- 요약 정보 -->
<div class="lg:col-span-1">
<div class="bg-white rounded-lg shadow-sm p-6">
<h2 class="text-lg font-semibold text-gray-800 mb-4">실행 정보</h2>
<dl class="space-y-3">
<div class="flex justify-between">
<dt class="text-gray-500">상태</dt>
<dd>
<span class="px-2 py-1 text-xs font-medium rounded {{ $run->status_color }}">
{{ $run->status_label }}
</span>
</dd>
</div>
<div class="flex justify-between">
<dt class="text-gray-500">진행률</dt>
<dd class="text-gray-900">{{ $run->progress }}%</dd>
</div>
<div class="flex justify-between">
<dt class="text-gray-500">완료 스텝</dt>
<dd class="text-gray-900">{{ $run->completed_steps }}/{{ $run->total_steps ?? '-' }}</dd>
</div>
@if($run->failed_step)
<div class="flex justify-between">
<dt class="text-gray-500">실패 스텝</dt>
<dd class="text-red-600">Step {{ $run->failed_step }}</dd>
</div>
@endif
<div class="flex justify-between">
<dt class="text-gray-500">소요시간</dt>
<dd class="text-gray-900">
@if($run->duration_ms)
{{ number_format($run->duration_ms / 1000, 2) }}s
@else
-
@endif
</dd>
</div>
<div class="flex justify-between">
<dt class="text-gray-500">시작시간</dt>
<dd class="text-gray-900">{{ $run->started_at?->format('H:i:s') ?? '-' }}</dd>
</div>
<div class="flex justify-between">
<dt class="text-gray-500">완료시간</dt>
<dd class="text-gray-900">{{ $run->completed_at?->format('H:i:s') ?? '-' }}</dd>
</div>
<div class="flex justify-between">
<dt class="text-gray-500">실행일</dt>
<dd class="text-gray-900">{{ $run->created_at->format('Y-m-d') }}</dd>
</div>
</dl>
</div>
@if($run->error_message)
<div class="mt-4 bg-red-50 border border-red-200 rounded-lg p-4">
<h3 class="text-sm font-medium text-red-800 mb-2">에러 메시지</h3>
<p class="text-sm text-red-700">{{ $run->error_message }}</p>
</div>
@endif
</div>
<!-- 실행 로그 -->
<div class="lg:col-span-2">
<div class="bg-white rounded-lg shadow-sm p-6">
<h2 class="text-lg font-semibold text-gray-800 mb-4">실행 로그</h2>
@if($run->execution_log)
<div class="space-y-4">
@foreach($run->execution_log as $index => $log)
<div class="border rounded-lg p-4 {{ ($log['success'] ?? false) ? 'border-green-200 bg-green-50' : 'border-red-200 bg-red-50' }}">
<div class="flex justify-between items-start mb-2">
<div class="flex items-center gap-2">
@if($log['success'] ?? false)
<svg class="w-5 h-5 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
</svg>
@else
<svg class="w-5 h-5 text-red-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
@endif
<span class="font-medium">{{ $log['step_id'] ?? 'Step '.($index + 1) }}</span>
<span class="text-gray-500">{{ $log['name'] ?? '' }}</span>
</div>
<span class="text-sm text-gray-500">{{ $log['duration'] ?? '' }}ms</span>
</div>
@if(isset($log['request']))
<div class="text-sm mb-2">
<span class="font-medium text-gray-600">Request:</span>
<code class="ml-2 text-gray-800">{{ $log['request']['method'] ?? '' }} {{ $log['request']['endpoint'] ?? '' }}</code>
</div>
@endif
@if(isset($log['response']))
<div class="text-sm">
<span class="font-medium text-gray-600">Response:</span>
<span class="ml-2 {{ ($log['response']['status'] ?? 0) < 400 ? 'text-green-600' : 'text-red-600' }}">
{{ $log['response']['status'] ?? '-' }}
</span>
@if(isset($log['expect']['status']))
<span class="ml-2 text-gray-500">
(예상: {{ is_array($log['expect']['status']) ? implode(', ', $log['expect']['status']) : $log['expect']['status'] }})
</span>
@endif
</div>
@endif
{{-- 성공/실패 이유 설명 --}}
@if(isset($log['reason']))
<div class="mt-2 text-sm {{ ($log['success'] ?? false) ? 'text-green-700 bg-green-100' : 'text-red-700 bg-red-100' }} px-2 py-1 rounded">
{{ $log['reason'] }}
</div>
@endif
{{-- 스텝 설명 --}}
@if(isset($log['description']) && $log['description'])
<div class="mt-1 text-xs text-gray-500 italic">
💡 {{ $log['description'] }}
</div>
@endif
@if(isset($log['error']))
<div class="mt-2 text-sm text-red-600">
{{ $log['error'] }}
</div>
@endif
</div>
@endforeach
</div>
@else
<div class="text-center py-8 text-gray-500">
<p>실행 로그가 없습니다.</p>
</div>
@endif
</div>
</div>
</div>
@endsection