Skip to content

Commit e97ddff

Browse files
committed
test: Add some tests for the Concise class
1 parent 73011e5 commit e97ddff

File tree

7 files changed

+211
-42
lines changed

7 files changed

+211
-42
lines changed

src/Concise.php

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Illuminate\Database\RecordsNotFoundException;
1010
use Illuminate\Foundation\Application;
1111
use Illuminate\Support\Str;
12+
use InvalidArgumentException;
1213
use ReflectionClass;
1314
use RuntimeException;
1415
use Throwable;
@@ -40,13 +41,22 @@ public function __construct(Application $app)
4041
*
4142
* @template MapperObject of object
4243
*
43-
* @param \Articulate\Concise\Contracts\Mapper<MapperObject> $mapper
44-
* @param bool $overwrite
44+
* @param \Articulate\Concise\Contracts\Mapper<MapperObject>|class-string<\Articulate\Concise\Contracts\Mapper<MapperObject>> $mapper
45+
* @param bool $overwrite
4546
*
4647
* @return bool
4748
*/
48-
public function register(Mapper $mapper, bool $overwrite = false): bool
49+
public function register(Mapper|string $mapper, bool $overwrite = false): bool
4950
{
51+
if (is_string($mapper)) {
52+
/** @phpstan-ignore function.alreadyNarrowedType */
53+
if (! is_subclass_of($mapper, Mapper::class)) {
54+
throw new InvalidArgumentException('Class [' . $mapper . '] is not a valid mapper.');
55+
}
56+
57+
$mapper = new $mapper($this);
58+
}
59+
5060
if ($mapper instanceof EntityMapper) {
5161
if ($overwrite === false && isset($this->entityMappers[$mapper->class()])) {
5262
return false;
@@ -83,6 +93,23 @@ public function entity(string $class): ?EntityMapper
8393
return $mapper;
8494
}
8595

96+
/**
97+
* Get a registered component mapper for the provided class.
98+
*
99+
* @template ComponentObject of object
100+
*
101+
* @param class-string<ComponentObject> $class
102+
*
103+
* @return \Articulate\Concise\Contracts\Mapper<ComponentObject>|null
104+
*/
105+
public function component(string $class): ?Mapper
106+
{
107+
/** @var \Articulate\Concise\Contracts\Mapper<ComponentObject>|null $mapper */
108+
$mapper = $this->componentMappers[$class] ?? null;
109+
110+
return $mapper;
111+
}
112+
86113
/**
87114
* Get an entity repository for the provided class.
88115
*
@@ -164,6 +191,8 @@ function (object $proxy) use ($repository, $identity, $mapper) {
164191
return $entity;
165192
}
166193
);
194+
195+
$reflector->getProperty($mapper->identity())->setRawValueWithoutLazyInitialization($lazy, $identity);
167196
} catch (Throwable $e) {
168197
report($e);
169198

src/EntityMapper.php

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Articulate\Concise;
5+
6+
use Illuminate\Support\Str;
7+
8+
/**
9+
* @template EntityObject of object
10+
*
11+
* @implements \Articulate\Concise\Contracts\EntityMapper<EntityObject>
12+
*/
13+
abstract class EntityMapper implements Contracts\EntityMapper
14+
{
15+
/**
16+
* @var \Articulate\Concise\Concise
17+
*/
18+
protected Concise $concise;
19+
20+
public function __construct(Concise $concise)
21+
{
22+
$this->concise = $concise;
23+
}
24+
25+
/**
26+
* Get the custom repository class for the entity
27+
*
28+
* @return null
29+
*/
30+
public function repository(): null
31+
{
32+
return null;
33+
}
34+
35+
/**
36+
* Get the connection the entity should use
37+
*
38+
* @return null
39+
*/
40+
public function connection(): null
41+
{
42+
return null;
43+
}
44+
45+
/**
46+
* Get the entities' database table
47+
*
48+
* @return string
49+
*/
50+
public function table(): string
51+
{
52+
return Str::snake(Str::pluralStudly(class_basename($this->class())));
53+
}
54+
55+
/**
56+
* Get the name of the identity field
57+
*
58+
* @return string
59+
*/
60+
public function identity(): string
61+
{
62+
return 'id';
63+
}
64+
65+
}

tests/ConciseTest.php

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,110 @@
33

44
namespace Articulate\Concise\Tests;
55

6+
use App\Components\AuthCredentials;
7+
use App\Components\Timestamps;
8+
use App\Entities\User;
9+
use App\Mappers\Components\AuthCredentialsMapper;
10+
use App\Mappers\Components\TimestampsMapper;
11+
use App\Mappers\Entities\UserMapper;
12+
use Articulate\Concise\Concise;
13+
use Articulate\Concise\EntityRepository;
14+
use InvalidArgumentException;
15+
use PHPUnit\Framework\Attributes\Test;
16+
use ReflectionClass;
17+
use stdClass;
18+
619
class ConciseTest extends TestCase
720
{
21+
#[Test]
22+
public function canManuallyRegisterEntityMappers(): void
23+
{
24+
$concise = $this->app->make(Concise::class);
25+
26+
$this->assertTrue($concise->register(new UserMapper($concise)));
27+
$this->assertInstanceOf(UserMapper::class, $concise->entity(User::class));
28+
}
29+
30+
#[Test]
31+
public function canManuallyRegisterComponentMappers(): void
32+
{
33+
$concise = $this->app->make(Concise::class);
34+
35+
$this->assertTrue($concise->register(new AuthCredentialsMapper()));
36+
$this->assertTrue($concise->register(new TimestampsMapper()));
37+
$this->assertInstanceOf(AuthCredentialsMapper::class, $concise->component(AuthCredentials::class));
38+
$this->assertInstanceOf(TimestampsMapper::class, $concise->component(Timestamps::class));
39+
}
40+
41+
#[Test]
42+
public function canManuallyRegisterEntityMappersByClass(): void
43+
{
44+
$concise = $this->app->make(Concise::class);
45+
46+
$this->assertTrue($concise->register(UserMapper::class));
47+
$this->assertInstanceOf(UserMapper::class, $concise->entity(User::class));
48+
}
49+
50+
#[Test]
51+
public function canManuallyRegisterComponentMappersByClass(): void
52+
{
53+
$concise = $this->app->make(Concise::class);
54+
55+
$this->assertTrue($concise->register(AuthCredentialsMapper::class));
56+
$this->assertTrue($concise->register(TimestampsMapper::class));
57+
$this->assertInstanceOf(AuthCredentialsMapper::class, $concise->component(AuthCredentials::class));
58+
$this->assertInstanceOf(TimestampsMapper::class, $concise->component(Timestamps::class));
59+
}
60+
61+
#[Test]
62+
public function throwsAnExceptionIfTheClassIsNotAMapper(): void
63+
{
64+
$concise = $this->app->make(Concise::class);
65+
66+
$this->expectException(InvalidArgumentException::class);
67+
$this->expectExceptionMessage('Class [stdClass] is not a valid mapper.');
68+
69+
$concise->register(stdClass::class);
70+
}
71+
72+
#[Test]
73+
public function doesNotOverwriteMappingsByDefault(): void
74+
{
75+
$concise = $this->app->make(Concise::class);
76+
77+
$this->assertTrue($concise->register(new UserMapper($concise)));
78+
$this->assertTrue($concise->register(new AuthCredentialsMapper()));
79+
$this->assertTrue($concise->register(new TimestampsMapper()));
80+
81+
$this->assertFalse($concise->register(new UserMapper($concise)));
82+
$this->assertFalse($concise->register(new AuthCredentialsMapper()));
83+
$this->assertFalse($concise->register(new TimestampsMapper()));
84+
}
85+
86+
#[Test]
87+
public function usesADefaultRepository(): void
88+
{
89+
$concise = $this->app->make(Concise::class);
90+
91+
$this->assertTrue($concise->register(new UserMapper($concise)));
92+
$this->assertInstanceOf(EntityRepository::class, $concise->repository(User::class));
93+
}
94+
95+
#[Test]
96+
public function canCreateLazyObjects(): void
97+
{
98+
$concise = $this->app->make(Concise::class);
99+
100+
$this->assertTrue($concise->register(new UserMapper($concise)));
101+
102+
$lazy = $concise->lazy(User::class, 7);
103+
104+
$this->assertInstanceOf(User::class, $lazy);
105+
$this->assertSame(7, $lazy->getId());
106+
$this->assertTrue($lazy->hasId());
107+
108+
$reflector = new ReflectionClass($lazy);
8109

110+
$this->assertTrue($reflector->isUninitializedLazyObject($lazy));
111+
}
9112
}

tests/ImplicitRouteBindingTest.php

Lines changed: 0 additions & 15 deletions
This file was deleted.

workbench/app/Mappers/Components/AuthCredentialsMapper.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
namespace App\Mappers\Components;
55

66
use App\Components\AuthCredentials;
7-
use OLD\Contracts\Mapper;
7+
use Articulate\Concise\Contracts\Mapper;
88

99
/**
10-
* @implements OLD\Contracts\Mapper<\App\Components\AuthCredentials>
10+
* @implements \Articulate\Concise\Contracts\Mapper<\App\Components\AuthCredentials>
1111
*/
1212
final class AuthCredentialsMapper implements Mapper
1313
{

workbench/app/Mappers/Components/TimestampsMapper.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
namespace App\Mappers\Components;
55

66
use App\Components\Timestamps;
7-
use OLD\Contracts\Mapper;
7+
use Articulate\Concise\Contracts\Mapper;
88

99
/**
10-
* @implements OLD\Contracts\Mapper<\App\Components\Timestamps>
10+
* @implements \Articulate\Concise\Contracts\Mapper<\App\Components\Timestamps>
1111
*/
1212
final class TimestampsMapper implements Mapper
1313
{

workbench/app/Mappers/Entities/UserMapper.php

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,13 @@
66
use App\Components\AuthCredentials;
77
use App\Components\Timestamps;
88
use App\Entities\User;
9-
use App\Repositories\UserRepository;
9+
use Articulate\Concise\EntityMapper;
1010
use Illuminate\Support\Arr;
11-
use OLD\Support\BaseEntityMapper;
1211

1312
/**
14-
* @extends OLD\Support\BaseEntityMapper<\App\Entities\User>
13+
* @extends \Articulate\Concise\EntityMapper<\App\Entities\User>
1514
*/
16-
final class UserMapper extends BaseEntityMapper
15+
final class UserMapper extends EntityMapper
1716
{
1817
/**
1918
* Get the object class.
@@ -25,16 +24,6 @@ public function class(): string
2524
return User::class;
2625
}
2726

28-
/**
29-
* Get the repository class name.
30-
*
31-
* @return class-string<\App\Repositories\UserRepository>|null
32-
*/
33-
public function repository(): ?string
34-
{
35-
return UserRepository::class;
36-
}
37-
3827
/**
3928
* Converts the given array of data into an object.
4029
*
@@ -51,14 +40,12 @@ public function toObject(array $data): object
5140
$user->setId($data['id'])
5241
->setName($data['name'])
5342
->setAuth(
54-
$this->concise->component(
55-
AuthCredentials::class,
43+
$this->concise->component(AuthCredentials::class)?->toObject(
5644
Arr::only($data, ['email', 'password', 'remember_token', 'email_verified_at'])
5745
)
5846
)
5947
->setTimestamps(
60-
$this->concise->component(
61-
Timestamps::class,
48+
$this->concise->component(Timestamps::class)?->toObject(
6249
Arr::only($data, ['created_at', 'updated_at'])
6350
)
6451
);
@@ -86,8 +73,8 @@ public function toData(object $object): array
8673
}
8774

8875
return array_merge(
89-
$this->concise->data($object->getAuth()),
90-
$this->concise->data($object->getTimestamps()),
76+
$this->concise->component(AuthCredentials::class)?->toData($object->getAuth()),
77+
$this->concise->component(Timestamps::class)?->toData($object->getTimestamps()),
9178
$data
9279
);
9380
}

0 commit comments

Comments
 (0)