ソースを参照

unit tests working

master
Daniel 2年前
コミット
e9a55ab7f5
31個のファイルの変更713行の追加370行の削除
  1. +263
    -263
      composer.lock
  2. +2
    -2
      src/ApiResource/CommentApi.php
  3. +3
    -2
      src/ApiResource/ContactApi.php
  4. +2
    -1
      src/ApiResource/PartnerApi.php
  5. +13
    -3
      src/ApiResource/PostingApi.php
  6. +4
    -3
      src/ApiResource/UserApi.php
  7. +3
    -15
      src/Entity/Comment.php
  8. +7
    -7
      src/Entity/Contact.php
  9. +1
    -0
      src/Entity/MediaObject.php
  10. +5
    -0
      src/Entity/Posting.php
  11. +1
    -1
      src/EventListener/AuthenticationSuccessListener.php
  12. +1
    -1
      src/Factory/PostingFactory.php
  13. +16
    -10
      src/Mapper/CommentApiToEntityMapper.php
  14. +3
    -4
      src/Mapper/CommentEntityToApiMapper.php
  15. +1
    -3
      src/Mapper/ContactApiToEntityMapper.php
  16. +4
    -4
      src/Mapper/ContactEntityToApiMapper.php
  17. +1
    -12
      src/Mapper/PartnerApiToEntityMapper.php
  18. +1
    -1
      src/Mapper/PartnerEntityToApiMapper.php
  19. +2
    -2
      src/Mapper/PostingApiToEntityMapper.php
  20. +2
    -2
      src/Mapper/UserApiToEntityMapper.php
  21. +2
    -2
      src/Mapper/UserEntityToApiMapper.php
  22. +46
    -0
      src/Voter/CommentApiVoter.php
  23. +2
    -6
      src/Voter/PostingApiVoter.php
  24. +1
    -2
      src/Voter/UserApiVoter.php
  25. +78
    -0
      tests/Functional/CommentResourceTest.php
  26. +82
    -0
      tests/Functional/ContactResourceTest.php
  27. +66
    -0
      tests/Functional/MediaObjectResourceTest.php
  28. +79
    -0
      tests/Functional/PartnerResourceTest.php
  29. +11
    -12
      tests/Functional/PostingResourceTest.php
  30. +11
    -12
      tests/Functional/UserResourceTest.php
  31. バイナリ
      tests/fixtures/1176.png

+ 263
- 263
composer.lock
ファイル差分が大きすぎるため省略します
ファイルの表示


+ 2
- 2
src/ApiResource/CommentApi.php ファイルの表示

@@ -54,13 +54,13 @@ class CommentApi
#[NotBlank]
public ?string $message = null;

#[IsValidOwner]
#[ApiProperty(writable: false)]
public ?UserApi $owner = null;

#[ApiProperty(writable: false)]
public ?string $ownerName = null;

public ?PostingApi $posting = null;
public ?PostingApi $post = null;

#[ApiProperty(writable: false)]
public ?\DateTimeImmutable $createdAt = null;


+ 3
- 2
src/ApiResource/ContactApi.php ファイルの表示

@@ -35,7 +35,7 @@ use Symfony\Component\Validator\Constraints\NotBlank;
security: 'is_granted("ROLE_USER")',
),
new Patch(
security: 'is_granted("EDIT", object)',
security: 'is_granted("ROLE_USER")',
),
new Delete(
security: 'is_granted("ROLE_ADMIN")',
@@ -59,6 +59,7 @@ class ContactApi
#[NotBlank]
public ?string $lastName = null;

#[NotBlank]
public ?PartnerApi $partner = null;

public ?\DateTimeInterface $birthday = null;
@@ -79,7 +80,7 @@ class ContactApi
* @var array<int, PostingApi>
*/
#[ApiProperty(writable: false)]
public array $postings = [];
public array $posts = [];

#[ApiProperty(writable: false)]
public ?\DateTimeImmutable $createdAt = null;

+ 2
- 1
src/ApiResource/PartnerApi.php ファイルの表示

@@ -37,7 +37,7 @@ use Symfony\Component\Validator\Constraints\NotBlank;
security: 'is_granted("ROLE_USER")',
),
new Patch(
security: 'is_granted("EDIT", object)',
security: 'is_granted("ROLE_USER")',
),
new Delete(
security: 'is_granted("ROLE_ADMIN")',
@@ -84,5 +84,6 @@ class PartnerApi
/**
* @var array<int, ContactApi>
*/
#[ApiProperty(writable: false)]
public array $contacts = [];
}

