12
12
use Doctrine \Common \DataFixtures \Purger \ORMPurger ;
13
13
use Doctrine \ORM \EntityManager ;
14
14
use Symfony \Bridge \Doctrine \Types \UuidType ;
15
+ use Symfony \Component \Serializer \Annotation \Groups ;
15
16
use Symfony \Component \Uid \Uuid ;
16
17
18
+ /**
19
+ * Base class for all tests of the project.
20
+ * It provides some helper methods.
21
+ */
17
22
abstract class EtuUTTApiTestCase extends ApiTestCase
18
23
{
19
24
protected EntityManager $ em ;
20
25
protected User $ user ;
21
26
private array $ databaseBackup ;
22
27
28
+ /**
29
+ * Initializes $this->em and $this->user.
30
+ * $this->user is an admin user. Its login is 'test'. Tests may use it to connect to the API.
31
+ * It also purges the database.
32
+ */
23
33
protected function setUp (): void
24
34
{
25
35
$ this ->em = static ::getContainer ()->get ('doctrine.orm.entity_manager ' );
@@ -28,6 +38,12 @@ protected function setUp(): void
28
38
$ this ->user = $ this ->createUser ('test ' , 'test ' , 'test ' , 'ROLE_ADMIN ' );
29
39
}
30
40
41
+ /**
42
+ * Asserts that the received group is the same as the expected one. It should have the layout defined by the {@see Groups} 'group:read:some' in the {@see Group} entity.
43
+ *
44
+ * @param Group $expected The group that should be received
45
+ * @param mixed $actual The group that was received (as an stdClass)
46
+ */
31
47
protected static function assertSameGroupReadSome (Group $ expected , mixed $ actual ): void
32
48
{
33
49
static ::assertIsObject ($ actual );
@@ -43,6 +59,12 @@ protected static function assertSameGroupReadSome(Group $expected, mixed $actual
43
59
static ::assertSame ($ expected ->getNumberOfMembers (), $ actual ->numberOfMembers );
44
60
}
45
61
62
+ /**
63
+ * Asserts that the received group is the same as the expected one. It should have the layout defined by the {@see Groups} 'group:read:one' in the {@see Group} entity.
64
+ *
65
+ * @param Group $expected The group that should be received
66
+ * @param mixed $actual The group that was received (as an stdClass)
67
+ */
46
68
protected static function assertSameGroupReadOne (Group $ expected , mixed $ actual ): void
47
69
{
48
70
static ::assertIsObject ($ actual );
@@ -66,6 +88,12 @@ protected static function assertSameGroupReadOne(Group $expected, mixed $actual)
66
88
static ::assertSame ($ expected ->getUpdatedAt ()->format (\DateTimeInterface::RFC3339 ), $ actual ->updatedAt );
67
89
}
68
90
91
+ /**
92
+ * Asserts that the received translation is the same as the expected one.
93
+ *
94
+ * @param Translation $expected The translation that should be received
95
+ * @param mixed $actual The translation that was received (as an stdClass)
96
+ */
69
97
protected static function assertSameTranslation (Translation $ expected , mixed $ actual ): void
70
98
{
71
99
static ::assertFalse (null === $ expected xor null === $ actual );
@@ -80,6 +108,12 @@ protected static function assertSameTranslation(Translation $expected, mixed $ac
80
108
static ::assertSame ($ expected ->getChinese (), $ actual ->chinese );
81
109
}
82
110
111
+ /**
112
+ * Asserts that the received user is the same as the expected one. It should have the layout defined by the {@see Groups} 'user:read:some' in the {@see User} entity.
113
+ *
114
+ * @param User $expected The user that should be received
115
+ * @param mixed $actual The user that was received (as an stdClass)
116
+ */
83
117
protected static function assertSameUserReadSome (User $ expected , mixed $ actual ): void
84
118
{
85
119
static ::assertIsObject ($ actual );
@@ -93,6 +127,12 @@ protected static function assertSameUserReadSome(User $expected, mixed $actual):
93
127
static ::assertSameUserInfosReadSome ($ expected ->getInfos (), $ actual ->infos );
94
128
}
95
129
130
+ /**
131
+ * Asserts that the received user infos are the same as the expected one. It should have the layout defined by the {@see Groups} 'user:read:some' in the {@see UserInfos} entity.
132
+ *
133
+ * @param UserInfos $expected The user infos that should be received
134
+ * @param mixed $actual The user infos that was received (as an stdClass)
135
+ */
96
136
protected static function assertSameUserInfosReadSome (UserInfos $ expected , mixed $ actual ): void
97
137
{
98
138
static ::assertIsObject ($ actual );
@@ -103,6 +143,11 @@ protected static function assertSameUserInfosReadSome(UserInfos $expected, mixed
103
143
static ::assertSame ($ expected ->getNickname (), $ actual ->nickname );
104
144
}
105
145
146
+ /**
147
+ * Loads the given fixtures.
148
+ *
149
+ * @param Fixture ...$fixtures The fixtures to load
150
+ */
106
151
protected function loadFixtures (Fixture ...$ fixtures )
107
152
{
108
153
$ fixtureLoader = new Loader ();
@@ -114,6 +159,15 @@ protected function loadFixtures(Fixture ...$fixtures)
114
159
}
115
160
}
116
161
162
+ /**
163
+ * Creates, persists, and returns a user. It can also flush the database if specified.
164
+ *
165
+ * @param string $firstName The first name of the user
166
+ * @param string $lastName The last name of the user
167
+ * @param string $login The login of the user
168
+ * @param null|string $role The role of the user (defaults to 'ROLE_USER')
169
+ * @param bool $flush Whether to flush the database or not (defaults to true)
170
+ */
117
171
protected function createUser (string $ firstName , string $ lastName , string $ login , ?string $ role = 'ROLE_USER ' , bool $ flush = true ): User
118
172
{
119
173
$ user = new User ();
@@ -129,12 +183,44 @@ protected function createUser(string $firstName, string $lastName, string $login
129
183
return $ user ;
130
184
}
131
185
186
+ /**
187
+ * Backups the database. It sets the value of {@see $databaseBackup}. It should be used before the database is altered.
188
+ * After changes, tests should use {@see assertDatabaseSameExcept} to assert that only specified fields have been modified.
189
+ */
132
190
protected function backupDatabase (): void
133
191
{
134
192
$ this ->databaseBackup = [];
135
193
$ this ->_backupDatabase ($ this ->databaseBackup );
136
194
}
137
195
196
+ /**
197
+ * Asserts that the database is the same as the backup, except for the specified fields.
198
+ *
199
+ * @param array $diff The fields that should be different from the backup. It should be an array of the form:
200
+ *
201
+ * <code>
202
+ * [
203
+ * '<table_name>' => [
204
+ * 'where' => [
205
+ * '<field>' => '<value>', // Changes are only expected where <field> have value <value>
206
+ * ],
207
+ * 'diff' => [
208
+ * '<modified_field>' => '<new_value>',
209
+ * ],
210
+ * ],
211
+ * ]
212
+ * </code>
213
+ * @param array $new The new entries that should be in the database. It should be an array of the form:
214
+ *
215
+ * <code>
216
+ * [
217
+ * '<table_name>' => [
218
+ * [
219
+ * '<field>' => '<value>',
220
+ * ], // Each array is a new entry
221
+ * ],
222
+ * </code>
223
+ */
138
224
protected function assertDatabaseSameExcept (array $ diff , array $ new ): void
139
225
{
140
226
$ actualDatabase = [];
@@ -153,18 +239,31 @@ protected function assertDatabaseSameExcept(array $diff, array $new): void
153
239
$ this ->databaseBackup [$ table ][] = $ entry ;
154
240
}
155
241
}
156
- static ::assertEquals ($ this ->databaseBackup , $ actualDatabase );
242
+ // Yes, that's dumb, but PHPFixer keeps changing it to assertSame
243
+ \call_user_func_array ([static ::class, 'assertEquals ' ], [$ this ->databaseBackup , $ actualDatabase ]);
157
244
}
158
245
246
+ /**
247
+ * Backups the database in the given array.
248
+ *
249
+ * @param array $backup A reference to the array in which the backup will be stored
250
+ */
159
251
private function _backupDatabase (array &$ backup ): void
160
252
{
161
253
$ backup = [];
254
+ // Fetch all tables
162
255
$ tables = $ this ->em ->getConnection ()->createSchemaManager ()->listTables ();
163
256
foreach ($ tables as $ table ) {
164
257
$ tableName = $ table ->getName ();
165
258
$ backup [$ tableName ] = [];
259
+ // Fetch all rows
166
260
$ rows = $ this ->em ->getConnection ()->prepare ("SELECT * FROM {$ tableName }" )->executeQuery ()->fetchAllAssociative ();
167
- $ getPrintableValue = fn (string $ column , $ value ): ?string => UuidType::class === $ table ->getColumn ($ column )->getType ()::class && null !== $ value ? Uuid::fromBinary ($ value )->jsonSerialize () : $ value ;
261
+ // We don't want to directly use the binary value of the UUIDs, but the more human-readable representation
262
+ $ getPrintableValue = function (string $ column , $ value ) use ($ table ): ?string {
263
+ $ shouldConvert = UuidType::class === $ table ->getColumn ($ column )->getType ()::class && null !== $ value ;
264
+
265
+ return $ shouldConvert ? Uuid::fromBinary ($ value )->jsonSerialize () : $ value ;
266
+ };
168
267
foreach ($ rows as $ row ) {
169
268
// Convert all values to printable values
170
269
foreach ($ row as $ column => &$ value ) {
0 commit comments