Skip to content

Commit ad27abb

Browse files
committed
Refactored LanguageServiceTest and added stricter validation for LanguageCreateStruct
1 parent a427eae commit ad27abb

File tree

8 files changed

+219
-120
lines changed

8 files changed

+219
-120
lines changed

phpunit-integration-legacy.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
<env name="SYMFONY_DEPRECATIONS_HELPER" value="disabled"/>
1313
<ini name="error_reporting" value="-1"/>
1414
<env name="DATABASE_URL" value="sqlite://:memory:"/>
15-
<env name="KERNEL_CLASS" value="Ibexa\Contracts\Core\Test\IbexaTestKernel"/>
15+
<env name="KERNEL_CLASS" value="Ibexa\Tests\Integration\Core\CoreTestKernel" />
1616
<env name="SEARCH_ENGINE" value="legacy"/>
1717
<env name="SYMFONY_DEPRECATIONS_HELPER" value="disabled"/>
1818
</php>

src/contracts/Repository/Values/Content/LanguageCreateStruct.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,16 @@ class LanguageCreateStruct extends ValueObject
1919
/**
2020
* The languageCode code.
2121
*
22-
* Needs to be a unique.
22+
* Needs to be unique.
2323
*/
2424
#[Assert\NotBlank]
25-
#[Assert\Regex('^[a-zA-Z\_\-]+$')]
25+
#[Assert\Regex('~^[a-zA-Z\_\-]+$~')]
2626
public ?string $languageCode = null;
2727

2828
/**
2929
* Human-readable name of the language.
3030
*/
31+
#[Assert\NotBlank]
3132
public ?string $name = null;
3233

