Skip to content

Commit 57fcc1b

Browse files
committed
magento#17833:  Child theme does not inherit translations from parent theme
- forward port unit tests from 2.2-develop branch
1 parent 90cf2e0 commit 57fcc1b

File tree

2 files changed

+373
-2
lines changed

2 files changed

+373
-2
lines changed
Lines changed: 371 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,371 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Framework\Test\Unit;
7+
8+
use Magento\Framework\Serialize\SerializerInterface;
9+
use Magento\Framework\Translate;
10+
11+
/**
12+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
13+
*/
14+
class TranslateTest extends \PHPUnit\Framework\TestCase
15+
{
16+
/** @var Translate */
17+
protected $translate;
18+
19+
/** @var \Magento\Framework\View\DesignInterface|\PHPUnit_Framework_MockObject_MockObject */
20+
protected $viewDesign;
21+
22+
/** @var \Magento\Framework\Cache\FrontendInterface|\PHPUnit_Framework_MockObject_MockObject */
23+
protected $cache;
24+
25+
/** @var \Magento\Framework\View\FileSystem|\PHPUnit_Framework_MockObject_MockObject */
26+
protected $viewFileSystem;
27+
28+
/** @var \Magento\Framework\Module\ModuleList|\PHPUnit_Framework_MockObject_MockObject */
29+
protected $moduleList;
30+
31+
/** @var \Magento\Framework\Module\Dir\Reader|\PHPUnit_Framework_MockObject_MockObject */
32+
protected $modulesReader;
33+
34+
/** @var \Magento\Framework\App\ScopeResolverInterface|\PHPUnit_Framework_MockObject_MockObject */
35+
protected $scopeResolver;
36+
37+
/** @var \Magento\Framework\Translate\ResourceInterface|\PHPUnit_Framework_MockObject_MockObject */
38+
protected $resource;
39+
40+
/** @var \Magento\Framework\Locale\ResolverInterface|\PHPUnit_Framework_MockObject_MockObject */
41+
protected $locale;
42+
43+
/** @var \Magento\Framework\App\State|\PHPUnit_Framework_MockObject_MockObject */
44+
protected $appState;
45+
46+
/** @var \Magento\Framework\Filesystem|\PHPUnit_Framework_MockObject_MockObject */
47+
protected $filesystem;
48+
49+
/** @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject */
50+
protected $request;
51+
52+
/** @var \Magento\Framework\File\Csv|\PHPUnit_Framework_MockObject_MockObject */
53+
protected $csvParser;
54+
55+
/** @var \Magento\Framework\App\Language\Dictionary|\PHPUnit_Framework_MockObject_MockObject */
56+
protected $packDictionary;
57+
58+
/** @var \Magento\Framework\Filesystem\Directory\ReadInterface|\PHPUnit_Framework_MockObject_MockObject */
59+
protected $directory;
60+
61+
/** @var \Magento\Framework\Filesystem\DriverInterface|\PHPUnit_Framework_MockObject_MockObject */
62+
protected $fileDriver;
63+
64+
protected function setUp()
65+
{
66+
$objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
67+
$this->viewDesign = $this->createMock(\Magento\Framework\View\DesignInterface::class);
68+
$this->cache = $this->createMock(\Magento\Framework\Cache\FrontendInterface::class);
69+
$this->viewFileSystem = $this->createMock(\Magento\Framework\View\FileSystem::class);
70+
$this->moduleList = $this->createMock(\Magento\Framework\Module\ModuleList::class);
71+
$this->modulesReader = $this->createMock(\Magento\Framework\Module\Dir\Reader::class);
72+
$this->scopeResolver = $this->createMock(\Magento\Framework\App\ScopeResolverInterface::class);
73+
$this->resource = $this->createMock(\Magento\Framework\Translate\ResourceInterface::class);
74+
$this->locale = $this->createMock(\Magento\Framework\Locale\ResolverInterface::class);
75+
$this->appState = $this->createMock(\Magento\Framework\App\State::class);
76+
$this->request = $this->getMockForAbstractClass(
77+
\Magento\Framework\App\RequestInterface::class,
78+
[],
79+
'',
80+
false,
81+
false,
82+
true,
83+
['getParam', 'getControllerModule']
84+
);
85+
$this->csvParser = $this->createMock(\Magento\Framework\File\Csv::class);
86+
$this->packDictionary = $this->createMock(\Magento\Framework\App\Language\Dictionary::class);
87+
$this->directory = $this->createMock(\Magento\Framework\Filesystem\Directory\ReadInterface::class);
88+
$filesystem = $this->createMock(\Magento\Framework\Filesystem::class);
89+
$filesystem->expects($this->once())->method('getDirectoryRead')->will($this->returnValue($this->directory));
90+
$this->fileDriver = $this->createMock(\Magento\Framework\Filesystem\DriverInterface::class);
91+
92+
$this->translate = new Translate(
93+
$this->viewDesign,
94+
$this->cache,
95+
$this->viewFileSystem,
96+
$this->moduleList,
97+
$this->modulesReader,
98+
$this->scopeResolver,
99+
$this->resource,
100+
$this->locale,
101+
$this->appState,
102+
$filesystem,
103+
$this->request,
104+
$this->csvParser,
105+
$this->packDictionary,
106+
$this->fileDriver
107+
);
108+
109+
$serializerMock = $this->createMock(SerializerInterface::class);
110+
$serializerMock->method('serialize')
111+
->willReturnCallback(function ($data) {
112+
return json_encode($data);
113+
});
114+
$serializerMock->method('unserialize')
115+
->willReturnCallback(function ($string) {
116+
return json_decode($string, true);
117+
});
118+
$objectManager->setBackwardCompatibleProperty(
119+
$this->translate,
120+
'serializer',
121+
$serializerMock
122+
);
123+
}
124+
125+
/**
126+
* @param string $area
127+
* @param bool $forceReload
128+
* @param array $cachedData
129+
* @dataProvider dataProviderLoadDataCachedTranslation
130+
*/
131+
public function testLoadDataCachedTranslation($area, $forceReload, $cachedData)
132+
{
133+
$this->expectsSetConfig('Magento/luma');
134+
135+
$this->cache->expects($this->once())
136+
->method('load')
137+
->will($this->returnValue(json_encode($cachedData)));
138+
139+
$this->appState->expects($this->exactly($area ? 0 : 1))
140+
->method('getAreaCode')
141+
->will($this->returnValue('frontend'));
142+
143+
$this->translate->loadData($area, $forceReload);
144+
$this->assertEquals($cachedData, $this->translate->getData());
145+
}
146+
147+
/**
148+
* @return array
149+
*/
150+
public function dataProviderLoadDataCachedTranslation()
151+
{
152+
$cachedData = ['cached 1' => 'translated 1', 'cached 2' => 'translated 2'];
153+
return [
154+
['adminhtml', false, $cachedData],
155+
['frontend', false, $cachedData],
156+
[null, false, $cachedData],
157+
];
158+
}
159+
160+
/**
161+
* @param string $area
162+
* @param bool $forceReload
163+
* @dataProvider dataProviderForTestLoadData
164+
* @SuppressWarnings(PHPMD.NPathComplexity)
165+
*/
166+
public function testLoadData($area, $forceReload)
167+
{
168+
$this->expectsSetConfig('Magento/luma');
169+
170+
$this->appState->expects($this->exactly($area ? 0 : 1))
171+
->method('getAreaCode')
172+
->will($this->returnValue('frontend'));
173+
174+
$this->cache->expects($this->exactly($forceReload ? 0 : 1))
175+
->method('load')
176+
->will($this->returnValue(false));
177+
178+
$this->directory->expects($this->any())->method('isExist')->will($this->returnValue(true));
179+
180+
// _loadModuleTranslation()
181+
$modules = ['some_module', 'other_module', 'another_module', 'current_module'];
182+
$this->request->expects($this->any())
183+
->method('getControllerModule')
184+
->willReturn('current_module');
185+
$this->moduleList->expects($this->once())->method('getNames')->will($this->returnValue($modules));
186+
$moduleData = [
187+
'module original' => 'module translated',
188+
'module theme' => 'module-theme original translated',
189+
'module pack' => 'module-pack original translated',
190+
'module db' => 'module-db original translated',
191+
];
192+
$this->modulesReader->expects($this->any())->method('getModuleDir')->will($this->returnValue('/app/module'));
193+
$themeData = [
194+
'theme original' => 'theme translated',
195+
'module theme' => 'theme translated overwrite',
196+
'module pack' => 'theme-pack translated overwrite',
197+
'module db' => 'theme-db translated overwrite',
198+
];
199+
$this->csvParser->expects($this->any())
200+
->method('getDataPairs')
201+
->will(
202+
$this->returnValueMap(
203+
[
204+
['/app/module/en_US.csv', 0, 1, $moduleData],
205+
['/app/module/en_GB.csv', 0, 1, $moduleData],
206+
['/theme.csv', 0, 1, $themeData],
207+
]
208+
)
209+
);
210+
$this->fileDriver->expects($this->any())
211+
->method('isExists')
212+
->will(
213+
$this->returnValueMap(
214+
[
215+
['/app/module/en_US.csv', true],
216+
['/app/module/en_GB.csv', true],
217+
['/theme.csv', true],
218+
]
219+
)
220+
);
221+
222+
// _loadPackTranslation
223+
$packData = [
224+
'pack original' => 'pack translated',
225+
'module pack' => 'pack translated overwrite',
226+
'module db' => 'pack-db translated overwrite',
227+
];
228+
$this->packDictionary->expects($this->once())->method('getDictionary')->will($this->returnValue($packData));
229+
230+
// _loadThemeTranslation()
231+
$this->viewFileSystem->expects($this->any())
232+
->method('getLocaleFileName')
233+
->will($this->returnValue('/theme.csv'));
234+
235+
// _loadDbTranslation()
236+
$dbData = [
237+
'db original' => 'db translated',
238+
'module db' => 'db translated overwrite',
239+
];
240+
$this->resource->expects($this->any())->method('getTranslationArray')->will($this->returnValue($dbData));
241+
242+
$this->cache->expects($this->exactly($forceReload ? 0 : 1))->method('save');
243+
244+
$this->translate->loadData($area, $forceReload);
245+
246+
$expected = [
247+
'module original' => 'module translated',
248+
'module theme' => 'theme translated overwrite',
249+
'module pack' => 'theme-pack translated overwrite',
250+
'module db' => 'db translated overwrite',
251+
'theme original' => 'theme translated',
252+
'pack original' => 'pack translated',
253+
'db original' => 'db translated',
254+
];
255+
$this->assertEquals($expected, $this->translate->getData());
256+
}
257+
258+
/**
259+
* @return array
260+
*/
261+
public function dataProviderForTestLoadData()
262+
{
263+
return [
264+
['adminhtml', true],
265+
['adminhtml', false],
266+
['frontend', true],
267+
['frontend', false],
268+
[null, true],
269+
[null, false]
270+
];
271+
}
272+
273+
/**
274+
* @param $data
275+
* @param $result
276+
* @dataProvider dataProviderForTestGetData
277+
*/
278+
public function testGetData($data, $result)
279+
{
280+
$this->cache->expects($this->once())
281+
->method('load')
282+
->will($this->returnValue(json_encode($data)));
283+
$this->expectsSetConfig('themeId');
284+
$this->translate->loadData('frontend');
285+
$this->assertEquals($result, $this->translate->getData());
286+
}
287+
288+
/**
289+
* @return array
290+
*/
291+
public function dataProviderForTestGetData()
292+
{
293+
$data = ['original 1' => 'translated 1', 'original 2' => 'translated 2'];
294+
return [
295+
[$data, $data],
296+
[null, []]
297+
];
298+
}
299+
300+
public function testGetLocale()
301+
{
302+
$this->locale->expects($this->once())->method('getLocale')->will($this->returnValue('en_US'));
303+
$this->assertEquals('en_US', $this->translate->getLocale());
304+
305+
$this->locale->expects($this->never())->method('getLocale');
306+
$this->assertEquals('en_US', $this->translate->getLocale());
307+
308+
$this->locale->expects($this->never())->method('getLocale');
309+
$this->translate->setLocale('en_GB');
310+
$this->assertEquals('en_GB', $this->translate->getLocale());
311+
}
312+
313+
public function testSetLocale()
314+
{
315+
$this->translate->setLocale('en_GB');
316+
$this->locale->expects($this->never())->method('getLocale');
317+
$this->assertEquals('en_GB', $this->translate->getLocale());
318+
}
319+
320+
public function testGetTheme()
321+
{
322+
$this->request->expects($this->at(0))->method('getParam')->with('theme')->will($this->returnValue(''));
323+
324+
$requestTheme = ['theme_title' => 'Theme Title'];
325+
$this->request->expects($this->at(1))->method('getParam')->with('theme')
326+
->will($this->returnValue($requestTheme));
327+
328+
$this->assertEquals('theme', $this->translate->getTheme());
329+
$this->assertEquals('themeTheme Title', $this->translate->getTheme());
330+
}
331+
332+
public function testLoadDataNoTheme()
333+
{
334+
$forceReload = true;
335+
$this->expectsSetConfig(null, null);
336+
$this->moduleList->expects($this->once())->method('getNames')->will($this->returnValue([]));
337+
$this->appState->expects($this->once())->method('getAreaCode')->will($this->returnValue('frontend'));
338+
$this->packDictionary->expects($this->once())->method('getDictionary')->will($this->returnValue([]));
339+
$this->resource->expects($this->any())->method('getTranslationArray')->will($this->returnValue([]));
340+
$this->assertEquals($this->translate, $this->translate->loadData(null, $forceReload));
341+
}
342+
343+
/**
344+
* Declare calls expectation for setConfig() method
345+
*/
346+
protected function expectsSetConfig($themeId, $localeCode = 'en_US')
347+
{
348+
$this->locale->expects($this->any())->method('getLocale')->will($this->returnValue($localeCode));
349+
$scope = new \Magento\Framework\DataObject(['code' => 'frontendCode', 'id' => 1]);
350+
$scopeAdmin = new \Magento\Framework\DataObject(['code' => 'adminCode', 'id' => 0]);
351+
$this->scopeResolver->expects($this->any())
352+
->method('getScope')
353+
->will(
354+
$this->returnValueMap(
355+
[
356+
[null, $scope],
357+
['admin', $scopeAdmin],
358+
]
359+
)
360+
);
361+
$designTheme = $this->getMockBuilder(\Magento\Theme\Model\Theme::class)
362+
->disableOriginalConstructor()
363+
->getMock();
364+
365+
$designTheme->expects($this->once())
366+
->method('getThemePath')
367+
->willReturn($themeId);
368+
369+
$this->viewDesign->expects($this->any())->method('getDesignTheme')->will($this->returnValue($designTheme));
370+
}
371+
}

lib/internal/Magento/Framework/Translate.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -398,11 +398,11 @@ protected function _getModuleTranslationFile($moduleName, $locale)
398398
/**
399399
* Get theme translation locale file name
400400
*
401-
* @param string $locale
401+
* @param string|null $locale
402402
* @param array $config
403403
* @return string|null
404404
*/
405-
private function getThemeTranslationFileName(string $locale, array $config): ?string
405+
private function getThemeTranslationFileName(?string $locale, array $config): ?string
406406
{
407407
$fileName = $this->_viewFileSystem->getLocaleFileName(
408408
'i18n' . '/' . $locale . '.csv',

0 commit comments

Comments
 (0)