NameTest.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Customer\Test\Unit\Block\Widget;
  7. use Magento\Customer\Api\Data\AttributeMetadataInterface;
  8. use Magento\Framework\Exception\NoSuchEntityException;
  9. use Magento\Customer\Block\Widget\Name;
  10. /**
  11. * Test class for \Magento\Customer\Block\Widget\Name.
  12. *
  13. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  14. */
  15. class NameTest extends \PHPUnit\Framework\TestCase
  16. {
  17. /**#@+
  18. * Constant values used throughout the various unit tests.
  19. */
  20. const PREFIX = 'Mr';
  21. const MIDDLENAME = 'Middle';
  22. const SUFFIX = 'Jr';
  23. const KEY_CLASS_NAME = 'class_name';
  24. const DEFAULT_CLASS_NAME = 'customer-name';
  25. const CUSTOM_CLASS_NAME = 'my-class-name';
  26. const CONTAINER_CLASS_NAME_PREFIX = '-prefix';
  27. const CONTAINER_CLASS_NAME_MIDDLENAME = '-middlename';
  28. const CONTAINER_CLASS_NAME_SUFFIX = '-suffix';
  29. const PREFIX_ATTRIBUTE_CODE = 'prefix';
  30. const INVALID_ATTRIBUTE_CODE = 'invalid attribute code';
  31. const PREFIX_STORE_LABEL = 'Name Prefix';
  32. /**#@-*/
  33. /** @var \PHPUnit_Framework_MockObject_MockObject | AttributeMetadataInterface */
  34. private $attribute;
  35. /** @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Customer\Model\Options */
  36. private $_options;
  37. /** @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\Escaper */
  38. private $_escaper;
  39. /** @var Name */
  40. private $_block;
  41. /** @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Customer\Api\CustomerMetadataInterface */
  42. private $customerMetadata;
  43. /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Customer\Api\AddressMetadataInterface */
  44. private $addressMetadata;
  45. /**
  46. * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager
  47. */
  48. protected $_objectManager;
  49. protected function setUp()
  50. {
  51. $this->_objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
  52. $this->_escaper = $this->createMock(\Magento\Framework\Escaper::class);
  53. $context = $this->createMock(\Magento\Framework\View\Element\Template\Context::class);
  54. $context->expects($this->any())->method('getEscaper')->will($this->returnValue($this->_escaper));
  55. $addressHelper = $this->createMock(\Magento\Customer\Helper\Address::class);
  56. $this->_options = $this->createMock(\Magento\Customer\Model\Options::class);
  57. $this->attribute = $this->getMockBuilder(\Magento\Customer\Api\Data\AttributeMetadataInterface::class)
  58. ->getMockForAbstractClass();
  59. $this->customerMetadata = $this->getMockBuilder(\Magento\Customer\Api\CustomerMetadataInterface::class)
  60. ->getMockForAbstractClass();
  61. $this->customerMetadata->expects($this->any())
  62. ->method('getAttributeMetadata')
  63. ->will($this->returnValue($this->attribute));
  64. $this->customerMetadata
  65. ->expects($this->any())
  66. ->method('getCustomAttributesMetadata')
  67. ->will($this->returnValue([]));
  68. $this->addressMetadata = $this->getMockBuilder(\Magento\Customer\Api\AddressMetadataInterface::class)
  69. ->getMockForAbstractClass();
  70. $this->addressMetadata->expects($this->any())
  71. ->method('getAttributeMetadata')
  72. ->will($this->returnValue($this->attribute));
  73. $this->_block = new \Magento\Customer\Block\Widget\Name(
  74. $context,
  75. $addressHelper,
  76. $this->customerMetadata,
  77. $this->_options,
  78. $this->addressMetadata
  79. );
  80. }
  81. /**
  82. * @see self::_setUpShowAttribute()
  83. */
  84. public function testShowPrefix()
  85. {
  86. $this->_setUpShowAttribute([\Magento\Customer\Model\Data\Customer::PREFIX => self::PREFIX]);
  87. $this->assertTrue($this->_block->showPrefix());
  88. $this->attribute->expects($this->at(0))->method('isVisible')->will($this->returnValue(false));
  89. $this->assertFalse($this->_block->showPrefix());
  90. }
  91. public function testShowPrefixWithException()
  92. {
  93. $this->customerMetadata->expects(
  94. $this->any()
  95. )->method(
  96. 'getAttributeMetadata'
  97. )->will(
  98. $this->throwException(new NoSuchEntityException(
  99. __(
  100. 'No such entity with %fieldName = %fieldValue',
  101. ['fieldName' => 'field', 'fieldValue' => 'value']
  102. )
  103. ))
  104. );
  105. $this->assertFalse($this->_block->showPrefix());
  106. }
  107. /**
  108. * @param $method
  109. * @dataProvider methodDataProvider
  110. */
  111. public function testMethodWithNoSuchEntityException($method)
  112. {
  113. $this->customerMetadata->expects(
  114. $this->any()
  115. )->method(
  116. 'getAttributeMetadata'
  117. )->will(
  118. $this->throwException(new NoSuchEntityException(
  119. __(
  120. 'No such entity with %fieldName = %fieldValue',
  121. ['fieldName' => 'field', 'fieldValue' => 'value']
  122. )
  123. ))
  124. );
  125. $this->assertFalse($this->_block->{$method}());
  126. }
  127. /**
  128. * @return array
  129. */
  130. public function methodDataProvider()
  131. {
  132. return [
  133. 'showPrefix' => ['showPrefix'],
  134. 'isPrefixRequired' => ['isPrefixRequired'],
  135. 'showMiddlename' => ['showMiddlename'],
  136. 'isMiddlenameRequired' => ['isMiddlenameRequired'],
  137. 'showSuffix' => ['showSuffix'],
  138. 'isSuffixRequired' => ['isSuffixRequired']
  139. ];
  140. }
  141. /**
  142. * @see self::_setUpIsAttributeRequired()
  143. */
  144. public function testIsPrefixRequired()
  145. {
  146. $this->_setUpIsAttributeRequired();
  147. $this->assertTrue($this->_block->isPrefixRequired());
  148. }
  149. public function testShowMiddlename()
  150. {
  151. $this->_setUpShowAttribute([\Magento\Customer\Model\Data\Customer::MIDDLENAME => self::MIDDLENAME]);
  152. $this->assertTrue($this->_block->showMiddlename());
  153. }
  154. public function testIsMiddlenameRequired()
  155. {
  156. $this->_setUpIsAttributeRequired();
  157. $this->assertTrue($this->_block->isMiddlenameRequired());
  158. }
  159. public function testShowSuffix()
  160. {
  161. $this->_setUpShowAttribute([\Magento\Customer\Model\Data\Customer::SUFFIX => self::SUFFIX]);
  162. $this->assertTrue($this->_block->showSuffix());
  163. }
  164. public function testIsSuffixRequired()
  165. {
  166. $this->_setUpIsAttributeRequired();
  167. $this->assertTrue($this->_block->isSuffixRequired());
  168. }
  169. public function testGetPrefixOptionsNotEmpty()
  170. {
  171. /**
  172. * Added some padding so that the trim() call on Customer::getPrefix() will remove it. Also added
  173. * special characters so that the escapeHtml() method returns a htmlspecialchars translated value.
  174. */
  175. $customer = $this->getMockBuilder(
  176. \Magento\Customer\Api\Data\CustomerInterface::class
  177. )->getMockForAbstractClass();
  178. $customer->expects($this->once())->method('getPrefix')->willReturn(' <' . self::PREFIX . '> ');
  179. $this->_block->setObject($customer);
  180. $prefixOptions = ['Mrs' => 'Mrs', 'Ms' => 'Ms', 'Miss' => 'Miss'];
  181. $prefix = '&lt;' . self::PREFIX . '&gt;';
  182. $expectedOptions = $prefixOptions;
  183. $expectedOptions[$prefix] = $prefix;
  184. $this->_options->expects(
  185. $this->once()
  186. )->method(
  187. 'getNamePrefixOptions'
  188. )->will(
  189. $this->returnValue($prefixOptions)
  190. );
  191. $this->_escaper->expects($this->once())->method('escapeHtml')->will($this->returnValue($prefix));
  192. $this->assertSame($expectedOptions, $this->_block->getPrefixOptions());
  193. }
  194. public function testGetPrefixOptionsEmpty()
  195. {
  196. $customer = $this->getMockBuilder(
  197. \Magento\Customer\Api\Data\CustomerInterface::class
  198. )->getMockForAbstractClass();
  199. $this->_block->setObject($customer);
  200. $this->_options->expects(
  201. $this->once()
  202. )->method(
  203. 'getNamePrefixOptions'
  204. )->will(
  205. $this->returnValue([])
  206. );
  207. $this->assertEmpty($this->_block->getPrefixOptions());
  208. }
  209. public function testGetSuffixOptionsNotEmpty()
  210. {
  211. /**
  212. * Added padding and special characters to show that trim() works on Customer::getSuffix() and that
  213. * a properly htmlspecialchars translated value is returned.
  214. */
  215. $customer = $this->getMockBuilder(
  216. \Magento\Customer\Api\Data\CustomerInterface::class
  217. )->getMockForAbstractClass();
  218. $customer->expects($this->once())->method('getSuffix')->willReturn(' <' . self::SUFFIX . '> ');
  219. $this->_block->setObject($customer);
  220. $suffixOptions = ['Sr' => 'Sr'];
  221. $suffix = '&lt;' . self::SUFFIX . '&gt;';
  222. $expectedOptions = $suffixOptions;
  223. $expectedOptions[$suffix] = $suffix;
  224. $this->_options->expects(
  225. $this->once()
  226. )->method(
  227. 'getNameSuffixOptions'
  228. )->will(
  229. $this->returnValue($suffixOptions)
  230. );
  231. $this->_escaper->expects($this->once())->method('escapeHtml')->will($this->returnValue($suffix));
  232. $this->assertSame($expectedOptions, $this->_block->getSuffixOptions());
  233. }
  234. public function testGetSuffixOptionsEmpty()
  235. {
  236. $customer = $this->getMockBuilder(
  237. \Magento\Customer\Api\Data\CustomerInterface::class
  238. )->getMockForAbstractClass();
  239. $this->_block->setObject($customer);
  240. $this->_options->expects(
  241. $this->once()
  242. )->method(
  243. 'getNameSuffixOptions'
  244. )->will(
  245. $this->returnValue([])
  246. );
  247. $this->assertEmpty($this->_block->getSuffixOptions());
  248. }
  249. public function testGetClassName()
  250. {
  251. /** Test the default case when the block has no data set for the class name. */
  252. $this->assertEquals(self::DEFAULT_CLASS_NAME, $this->_block->getClassName());
  253. /** Set custom data for the class name and verify that the Name::getClassName() method returns it. */
  254. $this->_block->setData(self::KEY_CLASS_NAME, self::CUSTOM_CLASS_NAME);
  255. $this->assertEquals(self::CUSTOM_CLASS_NAME, $this->_block->getClassName());
  256. }
  257. /**
  258. * @param bool $isPrefixVisible Value returned by Name::showPrefix()
  259. * @param bool $isMiddlenameVisible Value returned by Name::showMiddlename()
  260. * @param bool $isSuffixVisible Value returned by Name::showSuffix()
  261. * @param string $expectedValue The expected value of Name::getContainerClassName()
  262. *
  263. * @dataProvider getContainerClassNameProvider
  264. */
  265. public function testGetContainerClassName($isPrefixVisible, $isMiddlenameVisible, $isSuffixVisible, $expectedValue)
  266. {
  267. $this->attribute->expects(
  268. $this->at(0)
  269. )->method(
  270. 'isVisible'
  271. )->will(
  272. $this->returnValue($isPrefixVisible)
  273. );
  274. $this->attribute->expects(
  275. $this->at(1)
  276. )->method(
  277. 'isVisible'
  278. )->will(
  279. $this->returnValue($isMiddlenameVisible)
  280. );
  281. $this->attribute->expects(
  282. $this->at(2)
  283. )->method(
  284. 'isVisible'
  285. )->will(
  286. $this->returnValue($isSuffixVisible)
  287. );
  288. $this->assertEquals($expectedValue, $this->_block->getContainerClassName());
  289. }
  290. /**
  291. * This data provider provides enough data sets to test both ternary operator code paths for each one
  292. * that's used in Name::getContainerClassName().
  293. *
  294. * @return array
  295. */
  296. public function getContainerClassNameProvider()
  297. {
  298. return [
  299. [false, false, false, self::DEFAULT_CLASS_NAME],
  300. [true, false, false, self::DEFAULT_CLASS_NAME . self::CONTAINER_CLASS_NAME_PREFIX],
  301. [false, true, false, self::DEFAULT_CLASS_NAME . self::CONTAINER_CLASS_NAME_MIDDLENAME],
  302. [false, false, true, self::DEFAULT_CLASS_NAME . self::CONTAINER_CLASS_NAME_SUFFIX],
  303. [
  304. true,
  305. true,
  306. true,
  307. self::DEFAULT_CLASS_NAME .
  308. self::CONTAINER_CLASS_NAME_PREFIX .
  309. self::CONTAINER_CLASS_NAME_MIDDLENAME .
  310. self::CONTAINER_CLASS_NAME_SUFFIX
  311. ]
  312. ];
  313. }
  314. /**
  315. * @param string $attributeCode An attribute code
  316. * @param string $storeLabel The attribute's store label
  317. * @param string $expectedValue The expected value of Name::getStoreLabel()
  318. *
  319. * @dataProvider getStoreLabelProvider
  320. */
  321. public function testGetStoreLabel($attributeCode, $storeLabel, $expectedValue)
  322. {
  323. $this->attribute->expects($this->atLeastOnce())->method('getStoreLabel')->willReturn($storeLabel);
  324. $this->assertEquals($expectedValue, $this->_block->getStoreLabel($attributeCode));
  325. }
  326. /**
  327. * This data provider provides two data sets. One tests that an empty string is returned for an invalid
  328. * attribute code instead of an exception being thrown. The second tests that the correct store label is
  329. * returned for a valid attribute code.
  330. *
  331. * @return array
  332. */
  333. public function getStoreLabelProvider()
  334. {
  335. return [
  336. [self::INVALID_ATTRIBUTE_CODE, '', ''],
  337. [self::PREFIX_ATTRIBUTE_CODE, self::PREFIX_STORE_LABEL, self::PREFIX_STORE_LABEL]
  338. ];
  339. }
  340. public function testGetStoreLabelWithException()
  341. {
  342. $this->customerMetadata->expects(
  343. $this->any()
  344. )->method(
  345. 'getAttributeMetadata'
  346. )->will(
  347. $this->throwException(new NoSuchEntityException(
  348. __(
  349. 'No such entity with %fieldName = %fieldValue',
  350. ['fieldName' => 'field', 'fieldValue' => 'value']
  351. )
  352. ))
  353. );
  354. $this->assertSame('', (string)$this->_block->getStoreLabel('attributeCode'));
  355. }
  356. /**
  357. * Helper method for testing all show*() methods.
  358. *
  359. * @param array $data Customer attribute(s)
  360. * @SuppressWarnings(PHPMD.UnusedFormalParameter)
  361. */
  362. private function _setUpShowAttribute(array $data)
  363. {
  364. $customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)
  365. ->getMockForAbstractClass();
  366. /**
  367. * These settings cause the first code path in Name::_getAttribute() to be executed, which
  368. * basically just returns the value of parent::_getAttribute().
  369. */
  370. $this->_block->setForceUseCustomerAttributes(true);
  371. $this->_block->setObject($customer);
  372. /**
  373. * The show*() methods return true for the attribute returned by parent::_getAttribute() for the
  374. * first call to the method. Subsequent calls may return true or false depending on the returnValue
  375. * of the at({0, 1, 2, 3, ...}), etc. calls as set and configured in a particular test.
  376. */
  377. $this->attribute->expects($this->at(0))->method('isVisible')->will($this->returnValue(true));
  378. }
  379. /**
  380. * Helper method for testing all is*Required() methods.
  381. */
  382. private function _setUpIsAttributeRequired()
  383. {
  384. /**
  385. * These settings cause the first code path in Name::_getAttribute() to be skipped so that the rest of
  386. * the code in the other code path(s) can be executed.
  387. */
  388. $this->_block->setForceUseCustomerAttributes(false);
  389. $this->_block->setForceUseCustomerRequiredAttributes(true);
  390. $this->_block->setObject(new \StdClass());
  391. /**
  392. * The first call to isRequired() is false so that the second if conditional in the other code path
  393. * of Name::_getAttribute() will evaluate to true, which causes the if's code block to be executed.
  394. * The second isRequired() call causes the code in the nested if conditional to be executed. Thus,
  395. * all code paths in Name::_getAttribute() will be executed. Returning true for the third isRequired()
  396. * call causes the is*Required() method of the block to return true for the attribute.
  397. */
  398. $this->attribute->expects($this->at(0))->method('isRequired')->will($this->returnValue(false));
  399. $this->attribute->expects($this->at(1))->method('isRequired')->will($this->returnValue(true));
  400. $this->attribute->expects($this->at(2))->method('isRequired')->will($this->returnValue(true));
  401. }
  402. }