3334
/**

src/lib/Repository/LanguageService.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ public function createLanguage(LanguageCreateStruct $languageCreateStruct): Lang
9494
// Do nothing
9595
}
9696

97+
$this->validator->assertValidStruct('$languageCreateStruct', $languageCreateStruct, ['create']);
98+
9799
$createStruct = new CreateStruct(
98100
[
99101
'languageCode' => $languageCreateStruct->languageCode,
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace Ibexa\Tests\Integration\Core;
4+
5+
use Ibexa\Contracts\Core\Test\IbexaTestKernel;
6+
use Symfony\Component\Config\Loader\LoaderInterface;
7+
8+
final class CoreTestKernel extends IbexaTestKernel
9+
{
10+
protected function loadConfiguration(LoaderInterface $loader): void
11+
{
12+
parent::loadConfiguration($loader);
13+
14+
$loader->load(__DIR__ . '/Resources/services/services.php');
15+
}
16+
}
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
<?php
2+
3+
/**
4+
* @copyright Copyright (C) Ibexa AS. All rights reserved.
5+
* @license For full copyright and license information view LICENSE file distributed with this source code.
6+
*/
7+
8+
namespace Ibexa\Tests\Integration\Core\Repository;
9+
10+
use Ibexa\Contracts\Core\Repository\Values\ValueObject;
11+
12+
trait AssertPropertiesTrait
13+
{
14+
/**
15+
* Asserts that properties given in $expectedValues are correctly set in
16+
* $actualObject.
17+
*
18+
* @param mixed[] $expectedValues
19+
* @param \Ibexa\Contracts\Core\Repository\Values\ValueObject $actualObject
20+
*/
21+
protected function assertPropertiesCorrect(array $expectedValues, ValueObject $actualObject): void
22+
{
23+
foreach ($expectedValues as $propertyName => $propertyValue) {
24+
if ($propertyValue instanceof ValueObject) {
25+
$this->assertStructPropertiesCorrect($propertyValue, $actualObject->$propertyName);
26+
} elseif (is_array($propertyValue)) {
27+
foreach ($propertyValue as $key => $value) {
28+
if ($value instanceof ValueObject) {
29+
$this->assertStructPropertiesCorrect($value, $actualObject->$propertyName[$key]);
30+
} else {
31+
$this->assertPropertiesEqual("$propertyName\[$key\]", $value, $actualObject->$propertyName[$key]);
32+
}
33+
}
34+
} else {
35+
$this->assertPropertiesEqual($propertyName, $propertyValue, $actualObject->$propertyName);
36+
}
37+
}
38+
}
39+
40+
/**
41+
* Asserts that properties given in $expectedValues are correctly set in
42+
* $actualObject.
43+
*
44+
* If the property type is array, it will be sorted before comparison.
45+
*
46+
* @TODO: introduced because of randomly failing tests, ref: https://issues.ibexa.co/browse/EZP-21734
47+
*
48+
* @param mixed[] $expectedValues
49+
* @param \Ibexa\Contracts\Core\Repository\Values\ValueObject $actualObject
50+
*/
51+
protected function assertPropertiesCorrectUnsorted(array $expectedValues, ValueObject $actualObject): void
52+
{
53+
foreach ($expectedValues as $propertyName => $propertyValue) {
54+
if ($propertyValue instanceof ValueObject) {
55+
$this->assertStructPropertiesCorrect($propertyValue, $actualObject->$propertyName);
56+
} else {
57+
$this->assertPropertiesEqual($propertyName, $propertyValue, $actualObject->$propertyName, true);
58+
}
59+
}
60+
}
61+
62+
/**
63+
* Asserts all properties from $expectedValues are correctly set in
64+
* $actualObject. Additional (virtual) properties can be asserted using
65+
* $additionalProperties.
66+
*
67+
* @param array<string> $additionalProperties
68+
*/
69+
protected function assertStructPropertiesCorrect(
70+
ValueObject $expectedValues,
71+
ValueObject $actualObject,
72+
array $additionalProperties = [],
73+
): void {
74+
foreach ($expectedValues as $propertyName => $propertyValue) {
75+
if ($propertyValue instanceof ValueObject) {
76+
$this->assertStructPropertiesCorrect($propertyValue, $actualObject->$propertyName);
77+
} else {
78+
$this->assertPropertiesEqual($propertyName, $propertyValue, $actualObject->$propertyName);
79+
}
80+
}
81+
82+
foreach ($additionalProperties as $propertyName) {
83+
$this->assertPropertiesEqual($propertyName, $expectedValues->$propertyName, $actualObject->$propertyName);
84+
}
85+
}
86+
87+
/**
88+
* @param array<scalar> $items An array of scalar values
89+
*
90+
* @see \Ibexa\Tests\Integration\Core\Repository\BaseTestCase::assertPropertiesCorrectUnsorted
91+
*/
92+
private function sortItems(array &$items): void
93+
{
94+
$sorter = static function ($a, $b): int {
95+
if (!is_scalar($a) || !is_scalar($b)) {
96+
self::fail('Wrong usage: method ' . __METHOD__ . ' accepts only an array of scalar values');
97+
}
98+
99+
return strcmp($a, $b);
100+
};
101+
usort($items, $sorter);
102+
}
103+
104+
private function assertPropertiesEqual($propertyName, $expectedValue, $actualValue, $sortArray = false): void
105+
{
106+
if ($expectedValue instanceof \ArrayObject) {
107+
$expectedValue = $expectedValue->getArrayCopy();
108+
} elseif ($expectedValue instanceof \DateTimeInterface) {
109+
$expectedValue = $expectedValue->format(\DateTime::RFC850);
110+
}
111+
if ($actualValue instanceof \ArrayObject) {
112+
$actualValue = $actualValue->getArrayCopy();
113+
} elseif ($actualValue instanceof \DateTimeInterface) {
114+
$actualValue = $actualValue->format(\DateTime::RFC850);
115+
}
116+
117+
if ($sortArray && is_array($actualValue) && is_array($expectedValue)) {
118+
$this->sortItems($actualValue);
119+
$this->sortItems($expectedValue);
120+
}
121+
122+
self::assertEquals(
123+
$expectedValue,
124+
$actualValue,
125+
sprintf('Object property "%s" incorrect.', $propertyName)
126+
);
127+
}
128+
}

tests/integration/Core/Repository/BaseTestCase.php

