fix(testmap): support flexible detail patch payloads and align patch route coverage
This commit is contained in:
parent
84cfff2201
commit
99d5117bd9
6
TODO.md
6
TODO.md
@ -1,6 +0,0 @@
|
|||||||
## Remaining Work
|
|
||||||
|
|
||||||
1. `PatVisitController::updateADT` needs to accept or infer `InternalPVID` so the ADT patch tests no longer error out.
|
|
||||||
2. Implement or expose `POST /api/result` and align `ResultController` responses with what `ResultPatchTest` expects (success + 400/404 handling).
|
|
||||||
3. For each patch test controller (Contact, Location, Organization modules, Specimen masters, Test/TestMap variants, Rule, User, etc.), ensure the update action validates payloads, rejects empty bodies with 400, returns 404 for absent IDs, and responds with 200/201 on success.
|
|
||||||
4. Once controllers are fixed, rerun `./vendor/bin/phpunit` to confirm the patch suite passes end-to-end.
|
|
||||||
@ -315,13 +315,13 @@ $routes->group('api', function ($routes) {
|
|||||||
$routes->get('/', 'Test\TestsController::index');
|
$routes->get('/', 'Test\TestsController::index');
|
||||||
$routes->get('(:num)', 'Test\TestsController::show/$1');
|
$routes->get('(:num)', 'Test\TestsController::show/$1');
|
||||||
$routes->post('/', 'Test\TestsController::create');
|
$routes->post('/', 'Test\TestsController::create');
|
||||||
$routes->patch('(:any)', 'Test\TestsController::update/$1');
|
$routes->patch('(:segment)', 'Test\TestsController::update/$1');
|
||||||
$routes->group('testmap', function ($routes) {
|
$routes->group('testmap', function ($routes) {
|
||||||
$routes->get('/', 'Test\TestMapController::index');
|
$routes->get('/', 'Test\TestMapController::index');
|
||||||
$routes->get('(:num)', 'Test\TestMapController::show/$1');
|
$routes->get('(:num)', 'Test\TestMapController::show/$1');
|
||||||
$routes->post('/', 'Test\TestMapController::create');
|
$routes->post('/', 'Test\TestMapController::create');
|
||||||
$routes->patch('(:any)', 'Test\TestMapController::update/$1');
|
$routes->patch('(:segment)', 'Test\TestMapController::update/$1');
|
||||||
$routes->delete('/', 'Test\TestMapController::delete');
|
$routes->delete('/', 'Test\TestMapController::delete');
|
||||||
|
|
||||||
// Filter routes
|
// Filter routes
|
||||||
$routes->get('by-testcode/(:any)', 'Test\TestMapController::showByTestCode/$1');
|
$routes->get('by-testcode/(:any)', 'Test\TestMapController::showByTestCode/$1');
|
||||||
@ -331,7 +331,7 @@ $routes->group('api', function ($routes) {
|
|||||||
$routes->get('/', 'Test\TestMapDetailController::index');
|
$routes->get('/', 'Test\TestMapDetailController::index');
|
||||||
$routes->get('(:num)', 'Test\TestMapDetailController::show/$1');
|
$routes->get('(:num)', 'Test\TestMapDetailController::show/$1');
|
||||||
$routes->post('/', 'Test\TestMapDetailController::create');
|
$routes->post('/', 'Test\TestMapDetailController::create');
|
||||||
$routes->patch('(:any)', 'Test\TestMapDetailController::update/$1');
|
$routes->patch('(:segment)', 'Test\TestMapDetailController::update/$1');
|
||||||
$routes->delete('/', 'Test\TestMapDetailController::delete');
|
$routes->delete('/', 'Test\TestMapDetailController::delete');
|
||||||
$routes->get('by-testmap/(:num)', 'Test\TestMapDetailController::showByTestMap/$1');
|
$routes->get('by-testmap/(:num)', 'Test\TestMapDetailController::showByTestMap/$1');
|
||||||
$routes->post('batch', 'Test\TestMapDetailController::batchCreate');
|
$routes->post('batch', 'Test\TestMapDetailController::batchCreate');
|
||||||
|
|||||||
@ -235,9 +235,9 @@ class TestMapController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($this->isDetailOpsPayload($detailsPayload)) {
|
if ($this->isDetailOpsPayload($detailsPayload)) {
|
||||||
$newItems = $this->normalizeDetailList($detailsPayload['new'] ?? []);
|
$newItems = $this->normalizeDetailList($detailsPayload['new'] ?? [], 'details.new');
|
||||||
if ($newItems === null) { return null; }
|
if ($newItems === null) { return null; }
|
||||||
$editItems = $this->normalizeDetailList($detailsPayload['edit'] ?? []);
|
$editItems = $this->normalizeDetailList($detailsPayload['edit'] ?? [], 'details.edit');
|
||||||
if ($editItems === null) { return null; }
|
if ($editItems === null) { return null; }
|
||||||
$deletedIds = $this->normalizeDetailIds($detailsPayload['deleted'] ?? []);
|
$deletedIds = $this->normalizeDetailIds($detailsPayload['deleted'] ?? []);
|
||||||
if ($deletedIds === null) { return null; }
|
if ($deletedIds === null) { return null; }
|
||||||
@ -246,13 +246,13 @@ class TestMapController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($this->isListPayload($detailsPayload)) {
|
if ($this->isListPayload($detailsPayload)) {
|
||||||
$items = $this->normalizeDetailList($detailsPayload);
|
$items = $this->normalizeDetailList($detailsPayload, 'details');
|
||||||
if ($items === null) { return null; }
|
if ($items === null) { return null; }
|
||||||
return ['new' => $items, 'edit' => [], 'deleted' => []];
|
return ['new' => $items, 'edit' => [], 'deleted' => []];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->isAssocArray($detailsPayload)) {
|
if ($this->isAssocArray($detailsPayload)) {
|
||||||
$items = $this->normalizeDetailList([$detailsPayload]);
|
$items = $this->normalizeDetailList([$detailsPayload], 'details');
|
||||||
if ($items === null) { return null; }
|
if ($items === null) { return null; }
|
||||||
return ['new' => $items, 'edit' => [], 'deleted' => []];
|
return ['new' => $items, 'edit' => [], 'deleted' => []];
|
||||||
}
|
}
|
||||||
@ -386,21 +386,25 @@ class TestMapController extends BaseController {
|
|||||||
return array_keys($payload) !== range(0, count($payload) - 1);
|
return array_keys($payload) !== range(0, count($payload) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function normalizeDetailList(mixed $value): ?array
|
private function normalizeDetailList(mixed $value, string $fieldPath): ?array
|
||||||
{
|
{
|
||||||
if ($value === null) {
|
if ($value === null) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_array($value)) {
|
if (!is_array($value)) {
|
||||||
$this->failValidationErrors('Details must be provided as an array of objects.');
|
$this->failValidationErrors("{$fieldPath} must be an array of objects.");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($value !== [] && $this->isAssocArray($value)) {
|
||||||
|
$value = [$value];
|
||||||
|
}
|
||||||
|
|
||||||
$results = [];
|
$results = [];
|
||||||
foreach ($value as $index => $item) {
|
foreach ($value as $index => $item) {
|
||||||
if (!is_array($item)) {
|
if (!is_array($item)) {
|
||||||
$this->failValidationErrors("details[{$index}] must be an object.");
|
$this->failValidationErrors("{$fieldPath}[{$index}] must be an object.");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
$results[] = $item;
|
$results[] = $item;
|
||||||
|
|||||||
@ -4199,21 +4199,6 @@ paths:
|
|||||||
type: integer
|
type: integer
|
||||||
description: Test Map ID
|
description: Test Map ID
|
||||||
requestBody:
|
requestBody:
|
||||||
'200':
|
|
||||||
description: Test mapping updated
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
status:
|
|
||||||
type: string
|
|
||||||
example: success
|
|
||||||
message:
|
|
||||||
type: string
|
|
||||||
data:
|
|
||||||
type: integer
|
|
||||||
description: Updated TestMapID
|
|
||||||
required: true
|
required: true
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
@ -4229,12 +4214,53 @@ paths:
|
|||||||
ClientID:
|
ClientID:
|
||||||
type: string
|
type: string
|
||||||
details:
|
details:
|
||||||
type: object
|
description: |
|
||||||
description: Apply detail-level changes together with the header update
|
Detail payload supports either a flat array/object (treated as new rows)
|
||||||
properties:
|
or an operations object with `new`, `edit`, and `deleted` arrays.
|
||||||
new:
|
oneOf:
|
||||||
type: array
|
- type: object
|
||||||
description: New detail records to insert
|
properties:
|
||||||
|
new:
|
||||||
|
type: array
|
||||||
|
description: New detail records to insert
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
HostTestCode:
|
||||||
|
type: string
|
||||||
|
HostTestName:
|
||||||
|
type: string
|
||||||
|
ConDefID:
|
||||||
|
type: integer
|
||||||
|
ClientTestCode:
|
||||||
|
type: string
|
||||||
|
ClientTestName:
|
||||||
|
type: string
|
||||||
|
edit:
|
||||||
|
type: array
|
||||||
|
description: Existing detail records to update
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
TestMapDetailID:
|
||||||
|
type: integer
|
||||||
|
HostTestCode:
|
||||||
|
type: string
|
||||||
|
HostTestName:
|
||||||
|
type: string
|
||||||
|
ConDefID:
|
||||||
|
type: integer
|
||||||
|
ClientTestCode:
|
||||||
|
type: string
|
||||||
|
ClientTestName:
|
||||||
|
type: string
|
||||||
|
deleted:
|
||||||
|
type: array
|
||||||
|
description: TestMapDetailIDs to soft delete
|
||||||
|
items:
|
||||||
|
type: integer
|
||||||
|
- type: array
|
||||||
|
description: Shortcut format for creating new details only
|
||||||
items:
|
items:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
@ -4248,30 +4274,35 @@ paths:
|
|||||||
type: string
|
type: string
|
||||||
ClientTestName:
|
ClientTestName:
|
||||||
type: string
|
type: string
|
||||||
edit:
|
- type: object
|
||||||
type: array
|
description: Shortcut format for creating a single new detail
|
||||||
description: Existing detail records to update
|
properties:
|
||||||
items:
|
HostTestCode:
|
||||||
type: object
|
type: string
|
||||||
properties:
|
HostTestName:
|
||||||
TestMapDetailID:
|
type: string
|
||||||
type: integer
|
ConDefID:
|
||||||
HostTestCode:
|
type: integer
|
||||||
type: string
|
ClientTestCode:
|
||||||
HostTestName:
|
type: string
|
||||||
type: string
|
ClientTestName:
|
||||||
ConDefID:
|
type: string
|
||||||
type: integer
|
responses:
|
||||||
ClientTestCode:
|
'200':
|
||||||
type: string
|
description: Test mapping updated
|
||||||
ClientTestName:
|
content:
|
||||||
type: string
|
application/json:
|
||||||
deleted:
|
schema:
|
||||||
type: array
|
type: object
|
||||||
description: TestMapDetailIDs to soft delete
|
properties:
|
||||||
items:
|
status:
|
||||||
type: integer
|
type: string
|
||||||
responses: null
|
example: success
|
||||||
|
message:
|
||||||
|
type: string
|
||||||
|
data:
|
||||||
|
type: integer
|
||||||
|
description: Updated TestMapID
|
||||||
/api/test/testmap/by-testcode/{testCode}:
|
/api/test/testmap/by-testcode/{testCode}:
|
||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
|
|||||||
@ -189,12 +189,53 @@
|
|||||||
ClientID:
|
ClientID:
|
||||||
type: string
|
type: string
|
||||||
details:
|
details:
|
||||||
type: object
|
description: |
|
||||||
description: Apply detail-level changes together with the header update
|
Detail payload supports either a flat array/object (treated as new rows)
|
||||||
properties:
|
or an operations object with `new`, `edit`, and `deleted` arrays.
|
||||||
new:
|
oneOf:
|
||||||
type: array
|
- type: object
|
||||||
description: New detail records to insert
|
properties:
|
||||||
|
new:
|
||||||
|
type: array
|
||||||
|
description: New detail records to insert
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
HostTestCode:
|
||||||
|
type: string
|
||||||
|
HostTestName:
|
||||||
|
type: string
|
||||||
|
ConDefID:
|
||||||
|
type: integer
|
||||||
|
ClientTestCode:
|
||||||
|
type: string
|
||||||
|
ClientTestName:
|
||||||
|
type: string
|
||||||
|
edit:
|
||||||
|
type: array
|
||||||
|
description: Existing detail records to update
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
TestMapDetailID:
|
||||||
|
type: integer
|
||||||
|
HostTestCode:
|
||||||
|
type: string
|
||||||
|
HostTestName:
|
||||||
|
type: string
|
||||||
|
ConDefID:
|
||||||
|
type: integer
|
||||||
|
ClientTestCode:
|
||||||
|
type: string
|
||||||
|
ClientTestName:
|
||||||
|
type: string
|
||||||
|
deleted:
|
||||||
|
type: array
|
||||||
|
description: TestMapDetailIDs to soft delete
|
||||||
|
items:
|
||||||
|
type: integer
|
||||||
|
- type: array
|
||||||
|
description: Shortcut format for creating new details only
|
||||||
items:
|
items:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
@ -208,30 +249,20 @@
|
|||||||
type: string
|
type: string
|
||||||
ClientTestName:
|
ClientTestName:
|
||||||
type: string
|
type: string
|
||||||
edit:
|
- type: object
|
||||||
type: array
|
description: Shortcut format for creating a single new detail
|
||||||
description: Existing detail records to update
|
properties:
|
||||||
items:
|
HostTestCode:
|
||||||
type: object
|
type: string
|
||||||
properties:
|
HostTestName:
|
||||||
TestMapDetailID:
|
type: string
|
||||||
type: integer
|
ConDefID:
|
||||||
HostTestCode:
|
type: integer
|
||||||
type: string
|
ClientTestCode:
|
||||||
HostTestName:
|
type: string
|
||||||
type: string
|
ClientTestName:
|
||||||
ConDefID:
|
type: string
|
||||||
type: integer
|
responses:
|
||||||
ClientTestCode:
|
|
||||||
type: string
|
|
||||||
ClientTestName:
|
|
||||||
type: string
|
|
||||||
deleted:
|
|
||||||
type: array
|
|
||||||
description: TestMapDetailIDs to soft delete
|
|
||||||
items:
|
|
||||||
type: integer
|
|
||||||
responses:
|
|
||||||
'200':
|
'200':
|
||||||
description: Test mapping updated
|
description: Test mapping updated
|
||||||
content:
|
content:
|
||||||
|
|||||||
@ -12,6 +12,7 @@ class TestMapDetailPatchTest extends CIUnitTestCase
|
|||||||
|
|
||||||
protected string $token;
|
protected string $token;
|
||||||
protected string $endpoint = 'api/test/testmap/detail';
|
protected string $endpoint = 'api/test/testmap/detail';
|
||||||
|
protected string $mapEndpoint = 'api/test/testmap';
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
@ -36,9 +37,23 @@ class TestMapDetailPatchTest extends CIUnitTestCase
|
|||||||
|
|
||||||
private function createTestMapDetail(array $data = []): array
|
private function createTestMapDetail(array $data = []): array
|
||||||
{
|
{
|
||||||
|
$mapResponse = $this->withHeaders($this->authHeaders())
|
||||||
|
->withBodyFormat('json')
|
||||||
|
->call('post', $this->mapEndpoint, [
|
||||||
|
'HostType' => 'SITE',
|
||||||
|
'HostID' => 1,
|
||||||
|
'ClientType' => 'SITE',
|
||||||
|
'ClientID' => 1,
|
||||||
|
]);
|
||||||
|
$mapResponse->assertStatus(201);
|
||||||
|
$mapID = json_decode($mapResponse->getJSON(), true)['data'];
|
||||||
|
|
||||||
$payload = array_merge([
|
$payload = array_merge([
|
||||||
'TestMapDetailCode' => 'TMD_' . uniqid(),
|
'TestMapID' => $mapID,
|
||||||
'TestMapDetailName' => 'Test Map Detail ' . uniqid(),
|
'HostTestCode' => 'HB',
|
||||||
|
'HostTestName' => 'Hemoglobin',
|
||||||
|
'ClientTestCode' => '2',
|
||||||
|
'ClientTestName' => 'Hemoglobin',
|
||||||
], $data);
|
], $data);
|
||||||
|
|
||||||
$response = $this->withHeaders($this->authHeaders())
|
$response = $this->withHeaders($this->authHeaders())
|
||||||
@ -47,7 +62,11 @@ class TestMapDetailPatchTest extends CIUnitTestCase
|
|||||||
|
|
||||||
$response->assertStatus(201);
|
$response->assertStatus(201);
|
||||||
$decoded = json_decode($response->getJSON(), true);
|
$decoded = json_decode($response->getJSON(), true);
|
||||||
return $decoded['data'];
|
$detailID = $decoded['data'];
|
||||||
|
|
||||||
|
$show = $this->withHeaders($this->authHeaders())->call('get', "{$this->endpoint}/{$detailID}");
|
||||||
|
$show->assertStatus(200);
|
||||||
|
return json_decode($show->getJSON(), true)['data'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateTestMapDetailSuccess()
|
public function testPartialUpdateTestMapDetailSuccess()
|
||||||
@ -57,7 +76,7 @@ class TestMapDetailPatchTest extends CIUnitTestCase
|
|||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['TestMapDetailName' => 'Updated Detail']);
|
->call('patch', "{$this->endpoint}/{$id}", ['ClientTestName' => 'Updated Detail']);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$patchData = json_decode($patch->getJSON(), true);
|
$patchData = json_decode($patch->getJSON(), true);
|
||||||
@ -67,15 +86,15 @@ class TestMapDetailPatchTest extends CIUnitTestCase
|
|||||||
$show->assertStatus(200);
|
$show->assertStatus(200);
|
||||||
$showData = json_decode($show->getJSON(), true)['data'];
|
$showData = json_decode($show->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertEquals('Updated Detail', $showData['TestMapDetailName']);
|
$this->assertEquals('Updated Detail', $showData['ClientTestName']);
|
||||||
$this->assertEquals($detail['TestMapDetailCode'], $showData['TestMapDetailCode']);
|
$this->assertEquals($detail['HostTestCode'], $showData['HostTestCode']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateTestMapDetailNotFound()
|
public function testPartialUpdateTestMapDetailNotFound()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/999999", ['TestMapDetailName' => 'Updated']);
|
->call('patch', "{$this->endpoint}/999999", ['ClientTestName' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(404);
|
$patch->assertStatus(404);
|
||||||
}
|
}
|
||||||
@ -84,7 +103,7 @@ class TestMapDetailPatchTest extends CIUnitTestCase
|
|||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/invalid", ['TestMapDetailName' => 'Updated']);
|
->call('patch', "{$this->endpoint}/invalid", ['ClientTestName' => 'Updated']);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
@ -108,14 +127,14 @@ class TestMapDetailPatchTest extends CIUnitTestCase
|
|||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['TestMapDetailCode' => 'NEW_' . uniqid()]);
|
->call('patch', "{$this->endpoint}/{$id}", ['HostTestCode' => 'HBA1C']);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$showData = json_decode($this->withHeaders($this->authHeaders())
|
$showData = json_decode($this->withHeaders($this->authHeaders())
|
||||||
->call('get', "{$this->endpoint}/{$id}")
|
->call('get', "{$this->endpoint}/{$id}")
|
||||||
->getJSON(), true)['data'];
|
->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertNotEquals($detail['TestMapDetailCode'], $showData['TestMapDetailCode']);
|
$this->assertNotEquals($detail['HostTestCode'], $showData['HostTestCode']);
|
||||||
$this->assertEquals($detail['TestMapDetailName'], $showData['TestMapDetailName']);
|
$this->assertEquals($detail['ClientTestName'], $showData['ClientTestName']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,8 +37,6 @@ class TestMapPatchTest extends CIUnitTestCase
|
|||||||
private function createTestMap(array $data = []): array
|
private function createTestMap(array $data = []): array
|
||||||
{
|
{
|
||||||
$payload = array_merge([
|
$payload = array_merge([
|
||||||
'TestMapCode' => 'TM_' . uniqid(),
|
|
||||||
'TestMapName' => 'Test Map ' . uniqid(),
|
|
||||||
'HostType' => 'SITE',
|
'HostType' => 'SITE',
|
||||||
'HostID' => 1,
|
'HostID' => 1,
|
||||||
'ClientType' => 'SITE',
|
'ClientType' => 'SITE',
|
||||||
@ -49,7 +47,6 @@ class TestMapPatchTest extends CIUnitTestCase
|
|||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('post', $this->endpoint, $payload);
|
->call('post', $this->endpoint, $payload);
|
||||||
|
|
||||||
fwrite(STDERR, 'Create response: ' . $response->getStatusCode() . ' ' . $response->getBody() . PHP_EOL);
|
|
||||||
$response->assertStatus(201);
|
$response->assertStatus(201);
|
||||||
$created = json_decode($response->getJSON(), true);
|
$created = json_decode($response->getJSON(), true);
|
||||||
$id = $created['data'];
|
$id = $created['data'];
|
||||||
@ -66,7 +63,7 @@ class TestMapPatchTest extends CIUnitTestCase
|
|||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['TestMapName' => 'Updated TestMap']);
|
->call('patch', "{$this->endpoint}/{$id}", ['ClientType' => 'WST']);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$patchData = json_decode($patch->getJSON(), true);
|
$patchData = json_decode($patch->getJSON(), true);
|
||||||
@ -76,15 +73,15 @@ class TestMapPatchTest extends CIUnitTestCase
|
|||||||
$show->assertStatus(200);
|
$show->assertStatus(200);
|
||||||
$showData = json_decode($show->getJSON(), true)['data'];
|
$showData = json_decode($show->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertEquals('Updated TestMap', $showData['TestMapName']);
|
$this->assertEquals('WST', $showData['ClientType']);
|
||||||
$this->assertEquals($testMap['TestMapCode'], $showData['TestMapCode']);
|
$this->assertEquals((string) $testMap['HostID'], (string) $showData['HostID']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPartialUpdateTestMapNotFound()
|
public function testPartialUpdateTestMapNotFound()
|
||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/999999", ['TestMapName' => 'Updated']);
|
->call('patch', "{$this->endpoint}/999999", ['ClientType' => 'WST']);
|
||||||
|
|
||||||
$patch->assertStatus(404);
|
$patch->assertStatus(404);
|
||||||
}
|
}
|
||||||
@ -93,7 +90,7 @@ class TestMapPatchTest extends CIUnitTestCase
|
|||||||
{
|
{
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/invalid", ['TestMapName' => 'Updated']);
|
->call('patch', "{$this->endpoint}/invalid", ['ClientType' => 'WST']);
|
||||||
|
|
||||||
$patch->assertStatus(400);
|
$patch->assertStatus(400);
|
||||||
}
|
}
|
||||||
@ -117,28 +114,28 @@ class TestMapPatchTest extends CIUnitTestCase
|
|||||||
|
|
||||||
$patch = $this->withHeaders($this->authHeaders())
|
$patch = $this->withHeaders($this->authHeaders())
|
||||||
->withBodyFormat('json')
|
->withBodyFormat('json')
|
||||||
->call('patch', "{$this->endpoint}/{$id}", ['TestMapCode' => 'NEW_' . uniqid()]);
|
->call('patch', "{$this->endpoint}/{$id}", ['HostID' => 2]);
|
||||||
|
|
||||||
$patch->assertStatus(200);
|
$patch->assertStatus(200);
|
||||||
$showData = json_decode($this->withHeaders($this->authHeaders())
|
$showData = json_decode($this->withHeaders($this->authHeaders())
|
||||||
->call('get', "{$this->endpoint}/{$id}")
|
->call('get', "{$this->endpoint}/{$id}")
|
||||||
->getJSON(), true)['data'];
|
->getJSON(), true)['data'];
|
||||||
|
|
||||||
$this->assertNotEquals($testMap['TestMapCode'], $showData['TestMapCode']);
|
$this->assertEquals('2', (string) $showData['HostID']);
|
||||||
$this->assertEquals($testMap['TestMapName'], $showData['TestMapName']);
|
$this->assertEquals((string) $testMap['ClientID'], (string) $showData['ClientID']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCreateTestMapWithDetails()
|
public function testCreateTestMapWithDetails()
|
||||||
{
|
{
|
||||||
$details = [
|
$details = [
|
||||||
[
|
[
|
||||||
'HostTestCode' => 'HB_' . uniqid(),
|
'HostTestCode' => 'HB',
|
||||||
'HostTestName' => 'Hemoglobin',
|
'HostTestName' => 'Hemoglobin',
|
||||||
'ClientTestCode' => '2',
|
'ClientTestCode' => '2',
|
||||||
'ClientTestName' => 'Hemoglobin',
|
'ClientTestName' => 'Hemoglobin',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'HostTestCode' => 'HCT_' . uniqid(),
|
'HostTestCode' => 'HCT',
|
||||||
'HostTestName' => 'Hematocrit',
|
'HostTestName' => 'Hematocrit',
|
||||||
'ClientTestCode' => '3',
|
'ClientTestCode' => '3',
|
||||||
'ClientTestName' => 'Hematocrit',
|
'ClientTestName' => 'Hematocrit',
|
||||||
@ -161,13 +158,13 @@ class TestMapPatchTest extends CIUnitTestCase
|
|||||||
{
|
{
|
||||||
$initialDetails = [
|
$initialDetails = [
|
||||||
[
|
[
|
||||||
'HostTestCode' => 'HB_' . uniqid(),
|
'HostTestCode' => 'HB',
|
||||||
'HostTestName' => 'Hemoglobin',
|
'HostTestName' => 'Hemoglobin',
|
||||||
'ClientTestCode' => '2',
|
'ClientTestCode' => '2',
|
||||||
'ClientTestName' => 'Hemoglobin',
|
'ClientTestName' => 'Hemoglobin',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'HostTestCode' => 'HCT_' . uniqid(),
|
'HostTestCode' => 'HCT',
|
||||||
'HostTestName' => 'Hematocrit',
|
'HostTestName' => 'Hematocrit',
|
||||||
'ClientTestCode' => '3',
|
'ClientTestCode' => '3',
|
||||||
'ClientTestName' => 'Hematocrit',
|
'ClientTestName' => 'Hematocrit',
|
||||||
@ -199,10 +196,10 @@ class TestMapPatchTest extends CIUnitTestCase
|
|||||||
],
|
],
|
||||||
'new' => [
|
'new' => [
|
||||||
[
|
[
|
||||||
'HostTestCode' => 'MCV_' . uniqid(),
|
'HostTestCode' => 'MCV',
|
||||||
'HostTestName' => 'MCV',
|
'HostTestName' => 'MCV',
|
||||||
'ClientTestCode' => '4',
|
'ClientTestCode' => '4',
|
||||||
'ClientTestName' => 'MCV',
|
'ClientTestName' => 'MCV',
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
'deleted' => [$deleteDetail['TestMapDetailID']],
|
'deleted' => [$deleteDetail['TestMapDetailID']],
|
||||||
@ -237,7 +234,7 @@ class TestMapPatchTest extends CIUnitTestCase
|
|||||||
'ClientID' => 3,
|
'ClientID' => 3,
|
||||||
'details' => [
|
'details' => [
|
||||||
[
|
[
|
||||||
'HostTestCode' => 'PLT_' . uniqid(),
|
'HostTestCode' => 'PLT',
|
||||||
'HostTestName' => 'Platelet',
|
'HostTestName' => 'Platelet',
|
||||||
'ClientTestCode' => '5',
|
'ClientTestCode' => '5',
|
||||||
'ClientTestName' => 'Platelet',
|
'ClientTestName' => 'Platelet',
|
||||||
|
|||||||
5
todo.md
5
todo.md
@ -1,5 +0,0 @@
|
|||||||
### TestMap detail sync fix
|
|
||||||
- Investigate why `TestMapController::create` and `patch` still reject payloads (400) despite passing required fields; log output hints validation errors.
|
|
||||||
- Complete detail operation helpers (new/edit/deleted) so frontend payload works end-to-end and rerun feature tests.
|
|
||||||
- Update tests once endpoints behave (remove stderr logging) and verify `phpunit tests/feature/Test/TestMapPatchTest.php` passes.
|
|
||||||
- Confirm OpenAPI docs reflect final behavior and bundle output already up-to-date.
|
|
||||||
Loading…
x
Reference in New Issue
Block a user