+ 13
- 3
src/ApiResource/PostingApi.php ファイルの表示

@@ -20,8 +20,9 @@ use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Patch;
use ApiPlatform\Metadata\Post;
use App\Validator\IsValidOwner;
use Symfony\Component\PropertyInfo\Type;
use Symfony\Component\Serializer\Attribute\Groups;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Constraints\NotBlank;

#[ApiResource(
@@ -34,9 +35,11 @@ use Symfony\Component\Validator\Constraints\NotBlank;
security: 'is_granted("ROLE_USER")',
),
new Post(
denormalizationContext: ['groups' => 'posting_create'],
security: 'is_granted("ROLE_USER")',
),
new Patch(
denormalizationContext: ['groups' => 'posting_patch'],
security: 'is_granted("EDIT", object)',
),
new Delete(
@@ -55,28 +58,35 @@ class PostingApi
public ?int $id = null;

#[NotBlank]
#[Groups(['posting_create', 'posting_patch'])]
public ?string $headline = null;

#[NotBlank]
#[Groups(['posting_create', 'posting_patch'])]
public ?string $message = null;

//#[IsValidOwner]
#[ApiProperty(writable: false)]
public ?UserApi $owner = null;

#[ApiProperty(writable: false)]
public ?string $ownerName = null;

#[ApiProperty(writable: true)]
#[Groups(['posting_create'])]
#[Assert\NotBlank(groups: ['posting_create'])]
public ?PartnerApi $partner = null;

#[ApiProperty(writable: true)]
#[Groups(['posting_create'])]
public ?ContactApi $contact = null;

/**
* @var array<int, CommentApi>
*/
#[ApiProperty(
writable: false,
readableLink: true,
writableLink: true,
writableLink: false,
fetchEager: true,
builtinTypes: [
new Type(


+ 4
- 3
src/ApiResource/UserApi.php ファイルの表示

@@ -30,10 +30,10 @@ use Symfony\Component\Validator\Constraints as Assert;
),
new Post(
security: 'is_granted("ROLE_ADMIN")',
validationContext: ['groups' => ['Default', 'postValidation']],
validationContext: ['groups' => ['Default', 'postValidation']]
),
new Patch(
security: 'is_granted("ROLE_USER")'
security: 'is_granted("is_granted("EDIT", object)")'
),
],
security: 'is_granted("ROLE_USER")',
@@ -74,7 +74,8 @@ class UserApi
/**
* @var array<int, PostingApi>
*/
public array $postings = [];
#[ApiProperty(writable: false)]
public array $posts = [];

#[ApiProperty(writable: false)]
public ?\DateTimeImmutable $createdAt = null;


+ 3
- 15
src/Entity/Comment.php ファイルの表示

@@ -28,8 +28,10 @@ class Comment
#[ORM\Column]
private ?\DateTimeImmutable $createdAt = null;

public function __construct()
public function __construct(User $owner, Posting $posting)
{
$this->owner = $owner;
$this->posting = $posting;
$this->createdAt = new \DateTimeImmutable();
}

@@ -62,25 +64,11 @@ class Comment
return $this->owner;
}

public function setOwner(?User $owner): static
{
$this->owner = $owner;

return $this;
}

public function getPosting(): ?Posting
{
return $this->posting;
}

public function setPosting(?Posting $posting): static
{
$this->posting = $posting;

return $this;
}