Lines changed: 2 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
*/
3838
abstract class BaseTestCase extends TestCase
3939
{
40+
use AssertPropertiesTrait;
41+
4042
/**
4143
* Maximum integer number accepted by the different backends.
4244
*/
@@ -184,120 +186,6 @@ protected function getSetupFactory(): SetupFactory
184186
return $this->setupFactory;
185187
}
186188

187-
/**
188-
* Asserts that properties given in $expectedValues are correctly set in
189-
* $actualObject.
190-
*
191-
* @param mixed[] $expectedValues
192-
* @param \Ibexa\Contracts\Core\Repository\Values\ValueObject $actualObject
193-
*/
194-
protected function assertPropertiesCorrect(array $expectedValues, ValueObject $actualObject)
195-
{
196-
foreach ($expectedValues as $propertyName => $propertyValue) {
197-
if ($propertyValue instanceof ValueObject) {
198-
$this->assertStructPropertiesCorrect($propertyValue, $actualObject->$propertyName);
199-
} elseif (is_array($propertyValue)) {
200-
foreach ($propertyValue as $key => $value) {
201-
if ($value instanceof ValueObject) {
202-
$this->assertStructPropertiesCorrect($value, $actualObject->$propertyName[$key]);
203-
} else {
204-
$this->assertPropertiesEqual("$propertyName\[$key\]", $value, $actualObject->$propertyName[$key]);
205-
}
206-
}
207-
} else {
208-
$this->assertPropertiesEqual($propertyName, $propertyValue, $actualObject->$propertyName);
209-
}
210-
}
211-
}
212-
213-
/**
214-
* Asserts that properties given in $expectedValues are correctly set in
215-
* $actualObject.
216-
*
217-
* If the property type is array, it will be sorted before comparison.
218-
*
219-
* @TODO: introduced because of randomly failing tests, ref: https://issues.ibexa.co/browse/EZP-21734
220-
*
221-
* @param mixed[] $expectedValues
222-
* @param \Ibexa\Contracts\Core\Repository\Values\ValueObject $actualObject
223-
*/
224-
protected function assertPropertiesCorrectUnsorted(array $expectedValues, ValueObject $actualObject)
225-
{
226-
foreach ($expectedValues as $propertyName => $propertyValue) {
227-
if ($propertyValue instanceof ValueObject) {
228-
$this->assertStructPropertiesCorrect($propertyValue, $actualObject->$propertyName);
229-
} else {
230-
$this->assertPropertiesEqual($propertyName, $propertyValue, $actualObject->$propertyName, true);
231-
}
232-
}
233-
}
234-
235-
/**
236-
* Asserts all properties from $expectedValues are correctly set in
237-
* $actualObject. Additional (virtual) properties can be asserted using
238-
* $additionalProperties.
239-
*
240-
* @param \Ibexa\Contracts\Core\Repository\Values\ValueObject $expectedValues
241-
* @param \Ibexa\Contracts\Core\Repository\Values\ValueObject $actualObject
242-
* @param array $propertyNames
243-
*/
244-
protected function assertStructPropertiesCorrect(ValueObject $expectedValues, ValueObject $actualObject, array $additionalProperties = [])
245-
{
246-
foreach ($expectedValues as $propertyName => $propertyValue) {
247-
if ($propertyValue instanceof ValueObject) {
248-
$this->assertStructPropertiesCorrect($propertyValue, $actualObject->$propertyName);
249-
} else {
250-
$this->assertPropertiesEqual($propertyName, $propertyValue, $actualObject->$propertyName);
251-
}
252-
}
253-
254-
foreach ($additionalProperties as $propertyName) {
255-
$this->assertPropertiesEqual($propertyName, $expectedValues->$propertyName, $actualObject->$propertyName);
256-
}
257-
}
258-
259-
/**
260-
* @param array $items An array of scalar values
261-
*
262-
* @see \Ibexa\Tests\Integration\Core\Repository\BaseTestCase::assertPropertiesCorrectUnsorted
263-
*/
264-
private function sortItems(array &$items)
265-
{
266-
$sorter = function ($a, $b): int {
267-
if (!is_scalar($a) || !is_scalar($b)) {
268-
$this->fail('Wrong usage: method ' . __METHOD__ . ' accepts only an array of scalar values');
269-
}
270-
271-
return strcmp($a, $b);
272-
};
273-
usort($items, $sorter);
274-
}
275-
276-
private function assertPropertiesEqual($propertyName, $expectedValue, $actualValue, $sortArray = false)
277-
{
278-
if ($expectedValue instanceof ArrayObject) {
279-
$expectedValue = $expectedValue->getArrayCopy();
280-
} elseif ($expectedValue instanceof DateTime) {
281-
$expectedValue = $expectedValue->format(DateTime::RFC850);
282-
}
283-
if ($actualValue instanceof ArrayObject) {
284-
$actualValue = $actualValue->getArrayCopy();
285-
} elseif ($actualValue instanceof DateTime) {
286-
$actualValue = $actualValue->format(DateTime::RFC850);
287-
}
288-
289-
if ($sortArray && is_array($actualValue) && is_array($expectedValue)) {
290-
$this->sortItems($actualValue);
291-
$this->sortItems($expectedValue);
292-
}
293-
294-
self::assertEquals(
295-
$expectedValue,
296-
$actualValue,
297-
sprintf('Object property "%s" incorrect.', $propertyName)
298-
);
299-
}
300-
301189
/**
302190
* Create a user in editor user group.
303191
*/

