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,12 +315,12 @@ $routes->group('api', function ($routes) {
|
||||
$routes->get('/', 'Test\TestsController::index');
|
||||
$routes->get('(:num)', 'Test\TestsController::show/$1');
|
||||
$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->get('/', 'Test\TestMapController::index');
|
||||
$routes->get('(:num)', 'Test\TestMapController::show/$1');
|
||||
$routes->post('/', 'Test\TestMapController::create');
|
||||
$routes->patch('(:any)', 'Test\TestMapController::update/$1');
|
||||
$routes->patch('(:segment)', 'Test\TestMapController::update/$1');
|
||||
$routes->delete('/', 'Test\TestMapController::delete');
|
||||
|
||||
// Filter routes
|
||||
@ -331,7 +331,7 @@ $routes->group('api', function ($routes) {
|
||||
$routes->get('/', 'Test\TestMapDetailController::index');
|
||||
$routes->get('(:num)', 'Test\TestMapDetailController::show/$1');
|
||||
$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->get('by-testmap/(:num)', 'Test\TestMapDetailController::showByTestMap/$1');
|
||||
$routes->post('batch', 'Test\TestMapDetailController::batchCreate');
|
||||
|
||||
@ -235,9 +235,9 @@ class TestMapController extends BaseController {
|
||||
}
|
||||
|
||||
if ($this->isDetailOpsPayload($detailsPayload)) {
|
||||
$newItems = $this->normalizeDetailList($detailsPayload['new'] ?? []);
|
||||
$newItems = $this->normalizeDetailList($detailsPayload['new'] ?? [], 'details.new');
|
||||
if ($newItems === null) { return null; }
|
||||
$editItems = $this->normalizeDetailList($detailsPayload['edit'] ?? []);
|
||||
$editItems = $this->normalizeDetailList($detailsPayload['edit'] ?? [], 'details.edit');
|
||||
if ($editItems === null) { return null; }
|
||||
$deletedIds = $this->normalizeDetailIds($detailsPayload['deleted'] ?? []);
|
||||
if ($deletedIds === null) { return null; }
|
||||
@ -246,13 +246,13 @@ class TestMapController extends BaseController {
|
||||
}
|
||||
|
||||
if ($this->isListPayload($detailsPayload)) {
|
||||
$items = $this->normalizeDetailList($detailsPayload);
|
||||
$items = $this->normalizeDetailList($detailsPayload, 'details');
|
||||
if ($items === null) { return null; }
|
||||
return ['new' => $items, 'edit' => [], 'deleted' => []];
|
||||
}
|
||||
|
||||
if ($this->isAssocArray($detailsPayload)) {
|
||||
$items = $this->normalizeDetailList([$detailsPayload]);
|
||||
$items = $this->normalizeDetailList([$detailsPayload], 'details');
|
||||
if ($items === null) { return null; }
|
||||
return ['new' => $items, 'edit' => [], 'deleted' => []];
|
||||
}
|
||||
@ -386,21 +386,25 @@ class TestMapController extends BaseController {
|
||||
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) {
|
||||
return [];
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if ($value !== [] && $this->isAssocArray($value)) {
|
||||
$value = [$value];
|
||||
}
|
||||
|
||||
$results = [];
|
||||
foreach ($value as $index => $item) {
|
||||
if (!is_array($item)) {
|
||||
$this->failValidationErrors("details[{$index}] must be an object.");
|
||||
$this->failValidationErrors("{$fieldPath}[{$index}] must be an object.");
|
||||
return null;
|
||||
}
|
||||
$results[] = $item;
|
||||
|
||||
@ -4199,21 +4199,6 @@ paths:
|
||||
type: integer
|
||||
description: Test Map ID
|
||||
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
|
||||
content:
|
||||
application/json:
|
||||
@ -4229,12 +4214,53 @@ paths:
|
||||
ClientID:
|
||||
type: string
|
||||
details:
|
||||
type: object
|
||||
description: Apply detail-level changes together with the header update
|
||||
properties:
|
||||
new:
|
||||
type: array
|
||||
description: New detail records to insert
|
||||
description: |
|
||||
Detail payload supports either a flat array/object (treated as new rows)
|
||||
or an operations object with `new`, `edit`, and `deleted` arrays.
|
||||
oneOf:
|
||||
- type: object
|
||||
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:
|
||||
type: object
|
||||
properties:
|
||||
@ -4248,30 +4274,35 @@ paths:
|
||||
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
|
||||
responses: null
|
||||
- type: object
|
||||
description: Shortcut format for creating a single new detail
|
||||
properties:
|
||||
HostTestCode:
|
||||
type: string
|
||||
HostTestName:
|
||||
type: string
|
||||
ConDefID:
|
||||
type: integer
|
||||
ClientTestCode:
|
||||
type: string
|
||||
ClientTestName:
|
||||
type: string
|
||||
responses:
|
||||
'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
|
||||
/api/test/testmap/by-testcode/{testCode}:
|
||||
get:
|
||||
tags:
|
||||
|
||||
@ -189,12 +189,53 @@
|
||||
ClientID:
|
||||
type: string
|
||||
details:
|
||||
type: object
|
||||
description: Apply detail-level changes together with the header update
|
||||
properties:
|
||||
new:
|
||||
type: array
|
||||
description: New detail records to insert
|
||||
description: |
|
||||
Detail payload supports either a flat array/object (treated as new rows)
|
||||
or an operations object with `new`, `edit`, and `deleted` arrays.
|
||||
oneOf:
|
||||
- type: object
|
||||
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:
|
||||
type: object
|
||||
properties:
|
||||
@ -208,30 +249,20 @@
|
||||
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
|
||||
responses:
|
||||
- type: object
|
||||
description: Shortcut format for creating a single new detail
|
||||
properties:
|
||||
HostTestCode:
|
||||
type: string
|
||||
HostTestName:
|
||||
type: string
|
||||
ConDefID:
|
||||
type: integer
|
||||
ClientTestCode:
|
||||
type: string
|
||||
ClientTestName:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: Test mapping updated
|
||||
content:
|
||||
|
||||
@ -12,6 +12,7 @@ class TestMapDetailPatchTest extends CIUnitTestCase
|
||||
|
||||
protected string $token;
|
||||
protected string $endpoint = 'api/test/testmap/detail';
|
||||
protected string $mapEndpoint = 'api/test/testmap';
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
@ -36,9 +37,23 @@ class TestMapDetailPatchTest extends CIUnitTestCase
|
||||
|
||||
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([
|
||||
'TestMapDetailCode' => 'TMD_' . uniqid(),
|
||||
'TestMapDetailName' => 'Test Map Detail ' . uniqid(),
|
||||
'TestMapID' => $mapID,
|
||||
'HostTestCode' => 'HB',
|
||||
'HostTestName' => 'Hemoglobin',
|
||||
'ClientTestCode' => '2',
|
||||
'ClientTestName' => 'Hemoglobin',
|
||||
], $data);
|
||||
|
||||
$response = $this->withHeaders($this->authHeaders())
|
||||
@ -47,7 +62,11 @@ class TestMapDetailPatchTest extends CIUnitTestCase
|
||||
|
||||
$response->assertStatus(201);
|
||||
$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()
|
||||
@ -57,7 +76,7 @@ class TestMapDetailPatchTest extends CIUnitTestCase
|
||||
|
||||
$patch = $this->withHeaders($this->authHeaders())
|
||||
->withBodyFormat('json')
|
||||
->call('patch', "{$this->endpoint}/{$id}", ['TestMapDetailName' => 'Updated Detail']);
|
||||
->call('patch', "{$this->endpoint}/{$id}", ['ClientTestName' => 'Updated Detail']);
|
||||
|
||||
$patch->assertStatus(200);
|
||||
$patchData = json_decode($patch->getJSON(), true);
|
||||
@ -67,15 +86,15 @@ class TestMapDetailPatchTest extends CIUnitTestCase
|
||||
$show->assertStatus(200);
|
||||
$showData = json_decode($show->getJSON(), true)['data'];
|
||||
|
||||
$this->assertEquals('Updated Detail', $showData['TestMapDetailName']);
|
||||
$this->assertEquals($detail['TestMapDetailCode'], $showData['TestMapDetailCode']);
|
||||
$this->assertEquals('Updated Detail', $showData['ClientTestName']);
|
||||
$this->assertEquals($detail['HostTestCode'], $showData['HostTestCode']);
|
||||
}
|
||||
|
||||
public function testPartialUpdateTestMapDetailNotFound()
|
||||
{
|
||||
$patch = $this->withHeaders($this->authHeaders())
|
||||
->withBodyFormat('json')
|
||||
->call('patch', "{$this->endpoint}/999999", ['TestMapDetailName' => 'Updated']);
|
||||
->call('patch', "{$this->endpoint}/999999", ['ClientTestName' => 'Updated']);
|
||||
|
||||
$patch->assertStatus(404);
|
||||
}
|
||||
@ -84,7 +103,7 @@ class TestMapDetailPatchTest extends CIUnitTestCase
|
||||
{
|
||||
$patch = $this->withHeaders($this->authHeaders())
|
||||
->withBodyFormat('json')
|
||||
->call('patch', "{$this->endpoint}/invalid", ['TestMapDetailName' => 'Updated']);
|
||||
->call('patch', "{$this->endpoint}/invalid", ['ClientTestName' => 'Updated']);
|
||||
|
||||
$patch->assertStatus(400);
|
||||
}
|
||||
@ -108,14 +127,14 @@ class TestMapDetailPatchTest extends CIUnitTestCase
|
||||
|
||||
$patch = $this->withHeaders($this->authHeaders())
|
||||
->withBodyFormat('json')
|
||||
->call('patch', "{$this->endpoint}/{$id}", ['TestMapDetailCode' => 'NEW_' . uniqid()]);
|
||||
->call('patch', "{$this->endpoint}/{$id}", ['HostTestCode' => 'HBA1C']);
|
||||
|
||||
$patch->assertStatus(200);
|
||||
$showData = json_decode($this->withHeaders($this->authHeaders())
|
||||
->call('get', "{$this->endpoint}/{$id}")
|
||||
->getJSON(), true)['data'];
|
||||
|
||||
$this->assertNotEquals($detail['TestMapDetailCode'], $showData['TestMapDetailCode']);
|
||||
$this->assertEquals($detail['TestMapDetailName'], $showData['TestMapDetailName']);
|
||||
$this->assertNotEquals($detail['HostTestCode'], $showData['HostTestCode']);
|
||||
$this->assertEquals($detail['ClientTestName'], $showData['ClientTestName']);
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,8 +37,6 @@ class TestMapPatchTest extends CIUnitTestCase
|
||||
private function createTestMap(array $data = []): array
|
||||
{
|
||||
$payload = array_merge([
|
||||
'TestMapCode' => 'TM_' . uniqid(),
|
||||
'TestMapName' => 'Test Map ' . uniqid(),
|
||||
'HostType' => 'SITE',
|
||||
'HostID' => 1,
|
||||
'ClientType' => 'SITE',
|
||||
@ -49,7 +47,6 @@ class TestMapPatchTest extends CIUnitTestCase
|
||||
->withBodyFormat('json')
|
||||
->call('post', $this->endpoint, $payload);
|
||||
|
||||
fwrite(STDERR, 'Create response: ' . $response->getStatusCode() . ' ' . $response->getBody() . PHP_EOL);
|
||||
$response->assertStatus(201);
|
||||
$created = json_decode($response->getJSON(), true);
|
||||
$id = $created['data'];
|
||||
@ -66,7 +63,7 @@ class TestMapPatchTest extends CIUnitTestCase
|
||||
|
||||
$patch = $this->withHeaders($this->authHeaders())
|
||||
->withBodyFormat('json')
|
||||
->call('patch', "{$this->endpoint}/{$id}", ['TestMapName' => 'Updated TestMap']);
|
||||
->call('patch', "{$this->endpoint}/{$id}", ['ClientType' => 'WST']);
|
||||
|
||||
$patch->assertStatus(200);
|
||||
$patchData = json_decode($patch->getJSON(), true);
|
||||
@ -76,15 +73,15 @@ class TestMapPatchTest extends CIUnitTestCase
|
||||
$show->assertStatus(200);
|
||||
$showData = json_decode($show->getJSON(), true)['data'];
|
||||
|
||||
$this->assertEquals('Updated TestMap', $showData['TestMapName']);
|
||||
$this->assertEquals($testMap['TestMapCode'], $showData['TestMapCode']);
|
||||
$this->assertEquals('WST', $showData['ClientType']);
|
||||
$this->assertEquals((string) $testMap['HostID'], (string) $showData['HostID']);
|
||||
}
|
||||
|
||||
public function testPartialUpdateTestMapNotFound()
|
||||
{
|
||||
$patch = $this->withHeaders($this->authHeaders())
|
||||
->withBodyFormat('json')
|
||||
->call('patch', "{$this->endpoint}/999999", ['TestMapName' => 'Updated']);
|
||||
->call('patch', "{$this->endpoint}/999999", ['ClientType' => 'WST']);
|
||||
|
||||
$patch->assertStatus(404);
|
||||
}
|
||||
@ -93,7 +90,7 @@ class TestMapPatchTest extends CIUnitTestCase
|
||||
{
|
||||
$patch = $this->withHeaders($this->authHeaders())
|
||||
->withBodyFormat('json')
|
||||
->call('patch', "{$this->endpoint}/invalid", ['TestMapName' => 'Updated']);
|
||||
->call('patch', "{$this->endpoint}/invalid", ['ClientType' => 'WST']);
|
||||
|
||||
$patch->assertStatus(400);
|
||||
}
|
||||
@ -117,28 +114,28 @@ class TestMapPatchTest extends CIUnitTestCase
|
||||
|
||||
$patch = $this->withHeaders($this->authHeaders())
|
||||
->withBodyFormat('json')
|
||||
->call('patch', "{$this->endpoint}/{$id}", ['TestMapCode' => 'NEW_' . uniqid()]);
|
||||
->call('patch', "{$this->endpoint}/{$id}", ['HostID' => 2]);
|
||||
|
||||
$patch->assertStatus(200);
|
||||
$showData = json_decode($this->withHeaders($this->authHeaders())
|
||||
->call('get', "{$this->endpoint}/{$id}")
|
||||
->getJSON(), true)['data'];
|
||||
|
||||
$this->assertNotEquals($testMap['TestMapCode'], $showData['TestMapCode']);
|
||||
$this->assertEquals($testMap['TestMapName'], $showData['TestMapName']);
|
||||
$this->assertEquals('2', (string) $showData['HostID']);
|
||||
$this->assertEquals((string) $testMap['ClientID'], (string) $showData['ClientID']);
|
||||
}
|
||||
|
||||
public function testCreateTestMapWithDetails()
|
||||
{
|
||||
$details = [
|
||||
[
|
||||
'HostTestCode' => 'HB_' . uniqid(),
|
||||
'HostTestCode' => 'HB',
|
||||
'HostTestName' => 'Hemoglobin',
|
||||
'ClientTestCode' => '2',
|
||||
'ClientTestName' => 'Hemoglobin',
|
||||
],
|
||||
[
|
||||
'HostTestCode' => 'HCT_' . uniqid(),
|
||||
'HostTestCode' => 'HCT',
|
||||
'HostTestName' => 'Hematocrit',
|
||||
'ClientTestCode' => '3',
|
||||
'ClientTestName' => 'Hematocrit',
|
||||
@ -161,13 +158,13 @@ class TestMapPatchTest extends CIUnitTestCase
|
||||
{
|
||||
$initialDetails = [
|
||||
[
|
||||
'HostTestCode' => 'HB_' . uniqid(),
|
||||
'HostTestCode' => 'HB',
|
||||
'HostTestName' => 'Hemoglobin',
|
||||
'ClientTestCode' => '2',
|
||||
'ClientTestName' => 'Hemoglobin',
|
||||
],
|
||||
[
|
||||
'HostTestCode' => 'HCT_' . uniqid(),
|
||||
'HostTestCode' => 'HCT',
|
||||
'HostTestName' => 'Hematocrit',
|
||||
'ClientTestCode' => '3',
|
||||
'ClientTestName' => 'Hematocrit',
|
||||
@ -199,10 +196,10 @@ class TestMapPatchTest extends CIUnitTestCase
|
||||
],
|
||||
'new' => [
|
||||
[
|
||||
'HostTestCode' => 'MCV_' . uniqid(),
|
||||
'HostTestName' => 'MCV',
|
||||
'ClientTestCode' => '4',
|
||||
'ClientTestName' => 'MCV',
|
||||
'HostTestCode' => 'MCV',
|
||||
'HostTestName' => 'MCV',
|
||||
'ClientTestCode' => '4',
|
||||
'ClientTestName' => 'MCV',
|
||||
],
|
||||
],
|
||||
'deleted' => [$deleteDetail['TestMapDetailID']],
|
||||
@ -237,7 +234,7 @@ class TestMapPatchTest extends CIUnitTestCase
|
||||
'ClientID' => 3,
|
||||
'details' => [
|
||||
[
|
||||
'HostTestCode' => 'PLT_' . uniqid(),
|
||||
'HostTestCode' => 'PLT',
|
||||
'HostTestName' => 'Platelet',
|
||||
'ClientTestCode' => '5',
|
||||
'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