| Current Path : /home/rtorresani/www/vendor/magento/module-customer/Test/Unit/Block/Widget/ |
| Current File : //home/rtorresani/www/vendor/magento/module-customer/Test/Unit/Block/Widget/NameTest.php |
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);
namespace Magento\Customer\Test\Unit\Block\Widget;
use Magento\Customer\Api\AddressMetadataInterface;
use Magento\Customer\Api\CustomerMetadataInterface;
use Magento\Customer\Api\Data\AttributeMetadataInterface;
use Magento\Customer\Api\Data\CustomerInterface;
use Magento\Customer\Block\Widget\Name;
use Magento\Customer\Helper\Address;
use Magento\Customer\Model\Data\Customer;
use Magento\Customer\Model\Options;
use Magento\Framework\Escaper;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
use Magento\Framework\View\Element\Template\Context;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
/**
* Test class for \Magento\Customer\Block\Widget\Name.
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class NameTest extends TestCase
{
/**#@+
* Constant values used throughout the various unit tests.
*/
const PREFIX = 'Mr';
const MIDDLENAME = 'Middle';
const SUFFIX = 'Jr';
const KEY_CLASS_NAME = 'class_name';
const DEFAULT_CLASS_NAME = 'customer-name';
const CUSTOM_CLASS_NAME = 'my-class-name';
const CONTAINER_CLASS_NAME_PREFIX = '-prefix';
const CONTAINER_CLASS_NAME_MIDDLENAME = '-middlename';
const CONTAINER_CLASS_NAME_SUFFIX = '-suffix';
const PREFIX_ATTRIBUTE_CODE = 'prefix';
const INVALID_ATTRIBUTE_CODE = 'invalid attribute code';
const PREFIX_STORE_LABEL = 'Name Prefix';
/**#@-*/
/**
* @var MockObject|AttributeMetadataInterface
*/
private $attribute;
/**
* @var MockObject|Options
*/
private $_options;
/**
* @var MockObject|Escaper
*/
private $_escaper;
/**
* @var Name
*/
private $_block;
/**
* @var MockObject|CustomerMetadataInterface
*/
private $customerMetadata;
/**
* @var MockObject|AddressMetadataInterface
*/
private $addressMetadata;
/**
* @var ObjectManager
*/
protected $_objectManager;
/**
* @var bool
*/
private $isVisibleAttribute = true;
/**
* @inheritDoc
*/
protected function setUp(): void
{
$this->_objectManager = new ObjectManager($this);
$this->_escaper = $this->createMock(Escaper::class);
$context = $this->createMock(Context::class);
$context->expects($this->any())->method('getEscaper')->willReturn($this->_escaper);
$addressHelper = $this->createMock(Address::class);
$this->_options = $this->createMock(Options::class);
$this->attribute = $this->getMockBuilder(AttributeMetadataInterface::class)
->getMockForAbstractClass();
$this->customerMetadata = $this->getMockBuilder(CustomerMetadataInterface::class)
->getMockForAbstractClass();
$this->customerMetadata->expects($this->any())
->method('getAttributeMetadata')
->willReturn($this->attribute);
$this->customerMetadata
->expects($this->any())
->method('getCustomAttributesMetadata')
->willReturn([]);
$this->addressMetadata = $this->getMockBuilder(AddressMetadataInterface::class)
->getMockForAbstractClass();
$this->addressMetadata->expects($this->any())
->method('getAttributeMetadata')
->willReturn($this->attribute);
$this->_block = new Name(
$context,
$addressHelper,
$this->customerMetadata,
$this->_options,
$this->addressMetadata
);
}
/**
* @return void
* @see self::_setUpShowAttribute()
*/
public function testShowPrefix(): void
{
$this->_setUpShowAttribute([Customer::PREFIX => self::PREFIX]);
$this->assertTrue($this->_block->showPrefix());
$this->isVisibleAttribute = false;
$this->assertFalse($this->_block->showPrefix());
$this->isVisibleAttribute = true;
}
/**
* @return void
*/
public function testShowPrefixWithException(): void
{
$this->customerMetadata->expects(
$this->any()
)->method(
'getAttributeMetadata'
)->willThrowException(
new NoSuchEntityException(
__(
'No such entity with %fieldName = %fieldValue',
['fieldName' => 'field', 'fieldValue' => 'value']
)
)
);
$this->assertFalse($this->_block->showPrefix());
}
/**
* @param $method
*
* @return void
* @dataProvider methodDataProvider
*/
public function testMethodWithNoSuchEntityException($method): void
{
$this->customerMetadata->expects(
$this->any()
)->method(
'getAttributeMetadata'
)->willThrowException(
new NoSuchEntityException(
__(
'No such entity with %fieldName = %fieldValue',
['fieldName' => 'field', 'fieldValue' => 'value']
)
)
);
$this->assertFalse($this->_block->{$method}());
}
/**
* @return array
*/
public function methodDataProvider(): array
{
return [
'showPrefix' => ['showPrefix'],
'isPrefixRequired' => ['isPrefixRequired'],
'showMiddlename' => ['showMiddlename'],
'isMiddlenameRequired' => ['isMiddlenameRequired'],
'showSuffix' => ['showSuffix'],
'isSuffixRequired' => ['isSuffixRequired']
];
}
/**
* @return void
* @see self::_setUpIsAttributeRequired()
*/
public function testIsPrefixRequired(): void
{
$this->_setUpIsAttributeRequired();
$this->assertTrue($this->_block->isPrefixRequired());
}
/**
* @return void
*/
public function testShowMiddlename(): void
{
$this->_setUpShowAttribute([Customer::MIDDLENAME => self::MIDDLENAME]);
$this->assertTrue($this->_block->showMiddlename());
}
/**
* @return void
*/
public function testIsMiddlenameRequired(): void
{
$this->_setUpIsAttributeRequired();
$this->assertTrue($this->_block->isMiddlenameRequired());
}
/**
* @return void
*/
public function testShowSuffix(): void
{
$this->_setUpShowAttribute([Customer::SUFFIX => self::SUFFIX]);
$this->assertTrue($this->_block->showSuffix());
}
/**
* @return void
*/
public function testIsSuffixRequired(): void
{
$this->_setUpIsAttributeRequired();
$this->assertTrue($this->_block->isSuffixRequired());
}
/**
* @return void
*/
public function testGetPrefixOptionsNotEmpty(): void
{
/**
* Added some padding so that the trim() call on Customer::getPrefix() will remove it. Also added
* special characters so that the escapeHtml() method returns a htmlspecialchars translated value.
*/
$customer = $this->getMockBuilder(
CustomerInterface::class
)->getMockForAbstractClass();
$customer->expects($this->once())->method('getPrefix')->willReturn(' <' . self::PREFIX . '> ');
$this->_block->setObject($customer);
$prefixOptions = ['Mrs' => 'Mrs', 'Ms' => 'Ms', 'Miss' => 'Miss'];
$prefix = '<' . self::PREFIX . '>';
$expectedOptions = $prefixOptions;
$expectedOptions[$prefix] = $prefix;
$this->_options->expects(
$this->once()
)->method(
'getNamePrefixOptions'
)->willReturn(
$prefixOptions
);
$this->_escaper->expects($this->once())->method('escapeHtml')->willReturn($prefix);
$this->assertSame($expectedOptions, $this->_block->getPrefixOptions());
}
/**
* @return void
*/
public function testGetPrefixOptionsEmpty(): void
{
$customer = $this->getMockBuilder(
CustomerInterface::class
)->getMockForAbstractClass();
$this->_block->setObject($customer);
$this->_options->expects(
$this->once()
)->method(
'getNamePrefixOptions'
)->willReturn(
[]
);
$this->assertEmpty($this->_block->getPrefixOptions());
}
/**
* @return void
*/
public function testGetSuffixOptionsNotEmpty(): void
{
/**
* Added padding and special characters to show that trim() works on Customer::getSuffix() and that
* a properly htmlspecialchars translated value is returned.
*/
$customer = $this->getMockBuilder(
CustomerInterface::class
)->getMockForAbstractClass();
$customer->expects($this->once())->method('getSuffix')->willReturn(' <' . self::SUFFIX . '> ');
$this->_block->setObject($customer);
$suffixOptions = ['Sr' => 'Sr'];
$suffix = '<' . self::SUFFIX . '>';
$expectedOptions = $suffixOptions;
$expectedOptions[$suffix] = $suffix;
$this->_options->expects(
$this->once()
)->method(
'getNameSuffixOptions'
)->willReturn(
$suffixOptions
);
$this->_escaper->expects($this->once())->method('escapeHtml')->willReturn($suffix);
$this->assertSame($expectedOptions, $this->_block->getSuffixOptions());
}
/**
* @return void
*/
public function testGetSuffixOptionsEmpty(): void
{
$customer = $this->getMockBuilder(
CustomerInterface::class
)->getMockForAbstractClass();
$this->_block->setObject($customer);
$this->_options->expects(
$this->once()
)->method(
'getNameSuffixOptions'
)->willReturn(
[]
);
$this->assertEmpty($this->_block->getSuffixOptions());
}
/**
* @return void
*/
public function testGetClassName(): void
{
/** Test the default case when the block has no data set for the class name. */
$this->assertEquals(self::DEFAULT_CLASS_NAME, $this->_block->getClassName());
/** Set custom data for the class name and verify that the Name::getClassName() method returns it. */
$this->_block->setData(self::KEY_CLASS_NAME, self::CUSTOM_CLASS_NAME);
$this->assertEquals(self::CUSTOM_CLASS_NAME, $this->_block->getClassName());
}
/**
* @param bool $isPrefixVisible Value returned by Name::showPrefix()
* @param bool $isMiddlenameVisible Value returned by Name::showMiddlename()
* @param bool $isSuffixVisible Value returned by Name::showSuffix()
* @param string $expectedValue The expected value of Name::getContainerClassName()
*
* @return void
* @dataProvider getContainerClassNameProvider
*/
public function testGetContainerClassName(
$isPrefixVisible,
$isMiddlenameVisible,
$isSuffixVisible,
$expectedValue
): void {
$this->attribute
->method('isVisible')
->willReturnOnConsecutiveCalls($isPrefixVisible, $isMiddlenameVisible, $isSuffixVisible);
$this->assertEquals($expectedValue, $this->_block->getContainerClassName());
}
/**
* This data provider provides enough data sets to test both ternary operator code paths for each one
* that's used in Name::getContainerClassName().
*
* @return array
*/
public function getContainerClassNameProvider(): array
{
return [
[false, false, false, self::DEFAULT_CLASS_NAME],
[true, false, false, self::DEFAULT_CLASS_NAME . self::CONTAINER_CLASS_NAME_PREFIX],
[false, true, false, self::DEFAULT_CLASS_NAME . self::CONTAINER_CLASS_NAME_MIDDLENAME],
[false, false, true, self::DEFAULT_CLASS_NAME . self::CONTAINER_CLASS_NAME_SUFFIX],
[
true,
true,
true,
self::DEFAULT_CLASS_NAME .
self::CONTAINER_CLASS_NAME_PREFIX .
self::CONTAINER_CLASS_NAME_MIDDLENAME .
self::CONTAINER_CLASS_NAME_SUFFIX
]
];
}
/**
* @param string $attributeCode An attribute code
* @param string $storeLabel The attribute's store label
* @param string $expectedValue The expected value of Name::getStoreLabel()
*
* @return void
* @dataProvider getStoreLabelProvider
*/
public function testGetStoreLabel($attributeCode, $storeLabel, $expectedValue): void
{
$this->attribute->expects($this->atLeastOnce())->method('getStoreLabel')->willReturn($storeLabel);
$this->assertEquals($expectedValue, $this->_block->getStoreLabel($attributeCode));
}
/**
* This data provider provides two data sets. One tests that an empty string is returned for an invalid
* attribute code instead of an exception being thrown. The second tests that the correct store label is
* returned for a valid attribute code.
*
* @return array
*/
public function getStoreLabelProvider(): array
{
return [
[self::INVALID_ATTRIBUTE_CODE, '', ''],
[self::PREFIX_ATTRIBUTE_CODE, self::PREFIX_STORE_LABEL, self::PREFIX_STORE_LABEL]
];
}
/**
* @return void
*/
public function testGetStoreLabelWithException(): void
{
$this->customerMetadata->expects(
$this->any()
)->method(
'getAttributeMetadata'
)->willThrowException(
new NoSuchEntityException(
__(
'No such entity with %fieldName = %fieldValue',
['fieldName' => 'field', 'fieldValue' => 'value']
)
)
);
$this->assertSame('', (string)$this->_block->getStoreLabel('attributeCode'));
}
/**
* Helper method for testing all show*() methods.
*
* @param array $data Customer attribute(s)
*
* @return void
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
private function _setUpShowAttribute(array $data): void
{
$customer = $this->getMockBuilder(CustomerInterface::class)
->getMockForAbstractClass();
/**
* These settings cause the first code path in Name::_getAttribute() to be executed, which
* basically just returns the value of parent::_getAttribute().
*/
$this->_block->setForceUseCustomerAttributes(true);
$this->_block->setObject($customer);
/**
* The show*() methods return true for the attribute returned by parent::_getAttribute() for the
* first call to the method. Subsequent calls may return true or false depending on the returnValue
* of the at({0, 1, 2, 3, ...}), etc. calls as set and configured in a particular test.
*/
$testClass = $this;
$this->attribute
->method('isVisible')
->willReturnCallback(function () use ($testClass) {
return $testClass->isVisibleAttribute;
});
}
/**
* Helper method for testing all is*Required() methods.
*
* @return void
*/
private function _setUpIsAttributeRequired(): void
{
/**
* These settings cause the first code path in Name::_getAttribute() to be skipped so that the rest of
* the code in the other code path(s) can be executed.
*/
$this->_block->setForceUseCustomerAttributes(false);
$this->_block->setForceUseCustomerRequiredAttributes(true);
$this->_block->setObject(new \StdClass());
/**
* The first call to isRequired() is false so that the second if conditional in the other code path
* of Name::_getAttribute() will evaluate to true, which causes the if's code block to be executed.
* The second isRequired() call causes the code in the nested if conditional to be executed. Thus,
* all code paths in Name::_getAttribute() will be executed. Returning true for the third isRequired()
* call causes the is*Required() method of the block to return true for the attribute.
*/
$this->attribute
->method('isRequired')
->willReturnOnConsecutiveCalls(false, true, true);
}
}