FIX_TMP_CLEAN_UP
This commit is contained in:
parent
b36a648995
commit
3e4447003a
@ -240,11 +240,15 @@ class StorageUploadTest extends BaseCommand
|
||||
{
|
||||
$path = storage_local_path($module, $subFolder, $fileName);
|
||||
|
||||
if (! is_file($path)) {
|
||||
throw new FileStorageException('Local processing path not readable: ' . $path);
|
||||
}
|
||||
try {
|
||||
if (! is_file($path)) {
|
||||
throw new FileStorageException('Local processing path not readable: ' . $path);
|
||||
}
|
||||
|
||||
CLI::write(' local path: ' . $path, 'white');
|
||||
CLI::write(' local path: ' . $path, 'white');
|
||||
} finally {
|
||||
storage_cleanup_temp($path);
|
||||
}
|
||||
}
|
||||
|
||||
private function assertTemporaryUrl(string $module, string $subFolder, string $fileName): void
|
||||
|
||||
@ -277,6 +277,13 @@ $routes->group('storage/browser', static function ($routes) {
|
||||
$routes->get('download', 'StorageBrowserController::download');
|
||||
});
|
||||
|
||||
$routes->group('logs', static function ($routes) {
|
||||
$routes->get('/', 'LogViewerController::index');
|
||||
$routes->get('list', 'LogViewerController::list');
|
||||
$routes->get('view', 'LogViewerController::view');
|
||||
$routes->get('download', 'LogViewerController::download');
|
||||
});
|
||||
|
||||
|
||||
$routes->get('checkPolicyDoc', 'PolicyController::readFile');
|
||||
$routes->get('calculateCommission', 'PolicyController::calculateCommission');
|
||||
|
||||
@ -86,6 +86,8 @@ class AgentIncentiveController extends ResourceController
|
||||
// -------------------------------------------------------------------------
|
||||
public function uploadGridFile()
|
||||
{
|
||||
$localPath = null;
|
||||
|
||||
try {
|
||||
/* ====================================================================
|
||||
* STEP 1 — Validate POST input
|
||||
@ -342,6 +344,8 @@ class AgentIncentiveController extends ResourceController
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return $this->respond(['status' => 'failed', 'code' => 500, 'data' => $e->getMessage()], 500);
|
||||
} finally {
|
||||
storage_cleanup_temp($localPath);
|
||||
}
|
||||
}
|
||||
// public function uploadGridFile_old()
|
||||
|
||||
@ -1209,70 +1209,75 @@ class InvoiceController extends ResourceController
|
||||
'created_by' => $updatedBy > 0 ? $updatedBy : null,
|
||||
], true);
|
||||
|
||||
$localPath = storage_local_path('agent', 'incentive_file', $storedFileName);
|
||||
$spreadsheet = IOFactory::load($localPath);
|
||||
$excelRows = $spreadsheet->getActiveSheet()->toArray(null, true, true, false);
|
||||
$localPath = null;
|
||||
try {
|
||||
$localPath = storage_local_path('agent', 'incentive_file', $storedFileName);
|
||||
$spreadsheet = IOFactory::load($localPath);
|
||||
$excelRows = $spreadsheet->getActiveSheet()->toArray(null, true, true, false);
|
||||
|
||||
if (empty($excelRows)) {
|
||||
return $this->respond([
|
||||
'status' => 'failed',
|
||||
'code' => 400,
|
||||
'message' => 'Uploaded file is empty',
|
||||
], 400);
|
||||
}
|
||||
|
||||
$headerRow = $excelRows[0] ?? [];
|
||||
$headerIndex = [];
|
||||
foreach ($headerRow as $idx => $headerValue) {
|
||||
$normalized = preg_replace('/[^a-z0-9]/', '', strtolower(trim((string)$headerValue)));
|
||||
if (!empty($normalized)) {
|
||||
$headerIndex[$normalized] = (int)$idx;
|
||||
}
|
||||
}
|
||||
|
||||
$policyIdx = $headerIndex['policynumber'] ?? null;
|
||||
$invoiceIdx = $headerIndex['invoicenumber'] ?? null;
|
||||
$commissionIdx = $headerIndex['commission'] ?? ($headerIndex['commissionamount'] ?? null);
|
||||
|
||||
if ($policyIdx === null || $commissionIdx === null) {
|
||||
return $this->respond([
|
||||
'status' => 'failed',
|
||||
'code' => 400,
|
||||
'message' => 'Expected columns: Policy Number, Invoice Number, Commission or Commission Amount',
|
||||
], 400);
|
||||
}
|
||||
|
||||
$fallbackInvoiceNo = trim((string)($post['invoice_number'] ?? ''));
|
||||
$rows = [];
|
||||
foreach ($excelRows as $index => $row) {
|
||||
if ($index === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$policyNo = trim((string)($row[$policyIdx] ?? ''));
|
||||
$invoiceNoFromFile = $invoiceIdx !== null ? trim((string)($row[$invoiceIdx] ?? '')) : '';
|
||||
$invoiceNo = $invoiceNoFromFile !== '' ? $invoiceNoFromFile : $fallbackInvoiceNo;
|
||||
$commissionRaw = trim((string)($row[$commissionIdx] ?? ''));
|
||||
|
||||
if ($policyNo === '' && $invoiceNo === '' && $commissionRaw === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$commission = (float)str_replace(',', '', $commissionRaw);
|
||||
if ($policyNo === '' || $invoiceNo === '' || !is_numeric(str_replace(',', '', $commissionRaw))) {
|
||||
if (empty($excelRows)) {
|
||||
return $this->respond([
|
||||
'status' => 'failed',
|
||||
'code' => 400,
|
||||
'message' => 'Invalid data at line ' . ($index + 1),
|
||||
'message' => 'Uploaded file is empty',
|
||||
], 400);
|
||||
}
|
||||
|
||||
$rows[] = [
|
||||
'line_no' => $index + 1,
|
||||
'policy_number' => $policyNo,
|
||||
'invoice_no' => $invoiceNo,
|
||||
'commission_amount' => $commission,
|
||||
];
|
||||
$headerRow = $excelRows[0] ?? [];
|
||||
$headerIndex = [];
|
||||
foreach ($headerRow as $idx => $headerValue) {
|
||||
$normalized = preg_replace('/[^a-z0-9]/', '', strtolower(trim((string)$headerValue)));
|
||||
if (!empty($normalized)) {
|
||||
$headerIndex[$normalized] = (int)$idx;
|
||||
}
|
||||
}
|
||||
|
||||
$policyIdx = $headerIndex['policynumber'] ?? null;
|
||||
$invoiceIdx = $headerIndex['invoicenumber'] ?? null;
|
||||
$commissionIdx = $headerIndex['commission'] ?? ($headerIndex['commissionamount'] ?? null);
|
||||
|
||||
if ($policyIdx === null || $commissionIdx === null) {
|
||||
return $this->respond([
|
||||
'status' => 'failed',
|
||||
'code' => 400,
|
||||
'message' => 'Expected columns: Policy Number, Invoice Number, Commission or Commission Amount',
|
||||
], 400);
|
||||
}
|
||||
|
||||
$fallbackInvoiceNo = trim((string)($post['invoice_number'] ?? ''));
|
||||
$rows = [];
|
||||
foreach ($excelRows as $index => $row) {
|
||||
if ($index === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$policyNo = trim((string)($row[$policyIdx] ?? ''));
|
||||
$invoiceNoFromFile = $invoiceIdx !== null ? trim((string)($row[$invoiceIdx] ?? '')) : '';
|
||||
$invoiceNo = $invoiceNoFromFile !== '' ? $invoiceNoFromFile : $fallbackInvoiceNo;
|
||||
$commissionRaw = trim((string)($row[$commissionIdx] ?? ''));
|
||||
|
||||
if ($policyNo === '' && $invoiceNo === '' && $commissionRaw === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$commission = (float)str_replace(',', '', $commissionRaw);
|
||||
if ($policyNo === '' || $invoiceNo === '' || !is_numeric(str_replace(',', '', $commissionRaw))) {
|
||||
return $this->respond([
|
||||
'status' => 'failed',
|
||||
'code' => 400,
|
||||
'message' => 'Invalid data at line ' . ($index + 1),
|
||||
], 400);
|
||||
}
|
||||
|
||||
$rows[] = [
|
||||
'line_no' => $index + 1,
|
||||
'policy_number' => $policyNo,
|
||||
'invoice_no' => $invoiceNo,
|
||||
'commission_amount' => $commission,
|
||||
];
|
||||
}
|
||||
} finally {
|
||||
storage_cleanup_temp($localPath);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
175
app/Controllers/LogViewerController.php
Normal file
175
app/Controllers/LogViewerController.php
Normal file
@ -0,0 +1,175 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use CodeIgniter\API\ResponseTrait;
|
||||
use CodeIgniter\HTTP\DownloadResponse;
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
|
||||
class LogViewerController extends BaseController
|
||||
{
|
||||
use ResponseTrait;
|
||||
|
||||
private string $logsPath;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->logsPath = rtrim(WRITEPATH . 'logs', DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
public function index(): string
|
||||
{
|
||||
return view('logs/index');
|
||||
}
|
||||
|
||||
public function list(): ResponseInterface
|
||||
{
|
||||
$search = trim((string) ($this->request->getGet('q') ?? ''));
|
||||
$page = max(1, (int) ($this->request->getGet('page') ?? 1));
|
||||
$limit = max(1, min(50, (int) ($this->request->getGet('limit') ?? 10)));
|
||||
|
||||
$all = $this->listLogFiles($search !== '' ? $search : null);
|
||||
$total = count($all);
|
||||
$offset = ($page - 1) * $limit;
|
||||
$files = array_slice($all, $offset, $limit);
|
||||
$pages = $total > 0 ? (int) ceil($total / $limit) : 0;
|
||||
|
||||
return $this->respond([
|
||||
'status' => 'success',
|
||||
'files' => $files,
|
||||
'page' => $page,
|
||||
'limit' => $limit,
|
||||
'total' => $total,
|
||||
'total_pages'=> $pages,
|
||||
'has_more' => $page < $pages,
|
||||
]);
|
||||
}
|
||||
|
||||
public function view(): string|ResponseInterface
|
||||
{
|
||||
$file = $this->resolveLogFile((string) ($this->request->getGet('file') ?? ''));
|
||||
|
||||
if ($file === null) {
|
||||
return $this->response->setStatusCode(404)->setBody('Log file not found.');
|
||||
}
|
||||
|
||||
$content = @file_get_contents($file['path']);
|
||||
if ($content === false) {
|
||||
return $this->response->setStatusCode(500)->setBody('Unable to read log file.');
|
||||
}
|
||||
|
||||
$maxBytes = 2 * 1024 * 1024;
|
||||
$truncated = false;
|
||||
if (strlen($content) > $maxBytes) {
|
||||
$content = substr($content, -$maxBytes);
|
||||
$truncated = true;
|
||||
}
|
||||
|
||||
return view('logs/view', [
|
||||
'file' => $file,
|
||||
'content' => $content,
|
||||
'truncated' => $truncated,
|
||||
'maxBytes' => $maxBytes,
|
||||
]);
|
||||
}
|
||||
|
||||
public function download(): DownloadResponse|ResponseInterface
|
||||
{
|
||||
$file = $this->resolveLogFile((string) ($this->request->getGet('file') ?? ''));
|
||||
|
||||
if ($file === null) {
|
||||
return $this->response->setStatusCode(404)->setBody('Log file not found.');
|
||||
}
|
||||
|
||||
return $this->response->download($file['path'], null)->setFileName($file['name']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<array{name: string, size: int, size_human: string, modified: string, modified_ts: int}>
|
||||
*/
|
||||
private function listLogFiles(?string $search = null): array
|
||||
{
|
||||
if (! is_dir($this->logsPath)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$files = glob($this->logsPath . 'log-*.log') ?: [];
|
||||
$result = [];
|
||||
$needle = $search !== null ? strtolower($search) : null;
|
||||
|
||||
foreach ($files as $path) {
|
||||
if (! is_file($path)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$name = basename($path);
|
||||
if ($needle !== null && ! str_contains(strtolower($name), $needle)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$size = (int) filesize($path);
|
||||
$mtime = (int) filemtime($path);
|
||||
|
||||
$result[] = [
|
||||
'name' => $name,
|
||||
'size' => $size,
|
||||
'size_human' => $this->formatBytes($size),
|
||||
'modified' => date('Y-m-d H:i:s', $mtime),
|
||||
'modified_ts' => $mtime,
|
||||
];
|
||||
}
|
||||
|
||||
usort($result, static fn (array $a, array $b): int => $b['modified_ts'] <=> $a['modified_ts']);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{name: string, path: string, size: int, size_human: string, modified: string}|null
|
||||
*/
|
||||
private function resolveLogFile(string $name): ?array
|
||||
{
|
||||
$name = basename(trim($name));
|
||||
|
||||
if ($name === '' || ! preg_match('/^log-\d{4}-\d{2}-\d{2}\.log$/', $name)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$path = $this->logsPath . $name;
|
||||
$realPath = realpath($path);
|
||||
$realLogs = realpath($this->logsPath);
|
||||
|
||||
if ($realPath === false || $realLogs === false || ! str_starts_with($realPath, $realLogs) || ! is_file($realPath)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$size = (int) filesize($realPath);
|
||||
|
||||
return [
|
||||
'name' => $name,
|
||||
'path' => $realPath,
|
||||
'size' => $size,
|
||||
'size_human' => $this->formatBytes($size),
|
||||
'modified' => date('Y-m-d H:i:s', (int) filemtime($realPath)),
|
||||
];
|
||||
}
|
||||
|
||||
private function formatBytes(int $bytes): string
|
||||
{
|
||||
if ($bytes < 1024) {
|
||||
return $bytes . ' B';
|
||||
}
|
||||
|
||||
$units = ['KB', 'MB', 'GB'];
|
||||
$value = (float) $bytes;
|
||||
|
||||
foreach ($units as $unit) {
|
||||
$value /= 1024;
|
||||
if ($value < 1024) {
|
||||
return round($value, 2) . ' ' . $unit;
|
||||
}
|
||||
}
|
||||
|
||||
return round($value / 1024, 2) . ' TB';
|
||||
}
|
||||
}
|
||||
@ -738,6 +738,7 @@ class PolicyController extends ResourceController
|
||||
|
||||
public function checkPolicyDoc($policyId = null , $return = null)
|
||||
{
|
||||
$pdfFilePath = null;
|
||||
|
||||
try
|
||||
{
|
||||
@ -794,7 +795,7 @@ class PolicyController extends ResourceController
|
||||
]), JSON_UNESCAPED_SLASHES));
|
||||
|
||||
if (!$pdfExists) {
|
||||
$missingPath = policy_local_pdf_path($pdfFileName);
|
||||
$missingPath = storage()->resolveKey('policy', 'policy_pdf', $pdfFileName);
|
||||
log_message('error', '[S3_FILE_GET][POLICY_READ][FAILED] policy PDF not found in storage | ' . json_encode(array_merge($s3LogCtx, [
|
||||
'pdf_file_name' => $pdfFileName,
|
||||
'resolved_path' => $missingPath,
|
||||
@ -1089,6 +1090,8 @@ class PolicyController extends ResourceController
|
||||
}else{
|
||||
return ['status'=>"failed", 'message'=> "Error: " . $e->getMessage()];
|
||||
}
|
||||
} finally {
|
||||
storage_cleanup_temp($pdfFilePath);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -151,6 +151,7 @@ class PolicyRagController extends ResourceController
|
||||
public function readPolicyDocViaRag($policyId = null)
|
||||
{
|
||||
$fileId = null;
|
||||
$pdfFilePath = null;
|
||||
|
||||
$this->logRagStep('READ_START', 'started', 'readPolicyDocViaRag', ['policy_id' => $policyId]);
|
||||
|
||||
@ -170,9 +171,11 @@ class PolicyRagController extends ResourceController
|
||||
$pdfFileName = $record['policy_pdf_file_name'] ?? '';
|
||||
|
||||
if ($pdfFileName === '' || !policy_exists_by_type($pdfFileName, 'policy_pdf')) {
|
||||
$pdfFilePath = $pdfFileName !== '' ? policy_local_pdf_path($pdfFileName) : '';
|
||||
$this->logRagStep('PDF_CHECK', 'failed', 'PDF file not found', ['path' => $pdfFilePath]);
|
||||
return $this->formatReadResponse('failed', "File not found at {$pdfFilePath}");
|
||||
$missingPath = $pdfFileName !== ''
|
||||
? storage()->resolveKey('policy', 'policy_pdf', $pdfFileName)
|
||||
: '';
|
||||
$this->logRagStep('PDF_CHECK', 'failed', 'PDF file not found', ['path' => $missingPath]);
|
||||
return $this->formatReadResponse('failed', "File not found at {$missingPath}");
|
||||
}
|
||||
|
||||
$pdfFilePath = policy_local_pdf_path($pdfFileName);
|
||||
@ -255,6 +258,8 @@ class PolicyRagController extends ResourceController
|
||||
]);
|
||||
return $this->formatReadResponse('failed', 'Error: ' . $e->getMessage());
|
||||
} finally {
|
||||
storage_cleanup_temp($pdfFilePath);
|
||||
|
||||
if (!empty($fileId)) {
|
||||
$this->logRagStep('DELETE', 'started', 'Deleting RAG file', [
|
||||
'policy_id' => $policyId,
|
||||
|
||||
@ -58,6 +58,17 @@ if (!function_exists('storage_local_path')) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('storage_cleanup_temp')) {
|
||||
/**
|
||||
* Remove an S3 downloadToTemp working copy under the OS temp dir.
|
||||
* Safe no-op for local writable paths and missing files.
|
||||
*/
|
||||
function storage_cleanup_temp(?string $path): bool
|
||||
{
|
||||
return storage()->cleanupTempPath($path);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('storage_delete')) {
|
||||
function storage_delete(string $module, string $subFolder, string $fileName): bool
|
||||
{
|
||||
|
||||
@ -381,6 +381,58 @@ class FileStorageService
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a path returned by getLocalPathForProcessing / downloadToTemp when it lives
|
||||
* under the OS temp directory (S3 working copies). Never deletes local writable/uploads files.
|
||||
*/
|
||||
public function cleanupTempPath(?string $path): bool
|
||||
{
|
||||
if ($path === null || $path === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! is_file($path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $this->isS3TempProcessingPath($path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$deleted = @unlink($path);
|
||||
|
||||
StorageLogger::log($deleted ? 'SUCCESS' : 'WARNING', 'Temp processing path cleanup', $this->baseContext([
|
||||
'path' => $path,
|
||||
'deleted' => $deleted,
|
||||
]));
|
||||
|
||||
return $deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
* True for S3 downloadToTemp paths like /tmp/s3_<uniqid>_<basename>.
|
||||
*/
|
||||
public function isS3TempProcessingPath(string $path): bool
|
||||
{
|
||||
$tempRoot = rtrim(str_replace(['/', '\\'], DIRECTORY_SEPARATOR, sys_get_temp_dir()), DIRECTORY_SEPARATOR);
|
||||
$normalized = str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $path);
|
||||
$realTemp = realpath(sys_get_temp_dir());
|
||||
if ($realTemp !== false) {
|
||||
$tempRoot = rtrim(str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $realTemp), DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
$realPath = realpath($path);
|
||||
$checkPath = $realPath !== false
|
||||
? str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $realPath)
|
||||
: $normalized;
|
||||
|
||||
if (! str_starts_with($checkPath, $tempRoot . DIRECTORY_SEPARATOR)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return str_starts_with(basename($checkPath), 's3_');
|
||||
}
|
||||
|
||||
public function getTemporaryUrl(string $module, string $subFolder, string $fileName, ?int $ttlSeconds = null): string
|
||||
{
|
||||
return $this->getTemporaryUrlForKey(
|
||||
|
||||
331
app/Views/logs/index.php
Normal file
331
app/Views/logs/index.php
Normal file
@ -0,0 +1,331 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Application Logs</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
--brand: #0d9488;
|
||||
--brand-dark: #0f766e;
|
||||
--brand-light: #ccfbf1;
|
||||
}
|
||||
|
||||
body {
|
||||
background: #f8fafc;
|
||||
font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
|
||||
color: #0f172a;
|
||||
}
|
||||
|
||||
.page-wrap {
|
||||
max-width: 1000px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem 1rem 3rem;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-size: 1.75rem;
|
||||
font-weight: 700;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.page-subtitle {
|
||||
color: #64748b;
|
||||
margin: 0.35rem 0 0;
|
||||
}
|
||||
|
||||
.panel {
|
||||
background: #fff;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.filters {
|
||||
padding: 1.25rem;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto;
|
||||
gap: 1rem;
|
||||
align-items: end;
|
||||
border-bottom: 1px solid #e2e8f0;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
color: #334155;
|
||||
}
|
||||
|
||||
.btn-brand {
|
||||
background: var(--brand);
|
||||
border-color: var(--brand);
|
||||
color: #fff;
|
||||
min-width: 110px;
|
||||
}
|
||||
|
||||
.btn-brand:hover,
|
||||
.btn-brand:focus {
|
||||
background: var(--brand-dark);
|
||||
border-color: var(--brand-dark);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.table thead th {
|
||||
font-size: 0.75rem;
|
||||
letter-spacing: 0.04em;
|
||||
text-transform: uppercase;
|
||||
color: #64748b;
|
||||
border-bottom-color: #e2e8f0;
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.table tbody td {
|
||||
vertical-align: middle;
|
||||
border-bottom-color: #f1f5f9;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
padding: 3rem 1rem;
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.footer-bar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0.9rem 1.25rem;
|
||||
border-top: 1px solid #e2e8f0;
|
||||
color: #64748b;
|
||||
font-size: 0.9rem;
|
||||
gap: 1rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.alert-inline {
|
||||
margin: 1rem 1.25rem 0;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.filters {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="page-wrap">
|
||||
<div class="page-header">
|
||||
<h1 class="page-title">Application Logs</h1>
|
||||
<p class="page-subtitle">View or download daily log files. Results load 10 at a time.</p>
|
||||
</div>
|
||||
|
||||
<div class="panel">
|
||||
<div id="alertBox"></div>
|
||||
|
||||
<div class="filters">
|
||||
<div>
|
||||
<label for="searchInput" class="form-label">File name</label>
|
||||
<input id="searchInput" type="text" class="form-control" placeholder="Search file name...">
|
||||
</div>
|
||||
<div>
|
||||
<button id="searchBtn" class="btn btn-brand w-100">Search</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>File name</th>
|
||||
<th>Size</th>
|
||||
<th>Last modified</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="logsBody">
|
||||
<tr>
|
||||
<td colspan="4" class="text-center py-4 text-muted">Loading logs...</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="footer-bar">
|
||||
<div id="pageInfo">Page —</div>
|
||||
<div class="d-flex gap-2">
|
||||
<button id="prevBtn" class="btn btn-outline-secondary btn-sm" disabled>Previous</button>
|
||||
<button id="nextBtn" class="btn btn-brand btn-sm" disabled>Next</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const baseUrl = <?= json_encode(base_url()) ?>.replace(/\/$/, '');
|
||||
const apiBase = baseUrl + '/logs';
|
||||
|
||||
const searchInput = document.getElementById('searchInput');
|
||||
const searchBtn = document.getElementById('searchBtn');
|
||||
const logsBody = document.getElementById('logsBody');
|
||||
const pageInfo = document.getElementById('pageInfo');
|
||||
const prevBtn = document.getElementById('prevBtn');
|
||||
const nextBtn = document.getElementById('nextBtn');
|
||||
const alertBox = document.getElementById('alertBox');
|
||||
|
||||
let currentSearch = '';
|
||||
let pageNumber = 1;
|
||||
let totalPages = 0;
|
||||
let totalFiles = 0;
|
||||
|
||||
function showAlert(message, type = 'danger') {
|
||||
alertBox.innerHTML = `<div class="alert alert-${type} alert-inline mb-0">${escapeHtml(message)}</div>`;
|
||||
}
|
||||
|
||||
function clearAlert() {
|
||||
alertBox.innerHTML = '';
|
||||
}
|
||||
|
||||
function escapeHtml(value) {
|
||||
return String(value)
|
||||
.replaceAll('&', '&')
|
||||
.replaceAll('<', '<')
|
||||
.replaceAll('>', '>')
|
||||
.replaceAll('"', '"')
|
||||
.replaceAll("'", ''');
|
||||
}
|
||||
|
||||
function renderEmpty(message) {
|
||||
logsBody.innerHTML = `
|
||||
<tr>
|
||||
<td colspan="4">
|
||||
<div class="empty-state">${escapeHtml(message)}</div>
|
||||
</td>
|
||||
</tr>`;
|
||||
}
|
||||
|
||||
function renderLoading() {
|
||||
logsBody.innerHTML = `
|
||||
<tr>
|
||||
<td colspan="4" class="text-center py-4 text-muted">Loading logs...</td>
|
||||
</tr>`;
|
||||
}
|
||||
|
||||
function renderFiles(files) {
|
||||
if (!files.length) {
|
||||
renderEmpty('No log files found');
|
||||
return;
|
||||
}
|
||||
|
||||
logsBody.innerHTML = files.map((file) => {
|
||||
const viewUrl = `${apiBase}/view?file=${encodeURIComponent(file.name)}`;
|
||||
const downloadUrl = `${apiBase}/download?file=${encodeURIComponent(file.name)}`;
|
||||
|
||||
return `
|
||||
<tr>
|
||||
<td><code>${escapeHtml(file.name)}</code></td>
|
||||
<td>${escapeHtml(file.size_human)}</td>
|
||||
<td>${escapeHtml(file.modified || '—')}</td>
|
||||
<td>
|
||||
<a class="btn btn-sm btn-outline-primary me-1" href="${viewUrl}" target="_blank" rel="noopener">View</a>
|
||||
<a class="btn btn-sm btn-brand" href="${downloadUrl}">Download</a>
|
||||
</td>
|
||||
</tr>`;
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function updatePagination() {
|
||||
if (totalFiles === 0) {
|
||||
pageInfo.textContent = 'No results';
|
||||
} else {
|
||||
pageInfo.textContent = `Page ${pageNumber} of ${totalPages} · ${totalFiles} file${totalFiles === 1 ? '' : 's'}`;
|
||||
}
|
||||
|
||||
prevBtn.disabled = pageNumber <= 1;
|
||||
nextBtn.disabled = pageNumber >= totalPages || totalPages === 0;
|
||||
}
|
||||
|
||||
async function loadLogs(resetPage = true) {
|
||||
clearAlert();
|
||||
|
||||
if (resetPage) {
|
||||
pageNumber = 1;
|
||||
}
|
||||
|
||||
renderLoading();
|
||||
|
||||
const params = new URLSearchParams({
|
||||
page: String(pageNumber),
|
||||
limit: '10',
|
||||
});
|
||||
|
||||
if (currentSearch) {
|
||||
params.set('q', currentSearch);
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`${apiBase}/list?${params.toString()}`);
|
||||
const data = await response.json();
|
||||
|
||||
if (data.status !== 'success') {
|
||||
showAlert(data.message || 'Unable to load logs');
|
||||
renderEmpty('Unable to load logs');
|
||||
totalPages = 0;
|
||||
totalFiles = 0;
|
||||
updatePagination();
|
||||
return;
|
||||
}
|
||||
|
||||
totalPages = data.total_pages || 0;
|
||||
totalFiles = data.total || 0;
|
||||
pageNumber = data.page || pageNumber;
|
||||
|
||||
renderFiles(data.files || []);
|
||||
updatePagination();
|
||||
} catch (error) {
|
||||
showAlert('Network error while loading logs');
|
||||
renderEmpty('Unable to load logs');
|
||||
totalPages = 0;
|
||||
totalFiles = 0;
|
||||
updatePagination();
|
||||
}
|
||||
}
|
||||
|
||||
function runSearch() {
|
||||
currentSearch = searchInput.value.trim();
|
||||
loadLogs(true);
|
||||
}
|
||||
|
||||
searchBtn.addEventListener('click', runSearch);
|
||||
searchInput.addEventListener('keydown', (event) => {
|
||||
if (event.key === 'Enter') {
|
||||
runSearch();
|
||||
}
|
||||
});
|
||||
|
||||
prevBtn.addEventListener('click', () => {
|
||||
if (pageNumber <= 1) {
|
||||
return;
|
||||
}
|
||||
pageNumber -= 1;
|
||||
loadLogs(false);
|
||||
});
|
||||
|
||||
nextBtn.addEventListener('click', () => {
|
||||
if (pageNumber >= totalPages) {
|
||||
return;
|
||||
}
|
||||
pageNumber += 1;
|
||||
loadLogs(false);
|
||||
});
|
||||
|
||||
loadLogs(true);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
139
app/Views/logs/view.php
Normal file
139
app/Views/logs/view.php
Normal file
@ -0,0 +1,139 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><?= esc($file['name']) ?> — Log Viewer</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
--brand: #0d9488;
|
||||
--brand-dark: #0f766e;
|
||||
--brand-light: #ccfbf1;
|
||||
}
|
||||
|
||||
body {
|
||||
background: #0f172a;
|
||||
color: #e2e8f0;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.topbar {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
background: #1e293b;
|
||||
border-bottom: 1px solid #334155;
|
||||
padding: 0.75rem 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.meta {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.15rem;
|
||||
}
|
||||
|
||||
.meta h1 {
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
margin: 0;
|
||||
color: #f8fafc;
|
||||
font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
|
||||
}
|
||||
|
||||
.meta span {
|
||||
font-size: 0.8rem;
|
||||
color: #94a3b8;
|
||||
font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.btn-brand {
|
||||
background: var(--brand);
|
||||
border-color: var(--brand);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.btn-brand:hover,
|
||||
.btn-brand:focus {
|
||||
background: var(--brand-dark);
|
||||
border-color: var(--brand-dark);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.truncate-note {
|
||||
background: #422006;
|
||||
color: #fde68a;
|
||||
border-bottom: 1px solid #854d0e;
|
||||
padding: 0.55rem 1rem;
|
||||
font-size: 0.85rem;
|
||||
font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
|
||||
}
|
||||
|
||||
.log-body {
|
||||
padding: 1rem;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
font-size: 0.82rem;
|
||||
line-height: 1.45;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.level-error { color: #fca5a5; }
|
||||
.level-critical, .level-emergency, .level-alert { color: #fb7185; }
|
||||
.level-warning { color: #fcd34d; }
|
||||
.level-info, .level-notice { color: #7dd3fc; }
|
||||
.level-debug { color: #a5b4fc; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="topbar">
|
||||
<div class="meta">
|
||||
<h1><?= esc($file['name']) ?></h1>
|
||||
<span><?= esc($file['size_human']) ?> · modified <?= esc($file['modified']) ?></span>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<a class="btn btn-sm btn-outline-light" href="<?= esc(site_url('logs')) ?>">← All logs</a>
|
||||
<a class="btn btn-sm btn-brand" href="<?= esc(site_url('logs/download?file=' . urlencode($file['name']))) ?>">Download</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (! empty($truncated)): ?>
|
||||
<div class="truncate-note">
|
||||
Showing the last <?= number_format((int) $maxBytes) ?> bytes of this file. Use Download for the full log.
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<pre class="log-body" id="logContent"><?= esc($content) ?></pre>
|
||||
|
||||
<script>
|
||||
// Soft-highlight log levels in the pre content without changing text
|
||||
(function () {
|
||||
const el = document.getElementById('logContent');
|
||||
if (!el) return;
|
||||
|
||||
const html = el.textContent
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/\b(ERROR|CRITICAL|EMERGENCY|ALERT|WARNING|INFO|NOTICE|DEBUG)\b/g, (match) => {
|
||||
return `<span class="level-${match.toLowerCase()}">${match}</span>`;
|
||||
});
|
||||
|
||||
el.innerHTML = html;
|
||||
window.scrollTo(0, document.body.scrollHeight);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@ -1 +1 @@
|
||||
{"version":2,"defects":{"Tests\\Unit\\Storage\\FileStorageServiceTest::testUploadModuleFileStoresPolicyPdf":8,"Tests\\Unit\\Storage\\FileStorageServiceTest::testDownloadReturnsAttachmentResponse":7,"Tests\\Unit\\Storage\\LocalStorageDriverTest::testUploadFromUploadedFileStoresUnderLocalRoot":8,"Tests\\Unit\\Storage\\LocalStorageDriverTest::testStreamDownloadReturnsResponseWithBody":7,"Tests\\Unit\\Storage\\PolicyStorageHelperTest::testPolicyUploadPdfStoresFile":8,"Tests\\Unit\\Storage\\PolicyStorageHelperTest::testPolicyUploadReceiptStoresFile":8,"Tests\\Unit\\Storage\\PolicyStorageHelperTest::testPolicyDownloadByTypeAttachment":7,"Tests\\Unit\\Storage\\PolicyStorageHelperTest::testPolicyDownloadByTypeInline":7,"Tests\\Unit\\Storage\\S3StorageIntegrationTest::testS3PolicyPdfUploadExistsReadAndDelete":1,"Tests\\Unit\\Storage\\S3StorageIntegrationTest::testS3PolicyReceiptUploadAndTemporaryUrl":1,"Tests\\Unit\\Storage\\S3StorageIntegrationTest::testS3EndorsementOriginalAndCompletionUpload":1,"Tests\\Unit\\Storage\\S3StorageIntegrationTest::testLocalDriverScenarioStillWorksWhenEnvIsLocal":1,"Tests\\Unit\\Storage\\S3StorageIntegrationTest::testS3DriverIsActiveFromEnv":1,"Tests\\Unit\\Storage\\S3StorageIntegrationTest::testS3PolicyMarkdownPutAndRead":1},"times":{"Tests\\Unit\\Storage\\FileStorageServiceTest::testResolveKeyWithSubFolder":0.006,"Tests\\Unit\\Storage\\FileStorageServiceTest::testResolveKeyWithoutSubFolder":0.001,"Tests\\Unit\\Storage\\FileStorageServiceTest::testUploadModuleFileStoresPolicyPdf":0.006,"Tests\\Unit\\Storage\\FileStorageServiceTest::testReadWriteAndDeleteByModule":0.003,"Tests\\Unit\\Storage\\FileStorageServiceTest::testGetLocalPathForProcessingPointsToWritableFile":0.002,"Tests\\Unit\\Storage\\FileStorageServiceTest::testCopyBetweenKeys":0.002,"Tests\\Unit\\Storage\\FileStorageServiceTest::testDownloadReturnsAttachmentResponse":0.005,"Tests\\Unit\\Storage\\FileStorageServiceTest::testGetTemporaryUrlForLocalUsesBaseUrl":0.003,"Tests\\Unit\\Storage\\LocalStorageDriverTest::testUploadFromUploadedFileStoresUnderLocalRoot":0.002,"Tests\\Unit\\Storage\\LocalStorageDriverTest::testUploadFromLocalPathCopiesFile":0.002,"Tests\\Unit\\Storage\\LocalStorageDriverTest::testPutWriteRawContents":0.002,"Tests\\Unit\\Storage\\LocalStorageDriverTest::testExistsReturnsFalseForMissingFile":0.001,"Tests\\Unit\\Storage\\LocalStorageDriverTest::testDeleteRemovesFile":0.001,"Tests\\Unit\\Storage\\LocalStorageDriverTest::testDownloadToTempReturnsExistingLocalPath":0.001,"Tests\\Unit\\Storage\\LocalStorageDriverTest::testCopyDuplicatesFile":0.002,"Tests\\Unit\\Storage\\LocalStorageDriverTest::testTemporaryUrlUsesBaseUrlForLocalDriver":0.002,"Tests\\Unit\\Storage\\LocalStorageDriverTest::testStreamDownloadReturnsResponseWithBody":0.002,"Tests\\Unit\\Storage\\PolicyStorageHelperTest::testPolicyFileTypeMapContainsExpectedTypes":0.001,"Tests\\Unit\\Storage\\PolicyStorageHelperTest::testPolicyMdFileNameConvertsPdfToMd":0.001,"Tests\\Unit\\Storage\\PolicyStorageHelperTest::testPolicyUploadPdfStoresFile":0.003,"Tests\\Unit\\Storage\\PolicyStorageHelperTest::testPolicyUploadReceiptStoresFile":0.003,"Tests\\Unit\\Storage\\PolicyStorageHelperTest::testPolicyUploadReturnsNullWhenNoFile":0.001,"Tests\\Unit\\Storage\\PolicyStorageHelperTest::testPolicyExistsByTypeReturnsFalseForInvalidType":0.001,"Tests\\Unit\\Storage\\PolicyStorageHelperTest::testPolicyDownloadByTypeAttachment":0.002,"Tests\\Unit\\Storage\\PolicyStorageHelperTest::testPolicyDownloadByTypeInline":0.002,"Tests\\Unit\\Storage\\PolicyStorageHelperTest::testPolicyDownloadByTypeThrowsForInvalidType":0.001,"Tests\\Unit\\Storage\\PolicyStorageHelperTest::testPolicyLocalPdfPathResolvesStoredPdf":0.002,"Tests\\Unit\\Storage\\PolicyStorageHelperTest::testPolicyMarkdownPutReadAndExists":0.002,"Tests\\Unit\\Storage\\S3StorageIntegrationTest::testS3DriverIsActiveFromEnv":0.097,"Tests\\Unit\\Storage\\S3StorageIntegrationTest::testS3PolicyPdfUploadExistsReadAndDelete":0.4,"Tests\\Unit\\Storage\\S3StorageIntegrationTest::testS3PolicyReceiptUploadAndTemporaryUrl":0.342,"Tests\\Unit\\Storage\\S3StorageIntegrationTest::testS3PolicyMarkdownPutAndRead":0.419,"Tests\\Unit\\Storage\\S3StorageIntegrationTest::testS3EndorsementOriginalAndCompletionUpload":0.534,"Tests\\Unit\\Storage\\S3StorageIntegrationTest::testLocalDriverScenarioStillWorksWhenEnvIsLocal":0.011}}
|
||||
{"version":2,"defects":{"Tests\\Unit\\Storage\\FileStorageServiceTest::testUploadModuleFileStoresPolicyPdf":8,"Tests\\Unit\\Storage\\FileStorageServiceTest::testDownloadReturnsAttachmentResponse":7,"Tests\\Unit\\Storage\\LocalStorageDriverTest::testUploadFromUploadedFileStoresUnderLocalRoot":8,"Tests\\Unit\\Storage\\LocalStorageDriverTest::testStreamDownloadReturnsResponseWithBody":7,"Tests\\Unit\\Storage\\PolicyStorageHelperTest::testPolicyUploadPdfStoresFile":8,"Tests\\Unit\\Storage\\PolicyStorageHelperTest::testPolicyUploadReceiptStoresFile":8,"Tests\\Unit\\Storage\\PolicyStorageHelperTest::testPolicyDownloadByTypeAttachment":7,"Tests\\Unit\\Storage\\PolicyStorageHelperTest::testPolicyDownloadByTypeInline":7,"Tests\\Unit\\Storage\\S3StorageIntegrationTest::testS3PolicyPdfUploadExistsReadAndDelete":1,"Tests\\Unit\\Storage\\S3StorageIntegrationTest::testS3PolicyReceiptUploadAndTemporaryUrl":1,"Tests\\Unit\\Storage\\S3StorageIntegrationTest::testS3EndorsementOriginalAndCompletionUpload":1,"Tests\\Unit\\Storage\\S3StorageIntegrationTest::testLocalDriverScenarioStillWorksWhenEnvIsLocal":1,"Tests\\Unit\\Storage\\S3StorageIntegrationTest::testS3DriverIsActiveFromEnv":1,"Tests\\Unit\\Storage\\S3StorageIntegrationTest::testS3PolicyMarkdownPutAndRead":1},"times":{"Tests\\Unit\\Storage\\FileStorageServiceTest::testResolveKeyWithSubFolder":0.004,"Tests\\Unit\\Storage\\FileStorageServiceTest::testResolveKeyWithoutSubFolder":0.001,"Tests\\Unit\\Storage\\FileStorageServiceTest::testUploadModuleFileStoresPolicyPdf":0.013,"Tests\\Unit\\Storage\\FileStorageServiceTest::testReadWriteAndDeleteByModule":0.002,"Tests\\Unit\\Storage\\FileStorageServiceTest::testGetLocalPathForProcessingPointsToWritableFile":0.002,"Tests\\Unit\\Storage\\FileStorageServiceTest::testCopyBetweenKeys":0.003,"Tests\\Unit\\Storage\\FileStorageServiceTest::testDownloadReturnsAttachmentResponse":0.005,"Tests\\Unit\\Storage\\FileStorageServiceTest::testGetTemporaryUrlForLocalUsesBaseUrl":0.004,"Tests\\Unit\\Storage\\LocalStorageDriverTest::testUploadFromUploadedFileStoresUnderLocalRoot":0.002,"Tests\\Unit\\Storage\\LocalStorageDriverTest::testUploadFromLocalPathCopiesFile":0.001,"Tests\\Unit\\Storage\\LocalStorageDriverTest::testPutWriteRawContents":0.001,"Tests\\Unit\\Storage\\LocalStorageDriverTest::testExistsReturnsFalseForMissingFile":0.001,"Tests\\Unit\\Storage\\LocalStorageDriverTest::testDeleteRemovesFile":0.001,"Tests\\Unit\\Storage\\LocalStorageDriverTest::testDownloadToTempReturnsExistingLocalPath":0.001,"Tests\\Unit\\Storage\\LocalStorageDriverTest::testCopyDuplicatesFile":0.002,"Tests\\Unit\\Storage\\LocalStorageDriverTest::testTemporaryUrlUsesBaseUrlForLocalDriver":0.003,"Tests\\Unit\\Storage\\LocalStorageDriverTest::testStreamDownloadReturnsResponseWithBody":0.002,"Tests\\Unit\\Storage\\PolicyStorageHelperTest::testPolicyFileTypeMapContainsExpectedTypes":0.001,"Tests\\Unit\\Storage\\PolicyStorageHelperTest::testPolicyMdFileNameConvertsPdfToMd":0.001,"Tests\\Unit\\Storage\\PolicyStorageHelperTest::testPolicyUploadPdfStoresFile":0.003,"Tests\\Unit\\Storage\\PolicyStorageHelperTest::testPolicyUploadReceiptStoresFile":0.003,"Tests\\Unit\\Storage\\PolicyStorageHelperTest::testPolicyUploadReturnsNullWhenNoFile":0.001,"Tests\\Unit\\Storage\\PolicyStorageHelperTest::testPolicyExistsByTypeReturnsFalseForInvalidType":0.001,"Tests\\Unit\\Storage\\PolicyStorageHelperTest::testPolicyDownloadByTypeAttachment":0.002,"Tests\\Unit\\Storage\\PolicyStorageHelperTest::testPolicyDownloadByTypeInline":0.003,"Tests\\Unit\\Storage\\PolicyStorageHelperTest::testPolicyDownloadByTypeThrowsForInvalidType":0.001,"Tests\\Unit\\Storage\\PolicyStorageHelperTest::testPolicyLocalPdfPathResolvesStoredPdf":0.002,"Tests\\Unit\\Storage\\PolicyStorageHelperTest::testPolicyMarkdownPutReadAndExists":0.002,"Tests\\Unit\\Storage\\S3StorageIntegrationTest::testS3DriverIsActiveFromEnv":0.097,"Tests\\Unit\\Storage\\S3StorageIntegrationTest::testS3PolicyPdfUploadExistsReadAndDelete":0.4,"Tests\\Unit\\Storage\\S3StorageIntegrationTest::testS3PolicyReceiptUploadAndTemporaryUrl":0.342,"Tests\\Unit\\Storage\\S3StorageIntegrationTest::testS3PolicyMarkdownPutAndRead":0.419,"Tests\\Unit\\Storage\\S3StorageIntegrationTest::testS3EndorsementOriginalAndCompletionUpload":0.534,"Tests\\Unit\\Storage\\S3StorageIntegrationTest::testLocalDriverScenarioStillWorksWhenEnvIsLocal":0.011,"Tests\\Unit\\Storage\\FileStorageServiceTest::testCleanupTempPathRemovesS3StyleTempFileOnly":0.003}}
|
||||
@ -1,49 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<testsuites>
|
||||
<testsuite name="CLI Arguments" tests="34" assertions="74" errors="0" failures="0" skipped="1" time="1.942890">
|
||||
<testsuite name="Tests\Unit\Storage\FileStorageServiceTest" file="/var/www/html/nhance_partner_be/tests/unit/Storage/FileStorageServiceTest.php" tests="8" assertions="15" errors="0" failures="0" skipped="0" time="0.051454">
|
||||
<testcase name="testResolveKeyWithSubFolder" file="/var/www/html/nhance_partner_be/tests/unit/Storage/FileStorageServiceTest.php" line="13" class="Tests\Unit\Storage\FileStorageServiceTest" classname="Tests.Unit.Storage.FileStorageServiceTest" assertions="1" time="0.016696"/>
|
||||
<testcase name="testResolveKeyWithoutSubFolder" file="/var/www/html/nhance_partner_be/tests/unit/Storage/FileStorageServiceTest.php" line="20" class="Tests\Unit\Storage\FileStorageServiceTest" classname="Tests.Unit.Storage.FileStorageServiceTest" assertions="1" time="0.002569"/>
|
||||
<testcase name="testUploadModuleFileStoresPolicyPdf" file="/var/www/html/nhance_partner_be/tests/unit/Storage/FileStorageServiceTest.php" line="27" class="Tests\Unit\Storage\FileStorageServiceTest" classname="Tests.Unit.Storage.FileStorageServiceTest" assertions="2" time="0.007923"/>
|
||||
<testcase name="testReadWriteAndDeleteByModule" file="/var/www/html/nhance_partner_be/tests/unit/Storage/FileStorageServiceTest.php" line="37" class="Tests\Unit\Storage\FileStorageServiceTest" classname="Tests.Unit.Storage.FileStorageServiceTest" assertions="4" time="0.005252"/>
|
||||
<testcase name="testGetLocalPathForProcessingPointsToWritableFile" file="/var/www/html/nhance_partner_be/tests/unit/Storage/FileStorageServiceTest.php" line="48" class="Tests\Unit\Storage\FileStorageServiceTest" classname="Tests.Unit.Storage.FileStorageServiceTest" assertions="2" time="0.003537"/>
|
||||
<testcase name="testCopyBetweenKeys" file="/var/www/html/nhance_partner_be/tests/unit/Storage/FileStorageServiceTest.php" line="59" class="Tests\Unit\Storage\FileStorageServiceTest" classname="Tests.Unit.Storage.FileStorageServiceTest" assertions="1" time="0.004232"/>
|
||||
<testcase name="testDownloadReturnsAttachmentResponse" file="/var/www/html/nhance_partner_be/tests/unit/Storage/FileStorageServiceTest.php" line="67" class="Tests\Unit\Storage\FileStorageServiceTest" classname="Tests.Unit.Storage.FileStorageServiceTest" assertions="3" time="0.006791"/>
|
||||
<testcase name="testGetTemporaryUrlForLocalUsesBaseUrl" file="/var/www/html/nhance_partner_be/tests/unit/Storage/FileStorageServiceTest.php" line="78" class="Tests\Unit\Storage\FileStorageServiceTest" classname="Tests.Unit.Storage.FileStorageServiceTest" assertions="1" time="0.004454"/>
|
||||
<testsuite name="CLI Arguments" tests="29" assertions="61" errors="0" failures="0" skipped="0" time="0.135343">
|
||||
<testsuite name="Tests\Unit\Storage\FileStorageServiceTest" file="/var/www/html/nhance_partner_be/tests/unit/Storage/FileStorageServiceTest.php" tests="9" assertions="21" errors="0" failures="0" skipped="0" time="0.061455">
|
||||
<testcase name="testResolveKeyWithSubFolder" file="/var/www/html/nhance_partner_be/tests/unit/Storage/FileStorageServiceTest.php" line="13" class="Tests\Unit\Storage\FileStorageServiceTest" classname="Tests.Unit.Storage.FileStorageServiceTest" assertions="1" time="0.014114"/>
|
||||
<testcase name="testResolveKeyWithoutSubFolder" file="/var/www/html/nhance_partner_be/tests/unit/Storage/FileStorageServiceTest.php" line="20" class="Tests\Unit\Storage\FileStorageServiceTest" classname="Tests.Unit.Storage.FileStorageServiceTest" assertions="1" time="0.002833"/>
|
||||
<testcase name="testUploadModuleFileStoresPolicyPdf" file="/var/www/html/nhance_partner_be/tests/unit/Storage/FileStorageServiceTest.php" line="27" class="Tests\Unit\Storage\FileStorageServiceTest" classname="Tests.Unit.Storage.FileStorageServiceTest" assertions="2" time="0.014719"/>
|
||||
<testcase name="testReadWriteAndDeleteByModule" file="/var/www/html/nhance_partner_be/tests/unit/Storage/FileStorageServiceTest.php" line="37" class="Tests\Unit\Storage\FileStorageServiceTest" classname="Tests.Unit.Storage.FileStorageServiceTest" assertions="4" time="0.004287"/>
|
||||
<testcase name="testGetLocalPathForProcessingPointsToWritableFile" file="/var/www/html/nhance_partner_be/tests/unit/Storage/FileStorageServiceTest.php" line="48" class="Tests\Unit\Storage\FileStorageServiceTest" classname="Tests.Unit.Storage.FileStorageServiceTest" assertions="2" time="0.003452"/>
|
||||
<testcase name="testCleanupTempPathRemovesS3StyleTempFileOnly" file="/var/www/html/nhance_partner_be/tests/unit/Storage/FileStorageServiceTest.php" line="59" class="Tests\Unit\Storage\FileStorageServiceTest" classname="Tests.Unit.Storage.FileStorageServiceTest" assertions="6" time="0.004347"/>
|
||||
<testcase name="testCopyBetweenKeys" file="/var/www/html/nhance_partner_be/tests/unit/Storage/FileStorageServiceTest.php" line="77" class="Tests\Unit\Storage\FileStorageServiceTest" classname="Tests.Unit.Storage.FileStorageServiceTest" assertions="1" time="0.005200"/>
|
||||
<testcase name="testDownloadReturnsAttachmentResponse" file="/var/www/html/nhance_partner_be/tests/unit/Storage/FileStorageServiceTest.php" line="85" class="Tests\Unit\Storage\FileStorageServiceTest" classname="Tests.Unit.Storage.FileStorageServiceTest" assertions="3" time="0.006838"/>
|
||||
<testcase name="testGetTemporaryUrlForLocalUsesBaseUrl" file="/var/www/html/nhance_partner_be/tests/unit/Storage/FileStorageServiceTest.php" line="96" class="Tests\Unit\Storage\FileStorageServiceTest" classname="Tests.Unit.Storage.FileStorageServiceTest" assertions="1" time="0.005665"/>
|
||||
</testsuite>
|
||||
<testsuite name="Tests\Unit\Storage\LocalStorageDriverTest" file="/var/www/html/nhance_partner_be/tests/unit/Storage/LocalStorageDriverTest.php" tests="9" assertions="16" errors="0" failures="0" skipped="0" time="0.033338">
|
||||
<testcase name="testUploadFromUploadedFileStoresUnderLocalRoot" file="/var/www/html/nhance_partner_be/tests/unit/Storage/LocalStorageDriverTest.php" line="101" class="Tests\Unit\Storage\LocalStorageDriverTest" classname="Tests.Unit.Storage.LocalStorageDriverTest" assertions="2" time="0.003572"/>
|
||||
<testcase name="testUploadFromLocalPathCopiesFile" file="/var/www/html/nhance_partner_be/tests/unit/Storage/LocalStorageDriverTest.php" line="112" class="Tests\Unit\Storage\LocalStorageDriverTest" classname="Tests.Unit.Storage.LocalStorageDriverTest" assertions="2" time="0.003582"/>
|
||||
<testcase name="testPutWriteRawContents" file="/var/www/html/nhance_partner_be/tests/unit/Storage/LocalStorageDriverTest.php" line="124" class="Tests\Unit\Storage\LocalStorageDriverTest" classname="Tests.Unit.Storage.LocalStorageDriverTest" assertions="2" time="0.004164"/>
|
||||
<testcase name="testExistsReturnsFalseForMissingFile" file="/var/www/html/nhance_partner_be/tests/unit/Storage/LocalStorageDriverTest.php" line="134" class="Tests\Unit\Storage\LocalStorageDriverTest" classname="Tests.Unit.Storage.LocalStorageDriverTest" assertions="1" time="0.003338"/>
|
||||
<testcase name="testDeleteRemovesFile" file="/var/www/html/nhance_partner_be/tests/unit/Storage/LocalStorageDriverTest.php" line="139" class="Tests\Unit\Storage\LocalStorageDriverTest" classname="Tests.Unit.Storage.LocalStorageDriverTest" assertions="2" time="0.003199"/>
|
||||
<testcase name="testDownloadToTempReturnsExistingLocalPath" file="/var/www/html/nhance_partner_be/tests/unit/Storage/LocalStorageDriverTest.php" line="148" class="Tests\Unit\Storage\LocalStorageDriverTest" classname="Tests.Unit.Storage.LocalStorageDriverTest" assertions="1" time="0.003496"/>
|
||||
<testcase name="testCopyDuplicatesFile" file="/var/www/html/nhance_partner_be/tests/unit/Storage/LocalStorageDriverTest.php" line="158" class="Tests\Unit\Storage\LocalStorageDriverTest" classname="Tests.Unit.Storage.LocalStorageDriverTest" assertions="2" time="0.004179"/>
|
||||
<testcase name="testTemporaryUrlUsesBaseUrlForLocalDriver" file="/var/www/html/nhance_partner_be/tests/unit/Storage/LocalStorageDriverTest.php" line="168" class="Tests\Unit\Storage\LocalStorageDriverTest" classname="Tests.Unit.Storage.LocalStorageDriverTest" assertions="1" time="0.004374"/>
|
||||
<testcase name="testStreamDownloadReturnsResponseWithBody" file="/var/www/html/nhance_partner_be/tests/unit/Storage/LocalStorageDriverTest.php" line="178" class="Tests\Unit\Storage\LocalStorageDriverTest" classname="Tests.Unit.Storage.LocalStorageDriverTest" assertions="3" time="0.003432"/>
|
||||
<testsuite name="Tests\Unit\Storage\LocalStorageDriverTest" file="/var/www/html/nhance_partner_be/tests/unit/Storage/LocalStorageDriverTest.php" tests="9" assertions="16" errors="0" failures="0" skipped="0" time="0.034179">
|
||||
<testcase name="testUploadFromUploadedFileStoresUnderLocalRoot" file="/var/www/html/nhance_partner_be/tests/unit/Storage/LocalStorageDriverTest.php" line="101" class="Tests\Unit\Storage\LocalStorageDriverTest" classname="Tests.Unit.Storage.LocalStorageDriverTest" assertions="2" time="0.003866"/>
|
||||
<testcase name="testUploadFromLocalPathCopiesFile" file="/var/www/html/nhance_partner_be/tests/unit/Storage/LocalStorageDriverTest.php" line="112" class="Tests\Unit\Storage\LocalStorageDriverTest" classname="Tests.Unit.Storage.LocalStorageDriverTest" assertions="2" time="0.003424"/>
|
||||
<testcase name="testPutWriteRawContents" file="/var/www/html/nhance_partner_be/tests/unit/Storage/LocalStorageDriverTest.php" line="124" class="Tests\Unit\Storage\LocalStorageDriverTest" classname="Tests.Unit.Storage.LocalStorageDriverTest" assertions="2" time="0.003003"/>
|
||||
<testcase name="testExistsReturnsFalseForMissingFile" file="/var/www/html/nhance_partner_be/tests/unit/Storage/LocalStorageDriverTest.php" line="134" class="Tests\Unit\Storage\LocalStorageDriverTest" classname="Tests.Unit.Storage.LocalStorageDriverTest" assertions="1" time="0.002957"/>
|
||||
<testcase name="testDeleteRemovesFile" file="/var/www/html/nhance_partner_be/tests/unit/Storage/LocalStorageDriverTest.php" line="139" class="Tests\Unit\Storage\LocalStorageDriverTest" classname="Tests.Unit.Storage.LocalStorageDriverTest" assertions="2" time="0.004788"/>
|
||||
<testcase name="testDownloadToTempReturnsExistingLocalPath" file="/var/www/html/nhance_partner_be/tests/unit/Storage/LocalStorageDriverTest.php" line="148" class="Tests\Unit\Storage\LocalStorageDriverTest" classname="Tests.Unit.Storage.LocalStorageDriverTest" assertions="1" time="0.003267"/>
|
||||
<testcase name="testCopyDuplicatesFile" file="/var/www/html/nhance_partner_be/tests/unit/Storage/LocalStorageDriverTest.php" line="158" class="Tests\Unit\Storage\LocalStorageDriverTest" classname="Tests.Unit.Storage.LocalStorageDriverTest" assertions="2" time="0.003318"/>
|
||||
<testcase name="testTemporaryUrlUsesBaseUrlForLocalDriver" file="/var/www/html/nhance_partner_be/tests/unit/Storage/LocalStorageDriverTest.php" line="168" class="Tests\Unit\Storage\LocalStorageDriverTest" classname="Tests.Unit.Storage.LocalStorageDriverTest" assertions="1" time="0.004557"/>
|
||||
<testcase name="testStreamDownloadReturnsResponseWithBody" file="/var/www/html/nhance_partner_be/tests/unit/Storage/LocalStorageDriverTest.php" line="178" class="Tests\Unit\Storage\LocalStorageDriverTest" classname="Tests.Unit.Storage.LocalStorageDriverTest" assertions="3" time="0.004998"/>
|
||||
</testsuite>
|
||||
<testsuite name="Tests\Unit\Storage\PolicyStorageHelperTest" file="/var/www/html/nhance_partner_be/tests/unit/Storage/PolicyStorageHelperTest.php" tests="11" assertions="24" errors="0" failures="0" skipped="0" time="0.040864">
|
||||
<testcase name="testPolicyFileTypeMapContainsExpectedTypes" file="/var/www/html/nhance_partner_be/tests/unit/Storage/PolicyStorageHelperTest.php" line="14" class="Tests\Unit\Storage\PolicyStorageHelperTest" classname="Tests.Unit.Storage.PolicyStorageHelperTest" assertions="4" time="0.003233"/>
|
||||
<testcase name="testPolicyMdFileNameConvertsPdfToMd" file="/var/www/html/nhance_partner_be/tests/unit/Storage/PolicyStorageHelperTest.php" line="24" class="Tests\Unit\Storage\PolicyStorageHelperTest" classname="Tests.Unit.Storage.PolicyStorageHelperTest" assertions="2" time="0.002691"/>
|
||||
<testcase name="testPolicyUploadPdfStoresFile" file="/var/www/html/nhance_partner_be/tests/unit/Storage/PolicyStorageHelperTest.php" line="30" class="Tests\Unit\Storage\PolicyStorageHelperTest" classname="Tests.Unit.Storage.PolicyStorageHelperTest" assertions="2" time="0.005686"/>
|
||||
<testcase name="testPolicyUploadReceiptStoresFile" file="/var/www/html/nhance_partner_be/tests/unit/Storage/PolicyStorageHelperTest.php" line="40" class="Tests\Unit\Storage\PolicyStorageHelperTest" classname="Tests.Unit.Storage.PolicyStorageHelperTest" assertions="2" time="0.004434"/>
|
||||
<testcase name="testPolicyUploadReturnsNullWhenNoFile" file="/var/www/html/nhance_partner_be/tests/unit/Storage/PolicyStorageHelperTest.php" line="50" class="Tests\Unit\Storage\PolicyStorageHelperTest" classname="Tests.Unit.Storage.PolicyStorageHelperTest" assertions="2" time="0.002654"/>
|
||||
<testcase name="testPolicyExistsByTypeReturnsFalseForInvalidType" file="/var/www/html/nhance_partner_be/tests/unit/Storage/PolicyStorageHelperTest.php" line="56" class="Tests\Unit\Storage\PolicyStorageHelperTest" classname="Tests.Unit.Storage.PolicyStorageHelperTest" assertions="1" time="0.002477"/>
|
||||
<testcase name="testPolicyDownloadByTypeAttachment" file="/var/www/html/nhance_partner_be/tests/unit/Storage/PolicyStorageHelperTest.php" line="61" class="Tests\Unit\Storage\PolicyStorageHelperTest" classname="Tests.Unit.Storage.PolicyStorageHelperTest" assertions="3" time="0.004665"/>
|
||||
<testcase name="testPolicyDownloadByTypeInline" file="/var/www/html/nhance_partner_be/tests/unit/Storage/PolicyStorageHelperTest.php" line="72" class="Tests\Unit\Storage\PolicyStorageHelperTest" classname="Tests.Unit.Storage.PolicyStorageHelperTest" assertions="3" time="0.003591"/>
|
||||
<testcase name="testPolicyDownloadByTypeThrowsForInvalidType" file="/var/www/html/nhance_partner_be/tests/unit/Storage/PolicyStorageHelperTest.php" line="83" class="Tests\Unit\Storage\PolicyStorageHelperTest" classname="Tests.Unit.Storage.PolicyStorageHelperTest" assertions="1" time="0.003291"/>
|
||||
<testcase name="testPolicyLocalPdfPathResolvesStoredPdf" file="/var/www/html/nhance_partner_be/tests/unit/Storage/PolicyStorageHelperTest.php" line="90" class="Tests\Unit\Storage\PolicyStorageHelperTest" classname="Tests.Unit.Storage.PolicyStorageHelperTest" assertions="2" time="0.003791"/>
|
||||
<testcase name="testPolicyMarkdownPutReadAndExists" file="/var/www/html/nhance_partner_be/tests/unit/Storage/PolicyStorageHelperTest.php" line="100" class="Tests\Unit\Storage\PolicyStorageHelperTest" classname="Tests.Unit.Storage.PolicyStorageHelperTest" assertions="2" time="0.004351"/>
|
||||
</testsuite>
|
||||
<testsuite name="Tests\Unit\Storage\S3StorageIntegrationTest" file="/var/www/html/nhance_partner_be/tests/unit/Storage/S3StorageIntegrationTest.php" tests="6" assertions="19" errors="0" failures="0" skipped="1" time="1.817235">
|
||||
<testcase name="testS3DriverIsActiveFromEnv" file="/var/www/html/nhance_partner_be/tests/unit/Storage/S3StorageIntegrationTest.php" line="39" class="Tests\Unit\Storage\S3StorageIntegrationTest" classname="Tests.Unit.Storage.S3StorageIntegrationTest" assertions="1" time="0.099073"/>
|
||||
<testcase name="testS3PolicyPdfUploadExistsReadAndDelete" file="/var/www/html/nhance_partner_be/tests/unit/Storage/S3StorageIntegrationTest.php" line="46" class="Tests\Unit\Storage\S3StorageIntegrationTest" classname="Tests.Unit.Storage.S3StorageIntegrationTest" assertions="7" time="0.401832"/>
|
||||
<testcase name="testS3PolicyReceiptUploadAndTemporaryUrl" file="/var/www/html/nhance_partner_be/tests/unit/Storage/S3StorageIntegrationTest.php" line="69" class="Tests\Unit\Storage\S3StorageIntegrationTest" classname="Tests.Unit.Storage.S3StorageIntegrationTest" assertions="4" time="0.344284"/>
|
||||
<testcase name="testS3PolicyMarkdownPutAndRead" file="/var/www/html/nhance_partner_be/tests/unit/Storage/S3StorageIntegrationTest.php" line="87" class="Tests\Unit\Storage\S3StorageIntegrationTest" classname="Tests.Unit.Storage.S3StorageIntegrationTest" assertions="2" time="0.422262"/>
|
||||
<testcase name="testS3EndorsementOriginalAndCompletionUpload" file="/var/www/html/nhance_partner_be/tests/unit/Storage/S3StorageIntegrationTest.php" line="101" class="Tests\Unit\Storage\S3StorageIntegrationTest" classname="Tests.Unit.Storage.S3StorageIntegrationTest" assertions="5" time="0.536949"/>
|
||||
<testcase name="testLocalDriverScenarioStillWorksWhenEnvIsLocal" file="/var/www/html/nhance_partner_be/tests/unit/Storage/S3StorageIntegrationTest.php" line="121" class="Tests\Unit\Storage\S3StorageIntegrationTest" classname="Tests.Unit.Storage.S3StorageIntegrationTest" assertions="0" time="0.012836">
|
||||
<skipped/>
|
||||
</testcase>
|
||||
<testsuite name="Tests\Unit\Storage\PolicyStorageHelperTest" file="/var/www/html/nhance_partner_be/tests/unit/Storage/PolicyStorageHelperTest.php" tests="11" assertions="24" errors="0" failures="0" skipped="0" time="0.039708">
|
||||
<testcase name="testPolicyFileTypeMapContainsExpectedTypes" file="/var/www/html/nhance_partner_be/tests/unit/Storage/PolicyStorageHelperTest.php" line="14" class="Tests\Unit\Storage\PolicyStorageHelperTest" classname="Tests.Unit.Storage.PolicyStorageHelperTest" assertions="4" time="0.002677"/>
|
||||
<testcase name="testPolicyMdFileNameConvertsPdfToMd" file="/var/www/html/nhance_partner_be/tests/unit/Storage/PolicyStorageHelperTest.php" line="24" class="Tests\Unit\Storage\PolicyStorageHelperTest" classname="Tests.Unit.Storage.PolicyStorageHelperTest" assertions="2" time="0.002543"/>
|
||||
<testcase name="testPolicyUploadPdfStoresFile" file="/var/www/html/nhance_partner_be/tests/unit/Storage/PolicyStorageHelperTest.php" line="30" class="Tests\Unit\Storage\PolicyStorageHelperTest" classname="Tests.Unit.Storage.PolicyStorageHelperTest" assertions="2" time="0.005102"/>
|
||||
<testcase name="testPolicyUploadReceiptStoresFile" file="/var/www/html/nhance_partner_be/tests/unit/Storage/PolicyStorageHelperTest.php" line="40" class="Tests\Unit\Storage\PolicyStorageHelperTest" classname="Tests.Unit.Storage.PolicyStorageHelperTest" assertions="2" time="0.006170"/>
|
||||
<testcase name="testPolicyUploadReturnsNullWhenNoFile" file="/var/www/html/nhance_partner_be/tests/unit/Storage/PolicyStorageHelperTest.php" line="50" class="Tests\Unit\Storage\PolicyStorageHelperTest" classname="Tests.Unit.Storage.PolicyStorageHelperTest" assertions="2" time="0.002235"/>
|
||||
<testcase name="testPolicyExistsByTypeReturnsFalseForInvalidType" file="/var/www/html/nhance_partner_be/tests/unit/Storage/PolicyStorageHelperTest.php" line="56" class="Tests\Unit\Storage\PolicyStorageHelperTest" classname="Tests.Unit.Storage.PolicyStorageHelperTest" assertions="1" time="0.002131"/>
|
||||
<testcase name="testPolicyDownloadByTypeAttachment" file="/var/www/html/nhance_partner_be/tests/unit/Storage/PolicyStorageHelperTest.php" line="61" class="Tests\Unit\Storage\PolicyStorageHelperTest" classname="Tests.Unit.Storage.PolicyStorageHelperTest" assertions="3" time="0.003352"/>
|
||||
<testcase name="testPolicyDownloadByTypeInline" file="/var/www/html/nhance_partner_be/tests/unit/Storage/PolicyStorageHelperTest.php" line="72" class="Tests\Unit\Storage\PolicyStorageHelperTest" classname="Tests.Unit.Storage.PolicyStorageHelperTest" assertions="3" time="0.004934"/>
|
||||
<testcase name="testPolicyDownloadByTypeThrowsForInvalidType" file="/var/www/html/nhance_partner_be/tests/unit/Storage/PolicyStorageHelperTest.php" line="83" class="Tests\Unit\Storage\PolicyStorageHelperTest" classname="Tests.Unit.Storage.PolicyStorageHelperTest" assertions="1" time="0.003290"/>
|
||||
<testcase name="testPolicyLocalPdfPathResolvesStoredPdf" file="/var/www/html/nhance_partner_be/tests/unit/Storage/PolicyStorageHelperTest.php" line="90" class="Tests\Unit\Storage\PolicyStorageHelperTest" classname="Tests.Unit.Storage.PolicyStorageHelperTest" assertions="2" time="0.003276"/>
|
||||
<testcase name="testPolicyMarkdownPutReadAndExists" file="/var/www/html/nhance_partner_be/tests/unit/Storage/PolicyStorageHelperTest.php" line="100" class="Tests\Unit\Storage\PolicyStorageHelperTest" classname="Tests.Unit.Storage.PolicyStorageHelperTest" assertions="2" time="0.003998"/>
|
||||
</testsuite>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
@ -58,6 +58,7 @@
|
||||
<li class="success">Upload module file stores policy pdf</li>
|
||||
<li class="success">Read write and delete by module</li>
|
||||
<li class="success">Get local path for processing points to writable file</li>
|
||||
<li class="success">Cleanup temp path removes s 3 style temp file only</li>
|
||||
<li class="success">Copy between keys</li>
|
||||
<li class="success">Download returns attachment response</li>
|
||||
<li class="success">Get temporary url for local uses base url</li>
|
||||
@ -88,14 +89,5 @@
|
||||
<li class="success">Policy local pdf path resolves stored pdf</li>
|
||||
<li class="success">Policy markdown put read and exists</li>
|
||||
</ul>
|
||||
<h2>S3Storage Integration (Tests\Unit\Storage\S3StorageIntegration)</h2>
|
||||
<ul>
|
||||
<li class="success">S 3 driver is active from env</li>
|
||||
<li class="success">S 3 policy pdf upload exists read and delete</li>
|
||||
<li class="success">S 3 policy receipt upload and temporary url</li>
|
||||
<li class="success">S 3 policy markdown put and read</li>
|
||||
<li class="success">S 3 endorsement original and completion upload</li>
|
||||
<li class="defect">Local driver scenario still works when env is local</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
@ -4,6 +4,7 @@ File Storage Service (Tests\Unit\Storage\FileStorageService)
|
||||
[x] Upload module file stores policy pdf
|
||||
[x] Read write and delete by module
|
||||
[x] Get local path for processing points to writable file
|
||||
[x] Cleanup temp path removes s 3 style temp file only
|
||||
[x] Copy between keys
|
||||
[x] Download returns attachment response
|
||||
[x] Get temporary url for local uses base url
|
||||
@ -32,11 +33,3 @@ Policy Storage Helper (Tests\Unit\Storage\PolicyStorageHelper)
|
||||
[x] Policy local pdf path resolves stored pdf
|
||||
[x] Policy markdown put read and exists
|
||||
|
||||
S3Storage Integration (Tests\Unit\Storage\S3StorageIntegration)
|
||||
[x] S 3 driver is active from env
|
||||
[x] S 3 policy pdf upload exists read and delete
|
||||
[x] S 3 policy receipt upload and temporary url
|
||||
[x] S 3 policy markdown put and read
|
||||
[x] S 3 endorsement original and completion upload
|
||||
[ ] Local driver scenario still works when env is local
|
||||
|
||||
|
||||
@ -56,6 +56,24 @@ final class FileStorageServiceTest extends StorageTestCase
|
||||
$this->assertSame('local', file_get_contents($path));
|
||||
}
|
||||
|
||||
public function testCleanupTempPathRemovesS3StyleTempFileOnly(): void
|
||||
{
|
||||
$tempPath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . uniqid('s3_', true) . '_policy.pdf';
|
||||
file_put_contents($tempPath, 'temp-pdf');
|
||||
|
||||
$this->assertTrue(storage()->isS3TempProcessingPath($tempPath));
|
||||
$this->assertTrue(storage_cleanup_temp($tempPath));
|
||||
$this->assertFileDoesNotExist($tempPath);
|
||||
|
||||
$fileName = 'keep-local.pdf';
|
||||
storage()->put(storage()->resolveKey('policy', 'policy_pdf', $fileName), 'keep');
|
||||
$localPath = storage()->getLocalPathForProcessing('policy', 'policy_pdf', $fileName);
|
||||
|
||||
$this->assertFalse(storage()->isS3TempProcessingPath($localPath));
|
||||
$this->assertFalse(storage_cleanup_temp($localPath));
|
||||
$this->assertFileExists($localPath);
|
||||
}
|
||||
|
||||
public function testCopyBetweenKeys(): void
|
||||
{
|
||||
storage()->put(storage()->resolveKey('policy', 'policy_pdf', 'from.pdf'), 'from');
|
||||
|
||||
@ -60,6 +60,8 @@ final class S3StorageIntegrationTest extends StorageTestCase
|
||||
|
||||
$tempPath = policy_local_pdf_path($stored);
|
||||
$this->assertFileExists($tempPath);
|
||||
storage_cleanup_temp($tempPath);
|
||||
$this->assertFileDoesNotExist($tempPath);
|
||||
|
||||
$this->assertTrue(storage_delete('policy', 'policy_pdf', $stored));
|
||||
$this->uploadedPolicyKey = null;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user