public function getCreatedAt(): ?\DateTimeImmutable
{
return $this->createdAt;


+ 7
- 7
src/Entity/Contact.php ファイルの表示

@@ -46,13 +46,13 @@ class Contact
private ?\DateTimeImmutable $createdAt = null;

#[ORM\OneToMany(mappedBy: 'contact', targetEntity: Posting::class, orphanRemoval: true)]
private Collection $postings;
private Collection $posts;

public function __construct(Partner $partner)
{
$this->partner = $partner;
$this->createdAt = new \DateTimeImmutable();
$this->postings = new ArrayCollection();
$this->posts = new ArrayCollection();
}

public function getId(): ?int
@@ -169,15 +169,15 @@ class Contact
/**
* @return Collection<int, Posting>
*/
public function getPostings(): Collection
public function getPosts(): Collection
{
return $this->postings;
return $this->posts;
}

public function addPosting(Posting $posting): static
{
if (!$this->postings->contains($posting)) {
$this->postings->add($posting);
if (!$this->posts->contains($posting)) {
$this->posts->add($posting);
$posting->setContact($this);
}

@@ -186,7 +186,7 @@ class Contact

public function removePosting(Posting $posting): static
{
if ($this->postings->removeElement($posting)) {
if ($this->posts->removeElement($posting)) {
// set the owning side to null (unless already changed)
if ($posting->getContact() === $this) {
$posting->setContact(null);


+ 1
- 0
src/Entity/MediaObject.php ファイルの表示

@@ -23,6 +23,7 @@ use Vich\UploaderBundle\Mapping\Annotation as Vich;
#[Vich\Uploadable]
#[ORM\Entity]
#[ApiResource(
shortName: 'Media',
types: ['https://schema.org/MediaObject'],
operations: [
new Get(),


+ 5
- 0
src/Entity/Posting.php ファイルの表示

@@ -70,6 +70,11 @@ class Posting
return $this->createdAt;
}

public function setOwner(?User $owner): void
{
$this->owner = $owner;
}

public function getOwner(): ?User
{
return $this->owner;


+ 1
- 1
src/EventListener/AuthenticationSuccessListener.php ファイルの表示

@@ -38,7 +38,7 @@ class AuthenticationSuccessListener
}

$userApi = $this->microMapper->map($user, UserApi::class, [
MicroMapperInterface::MAX_DEPTH => 3,
MicroMapperInterface::MAX_DEPTH => 1,
]);

$data['id'] = $this->iriConverter->getIriFromResource($userApi);


+ 1
- 1
src/Factory/PostingFactory.php ファイルの表示

@@ -46,7 +46,7 @@ final class PostingFactory extends ModelFactory
*/
protected function getDefaults(): array
{
$randomBoolean = (bool)random_int(0, 1);
$randomBoolean = ContactFactory::count() > 0 && (bool)random_int(0, 1);
return [
'headline' => self::faker()->words(random_int(1, 5), true),
'message' => $randomBoolean ? self::faker()->sentence() : self::faker()->sentences(random_int(1, 3), true),


+ 16
- 10
src/Mapper/CommentApiToEntityMapper.php ファイルの表示

@@ -4,6 +4,7 @@ namespace App\Mapper;

use App\ApiResource\CommentApi;
use App\Entity\Comment;
use App\Entity\Posting;
use App\Entity\User;
use App\Repository\CommentRepository;
use Symfony\Bundle\SecurityBundle\Security;
@@ -28,7 +29,21 @@ class CommentApiToEntityMapper implements MapperInterface
$dto = $from;
assert($dto instanceof CommentApi);

$entity = $dto->id ? $this->repository->find($dto->id) : new Comment();
if ($dto->id) {
$entity = $this->repository->find($dto->id);
} else {
$user = $this->security->getUser();
assert($user instanceof User);
if ($dto->post === null) {
throw new \Exception('Posting missing');
}
$posting = $this->microMapper->map($dto->post, Posting::class, [
MicroMapperInterface::MAX_DEPTH => 1,
]);
assert($posting instanceof Posting);
$entity = new Comment($user, $posting);
}

if (!$entity) {
throw new \Exception('Comment not found');
}
@@ -42,15 +57,6 @@ class CommentApiToEntityMapper implements MapperInterface
assert($dto instanceof CommentApi);
$entity = $to;
assert($entity instanceof Comment);

if ($dto->owner) {
$entity->setOwner($this->microMapper->map($dto->owner, User::class, [
MicroMapperInterface::MAX_DEPTH => 1,
]));
} else {
$entity->setOwner($this->security->getUser());
}
$entity->setPosting($dto->posting);
$entity->setMessage($dto->message);

return $entity;


+ 3
- 4
src/Mapper/CommentEntityToApiMapper.php ファイルの表示

@@ -15,8 +15,7 @@ use Symfonycasts\MicroMapper\MicroMapperInterface;
class CommentEntityToApiMapper implements MapperInterface
{
public function __construct(
private MicroMapperInterface $microMapper,
private Security $security,
private MicroMapperInterface $microMapper
)
{
}
@@ -41,12 +40,12 @@ class CommentEntityToApiMapper implements MapperInterface

$dto->message = $entity->getMessage();
$dto->owner = $this->microMapper->map($entity->getOwner(), UserApi::class, [
MicroMapperInterface::MAX_DEPTH => 0,
MicroMapperInterface::MAX_DEPTH => 1,
]);
$dto->ownerName = $entity->getOwner()?->getFirstName()." ".$entity->getOwner()?->getLastName();

$dto->posting = $this->microMapper->map($entity->getPosting(), PostingApi::class, [
MicroMapperInterface::MAX_DEPTH => 0,
MicroMapperInterface::MAX_DEPTH => 1,
]);

$dto->createdAt = $entity->getCreatedAt();


+ 1
- 3
src/Mapper/ContactApiToEntityMapper.php ファイルの表示

@@ -17,7 +17,6 @@ class ContactApiToEntityMapper implements MapperInterface
{
public function __construct(
private ContactRepository $repository,
private Security $security,
private MicroMapperInterface $microMapper,
)
{
@@ -36,7 +35,7 @@ class ContactApiToEntityMapper implements MapperInterface
throw new \Exception('Partner missing');
}
$partner = $this->microMapper->map($dto->partner, Partner::class, [
MicroMapperInterface::MAX_DEPTH => 0,
MicroMapperInterface::MAX_DEPTH => 1,
]);
$entity = new Contact($partner);
}
@@ -58,7 +57,6 @@ class ContactApiToEntityMapper implements MapperInterface

$entity->setFirstName($dto->firstName);
$entity->setLastName($dto->lastName);
$entity->setPartner($dto->partner);
$entity->setBirthday($dto->birthday);
$entity->setImage($dto->image);
$entity->setPosition($dto->position);


+ 4
- 4
src/Mapper/ContactEntityToApiMapper.php ファイルの表示

@@ -44,7 +44,7 @@ class ContactEntityToApiMapper implements MapperInterface
$dto->lastName = $entity->getLastName();
$dto->partner = $this->microMapper->map(
$entity->getPartner(), PartnerApi::class, [
MicroMapperInterface::MAX_DEPTH => 0,
MicroMapperInterface::MAX_DEPTH => 1,
]
);
$dto->birthday = $entity->getBirthday();
@@ -55,11 +55,11 @@ class ContactEntityToApiMapper implements MapperInterface
$dto->email = $entity->getEmail();
$dto->createdAt = $entity->getCreatedAt();

$dto->postings = array_map(function(Posting $posting) {
$dto->posts = array_map(function(Posting $posting) {
return $this->microMapper->map($posting, PostingApi::class, [
MicroMapperInterface::MAX_DEPTH => 0,
MicroMapperInterface::MAX_DEPTH => 1,
]);
}, $entity->getPostings()->getValues());
}, $entity->getPosts()->getValues());

return $dto;
}


+ 1
- 12
src/Mapper/PartnerApiToEntityMapper.php ファイルの表示

@@ -19,10 +19,7 @@ use Symfonycasts\MicroMapper\MicroMapperInterface;
class PartnerApiToEntityMapper implements MapperInterface
{
public function __construct(
private PartnerRepository $repository,
private Security $security,
private MicroMapperInterface $microMapper,
private PropertyAccessorInterface $propertyAccessor,
private PartnerRepository $repository
)
{

@@ -58,14 +55,6 @@ class PartnerApiToEntityMapper implements MapperInterface
$entity->setWebsite($dto->website);
$entity->setLogo($dto->logo);

$contactEntities = [];
foreach ($dto->contacts as $contactApi) {
$contactEntities[] = $this->microMapper->map($contactApi, Contact::class, [
MicroMapperInterface::MAX_DEPTH => 0,
]);
}
$this->propertyAccessor->setValue($entity, 'contacts', $contactEntities);

return $entity;
}
}

+ 1
- 1
src/Mapper/PartnerEntityToApiMapper.php ファイルの表示

@@ -52,7 +52,7 @@ class PartnerEntityToApiMapper implements MapperInterface
$dto->createdAt = $entity->getCreatedAt();
$dto->contacts = array_map(function(Contact $contact) {
return $this->microMapper->map($contact, ContactApi::class, [
MicroMapperInterface::MAX_DEPTH => 0,
MicroMapperInterface::MAX_DEPTH => 1,
]);
}, $entity->getContacts()->getValues());
return $dto;


+ 2
- 2
src/Mapper/PostingApiToEntityMapper.php ファイルの表示

@@ -40,13 +40,13 @@ class PostingApiToEntityMapper implements MapperInterface
throw new \Exception('Partner missing');
}
$partner = $this->microMapper->map($dto->partner, Partner::class, [
MicroMapperInterface::MAX_DEPTH => 0,
MicroMapperInterface::MAX_DEPTH => 1,
]);
$contact = null;
if ($dto->contact) {
assert($dto->contact instanceof ContactApi);
$contact = $this->microMapper->map($dto->contact, Contact::class, [
MicroMapperInterface::MAX_DEPTH => 0,
MicroMapperInterface::MAX_DEPTH => 1,
]);
}
assert($partner instanceof Partner);


+ 2
- 2
src/Mapper/UserApiToEntityMapper.php ファイルの表示

@@ -53,9 +53,9 @@ class UserApiToEntityMapper implements MapperInterface
}

$userPostsEntities = new ArrayCollection();
foreach ($dto->postings as $userPostApi) {
foreach ($dto->posts as $userPostApi) {
$userPostsEntities[] = $this->microMapper->map($userPostApi, Posting::class, [
MicroMapperInterface::MAX_DEPTH => 0,
MicroMapperInterface::MAX_DEPTH => 1,
]);
}
$this->propertyAccessor->setValue($entity, 'postings', $userPostsEntities);


+ 2
- 2
src/Mapper/UserEntityToApiMapper.php ファイルの表示

@@ -41,9 +41,9 @@ class UserEntityToApiMapper implements MapperInterface
$dto->firstName = $entity->getFirstName();
$dto->lastName = $entity->getLastName();

$dto->postings = array_map(function(Posting $posting) {
$dto->posts = array_map(function(Posting $posting) {
return $this->microMapper->map($posting, PostingApi::class, [
MicroMapperInterface::MAX_DEPTH => 0,
MicroMapperInterface::MAX_DEPTH => 1,
]);
}, $entity->getPostings()->getValues());



+ 46
- 0
src/Voter/CommentApiVoter.php ファイルの表示

@@ -0,0 +1,46 @@
<?php

namespace App\Voter;

use App\ApiResource\CommentApi;
use App\ApiResource\PostingApi;
use App\Entity\User;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;

class CommentApiVoter extends Voter
{
public const EDIT = 'EDIT';

public function __construct()
{
}

protected function supports(string $attribute, mixed $subject): bool
{
return $attribute === self::EDIT && $subject instanceof CommentApi;
}

protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
{
$user = $token->getUser();
// if the user is anonymous, do not grant access
if (!$user instanceof User) {
return false;
}

assert($subject instanceof CommentApi);

// ... (check conditions and return true to grant permission) ...
switch ($attribute) {
case self::EDIT:
if ($subject->owner?->id === $user->getId()) {
return true;
}
break;
}

return false;
}
}

+ 2
- 6
src/Voter/PostingApiVoter.php ファイルの表示

@@ -12,13 +12,13 @@ class PostingApiVoter extends Voter
{
public const EDIT = 'EDIT';

public function __construct(private Security $security)
public function __construct()
{
}

protected function supports(string $attribute, mixed $subject): bool
{
return in_array($attribute, [self::EDIT]) && $subject instanceof PostingApi;
return $attribute === self::EDIT && $subject instanceof PostingApi;
}

protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
@@ -29,10 +29,6 @@ class PostingApiVoter extends Voter
return false;
}

if ($this->security->isGranted('ROLE_ADMIN')) {
return true;
}

assert($subject instanceof PostingApi);

// ... (check conditions and return true to grant permission) ...


+ 1
- 2
src/Voter/UserApiVoter.php ファイルの表示

@@ -18,12 +18,11 @@ class UserApiVoter extends Voter

protected function supports(string $attribute, mixed $subject): bool
{
return in_array($attribute, [self::EDIT]) && $subject instanceof UserApi;
return $attribute === self::EDIT && $subject instanceof UserApi;
}

protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
{
//dd($subject);
$user = $token->getUser();
// if the user is anonymous, do not grant access
if (!$user instanceof User) {


+ 78
- 0
tests/Functional/CommentResourceTest.php ファイルの表示

@@ -0,0 +1,78 @@
<?php
/**
* @author Daniel Knudsen <d.knudsen@spawntree.de>
* @date 12.12.23
*/


namespace App\Tests\Functional;

use App\Enum\PartnerType;
use App\Factory\CommentFactory;
use App\Factory\MediaObjectLogoFactory;
use App\Factory\MediaObjectProfileFactory;
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 CommentResourceTest 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 testPostComment(): void
{
$user = UserFactory::createOne(
[
'firstName' => 'Peter',
'lastName' => 'Test',
'password' => 'test',
'email' => 'peter@test.de',
]
);
MediaObjectLogoFactory::createOne();
PartnerFactory::createOne();
$posting = PostingFactory::createOne();
CommentFactory::createOne();

$token = $this->JWTManager->create($user->object());

$this->browser()
->post('/api/comments' , [
'json' => [
'message' => 'my comment',
'post' => '/api/posts/' . $posting->getId(),
],
'headers' => [
'Authorization' => 'Bearer ' . $token,
]
])
->assertSuccessful()
;

$this->browser()
->get('/api/comments', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
],
])
->assertSuccessful()
->assertJsonMatches('"hydra:totalItems"', 2)
->assertJsonMatches('"hydra:member"[1].message', 'my comment')
;
}
}

+ 82
- 0
tests/Functional/ContactResourceTest.php ファイルの表示

@@ -0,0 +1,82 @@
<?php
/**
* @author Daniel Knudsen <d.knudsen@spawntree.de>
* @date 12.12.23
*/


namespace App\Tests\Functional;

use App\Enum\PartnerType;
use App\Factory\MediaObjectLogoFactory;
use App\Factory\MediaObjectProfileFactory;
use App\Factory\PartnerFactory;
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 ContactResourceTest 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 testPostContact(): void
{
MediaObjectLogoFactory::createOne();
$partner = PartnerFactory::createOne();
$user = UserFactory::createOne(
[
'firstName' => 'Peter',
'lastName' => 'Test',
'password' => 'test',
'email' => 'peter@test.de',
]
);

$mediaObject = MediaObjectProfileFactory::createOne();

$token = $this->JWTManager->create($user->object());

$this->browser()
->post('/api/contacts' , [
'json' => [
'firstName' => 'Peter',
'lastName' => 'Test',
'partner' => '/api/partners/' . $partner->getId(),
'birthday' => '1984-02-10',
'image' => '/api/medias/' . $mediaObject->getId(),
'position' => 'CEO',
'phone' => '123456789',
'email' => 'peter@test2.de',
],
'headers' => [
'Authorization' => 'Bearer ' . $token,
]
])
->assertSuccessful()
;

$this->browser()
->get('/api/contacts', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
],
])
->assertSuccessful()
->assertJsonMatches('"hydra:totalItems"', 1)
->assertJsonMatches('"hydra:member"[0].position', 'CEO')
;
}
}

+ 66
- 0
tests/Functional/MediaObjectResourceTest.php ファイルの表示

@@ -0,0 +1,66 @@
<?php
/**
* @author Daniel Knudsen <d.knudsen@spawntree.de>
* @date 01.03.24
*/


namespace App\Tests\Functional;

use App\Factory\UserFactory;
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Zenstruck\Browser\Test\HasBrowser;
use Zenstruck\Foundry\Test\Factories;
use Zenstruck\Foundry\Test\ResetDatabase;

class MediaObjectResourceTest extends KernelTestCase
{
use HasBrowser;
use ResetDatabase;
use Factories;

private JWTTokenManagerInterface $JWTManager;
private string $projectDir;

protected function setUp(): void
{
parent::setUp();
$this->JWTManager = self::getContainer()->get('lexik_jwt_authentication.jwt_manager');
$this->projectDir = self::getContainer()->get('kernel')->getProjectDir();
}

public function testCreateAMediaObject(): void
{
$path = $this->projectDir . '/tests/fixtures/';
$srcFile = $path . '1176.png';
$dstFile = $path . '1176_upload.png';
copy($srcFile, $dstFile);

$file = new UploadedFile($dstFile, 'image.png');

$user = UserFactory::createOne(
[
'firstName' => 'Peter',
'lastName' => 'Test',
'password' => 'test',
'email' => 'peter@test.de',
]
);
$token = $this->JWTManager->create($user->object());

$this->browser()
->post('/api/medias', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Content-Type' => 'multipart/form-data'
],
'files' => [
'file' => $file,
],
])
->assertSuccessful()
;
}
}

+ 79
- 0
tests/Functional/PartnerResourceTest.php ファイルの表示

@@ -0,0 +1,79 @@
<?php
/**
* @author Daniel Knudsen <d.knudsen@spawntree.de>
* @date 12.12.23
*/


namespace App\Tests\Functional;

use App\Enum\PartnerType;
use App\Factory\MediaObjectLogoFactory;
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 PartnerResourceTest 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 testPostPartner(): void
{
$user = UserFactory::createOne(
[
'email' => 'peter@test.de',
'firstName' => 'Peter',
'lastName' => 'Test',
'password' => 'test',
]
);

$mediaObject = MediaObjectLogoFactory::createOne();
$token = $this->JWTManager->create($user->object());

$this->browser()
->post('/api/partners' , [
'json' => [
'name' => 'test customer',
'type' => PartnerType::Customer,
'street' => 'test street',
'streetNo' => '11',
'zip' => '22335',
'city' => 'test city',
'country' => 'test country',
'website' => 'wwe.test.de',
'logo' => '/api/medias/' . $mediaObject->getId(),
],
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Content-Type' => 'application/ld+json'
]
])
->assertSuccessful()
;

$this->browser()
->get('/api/partners', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
],
])
->assertSuccessful()
->assertJsonMatches('"hydra:totalItems"', 1)
->assertJsonMatches('"hydra:member"[0].name', 'test customer')
;
}
}