tests/integration/Core/Repository/LanguageServiceTest.php

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use Ibexa\Contracts\Core\Repository\LanguageService;
1414
use Ibexa\Contracts\Core\Repository\Repository;
1515
use Ibexa\Contracts\Core\Repository\Values\Content\Language;
16+
use Ibexa\Contracts\Core\Test\IbexaKernelTestCase;
1617

1718
/**
1819
* Test case for operations in the LanguageService using in memory storage.
@@ -22,20 +23,32 @@
2223
* @group integration
2324
* @group language
2425
*/
25-
final class LanguageServiceTest extends BaseTestCase
26+
final class LanguageServiceTest extends IbexaKernelTestCase
2627
{
28+
use AssertPropertiesTrait;
29+
2730
private Repository $repository;
2831

2932
private LanguageService $languageService;
3033

3134
protected function setUp(): void
3235
{
33-
parent::setUp();
36+
self::bootKernel();
37+
38+
self::loadSchema();
39+
self::loadFixtures();
3440

35-
$this->repository = $this->getRepository();
41+
self::setAdministratorUser();
42+
43+
$this->repository = self::getServiceByClassName(Repository::class);
3644
$this->languageService = $this->repository->getContentLanguageService();
3745
}
3846

47+
private function generateId(string $type, string $rawId): string
48+
{
49+
return self::getServiceByClassName(IdManager::class)->generateId($type, $rawId);
50+
}
51+
3952
public function testNewLanguageCreateStruct(): void
4053
{
4154
$languageCreate = $this->languageService->newLanguageCreateStruct();
@@ -113,6 +126,33 @@ public function testCreateLanguageThrowsInvalidArgumentException(): void
113126
$this->languageService->createLanguage($languageCreate);
114127
}
115128

129+
public function testCreateLanguageWithEmptyLanguageCode(): void
130+
{
131+
$languageCreate = $this->languageService->newLanguageCreateStruct();
132+
$languageCreate->enabled = true;
133+
$languageCreate->name = 'English';
134+
$languageCreate->languageCode = '';
135+
136+
$this->expectException(InvalidArgumentException::class);
137+
$this->languageService->createLanguage($languageCreate);
138+
}
139+
140+
/**
141+
* @testWith ["."]
142+
* ["ąę"]
143+
* ["%^"]
144+
*/
145+
public function testCreateLanguageWithInvalidLanguageCode(): void
146+
{
147+
$languageCreate = $this->languageService->newLanguageCreateStruct();
148+
$languageCreate->enabled = true;
149+
$languageCreate->name = 'English';
150+
$languageCreate->languageCode = 'eng 123';
151+
152+
$this->expectException(InvalidArgumentException::class);
153+
$this->languageService->createLanguage($languageCreate);
154+
}
155+
116156
/**
117157
* @depends testCreateLanguage
118158
*/

0 commit comments

Comments
 (0)