From 8ef162ace6cc6f2eefafa75c68dc351b8357d976 Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 13 Mar 2024 17:33:35 +0100 Subject: [PATCH] wip tasks --- ...08161707.php => Version20240312084330.php} | 12 +- src/ApiResource/TaskApi.php | 82 +++++++++ src/DataFixtures/AppFixtures.php | 2 + src/DataFixtures/FakeValues.php | 17 ++ src/Entity/Contact.php | 2 +- src/Entity/Task.php | 159 ++++++++++++++++++ src/Entity/User.php | 2 +- src/Enum/PrioType.php | 15 ++ src/Factory/TaskFactory.php | 79 +++++++++ src/Mapper/TaskApiToEntityMapper.php | 76 +++++++++ src/Mapper/TaskEntityToApiMapper.php | 73 ++++++++ src/Repository/TaskRepository.php | 48 ++++++ tests/Functional/TaskResourceTest.php | 84 +++++++++ 13 files changed, 648 insertions(+), 3 deletions(-) rename migrations/{Version20240308161707.php => Version20240312084330.php} (78%) create mode 100644 src/ApiResource/TaskApi.php create mode 100644 src/Entity/Task.php create mode 100644 src/Enum/PrioType.php create mode 100644 src/Factory/TaskFactory.php create mode 100644 src/Mapper/TaskApiToEntityMapper.php create mode 100644 src/Mapper/TaskEntityToApiMapper.php create mode 100644 src/Repository/TaskRepository.php create mode 100644 tests/Functional/TaskResourceTest.php diff --git a/migrations/Version20240308161707.php b/migrations/Version20240312084330.php similarity index 78% rename from migrations/Version20240308161707.php rename to migrations/Version20240312084330.php index cd91d1e..5e33df2 100644 --- a/migrations/Version20240308161707.php +++ b/migrations/Version20240312084330.php @@ -10,7 +10,7 @@ use Doctrine\Migrations\AbstractMigration; /** * Auto-generated Migration: Please modify to your needs! */ -final class Version20240308161707 extends AbstractMigration +final class Version20240312084330 extends AbstractMigration { public function getDescription(): string { @@ -26,6 +26,7 @@ final class Version20240308161707 extends AbstractMigration $this->addSql('CREATE TABLE partner (id INT AUTO_INCREMENT NOT NULL, logo_id INT DEFAULT NULL, name VARCHAR(255) NOT NULL, type VARCHAR(255) NOT NULL, street VARCHAR(255) DEFAULT NULL, street_no VARCHAR(255) DEFAULT NULL, zip VARCHAR(255) DEFAULT NULL, city VARCHAR(255) DEFAULT NULL, country VARCHAR(255) DEFAULT NULL, website VARCHAR(255) DEFAULT NULL, created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', INDEX IDX_312B3E16F98F144A (logo_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); $this->addSql('CREATE TABLE posting (id INT AUTO_INCREMENT NOT NULL, owner_id INT NOT NULL, partner_id INT NOT NULL, contact_id INT DEFAULT NULL, headline VARCHAR(255) NOT NULL, message LONGTEXT NOT NULL, created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', INDEX IDX_BD275D737E3C61F9 (owner_id), INDEX IDX_BD275D739393F8FE (partner_id), INDEX IDX_BD275D73E7A1254A (contact_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); $this->addSql('CREATE TABLE product (id INT AUTO_INCREMENT NOT NULL, image_id INT DEFAULT NULL, name VARCHAR(255) NOT NULL, description LONGTEXT DEFAULT NULL, created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', INDEX IDX_D34A04AD3DA5256D (image_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE task (id INT AUTO_INCREMENT NOT NULL, created_by_id INT NOT NULL, assigned_to_id INT NOT NULL, partner_id INT DEFAULT NULL, contact_id INT DEFAULT NULL, headline VARCHAR(255) NOT NULL, description LONGTEXT DEFAULT NULL, due_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', prio VARCHAR(255) NOT NULL, completed TINYINT(1) NOT NULL, created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', INDEX IDX_527EDB25B03A8386 (created_by_id), INDEX IDX_527EDB25F4BD7827 (assigned_to_id), INDEX IDX_527EDB259393F8FE (partner_id), INDEX IDX_527EDB25E7A1254A (contact_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); $this->addSql('CREATE TABLE `user` (id INT AUTO_INCREMENT NOT NULL, image_id INT DEFAULT NULL, email VARCHAR(180) NOT NULL, first_name VARCHAR(255) NOT NULL, last_name VARCHAR(255) NOT NULL, roles JSON NOT NULL COMMENT \'(DC2Type:json)\', password VARCHAR(255) NOT NULL, active TINYINT(1) NOT NULL, created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', UNIQUE INDEX UNIQ_8D93D649E7927C74 (email), INDEX IDX_8D93D6493DA5256D (image_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); $this->addSql('ALTER TABLE comment ADD CONSTRAINT FK_9474526C7E3C61F9 FOREIGN KEY (owner_id) REFERENCES `user` (id)'); $this->addSql('ALTER TABLE comment ADD CONSTRAINT FK_9474526C9AE985F6 FOREIGN KEY (posting_id) REFERENCES posting (id)'); @@ -36,6 +37,10 @@ final class Version20240308161707 extends AbstractMigration $this->addSql('ALTER TABLE posting ADD CONSTRAINT FK_BD275D739393F8FE FOREIGN KEY (partner_id) REFERENCES partner (id)'); $this->addSql('ALTER TABLE posting ADD CONSTRAINT FK_BD275D73E7A1254A FOREIGN KEY (contact_id) REFERENCES contact (id)'); $this->addSql('ALTER TABLE product ADD CONSTRAINT FK_D34A04AD3DA5256D FOREIGN KEY (image_id) REFERENCES media_object (id) ON DELETE SET NULL'); + $this->addSql('ALTER TABLE task ADD CONSTRAINT FK_527EDB25B03A8386 FOREIGN KEY (created_by_id) REFERENCES `user` (id)'); + $this->addSql('ALTER TABLE task ADD CONSTRAINT FK_527EDB25F4BD7827 FOREIGN KEY (assigned_to_id) REFERENCES `user` (id)'); + $this->addSql('ALTER TABLE task ADD CONSTRAINT FK_527EDB259393F8FE FOREIGN KEY (partner_id) REFERENCES partner (id) ON DELETE SET NULL'); + $this->addSql('ALTER TABLE task ADD CONSTRAINT FK_527EDB25E7A1254A FOREIGN KEY (contact_id) REFERENCES contact (id) ON DELETE SET NULL'); $this->addSql('ALTER TABLE `user` ADD CONSTRAINT FK_8D93D6493DA5256D FOREIGN KEY (image_id) REFERENCES media_object (id) ON DELETE SET NULL'); } @@ -51,6 +56,10 @@ final class Version20240308161707 extends AbstractMigration $this->addSql('ALTER TABLE posting DROP FOREIGN KEY FK_BD275D739393F8FE'); $this->addSql('ALTER TABLE posting DROP FOREIGN KEY FK_BD275D73E7A1254A'); $this->addSql('ALTER TABLE product DROP FOREIGN KEY FK_D34A04AD3DA5256D'); + $this->addSql('ALTER TABLE task DROP FOREIGN KEY FK_527EDB25B03A8386'); + $this->addSql('ALTER TABLE task DROP FOREIGN KEY FK_527EDB25F4BD7827'); + $this->addSql('ALTER TABLE task DROP FOREIGN KEY FK_527EDB259393F8FE'); + $this->addSql('ALTER TABLE task DROP FOREIGN KEY FK_527EDB25E7A1254A'); $this->addSql('ALTER TABLE `user` DROP FOREIGN KEY FK_8D93D6493DA5256D'); $this->addSql('DROP TABLE comment'); $this->addSql('DROP TABLE contact'); @@ -58,6 +67,7 @@ final class Version20240308161707 extends AbstractMigration $this->addSql('DROP TABLE partner'); $this->addSql('DROP TABLE posting'); $this->addSql('DROP TABLE product'); + $this->addSql('DROP TABLE task'); $this->addSql('DROP TABLE `user`'); } } diff --git a/src/ApiResource/TaskApi.php b/src/ApiResource/TaskApi.php new file mode 100644 index 0000000..2ec8a25 --- /dev/null +++ b/src/ApiResource/TaskApi.php @@ -0,0 +1,82 @@ + + * @date 12.12.23 + */ + + +namespace App\ApiResource; + +use ApiPlatform\Doctrine\Orm\State\Options; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Patch; +use ApiPlatform\Metadata\Post; +use App\Entity\Task; +use App\Enum\PrioType; +use App\State\EntityClassDtoStateProcessor; +use App\State\EntityToDtoStateProvider; +use Symfony\Component\Validator\Constraints as Assert; + +#[ApiResource( + shortName: 'Task', + operations: [ + new Get( + security: 'is_granted("ROLE_USER")' + ), + new GetCollection( + security: 'is_granted("ROLE_USER")' + ), + new Post( + security: 'is_granted("ROLE_USER")', + validationContext: ['groups' => ['Default', 'postValidation']] + ), + new Patch( + security: 'is_granted("is_granted("EDIT", object)")' + ), + new Delete( + security: 'is_granted("ROLE_USER")', + ) + ], + security: 'is_granted("ROLE_USER")', + provider: EntityToDtoStateProvider::class, + processor: EntityClassDtoStateProcessor::class, + stateOptions: new Options(entityClass: Task::class), + +)] +class TaskApi +{ + #[ApiProperty(readable: false, writable: false, identifier: true)] + public ?int $id = null; + + #[Assert\NotBlank] + public ?string $headline = null; + + #[Assert\NotBlank] + public ?string $description = null; + + #[ApiProperty(writable: false)] + public ?UserApi $createdBy = null; + + #[Assert\NotBlank] + public ?UserApi $assignedTo = null; + + #[Assert\NotBlank] + public ?\DateTimeImmutable $dueAt = null; + + public ?PartnerApi $partner = null; + + public ?ContactApi $contact = null; + + #[Assert\NotBlank] + public PrioType $prio; + + public ?bool $completed = null; + + #[ApiProperty(writable: false)] + public ?\DateTimeImmutable $createdAt = null; + +} diff --git a/src/DataFixtures/AppFixtures.php b/src/DataFixtures/AppFixtures.php index 6616fe3..5178e9b 100644 --- a/src/DataFixtures/AppFixtures.php +++ b/src/DataFixtures/AppFixtures.php @@ -11,6 +11,7 @@ use App\Factory\MediaObjectUserFactory; use App\Factory\PartnerFactory; use App\Factory\PostingFactory; use App\Factory\ProductFactory; +use App\Factory\TaskFactory; use App\Factory\UserFactory; use Doctrine\Bundle\FixturesBundle\Fixture; use Doctrine\Persistence\ObjectManager; @@ -67,5 +68,6 @@ class AppFixtures extends Fixture CommentFactory::createMany(300); MediaObjectProductFactory::createMany(50); ProductFactory::createMany(100); + TaskFactory::createMany(50); } } diff --git a/src/DataFixtures/FakeValues.php b/src/DataFixtures/FakeValues.php index 359e712..c0ec168 100644 --- a/src/DataFixtures/FakeValues.php +++ b/src/DataFixtures/FakeValues.php @@ -204,4 +204,21 @@ class FakeValues 'CryoVortex Acid', 'NanoRadiance Blend', 'QuantumFusion Serum', 'SynthoFlare-X', 'PlasmaQuell Acid', 'MolecularGlow Blend', 'Luminex Catalyst-X', 'ElectroWave Serum', 'CryoMyst Acid', 'NeuroFusion Elixir', 'NanoSizzle Blend-X', 'QuantumPulse Acid', 'RadiantFlare Serum', 'BioQuanta Catalyst', ]; + + const TASKS = [ + 'Teller abwaschen', 'Staubsaugen', 'Wäsche falten', 'Müll rausbringen', + 'Fenster putzen', 'Boden wischen', 'Einkaufen gehen', 'Betten machen', + 'Geschirrspüler ausräumen', 'Küche aufräumen', 'Blumen gießen', 'Bad reinigen', + 'Briefkasten leeren', 'Rasen mähen', 'Regale abstauben', 'Post sortieren', + 'Auto waschen', 'Kühlschrank sauber machen', 'Toilette putzen', 'Kleiderschrank aufräumen', + 'Abendessen kochen', 'Mittagessen vorbereiten', 'Frühstück zubereiten', 'Tisch decken', + 'Schuhe putzen', 'Bücher sortieren', 'Schreibtisch aufräumen', 'Pflanzen gießen', + 'Handtücher wechseln', 'Kinderzimmer aufräumen', 'Fahrzeuge auftanken', 'Keller entrümpeln', + 'Lampen abstauben', 'Kerzen anzünden', 'Bügelwäsche erledigen', 'Spiegel putzen', + 'Mülleimer säubern', 'Arbeitsflächen desinfizieren', 'Kamin reinigen', 'Gardinen waschen', + 'Kabel ordnen', 'Geschenke einpacken', 'Fahrrad pflegen', 'Teppiche saugen', + 'Dachboden organisieren', 'Zimmer lüften', 'Küchengeräte reinigen', 'Garderobe aufräumen', + 'Hausaufgaben machen', 'Papierkram sortieren', + ]; + } \ No newline at end of file diff --git a/src/Entity/Contact.php b/src/Entity/Contact.php index 5df5f4f..80ee7c4 100644 --- a/src/Entity/Contact.php +++ b/src/Entity/Contact.php @@ -30,7 +30,7 @@ class Contact #[ORM\Column(type: Types::DATE_MUTABLE, nullable: true)] private ?\DateTimeInterface $birthday = null; - #[ORM\ManyToOne(targetEntity: MediaObject::class)] + #[ORM\ManyToOne] #[ORM\JoinColumn(nullable: true, onDelete: "SET NULL")] private ?MediaObject $image = null; diff --git a/src/Entity/Task.php b/src/Entity/Task.php new file mode 100644 index 0000000..fabc718 --- /dev/null +++ b/src/Entity/Task.php @@ -0,0 +1,159 @@ +createdBy = $createdBy; + $this->assignedTo = $assignedTo; + $this->createdAt = new \DateTimeImmutable(); + } + + public function getId(): ?int + { + return $this->id; + } + + public function getHeadline(): ?string + { + return $this->headline; + } + + public function setHeadline(?string $headline): void + { + $this->headline = $headline; + } + + public function getDescription(): ?string + { + return $this->description; + } + + public function setDescription(?string $description): void + { + $this->description = $description; + } + + public function getCreatedBy(): ?User + { + return $this->createdBy; + } + + public function setCreatedBy(?User $createdBy): void + { + $this->createdBy = $createdBy; + } + + public function getAssignedTo(): ?User + { + return $this->assignedTo; + } + + public function setAssignedTo(?User $assignedTo): void + { + $this->assignedTo = $assignedTo; + } + + public function getDueAt(): ?\DateTimeImmutable + { + return $this->dueAt; + } + + public function setDueAt(?\DateTimeImmutable $dueAt): void + { + $this->dueAt = $dueAt; + } + + public function getPartner(): ?Partner + { + return $this->partner; + } + + public function setPartner(?Partner $partner): void + { + $this->partner = $partner; + } + + public function getContact(): ?Contact + { + return $this->contact; + } + + public function setContact(?Contact $contact): void + { + $this->contact = $contact; + } + + public function getPrio(): PrioType + { + return $this->prio; + } + + public function setPrio(PrioType $prio): void + { + $this->prio = $prio; + } + + public function getCompleted(): ?bool + { + return $this->completed; + } + + public function setCompleted(?bool $completed): void + { + $this->completed = $completed; + } + + public function getCreatedAt(): ?\DateTimeImmutable + { + return $this->createdAt; + } + +} diff --git a/src/Entity/User.php b/src/Entity/User.php index 534dd7c..8c96145 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -27,7 +27,7 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface #[ORM\Column(length: 255)] private ?string $lastName = null; - #[ORM\ManyToOne(targetEntity: MediaObject::class)] + #[ORM\ManyToOne] #[ORM\JoinColumn(nullable: true, onDelete: "SET NULL")] private ?MediaObject $image = null; diff --git a/src/Enum/PrioType.php b/src/Enum/PrioType.php new file mode 100644 index 0000000..7c1a2cb --- /dev/null +++ b/src/Enum/PrioType.php @@ -0,0 +1,15 @@ + + * @date 20.12.23 + */ + + +namespace App\Enum; + + +enum PrioType: string { + case Low = 'low'; + case Medium = 'medium'; + case High = 'high'; +} diff --git a/src/Factory/TaskFactory.php b/src/Factory/TaskFactory.php new file mode 100644 index 0000000..28c6131 --- /dev/null +++ b/src/Factory/TaskFactory.php @@ -0,0 +1,79 @@ + + * + * @method Task|Proxy create(array|callable $attributes = []) + * @method static Task|Proxy createOne(array $attributes = []) + * @method static Task|Proxy find(object|array|mixed $criteria) + * @method static Task|Proxy findOrCreate(array $attributes) + * @method static Task|Proxy first(string $sortedField = 'id') + * @method static Task|Proxy last(string $sortedField = 'id') + * @method static Task|Proxy random(array $attributes = []) + * @method static Task|Proxy randomOrCreate(array $attributes = []) + * @method static TaskRepository|RepositoryProxy repository() + * @method static Task[]|Proxy[] all() + * @method static Task[]|Proxy[] createMany(int $number, array|callable $attributes = []) + * @method static Task[]|Proxy[] createSequence(iterable|callable $sequence) + * @method static Task[]|Proxy[] findBy(array $attributes) + * @method static Task[]|Proxy[] randomRange(int $min, int $max, array $attributes = []) + * @method static Task[]|Proxy[] randomSet(int $number, array $attributes = []) + */ +final class TaskFactory extends ModelFactory +{ + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#factories-as-services + * + * @todo inject services if required + */ + public function __construct() + { + parent::__construct(); + } + + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#model-factories + * + * @todo add your default values here + */ + protected function getDefaults(): array + { + $randomBoolean = ContactFactory::count() > 0 && (bool)random_int(0, 1); + return [ + 'headline' => self::faker()->randomElement(FakeValues::TASKS), + 'description' => self::faker()->sentence(), + 'createdBy' => UserFactory::new(), + 'assignedTo' => UserFactory::random(), + 'partner' => PartnerFactory::random(), + 'contact' => $randomBoolean ? ContactFactory::random() : null, + 'dueAt' => \DateTimeImmutable::createFromMutable(self::faker()->dateTime()), + 'completed' => self::faker()->boolean(), + 'prio' => self::faker()->randomElement(PrioType::cases()), + ]; + } + + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#initialization + */ + protected function initialize(): self + { + return $this + // ->afterInstantiate(function(Task $task): void {}) + ; + } + + protected static function getClass(): string + { + return Task::class; + } +} diff --git a/src/Mapper/TaskApiToEntityMapper.php b/src/Mapper/TaskApiToEntityMapper.php new file mode 100644 index 0000000..1550e1d --- /dev/null +++ b/src/Mapper/TaskApiToEntityMapper.php @@ -0,0 +1,76 @@ +microMapper->map($dto->assignedTo, User::class, [ + MicroMapperInterface::MAX_DEPTH => 1, + ]); + + if ($dto->id) { + $entity = $this->repository->find($dto->id); + if (!$entity) { + throw new \Exception('Task not found'); + } + $entity->setAssignedTo($assignedTo); + } else { + $user = $this->security->getUser(); + assert($user instanceof User); + assert($assignedTo instanceof User); + $entity = new Task($user, $assignedTo); + } + + if (!$entity) { + throw new \Exception('Task not found'); + } + + return $entity; + } + + public function populate(object $from, object $to, array $context): object + { + $dto = $from; + assert($dto instanceof TaskApi); + $entity = $to; + assert($entity instanceof Task); + $entity->setHeadline($dto->headline); + $entity->setDescription($dto->description); + $entity->setDueAt($dto->dueAt); + $entity->setPartner($this->microMapper->map($dto->partner, Partner::class, [ + MicroMapperInterface::MAX_DEPTH => 1, + ])); + $entity->setContact($this->microMapper->map($dto->contact, Contact::class, [ + MicroMapperInterface::MAX_DEPTH => 1, + ])); + $entity->setPrio($dto->prio); + $entity->setCompleted($dto->completed); + return $entity; + } +} diff --git a/src/Mapper/TaskEntityToApiMapper.php b/src/Mapper/TaskEntityToApiMapper.php new file mode 100644 index 0000000..d89746c --- /dev/null +++ b/src/Mapper/TaskEntityToApiMapper.php @@ -0,0 +1,73 @@ +id = $entity->getId(); + + return $dto; + } + + public function populate(object $from, object $to, array $context): object + { + $entity = $from; + $dto = $to; + assert($entity instanceof Task); + assert($dto instanceof TaskApi); + + $dto->headline = $entity->getHeadline(); + $dto->description = $entity->getDescription(); + $dto->createdBy = $this->microMapper->map($entity->getCreatedBy(), UserApi::class, [ + MicroMapperInterface::MAX_DEPTH => 1, + ]); + $dto->assignedTo = $this->microMapper->map($entity->getAssignedTo(), UserApi::class, [ + MicroMapperInterface::MAX_DEPTH => 1, + ]); + $dto->dueAt = $entity->getDueAt(); + + if ($entity->getPartner()) { + $dto->partner = $this->microMapper->map($entity->getPartner(), PartnerApi::class, [ + MicroMapperInterface::MAX_DEPTH => 1, + ]); + } + + if ($entity->getContact() !== null) { + $dto->contact = $this->microMapper->map($entity->getContact(), ContactApi::class, [ + MicroMapperInterface::MAX_DEPTH => 1, + ]); + } + + $dto->prio = $entity->getPrio(); + $dto->completed = $entity->getCompleted(); + $dto->createdAt = $entity->getCreatedAt(); + + return $dto; + } +} diff --git a/src/Repository/TaskRepository.php b/src/Repository/TaskRepository.php new file mode 100644 index 0000000..4625837 --- /dev/null +++ b/src/Repository/TaskRepository.php @@ -0,0 +1,48 @@ + + * + * @method Task|null find($id, $lockMode = null, $lockVersion = null) + * @method Task|null findOneBy(array $criteria, array $orderBy = null) + * @method Task[] findAll() + * @method Task[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class TaskRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Task::class); + } + +// /** +// * @return Task[] Returns an array of Task objects +// */ +// public function findByExampleField($value): array +// { +// return $this->createQueryBuilder('t') +// ->andWhere('t.exampleField = :val') +// ->setParameter('val', $value) +// ->orderBy('t.id', 'ASC') +// ->setMaxResults(10) +// ->getQuery() +// ->getResult() +// ; +// } + +// public function findOneBySomeField($value): ?Task +// { +// return $this->createQueryBuilder('t') +// ->andWhere('t.exampleField = :val') +// ->setParameter('val', $value) +// ->getQuery() +// ->getOneOrNullResult() +// ; +// } +} diff --git a/tests/Functional/TaskResourceTest.php b/tests/Functional/TaskResourceTest.php new file mode 100644 index 0000000..3e69391 --- /dev/null +++ b/tests/Functional/TaskResourceTest.php @@ -0,0 +1,84 @@ + + * @date 12.12.23 + */ + + +namespace App\Tests\Functional; + +use App\Enum\PartnerType; +use App\Factory\CommentFactory; +use App\Factory\ContactFactory; +use App\Factory\MediaObjectLogoFactory; +use App\Factory\MediaObjectContactFactory; +use App\Factory\PartnerFactory; +use App\Factory\PostingFactory; +use App\Factory\UserFactory; +use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface; +use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; +use Zenstruck\Browser\Test\HasBrowser; +use Zenstruck\Foundry\Test\Factories; +use Zenstruck\Foundry\Test\ResetDatabase; + +class TaskResourceTest extends KernelTestCase +{ + use HasBrowser; + use ResetDatabase; + use Factories; + + private JWTTokenManagerInterface $JWTManager; + + protected function setUp(): void + { + parent::setUp(); + $this->JWTManager = self::getContainer()->get('lexik_jwt_authentication.jwt_manager'); + } + + public function testPostTask(): void + { + $user = UserFactory::createOne( + [ + 'firstName' => 'Peter', + 'lastName' => 'Test', + 'password' => 'test', + 'email' => 'peter@test.de', + ] + ); + $partner = PartnerFactory::createOne(); + $contact = ContactFactory::createOne(); + + $token = $this->JWTManager->create($user->object()); + + $this->browser() + ->post('/api/tasks' , [ + 'json' => [ + 'headline' => 'new task', + 'description' => 'this is what is to do...', + 'assignedTo' => '/api/users/' . $user->getId(), + 'dueAt'=> "2024-03-12T08:57:39.892Z", + 'partner'=> "/api/partners/" . $partner->getId(), + 'contact'=> "/api/contacts/" . $contact->getId(), + 'prio'=> "low", + 'completed'=> false, + ], + 'headers' => [ + 'Authorization' => 'Bearer ' . $token, + ] + ]) + ->assertSuccessful() + ; + + $this->browser() + ->get('/api/tasks', [ + 'headers' => [ + 'Authorization' => 'Bearer ' . $token, + ], + ]) + ->assertSuccessful() + ->assertJsonMatches('"hydra:totalItems"', 1) + ->assertJsonMatches('"hydra:member"[0].headline', 'new task') + ; + + } +} \ No newline at end of file