+ 11
- 12
tests/Functional/PostingResourceTest.php ファイルの表示

@@ -13,6 +13,7 @@ use App\Factory\MediaObjectProfileFactory;
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;
@@ -24,9 +25,17 @@ class PostingResourceTest extends KernelTestCase
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 testPostPosting(): void
{
UserFactory::createOne(
$user = UserFactory::createOne(
[
'email' => 'peter@test.de',
'firstName' => 'Peter',
@@ -41,17 +50,7 @@ class PostingResourceTest extends KernelTestCase
$contact = ContactFactory::createOne();
PostingFactory::createOne();

$response = $this->browser()
->post('/auth', [
'json' => [
'email' => 'peter@test.de',
'password' => 'test',
]
])
->assertSuccessful()
->content();
$authResponseData = json_decode($response, true);
$token = $authResponseData['token'];
$token = $this->JWTManager->create($user->object());

$this->browser()
->post('/api/posts' , [


+ 11
- 12
tests/Functional/UserResourceTest.php ファイルの表示

@@ -8,6 +8,7 @@
namespace App\Tests\Functional;

use App\Factory\UserFactory;
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Zenstruck\Browser\Json;
use Zenstruck\Browser\Test\HasBrowser;
@@ -20,6 +21,14 @@ class UserResourceTest extends KernelTestCase
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 testPostUser(): void
{
UserFactory::createOne(
@@ -79,7 +88,7 @@ class UserResourceTest extends KernelTestCase

public function testPostUserNoAdmin(): void
{
UserFactory::createOne(
$user = UserFactory::createOne(
[
'email' => 'peter@test.de',
'firstName' => 'Peter',
@@ -87,18 +96,8 @@ class UserResourceTest extends KernelTestCase
'password' => 'test',
]
);
$response = $this->browser()
->post('/auth', [
'json' => [
'email' => 'peter@test.de',
'password' => 'test',
]
])
->assertSuccessful()
->content();
$authResponseData = json_decode($response, true);
$token = $authResponseData['token'];

$token = $this->JWTManager->create($user->object());
$this->browser()
->post('/api/users' , [
'json' => [


バイナリ
tests/fixtures/1176.png ファイルの表示

変更前 変更後
幅: 256  |  高さ: 256  |  サイズ: 3.9 KiB

読み込み中…
キャンセル
保存