- TagsSettingsPage modal: replace native color input with 4 preset swatches, add 'وضعیت برچسب' active toggle, update labels and submit button to mirror tauri AddPurchaseSubTabModal - TenantTagController::create now honors an optional 'active' flag (defaults true, non-breaking for existing callers) - tests: backend active-flag case, frontend preset-color + inactive case - docs/api/tag.md: document the new create 'active' field Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
97 lines
3.3 KiB
PHP
97 lines
3.3 KiB
PHP
<?php
|
|
|
|
namespace App\Tests\Tag;
|
|
|
|
use App\Doctor\Entity\Doctor;
|
|
use App\Tests\ApiTestCase;
|
|
|
|
/**
|
|
* Per-tenant tag CRUD, scoped to the caller's doctor/clinic entity.
|
|
*/
|
|
class TenantTagTest extends ApiTestCase
|
|
{
|
|
private function doctorUser(): array
|
|
{
|
|
$user = $this->createUser(['ROLE_DOCTOR']);
|
|
$doctor = new Doctor($user, 'دکتر');
|
|
$this->em->persist($doctor);
|
|
$this->em->flush();
|
|
return [$user, $doctor];
|
|
}
|
|
|
|
public function testCreateListUpdateDelete(): void
|
|
{
|
|
[$user] = $this->doctorUser();
|
|
|
|
// create
|
|
$created = $this->authJson('POST', '/api/v1/tenant-tag', $user, [
|
|
'name' => 'فوری', 'color' => '#FF0000',
|
|
]);
|
|
self::assertSame(201, $this->responseCode());
|
|
self::assertSame('فوری', $created['data']['name']);
|
|
self::assertSame('#FF0000', $created['data']['color']);
|
|
$uuid = $created['data']['uuid'];
|
|
|
|
// list
|
|
$list = $this->authJson('GET', '/api/v1/tenant-tags', $user);
|
|
self::assertSame(200, $this->responseCode());
|
|
self::assertSame('فوری', $list['data'][0]['name']);
|
|
|
|
// update
|
|
$this->authJson('PATCH', '/api/v1/tenant-tag/' . $uuid, $user, [
|
|
'name' => 'مهم', 'color' => '#00AA00', 'active' => false,
|
|
]);
|
|
self::assertSame(200, $this->responseCode());
|
|
|
|
// delete
|
|
$this->authJson('DELETE', '/api/v1/tenant-tag/' . $uuid, $user);
|
|
self::assertSame(200, $this->responseCode());
|
|
|
|
$after = $this->authJson('GET', '/api/v1/tenant-tags', $user);
|
|
self::assertCount(0, $after['data']);
|
|
}
|
|
|
|
public function testCreateHonorsActiveFlag(): void
|
|
{
|
|
[$user] = $this->doctorUser();
|
|
|
|
// explicit active:false is persisted, not forced to the default true
|
|
$created = $this->authJson('POST', '/api/v1/tenant-tag', $user, [
|
|
'name' => 'بایگانی', 'color' => '#123456', 'active' => false,
|
|
]);
|
|
self::assertSame(201, $this->responseCode());
|
|
self::assertFalse($created['data']['active']);
|
|
|
|
// omitting active still defaults to true
|
|
$default = $this->authJson('POST', '/api/v1/tenant-tag', $user, [
|
|
'name' => 'پیشفرض', 'color' => '#654321',
|
|
]);
|
|
self::assertTrue($default['data']['active']);
|
|
}
|
|
|
|
public function testRejectsInvalidNameAndColor(): void
|
|
{
|
|
[$user] = $this->doctorUser();
|
|
|
|
$this->authJson('POST', '/api/v1/tenant-tag', $user, ['name' => '', 'color' => '#FF0000']);
|
|
self::assertSame(422, $this->responseCode());
|
|
|
|
$this->authJson('POST', '/api/v1/tenant-tag', $user, ['name' => 'ok', 'color' => 'red']);
|
|
self::assertSame(422, $this->responseCode());
|
|
}
|
|
|
|
public function testCannotTouchAnotherTenantsTag(): void
|
|
{
|
|
[$ownerA] = $this->doctorUser();
|
|
$created = $this->authJson('POST', '/api/v1/tenant-tag', $ownerA, ['name' => 'مال A', 'color' => '#123456']);
|
|
$uuid = $created['data']['uuid'];
|
|
|
|
[$ownerB] = $this->doctorUser();
|
|
$this->authJson('PATCH', '/api/v1/tenant-tag/' . $uuid, $ownerB, ['name' => 'دزدی']);
|
|
self::assertSame(404, $this->responseCode());
|
|
|
|
$this->authJson('DELETE', '/api/v1/tenant-tag/' . $uuid, $ownerB);
|
|
self::assertSame(404, $this->responseCode());
|
|
}
|
|
}
|