Skip to content

Commit a5d6313

Browse files
committed
test: write tests for translation manager
1 parent 26a7f14 commit a5d6313

1 file changed

Lines changed: 217 additions & 0 deletions

File tree

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
<?php
2+
3+
use Ahc\Cli\Translations\Translator;
4+
use PHPUnit\Framework\TestCase;
5+
6+
class TranslatorTest extends TestCase
7+
{
8+
protected Translator $translator;
9+
10+
protected static string $baseTranslationsDir;
11+
12+
protected function setUp(): void
13+
{
14+
$this->translator = new Translator();
15+
}
16+
17+
public static function setUpBeforeClass(): void
18+
{
19+
self::$baseTranslationsDir = Translator::$translations_dir;
20+
}
21+
22+
protected function tearDown(): void
23+
{
24+
Translator::$translations_dir = self::$baseTranslationsDir;
25+
}
26+
27+
public function test_get_message_returns_empty_string_for_empty_key(): void
28+
{
29+
$result = $this->translator->getMessage('');
30+
$this->assertSame('', $result);
31+
}
32+
33+
public function test_default_translations_loaded_on_instantiation(): void
34+
{
35+
$reflector = new ReflectionClass(Translator::class);
36+
$translationsProperty = $reflector->getProperty('translations');
37+
$translationsProperty->setAccessible(true);
38+
39+
$translations = $translationsProperty->getValue();
40+
41+
$this->assertArrayHasKey('__default__', $translations);
42+
$this->assertNotEmpty($translations['__default__']);
43+
$this->assertSame(require self::$baseTranslationsDir . '/en.php', $translations['__default__']);
44+
}
45+
46+
public function test_get_message_returns_correct_translation_for_default_locale(): void
47+
{
48+
$key = 'badProgram';
49+
$expectedTranslation = 'Bad program could not be started.';
50+
51+
$result = $this->translator->getMessage($key);
52+
53+
$this->assertSame($expectedTranslation, $result);
54+
}
55+
56+
public function test_get_message_replaces_placeholders_with_arguments(): void
57+
{
58+
$key = 'test_placeholder';
59+
$message = 'Hello, %s! You are %d years old.';
60+
$args = ['John', 30];
61+
$expectedResult = 'Hello, John! You are 30 years old.';
62+
63+
// Set up a mock translation
64+
$reflector = new ReflectionClass(Translator::class);
65+
$translationsProperty = $reflector->getProperty('translations');
66+
$translationsProperty->setAccessible(true);
67+
$translationsProperty->setValue([
68+
'en' => [$key => $message]
69+
]);
70+
71+
$result = $this->translator->getMessage($key, $args);
72+
73+
$this->assertSame($expectedResult, $result);
74+
}
75+
76+
public function test_get_message_returns_empty_string_for_non_existent_key(): void
77+
{
78+
$nonExistentKey = 'non_existent_key';
79+
$result = $this->translator->getMessage($nonExistentKey);
80+
$this->assertSame('', $result);
81+
}
82+
83+
public function test_load_translations_for_non_default_locale(): void
84+
{
85+
$customLocale = 'french'; // dont use `fr` because it's a true locale and file exist
86+
Translator::$locale = $customLocale;
87+
88+
// Create a mock translation file for the custom locale
89+
$mockTranslations = [
90+
'test_key' => 'Test en français',
91+
];
92+
$mockFilePath = Translator::$translations_dir . '/' . $customLocale . '.php';
93+
file_put_contents($mockFilePath, '<?php return ' . var_export($mockTranslations, true) . ';');
94+
95+
$translator = new Translator();
96+
$result = $translator->getMessage('test_key');
97+
98+
$this->assertSame('Test en français', $result);
99+
100+
// Clean up
101+
unlink($mockFilePath);
102+
Translator::$locale = 'en';
103+
}
104+
105+
public function test_merge_custom_translations_with_default_translations(): void
106+
{
107+
$customLocale = 'fr';
108+
Translator::$locale = $customLocale;
109+
Translator::$translations_dir = __DIR__;
110+
111+
// Create mock custom translations
112+
$customTranslations = [
113+
'usage' => 'Utilisation',
114+
];
115+
116+
$mockCustomPath = Translator::$translations_dir . '/' . $customLocale . '.php';
117+
file_put_contents($mockCustomPath, '<?php return ' . var_export($customTranslations, true) . ';');
118+
119+
$translator = new Translator();
120+
121+
// Test merged translations
122+
$this->assertSame('Utilisation', $translator->getMessage('usage'));
123+
$this->assertSame('Usage Examples', $translator->getMessage('usageExamples'));
124+
125+
unlink($mockCustomPath);
126+
Translator::$locale = 'en';
127+
}
128+
129+
public function test_use_cached_translations_when_requesting_same_locale_multiple_times(): void
130+
{
131+
$customLocale = 'fr';
132+
Translator::$locale = $customLocale;
133+
Translator::$translations_dir = __DIR__;
134+
135+
// Create a mock translation file for the custom locale
136+
$mockTranslations = [
137+
'test_key' => 'Test en français',
138+
];
139+
$mockFilePath = Translator::$translations_dir . '/' . $customLocale . '.php';
140+
file_put_contents($mockFilePath, '<?php return ' . var_export($mockTranslations, true) . ';');
141+
142+
$translator = new Translator();
143+
144+
// First call to load translations
145+
$result1 = $translator->getMessage('test_key');
146+
$this->assertSame('Test en français', $result1);
147+
148+
// Modify the mock file to ensure we're using cached translations
149+
file_put_contents($mockFilePath, '<?php return ' . var_export(['test_key' => 'Modified test'], true) . ';');
150+
151+
// Second call should use cached translations
152+
$result2 = $translator->getMessage('test_key');
153+
$this->assertSame('Test en français', $result2);
154+
155+
// Clean up
156+
unlink($mockFilePath);
157+
Translator::$locale = 'en';
158+
}
159+
160+
public function test_handle_non_existent_translation_file(): void
161+
{
162+
$nonExistentLocale = 'xx';
163+
Translator::$locale = $nonExistentLocale;
164+
165+
// Ensure the translation file doesn't exist
166+
$nonExistentPath = Translator::$translations_dir . '/' . $nonExistentLocale . '.php';
167+
$this->assertFileDoesNotExist($nonExistentPath);
168+
169+
$translator = new Translator();
170+
171+
// Test with a key that exists in the default translations
172+
$defaultKey = 'badProgram';
173+
$expectedDefaultTranslation = 'Bad program could not be started.';
174+
$result = $translator->getMessage($defaultKey);
175+
$this->assertSame($expectedDefaultTranslation, $result);
176+
177+
// Test with a key that doesn't exist in the default translations
178+
$nonExistentKey = 'non_existent_key';
179+
$result = $translator->getMessage($nonExistentKey);
180+
$this->assertSame('', $result);
181+
182+
// Reset the locale
183+
Translator::$locale = 'en';
184+
}
185+
186+
public function test_change_locale_after_initial_translations_loaded(): void
187+
{
188+
Translator::$translations_dir = __DIR__;
189+
190+
// Set up initial locale and translations
191+
Translator::$locale = 'en';
192+
$translator = new Translator();
193+
$initialMessage = $translator->getMessage('badProgram');
194+
195+
// Change locale to a new one
196+
$newLocale = 'fr';
197+
Translator::$locale = $newLocale;
198+
199+
// Create mock translations for the new locale
200+
$mockTranslations = [
201+
'badProgram' => 'Mauvais programme',
202+
];
203+
$mockFilePath = Translator::$translations_dir . '/' . $newLocale . '.php';
204+
file_put_contents($mockFilePath, '<?php return ' . var_export($mockTranslations, true) . ';');
205+
206+
// Get message with new locale
207+
$newMessage = $translator->getMessage('badProgram');
208+
209+
// Assert that the messages are different
210+
$this->assertNotSame($initialMessage, $newMessage);
211+
$this->assertSame('Mauvais programme', $newMessage);
212+
213+
// Clean up
214+
unlink($mockFilePath);
215+
Translator::$locale = 'en';
216+
}
217+
}

0 commit comments

Comments
 (0)