mirror of https://github.com/FreshRSS/FreshRSS.git
Add tests on i18n classes (#4756)
This commit is contained in:
parent
d4181e098d
commit
1f4e347cae
|
@ -16,6 +16,12 @@ class I18nCompletionValidator implements I18nValidatorInterface {
|
|||
}
|
||||
|
||||
public function displayReport() {
|
||||
if ($this->passEntries > $this->totalEntries) {
|
||||
throw new \RuntimeException('The number of translated strings cannot be higher than the number of strings');
|
||||
}
|
||||
if ($this->totalEntries === 0) {
|
||||
return 'There is no data.' . PHP_EOL;
|
||||
}
|
||||
return sprintf('Translation is %5.1f%% complete.', $this->passEntries / $this->totalEntries * 100) . PHP_EOL;
|
||||
}
|
||||
|
||||
|
@ -27,7 +33,7 @@ class I18nCompletionValidator implements I18nValidatorInterface {
|
|||
foreach ($this->reference as $file => $data) {
|
||||
foreach ($data as $refKey => $refValue) {
|
||||
$this->totalEntries++;
|
||||
if (!array_key_exists($refKey, $this->language[$file])) {
|
||||
if (!array_key_exists($file, $this->language) || !array_key_exists($refKey, $this->language[$file])) {
|
||||
$this->result .= "Missing key $refKey" . PHP_EOL;
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -3,16 +3,9 @@
|
|||
require_once __DIR__ . '/I18nValue.php';
|
||||
|
||||
class I18nFile {
|
||||
|
||||
private $i18nPath;
|
||||
|
||||
public function __construct() {
|
||||
$this->i18nPath = __DIR__ . '/../../app/i18n';
|
||||
}
|
||||
|
||||
public function load() {
|
||||
$i18n = array();
|
||||
$dirs = new DirectoryIterator($this->i18nPath);
|
||||
$dirs = new DirectoryIterator(I18N_PATH);
|
||||
foreach ($dirs as $dir) {
|
||||
if ($dir->isDot()) {
|
||||
continue;
|
||||
|
@ -32,7 +25,7 @@ class I18nFile {
|
|||
|
||||
public function dump(array $i18n) {
|
||||
foreach ($i18n as $language => $file) {
|
||||
$dir = $this->i18nPath . DIRECTORY_SEPARATOR . $language;
|
||||
$dir = I18N_PATH . DIRECTORY_SEPARATOR . $language;
|
||||
if (!file_exists($dir)) {
|
||||
mkdir($dir);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,12 @@ class I18nUsageValidator implements I18nValidatorInterface {
|
|||
}
|
||||
|
||||
public function displayReport() {
|
||||
if ($this->failedEntries > $this->totalEntries) {
|
||||
throw new \RuntimeException('The number of unused strings cannot be higher than the number of strings');
|
||||
}
|
||||
if ($this->totalEntries === 0) {
|
||||
return 'There is no data.' . PHP_EOL;
|
||||
}
|
||||
return sprintf('%5.1f%% of translation keys are unused.', $this->failedEntries / $this->totalEntries * 100) . PHP_EOL;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
require_once __DIR__ . '/i18n/I18nData.php';
|
||||
require_once __DIR__ . '/i18n/I18nFile.php';
|
||||
require_once __DIR__ . '/../constants.php';
|
||||
|
||||
|
||||
$options = getopt("a:hk:l:o:rv:");
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ define('INDEX_PATH', PUBLIC_PATH . PUBLIC_TO_INDEX_PATH);
|
|||
define('PUBLIC_RELATIVE', '..');
|
||||
define('LIB_PATH', FRESHRSS_PATH . '/lib');
|
||||
define('APP_PATH', FRESHRSS_PATH . '/app');
|
||||
define('I18N_PATH', APP_PATH . '/i18n');
|
||||
define('CORE_EXTENSIONS_PATH', LIB_PATH . '/core-extensions');
|
||||
define('TESTS_PATH', FRESHRSS_PATH . '/tests');
|
||||
//</Not customisable>
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
<?php
|
||||
|
||||
require_once __DIR__ . '/../../../cli/i18n/I18nCompletionValidator.php';
|
||||
require_once __DIR__ . '/../../../cli/i18n/I18nValue.php';
|
||||
|
||||
class I18nCompletionValidatorTest extends PHPUnit\Framework\TestCase {
|
||||
private $value;
|
||||
|
||||
public function setUp(): void {
|
||||
$this->value = $this->getMockBuilder(I18nValue::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
}
|
||||
|
||||
public function testDisplayReport() {
|
||||
$validator = new I18nCompletionValidator([], []);
|
||||
|
||||
$this->assertEquals("There is no data.\n", $validator->displayReport());
|
||||
|
||||
$reflectionTotalEntries = new ReflectionProperty(I18nCompletionValidator::class, 'totalEntries');
|
||||
$reflectionTotalEntries->setAccessible(true);
|
||||
$reflectionTotalEntries->setValue($validator, 100);
|
||||
|
||||
$this->assertEquals("Translation is 0.0% complete.\n", $validator->displayReport());
|
||||
|
||||
$reflectionPassEntries = new ReflectionProperty(I18nCompletionValidator::class, 'passEntries');
|
||||
$reflectionPassEntries->setAccessible(true);
|
||||
$reflectionPassEntries->setValue($validator, 25);
|
||||
|
||||
$this->assertEquals("Translation is 25.0% complete.\n", $validator->displayReport());
|
||||
|
||||
$reflectionPassEntries->setValue($validator, 100);
|
||||
|
||||
$this->assertEquals("Translation is 100.0% complete.\n", $validator->displayReport());
|
||||
|
||||
$reflectionPassEntries->setValue($validator, 200);
|
||||
|
||||
$this->expectException(\RuntimeException::class);
|
||||
$this->expectExceptionMessage('The number of translated strings cannot be higher than the number of strings');
|
||||
$validator->displayReport();
|
||||
}
|
||||
|
||||
public function testValidateWhenNoData() {
|
||||
$validator = new I18nCompletionValidator([], []);
|
||||
$this->assertTrue($validator->validate());
|
||||
$this->assertEquals('', $validator->displayResult());
|
||||
}
|
||||
|
||||
public function testValidateWhenKeyIsMissing() {
|
||||
$validator = new I18nCompletionValidator([
|
||||
'file1.php' => [
|
||||
'file1.l1.l2.k1' => $this->value,
|
||||
],
|
||||
'file2.php' => [
|
||||
'file2.l1.l2.k1' => $this->value,
|
||||
],
|
||||
], []);
|
||||
|
||||
$this->assertFalse($validator->validate());
|
||||
$this->assertEquals("Missing key file1.l1.l2.k1\nMissing key file2.l1.l2.k1\n", $validator->displayResult());
|
||||
}
|
||||
|
||||
public function testValidateWhenKeyIsIgnored() {
|
||||
$this->value->expects($this->exactly(2))
|
||||
->method('isIgnore')
|
||||
->willReturn(true);
|
||||
|
||||
$validator = new I18nCompletionValidator([
|
||||
'file1.php' => [
|
||||
'file1.l1.l2.k1' => $this->value,
|
||||
],
|
||||
'file2.php' => [
|
||||
'file2.l1.l2.k1' => $this->value,
|
||||
],
|
||||
], [
|
||||
'file1.php' => [
|
||||
'file1.l1.l2.k1' => $this->value,
|
||||
],
|
||||
'file2.php' => [
|
||||
'file2.l1.l2.k1' => $this->value,
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertTrue($validator->validate());
|
||||
$this->assertEquals('', $validator->displayResult());
|
||||
}
|
||||
|
||||
public function testValidateWhenValueIsEqual() {
|
||||
$this->value->expects($this->exactly(2))
|
||||
->method('isIgnore')
|
||||
->willReturn(false);
|
||||
$this->value->expects($this->exactly(2))
|
||||
->method('equal')
|
||||
->willReturn(true);
|
||||
|
||||
$validator = new I18nCompletionValidator([
|
||||
'file1.php' => [
|
||||
'file1.l1.l2.k1' => $this->value,
|
||||
],
|
||||
'file2.php' => [
|
||||
'file2.l1.l2.k1' => $this->value,
|
||||
],
|
||||
], [
|
||||
'file1.php' => [
|
||||
'file1.l1.l2.k1' => $this->value,
|
||||
],
|
||||
'file2.php' => [
|
||||
'file2.l1.l2.k1' => $this->value,
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertFalse($validator->validate());
|
||||
$this->assertEquals("Untranslated key file1.l1.l2.k1 - \nUntranslated key file2.l1.l2.k1 - \n", $validator->displayResult());
|
||||
}
|
||||
|
||||
public function testValidateWhenValueIsDifferent() {
|
||||
$this->value->expects($this->exactly(2))
|
||||
->method('isIgnore')
|
||||
->willReturn(false);
|
||||
$this->value->expects($this->exactly(2))
|
||||
->method('equal')
|
||||
->willReturn(false);
|
||||
|
||||
$validator = new I18nCompletionValidator([
|
||||
'file1.php' => [
|
||||
'file1.l1.l2.k1' => $this->value,
|
||||
],
|
||||
'file2.php' => [
|
||||
'file2.l1.l2.k1' => $this->value,
|
||||
],
|
||||
], [
|
||||
'file1.php' => [
|
||||
'file1.l1.l2.k1' => $this->value,
|
||||
],
|
||||
'file2.php' => [
|
||||
'file2.l1.l2.k1' => $this->value,
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertTrue($validator->validate());
|
||||
$this->assertEquals('', $validator->displayResult());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
require_once __DIR__ . '/../../../cli/i18n/I18nFile.php';
|
||||
|
||||
class I18nFileTest extends PHPUnit\Framework\TestCase {
|
||||
public function test() {
|
||||
$before = $this->computeFilesHash();
|
||||
|
||||
$file = new I18nFile();
|
||||
$data = $file->load();
|
||||
$file->dump($data);
|
||||
|
||||
$after = $this->computeFilesHash();
|
||||
|
||||
$this->assertEquals($before, $after);
|
||||
}
|
||||
|
||||
private function computeFilesHash() {
|
||||
$hashes = [];
|
||||
|
||||
$dirs = new DirectoryIterator(I18N_PATH);
|
||||
foreach ($dirs as $dir) {
|
||||
if ($dir->isDot()) {
|
||||
continue;
|
||||
}
|
||||
$files = new DirectoryIterator($dir->getPathname());
|
||||
foreach ($files as $file) {
|
||||
if (!$file->isFile()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$hashes[$file->getPathName()] = sha1_file($file->getPathName());
|
||||
}
|
||||
}
|
||||
|
||||
return $hashes;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
<?php
|
||||
|
||||
require_once __DIR__ . '/../../../cli/i18n/I18nValue.php';
|
||||
require_once __DIR__ . '/../../../cli/i18n/I18nUsageValidator.php';
|
||||
|
||||
class I18nUsageValidatorTest extends PHPUnit\Framework\TestCase {
|
||||
private $value;
|
||||
|
||||
public function setUp(): void {
|
||||
$this->value = $this->getMockBuilder(I18nValue::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
}
|
||||
|
||||
public function testDisplayReport() {
|
||||
$validator = new I18nUsageValidator([], []);
|
||||
|
||||
$this->assertEquals("There is no data.\n", $validator->displayReport());
|
||||
|
||||
$reflectionTotalEntries = new ReflectionProperty(I18nUsageValidator::class, 'totalEntries');
|
||||
$reflectionTotalEntries->setAccessible(true);
|
||||
$reflectionTotalEntries->setValue($validator, 100);
|
||||
|
||||
$this->assertEquals(" 0.0% of translation keys are unused.\n", $validator->displayReport());
|
||||
|
||||
$reflectionFailedEntries = new ReflectionProperty(I18nUsageValidator::class, 'failedEntries');
|
||||
$reflectionFailedEntries->setAccessible(true);
|
||||
$reflectionFailedEntries->setValue($validator, 25);
|
||||
|
||||
$this->assertEquals(" 25.0% of translation keys are unused.\n", $validator->displayReport());
|
||||
|
||||
$reflectionFailedEntries->setValue($validator, 100);
|
||||
|
||||
$this->assertEquals("100.0% of translation keys are unused.\n", $validator->displayReport());
|
||||
|
||||
$reflectionFailedEntries->setValue($validator, 200);
|
||||
|
||||
$this->expectException(\RuntimeException::class);
|
||||
$this->expectExceptionMessage('The number of unused strings cannot be higher than the number of strings');
|
||||
$validator->displayReport();
|
||||
}
|
||||
|
||||
public function testValidateWhenNoData() {
|
||||
$validator = new I18nUsageValidator([], []);
|
||||
$this->assertTrue($validator->validate());
|
||||
$this->assertEquals('', $validator->displayResult());
|
||||
}
|
||||
|
||||
public function testValidateWhenParentKeyExistsWithoutTransformation() {
|
||||
$validator = new I18nUsageValidator([
|
||||
'file1' => [
|
||||
'file1.l1.l2._' => $this->value,
|
||||
],
|
||||
'file2' => [
|
||||
'file2.l1.l2._' => $this->value,
|
||||
],
|
||||
], [
|
||||
'file1.l1.l2._',
|
||||
'file2.l1.l2._',
|
||||
]);
|
||||
$this->assertTrue($validator->validate());
|
||||
$this->assertEquals('', $validator->displayResult());
|
||||
}
|
||||
|
||||
public function testValidateWhenParentKeyExistsWithTransformation() {
|
||||
$validator = new I18nUsageValidator([
|
||||
'file1' => [
|
||||
'file1.l1.l2._' => $this->value,
|
||||
],
|
||||
'file2' => [
|
||||
'file2.l1.l2._' => $this->value,
|
||||
],
|
||||
], [
|
||||
'file1.l1.l2',
|
||||
'file2.l1.l2',
|
||||
]);
|
||||
$this->assertTrue($validator->validate());
|
||||
$this->assertEquals('', $validator->displayResult());
|
||||
}
|
||||
|
||||
public function testValidateWhenParentKeyDoesNotExist() {
|
||||
$validator = new I18nUsageValidator([
|
||||
'file1' => [
|
||||
'file1.l1.l2._' => $this->value,
|
||||
],
|
||||
'file2' => [
|
||||
'file2.l1.l2._' => $this->value,
|
||||
],
|
||||
], []);
|
||||
$this->assertFalse($validator->validate());
|
||||
$this->assertEquals("Unused key file1.l1.l2._ - \nUnused key file2.l1.l2._ - \n", $validator->displayResult());
|
||||
}
|
||||
|
||||
public function testValidateWhenChildKeyExists() {
|
||||
$validator = new I18nUsageValidator([
|
||||
'file1' => [
|
||||
'file1.l1.l2.k1' => $this->value,
|
||||
],
|
||||
'file2' => [
|
||||
'file2.l1.l2.k1' => $this->value,
|
||||
],
|
||||
], [
|
||||
'file1.l1.l2.k1',
|
||||
'file2.l1.l2.k1',
|
||||
]);
|
||||
$this->assertTrue($validator->validate());
|
||||
$this->assertEquals('', $validator->displayResult());
|
||||
}
|
||||
|
||||
public function testValidateWhenChildKeyDoesNotExist() {
|
||||
$validator = new I18nUsageValidator([
|
||||
'file1' => [
|
||||
'file1.l1.l2.k1' => $this->value,
|
||||
],
|
||||
'file2' => [
|
||||
'file2.l1.l2.k1' => $this->value,
|
||||
],
|
||||
], []);
|
||||
$this->assertFalse($validator->validate());
|
||||
$this->assertEquals("Unused key file1.l1.l2.k1 - \nUnused key file2.l1.l2.k1 - \n", $validator->displayResult());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
|
||||
require_once __DIR__ . '/../../../cli/i18n/I18nValue.php';
|
||||
|
||||
class I18nValueTest extends PHPUnit\Framework\TestCase {
|
||||
public function testConstructorWithoutState() {
|
||||
$value = new I18nValue('some value');
|
||||
$this->assertEquals('some value', $value->getValue());
|
||||
$this->assertFalse($value->isIgnore());
|
||||
$this->assertFalse($value->isTodo());
|
||||
}
|
||||
|
||||
public function testConstructorWithUnknownState() {
|
||||
$value = new I18nValue('some value -> unknown');
|
||||
$this->assertEquals('some value', $value->getValue());
|
||||
$this->assertFalse($value->isIgnore());
|
||||
$this->assertFalse($value->isTodo());
|
||||
}
|
||||
|
||||
public function testConstructorWithTodoState() {
|
||||
$value = new I18nValue('some value -> todo');
|
||||
$this->assertEquals('some value', $value->getValue());
|
||||
$this->assertFalse($value->isIgnore());
|
||||
$this->assertTrue($value->isTodo());
|
||||
}
|
||||
|
||||
public function testConstructorWithIgnoreState() {
|
||||
$value = new I18nValue('some value -> ignore');
|
||||
$this->assertEquals('some value', $value->getValue());
|
||||
$this->assertTrue($value->isIgnore());
|
||||
$this->assertFalse($value->isTodo());
|
||||
}
|
||||
|
||||
public function testClone() {
|
||||
$value = new I18nValue('some value');
|
||||
$clonedValue = clone $value;
|
||||
$this->assertEquals('some value', $value->getValue());
|
||||
$this->assertEquals('some value', $clonedValue->getValue());
|
||||
$this->assertFalse($value->isIgnore());
|
||||
$this->assertFalse($clonedValue->isIgnore());
|
||||
$this->assertFalse($value->isTodo());
|
||||
$this->assertTrue($clonedValue->isTodo());
|
||||
}
|
||||
|
||||
public function testEqualWhenValueIsIdentical() {
|
||||
$value = new I18nValue('some value');
|
||||
$clonedValue = clone $value;
|
||||
$this->assertTrue($value->equal($clonedValue));
|
||||
$this->assertTrue($clonedValue->equal($value));
|
||||
}
|
||||
|
||||
public function testEqualWhenValueIsDifferent() {
|
||||
$value = new I18nValue('some value');
|
||||
$otherValue = new I18nValue('some other value');
|
||||
$this->assertFalse($value->equal($otherValue));
|
||||
$this->assertFalse($otherValue->equal($value));
|
||||
}
|
||||
|
||||
public function testStates() {
|
||||
$reflectionProperty = new ReflectionProperty(I18nValue::class, 'state');
|
||||
$reflectionProperty->setAccessible(true);
|
||||
|
||||
$value = new I18nValue('some value');
|
||||
$this->assertNull($reflectionProperty->getValue($value));
|
||||
$value->markAsDirty();
|
||||
$this->assertEquals('dirty', $reflectionProperty->getValue($value));
|
||||
$value->unmarkAsIgnore();
|
||||
$this->assertEquals('dirty', $reflectionProperty->getValue($value));
|
||||
$value->markAsIgnore();
|
||||
$this->assertEquals('ignore', $reflectionProperty->getValue($value));
|
||||
$value->unmarkAsIgnore();
|
||||
$this->assertNull($reflectionProperty->getValue($value));
|
||||
$value->markAsTodo();
|
||||
$this->assertEquals('todo', $reflectionProperty->getValue($value));
|
||||
}
|
||||
|
||||
public function testToString() {
|
||||
$value = new I18nValue('some value');
|
||||
$this->assertEquals('some value', $value->__toString());
|
||||
$value->markAsTodo();
|
||||
$this->assertEquals('some value -> todo', $value->__toString());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue