- Rename all controllers from X.php to XController.php format - Add new RefTxtModel for text-based reference ranges - Rename group_dialog.php to grp_dialog.php and remove title_dialog.php - Add comprehensive test suite for v2/master/TestDef module - Update Routes.php to reflect controller renames - Remove obsolete data files (clqms_v2.sql, lab.dbml)
376 lines
11 KiB
PHP
376 lines
11 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature\v2\master\TestDef;
|
|
|
|
use Tests\Support\v2\MasterTestCase;
|
|
|
|
/**
|
|
* Feature tests for v2 Test Definition API endpoints
|
|
*
|
|
* Tests CRUD operations for TEST, PARAM, GROUP, and CALC types
|
|
*/
|
|
class TestDefSiteTest extends MasterTestCase
|
|
{
|
|
protected string $endpoint = 'v2/master/tests';
|
|
|
|
/**
|
|
* Test index endpoint returns list of tests
|
|
*/
|
|
public function testIndexReturnsTestList(): void
|
|
{
|
|
$result = $this->get($this->endpoint);
|
|
$result->assertStatus(200);
|
|
|
|
$body = json_decode($result->response()->getBody(), true);
|
|
$this->assertArrayHasKey('status', $body);
|
|
$this->assertArrayHasKey('data', $body);
|
|
$this->assertArrayHasKey('message', $body);
|
|
}
|
|
|
|
/**
|
|
* Test index with SiteID filter
|
|
*/
|
|
public function testIndexWithSiteFilter(): void
|
|
{
|
|
$result = $this->get($this->endpoint . '?SiteID=1');
|
|
$result->assertStatus(200);
|
|
|
|
$body = json_decode($result->response()->getBody(), true);
|
|
$this->assertEquals('success', $body['status']);
|
|
}
|
|
|
|
/**
|
|
* Test index with TestType filter
|
|
*/
|
|
public function testIndexWithTestTypeFilter(): void
|
|
{
|
|
// Filter by TEST type
|
|
$result = $this->get($this->endpoint . '?TestType=TEST');
|
|
$result->assertStatus(200);
|
|
|
|
$body = json_decode($result->response()->getBody(), true);
|
|
$this->assertEquals('success', $body['status']);
|
|
}
|
|
|
|
/**
|
|
* Test index with Visibility filter
|
|
*/
|
|
public function testIndexWithVisibilityFilter(): void
|
|
{
|
|
$result = $this->get($this->endpoint . '?VisibleScr=1&VisibleRpt=1');
|
|
$result->assertStatus(200);
|
|
|
|
$body = json_decode($result->response()->getBody(), true);
|
|
$this->assertEquals('success', $body['status']);
|
|
}
|
|
|
|
/**
|
|
* Test index with keyword search
|
|
*/
|
|
public function testIndexWithKeywordSearch(): void
|
|
{
|
|
$result = $this->get($this->endpoint . '?TestSiteName=hemoglobin');
|
|
$result->assertStatus(200);
|
|
|
|
$body = json_decode($result->response()->getBody(), true);
|
|
$this->assertEquals('success', $body['status']);
|
|
}
|
|
|
|
/**
|
|
* Test show endpoint returns single test
|
|
*/
|
|
public function testShowReturnsSingleTest(): void
|
|
{
|
|
// First get the list to find a valid ID
|
|
$indexResult = $this->get($this->endpoint);
|
|
$indexBody = json_decode($indexResult->response()->getBody(), true);
|
|
|
|
if (isset($indexBody['data']) && is_array($indexBody['data']) && !empty($indexBody['data'])) {
|
|
$firstItem = $indexBody['data'][0];
|
|
$testSiteID = $firstItem['TestSiteID'] ?? null;
|
|
|
|
if ($testSiteID) {
|
|
$showResult = $this->get($this->endpoint . '/' . $testSiteID);
|
|
$showResult->assertStatus(200);
|
|
|
|
$body = json_decode($showResult->response()->getBody(), true);
|
|
$this->assertArrayHasKey('data', $body);
|
|
$this->assertEquals('success', $body['status']);
|
|
|
|
// Check that related details are loaded based on TestType
|
|
if ($body['data'] !== null) {
|
|
$typeCode = $body['data']['TypeCode'] ?? '';
|
|
if ($typeCode === 'CALC') {
|
|
$this->assertArrayHasKey('testdefcal', $body['data']);
|
|
} elseif ($typeCode === 'GROUP') {
|
|
$this->assertArrayHasKey('testdefgrp', $body['data']);
|
|
} elseif (in_array($typeCode, ['TEST', 'PARAM'])) {
|
|
$this->assertArrayHasKey('testdeftech', $body['data']);
|
|
}
|
|
// All types should have testmap
|
|
$this->assertArrayHasKey('testmap', $body['data']);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Test show with non-existent ID returns null data
|
|
*/
|
|
public function testShowWithInvalidIDReturnsNull(): void
|
|
{
|
|
$result = $this->get($this->endpoint . '/9999999');
|
|
$result->assertStatus(200);
|
|
|
|
$body = json_decode($result->response()->getBody(), true);
|
|
$this->assertArrayHasKey('data', $body);
|
|
$this->assertNull($body['data']);
|
|
}
|
|
|
|
/**
|
|
* Test create new TEST type test definition
|
|
*/
|
|
public function testCreateTestTypeTest(): void
|
|
{
|
|
$testData = $this->createTestData();
|
|
|
|
$result = $this->post($this->endpoint, ['body' => json_encode($testData)]);
|
|
|
|
$status = $result->response()->getStatusCode();
|
|
// Expect 201 (created) or 400 (validation error) or 500 (server error)
|
|
$this->assertTrue(
|
|
in_array($status, [201, 400, 500]),
|
|
"Expected 201, 400, or 500, got $status"
|
|
);
|
|
|
|
if ($status === 201) {
|
|
$body = json_decode($result->response()->getBody(), true);
|
|
$this->assertEquals('created', $body['status']);
|
|
$this->assertArrayHasKey('TestSiteId', $body['data']);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Test create new PARAM type test definition
|
|
*/
|
|
public function testCreateParamTypeTest(): void
|
|
{
|
|
$paramData = $this->createParamData();
|
|
|
|
$result = $this->post($this->endpoint, ['body' => json_encode($paramData)]);
|
|
|
|
$status = $result->response()->getStatusCode();
|
|
$this->assertTrue(
|
|
in_array($status, [201, 400, 500]),
|
|
"Expected 201, 400, or 500, got $status"
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Test create new GROUP type test definition
|
|
*/
|
|
public function testCreateGroupTypeTest(): void
|
|
{
|
|
// First create some member tests
|
|
$memberIds = $this->getExistingTestIds();
|
|
|
|
$groupData = $this->createGroupData($memberIds);
|
|
|
|
$result = $this->post($this->endpoint, ['body' => json_encode($groupData)]);
|
|
|
|
$status = $result->response()->getStatusCode();
|
|
$this->assertTrue(
|
|
in_array($status, [201, 400, 500]),
|
|
"Expected 201, 400, or 500, got $status"
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Test create new CALC type test definition
|
|
*/
|
|
public function testCreateCalcTypeTest(): void
|
|
{
|
|
$calcData = $this->createCalcData();
|
|
|
|
$result = $this->post($this->endpoint, ['body' => json_encode($calcData)]);
|
|
|
|
$status = $result->response()->getStatusCode();
|
|
$this->assertTrue(
|
|
in_array($status, [201, 400, 500]),
|
|
"Expected 201, 400, or 500, got $status"
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Test update existing test
|
|
*/
|
|
public function testUpdateTest(): void
|
|
{
|
|
$indexResult = $this->get($this->endpoint);
|
|
$indexBody = json_decode($indexResult->response()->getBody(), true);
|
|
|
|
if (isset($indexBody['data']) && is_array($indexBody['data']) && !empty($indexBody['data'])) {
|
|
$firstItem = $indexBody['data'][0];
|
|
$testSiteID = $firstItem['TestSiteID'] ?? null;
|
|
|
|
if ($testSiteID) {
|
|
$updateData = [
|
|
'TestSiteName' => 'Updated Test Name ' . time(),
|
|
'Description' => 'Updated description'
|
|
];
|
|
|
|
$result = $this->put($this->endpoint . '/' . $testSiteID, ['body' => json_encode($updateData)]);
|
|
$status = $result->response()->getStatusCode();
|
|
$this->assertTrue(
|
|
in_array($status, [200, 404, 500]),
|
|
"Expected 200, 404, or 500, got $status"
|
|
);
|
|
|
|
if ($status === 200) {
|
|
$body = json_decode($result->response()->getBody(), true);
|
|
$this->assertEquals('success', $body['status']);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Test soft delete (disable) test
|
|
*/
|
|
public function testDeleteTest(): void
|
|
{
|
|
// Create a test first to delete
|
|
$testData = $this->createTestData();
|
|
$testData['TestSiteCode'] = 'DEL' . substr(time(), -4);
|
|
|
|
$createResult = $this->post($this->endpoint, ['body' => json_encode($testData)]);
|
|
$createStatus = $createResult->response()->getStatusCode();
|
|
|
|
if ($createStatus === 201) {
|
|
$createBody = json_decode($createResult->response()->getBody(), true);
|
|
$testSiteID = $createBody['data']['TestSiteId'] ?? null;
|
|
|
|
if ($testSiteID) {
|
|
$deleteResult = $this->delete($this->endpoint . '/' . $testSiteID);
|
|
$deleteStatus = $deleteResult->response()->getStatusCode();
|
|
|
|
$this->assertTrue(
|
|
in_array($deleteStatus, [200, 404, 500]),
|
|
"Expected 200, 404, or 500, got $deleteStatus"
|
|
);
|
|
|
|
if ($deleteStatus === 200) {
|
|
$deleteBody = json_decode($deleteResult->response()->getBody(), true);
|
|
$this->assertEquals('success', $deleteBody['status']);
|
|
$this->assertArrayHasKey('EndDate', $deleteBody['data']);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Test validation - missing required fields
|
|
*/
|
|
public function testCreateValidationRequiredFields(): void
|
|
{
|
|
$invalidData = [
|
|
'TestSiteName' => 'Test without required fields'
|
|
];
|
|
|
|
$result = $this->post($this->endpoint, ['body' => json_encode($invalidData)]);
|
|
$result->assertStatus(400);
|
|
}
|
|
|
|
/**
|
|
* Test that TestSiteCode is max 6 characters
|
|
*/
|
|
public function testTestSiteCodeLength(): void
|
|
{
|
|
$invalidData = [
|
|
'SiteID' => 1,
|
|
'TestSiteCode' => 'HB123456', // 8 characters - invalid
|
|
'TestSiteName' => 'Test with too long code',
|
|
'TestType' => $this::TEST_TYPE_TEST
|
|
];
|
|
|
|
$result = $this->post($this->endpoint, ['body' => json_encode($invalidData)]);
|
|
$result->assertStatus(400);
|
|
}
|
|
|
|
/**
|
|
* Test that TestSiteCode is at least 3 characters
|
|
*/
|
|
public function testTestSiteCodeMinLength(): void
|
|
{
|
|
$invalidData = [
|
|
'SiteID' => 1,
|
|
'TestSiteCode' => 'HB', // 2 characters - invalid
|
|
'TestSiteName' => 'Test with too short code',
|
|
'TestType' => $this::TEST_TYPE_TEST
|
|
];
|
|
|
|
$result = $this->post($this->endpoint, ['body' => json_encode($invalidData)]);
|
|
$result->assertStatus(400);
|
|
}
|
|
|
|
/**
|
|
* Test that duplicate TestSiteCode is rejected
|
|
*/
|
|
public function testDuplicateTestSiteCode(): void
|
|
{
|
|
// First create a test
|
|
$testData = $this->createTestData();
|
|
$testData['TestSiteCode'] = 'DUP' . substr(time(), -3);
|
|
|
|
$this->post($this->endpoint, ['body' => json_encode($testData)]);
|
|
|
|
// Try to create another test with the same code
|
|
$duplicateData = $testData;
|
|
$duplicateData['TestSiteName'] = 'Different Name';
|
|
|
|
$result = $this->post($this->endpoint, ['body' => json_encode($duplicateData)]);
|
|
|
|
// Should fail with 400 or 500
|
|
$status = $result->response()->getStatusCode();
|
|
$this->assertTrue(
|
|
in_array($status, [400, 500]),
|
|
"Expected 400 or 500 for duplicate, got $status"
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Test filtering by multiple parameters
|
|
*/
|
|
public function testIndexWithMultipleFilters(): void
|
|
{
|
|
$result = $this->get($this->endpoint . '?SiteID=1&TestType=TEST&VisibleScr=1');
|
|
$result->assertStatus(200);
|
|
|
|
$body = json_decode($result->response()->getBody(), true);
|
|
$this->assertEquals('success', $body['status']);
|
|
}
|
|
|
|
/**
|
|
* Helper method to get existing test IDs for group members
|
|
*/
|
|
private function getExistingTestIds(): array
|
|
{
|
|
$indexResult = $this->get($this->endpoint);
|
|
$indexBody = json_decode($indexResult->response()->getBody(), true);
|
|
|
|
$ids = [];
|
|
if (isset($indexBody['data']) && is_array($indexBody['data'])) {
|
|
foreach ($indexBody['data'] as $item) {
|
|
if (isset($item['TestSiteID'])) {
|
|
$ids[] = $item['TestSiteID'];
|
|
}
|
|
if (count($ids) >= 2) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $ids ?: [1, 2];
|
|
}
|
|
}
|