tests/Codes/Partials/TranslatableExtendableCodeTest.php
<?php declare(strict_types=1);
namespace DrdPlus\Tests\Codes\Partials;
use DrdPlus\Codes\Partials\Translatable;
use DrdPlus\Codes\Partials\TranslatableExtendableCode;
abstract class TranslatableExtendableCodeTest extends TranslatableCodeTest
{
/**
* @var \ReflectionClass
*/
private $sutReflection;
/**
* @throws \ReflectionException
*/
protected function setUp(): void
{
parent::setUp();
$sutClass = self::getSutClass();
self::assertTrue(
is_a($sutClass, TranslatableExtendableCode::class, true),
$sutClass . ' should be an instance of ' . TranslatableExtendableCode::class
);
$this->sutReflection = new \ReflectionClass($sutClass);
}
/**
* @throws \ReflectionException
*/
protected function tearDown(): void
{
// clean up custom translations
$translatableExtendableCode = new \ReflectionClass(TranslatableExtendableCode::class);
$customValues = $translatableExtendableCode->getProperty('customValues');
$customValues->setAccessible(true);
$customValues->setValue([]);
$customValues->setAccessible(false);
$customCodeTranslations = $translatableExtendableCode->getProperty('customCodeTranslations');
$customCodeTranslations->setAccessible(true);
$customCodeTranslations->setValue([]);
$customCodeTranslations->setAccessible(false);
parent::tearDown();
}
/**
* @test
* @throws \ReflectionException
*/
public function Method_to_get_default_values_is_not_public()
{
$sutClass = self::getSutClass();
$getDefaultValues = $this->sutReflection->getMethod('getDefaultValues');
self::assertFalse($getDefaultValues->isPublic(), "Method $sutClass::getDefaultValues is not intended to be public");
}
/**
* @test
* @throws \ReflectionException
*/
public function I_can_extended_it_by_custom_translatable_code()
{
/** @var TranslatableExtendableCode $sutClass */
$sutClass = self::getSutClass();
$translations = $this->sutReflection->getProperty('translations');
$translations->setAccessible(true);
// to reset already initialized translations and force them to be loaded again
$translations->setValue(null);
$translations->setAccessible(false);
self::assertNotContains('foo', $sutClass::getPossibleValues());
self::assertFalse($sutClass::hasIt('foo'));
/** like @see \DrdPlus\Codes\Armaments\ArrowCode::addNewArrowCode */
$addNewCode = 'addNew' . $this->getSutBaseName();
self::assertTrue($sutClass::$addNewCode('foo', []));
self::assertFalse(
$sutClass::$addNewCode('foo', ['en' => ['one' => 'foo']]),
'Same custom code to register should be skipped. Have you overloaded getDefaultValues method?'
);
self::assertContains('foo', $sutClass::getPossibleValues());
self::assertTrue($sutClass::hasIt('foo'));
self::assertTrue($sutClass::$addNewCode('bar', ['cs' => ['one' => 'taková laťka']]));
self::assertContains('bar', $sutClass::getPossibleValues());
self::assertTrue($sutClass::hasIt('bar'));
if ((new \ReflectionClass($sutClass))->isAbstract()) {
return;
}
/** @var Translatable $bar */
$bar = $sutClass::getIt('bar');
self::assertSame('taková laťka', $bar->translateTo('cs'));
self::assertTrue($sutClass::$addNewCode('baz', ['cs' => ['one' => 'eee, ehm?']]));
$bar = $sutClass::getIt('baz');
self::assertSame('eee, ehm?', $bar->translateTo('cs'));
}
protected function getSutBaseName(): string
{
return preg_replace('~^.+\\\([^\\\]+$)~', '$1', static::getSutClass());
}
/**
* @test
* @throws \ReflectionException
*/
public function All_public_constants_can_be_given_by_getter()
{
$constants = $this->sutReflection->getConstants();
self::assertEquals($constants, array_unique($constants));
asort($constants);
$sutClass = self::getSutClass();
$possibleValues = $sutClass::getPossibleValues();
self::assertEquals($possibleValues, array_unique($possibleValues), 'Possible values should be unique');
sort($possibleValues);
self::assertSame(
[],
array_diff(array_values($constants), $possibleValues),
'Some constants are missing in possible values: ' . implode(',', array_diff(array_values($constants), $possibleValues))
);
$possibleValuesAndConstantsDifference = array_diff($possibleValues, array_values($constants));
$reflectionClass = new \ReflectionClass(TranslatableExtendableCode::class);
$customValuesReflection = $reflectionClass->getProperty('customValues');
$customValuesReflection->setAccessible(true);
$customValues = $customValuesReflection->getValue()[$sutClass] ?? [];
sort($possibleValuesAndConstantsDifference);
sort($customValues);
self::assertEquals(
$possibleValuesAndConstantsDifference,
$customValues,
'That is strange, have you overloaded getDefaultValues method?'
);
foreach ($possibleValues as $value) {
if (in_array($value, $customValues, true)) { // custom values are not as constants
continue;
}
$constantName = strtoupper($value);
self::assertArrayHasKey($constantName, $constants);
self::assertSame($constants[$constantName], $value);
}
}
/**
* @test
*/
public function I_can_not_use_invalid_language_code_format_for_custom_code()
{
$this->expectException(\DrdPlus\Codes\Partials\Exceptions\InvalidLanguageCode::class);
$this->expectExceptionMessageMatches('~a1~');
/** @var TranslatableExtendableCode $sutClass */
$sutClass = self::getSutClass();
/** like @see \DrdPlus\Codes\Armaments\ArrowCode::addNewArrowCode */
$addNewCode = 'addNew' . $this->getSutBaseName();
try {
$extended = $sutClass::$addNewCode('qux', ['cs' => ['one' => 'štěstí']]);
} catch (\Exception $exception) {
self::fail('No exception expected so far: ' . $exception->getMessage());
return;
}
self::assertTrue($extended, 'Code should not be already registered for this test');
self::assertTrue(
$sutClass::$addNewCode('quux', ['a1' => 'anything here']),
'Code should not be already registered for this test'
);
}
/**
* @test
*/
public function I_can_not_use_invalid_data_format_of_translations_for_custom_code()
{
$this->expectException(\DrdPlus\Codes\Partials\Exceptions\InvalidTranslationFormat::class);
$this->expectExceptionMessageMatches('~this should be array~');
/** like @see \DrdPlus\Codes\Armaments\ArrowCode::addNewArrowCode */
$addNewCode = 'addNew' . $this->getSutBaseName();
/** @var TranslatableExtendableCode $sutClass */
$sutClass = self::getSutClass();
self::assertTrue(
$sutClass::$addNewCode('foobar', ['uk' => 'this should be array']),
'Code should not be already registered for this test'
);
}
/**
* @test
*/
public function I_can_not_use_invalid_plural_for_translation_of_custom_code()
{
$this->expectException(\DrdPlus\Codes\Partials\Exceptions\UnknownTranslationPlural::class);
$this->expectExceptionMessageMatches('~all~');
/** like @see \DrdPlus\Codes\Armaments\ArrowCode::addNewArrowCode */
$addNewCode = 'addNew' . $this->getSutBaseName();
/** @var TranslatableExtendableCode $sutClass */
$sutClass = self::getSutClass();
self::assertTrue(
$sutClass::$addNewCode('foobaz', ['cs' => ['all' => 'have I missed something?']]),
'Code should not be already registered for this test'
);
}
/**
* @test
*/
public function I_can_not_use_non_string_for_translation_of_custom_code()
{
$this->expectException(\DrdPlus\Codes\Partials\Exceptions\InvalidTranslationFormat::class);
$this->expectExceptionMessageMatches('~NULL~');
/** like @see \DrdPlus\Codes\Armaments\ArrowCode::addNewArrowCode */
$addNewCode = 'addNew' . $this->getSutBaseName();
/** @var TranslatableExtendableCode $sutClass */
$sutClass = self::getSutClass();
self::assertTrue(
$sutClass::$addNewCode('fooqux', ['cs' => ['one' => null]]),
'Code should not be already registered for this test'
);
}
/**
* @test
*/
public function I_can_not_use_empty_string_for_translation_of_custom_code()
{
$this->expectException(\DrdPlus\Codes\Partials\Exceptions\InvalidTranslationFormat::class);
$this->expectExceptionMessageMatches("~''~");
/** like @see \DrdPlus\Codes\Armaments\ArrowCode::addNewArrowCode */
$addNewCode = 'addNew' . $this->getSutBaseName();
/** @var TranslatableExtendableCode $sutClass */
$sutClass = self::getSutClass();
self::assertTrue(
$sutClass::$addNewCode('barfoo', ['cs' => ['one' => '']]),
'Code should not be already registered for this test'
);
}
/**
* @test
*/
public function It_uses_parent_values_as_default_if_not_overloaded()
{
self::assertSame([], TranslatableExtendableCode::getPossibleValues());
}
}