'localhost', 'aud' => 'localhost', 'iat' => time(), 'nbf' => time(), 'exp' => time() + 3600, 'uid' => 1, 'email' => 'admin@admin.com', ]; $this->token = JWT::encode($payload, $key, 'HS256'); } private function authHeaders(): array { return ['Cookie' => 'token=' . $this->token]; } private function createResource(string $endpoint, array $payload) { $response = $this->withHeaders($this->authHeaders()) ->withBody(json_encode($payload)) ->call('post', $endpoint); $response->assertStatus(201); $decoded = json_decode($response->getJSON(), true); $this->assertEquals('success', $decoded['status']); return $decoded['data']; } private function fetchFirstRecord(string $endpoint, string $idKey): array { try { $response = $this->withHeaders($this->authHeaders())->call('get', $endpoint); } catch (PageNotFoundException $e) { $this->markTestSkipped("{$endpoint} GET not available: {$e->getMessage()}"); } $response->assertStatus(200); $decoded = json_decode($response->getJSON(), true); $rows = $decoded['data'] ?? []; if (empty($rows)) { $this->markTestSkipped("No data available at {$endpoint}"); } $record = $rows[0]; $this->assertArrayHasKey($idKey, $record); return $record; } private function fetchResource(string $endpoint, $id): array { try { $response = $this->withHeaders($this->authHeaders()) ->call('get', "$endpoint/{$id}"); } catch (PageNotFoundException $e) { $this->markTestSkipped("{$endpoint}/{$id} GET not available: {$e->getMessage()}"); } $response->assertStatus(200); $decoded = json_decode($response->getJSON(), true); return $decoded['data']; } public function testPartialUpdateOccupation() { $occCode = 'PATCH_OCC_' . uniqid(); $id = $this->createResource('api/occupation', [ 'OccCode' => $occCode, 'OccText' => 'Original text', ]); $originalData = $this->fetchResource('api/occupation', $id); $originalCode = $originalData['OccCode']; $patch = $this->withHeaders($this->authHeaders()) ->withBodyFormat('json') ->call('patch', "api/occupation/{$id}", ['OccText' => 'Patched occupation']); $patch->assertStatus(201); $patchData = json_decode($patch->getJSON(), true); $this->assertEquals('success', $patchData['status']); $showData = $this->fetchResource('api/occupation', $id); $this->assertEquals('Patched occupation', $showData['OccText']); $this->assertEquals($originalCode, $showData['OccCode']); } public function testPartialUpdateMedicalSpecialty() { $text = 'Specialty ' . uniqid(); $id = $this->createResource('api/medicalspecialty', ['SpecialtyText' => $text]); $patch = $this->withHeaders($this->authHeaders()) ->withBodyFormat('json') ->call('patch', "api/medicalspecialty/{$id}", ['SpecialtyText' => 'Updated specialty']); $patch->assertStatus(201); $show = $this->withHeaders($this->authHeaders())->call('get', "api/medicalspecialty/{$id}"); $show->assertStatus(200); $showData = json_decode($show->getJSON(), true)['data']; $this->assertEquals('Updated specialty', $showData['SpecialtyText']); } public function testPartialUpdateCounter() { $initial = 'Counter ' . uniqid(); $id = $this->createResource('api/counter', [ 'CounterName' => $initial, 'CounterValue' => 1, 'CounterStart' => 1, 'CounterEnd' => 10, 'CounterReset' => 1, ]); $patch = $this->withHeaders($this->authHeaders()) ->withBodyFormat('json') ->call('patch', "api/counter/{$id}", ['CounterName' => 'Updated counter']); $patch->assertStatus(201); $show = $this->withHeaders($this->authHeaders())->call('get', "api/counter/{$id}"); $show->assertStatus(200); $showData = json_decode($show->getJSON(), true)['data']; $this->assertEquals('Updated counter', $showData['CounterName']); $this->assertEquals(1, (int) $showData['CounterValue']); } public function testPartialUpdateOrganizationAccount() { $name = 'Account ' . uniqid(); $id = $this->createResource('api/organization/account', ['AccountName' => $name]); $patch = $this->withHeaders($this->authHeaders()) ->withBodyFormat('json') ->call('patch', "api/organization/account/{$id}", ['AccountName' => 'Updated account']); $patch->assertStatus(200); $show = $this->withHeaders($this->authHeaders())->call('get', "api/organization/account/{$id}"); $show->assertStatus(200); $showData = json_decode($show->getJSON(), true)['data']; $this->assertEquals('Updated account', $showData['AccountName']); } public function testPartialUpdateDiscipline() { $code = 'DIS_' . strtoupper(bin2hex(random_bytes(2))); $name = 'Discipline ' . uniqid(); $id = $this->createResource('api/organization/discipline', [ 'DisciplineCode' => $code, 'DisciplineName' => $name, ]); $patch = $this->withHeaders($this->authHeaders()) ->withBodyFormat('json') ->call('patch', "api/organization/discipline/{$id}", ['DisciplineName' => 'Discipline Updated']); $patch->assertStatus(201); $show = $this->withHeaders($this->authHeaders())->call('get', "api/organization/discipline/{$id}"); $show->assertStatus(200); $showData = json_decode($show->getJSON(), true)['data']; $this->assertEquals('Discipline Updated', $showData['DisciplineName']); $this->assertEquals($code, $showData['DisciplineCode']); } public function testPartialUpdateCodingSystem() { $abbr = 'CS' . strtoupper(bin2hex(random_bytes(2))); $full = 'Full text ' . uniqid(); $id = $this->createResource('api/organization/codingsys', [ 'CodingSysAbb' => $abbr, 'FullText' => $full, ]); $patch = $this->withHeaders($this->authHeaders()) ->withBodyFormat('json') ->call('patch', "api/organization/codingsys/{$id}", ['FullText' => 'Updated full text']); $patch->assertStatus(201); $show = $this->withHeaders($this->authHeaders())->call('get', "api/organization/codingsys/{$id}"); $show->assertStatus(200); $showData = json_decode($show->getJSON(), true)['data']; $this->assertEquals('Updated full text', $showData['FullText']); $this->assertEquals($abbr, $showData['CodingSysAbb']); } public function testPartialUpdateSpecimenContainer() { $record = $this->fetchFirstRecord('api/specimen/container', 'ConDefID'); $id = $record['ConDefID']; $newName = 'Patch Container ' . uniqid(); $patch = $this->withHeaders($this->authHeaders()) ->withBodyFormat('json') ->call('patch', "api/specimen/container/{$id}", ['ConName' => $newName]); $patch->assertStatus(201); $showData = $this->fetchResource('api/specimen/container', $id); $this->assertEquals($newName, $showData['ConName']); $this->assertEquals($record['ConCode'] ?? null, $showData['ConCode'] ?? null); } public function testPartialUpdateSpecimenPrep() { $record = $this->fetchFirstRecord('api/specimen/prep', 'SpcPrpID'); $id = $record['SpcPrpID']; $newDesc = 'Partial Prep ' . uniqid(); $patch = $this->withHeaders($this->authHeaders()) ->withBodyFormat('json') ->call('patch', "api/specimen/prep/{$id}", ['Description' => $newDesc]); $patch->assertStatus(201); $showData = $this->fetchResource('api/specimen/prep', $id); $this->assertEquals($newDesc, $showData['Description']); $this->assertEquals($record['SpcStaID'] ?? null, $showData['SpcStaID'] ?? null); } public function testPartialUpdateSpecimenStatus() { $record = $this->fetchFirstRecord('api/specimen/status', 'SpcStaID'); $id = $record['SpcStaID']; $newStatus = 'UpdatedStatus'; $patch = $this->withHeaders($this->authHeaders()) ->withBodyFormat('json') ->call('patch', "api/specimen/status/{$id}", ['SpcStatus' => $newStatus]); $patch->assertStatus(201); $showData = $this->fetchResource('api/specimen/status', $id); $this->assertEquals($newStatus, $showData['SpcStatus']); $this->assertEquals($record['OrderID'] ?? null, $showData['OrderID'] ?? null); } public function testPartialUpdateSpecimenCollection() { $record = $this->fetchFirstRecord('api/specimen/collection', 'SpcColID'); $id = $record['SpcColID']; $newBodySite = 'BodySite ' . uniqid(); $patch = $this->withHeaders($this->authHeaders()) ->withBodyFormat('json') ->call('patch', "api/specimen/collection/{$id}", ['BodySite' => $newBodySite]); $patch->assertStatus(201); $showData = $this->fetchResource('api/specimen/collection', $id); $this->assertEquals($newBodySite, $showData['BodySite']); $this->assertEquals($record['SpRole'] ?? null, $showData['SpRole'] ?? null); } public function testPartialUpdateEquipmentList() { $record = $this->fetchFirstRecord('api/equipmentlist', 'EID'); $id = $record['EID']; $newName = 'Equipment ' . uniqid(); $patch = $this->withHeaders($this->authHeaders()) ->withBodyFormat('json') ->call('patch', "api/equipmentlist/{$id}", ['InstrumentName' => $newName]); $patch->assertStatus(200, 'Equipment patch should return 200'); $showData = $this->fetchResource('api/equipmentlist', $id); $this->assertEquals($newName, $showData['InstrumentName']); $this->assertEquals($record['DepartmentID'] ?? null, $showData['DepartmentID'] ?? null); } }