diff --git a/app/code/Magento/Authorizenet/Model/Authorizenet.php b/app/code/Magento/Authorizenet/Model/Authorizenet.php index b35e4f4c39911df89d553ef98ad77eba768ccf3c..4ad08d89cc495556bd4b5b794417fb7185817d92 100644 --- a/app/code/Magento/Authorizenet/Model/Authorizenet.php +++ b/app/code/Magento/Authorizenet/Model/Authorizenet.php @@ -6,6 +6,7 @@ namespace Magento\Authorizenet\Model; use Magento\Authorizenet\Model\TransactionService; +use Magento\Framework\HTTP\ZendClientFactory; /** * @SuppressWarnings(PHPMD.TooManyFields) @@ -97,6 +98,11 @@ abstract class Authorizenet extends \Magento\Payment\Model\Method\Cc */ protected $_debugReplacePrivateDataKeys = ['merchantAuthentication', 'x_login']; + /** + * @var \Magento\Framework\HTTP\ZendClientFactory + */ + protected $httpClientFactory; + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -111,6 +117,7 @@ abstract class Authorizenet extends \Magento\Payment\Model\Method\Cc * @param \Magento\Authorizenet\Model\Request\Factory $requestFactory * @param \Magento\Authorizenet\Model\Response\Factory $responseFactory * @param \Magento\Authorizenet\Model\TransactionService $transactionService + * @param \Magento\Framework\HTTP\ZendClientFactory $httpClientFactory * @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data @@ -130,6 +137,7 @@ abstract class Authorizenet extends \Magento\Payment\Model\Method\Cc \Magento\Authorizenet\Model\Request\Factory $requestFactory, \Magento\Authorizenet\Model\Response\Factory $responseFactory, TransactionService $transactionService, + ZendClientFactory $httpClientFactory, \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] @@ -138,6 +146,7 @@ abstract class Authorizenet extends \Magento\Payment\Model\Method\Cc $this->requestFactory = $requestFactory; $this->responseFactory = $responseFactory; $this->transactionService = $transactionService; + $this->httpClientFactory = $httpClientFactory; parent::__construct( $context, @@ -370,7 +379,8 @@ abstract class Authorizenet extends \Magento\Payment\Model\Method\Cc protected function postRequest(\Magento\Authorizenet\Model\Request $request) { $result = $this->responseFactory->create(); - $client = new \Magento\Framework\HTTP\ZendClient(); + /** @var \Magento\Framework\HTTP\ZendClient $client */ + $client = $this->httpClientFactory->create(); $url = $this->getConfigData('cgi_url') ?: self::CGI_URL; $debugData = ['url' => $url, 'request' => $request->getData()]; $client->setUri($url); diff --git a/app/code/Magento/Authorizenet/Model/Directpost.php b/app/code/Magento/Authorizenet/Model/Directpost.php index bbfcd0f7d6e128fb7d0e5d0740223ef42282c469..68fd630f21f4593740fed6288e3821b87677d7db 100644 --- a/app/code/Magento/Authorizenet/Model/Directpost.php +++ b/app/code/Magento/Authorizenet/Model/Directpost.php @@ -6,6 +6,7 @@ namespace Magento\Authorizenet\Model; use Magento\Authorizenet\Model\TransactionService; +use Magento\Framework\HTTP\ZendClientFactory; use Magento\Payment\Model\Method\ConfigInterface; use Magento\Payment\Model\Method\TransparentInterface; use Magento\Sales\Model\Order\Email\Sender\OrderSender; @@ -132,6 +133,7 @@ class Directpost extends \Magento\Authorizenet\Model\Authorizenet implements Tra * @param Directpost\Request\Factory $requestFactory * @param Directpost\Response\Factory $responseFactory * @param \Magento\Authorizenet\Model\TransactionService $transactionService + * @param \Magento\Framework\HTTP\ZendClientFactory $httpClientFactory * @param \Magento\Sales\Model\OrderFactory $orderFactory * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Quote\Model\QuoteRepository $quoteRepository @@ -156,6 +158,7 @@ class Directpost extends \Magento\Authorizenet\Model\Authorizenet implements Tra \Magento\Authorizenet\Model\Directpost\Request\Factory $requestFactory, \Magento\Authorizenet\Model\Directpost\Response\Factory $responseFactory, TransactionService $transactionService, + ZendClientFactory $httpClientFactory, \Magento\Sales\Model\OrderFactory $orderFactory, \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Quote\Model\QuoteRepository $quoteRepository, @@ -187,6 +190,7 @@ class Directpost extends \Magento\Authorizenet\Model\Authorizenet implements Tra $requestFactory, $responseFactory, $transactionService, + $httpClientFactory, $resource, $resourceCollection, $data @@ -404,9 +408,7 @@ class Directpost extends \Magento\Authorizenet\Model\Authorizenet implements Tra if ($result->getXTransId() != $payment->getParentTransactionId()) { $payment->setTransactionId($result->getXTransId()); } - $shouldCloseCaptureTransaction = $payment->getOrder()->canCreditmemo() ? 0 : 1; - $payment->setIsTransactionClosed(1) - ->setShouldCloseParentTransaction($shouldCloseCaptureTransaction) + $payment->setIsTransactionClosed(true) ->setTransactionAdditionalInfo(self::REAL_TRANSACTION_ID_KEY, $result->getXTransId()); return $this; } diff --git a/app/code/Magento/Authorizenet/Test/Unit/Model/DirectpostTest.php b/app/code/Magento/Authorizenet/Test/Unit/Model/DirectpostTest.php index 3247ed2cb9329f86e0efda4e07aeae938515f05b..3726d4e5108ae84b6076a8e39b4e8b628620a7f9 100644 --- a/app/code/Magento/Authorizenet/Test/Unit/Model/DirectpostTest.php +++ b/app/code/Magento/Authorizenet/Test/Unit/Model/DirectpostTest.php @@ -9,13 +9,21 @@ use Magento\Framework\Simplexml\Element; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; use Magento\Authorizenet\Model\Directpost; use Magento\Authorizenet\Model\TransactionService; +use Magento\Authorizenet\Model\Request; +use Magento\Authorizenet\Model\Directpost\Request\Factory; +use Magento\Sales\Model\Order; use Magento\Sales\Model\Order\Payment\Transaction\Repository as TransactionRepository; /** * Class DirectpostTest + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class DirectpostTest extends \PHPUnit_Framework_TestCase { + const TOTAL_AMOUNT = 100.02; + const INVOICE_NUM = '00000001'; + const TRANSACTION_ID = '41a23x34fd124'; + /** * @var \Magento\Authorizenet\Model\Directpost */ @@ -56,6 +64,16 @@ class DirectpostTest extends \PHPUnit_Framework_TestCase */ protected $transactionServiceMock; + /** + * @var \Magento\Framework\HTTP\ZendClient|\PHPUnit_Framework_MockObject_MockObject + */ + protected $httpClientMock; + + /** + * @var \Magento\Authorizenet\Model\Directpost\Request\Factory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $requestFactory; + protected function setUp() { $this->scopeConfigMock = $this->getMockBuilder('Magento\Framework\App\Config\ScopeConfigInterface') @@ -64,7 +82,8 @@ class DirectpostTest extends \PHPUnit_Framework_TestCase ->disableOriginalConstructor() ->setMethods([ 'getOrder', 'getId', 'setAdditionalInformation', 'getAdditionalInformation', - 'setIsTransactionDenied', 'setIsTransactionClosed' + 'setIsTransactionDenied', 'setIsTransactionClosed', 'decrypt', 'getCcLast4', + 'getParentTransactionId', 'getPoNumber' ]) ->getMock(); $this->dataHelperMock = $this->getMockBuilder('Magento\Authorizenet\Helper\Data') @@ -85,15 +104,20 @@ class DirectpostTest extends \PHPUnit_Framework_TestCase ->setMethods(['getTransactionDetails']) ->getMock(); + $this->requestFactory = $this->getRequestFactoryMock(); + $httpClientFactoryMock = $this->getHttpClientFactoryMock(); + $helper = new ObjectManagerHelper($this); $this->directpost = $helper->getObject( 'Magento\Authorizenet\Model\Directpost', [ 'scopeConfig' => $this->scopeConfigMock, 'dataHelper' => $this->dataHelperMock, + 'requestFactory' => $this->requestFactory, 'responseFactory' => $this->responseFactoryMock, 'transactionRepository' => $this->transactionRepositoryMock, - 'transactionService' => $this->transactionServiceMock + 'transactionService' => $this->transactionServiceMock, + 'httpClientFactory' => $httpClientFactoryMock ] ); } @@ -376,7 +400,7 @@ class DirectpostTest extends \PHPUnit_Framework_TestCase } /** - * @covers \Magento\Authorizenet\Model\Directpost::fetchTransactionInfo + * @covers \Magento\Authorizenet\Model\Directpost::fetchTransactionInfo * * @param $transactionId * @param $resultStatus @@ -440,6 +464,72 @@ class DirectpostTest extends \PHPUnit_Framework_TestCase $this->directpost->fetchTransactionInfo($this->paymentMock, $transactionId); } + /** + * @covers \Magento\Authorizenet\Model\Directpost::refund() + * @return void + */ + public function testSuccessRefund() + { + $card = 1111; + + $this->paymentMock->expects(static::exactly(2)) + ->method('getCcLast4') + ->willReturn($card); + $this->paymentMock->expects(static::once()) + ->method('decrypt') + ->willReturn($card); + $this->paymentMock->expects(static::exactly(3)) + ->method('getParentTransactionId') + ->willReturn(self::TRANSACTION_ID . '-capture'); + $this->paymentMock->expects(static::once()) + ->method('getPoNumber') + ->willReturn(self::INVOICE_NUM); + $this->paymentMock->expects(static::once()) + ->method('setIsTransactionClosed') + ->with(true) + ->willReturnSelf(); + + $orderMock = $this->getOrderMock(); + + $this->paymentMock->expects(static::exactly(2)) + ->method('getOrder') + ->willReturn($orderMock); + + $transactionMock = $this->getMockBuilder(Order\Payment\Transaction::class) + ->disableOriginalConstructor() + ->setMethods(['getAdditionalInformation']) + ->getMock(); + $transactionMock->expects(static::once()) + ->method('getAdditionalInformation') + ->with(Directpost::REAL_TRANSACTION_ID_KEY) + ->willReturn(self::TRANSACTION_ID); + + $this->transactionRepositoryMock->expects(static::once()) + ->method('getByTransactionId') + ->willReturn($transactionMock); + + $response = $this->getRefundResponseBody( + Directpost::RESPONSE_CODE_APPROVED, + Directpost::RESPONSE_REASON_CODE_APPROVED, + 'Successful' + ); + $this->httpClientMock->expects(static::once()) + ->method('getBody') + ->willReturn($response); + + $this->responseMock->expects(static::once()) + ->method('getXResponseCode') + ->willReturn(Directpost::RESPONSE_CODE_APPROVED); + $this->responseMock->expects(static::once()) + ->method('getXResponseReasonCode') + ->willReturn(Directpost::RESPONSE_REASON_CODE_APPROVED); + + $this->dataHelperMock->expects(static::never()) + ->method('wrapGatewayError'); + + $this->directpost->refund($this->paymentMock, self::TOTAL_AMOUNT); + } + /** * Get data for tests * @return array @@ -468,14 +558,48 @@ class DirectpostTest extends \PHPUnit_Framework_TestCase $this->responseMock = $this->getMockBuilder('Magento\Authorizenet\Model\Directpost\Response') ->setMethods( [ - 'setData', 'isValidHash', 'getXTransId', - 'getXResponseCode', 'getXResponseReasonText', - 'getXAmount' + 'isValidHash', + 'getXTransId', 'getXResponseCode', 'getXResponseReasonCode', 'getXResponseReasonText', 'getXAmount', + 'setXResponseCode', 'setXResponseReasonCode', 'setXAvsCode', 'setXResponseReasonText', + 'setXTransId', 'setXInvoiceNum', 'setXAmount', 'setXMethod', 'setXType', 'setData', + 'setXAccountNumber', + '__wakeup' ] ) ->disableOriginalConstructor() ->getMock(); + $this->responseMock->expects(static::any()) + ->method('setXResponseCode') + ->willReturnSelf(); + $this->responseMock->expects(static::any()) + ->method('setXResponseReasonCode') + ->willReturnSelf(); + $this->responseMock->expects(static::any()) + ->method('setXResponseReasonText') + ->willReturnSelf(); + $this->responseMock->expects(static::any()) + ->method('setXAvsCode') + ->willReturnSelf(); + $this->responseMock->expects(static::any()) + ->method('setXTransId') + ->willReturnSelf(); + $this->responseMock->expects(static::any()) + ->method('setXInvoiceNum') + ->willReturnSelf(); + $this->responseMock->expects(static::any()) + ->method('setXAmount') + ->willReturnSelf(); + $this->responseMock->expects(static::any()) + ->method('setXMethod') + ->willReturnSelf(); + $this->responseMock->expects(static::any()) + ->method('setXType') + ->willReturnSelf(); + $this->responseMock->expects(static::any()) + ->method('setData') + ->willReturnSelf(); + $this->responseFactoryMock->expects($this->any()) ->method('create') ->willReturn($this->responseMock); @@ -530,4 +654,105 @@ class DirectpostTest extends \PHPUnit_Framework_TestCase libxml_use_internal_errors(false); return $document; } + + /** + * Get mock for authorize.net request factory + * @return \PHPUnit_Framework_MockObject_MockBuilder + */ + private function getRequestFactoryMock() + { + $requestFactory = $this->getMockBuilder(Factory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $request = $this->getMockBuilder(Request::class) + ->disableOriginalConstructor() + ->setMethods(['__wakeup']) + ->getMock(); + $requestFactory->expects(static::any()) + ->method('create') + ->willReturn($request); + return $requestFactory; + } + + /** + * Get mock for order + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function getOrderMock() + { + $orderMock = $this->getMockBuilder(Order::class) + ->disableOriginalConstructor() + ->setMethods([ + 'getId', 'getIncrementId', 'getStoreId', 'getBillingAddress', 'getShippingAddress', + 'getBaseCurrencyCode', 'getBaseTaxAmount', '__wakeup' + ]) + ->getMock(); + + $orderMock->expects(static::once()) + ->method('getId') + ->willReturn(1); + + $orderMock->expects(static::exactly(2)) + ->method('getIncrementId') + ->willReturn(self::INVOICE_NUM); + + $orderMock->expects(static::once()) + ->method('getStoreId') + ->willReturn(1); + + $orderMock->expects(static::once()) + ->method('getBaseCurrencyCode') + ->willReturn('USD'); + return $orderMock; + } + + /** + * Create and return mock for http client factory + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function getHttpClientFactoryMock() + { + $this->httpClientMock = $this->getMockBuilder(\Magento\Framework\HTTP\ZendClient::class) + ->disableOriginalConstructor() + ->setMethods(['request', 'getBody', '__wakeup']) + ->getMock(); + + $this->httpClientMock->expects(static::any()) + ->method('request') + ->willReturnSelf(); + + $httpClientFactoryMock = $this->getMockBuilder(\Magento\Framework\HTTP\ZendClientFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + + $httpClientFactoryMock->expects(static::any()) + ->method('create') + ->willReturn($this->httpClientMock); + return $httpClientFactoryMock; + } + + /** + * Get mocked response for refund transaction + * @param $code + * @param $reasonCode + * @param $reasonText + * @return string + */ + private function getRefundResponseBody($code, $reasonCode, $reasonText) + { + $result = array_fill(0, 50, ''); + $result[0] = $code; // XResponseCode + $result[2] = $reasonCode; // XResponseReasonCode + $result[3] = $reasonText; // XResponseReasonText + $result[6] = self::TRANSACTION_ID; // XTransId + $result[7] = self::INVOICE_NUM; // XInvoiceNum + $result[9] = self::TOTAL_AMOUNT; // XAmount + $result[10] = Directpost::REQUEST_METHOD_CC; // XMethod + $result[11] = Directpost::REQUEST_TYPE_CREDIT; // XType + $result[37] = md5(self::TRANSACTION_ID); // x_MD5_Hash + $result[50] = '48329483921'; // setXAccountNumber + return implode(Directpost::RESPONSE_DELIM_CHAR, $result); + } } diff --git a/app/code/Magento/Authorizenet/view/adminhtml/templates/directpost/info.phtml b/app/code/Magento/Authorizenet/view/adminhtml/templates/directpost/info.phtml index 6c02076b5a7dbe55d9a81b7114599221c6c9f14e..9251ad16e7258cfb7938591fe66c9a1a2d353f50 100644 --- a/app/code/Magento/Authorizenet/view/adminhtml/templates/directpost/info.phtml +++ b/app/code/Magento/Authorizenet/view/adminhtml/templates/directpost/info.phtml @@ -9,7 +9,7 @@ * @var \Magento\Authorizenet\Block\Transparent\Iframe $block * @see \Magento\Authorizenet\Block\Transparent\Iframe */ -$code = $block->getMethodCode(); +$code = $block->escapeHtml($block->getMethodCode()); $method = $block->getMethod(); $controller = $block->escapeHtml($block->getRequest()->getControllerName()); $orderUrl = $block->escapeUrl($this->helper('Magento\Authorizenet\Helper\Backend\Data')->getPlaceOrderAdminUrl()); @@ -20,12 +20,12 @@ $ccExpYear = $block->getInfoData('cc_exp_year'); <!-- IFRAME for request to our server --> <iframe id="order-directpost-iframe" allowtransparency="true" frameborder="0" name="iframeSubmitOrder" style="display:none;width:100%;background-color:transparent" - src="<?php /* @noEscape */ echo $block->getViewFileUrl('blank.html'); ?>"> + src="<?php echo $block->escapeUrl($block->getViewFileUrl('blank.html')); ?>"> </iframe> <!-- IFRAME for request to Authorize.net --> <iframe id="directpost-iframe" allowtransparency="true" frameborder="0" name="iframeDirectPost" style="display:none;width:100%;background-color:transparent" - src="<?php /* @noEscape */ echo $block->getViewFileUrl('blank.html'); ?>"> + src="<?php echo $block->escapeUrl($block->getViewFileUrl('blank.html')); ?>"> </iframe> <fieldset class="admin__fieldset payment-method" id="payment_form_<?php /* @noEscape */ echo $code; ?>" style="display:none;"> @@ -124,9 +124,9 @@ $ccExpYear = $block->getInfoData('cc_exp_year'); '<?php /* @noEscape */ echo $controller; ?>', '<?php /* @noEscape */ echo $orderUrl; ?>', '<?php echo $block->escapeUrl($method->getCgiUrl()); ?>', - '<?php /* @noEscape */ echo $block->getUrl('*/*/save', [ + '<?php echo $block->escapeUrl($block->getUrl('*/*/save', [ '_secure' => $block->getRequest()->isSecure() - ]);?>'); + ]));?>'); <?php if (!$block->isAjaxRequest()): ?> }); diff --git a/app/code/Magento/Backend/Block/Widget/Button/Item.php b/app/code/Magento/Backend/Block/Widget/Button/Item.php index a500f836312fb3edacd942cc80e24e0582d2094e..73ed2c5f50e6993e5ebbff026d0b89194abcc52b 100644 --- a/app/code/Magento/Backend/Block/Widget/Button/Item.php +++ b/app/code/Magento/Backend/Block/Widget/Button/Item.php @@ -7,12 +7,12 @@ namespace Magento\Backend\Block\Widget\Button; /** - * @method string getButtonKey - * @method string getRegion - * @method string getName - * @method int getLevel - * @method int getSortOrder - * @method string getTitle + * @method string getButtonKey() + * @method string getRegion() + * @method string getName() + * @method int getLevel() + * @method int getSortOrder() + * @method string getTitle() */ class Item extends \Magento\Framework\DataObject { diff --git a/app/code/Magento/Backend/Block/Widget/Button/Toolbar/Container.php b/app/code/Magento/Backend/Block/Widget/Button/Toolbar/Container.php index e7c199cf4787ff9aedca6aa13061fddfafe5d20c..959ef806acfa15571046dbaf9e8b6b3055ef6d0b 100644 --- a/app/code/Magento/Backend/Block/Widget/Button/Toolbar/Container.php +++ b/app/code/Magento/Backend/Block/Widget/Button/Toolbar/Container.php @@ -9,8 +9,8 @@ namespace Magento\Backend\Block\Widget\Button\Toolbar; use Magento\Backend\Block\Widget\Button\ContextInterface; /** - * @method \Magento\Backend\Block\Widget\Button\Item getButtonItem - * @method ContextInterface getContext + * @method \Magento\Backend\Block\Widget\Button\Item getButtonItem() + * @method ContextInterface getContext() * @method ContextInterface setContext(ContextInterface $context) */ class Container extends \Magento\Framework\View\Element\AbstractBlock diff --git a/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Checkbox.php b/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Checkbox.php index 3329f8aaf93c6b5d9a813f06de710f75634eb939..ec10318fd59913fcf938c896d4033c601668360b 100644 --- a/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Checkbox.php +++ b/app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Checkbox.php @@ -116,15 +116,18 @@ class Checkbox extends \Magento\Backend\Block\Widget\Grid\Column\Renderer\Abstra */ protected function _getCheckboxHtml($value, $checked) { - $html = '<input type="checkbox" '; + $html = '<label class="data-grid-checkbox-cell-inner" '; + $html .= ' for="id_' . $this->escapeHtml($value) . '">'; + $html .= '<input type="checkbox" '; $html .= 'name="' . $this->getColumn()->getFieldName() . '" '; $html .= 'value="' . $this->escapeHtml($value) . '" '; + $html .= 'id="id_' . $this->escapeHtml($value) . '" '; $html .= 'class="' . ($this->getColumn()->getInlineCss() ? $this->getColumn()->getInlineCss() : 'checkbox') . - ' admin__control-checkbox' . - '"'; + ' admin__control-checkbox' . '"'; $html .= $checked . $this->getDisabled() . '/>'; - $html .= '<label></label>'; + $html .= '<label for="id_' . $this->escapeHtml($value) . '"></label>'; + $html .= '</label>'; /* ToDo UI: add class="admin__field-label" after some refactoring _fields.less */ return $html; } diff --git a/app/code/Magento/Backend/Console/Command/AbstractCacheTypeManageCommand.php b/app/code/Magento/Backend/Console/Command/AbstractCacheTypeManageCommand.php index 5974798f74be4355cff4926d0bd4e65b48f583f9..56970004795e1b93758432657da8bf4db3e06af8 100644 --- a/app/code/Magento/Backend/Console/Command/AbstractCacheTypeManageCommand.php +++ b/app/code/Magento/Backend/Console/Command/AbstractCacheTypeManageCommand.php @@ -6,11 +6,28 @@ namespace Magento\Backend\Console\Command; +use Magento\Framework\Event\ManagerInterface as EventManagerInterface; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Magento\Framework\App\Cache\Manager; abstract class AbstractCacheTypeManageCommand extends AbstractCacheManageCommand { + /** @var EventManagerInterface */ + protected $eventManager; + + /** + * @param Manager $cacheManager + * @param EventManagerInterface $eventManager + */ + public function __construct( + Manager $cacheManager, + EventManagerInterface $eventManager + ) { + $this->eventManager = $eventManager; + parent::__construct($cacheManager); + } + /** * Perform a cache management action on cache types * diff --git a/app/code/Magento/Backend/Console/Command/CacheCleanCommand.php b/app/code/Magento/Backend/Console/Command/CacheCleanCommand.php index ab57f0ff7b578611ee3a64402650aa07ba52219e..49aeb17839e2ae54fd39c86865c8b2e4e36b2941 100644 --- a/app/code/Magento/Backend/Console/Command/CacheCleanCommand.php +++ b/app/code/Magento/Backend/Console/Command/CacheCleanCommand.php @@ -29,6 +29,7 @@ class CacheCleanCommand extends AbstractCacheTypeManageCommand */ protected function performAction(array $cacheTypes) { + $this->eventManager->dispatch('adminhtml_cache_flush_system'); $this->cacheManager->clean($cacheTypes); } diff --git a/app/code/Magento/Backend/Console/Command/CacheFlushCommand.php b/app/code/Magento/Backend/Console/Command/CacheFlushCommand.php index c847204de9043e84ded25607e890273441ec0e4e..7572fb21cba6dc3e8fb6a7d785ed3d7bbf32e97d 100644 --- a/app/code/Magento/Backend/Console/Command/CacheFlushCommand.php +++ b/app/code/Magento/Backend/Console/Command/CacheFlushCommand.php @@ -29,6 +29,7 @@ class CacheFlushCommand extends AbstractCacheTypeManageCommand */ protected function performAction(array $cacheTypes) { + $this->eventManager->dispatch('adminhtml_cache_flush_all'); $this->cacheManager->flush($cacheTypes); } diff --git a/app/code/Magento/Backend/Test/Unit/Console/Command/AbstractCacheCommandTest.php b/app/code/Magento/Backend/Test/Unit/Console/Command/AbstractCacheCommandTest.php index 33bce6388fb71d5a8765c86e2c078916858b1741..b7ecddf4d23610b94cee2519c597a907cb4effe5 100644 --- a/app/code/Magento/Backend/Test/Unit/Console/Command/AbstractCacheCommandTest.php +++ b/app/code/Magento/Backend/Test/Unit/Console/Command/AbstractCacheCommandTest.php @@ -13,7 +13,7 @@ abstract class AbstractCacheCommandTest extends \PHPUnit_Framework_TestCase /** * @var \Magento\Framework\App\Cache\Manager|\PHPUnit_Framework_MockObject_MockObject */ - protected $cacheManager; + protected $cacheManagerMock; /** * @var AbstractCacheManageCommand @@ -22,7 +22,7 @@ abstract class AbstractCacheCommandTest extends \PHPUnit_Framework_TestCase public function setUp() { - $this->cacheManager = $this->getMock('Magento\Framework\App\Cache\Manager', [], [], '', false); + $this->cacheManagerMock = $this->getMock('Magento\Framework\App\Cache\Manager', [], [], '', false); } /** diff --git a/app/code/Magento/Backend/Test/Unit/Console/Command/AbstractCacheManageCommandTest.php b/app/code/Magento/Backend/Test/Unit/Console/Command/AbstractCacheManageCommandTest.php index 53ed624db47685ea3b72ed92b8b466dbeca363bb..97d1f57ad1c1f67eb2af82640bc3e81f679c9199 100644 --- a/app/code/Magento/Backend/Test/Unit/Console/Command/AbstractCacheManageCommandTest.php +++ b/app/code/Magento/Backend/Test/Unit/Console/Command/AbstractCacheManageCommandTest.php @@ -10,6 +10,20 @@ use Symfony\Component\Console\Tester\CommandTester; abstract class AbstractCacheManageCommandTest extends AbstractCacheCommandTest { + /** @var string */ + protected $cacheEventName; + + /** @var \Magento\Framework\Event\ManagerInterface | \PHPUnit_Framework_MockObject_MockObject */ + protected $eventManagerMock; + + public function setUp() + { + $this->eventManagerMock = $this->getMockBuilder('\Magento\Framework\Event\ManagerInterface') + ->disableOriginalConstructor() + ->getMock(); + parent::setUp(); + } + /** * @return array */ @@ -35,7 +49,7 @@ abstract class AbstractCacheManageCommandTest extends AbstractCacheCommandTest */ public function testExecuteInvalidCacheType() { - $this->cacheManager->expects($this->once())->method('getAvailableTypes')->willReturn(['A', 'B', 'C']); + $this->cacheManagerMock->expects($this->once())->method('getAvailableTypes')->willReturn(['A', 'B', 'C']); $param = ['types' => ['A', 'D']]; $commandTester = new CommandTester($this->command); $commandTester->execute($param); diff --git a/app/code/Magento/Backend/Test/Unit/Console/Command/CacheCleanCommandTest.php b/app/code/Magento/Backend/Test/Unit/Console/Command/CacheCleanCommandTest.php index a51fa92c1addf7dfca4f654a6d5e72079cc9d3ca..fe812c1a93daa190f555e189f9fc95aa26471b05 100644 --- a/app/code/Magento/Backend/Test/Unit/Console/Command/CacheCleanCommandTest.php +++ b/app/code/Magento/Backend/Test/Unit/Console/Command/CacheCleanCommandTest.php @@ -13,8 +13,9 @@ class CacheCleanCommandTest extends AbstractCacheManageCommandTest { public function setUp() { + $this->cacheEventName = 'adminhtml_cache_flush_system'; parent::setUp(); - $this->command = new CacheCleanCommand($this->cacheManager); + $this->command = new CacheCleanCommand($this->cacheManagerMock, $this->eventManagerMock); } /** @@ -25,8 +26,9 @@ class CacheCleanCommandTest extends AbstractCacheManageCommandTest */ public function testExecute($param, $types, $output) { - $this->cacheManager->expects($this->once())->method('getAvailableTypes')->willReturn(['A', 'B', 'C']); - $this->cacheManager->expects($this->once())->method('clean')->with($types); + $this->cacheManagerMock->expects($this->once())->method('getAvailableTypes')->willReturn(['A', 'B', 'C']); + $this->cacheManagerMock->expects($this->once())->method('clean')->with($types); + $this->eventManagerMock->expects($this->once())->method('dispatch')->with($this->cacheEventName); $commandTester = new CommandTester($this->command); $commandTester->execute($param); diff --git a/app/code/Magento/Backend/Test/Unit/Console/Command/CacheDisableCommandTest.php b/app/code/Magento/Backend/Test/Unit/Console/Command/CacheDisableCommandTest.php index 1eb4cffd23fd64cda13e2cc49c7ac4dd557dc374..4446b1b992e03b44bb3602adbab2c16cda301106 100644 --- a/app/code/Magento/Backend/Test/Unit/Console/Command/CacheDisableCommandTest.php +++ b/app/code/Magento/Backend/Test/Unit/Console/Command/CacheDisableCommandTest.php @@ -14,7 +14,7 @@ class CacheDisableCommandTest extends AbstractCacheSetCommandTest public function setUp() { parent::setUp(); - $this->command = new CacheDisableCommand($this->cacheManager); + $this->command = new CacheDisableCommand($this->cacheManagerMock); } /** @@ -26,8 +26,13 @@ class CacheDisableCommandTest extends AbstractCacheSetCommandTest */ public function testExecute($param, $enable, $result, $output) { - $this->cacheManager->expects($this->once())->method('getAvailableTypes')->willReturn(['A', 'B', 'C']); - $this->cacheManager->expects($this->once())->method('setEnabled')->with($enable, false)->willReturn($result); + $this->cacheManagerMock->expects($this->once()) + ->method('getAvailableTypes') + ->willReturn(['A', 'B', 'C']); + $this->cacheManagerMock->expects($this->once()) + ->method('setEnabled') + ->with($enable, false) + ->willReturn($result); $commandTester = new CommandTester($this->command); $commandTester->execute($param); diff --git a/app/code/Magento/Backend/Test/Unit/Console/Command/CacheEnableCommandTest.php b/app/code/Magento/Backend/Test/Unit/Console/Command/CacheEnableCommandTest.php index e20978e81e7d759e23e18f1fc1bdd5277cebed8a..e44b71d06f9fdc9a624959b50a32521c2db479eb 100644 --- a/app/code/Magento/Backend/Test/Unit/Console/Command/CacheEnableCommandTest.php +++ b/app/code/Magento/Backend/Test/Unit/Console/Command/CacheEnableCommandTest.php @@ -14,7 +14,7 @@ class CacheEnableCommandTest extends AbstractCacheSetCommandTest public function setUp() { parent::setUp(); - $this->command = new CacheEnableCommand($this->cacheManager); + $this->command = new CacheEnableCommand($this->cacheManagerMock); } /** @@ -26,9 +26,15 @@ class CacheEnableCommandTest extends AbstractCacheSetCommandTest */ public function testExecute($param, $enable, $result, $output) { - $this->cacheManager->expects($this->once())->method('getAvailableTypes')->willReturn(['A', 'B', 'C']); - $this->cacheManager->expects($this->once())->method('setEnabled')->with($enable, true)->willReturn($result); - $this->cacheManager->expects($result === [] ? $this->never() : $this->once())->method('clean')->with($enable); + $this->cacheManagerMock->expects($this->once())->method('getAvailableTypes')->willReturn(['A', 'B', 'C']); + $this->cacheManagerMock->expects($this->once()) + ->method('setEnabled') + ->with($enable, true) + ->willReturn($result); + $cleanInvocationCount = $result === [] ? 0 : 1; + $this->cacheManagerMock->expects($this->exactly($cleanInvocationCount)) + ->method('clean') + ->with($enable); $commandTester = new CommandTester($this->command); $commandTester->execute($param); diff --git a/app/code/Magento/Backend/Test/Unit/Console/Command/CacheFlushCommandTest.php b/app/code/Magento/Backend/Test/Unit/Console/Command/CacheFlushCommandTest.php index 53032fe55ae049267f802b85b3e6127a02def5d7..07828c6627d5d440e9c10fcd28716ed7b280c067 100644 --- a/app/code/Magento/Backend/Test/Unit/Console/Command/CacheFlushCommandTest.php +++ b/app/code/Magento/Backend/Test/Unit/Console/Command/CacheFlushCommandTest.php @@ -13,8 +13,9 @@ class CacheFlushCommandTest extends AbstractCacheManageCommandTest { public function setUp() { + $this->cacheEventName = 'adminhtml_cache_flush_all'; parent::setUp(); - $this->command = new CacheFlushCommand($this->cacheManager); + $this->command = new CacheFlushCommand($this->cacheManagerMock, $this->eventManagerMock); } /** @@ -25,8 +26,9 @@ class CacheFlushCommandTest extends AbstractCacheManageCommandTest */ public function testExecute($param, $types, $output) { - $this->cacheManager->expects($this->once())->method('getAvailableTypes')->willReturn(['A', 'B', 'C']); - $this->cacheManager->expects($this->once())->method('flush')->with($types); + $this->cacheManagerMock->expects($this->once())->method('getAvailableTypes')->willReturn(['A', 'B', 'C']); + $this->cacheManagerMock->expects($this->once())->method('flush')->with($types); + $this->eventManagerMock->expects($this->once())->method('dispatch')->with($this->cacheEventName); $commandTester = new CommandTester($this->command); $commandTester->execute($param); diff --git a/app/code/Magento/Backend/Test/Unit/Console/Command/CacheStatusCommandTest.php b/app/code/Magento/Backend/Test/Unit/Console/Command/CacheStatusCommandTest.php index 4c792a4548dd1833d33334c6005ea4b2953f52e3..a8ee48491fbb7523f23cdc3d230092f86a967293 100644 --- a/app/code/Magento/Backend/Test/Unit/Console/Command/CacheStatusCommandTest.php +++ b/app/code/Magento/Backend/Test/Unit/Console/Command/CacheStatusCommandTest.php @@ -14,13 +14,13 @@ class CacheStatusCommandTest extends AbstractCacheCommandTest public function setUp() { parent::setUp(); - $this->command = new CacheStatusCommand($this->cacheManager); + $this->command = new CacheStatusCommand($this->cacheManagerMock); } public function testExecute() { $cacheTypes = ['A' => 0, 'B' => 1, 'C' => 1]; - $this->cacheManager->expects($this->once())->method('getStatus')->willReturn($cacheTypes); + $this->cacheManagerMock->expects($this->once())->method('getStatus')->willReturn($cacheTypes); $commandTester = new CommandTester($this->command); $commandTester->execute([]); diff --git a/app/code/Magento/Backend/i18n/de_DE.csv b/app/code/Magento/Backend/i18n/de_DE.csv index 8bd82b41c2050a73b6cefcad5a4a53a280627769..7c6b4dab5992d69ca9214ebabc18c6b9e4e6eca3 100644 --- a/app/code/Magento/Backend/i18n/de_DE.csv +++ b/app/code/Magento/Backend/i18n/de_DE.csv @@ -606,3 +606,11 @@ Tags,Tags Options,Options "Magento Admin","Magento Admin" "Community Edition","Community Edition" +Marketing,Marketing +Communications,Communications +"SEO & Search","SEO & Search" +"User Content","User Content" +"Data Transfer","Data Transfer" +"Import History","Import History" +Extensions,Extensions +"Web Setup Wizard","Web Setup Wizard" diff --git a/app/code/Magento/Backend/i18n/en_US.csv b/app/code/Magento/Backend/i18n/en_US.csv index 8bd82b41c2050a73b6cefcad5a4a53a280627769..7c6b4dab5992d69ca9214ebabc18c6b9e4e6eca3 100644 --- a/app/code/Magento/Backend/i18n/en_US.csv +++ b/app/code/Magento/Backend/i18n/en_US.csv @@ -606,3 +606,11 @@ Tags,Tags Options,Options "Magento Admin","Magento Admin" "Community Edition","Community Edition" +Marketing,Marketing +Communications,Communications +"SEO & Search","SEO & Search" +"User Content","User Content" +"Data Transfer","Data Transfer" +"Import History","Import History" +Extensions,Extensions +"Web Setup Wizard","Web Setup Wizard" diff --git a/app/code/Magento/Backend/i18n/es_ES.csv b/app/code/Magento/Backend/i18n/es_ES.csv index 8bd82b41c2050a73b6cefcad5a4a53a280627769..7c6b4dab5992d69ca9214ebabc18c6b9e4e6eca3 100644 --- a/app/code/Magento/Backend/i18n/es_ES.csv +++ b/app/code/Magento/Backend/i18n/es_ES.csv @@ -606,3 +606,11 @@ Tags,Tags Options,Options "Magento Admin","Magento Admin" "Community Edition","Community Edition" +Marketing,Marketing +Communications,Communications +"SEO & Search","SEO & Search" +"User Content","User Content" +"Data Transfer","Data Transfer" +"Import History","Import History" +Extensions,Extensions +"Web Setup Wizard","Web Setup Wizard" diff --git a/app/code/Magento/Backend/i18n/fr_FR.csv b/app/code/Magento/Backend/i18n/fr_FR.csv index 8bd82b41c2050a73b6cefcad5a4a53a280627769..7c6b4dab5992d69ca9214ebabc18c6b9e4e6eca3 100644 --- a/app/code/Magento/Backend/i18n/fr_FR.csv +++ b/app/code/Magento/Backend/i18n/fr_FR.csv @@ -606,3 +606,11 @@ Tags,Tags Options,Options "Magento Admin","Magento Admin" "Community Edition","Community Edition" +Marketing,Marketing +Communications,Communications +"SEO & Search","SEO & Search" +"User Content","User Content" +"Data Transfer","Data Transfer" +"Import History","Import History" +Extensions,Extensions +"Web Setup Wizard","Web Setup Wizard" diff --git a/app/code/Magento/Backend/i18n/nl_NL.csv b/app/code/Magento/Backend/i18n/nl_NL.csv index 8bd82b41c2050a73b6cefcad5a4a53a280627769..7c6b4dab5992d69ca9214ebabc18c6b9e4e6eca3 100644 --- a/app/code/Magento/Backend/i18n/nl_NL.csv +++ b/app/code/Magento/Backend/i18n/nl_NL.csv @@ -606,3 +606,11 @@ Tags,Tags Options,Options "Magento Admin","Magento Admin" "Community Edition","Community Edition" +Marketing,Marketing +Communications,Communications +"SEO & Search","SEO & Search" +"User Content","User Content" +"Data Transfer","Data Transfer" +"Import History","Import History" +Extensions,Extensions +"Web Setup Wizard","Web Setup Wizard" diff --git a/app/code/Magento/Backend/i18n/pt_BR.csv b/app/code/Magento/Backend/i18n/pt_BR.csv index 8bd82b41c2050a73b6cefcad5a4a53a280627769..7c6b4dab5992d69ca9214ebabc18c6b9e4e6eca3 100644 --- a/app/code/Magento/Backend/i18n/pt_BR.csv +++ b/app/code/Magento/Backend/i18n/pt_BR.csv @@ -606,3 +606,11 @@ Tags,Tags Options,Options "Magento Admin","Magento Admin" "Community Edition","Community Edition" +Marketing,Marketing +Communications,Communications +"SEO & Search","SEO & Search" +"User Content","User Content" +"Data Transfer","Data Transfer" +"Import History","Import History" +Extensions,Extensions +"Web Setup Wizard","Web Setup Wizard" diff --git a/app/code/Magento/Backend/i18n/zh_Hans_CN.csv b/app/code/Magento/Backend/i18n/zh_Hans_CN.csv index 8bd82b41c2050a73b6cefcad5a4a53a280627769..7c6b4dab5992d69ca9214ebabc18c6b9e4e6eca3 100644 --- a/app/code/Magento/Backend/i18n/zh_Hans_CN.csv +++ b/app/code/Magento/Backend/i18n/zh_Hans_CN.csv @@ -606,3 +606,11 @@ Tags,Tags Options,Options "Magento Admin","Magento Admin" "Community Edition","Community Edition" +Marketing,Marketing +Communications,Communications +"SEO & Search","SEO & Search" +"User Content","User Content" +"Data Transfer","Data Transfer" +"Import History","Import History" +Extensions,Extensions +"Web Setup Wizard","Web Setup Wizard" diff --git a/app/code/Magento/Braintree/Model/PaymentMethod.php b/app/code/Magento/Braintree/Model/PaymentMethod.php index 45171956e87bcf8832723f7b7dffeb90ea5f1f79..da5ff0d88e29aaf2bf417fa332cf57659672fe04 100644 --- a/app/code/Magento/Braintree/Model/PaymentMethod.php +++ b/app/code/Magento/Braintree/Model/PaymentMethod.php @@ -604,7 +604,7 @@ class PaymentMethod extends \Magento\Payment\Model\Method\Cc if ($result->success) { $payment->setIsTransactionClosed(false) ->setShouldCloseParentTransaction(false); - if ($this->isFinalCapture($payment->getParentId(), $amount)) { + if ($payment->isCaptureFinal($amount)) { $payment->setShouldCloseParentTransaction(true); } } else { @@ -657,7 +657,6 @@ class PaymentMethod extends \Magento\Payment\Model\Method\Cc : $this->braintreeTransaction->refund($transactionId, $amount); $this->_debug($this->_convertObjToArray($result)); if ($result->success) { - $payment->setTransactionId($transactionId . '-' . Transaction::TYPE_REFUND); $payment->setIsTransactionClosed(true); } else { throw new LocalizedException($this->errorHelper->parseBraintreeError($result)); @@ -905,7 +904,7 @@ class PaymentMethod extends \Magento\Payment\Model\Method\Cc ->setAdditionalInformation($this->getExtraTransactionInformation($result->transaction)) ->setAmount($amount) ->setShouldCloseParentTransaction(false); - if ($this->isFinalCapture($payment->getParentId(), $amount)) { + if ($payment->isCaptureFinal($amount)) { $payment->setShouldCloseParentTransaction(true); } if (isset($result->transaction->creditCard['token']) && $result->transaction->creditCard['token']) { @@ -964,21 +963,4 @@ class PaymentMethod extends \Magento\Payment\Model\Method\Cc { return json_decode(json_encode($data), true); } - - /** - * Checks whether the capture is final - * - * @param string $orderId - * @param string $amount - * @return bool - */ - protected function isFinalCapture($orderId, $amount) - { - if (!empty($orderId)) { - $order = $this->orderRepository->get($orderId); - return (float)$order->getTotalDue() === (float) $amount; - } - - return false; - } } diff --git a/app/code/Magento/Braintree/Test/Unit/Model/PaymentMethodTest.php b/app/code/Magento/Braintree/Test/Unit/Model/PaymentMethodTest.php index e20af765062e3b3b0713c5732d5b67f8f3c279f3..749c2cf390f36359a4364027e9612a76ed810f89 100644 --- a/app/code/Magento/Braintree/Test/Unit/Model/PaymentMethodTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Model/PaymentMethodTest.php @@ -32,6 +32,7 @@ class PaymentMethodTest extends \PHPUnit_Framework_TestCase const LNAME = 'Doe'; const AUTH_TRAN_ID = 'r4z34j'; const AUTH_AMOUNT = 5.76; + const TOTAL_AMOUNT = 10.02; const AUTH_CC_LAST_4 = '0004'; const CUSTOMER_ID = '221b3649effb4bb1b62fc940691bd18c'; @@ -325,11 +326,8 @@ class PaymentMethodTest extends \PHPUnit_Framework_TestCase * @param $ccType * @param null $ccToken */ - protected function setupInfoInstance( - $countryId, - $ccType, - $ccToken = null - ) { + protected function setupInfoInstance($countryId, $ccType, $ccToken = null) + { $quoteObj = new \Magento\Framework\DataObject( [ 'billing_address' => new \Magento\Framework\DataObject( @@ -501,6 +499,7 @@ class PaymentMethodTest extends \PHPUnit_Framework_TestCase 'getCustomerEmail', 'getCustomerId', 'getStoreId', + 'getTotalDue' ] )->getMock(); @@ -522,18 +521,25 @@ class PaymentMethodTest extends \PHPUnit_Framework_TestCase $orderMock->expects($this->any()) ->method('getStoreId') ->willReturn($storeId); + $orderMock->expects(static::any()) + ->method('getTotalDue') + ->willReturn(self::TOTAL_AMOUNT); + + $this->orderRepository->expects(static::any()) + ->method('get') + ->willReturn($orderMock); + return $orderMock; } + /** * @param \Magento\Framework\DataObject $paymentObject * @param int $storeId * @return array * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - protected function setupPaymentObject( - \Magento\Framework\DataObject $paymentObject, - $storeId - ) { + protected function setupPaymentObject(\Magento\Framework\DataObject $paymentObject, $storeId) + { $customerId = '12'; $customerEmail = 'abc@example.com'; $company = 'NA'; @@ -564,13 +570,9 @@ class PaymentMethodTest extends \PHPUnit_Framework_TestCase 'address_type' => 'billing', ]; - $billingAddress = new \Magento\Framework\DataObject( - $addressData - ); + $billingAddress = new \Magento\Framework\DataObject($addressData); $addressData['address_type'] = 'shipping'; - $shippingAddress = new \Magento\Framework\DataObject( - $addressData - ); + $shippingAddress = new \Magento\Framework\DataObject($addressData); $order = $this->setupOrderMock( $billingAddress, @@ -606,26 +608,26 @@ class PaymentMethodTest extends \PHPUnit_Framework_TestCase ->willReturn($regionMock); $braintreeAddressData = [ - 'firstName' => self::FNAME, - 'lastName' => self::LNAME, - 'company' => $company, - 'streetAddress' => $street, - 'extendedAddress' => $street2, - 'locality' => $city, - 'region' => $regionCode, - 'postalCode' => $postcode, + 'firstName' => self::FNAME, + 'lastName' => self::LNAME, + 'company' => $company, + 'streetAddress' => $street, + 'extendedAddress' => $street2, + 'locality' => $city, + 'region' => $regionCode, + 'postalCode' => $postcode, 'countryCodeAlpha2' => $countryId, ]; return [ - 'channel' => self::CHANNEL, - 'orderId' => $orderId, - 'customer' => [ + 'channel' => self::CHANNEL, + 'orderId' => $orderId, + 'customer' => [ 'firstName' => self::FNAME, - 'lastName' => self::LNAME, - 'company' => $company, - 'phone' => $phone, - 'fax' => $fax, - 'email' => $customerEmail, + 'lastName' => self::LNAME, + 'company' => $company, + 'phone' => $phone, + 'fax' => $fax, + 'email' => $customerEmail, ], 'billing' => $braintreeAddressData, 'shipping' => $braintreeAddressData, @@ -765,8 +767,11 @@ class PaymentMethodTest extends \PHPUnit_Framework_TestCase ) { $storeId = 3; $amount = self::AUTH_AMOUNT; - $paymentObject = $this->objectManagerHelper->getObject('Magento\Sales\Model\Order\Payment'); - + $currencyMock = $this->getPriceCurrencyMock(); + /** @var \Magento\Sales\Model\Order\Payment $paymentObject */ + $paymentObject = $this->objectManagerHelper->getObject('Magento\Sales\Model\Order\Payment', [ + 'priceCurrency' => $currencyMock + ]); $expectedRequestAttribs = $this->setupAuthorizeRequest( $configData, @@ -798,14 +803,6 @@ class PaymentMethodTest extends \PHPUnit_Framework_TestCase } $paymentObject->setParentId('1'); - $order = $this->getMockBuilder('Magento\Sales\Api\Data\OrderInterface') - ->getMockForAbstractClass(); - $order->expects($this->once()) - ->method('getTotalDue') - ->willReturn(10.02); - $this->orderRepository->expects($this->once()) - ->method('get') - ->willReturn($order); $this->assertEquals($this->model, $this->model->authorize($paymentObject, $amount)); foreach ($expectedPaymentFields as $key => $value) { @@ -1598,13 +1595,8 @@ class PaymentMethodTest extends \PHPUnit_Framework_TestCase * @expectedException \Magento\Framework\Exception\LocalizedException * @expectedExceptionMessage error */ - public function testAuthorizeError( - array $configData, - $vault, - $registry, - $existingCustomer, - array $paymentInfo - ) { + public function testAuthorizeError(array $configData, $vault, $registry, $existingCustomer, array $paymentInfo) + { $storeId = 3; $amount = self::AUTH_AMOUNT; $paymentObject = $this->objectManagerHelper->getObject('Magento\Sales\Model\Order\Payment'); @@ -1649,13 +1641,8 @@ class PaymentMethodTest extends \PHPUnit_Framework_TestCase * @expectedException \Magento\Framework\Exception\LocalizedException * @expectedExceptionMessage Please try again later */ - public function testAuthorizeException( - array $configData, - $vault, - $registry, - $existingCustomer, - array $paymentInfo - ) { + public function testAuthorizeException(array $configData, $vault, $registry, $existingCustomer, array $paymentInfo) + { $storeId = 3; $amount = self::AUTH_AMOUNT; $paymentObject = $this->objectManagerHelper->getObject('Magento\Sales\Model\Order\Payment'); @@ -1716,10 +1703,8 @@ class PaymentMethodTest extends \PHPUnit_Framework_TestCase * @param int $numberOfTransactions * @return $this */ - protected function setupSalesTransaction( - $paymentId, - $numberOfTransactions - ) { + protected function setupSalesTransaction($paymentId, $numberOfTransactions) + { $transactionCollectionMock = $this->getMockBuilder( 'Magento\Sales\Model\ResourceModel\Order\Payment\Transaction\Collection' )->disableOriginalConstructor() @@ -1741,12 +1726,24 @@ class PaymentMethodTest extends \PHPUnit_Framework_TestCase return $this; } - protected function setupPaymentObjectForCapture( - $paymentId - ) { + protected function setupPaymentObjectForCapture($paymentId) + { + $order = $this->getMockBuilder('Magento\Sales\Api\Data\OrderInterface') + ->getMockForAbstractClass(); + $order->expects(static::any()) + ->method('getTotalDue') + ->willReturn(self::TOTAL_AMOUNT); + $this->orderRepository->expects(static::any()) + ->method('get') + ->willReturn($order); + + $currencyMock = $this->getPriceCurrencyMock(); + $paymentObject = $this->objectManagerHelper->getObject( 'Magento\Sales\Model\Order\Payment', [ + 'priceCurrency' => $currencyMock, + 'orderRepository' => $this->orderRepository, 'data' => [ 'id' => $paymentId, 'cc_trans_id' => self::AUTH_TRAN_ID, @@ -1756,6 +1753,11 @@ class PaymentMethodTest extends \PHPUnit_Framework_TestCase return $paymentObject; } + + /** + * @covers \Magento\Braintree\Model\PaymentMethod::capture() + * @throws LocalizedException + */ public function testCaptureSuccess() { $amount = self::AUTH_AMOUNT; @@ -1774,20 +1776,40 @@ class PaymentMethodTest extends \PHPUnit_Framework_TestCase ->method('critical'); $paymentObject->setParentId('1'); - $order = $this->getMockBuilder('Magento\Sales\Api\Data\OrderInterface') - ->getMockForAbstractClass(); - $order->expects($this->once()) - ->method('getTotalDue') - ->willReturn(10.02); - $this->orderRepository->expects($this->once()) - ->method('get') - ->willReturn($order); $this->model->capture($paymentObject, $amount); $this->assertEquals(0, $paymentObject->getIsTransactionClosed()); $this->assertFalse($paymentObject->getShouldCloseParentTransaction()); } + /** + * @covers \Magento\Braintree\Model\PaymentMethod::capture() + * @return void + */ + public function testCaptureSuccessAuthTransactionClosed() + { + $paymentId = 31232; + /** @var \Magento\Sales\Model\Order\Payment $payment */ + $payment = $this->setupPaymentObjectForCapture($paymentId); + $this->setupSalesTransaction($paymentId, 0); //no existing capture transaction + + $result = $this->setupSuccessResponse([]); + $this->braintreeTransactionMock->expects(static::once()) + ->method('submitForSettlement') + ->with(self::AUTH_TRAN_ID, self::TOTAL_AMOUNT) + ->willReturn($result); + + $this->psrLoggerMock->expects(static::never()) + ->method('critical'); + + $payment->setParentId(1); + $this->model->capture($payment, self::TOTAL_AMOUNT); + + static::assertFalse($payment->getIsTransactionClosed()); + static::assertTrue($payment->getShouldCloseParentTransaction()); + + } + /** * @expectedException \Magento\Framework\Exception\LocalizedException * @expectedExceptionMessage There was an error capturing the transaction: error. @@ -1820,10 +1842,8 @@ class PaymentMethodTest extends \PHPUnit_Framework_TestCase $this->model->capture($paymentObject, $amount); } - protected function setupAuthTransaction( - $paymentId, - $authTransaction - ) { + protected function setupAuthTransaction($paymentId, $authTransaction) + { $authTransactionCollectionMock = $this->getMockBuilder( 'Magento\Sales\Model\ResourceModel\Order\Payment\Transaction\Collection' )->disableOriginalConstructor() @@ -1926,14 +1946,6 @@ class PaymentMethodTest extends \PHPUnit_Framework_TestCase ->willReturn($result); $paymentObject->setParentId('1'); - $order = $this->getMockBuilder('Magento\Sales\Api\Data\OrderInterface') - ->getMockForAbstractClass(); - $order->expects($this->once()) - ->method('getTotalDue') - ->willReturn(10.02); - $this->orderRepository->expects($this->once()) - ->method('get') - ->willReturn($order); $this->model->capture($paymentObject, $amount); $this->assertEquals(0, $paymentObject->getIsTransactionClosed()); @@ -2115,17 +2127,10 @@ class PaymentMethodTest extends \PHPUnit_Framework_TestCase 'submitForSettlement' => true, ], ] - )->willReturn($resultSuccess); + ) + ->willReturn($resultSuccess); $paymentObject->setParentId('1'); - $order = $this->getMockBuilder('Magento\Sales\Api\Data\OrderInterface') - ->getMockForAbstractClass(); - $order->expects($this->once()) - ->method('getTotalDue') - ->willReturn(10.02); - $this->orderRepository->expects($this->once()) - ->method('get') - ->willReturn($order); $this->model->capture($paymentObject, $amount); $this->assertEquals(PaymentMethod::STATUS_APPROVED, $paymentObject->getStatus()); @@ -2192,9 +2197,8 @@ class PaymentMethodTest extends \PHPUnit_Framework_TestCase //End: test capture //Start: test refund - protected function setupPaymentObjectForRefund( - $refundTransactionId - ) { + protected function setupPaymentObjectForRefund($refundTransactionId) + { $paymentObject = $this->objectManagerHelper->getObject( 'Magento\Sales\Model\Order\Payment', [ @@ -2379,7 +2383,6 @@ class PaymentMethodTest extends \PHPUnit_Framework_TestCase $this->model->refund($paymentObject, $amount); $this->assertEquals(1, $paymentObject->getIsTransactionClosed()); - $this->assertEquals($refundTransactionId . '-' .Transaction::TYPE_REFUND, $paymentObject->getTransactionId()); } /** @@ -2461,9 +2464,8 @@ class PaymentMethodTest extends \PHPUnit_Framework_TestCase ->willReturnArgument(0); } - protected function setupPaymentObjectForVoid( - $orderId - ) { + protected function setupPaymentObjectForVoid($orderId) + { $paymentObject = $this->objectManagerHelper->getObject( 'Magento\Sales\Model\Order\Payment' ); @@ -2666,4 +2668,22 @@ class PaymentMethodTest extends \PHPUnit_Framework_TestCase ->willReturn($orderMock); $this->assertEquals(false, $this->model->canVoid()); } + + /** + * @return \Magento\Directory\Model\PriceCurrency|\PHPUnit_Framework_MockObject_MockObject + */ + protected function getPriceCurrencyMock() + { + $currencyMock = $this->getMockBuilder('\Magento\Directory\Model\PriceCurrency') + ->disableOriginalConstructor() + ->setMethods(['round']) + ->getMock(); + $currencyMock->expects(static::any()) + ->method('round') + ->willReturnMap([ + [self::TOTAL_AMOUNT, round(self::TOTAL_AMOUNT, 2)], + [self::AUTH_AMOUNT, round(self::AUTH_AMOUNT, 2)] + ]); + return $currencyMock; + } } diff --git a/app/code/Magento/Braintree/view/adminhtml/templates/form.phtml b/app/code/Magento/Braintree/view/adminhtml/templates/form.phtml index 5610e082e1715e36dcecc8f7cc241bf1aeee2798..508313a25527a942d6c55cea7fd64873528e91a6 100644 --- a/app/code/Magento/Braintree/view/adminhtml/templates/form.phtml +++ b/app/code/Magento/Braintree/view/adminhtml/templates/form.phtml @@ -7,7 +7,7 @@ // @codingStandardsIgnoreFile /** @var \Magento\Braintree\Block\Form $block */ -$code = $block->getMethodCode(); +$code = $block->escapeHtml($block->getMethodCode()); $storedCards = $this->helper('\Magento\Braintree\Helper\Createorder')->getLoggedInCustomerCards(); $useVault = $block->useVault(); $useCvv = $block->useCvv(); diff --git a/app/code/Magento/Braintree/view/frontend/layout/braintree_paypal_review.xml b/app/code/Magento/Braintree/view/frontend/layout/braintree_paypal_review.xml index 1c7b14abfa13d308f65ec8ff17aa6042c42a1497..126f80a2e25e82ba2d4c82638fb13d035844481d 100644 --- a/app/code/Magento/Braintree/view/frontend/layout/braintree_paypal_review.xml +++ b/app/code/Magento/Braintree/view/frontend/layout/braintree_paypal_review.xml @@ -24,7 +24,7 @@ <block class="Magento\Framework\View\Element\Text\ListText" name="paypal.additional.actions"/> <block class="Magento\Paypal\Block\Express\Review\Details" name="paypal.express.review.details" as="details" template="express/review/details.phtml"> <block class="Magento\Framework\View\Element\RendererList" name="checkout.onepage.review.item.renderers" as="renderer.list"/> - <block class="Magento\Checkout\Block\Cart\Totals" name="paypal.express.review.details.totals" as="totals" template="onepage/review/totals.phtml"/> + <block class="Magento\Checkout\Block\Cart\Totals" name="paypal.express.review.details.totals" as="totals" template="checkout/onepage/review/totals.phtml"/> </block> <block class="Magento\CheckoutAgreements\Block\Agreements" name="paypal.express.review.details.agreements" as="agreements" template="Magento_CheckoutAgreements::additional_agreements.phtml"/> </block> diff --git a/app/code/Magento/Braintree/view/frontend/templates/PayPal/shortcut.phtml b/app/code/Magento/Braintree/view/frontend/templates/PayPal/shortcut.phtml index 267a6fede0644551bf2e45c5027bf2aebc9effe4..6edb66bd04c8f1c5858104007035a9b83c14fad9 100644 --- a/app/code/Magento/Braintree/view/frontend/templates/PayPal/shortcut.phtml +++ b/app/code/Magento/Braintree/view/frontend/templates/PayPal/shortcut.phtml @@ -42,7 +42,7 @@ $config = [ class="paypal checkout <?php echo $block->escapeHtml($block->getShowOrPosition()) ?> paypal-logo" > <fieldset class="fieldset paypal items"> - <div id="<?php /* @noEscape */ echo $containerId ?>" + <div id="<?php echo $block->escapeHtml($containerId); ?>" data-mage-init='<?php /* @noEscape */ echo json_encode($config); ?>'></div> </fieldset> </div> diff --git a/app/code/Magento/Braintree/view/frontend/templates/creditcard/edit.phtml b/app/code/Magento/Braintree/view/frontend/templates/creditcard/edit.phtml index 6fcac2eae9c411929472c7b79ef1038836646183..7c49fa2eecbd8f9859e66af635d3369ad6bb8a21 100644 --- a/app/code/Magento/Braintree/view/frontend/templates/creditcard/edit.phtml +++ b/app/code/Magento/Braintree/view/frontend/templates/creditcard/edit.phtml @@ -9,8 +9,8 @@ /** @var $block \Magento\Braintree\Block\Creditcard\Management */ echo $block->getLayout()->getMessagesBlock()->getGroupedHtml(); -$defaultExpMonth = $block->getTodayMonth(); -$defaultExpYear = $block->getTodayYear(); +$defaultExpMonth = ''; +$defaultExpYear = ''; $countrySpecificCardTypeConfig = $block->getCountrySpecificCardTypeConfig(); $applicableCardTypeConfig = $block->getCcApplicableTypes(); if ($block->isEditMode()) { @@ -164,7 +164,7 @@ $serializedFormData = $this->helper('Magento\Framework\Json\Helper\Data')->jsonE class="year required-entry" data-validate="{required:true}"> <?php foreach ($block->getCcYears() as $k => $v): ?> - <option value="<?php /* @noEscape */ echo $k ? $k : ''; ?>" + <option value="<?php /* @noEscape */ echo $k ? $block->escapeHtml($k) : ''; ?>" <?php if ($k == $defaultExpYear): ?> selected="selected"<?php endif; ?>> <?php echo $block->escapeHtml($v); ?> </option> @@ -328,7 +328,7 @@ $serializedFormData = $this->helper('Magento\Framework\Json\Helper\Data')->jsonE </label> <div class="control"> - <?php echo $block->escapeHtml($block->countrySelect('credit_card[billing_address][country_code_alpha2]', 'billing_address_country', $default)); ?> + <?php /* @noEscape */ echo $block->countrySelect('credit_card[billing_address][country_code_alpha2]', 'billing_address_country', $default); ?> </div> </div> </fieldset> diff --git a/app/code/Magento/Braintree/view/frontend/templates/form.phtml b/app/code/Magento/Braintree/view/frontend/templates/form.phtml index 459a61568cff7fa67f19d3146b1a2f7e0fb5ff5d..41029526cc388a58d93dc9c8ef119d99a1ccafd4 100644 --- a/app/code/Magento/Braintree/view/frontend/templates/form.phtml +++ b/app/code/Magento/Braintree/view/frontend/templates/form.phtml @@ -7,7 +7,7 @@ // @codingStandardsIgnoreFile /** @var \Magento\Braintree\Block\Form $block */ -$code = $block->getMethodCode(); +$code = $block->escapeHtml($block->getMethodCode()); $loggedIn = $block->isCustomerLoggedIn(); $storedCards = $block->getStoredCards(); $useVault = $loggedIn && $block->useVault() && count($storedCards); diff --git a/app/code/Magento/Bundle/Block/Adminhtml/Order/Create/Sidebar.php b/app/code/Magento/Bundle/Block/Adminhtml/Order/Create/Sidebar.php new file mode 100644 index 0000000000000000000000000000000000000000..12a3d48d20c4bf596652cdd1635bfe27584cef67 --- /dev/null +++ b/app/code/Magento/Bundle/Block/Adminhtml/Order/Create/Sidebar.php @@ -0,0 +1,51 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Bundle\Block\Adminhtml\Order\Create; + +class Sidebar +{ + /** + * Get item qty + * + * @param \Magento\Sales\Block\Adminhtml\Order\Create\Sidebar\AbstractSidebar $subject + * @param callable $proceed + * @param \Magento\Framework\DataObject $item + * + * @return string + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function aroundGetItemQty( + \Magento\Sales\Block\Adminhtml\Order\Create\Sidebar\AbstractSidebar $subject, + \Closure $proceed, + \Magento\Framework\DataObject $item + ) { + if ($item->getProduct()->getTypeId() == \Magento\Bundle\Model\Product\Type::TYPE_CODE) { + return ''; + } + return $proceed($item); + } + + /** + * Check whether product configuration is required before adding to order + * + * @param \Magento\Sales\Block\Adminhtml\Order\Create\Sidebar\AbstractSidebar $subject + * @param callable $proceed + * @param string $productType + * + * @return bool + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function aroundIsConfigurationRequired( + \Magento\Sales\Block\Adminhtml\Order\Create\Sidebar\AbstractSidebar $subject, + \Closure $proceed, + $productType + ) { + if ($productType == \Magento\Bundle\Model\Product\Type::TYPE_CODE) { + return true; + } + return $proceed($productType); + } +} diff --git a/app/code/Magento/Bundle/Model/Product/Price.php b/app/code/Magento/Bundle/Model/Product/Price.php index d7dd23bc8931e46a74cc4eb728eaa4858522fa0d..73902761e14a527539f29719f6ba7dc30cdc726c 100644 --- a/app/code/Magento/Bundle/Model/Product/Price.php +++ b/app/code/Magento/Bundle/Model/Product/Price.php @@ -118,9 +118,8 @@ class Price extends \Magento\Catalog\Model\Product\Type\Price { $price = 0.0; if ($product->hasCustomOptions()) { - $customOption = $product->getCustomOption('bundle_selection_ids'); - if ($customOption) { - $selectionIds = unserialize($customOption->getValue()); + $selectionIds = $this->getBundleSelectionIds($product); + if ($selectionIds) { $selections = $product->getTypeInstance()->getSelectionsByIds($selectionIds, $product); $selections->addTierPriceData(); $this->_eventManager->dispatch( @@ -145,6 +144,24 @@ class Price extends \Magento\Catalog\Model\Product\Type\Price return $price; } + /** + * Retrieve array of bundle selection IDs + * + * @param \Magento\Catalog\Model\Product $product + * @return array + */ + protected function getBundleSelectionIds(\Magento\Catalog\Model\Product $product) + { + $customOption = $product->getCustomOption('bundle_selection_ids'); + if ($customOption) { + $selectionIds = unserialize($customOption->getValue()); + if (!empty($selectionIds) && is_array($selectionIds)) { + return $selectionIds; + } + } + return []; + } + /** * Get product final price * diff --git a/app/code/Magento/Bundle/Model/Product/Type.php b/app/code/Magento/Bundle/Model/Product/Type.php index 65742f76f261fc8d391bc992d7d56db848307148..2270f6cb149eb9dc14c15bc097824673cad24bc8 100644 --- a/app/code/Magento/Bundle/Model/Product/Type.php +++ b/app/code/Magento/Bundle/Model/Product/Type.php @@ -19,6 +19,11 @@ use Magento\Framework\Pricing\PriceCurrencyInterface; */ class Type extends \Magento\Catalog\Model\Product\Type\AbstractType { + /** + * Product type + */ + const TYPE_CODE = 'bundle'; + /** * Product is composite * diff --git a/app/code/Magento/Bundle/Test/Unit/Model/Product/PriceTest.php b/app/code/Magento/Bundle/Test/Unit/Model/Product/PriceTest.php index 226418b97aed883cabefb2c24e889633c15a5cf0..887d772ea403248fba1ae574e3f5864d0a00fe6b 100644 --- a/app/code/Magento/Bundle/Test/Unit/Model/Product/PriceTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Model/Product/PriceTest.php @@ -146,4 +146,121 @@ class PriceTest extends \PHPUnit_Framework_TestCase [10, 100, 1, true, 10], ]; } + + public function testGetTotalBundleItemsPriceWithNoCustomOptions() + { + $productMock = $this->getMockBuilder('Magento\Catalog\Model\Product') + ->disableOriginalConstructor() + ->getMock(); + + $productMock->expects($this->once()) + ->method('hasCustomOptions') + ->willReturn(false); + + $this->assertEquals(0, $this->model->getTotalBundleItemsPrice($productMock)); + } + + /** + * @param string|null $value + * @dataProvider dataProviderWithEmptyOptions + */ + public function testGetTotalBundleItemsPriceWithEmptyOptions($value) + { + $dataObjectMock = $this->getMockBuilder('Magento\Framework\DataObject') + ->setMethods(['getValue']) + ->disableOriginalConstructor() + ->getMock(); + + $productMock = $this->getMockBuilder('Magento\Catalog\Model\Product') + ->disableOriginalConstructor() + ->getMock(); + + $productMock->expects($this->once()) + ->method('hasCustomOptions') + ->willReturn(true); + $productMock->expects($this->once()) + ->method('getCustomOption') + ->with('bundle_selection_ids') + ->willReturn($dataObjectMock); + + $dataObjectMock->expects($this->once()) + ->method('getValue') + ->willReturn($value); + + $this->assertEquals(0, $this->model->getTotalBundleItemsPrice($productMock)); + } + + /** + * @return array + */ + public function dataProviderWithEmptyOptions() + { + return [ + ['a:0:{}'], + [''], + [null], + ]; + } + + public function testGetTotalBundleItemsPriceWithNoItems() + { + $storeId = 1; + + $dataObjectMock = $this->getMockBuilder('Magento\Framework\DataObject') + ->setMethods(['getValue']) + ->disableOriginalConstructor() + ->getMock(); + + $productMock = $this->getMockBuilder('Magento\Catalog\Model\Product') + ->disableOriginalConstructor() + ->getMock(); + + $productTypeMock = $this->getMockBuilder('Magento\Bundle\Model\Product\Type') + ->disableOriginalConstructor() + ->getMock(); + + $selectionsMock = $this->getMockBuilder('Magento\Bundle\Model\ResourceModel\Selection\Collection') + ->disableOriginalConstructor() + ->getMock(); + + $productMock->expects($this->once()) + ->method('hasCustomOptions') + ->willReturn(true); + $productMock->expects($this->once()) + ->method('getCustomOption') + ->with('bundle_selection_ids') + ->willReturn($dataObjectMock); + $productMock->expects($this->once()) + ->method('getTypeInstance') + ->willReturn($productTypeMock); + $productMock->expects($this->once()) + ->method('getStoreId') + ->willReturn($storeId); + + $dataObjectMock->expects($this->once()) + ->method('getValue') + ->willReturn('a:1:{i:0;s:1:"1";}'); + + $productTypeMock->expects($this->once()) + ->method('getSelectionsByIds') + ->with([1], $productMock) + ->willReturn($selectionsMock); + + $selectionsMock->expects($this->once()) + ->method('addTierPriceData') + ->willReturnSelf(); + $selectionsMock->expects($this->once()) + ->method('getItems') + ->willReturn([]); + + $this->eventManagerMock->expects($this->once()) + ->method('dispatch') + ->with( + 'prepare_catalog_product_collection_prices', + ['collection' => $selectionsMock, 'store_id' => $storeId] + ) + ->willReturnSelf(); + + $this->assertEquals(0, $this->model->getTotalBundleItemsPrice($productMock)); + } } diff --git a/app/code/Magento/Bundle/etc/adminhtml/di.xml b/app/code/Magento/Bundle/etc/adminhtml/di.xml index 0270ff9164b5980aa8c6b8b62c32bcea0e21a628..91970a4cdd9f3a145faff60f4d877bcba563ceda 100644 --- a/app/code/Magento/Bundle/etc/adminhtml/di.xml +++ b/app/code/Magento/Bundle/etc/adminhtml/di.xml @@ -9,6 +9,9 @@ <type name="Magento\Catalog\Controller\Adminhtml\Product\Initialization\Helper"> <plugin name="Bundle" type="Magento\Bundle\Controller\Adminhtml\Product\Initialization\Helper\Plugin\Bundle" sortOrder="60" /> </type> + <type name="Magento\Sales\Block\Adminhtml\Order\Create\Sidebar\AbstractSidebar"> + <plugin name="Bundle" type="Magento\Bundle\Block\Adminhtml\Order\Create\Sidebar" sortOrder="200"/> + </type> <type name="Magento\Catalog\Model\Product\CopyConstructor\Composite"> <arguments> <argument name="constructors" xsi:type="array"> diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit.php index 96d204f7400e01651de1a2b2e75af3cec9c569a4..29f7d7227a290bac1a230be877481c0d9f3d4094 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit.php @@ -54,9 +54,9 @@ class Edit extends \Magento\Backend\Block\Widget\Form\Container $this->addButton( 'save_in_new_set', [ - 'label' => __('Save in New Product Template'), + 'label' => __('Save in New Attribute Set'), 'class' => 'save', - 'onclick' => 'saveAttributeInNewSet(\'' . __('Enter Name for New Product Template') . '\')' + 'onclick' => 'saveAttributeInNewSet(\'' . __('Enter Name for New Attribute Set') . '\')' ], 100 ); diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Advanced.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Advanced.php index dec89ab52ff89d9275791fde97f7f2d4024de97d..5ed9016a59f6a799258ad17cee50c43c614ead97 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Advanced.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Advanced.php @@ -31,12 +31,18 @@ class Advanced extends Generic */ protected $_yesNo; + /** + * @var array + */ + protected $disableScopeChangeList; + /** * @param \Magento\Backend\Block\Template\Context $context * @param \Magento\Framework\Registry $registry * @param \Magento\Framework\Data\FormFactory $formFactory * @param Yesno $yesNo * @param Data $eavData + * @param array $disableScopeChangeList * @param array $data */ public function __construct( @@ -45,10 +51,12 @@ class Advanced extends Generic \Magento\Framework\Data\FormFactory $formFactory, Yesno $yesNo, Data $eavData, + array $disableScopeChangeList = ['sku'], array $data = [] ) { $this->_yesNo = $yesNo; $this->_eavData = $eavData; + $this->disableScopeChangeList = $disableScopeChangeList; parent::__construct($context, $registry, $formFactory, $data); } @@ -229,7 +237,7 @@ class Advanced extends Generic ); $this->_eventManager->dispatch('product_attribute_form_build', ['form' => $form]); - if ($attributeObject->getId() && !$attributeObject->getIsUserDefined()) { + if (in_array($attributeObject->getAttributeCode(), $this->disableScopeChangeList)) { $form->getElement('is_global')->setDisabled(1); } $this->setForm($form); diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Options.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Options.php index eabcac9f715747f01c211f9d5fc7d6fcee0bf718..b08fdb85de106f3cb0197da629036350c5f90571 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Options.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Options.php @@ -8,7 +8,7 @@ * Product attribute add/edit form options tab * * @method \Magento\Catalog\Block\Adminhtml\Product\Attribute\Edit\Tab\Options setReadOnly(bool $value) - * @method null|bool getReadOnly + * @method null|bool getReadOnly() * * @author Magento Core Team <core@magentocommerce.com> */ diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Set/Main.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Set/Main.php index 34025f7fc5bcfbe5df6880ae4738c98acc19bd25..9215bdb305f892d29bfa6613dd9732f27d8b95dc 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Set/Main.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Set/Main.php @@ -129,7 +129,7 @@ class Main extends \Magento\Backend\Block\Template 'label' => __('Delete'), 'onclick' => 'deleteConfirm(\'' . $this->escapeJsQuote( __( - 'You are about to delete all products in this product template. ' + 'You are about to delete all products in this attribute set. ' . 'Are you sure you want to do that?' ) ) . '\', \'' . $this->getUrl( @@ -187,7 +187,7 @@ class Main extends \Magento\Backend\Block\Template */ protected function _getHeader() { - return __("Edit Product Template '%1'", $this->_getAttributeSet()->getAttributeSetName()); + return __("Edit Attribute Set '%1'", $this->_getAttributeSet()->getAttributeSetName()); } /** diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Set/Main/Formset.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Set/Main/Formset.php index ab4bcab4dbf1d7602d34cc7a9c42a542c94ab0e6..ecfdb19e430251c3d84185273801787e569b7a42 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Set/Main/Formset.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Set/Main/Formset.php @@ -43,7 +43,7 @@ class Formset extends \Magento\Backend\Block\Widget\Form\Generic /** @var \Magento\Framework\Data\Form $form */ $form = $this->_formFactory->create(); - $fieldset = $form->addFieldset('set_name', ['legend' => __('Edit Product Template Name')]); + $fieldset = $form->addFieldset('set_name', ['legend' => __('Edit Attribute Set Name')]); $fieldset->addField( 'attribute_set_name', 'text', diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Set/Toolbar/Add.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Set/Toolbar/Add.php index 42434c7094c6464bc98657e856416e5109e80a36..f4f6dc467ca0d47cc86b782a7f55f7cd6befcada 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Set/Toolbar/Add.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Set/Toolbar/Add.php @@ -57,7 +57,7 @@ class Add extends \Magento\Backend\Block\Template */ protected function _getHeader() { - return __('Add New Product Template'); + return __('Add New Attribute Set'); } /** diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Set/Toolbar/Main.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Set/Toolbar/Main.php index cedf419205b6f704b1ebc4dd60009ea20beb4b55..a04f09439e1bc8811373dae7106817af955b421b 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Set/Toolbar/Main.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Set/Toolbar/Main.php @@ -27,7 +27,7 @@ class Main extends \Magento\Backend\Block\Template 'addButton', 'Magento\Backend\Block\Widget\Button', [ - 'label' => __('Add Product Template'), + 'label' => __('Add Attribute Set'), 'onclick' => 'setLocation(\'' . $this->getUrl('catalog/*/add') . '\')', 'class' => 'add primary add-set' ] @@ -48,7 +48,7 @@ class Main extends \Magento\Backend\Block\Template */ protected function _getHeader() { - return __('Product Templates'); + return __('Attribute Sets'); } /** diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/AttributeSet.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/AttributeSet.php index 5b8bb9a77fa3bc10528129cfa5097d3350776ddd..df7a36b961a3432f25387f9d332dbaabf333ca9f 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/AttributeSet.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/AttributeSet.php @@ -42,7 +42,7 @@ class AttributeSet extends \Magento\Backend\Block\Widget\Form public function getSelectorOptions() { return [ - 'source' => $this->getUrl('catalog/product/suggestProductTemplates'), + 'source' => $this->getUrl('catalog/product/suggestAttributeSets'), 'className' => 'category-select', 'showRecent' => true, 'storageKey' => 'product-template-key', diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Crosssell.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Crosssell.php index 8f6c08bb52bca13d6ded0f70f31ab034c9549d2f..09fbbd9b2a292c037815df8e1720a54f3e1b0bb9 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Crosssell.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Crosssell.php @@ -249,7 +249,7 @@ class Crosssell extends Extended $this->addColumn( 'set_name', [ - 'header' => __('Product Template'), + 'header' => __('Attribute Set'), 'index' => 'attribute_set_id', 'type' => 'options', 'options' => $sets, diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Options/Option.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Options/Option.php index f507d9ee30ec0bf3a8094bdc5fd7796f047e3cd3..7dbacd96990b59888da7ecccb736760b1836c5a4 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Options/Option.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Options/Option.php @@ -461,4 +461,14 @@ class Option extends Widget { return $this->getUrl('catalog/*/customOptions'); } + + /** + * Return current product id + * + * @return null|int + */ + public function getCurrentProductId() + { + return $this->getProduct()->getId(); + } } diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Options/Popup/Grid.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Options/Popup/Grid.php index 53bcc298732f9d804846b252f950e4e9c5d3b936..646db241f82248d612d0d34e8d1dd74745cd85ef 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Options/Popup/Grid.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Options/Popup/Grid.php @@ -62,7 +62,19 @@ class Grid extends \Magento\Catalog\Block\Adminhtml\Product\Grid protected function _prepareCollection() { parent::_prepareCollection(); - $this->getCollection()->addFieldToFilter('has_options', 1); + + if (null !== $this->getRequest()->getParam('current_product_id')) { + $this->getCollection()->getSelect()->where( + 'e.entity_id != ?', + $this->getRequest()->getParam('current_product_id') + ); + } + + $this->getCollection()->getSelect()->distinct()->join( + ['opt' => $this->getCollection()->getTable('catalog_product_option')], + 'opt.product_id = e.entity_id', + null + ); return $this; } diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Related.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Related.php index 0e87290ec2729752ef2b35adcffa418ad3d8da9c..af104d601ac4e9a2d04dc08b7c27a3496ecbea30 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Related.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Related.php @@ -243,7 +243,7 @@ class Related extends Extended $this->addColumn( 'set_name', [ - 'header' => __('Product Template'), + 'header' => __('Attribute Set'), 'index' => 'attribute_set_id', 'type' => 'options', 'options' => $sets, diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Upsell.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Upsell.php index cad5aafe5d0ccfd2c4ee561e8f425a6d9695ea32..2ea563292e69c8bb8ccebcd77f96da2d20c2d76e 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Upsell.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Edit/Tab/Upsell.php @@ -239,7 +239,7 @@ class Upsell extends \Magento\Backend\Block\Widget\Grid\Extended $this->addColumn( 'set_name', [ - 'header' => __('Product Template'), + 'header' => __('Attribute Set'), 'index' => 'attribute_set_id', 'type' => 'options', 'options' => $sets, diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Grid.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Grid.php index e6f12259918729648a443e1310e05b196f2e7b25..e426c08e70a44e9ee178993f204901976683ba9f 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Grid.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Grid.php @@ -263,7 +263,7 @@ class Grid extends \Magento\Backend\Block\Widget\Grid\Extended $this->addColumn( 'set_name', [ - 'header' => __('Product Template'), + 'header' => __('Attribute Set'), 'index' => 'attribute_set_id', 'type' => 'options', 'options' => $sets, diff --git a/app/code/Magento/Catalog/Block/Product/TemplateSelector.php b/app/code/Magento/Catalog/Block/Product/TemplateSelector.php index 0fa415acf082b57e582d31793fa67e84a9a73006..e2cb3d356a6f40e6cd1e17b46aae73615b249565 100644 --- a/app/code/Magento/Catalog/Block/Product/TemplateSelector.php +++ b/app/code/Magento/Catalog/Block/Product/TemplateSelector.php @@ -54,7 +54,7 @@ class TemplateSelector extends \Magento\Framework\View\Element\Template } /** - * Retrieve list of product templates with search part contained in label + * Retrieve list of attribute sets with search part contained in label * * @param string $labelPart * @return array diff --git a/app/code/Magento/Catalog/Block/Product/View/Options.php b/app/code/Magento/Catalog/Block/Product/View/Options.php index 5e4efdb8e56cbcb45dbaa32a20e54367021c05fe..befca9212fccc264c9a5af55996f474b4d60cf41 100644 --- a/app/code/Magento/Catalog/Block/Product/View/Options.php +++ b/app/code/Magento/Catalog/Block/Product/View/Options.php @@ -162,7 +162,7 @@ class Options extends \Magento\Framework\View\Element\Template $data = [ 'prices' => [ 'oldPrice' => [ - 'amount' => $this->pricingHelper->currency($option->getPrice(false), false, false), + 'amount' => $optionPrice, 'adjustments' => [], ], 'basePrice' => [ diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/AddAttributeToTemplate.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/AddAttributeToTemplate.php index 7d337411b0a234f947c20f243bce508de82a8481..26fea5b4039fdcf5b10dc72f2bd17f9ef501ac3e 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/AddAttributeToTemplate.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/AddAttributeToTemplate.php @@ -27,7 +27,7 @@ class AddAttributeToTemplate extends \Magento\Catalog\Controller\Adminhtml\Produ $this->resultJsonFactory = $resultJsonFactory; } /** - * Add attribute to product template + * Add attribute to attribute set * * @return \Magento\Framework\Controller\Result\Json */ diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Add.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Add.php index 81f61ec8362a54a1e3e094902ef15365e78ab056..7e4bee7a769130c5bee46b3ec708192811e79d7b 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Add.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Add.php @@ -37,7 +37,7 @@ class Add extends \Magento\Catalog\Controller\Adminhtml\Product\Set /** @var \Magento\Backend\Model\View\Result\Page $resultPage */ $resultPage = $this->resultPageFactory->create(); $resultPage->setActiveMenu('Magento_Catalog::catalog_attributes_sets'); - $resultPage->getConfig()->getTitle()->prepend(__('New Product Template')); + $resultPage->getConfig()->getTitle()->prepend(__('New Attribute Set')); $resultPage->addContent( $resultPage->getLayout()->createBlock('Magento\Catalog\Block\Adminhtml\Product\Attribute\Set\Toolbar\Add') ); diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Delete.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Delete.php index 9849dc6884732048424f4b95adc8782eca6954c9..9585bce699f5faa9b579089f3fbbd8313344b346 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Delete.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Delete.php @@ -36,7 +36,7 @@ class Delete extends \Magento\Catalog\Controller\Adminhtml\Product\Set $resultRedirect = $this->resultRedirectFactory->create(); try { $this->attributeSetRepository->deleteById($setId); - $this->messageManager->addSuccess(__('The product template has been removed.')); + $this->messageManager->addSuccess(__('The attribute set has been removed.')); $resultRedirect->setPath('catalog/*/'); } catch (\Exception $e) { $this->messageManager->addError(__('We can\'t delete this set right now.')); diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Edit.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Edit.php index d40982a5d5641e8d2c3a3099015686f5435e52b8..8f7dafbf28892ece98cc1c430d81d92f3ab536cf 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Edit.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Edit.php @@ -45,7 +45,7 @@ class Edit extends \Magento\Catalog\Controller\Adminhtml\Product\Set /** @var \Magento\Backend\Model\View\Result\Page $resultPage */ $resultPage = $this->resultPageFactory->create(); $resultPage->setActiveMenu('Magento_Catalog::catalog_attributes_sets'); - $resultPage->getConfig()->getTitle()->prepend(__('Product Templates')); + $resultPage->getConfig()->getTitle()->prepend(__('Attribute Sets')); $resultPage->getConfig()->getTitle()->prepend( $attributeSet->getId() ? $attributeSet->getAttributeSetName() : __('New Set') ); diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Index.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Index.php index 7b9edb21c7e2f8951643e51963411f2252b655a9..2e1e1a4b642f660595911445bc12a35777f82cf4 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Index.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Index.php @@ -37,9 +37,9 @@ class Index extends \Magento\Catalog\Controller\Adminhtml\Product\Set /** @var \Magento\Backend\Model\View\Result\Page $resultPage */ $resultPage = $this->resultPageFactory->create(); $resultPage->setActiveMenu('Magento_Catalog::catalog_attributes_sets'); - $resultPage->getConfig()->getTitle()->prepend(__('Product Templates')); + $resultPage->getConfig()->getTitle()->prepend(__('Attribute Sets')); $resultPage->addBreadcrumb(__('Catalog'), __('Catalog')); - $resultPage->addBreadcrumb(__('Manage Product Templates'), __('Product Templates')); + $resultPage->addBreadcrumb(__('Manage Attribute Sets'), __('Attribute Sets')); return $resultPage; } } diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Save.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Save.php index 5870190db02b73a9bbae7b804d0ad1e75b8acfe5..480a079d53d7ee70d77f3f7f0c048a31d2cdaac6 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Save.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Save.php @@ -82,7 +82,7 @@ class Save extends \Magento\Catalog\Controller\Adminhtml\Product\Set } if (!$model->getId()) { throw new \Magento\Framework\Exception\LocalizedException( - __('This product template no longer exists.') + __('This attribute set no longer exists.') ); } $data = $this->_objectManager->get('Magento\Framework\Json\Helper\Data') @@ -100,12 +100,12 @@ class Save extends \Magento\Catalog\Controller\Adminhtml\Product\Set $model->initFromSkeleton($this->getRequest()->getParam('skeleton_set')); } $model->save(); - $this->messageManager->addSuccess(__('You saved the product template.')); + $this->messageManager->addSuccess(__('You saved the attribute set.')); } catch (\Magento\Framework\Exception\LocalizedException $e) { $this->messageManager->addError($e->getMessage()); $hasError = true; } catch (\Exception $e) { - $this->messageManager->addException($e, __('Something went wrong while saving the product template.')); + $this->messageManager->addException($e, __('Something went wrong while saving the attribute set.')); $hasError = true; } diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/SuggestProductTemplates.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/SuggestAttributeSets.php similarity index 92% rename from app/code/Magento/Catalog/Controller/Adminhtml/Product/SuggestProductTemplates.php rename to app/code/Magento/Catalog/Controller/Adminhtml/Product/SuggestAttributeSets.php index d28b72799e770cebf089341b9749125141baefdf..456a579c6191d9a284e0cf7f5f16a99d38e317d3 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/SuggestProductTemplates.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/SuggestAttributeSets.php @@ -6,7 +6,7 @@ */ namespace Magento\Catalog\Controller\Adminhtml\Product; -class SuggestProductTemplates extends \Magento\Backend\App\Action +class SuggestAttributeSets extends \Magento\Backend\App\Action { /** * @var \Magento\Framework\Controller\Result\JsonFactory @@ -34,7 +34,7 @@ class SuggestProductTemplates extends \Magento\Backend\App\Action } /** - * Action for product template selector + * Action for attribute set selector * * @return \Magento\Framework\Controller\Result\Json */ diff --git a/app/code/Magento/Catalog/Helper/Product/Flat/Indexer.php b/app/code/Magento/Catalog/Helper/Product/Flat/Indexer.php index a54b13b3d6fbc9742cfc1f9571bb9981b11c6849..b88dac52725b279759f938ea53cb5d789c5dfa5f 100644 --- a/app/code/Magento/Catalog/Helper/Product/Flat/Indexer.php +++ b/app/code/Magento/Catalog/Helper/Product/Flat/Indexer.php @@ -204,7 +204,7 @@ class Indexer extends \Magento\Framework\App\Helper\AbstractHelper 'unsigned' => true, 'nullable' => false, 'default' => '0', - 'comment' => 'Product Template ID', + 'comment' => 'Attribute Set ID', ]; $columns['type_id'] = [ 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, diff --git a/app/code/Magento/Catalog/Model/CategoryLinkManagement.php b/app/code/Magento/Catalog/Model/CategoryLinkManagement.php index 0c2c324bd8e2c931b57babe59147837b4feb193b..4ff351dc3d735b79ad3ee2adf3d9275ceb54c0c3 100644 --- a/app/code/Magento/Catalog/Model/CategoryLinkManagement.php +++ b/app/code/Magento/Catalog/Model/CategoryLinkManagement.php @@ -36,20 +36,20 @@ class CategoryLinkManagement implements \Magento\Catalog\Api\CategoryLinkManagem public function getAssignedProducts($categoryId) { $category = $this->categoryRepository->get($categoryId); - $productsPosition = $category->getProductsPosition(); - /** @var \Magento\Framework\Data\Collection\AbstractDb $products */ + /** @var \Magento\Catalog\Model\ResourceModel\Product\Collection $products */ $products = $category->getProductCollection(); + $products->addFieldToSelect('position'); /** @var \Magento\Catalog\Api\Data\CategoryProductLinkInterface[] $links */ $links = []; /** @var \Magento\Catalog\Model\Product $product */ - foreach ($products->getItems() as $productId => $product) { + foreach ($products->getItems() as $product) { /** @var \Magento\Catalog\Api\Data\CategoryProductLinkInterface $link */ $link = $this->productLinkFactory->create(); $link->setSku($product->getSku()) - ->setPosition($productsPosition[$productId]) + ->setPosition($product->getData('cat_index_position')) ->setCategoryId($category->getId()); $links[] = $link; } diff --git a/app/code/Magento/Catalog/Model/Config/Source/Product/Options/Type.php b/app/code/Magento/Catalog/Model/Config/Source/Product/Options/Type.php index 5d0c1f24872a76b3345d9a4995535c180f4931e8..ca62402f23a378129cac9cd10f43a42a5a463aa7 100644 --- a/app/code/Magento/Catalog/Model/Config/Source/Product/Options/Type.php +++ b/app/code/Magento/Catalog/Model/Config/Source/Product/Options/Type.php @@ -43,7 +43,7 @@ class Type implements \Magento\Framework\Option\ArrayInterface $types[] = ['label' => __($type['label']), 'value' => $type['name']]; } if (count($types)) { - $groups[] = ['label' => __($option['label']), 'value' => $types]; + $groups[] = ['label' => __($option['label']), 'value' => $types, 'optgroup-name' => $option['label']]; } } diff --git a/app/code/Magento/Catalog/Model/Product.php b/app/code/Magento/Catalog/Model/Product.php index 99709b513ca2cf08167a07f76ac22169ec2001b7..63045d6d5e26f0be48e8602ff7aa5b0430ed263e 100644 --- a/app/code/Magento/Catalog/Model/Product.php +++ b/app/code/Magento/Catalog/Model/Product.php @@ -25,7 +25,7 @@ use Magento\Catalog\Api\Data\ProductAttributeMediaGalleryEntryExtensionFactory; * @method array getAssociatedProductIds() * @method Product setNewVariationsAttributeSetId(int $value) * @method int getNewVariationsAttributeSetId() - * @method int getPriceType + * @method int getPriceType() * @method \Magento\Catalog\Model\ResourceModel\Product\Collection getCollection() * @method string getUrlKey() * @method Product setUrlKey(string $urlKey) diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Media.php b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Media.php index 8ca5ffbc429e567ddc1b37f5c24b482e62ec5335..f7fd135a134061614cbbc4b7d6c8557289cd0ad8 100644 --- a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Media.php +++ b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Media.php @@ -85,7 +85,7 @@ class Media extends Product\Attribute\Backend\AbstractMedia // For duplicating we need copy original images. $duplicate = []; foreach ($value['images'] as &$image) { - if (empty($image['value_id'])) { + if (empty($image['value_id']) || !empty($image['removed'])) { continue; } $duplicate[$image['value_id']] = $this->copyImage($image['file']); diff --git a/app/code/Magento/Catalog/Model/Product/AttributeSet/Build.php b/app/code/Magento/Catalog/Model/Product/AttributeSet/Build.php index 7c5be52e6d7e89e9d387a0d6c5e5d63f66af9d61..a70ae163575947f344ad368f1b56f950f56fe6b7 100644 --- a/app/code/Magento/Catalog/Model/Product/AttributeSet/Build.php +++ b/app/code/Magento/Catalog/Model/Product/AttributeSet/Build.php @@ -79,7 +79,7 @@ class Build $attributeSet = $this->attributeSetFactory->create(); $attributeSet->setEntityTypeId($this->entityTypeId)->load($this->name, 'attribute_set_name'); if ($attributeSet->getId()) { - throw new AlreadyExistsException(__('Product Template already exists.')); + throw new AlreadyExistsException(__('Attribute Set already exists.')); } $attributeSet->setAttributeSetName($this->name)->validate(); diff --git a/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidatorFile.php b/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidatorFile.php index a9f7a1188c554ddfbd13abfd7aa2d57bdbc37ba1..1b3b2c5f0d8f3f2f824b16e2dde53d08e91a5505 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidatorFile.php +++ b/app/code/Magento/Catalog/Model/Product/Option/Type/File/ValidatorFile.php @@ -21,21 +21,21 @@ class ValidatorFile extends Validator * * @var string */ - protected $path = '/custom_options'; + protected $path = 'custom_options'; /** * Relative path for quote folder * * @var string */ - protected $quotePath = '/custom_options/quote'; + protected $quotePath = 'custom_options/quote'; /** * Relative path for order folder * * @var string */ - protected $orderPath = '/custom_options/order'; + protected $orderPath = 'custom_options/order'; /** * @var \Magento\Framework\Filesystem\Directory\WriteInterface @@ -175,12 +175,12 @@ class ValidatorFile extends Validator $_height = $imageSize[1]; } } - $uri = $this->filesystem->getUri(DirectoryList::MEDIA); + $userValue = [ 'type' => $fileInfo['type'], 'title' => $fileInfo['name'], - 'quote_path' => $uri . $this->quotePath . $filePath, - 'order_path' => $uri . $this->orderPath . $filePath, + 'quote_path' => $this->quotePath . $filePath, + 'order_path' => $this->orderPath . $filePath, 'fullpath' => $fileFullPath, 'size' => $fileInfo['size'], 'width' => $_width, diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Category/Flat.php b/app/code/Magento/Catalog/Model/ResourceModel/Category/Flat.php index 82000fb03d1703e6e34dfeb854e6d1ad6aca80ee..30c9476931f10aa0daf23dbbf1ff389bb02d2abd 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Category/Flat.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Category/Flat.php @@ -671,4 +671,23 @@ class Flat extends \Magento\Indexer\Model\ResourceModel\AbstractResource return $this->getConnection()->fetchCol($select); } + + /** + * Get positions of associated to category products + * + * @param \Magento\Catalog\Model\Category $category + * @return array + */ + public function getProductsPosition($category) + { + $select = $this->getConnection()->select()->from( + $this->getTable('catalog_category_product'), + ['product_id', 'position'] + )->where( + 'category_id = :category_id' + ); + $bind = ['category_id' => (int)$category->getId()]; + + return $this->getConnection()->fetchPairs($select, $bind); + } } diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product.php b/app/code/Magento/Catalog/Model/ResourceModel/Product.php index b4d5298035dadab55cb0158a5ef72d64226d4253..130cd77177306433c5a9202e3ae85906f03ed516 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product.php @@ -656,7 +656,7 @@ class Product extends AbstractResource $entityType = $this->typeFactory->create()->loadByCode(\Magento\Catalog\Model\Product::ENTITY); $attributeSet = $this->setFactory->create()->load($object->getAttributeSetId()); if ($attributeSet->getEntityTypeId() != $entityType->getId()) { - return ['attribute_set' => 'Invalid product template entity type']; + return ['attribute_set' => 'Invalid attribute set entity type']; } return parent::validate($object); diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Attribute/Backend/Media.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Attribute/Backend/Media.php index a77ea68ae16d5e42855e7e422ff3662eeba5bcf6..0ac7a8c1a7bf612d352c6ea352a879c40f303abe 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Attribute/Backend/Media.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Attribute/Backend/Media.php @@ -324,11 +324,12 @@ class Media extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb foreach ($this->getConnection()->fetchAll($select) as $row) { $data = [ 'attribute_id' => $attributeId, - 'entity_id' => $newProductId, 'value' => isset($newFiles[$row['value_id']]) ? $newFiles[$row['value_id']] : $row['value'], ]; $valueIdMap[$row['value_id']] = $this->insertGallery($data); + $this->bindValueToEntity($valueIdMap[$row['value_id']], $newProductId); + } if (count($valueIdMap) == 0) { @@ -344,6 +345,8 @@ class Media extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb ); foreach ($this->getConnection()->fetchAll($select) as $row) { + unset($row['record_id']); + $row['entity_id'] = $newProductId; $row['value_id'] = $valueIdMap[$row['value_id']]; $this->insertGalleryValueInStore($row); } diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php index 0393bf02276257507ebd9f392ef6b499a7866bee..15421607a696fe8e09d9efeddc85c9505dcb4942 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php @@ -133,22 +133,6 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Collection\Abstrac */ protected $_priceDataFieldFilters = []; - /** - * Map of price fields - * - * @var array - */ - protected $_map = [ - 'fields' => [ - 'price' => 'price_index.price', - 'final_price' => 'price_index.final_price', - 'min_price' => 'price_index.min_price', - 'max_price' => 'price_index.max_price', - 'tier_price' => 'price_index.tier_price', - 'special_price' => 'price_index.special_price', - ], - ]; - /** * Price expression sql * diff --git a/app/code/Magento/Catalog/Setup/InstallSchema.php b/app/code/Magento/Catalog/Setup/InstallSchema.php index c507f35db664497d5a59c4f45a5e458833dde4d2..927dd2596cb2951597bb2b81e98ec24cd2913702 100644 --- a/app/code/Magento/Catalog/Setup/InstallSchema.php +++ b/app/code/Magento/Catalog/Setup/InstallSchema.php @@ -42,7 +42,7 @@ class InstallSchema implements InstallSchemaInterface \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, null, ['unsigned' => true, 'nullable' => false, 'default' => '0'], - 'Product Template ID' + 'Attribute Set ID' ) ->addColumn( 'type_id', diff --git a/app/code/Magento/Catalog/Test/Unit/Block/Adminhtml/Product/Attribute/Edit/Tab/AdvancedTest.php b/app/code/Magento/Catalog/Test/Unit/Block/Adminhtml/Product/Attribute/Edit/Tab/AdvancedTest.php index a54834d4f56966f448480c1000f1f98ba45c4356..7408df0ede1d678644939f92c9055007e97e3759 100644 --- a/app/code/Magento/Catalog/Test/Unit/Block/Adminhtml/Product/Attribute/Edit/Tab/AdvancedTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Block/Adminhtml/Product/Attribute/Edit/Tab/AdvancedTest.php @@ -89,7 +89,7 @@ class AdvancedTest extends \PHPUnit_Framework_TestCase $this->localeDate->expects($this->any())->method('getDateFormat')->willReturn('mm/dd/yy'); $entityType->expects($this->any())->method('getEntityTypeCode')->willReturn('entity_type_code'); $this->eavData->expects($this->any())->method('getFrontendClasses')->willReturn([]); - $formElement->expects($this->exactly(3))->method('setDisabled')->willReturnSelf(); + $formElement->expects($this->exactly(2))->method('setDisabled')->willReturnSelf(); $this->yesNo->expects($this->any())->method('toOptionArray')->willReturn(['yes', 'no']); $this->filesystem->expects($this->any())->method('getDirectoryRead')->willReturn($directoryReadInterface); $directoryReadInterface->expects($this->any())->method('getRelativePath')->willReturn('relative_path'); diff --git a/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkManagementTest.php b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkManagementTest.php index 9e75726f9dfa284355307d81760d848aa2d7de6e..4be4d33c4fcf2852cb23586fbdf505e387b0682b 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkManagementTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkManagementTest.php @@ -44,7 +44,7 @@ class CategoryLinkManagementTest extends \PHPUnit_Framework_TestCase { $categoryId = 42; $productId = 55; - $productsPosition = [$productId => 25]; + $position = 25; $productSku = 'testSku'; $categoryProductLinkMock = $this->getMock('\Magento\Catalog\Api\Data\CategoryProductLinkInterface'); $categoryMock = $this->getMock( @@ -56,13 +56,14 @@ class CategoryLinkManagementTest extends \PHPUnit_Framework_TestCase ); $productMock = $this->getMock('\Magento\Catalog\Model\Product', [], [], '', false); $productMock->expects($this->once())->method('getSku')->willReturn($productSku); + $productMock->expects($this->once())->method('getData')->with('cat_index_position')->willReturn($position); $items = [$productId => $productMock]; - $productsMock = $this->getMock('\Magento\Framework\Data\Collection\AbstractDb', [], [], '', false); + $productsMock = $this->getMock('Magento\Catalog\Model\ResourceModel\Product\Collection', [], [], '', false); $this->categoryRepositoryMock->expects($this->once())->method('get')->with($categoryId) ->willReturn($categoryMock); - $categoryMock->expects($this->once())->method('getProductsPosition')->willReturn($productsPosition); $categoryMock->expects($this->once())->method('getProductCollection')->willReturn($productsMock); $categoryMock->expects($this->once())->method('getId')->willReturn($categoryId); + $productsMock->expects($this->once())->method('addFieldToSelect')->with('position')->willReturnSelf(); $productsMock->expects($this->once())->method('getItems')->willReturn($items); $this->productLinkFactoryMock->expects($this->once())->method('create')->willReturn($categoryProductLinkMock); $categoryProductLinkMock->expects($this->once()) @@ -71,7 +72,7 @@ class CategoryLinkManagementTest extends \PHPUnit_Framework_TestCase ->willReturnSelf(); $categoryProductLinkMock->expects($this->once()) ->method('setPosition') - ->with(25) + ->with($position) ->willReturnSelf(); $categoryProductLinkMock->expects($this->once()) ->method('setCategoryId') diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Config/Source/Product/Options/TypeTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Config/Source/Product/Options/TypeTest.php index aa686d39ce8d9e1bcc08a00a1bcc6ab1bbb997c7..0696faaa9343593ec21d5108a3ccd5c8e98f1850 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Config/Source/Product/Options/TypeTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Config/Source/Product/Options/TypeTest.php @@ -51,7 +51,11 @@ class TypeTest extends \PHPUnit_Framework_TestCase ]; $expect = [ ['value' => '', 'label' => __('-- Please select --')], - ['label' => 'optionLabel', 'value' => [['label' => 'typeLabel', 'value' => 'typeName']]], + [ + 'label' => 'optionLabel', + 'optgroup-name' => 'optionLabel', + 'value' => [['label' => 'typeLabel', 'value' => 'typeName']] + ], ]; $this->productOptionConfig->expects($this->any())->method('getAll')->will($this->returnValue($allOptions)); diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Media/AttributeManagementTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Media/AttributeManagementTest.php index 3e8a85a77166a9facfa71e6aa0b011cd07bde981..cc65bb7803ba8d52983564708deb9ee0cdb779f4 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/Media/AttributeManagementTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Media/AttributeManagementTest.php @@ -58,7 +58,7 @@ class AttributeManagementTest extends \PHPUnit_Framework_TestCase public function testGetList() { - $attributeSetName = 'Default Product Template'; + $attributeSetName = 'Default Attribute Set'; $expectedResult = [ $this->getMock('\Magento\Catalog\Api\Data\ProductAttributeInterface'), ]; diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/ProductTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/ProductTest.php index 9967344b70e8da0c9f50a1995647fa7afb3fd96d..d3c8792274104fc65aabdc4c72fce36acfc411b3 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/ProductTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/ProductTest.php @@ -56,7 +56,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase public function testValidateWrongAttributeSet() { $productTypeId = 4; - $expectedErrorMessage = ['attribute_set' => 'Invalid product template entity type']; + $expectedErrorMessage = ['attribute_set' => 'Invalid attribute set entity type']; $productMock = $this->getMock( '\Magento\Framework\DataObject', diff --git a/app/code/Magento/Catalog/Ui/Component/ColumnFactory.php b/app/code/Magento/Catalog/Ui/Component/ColumnFactory.php index 58de2b262c8ab7489b6f37691e592484dd7d624b..ab061a2c756c3a5a4eb5aa312312459e163720a1 100644 --- a/app/code/Magento/Catalog/Ui/Component/ColumnFactory.php +++ b/app/code/Magento/Catalog/Ui/Component/ColumnFactory.php @@ -55,6 +55,9 @@ class ColumnFactory 'dataType' => $this->getDataType($attribute), 'add_field' => true, 'visible' => $attribute->getIsVisibleInGrid(), + 'filter' => ($attribute->getIsFilterableInGrid()) + ? $this->getFilterType($attribute->getFrontendInput()) + : null, ], $config); if ($attribute->usesSource()) { @@ -92,4 +95,17 @@ class ColumnFactory ? $this->dataTypeMap[$attribute->getFrontendInput()] : $this->dataTypeMap['default']; } + + /** + * Retrieve filter type by $frontendInput + * + * @param string $frontendInput + * @return string + */ + protected function getFilterType($frontendInput) + { + $filtersMap = ['date' => 'dateRange']; + $result = array_replace_recursive($this->dataTypeMap, $filtersMap); + return isset($result[$frontendInput]) ? $result[$frontendInput] : $result['default']; + } } diff --git a/app/code/Magento/Catalog/Ui/Component/Listing/Columns/Price.php b/app/code/Magento/Catalog/Ui/Component/Listing/Columns/Price.php index 2c4af877568c3d9d33dfb033d034c254e03b376f..bcfef825f53453c3df348a1ea0313aebca153cac 100644 --- a/app/code/Magento/Catalog/Ui/Component/Listing/Columns/Price.php +++ b/app/code/Magento/Catalog/Ui/Component/Listing/Columns/Price.php @@ -53,14 +53,12 @@ class Price extends \Magento\Ui\Component\Listing\Columns\Column $store = $this->storeManager->getStore( $this->context->getFilterParam('store_id', \Magento\Store\Model\Store::DEFAULT_STORE_ID) ); - $currencyCode = $store->getCurrentCurrencyCode(); - $currencyRate = $store->getCurrentCurrencyRate(); - $currency = $this->localeCurrency->getCurrency($currencyCode); + $currency = $this->localeCurrency->getCurrency($store->getBaseCurrencyCode()); $fieldName = $this->getData('name'); foreach ($dataSource['data']['items'] as & $item) { if (isset($item[$fieldName])) { - $item[$fieldName] = $currency->toCurrency(sprintf("%f", $item[$fieldName] * $currencyRate)); + $item[$fieldName] = $currency->toCurrency(sprintf("%f", $item[$fieldName])); } } } diff --git a/app/code/Magento/Catalog/etc/acl.xml b/app/code/Magento/Catalog/etc/acl.xml index 0811d1393129b0dc6ef29ae61fc8793474b6bd78..0fc34da2584446847da5ab5234563d05c0ee8d46 100644 --- a/app/code/Magento/Catalog/etc/acl.xml +++ b/app/code/Magento/Catalog/etc/acl.xml @@ -24,7 +24,7 @@ <resource id="Magento_Backend::stores_attributes"> <resource id="Magento_Catalog::attributes_attributes" title="Product" sortOrder="30" /> <resource id="Magento_Catalog::update_attributes" title="Update Attributes" sortOrder="35" /> - <resource id="Magento_Catalog::sets" title="Product Template" sortOrder="40"/> + <resource id="Magento_Catalog::sets" title="Attribute Set" sortOrder="40"/> </resource> </resource> </resource> diff --git a/app/code/Magento/Catalog/etc/adminhtml/menu.xml b/app/code/Magento/Catalog/etc/adminhtml/menu.xml index 0d9783b0fea0af781b38b548aa6a26cf8abf00d7..53db61bd3a1ccdf477672bc10d74c00c76e8156f 100644 --- a/app/code/Magento/Catalog/etc/adminhtml/menu.xml +++ b/app/code/Magento/Catalog/etc/adminhtml/menu.xml @@ -11,7 +11,7 @@ <add id="Magento_Catalog::catalog_products" title="Catalog" module="Magento_Catalog" sortOrder="10" parent="Magento_Catalog::inventory" action="catalog/product/" resource="Magento_Catalog::products"/> <add id="Magento_Catalog::catalog_categories" title="Categories" module="Magento_Catalog" sortOrder="20" parent="Magento_Catalog::inventory" action="catalog/category/" resource="Magento_Catalog::categories"/> <add id="Magento_Catalog::catalog_attributes_attributes" title="Product" module="Magento_Catalog" sortOrder="30" parent="Magento_Backend::stores_attributes" action="catalog/product_attribute/" resource="Magento_Catalog::attributes_attributes"/> - <add id="Magento_Catalog::catalog_attributes_sets" title="Product Template" module="Magento_Catalog" sortOrder="40" parent="Magento_Backend::stores_attributes" action="catalog/product_set/" resource="Magento_Catalog::sets"/> + <add id="Magento_Catalog::catalog_attributes_sets" title="Attribute Set" module="Magento_Catalog" sortOrder="40" parent="Magento_Backend::stores_attributes" action="catalog/product_set/" resource="Magento_Catalog::sets"/> <add id="Magento_Catalog::inventory" title="Inventory" module="Magento_Catalog" sortOrder="10" parent="Magento_Catalog::catalog" dependsOnModule="Magento_Catalog" resource="Magento_Catalog::catalog"/> </menu> diff --git a/app/code/Magento/Catalog/i18n/de_DE.csv b/app/code/Magento/Catalog/i18n/de_DE.csv index ecbd2cb02116bf9af5c3f6ac5bae02811a89a110..13f728de1c48bf5b7d2129e11186f94fcb71780a 100644 --- a/app/code/Magento/Catalog/i18n/de_DE.csv +++ b/app/code/Magento/Catalog/i18n/de_DE.csv @@ -160,7 +160,9 @@ Empty,Leer "Based On","Basierend auf" "Add New Attribute Set","Neuer Eigenschaftensatz hinzufügen" "Add New Set","Neuen Satz hinzufügen" +"Attribute Sets","Attribute Sets" "Product Templates","Product Templates" +"Product Template","Product Template" "Close Window","Fenster Schließen" "New Product","Neues Produkt" "Save & Edit","Save & Edit" @@ -280,6 +282,7 @@ Categories,Kategorien "This attribute set no longer exists.","Dieses Eigenschaftenset existiert nicht mehr." "You saved the attribute set.","You saved the attribute set." "An error occurred while saving the attribute set.","Beim Speichern des Eigenschaftensatzes ist ein Fehler aufgetreten." +"New Attribute Set","New Attribute Set" "New Product Template","New Product Template" "The attribute set has been removed.","The attribute set has been removed." "An error occurred while deleting this set.","An error occurred while deleting this set." diff --git a/app/code/Magento/Catalog/i18n/en_US.csv b/app/code/Magento/Catalog/i18n/en_US.csv index 2cfe7083932dd18f5c4e4082eb80fe321b2ee809..87bcbd26408da6c7cf300b6a6af1bbe718158aad 100644 --- a/app/code/Magento/Catalog/i18n/en_US.csv +++ b/app/code/Magento/Catalog/i18n/en_US.csv @@ -160,7 +160,9 @@ Empty,Empty "Based On","Based On" "Add New Attribute Set","Add New Attribute Set" "Add New Set","Add New Set" +"Attribute Sets","Attribute Sets" "Product Templates","Product Templates" +"Product Template","Product Template" "Close Window","Close Window" "New Product","New Product" "Save & Edit","Save & Edit" @@ -280,6 +282,7 @@ Categories,Categories "This attribute set no longer exists.","This attribute set no longer exists." "You saved the attribute set.","You saved the attribute set." "An error occurred while saving the attribute set.","An error occurred while saving the attribute set." +"New Attribute Set","New Attribute Set" "New Product Template","New Product Template" "The attribute set has been removed.","The attribute set has been removed." "An error occurred while deleting this set.","An error occurred while deleting this set." diff --git a/app/code/Magento/Catalog/i18n/es_ES.csv b/app/code/Magento/Catalog/i18n/es_ES.csv index 83b48a5ad10cb4176b43d2cd321bb4e2a15c1e94..b80323c57f1d54b730d2396e535efec64cef92b2 100644 --- a/app/code/Magento/Catalog/i18n/es_ES.csv +++ b/app/code/Magento/Catalog/i18n/es_ES.csv @@ -160,7 +160,9 @@ Empty,VacÃo(a) "Based On","Basado en" "Add New Attribute Set","Agregar nuevo conjunto de atributos" "Add New Set","Agregar nuevo conjunto" +"Attribute Sets","Attribute Sets" "Product Templates","Product Templates" +"Product Template","Product Template" "Close Window","Cerrar Ventana" "New Product","Nuevo producto" "Save & Edit","Save & Edit" @@ -280,6 +282,7 @@ Categories,CategorÃas "This attribute set no longer exists.","Este conjunto de atributos ya no existe." "You saved the attribute set.","You saved the attribute set." "An error occurred while saving the attribute set.","Se produjo un error mientras se guardaba el conjunto de atributos." +"New Attribute Set","New Attribute Set" "New Product Template","New Product Template" "The attribute set has been removed.","The attribute set has been removed." "An error occurred while deleting this set.","An error occurred while deleting this set." diff --git a/app/code/Magento/Catalog/i18n/fr_FR.csv b/app/code/Magento/Catalog/i18n/fr_FR.csv index 62cb82be609505db81ff49c6c1300a2416c2ed6c..1ea1cd2d717d2d0c1a0c0362bb912878ef85fc33 100644 --- a/app/code/Magento/Catalog/i18n/fr_FR.csv +++ b/app/code/Magento/Catalog/i18n/fr_FR.csv @@ -160,7 +160,9 @@ Empty,Vide "Based On","Basé sur" "Add New Attribute Set","Ajouter un nouveau jeu d'attributs" "Add New Set","Ajouter une nouvelle série" +"Attribute Sets","Attribute Sets" "Product Templates","Product Templates" +"Product Template","Product Template" "Close Window","Fermer la fenêtre" "New Product","Nouveau produit" "Save & Edit","Save & Edit" @@ -280,6 +282,7 @@ Categories,catégories "This attribute set no longer exists.","La série d'attributs n'existe plus." "You saved the attribute set.","You saved the attribute set." "An error occurred while saving the attribute set.","Une erreur est survenue pendant la sauvegarde de la série d'attributs." +"New Attribute Set","New Attribute Set" "New Product Template","New Product Template" "The attribute set has been removed.","The attribute set has been removed." "An error occurred while deleting this set.","An error occurred while deleting this set." diff --git a/app/code/Magento/Catalog/i18n/nl_NL.csv b/app/code/Magento/Catalog/i18n/nl_NL.csv index ee1eb9baee9d9cad43ceabb2583b62b7a104c181..5b99980e6ecae088a5ded2b78d6adca58bb4f413 100644 --- a/app/code/Magento/Catalog/i18n/nl_NL.csv +++ b/app/code/Magento/Catalog/i18n/nl_NL.csv @@ -160,7 +160,9 @@ Empty,Leeg "Based On","Gebaseerd op" "Add New Attribute Set","Voeg Nieuwe Attribuut Set toe" "Add New Set","Voeg Nieuwe Reeks Toe" +"Attribute Sets","Attribute Sets" "Product Templates","Product Templates" +"Product Template","Product Template" "Close Window","Venster Sluiten" "New Product","Nieuw Product" "Save & Edit","Save & Edit" @@ -280,6 +282,7 @@ Categories,Categoriën "This attribute set no longer exists.","Deze attribuutset bestaat niet meer." "You saved the attribute set.","You saved the attribute set." "An error occurred while saving the attribute set.","Er is een fout opgetreden tijdens het opslaan van de attribuut set." +"New Attribute Set","New Attribute Set" "New Product Template","New Product Template" "The attribute set has been removed.","The attribute set has been removed." "An error occurred while deleting this set.","An error occurred while deleting this set." diff --git a/app/code/Magento/Catalog/i18n/pt_BR.csv b/app/code/Magento/Catalog/i18n/pt_BR.csv index 3e0887c87547d57e94da6a9b472d1ee69de8e43a..f539953fb7554f505e900850da9d5a9c0bc3543b 100644 --- a/app/code/Magento/Catalog/i18n/pt_BR.csv +++ b/app/code/Magento/Catalog/i18n/pt_BR.csv @@ -160,7 +160,9 @@ Empty,Vazio "Based On","Baseado Em" "Add New Attribute Set","Adicionar Novo Conjunto de Atributos" "Add New Set","Adicionar Novo Conjunto" +"Attribute Sets","Attribute Sets" "Product Templates","Product Templates" +"Product Template","Product Template" "Close Window","Fechar Janela" "New Product","Novo Produto" "Save & Edit","Save & Edit" @@ -280,6 +282,7 @@ Categories,Categorias "This attribute set no longer exists.","Este conjunto de atributos não existe mais." "You saved the attribute set.","You saved the attribute set." "An error occurred while saving the attribute set.","Ocorreu um erro ao salvar o conjunto de atributos." +"New Attribute Set","New Attribute Set" "New Product Template","New Product Template" "The attribute set has been removed.","The attribute set has been removed." "An error occurred while deleting this set.","An error occurred while deleting this set." diff --git a/app/code/Magento/Catalog/i18n/zh_Hans_CN.csv b/app/code/Magento/Catalog/i18n/zh_Hans_CN.csv index 4774b64706d9a98e98551936c7629de04c5050ac..5180add5db942ca46a9d3159b7c7858e4625ecd7 100644 --- a/app/code/Magento/Catalog/i18n/zh_Hans_CN.csv +++ b/app/code/Magento/Catalog/i18n/zh_Hans_CN.csv @@ -160,7 +160,9 @@ Empty,空 "Based On",基于 "Add New Attribute Set",æ·»åŠ æ–°å±žæ€§é›† "Add New Set",æ·»åŠ æ–°é›† +"Attribute Sets","Attribute Sets" "Product Templates","Product Templates" +"Product Template","Product Template" "Close Window",å…³é—çª—å£ "New Product",æ–°äº§å“ "Save & Edit","Save & Edit" @@ -280,6 +282,7 @@ Categories,分类 "This attribute set no longer exists.",该属性已ä¸å˜åœ¨ã€‚ "You saved the attribute set.","You saved the attribute set." "An error occurred while saving the attribute set.",ä¿å˜å±žæ€§é›†æ—¶å‘生错误。 +"New Attribute Set","New Attribute Set" "New Product Template","New Product Template" "The attribute set has been removed.","The attribute set has been removed." "An error occurred while deleting this set.","An error occurred while deleting this set." diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/checkboxes/tree.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/checkboxes/tree.phtml index 15e6732c51b009bebb8da26bf44e122aee819051..25aaaea0ffe2b98a6e46a7e133c53b743603530e 100644 --- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/checkboxes/tree.phtml +++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/checkboxes/tree.phtml @@ -10,9 +10,7 @@ <?php $_divId = 'tree-div_' . time() ?> <div id="<?php /* @escapeNotVerified */ echo $_divId ?>" class="tree"></div> -<!--[if IE]> <script id="ie-deferred-loader" defer="defer" src=""></script> -<![endif]--> <script> require([ 'jquery', diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/tree.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/tree.phtml index 9e1c939c542386dea232351f7be694945c4dd984..894a4d5bc63fcdf67973f12e5e7bdc25cebe947c 100644 --- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/tree.phtml +++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/tree.phtml @@ -35,9 +35,7 @@ <div><?php /* @escapeNotVerified */ echo __('This operation can take a long time'); ?></div> </div> </div> - <!--[if IE]> <script id="ie-deferred-loader" defer="defer" src=""></script> - <![endif]--> <script> var tree; require([ @@ -466,7 +464,7 @@ click: function () { (function ($) { $.ajax({ - url: '<?php /* @escapeNotVerified */ echo $block->getMoveUrl() ?>//', + url: '<?php /* @escapeNotVerified */ echo $block->getMoveUrl() ?>', method: 'POST', data: pd.join(""), showLoader: true diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/widget/tree.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/widget/tree.phtml index 9e303fe921dfd328453c0f736a107fa4be70e6fa..2549cd64c5c7a1ee489804e48c4feed2a3364915 100644 --- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/widget/tree.phtml +++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/widget/tree.phtml @@ -10,9 +10,8 @@ <?php $_divId = 'tree' . $block->getId() ?> <div id="<?php /* @escapeNotVerified */ echo $_divId ?>" class="tree"></div> -<!--[if IE]> <script id="ie-deferred-loader" defer="defer" src=""></script> -<![endif]--> +<![]--> <script> require(['jquery', "prototype", "extjs/ext-tree-checkbox"], function(jQuery){ diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/set/main.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/set/main.phtml index 06edcfbaa2588ae285fac4a456ec0ae5c05b8846..f1bba6cc3c07ca0603e149afc8f0ad24b342a467 100644 --- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/set/main.phtml +++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/set/main.phtml @@ -38,9 +38,7 @@ <span class="title"><?php /* @escapeNotVerified */ echo __('Unassigned Attributes') ?></span> </div> <div id="tree-div2" class="attribute-set-tree"></div> - <!--[if IE]> <script id="ie-deferred-loader" defer="defer" src=""></script> - <![endif]--> <script> define("tree-panel", [ @@ -354,7 +352,7 @@ rightBeforeAppend : function(tree, nodeThis, node, newParent) { if (node.attributes.is_user_defined == 0) { alert({ - content: '<?php /* @escapeNotVerified */ echo $block->escapeJsQuote(__('You can\'t remove attributes from this product template.')) ?>' + content: '<?php /* @escapeNotVerified */ echo $block->escapeJsQuote(__('You can\'t remove attributes from this attribute set.')) ?>' }); return false; } else { @@ -370,7 +368,7 @@ if (node.attributes.is_unassignable == 0) { alert({ - content: '<?php /* @escapeNotVerified */ echo $block->escapeJsQuote(__('You can\'t remove attributes from this product template.')) ?>' + content: '<?php /* @escapeNotVerified */ echo $block->escapeJsQuote(__('You can\'t remove attributes from this attribute set.')) ?>' }); return false; } else { diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit.phtml index 3bce181616dab3a8a99102a7105ba6dea9bd880e..30048cce246460ab521b5d608865acea320ea488 100644 --- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit.phtml +++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit.phtml @@ -21,7 +21,7 @@ </button> <ul class="dropdown-menu"> <li><input type="text" id="product-template-suggest" class="search" - placeholder="start typing to search template"/></li> + placeholder="<?php /* @noEscape */ echo __('start typing to search template'); ?>"/></li> </ul> </div> </div> diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit/options.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit/options.phtml index 67b1e95e3084663f375efad98714f295ac897c41..6ed486f4c0b4ae21234947626e3f2749aa226d57 100644 --- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit/options.phtml +++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit/options.phtml @@ -9,7 +9,7 @@ ?> <?php /** @var $block \Magento\Catalog\Block\Adminhtml\Product\Edit\Tab\Options */ ?> -<div class="fieldset-wrapper" id="product-custom-options-wrapper"> +<div class="fieldset-wrapper" id="product-custom-options-wrapper" data-block="product-custom-options"> <div class="fieldset-wrapper-title"> <strong class="title"> <span><?php /* @escapeNotVerified */ echo __('Custom Options') ?></span> diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit/options/option.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit/options/option.phtml index 3403d4447f82f705375a32e5467793aabd2dff4d..778c8657a83c25d67548a80f156d9f3e674cd39c 100644 --- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit/options/option.phtml +++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit/options/option.phtml @@ -88,7 +88,7 @@ require([ ], function(jQuery){ jQuery(function ($) { - var fieldSet = $('#Custom_Options'); + var fieldSet = $('[data-block=product-custom-options]'); fieldSet.customOptions(<?php /* @escapeNotVerified */ echo $this->helper('Magento\Framework\Json\Helper\Data')->jsonEncode( [ 'fieldId' => $block->getFieldId(), @@ -97,6 +97,7 @@ jQuery(function ($) { 'customOptionsUrl' => $block->getCustomOptionsUrl(), 'isReadonly' => $block->isReadonly(), 'itemCount' => $block->getItemCount(), + 'currentProductId' => $block->getCurrentProductId(), ] )?>); //adding data to templates diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/product/edit/attribute/search.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/product/edit/attribute/search.phtml index d3c382f9276b8a2d9df9ec1473fbe1707779fc42..8d2cca19f20cae71303e2da1d50f12569dfd41fe 100644 --- a/app/code/Magento/Catalog/view/adminhtml/templates/product/edit/attribute/search.phtml +++ b/app/code/Magento/Catalog/view/adminhtml/templates/product/edit/attribute/search.phtml @@ -17,7 +17,7 @@ <input data-role="product-attribute-search" data-group="<?php echo $block->escapeHtml($block->getGroupCode()); ?>" class="search" type="text" - placeholder="start typing to search attribute"/> + placeholder="<?php /* @noEscape */ echo __('start typing to search attribute'); ?>" /> </div> </div> diff --git a/app/code/Magento/Catalog/view/adminhtml/web/catalog/product/composite/configure.js b/app/code/Magento/Catalog/view/adminhtml/web/catalog/product/composite/configure.js index 030962f2f06413a56129efbbbc6aa3c6d8b4830a..1b5fbe954b89d8bb5edab7477dc7785c0f4ca6c3 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/catalog/product/composite/configure.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/catalog/product/composite/configure.js @@ -761,8 +761,5 @@ define([ } }; - jQuery(document).ready(function(){ - productConfigure = new ProductConfigure(); - }); - + productConfigure = new ProductConfigure(); }); \ No newline at end of file diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/custom-options.js b/app/code/Magento/Catalog/view/adminhtml/web/js/custom-options.js index d68497046a5bf00619fc2db9109ffb8869b7eed2..ae23c3476b8b71df0fd2ff600672c80279247b3b 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/custom-options.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/custom-options.js @@ -179,7 +179,7 @@ define([ }); importContainer.load( this.options.productGridUrl, - {form_key: this.options.formKey}, + {form_key: this.options.formKey, current_product_id : this.options.currentProductId}, function () { importContainer.modal('openModal'); } @@ -194,7 +194,8 @@ define([ var widget = this, currentElement = $(event.target), parentId = '#' + currentElement.closest('.fieldset-alt').attr('id'), - group = currentElement.find('[value="' + currentElement.val() + '"]').closest('optgroup').attr('label'), + group = currentElement.find('[value="' + currentElement.val() + '"]') + .closest('optgroup').attr('data-optgroup-name'), previousGroup = $(parentId + '_previous_group').val(), previousBlock = $(parentId + '_type_' + previousGroup), tmpl; diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Product.php index a2a98fcdbc51ed0b8c57a0a779da126b43bdff50..24475736833f8cbcbda2528614e5f3d3573b2e53 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product.php @@ -207,7 +207,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity ValidatorInterface::ERROR_INVALID_SCOPE => 'Invalid value in Scope column', ValidatorInterface::ERROR_INVALID_WEBSITE => 'Invalid value in Website column (website does not exists?)', ValidatorInterface::ERROR_INVALID_STORE => 'Invalid value in Store column (store doesn\'t exist?)', - ValidatorInterface::ERROR_INVALID_ATTR_SET => 'Invalid value for Product Template column (set doesn\'t exist?)', + ValidatorInterface::ERROR_INVALID_ATTR_SET => 'Invalid value for Attribute Set column (set doesn\'t exist?)', ValidatorInterface::ERROR_INVALID_TYPE => 'Product Type is invalid or not supported', ValidatorInterface::ERROR_INVALID_CATEGORY => 'Category does not exists', ValidatorInterface::ERROR_VALUE_IS_REQUIRED => 'Please make sure attribute "%s" is not empty.', @@ -217,7 +217,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity ValidatorInterface::ERROR_CHANGE_TYPE => 'Product type change is not allowed', ValidatorInterface::ERROR_DUPLICATE_SCOPE => 'Duplicate scope', ValidatorInterface::ERROR_DUPLICATE_SKU => 'Duplicate SKU', - ValidatorInterface::ERROR_CHANGE_ATTR_SET => 'Product template change is not allowed', + ValidatorInterface::ERROR_CHANGE_ATTR_SET => 'Attribute set change is not allowed', ValidatorInterface::ERROR_TYPE_UNSUPPORTED => 'Product type is not supported', ValidatorInterface::ERROR_ROW_IS_ORPHAN => 'Orphan rows that will be skipped due default row errors', ValidatorInterface::ERROR_INVALID_TIER_PRICE_QTY => 'Tier Price data price or quantity value is invalid', diff --git a/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Filter/Preprocessor.php b/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Filter/Preprocessor.php index 98aa6bb7e710ab1492fff90a66ae24dd7f5391ea..e692ea59d2d6ef1b97ea0b81a6458c8773907cf4 100644 --- a/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Filter/Preprocessor.php +++ b/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Filter/Preprocessor.php @@ -6,6 +6,7 @@ namespace Magento\CatalogSearch\Model\Adapter\Mysql\Filter; use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\ResourceModel\Eav\Attribute; use Magento\CatalogSearch\Model\Search\TableMapper; use Magento\Eav\Model\Config; use Magento\Framework\App\ResourceConnection; @@ -97,7 +98,7 @@ class Preprocessor implements PreprocessorInterface */ private function processQueryWithField(FilterInterface $filter, $isNegation, $query) { - /** @var \Magento\Catalog\Model\ResourceModel\Eav\Attribute $attribute */ + /** @var Attribute $attribute */ $attribute = $this->config->getAttribute(Product::ENTITY, $filter->getField()); if ($filter->getField() === 'price') { $resultQuery = str_replace( @@ -114,24 +115,16 @@ class Preprocessor implements PreprocessorInterface $this->connection->quoteIdentifier($alias . '.' . $attribute->getAttributeCode()), $query ); - } elseif ($filter->getType() === FilterInterface::TYPE_TERM - && in_array($attribute->getFrontendInput(), ['select', 'multiselect'], true) + } elseif ( + $filter->getType() === FilterInterface::TYPE_TERM && + in_array($attribute->getFrontendInput(), ['select', 'multiselect'], true) ) { - $alias = $this->tableMapper->getMappingAlias($filter); - if (is_array($filter->getValue())) { - $value = sprintf( - '%s IN (%s)', - ($isNegation ? 'NOT' : ''), - implode(',', $filter->getValue()) - ); - } else { - $value = ($isNegation ? '!' : '') . '= ' . $filter->getValue(); - } - $resultQuery = sprintf( - '%1$s.value %2$s', - $alias, - $value - ); + $resultQuery = $this->processTermSelect($filter, $isNegation); + } elseif ( + $filter->getType() === FilterInterface::TYPE_RANGE && + in_array($attribute->getBackendType(), ['decimal', 'int'], true) + ) { + $resultQuery = $this->processRangeNumeric($filter, $query, $attribute); } else { $table = $attribute->getBackendTable(); $select = $this->connection->select(); @@ -161,4 +154,57 @@ class Preprocessor implements PreprocessorInterface return $resultQuery; } + + /** + * @param FilterInterface $filter + * @param string $query + * @param Attribute $attribute + * @return string + */ + private function processRangeNumeric(FilterInterface $filter, $query, $attribute) + { + $tableSuffix = $attribute->getBackendType() === 'decimal' ? '_decimal' : ''; + $table = $this->resource->getTableName("catalog_product_index_eav{$tableSuffix}"); + $select = $this->connection->select(); + + $currentStoreId = $this->scopeResolver->getScope()->getId(); + + $select->from(['main_table' => $table], 'entity_id') + ->columns([$filter->getField() => 'main_table.value']) + ->where('main_table.attribute_id = ?', $attribute->getAttributeId()) + ->where('main_table.store_id = ?', $currentStoreId) + ->having($query); + + $resultQuery = 'search_index.entity_id IN ( + select entity_id from ' . $this->conditionManager->wrapBrackets($select) . ' as filter + )'; + + return $resultQuery; + } + + /** + * @param FilterInterface $filter + * @param bool $isNegation + * @return string + */ + private function processTermSelect(FilterInterface $filter, $isNegation) + { + $alias = $this->tableMapper->getMappingAlias($filter); + if (is_array($filter->getValue())) { + $value = sprintf( + '%s IN (%s)', + ($isNegation ? 'NOT' : ''), + implode(',', $filter->getValue()) + ); + } else { + $value = ($isNegation ? '!' : '') . '= ' . $filter->getValue(); + } + $resultQuery = sprintf( + '%1$s.value %2$s', + $alias, + $value + ); + + return $resultQuery; + } } diff --git a/app/code/Magento/CatalogUrlRewrite/Observer/ProductToWebsiteChangeObserver.php b/app/code/Magento/CatalogUrlRewrite/Observer/ProductToWebsiteChangeObserver.php new file mode 100644 index 0000000000000000000000000000000000000000..cd094719838136b954de00b78e411e0ee7148461 --- /dev/null +++ b/app/code/Magento/CatalogUrlRewrite/Observer/ProductToWebsiteChangeObserver.php @@ -0,0 +1,78 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\CatalogUrlRewrite\Observer; + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\CatalogUrlRewrite\Model\ProductUrlRewriteGenerator; +use Magento\Framework\App\RequestInterface; +use Magento\Framework\Event\ObserverInterface; +use Magento\Store\Model\Store; +use Magento\UrlRewrite\Model\UrlPersistInterface; +use Magento\UrlRewrite\Service\V1\Data\UrlRewrite; + +class ProductToWebsiteChangeObserver implements ObserverInterface +{ + /** + * @var ProductUrlRewriteGenerator + */ + protected $productUrlRewriteGenerator; + + /** + * @var UrlPersistInterface + */ + protected $urlPersist; + + /** + * @var ProductRepositoryInterface + */ + protected $productRepository; + + /** + * @var RequestInterface + */ + protected $request; + + /** + * @param ProductUrlRewriteGenerator $productUrlRewriteGenerator + * @param UrlPersistInterface $urlPersist + * @param ProductRepositoryInterface $productRepository + * @param RequestInterface $request + */ + public function __construct( + ProductUrlRewriteGenerator $productUrlRewriteGenerator, + UrlPersistInterface $urlPersist, + ProductRepositoryInterface $productRepository, + RequestInterface $request + ) { + $this->productUrlRewriteGenerator = $productUrlRewriteGenerator; + $this->urlPersist = $urlPersist; + $this->productRepository = $productRepository; + $this->request = $request; + } + + /** + * Generate urls for UrlRewrite and save it in storage + * + * @param \Magento\Framework\Event\Observer $observer + * @return void + */ + public function execute(\Magento\Framework\Event\Observer $observer) + { + foreach ($observer->getEvent()->getProducts() as $productId) { + $product = $this->productRepository->getById( + $productId, + false, + $this->request->getParam('store_id', Store::DEFAULT_STORE_ID) + ); + + $this->urlPersist->deleteByData([ + UrlRewrite::ENTITY_ID => $product->getId(), + UrlRewrite::ENTITY_TYPE => ProductUrlRewriteGenerator::ENTITY_TYPE, + ]); + $this->urlPersist->replace($this->productUrlRewriteGenerator->generate($product)); + } + } +} diff --git a/app/code/Magento/CatalogUrlRewrite/etc/adminhtml/events.xml b/app/code/Magento/CatalogUrlRewrite/etc/adminhtml/events.xml index 194b45d59a41ab1754da85805935bb7d82e968ea..477a6cf338b1ba397c3559533c8957c617519017 100644 --- a/app/code/Magento/CatalogUrlRewrite/etc/adminhtml/events.xml +++ b/app/code/Magento/CatalogUrlRewrite/etc/adminhtml/events.xml @@ -27,4 +27,7 @@ <event name="catalog_category_move_after"> <observer name="process_url_rewrite_moving" instance="Magento\CatalogUrlRewrite\Observer\CategoryProcessUrlRewriteMovingObserver"/> </event> + <event name="catalog_product_to_website_change"> + <observer name="catalog_product_to_website_change" instance="Magento\CatalogUrlRewrite\Observer\ProductToWebsiteChangeObserver"/> + </event> </config> diff --git a/app/code/Magento/Checkout/Block/Onepage.php b/app/code/Magento/Checkout/Block/Onepage.php index d298599319540e5cbdf5143567e4e04fda46246b..25cbb6081959d727fd6415fec3896657846faf93 100644 --- a/app/code/Magento/Checkout/Block/Onepage.php +++ b/app/code/Magento/Checkout/Block/Onepage.php @@ -5,15 +5,11 @@ */ namespace Magento\Checkout\Block; -use Magento\Checkout\Block\Checkout\LayoutProcessorInterface; -use Magento\Customer\Api\CustomerRepositoryInterface; -use Magento\Customer\Model\Address\Config as AddressConfig; - /** * Onepage checkout block * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class Onepage extends \Magento\Checkout\Block\Onepage\AbstractOnepage +class Onepage extends \Magento\Framework\View\Element\Template { /** * @var \Magento\Framework\Data\Form\FormKey @@ -36,60 +32,25 @@ class Onepage extends \Magento\Checkout\Block\Onepage\AbstractOnepage protected $configProvider; /** - * @var array|Checkout\LayoutProcessorInterface[] + * @var array|\Magento\Checkout\Block\Checkout\LayoutProcessorInterface[] */ protected $layoutProcessors; /** * @param \Magento\Framework\View\Element\Template\Context $context - * @param \Magento\Directory\Helper\Data $directoryHelper - * @param \Magento\Framework\App\Cache\Type\Config $configCacheType - * @param \Magento\Customer\Model\Session $customerSession - * @param \Magento\Checkout\Model\Session $resourceSession - * @param \Magento\Directory\Model\ResourceModel\Country\CollectionFactory $countryCollectionFactory - * @param \Magento\Directory\Model\ResourceModel\Region\CollectionFactory $regionCollectionFactory - * @param CustomerRepositoryInterface $customerRepository - * @param AddressConfig $addressConfig - * @param \Magento\Framework\App\Http\Context $httpContext - * @param \Magento\Customer\Model\Address\Mapper $addressMapper * @param \Magento\Framework\Data\Form\FormKey $formKey * @param \Magento\Checkout\Model\CompositeConfigProvider $configProvider - * @param LayoutProcessorInterface[] $layoutProcessors + * @param array $layoutProcessors * @param array $data - * @codeCoverageIgnore - * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( \Magento\Framework\View\Element\Template\Context $context, - \Magento\Directory\Helper\Data $directoryHelper, - \Magento\Framework\App\Cache\Type\Config $configCacheType, - \Magento\Customer\Model\Session $customerSession, - \Magento\Checkout\Model\Session $resourceSession, - \Magento\Directory\Model\ResourceModel\Country\CollectionFactory $countryCollectionFactory, - \Magento\Directory\Model\ResourceModel\Region\CollectionFactory $regionCollectionFactory, - CustomerRepositoryInterface $customerRepository, - AddressConfig $addressConfig, - \Magento\Framework\App\Http\Context $httpContext, - \Magento\Customer\Model\Address\Mapper $addressMapper, \Magento\Framework\Data\Form\FormKey $formKey, \Magento\Checkout\Model\CompositeConfigProvider $configProvider, array $layoutProcessors = [], array $data = [] ) { - parent::__construct( - $context, - $directoryHelper, - $configCacheType, - $customerSession, - $resourceSession, - $countryCollectionFactory, - $regionCollectionFactory, - $customerRepository, - $addressConfig, - $httpContext, - $addressMapper, - $data - ); + parent::__construct($context, $data); $this->formKey = $formKey; $this->_isScopePrivate = true; $this->jsLayout = isset($data['jsLayout']) && is_array($data['jsLayout']) ? $data['jsLayout'] : []; diff --git a/app/code/Magento/Checkout/Block/Onepage/AbstractOnepage.php b/app/code/Magento/Checkout/Block/Onepage/AbstractOnepage.php deleted file mode 100644 index 6b4e92640ec7090878068aed4f6f6be55afee980..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/Block/Onepage/AbstractOnepage.php +++ /dev/null @@ -1,391 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Checkout\Block\Onepage; - -use Magento\Customer\Api\CustomerRepositoryInterface; -use Magento\Customer\Model\Address\Config as AddressConfig; -use Magento\Directory\Model\ResourceModel\Country\Collection; -use Magento\Directory\Model\ResourceModel\Region\Collection as RegionCollection; -use Magento\Framework\Exception\NoSuchEntityException; -use Magento\Quote\Model\Quote; - -/** - * One page common functionality block - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - */ -abstract class AbstractOnepage extends \Magento\Framework\View\Element\Template -{ - /** - * @var \Magento\Framework\App\Cache\Type\Config - */ - protected $_configCacheType; - - /** - * @var \Magento\Customer\Api\Data\CustomerInterface - */ - protected $_customer; - - /** - * @var Quote - */ - protected $_quote; - - /** - * @var Collection - */ - protected $_countryCollection; - - /** - * @var RegionCollection - */ - protected $_regionCollection; - - /** - * @var mixed - */ - protected $_addressesCollection; - - /** - * @var \Magento\Checkout\Model\Session - */ - protected $_checkoutSession; - - /** - * @var \Magento\Directory\Model\ResourceModel\Region\CollectionFactory - */ - protected $_regionCollectionFactory; - - /** - * @var \Magento\Directory\Model\ResourceModel\Country\CollectionFactory - */ - protected $_countryCollectionFactory; - - /** - * @var \Magento\Directory\Helper\Data - */ - protected $directoryHelper; - - /** - * @var CustomerRepositoryInterface - */ - protected $customerRepository; - - /** - * @var \Magento\Customer\Model\Address\Config - */ - private $_addressConfig; - - /** - * @var \Magento\Framework\App\Http\Context - */ - protected $httpContext; - - /** - * @var \Magento\Customer\Model\Address\Mapper - */ - protected $addressMapper; - - /** - * @param \Magento\Framework\View\Element\Template\Context $context - * @param \Magento\Directory\Helper\Data $directoryHelper - * @param \Magento\Framework\App\Cache\Type\Config $configCacheType - * @param \Magento\Customer\Model\Session $customerSession - * @param \Magento\Checkout\Model\Session $resourceSession - * @param \Magento\Directory\Model\ResourceModel\Country\CollectionFactory $countryCollectionFactory - * @param \Magento\Directory\Model\ResourceModel\Region\CollectionFactory $regionCollectionFactory - * @param CustomerRepositoryInterface $customerRepository - * @param AddressConfig $addressConfig - * @param \Magento\Framework\App\Http\Context $httpContext - * @param \Magento\Customer\Model\Address\Mapper $addressMapper - * @param array $data - * @SuppressWarnings(PHPMD.ExcessiveParameterList) - */ - public function __construct( - \Magento\Framework\View\Element\Template\Context $context, - \Magento\Directory\Helper\Data $directoryHelper, - \Magento\Framework\App\Cache\Type\Config $configCacheType, - \Magento\Customer\Model\Session $customerSession, - \Magento\Checkout\Model\Session $resourceSession, - \Magento\Directory\Model\ResourceModel\Country\CollectionFactory $countryCollectionFactory, - \Magento\Directory\Model\ResourceModel\Region\CollectionFactory $regionCollectionFactory, - CustomerRepositoryInterface $customerRepository, - AddressConfig $addressConfig, - \Magento\Framework\App\Http\Context $httpContext, - \Magento\Customer\Model\Address\Mapper $addressMapper, - array $data = [] - ) { - $this->directoryHelper = $directoryHelper; - $this->_configCacheType = $configCacheType; - $this->_customerSession = $customerSession; - $this->_checkoutSession = $resourceSession; - $this->_countryCollectionFactory = $countryCollectionFactory; - $this->_regionCollectionFactory = $regionCollectionFactory; - $this->httpContext = $httpContext; - parent::__construct($context, $data); - $this->_isScopePrivate = true; - $this->customerRepository = $customerRepository; - $this->_addressConfig = $addressConfig; - $this->addressMapper = $addressMapper; - } - - /** - * Get config - * - * @param string $path - * @return string|null - */ - public function getConfig($path) - { - return $this->_scopeConfig->getValue($path, \Magento\Store\Model\ScopeInterface::SCOPE_STORE); - } - - /** - * Get logged in customer - * - * @return \Magento\Customer\Api\Data\CustomerInterface - */ - protected function _getCustomer() - { - if (empty($this->_customer)) { - $this->_customer = $this->customerRepository->getById($this->_customerSession->getCustomerId()); - } - return $this->_customer; - } - - /** - * Retrieve checkout session model - * - * @return \Magento\Checkout\Model\Session - */ - public function getCheckout() - { - return $this->_checkoutSession; - } - - /** - * Retrieve sales quote model - * - * @return Quote - */ - public function getQuote() - { - if (empty($this->_quote)) { - $this->_quote = $this->getCheckout()->getQuote(); - } - return $this->_quote; - } - - /** - * @return bool - */ - public function isCustomerLoggedIn() - { - return $this->httpContext->getValue(\Magento\Customer\Model\Context::CONTEXT_AUTH); - } - - /** - * @return Collection - * @removeCandidate - */ - public function getCountryCollection() - { - if (!$this->_countryCollection) { - $this->_countryCollection = $this->_countryCollectionFactory->create()->loadByStore(); - } - return $this->_countryCollection; - } - - /** - * @return RegionCollection - * @removeCandidate - */ - public function getRegionCollection() - { - if (!$this->_regionCollection) { - $this->_regionCollection = $this->_regionCollectionFactory->create()->addCountryFilter( - $this->getAddress()->getCountryId() - )->load(); - } - return $this->_regionCollection; - } - - /** - * @return int - * @removeCandidate - */ - public function customerHasAddresses() - { - try { - return count($this->_getCustomer()->getAddresses()); - } catch (NoSuchEntityException $e) { - return 0; - } - } - - /** - * @param string $type - * @return string - * @removeCandidate - */ - public function getAddressesHtmlSelect($type) - { - if ($this->isCustomerLoggedIn()) { - $options = []; - - try { - $addresses = $this->_getCustomer()->getAddresses(); - } catch (NoSuchEntityException $e) { - $addresses = []; - } - - foreach ($addresses as $address) { - $builtOutputAddressData = $this->addressMapper->toFlatArray($address); - $label = $this->_addressConfig - ->getFormatByCode(AddressConfig::DEFAULT_ADDRESS_FORMAT) - ->getRenderer() - ->renderArray($builtOutputAddressData); - - $options[] = ['value' => $address->getId(), 'label' => $label]; - } - - $addressId = $this->getAddress()->getCustomerAddressId(); - if (empty($addressId)) { - try { - if ($type == 'billing') { - $addressId = $this->_getCustomer()->getDefaultBilling(); - } else { - $addressId = $this->_getCustomer()->getDefaultShipping(); - } - } catch (NoSuchEntityException $e) { - // Do nothing - } - } - - $select = $this->getLayout()->createBlock('Magento\Framework\View\Element\Html\Select') - ->setName($type . '_address_id') - ->setId($type . ':address-select') - ->setClass('address-select') - ->setValue($addressId) - ->setOptions($options); - - $select->addOption('', __('New Address')); - - return $select->getHtml(); - } - return ''; - } - - /** - * @param string $type - * @return string - * @removeCandidate - */ - public function getCountryHtmlSelect($type) - { - $countryId = $this->getAddress()->getCountryId(); - if ($countryId === null) { - $countryId = $this->directoryHelper->getDefaultCountry(); - } - $select = $this->getLayout()->createBlock( - 'Magento\Framework\View\Element\Html\Select' - )->setName( - $type . '[country_id]' - )->setId( - $type . ':country_id' - )->setTitle( - __('Country') - )->setClass( - 'validate-select' - )->setValue( - $countryId - )->setOptions( - $this->getCountryOptions() - ); - return $select->getHtml(); - } - - /** - * @param string $type - * @return string - * @removeCandidate - */ - public function getRegionHtmlSelect($type) - { - $select = $this->getLayout()->createBlock( - 'Magento\Framework\View\Element\Html\Select' - )->setName( - $type . '[region]' - )->setId( - $type . ':region' - )->setTitle( - __('State/Province') - )->setClass( - 'required-entry validate-state' - )->setValue( - $this->getAddress()->getRegionId() - )->setOptions( - $this->getRegionCollection()->toOptionArray() - ); - - return $select->getHtml(); - } - - /** - * @return mixed - * @removeCandidate - */ - public function getCountryOptions() - { - $options = false; - $cacheId = 'DIRECTORY_COUNTRY_SELECT_STORE_' . $this->_storeManager->getStore()->getCode(); - if ($optionsCache = $this->_configCacheType->load($cacheId)) { - $options = unserialize($optionsCache); - } - - if ($options == false) { - $options = $this->getCountryCollection()->toOptionArray(); - $this->_configCacheType->save(serialize($options), $cacheId); - } - return $options; - } - - /** - * Get checkout steps codes - * - * @return string[] - * @removeCandidate - */ - protected function _getStepCodes() - { - return ['login', 'billing', 'shipping', 'shipping_method', 'payment', 'review']; - } - - /** - * Retrieve is allow and show block - * - * @return bool - * @removeCandidate - */ - public function isShow() - { - return true; - } - - /** - * Return the html text for shipping price - * - * @param \Magento\Quote\Model\Quote\Address\Rate $rate - * @return string - * @removeCandidate - */ - public function getShippingPriceHtml(\Magento\Quote\Model\Quote\Address\Rate $rate) - { - /** @var \Magento\Checkout\Block\Shipping\Price $block */ - $block = $this->getLayout()->getBlock('checkout.shipping.price'); - $block->setShippingRate($rate); - return $block->toHtml(); - } -} diff --git a/app/code/Magento/Checkout/Block/Onepage/Billing.php b/app/code/Magento/Checkout/Block/Onepage/Billing.php deleted file mode 100644 index 1aee1948f0f3518fd9480e9e2992db5fca543824..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/Block/Onepage/Billing.php +++ /dev/null @@ -1,235 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Checkout\Block\Onepage; - -use Magento\Customer\Api\CustomerRepositoryInterface; -use Magento\Customer\Model\Address\Config as AddressConfig; - -/** - * One page checkout status - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - * @removeCandidate - */ -class Billing extends \Magento\Checkout\Block\Onepage\AbstractOnepage -{ - /** - * Sales Quote Billing Address instance - * - * @var \Magento\Quote\Model\Quote\Address - */ - protected $_address; - - /** - * Customer Taxvat Widget block - * - * @var \Magento\Customer\Block\Widget\Taxvat - */ - protected $_taxvat; - - /** - * @var \Magento\Quote\Model\Quote\AddressFactory - */ - protected $_addressFactory; - - /** - * @param \Magento\Framework\View\Element\Template\Context $context - * @param \Magento\Directory\Helper\Data $directoryHelper - * @param \Magento\Framework\App\Cache\Type\Config $configCacheType - * @param \Magento\Customer\Model\Session $customerSession - * @param \Magento\Checkout\Model\Session $resourceSession - * @param \Magento\Directory\Model\ResourceModel\Country\CollectionFactory $countryCollectionFactory - * @param \Magento\Directory\Model\ResourceModel\Region\CollectionFactory $regionCollectionFactory - * @param CustomerRepositoryInterface $customerRepository - * @param AddressConfig $addressConfig - * @param \Magento\Framework\App\Http\Context $httpContext - * @param \Magento\Customer\Model\Address\Mapper $addressMapper - * @param \Magento\Quote\Model\Quote\AddressFactory $addressFactory - * @param array $data - * @SuppressWarnings(PHPMD.ExcessiveParameterList) - */ - public function __construct( - \Magento\Framework\View\Element\Template\Context $context, - \Magento\Directory\Helper\Data $directoryHelper, - \Magento\Framework\App\Cache\Type\Config $configCacheType, - \Magento\Customer\Model\Session $customerSession, - \Magento\Checkout\Model\Session $resourceSession, - \Magento\Directory\Model\ResourceModel\Country\CollectionFactory $countryCollectionFactory, - \Magento\Directory\Model\ResourceModel\Region\CollectionFactory $regionCollectionFactory, - CustomerRepositoryInterface $customerRepository, - AddressConfig $addressConfig, - \Magento\Framework\App\Http\Context $httpContext, - \Magento\Customer\Model\Address\Mapper $addressMapper, - \Magento\Quote\Model\Quote\AddressFactory $addressFactory, - array $data = [] - ) { - $this->_addressFactory = $addressFactory; - parent::__construct( - $context, - $directoryHelper, - $configCacheType, - $customerSession, - $resourceSession, - $countryCollectionFactory, - $regionCollectionFactory, - $customerRepository, - $addressConfig, - $httpContext, - $addressMapper, - $data - ); - $this->_isScopePrivate = true; - } - - /** - * Initialize billing address step - * - * @return void - */ - protected function _construct() - { - $this->getCheckout()->setStepData( - 'billing', - ['label' => __('Billing Information'), 'is_show' => $this->isShow()] - ); - - if ($this->isCustomerLoggedIn()) { - $this->getCheckout()->setStepData('billing', 'allow', true); - } - parent::_construct(); - } - - /** - * @return bool - */ - public function isUseBillingAddressForShipping() - { - if ($this->getQuote()->getIsVirtual() || !$this->getQuote()->getShippingAddress()->getSameAsBilling()) { - return false; - } - return true; - } - - /** - * Return country collection - * - * @return \Magento\Directory\Model\ResourceModel\Country\Collection - */ - public function getCountries() - { - return $this->_countryCollectionFactory->create()->loadByStore(); - } - - /** - * Return checkout method - * - * @return string - */ - public function getMethod() - { - return $this->getQuote()->getCheckoutMethod(); - } - - /** - * Return Sales Quote Address model - * - * @return \Magento\Quote\Model\Quote\Address - */ - public function getAddress() - { - if ($this->_address === null) { - if ($this->isCustomerLoggedIn()) { - $this->_address = $this->getQuote()->getBillingAddress(); - if (!$this->_address->getFirstname()) { - $this->_address->setFirstname($this->getQuote()->getCustomer()->getFirstname()); - } - if (!$this->_address->getLastname()) { - $this->_address->setLastname($this->getQuote()->getCustomer()->getLastname()); - } - } else { - $this->_address = $this->_addressFactory->create(); - } - } - - return $this->_address; - } - - /** - * Return Customer Address First Name - * If Sales Quote Address First Name is not defined - return Customer First Name - * - * @return string - */ - public function getFirstname() - { - return $this->getAddress()->getFirstname(); - } - - /** - * Return Customer Address Last Name - * If Sales Quote Address Last Name is not defined - return Customer Last Name - * - * @return string - */ - public function getLastname() - { - return $this->getAddress()->getLastname(); - } - - /** - * Check is Quote items can ship to - * - * @return bool - */ - public function canShip() - { - return !$this->getQuote()->isVirtual(); - } - - /** - * @return void - */ - public function getSaveUrl() - { - } - - /** - * Get Customer Taxvat Widget block - * - * @return \Magento\Customer\Block\Widget\Taxvat - */ - protected function _getTaxvat() - { - if (!$this->_taxvat) { - $this->_taxvat = $this->getLayout()->createBlock('Magento\Customer\Block\Widget\Taxvat'); - } - - return $this->_taxvat; - } - - /** - * Check whether taxvat is enabled - * - * @return bool - */ - public function isTaxvatEnabled() - { - return $this->_getTaxvat()->isEnabled(); - } - - /** - * @return string - */ - public function getTaxvatHtml() - { - return $this->_getTaxvat()->setTaxvat( - $this->getQuote()->getCustomerTaxvat() - )->setFieldIdFormat( - 'billing:%s' - )->setFieldNameFormat( - 'billing[%s]' - )->toHtml(); - } -} diff --git a/app/code/Magento/Checkout/Block/Onepage/Payment.php b/app/code/Magento/Checkout/Block/Onepage/Payment.php deleted file mode 100644 index 4298784226ae932e3c74dea26f35d79cf082b1eb..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/Block/Onepage/Payment.php +++ /dev/null @@ -1,69 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Checkout\Block\Onepage; - -/** - * One page checkout status - * - * @author Magento Core Team <core@magentocommerce.com> - * @removeCandidate - */ -class Payment extends \Magento\Checkout\Block\Onepage\AbstractOnepage -{ - /** - * @return void - */ - protected function _construct() - { - $this->getCheckout()->setStepData( - 'payment', - ['label' => __('Payment Information'), 'is_show' => $this->isShow()] - ); - parent::_construct(); - } - - /** - * Getter - * - * @return float - */ - public function getQuoteBaseGrandTotal() - { - return (double)$this->getQuote()->getBaseGrandTotal(); - } - - /** - * Get options - * - * @return array - */ - public function getOptions() - { - $registerParam = $this->getRequest()->getParam('register'); - return [ - 'quoteBaseGrandTotal' => $this->getQuoteBaseGrandTotal(), - 'progressUrl' => $this->getUrl('checkout/onepage/progress'), - 'reviewUrl' => $this->getUrl('checkout/onepage/review'), - 'failureUrl' => $this->getUrl('checkout/cart'), - 'getAddressUrl' => $this->getUrl('checkout/onepage/getAddress') . 'address/', - 'checkout' => [ - 'suggestRegistration' => $registerParam || $registerParam === '', - 'saveUrl' => $this->getUrl('checkout/onepage/saveMethod'), - ], - 'billing' => ['saveUrl' => $this->getUrl('checkout/onepage/saveBilling')], - 'shipping' => ['saveUrl' => $this->getUrl('checkout/onepage/saveShipping')], - 'shippingMethod' => ['saveUrl' => $this->getUrl('checkout/onepage/saveShippingMethod')], - 'payment' => [ - 'defaultPaymentMethod' => $this->getChildBlock('methods')->getSelectedMethodCode(), - 'saveUrl' => $this->getUrl('checkout/onepage/savePayment'), - ], - 'review' => [ - 'saveUrl' => $this->getUrl('checkout/onepage/saveOrder'), - 'successUrl' => $this->getUrl('checkout/onepage/success'), - ] - ]; - } -} diff --git a/app/code/Magento/Checkout/Block/Onepage/Payment/Info.php b/app/code/Magento/Checkout/Block/Onepage/Payment/Info.php deleted file mode 100644 index 67f682a25c19d95c37798e534a75376a8f7c2b49..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/Block/Onepage/Payment/Info.php +++ /dev/null @@ -1,63 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Checkout\Block\Onepage\Payment; - -/** - * Checkout payment information data - * - * @author Magento Core Team <core@magentocommerce.com> - * @removeCandidate - */ -class Info extends \Magento\Payment\Block\Info\AbstractContainer -{ - /** - * @var \Magento\Checkout\Model\Session - */ - protected $_checkoutSession; - - /** - * @param \Magento\Framework\View\Element\Template\Context $context - * @param \Magento\Payment\Helper\Data $paymentData - * @param \Magento\Checkout\Model\Session $checkoutSession - * @param array $data - */ - public function __construct( - \Magento\Framework\View\Element\Template\Context $context, - \Magento\Payment\Helper\Data $paymentData, - \Magento\Checkout\Model\Session $checkoutSession, - array $data = [] - ) { - $this->_checkoutSession = $checkoutSession; - parent::__construct($context, $paymentData, $data); - $this->_isScopePrivate = true; - } - - /** - * Retrieve payment info model - * - * @return \Magento\Payment\Model\Info|false - */ - public function getPaymentInfo() - { - $info = $this->_checkoutSession->getQuote()->getPayment(); - if ($info->getMethod()) { - return $info; - } - return false; - } - - /** - * @return string - */ - protected function _toHtml() - { - $html = ''; - if ($block = $this->getChildBlock($this->_getInfoBlockName())) { - $html = $block->toHtml(); - } - return $html; - } -} diff --git a/app/code/Magento/Checkout/Block/Onepage/Payment/Methods.php b/app/code/Magento/Checkout/Block/Onepage/Payment/Methods.php deleted file mode 100644 index 48285ad73dc277fa9890d46e7fa758246d5865e0..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/Block/Onepage/Payment/Methods.php +++ /dev/null @@ -1,113 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -/** - * One page checkout status - * - * @author Magento Core Team <core@magentocommerce.com> - * @removeCandidate - */ -namespace Magento\Checkout\Block\Onepage\Payment; - -class Methods extends \Magento\Payment\Block\Form\Container -{ - /** - * @var \Magento\Checkout\Model\Session - */ - protected $_checkoutSession; - - /** - * @param \Magento\Framework\View\Element\Template\Context $context - * @param \Magento\Payment\Helper\Data $paymentHelper - * @param \Magento\Payment\Model\Checks\SpecificationFactory $methodSpecificationFactory - * @param \Magento\Checkout\Model\Session $checkoutSession - * @param array $data - */ - public function __construct( - \Magento\Framework\View\Element\Template\Context $context, - \Magento\Payment\Helper\Data $paymentHelper, - \Magento\Payment\Model\Checks\SpecificationFactory $methodSpecificationFactory, - \Magento\Checkout\Model\Session $checkoutSession, - array $data = [] - ) { - $this->_checkoutSession = $checkoutSession; - parent::__construct($context, $paymentHelper, $methodSpecificationFactory, $data); - $this->_isScopePrivate = true; - } - - /** - * @return \Magento\Quote\Model\Quote - */ - public function getQuote() - { - return $this->_checkoutSession->getQuote(); - } - - /** - * Check payment method model - * - * @param \Magento\Payment\Model\MethodInterface $method - * @return bool - */ - protected function _canUseMethod($method) - { - return $method && $method->canUseCheckout() && parent::_canUseMethod($method); - } - - /** - * Retrieve code of current payment method - * - * @return mixed - */ - public function getSelectedMethodCode() - { - $method = $this->getQuote()->getPayment()->getMethod(); - if ($method) { - return $method; - } - return false; - } - - /** - * Payment method form html getter - * - * @param \Magento\Payment\Model\MethodInterface $method - * @return string - */ - public function getPaymentMethodFormHtml(\Magento\Payment\Model\MethodInterface $method) - { - return $this->getChildHtml('payment.method.' . $method->getCode()); - } - - /** - * Return method title for payment selection page - * - * @param \Magento\Payment\Model\MethodInterface $method - * @return string - */ - public function getMethodTitle(\Magento\Payment\Model\MethodInterface $method) - { - $form = $this->getChildBlock('payment.method.' . $method->getCode()); - if ($form && $form->hasMethodTitle()) { - return $form->getMethodTitle(); - } - return $method->getTitle(); - } - - /** - * Payment method additional label part getter - * - * @param \Magento\Payment\Model\MethodInterface $method - * @return string - */ - public function getMethodLabelAfterHtml(\Magento\Payment\Model\MethodInterface $method) - { - $form = $this->getChildBlock('payment.method.' . $method->getCode()); - if ($form) { - return $form->getMethodLabelAfterHtml(); - } - } -} diff --git a/app/code/Magento/Checkout/Block/Onepage/Review/Button.php b/app/code/Magento/Checkout/Block/Onepage/Review/Button.php deleted file mode 100644 index 39cba9ffce7470f1f0508fc8503fed741cf84341..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/Block/Onepage/Review/Button.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Checkout\Block\Onepage\Review; - -use Magento\Framework\View\Element\Template; - -/** - * One page checkout order review button - * @removeCandidate - */ -class Button extends Template -{ - /** - * {@inheritdoc} - * - * @param string $template - * @return $this - */ - public function setTemplate($template) - { - if (!empty($template)) { - parent::setTemplate($template); - } - return $this; - } -} diff --git a/app/code/Magento/Checkout/Block/Onepage/Review/Info.php b/app/code/Magento/Checkout/Block/Onepage/Review/Info.php deleted file mode 100644 index 9adbc1c4e5ed140507e0c613ae8bd66c13ea7b6b..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/Block/Onepage/Review/Info.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Checkout\Block\Onepage\Review; - -/** - * One page checkout order review - * @removeCandidate - */ -class Info extends \Magento\Sales\Block\Items\AbstractItems -{ - /** - * @var \Magento\Checkout\Model\Session - */ - protected $_checkoutSession; - - /** - * @param \Magento\Framework\View\Element\Template\Context $context - * @param \Magento\Checkout\Model\Session $checkoutSession - * @param array $data - */ - public function __construct( - \Magento\Framework\View\Element\Template\Context $context, - \Magento\Checkout\Model\Session $checkoutSession, - array $data = [] - ) { - $this->_checkoutSession = $checkoutSession; - parent::__construct($context, $data); - $this->_isScopePrivate = true; - } - - /** - * @return array - */ - public function getItems() - { - return $this->_checkoutSession->getQuote()->getAllVisibleItems(); - } - - /** - * @return array - */ - public function getTotals() - { - return $this->_checkoutSession->getQuote()->getTotals(); - } -} diff --git a/app/code/Magento/Checkout/Block/Onepage/Shipping.php b/app/code/Magento/Checkout/Block/Onepage/Shipping.php deleted file mode 100644 index d8dcad11e01c0e50a726c2f85e2f1a10165ac12c..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/Block/Onepage/Shipping.php +++ /dev/null @@ -1,131 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Checkout\Block\Onepage; - -use Magento\Customer\Api\CustomerRepositoryInterface; -use Magento\Customer\Model\Address\Config as AddressConfig; - -/** - * One page checkout status - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - * @removeCandidate - */ -class Shipping extends \Magento\Checkout\Block\Onepage\AbstractOnepage -{ - /** - * Sales Quote Shipping Address instance - * - * @var \Magento\Quote\Model\Quote\Address - */ - protected $_address = null; - - /** - * @var \Magento\Quote\Model\Quote\AddressFactory - */ - protected $_addressFactory; - - /** - * @param \Magento\Framework\View\Element\Template\Context $context - * @param \Magento\Directory\Helper\Data $directoryHelper - * @param \Magento\Framework\App\Cache\Type\Config $configCacheType - * @param \Magento\Customer\Model\Session $customerSession - * @param \Magento\Checkout\Model\Session $resourceSession - * @param \Magento\Directory\Model\ResourceModel\Country\CollectionFactory $countryCollectionFactory - * @param \Magento\Directory\Model\ResourceModel\Region\CollectionFactory $regionCollectionFactory - * @param CustomerRepositoryInterface $customerRepository - * @param AddressConfig $addressConfig - * @param \Magento\Framework\App\Http\Context $httpContext - * @param \Magento\Customer\Model\Address\Mapper $addressMapper - * @param \Magento\Quote\Model\Quote\AddressFactory $addressFactory - * @param array $data - * @SuppressWarnings(PHPMD.ExcessiveParameterList) - */ - public function __construct( - \Magento\Framework\View\Element\Template\Context $context, - \Magento\Directory\Helper\Data $directoryHelper, - \Magento\Framework\App\Cache\Type\Config $configCacheType, - \Magento\Customer\Model\Session $customerSession, - \Magento\Checkout\Model\Session $resourceSession, - \Magento\Directory\Model\ResourceModel\Country\CollectionFactory $countryCollectionFactory, - \Magento\Directory\Model\ResourceModel\Region\CollectionFactory $regionCollectionFactory, - CustomerRepositoryInterface $customerRepository, - AddressConfig $addressConfig, - \Magento\Framework\App\Http\Context $httpContext, - \Magento\Customer\Model\Address\Mapper $addressMapper, - \Magento\Quote\Model\Quote\AddressFactory $addressFactory, - array $data = [] - ) { - $this->_addressFactory = $addressFactory; - parent::__construct( - $context, - $directoryHelper, - $configCacheType, - $customerSession, - $resourceSession, - $countryCollectionFactory, - $regionCollectionFactory, - $customerRepository, - $addressConfig, - $httpContext, - $addressMapper, - $data - ); - $this->_isScopePrivate = true; - } - - /** - * Initialize shipping address step - * - * @return void - */ - protected function _construct() - { - $this->getCheckout()->setStepData( - 'shipping', - ['label' => __('Shipping Information'), 'is_show' => $this->isShow()] - ); - - parent::_construct(); - } - - /** - * Return checkout method - * - * @return string - */ - public function getMethod() - { - return $this->getQuote()->getCheckoutMethod(); - } - - /** - * Return Sales Quote Address model (shipping address) - * - * @return \Magento\Quote\Model\Quote\Address - */ - public function getAddress() - { - if ($this->_address === null) { - if ($this->isCustomerLoggedIn()) { - $this->_address = $this->getQuote()->getShippingAddress(); - } else { - $this->_address = $this->_addressFactory->create(); - } - } - - return $this->_address; - } - - /** - * Retrieve is allow and show block - * - * @return bool - */ - public function isShow() - { - return !$this->getQuote()->isVirtual(); - } -} diff --git a/app/code/Magento/Checkout/Block/Onepage/Shipping/Method.php b/app/code/Magento/Checkout/Block/Onepage/Shipping/Method.php deleted file mode 100644 index 5145d6fdca269a7613618b6b12f0dd979220e0e9..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/Block/Onepage/Shipping/Method.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Checkout\Block\Onepage\Shipping; - -/** - * One page checkout status - * - * @author Magento Core Team <core@magentocommerce.com> - * @removeCandidate - */ -class Method extends \Magento\Checkout\Block\Onepage\AbstractOnepage -{ - /** - * @return void - */ - protected function _construct() - { - $this->getCheckout()->setStepData( - 'shipping_method', - ['label' => __('Shipping Method'), 'is_show' => $this->isShow()] - ); - parent::_construct(); - } - - /** - * Retrieve is allow and show block - * - * @return bool - */ - public function isShow() - { - return !$this->getQuote()->isVirtual(); - } -} diff --git a/app/code/Magento/Checkout/Block/Onepage/Shipping/Method/Additional.php b/app/code/Magento/Checkout/Block/Onepage/Shipping/Method/Additional.php deleted file mode 100644 index bf27a8fa212086889f4b88616f84edb14f6307df..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/Block/Onepage/Shipping/Method/Additional.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Checkout\Block\Onepage\Shipping\Method; - -/** - * Block for additional information in shipping method - * - * @author Magento Core Team <core@magentocommerce.com> - * @removeCandidate - */ -class Additional extends \Magento\Checkout\Block\Onepage\AbstractOnepage -{ -} diff --git a/app/code/Magento/Checkout/Block/Onepage/Shipping/Method/Available.php b/app/code/Magento/Checkout/Block/Onepage/Shipping/Method/Available.php deleted file mode 100644 index 582beafbbb5f4710f9be6558cc1644cad16e8376..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/Block/Onepage/Shipping/Method/Available.php +++ /dev/null @@ -1,122 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Checkout\Block\Onepage\Shipping\Method; - -use Magento\Customer\Api\CustomerRepositoryInterface; -use Magento\Customer\Model\Address\Config as AddressConfig; -use Magento\Quote\Model\Quote\Address; - -/** - * One page checkout status - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - * @removeCandidate - */ -class Available extends \Magento\Checkout\Block\Onepage\AbstractOnepage -{ - /** - * @var array - */ - protected $_rates; - - /** - * @var Address - */ - protected $_address; - - /** - * @param \Magento\Framework\View\Element\Template\Context $context - * @param \Magento\Directory\Helper\Data $directoryHelper - * @param \Magento\Framework\App\Cache\Type\Config $configCacheType - * @param \Magento\Customer\Model\Session $customerSession - * @param \Magento\Checkout\Model\Session $resourceSession - * @param \Magento\Directory\Model\ResourceModel\Country\CollectionFactory $countryCollectionFactory - * @param \Magento\Directory\Model\ResourceModel\Region\CollectionFactory $regionCollectionFactory - * @param CustomerRepositoryInterface $customerRepository - * @param AddressConfig $addressConfig - * @param \Magento\Framework\App\Http\Context $httpContext - * @param \Magento\Customer\Model\Address\Mapper $addressMapper - * @param array $data - * @SuppressWarnings(PHPMD.ExcessiveParameterList) - */ - public function __construct( - \Magento\Framework\View\Element\Template\Context $context, - \Magento\Directory\Helper\Data $directoryHelper, - \Magento\Framework\App\Cache\Type\Config $configCacheType, - \Magento\Customer\Model\Session $customerSession, - \Magento\Checkout\Model\Session $resourceSession, - \Magento\Directory\Model\ResourceModel\Country\CollectionFactory $countryCollectionFactory, - \Magento\Directory\Model\ResourceModel\Region\CollectionFactory $regionCollectionFactory, - CustomerRepositoryInterface $customerRepository, - AddressConfig $addressConfig, - \Magento\Framework\App\Http\Context $httpContext, - \Magento\Customer\Model\Address\Mapper $addressMapper, - array $data = [] - ) { - parent::__construct( - $context, - $directoryHelper, - $configCacheType, - $customerSession, - $resourceSession, - $countryCollectionFactory, - $regionCollectionFactory, - $customerRepository, - $addressConfig, - $httpContext, - $addressMapper, - $data - ); - $this->_isScopePrivate = true; - } - - /** - * @return array - */ - public function getShippingRates() - { - if (empty($this->_rates)) { - $this->getAddress()->collectShippingRates()->save(); - $this->_rates = $this->getAddress()->getGroupedAllShippingRates(); - } - - return $this->_rates; - } - - /** - * @return Address - */ - public function getAddress() - { - if (empty($this->_address)) { - $this->_address = $this->getQuote()->getShippingAddress(); - } - return $this->_address; - } - - /** - * @param string $carrierCode - * @return string - */ - public function getCarrierName($carrierCode) - { - if ($name = $this->_scopeConfig->getValue( - 'carriers/' . $carrierCode . '/title', - \Magento\Store\Model\ScopeInterface::SCOPE_STORE - ) - ) { - return $name; - } - return $carrierCode; - } - - /** - * @return string - */ - public function getAddressShippingMethod() - { - return $this->getAddress()->getShippingMethod(); - } -} diff --git a/app/code/Magento/Checkout/Controller/Onepage/SaveOrder.php b/app/code/Magento/Checkout/Controller/Onepage/SaveOrder.php index 82e9d18b8854e5e2f0e51b131a2f4a84a496bb69..6c66fd165de554889cdbbd39b4b1f40608bb9983 100644 --- a/app/code/Magento/Checkout/Controller/Onepage/SaveOrder.php +++ b/app/code/Magento/Checkout/Controller/Onepage/SaveOrder.php @@ -8,9 +8,6 @@ namespace Magento\Checkout\Controller\Onepage; use Magento\Framework\DataObject; use Magento\Framework\Exception\PaymentException; -/** - * @removeCandidate - */ class SaveOrder extends \Magento\Checkout\Controller\Onepage { /** diff --git a/app/code/Magento/Checkout/Test/Unit/Block/OnepageTest.php b/app/code/Magento/Checkout/Test/Unit/Block/OnepageTest.php index e3ef9b58e827f6031b03c6678e8aeea99f0dd536..d29475962ef4dfe3b80b3b98f01f8ccb5983cd0e 100644 --- a/app/code/Magento/Checkout/Test/Unit/Block/OnepageTest.php +++ b/app/code/Magento/Checkout/Test/Unit/Block/OnepageTest.php @@ -35,13 +35,6 @@ class OnepageTest extends \PHPUnit_Framework_TestCase protected function setUp() { $contextMock = $this->getMock('\Magento\Framework\View\Element\Template\Context', [], [], '', false); - $directoryHelperMock = $this->getMock('\Magento\Directory\Helper\Data', [], [], '', false); - $configCacheTypeMock = $this->getMock('\Magento\Framework\App\Cache\Type\Config', [], [], '', false); - $customerSessionMock = $this->getMock('\Magento\Customer\Model\Session', [], [], '', false); - $resourceSessionMock = $this->getMock('\Magento\Checkout\Model\Session', [], [], '', false); - $addressConfigMock = $this->getMock('\Magento\Customer\Model\Address\Config', [], [], '', false); - $httpContextMock = $this->getMock('\Magento\Framework\App\Http\Context', [], [], '', false); - $addressMapperMock = $this->getMock('\Magento\Customer\Model\Address\Mapper', [], [], '', false); $this->formKeyMock = $this->getMock('\Magento\Framework\Data\Form\FormKey', [], [], '', false); $this->configProviderMock = $this->getMock( '\Magento\Checkout\Model\CompositeConfigProvider', @@ -50,27 +43,6 @@ class OnepageTest extends \PHPUnit_Framework_TestCase '', false ); - $countryCollectionFactoryMock = $this->getMock( - 'Magento\Directory\Model\ResourceModel\Country\CollectionFactory', - ['create'], - [], - '', - false - ); - $regionCollectionFactoryMock = $this->getMock( - 'Magento\Directory\Model\ResourceModel\Region\CollectionFactory', - ['create'], - [], - '', - false - ); - $customerRepositoryMock = $this->getMock( - '\Magento\Customer\Api\CustomerRepositoryInterface', - [], - [], - '', - false - ); $this->storeManagerMock = $this->getMock('\Magento\Store\Model\StoreManagerInterface', [], [], '', false); $contextMock->expects($this->once())->method('getStoreManager')->willReturn($this->storeManagerMock); @@ -84,16 +56,6 @@ class OnepageTest extends \PHPUnit_Framework_TestCase $this->model = new \Magento\Checkout\Block\Onepage( $contextMock, - $directoryHelperMock, - $configCacheTypeMock, - $customerSessionMock, - $resourceSessionMock, - $countryCollectionFactoryMock, - $regionCollectionFactoryMock, - $customerRepositoryMock, - $addressConfigMock, - $httpContextMock, - $addressMapperMock, $this->formKeyMock, $this->configProviderMock, [$this->layoutProcessorMock] diff --git a/app/code/Magento/Checkout/composer.json b/app/code/Magento/Checkout/composer.json index 775fe8406e930313ad64a49daf716d7792b60335..ca4d5b91da09dd595225d73f954bfefe0c0cfcac 100644 --- a/app/code/Magento/Checkout/composer.json +++ b/app/code/Magento/Checkout/composer.json @@ -15,7 +15,6 @@ "magento/module-tax": "1.0.0-beta", "magento/module-directory": "1.0.0-beta", "magento/module-eav": "1.0.0-beta", - "magento/module-gift-message": "1.0.0-beta", "magento/module-page-cache": "1.0.0-beta", "magento/module-sales-rule": "1.0.0-beta", "magento/module-theme": "1.0.0-beta", diff --git a/app/code/Magento/Checkout/view/frontend/requirejs-config.js b/app/code/Magento/Checkout/view/frontend/requirejs-config.js index e8a99235212544b2c3c7c219865cda4b7d3eab9c..a7055ed7d1558505ac1bf32b6c377d7b13f879f7 100644 --- a/app/code/Magento/Checkout/view/frontend/requirejs-config.js +++ b/app/code/Magento/Checkout/view/frontend/requirejs-config.js @@ -9,10 +9,7 @@ var config = { discountCode: 'Magento_Checkout/js/discount-codes', shoppingCart: 'Magento_Checkout/js/shopping-cart', regionUpdater: 'Magento_Checkout/js/region-updater', - opcOrderReview: 'Magento_Checkout/js/opc-order-review', - sidebar: 'Magento_Checkout/js/sidebar', - payment: 'Magento_Checkout/js/payment', - paymentAuthentication: 'Magento_Checkout/js/payment-authentication' + sidebar: 'Magento_Checkout/js/sidebar' } } }; diff --git a/app/code/Magento/Checkout/view/frontend/templates/onepage/billing.phtml b/app/code/Magento/Checkout/view/frontend/templates/onepage/billing.phtml deleted file mode 100644 index 49369053b5be56cb3ea02dee5726ba776aa1c40d..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/templates/onepage/billing.phtml +++ /dev/null @@ -1,214 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -// @codingStandardsIgnoreFile - -/** @var \Magento\Checkout\Block\Onepage\Billing $block */ -/** - * @removeCandidate - */ -?> -<form class="form billing" id="co-billing-form" data-hasrequired="<?php /* @escapeNotVerified */ echo __('* Required Fields') ?>"> - - <?php if ($block->customerHasAddresses()): ?> - <div class="field addresses"> - <label class="label" for="billing:address-select"><span><?php /* @escapeNotVerified */ echo __('Select a billing address from your address book or enter a new address.') ?></span></label> - <div class="control"> - <?php echo $block->getAddressesHtmlSelect('billing') ?> - </div> - </div> - <?php endif; ?> - <fieldset class="fieldset address" id="billing-new-address-form"<?php if ($block->customerHasAddresses()): ?> style="display:none;"<?php endif; ?>> - <input type="hidden" name="billing[address_id]" value="<?php /* @escapeNotVerified */ echo $block->getAddress()->getId() ?>" id="billing:address_id" /> - - <?php echo $block->getLayout()->createBlock('Magento\Customer\Block\Widget\Name')->setObject($block->getAddress()->getFirstname() ? $block->getAddress() : $block->getQuote()->getCustomer())->setForceUseCustomerRequiredAttributes(!$block->isCustomerLoggedIn())->setFieldIdFormat('billing:%s')->setFieldNameFormat('billing[%s]')->toHtml() ?> - - <?php if (!$block->isCustomerLoggedIn()): ?> - <div class="field required email"> - <label class="label" for="billing:email"><span><?php /* @escapeNotVerified */ echo __('Email') ?></span></label> - <div class="control"> - <input type="email" name="billing[email]" id="billing:email" value="<?php echo $block->escapeHtml($block->getAddress()->getEmail()) ?>" title="<?php /* @escapeNotVerified */ echo __('Email') ?>" class="input-text" data-validate="{required:true, 'validate-email':true}"/> - </div> - </div> - <?php endif; ?> - - <div class="field company"> - <label class="label" for="billing:company"><span><?php /* @escapeNotVerified */ echo __('Company') ?></span></label> - <div class="control"> - <input type="text" id="billing:company" name="billing[company]" value="<?php echo $block->escapeHtml($block->getAddress()->getCompany()) ?>" title="<?php /* @escapeNotVerified */ echo __('Company') ?>" class="input-text <?php /* @escapeNotVerified */ echo $this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('company') ?>" /> - </div> - </div> - - <?php if ($this->helper('Magento\Customer\Helper\Address')->isVatAttributeVisible()) : ?> - <div class="field taxvat"> - <label class="label" for="billing:vat_id"><span><?php /* @escapeNotVerified */ echo __('VAT Number') ?></span></label> - <div class="control"> - <input type="text" id="billing:vat_id" name="billing[vat_id]" value="<?php echo $block->escapeHtml($block->getAddress()->getVatId()) ?>" title="<?php /* @escapeNotVerified */ echo __('VAT Number') ?>" class="input-text <?php /* @escapeNotVerified */ echo $this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('vat_id') ?>" /> - </div> - </div> - <?php endif; ?> - - <?php $_streetValidationClass = $this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('street'); ?> - <div class="field street required"> - <label class="label" for="billing:street1"><span><?php /* @escapeNotVerified */ echo __('Address') ?></span></label> - <div class="control"> - <input type="text" title="<?php /* @escapeNotVerified */ echo __('Street Address') ?>" name="billing[street][]" id="billing:street1" value="<?php echo $block->escapeHtml($block->getAddress()->getStreetLine(1)) ?>" class="input-text <?php /* @escapeNotVerified */ echo $_streetValidationClass ?>" /> - <div class="nested"> - <?php $_streetValidationClass = trim(str_replace('required-entry', '', $_streetValidationClass)); ?> - <?php for ($_i = 2, $_n = $this->helper('Magento\Customer\Helper\Address')->getStreetLines(); $_i <= $_n; $_i++): ?> - <div class="field additional"> - <label class="label" for="billing:street<?php /* @escapeNotVerified */ echo $_i ?>"> - <span><?php /* @escapeNotVerified */ echo __('Address') ?></span> - </label> - <div class="control"> - <input type="text" title="<?php /* @escapeNotVerified */ echo __('Street Address %1', $_i) ?>" name="billing[street][]" id="billing:street<?php /* @escapeNotVerified */ echo $_i ?>" value="<?php echo $block->escapeHtml($block->getAddress()->getStreetLine($_i)) ?>" class="input-text <?php /* @escapeNotVerified */ echo $_streetValidationClass ?>" /> - </div> - </div> - <?php endfor; ?> - </div> - </div> - </div> - - - <div class="field city required"> - <label class="label" for="billing:city"><span><?php /* @escapeNotVerified */ echo __('City') ?></span></label> - <div class="control"> - <input type="text" title="<?php /* @escapeNotVerified */ echo __('City') ?>" name="billing[city]" value="<?php echo $block->escapeHtml($block->getAddress()->getCity()) ?>" class="input-text <?php /* @escapeNotVerified */ echo $this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('city') ?>" id="billing:city" /> - </div> - </div> - - <div class="field region required"> - <label class="label" for="billing:region_id"><span><?php /* @escapeNotVerified */ echo __('State/Province') ?></span></label> - <div class="control"> - <select id="billing:region_id" - name="billing[region_id]" - title="<?php /* @escapeNotVerified */ echo __('State/Province') ?>" - data-validate="{'validate-select':true}" - <?php if ($block->getConfig('general/region/display_all') === 0):?>disabled="disabled"<?php endif; ?> - style="display:none;"> - <option value=""><?php /* @escapeNotVerified */ echo __('Please select a region, state or province.') ?></option> - </select> - <input type="text" - id="billing:region" - name="billing[region]" - value="<?php echo $block->escapeHtml($block->getAddress()->getRegion()) ?>" - title="<?php /* @escapeNotVerified */ echo __('State/Province') ?>" - class="input-text <?php /* @escapeNotVerified */ echo $this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('region') ?>" - <?php if ($block->getConfig('general/region/display_all') === 0):?>disabled="disabled"<?php endif; ?> - style="display:none;" /> - </div> - </div> - - <div class="field zip required"> - <label class="label" for="billing:postcode"><span><?php /* @escapeNotVerified */ echo __('Zip/Postal Code') ?></span></label> - <div class="control"> - <input type="text" title="<?php /* @escapeNotVerified */ echo __('Zip/Postal Code') ?>" name="billing[postcode]" id="billing:postcode" value="<?php echo $block->escapeHtml($block->getAddress()->getPostcode()) ?>" class="input-text <?php /* @escapeNotVerified */ echo $this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('postcode') ?>" data-validate="{'required':true, 'validate-zip-international':true}"/> - </div> - </div> - - <div class="field country required"> - <label class="label" for="billing:country_id"><span><?php /* @escapeNotVerified */ echo __('Country') ?></span></label> - <div class="control"> - <?php echo $block->getCountryHtmlSelect('billing') ?> - </div> - </div> - - <div class="field telephone required"> - <label class="label" for="billing:telephone"><span><?php /* @escapeNotVerified */ echo __('Phone Number') ?></span></label> - <div class="control"> - <input type="text" name="billing[telephone]" value="<?php echo $block->escapeHtml($block->getAddress()->getTelephone()) ?>" title="<?php /* @escapeNotVerified */ echo __('Telephone') ?>" class="input-text <?php /* @escapeNotVerified */ echo $this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('telephone') ?>" id="billing:telephone" /> - </div> - </div> - - <div class="field fax"> - <label class="label" for="billing:fax"><span><?php /* @escapeNotVerified */ echo __('Fax') ?></span></label> - <div class="control"> - <input type="text" name="billing[fax]" value="<?php echo $block->escapeHtml($block->getAddress()->getFax()) ?>" title="<?php /* @escapeNotVerified */ echo __('Fax') ?>" class="input-text <?php /* @escapeNotVerified */ echo $this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('fax') ?>" id="billing:fax" /> - </div> - </div> - - <?php if (!$block->isCustomerLoggedIn()): ?> - <?php $_dob = $block->getLayout()->createBlock('Magento\Customer\Block\Widget\Dob') ?> - <?php $_taxvat = $block->getLayout()->createBlock('Magento\Customer\Block\Widget\Taxvat') ?> - <?php $_gender = $block->getLayout()->createBlock('Magento\Customer\Block\Widget\Gender') ?> - - <?php if ($_dob->isEnabled()): ?> - <?php echo $_dob->setDate($block->getQuote()->getCustomerDob())->setFieldIdFormat('billing:%s')->setFieldNameFormat('billing[%s]')->toHtml() ?> - <?php endif; ?> - <?php if ($_taxvat->isEnabled()): ?> - <?php echo $_taxvat->setTaxvat($block->getQuote()->getCustomerTaxvat())->setFieldIdFormat('billing:%s')->setFieldNameFormat('billing[%s]')->toHtml() ?> - <?php endif ?> - <?php if ($_gender->isEnabled()): ?> - <?php echo $_gender->setGender($block->getQuote()->getCustomerGender())->setFieldIdFormat('billing:%s')->setFieldNameFormat('billing[%s]')->toHtml() ?> - <?php endif ?> - <?php $customerAttributes = $block->getChildBlock('customer_form_customer_user_defined_attributes');?> - <?php if ($customerAttributes): ?> - <?php $customerAttributes->setEntityModelClass('Magento\Customer\Model\Customer')->setFieldIdFormat('billing:%1$s');?> - <?php $customerAttributes->setFieldNameFormat('billing[%1$s]')->setShowContainer(false);?> - <?php echo $customerAttributes->toHtml()?> - <?php endif;?> - <div class="field password required"> - <label class="label" for="billing:customer_password"><span><?php /* @escapeNotVerified */ echo __('Password') ?></span></label> - <div class="control"> - <input type="password" name="billing[customer_password]" id="billing:customer_password" title="<?php /* @escapeNotVerified */ echo __('Password') ?>" class="input-text" data-validate="{required:true, 'validate-password':true}"/> - </div> - </div> - <div class="field confirm required"> - <label class="label" for="billing:confirm_password"><span><?php /* @escapeNotVerified */ echo __('Confirm Password') ?></span></label> - <div class="control"> - <input type="password" name="billing[confirm_password]" title="<?php /* @escapeNotVerified */ echo __('Confirm Password') ?>" id="billing:confirm_password" class="input-text" data-validate="{required:true, 'validate-cpassword':true, equalTo: '#billing\\:customer_password'}"/> - </div> - </div> - <?php endif; ?> - <?php echo $block->getChildHtml('form_additional_info'); ?> - <?php if ($block->isCustomerLoggedIn() && $block->customerHasAddresses()):?> - <div class="field save choice"> - <input type="checkbox" name="billing[save_in_address_book]" value="1" title="<?php /* @escapeNotVerified */ echo __('Save in address book') ?>" id="billing:save_in_address_book" <?php if ($block->getAddress()->getSaveInAddressBook()):?> checked="checked"<?php endif;?> class="checkbox" /> - <label class="label" for="billing:save_in_address_book"><span><?php /* @escapeNotVerified */ echo __('Save in address book') ?></span></label> - </div> - <?php else:?> - <input type="hidden" name="billing[save_in_address_book]" value="1" /> - <?php endif; ?> - <?php /* Extensions placeholder */ ?> - <?php echo $block->getChildHtml('checkout.onepage.billing.extra')?> -</fieldset> -<?php if ($block->canShip()): ?> - <div class="field choice"> - <input type="radio" name="billing[use_for_shipping]" id="billing:use_for_shipping_yes" value="1"<?php if ($block->isUseBillingAddressForShipping()) { - ?> checked="checked"<?php -}?> class="radio" /> - <label class="label" for="billing:use_for_shipping_yes"><span><?php /* @escapeNotVerified */ echo __('Ship to this address') ?></span></label> - </div> - <div class="field choice"> - <input type="radio" name="billing[use_for_shipping]" id="billing:use_for_shipping_no" value="0"<?php if (!$block->isUseBillingAddressForShipping()) { - ?> checked="checked"<?php -}?> class="radio" /> - <label class="label" for="billing:use_for_shipping_no"><span><?php /* @escapeNotVerified */ echo __('Ship to different address') ?></span></label> - </div> -<?php endif; ?> - -<?php if (!$block->canShip()): ?> - <input type="hidden" name="billing[use_for_shipping]" value="1" /> -<?php endif; ?> -<div class="actions" id="billing-buttons-container"> - <div class="primary"><button data-role="opc-continue" type="button" class="button action continue primary"><span><?php /* @escapeNotVerified */ echo __('Continue') ?></span></button></div> -</div> -</form> -<script type="text/x-magento-init"> - { - "#billing\\:country_id": { - "regionUpdater": { - "optionalRegionAllowed": <?php /* @escapeNotVerified */ echo($block->getConfig('general/region/display_all') ? 'true' : 'false'); ?>, - "regionListId": "#billing\\:region_id", - "regionInputId": "#billing\\:region", - "postcodeId": "#billing\\:postcode", - "regionJson": <?php /* @escapeNotVerified */ echo $this->helper('Magento\Directory\Helper\Data')->getRegionJson() ?>, - "defaultRegion": "<?php /* @escapeNotVerified */ echo $block->getAddress()->getRegionId() ?>", - "countriesWithOptionalZip": <?php /* @escapeNotVerified */ echo $this->helper('Magento\Directory\Helper\Data')->getCountriesWithOptionalZip(true) ?> - } - } - } -</script> diff --git a/app/code/Magento/Checkout/view/frontend/templates/onepage/payment.phtml b/app/code/Magento/Checkout/view/frontend/templates/onepage/payment.phtml deleted file mode 100644 index f9ac39fd39dca380af9b9e422fb7e45656f50c20..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/templates/onepage/payment.phtml +++ /dev/null @@ -1,31 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -// @codingStandardsIgnoreFile - -/** - * @removeCandidate - */ -?> -<form id="co-payment-form" class="form payments"> - <?php echo $block->getBlockHtml('formkey') ?> - <fieldset class="fieldset"> - <legend class="legend payments-title"> - <span><?php /* @escapeNotVerified */ echo __('Payment Information') ?></span> - </legend><br> - <?php echo $block->getChildChildHtml('methods_additional') ?> - <div id="checkout-payment-method-load" class="opc-payment"></div> - </fieldset> - <?php echo $block->getChildChildHtml('additional') ?> - <div class="actions-toolbar" id="payment-buttons-container"> - <div class="primary"> - <button data-role="opc-continue" type="button" class="button action continue primary"><span><?php /* @escapeNotVerified */ echo __('Continue') ?></span></button> - </div> - <div class="secondary"> - <a class="action back" href="#"><span><?php /* @escapeNotVerified */ echo __('Back') ?></span></a> - </div> - </div> -</form> diff --git a/app/code/Magento/Checkout/view/frontend/templates/onepage/payment/methods.phtml b/app/code/Magento/Checkout/view/frontend/templates/onepage/payment/methods.phtml deleted file mode 100644 index f3c0f86cc46bb59bf8528a71db0e40a63635ec1a..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/templates/onepage/payment/methods.phtml +++ /dev/null @@ -1,52 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -// @codingStandardsIgnoreFile - -/** - * @removeCandidate - */ -?> -<?php -/** - * One page checkout payment methods - * - * @var $block \Magento\Checkout\Block\Onepage\Payment\Methods - */ -?> -<dl class="items methods-payment"> -<?php - $methods = $block->getMethods(); - $oneMethod = count($methods) <= 1; -?> -<?php if (empty($methods)): ?> - <dt class="item-title"> - <?php /* @escapeNotVerified */ echo __('No Payment Methods') ?> - </dt> -<?php else: - foreach ($methods as $_method): - $_code = $_method->getCode(); -?> - <dt class="item-title <?php /* @escapeNotVerified */ echo $_code ?>"> - <?php if (!$oneMethod): ?> - <input id="p_method_<?php /* @escapeNotVerified */ echo $_code ?>" value="<?php /* @escapeNotVerified */ echo $_code ?>" type="radio" name="payment[method]" title="<?php echo $block->escapeHtml($_method->getTitle()) ?>" <?php if ($block->getSelectedMethodCode() == $_code): ?> checked="checked"<?php endif; ?> class="radio" /> - <?php else: ?> - <input id="p_method_<?php /* @escapeNotVerified */ echo $_code ?>" value="<?php /* @escapeNotVerified */ echo $_code ?>" type="radio" name="payment[method]" checked="checked" class="radio no-display" /> - <?php $oneMethod = $_code; ?> - <?php endif; ?> - <label for="p_method_<?php /* @escapeNotVerified */ echo $_code ?>"><?php echo $block->escapeHtml($block->getMethodTitle($_method)) ?> <?php echo $block->getMethodLabelAfterHtml($_method) ?></label> - </dt> - <?php if ($html = $block->getPaymentMethodFormHtml($_method)): ?> - <dd class="item-content <?php /* @escapeNotVerified */ echo $_code ?>"> - <?php /* @escapeNotVerified */ echo $html; ?> - </dd> - <?php endif; ?> -<?php endforeach; - endif; -?> -</dl> -<div class="no-display" data-checkout-price="<?php echo (float)$block->getQuote()->getBaseGrandTotal(); ?>"></div> -<?php echo $block->getChildChildHtml('additional'); ?> diff --git a/app/code/Magento/Checkout/view/frontend/templates/onepage/review/button.phtml b/app/code/Magento/Checkout/view/frontend/templates/onepage/review/button.phtml deleted file mode 100644 index 1b26f9922c5faac3b3dc2e0e72d9a60644d0a925..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/templates/onepage/review/button.phtml +++ /dev/null @@ -1,13 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -// @codingStandardsIgnoreFile -/** - * @removeCandidate - */ -?> -<button data-role="review-save" type="submit" title="<?php /* @escapeNotVerified */ echo __('Place Order') ?>" - class="button action primary checkout"><span><?php /* @escapeNotVerified */ echo __('Place Order') ?></span></button> diff --git a/app/code/Magento/Checkout/view/frontend/templates/onepage/review/info.phtml b/app/code/Magento/Checkout/view/frontend/templates/onepage/review/info.phtml deleted file mode 100644 index 8e390e653fd79cf1743b4b7c6d134310d2f02f21..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/templates/onepage/review/info.phtml +++ /dev/null @@ -1,54 +0,0 @@ -\<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -// @codingStandardsIgnoreFile - -/** @var $block \Magento\Checkout\Block\Onepage\Review\Info */ - -/** - * @removeCandidate - */ -?> -<?php echo $block->getChildHtml('items_before'); ?> -<div id="checkout-review-table-wrapper" class="order-review-wrapper table-wrapper"> - <?php if ($this->helper('Magento\Tax\Helper\Data')->displayCartBothPrices()): $colspan = $rowspan = 2; else: $colspan = $rowspan = 1; endif; ?> - <table class="data table table-order-review items" id="checkout-review-table"> - <caption class="table-caption"><?php /* @escapeNotVerified */ echo __('Order Review'); ?></caption> - <thead> - <tr> - <th class="col item" scope="col"><?php /* @escapeNotVerified */ echo __('Product Name') ?></th> - <th class="col price" scope="col"><?php /* @escapeNotVerified */ echo __('Price') ?></th> - <th class="col qty" scope="col"><?php /* @escapeNotVerified */ echo __('Qty') ?></th> - <th class="col subtotal" scope="col"><?php /* @escapeNotVerified */ echo __('Subtotal') ?></th> - </tr> - </thead> - <tbody> - <?php foreach ($block->getItems() as $_item): ?> - <?php echo $block->getItemHtml($_item)?> - <?php endforeach ?> - </tbody> - <tfoot> - <?php echo $block->getChildHtml('totals'); ?> - </tfoot> - </table> -</div> -<?php echo $block->getChildHtml('items_after'); ?> -<div id="checkout-review-submit" data-mage-init='{"paymentAuthentication":{}}' class="checkout-submit-order"> - <?php echo $block->getChildHtml('agreements') ?> - <div class="actions-toolbar" id="review-buttons-container"> - <div class="primary"><?php echo $block->getChildHtml('button') ?></div> - <div class="secondary"> - <span id="checkout-review-edit-label"> - <?php /* @escapeNotVerified */ echo __('Forgot an Item?') ?> - </span> - <a href="<?php /* @escapeNotVerified */ echo $block->getUrl('checkout/cart') ?>" - aria-describedby="checkout-review-edit-label" - class="action edit"> - <span><?php /* @escapeNotVerified */ echo __('Edit Your Cart') ?></span> - </a> - </div> - </div> -</div> diff --git a/app/code/Magento/Checkout/view/frontend/templates/onepage/review/item.phtml b/app/code/Magento/Checkout/view/frontend/templates/onepage/review/item.phtml index 7d107a0589d53580c0e9b9512b3c936b063b49be..54748a318b6adedd0bf8d354eebaeaf8bdcd9c12 100644 --- a/app/code/Magento/Checkout/view/frontend/templates/onepage/review/item.phtml +++ b/app/code/Magento/Checkout/view/frontend/templates/onepage/review/item.phtml @@ -8,10 +8,6 @@ /** @var $block Magento\Checkout\Block\Cart\Item\Renderer */ -/** - * @removeCandidate - */ - $_item = $block->getItem(); ?> <tbody class="cart item"> diff --git a/app/code/Magento/Checkout/view/frontend/templates/onepage/review/item/price/row_excl_tax.phtml b/app/code/Magento/Checkout/view/frontend/templates/onepage/review/item/price/row_excl_tax.phtml index d10b01b1591fca77c9bd511743064a94588b836d..f0ead67e1bdc2a009f77e2bf646408e3e3d79929 100644 --- a/app/code/Magento/Checkout/view/frontend/templates/onepage/review/item/price/row_excl_tax.phtml +++ b/app/code/Magento/Checkout/view/frontend/templates/onepage/review/item/price/row_excl_tax.phtml @@ -8,10 +8,6 @@ /** @var $block \Magento\Checkout\Block\Item\Price\Renderer */ -/** - * @removeCandidate - */ - $_item = $block->getItem(); ?> <span class="cart-price"> diff --git a/app/code/Magento/Checkout/view/frontend/templates/onepage/review/item/price/row_incl_tax.phtml b/app/code/Magento/Checkout/view/frontend/templates/onepage/review/item/price/row_incl_tax.phtml index 09230fd5c336c67769392d2d083cb95af64e20f0..df0f4f3233cb73a5a3552a3355aa9d391f5f223c 100644 --- a/app/code/Magento/Checkout/view/frontend/templates/onepage/review/item/price/row_incl_tax.phtml +++ b/app/code/Magento/Checkout/view/frontend/templates/onepage/review/item/price/row_incl_tax.phtml @@ -8,10 +8,6 @@ /** @var $block \Magento\Checkout\Block\Item\Price\Renderer */ -/** - * @removeCandidate - */ - $_item = $block->getItem(); ?> <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getSubtotalInclTax($_item); ?> diff --git a/app/code/Magento/Checkout/view/frontend/templates/onepage/review/item/price/unit_excl_tax.phtml b/app/code/Magento/Checkout/view/frontend/templates/onepage/review/item/price/unit_excl_tax.phtml index f81ddc607c938bbc6acc8ba9897b1a296a7e14c6..b4b340e78b553c84f10888facbbbbb9ef55f6101 100644 --- a/app/code/Magento/Checkout/view/frontend/templates/onepage/review/item/price/unit_excl_tax.phtml +++ b/app/code/Magento/Checkout/view/frontend/templates/onepage/review/item/price/unit_excl_tax.phtml @@ -8,10 +8,6 @@ /** @var $block \Magento\Checkout\Block\Item\Price\Renderer */ -/** - * @removeCandidate - */ - $_item = $block->getItem(); ?> <span class="cart-price"> diff --git a/app/code/Magento/Checkout/view/frontend/templates/onepage/review/item/price/unit_incl_tax.phtml b/app/code/Magento/Checkout/view/frontend/templates/onepage/review/item/price/unit_incl_tax.phtml index 6ff351b90f76a939edd05cce488504d0df22cf70..53118c3312595f301cb9afc861b3476da7a49194 100644 --- a/app/code/Magento/Checkout/view/frontend/templates/onepage/review/item/price/unit_incl_tax.phtml +++ b/app/code/Magento/Checkout/view/frontend/templates/onepage/review/item/price/unit_incl_tax.phtml @@ -8,10 +8,6 @@ /** @var $block \Magento\Checkout\Block\Item\Price\Renderer */ -/** - * @removeCandidate - */ - $_item = $block->getItem(); ?> <?php $_incl = $this->helper('Magento\Checkout\Helper\Data')->getPriceInclTax($_item); ?> diff --git a/app/code/Magento/Checkout/view/frontend/templates/onepage/shipping.phtml b/app/code/Magento/Checkout/view/frontend/templates/onepage/shipping.phtml deleted file mode 100644 index aaff68ef03aca5f2230b68512bca28792c3cee9f..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/templates/onepage/shipping.phtml +++ /dev/null @@ -1,133 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -// @codingStandardsIgnoreFile - -/** - * @removeCandidate - */ -?> -<form class="form shipping address" id="co-shipping-form" data-hasrequired="<?php /* @escapeNotVerified */ echo __('* Required Fields') ?>"> - -<?php if ($block->customerHasAddresses()): ?> - <div class="field addresses"> - <label class="label" for="shipping:address-select"><span><?php /* @escapeNotVerified */ echo __('Select a shipping address from your address book or enter a new address.') ?></span></label> - <div class="control"><?php echo $block->getAddressesHtmlSelect('shipping') ?></div> - </div> -<?php endif ?> - <fieldset class="fieldset address" id="shipping-new-address-form"<?php if ($block->customerHasAddresses()): ?> style="display:none;"<?php endif ?>> - <input type="hidden" name="shipping[address_id]" value="<?php /* @escapeNotVerified */ echo $block->getAddress()->getId() ?>" id="shipping:address_id" /> - <?php echo $block->getLayout()->createBlock('Magento\Customer\Block\Widget\Name')->setObject($block->getAddress())->setFieldIdFormat('shipping:%s')->setFieldNameFormat('shipping[%s]')->toHtml() ?> - <div class="field company"> - <label class="label" for="shipping:company"><span><?php /* @escapeNotVerified */ echo __('Company') ?></span></label> - <div class="control"> - <input type="text" id="shipping:company" name="shipping[company]" value="<?php echo $block->escapeHtml($block->getAddress()->getCompany()) ?>" title="<?php /* @escapeNotVerified */ echo __('Company') ?>" class="input-text <?php /* @escapeNotVerified */ echo $this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('company') ?>" /> - </div> - </div> - <?php if ($this->helper('Magento\Customer\Helper\Address')->isVatAttributeVisible()) : ?> - <div class="field taxvat"> - <label class="label" for="shipping:vat_id"><span><?php /* @escapeNotVerified */ echo __('VAT Number'); ?></span></label> - <div class="control"> - <input type="text" id="shipping:vat_id" name="shipping[vat_id]" value="<?php echo $block->escapeHtml($block->getAddress()->getVatId()); ?>" title="<?php /* @escapeNotVerified */ echo __('VAT Number'); ?>" class="input-text <?php /* @escapeNotVerified */ echo $this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('vat_id') ?>" /> - </div> - </div> - <?php endif; ?> - <?php $_streetValidationClass = $this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('street'); ?> - <div class="field street required"> - <label class="label" for="shipping:street1"><span><?php /* @escapeNotVerified */ echo __('Address') ?></span></label> - <div class="control"> - <input type="text" title="<?php /* @escapeNotVerified */ echo __('Street Address') ?>" name="shipping[street][]" id="shipping:street1" value="<?php echo $block->escapeHtml($block->getAddress()->getStreetLine(1)) ?>" class="input-text <?php /* @escapeNotVerified */ echo $_streetValidationClass ?>" /> - <div class="nested"> - <?php $_streetValidationClass = trim(str_replace('required-entry', '', $_streetValidationClass)); ?> - <?php for ($_i = 2, $_n = $this->helper('Magento\Customer\Helper\Address')->getStreetLines(); $_i <= $_n; $_i++): ?> - <div class="field additional"> - <label class="label" for="shipping:street<?php /* @escapeNotVerified */ echo $_i ?>"> - <span><?php /* @escapeNotVerified */ echo __('Street Address %1', $_i) ?></span> - </label> - <div class="control"> - <input type="text" title="<?php /* @escapeNotVerified */ echo __('Street Address %1', $_i) ?>" name="shipping[street][]" id="shipping:street<?php /* @escapeNotVerified */ echo $_i ?>" value="<?php echo $block->escapeHtml($block->getAddress()->getStreetLine($_i)) ?>" class="input-text <?php /* @escapeNotVerified */ echo $_streetValidationClass ?>" /> - </div> - </div> - <?php endfor; ?> - </div> - </div> - </div> - - <div class="field city required"> - <label class="label" for="shipping:city"><span><?php /* @escapeNotVerified */ echo __('City') ?></span></label> - <div class="control"> - <input type="text" title="<?php /* @escapeNotVerified */ echo __('City') ?>" name="shipping[city]" value="<?php echo $block->escapeHtml($block->getAddress()->getCity()) ?>" class="input-text <?php /* @escapeNotVerified */ echo $this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('city') ?>" id="shipping:city" /> - </div> - </div> - <div class="field region required"> - <label class="label" for="shipping:region"><span><?php /* @escapeNotVerified */ echo __('State/Province') ?></span></label> - <div class="control"> - <select id="shipping:region_id" name="shipping[region_id]" title="<?php /* @escapeNotVerified */ echo __('State/Province') ?>" class="validate-select" style="display:none;"> - <option value=""><?php /* @escapeNotVerified */ echo __('Please select a region, state or province.') ?></option> - </select> - <input type="text" id="shipping:region" name="shipping[region]" value="<?php echo $block->escapeHtml($block->getAddress()->getRegion()) ?>" title="<?php /* @escapeNotVerified */ echo __('State/Province') ?>" class="input-text <?php /* @escapeNotVerified */ echo $this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('region') ?>" style="display:none;" /> - </div> - </div> - <div class="field zip required"> - <label class="label" for="shipping:postcode"><span><?php /* @escapeNotVerified */ echo __('Zip/Postal Code') ?></span></label> - <div class="control"> - <input type="text" title="<?php /* @escapeNotVerified */ echo __('Zip/Postal Code') ?>" name="shipping[postcode]" id="shipping:postcode" value="<?php echo $block->escapeHtml($block->getAddress()->getPostcode()) ?>" class="input-text validate-zip-international <?php /* @escapeNotVerified */ echo $this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('postcode') ?>" data-validate="{'required':true, 'validate-zip-international':true}" /> - </div> - </div> - <div class="field country required"> - <label class="label" for="shipping:country_id"><span><?php /* @escapeNotVerified */ echo __('Country') ?></span></label> - <div class="control"> - <?php echo $block->getCountryHtmlSelect('shipping') ?> - </div> - </div> - <div class="field telephone required"> - <label class="label" for="shipping:telephone"><span><?php /* @escapeNotVerified */ echo __('Phone Number') ?></span></label> - <div class="control"> - <input type="text" name="shipping[telephone]" value="<?php echo $block->escapeHtml($block->getAddress()->getTelephone()) ?>" title="<?php /* @escapeNotVerified */ echo __('Telephone') ?>" class="input-text <?php /* @escapeNotVerified */ echo $this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('telephone') ?>" id="shipping:telephone" /> - </div> - </div> - <div class="field fax"> - <label class="label" for="shipping:fax"><span><?php /* @escapeNotVerified */ echo __('Fax') ?></span></label> - <div class="control"> - <input type="text" name="shipping[fax]" value="<?php echo $block->escapeHtml($block->getAddress()->getFax()) ?>" title="<?php /* @escapeNotVerified */ echo __('Fax') ?>" class="input-text <?php /* @escapeNotVerified */ echo $this->helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('fax') ?>" id="shipping:fax" /> - </div> - </div> - - <?php if ($block->isCustomerLoggedIn() && $block->customerHasAddresses()):?> - <div class="field choice save"> - <input type="checkbox" name="shipping[save_in_address_book]" value="1" title="<?php /* @escapeNotVerified */ echo __('Save in address book') ?>" id="shipping:save_in_address_book" <?php if ($block->getAddress()->getSaveInAddressBook()):?> checked="checked"<?php endif;?> class="checkbox" /> - <label class="label" for="shipping:save_in_address_book"><span><?php /* @escapeNotVerified */ echo __('Save in address book') ?></span></label> - </div> - <?php else:?> - <input type="hidden" name="shipping[save_in_address_book]" value="1" /> - <?php endif;?> - </fieldset> - <div class="choice field"> - <input type="checkbox" name="shipping[same_as_billing]" id="shipping:same_as_billing" value="1"<?php if ($block->getAddress()->getSameAsBilling()): ?> checked="checked"<?php endif; ?> class="checkbox" /> - <label class="label" for="shipping:same_as_billing"><span><?php /* @escapeNotVerified */ echo __('Use Billing Address') ?></span></label> - </div> - <div class="actions-toolbar" id="shipping-buttons-container"> - <div class="primary"> - <button data-role="opc-continue" type="button" class="action continue primary"><span><?php /* @escapeNotVerified */ echo __('Continue') ?></span></button> - </div> - <div class="secondary"><a href="#" class="action back"><span><?php /* @escapeNotVerified */ echo __('Back') ?></span></a></div> - </div> -</form> -<script type="text/x-magento-init"> - { - "#shipping\\:country_id": { - "regionUpdater": { - "optionalRegionAllowed": <?php /* @escapeNotVerified */ echo($block->getConfig('general/region/display_all') ? 'true' : 'false'); ?>, - "regionListId": "#shipping\\:region_id", - "regionInputId": "#shipping\\:region", - "postcodeId": "#shipping\\:postcode", - "regionJson": <?php /* @escapeNotVerified */ echo $this->helper('Magento\Directory\Helper\Data')->getRegionJson() ?>, - "defaultRegion": "<?php /* @escapeNotVerified */ echo $block->getAddress()->getRegionId() ?>", - "countriesWithOptionalZip": <?php /* @escapeNotVerified */ echo $this->helper('Magento\Directory\Helper\Data')->getCountriesWithOptionalZip(true) ?> - } - } - } -</script> diff --git a/app/code/Magento/Checkout/view/frontend/templates/onepage/shipping_method.phtml b/app/code/Magento/Checkout/view/frontend/templates/onepage/shipping_method.phtml deleted file mode 100644 index 4ab0004006b422c96f48ffd63410853abd473a8c..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/templates/onepage/shipping_method.phtml +++ /dev/null @@ -1,24 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -// @codingStandardsIgnoreFile - -/** - * @removeCandidate - */ -?> -<form class="form methods-shipping" id="co-shipping-method-form"> - <div id="checkout-shipping-method-load"></div> - <div id="onepage-checkout-shipping-method-additional-load"> - <?php echo $block->getChildHtml('additional') ?> - </div> - <div class="actions-toolbar" id="shipping-method-buttons-container"> - <div class="primary"> - <button data-role="opc-continue" type="button" class="button action continue primary"><span><?php /* @escapeNotVerified */ echo __('Continue') ?></span></button> - </div> - <div class="secondary"><a class="action back" href="#"><span><?php /* @escapeNotVerified */ echo __('Back') ?></span></a></div> - </div> -</form> diff --git a/app/code/Magento/Checkout/view/frontend/templates/onepage/shipping_method/additional.phtml b/app/code/Magento/Checkout/view/frontend/templates/onepage/shipping_method/additional.phtml deleted file mode 100644 index ac87ff9ce6691d7e0062c81b1fa59d59aa817df2..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/templates/onepage/shipping_method/additional.phtml +++ /dev/null @@ -1,15 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -// @codingStandardsIgnoreFile - -/** - * @removeCandidate - */ -?> -<?php if (!$block->getQuote()->isVirtual()): ?> - <?php /* @escapeNotVerified */ echo $this->helper('Magento\GiftMessage\Helper\Message')->getInline('onepage_checkout', $block->getQuote(), $block->getDontDisplayContainer()) ?> -<?php endif; ?> diff --git a/app/code/Magento/Checkout/view/frontend/templates/onepage/shipping_method/available.phtml b/app/code/Magento/Checkout/view/frontend/templates/onepage/shipping_method/available.phtml deleted file mode 100644 index f2b37b4be7c835b7ec4fe521af4b907e35678510..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/templates/onepage/shipping_method/available.phtml +++ /dev/null @@ -1,50 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -// @codingStandardsIgnoreFile - -/** - * @removeCandidate - */ -?> -<?php /** @var $block \Magento\Checkout\Block\Onepage\Shipping\Method\Available */ ?> -<?php $_shippingRateGroups = $block->getShippingRates(); ?> -<?php if (!$_shippingRateGroups): ?> - <p><?php /* @escapeNotVerified */ echo __('Sorry, no quotes are available for this order right now.') ?></p> -<?php else: ?> - <dl class="items methods-shipping"> - <?php $shippingCodePrice = []; ?> - <?php $_sole = count($_shippingRateGroups) == 1; foreach ($_shippingRateGroups as $code => $_rates): ?> - <dt class="item-title <?php /* @escapeNotVerified */ echo $code ?>"><?php echo $block->escapeHtml($block->getCarrierName($code)) ?></dt> - <dd class="item-content <?php /* @escapeNotVerified */ echo $code ?>"> - <fieldset class="fieldset"> - <legend class="legend"><span><?php echo $block->escapeHtml($block->getCarrierName($code)) ?></span></legend><br> - <?php $_sole = $_sole && count($_rates) == 1; foreach ($_rates as $_rate): ?> - <?php $shippingCodePrice[] = '"'.$_rate->getCode().'":'.(float)$_rate->getPrice(); ?> - <div class="field choice"> - <?php if ($_rate->getErrorMessage()): ?> - <div class="message error"><div><?php echo $block->escapeHtml($_rate->getErrorMessage()) ?></div></div> - <?php else: ?> - <?php if ($_sole) : ?> - <span class="no-display"><input name="shipping_method" type="radio" value="<?php /* @escapeNotVerified */ echo $_rate->getCode() ?>" id="s_method_<?php /* @escapeNotVerified */ echo $_rate->getCode() ?>" checked="checked" /></span> - <?php else: ?> - <div class="control"> - <input name="shipping_method" type="radio" value="<?php /* @escapeNotVerified */ echo $_rate->getCode() ?>" id="s_method_<?php /* @escapeNotVerified */ echo $_rate->getCode() ?>"<?php if($_rate->getCode()===$block->getAddressShippingMethod()) echo ' checked="checked"' ?> class="radio"/> - </div> - <?php endif; ?> - <label class="label" for="s_method_<?php /* @escapeNotVerified */ echo $_rate->getCode() ?>"><span><?php echo $block->escapeHtml($_rate->getMethodTitle()) ?> - <?php echo $block->getShippingPriceHtml($_rate); ?> - </span> - </label> - <?php endif ?> - </div> - <?php endforeach; ?> - </fieldset> - </dd> - <?php endforeach; ?> - </dl> - <div class="no-display" data-shipping-code-price='{<?php /* @escapeNotVerified */ echo implode(",",$shippingCodePrice); ?>}'></div> -<?php endif; ?> diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/set-billing-address.js b/app/code/Magento/Checkout/view/frontend/web/js/action/set-billing-address.js index 2090bdabfe69b2af20f08e340af079cd76d551bd..0c0060f737d536ec0b78774e1e9dcedf38662861 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/action/set-billing-address.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/action/set-billing-address.js @@ -59,6 +59,7 @@ define( if (!quote.isVirtual()) { getTotalsAction([]); + fullScreenLoader.stopLoader(); } else { deferred = $.Deferred(); getPaymentInformationAction(deferred); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validator.js b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validator.js index c510194a2087382d07fed7f8367408ce95aafdb9..732f328ff727403e2e52e10d2980d902c0839611 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validator.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validator.js @@ -15,31 +15,46 @@ define( ], function ($, ko, shippingRatesValidationRules, addressConverter, selectShippingAddress, postcodeValidator, $t) { 'use strict'; - var checkoutConfig = window.checkoutConfig; - var validators = []; - var observedElements = []; - var postcodeElement = null; + + var checkoutConfig = window.checkoutConfig, + validators = [], + observedElements = [], + postcodeElement = null; return { validateAddressTimeout: 0, validateDelay: 2000, - registerValidator: function(carrier, validator) { + /** + * @param {String} carrier + * @param {Object} validator + */ + registerValidator: function (carrier, validator) { if (checkoutConfig.activeCarriers.indexOf(carrier) != -1) { validators.push(validator); } }, - validateAddressData: function(address) { + /** + * @param {Object} address + * @return {Boolean} + */ + validateAddressData: function (address) { return validators.some(function(validator) { return validator.validate(address); }); }, - bindChangeHandlers: function(elements, force, delay) { - var self = this; - var observableFields = shippingRatesValidationRules.getObservableFields(); - $.each(elements, function(index, elem) { + /** + * @param {*} elements + * @param {Boolean} force + * @param {Number} delay + */ + bindChangeHandlers: function (elements, force, delay) { + var self = this, + observableFields = shippingRatesValidationRules.getObservableFields(); + + $.each(elements, function (index, elem) { if (elem && (observableFields.indexOf(elem.index) != -1 || force)) { if (elem.index !== 'postcode') { self.bindHandler(elem, delay); @@ -53,17 +68,23 @@ define( }); }, - bindHandler: function(element, delay) { + /** + * @param {Object} element + * @param {Number} delay + */ + bindHandler: function (element, delay) { var self = this; + delay = typeof delay === "undefined" ? self.validateDelay : delay; + if (element.component.indexOf('/group') != -1) { - $.each(element.elems(), function(index, elem) { + $.each(element.elems(), function (index, elem) { self.bindHandler(elem); }); } else { - element.on('value', function() { + element.on('value', function () { clearTimeout(self.validateAddressTimeout); - self.validateAddressTimeout = setTimeout(function() { + self.validateAddressTimeout = setTimeout(function () { if (self.postcodeValidation()) { self.validateFields(); } @@ -73,36 +94,44 @@ define( } }, - postcodeValidation: function() { + /** + * @return {*} + */ + postcodeValidation: function () { + var countryId = $('select[name="country_id"]').val(), + validationResult = postcodeValidator.validate(postcodeElement.value(), countryId), + warnMessage; + if (postcodeElement == null || postcodeElement.value() == null) { return true; } - var countryId = $('select[name="shippingAddress[country_id]"]').val(); - var validationResult = postcodeValidator.validate(postcodeElement.value(), countryId); - postcodeElement.warn(null); + if (!validationResult) { - var warnMessage = $t('Provided Zip/Postal Code seems to be invalid.'); + warnMessage = $t('Provided Zip/Postal Code seems to be invalid.'); if (postcodeValidator.validatedPostCodeExample.length) { warnMessage += $t(' Example: ') + postcodeValidator.validatedPostCodeExample.join('; ') + '. '; } warnMessage += $t('If you believe it is the right one you can ignore this notice.'); postcodeElement.warn(warnMessage); } + return validationResult; }, /** * Convert form data to quote address and validate fields for shipping rates */ - validateFields: function() { + validateFields: function () { var addressFlat = addressConverter.formDataProviderToFlatData( - this.collectObservedData(), - 'shippingAddress' - ); + this.collectObservedData(), + 'shippingAddress' + ), + address; + if (this.validateAddressData(addressFlat)) { - var address = addressConverter.formAddressDataToQuoteAddress(addressFlat); + address = addressConverter.formAddressDataToQuoteAddress(addressFlat); selectShippingAddress(address); } }, @@ -112,11 +141,13 @@ define( * * @returns {*} */ - collectObservedData: function() { + collectObservedData: function () { var observedValues = {}; - $.each(observedElements, function(index, field) { + + $.each(observedElements, function (index, field) { observedValues[field.dataScope] = field.value(); }); + return observedValues; } }; diff --git a/app/code/Magento/Checkout/view/frontend/web/js/opc-billing-info.js b/app/code/Magento/Checkout/view/frontend/web/js/opc-billing-info.js deleted file mode 100644 index 5ed385463d8bca9873012ce9effe69244762c47a..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/js/opc-billing-info.js +++ /dev/null @@ -1,57 +0,0 @@ -/** - * @category one page checkout second step - * @package mage - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*jshint browser:true jquery:true*/ -/*global alert*/ -/** - * @removeCandidate - */ -define([ - "jquery", - "jquery/ui", - "Magento_Checkout/js/opc-checkout-method", - "mage/validation" -], function($){ - 'use strict'; - - // Extension for mage.opcheckout - second section(Billing Information) in one page checkout accordion - $.widget('mage.opcBillingInfo', $.mage.opcCheckoutMethod, { - options: { - billing: { - form: '#co-billing-form', - continueSelector: '#opc-billing [data-role=opc-continue]', - addressDropdownSelector: '#billing\\:address-select', - newAddressFormSelector: '#billing-new-address-form', - emailAddressName: 'billing[email]' - } - }, - - _create: function() { - this._super(); - var events = {}; - events['change ' + this.options.billing.addressDropdownSelector] = function(e) { - this.element.find(this.options.billing.newAddressFormSelector).toggle(!$(e.target).val()); - }; - events['click ' + this.options.billing.continueSelector] = function() { - if ($(this.options.billing.form).validation && $(this.options.billing.form).validation('isValid')) { - this._billingSave(); - } - }; - this._on(events); - - this.element.find(this.options.billing.form).validation(); - } , - - _billingSave: function() { - this._ajaxContinue(this.options.billing.saveUrl, $(this.options.billing.form).serialize(), false, function() { - //Trigger indicating billing save. eg. GiftMessage listens to this to inject gift options - this.element.trigger('billingSave'); - }); - } - }); - - return $.mage.opcBillingInfo; -}); \ No newline at end of file diff --git a/app/code/Magento/Checkout/view/frontend/web/js/opc-checkout-method.js b/app/code/Magento/Checkout/view/frontend/web/js/opc-checkout-method.js deleted file mode 100644 index 0f92f6ea63362f1de7e995e7db9ee721d012b15c..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/js/opc-checkout-method.js +++ /dev/null @@ -1,291 +0,0 @@ -/** - * @category one page checkout first step - * @package mage - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*jshint browser:true jquery:true*/ -/*global alert*/ -/** - * @removeCandidate - */ -define([ - "jquery", - "accordion", - 'Magento_Ui/js/modal/alert', - "jquery/ui", - "mage/validation/validation", - "mage/translate" -], function($, accordion, alert){ - 'use strict'; - - // Base widget, handle ajax events and first section(Checkout Method) in one page checkout accordion - $.widget('mage.opcCheckoutMethod', { - options: { - checkout: { - loginGuestSelector: '[data-role=checkout-method-guest]', - loginRegisterSelector: '[data-role=checkout-method-register]', - loginFormSelector: 'form[data-role=login]', - continueSelector: '#opc-login [data-role=opc-continue]', - registerCustomerPasswordSelector: '#co-billing-form .field.password,#co-billing-form .field.confirm', - captchaGuestCheckoutSelector: '#co-billing-form [role="guest_checkout"]', - registerDuringCheckoutSelector: '#co-billing-form [role="register_during_checkout"]', - suggestRegistration: false - }, - pageMessages: '#maincontent .messages .message', - sectionSelectorPrefix: 'opc-', - billingSection: 'billing', - ajaxLoaderPlaceButton: false, - updateSelectorPrefix: '#checkout-', - updateSelectorSuffix: '-load', - backSelector: '.action.back', - minBalance: 0.0001, - methodsListContainer: 'dl', - methodContainer: 'dt', - methodDescription : 'dd ul', - methodOn: 'dt input:radio' - }, - - _create: function() { - var self = this; - - this._initAccordion(); - - this.sectionActiveClass = this.element.accordion("option","openedState"); - this.contentSelector = this.element.accordion("option","content"); - this.checkoutPrice = this.options.quoteBaseGrandTotal; - - if (this.options.checkout.suggestRegistration) { - $(this.options.checkout.loginGuestSelector).prop('checked', false); - $(this.options.checkout.loginRegisterSelector).prop('checked', true); - } - this._handleSteps(); - var events = {}; - events['click ' + this.options.checkout.continueSelector] = function(e) { - this._continue($(e.currentTarget)); - }; - events['click ' + this.options.backSelector] = function(event) { - event.preventDefault(); - var prev = self.steps.index($('li.' + self.sectionActiveClass)) -1 ; - this._activateSection(prev); - }; - events['click ' + '[data-action=checkout-method-login]'] = function(event) { - if($(self.options.checkout.loginFormSelector).validation('isValid')){ - self.element.find('.section').filter('.' + self.sectionActiveClass).children(self.contentSelector).trigger("processStart"); - event.preventDefault(); - setTimeout(function(){ - $(self.options.checkout.loginFormSelector).submit(); - }, 300); - } - }; - - $(document).on({ - 'ajaxError': this._ajaxError.bind(this) - }); - - $.extend(events, { - showAjaxLoader: '_ajaxSend', - hideAjaxLoader: '_ajaxComplete', - gotoSection: function(e, section) { - self.element.find('.section').filter('.' + self.sectionActiveClass).children(self.contentSelector).trigger("processStop"); - var toActivate = this.steps.index($('#' + self.options.sectionSelectorPrefix + section)); - this._activateSection(toActivate); - } - }); - this._on(events); - - this._on($(this.options.checkoutProgressContainer), { - 'click [data-goto-section]' : function(e) { - var gotoSection = $(e.target).data('goto-section'); - self.element.find('.section').filter('.' + self.sectionActiveClass).children(self.contentSelector).trigger("processStop"); - var toActivate = this.steps.index($('#' + self.options.sectionSelectorPrefix + gotoSection)); - this._activateSection(toActivate); - return false; - } - }); - }, - - _initAccordion: function(){ - var config = this.element.data('accordion'); - - accordion(config, this.element[0]); - }, - - /** - * Get the checkout steps, disable steps but first, adding callback on before opening section to - * disable all next steps - * @private - */ - _handleSteps: function() { - var self = this; - this.steps = $(this.element).children('[id^=' + this.options.sectionSelectorPrefix + ']'); - this.element.accordion("disable"); - this._activateSection(0); - $.each(this.steps,function() { - $(this).on("beforeOpen",function() { - $(this).nextAll('[id^=' + self.options.sectionSelectorPrefix + ']').collapsible("disable"); - $(this).prevAll('[id^=' + self.options.sectionSelectorPrefix + ']').collapsible("enable"); - }); - }); - }, - - /** - * Activate section - * @param index the index of section you want to open - * @private - */ - _activateSection: function(index) { - this.element.accordion("enable",index); - this.element.accordion("activate",index); - }, - - /** - * Callback function for before ajax send event(global) - * @private - */ - _ajaxSend: function() { - this.element.find('.section').filter('.' + this.sectionActiveClass).children(this.contentSelector).trigger("processStart"); - }, - - /** - * Callback function for ajax complete event(global) - * @private - */ - _ajaxComplete: function() { - this.element.find('.section').filter('.' + this.sectionActiveClass).children(this.contentSelector).trigger("processStop"); - }, - - /** - * ajax error for all onepage checkout ajax calls - * @private - */ - _ajaxError: function() { - window.location.href = this.options.failureUrl; - }, - - /** - * callback function when continue button is clicked - * @private - * @param elem - continue button - * @return {Boolean} - */ - _continue: function(elem) { - var json = elem.data('checkout'), - checkout = this.options.checkout, - guestChecked = $( checkout.loginGuestSelector ).is( ':checked' ), - registerChecked = $( checkout.loginRegisterSelector ).is( ':checked' ), - method = 'register', - isRegistration = true; - - //Remove page messages - $(this.options.pageMessages).remove(); - - if (json.isGuestCheckoutAllowed) { - - if( !guestChecked && !registerChecked ){ - alert({ - content: $.mage.__('Please create an account or check out as a guest.') - }); - - return false; - } - - if( guestChecked ){ - method = 'guest'; - isRegistration = false; - } - - this._ajaxContinue( - checkout.saveUrl, - { method: method }, - this.options.billingSection - ); - - this.element.find(checkout.registerCustomerPasswordSelector).toggle(isRegistration); - this.element.find(checkout.captchaGuestCheckoutSelector).toggle(!isRegistration); - this.element.find(checkout.registerDuringCheckoutSelector).toggle(isRegistration); - } - else if( json.registrationUrl ){ - window.location = json.registrationUrl; - } - - this.element.trigger('login'); - }, - - /** - * Ajax call to save checkout info to backend and enable next section in accordion - * @private - * @param url - ajax url - * @param data - post data for ajax call - * @param gotoSection - the section needs to show after ajax call - * @param successCallback - custom callback function in ajax success - */ - _ajaxContinue: function(url, data, gotoSection, successCallback) { - $.ajax({ - url: url, - type: 'post', - context: this, - data: data, - dataType: 'json', - beforeSend: this._ajaxSend, - complete: this._ajaxComplete, - success: function (response) { - if (successCallback) { - successCallback.call(this, response); - } - if ($.type(response) === 'object' && !$.isEmptyObject(response)) { - if (response.error) { - var msg = response.message || response.error_messages || response.error; - - if (msg) { - if (Array.isArray(msg)) { - msg = msg.reduce(function (str, chunk) { - str += '\n' + chunk; - return str; - }, ''); - } - - $(this.options.countrySelector).trigger('change'); - - alert({ - content: msg - }); - } - - return; - } - if (response.redirect) { - $.mage.redirect(response.redirect); - return false; - } - else if (response.success) { - $.mage.redirect(this.options.review.successUrl); - return false; - } - if (response.update_section) { - if (response.update_section.name === 'payment-method' && response.update_section.html.indexOf('data-checkout-price')) { - this.element.find(this.options.payment.form).find('[data-checkout-price]').remove(); - } - $(this.options.updateSelectorPrefix + response.update_section.name + this.options.updateSelectorSuffix) - .html($(response.update_section.html)).trigger('contentUpdated'); - } - if (response.update_progress) { - $(this.options.checkoutProgressContainer).html($(response.update_progress.html)).trigger('progressUpdated'); - } - if (response.duplicateBillingInfo) { - $(this.options.shipping.copyBillingSelector).prop('checked', true).trigger('click'); - $(this.options.shipping.addressDropdownSelector).val($(this.options.billing.addressDropdownSelector).val()).change(); - } - if (response.goto_section) { - this.element.trigger('gotoSection', response.goto_section); - } - } else { - this.element.trigger('gotoSection', gotoSection); - } - } - }); - } - }); - - return $.mage.opcCheckoutMethod; -}); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/opc-order-review.js b/app/code/Magento/Checkout/view/frontend/web/js/opc-order-review.js deleted file mode 100644 index 83313faeebf5c513acfc11577db030f644b15500..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/js/opc-order-review.js +++ /dev/null @@ -1,60 +0,0 @@ -/** - * @category one page checkout last step - * @package mage - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*jshint browser:true jquery:true*/ -/*global alert*/ -/** - * @removeCandidate - */ -define([ - "jquery", - "jquery/ui", - "Magento_Checkout/js/opc-payment-info" -], function($){ - 'use strict'; - - // Extension for mage.opcheckout - last section(Order Review) in one page checkout accordion - $.widget('mage.opcOrderReview', $.mage.opcPaymentInfo, { - options: { - review: { - continueSelector: '#opc-review [data-role=review-save]', - container: '#opc-review', - agreementGroupSelector: '#checkout-agreements' - } - }, - - _create: function() { - this._super(); - var events = {}; - events['click ' + this.options.review.continueSelector] = this._saveOrder; - events['saveOrder' + this.options.review.container] = this._saveOrder; - this._on(events); - }, - - _saveOrder: function() { - var agreementFormsGroup = $(this.options.review.agreementGroupSelector), - paymentForm = $(this.options.payment.form); - var isAgreementValid = true; - agreementFormsGroup.find('form').each( - function(){ - isAgreementValid = $(this).validation() && $(this).validation('isValid') && isAgreementValid; - } - ); - - if (isAgreementValid && - paymentForm.validation && - paymentForm.validation('isValid')) { - var serializedAgreement = ''; - agreementFormsGroup.find('form').each(function(){serializedAgreement += '&' + $(this).serialize();}); - this._ajaxContinue( - this.options.review.saveUrl, - paymentForm.serialize() + serializedAgreement); - } - } - }); - - return $.mage.opcOrderReview; -}); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/opc-payment-info.js b/app/code/Magento/Checkout/view/frontend/web/js/opc-payment-info.js deleted file mode 100644 index bfa87548aea2a170d7372bbc547266c482e9d7f6..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/js/opc-payment-info.js +++ /dev/null @@ -1,178 +0,0 @@ -/** - * @category one page checkout fifth step - * @package mage - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*jshint browser:true*/ -/*global alert*/ -/** - * @removeCandidate - */ -define([ - 'jquery', - 'mage/template', - 'Magento_Ui/js/modal/alert', - 'jquery/ui', - 'mage/translate', - 'Magento_Checkout/js/opc-shipping-method' -], function ($, mageTemplate, alert) { - 'use strict'; - - // Extension for mage.opcheckout - fifth section(Payment Information) in one page checkout accordion - $.widget('mage.opcPaymentInfo', $.mage.opcShippingMethod, { - options: { - payment: { - form: '#co-payment-form', - continueSelector: '#payment [data-role=opc-continue]', - methodsContainer: '#checkout-payment-method-load', - freeInput: { - tmpl: '<input id="hidden-free" type="hidden" name="payment[method]" value="free">', - selector: '#hidden-free' - } - } - }, - - _create: function () { - this._super(); - - var events = {}; - - this.freeInputTmpl = mageTemplate(this.options.payment.freeInput.tmpl); - - events['click ' + this.options.payment.continueSelector] = function () { - if (this._validatePaymentMethod() && - $(this.options.payment.form).validation && - $(this.options.payment.form).validation('isValid')) { - this._ajaxContinue(this.options.payment.saveUrl, $(this.options.payment.form).serialize()); - } - }; - - events['contentUpdated ' + this.options.payment.form] = function () { - $(this.options.payment.form).find('dd [name^="payment["]').prop('disabled', true); - var checkoutPrice = this.element.find(this.options.payment.form).find('[data-checkout-price]').data('checkout-price'); - - if ($.isNumeric(checkoutPrice)) { - this.checkoutPrice = checkoutPrice; - } - - if (this.checkoutPrice < this.options.minBalance) { - this._disablePaymentMethods(); - } else { - this._enablePaymentMethods(); - } - }; - - events['click ' + this.options.payment.form + ' dt input:radio'] = '_paymentMethodHandler'; - - $.extend(events, { - updateCheckoutPrice: function (event, data) { - if (data.price) { - this.checkoutPrice += data.price; - } - - if (data.totalPrice) { - data.totalPrice = this.checkoutPrice; - } - - if (this.checkoutPrice < this.options.minBalance) { - // Add free input field, hide and disable unchecked checkbox payment method and all radio button payment methods - this._disablePaymentMethods(); - } else { - // Remove free input field, show all payment method - this._enablePaymentMethods(); - } - } - }); - - this._on(events); - - this.element.find(this.options.payment.form).validation({ - errorPlacement: function (error, element) { - if (element.attr('data-validate') && element.attr('data-validate').indexOf('validate-cc-ukss') >= 0) { - element.parents('form').find('[data-validation-msg="validate-cc-ukss"]').html(error); - } else { - element.after(error); - } - } - }); - }, - - /** - * Display payment details when payment method radio button is checked - * @private - * @param {EventObject} e - */ - _paymentMethodHandler: function (e) { - var _this = $(e.target), - parentsDl = _this.closest(this.options.methodsListContainer); - parentsDl.find(this.options.methodOn).prop('checked', false); - _this.prop('checked', true); - parentsDl.find(this.options.methodDescription).hide().find('[name^="payment["]').prop('disabled', true); - _this.parent().nextUntil(this.options.methodContainer).find(this.options.methodDescription).show().find('[name^="payment["]').prop('disabled', false); - }, - - /** - * make sure one payment method is selected - * @private - * @return {Boolean} - */ - _validatePaymentMethod: function () { - var methods = this.element.find('[name^="payment["]'); - - if (methods.length === 0) { - alert({ - content: $.mage.__('We can\'t complete your order because you don\'t have a payment method set up.') - }); - - return false; - } - - if (this.checkoutPrice < this.options.minBalances) { - return true; - } else if (methods.filter('input:radio:checked').length) { - return true; - } - - alert({ - content: $.mage.__('Please choose a payment method.') - }); - - return false; - }, - - /** - * Disable and enable payment methods - * @private - */ - _disablePaymentMethods: function () { - var paymentForm = $(this.options.payment.form), - tmpl = this.freeInputTmpl({ - data: {} - }); - - paymentForm.find('input[name="payment[method]"]').prop('disabled', true); - paymentForm.find(this.options.payment.methodsContainer).find('[name^="payment["]').prop('disabled', true); - paymentForm.find('input[id^="use"][name^="payment[use"]:not(:checked)').prop('disabled', true).parent(); - paymentForm.find(this.options.payment.freeInput.selector).remove(); - - $(tmpl).appendTo(paymentForm); - }, - - /** - * Enable and enable payment methods - * @private - */ - _enablePaymentMethods: function () { - var paymentForm = $(this.options.payment.form); - - paymentForm.find('input[name="payment[method]"]').prop('disabled', false); - paymentForm.find('input[name="payment[method]"]:checked').trigger('click'); - paymentForm.find(this.options.payment.methodsContainer).show(); - paymentForm.find('input[id^="use"][name^="payment[use"]:not(:checked)').prop('disabled', false).parent().show(); - paymentForm.find(this.options.payment.freeInput.selector).remove(); - } - }); - - return $.mage.opcPaymentInfo; -}); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/opc-shipping-info.js b/app/code/Magento/Checkout/view/frontend/web/js/opc-shipping-info.js deleted file mode 100644 index bf3ef59bcf42938b341150c75d6df91d497be10f..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/js/opc-shipping-info.js +++ /dev/null @@ -1,81 +0,0 @@ -/** - * @category one page checkout third step - * @package mage - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*jshint browser:true jquery:true*/ -/*global alert*/ -/** - * @removeCandidate - */ -define([ - "jquery", - "jquery/ui", - "Magento_Checkout/js/opc-billing-info", - "mage/validation" -], function($){ - 'use strict'; - - // Extension for mage.opcheckout - third section(Shipping Information) in one page checkout accordion - $.widget('mage.opcShippingInfo', $.mage.opcBillingInfo, { - options: { - shipping: { - form: '#co-shipping-form', - continueSelector:'#shipping [data-role=opc-continue]', - addressDropdownSelector: '#shipping\\:address-select', - newAddressFormSelector: '#shipping-new-address-form', - copyBillingSelector: '#shipping\\:same_as_billing', - countrySelector: '#shipping\\:country_id' - } - }, - - _create: function() { - this._super(); - var events = {}; - var onInputPropChange = function() { - $(this.options.shipping.copyBillingSelector).prop('checked', false); - }; - events['change ' + this.options.shipping.addressDropdownSelector] = function(e) { - $(this.options.shipping.newAddressFormSelector).toggle(!$(e.target).val()); - onInputPropChange.call(this); - }; - // for guest checkout - events['input ' + this.options.shipping.form + ' :input[name]'] = onInputPropChange; - events['propertychange ' + this.options.shipping.form + ' :input[name]'] = onInputPropChange; - events['click ' + this.options.shipping.copyBillingSelector] = function(e) { - if ($(e.target).is(':checked')) { - this._billingToShipping(); - } - }; - events['click ' + this.options.shipping.continueSelector] = function() { - if ($(this.options.shipping.form).validation && $(this.options.shipping.form).validation('isValid')) { - this._ajaxContinue(this.options.shipping.saveUrl, $(this.options.shipping.form).serialize(), false, function() { - //Trigger indicating shipping save. eg. GiftMessage listens to this to inject gift options - this.element.trigger('shippingSave'); - }); - } - }; - this._on(events); - - this.element.find(this.options.shipping.form).validation(); - }, - - /** - * Copy billing address info to shipping address - * @private - */ - _billingToShipping: function() { - $(':input[name]', this.options.billing.form).each($.proxy(function(key, value) { - var fieldObj = $(value.id.replace('billing:', '#shipping\\:')); - fieldObj.val($(value).val()); - if (fieldObj.is("select")) { - fieldObj.trigger('change'); - } - }, this)); - $(this.options.shipping.copyBillingSelector).prop('checked', true); - } - }); - - return $.mage.opcShippingInfo; -}); \ No newline at end of file diff --git a/app/code/Magento/Checkout/view/frontend/web/js/opc-shipping-method.js b/app/code/Magento/Checkout/view/frontend/web/js/opc-shipping-method.js deleted file mode 100644 index 505db47ab57901c4dcc73330ed27ebf66d0a4968..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/js/opc-shipping-method.js +++ /dev/null @@ -1,85 +0,0 @@ -/** - * @category one page checkout fourth step - * @package mage - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*jshint browser:true jquery:true*/ -/*global alert*/ -/** - * @removeCandidate - */ -define([ - "jquery", - 'Magento_Ui/js/modal/alert', - "jquery/ui", - "Magento_Checkout/js/opc-shipping-info", - "mage/validation", - "mage/translate" -], function($, alert){ - 'use strict'; - - // Extension for mage.opcheckout - fourth section(Shipping Method) in one page checkout accordion - $.widget('mage.opcShippingMethod', $.mage.opcShippingInfo, { - options: { - shippingMethod: { - form: '#co-shipping-method-form', - continueSelector: '#opc-shipping_method [data-role=opc-continue]' - } - }, - - _create: function() { - this._super(); - var events = {}; - events['click ' + this.options.shippingMethod.continueSelector] = function() { - if (this._validateShippingMethod()&& - $(this.options.shippingMethod.form).validation && - $(this.options.shippingMethod.form).validation('isValid')) { - this._ajaxContinue(this.options.shippingMethod.saveUrl, $(this.options.shippingMethod.form).serialize()); - } - }; - $.extend(events, { - 'click input[name=shipping_method]': function(e) { - var selectedPrice = this.shippingCodePrice[$(e.target).val()] || 0, - oldPrice = this.shippingCodePrice[this.currentShippingMethod] || 0; - this.checkoutPrice = this.checkoutPrice - oldPrice + selectedPrice; - this.currentShippingMethod = $(e.target).val(); - }, - 'contentUpdated': function() { - this.currentShippingMethod = this.element.find('input[name="shipping_method"]:checked').val(); - this.shippingCodePrice = this.element.find('[data-shipping-code-price]').data('shipping-code-price'); - } - }); - this._on(events); - - this.element.find(this.options.shippingMethod.form).validation(); - }, - - /** - * Make sure at least one shipping method is selected - * @return {Boolean} - * @private - */ - _validateShippingMethod: function() { - var methods = this.element.find('[name="shipping_method"]'); - if (methods.length === 0) { - alert({ - content: $.mage.__('We can\'t ship to this address. Please enter another address or edit this one.') - }); - - return false; - } - - if (methods.filter(':checked').length) { - return true; - } - alert({ - content:$.mage.__('Please specify a shipping method.') - }); - - return false; - } - }); - - return $.mage.opcShippingMethod; -}); \ No newline at end of file diff --git a/app/code/Magento/Checkout/view/frontend/web/js/opcheckout.js b/app/code/Magento/Checkout/view/frontend/web/js/opcheckout.js deleted file mode 100644 index 570dd9edf2d892eb39266dc467fc85f2861c84fc..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/js/opcheckout.js +++ /dev/null @@ -1,645 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*jshint browser:true*/ -/*global alert*/ -/** - * @removeCandidate - */ -define([ - 'jquery', - 'mage/template', - 'Magento_Ui/js/modal/alert', - 'jquery/ui', - 'mage/validation', - 'mage/translate' -], function ($, mageTemplate, alert) { - 'use strict'; - - // Base widget, handle ajax events and first section(Checkout Method) in one page checkout accordion - $.widget('mage.opcheckout', { - options: { - checkout: { - loginGuestSelector: '#login\\:guest', - loginRegisterSelector: '#login\\:register', - loginFormSelector: '#login-form', - continueSelector: '#onepage-guest-register-button', - registerCustomerPasswordSelector: '#co-billing-form .field.password,#co-billing-form .field.confirm', - suggestRegistration: false - }, - sectionSelectorPrefix: '#opc-', - billingSection: 'billing', - ajaxLoaderPlaceButton: false, - updateSelectorPrefix: '#checkout-', - updateSelectorSuffix: '-load', - backSelector: '.action.back', - minBalance: 0.0001, - methodsListContainer: 'dl', - methodContainer: 'dt', - methodDescription: 'dd ul', - methodOn: 'dt input:radio' - }, - - _create: function () { - var events = {}; - - this.checkoutPrice = this.options.quoteBaseGrandTotal; - - if (this.options.checkout.suggestRegistration) { - $(this.options.checkout.loginGuestSelector).prop('checked', false); - $(this.options.checkout.loginRegisterSelector).prop('checked', true); - } - - events['click ' + this.options.checkout.continueSelector] = function (e) { - this._continue($(e.currentTarget)); - }; - - events['click ' + this.options.backSelector] = function () { - this.element.trigger('enableSection', { - selector: '#' + this.element.find('.active').prev().attr('id') - }); - }; - - $(document).on({ - 'ajaxError': this._ajaxError.bind(this) - }); - - $.extend(events, { - showAjaxLoader: '_ajaxSend', - hideAjaxLoader: '_ajaxComplete', - gotoSection: function (e, section) { - this._ajaxUpdateProgress(section); - this.element.trigger('enableSection', { - selector: this.options.sectionSelectorPrefix + section - }); - }, - 'click [data-action=login-form-submit]': function () { - $(this.options.checkout.loginFormSelector).submit(); - } - }); - - this._on(events); - - this._on($(this.options.checkoutProgressContainer), { - 'click [data-goto-section]': function (e) { - var gotoSection = $(e.target).data('goto-section'); - - this._ajaxUpdateProgress(gotoSection); - - this.element.trigger('enableSection', { - selector: this.options.sectionSelectorPrefix + gotoSection - }); - - return false; - } - }); - }, - - /** - * Callback function for before ajax send event(global) - * @private - */ - _ajaxSend: function () { - var loader; - - this.element.addClass('loading'); - - loader = this.element.find('.please-wait').show(); - - if (this.options.ajaxLoaderPlaceButton) { - loader.siblings('.button').hide(); - } - }, - - /** - * Callback function for ajax complete event(global) - * @private - */ - _ajaxComplete: function () { - this.element.removeClass('loading'); - this.element.find('.please-wait').hide(); - - if (this.options.ajaxLoaderPlaceButton) { - this.element.find('.button').show(); - } - }, - - /** - * ajax error for all onepage checkout ajax calls - * @private - */ - _ajaxError: function () { - window.location.href = this.options.failureUrl; - }, - - /** - * callback function when continue button is clicked - * @private - * @param elem - continue button - * @return {Boolean} - */ - _continue: function (elem) { - var json = elem.data('checkout'); - - if (json.isGuestCheckoutAllowed) { - if ($(this.options.checkout.loginGuestSelector).is(':checked')) { - this._ajaxContinue(this.options.checkout.saveUrl, { - method: 'guest' - }, this.options.billingSection); - - this.element.find(this.options.checkout.registerCustomerPasswordSelector).hide(); - } else if ($(this.options.checkout.loginRegisterSelector).is(':checked')) { - this._ajaxContinue(this.options.checkout.saveUrl, { - method: 'register' - }, this.options.billingSection); - - this.element.find(this.options.checkout.registerCustomerPasswordSelector).show(); - } else { - alert({ - content: $.mage.__('Please create an account or check out as a guest.') - }); - - return false; - } - } else { - if (json.registrationUrl) { - window.location.href = json.registrationUrl; - } - } - - this.element.trigger('login'); - }, - - /** - * Ajax call to save checkout info to backend and enable next section in accordion - * @private - * @param url - ajax url - * @param data - post data for ajax call - * @param gotoSection - the section needs to show after ajax call - * @param successCallback - custom callback function in ajax success - */ - _ajaxContinue: function (url, data, gotoSection, successCallback) { - $.ajax({ - url: url, - type: 'post', - context: this, - data: data, - dataType: 'json', - beforeSend: this._ajaxSend, - complete: this._ajaxComplete, - success: function (response) { - if (successCallback) { - successCallback.call(this, response); - } - - if ($.type(response) === 'object' && !$.isEmptyObject(response)) { - if (response.error) { - var msg = response.message || response.error_messages; - - if (msg) { - if ($.type(msg) === 'array') { - msg = msg.join("\n"); - } - - $(this.options.countrySelector).trigger('change'); - - alert({ - content: msg - }); - } else { - alert({ - content: response.error - }); - } - - return; - } - - if (response.redirect) { - $.mage.redirect(response.redirect); - - return false; - } else if (response.success) { - $.mage.redirect(this.options.review.successUrl); - - return false; - } - - if (response.update_section) { - if (response.update_section.name === 'payment-method' && response.update_section.html.indexOf('data-checkout-price')) { - this.element.find(this.options.payment.form).find('[data-checkout-price]').remove(); - } - $(this.options.updateSelectorPrefix + response.update_section.name + this.options.updateSelectorSuffix) - .html($(response.update_section.html)).trigger('contentUpdated'); - } - - if (response.duplicateBillingInfo) { - $(this.options.shipping.copyBillingSelector).prop('checked', true).trigger('click'); - $(this.options.shipping.addressDropdownSelector).val($(this.options.billing.addressDropdownSelector).val()).change(); - } - - if (response.goto_section) { - this.element.trigger('gotoSection', response.goto_section); - } - } else { - this.element.trigger('gotoSection', gotoSection); - } - } - }); - }, - - /** - * Update progress sidebar content - * @private - * @param {*} toStep - */ - _ajaxUpdateProgress: function (toStep) { - if (toStep) { - $.ajax({ - url: this.options.progressUrl, - type: 'get', - async: false, - cache: false, - context: this, - data: toStep ? { - toStep: toStep - } : null, - success: function (response) { - $(this.options.checkoutProgressContainer).html(response); - } - }); - } - } - }); - - // Extension for mage.opcheckout - second section(Billing Information) in one page checkout accordion - $.widget('mage.opcheckout', $.mage.opcheckout, { - options: { - billing: { - addressDropdownSelector: '#billing\\:address-select', - newAddressFormSelector: '#billing-new-address-form', - continueSelector: '#billing-buttons-container .button', - form: '#co-billing-form' - } - }, - - _create: function () { - var events; - - this._super(); - - events = {}; - - events['change ' + this.options.billing.addressDropdownSelector] = function (e) { - this.element.find(this.options.billing.newAddressFormSelector).toggle(!$(e.target).val()); - }; - - events['click ' + this.options.billing.continueSelector] = function () { - if ($(this.options.billing.form).validation && $(this.options.billing.form).validation('isValid')) { - this._billingSave(); - } - }; - - this._on(events); - - this.element.find(this.options.billing.form).validation(); - }, - - _billingSave: function () { - this._ajaxContinue(this.options.billing.saveUrl, $(this.options.billing.form).serialize(), false, function () { - //Trigger indicating billing save. eg. GiftMessage listens to this to inject gift options - this.element.trigger('billingSave'); - }); - } - }); - - // Extension for mage.opcheckout - third section(Shipping Information) in one page checkout accordion - $.widget('mage.opcheckout', $.mage.opcheckout, { - options: { - shipping: { - form: '#co-shipping-form', - addressDropdownSelector: '#shipping\\:address-select', - newAddressFormSelector: '#shipping-new-address-form', - copyBillingSelector: '#shipping\\:same_as_billing', - countrySelector: '#shipping\\:country_id', - continueSelector: '#shipping-buttons-container .button' - } - }, - - _create: function () { - var events, - onInputPropChange; - - this._super(); - - events = {}; - - onInputPropChange = function () { - $(this.options.shipping.copyBillingSelector).prop('checked', false); - }; - - events['change ' + this.options.shipping.addressDropdownSelector] = function (e) { - $(this.options.shipping.newAddressFormSelector).toggle(!$(e.target).val()); - onInputPropChange.call(this); - }; - - // for guest checkout - events['input ' + this.options.shipping.form + ' :input[name]'] = onInputPropChange; - - events['propertychange ' + this.options.shipping.form + ' :input[name]'] = onInputPropChange; - - events['click ' + this.options.shipping.copyBillingSelector] = function (e) { - if ($(e.target).is(':checked')) { - this._billingToShipping(); - } - }; - - events['click ' + this.options.shipping.continueSelector] = function () { - if ($(this.options.shipping.form).validation && $(this.options.shipping.form).validation('isValid')) { - this._ajaxContinue(this.options.shipping.saveUrl, $(this.options.shipping.form).serialize(), false, function () { - //Trigger indicating shipping save. eg. GiftMessage listens to this to inject gift options - this.element.trigger('shippingSave'); - }); - } - }; - - this._on(events); - - this.element.find(this.options.shipping.form).validation(); - }, - - /** - * Copy billing address info to shipping address - * @private - */ - _billingToShipping: function () { - $(':input[name]', this.options.billing.form).each($.proxy(function (key, value) { - var fieldObj = $(value.id.replace('billing:', '#shipping\\:')); - - fieldObj.val($(value).val()); - - if (fieldObj.is('select')) { - fieldObj.trigger('change'); - } - }, this)); - - $(this.options.shipping.copyBillingSelector).prop('checked', true); - } - }); - - // Extension for mage.opcheckout - fourth section(Shipping Method) in one page checkout accordion - $.widget('mage.opcheckout', $.mage.opcheckout, { - options: { - shippingMethod: { - continueSelector: '#shipping-method-buttons-container .button', - form: '#co-shipping-method-form' - } - }, - - _create: function () { - this._super(); - var events = {}; - events['click ' + this.options.shippingMethod.continueSelector] = function () { - if (this._validateShippingMethod() && - $(this.options.shippingMethod.form).validation && - $(this.options.shippingMethod.form).validation('isValid')) { - this._ajaxContinue(this.options.shippingMethod.saveUrl, $(this.options.shippingMethod.form).serialize()); - } - }; - $.extend(events, { - 'click input[name=shipping_method]': function (e) { - var selectedPrice = this.shippingCodePrice[$(e.target).val()] || 0, - oldPrice = this.shippingCodePrice[this.currentShippingMethod] || 0; - this.checkoutPrice = this.checkoutPrice - oldPrice + selectedPrice; - this.currentShippingMethod = $(e.target).val(); - }, - 'contentUpdated': function () { - this.currentShippingMethod = this.element.find('input[name="shipping_method"]:checked').val(); - this.shippingCodePrice = this.element.find('[data-shipping-code-price]').data('shipping-code-price'); - } - }); - this._on(events); - - this.element.find(this.options.shippingMethod.form).validation(); - }, - - /** - * Make sure at least one shipping method is selected - * @return {Boolean} - * @private - */ - _validateShippingMethod: function () { - var methods = this.element.find('[name="shipping_method"]'); - - if (methods.length === 0) { - alert({ - content: $.mage.__('We can\'t ship to this address. Please choose another address or edit the current one.') - }); - - return false; - } - - if (methods.filter(':checked').length) { - return true; - } - - alert({ - content: $.mage.__('Please specify a shipping method.') - }); - - return false; - } - }); - - // Extension for mage.opcheckout - fifth section(Payment Information) in one page checkout accordion - $.widget('mage.opcheckout', $.mage.opcheckout, { - options: { - payment: { - continueSelector: '#payment-buttons-container .button', - form: '#co-payment-form', - methodsContainer: '#checkout-payment-method-load', - freeInput: { - tmpl: '<input id="hidden-free" type="hidden" name="payment[method]" value="free">', - selector: '#hidden-free' - } - } - }, - - _create: function () { - var events; - - this._super(); - - this.freeInputTmpl = mageTemplate(this.options.payment.freeInput.tmpl); - - events = {}; - - events['click ' + this.options.payment.continueSelector] = function () { - if (this._validatePaymentMethod() && - $(this.options.payment.form).validation && - $(this.options.payment.form).validation('isValid')) { - this._ajaxContinue(this.options.payment.saveUrl, $(this.options.payment.form).serialize()); - } - }; - - events['contentUpdated ' + this.options.payment.form] = function () { - var checkoutPrice; - - $(this.options.payment.form).find('dd [name^="payment["]').prop('disabled', true); - - checkoutPrice = this.element.find(this.options.payment.form).find('[data-checkout-price]').data('checkout-price'); - - if ($.isNumeric(checkoutPrice)) { - this.checkoutPrice = checkoutPrice; - } - - if (this.checkoutPrice < this.options.minBalance) { - this._disablePaymentMethods(); - } else { - this._enablePaymentMethods(); - } - }; - - events['click ' + this.options.payment.form + ' dt input:radio'] = '_paymentMethodHandler'; - - $.extend(events, { - updateCheckoutPrice: function (event, data) { - if (data.price) { - this.checkoutPrice += data.price; - } - - if (data.totalPrice) { - data.totalPrice = this.checkoutPrice; - } - - if (this.checkoutPrice < this.options.minBalance) { - // Add free input field, hide and disable unchecked checkbox payment method and all radio button payment methods - this._disablePaymentMethods(); - } else { - // Remove free input field, show all payment method - this._enablePaymentMethods(); - } - } - }); - - this._on(events); - - this.element.find(this.options.payment.form).validation({ - errorPlacement: function (error, element) { - if (element.attr('data-validate') && element.attr('data-validate').indexOf('validate-cc-ukss') >= 0) { - element.parents('form').find('[data-validation-msg="validate-cc-ukss"]').html(error); - } else { - element.after(error); - } - } - }); - }, - - /** - * Display payment details when payment method radio button is checked - * @private - * @param {EventObject} e - */ - _paymentMethodHandler: function (e) { - var _this = $(e.target), - parentsDl = _this.closest(this.options.methodsListContainer); - parentsDl.find(this.options.methodOn).prop('checked', false); - _this.prop('checked', true); - parentsDl.find(this.options.methodDescription).hide().find('[name^="payment["]').prop('disabled', true); - _this.closest(this.options.methodContainer) - .nextUntil(this.options.methodContainer) - .find(this.options.methodDescription).show().find('[name^="payment["]').prop('disabled', false); - }, - - /** - * make sure one payment method is selected - * @private - * @return {Boolean} - */ - _validatePaymentMethod: function () { - var methods = this.element.find('[name^="payment["]'); - - if (methods.length === 0) { - alert({ - content: $.mage.__('We can\'t complete your order because you don\'t have a payment method set up.') - }); - - return false; - } - - if (this.checkoutPrice < this.options.minBalance) { - return true; - } else if (methods.filter('input:radio:checked').length) { - return true; - } - - alert({ - content: $.mage.__('Please choose a payment method.') - }); - - return false; - }, - - /** - * Disable and enable payment methods - * @private - */ - _disablePaymentMethods: function () { - var paymentForm = $(this.options.payment.form), - tmpl = this.freeInputTmpl({ - data: {} - }); - - paymentForm.find('input[name="payment[method]"]').prop('disabled', true); - paymentForm.find(this.options.payment.methodsContainer).find('[name^="payment["]').prop('disabled', true); - paymentForm.find('input[id^="use"][name^="payment[use"]:not(:checked)').prop('disabled', true).parent(); - paymentForm.find(this.options.payment.freeInput.selector).remove(); - - $(tmpl).appendTo(paymentForm); - }, - - /** - * Enable and enable payment methods - * @private - */ - _enablePaymentMethods: function () { - var paymentForm = $(this.options.payment.form); - paymentForm.find('input[name="payment[method]"]').prop('disabled', false); - paymentForm.find('input[name="payment[method]"]:checked').trigger('click'); - paymentForm.find(this.options.payment.methodsContainer).show(); - paymentForm.find('input[id^="use"][name^="payment[use"]:not(:checked)').prop('disabled', false).parent().show(); - paymentForm.find(this.options.payment.freeInput.selector).remove(); - } - }); - - // Extension for mage.opcheckout - last section(Order Review) in one page checkout accordion - $.widget('mage.opcheckout', $.mage.opcheckout, { - options: { - review: { - continueSelector: '#review-buttons-container .button', - container: '#opc-review', - agreementFormSelector: '#checkout-agreements input[type="checkbox"]' - } - }, - - _create: function () { - this._super(); - var events = {}; - events['click ' + this.options.review.continueSelector] = this._saveOrder; - events['saveOrder' + this.options.review.container] = this._saveOrder; - this._on(events); - }, - - _saveOrder: function () { - if ($(this.options.payment.form).validation && - $(this.options.payment.form).validation('isValid')) { - this._ajaxContinue( - this.options.review.saveUrl, - $(this.options.payment.form).serialize() + '&' + $(this.options.review.agreementFormSelector).serialize()); - } - } - }); - - return $.mage.opcheckout; -}); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/payment-authentication.js b/app/code/Magento/Checkout/view/frontend/web/js/payment-authentication.js deleted file mode 100644 index 8b03193bb79c95626391cfb4d75691def2f3a1cd..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/js/payment-authentication.js +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*jshint jquery:true*/ -/** - * @removeCandidate - */ -define([ - "jquery", - "jquery/ui" -], function($){ - "use strict"; - - $.widget('mage.paymentAuthentication', { - options : { - bodySelector: '[data-container="body"]' - }, - - _create: function () { - // add a trigger on the body for payment authentication state changes - this.element.closest(this.options.bodySelector).on("paymentAuthentication", $.proxy(this._paymentmentAthenticationTrigger, this)); - }, - - /** - * This method processes the paymentAuthentication actions. - */ - _paymentmentAthenticationTrigger: function (event, data) { - if (data.state === 'start') { - this.element.hide(); - } else { - this.element.show(); - } - } - }); - - return $.mage.paymentAuthentication; -}); \ No newline at end of file diff --git a/app/code/Magento/Checkout/view/frontend/web/js/proceed-to-checkout.js b/app/code/Magento/Checkout/view/frontend/web/js/proceed-to-checkout.js index 7a6b4e88be10c65b823c7616ac0e46a3ed5720a1..7754719a506ff406fb18b2b6f3a92aff3366073c 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/proceed-to-checkout.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/proceed-to-checkout.js @@ -8,15 +8,19 @@ define([ 'Magento_Customer/js/model/authentication-popup', 'Magento_Customer/js/customer-data' ], - function($, authenticationPopup, customerData) { + function ($, authenticationPopup, customerData) { + 'use strict'; + return function (config, element) { - $(element).click(function(event) { - event.preventDefault(); + $(element).click(function (event) { var cart = customerData.get('cart'), customer = customerData.get('customer'); + event.preventDefault(); + if (!customer().firstname && !cart().isGuestCheckoutAllowed) { authenticationPopup.showModal(); + return false; } location.href = config.checkoutUrl; diff --git a/app/code/Magento/Checkout/view/frontend/web/js/sidebar.js b/app/code/Magento/Checkout/view/frontend/web/js/sidebar.js index 34501bbeb107889899f1e26478fa41aadb772847..f503e5be641c3af6dcd5307842610dd3da77fd1c 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/sidebar.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/sidebar.js @@ -53,6 +53,9 @@ define([ actions: { confirm: function () { self._removeItem($(event.currentTarget)); + }, + always: function (event) { + event.stopImmediatePropagation(); } } }); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js b/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js index 80d9a5982a6ab575ab68f6500ec72d0e2117d788..b69365ebc0f17eedcdc4b039c235e8286ce3bf73 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js @@ -82,11 +82,14 @@ define( }); quote.billingAddress.subscribe(function (newAddress) { - this.isAddressSameAsShipping( - newAddress != null && - newAddress.getCacheKey() == quote.shippingAddress().getCacheKey() && - !quote.isVirtual() - ); + if (quote.isVirtual()) { + this.isAddressSameAsShipping(false); + } else { + this.isAddressSameAsShipping( + newAddress != null && + newAddress.getCacheKey() == quote.shippingAddress().getCacheKey() + ); + } if (newAddress != null && newAddress.saveInAddressBook !== undefined) { this.saveInAddressBook(newAddress.saveInAddressBook); @@ -115,6 +118,9 @@ define( useShippingAddress: function () { if (this.isAddressSameAsShipping()) { selectBillingAddress(quote.shippingAddress()); + if (window.checkoutConfig.reloadOnBillingAddress) { + setBillingAddressAction(globalMessageList); + } this.isAddressDetailsVisible(true); } else { lastSelectedBillingAddress = quote.billingAddress(); @@ -142,12 +148,13 @@ define( if (!this.source.get('params.invalid')) { var addressData = this.source.get(this.dataScopePrefix), - newBillingAddress = createBillingAddress(addressData); + newBillingAddress; - if (this.isCustomerLoggedIn && !this.customerHasAddresses) { + if (customer.isLoggedIn() && !this.customerHasAddresses) { this.saveInAddressBook(true); } addressData.save_in_address_book = this.saveInAddressBook(); + newBillingAddress = createBillingAddress(addressData); // New address must be selected as a billing address selectBillingAddress(newBillingAddress); diff --git a/app/code/Magento/Checkout/view/frontend/web/template/cart/totals/grand-total.html b/app/code/Magento/Checkout/view/frontend/web/template/cart/totals/grand-total.html index e4ac4affabb341b664f3e868b6d298989fbf416b..751e4eaaa51425b29f2c8dce5478da8b7541fb2d 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/cart/totals/grand-total.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/cart/totals/grand-total.html @@ -6,7 +6,7 @@ --> <tr class="grand totals"> <th class="mark" colspan="1" scope="row"> - <strong data-bind="text: $t(title)"></strong> + <strong data-bind="text: title"></strong> </th> <td class="amount" data-th="Order Total"> <strong><span class="price" data-bind="text: getValue()"></span></strong> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/cart/totals/shipping.html b/app/code/Magento/Checkout/view/frontend/web/template/cart/totals/shipping.html index 17c41206ab4e65e210343ce60b15c53e041f7073..7cf6d85f66884f5e2f0565287fe7f20689ff923a 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/cart/totals/shipping.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/cart/totals/shipping.html @@ -6,7 +6,7 @@ --> <!-- ko if: isCalculated() --> <tr class="totals shipping excl"> - <th class="mark" colspan="1" scope="row" data-bind="text: $t(title) + ' (' + $t(getShippingMethodTitle()) + ')'"></th> + <th class="mark" colspan="1" scope="row" data-bind="text: title + ' (' + getShippingMethodTitle() + ')'"></th> <td class="amount"> <span class="price" data-bind="text: getValue()"></span> </td> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/cart/totals/subtotal.html b/app/code/Magento/Checkout/view/frontend/web/template/cart/totals/subtotal.html index b5b7e2ecf683a8342a869bfcebded09457a60d20..be761940327f8e43fe3c1c46a8db537d013bc2cb 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/cart/totals/subtotal.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/cart/totals/subtotal.html @@ -5,7 +5,7 @@ */ --> <tr class="totals sub"> - <th class="mark" colspan="1" scope="row" data-bind="text: $t(title)"></th> + <th class="mark" colspan="1" scope="row" data-bind="text: title"></th> <td class="amount" data-th="Subtotal"> <span class="price" data-bind="text: getValue()"></span> </td> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/estimation.html b/app/code/Magento/Checkout/view/frontend/web/template/estimation.html index 36009ab7b4634ab66da8c232712b33c6aa052fd1..f8b396939cef704fceedbda2413f5b3dd848614e 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/estimation.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/estimation.html @@ -7,7 +7,7 @@ <div class="opc-estimated-wrapper" data-bind="blockLoader: isLoading"> <div class="estimated-block"> <span class="estimated-label" data-bind="i18n: 'Estimated Total'"></span> - <span class="estimated-price" data-bind="i18n: getValue()"></span> + <span class="estimated-price" data-bind="text: getValue()"></span> </div> <div class="minicart-wrapper"> <button type="button" class="action showcart" data-bind="click: showSidebar" data-toggle="opc-summary"> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/payment.html b/app/code/Magento/Checkout/view/frontend/web/template/payment.html index d73f8ff5cb3434721a62ef47bff0f27efb6fe9e9..964be62c167b5dc2db04d1348d4e395c41120afa 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/payment.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/payment.html @@ -5,7 +5,7 @@ */ --> <li id="payment" role="presentation" class="checkout-payment-method" data-bind="fadeVisible: isVisible"> - <div class="step-title" data-bind="i18n: title" data-role="title"></div> + <div class="step-title" data-bind="text: title" data-role="title"></div> <div id="checkout-step-payment" class="step-content" data-role="content" diff --git a/app/code/Magento/Checkout/view/frontend/web/template/progress-bar.html b/app/code/Magento/Checkout/view/frontend/web/template/progress-bar.html index 6276cae43639e4c7b873f6184c49b47455911286..7e51c678147ebc4911738ccd18a3735d4ebb2f3c 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/progress-bar.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/progress-bar.html @@ -7,7 +7,7 @@ <ul class="opc-progress-bar"> <!-- ko foreach: { data: steps().sort(sortItems), as: 'item' } --> <li class="opc-progress-bar-item" data-bind="css: item.isVisible() ? '_active' : ($parent.isProcessed(item) ? '_complete' : '')"> - <span data-bind="i18n: item.title, click: $parent.navigateTo"></span> + <span data-bind="text: item.title, click: $parent.navigateTo"></span> </li> <!-- /ko --> </ul> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/registration.html b/app/code/Magento/Checkout/view/frontend/web/template/registration.html index 1cb610134a90caf59dcf99c6982563142c9df138..53c1248a210ab36f26f9d238bf38fd168d0aa9ba 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/registration.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/registration.html @@ -13,6 +13,6 @@ </form> <!-- /ko --> <!-- ko if: accountCreated --> - <p data-bind="i18n: $t('A letter with further instructions will be sent to your email.')"></p> + <p data-bind="i18n: 'A letter with further instructions will be sent to your email.'"></p> <!-- /ko --> </div> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping-information.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping-information.html index 0e6ad40d317031dddbe7b120901432bf3e7bca8e..a7c4edce8a64c0eb026019f78a73b9283692d2d4 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/shipping-information.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/shipping-information.html @@ -28,7 +28,7 @@ </button> </div> <div class="shipping-information-content"> - <span class="value" data-bind="i18n: getShippingMethodTitle()"></span> + <span class="value" data-bind="text: getShippingMethodTitle()"></span> </div> </div> </div> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping.html index 7c981e83bc97859cef4e11ca96ebf8b679262f48..91960304668539f2d4b6c09b5f592ad948da3381 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/shipping.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/shipping.html @@ -112,17 +112,17 @@ </td> <td class="col col-method" - data-bind="i18n: method.method_title, attr: {'id': 'label_method_' + method.method_code + '_' + method.carrier_code}"></td> + data-bind="text: method.method_title, attr: {'id': 'label_method_' + method.method_code + '_' + method.carrier_code}"></td> <td class="col col-carrier" - data-bind="i18n: method.carrier_title, attr: {'id': 'label_carrier_' + method.method_code + '_' + method.carrier_code}"></td> + data-bind="text: method.carrier_title, attr: {'id': 'label_carrier_' + method.method_code + '_' + method.carrier_code}"></td> </tr> <!-- ko if: method.error_message --> <tr class="row row-error"> <td class="col col-error" colspan="4"> <div class="message error"> - <div data-bind="i18n: method.error_message"></div> + <div data-bind="text: method.error_message"></div> </div> <span class="no-display"> <input name="shipping_method" type="radio" data-bind="attr: {'value' : method.method_code, 'id': 's_method_' + method.method_code}"/> @@ -143,7 +143,7 @@ </div> <!-- ko if: errorValidationMessage().length > 0 --> <div class="message notice"> - <span><!-- ko i18n: errorValidationMessage()--><!-- /ko --></span> + <span><!-- ko text: errorValidationMessage()--><!-- /ko --></span> </div> <!-- /ko --> <div class="actions-toolbar" id="shipping-method-buttons-container"> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/summary/grand-total.html b/app/code/Magento/Checkout/view/frontend/web/template/summary/grand-total.html index 107907b157acfd2ef31db7fb9bfd08e7d5659551..009c7e01435019d493d9f6ea93a8321ebd19ddb5 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/summary/grand-total.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/summary/grand-total.html @@ -6,9 +6,9 @@ --> <!-- ko if: isDisplayed() --> <tr> - <td colspan="2" data-bind="i18n: title"></td> + <td colspan="2" data-bind="text: title"></td> <td class="col grandtotal"> - <span data-bind ="text: getValue(), attr:{'data-label': $t(title)}"></span> + <span data-bind ="text: getValue(), attr:{'data-label': title}"></span> <!-- ko foreach: elems() --> <!-- ko template: getTemplate() --><!-- /ko --> <!-- /ko --> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/summary/item/details.html b/app/code/Magento/Checkout/view/frontend/web/template/summary/item/details.html index 05b39a8f11e00bc8ea5f9953422bde9d6d78e6e1..69f698a7a5a4a1c0b9dc7a40ba8928d5e0d16b04 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/summary/item/details.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/summary/item/details.html @@ -12,7 +12,7 @@ <div class="product-item-inner"> <div class="product-item-name-block"> - <strong class="product-item-name" data-bind="i18n: $parent.name"></strong> + <strong class="product-item-name" data-bind="text: $parent.name"></strong> <div class="details-qty"> <span class="label"><!-- ko i18n: 'Qty' --><!-- /ko --></span> <span class="value" data-bind="text: $parent.qty"></span> @@ -30,7 +30,7 @@ <strong class="subtitle"><!-- ko i18n: 'Options Details' --><!-- /ko --></strong> <dl class="item-options"> <!--ko foreach: JSON.parse($parent.options)--> - <dt class="label" data-bind="i18n: label"></dt> + <dt class="label" data-bind="text: label"></dt> <!-- ko if: ($data.full_view)--> <dd class="values" data-bind="html: full_view"></dd> <!-- /ko --> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/summary/shipping.html b/app/code/Magento/Checkout/view/frontend/web/template/summary/shipping.html index f3a22cef746e52c1147a86475bc4f48fc0ec2713..a6dc09dc74656e0d31d1c52aeabb7814c6c7a7bd 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/summary/shipping.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/summary/shipping.html @@ -7,17 +7,17 @@ <!-- ko if: quoteIsVirtual == 0 --> <tr class="totals shipping excl"> <th class="mark" scope="row"> - <span class="label" data-bind="i18n: title"></span> - <span class="value" data-bind="i18n: getShippingMethodTitle()"></span> + <span class="label" data-bind="text: title"></span> + <span class="value" data-bind="text: getShippingMethodTitle()"></span> </th> <td class="amount"> <!-- ko if: isCalculated() --> <span class="price" - data-bind="i18n: getValue(), attr: {'data-th': $t(title)}"></span> + data-bind="text: getValue(), attr: {'data-th': title}"></span> <!-- /ko --> <!-- ko ifnot: isCalculated() --> <span class="not-calculated" - data-bind="i18n: getValue(), attr: {'data-th': $t(title)}"></span> + data-bind="text: getValue(), attr: {'data-th': title}"></span> <!-- /ko --> </td> </tr> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/summary/subtotal.html b/app/code/Magento/Checkout/view/frontend/web/template/summary/subtotal.html index e217668f605f177665d97229dd1f9720bb426257..47b1bbc221fe4bbee89cfd669f3ca5c88658ad5b 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/summary/subtotal.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/summary/subtotal.html @@ -6,9 +6,9 @@ --> <tr class="totals"> - <th class="mark" scope="row" data-bind="i18n: title"></th> + <th class="mark" scope="row" data-bind="text: title"></th> <td class="amount"> - <span class="price" data-bind ="text: getValue(), attr:{'data-label': $t(title)}"></span> + <span class="price" data-bind ="text: getValue(), attr:{'data-label': title}"></span> <!-- ko foreach: elems() --> <!-- ko template: getTemplate() --><!-- /ko --> <!-- /ko --> diff --git a/app/code/Magento/Cms/i18n/de_DE.csv b/app/code/Magento/Cms/i18n/de_DE.csv index 09eb96234df10a47b690764805513bf260645591..e3dc8b9b189c695de297a33e56f1528356a047eb 100644 --- a/app/code/Magento/Cms/i18n/de_DE.csv +++ b/app/code/Magento/Cms/i18n/de_DE.csv @@ -119,3 +119,8 @@ Template,Vorlage "CMS Static Block","CMS statischer Block" "Contents of a Static Block","Inhalte eines statischen Blocks" "CMS Static Block Default Template","CMS statischer Block Standardvorlage" +Elements,Elements +Blocks,Blocks +Widgets,Widgets +Themes,Themes +Schedule,Schedule diff --git a/app/code/Magento/Cms/i18n/en_US.csv b/app/code/Magento/Cms/i18n/en_US.csv index 03a82317472dc7df606cb40782c2eeca7954a2d8..58485f3d9d2c5193bd5f6ecc2a1f7fa05e13cb1f 100644 --- a/app/code/Magento/Cms/i18n/en_US.csv +++ b/app/code/Magento/Cms/i18n/en_US.csv @@ -119,3 +119,8 @@ Template,Template "CMS Static Block","CMS Static Block" "Contents of a Static Block","Contents of a Static Block" "CMS Static Block Default Template","CMS Static Block Default Template" +Elements,Elements +Blocks,Blocks +Widgets,Widgets +Themes,Themes +Schedule,Schedule diff --git a/app/code/Magento/Cms/i18n/es_ES.csv b/app/code/Magento/Cms/i18n/es_ES.csv index 90bcb395cd0570d7961667d5e8b1e7927dd1a326..62584b6799530621a270f7d7e383236985bfd2b6 100644 --- a/app/code/Magento/Cms/i18n/es_ES.csv +++ b/app/code/Magento/Cms/i18n/es_ES.csv @@ -119,3 +119,8 @@ Template,Plantilla "CMS Static Block","Bloque estático CMS" "Contents of a Static Block","Cotenidos de un bloque estático" "CMS Static Block Default Template","Tema por defecto del bloque estático CMS" +Elements,Elements +Blocks,Blocks +Widgets,Widgets +Themes,Themes +Schedule,Schedule diff --git a/app/code/Magento/Cms/i18n/fr_FR.csv b/app/code/Magento/Cms/i18n/fr_FR.csv index 3feb0add8c11d203677a235adb6e4f3c4b9846e8..92e0c3ab029d77f7bfa6806f5ebfd3bc8e9ae5fa 100644 --- a/app/code/Magento/Cms/i18n/fr_FR.csv +++ b/app/code/Magento/Cms/i18n/fr_FR.csv @@ -119,3 +119,8 @@ Template,"Modèle visuel" "CMS Static Block","Bloc statique du CMS" "Contents of a Static Block","Contenu des blocs statiques" "CMS Static Block Default Template","Modèle de bloc statique par défaut du CMS" +Elements,Elements +Blocks,Blocks +Widgets,Widgets +Themes,Themes +Schedule,Schedule diff --git a/app/code/Magento/Cms/i18n/nl_NL.csv b/app/code/Magento/Cms/i18n/nl_NL.csv index 259123f1fe6e20312d69e9491575193b9d5b1122..ef34949cc0eb94c03568e7980577ec2c07c11e62 100644 --- a/app/code/Magento/Cms/i18n/nl_NL.csv +++ b/app/code/Magento/Cms/i18n/nl_NL.csv @@ -119,3 +119,8 @@ Template,Thema "CMS Static Block","CMS statisch blok" "Contents of a Static Block","Inhoud van een statisch blok" "CMS Static Block Default Template","CMS statisch blok standaard thema" +Elements,Elements +Blocks,Blocks +Widgets,Widgets +Themes,Themes +Schedule,Schedule diff --git a/app/code/Magento/Cms/i18n/pt_BR.csv b/app/code/Magento/Cms/i18n/pt_BR.csv index daf3cf4a6f53e4aabc1948ae39ddff01b1436004..706c52533cad0f4a4f10f2c98bb855a7ea7c8aaa 100644 --- a/app/code/Magento/Cms/i18n/pt_BR.csv +++ b/app/code/Magento/Cms/i18n/pt_BR.csv @@ -119,3 +119,8 @@ Template,Modelo "CMS Static Block","Bloco Estático do CMS" "Contents of a Static Block","Conteúdos de um Bloco Estático" "CMS Static Block Default Template","Template Padrão do Bloco Estático do CMS" +Elements,Elements +Blocks,Blocks +Widgets,Widgets +Themes,Themes +Schedule,Schedule diff --git a/app/code/Magento/Cms/i18n/zh_Hans_CN.csv b/app/code/Magento/Cms/i18n/zh_Hans_CN.csv index e27e81aa3b8ef4737e17e9af0c97b88f530852aa..338aa81bc8cfb6af9925f72e57e3b90c80dc151d 100644 --- a/app/code/Magento/Cms/i18n/zh_Hans_CN.csv +++ b/app/code/Magento/Cms/i18n/zh_Hans_CN.csv @@ -119,3 +119,8 @@ Template,æ¨¡æ¿ "CMS Static Block","CMS 陿€åŒºå—" "Contents of a Static Block",陿€åŒºå—的内容 "CMS Static Block Default Template","CMS 陿€åŒºå—默认模æ¿" +Elements,Elements +Blocks,Blocks +Widgets,Widgets +Themes,Themes +Schedule,Schedule diff --git a/app/code/Magento/Cms/view/adminhtml/ui_component/cms_block_listing.xml b/app/code/Magento/Cms/view/adminhtml/ui_component/cms_block_listing.xml index 6934d263535b59bde9a0a6c72ead01ec3dc0e0c0..6775549e39d49d9b1d097c99861a8683b164ab1f 100644 --- a/app/code/Magento/Cms/view/adminhtml/ui_component/cms_block_listing.xml +++ b/app/code/Magento/Cms/view/adminhtml/ui_component/cms_block_listing.xml @@ -85,6 +85,14 @@ <item name="provider" xsi:type="string">cms_block_listing.cms_block_listing.listing_top.bookmarks</item> <item name="namespace" xsi:type="string">current.filters</item> </item> + <item name="templates" xsi:type="array"> + <item name="filters" xsi:type="array"> + <item name="select" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/form/element/ui-select</item> + <item name="template" xsi:type="string">ui/grid/filters/elements/ui-select</item> + </item> + </item> + </item> <item name="childDefaults" xsi:type="array"> <item name="provider" xsi:type="string">cms_block_listing.cms_block_listing.listing_top.listing_filters</item> <item name="imports" xsi:type="array"> diff --git a/app/code/Magento/Cms/view/adminhtml/ui_component/cms_page_listing.xml b/app/code/Magento/Cms/view/adminhtml/ui_component/cms_page_listing.xml index c55c919be2164d32927ef1dce7d2933fcfb178da..27cc3ddc2e019535e117e1ba519a48c7264ee7cd 100644 --- a/app/code/Magento/Cms/view/adminhtml/ui_component/cms_page_listing.xml +++ b/app/code/Magento/Cms/view/adminhtml/ui_component/cms_page_listing.xml @@ -86,6 +86,14 @@ <item name="provider" xsi:type="string">cms_page_listing.cms_page_listing.listing_top.bookmarks</item> <item name="namespace" xsi:type="string">current.filters</item> </item> + <item name="templates" xsi:type="array"> + <item name="filters" xsi:type="array"> + <item name="select" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/form/element/ui-select</item> + <item name="template" xsi:type="string">ui/grid/filters/elements/ui-select</item> + </item> + </item> + </item> <item name="childDefaults" xsi:type="array"> <item name="provider" xsi:type="string">cms_page_listing.cms_page_listing.listing_top.listing_filters</item> <item name="imports" xsi:type="array"> diff --git a/app/code/Magento/Cms/view/frontend/templates/default/home.phtml b/app/code/Magento/Cms/view/frontend/templates/default/home.phtml index 9c51cd0004f6c28cafd1c583841a6fdb6c7b0c4e..4fae6ce09006f455f289f4be5de61304d1f97e22 100644 --- a/app/code/Magento/Cms/view/frontend/templates/default/home.phtml +++ b/app/code/Magento/Cms/view/frontend/templates/default/home.phtml @@ -4,4 +4,4 @@ * See COPYING.txt for license details. */ ?> -There was no Home CMS page configured or found. +There was no Home CMS page configured or found. \ No newline at end of file diff --git a/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/ProductTemplate/Form.php b/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/AttributeSet/Form.php similarity index 93% rename from app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/ProductTemplate/Form.php rename to app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/AttributeSet/Form.php index 09370fdce3e72ac650a640a1096bf6b62b8582a4..65c88dd19a05faeac5fc7ef50208bd646d94ad34 100644 --- a/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/ProductTemplate/Form.php +++ b/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/AttributeSet/Form.php @@ -7,7 +7,7 @@ /** * Product attribute set selector form */ -namespace Magento\ConfigurableProduct\Block\Adminhtml\Product\Edit\ProductTemplate; +namespace Magento\ConfigurableProduct\Block\Adminhtml\Product\Edit\AttributeSet; class Form extends \Magento\Backend\Block\Widget\Form\Generic { @@ -57,7 +57,7 @@ class Form extends \Magento\Backend\Block\Widget\Form\Generic 'radio', [ 'after_element_html' => __( - 'Add configurable attributes to the current Product Template ("%1")', + 'Add configurable attributes to the current Attribute Set ("%1")', sprintf('<span data-role="name-container">%s</span>', $this->getCurrentAttributeSetName()) ), 'name' => 'affected-attribute-set', @@ -70,7 +70,7 @@ class Form extends \Magento\Backend\Block\Widget\Form\Generic 'new-affected-attribute-set', 'radio', [ - 'after_element_html' => __('Add configurable attributes to the new Product Template based on current'), + 'after_element_html' => __('Add configurable attributes to the new Attribute Set based on current'), 'name' => 'affected-attribute-set', 'class' => 'admin__control-radio', 'value' => 'new' @@ -80,7 +80,7 @@ class Form extends \Magento\Backend\Block\Widget\Form\Generic 'new-attribute-set-name', 'text', [ - 'label' => __('New product template name'), + 'label' => __('New attribute set name'), 'name' => 'new-attribute-set-name', 'required' => true, 'css_class' => 'no-display', @@ -92,7 +92,7 @@ class Form extends \Magento\Backend\Block\Widget\Form\Generic 'existing-affected-attribute-set', 'radio', [ - 'after_element_html' => __('Add configurable attributes to the existing Product Template'), + 'after_element_html' => __('Add configurable attributes to the existing Attribute Set'), 'name' => 'affected-attribute-set', 'required' => true, 'class' => 'admin__control-radio no-display', @@ -103,7 +103,7 @@ class Form extends \Magento\Backend\Block\Widget\Form\Generic 'choose-affected-attribute-set', 'select', [ - 'label' => __('Choose existing Product Template'), + 'label' => __('Choose existing Attribute Set'), 'name' => 'attribute-set-name', 'required' => true, 'css_class' => 'no-display', diff --git a/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Super/Config/Matrix.php b/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Super/Config/Matrix.php index e48634a2c7d54cc513997d3b742ed612f9594c8b..bf336cbf87059b52ac2a024c8368d99e30aafe28 100644 --- a/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Super/Config/Matrix.php +++ b/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Super/Config/Matrix.php @@ -54,6 +54,11 @@ class Matrix extends \Magento\Backend\Block\Template /** @var null|array */ private $productAttributes; + /** + * @var \Magento\Framework\Locale\CurrencyInterface + */ + protected $localeCurrency; + /** * @param \Magento\Backend\Block\Template\Context $context * @param \Magento\ConfigurableProduct\Model\Product\Type\Configurable $configurableType @@ -62,6 +67,7 @@ class Matrix extends \Magento\Backend\Block\Template * @param \Magento\ConfigurableProduct\Model\Product\Type\VariationMatrix $variationMatrix * @param ProductRepositoryInterface $productRepository * @param \Magento\Catalog\Helper\Image $image + * @param \Magento\Framework\Locale\CurrencyInterface $localeCurrency * @param array $data */ public function __construct( @@ -72,6 +78,7 @@ class Matrix extends \Magento\Backend\Block\Template \Magento\ConfigurableProduct\Model\Product\Type\VariationMatrix $variationMatrix, ProductRepositoryInterface $productRepository, \Magento\Catalog\Helper\Image $image, + \Magento\Framework\Locale\CurrencyInterface $localeCurrency, array $data = [] ) { parent::__construct($context, $data); @@ -80,6 +87,7 @@ class Matrix extends \Magento\Backend\Block\Template $this->stockRegistry = $stockRegistry; $this->variationMatrix = $variationMatrix; $this->productRepository = $productRepository; + $this->localeCurrency = $localeCurrency; $this->image = $image; } @@ -88,7 +96,7 @@ class Matrix extends \Magento\Backend\Block\Template */ public function getCurrencySymbol() { - return $this->_storeManager->getStore()->getCurrentCurrency()->getCurrencySymbol(); + return $this->localeCurrency->getCurrency($this->_storeManager->getStore()->getBaseCurrencyCode())->getSymbol(); } /** diff --git a/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Steps/Bulk.php b/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Steps/Bulk.php index 69960ac40a6f37ab455591503f20b524c8244d99..d440b7347b6e65ad1b825b9e66fb43ad31ad2f80 100644 --- a/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Steps/Bulk.php +++ b/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Steps/Bulk.php @@ -39,12 +39,4 @@ class Bulk extends \Magento\Ui\Block\Component\StepsWizard\StepAbstract { return $this->image->getDefaultPlaceholderUrl('thumbnail'); } - - /** - * @return string - */ - public function getCurrencySymbol() - { - return $this->_storeManager->getStore()->getCurrentCurrency()->getCurrencySymbol(); - } } diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/layout/catalog_product_new.xml b/app/code/Magento/ConfigurableProduct/view/adminhtml/layout/catalog_product_new.xml index b6683bdeca4a7f6866a9adc90581af1e59afc2f4..322360d8703f9e443d3537c72576dbd42b29d7a9 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/layout/catalog_product_new.xml +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/layout/catalog_product_new.xml @@ -16,7 +16,7 @@ </referenceContainer> <referenceContainer name="content"> <block class="Magento\Framework\View\Element\Template" name="affected-attribute-set-selector" template="Magento_ConfigurableProduct::product/configurable/affected-attribute-set-selector/form.phtml"> - <block class="Magento\ConfigurableProduct\Block\Adminhtml\Product\Edit\ProductTemplate\Form" name="affected-attribute-set-form" /> + <block class="Magento\ConfigurableProduct\Block\Adminhtml\Product\Edit\AttributeSet\Form" name="affected-attribute-set-form" /> </block> </referenceContainer> </body> diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/attribute/set/js.phtml b/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/attribute/set/js.phtml index ea036bbf5d6c0eedfd3cb70d46125ac1d9c80938..c9aeeddfd2b308a70cf84347113ca4c3a5437a00 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/attribute/set/js.phtml +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/attribute/set/js.phtml @@ -40,7 +40,7 @@ editSet.submit = editSet.submit.wrap(function(original) { editSet.rightBeforeAppend = editSet.rightBeforeAppend.wrap(function(original, tree, nodeThis, node, newParent) { if (node.attributes.is_configurable == 1) { alert({ - content: '<?php /* @escapeNotVerified */ echo $block->escapeJsQuote(__('This attribute is used in configurable products. You cannot remove it from the product template.')) ?>' + content: '<?php /* @escapeNotVerified */ echo $block->escapeJsQuote(__('This attribute is used in configurable products. You cannot remove it from the attribute set.')) ?>' }); return false; } @@ -50,7 +50,7 @@ editSet.rightBeforeAppend = editSet.rightBeforeAppend.wrap(function(original, tr editSet.rightBeforeInsert = editSet.rightBeforeInsert.wrap(function(original, tree, nodeThis, node, newParent) { if (node.attributes.is_configurable == 1) { alert({ - content: '<?php /* @escapeNotVerified */ echo $block->escapeJsQuote(__('This attribute is used in configurable products. You cannot remove it from the product template.')) ?>' + content: '<?php /* @escapeNotVerified */ echo $block->escapeJsQuote(__('This attribute is used in configurable products. You cannot remove it from the attribute set.')) ?>' }); return false; } diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/attribute/steps/bulk.phtml b/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/attribute/steps/bulk.phtml index 8a1b3edc8053e65e07b1f9c59dd2887d0f5c1bb0..df8785085dea3ec27b267ac6835a42e6f75bebf8 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/attribute/steps/bulk.phtml +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/attribute/steps/bulk.phtml @@ -655,7 +655,6 @@ "component": "Magento_ConfigurableProduct/js/variations/steps/bulk", "appendTo": "<?= /* @escapeNotVerified */ $block->getParentComponentName()?>", "noImage": "<?= /* @escapeNotVerified */ $block->getNoImageUrl() ?>", - "currencySymbol": "<?= /* @escapeNotVerified */ $block->getCurrencySymbol() ?>", "variationsComponent": "configurableVariations" } } diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/super/config.phtml b/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/super/config.phtml index b71eadea028641416be173ce6700cb0b860e8561..b1d12ed35ed1e3912a12ab4f13e910489f938595 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/super/config.phtml +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/super/config.phtml @@ -16,7 +16,7 @@ You need to create a simple product for each configuration (Ex: a product for each color).');?> </div> </div> - <div class="product-create-configuration-actions"> + <div class="product-create-configuration-actions" data-action="product-create-configuration-buttons"> <div class="product-create-configuration-action"> <button type="button" data-action="open-steps-wizard" title="Create Product Configurations" class="action-secondary" data-bind="click: open"> diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/super/matrix.phtml b/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/super/matrix.phtml index e962963ccac6ca28245e4e25edc5b0917c01bfd9..0286f7c556108936d871bc628e448357dd5def64 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/super/matrix.phtml +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/super/matrix.phtml @@ -144,7 +144,7 @@ $currencySymbol = $block->getCurrencySymbol(); </td> <td class="col-price" data-column="price"> <!-- ko ifnot: variation.editable --> - <!-- ko text: '<?= /* @noEscape */ $currencySymbol?>' + variation.price --><!--/ko--> + <!-- ko text: $parent.getCurrencySymbol() + variation.price --><!--/ko--> <!-- /ko --> <!-- ko if: variation.editable --> <div class="addon"> @@ -156,7 +156,7 @@ $currencySymbol = $block->getCurrencySymbol(); value: variation.price}"/> <label class="addafter" data-bind="attr: {for: $parent.getRowId(variation, 'price')"> - <strong>$</strong> + <strong data-bind="text: $parent.getCurrencySymbol()"></strong> </label> </div> <!-- /ko --> @@ -213,7 +213,7 @@ $currencySymbol = $block->getCurrencySymbol(); </li> <li> <a class="action-menu-item" data-bind=" - i18n: variation.status == 1 ? 'Disable Product' : 'Enable Product', + text: variation.status == 1 ? $t('Disable Product') : $t('Enable Product'), click: $parent.toggleProduct.bind($parent, $index())"> </a> </li> @@ -255,6 +255,7 @@ $currencySymbol = $block->getCurrencySymbol(); "variations": <?= /* @noEscape */ $this->helper('Magento\Framework\Json\Helper\Data')->jsonEncode($productMatrix) ?>, "productAttributes": <?= /* @noEscape */ $this->helper('Magento\Framework\Json\Helper\Data')->jsonEncode($attributes) ?>, "productUrl": "<?= /* @noEscape */ $block->getUrl('catalog/product/edit', ['id' => '%id%']) ?>", + "currencySymbol": "<?= /* @noEscape */ $currencySymbol ?>", "configurableProductGrid": "configurableProductGrid" } } diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/product/configurable/affected-attribute-set-selector/js.phtml b/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/product/configurable/affected-attribute-set-selector/js.phtml index 704568283748a660aed1941410b28ebf1e99b622..4716938b4a0942d305a2a529e2ea29d995dc8366 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/product/configurable/affected-attribute-set-selector/js.phtml +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/product/configurable/affected-attribute-set-selector/js.phtml @@ -33,6 +33,12 @@ newAttributeSetContainer = $('[data-role=affected-attribute-set-new-name-container]'), existingAttributeSetContainer = $('[data-role=affected-attribute-set-existing-name-container]'); + $form.find('input[type=text]').on('keypress',function(e){ + if(e.keyCode === 13){ + e.preventDefault(); + $form.closest('[data-role=modal]').find('button[data-action=confirm]').click(); + } + }); $('[data-form=edit-product]').append($('<input>', { type: 'hidden', @@ -42,12 +48,15 @@ $form .modal({ - title: '<?php /* @escapeNotVerified */ echo __('Choose Affected Product Template'); ?>', + title: '<?php /* @escapeNotVerified */ echo __('Choose Affected Attribute Set'); ?>', closed: function () { resetValidation(); }, buttons: [{ text: '<?php /* @escapeNotVerified */ echo __('Confirm'); ?>', + attr: { + 'data-action': 'confirm' + }, 'class': 'action-secondary', click: function() { var affectedAttributeSetId = $form.find('input[name=affected-attribute-set]:checked').val(); diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/steps/bulk.js b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/steps/bulk.js index 5f4af9cd5e3e2e777c05fe58bd5760e938654661..499962f8e59f8f68e598ce4800ac90ff824f7578 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/steps/bulk.js +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/steps/bulk.js @@ -55,7 +55,7 @@ define([ type: ko.observable('none'), value: ko.observable(), attribute: ko.observable(), - currencySymbol: this.currencySymbol + currencySymbol: this.variationsComponent().getCurrencySymbol() }, quantity: { label: 'quantity', diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/steps/summary.js b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/steps/summary.js index 0da35357808085b8fe91792cd7bdac8e523a3e37..0a1088393c04f8b50c48c2405c6668477b2eb95f 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/steps/summary.js +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/steps/summary.js @@ -40,7 +40,7 @@ define([ nextLabelText: $.mage.__('Generate Products'), variations: [], generateGrid: function (variations, getSectionValue) { - var productName = this.variationsComponent().getProductValue('name'), + var productSku = this.variationsComponent().getProductValue('sku'), productPrice = this.variationsComponent().getProductValue('price'), productWeight = this.variationsComponent().getProductValue('weight'), variationsKeys = [], @@ -59,7 +59,7 @@ define([ }); } images = getSectionValue('images', options); - sku = productName + _.reduce(options, function (memo, option) { + sku = productSku + _.reduce(options, function (memo, option) { return memo + '-' + option.label; }, ''); quantity = getSectionValue('quantity', options); @@ -129,7 +129,7 @@ define([ _.each(variation.options, function (option) { row.push(option.label); }); - row.push('$ ' + variation.price); + row.push(this.variationsComponent().getCurrencySymbol() + ' ' + variation.price); return row; }, diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/variations.js b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/variations.js index 862ffe05a6cfc78bfa750cce52b2c2fef1258273..150326b3fabaf055dbf1184c363635c7b4b16db8 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/variations.js +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/variations.js @@ -368,6 +368,14 @@ define([ .addClass('disabled-configurable-elements') .prop('disabled', true); }); + }, + + /** + * Get currency symbol + * @returns {*} + */ + getCurrencySymbol: function () { + return this.currencySymbol; } }); }); diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index 500a104861d3bd1f8e74d1454c24dddf30adeab8..06be21a82e3c108edd8838b8834c7b1ac1676051 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -513,6 +513,13 @@ class AccountManagement implements AccountManagementInterface $customer->setStoreId($storeId); } + // Update 'created_in' value with actual store name + if ($customer->getId() === null) { + $storeName = $this->storeManager->getStore($customer->getStoreId()) + ->getName(); + $customer->setCreatedIn($storeName); + } + $customerAddresses = $customer->getAddresses() ?: []; $customer->setAddresses(null); try { diff --git a/app/code/Magento/Customer/Model/Config/Backend/Address/Street.php b/app/code/Magento/Customer/Model/Config/Backend/Address/Street.php index d456491e5c33462e25d49386eb0c77fbf7674684..7ac2be353e6a403afbb46ee599a880e0704a4bc5 100644 --- a/app/code/Magento/Customer/Model/Config/Backend/Address/Street.php +++ b/app/code/Magento/Customer/Model/Config/Backend/Address/Street.php @@ -10,7 +10,7 @@ use Magento\Framework\App\Config\ScopeConfigInterface; /** * Line count config model for customer address street attribute * - * @method string getWebsiteCode + * @method string getWebsiteCode() */ class Street extends \Magento\Framework\App\Config\Value { diff --git a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php index d5fc01b379051a1a0f0fe415e6d88c7a4528627f..62d7232bda0f2145e84cb56a94970882295f366a 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php @@ -265,7 +265,7 @@ class AccountManagementTest extends \PHPUnit_Framework_TestCase ->method('getDefaultStore') ->willReturn($store); $customer = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface')->getMock(); - $customer->expects($this->once()) + $customer->expects($this->atLeastOnce()) ->method('getId') ->willReturn($customerId); $customer->expects($this->once()) @@ -341,7 +341,7 @@ class AccountManagementTest extends \PHPUnit_Framework_TestCase ->method('getDefaultStore') ->willReturn($store); $customer = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface')->getMock(); - $customer->expects($this->once()) + $customer->expects($this->atLeastOnce()) ->method('getId') ->willReturn($customerId); $customer->expects($this->once()) @@ -478,6 +478,61 @@ class AccountManagementTest extends \PHPUnit_Framework_TestCase $this->accountManagement->createAccountWithPasswordHash($customer, $hash); } + /** + * @expectedException \Magento\Framework\Exception\LocalizedException + */ + public function testCreateAccountWithPasswordHashWithNewCustomerAndLocalizedException() + { + $storeId = 1; + $storeName = 'store_name'; + $hash = '4nj54lkj5jfi03j49f8bgujfgsd'; + + $customerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface') + ->getMockForAbstractClass(); + + $customerMock->expects($this->atLeastOnce()) + ->method('getId') + ->willReturn(null); + $customerMock->expects($this->atLeastOnce()) + ->method('getStoreId') + ->willReturn($storeId); + $customerMock->expects($this->once()) + ->method('setCreatedIn') + ->with($storeName) + ->willReturnSelf(); + $customerMock->expects($this->once()) + ->method('getAddresses') + ->willReturn([]); + $customerMock->expects($this->once()) + ->method('setAddresses') + ->with(null) + ->willReturnSelf(); + + $storeMock = $this->getMockBuilder('Magento\Store\Model\Store') + ->disableOriginalConstructor() + ->getMock(); + + $storeMock->expects($this->once()) + ->method('getName') + ->willReturn($storeName); + + $this->storeManager->expects($this->once()) + ->method('getStore') + ->with($storeId) + ->willReturn($storeMock); + + $exception = new \Magento\Framework\Exception\LocalizedException( + new \Magento\Framework\Phrase('Exception message') + ); + $this->customerRepository + ->expects($this->once()) + ->method('save') + ->with($customerMock, $hash) + ->willThrowException($exception); + + $this->accountManagement->createAccountWithPasswordHash($customerMock, $hash); + } + /** * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ diff --git a/app/code/Magento/Customer/i18n/de_DE.csv b/app/code/Magento/Customer/i18n/de_DE.csv index e138d63071cf90f8d6ef40ef8de27353c9aec7d5..ec5acd01becc9b74ca3f1dafaee1ce2c7c13844c 100644 --- a/app/code/Magento/Customer/i18n/de_DE.csv +++ b/app/code/Magento/Customer/i18n/de_DE.csv @@ -415,3 +415,5 @@ n/a,"Keine Angabe" "Password forgotten","Passwort vergessen" "My Dashboard","Meine Startseite" "You are now logged out","Sie sind jetzt abgemeldet" +"All Customers", "All Customers" +"Now Online", "Now Online" diff --git a/app/code/Magento/Customer/i18n/en_US.csv b/app/code/Magento/Customer/i18n/en_US.csv index f3ed0e19fb9e3d087f254aa5694a15c5877161f7..24d087d95d06cf5aaca2f26f069e7183e31df66f 100644 --- a/app/code/Magento/Customer/i18n/en_US.csv +++ b/app/code/Magento/Customer/i18n/en_US.csv @@ -414,3 +414,5 @@ n/a,n/a "Password forgotten","Password forgotten" "My Dashboard","My Dashboard" "You are now logged out","You are now logged out" +"All Customers", "All Customers" +"Now Online", "Now Online" diff --git a/app/code/Magento/Customer/i18n/es_ES.csv b/app/code/Magento/Customer/i18n/es_ES.csv index 6ee5727639a0e87b37b1e8b2b606bcc51d7d11ed..a2d8a49b8e6cd62d637b5e6d4030c277788a0b65 100644 --- a/app/code/Magento/Customer/i18n/es_ES.csv +++ b/app/code/Magento/Customer/i18n/es_ES.csv @@ -414,3 +414,5 @@ n/a,n/d "Password forgotten","Olvido de contraseña" "My Dashboard","Mi panel de control" "You are now logged out","Ha cerrado sesión." +"All Customers", "All Customers" +"Now Online", "Now Online" diff --git a/app/code/Magento/Customer/i18n/fr_FR.csv b/app/code/Magento/Customer/i18n/fr_FR.csv index e32c2759c36ce1355a2701d6fa58a33183142e54..ded34d3149b9d6c4040fbf36924014165e94fa67 100644 --- a/app/code/Magento/Customer/i18n/fr_FR.csv +++ b/app/code/Magento/Customer/i18n/fr_FR.csv @@ -414,3 +414,5 @@ n/a,n/a "Password forgotten","Mot de passe oublié" "My Dashboard","Mon espace de travail" "You are now logged out","Vous êtes maintenant déconnecté." +"All Customers", "All Customers" +"Now Online", "Now Online" diff --git a/app/code/Magento/Customer/i18n/nl_NL.csv b/app/code/Magento/Customer/i18n/nl_NL.csv index bde6b074652d886e1e53606600c0dbb044e43596..4953a8783567dfa27d7609249384855839a3fc1a 100644 --- a/app/code/Magento/Customer/i18n/nl_NL.csv +++ b/app/code/Magento/Customer/i18n/nl_NL.csv @@ -414,3 +414,5 @@ n/a,n.v.t. "Password forgotten","Wachtwoord vergeten" "My Dashboard","Mijn Dashboard" "You are now logged out","U bent nu uitgelogd" +"All Customers", "All Customers" +"Now Online", "Now Online" diff --git a/app/code/Magento/Customer/i18n/pt_BR.csv b/app/code/Magento/Customer/i18n/pt_BR.csv index b02e6801702bab888b2741cb932bbf68bf5acf86..e3f1d8e704a73d39f6953849433856919d62fcb7 100644 --- a/app/code/Magento/Customer/i18n/pt_BR.csv +++ b/app/code/Magento/Customer/i18n/pt_BR.csv @@ -414,3 +414,5 @@ n/a,n/d "Password forgotten","Senha esquecida" "My Dashboard","Meu Painel" "You are now logged out","Agora você está desconectado" +"All Customers", "All Customers" +"Now Online", "Now Online" diff --git a/app/code/Magento/Customer/i18n/zh_Hans_CN.csv b/app/code/Magento/Customer/i18n/zh_Hans_CN.csv index e344fa595c39e2e87f0340f5f88f143b18249a5a..927f8db2406783e9a4192f8c4767b83eb04f50c5 100644 --- a/app/code/Magento/Customer/i18n/zh_Hans_CN.csv +++ b/app/code/Magento/Customer/i18n/zh_Hans_CN.csv @@ -414,3 +414,5 @@ n/a,ä¸å¯ç”¨ "Password forgotten",密ç 忘记 "My Dashboard",æˆ‘çš„ä»ªè¡¨æ¿ "You are now logged out",您已注销 +"All Customers", "All Customers" +"Now Online", "Now Online" diff --git a/app/code/Magento/CustomerImportExport/Model/Import/Customer.php b/app/code/Magento/CustomerImportExport/Model/Import/Customer.php index 6cf06f839c175efd29b42a98d63b1ecf8f959b82..513c2a703b5d439ac5df946d9129af9cbce44819 100644 --- a/app/code/Magento/CustomerImportExport/Model/Import/Customer.php +++ b/app/code/Magento/CustomerImportExport/Model/Import/Customer.php @@ -5,6 +5,7 @@ */ namespace Magento\CustomerImportExport\Model\Import; +use Magento\Customer\Api\Data\CustomerInterface; use Magento\ImportExport\Model\Import\ErrorProcessing\ProcessingErrorAggregatorInterface; /** @@ -135,25 +136,25 @@ class Customer extends AbstractCustomer /** * Customer fields in file */ - public $customerFields = [ - 'group_id', - 'store_id', - 'updated_at', - 'created_at', - 'created_in', - 'prefix', - 'firstname', - 'middlename', - 'lastname', - 'suffix', - 'dob', + protected $customerFields = [ + CustomerInterface::GROUP_ID, + CustomerInterface::STORE_ID, + CustomerInterface::UPDATED_AT, + CustomerInterface::CREATED_AT, + CustomerInterface::CREATED_IN, + CustomerInterface::PREFIX, + CustomerInterface::FIRSTNAME, + CustomerInterface::MIDDLENAME, + CustomerInterface::LASTNAME, + CustomerInterface::SUFFIX, + CustomerInterface::DOB, 'password_hash', - 'taxvat', - 'confirmation', - 'gender', + CustomerInterface::TAXVAT, + CustomerInterface::CONFIRMATION, + CustomerInterface::GENDER, 'rp_token', 'rp_token_created_at', - ]; + ]; /** * @param \Magento\Framework\Stdlib\StringUtils $string @@ -237,11 +238,6 @@ class Customer extends AbstractCustomer $this->_initStores(true)->_initAttributes(); - $this->validColumnNames = array_merge( - $this->validColumnNames, - $this->customerFields - ); - $this->_customerModel = $customerFactory->create(); /** @var $customerResource \Magento\Customer\Model\ResourceModel\Customer */ $customerResource = $this->_customerModel->getResource(); @@ -381,7 +377,9 @@ class Customer extends AbstractCustomer $attributeParameters = $this->_attributes[$attributeCode]; if ('select' == $attributeParameters['type']) { - $value = $attributeParameters['options'][strtolower($value)]; + $value = isset($attributeParameters['options'][strtolower($value)]) + ? $attributeParameters['options'][strtolower($value)] + : 0; } elseif ('datetime' == $attributeParameters['type']) { $value = (new \DateTime())->setTimestamp(strtotime($value)); $value = $value->format(\Magento\Framework\Stdlib\DateTime::DATETIME_PHP_FORMAT); @@ -562,4 +560,17 @@ class Customer extends AbstractCustomer { return $this->_entityTable; } + + /** + * @inheritDoc + */ + public function getValidColumnNames() + { + $this->validColumnNames = array_merge( + $this->validColumnNames, + $this->customerFields + ); + + return $this->validColumnNames; + } } diff --git a/app/code/Magento/CustomerImportExport/Model/Import/CustomerComposite.php b/app/code/Magento/CustomerImportExport/Model/Import/CustomerComposite.php index ed7d2f8fe9e85b92ffaf8da22c75b85fb9ffa7b2..a42167fb68134b428490f5f6f804852340899c22 100644 --- a/app/code/Magento/CustomerImportExport/Model/Import/CustomerComposite.php +++ b/app/code/Magento/CustomerImportExport/Model/Import/CustomerComposite.php @@ -224,13 +224,6 @@ class CustomerComposite extends \Magento\ImportExport\Model\Import\AbstractEntit } $this->_initAddressAttributes(); - $this->validColumnNames = array_merge( - $this->validColumnNames, - $this->_customerAttributes, - $this->_addressAttributes, - $this->_customerEntity->customerFields - ); - // next customer id if (isset($data['next_customer_id'])) { $this->_nextCustomerId = $data['next_customer_id']; @@ -489,4 +482,19 @@ class CustomerComposite extends \Magento\ImportExport\Model\Import\AbstractEntit return parent::_prepareRowForDb($rowData); } + + /** + * @inheritDoc + */ + public function getValidColumnNames() + { + $this->validColumnNames = array_merge( + $this->validColumnNames, + $this->_customerAttributes, + $this->_addressAttributes, + $this->_customerEntity->getValidColumnNames() + ); + + return $this->validColumnNames; + } } diff --git a/app/code/Magento/Deploy/Model/Filesystem.php b/app/code/Magento/Deploy/Model/Filesystem.php index 178ad26a2d00e322d12dd7dd4c24da97bf424c87..3f695ea47041889903a4fb3c3765b2cb2d0d9d72 100644 --- a/app/code/Magento/Deploy/Model/Filesystem.php +++ b/app/code/Magento/Deploy/Model/Filesystem.php @@ -6,11 +6,10 @@ namespace Magento\Deploy\Model; -use Symfony\Component\Console\Output\OutputInterface; use Magento\Framework\App\State; use Magento\Framework\App\DeploymentConfig\Writer; use Magento\Framework\App\Filesystem\DirectoryList; -use Magento\Developer\Console\Command\CssDeployCommand; +use Magento\Developer\Console\Command\SourceThemeDeployCommand; /** * A class to manage Magento modes @@ -137,9 +136,10 @@ class Filesystem $themeLocalePairs = $this->storeView->retrieveThemeLocalePairs(); foreach ($themeLocalePairs as $themeLocalePair) { $theme = $themeLocalePair['theme'] ?: self::DEFAULT_THEME; - $cmd = $this->functionCallPath . 'dev:css:deploy less' - . ' --' . CssDeployCommand::THEME_OPTION . '="' . $theme . '"' - . ' --' . CssDeployCommand::LOCALE_OPTION . '="' . $themeLocalePair['locale'] . '"'; + $cmd = $this->functionCallPath . 'dev:source_theme:deploy' + . ' --' . SourceThemeDeployCommand::TYPE_ARGUMENT . '="less"' + . ' --' . SourceThemeDeployCommand::THEME_OPTION . '="' . $theme . '"' + . ' --' . SourceThemeDeployCommand::LOCALE_OPTION . '="' . $themeLocalePair['locale'] . '"'; /** * @todo build a solution that does not depend on exec diff --git a/app/code/Magento/Developer/Console/Command/CssDeployCommand.php b/app/code/Magento/Developer/Console/Command/CssDeployCommand.php deleted file mode 100644 index ac651b633d026790bfe6d6d3a50283303e00eaa1..0000000000000000000000000000000000000000 --- a/app/code/Magento/Developer/Console/Command/CssDeployCommand.php +++ /dev/null @@ -1,241 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\Developer\Console\Command; - -use Magento\Framework\View\Asset\PreProcessor\Pool; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Magento\Framework\Filesystem; -use Magento\Framework\View\Asset\Source; -use Magento\Framework\App\State; -use Magento\Framework\View\Asset\Repository; -use Magento\Framework\ObjectManagerInterface; -use Magento\Framework\App\ObjectManager\ConfigLoader; -use Magento\Framework\View\Asset\PreProcessor\ChainFactoryInterface; -use Magento\Framework\App\Filesystem\DirectoryList; -use Magento\Framework\Validator\Locale; - -/** - * Class CssDeployCommand - collects, processes and publishes source files like LESS or SASS - * @SuppressWarnings("PMD.CouplingBetweenObjects") - */ -class CssDeployCommand extends Command -{ - /** - * Locale option key - */ - const LOCALE_OPTION = 'locale'; - - /** - * Area option key - */ - const AREA_OPTION = 'area'; - - /** - * Theme option key - */ - const THEME_OPTION = 'theme'; - - /** - * Type argument key - */ - const TYPE_ARGUMENT = 'type'; - - /** - * Files argument key - */ - const FILE_ARGUMENT = 'file'; - - /** - * @var ObjectManagerInterface - */ - private $objectManager; - - /** - * @var Repository - */ - private $assetRepo; - - /** - * @var ConfigLoader - */ - private $configLoader; - - /** - * @var State - */ - private $state; - - /** - * @var Source - */ - private $assetSource; - - /** - * @var ChainFactoryInterface - */ - private $chainFactory; - - /** - * @var Filesystem - */ - private $filesystem; - - /** - * @var Locale - */ - private $validator; - - /** - * @var Pool - */ - private $pool; - - /** - * Inject dependencies - * - * @param ObjectManagerInterface $objectManager - * @param Repository $assetRepo - * @param ConfigLoader $configLoader - * @param State $state - * @param Source $assetSource - * @param ChainFactoryInterface $chainFactory - * @param Filesystem $filesystem - * @param Locale $validator - * @param Pool $pool - */ - public function __construct( - ObjectManagerInterface $objectManager, - Repository $assetRepo, - ConfigLoader $configLoader, - State $state, - Source $assetSource, - ChainFactoryInterface $chainFactory, - Filesystem $filesystem, - Locale $validator, - Pool $pool - ) { - $this->state = $state; - $this->objectManager = $objectManager; - $this->configLoader = $configLoader; - $this->assetRepo = $assetRepo; - $this->assetSource = $assetSource; - $this->chainFactory = $chainFactory; - $this->filesystem = $filesystem; - $this->validator = $validator; - - parent::__construct(); - $this->pool = $pool; - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this->setName('dev:css:deploy') - ->setDescription('Collects, processes and publishes source LESS files') - ->setDefinition([ - new InputArgument( - self::TYPE_ARGUMENT, - InputArgument::REQUIRED, - 'Type of dynamic stylesheet language: [less]' - ), - new InputArgument( - self::FILE_ARGUMENT, - InputArgument::IS_ARRAY, - 'Files to pre-process (file should be specified without extension)', - ['css/styles-m'] - ), - new InputOption( - self::LOCALE_OPTION, - null, - InputOption::VALUE_REQUIRED, - 'Locale', - 'en_US' - ), - new InputOption( - self::AREA_OPTION, - null, - InputOption::VALUE_REQUIRED, - 'Area, one of [frontend|adminhtml]', - 'frontend' - ), - new InputOption( - self::THEME_OPTION, - null, - InputOption::VALUE_REQUIRED, - 'Theme in format Vendor/theme', - 'Magento/blank' - ), - - ]); - - parent::configure(); - } - - /** - * {@inheritdoc} - * @throws \InvalidArgumentException - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $locale = $input->getOption(self::LOCALE_OPTION); - - if (!$this->validator->isValid($locale)) { - throw new \InvalidArgumentException( - $locale . ' argument has invalid value, please run info:language:list for list of available locales' - ); - } - - $area = $input->getOption(self::AREA_OPTION); - $theme = $input->getOption(self::THEME_OPTION); - - $type = $input->getArgument(self::TYPE_ARGUMENT); - - $this->state->setAreaCode($area); - $this->objectManager->configure($this->configLoader->load($area)); - - foreach ($input->getArgument(self::FILE_ARGUMENT) as $file) { - $file .= '.' . $type; - - $output->writeln("<info>Gathering {$file} sources.</info>"); - - $asset = $this->assetRepo->createAsset( - $file, - [ - 'area' => $area, - 'theme' => $theme, - 'locale' => $locale, - ] - ); - - $rootDir = $this->filesystem->getDirectoryWrite(DirectoryList::ROOT); - $sourceFile = $this->assetSource->findSource($asset); - $relativePath = $rootDir->getRelativePath($sourceFile); - $content = $rootDir->readFile($relativePath); - - $chain = $this->chainFactory->create( - [ - 'asset' => $asset, - 'origContent' => $content, - 'origContentType' => $asset->getContentType(), - 'origAssetPath' => $relativePath - ] - ); - - $this->pool->process($chain); - $targetDir = $this->filesystem->getDirectoryWrite(DirectoryList::STATIC_VIEW); - $targetDir->writeFile($chain->getAsset()->getPath(), $chain->getContent()); - - $output->writeln('<info>Successfully processed dynamic stylesheet into CSS</info>'); - } - } -} diff --git a/app/code/Magento/Developer/Console/Command/SourceThemeDeployCommand.php b/app/code/Magento/Developer/Console/Command/SourceThemeDeployCommand.php new file mode 100644 index 0000000000000000000000000000000000000000..0726f83859c4c410050e418475038d4278d8f1d5 --- /dev/null +++ b/app/code/Magento/Developer/Console/Command/SourceThemeDeployCommand.php @@ -0,0 +1,173 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Developer\Console\Command; + +use Magento\Framework\App\State; +use Magento\Framework\Validator\Locale; +use Magento\Framework\View\Asset\Repository; +use Symfony\Component\Console\Command\Command; +use Magento\Framework\App\View\Asset\Publisher; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Class SourceThemeDeployCommand + * + * Collects and publishes source files for theme + */ +class SourceThemeDeployCommand extends Command +{ + /** + * Locale option key + */ + const LOCALE_OPTION = 'locale'; + + /** + * Area option key + */ + const AREA_OPTION = 'area'; + + /** + * Theme option key + */ + const THEME_OPTION = 'theme'; + + /** + * Type argument key + */ + const TYPE_ARGUMENT = 'type'; + + /** + * Files argument key + */ + const FILE_ARGUMENT = 'file'; + + /** + * @var Locale + */ + private $validator; + + /** + * @var Publisher + */ + private $assetPublisher; + + /** + * @var Repository + */ + private $assetRepository; + + /** + * Constructor + * + * @param Locale $validator + * @param Publisher $assetPublisher + * @param Repository $assetRepository + */ + public function __construct( + Locale $validator, + Publisher $assetPublisher, + Repository $assetRepository + ) { + parent::__construct('dev:source_theme:deploy'); + $this->validator = $validator; + $this->assetPublisher = $assetPublisher; + $this->assetRepository = $assetRepository; + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + parent::configure(); + $this->setDescription('Collects and publishes source files for theme.') + ->setDefinition([ + new InputArgument( + self::FILE_ARGUMENT, + InputArgument::IS_ARRAY, + 'Files to pre-process (file should be specified without extension)', + ['css/styles-m', 'css/styles-l'] + ), + new InputOption( + self::TYPE_ARGUMENT, + null, + InputOption::VALUE_REQUIRED, + 'Type of source files: [less]', + 'less' + ), + new InputOption( + self::LOCALE_OPTION, + null, + InputOption::VALUE_REQUIRED, + 'Locale: [en_US]', + 'en_US' + ), + new InputOption( + self::AREA_OPTION, + null, + InputOption::VALUE_REQUIRED, + 'Area: [frontend|adminhtml]', + 'frontend' + ), + new InputOption( + self::THEME_OPTION, + null, + InputOption::VALUE_REQUIRED, + 'Theme: [Vendor/theme]', + 'Magento/luma' + ), + + ]); + } + + /** + * @inheritdoc + * @throws \InvalidArgumentException + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $area = $input->getOption(self::AREA_OPTION); + $locale = $input->getOption(self::LOCALE_OPTION); + $theme = $input->getOption(self::THEME_OPTION); + $type = $input->getOption(self::TYPE_ARGUMENT); + + $files = $input->getArgument(self::FILE_ARGUMENT); + + if (!$this->validator->isValid($locale)) { + throw new \InvalidArgumentException( + $locale . ' argument has invalid value, please run info:language:list for list of available locales' + ); + } + $message = sprintf( + '<info>Processed Area: %s, Locale: %s, Theme: %s, File type: %s.</info>', + $area, + $locale, + $theme, + $type + ); + $output->writeln($message); + + foreach ($files as $file) { + $fileInfo = pathinfo($file); + $asset = $this->assetRepository->createAsset( + $fileInfo['dirname'] . DIRECTORY_SEPARATOR . $fileInfo['basename'] . '.' . $type, + [ + 'area' => $area, + 'theme' => $theme, + 'locale' => $locale, + ] + ); + + $this->assetPublisher->publish($asset); + $output->writeln('<comment>-> ' . $asset->getFilePath() . '</comment>'); + } + + $output->writeln('<info>Successfully processed.</info>'); + } +} diff --git a/app/code/Magento/Developer/Model/Css/PreProcessor/FileGenerator/PublicationDecorator.php b/app/code/Magento/Developer/Model/Css/PreProcessor/FileGenerator/PublicationDecorator.php index 79c470443192c37a2a4adf6dfdbbdd81cd3785dc..7c14c8f9e1d0ad8ed07ed57868ad2e21b02dc7b3 100644 --- a/app/code/Magento/Developer/Model/Css/PreProcessor/FileGenerator/PublicationDecorator.php +++ b/app/code/Magento/Developer/Model/Css/PreProcessor/FileGenerator/PublicationDecorator.php @@ -5,45 +5,47 @@ */ namespace Magento\Developer\Model\Css\PreProcessor\FileGenerator; -use Magento\Framework\Css\PreProcessor\FileGenerator\RelatedGenerator; use Magento\Framework\View\Asset\LocalInterface; +use Magento\Framework\Css\PreProcessor\FileGenerator\RelatedGenerator; /** * Class PublicationDecorator - * Decorates generator of related assets and publishes them * - * @package Magento\Developer\Model\Less\FileGenerator + * Decorates generator of related assets and publishes them */ class PublicationDecorator extends RelatedGenerator { /** * @var \Magento\Framework\App\View\Asset\Publisher */ - private $publisher; + private $assetPublisher; /** + * Constructor + * * @param \Magento\Framework\Filesystem $filesystem * @param \Magento\Framework\View\Asset\Repository $assetRepo * @param \Magento\Framework\Css\PreProcessor\File\Temporary $temporaryFile - * @param \Magento\Framework\App\View\Asset\Publisher $publisher + * @param \Magento\Framework\App\View\Asset\Publisher $assetPublisher */ public function __construct( \Magento\Framework\Filesystem $filesystem, \Magento\Framework\View\Asset\Repository $assetRepo, \Magento\Framework\Css\PreProcessor\File\Temporary $temporaryFile, - \Magento\Framework\App\View\Asset\Publisher $publisher + \Magento\Framework\App\View\Asset\Publisher $assetPublisher ) { parent::__construct($filesystem, $assetRepo, $temporaryFile); - $this->publisher = $publisher; + $this->assetPublisher = $assetPublisher; } /** - * {inheritdoc} + * @inheritdoc */ protected function generateRelatedFile($relatedFileId, LocalInterface $asset) { $relatedAsset = parent::generateRelatedFile($relatedFileId, $asset); - $this->publisher->publish($relatedAsset); + $this->assetPublisher->publish($relatedAsset); + return $relatedAsset; } } diff --git a/app/code/Magento/Developer/Test/Unit/Console/Command/CssDeployCommandTest.php b/app/code/Magento/Developer/Test/Unit/Console/Command/CssDeployCommandTest.php deleted file mode 100644 index 0d930989e424eefbcd192c0c3ca33322c13ba06a..0000000000000000000000000000000000000000 --- a/app/code/Magento/Developer/Test/Unit/Console/Command/CssDeployCommandTest.php +++ /dev/null @@ -1,191 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\Developer\Test\Unit\Console\Command; - -use Magento\Framework\Filesystem; -use Magento\Framework\View\Asset\PreProcessor\Pool; -use Magento\Framework\View\Asset\Source; -use Magento\Framework\App\State; -use Magento\Framework\View\Asset\Repository; -use Magento\Framework\ObjectManagerInterface; -use Magento\Framework\App\ObjectManager\ConfigLoader; -use Magento\Framework\View\Asset\PreProcessor\ChainFactoryInterface; -use Magento\Developer\Console\Command\CssDeployCommand; -use Symfony\Component\Console\Tester\CommandTester; -use Magento\Framework\Validator\Locale; - -/** - * Class CssDeployCommandTest - */ -class CssDeployCommandTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var CssDeployCommand - */ - private $command; - - /** - * @var ObjectManagerInterface|\PHPUnit_Framework_MockObject_MockObject - */ - private $objectManager; - - /** - * @var Repository|\PHPUnit_Framework_MockObject_MockObject - */ - private $assetRepo; - - /** - * @var ConfigLoader|\PHPUnit_Framework_MockObject_MockObject - */ - private $configLoader; - - /** - * @var State|\PHPUnit_Framework_MockObject_MockObject - */ - private $state; - - /** - * @var Source|\PHPUnit_Framework_MockObject_MockObject - */ - private $assetSource; - - /** - * @var ChainFactoryInterface|\PHPUnit_Framework_MockObject_MockObject - */ - private $chainFactory; - - /** - * @var Filesystem|\PHPUnit_Framework_MockObject_MockObject - */ - private $filesystem; - - /** - * @var Locale|\PHPUnit_Framework_MockObject_MockObject - */ - private $validator; - - /** - * @var Pool|\PHPUnit_Framework_MockObject_MockObject - */ - private $poolMock; - - public function setUp() - { - $this->objectManager = $this->getMockForAbstractClass('Magento\Framework\ObjectManagerInterface'); - $this->assetRepo = $this->getMock('Magento\Framework\View\Asset\Repository', [], [], '', false); - $this->configLoader = $this->getMock('Magento\Framework\App\ObjectManager\ConfigLoader', [], [], '', false); - $this->state = $this->getMock('Magento\Framework\App\State', [], [], '', false); - $this->assetSource = $this->getMock('Magento\Framework\View\Asset\Source', [], [], '', false); - $this->chainFactory = $this->getMockForAbstractClass( - 'Magento\Framework\View\Asset\PreProcessor\ChainFactoryInterface' - ); - $this->filesystem = $this->getMock('Magento\Framework\Filesystem', [], [], '', false); - $this->validator = $this->getMock('Magento\Framework\Validator\Locale', [], [], '', false); - $this->poolMock = $this->getMockBuilder('Magento\Framework\View\Asset\PreProcessor\Pool') - ->disableOriginalConstructor() - ->getMock(); - - $this->command = new CssDeployCommand( - $this->objectManager, - $this->assetRepo, - $this->configLoader, - $this->state, - $this->assetSource, - $this->chainFactory, - $this->filesystem, - $this->validator, - $this->poolMock - ); - } - - public function testExecute() - { - $file = 'css/styles-m' . '.less'; - - $this->configLoader->expects($this->once())->method('load')->with('frontend')->willReturn([]); - $this->objectManager->expects($this->once())->method('configure'); - $asset = $this->getMockForAbstractClass('Magento\Framework\View\Asset\LocalInterface'); - $asset->expects($this->once())->method('getContentType')->willReturn('type'); - $this->assetRepo->expects($this->once()) - ->method('createAsset') - ->with( - $file, - [ - 'area' => 'frontend', - 'theme' => 'Magento/blank', - 'locale' => 'en_US' - ] - ) - ->willReturn($asset); - $this->assetSource->expects($this->once())->method('findSource')->willReturn('/dev/null'); - - $chainMock = $this->getMock('Magento\Framework\View\Asset\PreProcessor\Chain', [], [], '', false); - $assetMock = $this->getMockBuilder('Magento\Framework\View\Asset\LocalInterface') - ->getMockForAbstractClass(); - - $this->chainFactory->expects($this->once()) - ->method('create') - ->with( - [ - 'asset' => $asset, - 'origContent' => 'content', - 'origContentType' => 'type', - 'origAssetPath' => 'relative/path', - ] - )->willReturn($chainMock); - - $chainMock->expects(self::once()) - ->method('getAsset') - ->willReturn($assetMock); - - $rootDir = $this->getMock('\Magento\Framework\Filesystem\Directory\WriteInterface', [], [], '', false); - $this->filesystem->expects($this->at(0))->method('getDirectoryWrite')->willReturn($rootDir); - $this->filesystem->expects($this->at(1))->method('getDirectoryWrite')->willReturn( - $this->getMock('\Magento\Framework\Filesystem\Directory\WriteInterface', [], [], '', false) - ); - $rootDir->expects($this->atLeastOnce())->method('getRelativePath')->willReturn('relative/path'); - $rootDir->expects($this->once())->method('readFile')->willReturn('content'); - - $this->validator->expects($this->once())->method('isValid')->with('en_US')->willReturn(true); - - $commandTester = new CommandTester($this->command); - $commandTester->execute( - [ - 'type' => 'less' - ] - ); - $this->assertContains( - 'Successfully processed dynamic stylesheet into CSS', - $commandTester->getDisplay() - ); - } - - /** - * @expectedException \RuntimeException - * @expectedExceptionMessage Not enough arguments - */ - public function testExecuteWithoutParameters() - { - $commandTester = new CommandTester($this->command); - $commandTester->execute([]); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage WRONG_LOCALE argument has invalid value, please run info:language:list - */ - public function testExecuteWithWrongFormat() - { - $commandTester = new CommandTester($this->command); - $commandTester->execute( - [ - 'type' => 'less', - '--locale' => 'WRONG_LOCALE' - ] - ); - } -} diff --git a/app/code/Magento/Developer/Test/Unit/Console/Command/SourceThemeDeployCommandTest.php b/app/code/Magento/Developer/Test/Unit/Console/Command/SourceThemeDeployCommandTest.php new file mode 100644 index 0000000000000000000000000000000000000000..cc66a9830f20e6eba578de4eb49b416673e5d115 --- /dev/null +++ b/app/code/Magento/Developer/Test/Unit/Console/Command/SourceThemeDeployCommandTest.php @@ -0,0 +1,156 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Developer\Test\Unit\Console\Command; + +use Magento\Framework\Validator\Locale; +use Magento\Framework\View\Asset\Repository; +use Magento\Framework\App\View\Asset\Publisher; +use Magento\Framework\View\Asset\LocalInterface; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Magento\Developer\Console\Command\SourceThemeDeployCommand; + +/** + * Class SourceThemeDeployCommandTest + * + * @see \Magento\Developer\Console\Command\SourceThemeDeployCommand + */ +class SourceThemeDeployCommandTest extends \PHPUnit_Framework_TestCase +{ + const AREA_TEST_VALUE = 'area-test-value'; + + const LOCALE_TEST_VALUE = 'locale-test-value'; + + const THEME_TEST_VALUE = 'theme-test-value'; + + const TYPE_TEST_VALUE = 'type-test-value'; + + const FILE_TEST_VALUE = 'file-test-value/test/file'; + + /** + * @var SourceThemeDeployCommand + */ + private $sourceThemeDeployCommand; + + /** + * @var Locale|\PHPUnit_Framework_MockObject_MockObject + */ + private $validatorMock; + + /** + * @var Publisher|\PHPUnit_Framework_MockObject_MockObject + */ + private $assetPublisherMock; + + /** + * @var Repository|\PHPUnit_Framework_MockObject_MockObject + */ + private $assetRepositoryMock; + + /** + * Set up + */ + protected function setUp() + { + $this->validatorMock = $this->getMockBuilder(Locale::class) + ->disableOriginalConstructor() + ->getMock(); + $this->assetPublisherMock = $this->getMockBuilder(Publisher::class) + ->disableOriginalConstructor() + ->getMock(); + $this->assetRepositoryMock = $this->getMockBuilder(Repository::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->sourceThemeDeployCommand = new SourceThemeDeployCommand( + $this->validatorMock, + $this->assetPublisherMock, + $this->assetRepositoryMock + ); + } + + /** + * Run test for execute method + */ + public function testExecute() + { + /** @var OutputInterface|\PHPUnit_Framework_MockObject_MockObject $outputMock */ + $outputMock = $this->getMockBuilder(OutputInterface::class) + ->getMockForAbstractClass(); + $assetMock = $this->getMockBuilder(LocalInterface::class) + ->getMockForAbstractClass(); + + $this->validatorMock->expects(self::once()) + ->method('isValid') + ->with(self::LOCALE_TEST_VALUE) + ->willReturn(true); + + $message = sprintf( + '<info>Processed Area: %s, Locale: %s, Theme: %s, File type: %s.</info>', + self::AREA_TEST_VALUE, + self::LOCALE_TEST_VALUE, + self::THEME_TEST_VALUE, + self::TYPE_TEST_VALUE + ); + + $outputMock->expects(self::at(0)) + ->method('writeln') + ->with($message); + $outputMock->expects(self::at(1)) + ->method('writeln') + ->with('<comment>-> file-test-value/test/file</comment>'); + $outputMock->expects(self::at(2)) + ->method('writeln') + ->with('<info>Successfully processed.</info>'); + + $this->assetRepositoryMock->expects(self::once()) + ->method('createAsset') + ->with( + 'file-test-value/test' . DIRECTORY_SEPARATOR . 'file' . '.' . self::TYPE_TEST_VALUE, + [ + 'area' => self::AREA_TEST_VALUE, + 'theme' => self::THEME_TEST_VALUE, + 'locale' => self::LOCALE_TEST_VALUE, + ] + )->willReturn($assetMock); + + $this->assetPublisherMock->expects(self::once()) + ->method('publish') + ->with($assetMock); + + $assetMock->expects(self::once()) + ->method('getFilePath') + ->willReturn(self::FILE_TEST_VALUE); + + $this->sourceThemeDeployCommand->run($this->getInputMock(), $outputMock); + } + + /** + * @return InputInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private function getInputMock() + { + $inputMock = $this->getMockBuilder(InputInterface::class) + ->getMockForAbstractClass(); + + $inputMock->expects(self::exactly(4)) + ->method('getOption') + ->willReturnMap( + [ + ['area', self::AREA_TEST_VALUE], + ['locale', self::LOCALE_TEST_VALUE], + ['theme', self::THEME_TEST_VALUE], + ['type', self::TYPE_TEST_VALUE] + ] + ); + $inputMock->expects(self::once()) + ->method('getArgument') + ->with('file') + ->willReturn([self::FILE_TEST_VALUE]); + + return $inputMock; + } +} diff --git a/app/code/Magento/Developer/Test/Unit/Model/Css/PreProcessor/FileGenerator/PublicationDecoratorTest.php b/app/code/Magento/Developer/Test/Unit/Model/Css/PreProcessor/FileGenerator/PublicationDecoratorTest.php index 56cca40bf6666eb670ba3e2aeb36201e5dd809a7..9d0538f265cd6e8bd937c5900de936f2372d174f 100644 --- a/app/code/Magento/Developer/Test/Unit/Model/Css/PreProcessor/FileGenerator/PublicationDecoratorTest.php +++ b/app/code/Magento/Developer/Test/Unit/Model/Css/PreProcessor/FileGenerator/PublicationDecoratorTest.php @@ -3,11 +3,15 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Developer\Test\Unit\Model\Css\PreProcessor\FileGenerator; -use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\Filesystem; +use Magento\Framework\Css\PreProcessor\File\Temporary; +use Magento\Developer\Model\Css\PreProcessor\FileGenerator\PublicationDecorator; +/** + * Class PublicationDecoratorTest + */ class PublicationDecoratorTest extends \PHPUnit_Framework_TestCase { /** @@ -15,6 +19,13 @@ class PublicationDecoratorTest extends \PHPUnit_Framework_TestCase */ public function testGenerateRelatedFile() { + $filesystemMock = $this->getMockBuilder(Filesystem::class) + ->disableOriginalConstructor() + ->getMock(); + $fileTemporaryMock = $this->getMockBuilder(Temporary::class) + ->disableOriginalConstructor() + ->getMock(); + $publisherMock = $this->getMockBuilder('Magento\Framework\App\View\Asset\Publisher') ->disableOriginalConstructor() ->getMock(); @@ -33,24 +44,24 @@ class PublicationDecoratorTest extends \PHPUnit_Framework_TestCase $relatedFileId = 'file_id'; $relatedFiles = [[$relatedFileId, $localAssetMock]]; - $importGeneratorMock->expects($this->any()) + + $importGeneratorMock->expects(self::any()) ->method('getRelatedFiles') - ->will($this->onConsecutiveCalls($relatedFiles, [])); - $assetRepoMock->expects($this->any()) + ->will(self::onConsecutiveCalls($relatedFiles, [])); + + $assetRepoMock->expects(self::any()) ->method('createRelated') ->willReturn($relatedAssetMock); - $publisherMock->expects($this->once()) + + $publisherMock->expects(self::once()) ->method('publish') ->with($relatedAssetMock); - $args = [ - 'assetRepo' => $assetRepoMock, - 'publisher' => $publisherMock - ]; - - $model = (new ObjectManager($this))->getObject( - 'Magento\Developer\Model\Css\PreProcessor\FileGenerator\PublicationDecorator', - $args + $model = new PublicationDecorator( + $filesystemMock, + $assetRepoMock, + $fileTemporaryMock, + $publisherMock ); $model->generate($importGeneratorMock); diff --git a/app/code/Magento/Developer/etc/di.xml b/app/code/Magento/Developer/etc/di.xml index a208ec7c5de01f26250b2a93d5d571732899c2d6..a393b0ebce8bc9101a6b69f0f3bdacef49235652 100644 --- a/app/code/Magento/Developer/etc/di.xml +++ b/app/code/Magento/Developer/etc/di.xml @@ -23,11 +23,70 @@ </argument> </arguments> </type> + + <!-- Configuration for \Magento\Developer\Console\Command\SourceThemeDeployCommand --> + <virtualType name="AssetMaterializationStrategyFactoryForSourceThemeDeploy" type="Magento\Framework\App\View\Asset\MaterializationStrategy\Factory"> + <arguments> + <argument name="strategiesList" xsi:type="array"> + <item name="symlink" xsi:type="object">Magento\Framework\App\View\Asset\MaterializationStrategy\Symlink</item> + <item name="copy" xsi:type="object">Magento\Framework\App\View\Asset\MaterializationStrategy\Copy</item> + </argument> + </arguments> + </virtualType> + <virtualType name="AssetPublisherForSourceThemeDeploy" type="Magento\Framework\App\View\Asset\Publisher"> + <arguments> + <argument name="materializationStrategyFactory" xsi:type="object">AssetMaterializationStrategyFactoryForSourceThemeDeploy</argument> + </arguments> + </virtualType> + <type name="Magento\Developer\Model\Css\PreProcessor\FileGenerator\PublicationDecorator"> + <arguments> + <argument name="assetRepo" xsi:type="object">AssetRepositoryForSourceThemeDeploy</argument> + <argument name="assetPublisher" xsi:type="object">AssetPublisherForSourceThemeDeploy</argument> + </arguments> + </type> + <virtualType name="PreProcessorInstructionImportForSourceThemeDeploy" type="Magento\Framework\Css\PreProcessor\Instruction\Import"> + <arguments> + <argument name="relatedFileGenerator" xsi:type="object">Magento\Developer\Model\Css\PreProcessor\FileGenerator\PublicationDecorator</argument> + </arguments> + </virtualType> + <virtualType name="AssetPreProcessorPoolForSourceThemeDeploy" type="Magento\Framework\View\Asset\PreProcessor\Pool"> + <arguments> + <argument name="preprocessors" xsi:type="array"> + <item name="less" xsi:type="array"> + <item name="magento_import" xsi:type="array"> + <item name="class" xsi:type="string">Magento\Framework\Css\PreProcessor\Instruction\MagentoImport</item> + </item> + <item name="import" xsi:type="array"> + <item name="after" xsi:type="string">magento_import</item> + <item name="class" xsi:type="string">PreProcessorInstructionImportForSourceThemeDeploy</item> + </item> + </item> + </argument> + </arguments> + </virtualType> + <virtualType name="AssetSourceForSourceThemeDeploy" type="Magento\Framework\View\Asset\Source"> + <arguments> + <argument name="preProcessorPool" xsi:type="object">AssetPreProcessorPoolForSourceThemeDeploy</argument> + </arguments> + </virtualType> + <virtualType name="AssetRepositoryForSourceThemeDeploy" type="Magento\Framework\View\Asset\Repository"> + <arguments> + <argument name="assetSource" xsi:type="object">AssetSourceForSourceThemeDeploy</argument> + </arguments> + </virtualType> + <type name="Magento\Developer\Console\Command\SourceThemeDeployCommand"> + <arguments> + <argument name="assetPublisher" xsi:type="object">AssetPublisherForSourceThemeDeploy</argument> + <argument name="assetRepository" xsi:type="object">AssetRepositoryForSourceThemeDeploy</argument> + </arguments> + </type> + <!-- End configuration for \Magento\Developer\Console\Command\SourceThemeDeployCommand --> + <type name="Magento\Framework\Console\CommandList"> <arguments> <argument name="commands" xsi:type="array"> <item name="dev_tests_run" xsi:type="object">Magento\Developer\Console\Command\DevTestsRunCommand</item> - <item name="dev_css_deploy" xsi:type="object">Magento\Developer\Console\Command\CssDeployCommand</item> + <item name="dev_source_theme_deploy" xsi:type="object">Magento\Developer\Console\Command\SourceThemeDeployCommand</item> <item name="xml_converter" xsi:type="object">Magento\Developer\Console\Command\XmlConverterCommand</item> </argument> </arguments> @@ -62,6 +121,11 @@ <type name="Magento\Framework\View\Asset\PreProcessor\Pool"> <arguments> <argument name="defaultPreprocessor" xsi:type="string">Magento\Framework\View\Asset\PreProcessor\Passthrough</argument> + </arguments> + </type> + + <virtualType name="AssetPreProcessorPool" type="Magento\Framework\View\Asset\PreProcessor\Pool"> + <arguments> <argument name="preprocessors" xsi:type="array"> <item name="less" xsi:type="array"> <item name="magento_import" xsi:type="array"> @@ -96,6 +160,12 @@ </item> </argument> </arguments> + </virtualType> + + <type name="Magento\Framework\View\Asset\Source"> + <arguments> + <argument name="preProcessorPool" xsi:type="object">AssetPreProcessorPool</argument> + </arguments> </type> <type name="Magento\Framework\Css\PreProcessor\Instruction\MagentoImport"> diff --git a/app/code/Magento/Downloadable/Block/Adminhtml/Catalog/Product/Edit/Tab/Downloadable/Links.php b/app/code/Magento/Downloadable/Block/Adminhtml/Catalog/Product/Edit/Tab/Downloadable/Links.php index b07b6e82bdc4d04f71bc4c8a46ac686f82bf2332..fb92f2bc3fffd09f5ac54eca2a2fb65e77bd913b 100644 --- a/app/code/Magento/Downloadable/Block/Adminhtml/Catalog/Product/Edit/Tab/Downloadable/Links.php +++ b/app/code/Magento/Downloadable/Block/Adminhtml/Catalog/Product/Edit/Tab/Downloadable/Links.php @@ -463,4 +463,13 @@ class Links extends \Magento\Backend\Block\Template { return $this->_storeManager->getStore($storeId)->getBaseCurrencyCode(); } + + /** + * @param null|string|bool|int|\Magento\Store\Model\Store $storeId $storeId + * @return string + */ + public function getBaseCurrencySymbol($storeId) + { + return $this->_storeManager->getStore($storeId)->getBaseCurrency()->getCurrencySymbol(); + } } diff --git a/app/code/Magento/Downloadable/view/adminhtml/templates/product/edit/downloadable.phtml b/app/code/Magento/Downloadable/view/adminhtml/templates/product/edit/downloadable.phtml index 0c4077543059fd746f88a67b946889ca286ce287..dac2edad7be49ec47e029d391901da6842ed6154 100644 --- a/app/code/Magento/Downloadable/view/adminhtml/templates/product/edit/downloadable.phtml +++ b/app/code/Magento/Downloadable/view/adminhtml/templates/product/edit/downloadable.phtml @@ -67,9 +67,9 @@ var uploaderTemplate = '<div class="no-display" id="[[idName]]-template">' + } }; - var configurationSectionMessageHandler = (new function(attributeTitle, attributeTab) { + var configurationSectionMessageHandler = (new function(attributeTitle, buttons) { this.title = jQuery(attributeTitle); - this.buttons = jQuery('button', attributeTab); + this.buttons = jQuery(buttons); this.newText = '<?= /* @noEscape */ __('Configurations cannot be created for a standard product with downloadable files.' . ' To create configurations, first remove all downloadable files.');?>'; this.oldText = this.title.text(); @@ -86,7 +86,7 @@ var uploaderTemplate = '<div class="no-display" id="[[idName]]-template">' + this.title.text(this.newText); this.buttons.hide(); } - }('[data-role="product-create-configuration-info"]', '[data-tab="super_config"]')); + }('[data-role="product-create-configuration-info"]', '[data-action="product-create-configuration-buttons"]')); downloadableCheckbox.on('change', function () { switchConfigurationSectionMessage(!jQuery(this).is(':checked')); diff --git a/app/code/Magento/Downloadable/view/adminhtml/templates/product/edit/downloadable/links.phtml b/app/code/Magento/Downloadable/view/adminhtml/templates/product/edit/downloadable/links.phtml index d5c4b6dca86ea769bc9bb04fe98309bffcccd0e5..cf43aa7d3f4f62de46a4d86395648c671a654c2a 100644 --- a/app/code/Magento/Downloadable/view/adminhtml/templates/product/edit/downloadable/links.phtml +++ b/app/code/Magento/Downloadable/view/adminhtml/templates/product/edit/downloadable/links.phtml @@ -107,8 +107,10 @@ require([ '</td>'+ <?php if ($block->getCanReadPrice() !== false) : ?> '<td class="col-price">'+ - '<input type="text" id="downloadable_link_<%- data.id %>_price_value" class="input-text admin__control-text validate-number link-prices<?php if ($block->getCanEditPrice() === false) : ?> disabled<?php endif; ?>" name="downloadable[link][<%- data.id %>][price]" value="<%- data.price %>"<?php if ($block->getCanEditPrice() === false) : ?> disabled="disabled"<?php endif; ?> /> ' + - '<div class="note">[<?php /* @escapeNotVerified */ echo $block->getBaseCurrencyCode($_product->getStoreId()) ?>]</div>' + + '<div class="admin__control-addon">' + + '<input type="text" id="downloadable_link_<%- data.id %>_price_value" class="input-text admin__control-text validate-number link-prices<?php if ($block->getCanEditPrice() === false) : ?> disabled<?php endif; ?>" name="downloadable[link][<%- data.id %>][price]" value="<%- data.price %>"<?php if ($block->getCanEditPrice() === false) : ?> disabled="disabled"<?php endif; ?> /> ' + + '<label class="admin__addon-prefix"><span><?php echo $block->escapeHtml($block->getBaseCurrencySymbol($_product->getStoreId())) ?></span></label>' + + '</div>' + <?php if ($_product->getStoreId() && $block->getIsPriceWebsiteScope()) : ?> '<div class="admin__field admin__field-option">'+ '<input type="checkbox" id="downloadable_link_<%- data.id %>_price" name="downloadable[link][<%- data.id %>][use_default_price]" value="1"<?php if ($block->getCanEditPrice() === false) : ?> disabled="disabled"<?php endif; ?> class="admin__control-checkbox" />'+ diff --git a/app/code/Magento/Eav/Model/Entity/AbstractEntity.php b/app/code/Magento/Eav/Model/Entity/AbstractEntity.php index 14147d6849de94bee388891d8ecfe389fd252ee5..c52d87b51b419a9e607e6f0a85abb0ae93420414 100644 --- a/app/code/Magento/Eav/Model/Entity/AbstractEntity.php +++ b/app/code/Magento/Eav/Model/Entity/AbstractEntity.php @@ -1296,11 +1296,11 @@ abstract class AbstractEntity extends AbstractResource implements EntityInterfac } elseif (!is_numeric($v) && $v !== $origData[$k] || is_numeric($v) && $v != $origData[$k]) { $update[$attrId] = [ 'value_id' => $attribute->getBackend()->getEntityValueId($newObject), - 'value' => $v, + 'value' => is_array($v) ? array_shift($v) : $v,//@TODO: MAGETWO-44182, ]; } } elseif (!$this->_isAttributeValueEmpty($attribute, $v)) { - $insert[$attrId] = $v; + $insert[$attrId] = is_array($v) ? array_shift($v) : $v;//@TODO: MAGETWO-44182 } } diff --git a/app/code/Magento/EncryptionKey/i18n/de_DE.csv b/app/code/Magento/EncryptionKey/i18n/de_DE.csv index 6f364baa1ff9fbf44f2e7c5a64f1b795a02a3b58..705d98a99d2982a35101e309641c8d508a084f75 100644 --- a/app/code/Magento/EncryptionKey/i18n/de_DE.csv +++ b/app/code/Magento/EncryptionKey/i18n/de_DE.csv @@ -17,3 +17,4 @@ Username,Benutzername "The encryption key format is invalid.","The encryption key format is invalid." "File %1 is not writeable.","File %1 is not writeable." "Encryption Key Change","Änderung des Verschlüsselungscodes" +"Manage Encryption Key","Manage Encryption Key" diff --git a/app/code/Magento/EncryptionKey/i18n/en_US.csv b/app/code/Magento/EncryptionKey/i18n/en_US.csv index 792bc2f60f5a8def580c8675735e45a6e085fe99..f111edc33abb1104585153b846ad91ac3d42ed24 100644 --- a/app/code/Magento/EncryptionKey/i18n/en_US.csv +++ b/app/code/Magento/EncryptionKey/i18n/en_US.csv @@ -17,3 +17,4 @@ Username,Username "The encryption key format is invalid.","The encryption key format is invalid." "File %1 is not writeable.","File %1 is not writeable." "Encryption Key Change","Encryption Key Change" +"Manage Encryption Key","Manage Encryption Key" diff --git a/app/code/Magento/EncryptionKey/i18n/es_ES.csv b/app/code/Magento/EncryptionKey/i18n/es_ES.csv index 0840d0cb0b5b2e257052b579913561c1e47d62ab..16fe7d35f56db0e6d6765344bc56a664b8c288ae 100644 --- a/app/code/Magento/EncryptionKey/i18n/es_ES.csv +++ b/app/code/Magento/EncryptionKey/i18n/es_ES.csv @@ -17,3 +17,4 @@ Username,"Nombre de Usuario" "The encryption key format is invalid.","The encryption key format is invalid." "File %1 is not writeable.","File %1 is not writeable." "Encryption Key Change","Cambio de clave de encriptación" +"Manage Encryption Key","Manage Encryption Key" diff --git a/app/code/Magento/EncryptionKey/i18n/fr_FR.csv b/app/code/Magento/EncryptionKey/i18n/fr_FR.csv index 0604b96989aef7ece5052119ada362ddb58325f5..6311d1da4f3e34cb60e93229c9e13e045a494b5f 100644 --- a/app/code/Magento/EncryptionKey/i18n/fr_FR.csv +++ b/app/code/Magento/EncryptionKey/i18n/fr_FR.csv @@ -17,3 +17,4 @@ Username,"Nom d'utilisateur" "The encryption key format is invalid.","The encryption key format is invalid." "File %1 is not writeable.","File %1 is not writeable." "Encryption Key Change","Modification Clé de Chiffrement" +"Manage Encryption Key","Manage Encryption Key" diff --git a/app/code/Magento/EncryptionKey/i18n/nl_NL.csv b/app/code/Magento/EncryptionKey/i18n/nl_NL.csv index cffae21b4184be2befdef775de0bf08798fa9cd8..11268b36d5d1bb5e228d8fcea0255a9b06f9a455 100644 --- a/app/code/Magento/EncryptionKey/i18n/nl_NL.csv +++ b/app/code/Magento/EncryptionKey/i18n/nl_NL.csv @@ -17,3 +17,4 @@ Username,Gebruikersnaam "The encryption key format is invalid.","The encryption key format is invalid." "File %1 is not writeable.","File %1 is not writeable." "Encryption Key Change","Encryptie Code Veranderen" +"Manage Encryption Key","Manage Encryption Key" diff --git a/app/code/Magento/EncryptionKey/i18n/pt_BR.csv b/app/code/Magento/EncryptionKey/i18n/pt_BR.csv index 495e0c38d96cff463f3235907d667bd4203158ff..2529b0b015a7d1b0b6d8a72df6ebfdd0f8f9227e 100644 --- a/app/code/Magento/EncryptionKey/i18n/pt_BR.csv +++ b/app/code/Magento/EncryptionKey/i18n/pt_BR.csv @@ -17,3 +17,4 @@ Username,"Nome do usuário" "The encryption key format is invalid.","The encryption key format is invalid." "File %1 is not writeable.","File %1 is not writeable." "Encryption Key Change","Mudança na Chave de Criptografia" +"Manage Encryption Key","Manage Encryption Key" diff --git a/app/code/Magento/EncryptionKey/i18n/zh_Hans_CN.csv b/app/code/Magento/EncryptionKey/i18n/zh_Hans_CN.csv index 3b5711dc0af9b1b68e12220bd7aaa16372859c67..02b9c53f97bb4de358834eaa8a9148bec10cfd71 100644 --- a/app/code/Magento/EncryptionKey/i18n/zh_Hans_CN.csv +++ b/app/code/Magento/EncryptionKey/i18n/zh_Hans_CN.csv @@ -17,3 +17,4 @@ Username,用户å "The encryption key format is invalid.","The encryption key format is invalid." "File %1 is not writeable.","File %1 is not writeable." "Encryption Key Change",åŠ å¯†å¯†é’¥å·²æ›´æ”¹ +"Manage Encryption Key","Manage Encryption Key" diff --git a/app/code/Magento/GiftMessage/view/frontend/web/js/model/gift-options.js b/app/code/Magento/GiftMessage/view/frontend/web/js/model/gift-options.js index 187f17e5b3962788ba0eb03a95858e4672d27c7b..53b8d8fde3b48ba4bc2579738dfe7ee55d10f8f7 100644 --- a/app/code/Magento/GiftMessage/view/frontend/web/js/model/gift-options.js +++ b/app/code/Magento/GiftMessage/view/frontend/web/js/model/gift-options.js @@ -3,19 +3,33 @@ * See COPYING.txt for license details. */ /*global define*/ -define(['underscore'], - function (_) { - "use strict"; +define(['underscore', 'ko'], + function (_, ko) { + + 'use strict'; + return { - options: [], - addOption: function(option) { - if(!this.options.hasOwnProperty(option.itemId)) { - this.options[option.itemId] = option; + options: ko.observableArray([]), + addOption: function (option) { + if (!this.options().hasOwnProperty(option.itemId)) { + this.options.push({ + id: option.itemId, value: option + } + ); } }, - getOptionByItemId: function(itemId) { - return this.options.hasOwnProperty(itemId) ? this.options[itemId] : null; + getOptionByItemId: function (itemId) { + var option = null; + _.each(this.options(), function (data) { + if (data.id === itemId) { + option = data.value; + + return false; + } + }); + + return option; } - } + }; } ); diff --git a/app/code/Magento/GiftMessage/view/frontend/web/js/view/gift-message.js b/app/code/Magento/GiftMessage/view/frontend/web/js/view/gift-message.js index dae05d712dd9b05eba81c48108e2908c0290b9ee..fc4d6931be2e0629fe444de52c4b19e8e83ae209 100644 --- a/app/code/Magento/GiftMessage/view/frontend/web/js/view/gift-message.js +++ b/app/code/Magento/GiftMessage/view/frontend/web/js/view/gift-message.js @@ -3,7 +3,12 @@ * See COPYING.txt for license details. */ /*global define*/ -define(['uiComponent', '../model/gift-message', '../model/gift-options', '../action/gift-options'], +define([ + 'uiComponent', + 'Magento_GiftMessage/js/model/gift-message', + 'Magento_GiftMessage/js/model/gift-options', + 'Magento_GiftMessage/js/action/gift-options' + ], function (Component, giftMessage, giftOptions, giftOptionsService) { "use strict"; return Component.extend({ diff --git a/app/code/Magento/GroupedProduct/view/adminhtml/layout/groupedproduct_popup_grid.xml b/app/code/Magento/GroupedProduct/view/adminhtml/layout/groupedproduct_popup_grid.xml index 87435ac42e867730101a2752f0cd1c95747d0fb2..e47123ca4322c75030941a8382f9fb8072a703ac 100644 --- a/app/code/Magento/GroupedProduct/view/adminhtml/layout/groupedproduct_popup_grid.xml +++ b/app/code/Magento/GroupedProduct/view/adminhtml/layout/groupedproduct_popup_grid.xml @@ -24,11 +24,17 @@ <arguments> <argument name="id" xsi:type="string">grouped_grid_popup</argument> </arguments> - <block class="Magento\Backend\Block\Widget\Grid\Column" as="entity_id"> + <block class="Magento\Backend\Block\Widget\Grid\Column" as="entity_ids"> <arguments> - <argument name="header" xsi:type="string" translate="true">ID</argument> <argument name="type" xsi:type="string">skip-list</argument> <argument name="renderer" xsi:type="string">Magento\Backend\Block\Widget\Grid\Column\Renderer\Checkbox</argument> + <argument name="name" xsi:type="string">entity_ids</argument> + <argument name="index" xsi:type="string">entity_id</argument> + </arguments> + </block> + <block class="Magento\Backend\Block\Widget\Grid\Column" as="entity_id"> + <arguments> + <argument name="header" xsi:type="string" translate="true">ID</argument> <argument name="index" xsi:type="string">entity_id</argument> </arguments> </block> diff --git a/app/code/Magento/GroupedProduct/view/adminhtml/web/js/grouped-product.js b/app/code/Magento/GroupedProduct/view/adminhtml/web/js/grouped-product.js index b7badba6e79c142c8c1a92e0d60cdb41500507d4..1e497ed7b8231de9c057b986dc1f6c0387aa6aa2 100644 --- a/app/code/Magento/GroupedProduct/view/adminhtml/web/js/grouped-product.js +++ b/app/code/Magento/GroupedProduct/view/adminhtml/web/js/grouped-product.js @@ -132,7 +132,7 @@ define([ if (!target.is('input')) { target.closest('[data-role=row]') - .find('[data-column=entity_id] input') + .find('[data-column=entity_ids] input') .prop('checked', function (element, value) { return !value; }) @@ -142,7 +142,7 @@ define([ popup.on( 'change', - '[data-role=row] [data-column=entity_id] input', + '[data-role=row] [data-column=entity_ids] input', $.proxy(function (event) { var element = $(event.target), product = {}; @@ -175,12 +175,12 @@ define([ return $(element).val(); }).toArray(); ajaxSettings.data.filter = $.extend(ajaxSettings.data.filter || {}, { - 'entity_id': ids + 'entity_ids': ids }); }) .on('gridajax', function (event, ajaxRequest) { ajaxRequest.done(function () { - popup.find('[data-role=row] [data-column=entity_id] input') + popup.find('[data-role=row] [data-column=entity_ids] input') .each(function (index, element) { var $element = $(element); $element.prop('checked', !!selectedProductList[$element.val()]); diff --git a/app/code/Magento/ImportExport/Block/Adminhtml/Export/Filter.php b/app/code/Magento/ImportExport/Block/Adminhtml/Export/Filter.php index 4cd75e3313d2cee2f4185bfe5b734235e6205dfc..6dca0a90a8c32d5dd42af32eaccb3a4dc1d74a38 100644 --- a/app/code/Magento/ImportExport/Block/Adminhtml/Export/Filter.php +++ b/app/code/Magento/ImportExport/Block/Adminhtml/Export/Filter.php @@ -120,7 +120,7 @@ class Filter extends \Magento\Backend\Block\Widget\Grid\Extended { $html = '<input type="text" name="' . $this->getFilterElementName( $attribute->getAttributeCode() - ) . '" class="input-text input-text-export-filter"'; + ) . '" class="admin__control-text input-text input-text-export-filter"'; if ($value) { $html .= ' value="' . $this->escapeHtml($value) . '"'; } @@ -190,7 +190,7 @@ class Filter extends \Magento\Backend\Block\Widget\Grid\Extended ':</strong> ' . '<input type="text" name="' . $name . - '[]" class="input-text input-text-range"' . + '[]" class="admin__control-text input-text input-text-range"' . ' value="' . $fromValue . '"/> ' . @@ -200,7 +200,7 @@ class Filter extends \Magento\Backend\Block\Widget\Grid\Extended ) . ':</strong> <input type="text" name="' . $name . - '[]" class="input-text input-text-range" value="' . + '[]" class="admin__control-text input-text input-text-range" value="' . $toValue . '" />'; } @@ -236,7 +236,7 @@ class Filter extends \Magento\Backend\Block\Widget\Grid\Extended $arguments = [ 'name' => $this->getFilterElementName($attribute->getAttributeCode()), 'id' => $this->getFilterElementId($attribute->getAttributeCode()), - 'class' => 'select select-export-filter', + 'class' => 'admin__control-select select select-export-filter', ]; /** @var $selectBlock \Magento\Framework\View\Element\Html\Select */ $selectBlock = $this->_layout->createBlock( diff --git a/app/code/Magento/ImportExport/Model/Import/AbstractEntity.php b/app/code/Magento/ImportExport/Model/Import/AbstractEntity.php index e9b684c2bd2a9aeb74dbbc6368c7ff6c0e6b71a5..085c9261e341229fb19bebc078874f87e9dff561 100644 --- a/app/code/Magento/ImportExport/Model/Import/AbstractEntity.php +++ b/app/code/Magento/ImportExport/Model/Import/AbstractEntity.php @@ -792,7 +792,7 @@ abstract class AbstractEntity $emptyHeaderColumns[] = $columnNumber; } elseif (!preg_match('/^[a-z][a-z0-9_]*$/', $columnName)) { $invalidColumns[] = $columnName; - } elseif ($this->needColumnCheck && !in_array($columnName, $this->validColumnNames)) { + } elseif ($this->needColumnCheck && !in_array($columnName, $this->getValidColumnNames())) { $invalidAttributes[] = $columnName; } } @@ -854,4 +854,14 @@ abstract class AbstractEntity $this->countItemsDeleted = count($deleted); return $this; } + + /** + * Retrieve valid column names + * + * @return array + */ + public function getValidColumnNames() + { + return $this->validColumnNames; + } } diff --git a/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php b/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php index 81422c45e13a871f8162a0535802db1cf96a2df5..9a0971d18e1042fea2339d50508d0816e2cbdac9 100644 --- a/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php +++ b/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php @@ -763,7 +763,7 @@ abstract class AbstractEntity $emptyHeaderColumns[] = $columnNumber; } elseif (!preg_match('/^[a-z][a-z0-9_]*$/', $columnName)) { $invalidColumns[] = $columnName; - } elseif ($this->needColumnCheck && !in_array($columnName, $this->validColumnNames)) { + } elseif ($this->needColumnCheck && !in_array($columnName, $this->getValidColumnNames())) { $invalidAttributes[] = $columnName; } } @@ -818,4 +818,14 @@ abstract class AbstractEntity { return $this->countItemsDeleted; } + + /** + * Retrieve valid column names + * + * @return array + */ + public function getValidColumnNames() + { + return $this->validColumnNames; + } } diff --git a/app/code/Magento/ImportExport/view/adminhtml/templates/export/form/after.phtml b/app/code/Magento/ImportExport/view/adminhtml/templates/export/form/after.phtml index ace41a768af027afaabce0a4877678e5d10abe8c..929fcf56bb537acede9cc11cf5c57ba57f292b2f 100644 --- a/app/code/Magento/ImportExport/view/adminhtml/templates/export/form/after.phtml +++ b/app/code/Magento/ImportExport/view/adminhtml/templates/export/form/after.phtml @@ -6,8 +6,8 @@ // @codingStandardsIgnoreFile ?> -<fieldset class="fieldset" id="export_filter_container" style="display:none;"> - <legend class="legend"> +<fieldset class="admin__fieldset" id="export_filter_container" style="display:none;"> + <legend class="admin__legend"> <span><?php /* @escapeNotVerified */ echo __('Entity Attributes'); ?></span> </legend> <br /> diff --git a/app/code/Magento/Integration/Block/Adminhtml/Integration/Tokens.php b/app/code/Magento/Integration/Block/Adminhtml/Integration/Tokens.php index e8654ef4fd3d3eded0d52557415294199801a8aa..f48a5e033b93f3845b7794b4e12d4f8ad2acd5f2 100644 --- a/app/code/Magento/Integration/Block/Adminhtml/Integration/Tokens.php +++ b/app/code/Magento/Integration/Block/Adminhtml/Integration/Tokens.php @@ -37,7 +37,7 @@ class Tokens extends \Magento\Backend\Block\Widget\Form\Generic $fieldset = $form->addFieldset( 'base_fieldset', - ['legend' => __('Integration Tokens for Extensions'), 'class' => 'fieldset-wide'] + ['legend' => __('Integration Tokens for Extensions'), 'class' => ' fieldset-wide'] ); foreach ($this->getFormFields() as $field) { diff --git a/app/code/Magento/Integration/view/adminhtml/templates/integration/activate/permissions/tab/webapi.phtml b/app/code/Magento/Integration/view/adminhtml/templates/integration/activate/permissions/tab/webapi.phtml index 52539a96e184a358ebfab50ff4f22df118ddd8c3..ba9ed08ce44b9a1d6b3a5fb4eb686d0cc05cc1ad 100644 --- a/app/code/Magento/Integration/view/adminhtml/templates/integration/activate/permissions/tab/webapi.phtml +++ b/app/code/Magento/Integration/view/adminhtml/templates/integration/activate/permissions/tab/webapi.phtml @@ -11,7 +11,7 @@ // @codingStandardsIgnoreFile ?> -<fieldset class="fieldset form-inline entry-edit"> +<fieldset class="admin__fieldset form-inline entry-edit"> <?php if ($block->isTreeEmpty()): ?> <p class="empty"><?php /* @escapeNotVerified */ echo __('No permissions requested'); ?></p> <?php else: ?> diff --git a/app/code/Magento/LayeredNavigation/view/frontend/layout/1column.xml b/app/code/Magento/LayeredNavigation/view/frontend/layout/1column.xml deleted file mode 100644 index 4d0318516508c3d23b6eea467edf8f855f3352c3..0000000000000000000000000000000000000000 --- a/app/code/Magento/LayeredNavigation/view/frontend/layout/1column.xml +++ /dev/null @@ -1,12 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd" label="All One-Column Layout Pages" design_abstraction="page_layout"> - <body> - <move element="catalog.leftnav" destination="content.top" after="-"/> - </body> -</page> diff --git a/app/code/Magento/LayeredNavigation/view/frontend/layout/2columns-left.xml b/app/code/Magento/LayeredNavigation/view/frontend/layout/2columns-left.xml deleted file mode 100644 index 7b679489fe942bc693b9948de94883e4bcab25cd..0000000000000000000000000000000000000000 --- a/app/code/Magento/LayeredNavigation/view/frontend/layout/2columns-left.xml +++ /dev/null @@ -1,12 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd" label="All Two-Column Layout Pages (Left Column)" design_abstraction="page_layout"> - <body> - <move element="catalog.leftnav" destination="sidebar.main" before="-"/> - </body> -</page> diff --git a/app/code/Magento/LayeredNavigation/view/frontend/layout/2columns-right.xml b/app/code/Magento/LayeredNavigation/view/frontend/layout/2columns-right.xml deleted file mode 100644 index 5e8b8e338716d710d43d7859a77557443cb0662e..0000000000000000000000000000000000000000 --- a/app/code/Magento/LayeredNavigation/view/frontend/layout/2columns-right.xml +++ /dev/null @@ -1,12 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd" label="All Two-Column Layout Pages (Right Column)" design_abstraction="page_layout"> - <body> - <move element="catalog.leftnav" destination="sidebar.main" before="-"/> - </body> -</page> diff --git a/app/code/Magento/LayeredNavigation/view/frontend/layout/3columns.xml b/app/code/Magento/LayeredNavigation/view/frontend/layout/3columns.xml deleted file mode 100644 index 5b97b56d83d48958b92d9db9860d2c9f6b574a3e..0000000000000000000000000000000000000000 --- a/app/code/Magento/LayeredNavigation/view/frontend/layout/3columns.xml +++ /dev/null @@ -1,12 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd" label="All Three-Column Layout Pages" design_abstraction="page_layout"> - <body> - <move element="catalog.leftnav" destination="sidebar.main" before="-"/> - </body> -</page> diff --git a/app/code/Magento/LayeredNavigation/view/frontend/layout/page_empty.xml b/app/code/Magento/LayeredNavigation/view/frontend/layout/page_empty.xml deleted file mode 100644 index aaf387bdfdea016140bcf8e179ddd1174013d721..0000000000000000000000000000000000000000 --- a/app/code/Magento/LayeredNavigation/view/frontend/layout/page_empty.xml +++ /dev/null @@ -1,12 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd" label="All Empty Layout Pages" design_abstraction="page_layout"> - <body> - <move element="catalog.leftnav" destination="category.product.list.additional" before="-"/> - </body> -</page> diff --git a/app/code/Magento/LayeredNavigation/view/frontend/page_layout/1column.xml b/app/code/Magento/LayeredNavigation/view/frontend/page_layout/1column.xml new file mode 100644 index 0000000000000000000000000000000000000000..d35beff77e8b896b26611c0cf123e88e1bcf4919 --- /dev/null +++ b/app/code/Magento/LayeredNavigation/view/frontend/page_layout/1column.xml @@ -0,0 +1,10 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_layout.xsd"> + <move element="catalog.leftnav" destination="content.top" after="-"/> +</layout> diff --git a/app/code/Magento/LayeredNavigation/view/frontend/page_layout/2columns-left.xml b/app/code/Magento/LayeredNavigation/view/frontend/page_layout/2columns-left.xml new file mode 100644 index 0000000000000000000000000000000000000000..94286e3cd4d3ea68ea42680dffa5cf51eff52af2 --- /dev/null +++ b/app/code/Magento/LayeredNavigation/view/frontend/page_layout/2columns-left.xml @@ -0,0 +1,10 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_layout.xsd"> + <move element="catalog.leftnav" destination="sidebar.main" before="-"/> +</layout> diff --git a/app/code/Magento/LayeredNavigation/view/frontend/page_layout/2columns-right.xml b/app/code/Magento/LayeredNavigation/view/frontend/page_layout/2columns-right.xml new file mode 100644 index 0000000000000000000000000000000000000000..94286e3cd4d3ea68ea42680dffa5cf51eff52af2 --- /dev/null +++ b/app/code/Magento/LayeredNavigation/view/frontend/page_layout/2columns-right.xml @@ -0,0 +1,10 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_layout.xsd"> + <move element="catalog.leftnav" destination="sidebar.main" before="-"/> +</layout> diff --git a/app/code/Magento/LayeredNavigation/view/frontend/page_layout/3columns.xml b/app/code/Magento/LayeredNavigation/view/frontend/page_layout/3columns.xml new file mode 100644 index 0000000000000000000000000000000000000000..94286e3cd4d3ea68ea42680dffa5cf51eff52af2 --- /dev/null +++ b/app/code/Magento/LayeredNavigation/view/frontend/page_layout/3columns.xml @@ -0,0 +1,10 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_layout.xsd"> + <move element="catalog.leftnav" destination="sidebar.main" before="-"/> +</layout> diff --git a/app/code/Magento/LayeredNavigation/view/frontend/page_layout/empty.xml b/app/code/Magento/LayeredNavigation/view/frontend/page_layout/empty.xml new file mode 100644 index 0000000000000000000000000000000000000000..6a45bb383141099dd4d367120ecfe131c77fa4c7 --- /dev/null +++ b/app/code/Magento/LayeredNavigation/view/frontend/page_layout/empty.xml @@ -0,0 +1,10 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_layout.xsd"> + <move element="catalog.leftnav" destination="category.product.list.additional" before="-"/> +</layout> diff --git a/app/code/Magento/Marketplace/i18n/de_DE.csv b/app/code/Magento/Marketplace/i18n/de_DE.csv new file mode 100644 index 0000000000000000000000000000000000000000..e0a266e1291f3390c5baee7087ada17c1bcdf28a --- /dev/null +++ b/app/code/Magento/Marketplace/i18n/de_DE.csv @@ -0,0 +1 @@ +"Find Partners & Extensions","Find Partners & Extensions" diff --git a/app/code/Magento/Marketplace/i18n/en_US.csv b/app/code/Magento/Marketplace/i18n/en_US.csv new file mode 100644 index 0000000000000000000000000000000000000000..e0a266e1291f3390c5baee7087ada17c1bcdf28a --- /dev/null +++ b/app/code/Magento/Marketplace/i18n/en_US.csv @@ -0,0 +1 @@ +"Find Partners & Extensions","Find Partners & Extensions" diff --git a/app/code/Magento/Marketplace/i18n/es_ES.csv b/app/code/Magento/Marketplace/i18n/es_ES.csv new file mode 100644 index 0000000000000000000000000000000000000000..e0a266e1291f3390c5baee7087ada17c1bcdf28a --- /dev/null +++ b/app/code/Magento/Marketplace/i18n/es_ES.csv @@ -0,0 +1 @@ +"Find Partners & Extensions","Find Partners & Extensions" diff --git a/app/code/Magento/Marketplace/i18n/fr_FR.csv b/app/code/Magento/Marketplace/i18n/fr_FR.csv new file mode 100644 index 0000000000000000000000000000000000000000..e0a266e1291f3390c5baee7087ada17c1bcdf28a --- /dev/null +++ b/app/code/Magento/Marketplace/i18n/fr_FR.csv @@ -0,0 +1 @@ +"Find Partners & Extensions","Find Partners & Extensions" diff --git a/app/code/Magento/Marketplace/i18n/nl_NL.csv b/app/code/Magento/Marketplace/i18n/nl_NL.csv new file mode 100644 index 0000000000000000000000000000000000000000..e0a266e1291f3390c5baee7087ada17c1bcdf28a --- /dev/null +++ b/app/code/Magento/Marketplace/i18n/nl_NL.csv @@ -0,0 +1 @@ +"Find Partners & Extensions","Find Partners & Extensions" diff --git a/app/code/Magento/Marketplace/i18n/pt_BR.csv b/app/code/Magento/Marketplace/i18n/pt_BR.csv new file mode 100644 index 0000000000000000000000000000000000000000..e0a266e1291f3390c5baee7087ada17c1bcdf28a --- /dev/null +++ b/app/code/Magento/Marketplace/i18n/pt_BR.csv @@ -0,0 +1 @@ +"Find Partners & Extensions","Find Partners & Extensions" diff --git a/app/code/Magento/Marketplace/i18n/zh_Hans_CN.csv b/app/code/Magento/Marketplace/i18n/zh_Hans_CN.csv new file mode 100644 index 0000000000000000000000000000000000000000..e0a266e1291f3390c5baee7087ada17c1bcdf28a --- /dev/null +++ b/app/code/Magento/Marketplace/i18n/zh_Hans_CN.csv @@ -0,0 +1 @@ +"Find Partners & Extensions","Find Partners & Extensions" diff --git a/app/code/Magento/Multishipping/view/frontend/requirejs-config.js b/app/code/Magento/Multishipping/view/frontend/requirejs-config.js index 034ecbd8057cc90818703b5c87aca8e3aeec4078..dbbc46fd928660b3293d2fcd4d2f9a2c270ecb59 100644 --- a/app/code/Magento/Multishipping/view/frontend/requirejs-config.js +++ b/app/code/Magento/Multishipping/view/frontend/requirejs-config.js @@ -7,7 +7,8 @@ var config = { map: { '*': { multiShipping: 'Magento_Multishipping/js/multi-shipping', - orderOverview: 'Magento_Multishipping/js/overview' + orderOverview: 'Magento_Multishipping/js/overview', + payment: 'Magento_Multishipping/js/payment' } } }; \ No newline at end of file diff --git a/app/code/Magento/Multishipping/view/frontend/templates/checkout/success.phtml b/app/code/Magento/Multishipping/view/frontend/templates/checkout/success.phtml index dc0c669468da9a1aaae43fc83bfa32cc22776044..21b83793d7d27f94ea511f1e7a6cde2ab0a8384f 100644 --- a/app/code/Magento/Multishipping/view/frontend/templates/checkout/success.phtml +++ b/app/code/Magento/Multishipping/view/frontend/templates/checkout/success.phtml @@ -8,16 +8,16 @@ ?> <div class="multicheckout success"> - <h2 class="subtitle"><?php /* @noEscape */ echo __('Thank you for your purchase!') ?></h2> - <p><?php /* @escapeNotVerified */ echo __('Thanks for your order. We\'ll email you order details and tracking information.') ?></p> + <h2 class="subtitle"><?php echo $block->escapeHtml(__('Thank you for your purchase!')) ?></h2> + <p><?php echo $block->escapeHtml(__('Thanks for your order. We\'ll email you order details and tracking information.')) ?></p> <?php if ($_orderIds = $block->getOrderIds()): ?> <p class="order-number"> <?php $flag = false ?> <span> <?php if (count($_orderIds) > 1): ?> - <?php /* @noEscape */ echo __('Your order numbers are: ') ?> + <?php echo $block->escapeHtml(__('Your order numbers are: ')) ?> <?php else : ?> - <?php /* @noEscape */ echo __('Your order number is: ') ?> + <?php echo $block->escapeHtml(__('Your order number is: ')) ?> <?php endif; ?> </span> <?php foreach ($_orderIds as $orderId => $incrementId): ?><?php if ($flag): ?><?php echo ', ' ?><?php endif; ?><?php $flag = true ?><a href="<?php /* @escapeNotVerified */ echo $block->getViewOrderUrl($orderId) ?>"><?php /* @escapeNotVerified */ echo $incrementId ?></a><?php endforeach; ?> @@ -25,6 +25,6 @@ <?php endif; ?> <?php echo $block->getChildHtml() ?> <div class="actions"> - <a class="action continue" title="<?php /* @noEscape */ echo __('Continue Shopping') ?>" href="<?php /* @escapeNotVerified */ echo $block->getContinueUrl() ?>"><span><?php /* @noEscape */ echo __('Continue Shopping') ?></span></a> + <a class="action continue" title="<?php echo $block->escapeHtml(__('Continue Shopping')) ?>" href="<?php /* @escapeNotVerified */ echo $block->getContinueUrl() ?>"><span><?php echo $block->escapeHtml(__('Continue Shopping')) ?></span></a> </div> </div> diff --git a/app/code/Magento/Checkout/view/frontend/web/js/payment.js b/app/code/Magento/Multishipping/view/frontend/web/js/payment.js similarity index 99% rename from app/code/Magento/Checkout/view/frontend/web/js/payment.js rename to app/code/Magento/Multishipping/view/frontend/web/js/payment.js index 1442bb787605236b3b40abfe430e9b98af6afd24..8baea212f57c07b5449d38b38987010f0f72f790 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/payment.js +++ b/app/code/Magento/Multishipping/view/frontend/web/js/payment.js @@ -4,9 +4,7 @@ */ /*jshint browser:true*/ /*global alert*/ -/** - * @removeCandidate - */ + define([ 'jquery', 'mage/template', diff --git a/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php b/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php index 7ee8fc1c9f6aad5c28d8dd2e1f67f355ad23af8e..781c181eb903a4d6216a4da6fb0ca1ab6d6a3412 100644 --- a/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php +++ b/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php @@ -5,6 +5,8 @@ */ namespace Magento\Newsletter\Model\Queue; +use Magento\Email\Model\AbstractTemplate; + class TransportBuilder extends \Magento\Framework\Mail\Template\TransportBuilder { /** @@ -26,17 +28,30 @@ class TransportBuilder extends \Magento\Framework\Mail\Template\TransportBuilder return $this; } + /** + * @param AbstractTemplate $template + * @return void + */ + protected function setTemplateFilter(AbstractTemplate $template) + { + if (isset($this->templateData['template_filter'])) { + $template->setTemplateFilter($this->templateData['template_filter']); + } + } + /** * @inheritdoc */ protected function prepareMessage() { + /** @var AbstractTemplate $template */ $template = $this->getTemplate()->setData($this->templateData); + $this->setTemplateFilter($template); $this->message->setMessageType( \Magento\Framework\Mail\MessageInterface::TYPE_HTML )->setBody( - $template->getProcessedTemplate() + $template->getProcessedTemplate($this->templateVars) )->setSubject( $template->getSubject() ); diff --git a/app/code/Magento/Newsletter/Model/Template/Filter.php b/app/code/Magento/Newsletter/Model/Template/Filter.php index 43a68d085bbf9a1b079f8751d5a5d52a99b910ff..0a2abbcacfd6ce468b345f20d841f337ef168dcf 100644 --- a/app/code/Magento/Newsletter/Model/Template/Filter.php +++ b/app/code/Magento/Newsletter/Model/Template/Filter.php @@ -11,7 +11,7 @@ */ namespace Magento\Newsletter\Model\Template; -class Filter extends \Magento\Widget\Model\Template\Filter +class Filter extends \Magento\Widget\Model\Template\FilterEmulate { /** * Generate widget HTML if template variables are assigned diff --git a/app/code/Magento/Newsletter/Test/Unit/Model/Queue/TransportBuilderTest.php b/app/code/Magento/Newsletter/Test/Unit/Model/Queue/TransportBuilderTest.php index 52a501f9ef3b6b15fd72079266db9629fef8fa98..dd7ff0eac5fb90056221ad1c244dc8ba69992f97 100644 --- a/app/code/Magento/Newsletter/Test/Unit/Model/Queue/TransportBuilderTest.php +++ b/app/code/Magento/Newsletter/Test/Unit/Model/Queue/TransportBuilderTest.php @@ -32,11 +32,13 @@ class TransportBuilderTest extends \Magento\Framework\Mail\Test\Unit\Template\Tr $messageType = MessageInterface::TYPE_HTML, $bodyText = '<h1>Html message</h1>' ) { + $filter = $this->getMock('Magento\Email\Model\Template\Filter', [], [], '', false); $data = [ 'template_subject' => 'Email Subject', 'template_text' => $bodyText, 'template_styles' => 'Styles', 'template_type' => $templateType, + 'template_filter' => $filter, ]; $vars = ['reason' => 'Reason', 'customer' => 'Customer']; $options = ['area' => 'frontend', 'store' => 1]; @@ -52,8 +54,14 @@ class TransportBuilderTest extends \Magento\Framework\Mail\Test\Unit\Template\Tr $this->returnSelf() ); $template->expects($this->once())->method('getSubject')->will($this->returnValue('Email Subject')); - $template->expects($this->once())->method('getProcessedTemplate')->will($this->returnValue($bodyText)); $template->expects($this->once())->method('setData')->with($this->equalTo($data))->will($this->returnSelf()); + $template->expects($this->once()) + ->method('getProcessedTemplate') + ->with($vars) + ->will($this->returnValue($bodyText)); + $template->expects($this->once()) + ->method('setTemplateFilter') + ->with($filter); $this->templateFactoryMock->expects( $this->once() diff --git a/app/code/Magento/Newsletter/Test/Unit/Model/Template/FilterTest.php b/app/code/Magento/Newsletter/Test/Unit/Model/Template/FilterTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c099b048f07ad7c42d6c31e8fc7b50c4db65c864 --- /dev/null +++ b/app/code/Magento/Newsletter/Test/Unit/Model/Template/FilterTest.php @@ -0,0 +1,128 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Newsletter\Test\Unit\Model\Template; + +class FilterTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Newsletter\Model\Template\Filter + */ + protected $filter; + + /** + * @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $storeManager; + + /** + * @var \Magento\Framework\App\State|\PHPUnit_Framework_MockObject_MockObject + */ + protected $appState; + + public function setUp() + { + $scopeConfig = $this->getMockForAbstractClass( + '\Magento\Framework\App\Config\ScopeConfigInterface', + [], + '', + false + ); + $this->storeManager = $this->getMockForAbstractClass( + '\Magento\Store\Model\StoreManagerInterface', + [], + '', + false + ); + $logger = $this->getMockForAbstractClass('\Psr\Log\LoggerInterface', [], '', false); + $layout = $this->getMockForAbstractClass('\Magento\Framework\View\LayoutInterface', [], '', false); + $urlModel = $this->getMockForAbstractClass('\Magento\Framework\UrlInterface', [], '', false); + $string = $this->getMock('\Magento\Framework\Stdlib\StringUtils', [], [], '', false); + $escaper = $this->getMock('\Magento\Framework\Escaper', [], [], '', false); + $assetRepo = $this->getMock('\Magento\Framework\View\Asset\Repository', [], [], '', false); + $coreVariableFactory = $this->getMock('\Magento\Variable\Model\VariableFactory', ['create'], [], '', false); + $layoutFactory = $this->getMock('\Magento\Framework\View\LayoutFactory', ['create'], [], '', false); + $this->appState = $this->getMock('\Magento\Framework\App\State', [], [], '', false); + $emogrifier = $this->getMock('\Pelago\Emogrifier', [], [], '', false); + $configVariables = $this->getMock('\Magento\Email\Model\Source\Variables', [], [], '', false); + $widgetResource = $this->getMock('\Magento\Widget\Model\ResourceModel\Widget', [], [], '', false); + $widget = $this->getMock('\Magento\Widget\Model\Widget', [], [], '', false); + + $this->filter = new \Magento\Newsletter\Model\Template\Filter( + $string, + $logger, + $escaper, + $assetRepo, + $scopeConfig, + $coreVariableFactory, + $this->storeManager, + $layout, + $layoutFactory, + $this->appState, + $urlModel, + $emogrifier, + $configVariables, + $widgetResource, + $widget + ); + + } + + public function testWidgetDirective() + { + $subscriber = $this->getMock('\Magento\Newsletter\Model\Subscriber', [], [], '', false); + $this->filter->setVariables(['subscriber' => $subscriber]); + + $construction = '{{widget type="\Magento\Cms\Block\Widget\Page\Link" page_id="1"}}'; + + $store = $this->getMockForAbstractClass('Magento\Store\Api\Data\StoreInterface', [], '', false); + $store->expects($this->once()) + ->method('getId') + ->willReturn(1); + $this->storeManager->expects($this->once()) + ->method('getStore') + ->willReturn($store); + $this->appState->expects($this->once()) + ->method('emulateAreaCode') + ->with( + 'frontend', + [$this->filter, 'generateWidget'], + [ + [ + 1 => $construction, + 2 => 'type="\Magento\Cms\Block\Widget\Page\Link" page_id="1" store_id ="1"' + ] + ] + ) + ->willReturn( + '<div class="widget block block-cms-link-inline"> + <a href="http://magento.test/"> + <span>Home page</span> + </a> + </div>' + ); + + $this->filter->widgetDirective([ + 1 => $construction, + 2 => 'type="\Magento\Cms\Block\Widget\Page\Link" page_id="1"' + ]); + } + + public function testWidgetDirectiveWithoutRequiredVariable() + { + $construction = '{{widget type="\Magento\Cms\Block\Widget\Page\Link" page_id="1"}}'; + + $this->storeManager->expects($this->never()) + ->method('getStore'); + $result = $this->filter->widgetDirective( + [ + 0 => $construction, + 1 => 'type="\Magento\Cms\Block\Widget\Page\Link" page_id="1"' + ] + ); + + $this->assertEquals($construction, $result); + } +} diff --git a/app/code/Magento/Newsletter/i18n/de_DE.csv b/app/code/Magento/Newsletter/i18n/de_DE.csv index 2fc3bee3bc65b5b1a9af57970fa18a590568df88..98a16ae2e77028ea0434282a11dfae6a54a5aad1 100644 --- a/app/code/Magento/Newsletter/i18n/de_DE.csv +++ b/app/code/Magento/Newsletter/i18n/de_DE.csv @@ -138,3 +138,4 @@ Unsubscribe,"Abonnement kündigen" Subscribed,Abonniert Unsubscribed,"Abonnements gekündigt" Unconfirmed,Unbestätigt +"Newsletter Template","Newsletter Vorlage" diff --git a/app/code/Magento/Newsletter/i18n/en_US.csv b/app/code/Magento/Newsletter/i18n/en_US.csv index ac79fef143eec52fc0462266718693aebafa8954..a30b48f0c939a8833cc606209a2ce70d8db62129 100644 --- a/app/code/Magento/Newsletter/i18n/en_US.csv +++ b/app/code/Magento/Newsletter/i18n/en_US.csv @@ -138,3 +138,4 @@ Unsubscribe,Unsubscribe Subscribed,Subscribed Unsubscribed,Unsubscribed Unconfirmed,Unconfirmed +"Newsletter Template","Newsletter Template" diff --git a/app/code/Magento/Newsletter/i18n/es_ES.csv b/app/code/Magento/Newsletter/i18n/es_ES.csv index 3be9617100dd0566047b3a0b03eb643331444af3..43c2e724ea7692433db5052fdd27e0346d036403 100644 --- a/app/code/Magento/Newsletter/i18n/es_ES.csv +++ b/app/code/Magento/Newsletter/i18n/es_ES.csv @@ -138,3 +138,4 @@ Unsubscribe,"Cancelar suscripción" Subscribed,Suscrito Unsubscribed,"Suscripción cancelada" Unconfirmed,"Sin confirmar" +"Newsletter Template","Newsletter Template" diff --git a/app/code/Magento/Newsletter/i18n/fr_FR.csv b/app/code/Magento/Newsletter/i18n/fr_FR.csv index cec853133f4625ae16b9523880b7c0d9971a16bd..65134aa5e433b3ca3ba6c370d401f4fcaecc399b 100644 --- a/app/code/Magento/Newsletter/i18n/fr_FR.csv +++ b/app/code/Magento/Newsletter/i18n/fr_FR.csv @@ -138,3 +138,4 @@ Unsubscribe,"Se désinscrire" Subscribed,Inscrit Unsubscribed,Désinscrit Unconfirmed,"Non confirmé" +"Newsletter Template","Newsletter Template" diff --git a/app/code/Magento/Newsletter/i18n/nl_NL.csv b/app/code/Magento/Newsletter/i18n/nl_NL.csv index 9280f66bdc00cebce78415489a1305e68b193884..7999b25e129757daf61e6ba0f1836818c07ea877 100644 --- a/app/code/Magento/Newsletter/i18n/nl_NL.csv +++ b/app/code/Magento/Newsletter/i18n/nl_NL.csv @@ -138,3 +138,4 @@ Unsubscribe,Uitschrijven Subscribed,Uitschrijven Unsubscribed,Uitgeschreven Unconfirmed,Onbevestigd +"Newsletter Template","Newsletter Template" diff --git a/app/code/Magento/Newsletter/i18n/pt_BR.csv b/app/code/Magento/Newsletter/i18n/pt_BR.csv index 4ec9dd0d67d0d4d9048bb3a2861df954ebc5b3e3..cb2fecc6a5900a91aba2d04614f26824d814fc1c 100644 --- a/app/code/Magento/Newsletter/i18n/pt_BR.csv +++ b/app/code/Magento/Newsletter/i18n/pt_BR.csv @@ -138,3 +138,4 @@ Unsubscribe,Desinscrever Subscribed,Assinado Unsubscribed,Desinscrito Unconfirmed,"Não Confirmado" +"Newsletter Template","Newsletter Template" diff --git a/app/code/Magento/Newsletter/i18n/zh_Hans_CN.csv b/app/code/Magento/Newsletter/i18n/zh_Hans_CN.csv index 96d65bc535252d743c200ca195c3b1268de5e9ae..71be218444fbc4ddbb97887efc076549cdb887ad 100644 --- a/app/code/Magento/Newsletter/i18n/zh_Hans_CN.csv +++ b/app/code/Magento/Newsletter/i18n/zh_Hans_CN.csv @@ -138,3 +138,4 @@ Unsubscribe,退订 Subscribed,已订阅 Unsubscribed,已退订 Unconfirmed,未确认 +"Newsletter Template","Newsletter Template" diff --git a/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/checkmo.html b/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/checkmo.html index e20e15111e5b6b393efba087fa2c3c2cd7e72975..64385884483dd132f627f833166de6ef6f69b9a1 100644 --- a/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/checkmo.html +++ b/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/checkmo.html @@ -25,12 +25,12 @@ <dl class="items check payable"> <!-- ko if: getPayableTo() --> <dt class="title"><!-- ko i18n: 'Make Check payable to:' --><!-- /ko --></dt> - <dd class="content"><!-- ko i18n: getPayableTo() --><!-- /ko --></dd> + <dd class="content"><!-- ko text: getPayableTo() --><!-- /ko --></dd> <!-- /ko --> <!-- ko if: getMailingAddress() --> <dt class="title"><!-- ko i18n: 'Send Check to:' --><!-- /ko --></dt> <dd class="content"> - <address class="checkmo mailing address" data-bind="html: $t(getMailingAddress())"></address> + <address class="checkmo mailing address" data-bind="html: getMailingAddress()"></address> </dd> <!-- /ko --> </dl> diff --git a/app/code/Magento/PageCache/Model/Cache/Server.php b/app/code/Magento/PageCache/Model/Cache/Server.php index fc52e41e3b23428142c147c8a13556005ca72e12..2e2f3a87fb8c07a7eb33c9b61f4ef421992e6c49 100644 --- a/app/code/Magento/PageCache/Model/Cache/Server.php +++ b/app/code/Magento/PageCache/Model/Cache/Server.php @@ -60,7 +60,7 @@ class Server $httpHost = $this->request->getHttpHost(); $servers[] = $httpHost ? UriFactory::factory('')->setHost($httpHost)->setPort(self::DEFAULT_PORT)->setScheme('http') : - UriFactory::factory($this->urlBuilder->getUrl('*')) + UriFactory::factory($this->urlBuilder->getUrl('*', ['_nosid' => true])) // Don't use SID in building URL ->setScheme('http') ->setPath(null) ->setQuery(null); diff --git a/app/code/Magento/PageCache/Model/System/Config/Source/Application.php b/app/code/Magento/PageCache/Model/System/Config/Source/Application.php index 45233bb59c70b2d61504d4a983ec00ad7624a4e7..eb428f7c0300a3d58c8cf74cbbe38a5bef0fa853 100644 --- a/app/code/Magento/PageCache/Model/System/Config/Source/Application.php +++ b/app/code/Magento/PageCache/Model/System/Config/Source/Application.php @@ -23,8 +23,14 @@ class Application implements \Magento\Framework\Option\ArrayInterface public function toOptionArray() { return [ - ['value' => \Magento\PageCache\Model\Config::BUILT_IN, 'label' => __('Built-in Application')], - ['value' => \Magento\PageCache\Model\Config::VARNISH, 'label' => __('Varnish Caching')] + [ + 'value' => \Magento\PageCache\Model\Config::BUILT_IN, + 'label' => __('Built-in Application (Not Recommended for Production Use)') + ], + [ + 'value' => \Magento\PageCache\Model\Config::VARNISH, + 'label' => __('Varnish Caching') + ] ]; } @@ -36,7 +42,8 @@ class Application implements \Magento\Framework\Option\ArrayInterface public function toArray() { return [ - \Magento\PageCache\Model\Config::BUILT_IN => __('Built-in Application'), + \Magento\PageCache\Model\Config::BUILT_IN => + __('Built-in Application (Not Recommended for Production Use)'), \Magento\PageCache\Model\Config::VARNISH => __('Varnish Caching') ]; } diff --git a/app/code/Magento/PageCache/Test/Unit/Model/Cache/ServerTest.php b/app/code/Magento/PageCache/Test/Unit/Model/Cache/ServerTest.php index 38cc49be2ff4839736af9bd27d18752a585e8aee..f18c5e04468da59169ae6b3b5642d428b7113667 100644 --- a/app/code/Magento/PageCache/Test/Unit/Model/Cache/ServerTest.php +++ b/app/code/Magento/PageCache/Test/Unit/Model/Cache/ServerTest.php @@ -64,7 +64,7 @@ class ServerTest extends \PHPUnit_Framework_TestCase ->willReturn($httpHost); $this->urlBuilderMock->expects($this->exactly($getUrlCallCtr)) ->method('getUrl') - ->with('*') + ->with('*', ['_nosid' => true]) ->willReturn($url); $uris = []; diff --git a/app/code/Magento/PageCache/i18n/de_DE.csv b/app/code/Magento/PageCache/i18n/de_DE.csv index 0d57f18488d74de68e153b35e305fa7629c104f0..701e12300596b25fedafc3bdd766ee5f064c98af 100644 --- a/app/code/Magento/PageCache/i18n/de_DE.csv +++ b/app/code/Magento/PageCache/i18n/de_DE.csv @@ -1,6 +1,6 @@ "Export VCL","Export VCL" "Ttl value ""%1"" is not valid. Please use only numbers equal or greater than zero.","Ttl value ""%1"" is not valid. Please use only numbers equal or greater than zero." -"Built-in Application","Built-in Application" +"Built-in Application (Not Recommended for Production Use)","Built-in Application (Not Recommended for Production Use)" "Varnish Caching","Varnish Caching" "Full Page Cache","Full Page Cache" "Caching Application","Caching Application" diff --git a/app/code/Magento/PageCache/i18n/en_US.csv b/app/code/Magento/PageCache/i18n/en_US.csv index 0d57f18488d74de68e153b35e305fa7629c104f0..701e12300596b25fedafc3bdd766ee5f064c98af 100644 --- a/app/code/Magento/PageCache/i18n/en_US.csv +++ b/app/code/Magento/PageCache/i18n/en_US.csv @@ -1,6 +1,6 @@ "Export VCL","Export VCL" "Ttl value ""%1"" is not valid. Please use only numbers equal or greater than zero.","Ttl value ""%1"" is not valid. Please use only numbers equal or greater than zero." -"Built-in Application","Built-in Application" +"Built-in Application (Not Recommended for Production Use)","Built-in Application (Not Recommended for Production Use)" "Varnish Caching","Varnish Caching" "Full Page Cache","Full Page Cache" "Caching Application","Caching Application" diff --git a/app/code/Magento/PageCache/i18n/es_ES.csv b/app/code/Magento/PageCache/i18n/es_ES.csv index 0d57f18488d74de68e153b35e305fa7629c104f0..701e12300596b25fedafc3bdd766ee5f064c98af 100644 --- a/app/code/Magento/PageCache/i18n/es_ES.csv +++ b/app/code/Magento/PageCache/i18n/es_ES.csv @@ -1,6 +1,6 @@ "Export VCL","Export VCL" "Ttl value ""%1"" is not valid. Please use only numbers equal or greater than zero.","Ttl value ""%1"" is not valid. Please use only numbers equal or greater than zero." -"Built-in Application","Built-in Application" +"Built-in Application (Not Recommended for Production Use)","Built-in Application (Not Recommended for Production Use)" "Varnish Caching","Varnish Caching" "Full Page Cache","Full Page Cache" "Caching Application","Caching Application" diff --git a/app/code/Magento/PageCache/i18n/fr_FR.csv b/app/code/Magento/PageCache/i18n/fr_FR.csv index 0d57f18488d74de68e153b35e305fa7629c104f0..701e12300596b25fedafc3bdd766ee5f064c98af 100644 --- a/app/code/Magento/PageCache/i18n/fr_FR.csv +++ b/app/code/Magento/PageCache/i18n/fr_FR.csv @@ -1,6 +1,6 @@ "Export VCL","Export VCL" "Ttl value ""%1"" is not valid. Please use only numbers equal or greater than zero.","Ttl value ""%1"" is not valid. Please use only numbers equal or greater than zero." -"Built-in Application","Built-in Application" +"Built-in Application (Not Recommended for Production Use)","Built-in Application (Not Recommended for Production Use)" "Varnish Caching","Varnish Caching" "Full Page Cache","Full Page Cache" "Caching Application","Caching Application" diff --git a/app/code/Magento/PageCache/i18n/nl_NL.csv b/app/code/Magento/PageCache/i18n/nl_NL.csv index 0d57f18488d74de68e153b35e305fa7629c104f0..701e12300596b25fedafc3bdd766ee5f064c98af 100644 --- a/app/code/Magento/PageCache/i18n/nl_NL.csv +++ b/app/code/Magento/PageCache/i18n/nl_NL.csv @@ -1,6 +1,6 @@ "Export VCL","Export VCL" "Ttl value ""%1"" is not valid. Please use only numbers equal or greater than zero.","Ttl value ""%1"" is not valid. Please use only numbers equal or greater than zero." -"Built-in Application","Built-in Application" +"Built-in Application (Not Recommended for Production Use)","Built-in Application (Not Recommended for Production Use)" "Varnish Caching","Varnish Caching" "Full Page Cache","Full Page Cache" "Caching Application","Caching Application" diff --git a/app/code/Magento/PageCache/i18n/pt_BR.csv b/app/code/Magento/PageCache/i18n/pt_BR.csv index 0d57f18488d74de68e153b35e305fa7629c104f0..701e12300596b25fedafc3bdd766ee5f064c98af 100644 --- a/app/code/Magento/PageCache/i18n/pt_BR.csv +++ b/app/code/Magento/PageCache/i18n/pt_BR.csv @@ -1,6 +1,6 @@ "Export VCL","Export VCL" "Ttl value ""%1"" is not valid. Please use only numbers equal or greater than zero.","Ttl value ""%1"" is not valid. Please use only numbers equal or greater than zero." -"Built-in Application","Built-in Application" +"Built-in Application (Not Recommended for Production Use)","Built-in Application (Not Recommended for Production Use)" "Varnish Caching","Varnish Caching" "Full Page Cache","Full Page Cache" "Caching Application","Caching Application" diff --git a/app/code/Magento/PageCache/i18n/zh_Hans_CN.csv b/app/code/Magento/PageCache/i18n/zh_Hans_CN.csv index 0d57f18488d74de68e153b35e305fa7629c104f0..701e12300596b25fedafc3bdd766ee5f064c98af 100644 --- a/app/code/Magento/PageCache/i18n/zh_Hans_CN.csv +++ b/app/code/Magento/PageCache/i18n/zh_Hans_CN.csv @@ -1,6 +1,6 @@ "Export VCL","Export VCL" "Ttl value ""%1"" is not valid. Please use only numbers equal or greater than zero.","Ttl value ""%1"" is not valid. Please use only numbers equal or greater than zero." -"Built-in Application","Built-in Application" +"Built-in Application (Not Recommended for Production Use)","Built-in Application (Not Recommended for Production Use)" "Varnish Caching","Varnish Caching" "Full Page Cache","Full Page Cache" "Caching Application","Caching Application" diff --git a/app/code/Magento/Payment/view/adminhtml/templates/form/cc.phtml b/app/code/Magento/Payment/view/adminhtml/templates/form/cc.phtml index ab38d3752a679f68d8a0371d087c126268707a99..f1109afb7974ef65ee42d01d18162dc121c428ab 100644 --- a/app/code/Magento/Payment/view/adminhtml/templates/form/cc.phtml +++ b/app/code/Magento/Payment/view/adminhtml/templates/form/cc.phtml @@ -8,7 +8,7 @@ /** * @var \Magento\Payment\Block\Adminhtml\Transparent\Form $block */ -$code = $block->getMethodCode(); +$code = $block->escapeHtml($block->getMethodCode()); $ccType = $block->getInfoData('cc_type'); $ccExpMonth = $block->getInfoData('cc_exp_month'); $ccExpYear = $block->getInfoData('cc_exp_year'); diff --git a/app/code/Magento/Payment/view/adminhtml/templates/transparent/form.phtml b/app/code/Magento/Payment/view/adminhtml/templates/transparent/form.phtml index 1bb248e6fd5662bced43e2f7ee9d4c5a942a1f69..0d28d33caea9cadcfce22c7fb68e2da557c7935b 100644 --- a/app/code/Magento/Payment/view/adminhtml/templates/transparent/form.phtml +++ b/app/code/Magento/Payment/view/adminhtml/templates/transparent/form.phtml @@ -7,7 +7,7 @@ // @codingStandardsIgnoreFile /** @var \Magento\Payment\Block\Transparent\Form $block */ -$code = $block->getMethodCode(); +$code = $block->escapeHtml($block->getMethodCode()); $ccType = $block->getInfoData('cc_type'); $ccExpYear = $block->getInfoData('cc_exp_year'); $ccExpMonth = $block->getInfoData('cc_exp_month'); @@ -29,7 +29,7 @@ $ccExpMonth = $block->getInfoData('cc_exp_month'); "controller":"<?php echo $block->escapeHtml($block->getRequest()->getControllerName()); ?>", "gateway":"<?php /* @noEscape */ echo $code; ?>", "dateDelim":"<?php echo $block->escapeHtml($block->getDateDelim()); ?>", - "cardFieldsMap":<?php /* @noEscape */ echo $block->getCardFieldsMap(); ?>, + "cardFieldsMap":<?php echo $block->escapeHtml($block->getCardFieldsMap()); ?>, "orderSaveUrl":"<?php echo $block->escapeUrl($block->getOrderUrl()); ?>", "cgiUrl":"<?php echo $block->escapeUrl($block->getCgiUrl()); ?>", "expireYearLength":"<?php echo $block->escapeHtml($block->getMethodConfigData('cc_year_length')); ?>", @@ -102,7 +102,7 @@ $ccExpMonth = $block->getInfoData('cc_exp_month'); data-container="<?php /* @noEscape */ echo $code; ?>-cc-year" data-validate='{required:true}'> <?php foreach ($block->getCcYears() as $k => $v): ?> <option - value="<?php /* @noEscape */ echo $k ? $k : '' ?>" + value="<?php /* @noEscape */ echo $k ? $block->escapeHtml($k) : '' ?>" <?php if ($k == $ccExpYear): ?> selected="selected"<?php endif ?>> <?php echo $block->escapeHtml($v); ?> </option> diff --git a/app/code/Magento/Payment/view/adminhtml/templates/transparent/info.phtml b/app/code/Magento/Payment/view/adminhtml/templates/transparent/info.phtml index 8deddb094d1799a1f1459a6be34e7fdbf5a054f0..8b20f64b5a60109508916e2a2ed2b07d36fa586f 100644 --- a/app/code/Magento/Payment/view/adminhtml/templates/transparent/info.phtml +++ b/app/code/Magento/Payment/view/adminhtml/templates/transparent/info.phtml @@ -11,6 +11,6 @@ * @see \Magento\Payment\Block\Transparent\Info */ ?> -<fieldset id="payment_form_<?php /* @noEscape */ echo $block->getMethodCode(); ?>" style="display:none" class="fieldset items redirect"> +<fieldset id="payment_form_<?php echo $block->escapeHtml($block->getMethodCode()); ?>" style="display:none" class="fieldset items redirect"> <div><?php echo $block->escapeHtml(__('We\'ll ask for your payment details before you place an order.')); ?></div> </fieldset> diff --git a/app/code/Magento/Payment/view/frontend/templates/form/cc.phtml b/app/code/Magento/Payment/view/frontend/templates/form/cc.phtml index 05d8d3c02c82cdfc54c16a9d77a6863422e7ecbd..a02de6dbaff84f73d2f9d7fa48dcc23c2b482f1d 100644 --- a/app/code/Magento/Payment/view/frontend/templates/form/cc.phtml +++ b/app/code/Magento/Payment/view/frontend/templates/form/cc.phtml @@ -8,7 +8,7 @@ /** * @var \Magento\Payment\Block\Transparent\Form $block */ -$code = $block->getMethodCode(); +$code = $block->escapeHtml($block->getMethodCode()); $ccType = $block->getInfoData('cc_type'); $ccExpMonth = $block->getInfoData('cc_exp_month'); $ccExpYear = $block->getInfoData('cc_exp_year'); diff --git a/app/code/Magento/Payment/view/frontend/templates/transparent/form.phtml b/app/code/Magento/Payment/view/frontend/templates/transparent/form.phtml index 64ea503996cd280d8b29dc154b4dc20e9e47f69d..a589900d6233ae186fbef507484d2334a64c1db6 100644 --- a/app/code/Magento/Payment/view/frontend/templates/transparent/form.phtml +++ b/app/code/Magento/Payment/view/frontend/templates/transparent/form.phtml @@ -7,7 +7,7 @@ // @codingStandardsIgnoreFile /** @var \Magento\Payment\Block\Transparent\Form $block */ -$code = $block->getMethodCode(); +$code = $block->escapeHtml($block->getMethodCode()); $ccExpMonth = $block->getInfoData('cc_exp_month'); $ccExpYear = $block->getInfoData('cc_exp_year'); $ccType = $block->getInfoData('cc_type'); @@ -20,7 +20,7 @@ $content = '<img src=\"' . $block->getViewFileUrl('Magento_Checkout::cvv.png') . <iframe width="0" height="0" id="<?php /* @noescape */ echo $code; ?>-transparent-iframe" data-container="<?php /* @noEscape */ echo $code; ?>-transparent-iframe" allowtransparency="true" frameborder="0" name="iframeTransparent" style="display:none;width:100%;background-color:transparent" - src="<?php /* @noEscape */ echo $block->getViewFileUrl('blank.html') ?>"></iframe> + src="<?php echo $block->escapeUrl($block->getViewFileUrl('blank.html')) ?>"></iframe> <form class="form" id="co-transparent-form" action="#" method="post" data-mage-init='{ "transparent":{ "controller":"<?php echo $block->escapeHtml($block->getRequest()->getControllerName()); ?>", @@ -28,7 +28,7 @@ $content = '<img src=\"' . $block->getViewFileUrl('Magento_Checkout::cvv.png') . "orderSaveUrl":"<?php echo $block->escapeUrl($block->getOrderUrl()); ?>", "cgiUrl":"<?php echo $block->escapeUrl($block->getCgiUrl()); ?>", "dateDelim":"<?php echo $block->escapeHtml($block->getDateDelim()); ?>", - "cardFieldsMap":<?php /* @noEscape */ echo $block->getCardFieldsMap(); ?>, + "cardFieldsMap":<?php echo $block->escapeHtml($block->getCardFieldsMap()); ?>, "nativeAction":"<?php echo $block->escapeUrl($block->getUrl('checkout/onepage/saveOrder', ['_secure' => $block->getRequest()->isSecure()])); ?>" }, "validation":[]}'> <fieldset class="fieldset ccard <?php /* @noEscape */ echo $code; ?>" id="payment_form_<?php /* @noEscape */ echo $code; ?>"> diff --git a/app/code/Magento/Payment/view/frontend/templates/transparent/iframe.phtml b/app/code/Magento/Payment/view/frontend/templates/transparent/iframe.phtml index b191981585af62dde6804c9dbfc44a3b0258e1b5..fc9624bde1016edc28d53a7bc282ca36ca64625f 100644 --- a/app/code/Magento/Payment/view/frontend/templates/transparent/iframe.phtml +++ b/app/code/Magento/Payment/view/frontend/templates/transparent/iframe.phtml @@ -33,7 +33,7 @@ $params = $block->getParams(); 'Magento_Checkout/js/action/place-order' ], function(quote, placeOrderAction) { - placeOrderAction(quote.paymentMethod(), true); + placeOrderAction({"method": quote.paymentMethod().method}, true); } ); <?php endif; ?> diff --git a/app/code/Magento/Payment/view/frontend/templates/transparent/info.phtml b/app/code/Magento/Payment/view/frontend/templates/transparent/info.phtml index c3ce1e5dbb7029ed65db079fcbf0230839373a3b..84cd69f6e4f698ff8731f76c5367e1b8244e0dae 100644 --- a/app/code/Magento/Payment/view/frontend/templates/transparent/info.phtml +++ b/app/code/Magento/Payment/view/frontend/templates/transparent/info.phtml @@ -11,7 +11,7 @@ * @see \Magento\Payment\Block\Transparent\Info */ ?> -<fieldset id="payment_form_<?php /* @noEscape */ echo $block->getMethodCode(); ?>" style="display:none" class="fieldset items redirect"> +<fieldset id="payment_form_<?php echo $block->escapeHtml($block->getMethodCode()); ?>" style="display:none" class="fieldset items redirect"> <div> <?php echo $block->escapeHtml(__('We\'ll ask for your payment details before you place an order.')); ?> </div> diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/validator.js b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/validator.js index 660f3e3c0471f40d168481723d316bfcf792c0ed..2812437f379e491bd301392e3d60afebe3e13dfa 100644 --- a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/validator.js +++ b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/validator.js @@ -21,13 +21,34 @@ "use strict"; $.each({ + 'validate-card-type': [ + function (number, item, allowedTypes) { + var cardInfo, + i, + l; + + if (!creditCardNumberValidator(number).isValid) { + return false; + } else { + cardInfo = creditCardNumberValidator(number).card; + + for (i = 0, l = allowedTypes.length; i < l; i++) { + if (cardInfo.title == allowedTypes[i].type) { + return true; + } + } + return false; + } + }, + 'Please enter a valid credit card type number.' + ], 'validate-card-number': [ /** * Validate credit card number based on mod 10 * @param number - credit card number * @return {boolean} */ - function (number) { + function (number) { return creditCardNumberValidator(number).isValid; }, 'Please enter a valid credit card number.' diff --git a/app/code/Magento/Payment/view/frontend/web/template/payment/cc-form.html b/app/code/Magento/Payment/view/frontend/web/template/payment/cc-form.html index 2df219f3dddf1df4770c7248310c9514682e6f68..7db455786537c37bf09c7a02fe9ca365f887de32 100644 --- a/app/code/Magento/Payment/view/frontend/web/template/payment/cc-form.html +++ b/app/code/Magento/Payment/view/frontend/web/template/payment/cc-form.html @@ -50,7 +50,7 @@ id: getCode() + '_cc_number', title: $t('Credit Card Number'), 'data-container': getCode() + '-cc-number', - 'data-validate': JSON.stringify({'required-number':true, 'validate-card-number':'#' + getCode() + '_cc_type', 'validate-cc-type':'#' + getCode() + '_cc_type'})}, + 'data-validate': JSON.stringify({'required-number':true, 'validate-card-type':getCcAvailableTypesValues(), 'validate-card-number':'#' + getCode() + '_cc_type', 'validate-cc-type':'#' + getCode() + '_cc_type'})}, enable: isActive($parents), value: creditCardNumber, valueUpdate: 'keyup' "/> diff --git a/app/code/Magento/Paypal/Block/Adminhtml/Billing/Agreement/View/Tab/Orders.php b/app/code/Magento/Paypal/Block/Adminhtml/Billing/Agreement/View/Tab/Orders.php index df81fff83bd338742a921f399696ba8a58f9dcd2..f8b577df7c12c971b564084e76211ce3744ba1ca 100644 --- a/app/code/Magento/Paypal/Block/Adminhtml/Billing/Agreement/View/Tab/Orders.php +++ b/app/code/Magento/Paypal/Block/Adminhtml/Billing/Agreement/View/Tab/Orders.php @@ -8,20 +8,54 @@ namespace Magento\Paypal\Block\Adminhtml\Billing\Agreement\View\Tab; +use Magento\Paypal\Model\ResourceModel\Billing\Agreement as BillingAgreementResource; +use Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory; +use Magento\Backend\Block\Widget\Grid\Extended as ExtendedGrid; +use Magento\Backend\Block\Widget\Tab\TabInterface; +use Magento\Backend\Block\Template\Context as TemplateContext; +use Magento\Backend\Helper\Data as BackendHelper; +use Magento\Framework\Registry; + /** * Adminhtml billing agreement related orders tab */ -class Orders extends \Magento\Framework\View\Element\Text\ListText implements \Magento\Backend\Block\Widget\Tab\TabInterface +class Orders extends ExtendedGrid implements TabInterface { /** - * Initialize grid params - * - * @return void + * @var CollectionFactory */ - protected function _construct() - { - parent::_construct(); - $this->setId('billing_agreement_orders'); + protected $collectionFactory; + + /** + * @var Registry + */ + protected $coreRegistry; + + /** + * @var BillingAgreementResource + */ + protected $billingAgreementResource; + + /** + * @param TemplateContext $context + * @param BackendHelper $backendHelper + * @param CollectionFactory $collectionFactory + * @param Registry $coreRegistry + * @param BillingAgreementResource $billingAgreementResource + * @param array $data + */ + public function __construct( + TemplateContext $context, + BackendHelper $backendHelper, + CollectionFactory $collectionFactory, + Registry $coreRegistry, + BillingAgreementResource $billingAgreementResource, + array $data = [] + ) { + $this->coreRegistry = $coreRegistry; + $this->collectionFactory = $collectionFactory; + $this->billingAgreementResource = $billingAgreementResource; + parent::__construct($context, $backendHelper, $data); } /** @@ -55,4 +89,82 @@ class Orders extends \Magento\Framework\View\Element\Text\ListText implements \M { return false; } + + /** + * {@inheritdoc} + */ + protected function _construct() + { + parent::_construct(); + $this->setId('billing_agreement_orders'); + $this->setUseAjax(true); + } + + /** + * Apply various selection filters to prepare the sales order grid collection. + * + * @return $this + */ + protected function _prepareCollection() + { + $billingAgreement = $this->coreRegistry->registry('current_billing_agreement'); + if ($billingAgreement) { + $collection = $this->collectionFactory->getReport('sales_order_grid_data_source')->addFieldToSelect( + 'entity_id' + )->addFieldToSelect( + 'increment_id' + )->addFieldToSelect( + 'customer_id' + )->addFieldToSelect( + 'created_at' + )->addFieldToSelect( + 'grand_total' + )->addFieldToSelect( + 'order_currency_code' + )->addFieldToSelect( + 'store_id' + )->addFieldToSelect( + 'billing_name' + )->addFieldToSelect( + 'shipping_name' + ); + $this->billingAgreementResource->addOrdersFilter($collection, $billingAgreement->getId()); + $this->setCollection($collection); + } + return parent::_prepareCollection(); + } + + /** + * {@inheritdoc} + */ + protected function _prepareColumns() + { + $this->addColumn('increment_id', ['header' => __('Order'), 'width' => '100', 'index' => 'increment_id']); + + $this->addColumn( + 'created_at', + ['header' => __('Purchased'), 'index' => 'created_at', 'type' => 'datetime'] + ); + + $this->addColumn('billing_name', ['header' => __('Bill-to Name'), 'index' => 'billing_name']); + $this->addColumn('shipping_name', ['header' => __('Ship-to Name'), 'index' => 'shipping_name']); + + $this->addColumn( + 'grand_total', + [ + 'header' => __('Order Total'), + 'index' => 'grand_total', + 'type' => 'currency', + 'currency' => 'order_currency_code' + ] + ); + + if (!$this->_storeManager->isSingleStoreMode()) { + $this->addColumn( + 'store_id', + ['header' => __('Purchase Point'), 'index' => 'store_id', 'type' => 'store', 'store_view' => true] + ); + } + return parent::_prepareColumns(); + } } diff --git a/app/code/Magento/Paypal/Block/Express/Review/Billing.php b/app/code/Magento/Paypal/Block/Express/Review/Billing.php index c613b56c40f0eb285d1b4b63d00c98daec0bb9f4..445582f9dbd6b7024d8f7c1ebaecd998c3486b9c 100644 --- a/app/code/Magento/Paypal/Block/Express/Review/Billing.php +++ b/app/code/Magento/Paypal/Block/Express/Review/Billing.php @@ -9,8 +9,222 @@ */ namespace Magento\Paypal\Block\Express\Review; -class Billing extends \Magento\Checkout\Block\Onepage\Billing +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Quote\Model\Quote; + +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class Billing extends \Magento\Framework\View\Element\Template { + /** + * Sales Quote Billing Address instance + * + * @var \Magento\Quote\Model\Quote\Address + */ + protected $address; + + /** + * Customer Taxvat Widget block + * + * @var \Magento\Customer\Block\Widget\Taxvat + */ + protected $taxvat; + + /** + * @var \Magento\Quote\Model\Quote\AddressFactory + */ + protected $addressFactory; + + /** + * @var \Magento\Customer\Api\Data\CustomerInterface + */ + protected $customer; + + /** + * @var Quote + */ + protected $quote; + + /** + * @var \Magento\Checkout\Model\Session + */ + protected $checkoutSession; + + /** + * @var \Magento\Customer\Model\Session + */ + protected $customerSession; + + /** + * @var CustomerRepositoryInterface + */ + protected $customerRepository; + + /** + * @var \Magento\Framework\App\Http\Context + */ + protected $httpContext; + + /** + * @var \Magento\Directory\Model\ResourceModel\Country\CollectionFactory + */ + protected $countryCollectionFactory; + + /** + * @param \Magento\Framework\View\Element\Template\Context $context + * @param \Magento\Customer\Model\Session $customerSession + * @param \Magento\Checkout\Model\Session $resourceSession + * @param \Magento\Directory\Model\ResourceModel\Country\CollectionFactory $countryCollectionFactory + * @param CustomerRepositoryInterface $customerRepository + * @param \Magento\Framework\App\Http\Context $httpContext + * @param Quote\AddressFactory $addressFactory + * @param array $data + */ + public function __construct( + \Magento\Framework\View\Element\Template\Context $context, + \Magento\Customer\Model\Session $customerSession, + \Magento\Checkout\Model\Session $resourceSession, + \Magento\Directory\Model\ResourceModel\Country\CollectionFactory $countryCollectionFactory, + CustomerRepositoryInterface $customerRepository, + \Magento\Framework\App\Http\Context $httpContext, + \Magento\Quote\Model\Quote\AddressFactory $addressFactory, + array $data = [] + ) { + $this->addressFactory = $addressFactory; + $this->_isScopePrivate = true; + $this->httpContext = $httpContext; + $this->customerRepository = $customerRepository; + $this->checkoutSession = $resourceSession; + $this->customerSession = $customerSession; + $this->countryCollectionFactory = $countryCollectionFactory; + parent::__construct($context, $data); + } + + /** + * Initialize billing address step + * + * @return void + */ + protected function _construct() + { + $this->getCheckout()->setStepData( + 'billing', + ['label' => __('Billing Information'), 'is_show' => true] + ); + + if ($this->isCustomerLoggedIn()) { + $this->getCheckout()->setStepData('billing', 'allow', true); + } + parent::_construct(); + } + + /** + * @return bool + */ + public function isUseBillingAddressForShipping() + { + if ($this->getQuote()->getIsVirtual() || !$this->getQuote()->getShippingAddress()->getSameAsBilling()) { + return false; + } + return true; + } + + /** + * Return country collection + * + * @return \Magento\Directory\Model\ResourceModel\Country\Collection + */ + public function getCountries() + { + return $this->countryCollectionFactory->create()->loadByStore(); + } + + /** + * Return checkout method + * + * @return string + */ + public function getMethod() + { + return $this->getQuote()->getCheckoutMethod(); + } + + /** + * Return Customer Address First Name + * If Sales Quote Address First Name is not defined - return Customer First Name + * + * @return string + */ + public function getFirstname() + { + return $this->getAddress()->getFirstname(); + } + + /** + * Return Customer Address Last Name + * If Sales Quote Address Last Name is not defined - return Customer Last Name + * + * @return string + */ + public function getLastname() + { + return $this->getAddress()->getLastname(); + } + + /** + * Check is Quote items can ship to + * + * @return bool + */ + public function canShip() + { + return !$this->getQuote()->isVirtual(); + } + + /** + * @return void + */ + public function getSaveUrl() + { + } + + /** + * Get Customer Taxvat Widget block + * + * @return \Magento\Customer\Block\Widget\Taxvat + */ + protected function _getTaxvat() + { + if (!$this->taxvat) { + $this->taxvat = $this->getLayout()->createBlock('Magento\Customer\Block\Widget\Taxvat'); + } + + return $this->taxvat; + } + + /** + * Check whether taxvat is enabled + * + * @return bool + */ + public function isTaxvatEnabled() + { + return $this->_getTaxvat()->isEnabled(); + } + + /** + * @return string + */ + public function getTaxvatHtml() + { + return $this->_getTaxvat() + ->setTaxvat($this->getQuote()->getCustomerTaxvat()) + ->setFieldIdFormat('billing:%s') + ->setFieldNameFormat('billing[%s]') + ->toHtml(); + } + /** * Return Sales Quote Address model * @@ -18,20 +232,75 @@ class Billing extends \Magento\Checkout\Block\Onepage\Billing */ public function getAddress() { - if ($this->_address === null) { + if ($this->address === null) { if ($this->isCustomerLoggedIn() || $this->getQuote()->getBillingAddress()) { - $this->_address = $this->getQuote()->getBillingAddress(); - if (!$this->_address->getFirstname()) { - $this->_address->setFirstname($this->getQuote()->getCustomer()->getFirstname()); + $this->address = $this->getQuote()->getBillingAddress(); + if (!$this->address->getFirstname()) { + $this->address->setFirstname($this->getQuote()->getCustomer()->getFirstname()); } - if (!$this->_address->getLastname()) { - $this->_address->setLastname($this->getQuote()->getCustomer()->getLastname()); + if (!$this->address->getLastname()) { + $this->address->setLastname($this->getQuote()->getCustomer()->getLastname()); } } else { - $this->_address = $this->_addressFactory->create(); + $this->address = $this->addressFactory->create(); } } - return $this->_address; + return $this->address; + } + + /** + * Get config + * + * @param string $path + * @return string|null + */ + public function getConfig($path) + { + return $this->_scopeConfig->getValue($path, \Magento\Store\Model\ScopeInterface::SCOPE_STORE); + } + + /** + * Get logged in customer + * + * @return \Magento\Customer\Api\Data\CustomerInterface + */ + protected function _getCustomer() + { + if (empty($this->customer)) { + $this->customer = $this->customerRepository->getById($this->customerSession->getCustomerId()); + } + return $this->customer; + } + + /** + * Retrieve checkout session model + * + * @return \Magento\Checkout\Model\Session + */ + public function getCheckout() + { + return $this->checkoutSession; + } + + /** + * Retrieve sales quote model + * + * @return Quote + */ + public function getQuote() + { + if (empty($this->quote)) { + $this->quote = $this->getCheckout()->getQuote(); + } + return $this->quote; + } + + /** + * @return bool + */ + public function isCustomerLoggedIn() + { + return $this->httpContext->getValue(\Magento\Customer\Model\Context::CONTEXT_AUTH); } } diff --git a/app/code/Magento/Paypal/Block/Express/Review/Shipping.php b/app/code/Magento/Paypal/Block/Express/Review/Shipping.php index 97fe0a20e9c3f045da8a8c29c830f5b97691a8f5..e49171238ceedc62304d95b5e2e0e7a00f6f5053 100644 --- a/app/code/Magento/Paypal/Block/Express/Review/Shipping.php +++ b/app/code/Magento/Paypal/Block/Express/Review/Shipping.php @@ -9,8 +9,115 @@ */ namespace Magento\Paypal\Block\Express\Review; -class Shipping extends \Magento\Checkout\Block\Onepage\Shipping +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Quote\Model\Quote; + +class Shipping extends \Magento\Framework\View\Element\Template { + /** + * Sales Quote Shipping Address instance + * + * @var \Magento\Quote\Model\Quote\Address + */ + protected $address = null; + + /** + * @var \Magento\Quote\Model\Quote\AddressFactory + */ + protected $addressFactory; + + /** + * @var \Magento\Customer\Api\Data\CustomerInterface + */ + protected $customer; + + /** + * @var Quote + */ + protected $quote; + + /** + * @var \Magento\Checkout\Model\Session + */ + protected $checkoutSession; + + /** + * @var CustomerRepositoryInterface + */ + protected $customerRepository; + + /** + * @var \Magento\Framework\App\Http\Context + */ + protected $httpContext; + + /** + * @var \Magento\Customer\Model\Session + */ + protected $customerSession; + + /** + * @param \Magento\Framework\View\Element\Template\Context $context + * @param \Magento\Customer\Model\Session $customerSession + * @param \Magento\Checkout\Model\Session $resourceSession + * @param CustomerRepositoryInterface $customerRepository + * @param \Magento\Framework\App\Http\Context $httpContext + * @param \Magento\Quote\Model\Quote\AddressFactory $addressFactory + * @param array $data + */ + public function __construct( + \Magento\Framework\View\Element\Template\Context $context, + \Magento\Customer\Model\Session $customerSession, + \Magento\Checkout\Model\Session $resourceSession, + CustomerRepositoryInterface $customerRepository, + \Magento\Framework\App\Http\Context $httpContext, + \Magento\Quote\Model\Quote\AddressFactory $addressFactory, + array $data = [] + ) { + $this->addressFactory = $addressFactory; + $this->_isScopePrivate = true; + $this->httpContext = $httpContext; + $this->customerRepository = $customerRepository; + $this->checkoutSession = $resourceSession; + $this->customerSession = $customerSession; + parent::__construct($context, $data); + } + + /** + * Initialize shipping address step + * + * @return void + */ + protected function _construct() + { + $this->checkoutSession->setStepData( + 'shipping', + ['label' => __('Shipping Information'), 'is_show' => $this->isShow()] + ); + + parent::_construct(); + } + + /** + * Return checkout method + * + * @return string + */ + public function getMethod() + { + return $this->getQuote()->getCheckoutMethod(); + } + + /** + * Retrieve is allow and show block + * + * @return bool + */ + public function isShow() + { + return !$this->getQuote()->isVirtual(); + } + /** * Return Sales Quote Address model (shipping address) * @@ -18,14 +125,59 @@ class Shipping extends \Magento\Checkout\Block\Onepage\Shipping */ public function getAddress() { - if ($this->_address === null) { + if ($this->address === null) { if ($this->isCustomerLoggedIn() || $this->getQuote()->getShippingAddress()) { - $this->_address = $this->getQuote()->getShippingAddress(); + $this->address = $this->getQuote()->getShippingAddress(); } else { - $this->_address = $this->_addressFactory->create(); + $this->address = $this->addressFactory->create(); } } - return $this->_address; + return $this->address; + } + + /** + * Get config + * + * @param string $path + * @return string|null + */ + public function getConfig($path) + { + return $this->_scopeConfig->getValue($path, \Magento\Store\Model\ScopeInterface::SCOPE_STORE); + } + + /** + * Get logged in customer + * + * @return \Magento\Customer\Api\Data\CustomerInterface + */ + protected function _getCustomer() + { + if (empty($this->customer)) { + $this->customer = $this->customerRepository->getById($this->customerSession->getCustomerId()); + } + return $this->customer; + } + + /** + * Retrieve sales quote model + * + * @return Quote + */ + public function getQuote() + { + if (empty($this->quote)) { + $this->quote = $this->checkoutSession->getQuote(); + } + return $this->quote; + } + + /** + * @return bool + */ + public function isCustomerLoggedIn() + { + return $this->httpContext->getValue(\Magento\Customer\Model\Context::CONTEXT_AUTH); } } diff --git a/app/code/Magento/Paypal/Model/Config.php b/app/code/Magento/Paypal/Model/Config.php index dd5a0696e3e295878b3b6ec3a6053866d340f674..1e4b95886fc04932b94c0104fd5a3311caa4ec23 100644 --- a/app/code/Magento/Paypal/Model/Config.php +++ b/app/code/Magento/Paypal/Model/Config.php @@ -208,12 +208,13 @@ class Config extends AbstractConfig 'NZD', 'PLN', 'GBP', + 'RUB', 'SGD', 'SEK', 'CHF', - 'USD', 'TWD', 'THB', + 'USD', ]; /** diff --git a/app/code/Magento/Paypal/Model/Config/Rules/Converter.php b/app/code/Magento/Paypal/Model/Config/Rules/Converter.php index a636188baf1cf571ea572625e6de6dec367b640e..5528f79b385758a89b1c4c1fad3d2fa90e92b08e 100644 --- a/app/code/Magento/Paypal/Model/Config/Rules/Converter.php +++ b/app/code/Magento/Paypal/Model/Config/Rules/Converter.php @@ -58,8 +58,8 @@ class Converter implements ConverterInterface protected function createEvents(\DOMElement $node) { $result = []; - /** @var \DOMElement $child */ foreach ($node->childNodes as $child) { + /** @var \DOMElement $child */ if ($this->hasNodeElement($child)) { $result[$child->getAttribute('name')] = [ 'value' => $child->getAttribute('value'), @@ -80,8 +80,8 @@ class Converter implements ConverterInterface protected function createPredicate(\DOMElement $node) { $result = []; - /** @var \DOMElement $child */ foreach ($node->childNodes as $child) { + /** @var \DOMElement $child */ if ($this->hasNodeElement($child)) { $result = [ 'name' => $child->getAttribute('name'), @@ -105,33 +105,18 @@ class Converter implements ConverterInterface { $result = []; foreach ($node->childNodes as $child) { + /** @var \DOMElement $child */ if ($this->hasNodeElement($child)) { - $result = array_merge($result, $this->createRule($child)); + $result[$child->getAttribute('type')][] = [ + 'event' => $child->getAttribute('event'), + 'argument' => $this->createArgument($child), + ]; } } return [$node->getAttribute('target') => $result]; } - /** - * Creating rules - * - * @param \DOMElement $node - * @return array - */ - protected function createRule(\DOMElement $node) - { - $result = []; - $type = $node->getAttribute('type'); - /** @var \DOMElement $node */ - $result[$type] = [ - 'event' => $node->getAttribute('event'), - ]; - $result[$type]['argument'] = $this->createArgument($node); - - return $result; - } - /** * Create argument * @@ -141,8 +126,8 @@ class Converter implements ConverterInterface protected function createArgument(\DOMElement $node) { $result = []; - /** @var \DOMElement $child */ foreach ($node->childNodes as $child) { + /** @var \DOMElement $child */ if ($this->hasNodeElement($child)) { $result[$child->getAttribute('name')] = $child->textContent; } diff --git a/app/code/Magento/Paypal/Model/Payflowpro.php b/app/code/Magento/Paypal/Model/Payflowpro.php index 6efc7e7cca4ed1735aeeaaacc8deee09aaf18eb1..894c0792a99e4ab689f5c40aed6b0d29c0d334a5 100644 --- a/app/code/Magento/Paypal/Model/Payflowpro.php +++ b/app/code/Magento/Paypal/Model/Payflowpro.php @@ -500,8 +500,7 @@ class Payflowpro extends \Magento\Payment\Model\Method\Cc implements GatewayInte $this->processErrors($response); if ($response->getResultCode() == self::RESPONSE_CODE_APPROVED) { - $payment->setTransactionId($response->getPnref())->setIsTransactionClosed(1); - $payment->setShouldCloseParentTransaction(!$payment->getCreditmemo()->getInvoice()->canRefund()); + $payment->setTransactionId($response->getPnref())->setIsTransactionClosed(true); } return $this; } diff --git a/app/code/Magento/Paypal/Model/ResourceModel/Billing/Agreement.php b/app/code/Magento/Paypal/Model/ResourceModel/Billing/Agreement.php index 6f714ae437e605c3836c55a0aa430a845b1f23fd..5344091f837bf0664b7a817dcd849c53a66de105 100644 --- a/app/code/Magento/Paypal/Model/ResourceModel/Billing/Agreement.php +++ b/app/code/Magento/Paypal/Model/ResourceModel/Billing/Agreement.php @@ -39,11 +39,11 @@ class Agreement extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb /** * Add billing agreement filter on orders collection * - * @param \Magento\Sales\Model\ResourceModel\Order\Collection $orderCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $orderCollection * @param string|int|array $agreementIds * @return $this */ - public function addOrdersFilter(\Magento\Sales\Model\ResourceModel\Order\Collection $orderCollection, $agreementIds) + public function addOrdersFilter(\Magento\Framework\Data\Collection\AbstractDb $orderCollection, $agreementIds) { $agreementIds = is_array($agreementIds) ? $agreementIds : [$agreementIds]; $orderCollection->getSelect()->joinInner( diff --git a/app/code/Magento/Paypal/Observer/AddBillingAgreementToSessionObserver.php b/app/code/Magento/Paypal/Observer/AddBillingAgreementToSessionObserver.php index 8bd494207b6b70faa97e1f92b775d13ade60c15f..2cc2425387b134c7c67ce9a3098a8be9ad5056c7 100644 --- a/app/code/Magento/Paypal/Observer/AddBillingAgreementToSessionObserver.php +++ b/app/code/Magento/Paypal/Observer/AddBillingAgreementToSessionObserver.php @@ -53,6 +53,7 @@ class AddBillingAgreementToSessionObserver implements ObserverInterface if ($agreement->isValid()) { $message = __('Created billing agreement #%1.', $agreement->getReferenceId()); $order->addRelatedObject($agreement); + $agreement->addOrderRelation($order); $this->checkoutSession->setLastBillingAgreementReferenceId($agreement->getReferenceId()); $agreementCreated = true; } else { diff --git a/app/code/Magento/Paypal/Test/Unit/Model/Config/Rules/ConverterTest.php b/app/code/Magento/Paypal/Test/Unit/Model/Config/Rules/ConverterTest.php index eb62d570481bde11725647a1ab54858c4ca96dcf..ffd2f141e0a0d7da9bc3f642e581e754d3324d6e 100644 --- a/app/code/Magento/Paypal/Test/Unit/Model/Config/Rules/ConverterTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Model/Config/Rules/ConverterTest.php @@ -78,22 +78,27 @@ class ConverterTest extends \PHPUnit_Framework_TestCase 'relations' => [ 'payment_test_1' => [ 'test' => [ - 'event' => 'event0', - 'argument' => [], + [ + 'event' => 'event0', + 'argument' => [], + ] ], ], 'payment_test_2' => [ 'test' => [ - 'event' => 'event1', - 'argument' => [ - ], + [ + 'event' => 'event1', + 'argument' => [], + ] ], 'test-two' => [ - 'event' => 'event1', - 'argument' => [ - 'argument1' => 'argument1', - 'argument2' => 'argument2', - ], + [ + 'event' => 'event1', + 'argument' => [ + 'argument1' => 'argument1', + 'argument2' => 'argument2', + ], + ] ], ], ], @@ -122,21 +127,34 @@ class ConverterTest extends \PHPUnit_Framework_TestCase 'relations' => [ 'payment_test_1' => [ 'test' => [ - 'event' => 'event0', - 'argument' => [], + [ + 'event' => 'event0', + 'argument' => [], + ] ], ], 'payment_test_2' => [ 'test' => [ - 'event' => 'event1', - 'argument' => [], + [ + 'event' => 'event1', + 'argument' => [], + ] ], 'test-two' => [ - 'event' => 'event1', - 'argument' => [ - 'argument1' => 'argument1', - 'argument2' => 'argument2', + [ + 'event' => 'event1', + 'argument' => [ + 'argument1' => 'argument1', + 'argument2' => 'argument2', + ], ], + [ + 'event' => 'event2', + 'argument' => [ + 'argument1' => 'argument1', + 'argument2' => 'argument2', + ], + ] ], ], ], diff --git a/app/code/Magento/Paypal/Test/Unit/Model/Config/Rules/ConvertibleContent/rules.xml b/app/code/Magento/Paypal/Test/Unit/Model/Config/Rules/ConvertibleContent/rules.xml index 297d3c8e620a06480da9c009f1cfc59ae81d746f..4b4c6833d92c92399d29fae6e687472d24cbedfb 100644 --- a/app/code/Magento/Paypal/Test/Unit/Model/Config/Rules/ConvertibleContent/rules.xml +++ b/app/code/Magento/Paypal/Test/Unit/Model/Config/Rules/ConvertibleContent/rules.xml @@ -52,6 +52,10 @@ <argument name="argument1">argument1</argument> <argument name="argument2">argument2</argument> </rule> + <rule type="test-two" event="event2"> + <argument name="argument1">argument1</argument> + <argument name="argument2">argument2</argument> + </rule> </relation> </payment> </rules> diff --git a/app/code/Magento/Paypal/Test/Unit/Model/PayflowproTest.php b/app/code/Magento/Paypal/Test/Unit/Model/PayflowproTest.php index 215680852225b7b3ed5b4507a223fda725b821b5..c6250a24903ee0e71b30669e762a44c00a3eb06c 100644 --- a/app/code/Magento/Paypal/Test/Unit/Model/PayflowproTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Model/PayflowproTest.php @@ -175,7 +175,6 @@ class PayflowproTest extends \PHPUnit_Framework_TestCase $this->payflowpro->fetchTransactionInfo($payment, 'AD49G8N825'); } - /** * @param $response * @dataProvider setTransStatusDataProvider @@ -323,6 +322,22 @@ class PayflowproTest extends \PHPUnit_Framework_TestCase ]; } + /** + * @covers \Magento\Paypal\Model\Payflowpro::refund() + */ + public function testRefund() + { + /** @var \Magento\Sales\Model\Order\Payment $paymentMock */ + $paymentMock = $this->getPaymentMock(); + + $response = $this->execGatewayRequest(); + + $amount = 213.04; + $this->payflowpro->refund($paymentMock, $amount); + static::assertEquals($response['pnref'], $paymentMock->getTransactionId()); + static::assertTrue($paymentMock->getIsTransactionClosed()); + } + /** * Create mock object for store model * @return void @@ -399,16 +414,16 @@ class PayflowproTest extends \PHPUnit_Framework_TestCase 'year' => 18, 'cvv' => 123 ]; - $paymentMock->expects(static::once()) + $paymentMock->expects(static::any()) ->method('getCcNumber') ->willReturn($cardData['number']); - $paymentMock->expects(static::once()) + $paymentMock->expects(static::any()) ->method('getCcExpMonth') ->willReturn($cardData['month']); - $paymentMock->expects(static::once()) + $paymentMock->expects(static::any()) ->method('getCcExpYear') ->willReturn($cardData['year']); - $paymentMock->expects(static::once()) + $paymentMock->expects(static::any()) ->method('getCcCid') ->willReturn($cardData['cvv']); return $paymentMock; diff --git a/app/code/Magento/Paypal/Test/Unit/Observer/AddBillingAgreementToSessionObserverTest.php b/app/code/Magento/Paypal/Test/Unit/Observer/AddBillingAgreementToSessionObserverTest.php index 7feea45b45d589f6485793750e1fe933a6999152..df0fc80c177e45d516f09cee03777bb887b8b3d5 100644 --- a/app/code/Magento/Paypal/Test/Unit/Observer/AddBillingAgreementToSessionObserverTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Observer/AddBillingAgreementToSessionObserverTest.php @@ -122,6 +122,7 @@ class AddBillingAgreementToSessionObserverTest extends \PHPUnit_Framework_TestCa )->will( $this->returnValue('agreement reference id') ); + $agreement->expects($this->once())->method('addOrderRelation')->with($order); $order->expects(new MethodInvokedAtIndex(0))->method('addRelatedObject')->with($agreement); $this->_checkoutSession->expects( $this->once() diff --git a/app/code/Magento/Paypal/etc/adminhtml/rules/payment_us.xml b/app/code/Magento/Paypal/etc/adminhtml/rules/payment_us.xml index c187130b357b85e975b93c17f457b30c78bd5f0f..4b5acbe6e073e8259ff3a3b4364c7c5c7ef70fac 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/rules/payment_us.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/rules/payment_us.xml @@ -329,7 +329,10 @@ <argument name="wpp_usuk">wpp_usuk</argument> <argument name="paypal_payflowpro_with_express_checkout">paypal_payflowpro_with_express_checkout</argument> </rule> + <rule type="payflow/bml/disable-conditional-express" event="deactivate-express"/> + <rule type="payflow/bml/disable-conditional-express" event=":load"/> + <rule type="payflow/bml/enable" event="activate-express"/> <rule type="payflow/express/lock-conditional" event=":load"/> <rule type="payflow/bml/lock-conditional" event=":load"/> diff --git a/app/code/Magento/Paypal/view/adminhtml/templates/billing/agreement/form.phtml b/app/code/Magento/Paypal/view/adminhtml/templates/billing/agreement/form.phtml index 0d933a861b54182146e34358253ac033072f4c28..e1f6c1ac9655bcaa39a0e78efcf0023c1564b6ae 100644 --- a/app/code/Magento/Paypal/view/adminhtml/templates/billing/agreement/form.phtml +++ b/app/code/Magento/Paypal/view/adminhtml/templates/billing/agreement/form.phtml @@ -7,7 +7,7 @@ // @codingStandardsIgnoreFile /** @var \Magento\Paypal\Block\Adminhtml\Billing\Agreement\View\Form $block */ ?> -<?php $code = $block->getMethodCode() ?> +<?php $code = $block->escapeHtml($block->getMethodCode()) ?> <fieldset class="form-list" id="payment_form_<?php /* @noEscape */ echo $code; ?>" style="display:none;"> <div class="admin__field _required"> <label for="<?php /* @noEscape */ echo $code; ?>_ba_agreement_id" class="admin__field-label"> diff --git a/app/code/Magento/Paypal/view/adminhtml/templates/payment/form/billing/agreement.phtml b/app/code/Magento/Paypal/view/adminhtml/templates/payment/form/billing/agreement.phtml index d3a6bab129806819191d864a6dde2c60c952703f..66c2184c31012317eaa1cd704b3a3ba3ec0f5385 100644 --- a/app/code/Magento/Paypal/view/adminhtml/templates/payment/form/billing/agreement.phtml +++ b/app/code/Magento/Paypal/view/adminhtml/templates/payment/form/billing/agreement.phtml @@ -7,7 +7,7 @@ // @codingStandardsIgnoreFile /* @var $block \Magento\Paypal\Block\Payment\Form\Billing\Agreement */ ?> -<?php $code = $block->getMethodCode() ?> +<?php $code = $block->escapeHtml($block->getMethodCode()) ?> <fieldset class="admin__fieldset payment-method form-list" id="payment_form_<?php /* @noEscape */ echo $code; ?>" style="display:none;"> <div class="admin__field _required"> diff --git a/app/code/Magento/Paypal/view/adminhtml/web/js/predicate/confirm.js b/app/code/Magento/Paypal/view/adminhtml/web/js/predicate/confirm.js index ea426368243185bc14ed8fded1b77387366dddb3..278b101c9c696aabe05c1c62a28d426ce399acaf 100644 --- a/app/code/Magento/Paypal/view/adminhtml/web/js/predicate/confirm.js +++ b/app/code/Magento/Paypal/view/adminhtml/web/js/predicate/confirm.js @@ -2,25 +2,28 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -define([], function () { - "use strict"; +define(['underscore'], function (_) { + 'use strict'; + return function (solution, message, argument) { var isConfirm = false; _.every(argument, function (name) { - if (solution.solutionsElements[name] - && solution.solutionsElements[name].find(solution.enableButton).val() == 1 + if (solution.solutionsElements[name] && + solution.solutionsElements[name].find(solution.enableButton).val() == 1 ) { isConfirm = true; + return !isConfirm; } + return !isConfirm; }, this); if (isConfirm) { return confirm(message); - } else { - return true; } + + return true; }; }); diff --git a/app/code/Magento/Paypal/view/adminhtml/web/js/rule.js b/app/code/Magento/Paypal/view/adminhtml/web/js/rule.js index b565aa2d66d6b46c2165650567b06fe440291b4e..c1c12344cc54c15ededbd2bb0b80184b09be19fd 100644 --- a/app/code/Magento/Paypal/view/adminhtml/web/js/rule.js +++ b/app/code/Magento/Paypal/view/adminhtml/web/js/rule.js @@ -3,18 +3,24 @@ * See COPYING.txt for license details. */ define([ - "uiClass", - "underscore" -], function (Class, _) { - "use strict"; + 'uiClass' +], function (Class) { + 'use strict'; + return Class.extend({ + /** * Constructor + * + * @param {Object} config + * @returns {exports.initialize} */ initialize: function (config) { this.initConfig(config); + return this; }, + /** * To apply the rule */ diff --git a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/conflict.js b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/conflict.js index 4d94f6a2a9ff63cdb9195b4bbdaf012f98ec4cf7..54b263be6421dcdd7534f811c7ef80a02be12e99 100644 --- a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/conflict.js +++ b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/conflict.js @@ -2,32 +2,42 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -(function() { +(function () { + 'use strict'; + var executed = false; + define([ - 'Magento_Ui/js/modal/alert' - ], function (alert) { - "use strict"; + 'Magento_Ui/js/modal/alert', + 'underscore' + ], function (alert, _) { + return function ($target, $owner, data) { - if ($owner.find(data.enableButton).val() == 1) { - var isDisabled = true; + var isDisabled = true, + newLine = String.fromCharCode(10, 13); + + if ($owner.find(data.enableButton).val() === '1') { _.every(data.argument, function (name) { - if (data.solutionsElements[name] - && data.solutionsElements[name].find(data.enableButton).val() == 1 + if (data.solutionsElements[name] && + data.solutionsElements[name].find(data.enableButton).val() === '1' ) { isDisabled = false; + return isDisabled; } + return isDisabled; }, this); if (!isDisabled && !executed) { executed = true; alert({ - content: "The following error(s) occured:\n\r" - +"Some PayPal solutions conflict.\n\r" - +"Please re-enable the previously enabled payment solutions." + content: 'The following error(s) occurred:' + + newLine + + 'Some PayPal solutions conflict.' + + newLine + + 'Please re-enable the previously enabled payment solutions.' }); } } diff --git a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/disable.js b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/disable.js index a5cc52ed96bc2b145d06a638cef1be7135ce920b..54e355580394b5437fb79b6d2ecc6e20be54e184 100644 --- a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/disable.js +++ b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/disable.js @@ -5,7 +5,8 @@ define([ 'Magento_Paypal/js/rules/simple/disable' ], function (disable) { - "use strict"; + 'use strict'; + return function ($target, $owner, data) { disable($target, $owner, data); $target.find(data.enableButton).change(); diff --git a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/bml/disable-conditional-express.js b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/bml/disable-conditional-express.js index 8fccdd054558b3e289fd79ec88c52fbb32dac7ce..e3d95340b8bfe534f1da36452b36dcc63bc2e4db 100644 --- a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/bml/disable-conditional-express.js +++ b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/bml/disable-conditional-express.js @@ -5,9 +5,10 @@ define([ 'Magento_Paypal/js/rules/payflow/bml/disable' ], function (disable) { - "use strict"; + 'use strict'; + return function ($target, $owner, data) { - if ($target.find(data.enableExpress).val() == "0") { + if ($target.find(data.enableExpress).val() === '0') { disable($target, $owner, data); } }; diff --git a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/bml/disable-conditional.js b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/bml/disable-conditional.js index 2c5ae4265342b266e9fe76d9b60994482e371a0e..20182ef0205f4135e853b77b3c937d17f59c66bc 100644 --- a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/bml/disable-conditional.js +++ b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/bml/disable-conditional.js @@ -5,9 +5,10 @@ define([ 'Magento_Paypal/js/rules/payflow/bml/disable' ], function (disable) { - "use strict"; + 'use strict'; + return function ($target, $owner, data) { - if ($target.find(data.enableButton).val() == "0") { + if ($target.find(data.enableButton).val() === '0') { disable($target, $owner, data); } }; diff --git a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/bml/disable.js b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/bml/disable.js index 873eea979583c30b3fdc10906b968b1c7a1fba00..01d241a0e36197981029a2cfa63eaf1399193967 100644 --- a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/bml/disable.js +++ b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/bml/disable.js @@ -3,7 +3,8 @@ * See COPYING.txt for license details. */ define([], function () { - "use strict"; + 'use strict'; + return function ($target, $owner, data) { $target.find('label[for="' + $target.find(data.enableBml).attr('id') + '"]').removeClass('enabled'); $target.find(data.enableBml + ' option[value="0"]').prop('selected', true); diff --git a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/bml/enable-conditional.js b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/bml/enable-conditional.js index f5d796397c705af56a476831d3710ff0c66f504b..9770d463f45fc676eeda339a9d7849368822f93f 100644 --- a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/bml/enable-conditional.js +++ b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/bml/enable-conditional.js @@ -2,18 +2,21 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -define([], function () { - "use strict"; +define(['underscore'], function (_) { + 'use strict'; + return function ($target, $owner, data) { var isDisabled = true; _.every(data.argument, function (name) { - if (data.solutionsElements[name] - && data.solutionsElements[name].find(data.enableButton).val() == 1 + if (data.solutionsElements[name] && + data.solutionsElements[name].find(data.enableButton).val() === '1' ) { isDisabled = false; + return isDisabled; } + return isDisabled; }, this); diff --git a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/bml/enable.js b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/bml/enable.js index e7710d80cf07fc84a6ee9769ee8bb4388c155921..3ddfc3b0f60446334670836e98fffcf2cdac2dd4 100644 --- a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/bml/enable.js +++ b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/bml/enable.js @@ -3,7 +3,8 @@ * See COPYING.txt for license details. */ define([], function () { - "use strict"; + 'use strict'; + return function ($target, $owner, data) { $target.find(data.enableBml).prop('disabled', false); $target.find(data.enableBml + ' option[value="1"]').prop('selected', true); diff --git a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/bml/lock-conditional.js b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/bml/lock-conditional.js index 09007924b0b4bb53f90f968717766af6e5ba9d74..607c56984e7dc6f4047a20a55b8a262442bd69ba 100644 --- a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/bml/lock-conditional.js +++ b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/bml/lock-conditional.js @@ -3,9 +3,10 @@ * See COPYING.txt for license details. */ define([], function () { - "use strict"; + 'use strict'; + return function ($target, $owner, data) { - if ($target.find(data.enableButton).val() == "0") { + if ($target.find(data.enableButton).val() === '0') { $target.find(data.enableBml).prop('disabled', true); } }; diff --git a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/express/disable-conditional.js b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/express/disable-conditional.js index f37306731b8857896fcade130783a5de86ccbe20..94b178c071642e09b80771094946ba7522541815 100644 --- a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/express/disable-conditional.js +++ b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/express/disable-conditional.js @@ -5,9 +5,10 @@ define([ 'Magento_Paypal/js/rules/payflow/express/disable' ], function (disableExpress) { - "use strict"; + 'use strict'; + return function ($target, $owner, data) { - if ($target.find(data.enableButton).val() == "0") { + if ($target.find(data.enableButton).val() === '0') { disableExpress($target, $owner, data); $target.find(data.enableExpress).change(); } diff --git a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/express/disable.js b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/express/disable.js index 4d8b6fa3ca39918293381d36e23d1314304f1439..77649695f3c11394c98f95d7e50bd57d4857971a 100644 --- a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/express/disable.js +++ b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/express/disable.js @@ -3,7 +3,8 @@ * See COPYING.txt for license details. */ define([], function () { - "use strict"; + 'use strict'; + return function ($target, $owner, data) { $target.find('label[for="' + $target.find(data.enableExpress).attr('id') + '"]').removeClass('enabled'); $target.find(data.enableExpress + ' option[value="0"]').prop('selected', true); diff --git a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/express/enable-conditional.js b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/express/enable-conditional.js index cc76875080a4ee00e98e93c56b182982bd06e233..ea9fc5f2d0ccbe6741615fed4bb9cd5cb0c85b74 100644 --- a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/express/enable-conditional.js +++ b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/express/enable-conditional.js @@ -2,18 +2,21 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -define([], function () { - "use strict"; +define(['underscore'], function (_) { + 'use strict'; + return function ($target, $owner, data) { var isDisabled = true; _.every(data.argument, function (name) { - if (data.solutionsElements[name] - && data.solutionsElements[name].find(data.enableButton).val() == 1 + if (data.solutionsElements[name] && + data.solutionsElements[name].find(data.enableButton).val() === '1' ) { isDisabled = false; + return isDisabled; } + return isDisabled; }, this); diff --git a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/express/enable.js b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/express/enable.js index 456b4a6ac78ddd8bc591653a45aaf247303f1d2a..6dc1a0a49cfba72168b9e0d69b067b9dab2fa380 100644 --- a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/express/enable.js +++ b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/express/enable.js @@ -3,7 +3,8 @@ * See COPYING.txt for license details. */ define([], function () { - "use strict"; + 'use strict'; + return function ($target, $owner, data) { $target.find(data.enableExpress).prop('disabled', false); $target.find(data.enableExpress + ' option[value="1"]').prop('selected', true); diff --git a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/express/lock-conditional.js b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/express/lock-conditional.js index 476af3b58366a86ffef757addeb4230a4f0436de..c07a0b5cf713e2b7c65bda537e331e47980f6e37 100644 --- a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/express/lock-conditional.js +++ b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/payflow/express/lock-conditional.js @@ -3,9 +3,10 @@ * See COPYING.txt for license details. */ define([], function () { - "use strict"; + 'use strict'; + return function ($target, $owner, data) { - if ($target.find(data.enableButton).val() == "0") { + if ($target.find(data.enableButton).val() === '0') { $target.find(data.enableExpress).prop('disabled', true); } }; diff --git a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/bml/disable-conditional.js b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/bml/disable-conditional.js index ed327a4678fbc1db79bc1250cee0557aa06f9e5f..d4b8d4100e56d5e9e5e2ffc134ae79e6a5445859 100644 --- a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/bml/disable-conditional.js +++ b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/bml/disable-conditional.js @@ -5,9 +5,10 @@ define([ 'Magento_Paypal/js/rules/paypal/bml/disable' ], function (disable) { - "use strict"; + 'use strict'; + return function ($target, $owner, data) { - if ($target.find(data.enableButton).val() == "0") { + if ($target.find(data.enableButton).val() === '0') { disable($target, $owner, data); } }; diff --git a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/bml/disable.js b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/bml/disable.js index 124c325c445dce34969c7e02a4ad89455daedbcf..c6ef93d332fb64b102a4ec2ba30370e5cc61d384 100644 --- a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/bml/disable.js +++ b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/bml/disable.js @@ -3,7 +3,8 @@ * See COPYING.txt for license details. */ define([], function () { - "use strict"; + 'use strict'; + return function ($target, $owner, data) { $target.find('label[for="' + $target.find(data.enableBmlPayPal).attr('id') + '"]').removeClass('enabled'); $target.find(data.enableBmlPayPal + ' option[value="0"]').prop('selected', true); diff --git a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/bml/enable.js b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/bml/enable.js index 1beb826bf39a003926868e7b420537a03686da50..90f7561734f14f34d21e126ba7df9d2d9926dadc 100644 --- a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/bml/enable.js +++ b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/bml/enable.js @@ -3,7 +3,8 @@ * See COPYING.txt for license details. */ define([], function () { - "use strict"; + 'use strict'; + return function ($target, $owner, data) { $target.find(data.enableBmlPayPal).prop('disabled', false); $target.find(data.enableBmlPayPal + ' option[value="1"]').prop('selected', true); diff --git a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/express/disable.js b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/express/disable.js index 8421803de67a2e84fc1030fcb60ab6909547b814..25e7b611a24692ed05b544bb8bcf8e80b05862b3 100644 --- a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/express/disable.js +++ b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/express/disable.js @@ -3,7 +3,8 @@ * See COPYING.txt for license details. */ define([], function () { - "use strict"; + 'use strict'; + return function ($target, $owner, data) { $target.find(data.enableButton + ' option[value="0"]').prop('selected', true); $target.find('label.enabled').removeClass('enabled'); diff --git a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/express/lock-configuration-conditional.js b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/express/lock-configuration-conditional.js index bd2c2f62a29f5b20a08910fdf3e2504c584bfdff..55a82e3cc19322136dec33e5b6c14e41ec0525f8 100644 --- a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/express/lock-configuration-conditional.js +++ b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/express/lock-configuration-conditional.js @@ -3,19 +3,23 @@ * See COPYING.txt for license details. */ define([ - 'Magento_Paypal/js/rules/paypal/express/lock-configuration' -], function (lockConfiguration) { - "use strict"; + 'Magento_Paypal/js/rules/paypal/express/lock-configuration', + 'underscore' +], function (lockConfiguration, _) { + 'use strict'; + return function ($target, $owner, data) { var isDisabled = true; _.every(data.argument, function (name) { - if (data.solutionsElements[name] - && data.solutionsElements[name].find(data.enableButton).val() == 1 + if (data.solutionsElements[name] && + data.solutionsElements[name].find(data.enableButton).val() === '1' ) { isDisabled = false; + return isDisabled; } + return isDisabled; }, this); diff --git a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/express/lock-configuration.js b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/express/lock-configuration.js index e549bda0adf3db7d2a8e8f0f626a72097f96530c..351f799b57b28a3739d23f37cb46bc0afaedafe8 100644 --- a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/express/lock-configuration.js +++ b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/express/lock-configuration.js @@ -3,7 +3,8 @@ * See COPYING.txt for license details. */ define([], function () { - "use strict"; + 'use strict'; + return function ($target, $owner, data) { $target.find(data.buttonConfiguration).addClass('disabled') .attr('disabled', 'disabled'); diff --git a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/express/mark-disable.js b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/express/mark-disable.js index 6bcf9a559b39a05e5d9a76ef35afb8e2b029d81a..7943c843b13cde484d9d0baf1149110ac4885754 100644 --- a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/express/mark-disable.js +++ b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/express/mark-disable.js @@ -3,19 +3,23 @@ * See COPYING.txt for license details. */ define([ - 'Magento_Paypal/js/rules/simple/disable' -], function (disable) { - "use strict"; + 'Magento_Paypal/js/rules/simple/disable', + 'underscore' +], function (disable, _) { + 'use strict'; + return function ($target, $owner, data) { var isDisabled = true; _.every(data.argument, function (name) { - if (data.solutionsElements[name] - && data.solutionsElements[name].find(data.enableButton).val() == 1 + if (data.solutionsElements[name] && + data.solutionsElements[name].find(data.enableButton).val() === '1' ) { isDisabled = false; + return isDisabled; } + return isDisabled; }, this); diff --git a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/express/unlock-configuration.js b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/express/unlock-configuration.js index 413a8bf08b1d013bfc0c1b0d7f4d49beb25b2997..fda160c6d94f4babe5257180db769a37aa667537 100644 --- a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/express/unlock-configuration.js +++ b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/paypal/express/unlock-configuration.js @@ -2,18 +2,21 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -define([], function () { - "use strict"; +define(['underscore'], function (_) { + 'use strict'; + return function ($target, $owner, data) { var isUnlock = true; _.every(data.argument, function (name) { - if (data.solutionsElements[name] - && data.solutionsElements[name].find(data.enableButton).val() == 1 + if (data.solutionsElements[name] && + data.solutionsElements[name].find(data.enableButton).val() === '1' ) { isUnlock = false; + return isUnlock; } + return isUnlock; }, this); diff --git a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/simple/disable.js b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/simple/disable.js index 4b7c4234dd3ede12113f544c9f3c76a3cd72ed41..7531d4fae1aaab06dc14f3ffd611b7bc63508e53 100644 --- a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/simple/disable.js +++ b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/simple/disable.js @@ -3,7 +3,8 @@ * See COPYING.txt for license details. */ define([], function () { - "use strict"; + 'use strict'; + return function ($target, $owner, data) { $target.find(data.enableButton + ' option[value="0"]').prop('selected', true); $target.find('label.enabled').removeClass('enabled'); diff --git a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/simple/mark-enable.js b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/simple/mark-enable.js index b686f1be7c949c484de9f9dc416611c4459fcb2b..1dec21bb5b4931c2109fe2c3ab4adec651c06c3d 100644 --- a/app/code/Magento/Paypal/view/adminhtml/web/js/rules/simple/mark-enable.js +++ b/app/code/Magento/Paypal/view/adminhtml/web/js/rules/simple/mark-enable.js @@ -3,8 +3,9 @@ * See COPYING.txt for license details. */ define([], function () { - "use strict"; - return function ($target, $owner, data) { + 'use strict'; + + return function ($target) { $target.find('.section-config').addClass('enabled'); }; }); diff --git a/app/code/Magento/Paypal/view/adminhtml/web/js/solution.js b/app/code/Magento/Paypal/view/adminhtml/web/js/solution.js index 787d9e066cdbe0234bb434f57d39919d00639181..4f8de68474d7a53dc3af22f5c73c12e4ce28ef98 100644 --- a/app/code/Magento/Paypal/view/adminhtml/web/js/solution.js +++ b/app/code/Magento/Paypal/view/adminhtml/web/js/solution.js @@ -3,39 +3,47 @@ * See COPYING.txt for license details. */ define([ - "jquery", - "uiClass", - "Magento_Paypal/js/rule", - "mageUtils", - "underscore" + 'jquery', + 'uiClass', + 'Magento_Paypal/js/rule', + 'mageUtils', + 'underscore' ], function ($, Class, Rule, utils, _) { - "use strict"; + 'use strict'; + return Class.extend({ defaults: { + /** * The event corresponding to the state change */ systemEvent: 'change', + /** * The rules applied after the page is loaded */ afterLoadRules: [], + /** * An attribute of the element responsible for the activation of the payment method (data attribute) */ enableButton: '[data-enable="payment"]', + /** * An attribute of the element responsible for the activation of the Payflow Express (data attribute) */ enableExpress: '[data-enable="express"]', + /** * An attribute of the element responsible for the activation of the Payflow Bml (data attribute) */ enableBml: '[data-enable="bml"]', + /** * An attribute of the element responsible for the activation of the PayPal Bml (data attribute) */ enableBmlPayPal: '[data-enable="bml-api"]', + /** * Templates element selectors */ @@ -43,100 +51,149 @@ define([ elementSelector: 'div.section-config tr[id$="${ $.identifier }"]:first' } }, + /** * Constructor + * + * @param {Object} config + * @param {String} identifier + * @returns {exports.initialize} */ initialize: function (config, identifier) { this.initConfig(config); this.$self = this.createElement(identifier); + return this; }, + /** * Initialization events + * + * @returns {exports.initEvents} */ initEvents: function () { _.each(this.config.events, function (elementEvents, selector) { + var solution = this, selectorButton = solution.$self.find(selector), $self = solution.$self, events = elementEvents; - selectorButton.on(solution.systemEvent, function (event) { + + selectorButton.on(solution.systemEvent, function () { _.each(events, function (elementEvent, name) { + var predicate = elementEvent.predicate, - result = true; + result = true, + + /** + * @param {Function} functionPredicate + */ + predicateCallback = function (functionPredicate) { + result = functionPredicate(solution, predicate.message, predicate.argument); + + if (result) { + $self.trigger(name); + } else { + $self.trigger(predicate.event); + } + }; + if (solution.getValue($(this)) === elementEvent.value) { if (predicate.name) { require([ 'Magento_Paypal/js/predicate/' + predicate.name - ], function (functionPredicate) { - result = functionPredicate(solution, predicate.message, predicate.argument); - if (result) { - $self.trigger(name); - } else { - $self.trigger(predicate.event); - } - }); + ], predicateCallback); } else { $self.trigger(name); } - } + } }, this); - }); + }); }, this); + return this; }, + /** + * @param {Object} $element + * @returns {*} + */ getValue: function ($element) { if ($element.is(':checkbox')) { return $element.prop('checked') ? '1' : '0'; } + return $element.val(); }, + /** * Adding event listeners + * + * @returns {exports.addListeners} */ addListeners: function () { + _.each(this.config.relations, function (rules, targetName) { + var $target = this.createElement(targetName); - _.each(rules, function (rule, name) { - var handler = new Rule({ - name :name, - $target: $target, - $owner: this.$self, - data: { - buttonConfiguration: this.buttonConfiguration, - enableButton: this.enableButton, - enableExpress: this.enableExpress, - enableBml: this.enableBml, - enableBmlPayPal: this.enableBmlPayPal, - solutionsElements: this.solutionsElements, - argument: rule.argument + + _.each(rules, function (instances, instanceName) { + + _.each(instances, function (instance) { + var handler = new Rule({ + name: instanceName, + $target: $target, + $owner: this.$self, + data: { + buttonConfiguration: this.buttonConfiguration, + enableButton: this.enableButton, + enableExpress: this.enableExpress, + enableBml: this.enableBml, + enableBmlPayPal: this.enableBmlPayPal, + solutionsElements: this.solutionsElements, + argument: instance.argument + } + }); + + if (instance.event === ':load') { + this.afterLoadRules.push(handler); + + return; } - }); - if (rule.event === ':load') { - this.afterLoadRules.push(handler); - return; - } - this.$self.on(rule.event, _.bind(handler.apply, handler)); + + this.$self.on(instance.event, _.bind(handler.apply, handler)); + }, this); }, this); }, this); + return this; }, + /** * Create a jQuery element according to selector + * + * @param {String} identifier + * @returns {*} */ createElement: function (identifier) { - if (':self' === identifier) { + if (identifier === ':self') { return this.$self; } - var selector = utils.template(this.templates.elementSelector, {identifier: identifier}); - return $(selector); + + return $(utils.template(this.templates.elementSelector, { + 'identifier': identifier + })); }, + /** * Assign solutions elements + * + * @param {Object} elements + * @returns {exports.setSolutionsElements} */ setSolutionsElements: function (elements) { this.solutionsElements = elements; + return this; } }); diff --git a/app/code/Magento/Paypal/view/adminhtml/web/js/solutions.js b/app/code/Magento/Paypal/view/adminhtml/web/js/solutions.js index b1e124aca387a556069a776721a90d0c529db62a..f92a531e91414da86c78fcc564d8accf96a32191 100644 --- a/app/code/Magento/Paypal/view/adminhtml/web/js/solutions.js +++ b/app/code/Magento/Paypal/view/adminhtml/web/js/solutions.js @@ -3,47 +3,64 @@ * See COPYING.txt for license details. */ define([ - "jquery", - "uiClass", - "Magento_Paypal/js/solution", - "underscore" + 'jquery', + 'uiClass', + 'Magento_Paypal/js/solution', + 'underscore' ], function ($, Class, Solution, _) { - "use strict"; + 'use strict'; + return Class.extend({ defaults: { + /** * Initialized solutions */ solutions: {}, + /** * The elements of created solutions */ solutionsElements: {}, + /** * The selector element responsible for configuration of payment method (CSS class) */ buttonConfiguration: '.button.action-configure' }, + /** * Constructor + * + * @param {Object} config + * @returns {exports.initialize} */ initialize: function (config) { this.initConfig(config) .initSolutions(); + return this; }, + /** * Initialization and configuration solutions + * + * @returns {exports.initSolutions} */ initSolutions: function () { _.each(this.config.solutions, this.addSolution, this); this.initializeSolutions() .wipeButtonsConfiguration(); _.each(this.solutions, this.applicationRules); + return this; }, + /** * The creation and addition of the solution according to the configuration + * + * @param {Object} solution + * @param {String} identifier */ addSolution: function (solution, identifier) { this.solutions[identifier] = new Solution({ @@ -52,6 +69,7 @@ define([ }, identifier); this.solutionsElements[identifier] = this.solutions[identifier].$self; }, + /** * Wiping buttons configuration of the payment method */ @@ -59,16 +77,22 @@ define([ $(this.buttonConfiguration).removeClass('disabled') .removeAttr('disabled'); }, + /** * Application of the rules + * + * @param {Object} solution */ applicationRules: function (solution) { _.each(solution.afterLoadRules, function (rule) { rule.apply(); }); }, + /** * Initialize solutions + * + * @returns {exports.initializeSolutions} */ initializeSolutions: function () { _.each(this.solutions, function (solution) { @@ -76,6 +100,7 @@ define([ .initEvents() .addListeners(); }, this); + return this; } }); diff --git a/app/code/Magento/Paypal/view/frontend/layout/paypal_express_review.xml b/app/code/Magento/Paypal/view/frontend/layout/paypal_express_review.xml index 60e525f463b8f15ad65139be01d9d31017061bd1..695adda9167dd09b65ff1ecc400ed0dcf6e4a951 100644 --- a/app/code/Magento/Paypal/view/frontend/layout/paypal_express_review.xml +++ b/app/code/Magento/Paypal/view/frontend/layout/paypal_express_review.xml @@ -24,7 +24,7 @@ <block class="Magento\Framework\View\Element\Text\ListText" name="paypal.additional.actions"/> <block class="Magento\Paypal\Block\Express\Review\Details" name="paypal.express.review.details" as="details" template="express/review/details.phtml"> <block class="Magento\Framework\View\Element\RendererList" name="checkout.onepage.review.item.renderers" as="renderer.list"/> - <block class="Magento\Checkout\Block\Cart\Totals" name="paypal.express.review.details.totals" as="totals" template="onepage/review/totals.phtml"/> + <block class="Magento\Checkout\Block\Cart\Totals" name="paypal.express.review.details.totals" as="totals" template="checkout/onepage/review/totals.phtml"/> </block> <block class="Magento\CheckoutAgreements\Block\Agreements" name="paypal.express.review.details.agreements" as="agreements" template="Magento_CheckoutAgreements::additional_agreements.phtml"/> </block> diff --git a/app/code/Magento/Paypal/view/frontend/layout/paypal_express_review_details.xml b/app/code/Magento/Paypal/view/frontend/layout/paypal_express_review_details.xml index 01be224c3d0f1d5c88ddce44ae8a42d1a24e8d9a..6594f0a472a8a64261dcf93a9759d7b5dc5361ca 100644 --- a/app/code/Magento/Paypal/view/frontend/layout/paypal_express_review_details.xml +++ b/app/code/Magento/Paypal/view/frontend/layout/paypal_express_review_details.xml @@ -10,7 +10,7 @@ <container name="root"> <block class="Magento\Paypal\Block\Express\Review\Details" name="page.block" template="express/review/details.phtml"> <block class="Magento\Framework\View\Element\RendererList" name="checkout.onepage.review.item.renderers" as="renderer.list"/> - <block class="Magento\Checkout\Block\Cart\Totals" name="paypal.express.review.details.totals" as="totals" template="onepage/review/totals.phtml"/> + <block class="Magento\Checkout\Block\Cart\Totals" name="paypal.express.review.details.totals" as="totals" template="checkout/onepage/review/totals.phtml"/> </block> </container> </layout> diff --git a/app/code/Magento/Paypal/view/frontend/layout/paypal_payflowexpress_review.xml b/app/code/Magento/Paypal/view/frontend/layout/paypal_payflowexpress_review.xml index e41ab21bced7420064dde9f1340cb62e6a2279c6..7fb0e07142bea9020e7d4c361b5e682de0a0c0b4 100644 --- a/app/code/Magento/Paypal/view/frontend/layout/paypal_payflowexpress_review.xml +++ b/app/code/Magento/Paypal/view/frontend/layout/paypal_payflowexpress_review.xml @@ -27,7 +27,7 @@ <block class="Magento\Framework\View\Element\Text\ListText" name="paypal.additional.actions"/> <block class="Magento\Paypal\Block\Express\Review\Details" name="paypal.express.review.details" as="details" template="express/review/details.phtml"> <block class="Magento\Framework\View\Element\RendererList" name="checkout.onepage.review.item.renderers" as="renderer.list"/> - <block class="Magento\Checkout\Block\Cart\Totals" name="paypal.express.review.details.totals" as="totals" template="onepage/review/totals.phtml"/> + <block class="Magento\Checkout\Block\Cart\Totals" name="paypal.express.review.details.totals" as="totals" template="checkout/onepage/review/totals.phtml"/> </block> <block class="Magento\CheckoutAgreements\Block\Agreements" name="paypal.express.review.details.agreements" as="agreements" template="Magento_CheckoutAgreements::additional_agreements.phtml"/> </block> diff --git a/app/code/Magento/Paypal/view/frontend/requirejs-config.js b/app/code/Magento/Paypal/view/frontend/requirejs-config.js index 49f8f54129f620c79eeee168324edeca563a4822..8e6be0da47bd15ba3550a7f04c4668a7165bbc1a 100644 --- a/app/code/Magento/Paypal/view/frontend/requirejs-config.js +++ b/app/code/Magento/Paypal/view/frontend/requirejs-config.js @@ -6,7 +6,6 @@ var config = { map: { '*': { - opcheckoutPaypalIframe: 'Magento_Paypal/js/opcheckout', orderReview: 'Magento_Paypal/order-review', paypalCheckout: 'Magento_Paypal/js/paypal-checkout' } diff --git a/app/code/Magento/Paypal/view/frontend/templates/billing/agreement/view.phtml b/app/code/Magento/Paypal/view/frontend/templates/billing/agreement/view.phtml index c026c3fca5e1f8fe7fbcb4a266d1267fe89d9f0b..835f442c0daadfb6a9127ddba69865d20a9ff235 100644 --- a/app/code/Magento/Paypal/view/frontend/templates/billing/agreement/view.phtml +++ b/app/code/Magento/Paypal/view/frontend/templates/billing/agreement/view.phtml @@ -105,7 +105,7 @@ $relatedOrders = $block->getRelatedOrders(); )); ?> </td> <td data-th="<?php echo $block->escapeHtml(__('Order Total')); ?>" class="col total"> - <?php echo $block->escapeHtml($block->getOrderItemValue($order, 'order_total')); ?> + <?php /* @noEscape */ echo $block->getOrderItemValue($order, 'order_total'); ?> </td> <td data-th="<?php echo $block->escapeHtml(__('Order Status')); ?>" class="col status"> <?php echo $block->escapeHtml($block->getOrderItemValue( diff --git a/app/code/Magento/Checkout/view/frontend/templates/onepage/review/totals.phtml b/app/code/Magento/Paypal/view/frontend/templates/checkout/onepage/review/totals.phtml similarity index 97% rename from app/code/Magento/Checkout/view/frontend/templates/onepage/review/totals.phtml rename to app/code/Magento/Paypal/view/frontend/templates/checkout/onepage/review/totals.phtml index ab70dbab565d4019eb9edbca45eef9ad0a9c6f4e..94aca67913e6b768bfb4200c35327d0315da7fb4 100644 --- a/app/code/Magento/Checkout/view/frontend/templates/onepage/review/totals.phtml +++ b/app/code/Magento/Paypal/view/frontend/templates/checkout/onepage/review/totals.phtml @@ -9,10 +9,6 @@ /** * @see \Magento\Checkout\Block\Cart\Totals */ - -/** - * @removeCandidate - */ ?> <?php if ($block->getTotals()): ?> <?php $_colspan = 3; ?> diff --git a/app/code/Magento/Paypal/view/frontend/templates/express/review.phtml b/app/code/Magento/Paypal/view/frontend/templates/express/review.phtml index 892e8771da7dce8e89e43717a2cf0fbfd5f626da..970607145f06b74c26336fbb743501da84e7e83d 100644 --- a/app/code/Magento/Paypal/view/frontend/templates/express/review.phtml +++ b/app/code/Magento/Paypal/view/frontend/templates/express/review.phtml @@ -84,7 +84,10 @@ </strong> <div class="box-content"> <address> - <?php /* @noEscape */ echo $block->renderAddress($block->getShippingAddress()); ?> + <?php echo $block->escapeHtml( + $block->renderAddress($block->getShippingAddress()), + ['br'] + ); ?> </address> </div> <?php if ($block->getCanEditShippingAddress()): ?> diff --git a/app/code/Magento/Paypal/view/frontend/templates/express/shortcut.phtml b/app/code/Magento/Paypal/view/frontend/templates/express/shortcut.phtml index fa9afa80e5fa8abd356ed6ccfe3d54e80e3638a4..5858917ed8964d3c56b696e78d787f33f411819b 100644 --- a/app/code/Magento/Paypal/view/frontend/templates/express/shortcut.phtml +++ b/app/code/Magento/Paypal/view/frontend/templates/express/shortcut.phtml @@ -43,9 +43,7 @@ if ($block->getConfirmationUrl() || $block->getIsInCatalogProduct()) { { ".paypal-logo.<?php /* @noEscape */ echo $shortcutHtmlId; ?>": { "paypalCheckout": { - "confirmMessage": "<?php /* @noEscape */ echo $block->escapeJsQuote( - $block->getConfirmationMessage() - ); ?>", + "confirmMessage": "<?php /* @noEscape */ echo $block->escapeJsQuote($block->getConfirmationMessage()); ?>", "confirmUrl": "<?php /* @noEscape */ echo !empty($confirmationUrl) ? $confirmationUrl : false; ?>", "isCatalogProduct": "<?php /* @noEscape */ echo !empty($isInCatalogProduct) ? (bool)$isInCatalogProduct : false; diff --git a/app/code/Magento/Paypal/view/frontend/templates/hss/info.phtml b/app/code/Magento/Paypal/view/frontend/templates/hss/info.phtml index 69bf40f9314e3efe35056fa5b0b1bc1915f61c33..c29f82418f83748e61f17632a13f6c891276bf38 100644 --- a/app/code/Magento/Paypal/view/frontend/templates/hss/info.phtml +++ b/app/code/Magento/Paypal/view/frontend/templates/hss/info.phtml @@ -11,7 +11,8 @@ * @see \Magento\Paypal\Block\Payflow\Link\Info */ ?> -<div id="payment_form_<?php /* @noEscape */ echo $block->getMethodCode(); ?>" style="display:none" class="hss items"> +<div id="payment_form_<?php echo $block->escapeHtml($block->getMethodCode()); ?>" + style="display:none" class="hss items"> <?php echo $block->escapeHtml(__( 'You will be required to enter your payment details after you place an order.' )); ?> diff --git a/app/code/Magento/Paypal/view/frontend/templates/onepage.phtml b/app/code/Magento/Paypal/view/frontend/templates/onepage.phtml deleted file mode 100644 index 140ad1a72e4841b5cf65c1ca7d7e981ef15b7c81..0000000000000000000000000000000000000000 --- a/app/code/Magento/Paypal/view/frontend/templates/onepage.phtml +++ /dev/null @@ -1,13 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -?> -<script type="text/x-magento-init"> - { - "#checkoutSteps": { - "opcheckoutPaypalIframe": {} - } - } -</script> \ No newline at end of file diff --git a/app/code/Magento/Paypal/view/frontend/templates/payflowadvanced/info.phtml b/app/code/Magento/Paypal/view/frontend/templates/payflowadvanced/info.phtml index a11a3786c2c2d9f40e13dddb8b5546c6d546016c..252622af0f40880c76412aa4a06e29d066275e05 100644 --- a/app/code/Magento/Paypal/view/frontend/templates/payflowadvanced/info.phtml +++ b/app/code/Magento/Paypal/view/frontend/templates/payflowadvanced/info.phtml @@ -9,7 +9,7 @@ * @var \Magento\Paypal\Block\Payflow\Advanced\Form $block */ ?> -<fieldset id="payment_form_<?php /* @noEscape */ echo $block->getMethodCode(); ?>" style="display:none" +<fieldset id="payment_form_<?php echo $block->escapeHtml($block->getMethodCode()); ?>" style="display:none" class="fieldset payflowadvanced items redirect"> <div> <?php echo $block->escapeHtml(__('You will be required to enter your payment details after you place an order.')); ?> diff --git a/app/code/Magento/Paypal/view/frontend/templates/payflowlink/info.phtml b/app/code/Magento/Paypal/view/frontend/templates/payflowlink/info.phtml index 629141539e2aacd9865c42e85ec04396fc77a999..7296aaabccf4ea15d86f1be1ef07fcf62950b08d 100644 --- a/app/code/Magento/Paypal/view/frontend/templates/payflowlink/info.phtml +++ b/app/code/Magento/Paypal/view/frontend/templates/payflowlink/info.phtml @@ -8,7 +8,7 @@ * @var \Magento\Paypal\Block\Payflow\Link\Form $block */ ?> -<div class="payflowlink items" id="payment_form_<?php /* @noEscape */ echo $block->getMethodCode(); ?>" +<div class="payflowlink items" id="payment_form_<?php echo $block->escapeHtml($block->getMethodCode()); ?>" style="display:none"> <?php echo $block->escapeHtml(__('You will be required to enter your payment details after you place an order.'));?> </div> diff --git a/app/code/Magento/Paypal/view/frontend/templates/payment/form/billing/agreement.phtml b/app/code/Magento/Paypal/view/frontend/templates/payment/form/billing/agreement.phtml index 834a623d65b3f0b59a37ae59e2cab5e67e3e0695..7eb9423ce3be47a5d0528d786e59d898e0eb5aa3 100644 --- a/app/code/Magento/Paypal/view/frontend/templates/payment/form/billing/agreement.phtml +++ b/app/code/Magento/Paypal/view/frontend/templates/payment/form/billing/agreement.phtml @@ -8,7 +8,7 @@ /** * @var \Magento\Paypal\Block\Payment\Form\Billing\Agreement $block */ -$code = $block->getMethodCode(); +$code = $block->escapeHtml($block->getMethodCode()); ?> <div class="field items required" id="payment_form_<?php /* @noEscape */ echo $code; ?>" style="display:none;"> <label for="<?php /* @noEscape */ echo $code; ?>_ba_agreement_id" class="label"> diff --git a/app/code/Magento/Paypal/view/frontend/templates/payment/redirect.phtml b/app/code/Magento/Paypal/view/frontend/templates/payment/redirect.phtml index 5397d9aba46151905be8f46ee6da030f2567c5eb..b10e2f975964f649791f9c5788d57b76819beb17 100644 --- a/app/code/Magento/Paypal/view/frontend/templates/payment/redirect.phtml +++ b/app/code/Magento/Paypal/view/frontend/templates/payment/redirect.phtml @@ -12,7 +12,7 @@ $code = $block->escapeHtml($block->getBillingAgreementCode()); ?> <fieldset class="fieldset paypal items redirect" style="display:none;" - id="payment_form_<?php /* @noEscape */ echo $block->getMethodCode(); ?>"> + id="payment_form_<?php echo $block->escapeHtml($block->getMethodCode()); ?>"> <div><?php echo $block->escapeHtml($block->getRedirectMessage()); ?></div> <?php ?> <?php if ($code): ?> diff --git a/app/code/Magento/Paypal/view/frontend/web/js/opcheckout.js b/app/code/Magento/Paypal/view/frontend/web/js/opcheckout.js deleted file mode 100644 index 416a455c511cb87b9732543fe64ed9c92bdb8d73..0000000000000000000000000000000000000000 --- a/app/code/Magento/Paypal/view/frontend/web/js/opcheckout.js +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*jshint browser:true jquery:true*/ -define([ - "jquery", - "Magento_Checkout/js/opc-order-review", - "jquery/ui" -], function($, opcOrderReview){ - "use strict"; - - $.widget('mage.opcheckoutPaypalIframe', opcOrderReview, { - options: { - review: { - submitContainer: '#checkout-review-submit' - } - }, - - _create: function() { - var events = {}; - events['contentUpdated' + this.options.review.container] = function() { - var paypalIframe = this.element.find(this.options.review.container) - .find('[data-container="paypal-iframe"]'); - if (paypalIframe.length) { - paypalIframe.show(); - $(this.options.review.submitContainer).hide(); - } - }; - this._on(events); - } - }); - - return $.mage.opcheckoutPaypalIframe; -}); \ No newline at end of file diff --git a/app/code/Magento/ProductVideo/view/adminhtml/web/js/video-modal.js b/app/code/Magento/ProductVideo/view/adminhtml/web/js/video-modal.js index f7e0e72de69c1037285fb71a1f7786614ed3f43d..a6e13f100fee793bea8e7acc11d76f3af11ae21a 100644 --- a/app/code/Magento/ProductVideo/view/adminhtml/web/js/video-modal.js +++ b/app/code/Magento/ProductVideo/view/adminhtml/web/js/video-modal.js @@ -4,56 +4,54 @@ */ define([ 'jquery', + 'productGallery', 'jquery/ui', 'Magento_Ui/js/modal/modal', 'mage/translate', 'mage/backend/tree-suggest', 'mage/backend/validation' -], function ($) { +], function ($, productGallery) { 'use strict'; - $.widget('mage.productGallery', - $.mage.productGallery, - { - - /** - * Fired when windget initialization start - * @private - */ - _create: function () { - this._bind(); - }, - - /** - * Bind events - * @private - */ - _bind: function () { - $(this.element).on('click', this.showModal.bind(this)); - $('.gallery.ui-sortable').on('openDialog', $.proxy(this._onOpenDialog, this)); - }, - - /** - * Open dialog for external video - * @private - */ - _onOpenDialog: function (e, imageData) { - - if (imageData['media_type'] !== 'external-video') { - return; - } - this.showModal(); - }, - - /** - * Fired on trigger "openModal" - */ - showModal: function () { - - $('#new-video').modal('openModal'); + $.widget('mage.productGallery', productGallery, { + + /** + * * Fired when widget initialization start + * @private + */ + _create: function () { + this._bind(); + }, + + /** + * Bind events + * @private + */ + _bind: function () { + $(this.element).on('click', this.showModal.bind(this)); + $('.gallery.ui-sortable').on('openDialog', $.proxy(this._onOpenDialog, this)); + }, + + /** + * Open dialog for external video + * @private + */ + _onOpenDialog: function (e, imageData) { + + if (imageData['media_type'] !== 'external-video') { + return; } + this.showModal(); + }, + + /** + * Fired on trigger "openModal" + */ + showModal: function () { + + $('#new-video').modal('openModal'); } - ); + }); return $.mage.productGallery; }); diff --git a/app/code/Magento/ProductVideo/view/frontend/layout/catalog_product_view.xml b/app/code/Magento/ProductVideo/view/frontend/layout/catalog_product_view.xml index 18417e1619da5d56717ce8602c53bf6359d44ac5..59d2ef3e2cd953c3d86661a6ce93b652701d8362 100644 --- a/app/code/Magento/ProductVideo/view/frontend/layout/catalog_product_view.xml +++ b/app/code/Magento/ProductVideo/view/frontend/layout/catalog_product_view.xml @@ -6,10 +6,6 @@ */ --> <page layout="1column" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> - <head> - <link src="Magento_ProductVideo::js/fotorama-add-video-events.js"/> - <link src="Magento_ProductVideo::js/load-player.js"/> - </head> <body> <referenceContainer name="product.info.media"> <block class="Magento\ProductVideo\Block\Product\View\Gallery" name="product.info.media.video" after="product.info.media.image" template="product/view/gallery.phtml"/> diff --git a/app/code/Magento/Reports/Block/Adminhtml/Shopcart/Abandoned/Grid.php b/app/code/Magento/Reports/Block/Adminhtml/Shopcart/Abandoned/Grid.php index 648db357ee120790bda999e2c009e6c21bfdd8ba..99d5ea9e11b1c04d7c0554aa6011dc32347b2fa7 100644 --- a/app/code/Magento/Reports/Block/Adminhtml/Shopcart/Abandoned/Grid.php +++ b/app/code/Magento/Reports/Block/Adminhtml/Shopcart/Abandoned/Grid.php @@ -8,7 +8,7 @@ namespace Magento\Reports\Block\Adminhtml\Shopcart\Abandoned; /** * Adminhtml abandoned shopping carts report grid block * - * @method \Magento\Reports\Model\ResourceModel\Quote\Collection getCollection + * @method \Magento\Reports\Model\ResourceModel\Quote\Collection getCollection() * * @author Magento Core Team <core@magentocommerce.com> * @SuppressWarnings(PHPMD.DepthOfInheritance) diff --git a/app/code/Magento/Reports/etc/acl.xml b/app/code/Magento/Reports/etc/acl.xml index 834fcdc528545f48bf118741349507b57b99a3a2..6d6972fd734122ad48d6c2a52637e1aec0c15a01 100644 --- a/app/code/Magento/Reports/etc/acl.xml +++ b/app/code/Magento/Reports/etc/acl.xml @@ -42,7 +42,7 @@ <resource id="Magento_Reports::downloads" title="Downloads" sortOrder="50" /> </resource> <resource id="Magento_Reports::statistics" title="Statistics" sortOrder="80"> - <resource id="Magento_Reports::statistics_refresh" title="Refresh statistics" sortOrder="10"/> + <resource id="Magento_Reports::statistics_refresh" title="Refresh Statistics" sortOrder="10"/> </resource> </resource> <resource id="Magento_Backend::stores"> diff --git a/app/code/Magento/Reports/i18n/de_DE.csv b/app/code/Magento/Reports/i18n/de_DE.csv index b2bd8ea9e794c94b53e26c11e1327a4b606c2230..c751048ec4fd224e38561e220861b868186431de 100644 --- a/app/code/Magento/Reports/i18n/de_DE.csv +++ b/app/code/Magento/Reports/i18n/de_DE.csv @@ -218,3 +218,10 @@ Hits,Treffer "Refresh Statistics for the Last Day","Aktualisiere Statistik für den letzten Tag" "Are you sure you want to refresh statistics for last day?","Are you sure you want to refresh statistics for last day?" undefined,undefiniert +"Products in Cart","Artikel in den Warenkörbe" +"By Customers","By Customers" +"By Products","By Products" +Refunds,Refunds +"PayPal Settlement","PayPal Settlement" +"Order Count","Order Count" +Bestseller,Bestseller diff --git a/app/code/Magento/Reports/i18n/en_US.csv b/app/code/Magento/Reports/i18n/en_US.csv index 03173d8b230fd1ecb99988c578b422ccfb2d2e4a..3ab4dda3fe68c2f1a4935bd58e955aa6a0e59ad5 100644 --- a/app/code/Magento/Reports/i18n/en_US.csv +++ b/app/code/Magento/Reports/i18n/en_US.csv @@ -219,3 +219,10 @@ Hits,Hits "Refresh Statistics for the Last Day","Refresh Statistics for the Last Day" "Are you sure you want to refresh statistics for last day?","Are you sure you want to refresh statistics for last day?" undefined,undefined +"Products in Cart","Products in Cart" +"By Customers","By Customers" +"By Products","By Products" +Refunds,Refunds +"PayPal Settlement","PayPal Settlement" +"Order Count","Order Count" +Bestseller,Bestseller diff --git a/app/code/Magento/Reports/i18n/es_ES.csv b/app/code/Magento/Reports/i18n/es_ES.csv index 26595380f01b54e41e4dd5bcaec1462c32883200..b025859c92e5165beeda1d478914a66b1346c056 100644 --- a/app/code/Magento/Reports/i18n/es_ES.csv +++ b/app/code/Magento/Reports/i18n/es_ES.csv @@ -218,3 +218,10 @@ Hits,Visitas. "Refresh Statistics for the Last Day","Actualiza estadÃsticas del último dÃa" "Are you sure you want to refresh statistics for last day?","Are you sure you want to refresh statistics for last day?" undefined,Indefinido +"Products in Cart","Products in Cart" +"By Customers","By Customers" +"By Products","By Products" +Refunds,Refunds +"PayPal Settlement","PayPal Settlement" +"Order Count","Order Count" +Bestseller,Bestseller diff --git a/app/code/Magento/Reports/i18n/fr_FR.csv b/app/code/Magento/Reports/i18n/fr_FR.csv index 488b76e42c438ae720f3bef18496d7172d46f4c2..de79ece2ef85639ec67c6598c2215df41e650ca8 100644 --- a/app/code/Magento/Reports/i18n/fr_FR.csv +++ b/app/code/Magento/Reports/i18n/fr_FR.csv @@ -218,3 +218,10 @@ Hits,Clics "Refresh Statistics for the Last Day","Rafraîchir les statistiques de la veille" "Are you sure you want to refresh statistics for last day?","Are you sure you want to refresh statistics for last day?" undefined,indéfini +"Products in Cart","Products in Cart" +"By Customers","By Customers" +"By Products","By Products" +Refunds,Refunds +"PayPal Settlement","PayPal Settlement" +"Order Count","Order Count" +Bestseller,Bestseller diff --git a/app/code/Magento/Reports/i18n/nl_NL.csv b/app/code/Magento/Reports/i18n/nl_NL.csv index d35cbaf6f8596c5018af24d5c16531646d61847f..f8b5dc7e7c8ec45bf3957f663d135f7d4d9bde9b 100644 --- a/app/code/Magento/Reports/i18n/nl_NL.csv +++ b/app/code/Magento/Reports/i18n/nl_NL.csv @@ -218,3 +218,10 @@ Hits,Bezoeken "Refresh Statistics for the Last Day","Statistiek voor de laatste dag verversen" "Are you sure you want to refresh statistics for last day?","Are you sure you want to refresh statistics for last day?" undefined,ongedefinieerd +"Products in Cart","Products in Cart" +"By Customers","By Customers" +"By Products","By Products" +Refunds,Refunds +"PayPal Settlement","PayPal Settlement" +"Order Count","Order Count" +Bestseller,Bestseller diff --git a/app/code/Magento/Reports/i18n/pt_BR.csv b/app/code/Magento/Reports/i18n/pt_BR.csv index 03072fb8a8dc293f50cfd4b97d9109fa33e2d3ea..8ef822b53a296caf6ef2a9fb615bfe6cc44ddbb5 100644 --- a/app/code/Magento/Reports/i18n/pt_BR.csv +++ b/app/code/Magento/Reports/i18n/pt_BR.csv @@ -218,3 +218,10 @@ Hits,CrÃticas "Refresh Statistics for the Last Day","Atualizar estatÃsticas para o Último dia" "Are you sure you want to refresh statistics for last day?","Are you sure you want to refresh statistics for last day?" undefined,indefinido +"Products in Cart","Products in Cart" +"By Customers","By Customers" +"By Products","By Products" +Refunds,Refunds +"PayPal Settlement","PayPal Settlement" +"Order Count","Order Count" +Bestseller,Bestseller diff --git a/app/code/Magento/Reports/i18n/zh_Hans_CN.csv b/app/code/Magento/Reports/i18n/zh_Hans_CN.csv index 3b36163f6b0e33456feaa2170fe8ebc758509d39..bf85485daa4fd388c8325b68833e802ea5e4ff0a 100644 --- a/app/code/Magento/Reports/i18n/zh_Hans_CN.csv +++ b/app/code/Magento/Reports/i18n/zh_Hans_CN.csv @@ -218,3 +218,10 @@ Hits,æç¤º "Refresh Statistics for the Last Day",åˆ·æ–°æ˜¨å¤©çš„çŠ¶æ€ "Are you sure you want to refresh statistics for last day?","Are you sure you want to refresh statistics for last day?" undefined,未定义 +"Products in Cart","Products in Cart" +"By Customers","By Customers" +"By Products","By Products" +Refunds,Refunds +"PayPal Settlement","PayPal Settlement" +"Order Count","Order Count" +Bestseller,Bestseller diff --git a/app/code/Magento/Review/Block/Product/Review.php b/app/code/Magento/Review/Block/Product/Review.php index b553291cfbf8728ae3865831d2fbf5ee10edb176..02764dc5123f1f59535e6865bb9024a361f9d635 100644 --- a/app/code/Magento/Review/Block/Product/Review.php +++ b/app/code/Magento/Review/Block/Product/Review.php @@ -5,13 +5,15 @@ */ namespace Magento\Review\Block\Product; +use Magento\Framework\DataObject\IdentityInterface; +use Magento\Framework\View\Element\Template; /** * Product Review Tab * * @author Magento Core Team <core@magentocommerce.com> */ -class Review extends \Magento\Framework\View\Element\Template +class Review extends Template implements IdentityInterface { /** * Core registry @@ -98,4 +100,14 @@ class Review extends \Magento\Framework\View\Element\Template return $collection->getSize(); } + + /** + * Return unique ID(s) for each object in system + * + * @return array + */ + public function getIdentities() + { + return [\Magento\Review\Model\Review::CACHE_TAG]; + } } diff --git a/app/code/Magento/Review/Model/Rating.php b/app/code/Magento/Review/Model/Rating.php index f9af9a9223ee7bcb99cf2b8b5a50eae449ee8add..f251cf838cc1381e4786a54d40bcbda4db5fe683 100644 --- a/app/code/Magento/Review/Model/Rating.php +++ b/app/code/Magento/Review/Model/Rating.php @@ -5,6 +5,8 @@ */ namespace Magento\Review\Model; +use Magento\Framework\DataObject\IdentityInterface; + /** * Rating model * @@ -18,7 +20,7 @@ namespace Magento\Review\Model; * * @author Magento Core Team <core@magentocommerce.com> */ -class Rating extends \Magento\Framework\Model\AbstractModel +class Rating extends \Magento\Framework\Model\AbstractModel implements IdentityInterface { /** * rating entity codes @@ -161,4 +163,15 @@ class Rating extends \Magento\Framework\Model\AbstractModel { return $this->getResource()->getEntityIdByCode($entityCode); } + + /** + * Return unique ID(s) for each object in system + * + * @return array + */ + public function getIdentities() + { + // clear cache for all reviews + return [Review::CACHE_TAG]; + } } diff --git a/app/code/Magento/Review/Model/Review.php b/app/code/Magento/Review/Model/Review.php index a44da6d2f825851d1e65636140c2a8047a491af2..792babfba4e3203a536054c4555cbc48471edd64 100644 --- a/app/code/Magento/Review/Model/Review.php +++ b/app/code/Magento/Review/Model/Review.php @@ -31,6 +31,11 @@ class Review extends \Magento\Framework\Model\AbstractModel implements IdentityI */ protected $_eventPrefix = 'review'; + /** + * Cache tag + */ + const CACHE_TAG = 'review_block'; + /** * Product entity review code */ diff --git a/app/code/Magento/Review/Test/Unit/Block/Product/ReviewTest.php b/app/code/Magento/Review/Test/Unit/Block/Product/ReviewTest.php new file mode 100644 index 0000000000000000000000000000000000000000..0bc6dd49473e2f59ec96f7313e98a4bdc1f32963 --- /dev/null +++ b/app/code/Magento/Review/Test/Unit/Block/Product/ReviewTest.php @@ -0,0 +1,163 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Review\Test\Unit\Block\Product; + +use Magento\Framework\Registry; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\View\Element\Template\Context; +use Magento\Catalog\Model\Product; +use Magento\Review\Block\Product\Review as ReviewBlock; +use Magento\Review\Model\ResourceModel\Review\Collection; +use Magento\Review\Model\ResourceModel\Review\CollectionFactory; +use Magento\Review\Model\Review; +use Magento\Store\Model\Store; +use Magento\Store\Model\StoreManager; + +/** + * Class ReviewTest + * @package Magento\Review\Test\Unit\Block\Product + */ +class ReviewTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Review\Block\Product\Review + */ + private $block; + + /** + * @var \Magento\Review\Model\ResourceModel\Review\Collection|\PHPUnit_Framework_MockObject_MockObject + */ + private $collection; + + /** + * @var \Magento\Review\Model\ResourceModel\Review\CollectionFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $collectionFactory; + + /** + * @var \Magento\Framework\Registry|\PHPUnit_Framework_MockObject_MockObject + */ + private $registry; + + /** + * @var \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject + */ + private $product; + + /** + * @var \Magento\Store\Model\StoreManager|\PHPUnit_Framework_MockObject_MockObject + */ + private $storeManager; + + /** + * @var \Magento\Store\Model\Store|\PHPUnit_Framework_MockObject_MockObject + */ + private $store; + + protected function setUp() + { + $this->initContextMock(); + $this->initRegistryMock(); + $this->initCollectionMocks(); + + $helper = new ObjectManager($this); + $this->block = $helper->getObject(ReviewBlock::class, [ + 'storeManager' => $this->storeManager, + 'registry' => $this->registry, + 'collectionFactory' => $this->collectionFactory, + ]); + } + + /** + * @covers \Magento\Review\Block\Product\Review::getIdentities() + */ + public function testGetIdentities() + { + static::assertEquals([Review::CACHE_TAG], $this->block->getIdentities()); + } + + /** + * Create mocks for collection and its factory + */ + private function initCollectionMocks() + { + $this->collection = $this->getMockBuilder(Collection::class) + ->disableOriginalConstructor() + ->setMethods(['addStoreFilter', 'addStatusFilter', 'addEntityFilter', 'getSize', '__wakeup']) + ->getMock(); + + $this->collection->expects(static::any()) + ->method('addStoreFilter') + ->willReturnSelf(); + + $this->collection->expects(static::any()) + ->method('addStatusFilter') + ->with(Review::STATUS_APPROVED) + ->willReturnSelf(); + + $this->collection->expects(static::any()) + ->method('addEntityFilter') + ->willReturnSelf(); + + $this->collectionFactory = $this->getMockBuilder(CollectionFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create', '__wakeup']) + ->getMock(); + + $this->collectionFactory->expects(static::once()) + ->method('create') + ->willReturn($this->collection); + } + + /** + * Create mock for registry object + */ + private function initRegistryMock() + { + $this->initProductMock(); + $this->registry = $this->getMockBuilder(Registry::class) + ->disableOriginalConstructor() + ->setMethods(['registry']) + ->getMock(); + + $this->registry->expects(static::once()) + ->method('registry') + ->with('product') + ->willReturn($this->product); + } + + /** + * Create mock object for catalog product + */ + private function initProductMock() + { + $this->product = $this->getMockBuilder(Product::class) + ->disableOriginalConstructor() + ->setMethods(['getId']) + ->getMock(); + } + + /** + * Create mock object for context + */ + private function initContextMock() + { + $this->store = $this->getMockBuilder(Store::class) + ->disableOriginalConstructor() + ->setMethods(['getId', '__wakeup']) + ->getMock(); + + $this->storeManager = $this->getMockBuilder(StoreManager::class) + ->disableOriginalConstructor() + ->setMethods(['getStore', '__wakeup']) + ->getMock(); + + $this->storeManager->expects(static::any()) + ->method('getStore') + ->willReturn($this->store); + } +} diff --git a/app/code/Magento/Review/Test/Unit/Model/RatingTest.php b/app/code/Magento/Review/Test/Unit/Model/RatingTest.php new file mode 100644 index 0000000000000000000000000000000000000000..82db181bedfb56dccf9af12ad10e0ce979e2b7c2 --- /dev/null +++ b/app/code/Magento/Review/Test/Unit/Model/RatingTest.php @@ -0,0 +1,36 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Review\Test\Unit\Model; + +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Review\Model\Review; +use Magento\Review\Model\Rating; + +class RatingTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Review\Model\Rating + */ + private $rating; + + /** + * Init objects needed by tests + */ + protected function setUp() + { + $helper = new ObjectManager($this); + $this->rating = $helper->getObject(Rating::class); + } + + /** + * @covers \Magento\Review\Model\Rating::getIdentities() + * @return void + */ + public function testGetIdentities() + { + static::assertEquals([Review::CACHE_TAG], $this->rating->getIdentities()); + } +} diff --git a/app/code/Magento/Rule/Model/Condition/Product/AbstractProduct.php b/app/code/Magento/Rule/Model/Condition/Product/AbstractProduct.php index c2184950d83e0ee967732fca8ded9c21e03655ac..784a78e5a4caeba2498b2451214d008e1acfd2ad 100644 --- a/app/code/Magento/Rule/Model/Condition/Product/AbstractProduct.php +++ b/app/code/Magento/Rule/Model/Condition/Product/AbstractProduct.php @@ -153,7 +153,7 @@ abstract class AbstractProduct extends \Magento\Rule\Model\Condition\AbstractCon */ protected function _addSpecialAttributes(array &$attributes) { - $attributes['attribute_set_id'] = __('Product Template'); + $attributes['attribute_set_id'] = __('Attribute Set'); $attributes['category_ids'] = __('Category'); } diff --git a/app/code/Magento/Sales/Api/CreditmemoCommentRepositoryInterface.php b/app/code/Magento/Sales/Api/CreditmemoCommentRepositoryInterface.php index d7c1f067cc046997e5fedc2901a803dee5757aa7..bc8cda48f2b216ecb5a5f00a40bd049eb8848a1e 100644 --- a/app/code/Magento/Sales/Api/CreditmemoCommentRepositoryInterface.php +++ b/app/code/Magento/Sales/Api/CreditmemoCommentRepositoryInterface.php @@ -32,10 +32,10 @@ interface CreditmemoCommentRepositoryInterface * * Returns a credit memo comment search results interface. * - * @param \Magento\Framework\Api\SearchCriteria $criteria The search criteria. + * @param \Magento\Framework\Api\SearchCriteria $searchCriteria The search criteria. * @return \Magento\Sales\Api\Data\CreditmemoCommentSearchResultInterface Credit memo comment search results interface. */ - public function getList(\Magento\Framework\Api\SearchCriteria $criteria); + public function getList(\Magento\Framework\Api\SearchCriteria $searchCriteria); /** * Deletes a specified credit memo comment. diff --git a/app/code/Magento/Sales/Api/CreditmemoItemRepositoryInterface.php b/app/code/Magento/Sales/Api/CreditmemoItemRepositoryInterface.php index b322cc7b68f48f26651dfd462ee085be56c5ac40..9921c53a8438537d65923d25cb153ecd11523b04 100644 --- a/app/code/Magento/Sales/Api/CreditmemoItemRepositoryInterface.php +++ b/app/code/Magento/Sales/Api/CreditmemoItemRepositoryInterface.php @@ -27,10 +27,10 @@ interface CreditmemoItemRepositoryInterface /** * Lists credit memo items that match specified search criteria. * - * @param \Magento\Framework\Api\SearchCriteria $criteria The search criteria. + * @param \Magento\Framework\Api\SearchCriteria $searchCriteria The search criteria. * @return \Magento\Sales\Api\Data\CreditmemoItemSearchResultInterface Credit memo item search results interface. */ - public function getList(\Magento\Framework\Api\SearchCriteria $criteria); + public function getList(\Magento\Framework\Api\SearchCriteria $searchCriteria); /** * Deletes a specified credit memo item. diff --git a/app/code/Magento/Sales/Api/CreditmemoManagementInterface.php b/app/code/Magento/Sales/Api/CreditmemoManagementInterface.php index 551f48488869ec27090402719588374cbb88cd0c..b2d7aab6eb09f3facf2f69e589cb9dfe3d7f721c 100644 --- a/app/code/Magento/Sales/Api/CreditmemoManagementInterface.php +++ b/app/code/Magento/Sales/Api/CreditmemoManagementInterface.php @@ -48,12 +48,10 @@ interface CreditmemoManagementInterface * * @param \Magento\Sales\Api\Data\CreditmemoInterface $creditmemo * @param bool $offlineRequested - * @param bool $notifyCustomer * @return \Magento\Sales\Api\Data\CreditmemoInterface */ public function refund( \Magento\Sales\Api\Data\CreditmemoInterface $creditmemo, - $offlineRequested = false, - $notifyCustomer = false + $offlineRequested = false ); } diff --git a/app/code/Magento/Sales/Api/CreditmemoRepositoryInterface.php b/app/code/Magento/Sales/Api/CreditmemoRepositoryInterface.php index 8bb487d732299972229da96cbee376258ab580ad..e1577630215c42a3010af96f96e2fba988cedc39 100644 --- a/app/code/Magento/Sales/Api/CreditmemoRepositoryInterface.php +++ b/app/code/Magento/Sales/Api/CreditmemoRepositoryInterface.php @@ -18,10 +18,10 @@ interface CreditmemoRepositoryInterface /** * Lists credit memos that match specified search criteria. * - * @param \Magento\Framework\Api\SearchCriteria $criteria The search criteria. + * @param \Magento\Framework\Api\SearchCriteria $searchCriteria The search criteria. * @return \Magento\Sales\Api\Data\CreditmemoSearchResultInterface Credit memo search result interface. */ - public function getList(\Magento\Framework\Api\SearchCriteria $criteria); + public function getList(\Magento\Framework\Api\SearchCriteria $searchCriteria); /** * Loads a specified credit memo. diff --git a/app/code/Magento/Sales/Api/InvoiceCommentRepositoryInterface.php b/app/code/Magento/Sales/Api/InvoiceCommentRepositoryInterface.php index f256bb88af2ab2fd0f57dc8c7603c7eea67ebeda..d9d698b987b61f99ef8c0e1f10d429dc92e48300 100644 --- a/app/code/Magento/Sales/Api/InvoiceCommentRepositoryInterface.php +++ b/app/code/Magento/Sales/Api/InvoiceCommentRepositoryInterface.php @@ -17,10 +17,10 @@ interface InvoiceCommentRepositoryInterface /** * Lists invoice comments that match specified search criteria. * - * @param \Magento\Framework\Api\SearchCriteria $criteria The search criteria. + * @param \Magento\Framework\Api\SearchCriteria $searchCriteria The search criteria. * @return \Magento\Sales\Api\Data\InvoiceCommentSearchResultInterface Invoice search result interface. */ - public function getList(\Magento\Framework\Api\SearchCriteria $criteria); + public function getList(\Magento\Framework\Api\SearchCriteria $searchCriteria); /** * Loads a specified invoice comment. diff --git a/app/code/Magento/Sales/Api/InvoiceItemRepositoryInterface.php b/app/code/Magento/Sales/Api/InvoiceItemRepositoryInterface.php index 90ae5cea092df03f80ce641764fe2141fb8211e8..510623d1932ba5258a4233efc2cd244e76150844 100644 --- a/app/code/Magento/Sales/Api/InvoiceItemRepositoryInterface.php +++ b/app/code/Magento/Sales/Api/InvoiceItemRepositoryInterface.php @@ -16,10 +16,10 @@ interface InvoiceItemRepositoryInterface /** * Lists the invoice items that match specified search criteria. * - * @param \Magento\Framework\Api\SearchCriteria $criteria + * @param \Magento\Framework\Api\SearchCriteria $searchCriteria * @return \Magento\Sales\Api\Data\InvoiceItemSearchResultInterface */ - public function getList(\Magento\Framework\Api\SearchCriteria $criteria); + public function getList(\Magento\Framework\Api\SearchCriteria $searchCriteria); /** * Loads a specified invoice item. diff --git a/app/code/Magento/Sales/Api/InvoiceRepositoryInterface.php b/app/code/Magento/Sales/Api/InvoiceRepositoryInterface.php index 0fa5f268be6429360a289232c6e49f0c56f9ae08..9b864ba2ea380b6c77d61fc311b245c370ab7df4 100644 --- a/app/code/Magento/Sales/Api/InvoiceRepositoryInterface.php +++ b/app/code/Magento/Sales/Api/InvoiceRepositoryInterface.php @@ -16,10 +16,10 @@ interface InvoiceRepositoryInterface /** * Lists invoices that match specified search criteria. * - * @param \Magento\Framework\Api\SearchCriteria $criteria The search criteria. + * @param \Magento\Framework\Api\SearchCriteria $searchCriteria The search criteria. * @return \Magento\Sales\Api\Data\InvoiceSearchResultInterface Invoice search result interface. */ - public function getList(\Magento\Framework\Api\SearchCriteria $criteria); + public function getList(\Magento\Framework\Api\SearchCriteria $searchCriteria); /** * Return Invoice object diff --git a/app/code/Magento/Sales/Api/OrderAddressRepositoryInterface.php b/app/code/Magento/Sales/Api/OrderAddressRepositoryInterface.php index 5c3db02774762f0296206d736bb917d1d8078d82..8071ec0c4894c2372adace78d317302fdba3cc31 100644 --- a/app/code/Magento/Sales/Api/OrderAddressRepositoryInterface.php +++ b/app/code/Magento/Sales/Api/OrderAddressRepositoryInterface.php @@ -18,10 +18,10 @@ interface OrderAddressRepositoryInterface /** * Lists order addresses that match specified search criteria. * - * @param \Magento\Framework\Api\SearchCriteria $criteria The search criteria. + * @param \Magento\Framework\Api\SearchCriteria $searchCriteria The search criteria. * @return \Magento\Sales\Api\Data\OrderAddressSearchResultInterface Order address search result interface. */ - public function getList(\Magento\Framework\Api\SearchCriteria $criteria); + public function getList(\Magento\Framework\Api\SearchCriteria $searchCriteria); /** * Loads a specified order address. diff --git a/app/code/Magento/Sales/Api/OrderItemRepositoryInterface.php b/app/code/Magento/Sales/Api/OrderItemRepositoryInterface.php index e1832a09e5568c47194b0e79a32cc1a12b4746fc..6355db859bbcf2fd1ccd223375f5a31c41e888aa 100644 --- a/app/code/Magento/Sales/Api/OrderItemRepositoryInterface.php +++ b/app/code/Magento/Sales/Api/OrderItemRepositoryInterface.php @@ -18,10 +18,10 @@ interface OrderItemRepositoryInterface /** * Lists order items that match specified search criteria. * - * @param \Magento\Framework\Api\SearchCriteria $criteria The search criteria. + * @param \Magento\Framework\Api\SearchCriteria $searchCriteria The search criteria. * @return \Magento\Sales\Api\Data\OrderItemSearchResultInterface Order item search result interface. */ - public function getList(\Magento\Framework\Api\SearchCriteria $criteria); + public function getList(\Magento\Framework\Api\SearchCriteria $searchCriteria); /** * Loads a specified order item. diff --git a/app/code/Magento/Sales/Api/OrderPaymentRepositoryInterface.php b/app/code/Magento/Sales/Api/OrderPaymentRepositoryInterface.php index e4ff2acf54ba627fcdedfa402021460c12e20020..005de16342db398b9e4e8afda49ff6f3ab21f7bd 100644 --- a/app/code/Magento/Sales/Api/OrderPaymentRepositoryInterface.php +++ b/app/code/Magento/Sales/Api/OrderPaymentRepositoryInterface.php @@ -18,10 +18,10 @@ interface OrderPaymentRepositoryInterface /** * Lists order payments that match specified search criteria. * - * @param \Magento\Framework\Api\SearchCriteria $criteria The search criteria. + * @param \Magento\Framework\Api\SearchCriteria $searchCriteria The search criteria. * @return \Magento\Sales\Api\Data\OrderPaymentSearchResultInterface Order payment search result interface. */ - public function getList(\Magento\Framework\Api\SearchCriteria $criteria); + public function getList(\Magento\Framework\Api\SearchCriteria $searchCriteria); /** * Loads a specified order payment. diff --git a/app/code/Magento/Sales/Api/OrderRepositoryInterface.php b/app/code/Magento/Sales/Api/OrderRepositoryInterface.php index d8420ce0da7294626a3567db9f2001ae54bd89ba..50a683b43715356ac8371146f42bae2cadf04e5f 100644 --- a/app/code/Magento/Sales/Api/OrderRepositoryInterface.php +++ b/app/code/Magento/Sales/Api/OrderRepositoryInterface.php @@ -18,10 +18,10 @@ interface OrderRepositoryInterface /** * Lists orders that match specified search criteria. * - * @param \Magento\Framework\Api\SearchCriteria $criteria The search criteria. + * @param \Magento\Framework\Api\SearchCriteria $searchCriteria The search criteria. * @return \Magento\Sales\Api\Data\OrderSearchResultInterface Order search result interface. */ - public function getList(\Magento\Framework\Api\SearchCriteria $criteria); + public function getList(\Magento\Framework\Api\SearchCriteria $searchCriteria); /** * Loads a specified order. diff --git a/app/code/Magento/Sales/Api/OrderStatusHistoryRepositoryInterface.php b/app/code/Magento/Sales/Api/OrderStatusHistoryRepositoryInterface.php index b99bf0dc2c729d7f97aef8560a7e0511769a4fb7..743f9aaa734e94ddc8a867071a40423685886294 100644 --- a/app/code/Magento/Sales/Api/OrderStatusHistoryRepositoryInterface.php +++ b/app/code/Magento/Sales/Api/OrderStatusHistoryRepositoryInterface.php @@ -21,10 +21,10 @@ interface OrderStatusHistoryRepositoryInterface /** * Lists order status history comments that match specified search criteria. * - * @param \Magento\Framework\Api\SearchCriteria $criteria The search criteria. + * @param \Magento\Framework\Api\SearchCriteria $searchCriteria The search criteria. * @return \Magento\Sales\Api\Data\OrderStatusHistorySearchResultInterface Order status history search result interface. */ - public function getList(\Magento\Framework\Api\SearchCriteria $criteria); + public function getList(\Magento\Framework\Api\SearchCriteria $searchCriteria); /** * Loads a specified order status comment. diff --git a/app/code/Magento/Sales/Api/ShipmentCommentRepositoryInterface.php b/app/code/Magento/Sales/Api/ShipmentCommentRepositoryInterface.php index e6605c9c5dd24267466d846eb82fd2a3e342d91a..9ca3bb336f268c515e91d4365fc2b9c01056bd14 100644 --- a/app/code/Magento/Sales/Api/ShipmentCommentRepositoryInterface.php +++ b/app/code/Magento/Sales/Api/ShipmentCommentRepositoryInterface.php @@ -17,10 +17,10 @@ interface ShipmentCommentRepositoryInterface /** * Lists shipment comments that match specific search criteria. * - * @param \Magento\Framework\Api\SearchCriteria $criteria The search criteria. + * @param \Magento\Framework\Api\SearchCriteria $searchCriteria The search criteria. * @return \Magento\Sales\Api\Data\ShipmentCommentSearchResultInterface Shipment comment search result interface. */ - public function getList(\Magento\Framework\Api\SearchCriteria $criteria); + public function getList(\Magento\Framework\Api\SearchCriteria $searchCriteria); /** * Loads a specified shipment comment. diff --git a/app/code/Magento/Sales/Api/ShipmentItemRepositoryInterface.php b/app/code/Magento/Sales/Api/ShipmentItemRepositoryInterface.php index 0db3adabf885cdd1fcf0c4059d19958151554530..5d2d3946a91971c23256a720b0258213ae1bcb58 100644 --- a/app/code/Magento/Sales/Api/ShipmentItemRepositoryInterface.php +++ b/app/code/Magento/Sales/Api/ShipmentItemRepositoryInterface.php @@ -17,10 +17,10 @@ interface ShipmentItemRepositoryInterface /** * Lists shipment items that match specified search criteria. * - * @param \Magento\Framework\Api\SearchCriteria $criteria The search criteria. + * @param \Magento\Framework\Api\SearchCriteria $searchCriteria The search criteria. * @return \Magento\Sales\Api\Data\ShipmentItemSearchResultInterface Shipment item search result interface. */ - public function getList(\Magento\Framework\Api\SearchCriteria $criteria); + public function getList(\Magento\Framework\Api\SearchCriteria $searchCriteria); /** * Loads a specified shipment item. diff --git a/app/code/Magento/Sales/Api/ShipmentRepositoryInterface.php b/app/code/Magento/Sales/Api/ShipmentRepositoryInterface.php index 1cfa85d87e66facb2affe05c8541a8a96982c68f..858347a6f166d47255572bc92064924c3a42efc7 100644 --- a/app/code/Magento/Sales/Api/ShipmentRepositoryInterface.php +++ b/app/code/Magento/Sales/Api/ShipmentRepositoryInterface.php @@ -17,10 +17,10 @@ interface ShipmentRepositoryInterface /** * Lists shipments that match specified search criteria. * - * @param \Magento\Framework\Api\SearchCriteria $criteria The search criteria. + * @param \Magento\Framework\Api\SearchCriteria $searchCriteria The search criteria. * @return \Magento\Sales\Api\Data\ShipmentSearchResultInterface Shipment search results interface. */ - public function getList(\Magento\Framework\Api\SearchCriteria $criteria); + public function getList(\Magento\Framework\Api\SearchCriteria $searchCriteria); /** * Loads a specified shipment. diff --git a/app/code/Magento/Sales/Api/ShipmentTrackRepositoryInterface.php b/app/code/Magento/Sales/Api/ShipmentTrackRepositoryInterface.php index 5d7817b0c828d997707e9b826c2a7890aa305bc2..ada64b54d862fbabdb3a514e03a73b29172be1e9 100644 --- a/app/code/Magento/Sales/Api/ShipmentTrackRepositoryInterface.php +++ b/app/code/Magento/Sales/Api/ShipmentTrackRepositoryInterface.php @@ -17,10 +17,10 @@ interface ShipmentTrackRepositoryInterface /** * Lists shipment tracks that match specified search criteria. * - * @param \Magento\Framework\Api\SearchCriteria $criteria The search criteria. + * @param \Magento\Framework\Api\SearchCriteria $searchCriteria The search criteria. * @return \Magento\Sales\Api\Data\ShipmentTrackSearchResultInterface Shipment track search result interface. */ - public function getList(\Magento\Framework\Api\SearchCriteria $criteria); + public function getList(\Magento\Framework\Api\SearchCriteria $searchCriteria); /** * Loads a specified shipment track. diff --git a/app/code/Magento/Sales/Api/TransactionRepositoryInterface.php b/app/code/Magento/Sales/Api/TransactionRepositoryInterface.php index 7a256e7deaf7ccc55bfd07ec8baf8625d17529e1..be5315f1329cc64f18ca3a2e65459e33d62bc6e5 100644 --- a/app/code/Magento/Sales/Api/TransactionRepositoryInterface.php +++ b/app/code/Magento/Sales/Api/TransactionRepositoryInterface.php @@ -16,10 +16,10 @@ interface TransactionRepositoryInterface /** * Lists transactions that match specified search criteria. * - * @param \Magento\Framework\Api\SearchCriteria $criteria The search criteria. + * @param \Magento\Framework\Api\SearchCriteria $searchCriteria The search criteria. * @return \Magento\Sales\Api\Data\TransactionSearchResultInterface Transaction search result interface. */ - public function getList(\Magento\Framework\Api\SearchCriteria $criteria); + public function getList(\Magento\Framework\Api\SearchCriteria $searchCriteria); /** * Loads a specified transaction. diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Form/Address.php b/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Form/Address.php index 1ee0386f871101b753d45cfd6814540cae15016c..4af19b69b136158103c391443fce0e8cc37163c0 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Form/Address.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Form/Address.php @@ -160,8 +160,8 @@ class Address extends \Magento\Sales\Block\Adminhtml\Order\Create\Form\AbstractF ->setConditionType('eq') ->create(); $this->searchCriteriaBuilder->addFilters([$filter]); - $criteria = $this->searchCriteriaBuilder->create(); - $result = $this->addressService->getList($criteria); + $searchCriteria = $this->searchCriteriaBuilder->create(); + $result = $this->addressService->getList($searchCriteria); return $result->getItems(); } return []; diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/AddressSave.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/AddressSave.php index e3d15fd93cdd6765c1c3aa3739603db07ac23f95..b10329e70d376ff7be228e65a9d99f5c686f42e0 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/AddressSave.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/AddressSave.php @@ -16,13 +16,20 @@ class AddressSave extends \Magento\Sales\Controller\Adminhtml\Order public function execute() { $addressId = $this->getRequest()->getParam('address_id'); - $address = $this->_objectManager->create('Magento\Sales\Model\Order\Address')->load($addressId); + /** @var $address \Magento\Sales\Api\Data\OrderAddressInterface|\Magento\Sales\Model\Order\Address */ + $address = $this->_objectManager->create('Magento\Sales\Api\Data\OrderAddressInterface')->load($addressId); $data = $this->getRequest()->getPostValue(); $resultRedirect = $this->resultRedirectFactory->create(); if ($data && $address->getId()) { $address->addData($data); try { $address->save(); + $this->_eventManager->dispatch( + 'admin_sales_order_address_update', + [ + 'order_id' => $address->getParentId() + ] + ); $this->messageManager->addSuccess(__('You updated the order address.')); return $resultRedirect->setPath('sales/*/view', ['order_id' => $address->getParentId()]); } catch (\Magento\Framework\Exception\LocalizedException $e) { diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/CreditmemoLoader.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/CreditmemoLoader.php index cf69855c1489cf99d438b9892f7b0b38da97870c..5918bdb0326b94b22357a02afa89e3551b245ae4 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/CreditmemoLoader.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/CreditmemoLoader.php @@ -14,14 +14,14 @@ use \Magento\Sales\Model\Order\CreditmemoFactory; * Class CreditmemoLoader * * @package Magento\Sales\Controller\Adminhtml\Order - * @method CreditmemoLoader setCreditmemoId - * @method CreditmemoLoader setCreditmemo - * @method CreditmemoLoader setInvoiceId - * @method CreditmemoLoader setOrderId - * @method int getCreditmemoId - * @method string getCreditmemo - * @method int getInvoiceId - * @method int getOrderId + * @method CreditmemoLoader setCreditmemoId($id) + * @method CreditmemoLoader setCreditmemo($creditMemo) + * @method CreditmemoLoader setInvoiceId($id) + * @method CreditmemoLoader setOrderId($id) + * @method int getCreditmemoId() + * @method string getCreditmemo() + * @method int getInvoiceId() + * @method int getOrderId() */ class CreditmemoLoader extends DataObject { diff --git a/app/code/Magento/Sales/Model/Download.php b/app/code/Magento/Sales/Model/Download.php index be8054315ea9ccf7ffaa42e4ffeaf86864f571bf..0f2649d7de582651d8ab65af4866b2cca21139d4 100644 --- a/app/code/Magento/Sales/Model/Download.php +++ b/app/code/Magento/Sales/Model/Download.php @@ -6,6 +6,7 @@ namespace Magento\Sales\Model; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\Exception\LocalizedException; class Download { @@ -29,19 +30,27 @@ class Download */ protected $_fileFactory; + /** + * @var string + */ + protected $rootDirBasePath; + /** * @param \Magento\Framework\Filesystem $filesystem * @param \Magento\MediaStorage\Helper\File\Storage\Database $fileStorageDatabase * @param \Magento\MediaStorage\Model\File\Storage\DatabaseFactory $storageDatabaseFactory * @param \Magento\Framework\App\Response\Http\FileFactory $fileFactory + * @param string $rootDirBasePath */ public function __construct( \Magento\Framework\Filesystem $filesystem, \Magento\MediaStorage\Helper\File\Storage\Database $fileStorageDatabase, \Magento\MediaStorage\Model\File\Storage\DatabaseFactory $storageDatabaseFactory, - \Magento\Framework\App\Response\Http\FileFactory $fileFactory + \Magento\Framework\App\Response\Http\FileFactory $fileFactory, + $rootDirBasePath = DirectoryList::MEDIA ) { - $this->_rootDir = $filesystem->getDirectoryWrite(DirectoryList::ROOT); + $this->rootDirBasePath = $rootDirBasePath; + $this->_rootDir = $filesystem->getDirectoryWrite($this->rootDirBasePath); $this->_fileStorageDatabase = $fileStorageDatabase; $this->_storageDatabaseFactory = $storageDatabaseFactory; $this->_fileFactory = $fileFactory; @@ -57,18 +66,19 @@ class Download public function downloadFile($info) { $relativePath = $info['order_path']; - if ($this->_isCanProcessed($relativePath)) { + if (!$this->_isCanProcessed($relativePath)) { //try get file from quote $relativePath = $info['quote_path']; - if ($this->_isCanProcessed($relativePath)) { - throw new \Exception(); + if (!$this->_isCanProcessed($relativePath)) { + throw new LocalizedException( + __('Path "%1" is not part of allowed directory "%2"', $relativePath, $this->rootDirBasePath) + ); } } - $this->_fileFactory->create( $info['title'], ['value' => $this->_rootDir->getRelativePath($relativePath), 'type' => 'filename'], - DirectoryList::ROOT + $this->rootDirBasePath ); } @@ -79,32 +89,28 @@ class Download protected function _isCanProcessed($relativePath) { $filePath = $this->_rootDir->getAbsolutePath($relativePath); - return (!$this->_rootDir->isFile( - $relativePath - ) || !$this->_rootDir->isReadable( - $relativePath - )) && !$this->_processDatabaseFile( - $filePath - ); + return (strpos($this->_rootDir->getDriver()->getRealPath($filePath), $relativePath) !== false + && $this->_rootDir->isFile($relativePath) && $this->_rootDir->isReadable($relativePath)) + || $this->_processDatabaseFile($filePath, $relativePath); } /** * Check file in database storage if needed and place it on file system * * @param string $filePath + * @param string $relativePath * @return bool */ - protected function _processDatabaseFile($filePath) + protected function _processDatabaseFile($filePath, $relativePath) { if (!$this->_fileStorageDatabase->checkDbUsage()) { return false; } - $relativePath = $this->_fileStorageDatabase->getMediaRelativePath($filePath); $file = $this->_storageDatabaseFactory->create()->loadByFilename($relativePath); if (!$file->getId()) { return false; } - $stream = $this->_rootDir->openFile($filePath, 'w+'); + $stream = $this->_rootDir->openFile($relativePath, 'w+'); $stream->lock(); $stream->write($filePath, $file->getContent()); $stream->unlock(); diff --git a/app/code/Magento/Sales/Model/Order/AddressRepository.php b/app/code/Magento/Sales/Model/Order/AddressRepository.php index 2e4c9df86fa22c97348f932c07b1d8dc41d46d46..ec5a39bce3b6c290d88bf0569d5af6d8d5082ba5 100644 --- a/app/code/Magento/Sales/Model/Order/AddressRepository.php +++ b/app/code/Magento/Sales/Model/Order/AddressRepository.php @@ -14,6 +14,8 @@ use Magento\Framework\Exception\InputException; /** * Repository class for @see \Magento\Sales\Api\Data\OrderAddressInterface + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class AddressRepository implements \Magento\Sales\Api\OrderAddressRepositoryInterface { @@ -77,24 +79,24 @@ class AddressRepository implements \Magento\Sales\Api\OrderAddressRepositoryInte /** * Find order addresses by criteria. * - * @param \Magento\Framework\Api\SearchCriteria $criteria + * @param \Magento\Framework\Api\SearchCriteria $searchCriteria * @return \Magento\Sales\Api\Data\OrderAddressInterface[] */ - public function getList(\Magento\Framework\Api\SearchCriteria $criteria) + public function getList(\Magento\Framework\Api\SearchCriteria $searchCriteria) { //@TODO: fix search logic /** @var \Magento\Sales\Api\Data\OrderAddressSearchResultInterface $searchResult */ $searchResult = $this->searchResultFactory->create(); - foreach ($criteria->getFilterGroups() as $filterGroup) { + foreach ($searchCriteria->getFilterGroups() as $filterGroup) { foreach ($filterGroup->getFilters() as $filter) { $condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq'; $searchResult->addFieldToFilter($filter->getField(), [$condition => $filter->getValue()]); } } - $searchResult->setCurPage($criteria->getCurrentPage()); - $searchResult->setPageSize($criteria->getPageSize()); + $searchResult->setCurPage($searchCriteria->getCurrentPage()); + $searchResult->setPageSize($searchCriteria->getPageSize()); return $searchResult; } diff --git a/app/code/Magento/Sales/Model/Order/CreditmemoRepository.php b/app/code/Magento/Sales/Model/Order/CreditmemoRepository.php index 200a57a73fff5804e589b9688d1ecc443db061e1..c9621a7e668d34ec8ae53db42e0051c8e4e59c07 100644 --- a/app/code/Magento/Sales/Model/Order/CreditmemoRepository.php +++ b/app/code/Magento/Sales/Model/Order/CreditmemoRepository.php @@ -87,21 +87,21 @@ class CreditmemoRepository implements \Magento\Sales\Api\CreditmemoRepositoryInt /** * Lists credit memos that match specified search criteria. * - * @param \Magento\Framework\Api\SearchCriteria $criteria The search criteria. + * @param \Magento\Framework\Api\SearchCriteria $searchCriteria The search criteria. * @return \Magento\Sales\Api\Data\CreditmemoSearchResultInterface Credit memo search result interface. */ - public function getList(\Magento\Framework\Api\SearchCriteria $criteria) + public function getList(\Magento\Framework\Api\SearchCriteria $searchCriteria) { /** @var \Magento\Sales\Api\Data\CreditmemoSearchResultInterface $searchResult */ $searchResult = $this->searchResultFactory->create(); - foreach ($criteria->getFilterGroups() as $filterGroup) { + foreach ($searchCriteria->getFilterGroups() as $filterGroup) { foreach ($filterGroup->getFilters() as $filter) { $condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq'; $searchResult->addFieldToFilter($filter->getField(), [$condition => $filter->getValue()]); } } - $searchResult->setCurPage($criteria->getCurrentPage()); - $searchResult->setPageSize($criteria->getPageSize()); + $searchResult->setCurPage($searchCriteria->getCurrentPage()); + $searchResult->setPageSize($searchCriteria->getPageSize()); return $searchResult; } diff --git a/app/code/Magento/Sales/Model/Order/InvoiceRepository.php b/app/code/Magento/Sales/Model/Order/InvoiceRepository.php index 04275723bda95706d78cf85f717bb195dbbbf6ff..6ac147108bb73a6da51fb8aeb22f803ef63c151c 100644 --- a/app/code/Magento/Sales/Model/Order/InvoiceRepository.php +++ b/app/code/Magento/Sales/Model/Order/InvoiceRepository.php @@ -83,21 +83,21 @@ class InvoiceRepository implements InvoiceRepositoryInterface /** * Find entities by criteria * - * @param \Magento\Framework\Api\SearchCriteria $criteria + * @param \Magento\Framework\Api\SearchCriteria $searchCriteria * @return \Magento\Sales\Api\Data\InvoiceInterface[] */ - public function getList(\Magento\Framework\Api\SearchCriteria $criteria) + public function getList(\Magento\Framework\Api\SearchCriteria $searchCriteria) { /** @var \Magento\Sales\Model\ResourceModel\Order\Invoice\Collection $collection */ $collection = $this->searchResultFactory->create(); - foreach ($criteria->getFilterGroups() as $filterGroup) { + foreach ($searchCriteria->getFilterGroups() as $filterGroup) { foreach ($filterGroup->getFilters() as $filter) { $condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq'; $collection->addFieldToFilter($filter->getField(), [$condition => $filter->getValue()]); } } - $collection->setCurPage($criteria->getCurrentPage()); - $collection->setPageSize($criteria->getPageSize()); + $collection->setCurPage($searchCriteria->getCurrentPage()); + $collection->setPageSize($searchCriteria->getPageSize()); return $collection; } diff --git a/app/code/Magento/Sales/Model/Order/ItemRepository.php b/app/code/Magento/Sales/Model/Order/ItemRepository.php index 776b862828658da8092d992697e790599941c770..983a87834fabfde0ba471c20c2a42ebbc6ca5b5c 100644 --- a/app/code/Magento/Sales/Model/Order/ItemRepository.php +++ b/app/code/Magento/Sales/Model/Order/ItemRepository.php @@ -114,16 +114,16 @@ class ItemRepository implements OrderItemRepositoryInterface /** * Find entities by criteria * - * @param SearchCriteria $criteria + * @param SearchCriteria $searchCriteria * @return OrderItemInterface[] */ - public function getList(SearchCriteria $criteria) + public function getList(SearchCriteria $searchCriteria) { /** @var OrderItemSearchResultInterface $searchResult */ $searchResult = $this->searchResultFactory->create(); - $searchResult->setSearchCriteria($criteria); + $searchResult->setSearchCriteria($searchCriteria); - foreach ($criteria->getFilterGroups() as $filterGroup) { + foreach ($searchCriteria->getFilterGroups() as $filterGroup) { foreach ($filterGroup->getFilters() as $filter) { $condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq'; $searchResult->addFieldToFilter($filter->getField(), [$condition => $filter->getValue()]); diff --git a/app/code/Magento/Sales/Model/Order/Payment.php b/app/code/Magento/Sales/Model/Order/Payment.php index 690bde68d5c575ece27f56d68165d1ccf31bc7d5..83cf0853fdab41721a8bde05cdfc46426fc6cd94 100644 --- a/app/code/Magento/Sales/Model/Order/Payment.php +++ b/app/code/Magento/Sales/Model/Order/Payment.php @@ -629,7 +629,7 @@ class Payment extends Info implements OrderPaymentInterface $this->getOrder()->getId() ); if ($captureTxn) { - $this->setParentTransactionId($captureTxn->getTxnId()); + $this->setTransactionIdsForRefund($captureTxn); } $this->setShouldCloseParentTransaction(true); // TODO: implement multiple refunds per capture @@ -638,10 +638,7 @@ class Payment extends Info implements OrderPaymentInterface $this->getOrder()->getStoreId() ); $this->setRefundTransactionId($invoice->getTransactionId()); - $gateway->refund( - $this, - $baseAmountToRefund - ); + $gateway->refund($this, $baseAmountToRefund); $creditmemo->setTransactionId($this->getLastTransId()); } catch (\Magento\Framework\Exception\LocalizedException $e) { @@ -1263,16 +1260,8 @@ class Payment extends Info implements OrderPaymentInterface */ public function isCaptureFinal($amountToCapture) { - $amountPaid = $this->formatAmount($this->getBaseAmountPaid(), true); - $amountToCapture = $this->formatAmount($amountToCapture, true); - $orderGrandTotal = $this->formatAmount($this->getOrder()->getBaseGrandTotal(), true); - if ($orderGrandTotal == $amountPaid + $amountToCapture) { - if (false !== $this->getShouldCloseParentTransaction()) { - $this->setShouldCloseParentTransaction(true); - } - return true; - } - return false; + $total = $this->getOrder()->getTotalDue(); + return $this->formatAmount($total, true) == $this->formatAmount($amountToCapture, true); } /** @@ -2414,5 +2403,24 @@ class Payment extends Info implements OrderPaymentInterface return (bool)$this->getData('should_close_parent_transaction'); } + /** + * Set payment parent transaction id and current transaction id if it not set + * @param Transaction $transaction + * @return void + */ + private function setTransactionIdsForRefund(Transaction $transaction) + { + if (!$this->getTransactionId()) { + $this->setTransactionId( + $this->transactionManager->generateTransactionId( + $this, + Transaction::TYPE_REFUND, + $transaction + ) + ); + } + $this->setParentTransactionId($transaction->getTxnId()); + } + //@codeCoverageIgnoreEnd } diff --git a/app/code/Magento/Sales/Model/Order/Payment/Operations/CaptureOperation.php b/app/code/Magento/Sales/Model/Order/Payment/Operations/CaptureOperation.php index 590422b153130b34b55dddb6f1777fd206ec4149..3bb13ccca2bf88b3d99cce521f59e7e0b6fb2126 100644 --- a/app/code/Magento/Sales/Model/Order/Payment/Operations/CaptureOperation.php +++ b/app/code/Magento/Sales/Model/Order/Payment/Operations/CaptureOperation.php @@ -37,13 +37,6 @@ class CaptureOperation extends AbstractOperation $amountToCapture = $payment->formatAmount($invoice->getBaseGrandTotal()); $order = $payment->getOrder(); - // prepare parent transaction and its amount - $paidWorkaround = 0; - if (!$invoice->wasPayCalled()) { - $paidWorkaround = (double)$amountToCapture; - } - $payment->isCaptureFinal($paidWorkaround); - $payment->setTransactionId( $this->transactionManager->generateTransactionId( $payment, @@ -72,38 +65,48 @@ class CaptureOperation extends AbstractOperation ); } - if (!$invoice->getIsPaid()) { - // attempt to capture: this can trigger "is_transaction_pending" - $method = $payment->getMethodInstance(); - $method->setStore( - $order->getStoreId() + if ($invoice->getIsPaid()) { + throw new \Magento\Framework\Exception\LocalizedException( + __('The transaction "%1" cannot be captured yet.', $invoice->getTransactionId()) ); - //TODO replace for sale usage - $method->capture($payment, $amountToCapture); + } + + // attempt to capture: this can trigger "is_transaction_pending" + $method = $payment->getMethodInstance(); + $method->setStore( + $order->getStoreId() + ); + //TODO replace for sale usage + $method->capture($payment, $amountToCapture); - $transactionBuilder = $this->transactionBuilder->setPayment($payment); - $transactionBuilder->setOrder($order); - $transactionBuilder->setFailSafe(true); - $transactionBuilder->setTransactionId($payment->getTransactionId()); - $transactionBuilder->setAdditionalInformation($payment->getTransactionAdditionalInfo()); - $transactionBuilder->setSalesDocument($invoice); - $transaction = $transactionBuilder->build(Transaction::TYPE_CAPTURE); + // prepare parent transaction and its amount + $paidWorkaround = 0; + if (!$invoice->wasPayCalled()) { + $paidWorkaround = (double)$amountToCapture; + } + if ($payment->isCaptureFinal($paidWorkaround)) { + $payment->setShouldCloseParentTransaction(true); + } - $message = $this->stateCommand->execute($payment, $amountToCapture, $order); - if ($payment->getIsTransactionPending()) { - $invoice->setIsPaid(false); - } else { - $invoice->setIsPaid(true); - $this->updateTotals($payment, ['base_amount_paid_online' => $amountToCapture]); - } - $message = $payment->prependMessage($message); - $payment->addTransactionCommentsToOrder($transaction, $message); - $invoice->setTransactionId($payment->getLastTransId()); + $transactionBuilder = $this->transactionBuilder->setPayment($payment); + $transactionBuilder->setOrder($order); + $transactionBuilder->setFailSafe(true); + $transactionBuilder->setTransactionId($payment->getTransactionId()); + $transactionBuilder->setAdditionalInformation($payment->getTransactionAdditionalInfo()); + $transactionBuilder->setSalesDocument($invoice); + $transaction = $transactionBuilder->build(Transaction::TYPE_CAPTURE); - return $payment; + $message = $this->stateCommand->execute($payment, $amountToCapture, $order); + if ($payment->getIsTransactionPending()) { + $invoice->setIsPaid(false); + } else { + $invoice->setIsPaid(true); + $this->updateTotals($payment, ['base_amount_paid_online' => $amountToCapture]); } - throw new \Magento\Framework\Exception\LocalizedException( - __('The transaction "%1" cannot be captured yet.', $invoice->getTransactionId()) - ); + $message = $payment->prependMessage($message); + $payment->addTransactionCommentsToOrder($transaction, $message); + $invoice->setTransactionId($payment->getLastTransId()); + + return $payment; } } diff --git a/app/code/Magento/Sales/Model/Order/Payment/Operations/RegisterCaptureNotificationOperation.php b/app/code/Magento/Sales/Model/Order/Payment/Operations/RegisterCaptureNotificationOperation.php index 7c5e892ce035878f1ae41ee5c55d89c0bab8056c..8b7759b79a680079aadee62d56279e59a267cc2d 100644 --- a/app/code/Magento/Sales/Model/Order/Payment/Operations/RegisterCaptureNotificationOperation.php +++ b/app/code/Magento/Sales/Model/Order/Payment/Operations/RegisterCaptureNotificationOperation.php @@ -44,6 +44,7 @@ class RegisterCaptureNotificationOperation extends AbstractOperation $invoice->setOrder($order); $order->addRelatedObject($invoice); $payment->setCreatedInvoice($invoice); + $payment->setShouldCloseParentTransaction(true); } else { $payment->setIsFraudDetected(!$skipFraudDetection); $this->updateTotals($payment, ['base_amount_paid_online' => $amount]); diff --git a/app/code/Magento/Sales/Model/Order/Payment/Repository.php b/app/code/Magento/Sales/Model/Order/Payment/Repository.php index 2517c4b9adbcc1aca5b648f7ad4974645624220c..ef3fb08b5daa1b4980a9ef2a34fd43bcd59fcd6b 100644 --- a/app/code/Magento/Sales/Model/Order/Payment/Repository.php +++ b/app/code/Magento/Sales/Model/Order/Payment/Repository.php @@ -47,21 +47,21 @@ class Repository implements OrderPaymentRepositoryInterface /** * Lists order payments that match specified search criteria. * - * @param \Magento\Framework\Api\SearchCriteria $criteria The search criteria. + * @param \Magento\Framework\Api\SearchCriteria $searchCriteria The search criteria. * @return \Magento\Sales\Api\Data\OrderPaymentSearchResultInterface Order payment search result interface. */ - public function getList(\Magento\Framework\Api\SearchCriteria $criteria) + public function getList(\Magento\Framework\Api\SearchCriteria $searchCriteria) { /** @var \Magento\Sales\Model\ResourceModel\Order\Payment\Collection $collection */ $collection = $this->searchResultFactory->create(); - foreach ($criteria->getFilterGroups() as $filterGroup) { + foreach ($searchCriteria->getFilterGroups() as $filterGroup) { foreach ($filterGroup->getFilters() as $filter) { $condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq'; $collection->addFieldToFilter($filter->getField(), [$condition => $filter->getValue()]); } } - $collection->setCurPage($criteria->getCurrentPage()); - $collection->setPageSize($criteria->getPageSize()); + $collection->setCurPage($searchCriteria->getCurrentPage()); + $collection->setPageSize($searchCriteria->getPageSize()); return $collection; } diff --git a/app/code/Magento/Sales/Model/Order/Payment/Transaction/Repository.php b/app/code/Magento/Sales/Model/Order/Payment/Transaction/Repository.php index 051ab5401d59fda4ded3f0af78bab2869e526617..a3550d6073ecd8f5040e230c5f350ea4ec0eb2ab 100644 --- a/app/code/Magento/Sales/Model/Order/Payment/Transaction/Repository.php +++ b/app/code/Magento/Sales/Model/Order/Payment/Transaction/Repository.php @@ -185,18 +185,18 @@ class Repository implements TransactionRepositoryInterface /** * {@inheritdoc} */ - public function getList(\Magento\Framework\Api\SearchCriteria $criteria) + public function getList(\Magento\Framework\Api\SearchCriteria $searchCriteria) { /** @var TransactionResource\Collection $collection */ $collection = $this->searchResultFactory->create(); - foreach ($criteria->getFilterGroups() as $filterGroup) { + foreach ($searchCriteria->getFilterGroups() as $filterGroup) { foreach ($filterGroup->getFilters() as $filter) { $condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq'; $collection->addFieldToFilter($filter->getField(), [$condition => $filter->getValue()]); } } - $collection->setCurPage($criteria->getCurrentPage()); - $collection->setPageSize($criteria->getPageSize()); + $collection->setCurPage($searchCriteria->getCurrentPage()); + $collection->setPageSize($searchCriteria->getPageSize()); $collection->addPaymentInformation(['method']); $collection->addOrderInformation(['increment_id']); return $collection; diff --git a/app/code/Magento/Sales/Model/Order/ShipmentRepository.php b/app/code/Magento/Sales/Model/Order/ShipmentRepository.php index c44fa79ae56c7525b36bd8fa9a2f15ffa0206946..9cb32363b480fcdd1c69c673f37c3fd9cf5a54a6 100644 --- a/app/code/Magento/Sales/Model/Order/ShipmentRepository.php +++ b/app/code/Magento/Sales/Model/Order/ShipmentRepository.php @@ -14,6 +14,8 @@ use Magento\Framework\Exception\InputException; /** * Repository class for @see \Magento\Sales\Api\Data\ShipmentInterface + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class ShipmentRepository implements \Magento\Sales\Api\ShipmentRepositoryInterface { @@ -77,24 +79,24 @@ class ShipmentRepository implements \Magento\Sales\Api\ShipmentRepositoryInterfa /** * Find shipments by criteria. * - * @param \Magento\Framework\Api\SearchCriteria $criteria + * @param \Magento\Framework\Api\SearchCriteria $searchCriteria * @return \Magento\Sales\Api\Data\ShipmentInterface[] */ - public function getList(\Magento\Framework\Api\SearchCriteria $criteria) + public function getList(\Magento\Framework\Api\SearchCriteria $searchCriteria) { //@TODO: fix search logic /** @var \Magento\Sales\Api\Data\ShipmentSearchResultInterface $searchResult */ $searchResult = $this->searchResultFactory->create(); - foreach ($criteria->getFilterGroups() as $filterGroup) { + foreach ($searchCriteria->getFilterGroups() as $filterGroup) { foreach ($filterGroup->getFilters() as $filter) { $condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq'; $searchResult->addFieldToFilter($filter->getField(), [$condition => $filter->getValue()]); } } - $searchResult->setCurPage($criteria->getCurrentPage()); - $searchResult->setPageSize($criteria->getPageSize()); + $searchResult->setCurPage($searchCriteria->getCurrentPage()); + $searchResult->setPageSize($searchCriteria->getPageSize()); return $searchResult; } diff --git a/app/code/Magento/Sales/Model/OrderRepository.php b/app/code/Magento/Sales/Model/OrderRepository.php index 976a03486a4f1ead05696c96dfc28ba9652f2d68..1d4a7b8e66a9a72b902636aae8efc8ae919a3204 100644 --- a/app/code/Magento/Sales/Model/OrderRepository.php +++ b/app/code/Magento/Sales/Model/OrderRepository.php @@ -73,22 +73,22 @@ class OrderRepository implements \Magento\Sales\Api\OrderRepositoryInterface /** * Find entities by criteria * - * @param \Magento\Framework\Api\SearchCriteria $criteria + * @param \Magento\Framework\Api\SearchCriteria $searchCriteria * @return \Magento\Sales\Api\Data\OrderInterface[] */ - public function getList(\Magento\Framework\Api\SearchCriteria $criteria) + public function getList(\Magento\Framework\Api\SearchCriteria $searchCriteria) { //@TODO: fix search logic /** @var \Magento\Sales\Api\Data\OrderSearchResultInterface $searchResult */ $searchResult = $this->searchResultFactory->create(); - foreach ($criteria->getFilterGroups() as $filterGroup) { + foreach ($searchCriteria->getFilterGroups() as $filterGroup) { foreach ($filterGroup->getFilters() as $filter) { $condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq'; $searchResult->addFieldToFilter($filter->getField(), [$condition => $filter->getValue()]); } } - $searchResult->setCurPage($criteria->getCurrentPage()); - $searchResult->setPageSize($criteria->getPageSize()); + $searchResult->setCurPage($searchCriteria->getCurrentPage()); + $searchResult->setPageSize($searchCriteria->getPageSize()); return $searchResult; } diff --git a/app/code/Magento/Sales/Model/ResourceModel/Order/Address.php b/app/code/Magento/Sales/Model/ResourceModel/Order/Address.php index 6df065f7ee30372b130c002875fb0518d266a8ca..625fe5e2b342f629ca0f62df308687c6d132c7e4 100644 --- a/app/code/Magento/Sales/Model/ResourceModel/Order/Address.php +++ b/app/code/Magento/Sales/Model/ResourceModel/Order/Address.php @@ -122,19 +122,4 @@ class Address extends SalesResource implements OrderAddressResourceInterface } return $this; } - - /** - * Update related grid table after object save - * - * @param \Magento\Framework\Model\AbstractModel|\Magento\Framework\DataObject $object - * @return \Magento\Framework\Model\ResourceModel\Db\AbstractDb - */ - protected function _afterSave(\Magento\Framework\Model\AbstractModel $object) - { - $resource = parent::_afterSave($object); - if ($object->getParentId()) { - $this->gridPool->refreshByOrderId($object->getParentId()); - } - return $resource; - } } diff --git a/app/code/Magento/Sales/Model/Service/CreditmemoService.php b/app/code/Magento/Sales/Model/Service/CreditmemoService.php index ea0e1ed82d1b3321648f2507ae646098cc620c8d..1993e1d1cae54bd62b2c4a2d632589c89f28cfd9 100644 --- a/app/code/Magento/Sales/Model/Service/CreditmemoService.php +++ b/app/code/Magento/Sales/Model/Service/CreditmemoService.php @@ -108,8 +108,8 @@ class CreditmemoService implements \Magento\Sales\Api\CreditmemoManagementInterf $this->searchCriteriaBuilder->addFilters( [$this->filterBuilder->setField('parent_id')->setValue($id)->setConditionType('eq')->create()] ); - $criteria = $this->searchCriteriaBuilder->create(); - return $this->commentRepository->getList($criteria); + $searchCriteria = $this->searchCriteriaBuilder->create(); + return $this->commentRepository->getList($searchCriteria); } /** @@ -129,13 +129,11 @@ class CreditmemoService implements \Magento\Sales\Api\CreditmemoManagementInterf * * @param \Magento\Sales\Api\Data\CreditmemoInterface $creditmemo * @param bool $offlineRequested - * @param bool $notifyCustomer * @return \Magento\Sales\Api\Data\CreditmemoInterface */ public function refund( \Magento\Sales\Api\Data\CreditmemoInterface $creditmemo, - $offlineRequested = false, - $notifyCustomer = false + $offlineRequested = false ) { $this->validateForRefund($creditmemo); $creditmemo->setState(\Magento\Sales\Model\Order\Creditmemo::STATE_REFUNDED); diff --git a/app/code/Magento/Sales/Model/Service/InvoiceService.php b/app/code/Magento/Sales/Model/Service/InvoiceService.php index 5c07bf365e9fb1669804dd81b554c79af88d8a62..7352d0f221e330110014f371c5a62713b496addf 100644 --- a/app/code/Magento/Sales/Model/Service/InvoiceService.php +++ b/app/code/Magento/Sales/Model/Service/InvoiceService.php @@ -103,8 +103,8 @@ class InvoiceService implements InvoiceManagementInterface $this->criteriaBuilder->addFilters( [$this->filterBuilder->setField('parent_id')->setValue($id)->setConditionType('eq')->create()] ); - $criteria = $this->criteriaBuilder->create(); - return $this->commentRepository->getList($criteria); + $searchCriteria = $this->criteriaBuilder->create(); + return $this->commentRepository->getList($searchCriteria); } /** diff --git a/app/code/Magento/Sales/Model/Service/OrderService.php b/app/code/Magento/Sales/Model/Service/OrderService.php index 5df21bf9df691206d6bcd6f64fc4b9264c940e1a..29b719a1873a6144d7e83853d8a47316bc9349c7 100644 --- a/app/code/Magento/Sales/Model/Service/OrderService.php +++ b/app/code/Magento/Sales/Model/Service/OrderService.php @@ -44,6 +44,11 @@ class OrderService implements OrderManagementInterface */ protected $eventManager; + /** + * @var \Magento\Sales\Model\Order\Email\Sender\OrderCommentSender + */ + protected $orderCommentSender; + /** * Constructor * @@ -53,6 +58,7 @@ class OrderService implements OrderManagementInterface * @param \Magento\Framework\Api\FilterBuilder $filterBuilder * @param \Magento\Sales\Model\OrderNotifier $notifier * @param \Magento\Framework\Event\ManagerInterface $eventManager + * @param \Magento\Sales\Model\Order\Email\Sender\OrderCommentSender $orderCommentSender */ public function __construct( \Magento\Sales\Api\OrderRepositoryInterface $orderRepository, @@ -60,7 +66,8 @@ class OrderService implements OrderManagementInterface \Magento\Framework\Api\SearchCriteriaBuilder $criteriaBuilder, \Magento\Framework\Api\FilterBuilder $filterBuilder, \Magento\Sales\Model\OrderNotifier $notifier, - \Magento\Framework\Event\ManagerInterface $eventManager + \Magento\Framework\Event\ManagerInterface $eventManager, + \Magento\Sales\Model\Order\Email\Sender\OrderCommentSender $orderCommentSender ) { $this->orderRepository = $orderRepository; $this->historyRepository = $historyRepository; @@ -68,6 +75,7 @@ class OrderService implements OrderManagementInterface $this->filterBuilder = $filterBuilder; $this->notifier = $notifier; $this->eventManager = $eventManager; + $this->orderCommentSender = $orderCommentSender; } /** @@ -98,8 +106,8 @@ class OrderService implements OrderManagementInterface $this->criteriaBuilder->addFilters( [$this->filterBuilder->setField('parent_id')->setValue($id)->setConditionType('eq')->create()] ); - $criteria = $this->criteriaBuilder->create(); - return $this->historyRepository->getList($criteria); + $searchCriteria = $this->criteriaBuilder->create(); + return $this->historyRepository->getList($searchCriteria); } /** @@ -114,6 +122,9 @@ class OrderService implements OrderManagementInterface $order = $this->orderRepository->get($id); $order->addStatusHistory($statusHistory); $this->orderRepository->save($order); + $notify = isset($statusHistory['is_customer_notified']) ? $statusHistory['is_customer_notified'] : false; + $comment = trim(strip_tags($statusHistory->getComment())); + $this->orderCommentSender->send($order, $notify, $comment); return true; } diff --git a/app/code/Magento/Sales/Model/Service/ShipmentService.php b/app/code/Magento/Sales/Model/Service/ShipmentService.php index 6523e8e83825e5112286d787a1f15bdff3e394bd..62593c1b1d0dc58165dafe3453291e13fcf0a123 100644 --- a/app/code/Magento/Sales/Model/Service/ShipmentService.php +++ b/app/code/Magento/Sales/Model/Service/ShipmentService.php @@ -91,8 +91,8 @@ class ShipmentService implements ShipmentManagementInterface $this->criteriaBuilder->addFilters( [$this->filterBuilder->setField('parent_id')->setValue($id)->setConditionType('eq')->create()] ); - $criteria = $this->criteriaBuilder->create(); - return $this->commentRepository->getList($criteria); + $searchCriteria = $this->criteriaBuilder->create(); + return $this->commentRepository->getList($searchCriteria); } /** diff --git a/app/code/Magento/Sales/Observer/GridProcessAddressChange.php b/app/code/Magento/Sales/Observer/GridProcessAddressChange.php new file mode 100644 index 0000000000000000000000000000000000000000..e053801290dbefb220c3e89af178495533ba24b4 --- /dev/null +++ b/app/code/Magento/Sales/Observer/GridProcessAddressChange.php @@ -0,0 +1,44 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Observer; + +use Magento\Framework\Event\Observer as EventObserver; +use Magento\Sales\Model\ResourceModel\GridPool; +use Magento\Framework\Event\ObserverInterface; + +/** + * Class GridProcessAddressChange + */ +class GridProcessAddressChange implements ObserverInterface +{ + + /** + * @var GridPool + */ + protected $gridPool; + + /** + * @param GridPool $gridPool + */ + public function __construct( + GridPool $gridPool + ) { + $this->gridPool= $gridPool; + } + + /** + * Refresh addresses in grids according to performed changed + * This is manual admin action, as result we perform this operation without delay + * + * @param EventObserver $observer + * @return void + */ + public function execute(EventObserver $observer) + { + $this->gridPool->refreshByOrderId($observer->getOrderId()); + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Model/DownloadTest.php b/app/code/Magento/Sales/Test/Unit/Model/DownloadTest.php index e7410b411bfa6de5ca497929115cf224d31f45f6..295981ef91ed16cb6102014764155615ae87b492 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/DownloadTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/DownloadTest.php @@ -39,6 +39,11 @@ class DownloadTest extends \PHPUnit_Framework_TestCase */ protected $writeDirectoryMock; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $driverMock; + protected function setUp() { $this->writeDirectoryMock = $this->getMockBuilder('Magento\Framework\Filesystem\Directory\Write') @@ -49,9 +54,10 @@ class DownloadTest extends \PHPUnit_Framework_TestCase ->getMock(); $this->filesystemMock->expects($this->any()) ->method('getDirectoryWrite') - ->with(DirectoryList::ROOT) + ->with(DirectoryList::MEDIA) ->will($this->returnValue($this->writeDirectoryMock)); + $this->driverMock = $this->getMockForAbstractClass('Magento\Framework\Filesystem\DriverInterface'); $this->storageMock = $this->getMockBuilder('Magento\MediaStorage\Helper\File\Storage\Database') ->disableOriginalConstructor() ->getMock(); @@ -83,17 +89,23 @@ class DownloadTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException \Exception + * @param $realPatchCheck + * @param $isFile + * @param $isReadable + * @expectedException \Magento\Framework\Exception\LocalizedException + * @dataProvider dataProviderForTestDownloadFileException */ - public function testDownloadFileException() + public function testDownloadFileException($realPatchCheck, $isFile, $isReadable) { $info = ['order_path' => 'test/path', 'quote_path' => 'test/path2', 'title' => 'test title']; - $isFile = true; - $isReadable = false; $this->writeDirectoryMock->expects($this->any()) ->method('getAbsolutePath') ->will($this->returnArgument(0)); + $this->writeDirectoryMock->expects($this->any()) + ->method('getDriver') + ->willReturn($this->driverMock); + $this->driverMock->expects($this->any())->method('getRealPath')->willReturn($realPatchCheck); $this->writeDirectoryMock->expects($this->any()) ->method('isFile') ->will($this->returnValue($isFile)); @@ -104,12 +116,25 @@ class DownloadTest extends \PHPUnit_Framework_TestCase $this->storageFactoryMock->expects($this->any()) ->method('checkDbUsage') ->will($this->returnValue(false)); + $this->httpFileFactoryMock->expects($this->never())->method('create'); $this->model->downloadFile($info); } /** - * @expectedException \Exception + * @return array + */ + public function dataProviderForTestDownloadFileException() + { + return [ + [1, true, false], + [1, false, true], + [false, true, true], + ]; + } + + /** + * @expectedException \Magento\Framework\Exception\LocalizedException */ public function testDownloadFileNoStorage() { @@ -120,6 +145,11 @@ class DownloadTest extends \PHPUnit_Framework_TestCase $this->writeDirectoryMock->expects($this->any()) ->method('getAbsolutePath') ->will($this->returnArgument(0)); + $this->writeDirectoryMock->expects($this->any()) + ->method('getDriver') + ->willReturn($this->driverMock); + $this->driverMock->expects($this->any())->method('getRealPath')->willReturn(true); + $this->writeDirectoryMock->expects($this->any()) ->method('isFile') ->will($this->returnValue($isFile)); @@ -130,9 +160,6 @@ class DownloadTest extends \PHPUnit_Framework_TestCase $this->storageMock->expects($this->any()) ->method('checkDbUsage') ->will($this->returnValue(true)); - $this->storageMock->expects($this->any()) - ->method('getMediaRelativePath') - ->will($this->returnArgument(0)); $storageDatabaseMock = $this->getMockBuilder('Magento\MediaStorage\Model\File\Storage\Database') ->disableOriginalConstructor() @@ -153,6 +180,7 @@ class DownloadTest extends \PHPUnit_Framework_TestCase $this->storageFactoryMock->expects($this->any()) ->method('create') ->will($this->returnValue($storageDatabaseMock)); + $this->httpFileFactoryMock->expects($this->never())->method('create'); $this->model->downloadFile($info); } @@ -178,6 +206,11 @@ class DownloadTest extends \PHPUnit_Framework_TestCase $this->writeDirectoryMock->expects($this->any()) ->method('getAbsolutePath') ->will($this->returnArgument(0)); + $this->writeDirectoryMock->expects($this->any()) + ->method('getDriver') + ->willReturn($this->driverMock); + $this->driverMock->expects($this->any())->method('getRealPath')->willReturn(true); + $this->writeDirectoryMock->expects($this->any()) ->method('isFile') ->will($this->returnValue($isFile)); @@ -195,9 +228,6 @@ class DownloadTest extends \PHPUnit_Framework_TestCase $this->storageMock->expects($this->any()) ->method('checkDbUsage') ->will($this->returnValue(true)); - $this->storageMock->expects($this->any()) - ->method('getMediaRelativePath') - ->will($this->returnArgument(0)); $storageDatabaseMock = $this->getMockBuilder('Magento\MediaStorage\Model\File\Storage\Database') ->disableOriginalConstructor() @@ -220,7 +250,7 @@ class DownloadTest extends \PHPUnit_Framework_TestCase ->with( $info['title'], ['value' => $info['order_path'], 'type' => 'filename'], - DirectoryList::ROOT, + DirectoryList::MEDIA, 'application/octet-stream', null ); diff --git a/app/code/Magento/Sales/Test/Unit/Model/InvoiceRepositoryTest.php b/app/code/Magento/Sales/Test/Unit/Model/InvoiceRepositoryTest.php index 4a2ef97a19764b757f6de4da62500cbfeee27653..0cb9a4dc715765cc8c9311d12218e244e28f0d72 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/InvoiceRepositoryTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/InvoiceRepositoryTest.php @@ -148,10 +148,10 @@ class InvoiceRepositoryTest extends \PHPUnit_Framework_TestCase ->method('getFilters') ->willReturn([$filter]); - $criteria = $this->getMockBuilder('Magento\Framework\Api\SearchCriteria') + $searchCriteria = $this->getMockBuilder('Magento\Framework\Api\SearchCriteria') ->disableOriginalConstructor() ->getMock(); - $criteria->expects($this->once()) + $searchCriteria->expects($this->once()) ->method('getFilterGroups') ->willReturn($filterGroups); @@ -166,7 +166,7 @@ class InvoiceRepositoryTest extends \PHPUnit_Framework_TestCase ->method('create') ->willReturn($collection); - $this->assertEquals($collection, $this->invoice->getList($criteria)); + $this->assertEquals($collection, $this->invoice->getList($searchCriteria)); } public function testDelete() diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/AddressRepositoryTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/AddressRepositoryTest.php index f943f6632225b1c026852e51ebfa4339444a999b..3dd1590bf72ad751cf18fbe81ba1c3951971a052 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/AddressRepositoryTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/AddressRepositoryTest.php @@ -170,14 +170,14 @@ class AddressRepositoryTest extends \PHPUnit_Framework_TestCase ->method('getFilters') ->willReturn([$filter]); - $criteria = $this->getMock( + $searchCriteria = $this->getMock( 'Magento\Framework\Api\SearchCriteria', ['getFilterGroups'], [], '', false ); - $criteria->expects($this->once()) + $searchCriteria->expects($this->once()) ->method('getFilterGroups') ->willReturn([$filterGroup]); @@ -196,7 +196,7 @@ class AddressRepositoryTest extends \PHPUnit_Framework_TestCase ->method('create') ->willReturn($collection); - $this->assertEquals($collection, $this->subject->getList($criteria)); + $this->assertEquals($collection, $this->subject->getList($searchCriteria)); } public function testDelete() diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/CreditmemoRepositoryTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/CreditmemoRepositoryTest.php index cba7908dacd42bae57729dfe770587a2708c8f4a..25357bd65177fe791572664736220c8ae59161b1 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/CreditmemoRepositoryTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/CreditmemoRepositoryTest.php @@ -153,10 +153,10 @@ class CreditmemoRepositoryTest extends \PHPUnit_Framework_TestCase ->method('getFilters') ->willReturn([$filter]); - $criteria = $this->getMockBuilder('Magento\Framework\Api\SearchCriteria') + $searchCriteria = $this->getMockBuilder('Magento\Framework\Api\SearchCriteria') ->disableOriginalConstructor() ->getMock(); - $criteria->expects($this->once()) + $searchCriteria->expects($this->once()) ->method('getFilterGroups') ->willReturn($filterGroups); @@ -171,7 +171,7 @@ class CreditmemoRepositoryTest extends \PHPUnit_Framework_TestCase ->method('create') ->willReturn($collection); - $this->assertEquals($collection, $this->creditmemo->getList($criteria)); + $this->assertEquals($collection, $this->creditmemo->getList($searchCriteria)); } public function testDelete() diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/ItemRepositoryTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/ItemRepositoryTest.php index e2deb200dbcfcd930ae170dee2cd48819509a8f3..314271c3156963559230464f983dc06f2872e7e1 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/ItemRepositoryTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/ItemRepositoryTest.php @@ -200,10 +200,10 @@ class ItemRepositoryTest extends \PHPUnit_Framework_TestCase ->method('getFilters') ->willReturn([$filterMock]); - $criteriaMock = $this->getMockBuilder('Magento\Framework\Api\SearchCriteria') + $searchCriteriaMock = $this->getMockBuilder('Magento\Framework\Api\SearchCriteria') ->disableOriginalConstructor() ->getMock(); - $criteriaMock->expects($this->once()) + $searchCriteriaMock->expects($this->once()) ->method('getFilterGroups') ->willReturn([$filterGroupMock]); @@ -230,7 +230,7 @@ class ItemRepositoryTest extends \PHPUnit_Framework_TestCase ->willReturn($searchResultMock); $model = $this->getModel($orderItemMock, $productType); - $this->assertSame($searchResultMock, $model->getList($criteriaMock)); + $this->assertSame($searchResultMock, $model->getList($searchCriteriaMock)); } public function testDeleteById() diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php index 29757fc570f2380410376d09d3ca137062ffad9d..b56c83e38d724a1783f82744e4c53d69846e42d8 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php @@ -17,6 +17,8 @@ use Magento\Sales\Model\Order\Payment\Transaction; */ class PaymentTest extends \PHPUnit_Framework_TestCase { + const TRANSACTION_ID = 'ewr34fM49V0'; + private $mockContext; /** * @var Payment @@ -166,6 +168,7 @@ class PaymentTest extends \PHPUnit_Framework_TestCase 'order', 'isInitializeNeeded', 'initialize', + 'refund' ] ) ->getMock(); @@ -258,7 +261,10 @@ class PaymentTest extends \PHPUnit_Framework_TestCase 'register', 'addComment', 'save', - 'getGrandTotal' + 'getGrandTotal', + 'getBaseGrandTotal', + 'getDoTransaction', + 'getInvoice' ], [], '', @@ -268,7 +274,7 @@ class PaymentTest extends \PHPUnit_Framework_TestCase $this->payment = $this->initPayment(); $this->payment->setMethod('any'); $this->payment->setOrder($this->orderMock); - $this->transactionId = 100; + $this->transactionId = self::TRANSACTION_ID; } protected function tearDown() @@ -825,13 +831,13 @@ class PaymentTest extends \PHPUnit_Framework_TestCase */ protected function mockInvoice($transactionId, $countCall = 1) { - $this->invoiceMock->expects($this->once()) + $this->invoiceMock->expects(static::any()) ->method('getTransactionId') ->willReturn($transactionId); - $this->invoiceMock->expects($this->once()) + $this->invoiceMock->expects(static::any()) ->method('load') ->with($transactionId); - $this->invoiceMock->expects($this->once()) + $this->invoiceMock->expects(static::any()) ->method('getId') ->willReturn($transactionId); $this->orderMock->expects($this->exactly($countCall)) @@ -1314,7 +1320,8 @@ class PaymentTest extends \PHPUnit_Framework_TestCase */ public function testRegisterRefundNotification() { - $message = 'Registered notification about refunded amount of . Transaction ID: "100-refund"'; + $message = 'Registered notification about refunded amount of . Transaction ID: "' . + self::TRANSACTION_ID . '-refund"'; $amount = 50; $grandTotalCreditMemo = 50; $invoiceBaseGrandTotal = 50; @@ -1429,6 +1436,73 @@ class PaymentTest extends \PHPUnit_Framework_TestCase $this->assertEquals($canRefund, $this->payment->canRefund()); } + /** + * @covers \Magento\Sales\Model\Order\Payment::refund() + */ + public function testRefund() + { + $amount = 204.04; + $this->creditMemoMock->expects(static::once()) + ->method('getBaseGrandTotal') + ->willReturn($amount); + $this->creditMemoMock->expects(static::once()) + ->method('getGrandTotal') + ->willReturn($amount); + $this->creditMemoMock->expects(static::once()) + ->method('getDoTransaction') + ->willReturn(true); + + $this->paymentMethodMock->expects(static::once()) + ->method('canRefund') + ->willReturn(true); + + $this->mockInvoice(self::TRANSACTION_ID, 0); + $this->creditMemoMock->expects(static::once()) + ->method('getInvoice') + ->willReturn($this->invoiceMock); + + $captureTranId = self::TRANSACTION_ID . '-' . Transaction::TYPE_CAPTURE; + $captureTransaction = $this->getMockBuilder(Transaction::class) + ->disableOriginalConstructor() + ->setMethods(['getTxnId']) + ->getMock(); + + $refundTranId = $captureTranId . '-' . Transaction::TYPE_REFUND; + $this->transactionManagerMock->expects(static::once()) + ->method('generateTransactionId') + ->willReturn($refundTranId); + $captureTransaction->expects(static::once()) + ->method('getTxnId') + ->willReturn($captureTranId); + $this->transactionRepositoryMock->expects(static::once()) + ->method('getByTransactionId') + ->willReturn($captureTransaction); + + $this->paymentMethodMock->expects(static::once()) + ->method('refund') + ->with($this->payment, $amount); + + $isOnline = true; + $this->getTransactionBuilderMock([], $isOnline, Transaction::TYPE_REFUND, $refundTranId); + + $this->currencyMock->expects(static::once()) + ->method('formatTxt') + ->willReturn($amount); + $this->orderMock->expects(static::once()) + ->method('getBaseCurrency') + ->willReturn($this->currencyMock); + + $status = 'status'; + $message = 'We refunded ' . $amount . ' online. Transaction ID: "' . $refundTranId . '"'; + $this->mockGetDefaultStatus(Order::STATE_PROCESSING, $status); + $this->assertOrderUpdated(Order::STATE_PROCESSING, $status, $message); + + static::assertSame($this->payment, $this->payment->refund($this->creditMemoMock)); + static::assertEquals($amount, $this->payment->getData('amount_refunded')); + static::assertEquals($amount, $this->payment->getData('base_amount_refunded_online')); + static::assertEquals($amount, $this->payment->getData('base_amount_refunded')); + } + public function boolProvider() { return [ @@ -1437,6 +1511,36 @@ class PaymentTest extends \PHPUnit_Framework_TestCase ]; } + /** + * @covers \Magento\Sales\Model\Order\Payment::isCaptureFinal() + * @return void + */ + public function testIsCaptureFinal() + { + $amount = 23.02; + $partialAmount = 12.00; + + $this->orderMock->expects(static::exactly(2)) + ->method('getTotalDue') + ->willReturn($amount); + + static::assertFalse($this->payment->isCaptureFinal($partialAmount)); + static::assertTrue($this->payment->isCaptureFinal($amount)); + } + + /** + * @covers \Magento\Sales\Model\Order\Payment::getShouldCloseParentTransaction() + * @return void + */ + public function testGetShouldCloseParentTransaction() + { + $this->payment->setShouldCloseParentTransaction(1); + static::assertTrue($this->payment->getShouldCloseParentTransaction()); + + $this->payment->setShouldCloseParentTransaction(0); + static::assertFalse($this->payment->getShouldCloseParentTransaction()); + } + protected function initPayment() { return (new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this))->getObject( diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/ShipmentRepositoryTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/ShipmentRepositoryTest.php index 36a8360ee094fbf2c05b70ed871492d1b0b0d25b..f76732578da21856a34ef5a9edee3011256dd831 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/ShipmentRepositoryTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/ShipmentRepositoryTest.php @@ -170,14 +170,14 @@ class ShipmentRepositoryTest extends \PHPUnit_Framework_TestCase ->method('getFilters') ->willReturn([$filter]); - $criteria = $this->getMock( + $searchCriteria = $this->getMock( 'Magento\Framework\Api\SearchCriteria', ['getFilterGroups'], [], '', false ); - $criteria->expects($this->once()) + $searchCriteria->expects($this->once()) ->method('getFilterGroups') ->willReturn([$filterGroup]); @@ -196,7 +196,7 @@ class ShipmentRepositoryTest extends \PHPUnit_Framework_TestCase ->method('create') ->willReturn($collection); - $this->assertEquals($collection, $this->subject->getList($criteria)); + $this->assertEquals($collection, $this->subject->getList($searchCriteria)); } public function testDelete() diff --git a/app/code/Magento/Sales/Test/Unit/Model/ResourceModel/Order/AddressTest.php b/app/code/Magento/Sales/Test/Unit/Model/ResourceModel/Order/AddressTest.php index ffeb136782b1ce1b16873f54caa70ce3a1dbbb88..8ac891f47b43efca38e9efae9abf6e217fdb7fea 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/ResourceModel/Order/AddressTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/ResourceModel/Order/AddressTest.php @@ -40,11 +40,6 @@ class AddressTest extends \PHPUnit_Framework_TestCase */ protected $validatorMock; - /** - * @var \Magento\Sales\Model\ResourceModel\GridPool|\PHPUnit_Framework_MockObject_MockObject - */ - protected $gridPoolMock; - /** * @var \Magento\Framework\Model\ResourceModel\Db\VersionControl\Snapshot|\PHPUnit_Framework_MockObject_MockObject */ @@ -87,13 +82,6 @@ class AddressTest extends \PHPUnit_Framework_TestCase '', false ); - $this->gridPoolMock = $this->getMock( - 'Magento\Sales\Model\ResourceModel\GridPool', - ['refreshByOrderId'], - [], - '', - false - ); $this->entitySnapshotMock = $this->getMock( 'Magento\Framework\Model\ResourceModel\Db\VersionControl\Snapshot', [], @@ -117,7 +105,6 @@ class AddressTest extends \PHPUnit_Framework_TestCase [ 'resource' => $this->appResourceMock, 'validator' => $this->validatorMock, - 'gridPool' => $this->gridPoolMock, 'entitySnapshot' => $this->entitySnapshotMock ] ); @@ -136,13 +123,9 @@ class AddressTest extends \PHPUnit_Framework_TestCase ->method('isModified') ->with($this->addressMock) ->willReturn(true); - $this->addressMock->expects($this->exactly(3)) + $this->addressMock->expects($this->once()) ->method('getParentId') ->will($this->returnValue(1)); - $this->gridPoolMock->expects($this->once()) - ->method('refreshByOrderId') - ->with($this->equalTo(1)) - ->will($this->returnSelf()); $this->addressResource->save($this->addressMock); } diff --git a/app/code/Magento/Sales/Test/Unit/Model/Service/OrderServiceTest.php b/app/code/Magento/Sales/Test/Unit/Model/Service/OrderServiceTest.php index dfbdd79bd337339cb1f54292df1f8c7ee3a36dd3..71a4bf2c0bb4819087bfeb07aa9a615a6d976545 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Service/OrderServiceTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Service/OrderServiceTest.php @@ -14,51 +14,67 @@ class OrderServiceTest extends \PHPUnit_Framework_TestCase * @var \Magento\Sales\Model\Service\OrderService */ protected $orderService; + /** * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Sales\Api\OrderRepositoryInterface */ protected $orderRepositoryMock; + /** * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Sales\Api\OrderStatusHistoryRepositoryInterface */ protected $orderStatusHistoryRepositoryMock; + /** * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Api\SearchCriteriaBuilder */ protected $searchCriteriaBuilderMock; + /** * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Api\SearchCriteria */ protected $searchCriteriaMock; + /** * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Api\FilterBuilder */ protected $filterBuilderMock; + /** * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Api\Filter */ protected $filterMock; + /** * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Sales\Model\OrderNotifier */ protected $orderNotifierMock; + /** * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Sales\Model\Order */ protected $orderMock; + /** * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Sales\Model\Order\Status\History */ protected $orderStatusHistoryMock; + /** * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Sales\Api\Data\OrderStatusHistorySearchResultInterface */ protected $orderSearchResultMock; + /** * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Event\ManagerInterface */ protected $eventManagerMock; + /** + * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Sales\Model\Order\Email\Sender\OrderCommentSender + */ + protected $orderCommentSender; + protected function setUp() { $this->orderRepositoryMock = $this->getMockBuilder( @@ -116,13 +132,20 @@ class OrderServiceTest extends \PHPUnit_Framework_TestCase ) ->disableOriginalConstructor() ->getMock(); + $this->orderCommentSender = $this->getMockBuilder( + 'Magento\Sales\Model\Order\Email\Sender\OrderCommentSender' + ) + ->disableOriginalConstructor() + ->getMock(); + $this->orderService = new \Magento\Sales\Model\Service\OrderService( $this->orderRepositoryMock, $this->orderStatusHistoryRepositoryMock, $this->searchCriteriaBuilderMock, $this->filterBuilderMock, $this->orderNotifierMock, - $this->eventManagerMock + $this->eventManagerMock, + $this->orderCommentSender ); } @@ -174,6 +197,7 @@ class OrderServiceTest extends \PHPUnit_Framework_TestCase public function testAddComment() { + $clearComment = "Comment text here..."; $this->orderRepositoryMock->expects($this->once()) ->method('get') ->with(123) @@ -182,10 +206,16 @@ class OrderServiceTest extends \PHPUnit_Framework_TestCase ->method('addStatusHistory') ->with($this->orderStatusHistoryMock) ->willReturn($this->orderMock); + $this->orderStatusHistoryMock->expects($this->once()) + ->method('getComment') + ->willReturn("<h1>" . $clearComment); $this->orderRepositoryMock->expects($this->once()) ->method('save') ->with($this->orderMock) ->willReturn([]); + $this->orderCommentSender->expects($this->once()) + ->method('send') + ->with($this->orderMock, false, $clearComment); $this->assertTrue($this->orderService->addComment(123, $this->orderStatusHistoryMock)); } diff --git a/app/code/Magento/Sales/Test/Unit/Observer/GridProcessAddressChangeTest.php b/app/code/Magento/Sales/Test/Unit/Observer/GridProcessAddressChangeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d6a8e5fab14f400a59d72ecf75aaddfe313577b6 --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Observer/GridProcessAddressChangeTest.php @@ -0,0 +1,51 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Test\Unit\Observer; + +/** + * Class GridProcessAddressChangeTest + */ +class GridProcessAddressChangeTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Sales\Observer\GridProcessAddressChange + */ + protected $observer; + + /** + * @var \Magento\Sales\Model\ResourceModel\GridPool|\PHPUnit_Framework_MockObject_MockObject + */ + protected $gridPoolMock; + + /** + * @var \Magento\Framework\Event\ObserverInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $eventObserverMock; + + public function setUp() + { + $this->gridPoolMock = $this->getMockBuilder('Magento\Sales\Model\ResourceModel\GridPool') + ->disableOriginalConstructor() + ->getMock(); + $this->eventObserverMock = $this->getMockBuilder('Magento\Framework\Event\Observer') + ->disableOriginalConstructor() + ->setMethods(['getOrderId']) + ->getMock(); + $this->observer = new \Magento\Sales\Observer\GridProcessAddressChange($this->gridPoolMock); + } + + public function testGridsReindex() + { + $this->eventObserverMock->expects($this->once()) + ->method('getOrderId') + ->willReturn(100500); + $this->gridPoolMock->expects($this->once()) + ->method('refreshByOrderId') + ->with(100500); + $this->assertNull($this->observer->execute($this->eventObserverMock)); + } +} diff --git a/app/code/Magento/Sales/etc/events.xml b/app/code/Magento/Sales/etc/events.xml index f02fcdd77a5bcfc8b4fdbce4414cb6c7f6886759..4dfe0d47c9c9a02372868b2602a6b4f3f0e2fcb3 100644 --- a/app/code/Magento/Sales/etc/events.xml +++ b/app/code/Magento/Sales/etc/events.xml @@ -33,6 +33,9 @@ <event name="sales_order_creditmemo_delete_after"> <observer name="sales_grid_order_creditmemo_sync_remove" instance="SalesCreditmemoIndexGridSyncRemove" /> </event> + <event name="admin_sales_order_address_update"> + <observer name="sales_grid_admin_refresh_grids" instance="Magento\Sales\Observer\GridProcessAddressChange" /> + </event> <event name="config_data_dev_grid_async_indexing_disabled"> <observer name="sales_grid_order_async_insert" instance="SalesOrderIndexGridAsyncInsertObserver" /> <observer name="sales_grid_order_invoice_async_insert" instance="SalesInvoiceIndexGridAsyncInsertObserver" /> diff --git a/app/code/Magento/Sales/i18n/de_DE.csv b/app/code/Magento/Sales/i18n/de_DE.csv index 8cd4ff0cf4df0f2a0f1a19dd8cd76501b258800c..736a5f91b8f7bdff46c575f58cef97634cc23241 100644 --- a/app/code/Magento/Sales/i18n/de_DE.csv +++ b/app/code/Magento/Sales/i18n/de_DE.csv @@ -679,3 +679,4 @@ order-header,order-header "State Code and Title","State Code and Title" "PDF Packing Slips","PDF Packzettel" "Status can't be unassigned, because it is used by existing order(s).","Status can't be unassigned, because it is used by existing order(s)." +Operations,Operations diff --git a/app/code/Magento/Sales/i18n/en_US.csv b/app/code/Magento/Sales/i18n/en_US.csv index 56fadf4515509308f95b77540604dc5f2d71d75a..5970b2ff82e61180ca857b984033987e748a25c1 100644 --- a/app/code/Magento/Sales/i18n/en_US.csv +++ b/app/code/Magento/Sales/i18n/en_US.csv @@ -679,3 +679,4 @@ order-header,order-header "State Code and Title","State Code and Title" "PDF Packing Slips","PDF Packing Slips" "Status can't be unassigned, because it is used by existing order(s).","Status can't be unassigned, because it is used by existing order(s)." +Operations,Operations diff --git a/app/code/Magento/Sales/i18n/es_ES.csv b/app/code/Magento/Sales/i18n/es_ES.csv index b14dd0c68fcbf24da272a1ee87d018e6707d71b7..d524aad0e94bab691f993b401f27bab7eaf89dd9 100644 --- a/app/code/Magento/Sales/i18n/es_ES.csv +++ b/app/code/Magento/Sales/i18n/es_ES.csv @@ -679,3 +679,4 @@ order-header,order-header "State Code and Title","State Code and Title" "PDF Packing Slips","Albaranes en PDF" "Status can't be unassigned, because it is used by existing order(s).","Status can't be unassigned, because it is used by existing order(s)." +Operations,Operations diff --git a/app/code/Magento/Sales/i18n/fr_FR.csv b/app/code/Magento/Sales/i18n/fr_FR.csv index d56acf87271da135c373d7758235de4e1dd3a419..e6ee0ec1c4a3f222b700b3a69b8608483fcea766 100644 --- a/app/code/Magento/Sales/i18n/fr_FR.csv +++ b/app/code/Magento/Sales/i18n/fr_FR.csv @@ -679,3 +679,4 @@ order-header,order-header "State Code and Title","State Code and Title" "PDF Packing Slips","Bons de livraison PDF" "Status can't be unassigned, because it is used by existing order(s).","Status can't be unassigned, because it is used by existing order(s)." +Operations,Operations diff --git a/app/code/Magento/Sales/i18n/nl_NL.csv b/app/code/Magento/Sales/i18n/nl_NL.csv index 8018624c475f507c9340145fd0b3b6b1f607e03f..1675d096d63af089cbc00fdadaf6521edde2f1b3 100644 --- a/app/code/Magento/Sales/i18n/nl_NL.csv +++ b/app/code/Magento/Sales/i18n/nl_NL.csv @@ -679,3 +679,4 @@ order-header,order-header "State Code and Title","State Code and Title" "PDF Packing Slips","PDF Packing Slips" "Status can't be unassigned, because it is used by existing order(s).","Status can't be unassigned, because it is used by existing order(s)." +Operations,Operations diff --git a/app/code/Magento/Sales/i18n/pt_BR.csv b/app/code/Magento/Sales/i18n/pt_BR.csv index ffba7bb166d6bd8f27bbbe74f2d1a791a88cec8e..41380ea687d54ada86ccbf21d77d50d9f14ae801 100644 --- a/app/code/Magento/Sales/i18n/pt_BR.csv +++ b/app/code/Magento/Sales/i18n/pt_BR.csv @@ -679,3 +679,4 @@ order-header,order-header "State Code and Title","State Code and Title" "PDF Packing Slips","Guias de remessas em PDF" "Status can't be unassigned, because it is used by existing order(s).","Status can't be unassigned, because it is used by existing order(s)." +Operations,Operations diff --git a/app/code/Magento/Sales/i18n/zh_Hans_CN.csv b/app/code/Magento/Sales/i18n/zh_Hans_CN.csv index ecbf74067715d46205ac92e77f11cf9eee47236a..72b4d5663d7eb6446ac3440a68092a338c16d861 100644 --- a/app/code/Magento/Sales/i18n/zh_Hans_CN.csv +++ b/app/code/Magento/Sales/i18n/zh_Hans_CN.csv @@ -679,3 +679,4 @@ order-header,order-header "State Code and Title","State Code and Title" "PDF Packing Slips",PDFç‰ˆåŒ…è£¹æ¸…å• "Status can't be unassigned, because it is used by existing order(s).","Status can't be unassigned, because it is used by existing order(s)." +Operations,Operations diff --git a/app/code/Magento/Sales/view/adminhtml/web/order/create/scripts.js b/app/code/Magento/Sales/view/adminhtml/web/order/create/scripts.js index 90f8b04c5c70b9d4d9fbb88d70e08bd307c83d04..1bde25b44a4fd95346b4cdd3b69e57f6243ec2e8 100644 --- a/app/code/Magento/Sales/view/adminhtml/web/order/create/scripts.js +++ b/app/code/Magento/Sales/view/adminhtml/web/order/create/scripts.js @@ -64,20 +64,22 @@ define([ }, 10); }; - this.dataArea.onLoad = this.dataArea.onLoad.wrap(function(proceed) { - proceed(); - this._parent.itemsArea.setNode($(this._parent.getAreaId('items'))); - this._parent.itemsArea.onLoad(); - }); + if (jQuery('#' + this.getAreaId('items')).is(':visible')) { + this.dataArea.onLoad = this.dataArea.onLoad.wrap(function(proceed) { + proceed(); + this._parent.itemsArea.setNode($(this._parent.getAreaId('items'))); + this._parent.itemsArea.onLoad(); + }); - this.itemsArea.onLoad = this.itemsArea.onLoad.wrap(function(proceed) { - proceed(); - if ($(searchAreaId) && !$(searchAreaId).visible()) { - this.addControlButton(searchButton); - } - }); - this.areasLoaded(); - this.itemsArea.onLoad(); + this.itemsArea.onLoad = this.itemsArea.onLoad.wrap(function(proceed) { + proceed(); + if ($(searchAreaId) && !$(searchAreaId).visible()) { + this.addControlButton(searchButton); + } + }); + this.areasLoaded(); + this.itemsArea.onLoad(); + } }).bind(this)); jQuery('#edit_form') @@ -85,7 +87,6 @@ define([ jQuery(this).trigger('realOrder'); }) .on('realOrder', this._realSubmit.bind(this)); - }, areasLoaded: function(){ diff --git a/app/code/Magento/SalesRule/Model/Plugin/Rule.php b/app/code/Magento/SalesRule/Model/Plugin/Rule.php index 7bf8cb3c43d8aad796e96c8aec699536466b0091..8aa29ffe419e73635fc8fb845a652d1bcc9af86e 100644 --- a/app/code/Magento/SalesRule/Model/Plugin/Rule.php +++ b/app/code/Magento/SalesRule/Model/Plugin/Rule.php @@ -13,7 +13,7 @@ class Rule * @return \Magento\SalesRule\Model\Rule * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function aroundLoadCouponCode( + public function aroundLoadRelations( \Magento\SalesRule\Model\Rule $subject, \Closure $proceed ) { diff --git a/app/code/Magento/SalesRule/Model/Rule.php b/app/code/Magento/SalesRule/Model/Rule.php index 200a836592c1c8bdfd1cf21d2330b23d7b609aca..4ecc75f77dd891ea1be1580e555c017ebda9da5d 100644 --- a/app/code/Magento/SalesRule/Model/Rule.php +++ b/app/code/Magento/SalesRule/Model/Rule.php @@ -231,11 +231,23 @@ class Rule extends \Magento\Rule\Model\AbstractModel */ protected function _afterLoad() { - $this->loadCouponCode(); + $this->loadRelations(); return parent::_afterLoad(); } /** + * Load all relative data + * + * @return void + */ + public function loadRelations() + { + $this->loadCouponCode(); + } + + /** + * Load coupon code + * * @return void */ public function loadCouponCode() diff --git a/app/code/Magento/SalesRule/Observer/SalesOrderAfterPlaceObserver.php b/app/code/Magento/SalesRule/Observer/SalesOrderAfterPlaceObserver.php index 1d1a6be10918d384aaaa5906b395c7f30f02c8e3..9ceb8221d17a2577af41219fc483601080e7cd11 100644 --- a/app/code/Magento/SalesRule/Observer/SalesOrderAfterPlaceObserver.php +++ b/app/code/Magento/SalesRule/Observer/SalesOrderAfterPlaceObserver.php @@ -77,6 +77,7 @@ class SalesOrderAfterPlaceObserver implements ObserverInterface $rule = $this->_ruleFactory->create(); $rule->load($ruleId); if ($rule->getId()) { + $rule->loadCouponCode(); $rule->setTimesUsed($rule->getTimesUsed() + 1); $rule->save(); diff --git a/app/code/Magento/SalesRule/Test/Unit/Model/Plugin/RuleTest.php b/app/code/Magento/SalesRule/Test/Unit/Model/Plugin/RuleTest.php index fb788c5cf5b6f22efc7b99f421bb77d6267b69ce..a30a4acb36a0f29d55a4716a17cc33d770cdd82a 100644 --- a/app/code/Magento/SalesRule/Test/Unit/Model/Plugin/RuleTest.php +++ b/app/code/Magento/SalesRule/Test/Unit/Model/Plugin/RuleTest.php @@ -14,7 +14,7 @@ class RuleTest extends \PHPUnit_Framework_TestCase protected $plugin; /**} - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\SalesRule\Model\Rule|\PHPUnit_Framework_MockObject_MockObject */ protected $subject; @@ -36,11 +36,11 @@ class RuleTest extends \PHPUnit_Framework_TestCase $this->plugin = $objectManager->getObject('Magento\SalesRule\Model\Plugin\Rule'); } - public function testLoadCouponCode() + public function testLoadRelations() { $this->assertEquals( $this->subject, - $this->plugin->aroundLoadCouponCode($this->subject, $this->genericClosure) + $this->plugin->aroundLoadRelations($this->subject, $this->genericClosure) ); } } diff --git a/app/code/Magento/SalesRule/view/frontend/web/template/cart/totals/discount.html b/app/code/Magento/SalesRule/view/frontend/web/template/cart/totals/discount.html index 1797b8ff9c276d5d0e3ecb760b764e594410eaf3..b8a057ff065dd211efb54bc8b6167d441e7702dc 100644 --- a/app/code/Magento/SalesRule/view/frontend/web/template/cart/totals/discount.html +++ b/app/code/Magento/SalesRule/view/frontend/web/template/cart/totals/discount.html @@ -7,7 +7,7 @@ <!-- ko if: isDisplayed() --> <tr class="totals"> <th colspan="1" style="" class="mark" scope="row" data-bind="text: title"></th> - <td class="amount" data-bind="attr: {'data-th': $t(title) }"> + <td class="amount" data-bind="attr: {'data-th': title}"> <span><span class="price" data-bind="text: getValue()"></span></span> </td> </tr> diff --git a/app/code/Magento/SalesRule/view/frontend/web/template/summary/discount.html b/app/code/Magento/SalesRule/view/frontend/web/template/summary/discount.html index 60ac9c7982a5f6a0a510abd25fb67e4ee11dc13a..705541de3b4fc90bb16fad0d109b58d587380e26 100644 --- a/app/code/Magento/SalesRule/view/frontend/web/template/summary/discount.html +++ b/app/code/Magento/SalesRule/view/frontend/web/template/summary/discount.html @@ -11,7 +11,7 @@ <span class="discount coupon" data-bind="text: getCouponCode()"></span> </th> <td class="amount"> - <span class="price" data-bind="text: getValue(), attr: {'data-th': $t(name) }"></span> + <span class="price" data-bind="text: getValue(), attr: {'data-th': name}"></span> </td> </tr> <!-- /ko --> diff --git a/app/code/Magento/Shipping/Controller/Adminhtml/Order/ShipmentLoader.php b/app/code/Magento/Shipping/Controller/Adminhtml/Order/ShipmentLoader.php index 6bbaac5a04d4a34331323019cc7cbd4f03fbf704..c837623ac8ffd99323b1b116bbb8648db83f7433 100644 --- a/app/code/Magento/Shipping/Controller/Adminhtml/Order/ShipmentLoader.php +++ b/app/code/Magento/Shipping/Controller/Adminhtml/Order/ShipmentLoader.php @@ -12,14 +12,14 @@ use Magento\Framework\DataObject; * Class ShipmentLoader * * @package Magento\Shipping\Controller\Adminhtml\Order - * @method ShipmentLoader setOrderId - * @method ShipmentLoader setShipmentId - * @method ShipmentLoader setShipment - * @method ShipmentLoader setTracking - * @method int getOrderId - * @method int getShipmentId - * @method array getShipment - * @method array getTracking + * @method ShipmentLoader setOrderId($id) + * @method ShipmentLoader setShipmentId($id) + * @method ShipmentLoader setShipment($shipment) + * @method ShipmentLoader setTracking($tracking) + * @method int getOrderId() + * @method int getShipmentId() + * @method array getShipment() + * @method array getTracking() */ class ShipmentLoader extends DataObject { diff --git a/app/code/Magento/Store/i18n/de_DE.csv b/app/code/Magento/Store/i18n/de_DE.csv index e498731b13b2ca4ef3655fbedbdd1abce242bdd7..5cbbe3e5697db62873b9fc7128aaa82510709608 100644 --- a/app/code/Magento/Store/i18n/de_DE.csv +++ b/app/code/Magento/Store/i18n/de_DE.csv @@ -21,3 +21,6 @@ Layouts,Layouts "Paths to pre-processed view files (e.g, CSS files with fixed paths or generated from LESS files).","Paths to pre-processed view files (e.g, CSS files with fixed paths or generated from LESS files)." "Collections Data","Collections Data" "Collection data files.","Collection data files." +"All Stores","All Stores" +"Other Settings","Other Settings" +Attribute,Attribute diff --git a/app/code/Magento/Store/i18n/en_US.csv b/app/code/Magento/Store/i18n/en_US.csv index e498731b13b2ca4ef3655fbedbdd1abce242bdd7..5cbbe3e5697db62873b9fc7128aaa82510709608 100644 --- a/app/code/Magento/Store/i18n/en_US.csv +++ b/app/code/Magento/Store/i18n/en_US.csv @@ -21,3 +21,6 @@ Layouts,Layouts "Paths to pre-processed view files (e.g, CSS files with fixed paths or generated from LESS files).","Paths to pre-processed view files (e.g, CSS files with fixed paths or generated from LESS files)." "Collections Data","Collections Data" "Collection data files.","Collection data files." +"All Stores","All Stores" +"Other Settings","Other Settings" +Attribute,Attribute diff --git a/app/code/Magento/Store/i18n/es_ES.csv b/app/code/Magento/Store/i18n/es_ES.csv index e498731b13b2ca4ef3655fbedbdd1abce242bdd7..5cbbe3e5697db62873b9fc7128aaa82510709608 100644 --- a/app/code/Magento/Store/i18n/es_ES.csv +++ b/app/code/Magento/Store/i18n/es_ES.csv @@ -21,3 +21,6 @@ Layouts,Layouts "Paths to pre-processed view files (e.g, CSS files with fixed paths or generated from LESS files).","Paths to pre-processed view files (e.g, CSS files with fixed paths or generated from LESS files)." "Collections Data","Collections Data" "Collection data files.","Collection data files." +"All Stores","All Stores" +"Other Settings","Other Settings" +Attribute,Attribute diff --git a/app/code/Magento/Store/i18n/fr_FR.csv b/app/code/Magento/Store/i18n/fr_FR.csv index e498731b13b2ca4ef3655fbedbdd1abce242bdd7..5cbbe3e5697db62873b9fc7128aaa82510709608 100644 --- a/app/code/Magento/Store/i18n/fr_FR.csv +++ b/app/code/Magento/Store/i18n/fr_FR.csv @@ -21,3 +21,6 @@ Layouts,Layouts "Paths to pre-processed view files (e.g, CSS files with fixed paths or generated from LESS files).","Paths to pre-processed view files (e.g, CSS files with fixed paths or generated from LESS files)." "Collections Data","Collections Data" "Collection data files.","Collection data files." +"All Stores","All Stores" +"Other Settings","Other Settings" +Attribute,Attribute diff --git a/app/code/Magento/Store/i18n/nl_NL.csv b/app/code/Magento/Store/i18n/nl_NL.csv index e498731b13b2ca4ef3655fbedbdd1abce242bdd7..5cbbe3e5697db62873b9fc7128aaa82510709608 100644 --- a/app/code/Magento/Store/i18n/nl_NL.csv +++ b/app/code/Magento/Store/i18n/nl_NL.csv @@ -21,3 +21,6 @@ Layouts,Layouts "Paths to pre-processed view files (e.g, CSS files with fixed paths or generated from LESS files).","Paths to pre-processed view files (e.g, CSS files with fixed paths or generated from LESS files)." "Collections Data","Collections Data" "Collection data files.","Collection data files." +"All Stores","All Stores" +"Other Settings","Other Settings" +Attribute,Attribute diff --git a/app/code/Magento/Store/i18n/pt_BR.csv b/app/code/Magento/Store/i18n/pt_BR.csv index e498731b13b2ca4ef3655fbedbdd1abce242bdd7..5cbbe3e5697db62873b9fc7128aaa82510709608 100644 --- a/app/code/Magento/Store/i18n/pt_BR.csv +++ b/app/code/Magento/Store/i18n/pt_BR.csv @@ -21,3 +21,6 @@ Layouts,Layouts "Paths to pre-processed view files (e.g, CSS files with fixed paths or generated from LESS files).","Paths to pre-processed view files (e.g, CSS files with fixed paths or generated from LESS files)." "Collections Data","Collections Data" "Collection data files.","Collection data files." +"All Stores","All Stores" +"Other Settings","Other Settings" +Attribute,Attribute diff --git a/app/code/Magento/Store/i18n/zh_Hans_CN.csv b/app/code/Magento/Store/i18n/zh_Hans_CN.csv index e498731b13b2ca4ef3655fbedbdd1abce242bdd7..5cbbe3e5697db62873b9fc7128aaa82510709608 100644 --- a/app/code/Magento/Store/i18n/zh_Hans_CN.csv +++ b/app/code/Magento/Store/i18n/zh_Hans_CN.csv @@ -21,3 +21,6 @@ Layouts,Layouts "Paths to pre-processed view files (e.g, CSS files with fixed paths or generated from LESS files).","Paths to pre-processed view files (e.g, CSS files with fixed paths or generated from LESS files)." "Collections Data","Collections Data" "Collection data files.","Collection data files." +"All Stores","All Stores" +"Other Settings","Other Settings" +Attribute,Attribute diff --git a/app/code/Magento/Swatches/view/adminhtml/templates/catalog/product/attribute/text.phtml b/app/code/Magento/Swatches/view/adminhtml/templates/catalog/product/attribute/text.phtml index 63af3ebae14bcd7e0610c47b1485aaecd5f5b19f..1cdb50d54a34da6ba0a617a4bd64de64bf10921c 100644 --- a/app/code/Magento/Swatches/view/adminhtml/templates/catalog/product/attribute/text.phtml +++ b/app/code/Magento/Swatches/view/adminhtml/templates/catalog/product/attribute/text.phtml @@ -8,7 +8,7 @@ /** @var $block \Magento\Swatches\Block\Adminhtml\Attribute\Edit\Options\Text */ ?> -<fieldset class="fieldset ignore-validate"> +<fieldset class="fieldset"> <legend class="legend"><span><?php /* @escapeNotVerified */ echo __('Manage Swatch (values of your attribute)') ?></span></legend> <div id="swatch-text-options-panel"> <?php //@todo move style to css file ?> @@ -33,16 +33,23 @@ <th class="col-delete"> </th> </tr> </thead> - <tbody data-role="swatch-text-options-container"></tbody> + <tbody data-role="swatch-text-options-container" class="ignore-validate"></tbody> <tfoot> - <th colspan="<?php /* @escapeNotVerified */ echo $storetotal; ?>" class="col-actions-add"> - <?php if (!$block->getReadOnly() && !$block->canManageOptionDefaultOnly()):?> - <button id="add_new_swatch_text_option_button" title="<?php /* @escapeNotVerified */ echo __('Add Swatch'); ?>" - type="button" class="action- scalable add"> - <span><?php /* @escapeNotVerified */ echo __('Add Swatch'); ?></span> - </button> - <?php endif; ?> - </th> + <tr> + <th colspan="<?php /* @escapeNotVerified */ echo $storetotal; ?>"> + <input type="hidden" class="required-swatch-entry"/> + </th> + </tr> + <tr> + <th colspan="<?php /* @escapeNotVerified */ echo $storetotal; ?>" class="col-actions-add"> + <?php if (!$block->getReadOnly() && !$block->canManageOptionDefaultOnly()):?> + <button id="add_new_swatch_text_option_button" title="<?php /* @escapeNotVerified */ echo __('Add Swatch'); ?>" + type="button" class="action- scalable add"> + <span><?php /* @escapeNotVerified */ echo __('Add Swatch'); ?></span> + </button> + <?php endif; ?> + </th> + </tr> </tfoot> </table> <input type="hidden" id="swatch-text-option-count-check" value="" /> diff --git a/app/code/Magento/Swatches/view/adminhtml/templates/catalog/product/attribute/visual.phtml b/app/code/Magento/Swatches/view/adminhtml/templates/catalog/product/attribute/visual.phtml index a236cf00dd1ab38353d560feb986ed05001f0a96..3871ccda9a3efeff5c33fb93d60836c6c49de11e 100644 --- a/app/code/Magento/Swatches/view/adminhtml/templates/catalog/product/attribute/visual.phtml +++ b/app/code/Magento/Swatches/view/adminhtml/templates/catalog/product/attribute/visual.phtml @@ -8,7 +8,7 @@ /** @var $block \Magento\Swatches\Block\Adminhtml\Attribute\Edit\Options\Visual */ ?> -<fieldset class="fieldset ignore-validate"> +<fieldset class="fieldset"> <legend class="legend"><span><?php /* @escapeNotVerified */ echo __('Manage Swatch (values of your attribute)') ?></span></legend> <div id="swatch-visual-options-panel"> <?php //@todo move style to css file ?> @@ -29,16 +29,23 @@ <th class="col-delete"> </th> </tr> </thead> - <tbody data-role="swatch-visual-options-container"></tbody> + <tbody data-role="swatch-visual-options-container" class="ignore-validate"></tbody> <tfoot> - <th colspan="<?php /* @escapeNotVerified */ echo $storetotal; ?>" class="col-actions-add"> - <?php if (!$block->getReadOnly() && !$block->canManageOptionDefaultOnly()):?> - <button id="add_new_swatch_visual_option_button" title="<?php /* @escapeNotVerified */ echo __('Add Swatch'); ?>" - type="button" class="action- scalable add"> - <span><?php /* @escapeNotVerified */ echo __('Add Swatch'); ?></span> - </button> - <?php endif; ?> - </th> + <tr> + <th colspan="<?php /* @escapeNotVerified */ echo $storetotal; ?>"> + <input type="hidden" class="required-swatch-entry"/> + </th> + </tr> + <tr> + <th colspan="<?php /* @escapeNotVerified */ echo $storetotal; ?>" class="col-actions-add"> + <?php if (!$block->getReadOnly() && !$block->canManageOptionDefaultOnly()):?> + <button id="add_new_swatch_visual_option_button" title="<?php /* @escapeNotVerified */ echo __('Add Swatch'); ?>" + type="button" class="action- scalable add"> + <span><?php /* @escapeNotVerified */ echo __('Add Swatch'); ?></span> + </button> + <?php endif; ?> + </th> + </tr> </tfoot> </table> <input type="hidden" id="swatch-visual-option-count-check" value="" /> diff --git a/app/code/Magento/Tax/CustomerData/CheckoutTotalsJsLayoutDataProvider.php b/app/code/Magento/Tax/CustomerData/CheckoutTotalsJsLayoutDataProvider.php index 61a94b5a84887f13d8d32767fa0b57a8e82abd3d..35af16ecba53dc6f82b323786fe2f7ecf3a3e14a 100644 --- a/app/code/Magento/Tax/CustomerData/CheckoutTotalsJsLayoutDataProvider.php +++ b/app/code/Magento/Tax/CustomerData/CheckoutTotalsJsLayoutDataProvider.php @@ -61,7 +61,7 @@ class CheckoutTotalsJsLayoutDataProvider implements JsLayoutDataProviderInterfac protected function getTotalsConfig() { return [ - 'display_subtotal_incl_tax' => (int)$this->taxConfig->displayCartSubtotalInclTax(), + 'display_cart_subtotal_incl_tax' => (int)$this->taxConfig->displayCartSubtotalInclTax(), 'display_cart_subtotal_excl_tax' => (int)$this->taxConfig->displayCartSubtotalExclTax(), ]; } diff --git a/app/code/Magento/Tax/Model/Calculation/AbstractAggregateCalculator.php b/app/code/Magento/Tax/Model/Calculation/AbstractAggregateCalculator.php index 05bd7fd103dbf27124974334778fe7cc9b429b8b..488cba181ade7669f1267b9c3566ac4348e7570e 100644 --- a/app/code/Magento/Tax/Model/Calculation/AbstractAggregateCalculator.php +++ b/app/code/Magento/Tax/Model/Calculation/AbstractAggregateCalculator.php @@ -28,7 +28,7 @@ abstract class AbstractAggregateCalculator extends AbstractCalculator $priceInclTax = $this->calculationTool->round($item->getUnitPrice()); $rowTotalInclTax = $priceInclTax * $quantity; if (!$this->isSameRateAsStore($rate, $storeRate)) { - $priceInclTax = $this->calculatePriceInclTax($priceInclTax, $storeRate, $rate); + $priceInclTax = $this->calculatePriceInclTax($priceInclTax, $storeRate, $rate, $round); $rowTotalInclTax = $priceInclTax * $quantity; } $rowTaxExact = $this->calculationTool->calcTaxAmount($rowTotalInclTax, $rate, true, false); diff --git a/app/code/Magento/Tax/Model/Calculation/AbstractCalculator.php b/app/code/Magento/Tax/Model/Calculation/AbstractCalculator.php index d8ab3e259b27960515c7e1f19196132023215349..8f37546c839b79f2c38bf118c636b2ca5a4d32e9 100644 --- a/app/code/Magento/Tax/Model/Calculation/AbstractCalculator.php +++ b/app/code/Magento/Tax/Model/Calculation/AbstractCalculator.php @@ -433,14 +433,18 @@ abstract class AbstractCalculator * @param float $storePriceInclTax * @param float $storeRate * @param float $customerRate + * @param boolean $round * @return float */ - protected function calculatePriceInclTax($storePriceInclTax, $storeRate, $customerRate) + protected function calculatePriceInclTax($storePriceInclTax, $storeRate, $customerRate, $round = true) { $storeTax = $this->calculationTool->calcTaxAmount($storePriceInclTax, $storeRate, true, false); $priceExclTax = $storePriceInclTax - $storeTax; $customerTax = $this->calculationTool->calcTaxAmount($priceExclTax, $customerRate, false, false); - $customerPriceInclTax = $this->calculationTool->round($priceExclTax + $customerTax); + $customerPriceInclTax = $priceExclTax + $customerTax; + if ($round) { + $customerPriceInclTax = $this->calculationTool->round($customerPriceInclTax); + } return $customerPriceInclTax; } } diff --git a/app/code/Magento/Tax/Model/Calculation/UnitBaseCalculator.php b/app/code/Magento/Tax/Model/Calculation/UnitBaseCalculator.php index 37c22cf5e147c4d4c7a01420650dd39a71d3e7da..fa8fa61379295bf6304781cad377f1123471b39e 100644 --- a/app/code/Magento/Tax/Model/Calculation/UnitBaseCalculator.php +++ b/app/code/Magento/Tax/Model/Calculation/UnitBaseCalculator.php @@ -45,7 +45,7 @@ class UnitBaseCalculator extends AbstractCalculator $applyTaxAfterDiscount = $this->config->applyTaxAfterDiscount($this->storeId); $priceInclTax = $this->calculationTool->round($item->getUnitPrice()); if (!$this->isSameRateAsStore($rate, $storeRate)) { - $priceInclTax = $this->calculatePriceInclTax($priceInclTax, $storeRate, $rate); + $priceInclTax = $this->calculatePriceInclTax($priceInclTax, $storeRate, $rate, $round); } $uniTax = $this->calculationTool->calcTaxAmount($priceInclTax, $rate, true, false); $deltaRoundingType = self::KEY_REGULAR_DELTA_ROUNDING; diff --git a/app/code/Magento/Tax/Model/Sales/Total/Quote/Tax.php b/app/code/Magento/Tax/Model/Sales/Total/Quote/Tax.php index c1cd2b9927c2fb1ba0db506fba2bf61a96344c05..34562754e0893aa11164945fc8e837db67c19d1b 100644 --- a/app/code/Magento/Tax/Model/Sales/Total/Quote/Tax.php +++ b/app/code/Magento/Tax/Model/Sales/Total/Quote/Tax.php @@ -88,6 +88,7 @@ class Tax extends CommonTaxCollector * @param ShippingAssignmentInterface $shippingAssignment * @param Address\Total $total * @return $this + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function collect( \Magento\Quote\Model\Quote $quote, @@ -291,6 +292,7 @@ class Tax extends CommonTaxCollector * @param Address\Total $total * @return array|null * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) */ public function fetch(\Magento\Quote\Model\Quote $quote, \Magento\Quote\Model\Quote\Address\Total $total) { @@ -298,6 +300,10 @@ class Tax extends CommonTaxCollector $store = $quote->getStore(); $applied = $total->getAppliedTaxes(); $amount = $total->getTaxAmount(); + if ($amount == null) { + $this->enhanceTotalData($quote, $total); + $amount = $total->getTaxAmount(); + } $taxAmount = $amount + $total->getTotalAmount('discount_tax_compensation'); $area = null; @@ -340,6 +346,44 @@ class Tax extends CommonTaxCollector return $totals; } + /** + * Adds minimal tax information to the "total" data structure + * + * @param \Magento\Quote\Model\Quote $quote + * @param Address\Total $total + * @return null + */ + protected function enhanceTotalData( + \Magento\Quote\Model\Quote $quote, + \Magento\Quote\Model\Quote\Address\Total $total + ) { + $taxAmount = 0; + $shippingTaxAmount = 0; + $discountTaxCompensation = 0; + + $subtotalInclTax = $total->getSubtotalInclTax(); + $computeSubtotalInclTax = true; + if ($total->getSubtotalInclTax() > 0) { + $computeSubtotalInclTax = false; + } + + /** @var \Magento\Quote\Model\Quote\Address $address */ + foreach ($quote->getAllAddresses() as $address) { + $taxAmount += $address->getTaxAmount(); + $shippingTaxAmount += $address->getShippingTaxAmount(); + $discountTaxCompensation += $address->getDiscountTaxCompensationAmount(); + if ($computeSubtotalInclTax) { + $subtotalInclTax += $address->getSubtotalInclTax(); + } + } + + $total->setTaxAmount($taxAmount); + $total->setShippingTaxAmount($shippingTaxAmount); + $total->setDiscountTaxCompensationAmount($discountTaxCompensation); // accessed via 'discount_tax_compensation' + $total->setSubtotalInclTax($subtotalInclTax); + return; + } + /** * Process model configuration array. * This method can be used for changing totals collect sort order diff --git a/app/code/Magento/Tax/Test/Unit/Model/Calculation/RowBaseAndTotalBaseCalculatorTestCase.php b/app/code/Magento/Tax/Test/Unit/Model/Calculation/RowBaseAndTotalBaseCalculatorTestCase.php index c4c271aef036101adb3366f5ab3588f7f65b2ed6..da0d9154d19bc7dd4be291a96537fdcde10e983f 100644 --- a/app/code/Magento/Tax/Test/Unit/Model/Calculation/RowBaseAndTotalBaseCalculatorTestCase.php +++ b/app/code/Magento/Tax/Test/Unit/Model/Calculation/RowBaseAndTotalBaseCalculatorTestCase.php @@ -20,6 +20,9 @@ class RowBaseAndTotalBaseCalculatorTestCase extends \PHPUnit_Framework_TestCase const RATE = 10; const STORE_RATE = 11; + const UNIT_PRICE_INCL_TAX = 495.49549549545; + const UNIT_PRICE_INCL_TAX_ROUNDED = 495.5; + const CODE = 'CODE'; const TYPE = 'TYPE'; @@ -71,7 +74,7 @@ class RowBaseAndTotalBaseCalculatorTestCase extends \PHPUnit_Framework_TestCase { $this->initMockItem($isTaxIncluded); $this->initMockConfig(); - $this->initMockCalculationTool(); + $this->initMockCalculationTool($isTaxIncluded); $this->initMockAppliedTaxDataObjectFactory(); } @@ -93,7 +96,7 @@ class RowBaseAndTotalBaseCalculatorTestCase extends \PHPUnit_Framework_TestCase $this->mockCalculationTool = $this->getMockBuilder('\Magento\Tax\Model\Calculation') ->disableOriginalConstructor() ->setMethods( - ['__wakeup', 'round', 'getRate', 'getStoreRate', 'getRateRequest', 'getAppliedRates', 'calcTaxAmount'] + ['__wakeup', 'round', 'getRate', 'getStoreRate', 'getRateRequest', 'getAppliedRates'] ) ->getMock(); $this->mockConfig = $this->getMockBuilder('\Magento\Tax\Model\Config') @@ -129,11 +132,12 @@ class RowBaseAndTotalBaseCalculatorTestCase extends \PHPUnit_Framework_TestCase /** * @param $calculator RowBaseCalculator|TotalBaseCalculator + * @param boolean $round * @return \Magento\Tax\Api\Data\TaxDetailsItemInterface */ - public function calculate($calculator) + public function calculate($calculator, $round = true) { - return $calculator->calculate($this->mockItem, 1); + return $calculator->calculate($this->mockItem, 1, $round); } /** @@ -147,7 +151,7 @@ class RowBaseAndTotalBaseCalculatorTestCase extends \PHPUnit_Framework_TestCase $this->mockItem, [ [ - self::ONCE => true, + self::ONCE => false, self::MOCK_METHOD_NAME => 'getDiscountAmount', self::MOCK_VALUE => 1, ], @@ -157,17 +161,17 @@ class RowBaseAndTotalBaseCalculatorTestCase extends \PHPUnit_Framework_TestCase self::MOCK_VALUE => self::CODE ], [ - self::ONCE => true, + self::ONCE => false, self::MOCK_METHOD_NAME => 'getType', self::MOCK_VALUE => self::TYPE ], [ - self::ONCE => true, + self::ONCE => false, self::MOCK_METHOD_NAME => 'getUnitPrice', self::MOCK_VALUE => self::UNIT_PRICE ], [ - self::ONCE => true, + self::ONCE => false, self::MOCK_METHOD_NAME => 'getIsTaxIncluded', self::MOCK_VALUE => $isTaxIncluded ] @@ -185,7 +189,7 @@ class RowBaseAndTotalBaseCalculatorTestCase extends \PHPUnit_Framework_TestCase $this->mockConfig, [ [ - self::ONCE => true, + self::ONCE => false, self::MOCK_METHOD_NAME => 'applyTaxAfterDiscount', self::MOCK_VALUE => true, ] @@ -196,47 +200,55 @@ class RowBaseAndTotalBaseCalculatorTestCase extends \PHPUnit_Framework_TestCase /** * init mock calculation model * + * @param boolean $isTaxIncluded */ - protected function initMockCalculationTool() + protected function initMockCalculationTool($isTaxIncluded) { - $this->mockReturnValues( - $this->mockCalculationTool, + $mockValues = [ [ - [ - self::ONCE => false, - self::MOCK_METHOD_NAME => 'calcTaxAmount', - self::MOCK_VALUE => 1.5, - ], - [ - self::ONCE => true, - self::MOCK_METHOD_NAME => 'getRate', - self::MOCK_VALUE => self::RATE - ], - [ - self::ONCE => true, - self::MOCK_METHOD_NAME => 'getAppliedRates', - self::MOCK_VALUE => [ - [ - 'id' => 0, - 'percent' => 1.4, - 'rates' => [ - [ - 'code' => 'sku_1', - 'title' => 'title1', - 'percent' => 1.1, - ], + self::ONCE => false, + self::MOCK_METHOD_NAME => 'getRate', + self::MOCK_VALUE => self::RATE + ], + [ + self::ONCE => false, + self::MOCK_METHOD_NAME => 'getAppliedRates', + self::MOCK_VALUE => [ + [ + 'id' => 0, + 'percent' => 1.4, + 'rates' => [ + [ + 'code' => 'sku_1', + 'title' => 'title1', + 'percent' => 1.1, ], ], - ] - ], - [ - self::ONCE => false, - self::MOCK_METHOD_NAME => 'round', - self::MOCK_VALUE => 1.3 + ], ] - ] + ], + ]; + + if ($isTaxIncluded) { + $mockValues[] = [ + self::ONCE => false, + self::MOCK_METHOD_NAME => 'getStoreRate', + self::MOCK_VALUE => self::STORE_RATE + ]; + } + + $this->mockReturnValues( + $this->mockCalculationTool, + $mockValues ); + $this->mockCalculationTool->expects($this->atLeastOnce()) + ->method('round') + ->willReturnCallback( + function ($price) { + return round($price, 2); + } + ); } /** @@ -249,7 +261,7 @@ class RowBaseAndTotalBaseCalculatorTestCase extends \PHPUnit_Framework_TestCase $this->appliedTaxDataObjectFactory, [ [ - self::ONCE => true, + self::ONCE => false, self::MOCK_METHOD_NAME => 'create', self::MOCK_VALUE => $this->mockAppliedTax, ] diff --git a/app/code/Magento/Tax/Test/Unit/Model/Calculation/RowBaseCalculatorTest.php b/app/code/Magento/Tax/Test/Unit/Model/Calculation/RowBaseCalculatorTest.php index 3de3c4b10ea28f0805e3598ad8bd581288339c88..ebf9239463a61ceaa05dde8fd99bb42cee6e62cf 100644 --- a/app/code/Magento/Tax/Test/Unit/Model/Calculation/RowBaseCalculatorTest.php +++ b/app/code/Magento/Tax/Test/Unit/Model/Calculation/RowBaseCalculatorTest.php @@ -26,8 +26,15 @@ class RowBaseCalculatorTest extends RowBaseAndTotalBaseCalculatorTestCase $this->assertSame( $this->taxDetailsItem, - $this->calculate($this->rowBaseCalculator) + $this->calculate($this->rowBaseCalculator, true) + ); + $this->assertEquals(self::UNIT_PRICE_INCL_TAX_ROUNDED, $this->taxDetailsItem->getPriceInclTax()); + + $this->assertSame( + $this->taxDetailsItem, + $this->calculate($this->rowBaseCalculator, false) ); + $this->assertEquals(self::UNIT_PRICE_INCL_TAX, $this->taxDetailsItem->getPriceInclTax()); } public function testCalculateWithTaxNotInPrice() diff --git a/app/code/Magento/Tax/Test/Unit/Model/Calculation/TotalBaseCalculatorTest.php b/app/code/Magento/Tax/Test/Unit/Model/Calculation/TotalBaseCalculatorTest.php index 880b9d57c81b56cc4750fa4da8de4cd6496c0495..d5c0c0ef85c8701778a651540880d8d6f8439dd6 100644 --- a/app/code/Magento/Tax/Test/Unit/Model/Calculation/TotalBaseCalculatorTest.php +++ b/app/code/Magento/Tax/Test/Unit/Model/Calculation/TotalBaseCalculatorTest.php @@ -22,6 +22,21 @@ class TotalBaseCalculatorTest extends RowBaseAndTotalBaseCalculatorTestCase $this->taxDetailsItem, $this->calculate($this->totalBaseCalculator) ); + $this->assertEquals(self::UNIT_PRICE_INCL_TAX_ROUNDED, $this->taxDetailsItem->getPriceInclTax()); + } + + public function testCalculateWithTaxInPriceNoRounding() + { + $this->initTotalBaseCalculator(); + $this->totalBaseCalculator->expects($this->exactly(3)) + ->method('deltaRound')->will($this->returnValue(0)); + $this->initMocks(true); + + $this->assertSame( + $this->taxDetailsItem, + $this->calculate($this->totalBaseCalculator, false) + ); + $this->assertEquals(self::UNIT_PRICE_INCL_TAX, $this->taxDetailsItem->getPriceInclTax()); } public function testCalculateWithTaxNotInPrice() diff --git a/app/code/Magento/Tax/Test/Unit/Model/Calculation/UnitBaseCalculatorTest.php b/app/code/Magento/Tax/Test/Unit/Model/Calculation/UnitBaseCalculatorTest.php index 9f69f1a2035bf1f8bd629490d795f0f64c1007c3..bed813c1f188860769a2316b55ed3665781d6f8f 100644 --- a/app/code/Magento/Tax/Test/Unit/Model/Calculation/UnitBaseCalculatorTest.php +++ b/app/code/Magento/Tax/Test/Unit/Model/Calculation/UnitBaseCalculatorTest.php @@ -18,7 +18,10 @@ class UnitBaseCalculatorTest extends \PHPUnit_Framework_TestCase const CODE = 'CODE'; const TYPE = 'TYPE'; - const ROW_TAX = 44.954136954136; + const ROW_TAX = 44.958682408681; + const ROW_TAX_ROUNDED = 44.95; + const PRICE_INCL_TAX = 495.4954954955; + const PRICE_INCL_TAX_ROUNDED = 495.50; /** @var \PHPUnit_Framework_MockObject_MockObject */ protected $taxDetailsItemDataObjectFactoryMock; @@ -68,7 +71,11 @@ class UnitBaseCalculatorTest extends \PHPUnit_Framework_TestCase $this->mockCalculationTool->expects($this->any()) ->method('round') ->withAnyParameters() - ->will($this->returnArgument(0)); + ->willReturnCallback( + function ($price) { + return round($price, 2); + } + ); $this->mockConfig = $this->getMockBuilder('\Magento\Tax\Model\Config') ->disableOriginalConstructor() ->getMock(); @@ -113,26 +120,26 @@ class UnitBaseCalculatorTest extends \PHPUnit_Framework_TestCase public function testCalculateWithTaxInPrice() { $mockItem = $this->getMockItem(); - $mockItem->expects($this->once()) + $mockItem->expects($this->atLeastOnce()) ->method('getIsTaxIncluded') ->will($this->returnValue(true)); - $this->mockConfig->expects($this->once()) + $this->mockConfig->expects($this->atLeastOnce()) ->method('crossBorderTradeEnabled') ->will($this->returnValue(false)); - $this->mockConfig->expects($this->once()) + $this->mockConfig->expects($this->atLeastOnce()) ->method('applyTaxAfterDiscount') ->will($this->returnValue(true)); - $this->mockCalculationTool->expects($this->once()) + $this->mockCalculationTool->expects($this->atLeastOnce()) ->method('getRate') ->with($this->addressRateRequest) ->will($this->returnValue(self::RATE)); - $this->mockCalculationTool->expects($this->once()) + $this->mockCalculationTool->expects($this->atLeastOnce()) ->method('getStoreRate') ->with($this->addressRateRequest, self::STORE_ID) ->will($this->returnValue(self::STORE_RATE)); - $this->mockCalculationTool->expects($this->once()) + $this->mockCalculationTool->expects($this->atLeastOnce()) ->method('getAppliedRates') ->withAnyParameters() ->will($this->returnValue([])); @@ -140,7 +147,14 @@ class UnitBaseCalculatorTest extends \PHPUnit_Framework_TestCase $this->assertSame($this->taxDetailsItem, $this->model->calculate($mockItem, self::QUANTITY)); $this->assertSame(self::CODE, $this->taxDetailsItem->getCode()); $this->assertSame(self::TYPE, $this->taxDetailsItem->getType()); + $this->assertSame(self::ROW_TAX_ROUNDED, $this->taxDetailsItem->getRowTax()); + $this->assertEquals(self::PRICE_INCL_TAX_ROUNDED, $this->taxDetailsItem->getPriceInclTax()); + + $this->assertSame($this->taxDetailsItem, $this->model->calculate($mockItem, self::QUANTITY, false)); + $this->assertSame(self::CODE, $this->taxDetailsItem->getCode()); + $this->assertSame(self::TYPE, $this->taxDetailsItem->getType()); $this->assertSame(self::ROW_TAX, $this->taxDetailsItem->getRowTax()); + $this->assertEquals(self::PRICE_INCL_TAX, $this->taxDetailsItem->getPriceInclTax()); } public function testCalculateWithTaxNotInPrice() @@ -178,16 +192,16 @@ class UnitBaseCalculatorTest extends \PHPUnit_Framework_TestCase $mockItem = $this->getMockBuilder('Magento\Tax\Api\Data\QuoteDetailsItemInterface') ->disableOriginalConstructor() ->getMock(); - $mockItem->expects($this->once()) + $mockItem->expects($this->atLeastOnce()) ->method('getDiscountAmount') ->will($this->returnValue(1)); $mockItem->expects($this->atLeastOnce()) ->method('getCode') ->will($this->returnValue(self::CODE)); - $mockItem->expects($this->once()) + $mockItem->expects($this->atLeastOnce()) ->method('getType') ->will($this->returnValue(self::TYPE)); - $mockItem->expects($this->once()) + $mockItem->expects($this->atLeastOnce()) ->method('getUnitPrice') ->will($this->returnValue(self::UNIT_PRICE)); diff --git a/app/code/Magento/Tax/Test/Unit/Model/Sales/Total/Quote/TaxTest.php b/app/code/Magento/Tax/Test/Unit/Model/Sales/Total/Quote/TaxTest.php index b5c223f0a6287acf8ad920a7b35cc6391a2a95e7..ee093ee6807bc586dc2ee41a1179d396726afc7a 100644 --- a/app/code/Magento/Tax/Test/Unit/Model/Sales/Total/Quote/TaxTest.php +++ b/app/code/Magento/Tax/Test/Unit/Model/Sales/Total/Quote/TaxTest.php @@ -576,7 +576,7 @@ class TaxTest extends \PHPUnit_Framework_TestCase /** * Tests the specific method * - * @param string $itemData + * @param string $appliedTaxesData * @param array $addressData * * @dataProvider dataProviderFetchArray @@ -584,7 +584,8 @@ class TaxTest extends \PHPUnit_Framework_TestCase */ public function testFetch($appliedTaxesData, $addressData) { - $methods = ['getAppliedTaxes', 'getTaxAmount', 'getTotalAmount', 'getGrandTotal', 'getSubtotalInclTax']; + $taxAmount = 8; + $methods = ['getAppliedTaxes', 'getTotalAmount', 'getGrandTotal', 'getSubtotalInclTax']; $totalsMock = $this->getMock('Magento\Quote\Model\Quote\Address\Total', $methods, [], '', false); $taxConfig = $this->getMockBuilder('\Magento\Tax\Model\Config') ->disableOriginalConstructor() @@ -632,10 +633,6 @@ class TaxTest extends \PHPUnit_Framework_TestCase ->expects($this->once()) ->method('getAppliedTaxes') ->will($this->returnValue($appliedTaxes)); - $address - ->expects($this->any()) - ->method('getQuote') - ->will($this->returnValue($quote)); $totalsMock ->expects($this->any()) ->method('getGrandTotal') @@ -644,10 +641,17 @@ class TaxTest extends \PHPUnit_Framework_TestCase ->expects($this->any()) ->method('getStore') ->will($this->returnValue($store)); + $quote->expects($this->any()) + ->method('getAllAddresses') + ->will($this->returnValue([$address])); + $address + ->expects($this->any()) + ->method('getQuote') + ->will($this->returnValue($quote)); $address ->expects($this->any()) ->method('getTaxAmount') - ->will($this->returnValue(8)); + ->will($this->returnValue($taxAmount)); $address ->expects($this->any()) ->method('getCustomAttributesCodes') @@ -658,7 +662,10 @@ class TaxTest extends \PHPUnit_Framework_TestCase $address->setData($key, $value); } - $taxTotalsCalcModel->fetch($quote, $totalsMock); + $this->assertNull($totalsMock->getTaxAmount()); + $totalsArray = $taxTotalsCalcModel->fetch($quote, $totalsMock); + $this->assertArrayHasKey('value', $totalsArray[0]); + $this->assertEquals($taxAmount, $totalsArray[0]['value']); } /** diff --git a/app/code/Magento/Tax/Test/Unit/Setup/TaxSetupTest.php b/app/code/Magento/Tax/Test/Unit/Setup/TaxSetupTest.php index c42a28490e3442ad20d004b535abfb6994ef3262..151cd1876c40294acb1e7bd0d013b4e8955ae6f4 100644 --- a/app/code/Magento/Tax/Test/Unit/Setup/TaxSetupTest.php +++ b/app/code/Magento/Tax/Test/Unit/Setup/TaxSetupTest.php @@ -19,11 +19,19 @@ class TaxSetupTest extends \PHPUnit_Framework_TestCase protected function setUp() { - $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->typeConfigMock = $this->getMock('Magento\Catalog\Model\ProductTypes\ConfigInterface'); + + $salesSetup = $this->getMock('\Magento\Sales\Setup\SalesSetup', [], [], '', false); + $salesSetupFactory = $this->getMock('Magento\Sales\Setup\SalesSetupFactory', ['create'], [], '', false); + $salesSetupFactory->expects($this->any())->method('create')->will($this->returnValue($salesSetup)); + + $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->taxSetup = $helper->getObject( 'Magento\Tax\Setup\TaxSetup', - ['productTypeConfig' => $this->typeConfigMock] + [ + 'productTypeConfig' => $this->typeConfigMock, + 'salesSetupFactory' => $salesSetupFactory, + ] ); } diff --git a/app/code/Magento/Tax/i18n/de_DE.csv b/app/code/Magento/Tax/i18n/de_DE.csv index 2365399967075268f0f0216770da3295cb27bba0..4fc035fa2f4a311e7ecfc689c6fb355f336671bb 100644 --- a/app/code/Magento/Tax/i18n/de_DE.csv +++ b/app/code/Magento/Tax/i18n/de_DE.csv @@ -157,3 +157,5 @@ Note:,Note: "Orders, Invoices, Credit Memos Display Settings","Orders, Invoices, Credit Memos Display Settings" State/Region,Bundesstaat/Region "Subtotal Only","Subtotal Only" +Taxes,Taxes +"Import/Export Tax Rates","Import/Export Tax Rates" diff --git a/app/code/Magento/Tax/i18n/en_US.csv b/app/code/Magento/Tax/i18n/en_US.csv index 078cef5d97b22d509be9cefcd6ded7e3abd56629..af228accb3440110e6172e35b33168e274b3deaa 100644 --- a/app/code/Magento/Tax/i18n/en_US.csv +++ b/app/code/Magento/Tax/i18n/en_US.csv @@ -157,3 +157,5 @@ Note:,Note: "Orders, Invoices, Credit Memos Display Settings","Orders, Invoices, Credit Memos Display Settings" State/Region,State/Region "Subtotal Only","Subtotal Only" +Taxes,Taxes +"Import/Export Tax Rates","Import/Export Tax Rates" diff --git a/app/code/Magento/Tax/i18n/es_ES.csv b/app/code/Magento/Tax/i18n/es_ES.csv index 999f3930c262c6cad3e89e6d12601d8e18bbe016..b97d5fe9cb3eec69d81bcaa5aad642f9dad170a8 100644 --- a/app/code/Magento/Tax/i18n/es_ES.csv +++ b/app/code/Magento/Tax/i18n/es_ES.csv @@ -157,3 +157,5 @@ Note:,Note: "Orders, Invoices, Credit Memos Display Settings","Orders, Invoices, Credit Memos Display Settings" State/Region,Estado/Región "Subtotal Only","Subtotal Only" +Taxes,Taxes +"Import/Export Tax Rates","Import/Export Tax Rates" diff --git a/app/code/Magento/Tax/i18n/fr_FR.csv b/app/code/Magento/Tax/i18n/fr_FR.csv index bf297e3d67360cb1c8bd3c8242e46fe96fbc7fb7..2687af941e9b2ee07dc46311a1ff8d0d46a84353 100644 --- a/app/code/Magento/Tax/i18n/fr_FR.csv +++ b/app/code/Magento/Tax/i18n/fr_FR.csv @@ -157,3 +157,5 @@ Note:,Note: "Orders, Invoices, Credit Memos Display Settings","Orders, Invoices, Credit Memos Display Settings" State/Region,État/Région "Subtotal Only","Subtotal Only" +Taxes,Taxes +"Import/Export Tax Rates","Import/Export Tax Rates" diff --git a/app/code/Magento/Tax/i18n/nl_NL.csv b/app/code/Magento/Tax/i18n/nl_NL.csv index ac644e6510cc1478a1b7a9b1b6a780e80cf8888c..212f01a0c4761fe4fd9694798f60fb95ae839db7 100644 --- a/app/code/Magento/Tax/i18n/nl_NL.csv +++ b/app/code/Magento/Tax/i18n/nl_NL.csv @@ -157,3 +157,5 @@ Note:,Note: "Orders, Invoices, Credit Memos Display Settings","Orders, Invoices, Credit Memos Display Settings" State/Region,Provincie "Subtotal Only","Subtotal Only" +Taxes,Taxes +"Import/Export Tax Rates","Import/Export Tax Rates" diff --git a/app/code/Magento/Tax/i18n/pt_BR.csv b/app/code/Magento/Tax/i18n/pt_BR.csv index 2c52eee8e592aaebe71c3cfc598032cf2257c7e1..d22d24f7218e324c1d0c3e3ea4b44361ee91a6af 100644 --- a/app/code/Magento/Tax/i18n/pt_BR.csv +++ b/app/code/Magento/Tax/i18n/pt_BR.csv @@ -157,3 +157,5 @@ Note:,Note: "Orders, Invoices, Credit Memos Display Settings","Orders, Invoices, Credit Memos Display Settings" State/Region,Estado/Região "Subtotal Only","Subtotal Only" +Taxes,Taxes +"Import/Export Tax Rates","Import/Export Tax Rates" diff --git a/app/code/Magento/Tax/i18n/zh_Hans_CN.csv b/app/code/Magento/Tax/i18n/zh_Hans_CN.csv index d47d26b939bd199abc6c46c2e69e7dad6edaff95..2a4d9e43e27e0972cd50eb939f4871c3be2e0644 100644 --- a/app/code/Magento/Tax/i18n/zh_Hans_CN.csv +++ b/app/code/Magento/Tax/i18n/zh_Hans_CN.csv @@ -157,3 +157,5 @@ Note:,Note: "Orders, Invoices, Credit Memos Display Settings","Orders, Invoices, Credit Memos Display Settings" State/Region,å·ž/地区 "Subtotal Only","Subtotal Only" +Taxes,Taxes +"Import/Export Tax Rates","Import/Export Tax Rates" diff --git a/app/code/Magento/Tax/view/adminhtml/templates/rule/edit.phtml b/app/code/Magento/Tax/view/adminhtml/templates/rule/edit.phtml index e04ddfeeefeb8028d1d6159558ef2340b8e80c1c..22adf3c427eaad459e2e317e943f984838e8ef5b 100644 --- a/app/code/Magento/Tax/view/adminhtml/templates/rule/edit.phtml +++ b/app/code/Magento/Tax/view/adminhtml/templates/rule/edit.phtml @@ -88,7 +88,7 @@ require([ item.itemElement = that.prev(); $('#tax-rate-form') .dialogRates({itemRate: item}) - .dialogRates('open'); + .dialogRates('openModal'); } else { if (result.error_message) diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/cart/totals/grand-total.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/cart/totals/grand-total.html index f756837bb1e7aa3be01ea1958ec7293ff99fe2bd..31bf3448f2020c312eae0b3667ba5e85f83a89c1 100644 --- a/app/code/Magento/Tax/view/frontend/web/template/checkout/cart/totals/grand-total.html +++ b/app/code/Magento/Tax/view/frontend/web/template/checkout/cart/totals/grand-total.html @@ -7,17 +7,17 @@ <!-- ko if: isTaxDisplayedInGrandTotal && isDisplayed() --> <tr class="grand totals incl"> <th class="mark" scope="row"> - <strong data-bind="text: $t(inclTaxLabel)"></strong> + <strong data-bind="text: inclTaxLabel"></strong> </th> - <td data-bind="attr: {'data-th': $t(inclTaxLabel) }" class="amount"> + <td data-bind="attr: {'data-th': inclTaxLabel}" class="amount"> <strong><span class="price" data-bind="text: getValue()"></span></strong> </td> </tr> <tr class="grand totals excl"> <th class="mark" scope="row"> - <strong data-bind="text: $t(exclTaxLabel)"></strong> + <strong data-bind="text: exclTaxLabel"></strong> </th> - <td data-bind="attr: {'data-th': exclTaxLabel }" class="amount"> + <td data-bind="attr: {'data-th': exclTaxLabel}" class="amount"> <strong><span class="price" data-bind="text: getGrandTotalExclTax()"></span></strong> </td> </tr> @@ -25,9 +25,9 @@ <!-- ko if: !isTaxDisplayedInGrandTotal && isDisplayed() --> <tr class="grand totals"> <th class="mark" scope="row"> - <strong data-bind="text: $t(title)"></strong> + <strong data-bind="text: title"></strong> </th> - <td data-bind="attr: {'data-th': $t(title)}" class="amount"> + <td data-bind="attr: {'data-th': title}" class="amount"> <strong><span class="price" data-bind="text: getValue()"></span></strong> </td> </tr> diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/cart/totals/shipping.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/cart/totals/shipping.html index 13fe7f3e716a63b661d5bf96e91dc1320435233e..37a8e82688a83dd963bcbdf07d235807854a26ca 100644 --- a/app/code/Magento/Tax/view/frontend/web/template/checkout/cart/totals/shipping.html +++ b/app/code/Magento/Tax/view/frontend/web/template/checkout/cart/totals/shipping.html @@ -8,46 +8,46 @@ <!-- ko if: isBothPricesDisplayed() --> <tr class="totals shipping excl"> <th class="mark" scope="row"> - <span class="label" data-bind="text: $t(title) + ' ' + $t(excludingTaxMessage)"></span> - <span class="value" data-bind="text: $t(getShippingMethodTitle())"></span> + <span class="label" data-bind="text: title + ' ' + excludingTaxMessage"></span> + <span class="value" data-bind="text: getShippingMethodTitle()"></span> </th> <td class="amount"> <span class="price" - data-bind="text: $t(getExcludingValue()), attr: {'data-th': $t(excludingTaxMessage)}"></span> + data-bind="text: getExcludingValue(), attr: {'data-th': excludingTaxMessage}"></span> </td> </tr> <tr class="totals shipping incl"> <th class="mark" scope="row"> - <span class="label" data-bind="text: $t(title) + ' ' + $t(includingTaxMessage)"></span> - <span class="value" data-bind="text: $t(getShippingMethodTitle())"></span> + <span class="label" data-bind="text: title + ' ' + includingTaxMessage"></span> + <span class="value" data-bind="text: getShippingMethodTitle()"></span> </th> <td class="amount"> <span class="price" - data-bind="text: $t(getIncludingValue()), attr: {'data-th': $t(title) + ' ' + $t(excludingTaxMessage)}"></span> + data-bind="text: getIncludingValue(), attr: {'data-th': title + ' ' + excludingTaxMessage}"></span> </td> </tr> <!-- /ko --> <!-- ko if: isIncludingDisplayed() --> <tr class="totals shipping incl"> <th class="mark" scope="row"> - <span class="label" data-bind="text: $t(title)"></span> - <span class="value" data-bind="text: $t(getShippingMethodTitle())"></span> + <span class="label" data-bind="text: title"></span> + <span class="value" data-bind="text: getShippingMethodTitle()"></span> </th> <td class="amount"> <span class="price" - data-bind="text: $t(getIncludingValue()), attr: {'data-th': $t(title)}"></span> + data-bind="text: getIncludingValue(), attr: {'data-th': title}"></span> </td> </tr> <!-- /ko --> <!-- ko if: isExcludingDisplayed() --> <tr class="totals shipping excl"> <th class="mark" scope="row"> - <span class="label" data-bind="text: $t(title)"></span> - <span class="value" data-bind="text: $t(getShippingMethodTitle())"></span> + <span class="label" data-bind="text: title"></span> + <span class="value" data-bind="text: getShippingMethodTitle()"></span> </th> <td class="amount"> <span class="price" - data-bind="text: $t(getValue()), attr: {'data-th': $t(title)}"></span> + data-bind="text: getValue(), attr: {'data-th': title}"></span> </td> </tr> <!-- /ko --> diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/cart/totals/tax.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/cart/totals/tax.html index c6f4c7833e0c0f346d70d1e350b82ad5522fb5c5..8d70052ddc2288568187cd9b041937a0c65e7ddb 100644 --- a/app/code/Magento/Tax/view/frontend/web/template/checkout/cart/totals/tax.html +++ b/app/code/Magento/Tax/view/frontend/web/template/checkout/cart/totals/tax.html @@ -7,9 +7,9 @@ <!-- ko if: ifShowValue() && !ifShowDetails() --> <tr class="totals-tax"> - <th data-bind="text: $t(title)" class="mark" colspan="1" scope="row"></th> - <td data-bind="attr: {'data-th': $t(title) }" class="amount"> - <span class="price" data-bind="text: $t(getValue())"></span> + <th data-bind="text: title" class="mark" colspan="1" scope="row"></th> + <td data-bind="attr: {'data-th': title}" class="amount"> + <span class="price" data-bind="text: getValue()"></span> </td> </tr> <!-- /ko --> @@ -17,10 +17,10 @@ <tr class="totals-tax-summary" data-bind="mageInit: {'toggleAdvanced':{'selectorsToggleClass': 'shown', 'baseToggleClass': 'expanded', 'toggleContainers': '.totals-tax-details'}}"> <th class="mark" scope="row" colspan="1"> - <span class="detailed" data-bind="text: $t(title)"></span> + <span class="detailed" data-bind="text: title"></span> </th> - <td data-bind="attr: {'data-th': $t(title) }" class="amount"> - <span class="price" data-bind="text: $t(getValue())"></span> + <td data-bind="attr: {'data-th': title}" class="amount"> + <span class="price" data-bind="text: getValue()"></span> </td> </tr> <!-- ko foreach: getDetails() --> diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/minicart/subtotal/totals.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/minicart/subtotal/totals.html index c3c28a58138221e7031bc00c463df46c62a9a416..5b04ee8298480f1c9910f94d1f9897d44c91dcb7 100644 --- a/app/code/Magento/Tax/view/frontend/web/template/checkout/minicart/subtotal/totals.html +++ b/app/code/Magento/Tax/view/frontend/web/template/checkout/minicart/subtotal/totals.html @@ -10,11 +10,11 @@ <span class="price-wrapper" data-bind="html: cart().subtotal_excl_tax"></span> <!-- /ko --> - <!-- ko if: !display_cart_subtotal_excl_tax && display_subtotal_incl_tax --> + <!-- ko if: !display_cart_subtotal_excl_tax && display_cart_subtotal_incl_tax --> <span class="price-wrapper" data-bind="html: cart().subtotal_incl_tax"></span> <!-- /ko --> - <!-- ko if: !display_cart_subtotal_excl_tax && !display_subtotal_incl_tax --> + <!-- ko if: !display_cart_subtotal_excl_tax && !display_cart_subtotal_incl_tax --> <span class="price-wrapper price-including-tax" data-bind="attr: { 'data-label': $t('Incl. Tax') }, html: cart().subtotal_incl_tax"> </span> diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/grand-total.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/grand-total.html index 4451adbf528d64dc6330e734e48389057062a710..9d2072b1bf99840ed11401c277a8c0362d2e493b 100644 --- a/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/grand-total.html +++ b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/grand-total.html @@ -7,17 +7,17 @@ <!-- ko if: isTaxDisplayedInGrandTotal && isDisplayed() --> <tr class="grand totals incl"> <th class="mark" scope="row"> - <strong data-bind="i18n: inclTaxLabel"></strong> + <strong data-bind="text: inclTaxLabel"></strong> </th> - <td data-bind="attr: {'data-th': $t(inclTaxLabel) }" class="amount"> + <td data-bind="attr: {'data-th': inclTaxLabel}" class="amount"> <strong><span class="price" data-bind="text: getValue()"></span></strong> </td> </tr> <tr class="grand totals excl"> <th class="mark" scope="row"> - <strong data-bind="i18n: exclTaxLabel"></strong> + <strong data-bind="text: exclTaxLabel"></strong> </th> - <td data-bind="attr: {'data-th': exclTaxLabel }" class="amount"> + <td data-bind="attr: {'data-th': exclTaxLabel}" class="amount"> <strong><span class="price" data-bind="text: getGrandTotalExclTax()"></span></strong> </td> </tr> @@ -25,18 +25,18 @@ <!-- ko if: !isTaxDisplayedInGrandTotal && isDisplayed() --> <tr class="grand totals"> <th class="mark" scope="row"> - <strong data-bind="i18n: title"></strong> + <strong data-bind="text: title"></strong> </th> - <td data-bind="attr: {'data-th': $t(title)}" class="amount"> + <td data-bind="attr: {'data-th': title}" class="amount"> <strong><span class="price" data-bind="text: getValue()"></span></strong> </td> </tr> <!-- /ko --> <!-- ko if: isBaseGrandTotalDisplayNeeded() && isDisplayed() --> <tr class="totals charge"> - <th class="mark" data-bind="i18n: basicCurrencyMessage" scope="row"></th> + <th class="mark" data-bind="text: basicCurrencyMessage" scope="row"></th> <td class="amount"> - <span class="price" data-bind="text: getBaseValue(), attr: {'data-th': $t(basicCurrencyMessage)}"></span> + <span class="price" data-bind="text: getBaseValue(), attr: {'data-th': basicCurrencyMessage}"></span> </td> </tr> <!-- /ko --> diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/shipping.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/shipping.html index 1608f78ad1c91708b66d777eb472ba331562f479..3bcd9bccd15ea60ddd7718044417537f409f53fc 100644 --- a/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/shipping.html +++ b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/shipping.html @@ -8,33 +8,33 @@ <!-- ko if: isBothPricesDisplayed() --> <tr class="totals shipping excl"> <th class="mark" scope="row"> - <span class="label" data-bind="text: $t(title)+ ' ' + $t(excludingTaxMessage)"></span> - <span class="value" data-bind="i18n: getShippingMethodTitle()"></span> + <span class="label" data-bind="text: title+ ' ' + excludingTaxMessage"></span> + <span class="value" data-bind="text: getShippingMethodTitle()"></span> </th> <td class="amount"> <!-- ko if: isCalculated() --> <span class="price" - data-bind="i18n: getExcludingValue(), attr: {'data-th': $t(excludingTaxMessage)}"></span> + data-bind="text: getExcludingValue(), attr: {'data-th': excludingTaxMessage}"></span> <!-- /ko --> <!-- ko ifnot: isCalculated() --> <span class="not-calculated" - data-bind="i18n: getExcludingValue(), attr: {'data-th': $t(excludingTaxMessage)}"></span> + data-bind="text: getExcludingValue(), attr: {'data-th': excludingTaxMessage}"></span> <!-- /ko --> </td> </tr> <tr class="totals shipping incl"> <th class="mark" scope="row"> - <span class="label" data-bind="text: $t(title) + ' ' + $t(includingTaxMessage)"></span> - <span class="value" data-bind="i18n: getShippingMethodTitle()"></span> + <span class="label" data-bind="text: title + ' ' + includingTaxMessage"></span> + <span class="value" data-bind="text: getShippingMethodTitle()"></span> </th> <td class="amount"> <!-- ko if: isCalculated() --> <span class="price" - data-bind="i18n: getIncludingValue(), attr: {'data-th': $t(title) + ' ' + $t(excludingTaxMessage)}"></span> + data-bind="text: getIncludingValue(), attr: {'data-th': title + ' ' + excludingTaxMessage}"></span> <!-- /ko --> <!-- ko ifnot: isCalculated() --> <span class="not-calculated" - data-bind="i18n: getIncludingValue(), attr: {'data-th': $t(title) + ' ' + $t(excludingTaxMessage)}"></span> + data-bind="text: getIncludingValue(), attr: {'data-th': title + ' ' + excludingTaxMessage}"></span> <!-- /ko --> </td> </tr> @@ -42,17 +42,17 @@ <!-- ko if: isIncludingDisplayed() --> <tr class="totals shipping incl"> <th class="mark" scope="row"> - <span class="label" data-bind="i18n: title"></span> - <span class="value" data-bind="i18n: getShippingMethodTitle()"></span> + <span class="label" data-bind="text: title"></span> + <span class="value" data-bind="text: getShippingMethodTitle()"></span> </th> <td class="amount"> <!-- ko if: isCalculated() --> <span class="price" - data-bind="i18n: getIncludingValue(), attr: {'data-th': $t(title)}"></span> + data-bind="text: getIncludingValue(), attr: {'data-th': title}"></span> <!-- /ko --> <!-- ko ifnot: isCalculated() --> <span class="not-calculated" - data-bind="i18n: getIncludingValue(), attr: {'data-th': $t(title)}"></span> + data-bind="text: getIncludingValue(), attr: {'data-th': title}"></span> <!-- /ko --> </td> </tr> @@ -60,17 +60,17 @@ <!-- ko if: isExcludingDisplayed() --> <tr class="totals shipping excl"> <th class="mark" scope="row"> - <span class="label" data-bind="i18n: title"></span> - <span class="value" data-bind="i18n: getShippingMethodTitle()"></span> + <span class="label" data-bind="text: title"></span> + <span class="value" data-bind="text: getShippingMethodTitle()"></span> </th> <td class="amount"> <!-- ko if: isCalculated() --> <span class="price" - data-bind="i18n: getValue(), attr: {'data-th': $t(title)}"></span> + data-bind="text: getValue(), attr: {'data-th': title}"></span> <!-- /ko --> <!-- ko ifnot: isCalculated() --> <span class="not-calculated" - data-bind="i18n: getValue(), attr: {'data-th': $t(title)}"></span> + data-bind="text: getValue(), attr: {'data-th': title}"></span> <!-- /ko --> </td> </tr> diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/subtotal.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/subtotal.html index a51407475cbfc66ad2f11a4c50166362efe2ef4d..618bb6fd3281fc280206cb809d8233ed489169b3 100644 --- a/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/subtotal.html +++ b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/subtotal.html @@ -7,36 +7,36 @@ <!-- ko if: isBothPricesDisplayed() --> <tr class="totals sub excl"> <th class="mark" scope="row"> - <span data-bind="i18n: title"></span> - <span data-bind="i18n: excludingTaxMessage"></span> + <span data-bind="text: title"></span> + <span data-bind="text: excludingTaxMessage"></span> </th> <td class="amount"> - <span class="price" data-bind="text: getValue(), attr: {'data-th': $t(excludingTaxMessage) }"></span> + <span class="price" data-bind="text: getValue(), attr: {'data-th': excludingTaxMessage}"></span> </td> </tr> <tr class="totals sub incl"> <th class="mark" scope="row"> - <span data-bind="i18n: title"></span> - <span data-bind="i18n: includingTaxMessage"></span> + <span data-bind="text: title"></span> + <span data-bind="text: includingTaxMessage"></span> </th> <td class="amount"> - <span class="price" data-bind="text: getValueInclTax(), attr: {'data-th': $t(includingTaxMessage) }"></span> + <span class="price" data-bind="text: getValueInclTax(), attr: {'data-th': includingTaxMessage}"></span> </td> </tr> <!-- /ko --> <!-- ko if: !isBothPricesDisplayed() && isIncludingTaxDisplayed() --> <tr class="totals sub"> - <th data-bind="i18n: title" class="mark" scope="row"></th> + <th data-bind="text: title" class="mark" scope="row"></th> <td class="amount"> - <span class="price" data-bind="text: getValueInclTax(), attr: {'data-th': $t(title)}"></span> + <span class="price" data-bind="text: getValueInclTax(), attr: {'data-th': title}"></span> </td> </tr> <!-- /ko --> <!-- ko if: !isBothPricesDisplayed() && !isIncludingTaxDisplayed() --> <tr class="totals sub"> - <th data-bind="i18n: title" class="mark" scope="row"></th> + <th data-bind="text: title" class="mark" scope="row"></th> <td class="amount"> - <span class="price" data-bind="text: getValue(), attr: {'data-th': $t(title)}"></span> + <span class="price" data-bind="text: getValue(), attr: {'data-th': title}"></span> </td> </tr> <!-- /ko --> diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/tax.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/tax.html index 5aa8b53e7fd082c0a477903db60a01cbdf24a347..3305b6956b8c74bfed641e1517cf04c9259bf9b2 100644 --- a/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/tax.html +++ b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/tax.html @@ -6,15 +6,15 @@ --> <!-- ko if: ifShowValue() && !ifShowDetails() --> <tr class="totals-tax"> - <th data-bind="i18n: title" class="mark" scope="row"></th> - <td data-bind="attr: {'data-th': $t(title) }" class="amount"> + <th data-bind="text: title" class="mark" scope="row"></th> + <td data-bind="attr: {'data-th': title}" class="amount"> <!-- ko if: isCalculated() --> <span class="price" - data-bind="i18n: getValue()"></span> + data-bind="text: getValue()"></span> <!-- /ko --> <!-- ko ifnot: isCalculated() --> <span class="not-calculated" - data-bind="i18n: getValue()"></span> + data-bind="text: getValue()"></span> <!-- /ko --> </td> </tr> @@ -22,15 +22,15 @@ <!-- ko if: ifShowValue() && ifShowDetails() --> <tr class="totals-tax-summary" data-bind="mageInit: {'toggleAdvanced':{'selectorsToggleClass': 'shown', 'baseToggleClass': 'expanded', 'toggleContainers': '.totals-tax-details'}}"> - <th data-bind="i18n: title" class="mark" scope="row"></th> - <td data-bind="attr: {'data-th': $t(title) }" class="amount"> + <th data-bind="text: title" class="mark" scope="row"></th> + <td data-bind="attr: {'data-th': title }" class="amount"> <!-- ko if: isCalculated() --> <span class="price" - data-bind="i18n: getValue()"></span> + data-bind="text: getValue()"></span> <!-- /ko --> <!-- ko ifnot: isCalculated() --> <span class="not-calculated" - data-bind="i18n: getValue()"></span> + data-bind="text: getValue()"></span> <!-- /ko --> </td> </tr> diff --git a/app/code/Magento/Theme/Block/Adminhtml/Wysiwyg/Files/Content/Files.php b/app/code/Magento/Theme/Block/Adminhtml/Wysiwyg/Files/Content/Files.php index 9b11f465787d75ba95c8349733e76ad6d7668790..1af3ea8e4bc986b49e0c718e0a3e9b4bb9006ead 100644 --- a/app/code/Magento/Theme/Block/Adminhtml/Wysiwyg/Files/Content/Files.php +++ b/app/code/Magento/Theme/Block/Adminhtml/Wysiwyg/Files/Content/Files.php @@ -9,7 +9,7 @@ * * @method * \Magento\Theme\Block\Adminhtml\Wysiwyg\Files\Content\Files setStorage(\Magento\Theme\Model\Wysiwyg\Storage $storage) - * @method \Magento\Theme\Model\Wysiwyg\Storage getStorage + * @method \Magento\Theme\Model\Wysiwyg\Storage getStorage() */ namespace Magento\Theme\Block\Adminhtml\Wysiwyg\Files\Content; diff --git a/app/code/Magento/Theme/view/base/page_layout/empty.xml b/app/code/Magento/Theme/view/base/page_layout/empty.xml index 09d5658a86c4b9e38d7d2b8c83646555b2a97c10..d69d34f79e64a5407baddca36d65d3455099cc5e 100644 --- a/app/code/Magento/Theme/view/base/page_layout/empty.xml +++ b/app/code/Magento/Theme/view/base/page_layout/empty.xml @@ -16,7 +16,7 @@ <container name="main" label="Main Content Container" htmlTag="div" htmlClass="column main"/> </container> </container> - <container name="page.bottom" as="page_bottom" label="Before Page Footer Container" after="main.content" htmlTag="div" htmlClass="page-bottom"/> + <container name="page.bottom.container" as="page_bottom_container" label="Before Page Footer Container" after="main.content" htmlTag="div" htmlClass="page-bottom"/> <container name="before.body.end" as="before_body_end" after="-" label="Page Bottom"/> </container> </container> diff --git a/app/code/Magento/Theme/view/frontend/templates/html/pager.phtml b/app/code/Magento/Theme/view/frontend/templates/html/pager.phtml index e7835bee90cc63bb03928e2f24edeccd8cb17987..331903c8ced116e52835c475c43e26559f25e55e 100644 --- a/app/code/Magento/Theme/view/frontend/templates/html/pager.phtml +++ b/app/code/Magento/Theme/view/frontend/templates/html/pager.phtml @@ -116,7 +116,7 @@ <?php if ($block->isShowPerPage()): ?> <div class="limiter"> <strong class="limiter-label"><?php /* @escapeNotVerified */ echo __('Show') ?></strong> - <select id="limiter" data-mage-redirect="{'event':'change'}" class="limiter-options"> + <select id="limiter" data-mage-init='{"redirectUrl": {"event":"change"}}' class="limiter-options"> <?php foreach ($block->getAvailableLimit() as $_key => $_limit): ?> <option value="<?php /* @escapeNotVerified */ echo $block->getLimitUrl($_key) ?>"<?php if ($block->isLimitCurrent($_key)): ?> selected="selected"<?php endif ?>> diff --git a/app/code/Magento/Translation/Model/Js/DataProvider.php b/app/code/Magento/Translation/Model/Js/DataProvider.php index ee6d8b3f5df193ae8444ba3c4e1ca9a87d61f617..a12859fe254d109a8a50a2dcb3ce1108327f2167 100644 --- a/app/code/Magento/Translation/Model/Js/DataProvider.php +++ b/app/code/Magento/Translation/Model/Js/DataProvider.php @@ -129,7 +129,7 @@ class DataProvider implements DataProviderInterface if ($result) { if (isset($matches[2])) { foreach ($matches[2] as $match) { - $phrases[] = $match; + $phrases[] = str_replace('\\\'', '\'', $match); } } } diff --git a/app/code/Magento/Translation/etc/di.xml b/app/code/Magento/Translation/etc/di.xml index 05c7f766a452e694c648138db45d7835b9721dd2..7d2ec64b604d8bb2f24ecd51bc0e03391584dbde 100644 --- a/app/code/Magento/Translation/etc/di.xml +++ b/app/code/Magento/Translation/etc/di.xml @@ -64,7 +64,7 @@ </arguments> </type> - <type name="Magento\Framework\View\Asset\PreProcessor\Pool"> + <virtualType name="AssetPreProcessorPool"> <arguments> <argument name="preprocessors" xsi:type="array"> <item name="js" xsi:type="array"> @@ -79,7 +79,7 @@ </item> </argument> </arguments> - </type> + </virtualType> <type name="Magento\Framework\Console\CommandList"> <arguments> diff --git a/app/code/Magento/Ui/Component/Filters.php b/app/code/Magento/Ui/Component/Filters.php index dadcdc2f09535bb7b8275eedea8f52f8dfc1b55f..3859f777f3e46d52b8799d4af5c9bc297bf75228 100644 --- a/app/code/Magento/Ui/Component/Filters.php +++ b/app/code/Magento/Ui/Component/Filters.php @@ -73,6 +73,11 @@ class Filters extends AbstractComponent implements ObserverInterface { if ($component instanceof ColumnInterface) { $filterType = $component->getData('config/filter'); + + if (is_array($filterType)) { + $filterType = $filterType['filterType']; + } + if (!$filterType) { return; } diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/multiselect.js b/app/code/Magento/Ui/view/base/web/js/form/element/multiselect.js index 6c5de791d1e87337876b2919c7b1c6180729ff1a..1260a366cc07a2434cc1b5306f8d6dc2711a4f20 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/multiselect.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/multiselect.js @@ -20,8 +20,10 @@ define([ * * @returns {Array} */ - normalizeData: function () { - var value = this._super(); + normalizeData: function (value) { + if (utils.isEmpty(value)) { + value = []; + } return _.isString(value) ? value.split(',') : value; }, diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/ui-select.js b/app/code/Magento/Ui/view/base/web/js/form/element/ui-select.js index 5547e3ad9dba80b8a4573e5ea08c6fc2107e710a..6fe8c40c4d8094513fa55070f6173e36cea5345d 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/ui-select.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/ui-select.js @@ -57,19 +57,6 @@ define([ } }, - /** - * Extends instance with defaults, extends config with formatted values - * and options, and invokes initialize method of AbstractElement class. - * - * @returns {Object} Chainable - */ - initialize: function () { - this._super() - .initOptions(); - - return this; - }, - /** * Parses options and merges the result with instance * diff --git a/app/code/Magento/Ui/view/base/web/js/grid/sticky/sticky.js b/app/code/Magento/Ui/view/base/web/js/grid/sticky/sticky.js index 8daa9999633ac16af713551813a11e9128ecb522..8a1ffe15de04bdabed5d9e3b6f9072abb8057e15 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/sticky/sticky.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/sticky/sticky.js @@ -73,12 +73,6 @@ define([ $.async(this.stickyContainerSelector, this, this.initContainerNode); - $.async(this.stickyElementSelector, - this.listing(), - this.initStickyListingNode); - $.async(this.stickyElementSelector, - this.toolbar(), - this.initStickyToolbarNode); return this; }, @@ -154,6 +148,13 @@ define([ $.async(this.rightDataGridCapSelector, node, this.initRightDataGridCap); + + $.async(this.stickyElementSelector, + this.listing(), + this.initStickyListingNode); + $.async(this.stickyElementSelector, + this.toolbar(), + this.initStickyToolbarNode); }, /** diff --git a/app/code/Magento/Ui/view/base/web/js/lib/core/storage.js b/app/code/Magento/Ui/view/base/web/js/lib/core/storage.js index 62f87dcd432d2ddec9b8ba11b01442cc8a5e92d5..1ffc8c880e485f1859d784bb32eb6aa32f7c94fc 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/core/storage.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/core/storage.js @@ -11,8 +11,72 @@ define([ 'use strict'; var root = 'appData', + localStorage = window.localStorage, + hasSupport, storage; + /** + * Flag which indicates whether localStorage is supported. + */ + hasSupport = (function () { + var key = '_storageSupported'; + + try { + localStorage.setItem(key, 'true'); + + if (localStorage.getItem(key) === 'true') { + localStorage.removeItem(key); + + return true; + } + + return false; + } catch (e) { + return false; + } + })(); + + if (!hasSupport) { + localStorage = { + _data: {}, + + /** + * Sets value of the specified item. + * + * @param {String} key - Key of the property. + * @param {*} value - Properties' value. + */ + setItem: function (key, value) { + this._data[key] = value + ''; + }, + + /** + * Retrieves specfied item. + * + * @param {String} key - Key of the property to be retrieved. + */ + getItem: function (key) { + return this._data[key]; + }, + + /** + * Removes specfied item. + * + * @param {String} key - Key of the property to be removed. + */ + removeItem: function (key) { + delete this._data[key]; + }, + + /** + * Removes all items. + */ + clear: function () { + this._data = {}; + } + }; + } + /** * Extracts and parses data stored in localStorage by the * key specified in 'root' varaible. diff --git a/app/code/Magento/Ui/view/base/web/js/lib/registry/events.js b/app/code/Magento/Ui/view/base/web/js/lib/registry/events.js index 69fcebf547ef5fa076440a736fece570373fc629..87d566a7ebc2cb34b89391b6175b589554586fcd 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/registry/events.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/registry/events.js @@ -2,6 +2,7 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ + define([ 'underscore', 'mageUtils', @@ -13,11 +14,11 @@ define([ * @constructor */ function Events(storage) { - this.id = 0, + this.id = 0; - this.requests = new Map(); - this.map = {}; - this.storage = storage; + this.requests = new Map(); + this.map = {}; + this.storage = storage; _.bindAll(this, '_resolve', '_clear'); } @@ -28,7 +29,7 @@ define([ /** * Tries to resolve dependencies affected by the scpecified element. * @param {String} elem - Elements' name. - * @returns {events} Chainable. + * @returns {Object} Chainable. */ resolve: function (elem) { var pending = this.map[elem]; @@ -44,17 +45,16 @@ define([ /** * Creates a new request for the specified set - of elements in case some of them wasn't registered yeat. - Otherwise triggers callback immediately. + * of elements in case some of them wasn't registered yeat. + * Otherwise triggers callback immediately. * @param {Array} elems - Requested elements. - * @param {Function} callback - - Callback that will be triggered as soon as - all of the elements will be registered. + * @param {Object} callback - that will be triggered as soon as + * all of the elements will be registered. * @returns {events} Chainable. */ wait: function (elems, callback) { var storage = this.storage, - map = this.map; + map = this.map; if (storage.has(elems)) { return callback.apply(null, storage.get(elems)); @@ -79,9 +79,9 @@ define([ * @returns {Boolean} Whether specified request was successfully resolved. */ _resolve: function (id) { - var request = this.requests.get(id), - elems = request.deps, - storage = this.storage, + var request = this.requests.get(id), + elems = request.deps, + storage = this.storage, isResolved; isResolved = storage.has(elems); @@ -99,8 +99,8 @@ define([ * @param {Number} id - Id of request. */ _clear: function (id) { - var map = this.map, - elems = this.requests.get(id).deps; + var map = this.map, + elems = this.requests.get(id).deps; elems.forEach(function (elem) { utils.remove(map[elem], id); diff --git a/app/code/Magento/Ui/view/base/web/js/modal/confirm.js b/app/code/Magento/Ui/view/base/web/js/modal/confirm.js index 098cb8669741e15eedb8fb0df607a0658cec98f8..1a27b96413c173a9b126d0996e232eb684d7e262 100644 --- a/app/code/Magento/Ui/view/base/web/js/modal/confirm.js +++ b/app/code/Magento/Ui/view/base/web/js/modal/confirm.js @@ -40,8 +40,8 @@ define([ /** * Click handler. */ - click: function () { - this.closeModal(); + click: function (event) { + this.closeModal(event); } }, { text: $.mage.__('OK'), @@ -50,8 +50,8 @@ define([ /** * Click handler. */ - click: function () { - this.closeModal(true); + click: function (event) { + this.closeModal(event, true); } }] }, @@ -82,15 +82,15 @@ define([ /** * Close modal window. */ - closeModal: function (result) { + closeModal: function (event, result) { result = result || false; if (result) { - this.options.actions.confirm(); + this.options.actions.confirm(event); } else { - this.options.actions.cancel(); + this.options.actions.cancel(event); } - this.options.actions.always(); + this.options.actions.always(event); this.element.bind('confirmclosed', _.bind(this._remove, this)); return this._super(); diff --git a/app/code/Magento/Ui/view/base/web/js/modal/modal.js b/app/code/Magento/Ui/view/base/web/js/modal/modal.js index e99f818068534b4578bdebc4b4f3ef2dc36becc3..23011d607cdadc301ee6cf4cebeb148b400c0260 100644 --- a/app/code/Magento/Ui/view/base/web/js/modal/modal.js +++ b/app/code/Magento/Ui/view/base/web/js/modal/modal.js @@ -22,7 +22,7 @@ define([ */ var transitionEvent = (function () { var transition, - elementStyle = document.body.style, + elementStyle = document.createElement('div').style, transitions = { 'transition': 'transitionend', 'OTransition': 'oTransitionEnd', @@ -78,8 +78,8 @@ define([ /** * Default action on button click */ - click: function () { - this.closeModal(); + click: function (event) { + this.closeModal(event); } }] }, diff --git a/app/code/Magento/Ups/view/adminhtml/templates/system/shipping/carrier_config.phtml b/app/code/Magento/Ups/view/adminhtml/templates/system/shipping/carrier_config.phtml index c3ca415c7c2869ffad51232487b894c7599a2f9f..7cffb845b9387b55dbb5d51eb89e8d332ee9b3bb 100644 --- a/app/code/Magento/Ups/view/adminhtml/templates/system/shipping/carrier_config.phtml +++ b/app/code/Magento/Ups/view/adminhtml/templates/system/shipping/carrier_config.phtml @@ -20,19 +20,19 @@ if (!$storeCode && $websiteCode) { /** @var $web \Magento\Store\Model\Website */ $web = $block->getWebsiteModel()->load($websiteCode); $storedAllowedMethods = explode(',', $web->getConfig('carriers/ups/allowed_methods')); - $storedOriginShipment = $web->getConfig('carriers/ups/origin_shipment'); - $storedFreeShipment = $web->getConfig('carriers/ups/free_method'); - $storedUpsType = $web->getConfig('carriers/ups/type'); + $storedOriginShipment = $block->escapeHtml($web->getConfig('carriers/ups/origin_shipment')); + $storedFreeShipment = $block->escapeHtml($web->getConfig('carriers/ups/free_method')); + $storedUpsType = $block->escapeHtml($web->getConfig('carriers/ups/type')); } elseif ($storeCode) { $storedAllowedMethods = explode(',', $block->getConfig('carriers/ups/allowed_methods', $storeCode)); - $storedOriginShipment = $block->getConfig('carriers/ups/origin_shipment', $storeCode); - $storedFreeShipment = $block->getConfig('carriers/ups/free_method', $storeCode); - $storedUpsType = $block->getConfig('carriers/ups/type', $storeCode); + $storedOriginShipment = $block->escapeHtml($block->getConfig('carriers/ups/origin_shipment', $storeCode)); + $storedFreeShipment = $block->escapeHtml($block->getConfig('carriers/ups/free_method', $storeCode)); + $storedUpsType = $block->escapeHtml($block->getConfig('carriers/ups/type', $storeCode)); } else { $storedAllowedMethods = explode(',', $block->getConfig('carriers/ups/allowed_methods')); - $storedOriginShipment = $block->getConfig('carriers/ups/origin_shipment'); - $storedFreeShipment = $block->getConfig('carriers/ups/free_method'); - $storedUpsType = $block->getConfig('carriers/ups/type'); + $storedOriginShipment = $block->escapeHtml($block->getConfig('carriers/ups/origin_shipment')); + $storedFreeShipment = $block->escapeHtml($block->getConfig('carriers/ups/free_method')); + $storedUpsType = $block->escapeHtml($block->getConfig('carriers/ups/type')); } ?> <script> diff --git a/app/code/Magento/User/i18n/de_DE.csv b/app/code/Magento/User/i18n/de_DE.csv index 63367a6ff3a321b4002fff23db3184b217fb90bf..eb4689a2501f93ea2407b2e12ff0b33c8ce21f0c 100644 --- a/app/code/Magento/User/i18n/de_DE.csv +++ b/app/code/Magento/User/i18n/de_DE.csv @@ -118,3 +118,5 @@ Unlock,Entsperren "Last login","Letzter Login" Failures,Fehler Unlocked,"Gesperrt bis" +"All Users","All Users" +"User Roles","User Roles" diff --git a/app/code/Magento/User/i18n/en_US.csv b/app/code/Magento/User/i18n/en_US.csv index 1f56f067006fcfc049f895c82d4be8e59d1eaa7f..7c85088044d4270d9274aeaa4c2b37c768122401 100644 --- a/app/code/Magento/User/i18n/en_US.csv +++ b/app/code/Magento/User/i18n/en_US.csv @@ -118,3 +118,5 @@ Unlock,Unlock "Last login","Last login" Failures,Failures Unlocked,Unlocked +"All Users","All Users" +"User Roles","User Roles" diff --git a/app/code/Magento/User/i18n/es_ES.csv b/app/code/Magento/User/i18n/es_ES.csv index 4dd4f371b4af5b3f4d91980e708cf2a166194117..1e9397fee14cac86e26df285f382fb8575296752 100644 --- a/app/code/Magento/User/i18n/es_ES.csv +++ b/app/code/Magento/User/i18n/es_ES.csv @@ -119,3 +119,5 @@ Unlock,Desbloquear "Last login","Ultimo acceso" Failures,Fallos Unlocked,"Bloqueado hasta" +"All Users","All Users" +"User Roles","User Roles" diff --git a/app/code/Magento/User/i18n/fr_FR.csv b/app/code/Magento/User/i18n/fr_FR.csv index bbe1e63a96cbdd9c48e1695577d071fd5c69648e..42116af645b085fc8f38a176a0805f6c90c35591 100644 --- a/app/code/Magento/User/i18n/fr_FR.csv +++ b/app/code/Magento/User/i18n/fr_FR.csv @@ -119,3 +119,5 @@ Unlock,Déverrouiller "Last login","Dernière connexion" Failures,Echecs Unlocked,"Verrouillé jusqu'" +"All Users","All Users" +"User Roles","User Roles" diff --git a/app/code/Magento/User/i18n/nl_NL.csv b/app/code/Magento/User/i18n/nl_NL.csv index 91813e3a13311cf7eef604e490e8290319e62f56..3745ad043022040dac213c07f7c699a6feff89a9 100644 --- a/app/code/Magento/User/i18n/nl_NL.csv +++ b/app/code/Magento/User/i18n/nl_NL.csv @@ -119,3 +119,5 @@ Unlock,Openen "Last login","Laatste login" Failures,Mislukkingen Unlocked,"Gesloten tot" +"All Users","All Users" +"User Roles","User Roles" diff --git a/app/code/Magento/User/i18n/pt_BR.csv b/app/code/Magento/User/i18n/pt_BR.csv index d8d16b8cd04f7e50e2301b010a834f019803e0f9..0edca55b30ea62af431ef96ad0f68a9fdccbcce3 100644 --- a/app/code/Magento/User/i18n/pt_BR.csv +++ b/app/code/Magento/User/i18n/pt_BR.csv @@ -119,3 +119,5 @@ Unlock,Desbloquear "Last login","Último login" Failures,Falhas Unlocked,"Bloqueado até" +"All Users","All Users" +"User Roles","User Roles" diff --git a/app/code/Magento/User/i18n/zh_Hans_CN.csv b/app/code/Magento/User/i18n/zh_Hans_CN.csv index 1c10afb0b649b2bbf78b617f2768563ba2dc382e..1c0292bf2db046eaef74958a6fb6f6ca40caa784 100644 --- a/app/code/Magento/User/i18n/zh_Hans_CN.csv +++ b/app/code/Magento/User/i18n/zh_Hans_CN.csv @@ -119,3 +119,5 @@ Unlock,è§£é” "Last login",上一次登录 Failures,失败 Unlocked,é”定直到 +"All Users","All Users" +"User Roles","User Roles" diff --git a/app/code/Magento/Weee/Helper/Data.php b/app/code/Magento/Weee/Helper/Data.php index 55db9791896ecb8307b01bee407fb1bf1a84eaa9..138ae26986b5aaf112780ed64e2c8ecd5f08cb0c 100644 --- a/app/code/Magento/Weee/Helper/Data.php +++ b/app/code/Magento/Weee/Helper/Data.php @@ -739,12 +739,12 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper } /** - * get FPT DISPLAY_INCL setting + * Get FPT DISPLAY_INCL setting * * @param int|null $storeId * @return bool */ - public function geDisplayIncl($storeId = null) + public function isDisplayIncl($storeId = null) { return $this->typeOfDisplay( WeeeDisplayConfig::DISPLAY_INCL, @@ -754,12 +754,27 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper } /** - * get FPT DISPLAY_EXCL_DESCR_INCL setting + * Get FPT DISPLAY_INCL_DESCR setting * * @param int|null $storeId * @return bool */ - public function geDisplayExlDescIncl($storeId = null) + public function isDisplayInclDesc($storeId = null) + { + return $this->typeOfDisplay( + WeeeDisplayConfig::DISPLAY_INCL_DESCR, + \Magento\Framework\Pricing\Render::ZONE_ITEM_VIEW, + $storeId + ); + } + + /** + * Get FPT DISPLAY_EXCL_DESCR_INCL setting + * + * @param int|null $storeId + * @return bool + */ + public function isDisplayExclDescIncl($storeId = null) { return $this->typeOfDisplay( WeeeDisplayConfig::DISPLAY_EXCL_DESCR_INCL, @@ -769,12 +784,12 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper } /** - * get FPT DISPLAY_EXCL setting + * Get FPT DISPLAY_EXCL setting * * @param int|null $storeId * @return bool */ - public function geDisplayExcl($storeId = null) + public function isDisplayExcl($storeId = null) { return $this->typeOfDisplay( WeeeDisplayConfig::DISPLAY_EXCL, diff --git a/app/code/Magento/Weee/Model/Config/Source/Display.php b/app/code/Magento/Weee/Model/Config/Source/Display.php index c5408a0489f491686df9c2765677ec76f43754f3..6782463857870196fdf75b7e46bc6dd487df1889 100644 --- a/app/code/Magento/Weee/Model/Config/Source/Display.php +++ b/app/code/Magento/Weee/Model/Config/Source/Display.php @@ -15,16 +15,22 @@ class Display implements \Magento\Framework\Option\ArrayInterface public function toOptionArray() { return [ - ['value' => \Magento\Weee\Model\Tax::DISPLAY_INCL, 'label' => __('Including FPT only')], + [ + 'value' => \Magento\Weee\Model\Tax::DISPLAY_INCL, + 'label' => __('Including FPT only') + ], [ 'value' => \Magento\Weee\Model\Tax::DISPLAY_INCL_DESCR, 'label' => __('Including FPT and FPT description') ], [ 'value' => \Magento\Weee\Model\Tax::DISPLAY_EXCL_DESCR_INCL, - 'label' => __('Excluding FPT, FPT description, final price') + 'label' => __('Excluding FPT. Including FPT description and final price') ], - ['value' => \Magento\Weee\Model\Tax::DISPLAY_EXCL, 'label' => __('Excluding FPT')] + [ + 'value' => \Magento\Weee\Model\Tax::DISPLAY_EXCL, + 'label' => __('Excluding FPT') + ] ]; } } diff --git a/app/code/Magento/Weee/Model/Tax.php b/app/code/Magento/Weee/Model/Tax.php index 8550915d5a21d2c56d86c019e04c3361418e1ac0..a21bc4a163ff30332cc9c7b10d0bcb2506591f92 100644 --- a/app/code/Magento/Weee/Model/Tax.php +++ b/app/code/Magento/Weee/Model/Tax.php @@ -27,7 +27,7 @@ class Tax extends \Magento\Framework\Model\AbstractModel const DISPLAY_INCL_DESCR = 1; /** - * Excluding FPT, FPT description, final price + * Excluding FPT. Including FPT description and final price */ const DISPLAY_EXCL_DESCR_INCL = 2; diff --git a/app/code/Magento/Weee/Observer/GetPriceConfigurationObserver.php b/app/code/Magento/Weee/Observer/GetPriceConfigurationObserver.php index 96effbb8545bfb5b54ec2fffa3e15481afd871c8..264bd13de6138459f94b6194240634b1e0bc88d5 100644 --- a/app/code/Magento/Weee/Observer/GetPriceConfigurationObserver.php +++ b/app/code/Magento/Weee/Observer/GetPriceConfigurationObserver.php @@ -142,8 +142,8 @@ class GetPriceConfigurationObserver implements ObserverInterface protected function getWhichCalcPriceToUse($storeId = null) { $calcPrice = 'finalPrice'; - if ($this->weeeData->geDisplayExcl($storeId) || - $this->weeeData->geDisplayExlDescIncl($storeId) || + if ($this->weeeData->isDisplayExcl($storeId) || + $this->weeeData->isDisplayExclDescIncl($storeId) || ($this->taxData->priceIncludesTax() && $this->taxData->displayPriceExcludingTax()) ) { $calcPrice = 'basePrice'; diff --git a/app/code/Magento/Weee/Observer/UpdateProductOptionsObserver.php b/app/code/Magento/Weee/Observer/UpdateProductOptionsObserver.php index 77d022811702a4fb2ab58bb76dc1a4fe760a79dd..3619e9ae9e643b9782c1747016846b78cd125018 100644 --- a/app/code/Magento/Weee/Observer/UpdateProductOptionsObserver.php +++ b/app/code/Magento/Weee/Observer/UpdateProductOptionsObserver.php @@ -59,23 +59,28 @@ class UpdateProductOptionsObserver implements ObserverInterface return $this; } - if ($this->weeeData->isEnabled() && - !$this->weeeData->geDisplayIncl($product->getStoreId()) && - !$this->weeeData->geDisplayExcl($product->getStoreId()) - ) { - // only do processing on bundle product - if ($product->getTypeId() == \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE) { - if (!array_key_exists('optionTemplate', $options)) { - $calcPrice = $this->getWhichCalcPriceToUse($product->getStoreId()); - $options['optionTemplate'] = '<%- data.label %>' - . '<% if (data.' . $calcPrice . '.value) { %>' - . ' +<%- data.' . $calcPrice . '.formatted %>' - . '<% } %>'; - } + // if the Weee module is enabled, then only do processing on bundle products + if ($this->weeeData->isEnabled() && $product->getTypeId() == \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE) { + + if ($this->taxData->priceIncludesTax() && $this->taxData->displayPriceExcludingTax()) { + // the Tax module might have set up a default, but we will re-decide which calcPrice field to use + unset($options['optionTemplate']); + } + + if (!array_key_exists('optionTemplate', $options)) { + $calcPrice = $this->getWhichCalcPriceToUse($product->getStoreId()); + $options['optionTemplate'] = '<%- data.label %>' + . '<% if (data.' . $calcPrice . '.value) { %>' + . ' +<%- data.' . $calcPrice . '.formatted %>' + . '<% } %>'; + } + if (!$this->weeeData->isDisplayIncl($product->getStoreId()) && + !$this->weeeData->isDisplayExcl($product->getStoreId())) { + // we need to display the individual Weee amounts foreach ($this->weeeData->getWeeeAttributesForBundle($product) as $weeeAttributes) { foreach ($weeeAttributes as $weeeAttribute) { - if (!preg_match('/'.$weeeAttribute->getCode().'/', $options['optionTemplate'])) { + if (!preg_match('/' . $weeeAttribute->getCode() . '/', $options['optionTemplate'])) { $options['optionTemplate'] .= sprintf( ' <%% if (data.weeePrice' . $weeeAttribute->getCode() . ') { %%>' . ' (' . $weeeAttribute->getName() @@ -86,15 +91,14 @@ class UpdateProductOptionsObserver implements ObserverInterface } } } + } - if ($this->weeeData->geDisplayExlDescIncl($product->getStoreId())) { - $options['optionTemplate'] .= sprintf( - ' <%% if (data.weeePrice) { %%>' - . '<%%- data.weeePrice.formatted %%>' - . '<%% } %%>' - ); - } - + if ($this->weeeData->isDisplayExclDescIncl($product->getStoreId())) { + $options['optionTemplate'] .= sprintf( + ' <%% if (data.weeePrice) { %%>' + . '<%%- data.weeePrice.formatted %%>' + . '<%% } %%>' + ); } } $response->setAdditionalOptions($options); @@ -102,7 +106,7 @@ class UpdateProductOptionsObserver implements ObserverInterface } /** - * Returns which product price to use as a basis for the Weee's final price + * Returns which product price to show (before listing the individual Weee amounts, if applicable) * * @param int|null $storeId * @return string @@ -110,10 +114,9 @@ class UpdateProductOptionsObserver implements ObserverInterface protected function getWhichCalcPriceToUse($storeId = null) { $calcPrice = 'finalPrice'; - if ($this->weeeData->geDisplayExcl($storeId) || - $this->weeeData->geDisplayExlDescIncl($storeId) || - ($this->taxData->priceIncludesTax() && $this->taxData->displayPriceExcludingTax()) - ) { + + if ($this->weeeData->isDisplayExclDescIncl($storeId) || + ($this->weeeData->isDisplayExcl($storeId) && $this->taxData->displayPriceExcludingTax())) { $calcPrice = 'basePrice'; } return $calcPrice; diff --git a/app/code/Magento/Weee/README.md b/app/code/Magento/Weee/README.md index 3fda5bbc12bb038acf560c52d48571ecfd587b4d..0218dcd85ed9cb433e21a52a44e856be287f8aaa 100644 --- a/app/code/Magento/Weee/README.md +++ b/app/code/Magento/Weee/README.md @@ -18,7 +18,7 @@ Magento_Weee module can be installed automatically (using native Magento install Magento installation with existing products with FPT: * Disable FPT on the backend * Remove all products with FPT -* Remove all FPT attributes from product templates +* Remove all FPT attributes from attribute sets * Delete all FPT attributes * Remove module directory from the code base * New Magento installation: diff --git a/app/code/Magento/Weee/Test/Unit/Observer/UpdateProductOptionsObserverTest.php b/app/code/Magento/Weee/Test/Unit/Observer/UpdateProductOptionsObserverTest.php index 8725a62d837be15e68989b1fb1eab050ab0f4968..9fa6c897807a78a8025e6cba387dcaba4eb728f4 100644 --- a/app/code/Magento/Weee/Test/Unit/Observer/UpdateProductOptionsObserverTest.php +++ b/app/code/Magento/Weee/Test/Unit/Observer/UpdateProductOptionsObserverTest.php @@ -6,25 +6,28 @@ namespace Magento\Weee\Test\Unit\Observer; -use \Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Weee\Model\Tax as WeeeDisplayConfig; +use Magento\Tax\Model\Config as TaxConfig; class UpdateProductOptionsObserverTest extends \PHPUnit_Framework_TestCase { /** * Tests the methods that rely on the ScopeConfigInterface object to provide their return values * - * @param array $testArray The initial array that specifies the set of additional options + * @param array $initialArray The initial array that specifies the set of additional options * @param bool $weeeEnabled Whether the Weee module is assumed to be enabled - * @param bool $weeeDisplayExclDescIncl Is this Weee display setting assumed to be set + * @param int $weeeDisplay Which Weee display is configured + * @param int $priceDisplay Values are: including tax, excluding tax, or both including and excluding tax * @param array $expectedArray The revised array of the additional options * * @dataProvider updateProductOptionsProvider */ - public function testUpdateProductOptions($testArray, $weeeEnabled, $weeeDisplayExclDescIncl, $expectedArray) + public function testUpdateProductOptions($initialArray, $weeeEnabled, $weeeDisplay, $priceDisplay, $expectedArray) { $configObj = new \Magento\Framework\DataObject( [ - 'additional_options' => $testArray, + 'additional_options' => $initialArray, ] ); @@ -47,12 +50,26 @@ class UpdateProductOptionsObserverTest extends \PHPUnit_Framework_TestCase ->method('isEnabled') ->will($this->returnValue($weeeEnabled)); $weeeHelper->expects($this->any()) - ->method('geDisplayExlDescIncl') - ->will($this->returnValue($weeeDisplayExclDescIncl)); + ->method('isDisplayIncl') + ->will($this->returnValue($weeeDisplay == WeeeDisplayConfig::DISPLAY_INCL)); + $weeeHelper->expects($this->any()) + ->method('isDisplayExclDescIncl') + ->will($this->returnValue($weeeDisplay == WeeeDisplayConfig::DISPLAY_EXCL_DESCR_INCL)); + $weeeHelper->expects($this->any()) + ->method('isDisplayExcl') + ->will($this->returnValue($weeeDisplay == WeeeDisplayConfig::DISPLAY_EXCL)); $weeeHelper->expects($this->any()) ->method('getWeeeAttributesForBundle') ->will($this->returnValue([['fpt1' => $weeeObject1], ['fpt1'=>$weeeObject1, 'fpt2'=>$weeeObject2]])); + $taxHelper=$this->getMock('Magento\Tax\Helper\Data', [], [], '', false); + $taxHelper->expects($this->any()) + ->method('displayPriceExcludingTax') + ->will($this->returnValue($priceDisplay == TaxConfig::DISPLAY_TYPE_EXCLUDING_TAX)); + $taxHelper->expects($this->any()) + ->method('priceIncludesTax') + ->will($this->returnValue(true)); + $responseObject=$this->getMock('Magento\Framework\Event\Observer', ['getResponseObject'], [], '', false); $responseObject->expects($this->any()) ->method('getResponseObject') @@ -83,6 +100,7 @@ class UpdateProductOptionsObserverTest extends \PHPUnit_Framework_TestCase 'Magento\Weee\Observer\UpdateProductOptionsObserver', [ 'weeeData' => $weeeHelper, + 'taxData' => $taxHelper, 'registry' => $registry, ] ); @@ -99,13 +117,30 @@ class UpdateProductOptionsObserverTest extends \PHPUnit_Framework_TestCase { return [ 'weee not enabled' => [ - 'testArray' => [ + 'initialArray' => [ + 'TOTAL_BASE_CALCULATION' => 'TOTAL_BASE_CALCULATION', + 'optionTemplate' => '<%= data.label %><% if (data.finalPrice.value) ' + . '{ %> +<%- data.finalPrice.formatted %><% } %>', + ], + 'weeeEnabled' => false, + 'weeeDisplay' => WeeeDisplayConfig::DISPLAY_INCL, // has no effect for this scenario + 'priceDisplay' => TaxConfig::DISPLAY_TYPE_EXCLUDING_TAX, // has no effect for this scenario + 'expectedArray' => [ + 'TOTAL_BASE_CALCULATION' => 'TOTAL_BASE_CALCULATION', + 'optionTemplate' => '<%= data.label %><% if (data.finalPrice.value) ' + . '{ %> +<%- data.finalPrice.formatted %><% } %>', + ], + ], + + 'weee enabled, and display with Weee included in the price' => [ + 'initialArray' => [ 'TOTAL_BASE_CALCULATION' => 'TOTAL_BASE_CALCULATION', 'optionTemplate' => '<%= data.label %><% if (data.basePrice.value) ' . '{ %> +<%- data.basePrice.formatted %><% } %>', ], - 'weeeEnabled' => false, - 'weeeDisplayExclDescIncl' => true, + 'weeeEnabled' => true, + 'weeeDisplay' => WeeeDisplayConfig::DISPLAY_INCL, + 'priceDisplay' => TaxConfig::DISPLAY_TYPE_INCLUDING_TAX, 'expectedArray' => [ 'TOTAL_BASE_CALCULATION' => 'TOTAL_BASE_CALCULATION', 'optionTemplate' => '<%= data.label %><% if (data.basePrice.value) ' @@ -113,31 +148,33 @@ class UpdateProductOptionsObserverTest extends \PHPUnit_Framework_TestCase ], ], - 'weee enabled, but not displaying ExclDescIncl' => [ - 'testArray' => [ + 'weee enabled, and display with Weee included in the price, and include the Weee descriptions' => [ + 'initialArray' => [ 'TOTAL_BASE_CALCULATION' => 'TOTAL_BASE_CALCULATION', 'optionTemplate' => '<%= data.label %><% if (data.basePrice.value) ' . '{ %> +<%- data.basePrice.formatted %><% } %>', ], 'weeeEnabled' => true, - 'weeeDisplayExclDescIncl' => false, + 'weeeDisplay' => WeeeDisplayConfig::DISPLAY_INCL_DESCR, + 'priceDisplay' => TaxConfig::DISPLAY_TYPE_INCLUDING_TAX, 'expectedArray' => [ 'TOTAL_BASE_CALCULATION' => 'TOTAL_BASE_CALCULATION', 'optionTemplate' => '<%= data.label %><% if (data.basePrice.value) ' . '{ %> +<%- data.basePrice.formatted %><% } %> <% if (data.weeePricefpt1) ' - . '{ %> (: <%- data.weeePricefpt1.formatted %>)<% } %>' - . ' <% if (data.weeePricefpt2) { %> (: <%- data.weeePricefpt2.formatted %>)<% } %>', + . '{ %> (: <%- data.weeePricefpt1.formatted %>)<% } %> ' + . '<% if (data.weeePricefpt2) { %> (: <%- data.weeePricefpt2.formatted %>)<% } %>', ], ], 'weee enabled, and display with ExclDescIncl' => [ - 'testArray' => [ + 'initialArray' => [ 'TOTAL_BASE_CALCULATION' => 'TOTAL_BASE_CALCULATION', 'optionTemplate' => '<%= data.label %><% if (data.basePrice.value) ' . '{ %> +<%- data.basePrice.formatted %><% } %>', ], 'weeeEnabled' => true, - 'weeeDisplayExclDescIncl' => true, + 'weeeDisplay' => WeeeDisplayConfig::DISPLAY_EXCL_DESCR_INCL, + 'priceDisplay' => TaxConfig::DISPLAY_TYPE_INCLUDING_TAX, 'expectedArray' => [ 'TOTAL_BASE_CALCULATION' => 'TOTAL_BASE_CALCULATION', 'optionTemplate' => '<%= data.label %><% if (data.basePrice.value) ' @@ -147,6 +184,34 @@ class UpdateProductOptionsObserverTest extends \PHPUnit_Framework_TestCase . '<% if (data.weeePrice) { %><%- data.weeePrice.formatted %><% } %>', ], ], + + 'weee enabled, and display prices including tax but without Weee' => [ + 'initialArray' => [ + 'TOTAL_BASE_CALCULATION' => 'TOTAL_BASE_CALCULATION', + ], + 'weeeEnabled' => true, + 'weeeDisplay' => WeeeDisplayConfig::DISPLAY_EXCL, + 'priceDisplay' => TaxConfig::DISPLAY_TYPE_INCLUDING_TAX, + 'expectedArray' => [ + 'TOTAL_BASE_CALCULATION' => 'TOTAL_BASE_CALCULATION', + 'optionTemplate' => '<%- data.label %><% if (data.finalPrice.value) ' + . '{ %> +<%- data.finalPrice.formatted %><% } %>', + ], + ], + + 'weee enabled, and display prices excluding tax but without Weee' => [ + 'initialArray' => [ + 'TOTAL_BASE_CALCULATION' => 'TOTAL_BASE_CALCULATION', + ], + 'weeeEnabled' => true, + 'weeeDisplay' => WeeeDisplayConfig::DISPLAY_EXCL, + 'priceDisplay' => TaxConfig::DISPLAY_TYPE_EXCLUDING_TAX, + 'expectedArray' => [ + 'TOTAL_BASE_CALCULATION' => 'TOTAL_BASE_CALCULATION', + 'optionTemplate' => '<%- data.label %><% if (data.basePrice.value) ' + . '{ %> +<%- data.basePrice.formatted %><% } %>', + ], + ], ]; } } diff --git a/app/code/Magento/Weee/i18n/de_DE.csv b/app/code/Magento/Weee/i18n/de_DE.csv index 7ec820d9eb205f5c9f27ebef7b290e9a4e9d3ca9..5c64ff992a1fafd049616625934bd2feb3b6ba77 100644 --- a/app/code/Magento/Weee/i18n/de_DE.csv +++ b/app/code/Magento/Weee/i18n/de_DE.csv @@ -7,7 +7,7 @@ Website,Website "We found a duplicate of website, country and state fields for a fixed product tax","We found a duplicate of website, country and state fields for a fixed product tax" "Including FPT only","Lediglich einschließlich FPT" "Including FPT and FPT description","Einschließlich FPT und FPT-Beschreibung" -"Excluding FPT, FPT description, final price","Ausschließlich FPT, FPT-Beschreibung, Endpreis" +"Excluding FPT. Including FPT description and final price","Excluding FPT. Including FPT description and final price" "Excluding FPT","Ausschließlich FPT" "Fixed Product Tax","Feste Produktsteuer" Country/State,Country/State diff --git a/app/code/Magento/Weee/i18n/en_US.csv b/app/code/Magento/Weee/i18n/en_US.csv index e0989690885440cf7da81d32be361a8b2814234e..668926b681505716a6eb73ed537d715559a0cf41 100644 --- a/app/code/Magento/Weee/i18n/en_US.csv +++ b/app/code/Magento/Weee/i18n/en_US.csv @@ -7,7 +7,7 @@ Website,Website "We found a duplicate of website, country and state fields for a fixed product tax","We found a duplicate of website, country and state fields for a fixed product tax" "Including FPT only","Including FPT only" "Including FPT and FPT description","Including FPT and FPT description" -"Excluding FPT, FPT description, final price","Excluding FPT, FPT description, final price" +"Excluding FPT. Including FPT description and final price","Excluding FPT. Including FPT description and final price" "Excluding FPT","Excluding FPT" "Fixed Product Tax","Fixed Product Tax" Country/State,Country/State diff --git a/app/code/Magento/Weee/i18n/es_ES.csv b/app/code/Magento/Weee/i18n/es_ES.csv index 75afe15b65ecdf9ebdd74e2c5623116e493d9a8a..967e9d55c1650a2482c4b46460dc62581d408bfc 100644 --- a/app/code/Magento/Weee/i18n/es_ES.csv +++ b/app/code/Magento/Weee/i18n/es_ES.csv @@ -7,7 +7,7 @@ Website,Website "We found a duplicate of website, country and state fields for a fixed product tax","We found a duplicate of website, country and state fields for a fixed product tax" "Including FPT only","Incluir sólo FPT" "Including FPT and FPT description","Inlcuir impuestos y descripción de los impuestos" -"Excluding FPT, FPT description, final price","Excluido FPT, descripción FPT, precio final" +"Excluding FPT. Including FPT description and final price","Excluding FPT. Including FPT description and final price" "Excluding FPT","FPT no incluido" "Fixed Product Tax","Impuesto fijo del producto" Country/State,Country/State diff --git a/app/code/Magento/Weee/i18n/fr_FR.csv b/app/code/Magento/Weee/i18n/fr_FR.csv index 7570f61e26c2639aa9e0a7ed5406f320cf9a2527..3361b7bc238a1a7fa451350672cf9b3cc363eb0b 100644 --- a/app/code/Magento/Weee/i18n/fr_FR.csv +++ b/app/code/Magento/Weee/i18n/fr_FR.csv @@ -7,7 +7,7 @@ Website,Website "We found a duplicate of website, country and state fields for a fixed product tax","We found a duplicate of website, country and state fields for a fixed product tax" "Including FPT only","Inclure uniquement les taxes sur les produits fixes" "Including FPT and FPT description","Inclure les taxes sur les produits fixes et leur description" -"Excluding FPT, FPT description, final price","Exclure les taxes sur les produits fixes, les descriptions, et le prix final" +"Excluding FPT. Including FPT description and final price","Excluding FPT. Including FPT description and final price" "Excluding FPT","Exclure les taxes sur les produits fixes" "Fixed Product Tax","Taxe sur le produit fixe" Country/State,Country/State diff --git a/app/code/Magento/Weee/i18n/nl_NL.csv b/app/code/Magento/Weee/i18n/nl_NL.csv index b86bb1920067043ab369c9e056293be0601982c1..b21a8574d6dd2e3b192d79a47700df287dc41391 100644 --- a/app/code/Magento/Weee/i18n/nl_NL.csv +++ b/app/code/Magento/Weee/i18n/nl_NL.csv @@ -7,7 +7,7 @@ Website,Website "We found a duplicate of website, country and state fields for a fixed product tax","We found a duplicate of website, country and state fields for a fixed product tax" "Including FPT only","Inclusief alleen FPT" "Including FPT and FPT description","Inclusief FPT en FPT omschrijving" -"Excluding FPT, FPT description, final price","Met uitzondering van FPT, FPT omschrijving, definitieve prijs" +"Excluding FPT. Including FPT description and final price","Excluding FPT. Including FPT description and final price" "Excluding FPT","Met uitzondering van FPT" "Fixed Product Tax","Vaste Product Belasting" Country/State,Country/State diff --git a/app/code/Magento/Weee/i18n/pt_BR.csv b/app/code/Magento/Weee/i18n/pt_BR.csv index 7f2a0e7632ad9ef4553e6225c06ba2aa31ab0d32..881b6fe4a60aff57b39dbae4619549883f392348 100644 --- a/app/code/Magento/Weee/i18n/pt_BR.csv +++ b/app/code/Magento/Weee/i18n/pt_BR.csv @@ -7,7 +7,7 @@ Website,Website "We found a duplicate of website, country and state fields for a fixed product tax","We found a duplicate of website, country and state fields for a fixed product tax" "Including FPT only","Incluindo somente FPT" "Including FPT and FPT description","Incluindo FPT e descrição de FPT" -"Excluding FPT, FPT description, final price","Excluindo FPT, descrição de FPT, preço final" +"Excluding FPT. Including FPT description and final price","Excluding FPT. Including FPT description and final price" "Excluding FPT","Excluindo FPT" "Fixed Product Tax","Imposto fixo do produto" Country/State,Country/State diff --git a/app/code/Magento/Weee/i18n/zh_Hans_CN.csv b/app/code/Magento/Weee/i18n/zh_Hans_CN.csv index a2c88c879992e63a8e090089d07671e0b3bc6773..55878a66c3ffbe5e528693b31e9f78ae00ed8939 100644 --- a/app/code/Magento/Weee/i18n/zh_Hans_CN.csv +++ b/app/code/Magento/Weee/i18n/zh_Hans_CN.csv @@ -7,7 +7,7 @@ Website,Website "We found a duplicate of website, country and state fields for a fixed product tax","We found a duplicate of website, country and state fields for a fixed product tax" "Including FPT only","ä»…åŒ…å« FPT" "Including FPT and FPT description","åŒ…å« FPT å’Œ FPT æè¿°" -"Excluding FPT, FPT description, final price","ä¸åŒ…å« FPT,FPT æè¿°ï¼Œæœ€ç»ˆä»·æ ¼" +"Excluding FPT. Including FPT description and final price","Excluding FPT. Including FPT description and final price" "Excluding FPT","ä¸åŒ…å« FPT" "Fixed Product Tax",固定产å“税费 Country/State,Country/State diff --git a/app/code/Magento/Weee/view/frontend/templates/checkout/cart/item/price/sidebar.phtml b/app/code/Magento/Weee/view/frontend/templates/checkout/cart/item/price/sidebar.phtml index 0f71192ce3985097bb36583c0f7be9463ee1d00e..2da14c7d14b5e96b7e87c2972d035324704071ee 100644 --- a/app/code/Magento/Weee/view/frontend/templates/checkout/cart/item/price/sidebar.phtml +++ b/app/code/Magento/Weee/view/frontend/templates/checkout/cart/item/price/sidebar.phtml @@ -9,24 +9,30 @@ /** @var $block \Magento\Weee\Block\Item\Price\Renderer */ $item = $block->getItem(); + +// ensure we use the zone for the shopping cart / minicart +$originalZone = $block->getZone(); +$block->setZone(\Magento\Framework\Pricing\Render::ZONE_CART); ?> + <?php if ($block->displayPriceInclTax() || $block->displayBothPrices()): ?> -<span class="price-including-tax" data-label="<?php echo $block->escapeHtml(__('Incl. Tax')); ?>"> - <?php if ($block->displayPriceWithWeeeDetails()): ?> - <span class="minicart-tax-total"> - <?php else: ?> + <span class="price-including-tax" data-label="<?php echo $block->escapeHtml(__('Incl. Tax')); ?>"> + <?php if ($block->displayPriceWithWeeeDetails()): ?> + <span class="minicart-tax-total"> + <?php else: ?> <span class="minicart-price"> - <?php endif; ?> + <?php endif; ?> <?php /* @escapeNotVerified */ echo $block->formatPrice($block->getUnitDisplayPriceInclTax()); ?> - </span> + </span> + <?php if ($block->displayPriceWithWeeeDetails()): ?> <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($item)): ?> - <span class="minicart-tax-info" style="display: none"> - <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($item) as $tax): ?> - <span class="weee" data-label="<?php /* @escapeNotVerified */ echo $tax['title']; ?>"> - <?php /* @escapeNotVerified */ echo $block->formatPrice($tax['amount_incl_tax'], true, true); ?> - </span> - <?php endforeach; ?> + <span class="minicart-tax-info"> + <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($item) as $tax): ?> + <span class="weee" data-label="<?php /* @escapeNotVerified */ echo $tax['title']; ?>"> + <?php /* @escapeNotVerified */ echo $block->formatPrice($tax['amount_incl_tax'], true, true); ?> + </span> + <?php endforeach; ?> </span> <?php if ($block->displayFinalPrice()): ?> @@ -37,35 +43,39 @@ $item = $block->getItem(); </span> <?php endif; ?> <?php endif; ?> - </span> <?php endif; ?> + </span> +<?php endif; ?> - <?php if ($block->displayPriceExclTax() || $block->displayBothPrices()): ?> +<?php if ($block->displayPriceExclTax() || $block->displayBothPrices()): ?> <span class="price-excluding-tax" data-label="<?php echo $block->escapeHtml(__('Excl. Tax')); ?>"> - <?php if ($block->displayPriceWithWeeeDetails()): ?> + <?php if ($block->displayPriceWithWeeeDetails()): ?> <span class="minicart-tax-total"> - <?php else: ?> - <span class="minicart-price"> - <?php endif; ?> + <?php else: ?> + <span class="minicart-price"> + <?php endif; ?> <?php /* @escapeNotVerified */ echo $block->formatPrice($block->getUnitDisplayPriceExclTax()); ?> - </span> + </span> - <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($item)): ?> - <span class="minicart-tax-info"> - <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($item) as $tax): ?> - <span class="weee" data-label="<?php /* @escapeNotVerified */ echo $tax['title']; ?>"> - <?php /* @escapeNotVerified */ echo $block->formatPrice($tax['amount'], true, true); ?> - </span> - <?php endforeach; ?> + <?php if ($block->displayPriceWithWeeeDetails()): ?> + <?php if ($this->helper('Magento\Weee\Helper\Data')->getApplied($item)): ?> + <span class="minicart-tax-info"> + <?php foreach ($this->helper('Magento\Weee\Helper\Data')->getApplied($item) as $tax): ?> + <span class="weee" data-label="<?php /* @escapeNotVerified */ echo $tax['title']; ?>"> + <?php /* @escapeNotVerified */ echo $block->formatPrice($tax['amount'], true, true); ?> + </span> + <?php endforeach; ?> </span> <?php if ($block->displayFinalPrice()): ?> - <span class="minicart-tax-total"> + <span class="minicart-tax-total"> <span class="weee" data-label="<?php echo $block->escapeHtml(__('Total')); ?>"> <?php /* @escapeNotVerified */ echo $block->formatPrice($block->getFinalUnitDisplayPriceExclTax()); ?> </span> </span> - <?php endif; ?> <?php endif; ?> - </span> <?php endif; ?> + <?php endif; ?> + </span> +<?php endif; ?> +<?php $block->setZone($originalZone); ?> diff --git a/app/code/Magento/Weee/view/frontend/web/template/checkout/summary/weee.html b/app/code/Magento/Weee/view/frontend/web/template/checkout/summary/weee.html index 886e2443918e634c70676bc8218f9e3a66e41bcb..c8d5d922f95677df77c0e5d16d27abcf1d80ec44 100644 --- a/app/code/Magento/Weee/view/frontend/web/template/checkout/summary/weee.html +++ b/app/code/Magento/Weee/view/frontend/web/template/checkout/summary/weee.html @@ -7,7 +7,7 @@ <!-- ko if: isDisplayed() --> <tr class="totals"> <th data-bind="text: title" class="mark" scope="row"></th> - <td class="amount" data-bind="attr: {'data-th': $t(title) }"> + <td class="amount" data-bind="attr: {'data-th': title}"> <span class="price" data-bind="text: getValue()"></span> </td> </tr> diff --git a/app/code/Magento/Widget/view/adminhtml/templates/catalog/category/widget/tree.phtml b/app/code/Magento/Widget/view/adminhtml/templates/catalog/category/widget/tree.phtml index e114d5ade56fe7584a4ded49e4cf8b67335abafc..135880f5f314214efdc4d95540f489a5fc7bd8fe 100644 --- a/app/code/Magento/Widget/view/adminhtml/templates/catalog/category/widget/tree.phtml +++ b/app/code/Magento/Widget/view/adminhtml/templates/catalog/category/widget/tree.phtml @@ -10,9 +10,7 @@ <?php $_divId = 'tree' . $block->getId() ?> <div id="<?php /* @escapeNotVerified */ echo $_divId ?>" class="tree"></div> -<!--[if IE]> <script id="ie-deferred-loader" defer="defer" src=""></script> -<![endif]--> <script> require(['jquery', "prototype", "extjs/ext-tree-checkbox"], function(jQuery){ diff --git a/app/code/Magento/Widget/view/adminhtml/templates/instance/edit/layout.phtml b/app/code/Magento/Widget/view/adminhtml/templates/instance/edit/layout.phtml index 94a3eb7145be0c27125f3adfbddd11b998bade3e..6831ca32a007b1c5abe9f67b322e76fe5ee38749 100644 --- a/app/code/Magento/Widget/view/adminhtml/templates/instance/edit/layout.phtml +++ b/app/code/Magento/Widget/view/adminhtml/templates/instance/edit/layout.phtml @@ -15,9 +15,7 @@ <div class="actions"><?php echo $block->getAddLayoutButtonHtml() ?></div> </div> </fieldset> -<!--[if IE]> <script id="ie-deferred-loader" defer="defer" src=""></script> -<![endif]--> <script> require([ 'jquery', diff --git a/app/code/Magento/Wishlist/CustomerData/Wishlist.php b/app/code/Magento/Wishlist/CustomerData/Wishlist.php index 2c4379872b8abf1136d02b1fc068c71afbf6c661..c937e334992c272815cd03f1cd2ee74daab80286 100644 --- a/app/code/Magento/Wishlist/CustomerData/Wishlist.php +++ b/app/code/Magento/Wishlist/CustomerData/Wishlist.php @@ -3,7 +3,6 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Wishlist\CustomerData; use Magento\Customer\CustomerData\SectionSourceInterface; @@ -24,9 +23,9 @@ class Wishlist implements SectionSourceInterface protected $wishlistHelper; /** - * @var \Magento\Catalog\Helper\Image + * @var \Magento\Catalog\Helper\ImageFactory */ - protected $imageHelper; + protected $imageHelperFactory; /** * @var \Magento\Framework\App\ViewInterface @@ -41,17 +40,17 @@ class Wishlist implements SectionSourceInterface /** * @param \Magento\Wishlist\Helper\Data $wishlistHelper * @param \Magento\Wishlist\Block\Customer\Sidebar $block - * @param \Magento\Catalog\Helper\Image $imageHelper + * @param \Magento\Catalog\Helper\ImageFactory $imageHelperFactory * @param \Magento\Framework\App\ViewInterface $view */ public function __construct( \Magento\Wishlist\Helper\Data $wishlistHelper, \Magento\Wishlist\Block\Customer\Sidebar $block, - \Magento\Catalog\Helper\Image $imageHelper, + \Magento\Catalog\Helper\ImageFactory $imageHelperFactory, \Magento\Framework\App\ViewInterface $view ) { $this->wishlistHelper = $wishlistHelper; - $this->imageHelper = $imageHelper; + $this->imageHelperFactory = $imageHelperFactory; $this->block = $block; $this->view = $view; } @@ -100,35 +99,77 @@ class Wishlist implements SectionSourceInterface protected function getItems() { $this->view->loadLayout(); + $collection = $this->wishlistHelper->getWishlistItemCollection(); $collection->clear()->setPageSize(self::SIDEBAR_ITEMS_NUMBER) ->setInStockFilter(true)->setOrder('added_at'); + $items = []; - /** @var \Magento\Wishlist\Model\Item $wishlistItem */ foreach ($collection as $wishlistItem) { - $product = $wishlistItem->getProduct(); - $this->imageHelper->init($product, 'wishlist_sidebar_block'); - $items[] = [ - 'image' => [ - 'src' => $this->imageHelper->getUrl(), - 'alt' => $this->imageHelper->getLabel(), - 'width' => $this->imageHelper->getWidth(), - 'height' => $this->imageHelper->getHeight(), - ], - 'product_url' => $this->wishlistHelper->getProductUrl($wishlistItem), - 'product_name' => $product->getName(), - 'product_price' => $this->block->getProductPriceHtml( - $product, - \Magento\Catalog\Pricing\Price\ConfiguredPriceInterface::CONFIGURED_PRICE_CODE, - \Magento\Framework\Pricing\Render::ZONE_ITEM_LIST, - ['item' => $wishlistItem] - ), - 'product_is_saleable_and_visible' => $product->isSaleable() && $product->isVisibleInSiteVisibility(), - 'product_has_required_options' => $product->getTypeInstance()->hasRequiredOptions($product), - 'add_to_cart_params' => $this->wishlistHelper->getAddToCartParams($wishlistItem, true), - 'delete_item_params' => $this->wishlistHelper->getRemoveParams($wishlistItem, true), - ]; + $items[] = $this->getItemData($wishlistItem); } return $items; } + + /** + * Retrieve wishlist item data + * + * @param \Magento\Wishlist\Model\Item $wishlistItem + * @return array + */ + protected function getItemData(\Magento\Wishlist\Model\Item $wishlistItem) + { + $product = $wishlistItem->getProduct(); + return [ + 'image' => $this->getImageData($product), + 'product_url' => $this->wishlistHelper->getProductUrl($wishlistItem), + 'product_name' => $product->getName(), + 'product_price' => $this->block->getProductPriceHtml( + $product, + \Magento\Catalog\Pricing\Price\ConfiguredPriceInterface::CONFIGURED_PRICE_CODE, + \Magento\Framework\Pricing\Render::ZONE_ITEM_LIST, + ['item' => $wishlistItem] + ), + 'product_is_saleable_and_visible' => $product->isSaleable() && $product->isVisibleInSiteVisibility(), + 'product_has_required_options' => $product->getTypeInstance()->hasRequiredOptions($product), + 'add_to_cart_params' => $this->wishlistHelper->getAddToCartParams($wishlistItem, true), + 'delete_item_params' => $this->wishlistHelper->getRemoveParams($wishlistItem, true), + ]; + } + + /** + * Retrieve product image data + * + * @param \Magento\Catalog\Model\Product $product + * @return \Magento\Catalog\Block\Product\Image + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + protected function getImageData($product) + { + /** @var \Magento\Catalog\Helper\Image $helper */ + $helper = $this->imageHelperFactory->create() + ->init($product, 'wishlist_sidebar_block'); + + $template = $helper->getFrame() + ? 'Magento_Catalog/product/image' + : 'Magento_Catalog/product/image_with_borders'; + + $imagesize = $helper->getResizedImageInfo(); + + $width = $helper->getFrame() + ? $helper->getWidth() + : (!empty($imagesize[0]) ? $imagesize[0] : $helper->getWidth()); + + $height = $helper->getFrame() + ? $helper->getHeight() + : (!empty($imagesize[1]) ? $imagesize[1] : $helper->getHeight()); + + return [ + 'template' => $template, + 'src' => $helper->getUrl(), + 'width' => $width, + 'height' => $height, + 'alt' => $helper->getLabel(), + ]; + } } diff --git a/app/code/Magento/Wishlist/Test/Unit/CustomerData/WishlistTest.php b/app/code/Magento/Wishlist/Test/Unit/CustomerData/WishlistTest.php index 24368820dc4df78f31f2bb407631a4a7caadd564..470be780e1269ea0f56088a151171820e67c1368 100644 --- a/app/code/Magento/Wishlist/Test/Unit/CustomerData/WishlistTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/CustomerData/WishlistTest.php @@ -46,16 +46,24 @@ class WishlistTest extends \PHPUnit_Framework_TestCase $this->sidebarMock = $this->getMockBuilder('Magento\Wishlist\Block\Customer\Sidebar') ->disableOriginalConstructor() ->getMock(); + $this->viewMock = $this->getMockBuilder('Magento\Framework\App\ViewInterface') + ->getMockForAbstractClass(); + $this->catalogImageHelperMock = $this->getMockBuilder('Magento\Catalog\Helper\Image') ->disableOriginalConstructor() ->getMock(); - $this->viewMock = $this->getMockBuilder('Magento\Framework\App\ViewInterface') - ->getMockForAbstractClass(); + $imageHelperFactory = $this->getMockBuilder('Magento\Catalog\Helper\ImageFactory') + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $imageHelperFactory->expects($this->any()) + ->method('create') + ->willReturn($this->catalogImageHelperMock); $this->model = new Wishlist( $this->wishlistHelperMock, $this->sidebarMock, - $this->catalogImageHelperMock, + $imageHelperFactory, $this->viewMock ); } @@ -83,6 +91,7 @@ class WishlistTest extends \PHPUnit_Framework_TestCase 'items' => [ [ 'image' => [ + 'template' => 'Magento_Catalog/product/image', 'src' => $imageUrl, 'alt' => $imageLabel, 'width' => $imageWidth, @@ -165,6 +174,12 @@ class WishlistTest extends \PHPUnit_Framework_TestCase $this->catalogImageHelperMock->expects($this->once()) ->method('getHeight') ->willReturn($imageHeight); + $this->catalogImageHelperMock->expects($this->any()) + ->method('getFrame') + ->willReturn(true); + $this->catalogImageHelperMock->expects($this->once()) + ->method('getResizedImageInfo') + ->willReturn([]); $this->wishlistHelperMock->expects($this->once()) ->method('getProductUrl') @@ -251,6 +266,7 @@ class WishlistTest extends \PHPUnit_Framework_TestCase 'items' => [ [ 'image' => [ + 'template' => 'Magento_Catalog/product/image', 'src' => $imageUrl, 'alt' => $imageLabel, 'width' => $imageWidth, @@ -266,6 +282,7 @@ class WishlistTest extends \PHPUnit_Framework_TestCase ], [ 'image' => [ + 'template' => 'Magento_Catalog/product/image', 'src' => $imageUrl, 'alt' => $imageLabel, 'width' => $imageWidth, @@ -342,6 +359,12 @@ class WishlistTest extends \PHPUnit_Framework_TestCase $this->catalogImageHelperMock->expects($this->exactly(2)) ->method('getHeight') ->willReturn($imageHeight); + $this->catalogImageHelperMock->expects($this->any()) + ->method('getFrame') + ->willReturn(true); + $this->catalogImageHelperMock->expects($this->exactly(2)) + ->method('getResizedImageInfo') + ->willReturn([]); $this->wishlistHelperMock->expects($this->exactly(2)) ->method('getProductUrl') diff --git a/app/code/Magento/Wishlist/view/frontend/templates/sidebar.phtml b/app/code/Magento/Wishlist/view/frontend/templates/sidebar.phtml index bab2e79a75f3310e63bbe5352f47818e81cd74a0..1d7eb6e7dcc73247b72d1999701a863eb97aaf7c 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/sidebar.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/sidebar.phtml @@ -26,7 +26,7 @@ $wishlistHelper = $this->helper('Magento\Wishlist\Helper\Data'); <li class="product-item"> <div class="product-item-info"> <a class="product-item-photo" data-bind="attr: { href: product_url, title: product_name }"> - <!-- ko template: {name: 'Magento_Wishlist/product_image', data: $data.image} --><!-- /ko --> + <!-- ko template: {name: $data.image.template, data: $data.image} --><!-- /ko --> </a> <div class="product-item-details"> <strong class="product-item-name"> diff --git a/app/code/Magento/Wishlist/view/frontend/web/template/product_image.html b/app/code/Magento/Wishlist/view/frontend/web/template/product_image.html deleted file mode 100644 index da88b3236c986563e459da8021213663f556158a..0000000000000000000000000000000000000000 --- a/app/code/Magento/Wishlist/view/frontend/web/template/product_image.html +++ /dev/null @@ -1,7 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<img class="photo image" data-bind="attr: {src: src, alt: alt}, style: {width: width + 'px', height: height + 'px'}" /> diff --git a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_collapsible-blocks.less b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_collapsible-blocks.less index 730f3d53ff58c7e23ab424d3926e85948cf1d305..78129d62a70de8796227b5d870c8aadafe147861 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_collapsible-blocks.less +++ b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_collapsible-blocks.less @@ -253,6 +253,9 @@ .scope-label { padding: 31px 1.5rem 0 0; } + .use-default { + padding: 29px 1.5rem 0 0; + } .value { padding-right: 4rem; } diff --git a/app/design/adminhtml/Magento/backend/Magento_ConfigurableProduct/web/css/source/_module.less b/app/design/adminhtml/Magento/backend/Magento_ConfigurableProduct/web/css/source/_module.less index 16606bb518d0a486f728d432bc957e385edf9e83..3d25c7dbf0b6731c2cffeaeff881d293dcefae95 100644 --- a/app/design/adminhtml/Magento/backend/Magento_ConfigurableProduct/web/css/source/_module.less +++ b/app/design/adminhtml/Magento/backend/Magento_ConfigurableProduct/web/css/source/_module.less @@ -11,7 +11,7 @@ @import 'module/components/_navigation-bar.less'; // Navigation Bar @import 'module/components/_grid.less'; // Grid styles @import 'module/components/_currency-addon.less'; // Currency Addon Styles -@import 'module/components/_attributes_template_popup.less'; // Choose Affected Product Template popup +@import 'module/components/_attributes_template_popup.less'; // Choose Affected Attribute Set popup // Main Steps @import 'module/steps/_select-attributes.less'; diff --git a/app/design/adminhtml/Magento/backend/web/css/styles-old.less b/app/design/adminhtml/Magento/backend/web/css/styles-old.less index 7390b3177b8360a5f41fd5cdfe839e1cbf56fa1c..9f624fea87ed90b28856fa0be9b5632e31471ea3 100644 --- a/app/design/adminhtml/Magento/backend/web/css/styles-old.less +++ b/app/design/adminhtml/Magento/backend/web/css/styles-old.less @@ -2640,8 +2640,8 @@ } // -// Configuration -> Design -// -------------------------------------- + // Configuration -> Design + // -------------------------------------- #row_design_theme_ua_regexp .design_theme_ua_regexp { float: left; @@ -2654,6 +2654,16 @@ clear: both; } + // + // Configuration -> Advanced -> System -> Notifications section + // -------------------------------------- + + #row_system_adminnotification_last_update { + .value { + vertical-align: bottom; + } + } + // // CMS -> Banners // -------------------------------------- diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_payment-options.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_payment-options.less index 0de27d21df32f5a65c45e23f1c67b5a09f1fd9d1..4f8c9b771654909e46c3d61764fa9a134c03ff44 100644 --- a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_payment-options.less +++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_payment-options.less @@ -105,6 +105,58 @@ filter: gray; // For IE 6 - 9 } } + + .ccard { + .legend { + &:extend(.abs-visually-hidden all); + } + .fields { + > .year { + padding-left: @indent__xs; + } + .select { + padding-left: @indent__xs; + padding-right: @indent__xs; + } + } + .month { + .select { + width: 140px; + } + } + .year { + .select { + width: 80px; + } + } + .number { + .input-text { + width: 225px; + } + } + + > .field.cvv { + > .control { + padding-right: @indent__base; + width: auto; + } + } + .cvv { + .input-text { + width: 55px; + } + } + + &.fieldset { + > .field { + .fields.group.group-2 { + .field { + width: auto !important; + } + } + } + } + } } } diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_payments.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_payments.less index 741516ae64dd30e2e11067ebc2a3c7d574ba95a9..516d9e21e8b091645193355d94bef8c86f5c2f87 100644 --- a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_payments.less +++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_payments.less @@ -76,13 +76,6 @@ margin: 0 0 @indent__base; } } - .field { - &.cvv { - .control { - width: 40%; - } - } - } } .field-select-billing, @@ -136,14 +129,6 @@ .no-payments-block { margin: @indent__base 0; } - .ccard { - .legend { - &:extend(.abs-visually-hidden all); - } - .year { - padding-left: @indent__l; - } - } .payments { .legend { &:extend(.abs-visually-hidden all); diff --git a/app/design/frontend/Magento/blank/Magento_LayeredNavigation/web/css/source/_module.less b/app/design/frontend/Magento/blank/Magento_LayeredNavigation/web/css/source/_module.less index 8b3d0a38fe55dcf3540acd828ce9a4eae32f0f4a..c51aac33382940011e165490c0ca0eae85451536 100644 --- a/app/design/frontend/Magento/blank/Magento_LayeredNavigation/web/css/source/_module.less +++ b/app/design/frontend/Magento/blank/Magento_LayeredNavigation/web/css/source/_module.less @@ -4,75 +4,88 @@ // */ // -// Common -//-------------------------------------- +// Common +// _____________________________________________ & when (@media-common = true) { -.block.filter { - margin-bottom: 40px; - .title { - margin-bottom: 20px; - strong { - font-size: 18px; - } - } - .subtitle { - display: none; - } - .filter-options-content { - .filter-count-label { - &:extend(.abs-visually-hidden all); + .block.filter { + margin-bottom: @indent__xl ; + .title { + margin-bottom: @indent__base; + strong { + font-size: 18px; + } } - } - .options { - margin: 0; - > dt { - .lib-heading(h4); - margin: 0 0 10px; + .subtitle { + display: none; } - > dd { - margin: 0 0 25px; - - .item { - margin-bottom: 3px; + .filter-options-content { + .filter-count-label { + &:extend(.abs-visually-hidden all); } } - .count { - .lib-css(color, @text__color__muted); - &:before { - content: '('; + .options { + margin: 0; + > dt { + .lib-heading(h4); + margin: 0 0 @indent__s; } - &:after { - content: ')'; + > dd { + margin: 0 0 @indent__m; + + .item { + margin-bottom: 3px; + } + } + .count { + .lib-css(color, @text__color__muted); + &:before { + content: '('; + } + &:after { + content: ')'; + } } } - } - .items { - &:extend(.abs-reset-list all); - } - .filtered { .items { - margin: 15px 0; + &:extend(.abs-reset-list all); } - .item { - position: relative; - padding-left: 22px; - margin-bottom: 6px; - .label { - font-weight: @font-weight__bold; + .filtered { + .items { + margin: 15px 0; } - .action.remove { - &:extend(.abs-remove-button-for-blocks all); - position: absolute; - left: -6px; - top: 0; + .item { + margin-bottom: 6px; + padding-left: 22px; + position: relative; + .label { + font-weight: @font-weight__bold; + } + .action.remove { + &:extend(.abs-remove-button-for-blocks all); + left: -6px; + position: absolute; + top: 0; + } + } + & + .actions { + margin-bottom: 35px; } - } - & + .actions { - margin-bottom: 35px; } } } +// +// Mobile +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) { + .page-with-filter { + .columns { + .sidebar-main { + .lib-vendor-prefix-order(0); + } + } + } } diff --git a/app/design/frontend/Magento/blank/web/css/source/_navigation.less b/app/design/frontend/Magento/blank/web/css/source/_navigation.less index 4e4b410c5f6e28d62b5619792c739f760976103f..f4fee4d5d7d4e92f7c16e69eb4c83c469f7b58b6 100644 --- a/app/design/frontend/Magento/blank/web/css/source/_navigation.less +++ b/app/design/frontend/Magento/blank/web/css/source/_navigation.less @@ -86,7 +86,7 @@ font-size: 1.6rem; font-weight: 700; margin: 0; - padding: 8px 20px; + padding: .8rem 3.5rem .8rem 2rem; .label { display: block; margin-bottom: @indent__xs; @@ -125,16 +125,17 @@ .header.links { .lib-list-reset-styles(); + border-bottom: 1px solid @color-gray82; li { - border-top: 1px solid @color-gray82; font-size: 1.6rem; margin: 0; &.greet.welcome { + border-top: 1px solid @color-gray82; font-weight: 700; - padding: 8px 20px; + padding: .8rem @indent__base; } - &:last-child { - border-bottom: 1px solid @color-gray82; + > a { + border-top: 1px solid @color-gray82; } } a, @@ -143,7 +144,10 @@ .lib-css(text-decoration, @navigation-level0-item__text-decoration); display: block; font-weight: 700; - padding: 8px 20px; + padding: .8rem @indent__base; + } + .header.links { + border: 0; } } } @@ -217,6 +221,11 @@ background: transparent; border-bottom: 0; } + .nav-sections-item-switch { + &:hover { + text-decoration: none; + } + } } &-item-content { diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_payment-options.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_payment-options.less new file mode 100644 index 0000000000000000000000000000000000000000..555098fcefb113aa8c98fa535c37ac960278abe2 --- /dev/null +++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_payment-options.less @@ -0,0 +1,203 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Variables +// _____________________________________________ + +@checkout-payment-option-title__border: @checkout-payment-method-title__border; +@checkout-payment-option-title__color: @link__color; +@checkout-payment-option-title__padding: @checkout-payment-method-title__padding; +@checkout-payment-option-title-mobile__padding: @checkout-payment-method-title-mobile__padding; + +@checkout-payment-option-title-icon__font-size: 32px; +@checkout-payment-option-title-icon__line-height: 16px; +@checkout-payment-option-title-icon__margin: 0; +@checkout-payment-option-title-icon__color: @minicart-icons-color; +@checkout-payment-option-title-icon__hover__color: @primary__color; + +@checkout-payment-option-content__padding__xl: @checkout-payment-method-content__padding__xl; + +// +// Common +// _____________________________________________ + +& when (@media-common = true) { + .checkout-payment-method { + .payment-option { + &._active { + .payment-option-title { + .action-toggle { + &:after { + content: @icon-up; + } + } + } + } + &._collapsible { + .payment-option-title { + cursor: pointer; + } + .payment-option-content { + display: none; + } + } + } + + .payment-option-title { + .lib-css(border-top, @checkout-payment-option-title__border); + .lib-css(padding, @checkout-payment-option-title__padding 0); + + .action-toggle { + .lib-css(color, @checkout-payment-option-title__color); + .lib-icon-font( + @icon-down, + @_icon-font-size: @checkout-payment-option-title-icon__font-size, + @_icon-font-line-height: @checkout-payment-option-title-icon__line-height, + @_icon-font-color: @checkout-payment-option-title-icon__color, + @_icon-font-color-hover: @checkout-payment-option-title-icon__hover__color, + @_icon-font-color-active: @checkout-payment-option-title-icon__color, + @_icon-font-margin: @checkout-payment-option-title-icon__margin, + @_icon-font-position: after + ); + } + } + + .payment-option-content { + .lib-css(padding, 0 0 @indent__base @checkout-payment-option-content__padding__xl); + } + + .payment-option-inner { + margin: 0 0 @indent__base; + } + + .credit-card-types { + padding: 0; + .item { + display: inline-block; + list-style: none; + margin: 0 @indent__xs 0 0; + vertical-align: top; + &._active { + font-weight: @font-weight__bold; + img { + -webkit-filter: grayscale(0%); + filter: grayscale(0%); + filter: none; + } + } + &._inactive { + opacity: 0.4; + filter: alpha(opacity=40); + } + span { + display: inline-block; + padding-top: 6px; + vertical-align: top; + } + } + img { + -webkit-filter: grayscale(100%); // For Webkit browsers + -webkit-transition: all .6s ease; // Fade to color for Chrome and Safari + filter: grayscale(100%); + filter: gray; // For IE 6 - 9 + } + } + + .ccard { + .legend { + &:extend(.abs-visually-hidden all); + } + .fields { + > .year { + padding-left: @indent__xs; + } + .select { + padding-left: @indent__xs; + padding-right: @indent__xs; + } + } + .month { + .select { + width: 140px; + } + } + .year { + .select { + width: 80px; + } + } + .number { + .input-text { + width: 225px; + } + } + + > .field.cvv { + > .control { + display: inline-block; + padding-right: @indent__base; + } + } + .cvv { + .label { + display: block; + } + .input-text { + width: 55px; + } + } + + &.fieldset { + > .field { + .fields.group.group-2 { + .field { + width: auto !important; + } + } + } + } + } + } +} + +// +// Mobile +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) { + .checkout-payment-method { + .payment-option { + .lib-css(margin, 0 -(@checkout-payment-option-title-mobile__padding)); + + .payment-option-title { + .lib-css(padding, @checkout-payment-option-title-mobile__padding) + } + + .payment-option-content { + .lib-css(padding, 0 @checkout-payment-option-title-mobile__padding @indent__base); + } + } + } +} + +// +// Desktop +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { + .checkout-payment-method { + .payment-option-title { + .lib-css(padding-left, @checkout-payment-option-content__padding__xl); + } + .payment-option-content { + .payment-option-inner { + + .actions-toolbar { + margin-left: 0; + } + } + } + } +} diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_payments.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_payments.less index c0f1168e6ef0f0a2513ed747ed59cebf21d85fe4..0940e6e4723609fa1da4a64f6fa315bca9999472 100644 --- a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_payments.less +++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_payments.less @@ -76,13 +76,6 @@ margin: 0 0 @indent__base; } } - .field { - &.cvv { - .control { - width: 40%; - } - } - } } .field-select-billing, @@ -136,14 +129,6 @@ .no-payments-block { margin: @indent__base 0; } - .ccard { - .legend { - &:extend(.abs-visually-hidden all); - } - .year { - padding-left: @indent__l; - } - } .payments { .legend { &:extend(.abs-visually-hidden all); diff --git a/app/design/frontend/Magento/luma/Magento_LayeredNavigation/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_LayeredNavigation/web/css/source/_module.less index 898ddc99afdfa2d23f5d8f7baf12d8d65baec71e..17cadfeb19cd5bec72ae4e0f54888586dbf3f39e 100644 --- a/app/design/frontend/Magento/luma/Magento_LayeredNavigation/web/css/source/_module.less +++ b/app/design/frontend/Magento/luma/Magento_LayeredNavigation/web/css/source/_module.less @@ -4,238 +4,239 @@ // */ // -// Common -//-------------------------------------- +// Common +// _____________________________________________ & when (@media-common = true) { + .filter { + &.block { + margin-bottom: 0; + } + &-title { + strong { + @_shadow: inset 0 1px 0 0 @color-white, inset 0 -1px 0 0 fade(@border-color__base, 30); -.filter { - &.block { - margin-bottom: 0; - } - &-title { - strong { - position: absolute; - z-index: 2; - line-height: 16px; - border: 1px solid @border-color__base; - text-align: center; - padding: 7px 10px; - @_shadow: inset 0 1px 0 0 @color-white, inset 0 -1px 0 0 fade(@border-color__base, 30); - .lib-css(background-color, @toolbar-element-background); - .lib-css(box-shadow, @_shadow); - border-radius: 3px; - font-weight: 400; - top: 0; - left: 0; - &[data-count]:after { - content: attr(data-count); - display: inline-block; - border-radius: 2px; - padding: 2px; - font-size: .8em; - margin: 0 5px; - .lib-css(color, @color-white); - min-width: 1em; - line-height: 1; - background: @color-orange-red4; - } - &.disabled { - opacity: .5; + .lib-css(background-color, @toolbar-element-background); + .lib-css(box-shadow, @_shadow); + border-radius: 3px; + border: 1px solid @border-color__base; + font-weight: 400; + left: 0; + line-height: 16px; + padding: 7px @indent__s; + position: absolute; + text-align: center; + top: 0; + z-index: 2; + &[data-count]:after { + .lib-css(color, @color-white); + background: @color-orange-red4; + border-radius: 2px; + content: attr(data-count); + display: inline-block; + font-size: .8em; + line-height: 1; + margin: 0 @indent__xs; + min-width: 1em; + padding: 2px; + } + &.disabled { + opacity: .5; + } } } - } - .block-subtitle { - font-weight: @font-weight__semibold; - padding: @indent__s @indent__s @indent__base; - font-size: @font-size__base; - line-height: 1em; - border-bottom: @border-width__base solid @border-color__base; - } - &-subtitle { - display: none; - } - &-current { - margin: 0; - .items { - padding: @indent__xs @indent__s; + .block-subtitle { + border-bottom: @border-width__base solid @border-color__base; + font-size: @font-size__base; + font-weight: @font-weight__semibold; + line-height: 1em; + padding: @indent__s @indent__s @indent__base; } - .item { - position: relative; - z-index: 1; - padding-left: 17px; + &-subtitle { + display: none; } - .filter &-subtitle { - display: block; - border: none; - padding-bottom: @indent__s; + &-current { + margin: 0; + .items { + padding: @indent__xs @indent__s; + } + .item { + padding-left: 17px; + position: relative; + z-index: 1; + } + .filter &-subtitle { + border: none; + display: block; + padding-bottom: @indent__s; + } + .action.remove { + &:extend(.abs-remove-button-for-blocks all); + left: -2px; + position: absolute; + top: -1px; + } } - .action.remove { - &:extend(.abs-remove-button-for-blocks all); - position: absolute; - left: -2px; - top: -1px; + &-actions { + margin-bottom: @indent__m; + padding: 0 @indent__s; } - } - &-actions { - padding: 0 @indent__s; - margin-bottom: @indent__m; - } - &-label { - font-weight: @font-weight__bold; - &:after { - content: ": "; + &-label { + font-weight: @font-weight__bold; + &:after { + content: ': '; + } } - } - &-value { - .lib-css(color, @filter-quantity); - } - &-options { - display: none; - margin: 0; - &-item { - border-bottom: @border-width__base solid @border-color__base; - padding-bottom: @indent__s; + &-value { + .lib-css(color, @filter-quantity); } - &-title { - cursor: pointer; - font-weight: @font-weight__semibold; + &-options { + display: none; margin: 0; - overflow: hidden; - padding: @indent__s 20px+@indent__s 0 @indent__s; - position: relative; - z-index: 1; - text-transform: uppercase; - - .lib-icon-font( + &-item { + border-bottom: @border-width__base solid @border-color__base; + padding-bottom: @indent__s; + } + &-title { + cursor: pointer; + font-weight: @font-weight__semibold; + margin: 0; + overflow: hidden; + padding: @indent__s 20px+@indent__s 0 @indent__s; + position: relative; + text-transform: uppercase; + z-index: 1; + .lib-icon-font( @_icon-font-content: @icon-down, @_icon-font-size: 13px, @_icon-font-position: after, @_icon-font-display: block - ); - &:after { - position: absolute; - right: 13px; - top: 9px; - } - &:hover { - .lib-css(color, @filter-link-hover); - } - .active > & { - .lib-icon-font-symbol( - @_icon-font-content: @icon-up, - @_icon-font-position: after ); - } - } - &-content { - margin: 0; - padding: @indent__s; - .item { - margin: @indent__s 0; - line-height: 1.5em; - } - a { - .lib-css(color, @filter-link); - margin-right: -5px; - padding-left: 5px; - margin-left: -5px; - padding-right: 7px; + + &:after { + position: absolute; + right: 13px; + top: 9px; + } &:hover { - background-color: @color-gray91; - text-decoration: none; - & + .count { + .lib-css(color, @filter-link-hover); + } + .active > & { + .lib-icon-font-symbol( + @_icon-font-content: @icon-up, + @_icon-font-position: after + ); + } + } + &-content { + margin: 0; + padding: @indent__s; + .item { + margin: @indent__s 0; + line-height: 1.5em; + } + a { + .lib-css(color, @filter-link); + margin-left: -5px; + margin-right: -5px; + padding-left: 5px; + padding-right: 7px; + &:hover { background-color: @color-gray91; + text-decoration: none; + & + .count { + background-color: @color-gray91; + } } } - } - .count { - .lib-css(color, @filter-quantity); - padding-right: 5px; - &:before { - content: "("; + .count { + .lib-css(color, @filter-quantity); + padding-right: 5px; + &:before { + content: '('; + } + &:after { + content: ')'; + } } - &:after { - content: ")"; + .filter-count-label { + &:extend(.abs-visually-hidden all); } } - .filter-count-label { - &:extend(.abs-visually-hidden all); - } } } } -} - // -// Mobile -//-------------------------------------- +// Mobile +// _____________________________________________ .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) { - body.filter-active { - .page-wrapper { - visibility: hidden; - height: 0; - margin-top: -999999em; - } - .columns { - z-index: 999; + body { + &.filter-active { + .page-wrapper { + height: 0; + margin-top: -999999em; + visibility: hidden; + } + .columns { + z-index: 999; + } } } .filter { &.active { position: relative; - z-index: 99; visibility: visible; + z-index: 99; .filter-options-item:last-child { margin-bottom: @indent__xl; } .filter-title { + border-bottom: 1px solid @border-color__base; + height: 48px; + left: 0; position: fixed; - top: 0; right: 0; - left: 0; - height: 48px; + top: 0; z-index: 2; - border-bottom: 1px solid @border-color__base; strong { - right: 3px; - left: auto; - top: 10px; - border: 0; - background: none; - .lib-css(box-shadow, none); - color: transparent; - .lib-icon-font( - @icon-remove, - @_icon-font-color: @text__color__muted, - @_icon-font-size: 16px, - @_icon-font-position: after - ); + .lib-css(box-shadow, none); + background: none; + border: 0; + color: transparent; + left: auto; + right: 3px; + top: 10px; + .lib-icon-font( + @icon-remove, + @_icon-font-color: @text__color__muted, + @_icon-font-size: 16px, + @_icon-font-position: after + ); } } .filter-subtitle { + .lib-css(background, @toolbar-background); display: block; + height: 50px; + left: 0; + line-height: 32px; position: fixed; - top: 0; right: 0; - left: 0; - height: 50px; - .lib-css(background, @toolbar-background); + top: 0; z-index: 1; - line-height: 32px; } .filter-options { + .lib-css(background, @color-white); + bottom: 0; display: block; - position: fixed; - top: 50px; left: 0; - right: 0; - bottom: 0; overflow: scroll; - .lib-css(background, @color-white); + position: fixed; + right: 0; + top: 50px; z-index: 10; } } @@ -253,36 +254,23 @@ padding: @indent__xs @indent__s; } } - .filter-no-options { - .filter-title:before { - content: ""; - width: 100px; - height: 40px; - background: rgba(255,255,255,.5); - display: block; - position: relative; - z-index: 99; - margin-top: -40px; - left: -15px; - } - } .filter .filter-current { - margin: @indent__xs -@indent__s 0; border: solid @border-color__base; border-width: 1px 0; + margin: @indent__xs -@indent__s 0; .items { display: none; } &-subtitle { - text-transform: uppercase; position: relative; + text-transform: uppercase; z-index: 1; .lib-icon-font( - @_icon-font-content: @icon-down, - @_icon-font-size: 13px, - @_icon-font-position: before, - @_icon-font-display: block + @_icon-font-content: @icon-down, + @_icon-font-size: 13px, + @_icon-font-position: before, + @_icon-font-display: block ); &:before { position: absolute; @@ -291,17 +279,17 @@ } &:after { + .lib-css(color, @text__color__muted); content:' (' attr(data-count) ')'; font-size:.9em; - .lib-css(color, @text__color__muted); } } &.active { padding-bottom: 30px; .block-subtitle { .lib-icon-font-symbol( - @_icon-font-content: @icon-up, - @_icon-font-position: before + @_icon-font-content: @icon-up, + @_icon-font-position: before ); } .items { @@ -315,6 +303,31 @@ display: none; } } + .filter-no-options { + .filter-title { + &:before { + background: rgba(255,255,255,.5); + content: ''; + display: block; + height: 40px; + left: -15px; + margin-top: -60px; + position: relative; + width: 100px; + z-index: 99; + } + } + .filter-content { + margin-bottom: @indent__base; + } + } + .page-with-filter { + .columns { + .sidebar-main { + .lib-vendor-prefix-order(0); + } + } + } } .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__s) { @@ -336,11 +349,11 @@ } &.active &-options, &-options { + background: transparent; clear: both; - position: static; - overflow: initial; display: block; - background: transparent; + overflow: initial; + position: static; } &-subtitle { position: static; @@ -357,9 +370,9 @@ position: static; } &.page-with-filter .column.main { + padding-top: 45px; position: relative; z-index: 1; - padding-top: 45px; } .filter { &.block { @@ -373,8 +386,8 @@ } &-options { &-item { - display: inline-block; border: 0; + display: inline-block; margin-right: @indent__m; &.active { position: relative; @@ -384,14 +397,14 @@ } &:after, &:before { - content: ""; - display: block; .lib-arrow(up, 8px, @color-black); - position: absolute; - left: 50%; bottom: -1px; + content: ''; + display: block; + left: 50%; + margin-left: -@indent__base; + position: absolute; z-index: 3; - margin-left: -20px; } &:after { .lib-css(border-bottom-color, @color-white); @@ -401,7 +414,7 @@ } } &-title { - padding: 0 20px 0 0; + padding: 0 @indent__base 0 0; &:after { right: 2px; top: 3px; @@ -409,15 +422,16 @@ } } &-content { - position: absolute; - z-index: 2; + @_shadow: 0 3px 5px 0 rgba(50, 50, 50, .75); + .lib-css(background, @color-white); - width: 180px; - top: 100%; + .lib-css(box-shadow, @_shadow, 1); border: 1px solid @border-color__base; padding: @indent__xs 0; - @_shadow: 0 3px 5px 0 rgba(50, 50, 50, .75); - .lib-css(box-shadow, @_shadow, 1); + position: absolute; + top: 100%; + width: 180px; + z-index: 2; .item { padding: @indent__xs; margin:0; @@ -434,13 +448,13 @@ display: inline; line-height: 35px; &-subtitle { - display: inline; - padding: 0; .lib-css(color, @text__color__muted); + display: inline; font-size: @font-size__base; font-weight: normal; + padding: 0; &:after { - content: ":"; + content: ':'; } } .item, diff --git a/app/design/frontend/Magento/luma/Magento_Sales/web/css/source/_email.less b/app/design/frontend/Magento/luma/Magento_Sales/web/css/source/_email.less index 8d002c55b8ea073b6f4e377e28050bc2cb877b48..9fbeb9458d058cc24b1d29f3d4c0b0cda16bae39 100644 --- a/app/design/frontend/Magento/luma/Magento_Sales/web/css/source/_email.less +++ b/app/design/frontend/Magento/luma/Magento_Sales/web/css/source/_email.less @@ -100,7 +100,7 @@ // ---------------------------------------------- .shipment-track { - .table(@table__width, 0); + .lib-table(@table__width, 0); thead, tbody { @@ -127,7 +127,7 @@ // ---------------------------------------------- .email-items { - .table(@table__width, 0); + .lib-table(@table__width, 0); tfoot { > tr { > th, @@ -241,6 +241,6 @@ .email-non-inline() { .email-items { - .table-overflow(); + .lib-table-overflow(); } } diff --git a/dev/tests/api-functional/testsuite/Magento/Bundle/Api/OrderItemRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Bundle/Api/OrderItemRepositoryTest.php index 72005876cc595da0a6d1a2ae85a258464b07781f..5944edff812c676dcaba7654e4c76d695dc7d6a3 100644 --- a/dev/tests/api-functional/testsuite/Magento/Bundle/Api/OrderItemRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Bundle/Api/OrderItemRepositoryTest.php @@ -76,7 +76,7 @@ class OrderItemRepositoryTest extends WebapiAbstract ] ); - $requestData = ['criteria' => $searchCriteriaBuilder->create()->__toArray()]; + $requestData = ['searchCriteria' => $searchCriteriaBuilder->create()->__toArray()]; $serviceInfo = [ 'rest' => [ diff --git a/dev/tests/api-functional/testsuite/Magento/Bundle/Api/ProductOptionRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Bundle/Api/ProductOptionRepositoryTest.php index 8c486761f3906fd7a456e0b46c79337298ca5ea6..2554dacd770551b56fae549f9306d7bcaabd65cc 100644 --- a/dev/tests/api-functional/testsuite/Magento/Bundle/Api/ProductOptionRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Bundle/Api/ProductOptionRepositoryTest.php @@ -147,16 +147,6 @@ class ProductOptionRepositoryTest extends \Magento\TestFramework\TestCase\Webapi */ public function testUpdate() { - /** TODO: Remove after MAGETWO-40822 */ - $isPhpVersionSupported = version_compare( - '7.0.0', - preg_replace('#^([^~+-]+).*$#', '$1', PHP_VERSION), - '>' - ); - if (!$isPhpVersionSupported) { - $this->markTestSkipped('MAGETWO-40822'); - } - $productSku = 'bundle-product'; $request = [ 'title' => 'someTitle', diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/OrderItemRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/OrderItemRepositoryTest.php index db63fbb6084601820a27dc4cc770fa6826a28507..613be6d50073ef492226d584b747077c26af59c4 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/OrderItemRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/OrderItemRepositoryTest.php @@ -76,7 +76,7 @@ class OrderItemRepositoryTest extends WebapiAbstract ] ); - $requestData = ['criteria' => $searchCriteriaBuilder->create()->__toArray()]; + $requestData = ['searchCriteria' => $searchCriteriaBuilder->create()->__toArray()]; $serviceInfo = [ 'rest' => [ diff --git a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/OrderItemRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/OrderItemRepositoryTest.php index 25cb0e8652bf2996a9864e68bfcbeb5fb977fe63..318a225288827759eb65bb32793fac5bf0536144 100644 --- a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/OrderItemRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/OrderItemRepositoryTest.php @@ -76,7 +76,7 @@ class OrderItemRepositoryTest extends WebapiAbstract ] ); - $requestData = ['criteria' => $searchCriteriaBuilder->create()->__toArray()]; + $requestData = ['searchCriteria' => $searchCriteriaBuilder->create()->__toArray()]; $serviceInfo = [ 'rest' => [ diff --git a/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/OrderItemRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/OrderItemRepositoryTest.php index 41a5c6a506962a018eeb8421c6d8bc53f5ad7567..e3da911ba3a17affc4049868fd524d93672a1611 100644 --- a/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/OrderItemRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/OrderItemRepositoryTest.php @@ -76,7 +76,7 @@ class OrderItemRepositoryTest extends WebapiAbstract ] ); - $requestData = ['criteria' => $searchCriteriaBuilder->create()->__toArray()]; + $requestData = ['searchCriteria' => $searchCriteriaBuilder->create()->__toArray()]; $serviceInfo = [ 'rest' => [ diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoListTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoListTest.php index d3216b9cf41c17d454e7e46ed7d8be1051561586..892f4ca944a4673641d705bdea7d9acd5da12ead 100644 --- a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoListTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoListTest.php @@ -68,7 +68,7 @@ class CreditmemoListTest extends WebapiAbstract ); $searchData = $searchCriteriaBuilder->create()->__toArray(); - $requestData = ['criteria' => $searchData]; + $requestData = ['searchCriteria' => $searchData]; $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '?' . http_build_query($requestData), diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceListTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceListTest.php index b529af4d554d2a5be200e05d1f3c42abc1b3f7b7..6b8aa48df12f2337e603c79bda7200806a5c358b 100644 --- a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceListTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceListTest.php @@ -53,7 +53,7 @@ class InvoiceListTest extends WebapiAbstract ); $searchData = $searchCriteriaBuilder->create()->__toArray(); - $requestData = ['criteria' => $searchData]; + $requestData = ['searchCriteria' => $searchData]; $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '?' . http_build_query($requestData), diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderItemGetListTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderItemGetListTest.php index 1cd2b7a30656eea7334dbf9266281f9871bceeec..e91f747116db0ac2eea035af55096c8ba9517e20 100644 --- a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderItemGetListTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderItemGetListTest.php @@ -48,7 +48,7 @@ class OrderItemGetListTest extends WebapiAbstract ] ); - $requestData = ['criteria' => $searchCriteriaBuilder->create()->__toArray()]; + $requestData = ['searchCriteria' => $searchCriteriaBuilder->create()->__toArray()]; $serviceInfo = [ 'rest' => [ diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderListTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderListTest.php index 003ccfccf94e8e7fffef995a27e4fd36932378cf..a6598376efb31d1119eba37ce3dad2decbef64ca 100644 --- a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderListTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderListTest.php @@ -54,7 +54,7 @@ class OrderListTest extends WebapiAbstract ); $searchData = $searchCriteriaBuilder->create()->__toArray(); - $requestData = ['criteria' => $searchData]; + $requestData = ['searchCriteria' => $searchData]; $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '?' . http_build_query($requestData), diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentListTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentListTest.php index a06f22664920a35b9990442f7a6f2adb4c6c013f..678edb386c75315b9d4dfa4ad5f15334f358c305 100644 --- a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentListTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipmentListTest.php @@ -46,7 +46,7 @@ class ShipmentListTest extends WebapiAbstract $searchCriteriaBuilder->addFilters([$filterBuilder->setField('shipment_status')->setValue(1)->create()]); $searchData = $searchCriteriaBuilder->create()->__toArray(); - $requestData = ['criteria' => $searchData]; + $requestData = ['searchCriteria' => $searchData]; $serviceInfo = [ 'rest' => [ 'resourcePath' => self::RESOURCE_PATH . '?' . http_build_query($requestData), diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/TransactionTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/TransactionTest.php index 2081f0502ff731d331d178c4257496e8b062284b..b0fb27eb25441a9797ba5cf5f15ba5ba4037f1e4 100644 --- a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/TransactionTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/TransactionTest.php @@ -118,7 +118,7 @@ class TransactionTest extends WebapiAbstract $searchCriteriaBuilder->addFilters($filters); $searchData = $searchCriteriaBuilder->create()->__toArray(); - $requestData = ['criteria' => $searchData]; + $requestData = ['searchCriteria' => $searchData]; $serviceInfo = [ 'rest' => [ diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Cache.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Cache.php index be0e3f829e2eb6eb668972e7143aa8e4e4dc35cb..eac82f0b3dcd31f844bc7a3ebeac7b8da1d29526 100644 --- a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Cache.php +++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Cache.php @@ -68,7 +68,7 @@ class Cache extends Block */ public function isStorageCacheFlushed() { - return $this->getMessagesBlock()->getSuccessMessages() == $this->messagesText['cache_storage_flushed']; + return $this->getMessagesBlock()->getSuccessMessage() == $this->messagesText['cache_storage_flushed']; } /** @@ -78,7 +78,7 @@ class Cache extends Block */ public function isMagentoCacheFlushed() { - return $this->getMessagesBlock()->getSuccessMessages() == $this->messagesText['cache_magento_flushed']; + return $this->getMessagesBlock()->getSuccessMessage() == $this->messagesText['cache_magento_flushed']; } /** diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Messages.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Messages.php index 586f0d9205f9ea6643a7b1e1f6f385260b89064c..8cfce3edc4ca9ac1b4140074b7685cfe1423bf11 100644 --- a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Messages.php +++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Messages.php @@ -21,6 +21,13 @@ class Messages extends Block */ protected $successMessage = '[data-ui-id$=message-success]'; + /** + * Last success message selector. + * + * @var string + */ + protected $lastSuccessMessage = '[data-ui-id$=message-success]:last-child'; + /** * Message link. * @@ -62,7 +69,7 @@ class Messages extends Block /** * Get all success messages which are present on the page. * - * @return string|array + * @return array */ public function getSuccessMessages() { @@ -74,7 +81,19 @@ class Messages extends Block $messages[] = $element->getText(); } - return count($messages) > 1 ? $messages : $messages[0]; + return $messages; + } + + /** + * Get last success message which is present on the page. + * + * @return string + */ + public function getSuccessMessage() + { + $this->waitForElementVisible($this->successMessage); + + return $this->_rootElement->find($this->lastSuccessMessage)->getText(); } /** @@ -96,11 +115,11 @@ class Messages extends Block } /** - * Get all error messages which are present on the page. + * Get all error message which is present on the page. * * @return string */ - public function getErrorMessages() + public function getErrorMessage() { return $this->_rootElement ->find($this->errorMessage, Locator::SELECTOR_CSS) @@ -108,13 +127,13 @@ class Messages extends Block } /** - * Click on link in the messages which are present on the page. + * Click on link in the message which is present on the page. * * @param string $messageType * @param string $linkText * @return void */ - public function clickLinkInMessages($messageType, $linkText) + public function clickLinkInMessage($messageType, $linkText) { if ($this->isVisibleMessage($messageType)) { $this->_rootElement @@ -162,7 +181,7 @@ class Messages extends Block * * @return string */ - public function getNoticeMessages() + public function getNoticeMessage() { $this->waitForElementVisible($this->noticeMessage); return $this->_rootElement->find($this->noticeMessage)->getText(); @@ -173,7 +192,7 @@ class Messages extends Block * * @return string */ - public function getWarningMessages() + public function getWarningMessage() { $this->waitForElementVisible($this->warningMessage); return $this->_rootElement->find($this->warningMessage)->getText(); diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Widget/Grid.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Widget/Grid.php index 65017b9c85d99fec33b811997c6aec9d17848d67..5952f4690c1c996296a65ed64cf505c9b6fede95 100644 --- a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Widget/Grid.php +++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Widget/Grid.php @@ -189,7 +189,7 @@ abstract class Grid extends Block protected $rowPattern = '//tbody/tr[%s]'; /** - * Selector for confirm. + * Selector for confirm. * * @var string */ diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Constraint/AssertCacheIsRefreshableAndInvalidated.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Constraint/AssertCacheIsRefreshableAndInvalidated.php index 5492c69ef0b27568f4289cab588a9f8894a5d925..76ab1d8b104c74b5ceee50faf13970c143813cd8 100644 --- a/dev/tests/functional/tests/app/Magento/Backend/Test/Constraint/AssertCacheIsRefreshableAndInvalidated.php +++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Constraint/AssertCacheIsRefreshableAndInvalidated.php @@ -41,7 +41,7 @@ class AssertCacheIsRefreshableAndInvalidated extends AbstractConstraint \PHPUnit_Framework_Assert::assertEquals( sprintf(self::SUCCESS_MESSAGE, count($items)), - $adminCache->getMessagesBlock()->getSuccessMessages(), + $adminCache->getMessagesBlock()->getSuccessMessage(), 'Cache is Invalid and refreshable.' ); } diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Constraint/AssertCacheManagementAction.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Constraint/AssertCacheManagementAction.php index 5ca1e4e677bbf7f3fa1ecf19f25114a19e547a2e..1be33c03244280bc59ebd442bb3fbe501680dd64 100644 --- a/dev/tests/functional/tests/app/Magento/Backend/Test/Constraint/AssertCacheManagementAction.php +++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Constraint/AssertCacheManagementAction.php @@ -25,7 +25,7 @@ class AssertCacheManagementAction extends AbstractConstraint { \PHPUnit_Framework_Assert::assertEquals( $successMessage, - $adminCache->getMessagesBlock()->getSuccessMessages(), + $adminCache->getMessagesBlock()->getSuccessMessage(), 'Action is not successful.' ); } diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/CreateBundleProductEntityTest.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/CreateBundleProductEntityTest.xml index 1654b19df2435385286d09db719cb4314f15fdba..530018bf81c4741e9785564800a14f39a3397ac1 100644 --- a/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/CreateBundleProductEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/CreateBundleProductEntityTest.xml @@ -129,7 +129,6 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertProductVisibleInCategory" /> <constraint name="Magento\Bundle\Test\Constraint\AssertBundleProductPage" /> <constraint name="Magento\Catalog\Test\Constraint\AssertProductInStock" /> - <constraint name="Magento\Bundle\Test\Constraint\AssertGroupedPriceOnBundleProductPage" /> <constraint name="Magento\Bundle\Test\Constraint\AssertBundleItemsOnProductPage" /> <constraint name="Magento\Bundle\Test\Constraint\AssertBundlePriceView" /> <constraint name="Magento\Bundle\Test\Constraint\AssertBundlePriceType" /> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Edit/CategoryForm.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Edit/CategoryForm.php index 6af0253e217e3f51e47e9a5b4021869037bb00c2..df04b06cb442cce34c174d067fe40ff104591984 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Edit/CategoryForm.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Edit/CategoryForm.php @@ -31,7 +31,7 @@ class CategoryForm extends FormTabs protected $dropdownBlock = '.dropdown'; /** - * Selector for confirm. + * Selector for confirm. * * @var string */ @@ -51,9 +51,9 @@ class CategoryForm extends FormTabs $store = $fixture->getStoreId(); $storeSwitcherBlock = $this->browser->find($this->storeSwitcherBlock); $storeSwitcherBlock->find($this->dropdownBlock, Locator::SELECTOR_CSS, 'liselectstore')->setValue($store); - $element = $this->browser->find($this->confirmModal); + $modalElement = $this->browser->find($this->confirmModal); /** @var \Magento\Ui\Test\Block\Adminhtml\Modal $modal */ - $modal = $this->blockFactory->create('Magento\Ui\Test\Block\Adminhtml\Modal', ['element' => $element]); + $modal = $this->blockFactory->create('Magento\Ui\Test\Block\Adminhtml\Modal', ['element' => $modalElement]); $modal->acceptAlert(); } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/CustomAttribute.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/CustomAttribute.php index 4dfc6d203b3f945c520bc8fadfff384600d1b20d..7d85ae5b237c01549832c92c601f4ad0a5f2a5f0 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/CustomAttribute.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/CustomAttribute.php @@ -19,7 +19,7 @@ class CustomAttribute extends SimpleElement * * @var string */ - protected $inputSelector = '.control [data-ui-id][name]'; + protected $inputSelector = '.control [name]:not([type="hidden"]), table'; /** * Attribute class to element type reference. @@ -45,7 +45,9 @@ class CustomAttribute extends SimpleElement $this->eventManager->dispatchEvent(['set_value'], [__METHOD__, $this->getAbsoluteSelector()]); $element = $this->getElementByClass($this->getElementClass()); $value = is_array($data) ? $data['value'] : $data; - $this->find($this->inputSelector, Locator::SELECTOR_CSS, $element)->setValue($value); + if ($value !== null) { + $this->find($this->inputSelector, Locator::SELECTOR_CSS, $element)->setValue($value); + } } /** diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/Set/GridPageActions.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/Set/GridPageActions.php index 49d3f926aa63111003e8a56440c30a1fd95160ed..9373e1ab10ffaf958e27b18f4719141979f63498 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/Set/GridPageActions.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/Set/GridPageActions.php @@ -10,7 +10,7 @@ use Magento\Backend\Test\Block\GridPageActions as AbstractGridPageActions; /** * Class GridPageActions - * Grid page actions block on Product Templates page + * Grid page actions block on Attribute Sets page */ class GridPageActions extends AbstractGridPageActions { diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/ProductTab.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/ProductTab.php index c7c48a1847c784ab2dc885b98fe3c3640c73549d..4754efe1f1bfcfe93081670cae1605a1a669a28b 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/ProductTab.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/ProductTab.php @@ -9,7 +9,6 @@ namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit; use Magento\Mtf\Client\Locator; use Magento\Backend\Test\Block\Widget\Tab; use Magento\Catalog\Test\Block\Adminhtml\Product\Attribute\Edit; -use Magento\Catalog\Test\Fixture\CatalogProductAttribute; /** * General class for tabs on product FormTabs with "Add attribute" button. diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/ProductDetails/AttributeSet.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/ProductDetails/AttributeSet.php index 93e96cf4e28ebcd26cd1029086c5abf846a8fa71..2ecde06b84bc3773ac4572c095c5ef74fe8914e0 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/ProductDetails/AttributeSet.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/ProductDetails/AttributeSet.php @@ -7,6 +7,7 @@ namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\ProductDetails; use Magento\Mtf\Client\Element\SuggestElement; +use Magento\Mtf\Client\Locator; /** * Class AttributeSet @@ -35,6 +36,13 @@ class AttributeSet extends SuggestElement */ protected $loader = '[data-role="loader"]'; + /** + * Page header selector. + * + * @var string + */ + protected $header = 'header'; + /** * Set value * @@ -44,8 +52,27 @@ class AttributeSet extends SuggestElement public function setValue($value) { if ($value !== $this->find($this->actionToggle)->getText()) { + $this->eventManager->dispatchEvent(['set_value'], [__METHOD__, $this->getAbsoluteSelector()]); $this->find($this->actionToggle)->click(); - parent::setValue($value); + $this->clear(); + if ($value == '') { + return; + } + foreach (str_split($value) as $symbol) { + $this->keys([$symbol]); + $searchedItem = $this->find(sprintf($this->resultItem, $value), Locator::SELECTOR_XPATH); + if ($searchedItem->isVisible()) { + try { + $searchedItem->hover(); + $this->driver->find($this->header)->hover(); + $searchedItem->click(); + break; + } catch (\Exception $e) { + // In parallel run on windows change the focus is lost on element + // that causes disappearing of category suggest list. + } + } + } } // Wait loader $element = $this->driver; diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View/CustomOptions.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View/CustomOptions.php index 7e4608bc008a1acf44807ac3937d283844f24fcc..9fcea9e345614a72f5489684d31a02ec5acd83ad 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View/CustomOptions.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/View/CustomOptions.php @@ -30,14 +30,14 @@ class CustomOptions extends Form * * @var string */ - protected $optionElement = '#product-options-wrapper .field'; + protected $optionElement = '#product-options-wrapper > * > .field'; /** * Selector for title of option * * @var string */ - protected $title = 'label'; + protected $title = 'label > span:nth-child(1), legend > span:nth-child(1)'; /** * Selector for required option @@ -381,7 +381,7 @@ class CustomOptions extends Form */ protected function parseOptionText($optionText) { - preg_match('`^(.*?)\+\$(\d.*?)$`', $optionText, $match); + preg_match('`^(.*?) \+ ?\$([\d\.,]*?)$`', $optionText, $match); $optionPrice = isset($match[2]) ? str_replace(',', '', $match[2]) : 0; $optionTitle = isset($match[1]) ? trim($match[1]) : $optionText; diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAddedProductAttributeOnProductForm.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAddedProductAttributeOnProductForm.php index 22cc3977640cb5e7fcf1ee60e7619bd5dcbaf38b..eeb6257ee1f1873813e89421e9fa2a3f0e42c52c 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAddedProductAttributeOnProductForm.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAddedProductAttributeOnProductForm.php @@ -28,7 +28,7 @@ class AssertAddedProductAttributeOnProductForm extends AbstractConstraint * @param CatalogProductIndex $productGrid * @param CatalogProductEdit $productEdit * @param CatalogProductAttribute $attribute - * @param CatalogAttributeSet $productTemplate + * @param CatalogAttributeSet $attributeSet * @param CatalogProductAttribute $productAttributeOriginal * @throws \Exception * @return void @@ -38,11 +38,11 @@ class AssertAddedProductAttributeOnProductForm extends AbstractConstraint CatalogProductIndex $productGrid, CatalogProductEdit $productEdit, CatalogProductAttribute $attribute, - CatalogAttributeSet $productTemplate, + CatalogAttributeSet $attributeSet, CatalogProductAttribute $productAttributeOriginal = null ) { if (!$product->hasData('sku')) { - $product = $this->createProductWithAttributeSet($productAttributeOriginal, $productTemplate); + $product = $this->createProductWithAttributeSet($productAttributeOriginal, $attributeSet); } $filterProduct = ['sku' => $product->getSku()]; $productGrid->open(); @@ -62,16 +62,16 @@ class AssertAddedProductAttributeOnProductForm extends AbstractConstraint * Create Product With AttributeSet. * * @param CatalogProductAttribute $attribute - * @param CatalogAttributeSet $productTemplate + * @param CatalogAttributeSet $attributeSet * @return CatalogProductSimple */ protected function createProductWithAttributeSet( CatalogProductAttribute $attribute, - CatalogAttributeSet $productTemplate + CatalogAttributeSet $attributeSet ) { $product = ObjectManager::getInstance()->create( - 'Magento\Catalog\Test\TestStep\AddAttributeToProductTemplateStep', - ['attribute' => $attribute, 'productTemplate' => $productTemplate] + 'Magento\Catalog\Test\TestStep\AddAttributeToAttributeSetStep', + ['attribute' => $attribute, 'attributeSet' => $attributeSet] )->run(); return $product['product']; } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateForm.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetForm.php similarity index 79% rename from dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateForm.php rename to dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetForm.php index 4a634c7d23dec5d00566c6e59a9254800b0a1eb2..527f609aa60bb8483ad07967fcf2ebecc105eb33 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateForm.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetForm.php @@ -13,14 +13,14 @@ use Magento\Catalog\Test\Page\Adminhtml\CatalogProductSetIndex; use Magento\Mtf\Constraint\AbstractConstraint; /** - * Class AssertProductTemplateForm - * Checking data from Product Template form with data fixture + * Class AssertAttributeSetForm + * Checking data from Attribute Set form with data fixture */ -class AssertProductTemplateForm extends AbstractConstraint +class AssertAttributeSetForm extends AbstractConstraint { /** - * Assert that after save a product template on edit product set page displays: - * 1. Correct product template name in Attribute set name field passed from fixture + * Assert that after save a attribute set on edit product set page displays: + * 1. Correct attribute set name in Attribute set name field passed from fixture * 2. Created Product Attribute (if was added) * * @param CatalogProductSetIndex $productSet @@ -43,7 +43,7 @@ class AssertProductTemplateForm extends AbstractConstraint \PHPUnit_Framework_Assert::assertEquals( $filterAttribute['set_name'], $productSetEdit->getAttributeSetEditBlock()->getAttributeSetName(), - 'Product Template not found' + 'Attribute Set not found' . "\nExpected: " . $filterAttribute['set_name'] . "\nActual: " . $productSetEdit->getAttributeSetEditBlock()->getAttributeSetName() ); @@ -51,7 +51,7 @@ class AssertProductTemplateForm extends AbstractConstraint $attributeLabel = $productAttribute->getFrontendLabel(); \PHPUnit_Framework_Assert::assertTrue( $productSetEdit->getAttributeSetEditBlock()->checkProductAttribute($attributeLabel), - "Product Attribute is absent on Product Template Groups" + "Product Attribute is absent on Attribute Set Groups" ); } } @@ -63,6 +63,6 @@ class AssertProductTemplateForm extends AbstractConstraint */ public function toString() { - return 'Data from the Product Template form matched with fixture'; + return 'Data from the Attribute Set form matched with fixture'; } } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateGroupOnProductForm.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetGroupOnProductForm.php similarity index 88% rename from dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateGroupOnProductForm.php rename to dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetGroupOnProductForm.php index 2baac340525f3c1506afbb7cde40e0325dffe918..3aa7d3e9361e30fae3c614b95549d2b697c752ea 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateGroupOnProductForm.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetGroupOnProductForm.php @@ -17,15 +17,15 @@ use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex; use Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit; /** - * Class AssertProductTemplateGroupOnProductForm - * Check that created product template displays in product template suggest container dropdown and + * Class AssertAttributeSetGroupOnProductForm + * Check that created attribute set displays in attribute set suggest container dropdown and * can be used for new created product */ -class AssertProductTemplateGroupOnProductForm extends AbstractConstraint +class AssertAttributeSetGroupOnProductForm extends AbstractConstraint { /** - * Assert that created product template: - * 1. Displays in product template suggest container dropdown + * Assert that created attribute set: + * 1. Displays in attribute set suggest container dropdown * 2. Can be used for new created product. * * @param FixtureFactory $fixtureFactory diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateInGrid.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetInGrid.php similarity index 67% rename from dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateInGrid.php rename to dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetInGrid.php index 281327b9f8c921784306d09d87b935261a42b5d5..6e6d02c324171284022529d2931f145f4dbacec1 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateInGrid.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetInGrid.php @@ -11,13 +11,13 @@ use Magento\Catalog\Test\Page\Adminhtml\CatalogProductSetIndex; use Magento\Mtf\Constraint\AbstractConstraint; /** - * Class AssertProductTemplateInGrid - * Checks present product template in Product Templates grid + * Class AssertAttributeSetInGrid + * Checks present attribute set in Attribute Sets grid */ -class AssertProductTemplateInGrid extends AbstractConstraint +class AssertAttributeSetInGrid extends AbstractConstraint { /** - * Assert that new product template displays in Product Templates grid + * Assert that new attribute set displays in Attribute Sets grid * * @param CatalogProductSetIndex $productSetPage * @param CatalogAttributeSet $attributeSet @@ -32,17 +32,17 @@ class AssertProductTemplateInGrid extends AbstractConstraint $productSetPage->open(); \PHPUnit_Framework_Assert::assertTrue( $productSetPage->getGrid()->isRowVisible($filterAttributeSet), - 'Product Template \'' . $filterAttributeSet['set_name'] . '\' is absent in Product Template grid.' + 'Attribute Set \'' . $filterAttributeSet['set_name'] . '\' is absent in Attribute Set grid.' ); } /** - * Text present new product template in grid + * Text present new attribute set in grid * * @return string */ public function toString() { - return 'Product template is present in Product Templates grid'; + return 'Attribute set is present in Attribute Sets grid'; } } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateNotInGrid.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetNotInGrid.php similarity index 62% rename from dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateNotInGrid.php rename to dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetNotInGrid.php index 02d8435fb2585e5c0372f07c1b52f20a5ce8b8ed..7d5ed1707c64dfcc2053f0b2326db0bc1a9e72e7 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateNotInGrid.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetNotInGrid.php @@ -11,42 +11,42 @@ use Magento\Catalog\Test\Page\Adminhtml\CatalogProductSetIndex; use Magento\Mtf\Constraint\AbstractConstraint; /** - * Class AssertProductTemplateNotInGrid - * Assert that Product Template absence on grid + * Class AssertAttributeSetNotInGrid + * Assert that Attribute Set absence on grid */ -class AssertProductTemplateNotInGrid extends AbstractConstraint +class AssertAttributeSetNotInGrid extends AbstractConstraint { /* tags */ const SEVERITY = 'low'; /* end tags */ /** - * Assert that product template is not displayed in Product Templates grid + * Assert that attribute set is not displayed in Attribute Sets grid * * @param CatalogProductSetIndex $productSetPage - * @param CatalogAttributeSet $productTemplate + * @param CatalogAttributeSet $attributeSet * @return void */ - public function processAssert(CatalogProductSetIndex $productSetPage, CatalogAttributeSet $productTemplate) + public function processAssert(CatalogProductSetIndex $productSetPage, CatalogAttributeSet $attributeSet) { $filterAttributeSet = [ - 'set_name' => $productTemplate->getAttributeSetName(), + 'set_name' => $attributeSet->getAttributeSetName(), ]; $productSetPage->open(); \PHPUnit_Framework_Assert::assertFalse( $productSetPage->getGrid()->isRowVisible($filterAttributeSet), - 'An attribute set named "' . $filterAttributeSet['set_name'] . '" is present in Product Template grid.' + 'An attribute set named "' . $filterAttributeSet['set_name'] . '" is present in Attribute Set grid.' ); } /** - * Text absent new product template in grid + * Text absent new attribute set in grid * * @return string */ public function toString() { - return 'Product template is absent in Product Templates grid'; + return 'Attribute set is absent in Attribute Sets grid'; } } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateOnProductForm.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetOnProductForm.php similarity index 88% rename from dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateOnProductForm.php rename to dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetOnProductForm.php index cf3e50c9f09009b498b96ad8bb74853d520f50ea..0f66f26036df9073cb1887d86255bc38f48dfc3e 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateOnProductForm.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetOnProductForm.php @@ -16,14 +16,14 @@ use Magento\Mtf\Constraint\AbstractConstraint; use Magento\Mtf\Fixture\FixtureFactory; /** - * Class AssertProductTemplateOnProductForm + * Class AssertAttributeSetOnProductForm * Check Attribute Set and Product Attribute on Product form */ -class AssertProductTemplateOnProductForm extends AbstractConstraint +class AssertAttributeSetOnProductForm extends AbstractConstraint { /** - * Assert that created product template: - * 1. Displays in product template suggest container dropdown + * Assert that created attribute set: + * 1. Displays in attribute set suggest container dropdown * 2. Can be used for new created product. * * @param FixtureFactory $fixtureFactory @@ -66,7 +66,7 @@ class AssertProductTemplateOnProductForm extends AbstractConstraint \PHPUnit_Framework_Assert::assertEquals( $attributeSet->getAttributeSetName(), $formAttributeSet, - 'Product Template not found on Product form.' + 'Attribute Set not found on Product form.' . "\nExpected: " . $attributeSet->getAttributeSetName() . "\nActual: " . $formAttributeSet ); @@ -88,6 +88,6 @@ class AssertProductTemplateOnProductForm extends AbstractConstraint */ public function toString() { - return 'Product Attribute and Product Template are present on the Product form.'; + return 'Product Attribute and Attribute Set are present on the Product form.'; } } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateSuccessDeleteMessage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetSuccessDeleteMessage.php similarity index 70% rename from dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateSuccessDeleteMessage.php rename to dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetSuccessDeleteMessage.php index 43cff91896a5373c3641bb780978fddf1ff44407..8da7dc6bd271f975b3f50d249971b9d512ef420c 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateSuccessDeleteMessage.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetSuccessDeleteMessage.php @@ -10,25 +10,25 @@ use Magento\Catalog\Test\Page\Adminhtml\CatalogProductSetIndex; use Magento\Mtf\Constraint\AbstractConstraint; /** - * Class AssertProductTemplateSuccessDeleteMessage - * Check Product Templates success delete message + * Class AssertAttributeSetSuccessDeleteMessage + * Check Attribute Sets success delete message */ -class AssertProductTemplateSuccessDeleteMessage extends AbstractConstraint +class AssertAttributeSetSuccessDeleteMessage extends AbstractConstraint { /** * Text value to be checked */ - const SUCCESS_DELETE_MESSAGE = 'The product template has been removed.'; + const SUCCESS_DELETE_MESSAGE = 'The attribute set has been removed.'; /** - * Assert that after deleting product template success delete message appears + * Assert that after deleting attribute set success delete message appears * * @param CatalogProductSetIndex $productSetIndex * @return void */ public function processAssert(CatalogProductSetIndex $productSetIndex) { - $actualMessage = $productSetIndex->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $productSetIndex->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_DELETE_MESSAGE, $actualMessage, @@ -45,6 +45,6 @@ class AssertProductTemplateSuccessDeleteMessage extends AbstractConstraint */ public function toString() { - return 'Product Templates success delete message is present.'; + return 'Attribute Sets success delete message is present.'; } } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetSuccessSaveMessage.php similarity index 69% rename from dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateSuccessSaveMessage.php rename to dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetSuccessSaveMessage.php index 457cac5b7082e897686f71f98b0571d0c070962e..789c2806091c11ff7853baf990a51f60dd3768f4 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductTemplateSuccessSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSetSuccessSaveMessage.php @@ -10,25 +10,25 @@ use Magento\Catalog\Test\Page\Adminhtml\CatalogProductSetIndex; use Magento\Mtf\Constraint\AbstractConstraint; /** - * Class AssertProductTemplateSuccessSaveMessage - * Check Product Templates success save message + * Class AssertAttributeSetSuccessSaveMessage + * Check Attribute Sets success save message */ -class AssertProductTemplateSuccessSaveMessage extends AbstractConstraint +class AssertAttributeSetSuccessSaveMessage extends AbstractConstraint { /** * Text value to be checked */ - const SUCCESS_MESSAGE = 'You saved the product template.'; + const SUCCESS_MESSAGE = 'You saved the attribute set.'; /** - * Assert that after save a product template "You saved the attribute set." successful message appears + * Assert that after save a attribute set "You saved the attribute set." successful message appears * * @param CatalogProductSetIndex $productSetIndex * @return void */ public function processAssert(CatalogProductSetIndex $productSetIndex) { - $actualMessage = $productSetIndex->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $productSetIndex->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, $actualMessage, @@ -45,6 +45,6 @@ class AssertProductTemplateSuccessSaveMessage extends AbstractConstraint */ public function toString() { - return 'Product Templates success save message is present.'; + return 'Attribute Sets success save message is present.'; } } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCategorySaveMessage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCategorySaveMessage.php index 454379830cd060168582a3f7067beb2fb5f22137..c983a5afc6e5b3fe9adff454cfacb4e7e4f97d3a 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCategorySaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCategorySaveMessage.php @@ -28,7 +28,7 @@ class AssertCategorySaveMessage extends AbstractConstraint */ public function processAssert(CatalogCategoryEdit $catalogCategoryEdit) { - $actualMessage = $catalogCategoryEdit->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $catalogCategoryEdit->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCategorySuccessDeleteMessage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCategorySuccessDeleteMessage.php index bb77a39089fe91bc5cb9394eed042d5017c83e8a..dbc9db525560f2fd294ecd5d81ed39118552770d 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCategorySuccessDeleteMessage.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCategorySuccessDeleteMessage.php @@ -28,7 +28,7 @@ class AssertCategorySuccessDeleteMessage extends AbstractConstraint */ public function processAssert(CatalogCategoryEdit $categoryEdit) { - $actualMessage = $categoryEdit->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $categoryEdit->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_DELETE_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertMassProductUpdateSuccessMessage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertMassProductUpdateSuccessMessage.php index 4aa368dcf71a14752ded095cc80e64ecd5d2b200..04639082d289d1466ebf5196cc699c6b31c76f18 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertMassProductUpdateSuccessMessage.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertMassProductUpdateSuccessMessage.php @@ -30,7 +30,7 @@ class AssertMassProductUpdateSuccessMessage extends AbstractConstraint { $countProducts = count($products) ? count($products) : 1; $expectedMessage = sprintf(self::SUCCESS_MESSAGE, $countProducts); - $actualMessage = $productGrid->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $productGrid->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( $expectedMessage, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInSearchOnProductForm.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInSearchOnProductForm.php index 4052a470a60642250dcefe83cae20bef9696df43..6ba9ad8b07825a832c853ceecc8d829d81a6b0c2 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInSearchOnProductForm.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInSearchOnProductForm.php @@ -12,12 +12,12 @@ use Magento\Catalog\Test\Page\Adminhtml\CatalogProductNew; use Magento\Mtf\Constraint\AbstractConstraint; /** - * Checks that product attribute cannot be added to product template on Product Page via Add Attribute control. + * Checks that product attribute cannot be added to attribute set on Product Page via Add Attribute control. */ class AssertProductAttributeAbsenceInSearchOnProductForm extends AbstractConstraint { /** - * Assert that deleted attribute can't be added to product template on Product Page via Add Attribute control. + * Assert that deleted attribute can't be added to attribute set on Product Page via Add Attribute control. * * @param CatalogProductAttribute $productAttribute * @param CatalogProductIndex $productGrid diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInTemplateGroups.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInTemplateGroups.php index 821d96b2db2215c60fc3fc4cfa155f552806815a..3d865b5ccddd79ca047adc636ab1e8302842aaeb 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInTemplateGroups.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInTemplateGroups.php @@ -13,45 +13,45 @@ use Magento\Mtf\Constraint\AbstractConstraint; /** * Class AssertProductAttributeAbsenceInTemplateGroups - * Checks that product attribute isn't displayed in Product template's Groups section + * Checks that product attribute isn't displayed in Attribute set's Groups section */ class AssertProductAttributeAbsenceInTemplateGroups extends AbstractConstraint { /** - * Assert that deleted attribute isn't displayed in Product template's Groups section + * Assert that deleted attribute isn't displayed in Attribute set's Groups section * - * @param CatalogAttributeSet $productTemplate + * @param CatalogAttributeSet $attributeSet * @param CatalogProductSetIndex $productSetIndex * @param CatalogProductSetEdit $productSetEdit * @return void */ public function processAssert( - CatalogAttributeSet $productTemplate, + CatalogAttributeSet $attributeSet, CatalogProductSetIndex $productSetIndex, CatalogProductSetEdit $productSetEdit ) { - $filter = ['set_name' => $productTemplate->getAttributeSetName()]; + $filter = ['set_name' => $attributeSet->getAttributeSetName()]; $productSetIndex->open(); $productSetIndex->getGrid()->searchAndOpen($filter); - $attributeCode = $productTemplate + $attributeCode = $attributeSet ->getDataFieldConfig('assigned_attributes')['source'] ->getAttributes()[0] ->getAttributeCode(); \PHPUnit_Framework_Assert::assertFalse( $productSetEdit->getAttributeSetEditBlock()->checkProductAttribute($attributeCode), - "Attribute " . $attributeCode . " is present in Product template's Groups section." + "Attribute " . $attributeCode . " is present in Attribute set's Groups section." ); } /** - * Text absent Product Attribute in Product template's Groups section + * Text absent Product Attribute in Attribute set's Groups section * * @return string */ public function toString() { - return "Product Attribute is absent in Product template's Groups section."; + return "Product Attribute is absent in Attribute set's Groups section."; } } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInUnassignedAttributes.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInUnassignedAttributes.php index d1f2f5e1eff19ed4e746ab1e8a2559be47318fc3..460d46cf55d1fca61d01ceeeacfc7e8dea29ade7 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInUnassignedAttributes.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInUnassignedAttributes.php @@ -13,45 +13,45 @@ use Magento\Mtf\Constraint\AbstractConstraint; /** * Class AssertProductAttributeAbsenceInUnassignedAttributes - * Checks that product attribute isn't displayed in Product template's Unassigned Attributes section + * Checks that product attribute isn't displayed in Attribute set's Unassigned Attributes section */ class AssertProductAttributeAbsenceInUnassignedAttributes extends AbstractConstraint { /** - * Assert that deleted attribute isn't displayed in Product template's Unassigned Attributes section + * Assert that deleted attribute isn't displayed in Attribute set's Unassigned Attributes section * - * @param CatalogAttributeSet $productTemplate + * @param CatalogAttributeSet $attributeSet * @param CatalogProductSetIndex $productSetIndex * @param CatalogProductSetEdit $productSetEdit * @return void */ public function processAssert( - CatalogAttributeSet $productTemplate, + CatalogAttributeSet $attributeSet, CatalogProductSetIndex $productSetIndex, CatalogProductSetEdit $productSetEdit ) { - $filter = ['set_name' => $productTemplate->getAttributeSetName()]; + $filter = ['set_name' => $attributeSet->getAttributeSetName()]; $productSetIndex->open(); $productSetIndex->getGrid()->searchAndOpen($filter); - $attributeCode = $productTemplate + $attributeCode = $attributeSet ->getDataFieldConfig('assigned_attributes')['source'] ->getAttributes()[0] ->getAttributeCode(); \PHPUnit_Framework_Assert::assertFalse( $productSetEdit->getAttributeSetEditBlock()->checkUnassignedProductAttribute($attributeCode), - "Attribute " . $attributeCode . " is present in Unassigned Product template's section." + "Attribute " . $attributeCode . " is present in Unassigned Attribute set's section." ); } /** - * Text absent Product Attribute Unassigned Product template's section + * Text absent Product Attribute Unassigned Attribute set's section * * @return string */ public function toString() { - return "Product Attribute is absent in Unassigned Product template's section."; + return "Product Attribute is absent in Unassigned Attribute set's section."; } } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeSaveMessage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeSaveMessage.php index 96b39d0d964311cb38903bf3a3a9b52ce33cb5c4..97dab27640a02bffaa38f20ed772f2ba5f582cea 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeSaveMessage.php @@ -14,6 +14,9 @@ use Magento\Mtf\Constraint\AbstractConstraint; */ class AssertProductAttributeSaveMessage extends AbstractConstraint { + /** + * Product attribute success save message. + */ const SUCCESS_MESSAGE = 'You saved the product attribute.'; /** @@ -24,12 +27,13 @@ class AssertProductAttributeSaveMessage extends AbstractConstraint */ public function processAssert(CatalogProductAttributeIndex $attributeIndex) { + $actualMessage = $attributeIndex->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, - $attributeIndex->getMessagesBlock()->getSuccessMessages(), + $actualMessage, 'Wrong success message is displayed.' . "\nExpected: " . self::SUCCESS_MESSAGE - . "\nActual: " . $attributeIndex->getMessagesBlock()->getSuccessMessages() + . "\nActual: " . $actualMessage ); } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeSuccessDeleteMessage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeSuccessDeleteMessage.php index e41e1b4ab6dd1a5990d28626bb999524a6c87fdc..c911e7f7b574c8b402728a16713114f5a297fe97 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeSuccessDeleteMessage.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeSuccessDeleteMessage.php @@ -25,12 +25,13 @@ class AssertProductAttributeSuccessDeleteMessage extends AbstractConstraint */ public function processAssert(CatalogProductAttributeIndex $attributeIndex) { + $actualMessage = $attributeIndex->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, - $attributeIndex->getMessagesBlock()->getSuccessMessages(), + $actualMessage, 'Wrong success message is displayed.' . "\nExpected: " . self::SUCCESS_MESSAGE - . "\nActual: " . $attributeIndex->getMessagesBlock()->getSuccessMessages() + . "\nActual: " . $actualMessage ); } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareSuccessAddMessage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareSuccessAddMessage.php index 733c8b726597606c1a79be502085fb1eebafe0d7..20f0ee59b380c2afd6935cb68fcdfc2250bd0ff0 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareSuccessAddMessage.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareSuccessAddMessage.php @@ -31,7 +31,7 @@ class AssertProductCompareSuccessAddMessage extends AbstractConstraint public function processAssert(CatalogProductView $catalogProductView, FixtureInterface $product) { $successMessage = sprintf(self::SUCCESS_MESSAGE, $product->getName()); - $actualMessage = $catalogProductView->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $catalogProductView->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( $successMessage, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareSuccessRemoveAllProductsMessage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareSuccessRemoveAllProductsMessage.php index 9fe455b2f260a7bbf2ec0239f3c92a73b683a51b..bd63bb17bb8c86be4eb840534ca4ac81af59af72 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareSuccessRemoveAllProductsMessage.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareSuccessRemoveAllProductsMessage.php @@ -24,7 +24,7 @@ class AssertProductCompareSuccessRemoveAllProductsMessage extends AbstractConstr */ public function processAssert(CatalogProductView $catalogProductView) { - $actualMessage = $catalogProductView->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $catalogProductView->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareSuccessRemoveMessage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareSuccessRemoveMessage.php index dfe1e7530b8682a84f6eb3d14a9d317300c52379..64fa8a851e7b869e053e1b580c798d5f19a3526f 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareSuccessRemoveMessage.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductCompareSuccessRemoveMessage.php @@ -28,7 +28,7 @@ class AssertProductCompareSuccessRemoveMessage extends AbstractConstraint public function processAssert(CatalogProductCompare $catalogProductCompare, FixtureInterface $product) { $successMessage = sprintf(self::SUCCESS_MESSAGE, $product->getName()); - $actualMessage = $catalogProductCompare->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $catalogProductCompare->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals($successMessage, $actualMessage, 'Wrong success message is displayed.'); } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductDuplicateMessage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductDuplicateMessage.php index 4c79e9f1a32629527c440a534c96722e6158acd0..1e034ca00527084dffb2572949f54f51018a5daa 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductDuplicateMessage.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductDuplicateMessage.php @@ -28,7 +28,6 @@ class AssertProductDuplicateMessage extends AbstractConstraint public function processAssert(CatalogProductEdit $productPage) { $actualMessages = $productPage->getMessagesBlock()->getSuccessMessages(); - $actualMessages = is_array($actualMessages) ? $actualMessages : [$actualMessages]; \PHPUnit_Framework_Assert::assertContains( self::DUPLICATE_MESSAGE, $actualMessages, diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductDuplicatedInGrid.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductDuplicatedInGrid.php index 64fcf763899dc95f7d178fdc4261b07285f67b0f..59462fc83da81a765185c39886437f18f8b2a23c 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductDuplicatedInGrid.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductDuplicatedInGrid.php @@ -16,7 +16,7 @@ use Magento\Mtf\Fixture\FixtureInterface; class AssertProductDuplicatedInGrid extends AbstractConstraint { /** - * Assert that duplicated product is found by sku and has correct product type, product template, + * Assert that duplicated product is found by sku and has correct product type, attribute set, * product status disabled and out of stock * * @param FixtureInterface $product diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductSaveMessage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductSaveMessage.php index 21c5c2353c69563ccb7c4c1613295b0a127a6a20..fa73d7abeba62e53f623df53d784f81ebed65169 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductSaveMessage.php @@ -28,7 +28,6 @@ class AssertProductSaveMessage extends AbstractConstraint public function processAssert(CatalogProductEdit $productPage) { $actualMessages = $productPage->getMessagesBlock()->getSuccessMessages(); - $actualMessages = is_array($actualMessages) ? $actualMessages : [$actualMessages]; \PHPUnit_Framework_Assert::assertContains( self::SUCCESS_MESSAGE, $actualMessages, diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductSuccessDeleteMessage.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductSuccessDeleteMessage.php index eb40dd8d4450c5281f01127f7f943f9b0c5263c5..17927acc9be86e4bf439a3fa25abfe4efee594b0 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductSuccessDeleteMessage.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductSuccessDeleteMessage.php @@ -31,7 +31,7 @@ class AssertProductSuccessDeleteMessage extends AbstractConstraint { $products = is_array($product) ? $product : [$product]; $deleteMessage = sprintf(self::SUCCESS_DELETE_MESSAGE, count($products)); - $actualMessage = $productPage->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $productPage->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( $deleteMessage, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertUsedSuperAttributeImpossibleDeleteMessages.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertUsedSuperAttributeImpossibleDeleteMessages.php index bfd1c1bd9194ef96a2390bcd258b81a8143a0f1b..ce954986fa22ebc71b36afdcd6cf040e6adaf04e 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertUsedSuperAttributeImpossibleDeleteMessages.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertUsedSuperAttributeImpossibleDeleteMessages.php @@ -30,7 +30,7 @@ class AssertUsedSuperAttributeImpossibleDeleteMessages extends AbstractConstrain { \PHPUnit_Framework_Assert::assertEquals( self::ERROR_DELETE_MESSAGE, - $newPage->getMessagesBlock()->getErrorMessages(), + $newPage->getMessagesBlock()->getErrorMessage(), 'Wrong impossible to delete message is not displayed.' ); } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/CustomAttribute.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/CustomAttribute.php index 1e9a5690533baef1822206cfdfa4f2d57ce134a5..d41542b0e75ac6b078ffba321f888b3c7865e6b0 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/CustomAttribute.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/CustomAttribute.php @@ -35,7 +35,12 @@ class CustomAttribute extends DataSource /** @var CatalogProductAttribute $data */ $data = $fixtureFactory->createByCode('catalogProductAttribute', ['dataset' => $data['dataset']]); } - $this->data['value'] = $this->getDefaultAttributeValue($data); + if (is_array($data) && isset($data['value'])) { + $this->data['value'] = $data['value']; + $data = $data['attribute']; + } else { + $this->data['value'] = $this->getDefaultAttributeValue($data); + } $this->data['code'] = $data->hasData('attribute_code') == false ? $this->createAttributeCode($data) : $data->getAttributeCode(); diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Product/AttributeSetId.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Product/AttributeSetId.php index 9a314c06e7d285c25dad13cf614d6317987a1d60..4865ef44562457ea5c3ef364fa1386a9b6919bac 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Product/AttributeSetId.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Product/AttributeSetId.php @@ -11,7 +11,7 @@ use Magento\Mtf\Fixture\FixtureFactory; use Magento\Catalog\Test\Fixture\CatalogAttributeSet; /** - * Product template entity data source. + * Attribute set entity data source. * * Data keys: * - dataset diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/NavigateMenuTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/NavigateMenuTest.xml index f38ac7d9baf9c18ad79bdfb4944e4c5b358527c9..847a1f2c242e6cbc840de37609d98898dd308a48 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/NavigateMenuTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/NavigateMenuTest.xml @@ -23,8 +23,8 @@ <constraint name="Magento\Backend\Test\Constraint\AssertBackendPageIsAvailable"/> </variation> <variation name="NavigateMenuTest12"> - <data name="menuItem" xsi:type="string">Stores > Product Template</data> - <data name="pageTitle" xsi:type="string">Product Templates</data> + <data name="menuItem" xsi:type="string">Stores > Attribute Set</data> + <data name="pageTitle" xsi:type="string">Attribute Sets</data> <constraint name="Magento\Backend\Test\Constraint\AssertBackendPageIsAvailable"/> </variation> </testCase> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/AddCompareProductsTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/AddCompareProductsTest.xml index 7e106eb611f86ddb15c13da1611ed7bbbc64d3f0..2aa04810e18e1a326aeb75c87ff6995f70d97511 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/AddCompareProductsTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/AddCompareProductsTest.xml @@ -21,7 +21,7 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertProductComparePage" /> </variation> <variation name="AddCompareProductsTestVariation3"> - <data name="products" xsi:type="string">configurableProduct::default</data> + <data name="products" xsi:type="string">configurableProduct::configurable_with_qty_1</data> <data name="isCustomerLoggedIn" xsi:type="string">Yes</data> <constraint name="Magento\Catalog\Test\Constraint\AssertProductCompareItemsLink" /> <constraint name="Magento\Catalog\Test\Constraint\AssertProductComparePage" /> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateAttributeSetEntityTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateAttributeSetEntityTest.php index 7ddb966ed99a38aed91201c7cb802a182f26d2b3..835086f15fa8d575fbfa0483ed570ee28f16bce8 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateAttributeSetEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateAttributeSetEntityTest.php @@ -18,12 +18,12 @@ use Magento\Mtf\TestCase\Injectable; * * Test Flow: * 1. Log in to Backend. - * 2. Navigate to Stores > Attributes > Product Template. - * 3. Start to create new Product Template. + * 2. Navigate to Stores > Attributes > Attribute Set. + * 3. Start to create new Attribute Set. * 4. Fill out fields data according to data set. - * 5. Add created Product Attribute to Product Template. - * 6. Save new Product Template. - * 7. Verify created Product Template. + * 5. Add created Product Attribute to Attribute Set. + * 6. Save new Attribute Set. + * 7. Verify created Attribute Set. * * @group Product_Attributes_(MX) * @ZephyrId MAGETWO-25104 diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateAttributeSetEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateAttributeSetEntityTest.xml index 68b4d38d82e36065fd6c206f58d7966f45ce8661..2db56cfeb2012c7c1c8a26487403f349d8329274 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateAttributeSetEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateAttributeSetEntityTest.xml @@ -6,14 +6,14 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/variations.xsd"> - <testCase name="Magento\Catalog\Test\TestCase\ProductAttribute\CreateAttributeSetEntityTest" summary="Create Attribute Set (Product Template)" ticketId="MAGETWO-25104"> + <testCase name="Magento\Catalog\Test\TestCase\ProductAttribute\CreateAttributeSetEntityTest" summary="Create Attribute Set (Attribute Set)" ticketId="MAGETWO-25104"> <variation name="CreateAttributeSetEntityTestVariation1"> - <data name="attributeSet/data/attribute_set_name" xsi:type="string">ProductTemplate%isolation%</data> + <data name="attributeSet/data/attribute_set_name" xsi:type="string">AttributeSet%isolation%</data> <data name="attributeSet/data/skeleton_set/dataset" xsi:type="string">default</data> - <constraint name="Magento\Catalog\Test\Constraint\AssertProductTemplateSuccessSaveMessage" /> - <constraint name="Magento\Catalog\Test\Constraint\AssertProductTemplateForm" /> - <constraint name="Magento\Catalog\Test\Constraint\AssertProductTemplateInGrid" /> - <constraint name="Magento\Catalog\Test\Constraint\AssertProductTemplateOnProductForm" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertAttributeSetSuccessSaveMessage" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertAttributeSetForm" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertAttributeSetInGrid" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertAttributeSetOnProductForm" /> </variation> </testCase> </config> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityFromProductPageTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityFromProductPageTest.xml index 007e25239d731a8a14631bec029e21a85411bcb3..d58f5e1afefbbfde16f9e47a9f562dfe561ed152 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityFromProductPageTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityFromProductPageTest.xml @@ -41,6 +41,9 @@ <data name="attribute/data/is_global" xsi:type="string">Global</data> <data name="attribute/data/is_filterable" xsi:type="string">Filterable (with results)</data> <data name="attribute/data/is_filterable_in_search" xsi:type="string">Yes</data> + <data name="assertProduct/data/name" xsi:type="string">Product name</data> + <data name="assertProduct/data/sku" xsi:type="string">product-sku</data> + <data name="assertProduct/data/price" xsi:type="string">25</data> <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeIsFilterable" /> <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeIsFilterableInSearch" /> <constraint name="Magento\ConfigurableProduct\Test\Constraint\AssertProductAttributeIsConfigurable" /> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityTest.xml index b945d770fe82d5992ca0a769a3da02da2da2a10d..328d270d0c9f0fdb3dea6fad1dcad9e40044fe30 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityTest.xml @@ -8,7 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Catalog\Test\TestCase\ProductAttribute\CreateProductAttributeEntityTest" summary="Create Product Attribute" ticketId="MAGETWO-24767"> <variation name="CreateProductAttributeEntityTestVariation1"> - <data name="productTemplate/dataset" xsi:type="string">custom_attribute_set</data> + <data name="attributeSet/dataset" xsi:type="string">custom_attribute_set</data> <data name="productAttribute/data/frontend_label" xsi:type="string">Text_Field_Admin_%isolation%</data> <data name="productAttribute/data/frontend_input" xsi:type="string">Text Field</data> <data name="productAttribute/data/is_required" xsi:type="string">No</data> @@ -19,7 +19,7 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertAddedProductAttributeOnProductForm" /> </variation> <variation name="CreateProductAttributeEntityTestVariation2"> - <data name="productTemplate/dataset" xsi:type="string">custom_attribute_set</data> + <data name="attributeSet/dataset" xsi:type="string">custom_attribute_set</data> <data name="productAttribute/data/frontend_label" xsi:type="string">Text_Field_Admin_%isolation%</data> <data name="productAttribute/data/frontend_input" xsi:type="string">Text Area</data> <data name="productAttribute/data/is_required" xsi:type="string">Yes</data> @@ -41,7 +41,7 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeIsComparable" /> </variation> <variation name="CreateProductAttributeEntityTestVariation3"> - <data name="productTemplate/dataset" xsi:type="string">custom_attribute_set</data> + <data name="attributeSet/dataset" xsi:type="string">custom_attribute_set</data> <data name="productAttribute/data/frontend_label" xsi:type="string">Date_Admin_%isolation%</data> <data name="productAttribute/data/frontend_input" xsi:type="string">Date</data> <data name="productAttribute/data/is_required" xsi:type="string">No</data> @@ -64,7 +64,7 @@ <constraint name="Magento\CatalogRule\Test\Constraint\AssertProductAttributeIsUsedPromoRules" /> </variation> <variation name="CreateProductAttributeEntityTestVariation4"> - <data name="productTemplate/dataset" xsi:type="string">custom_attribute_set</data> + <data name="attributeSet/dataset" xsi:type="string">custom_attribute_set</data> <data name="productAttribute/data/frontend_label" xsi:type="string">Yes/No_Admin_%isolation%</data> <data name="productAttribute/data/frontend_input" xsi:type="string">Yes/No</data> <data name="productAttribute/data/is_required" xsi:type="string">Yes</data> @@ -80,7 +80,7 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertAddedProductAttributeOnProductForm" /> </variation> <variation name="CreateProductAttributeEntityTestVariation5"> - <data name="productTemplate/dataset" xsi:type="string">custom_attribute_set</data> + <data name="attributeSet/dataset" xsi:type="string">custom_attribute_set</data> <data name="productAttribute/data/frontend_label" xsi:type="string">Multiple_Select_Admin_%isolation%</data> <data name="productAttribute/data/frontend_input" xsi:type="string">Multiple Select</data> <data name="productAttribute/data/options/dataset" xsi:type="string">default</data> @@ -109,7 +109,7 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertAttributeOptionsOnProductForm" /> </variation> <variation name="CreateProductAttributeEntityTestVariation6"> - <data name="productTemplate/dataset" xsi:type="string">custom_attribute_set</data> + <data name="attributeSet/dataset" xsi:type="string">custom_attribute_set</data> <data name="productAttribute/data/frontend_label" xsi:type="string">Dropdown_Admin_%isolation%</data> <data name="productAttribute/data/frontend_input" xsi:type="string">Dropdown</data> <data name="productAttribute/data/options/dataset" xsi:type="string">default</data> @@ -126,6 +126,9 @@ <data name="productAttribute/data/is_visible_on_front" xsi:type="string">Yes</data> <data name="productAttribute/data/used_in_product_listing" xsi:type="string">Yes</data> <data name="productAttribute/data/used_for_sort_by" xsi:type="string">Yes</data> + <data name="assertProduct/data/name" xsi:type="string">Product name</data> + <data name="assertProduct/data/sku" xsi:type="string">product-sku</data> + <data name="assertProduct/data/price" xsi:type="string">25</data> <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeInGrid" /> <constraint name="Magento\Catalog\Test\Constraint\AssertAttributeForm" /> <constraint name="Magento\Catalog\Test\Constraint\AssertAddedProductAttributeOnProductForm" /> @@ -142,7 +145,7 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertAttributeOptionsOnProductForm" /> </variation> <variation name="CreateProductAttributeEntityTestVariation7"> - <data name="productTemplate/dataset" xsi:type="string">custom_attribute_set</data> + <data name="attributeSet/dataset" xsi:type="string">custom_attribute_set</data> <data name="productAttribute/data/frontend_label" xsi:type="string">Price_Admin_%isolation%</data> <data name="productAttribute/data/frontend_input" xsi:type="string">Price</data> <data name="productAttribute/data/is_required" xsi:type="string">No</data> @@ -154,16 +157,16 @@ <data name="productAttribute/data/is_comparable" xsi:type="string">No</data> <data name="productAttribute/data/is_filterable" xsi:type="string">Filterable (with results)</data> <data name="productAttribute/data/is_filterable_in_search" xsi:type="string">Yes</data> + <data name="attributeValue" xsi:type="number">15</data> <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeInGrid" /> <constraint name="Magento\Catalog\Test\Constraint\AssertAttributeForm" /> <constraint name="Magento\Catalog\Test\Constraint\AssertAddedProductAttributeOnProductForm" /> - <constraint name="Magento\CatalogSearch\Test\Constraint\AssertAttributeSearchableByLabel" /> <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeDisplayingOnSearchForm" /> <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeIsFilterable" /> <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeIsFilterableInSearch" /> </variation> <variation name="CreateProductAttributeEntityTestVariation8"> - <data name="productTemplate/dataset" xsi:type="string">custom_attribute_set</data> + <data name="attributeSet/dataset" xsi:type="string">custom_attribute_set</data> <data name="productAttribute/data/frontend_label" xsi:type="string">Fixed_Product_Tax_Admin_%isolation%</data> <data name="productAttribute/data/frontend_input" xsi:type="string">Fixed Product Tax</data> <data name="productAttribute/data/attribute_code" xsi:type="string">attr_fpt_code_%isolation%</data> @@ -173,7 +176,7 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertAddedProductAttributeOnProductForm" /> </variation> <variation name="CreateProductAttributeEntityTestVariation9"> - <data name="productTemplate/dataset" xsi:type="string">custom_attribute_set</data> + <data name="attributeSet/dataset" xsi:type="string">custom_attribute_set</data> <data name="productAttribute/data/frontend_label" xsi:type="string">Text_Field_Admin_%isolation%</data> <data name="productAttribute/data/frontend_input" xsi:type="string">Text Field</data> <data name="productAttribute/data/is_required" xsi:type="string">Yes</data> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteAssignedToTemplateProductAttributeTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteAssignedToTemplateProductAttributeTest.php index a3c0028f6e70c13d348e9db060bbf528c24209d8..32b9303f802a36ebeb4c43bc7ee4fe2cb15a2160 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteAssignedToTemplateProductAttributeTest.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteAssignedToTemplateProductAttributeTest.php @@ -13,7 +13,7 @@ use Magento\Mtf\TestCase\Injectable; /** * Preconditions: - * 1. Create Product template, based on Default. + * 1. Create Attribute set, based on Default. * 2. Create product attribute and add to created template. * * Test Flow: @@ -64,14 +64,14 @@ class DeleteAssignedToTemplateProductAttributeTest extends Injectable /** * Run test. * - * @param CatalogAttributeSet $productTemplate + * @param CatalogAttributeSet $attributeSet * @return array */ - public function test(CatalogAttributeSet $productTemplate) + public function test(CatalogAttributeSet $attributeSet) { // Precondition - $productTemplate->persist(); - $attribute = $productTemplate->getDataFieldConfig('assigned_attributes')['source']->getAttributes()[0]; + $attributeSet->persist(); + $attribute = $attributeSet->getDataFieldConfig('assigned_attributes')['source']->getAttributes()[0]; // Steps $filter = ['attribute_code' => $attribute->getAttributeCode()]; @@ -80,6 +80,6 @@ class DeleteAssignedToTemplateProductAttributeTest extends Injectable $this->attributeNew->getPageActions()->delete(); $this->attributeNew->getModalBlock()->acceptAlert(); - return ['productTemplate' => $productTemplate, 'attribute' => $attribute]; + return ['attributeSet' => $attributeSet, 'attribute' => $attribute]; } } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteAssignedToTemplateProductAttributeTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteAssignedToTemplateProductAttributeTest.xml index 75b7694459abb5885d8dd3d12f3440888773ff2a..64961fdd6d4f3a50fbe0db726d29b4a8af1d1ee8 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteAssignedToTemplateProductAttributeTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteAssignedToTemplateProductAttributeTest.xml @@ -8,16 +8,19 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Catalog\Test\TestCase\ProductAttribute\DeleteAssignedToTemplateProductAttributeTest" summary="Delete Assigned to Template Product Attribute" ticketId="MAGETWO-26011"> <variation name="DeleteAssignedToTemplateProductAttributeTestVariation1"> - <data name="productTemplate/dataset" xsi:type="string">custom_attribute_set</data> - <data name="productTemplate/data/assigned_attributes/dataset" xsi:type="string">attribute_type_dropdown</data> + <data name="attributeSet/dataset" xsi:type="string">custom_attribute_set</data> + <data name="attributeSet/data/assigned_attributes/dataset" xsi:type="string">attribute_type_dropdown</data> <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeSuccessDeleteMessage" /> <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeAbsenceInGrid" /> <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeAbsenceInTemplateGroups" /> <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeAbsenceInUnassignedAttributes" /> </variation> <variation name="DeleteAssignedToTemplateProductAttributeTestVariation2"> - <data name="productTemplate/dataset" xsi:type="string">default</data> - <data name="productTemplate/data/assigned_attributes/dataset" xsi:type="string">attribute_type_text_field</data> + <data name="attributeSet/dataset" xsi:type="string">default</data> + <data name="attributeSet/data/assigned_attributes/dataset" xsi:type="string">attribute_type_text_field</data> + <data name="assertProduct/data/name" xsi:type="string">Product name</data> + <data name="assertProduct/data/sku" xsi:type="string">product-sku</data> + <data name="assertProduct/data/price" xsi:type="string">25</data> <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeSuccessDeleteMessage" /> <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeAbsenceInGrid" /> <constraint name="Magento\ConfigurableProduct\Test\Constraint\AssertProductAttributeAbsenceInVariationsSearch" /> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteAttributeSetTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteAttributeSetTest.php index d996e70adb41097c9c62ff5f37f52c5cfb7d4760..b6c3875db64af917d5f940e0f55456bd5070bc79 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteAttributeSetTest.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteAttributeSetTest.php @@ -13,7 +13,7 @@ use Magento\Mtf\Fixture\FixtureFactory; use Magento\Mtf\TestCase\Injectable; /** - * Test Creation for Delete Attribute Set (Product Template) + * Test Creation for Delete Attribute Set (Attribute Set) * * Preconditions: * 1. An attribute is created. @@ -22,8 +22,8 @@ use Magento\Mtf\TestCase\Injectable; * * Test Flow: * 1. Log in to Backend. - * 2. Navigate to Stores > Attributes > Product Template. - * 3. Open created Product Template. + * 2. Navigate to Stores > Attributes > Attribute Set. + * 3. Open created Attribute Set. * 4. Click 'Delete' button. * 5. Perform all assertions. * @@ -70,26 +70,26 @@ class DeleteAttributeSetTest extends Injectable * Run DeleteAttributeSet test * * @param FixtureFactory $fixtureFactory - * @param CatalogAttributeSet $productTemplate + * @param CatalogAttributeSet $attributeSet * @return array */ - public function test(FixtureFactory $fixtureFactory, CatalogAttributeSet $productTemplate) + public function test(FixtureFactory $fixtureFactory, CatalogAttributeSet $attributeSet) { // Precondition - $productTemplate->persist(); + $attributeSet->persist(); $product = $fixtureFactory->createByCode( 'catalogProductSimple', [ 'dataset' => 'default', 'data' => [ - 'attribute_set_id' => ['attribute_set' => $productTemplate], + 'attribute_set_id' => ['attribute_set' => $attributeSet], ], ] ); $product->persist(); // Steps - $filter = ['set_name' => $productTemplate->getAttributeSetName()]; + $filter = ['set_name' => $attributeSet->getAttributeSetName()]; $this->productSetIndex->open(); $this->productSetIndex->getGrid()->searchAndOpen($filter); $this->productSetEdit->getPageActions()->delete(); diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteAttributeSetTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteAttributeSetTest.xml index b4e1608eef6ac7612ace94d17441871b6923a2ed..b10b1444aa30daa3159fffe8cfb7fdd9141af889 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteAttributeSetTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteAttributeSetTest.xml @@ -6,13 +6,13 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/variations.xsd"> - <testCase name="Magento\Catalog\Test\TestCase\ProductAttribute\DeleteAttributeSetTest" summary="Delete Attribute Set (Product Template)" ticketId="MAGETWO-25473"> + <testCase name="Magento\Catalog\Test\TestCase\ProductAttribute\DeleteAttributeSetTest" summary="Delete Attribute Set (Attribute Set)" ticketId="MAGETWO-25473"> <variation name="DeleteAttributeSetTestVariation1"> - <data name="productTemplate/dataset" xsi:type="string">custom_attribute_set</data> - <data name="productTemplate/data/assigned_attributes/dataset" xsi:type="string">default</data> + <data name="attributeSet/dataset" xsi:type="string">custom_attribute_set</data> + <data name="attributeSet/data/assigned_attributes/dataset" xsi:type="string">default</data> <data name="product/dataset" xsi:type="string">default</data> - <constraint name="Magento\Catalog\Test\Constraint\AssertProductTemplateSuccessDeleteMessage" /> - <constraint name="Magento\Catalog\Test\Constraint\AssertProductTemplateNotInGrid" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertAttributeSetSuccessDeleteMessage" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertAttributeSetNotInGrid" /> <constraint name="Magento\Catalog\Test\Constraint\AssertProductNotInGrid" /> </variation> </testCase> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateAttributeSetTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateAttributeSetTest.php index 0939c76aadbe4c131169f2cbb7bed5ffc2d95a65..96b3e5971e1d6d661b789c8895646a22868ddd62 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateAttributeSetTest.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateAttributeSetTest.php @@ -21,12 +21,12 @@ use Magento\Mtf\TestCase\Injectable; * * Test Flow: * 1. Log in to Backend. - * 2. Navigate to Stores > Attributes > Product Template. - * 3. Open created Product Template. + * 2. Navigate to Stores > Attributes > Attribute Set. + * 3. Open created Attribute Set. * 4. Click 'Add New' button to create new group * 5. Add created Product Attribute to created group. * 6. Fill out other fields data according to data set. - * 7. Save Product Template. + * 7. Save Attribute Set. * 8. Preform all assertions. * * @group Product_Attributes_(MX) @@ -69,7 +69,7 @@ class UpdateAttributeSetTest extends Injectable } /** - * Run UpdateProductTemplate test + * Run UpdateAttributeSet test * * @param CatalogAttributeSet $attributeSet * @param CatalogAttributeSet $attributeSetOriginal diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateAttributeSetTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateAttributeSetTest.xml index 7a24dab72439588f6480959d2ee73229223140ea..4c10e0aa85c72d428c30ab8038170dc2fe766262 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateAttributeSetTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateAttributeSetTest.xml @@ -6,17 +6,17 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/variations.xsd"> - <testCase name="Magento\Catalog\Test\TestCase\ProductAttribute\UpdateAttributeSetTest" summary="Update Product Template" ticketId="MAGETWO-26251"> + <testCase name="Magento\Catalog\Test\TestCase\ProductAttribute\UpdateAttributeSetTest" summary="Update Attribute Set" ticketId="MAGETWO-26251"> <variation name="UpdateAttributeSetTestVariation1"> - <data name="attributeSet/data/attribute_set_name" xsi:type="string">ProductTemplateEdit1%isolation%</data> + <data name="attributeSet/data/attribute_set_name" xsi:type="string">AttributeSetEdit1%isolation%</data> <data name="attributeSet/data/group" xsi:type="string">Custom-group%isolation%</data> <data name="attributeSetOriginal/dataset" xsi:type="string">custom_attribute_set</data> <data name="productAttributeOriginal/dataset" xsi:type="string">attribute_type_text_field</data> - <constraint name="Magento\Catalog\Test\Constraint\AssertProductTemplateSuccessSaveMessage" /> - <constraint name="Magento\Catalog\Test\Constraint\AssertProductTemplateForm" /> - <constraint name="Magento\Catalog\Test\Constraint\AssertProductTemplateInGrid" /> - <constraint name="Magento\Catalog\Test\Constraint\AssertProductTemplateOnProductForm" /> - <constraint name="Magento\Catalog\Test\Constraint\AssertProductTemplateGroupOnProductForm" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertAttributeSetSuccessSaveMessage" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertAttributeSetForm" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertAttributeSetInGrid" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertAttributeSetOnProductForm" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertAttributeSetGroupOnProductForm" /> </variation> </testCase> </config> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.php index 755ff5eb886e3548425a84dec20644430f4b9330..d3b51ebdce2cc33be18ba574bf2a546534f14e69 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.php @@ -18,7 +18,7 @@ use Magento\Mtf\TestCase\Injectable; * Preconditions: * Dataset : AttributeOptions * 1. Attribute is created (Attribute) - * 2. Attribute set is created (Product Template) + * 2. Attribute set is created (Attribute Set) * * Test Flow: * 1. Log in to Backend. @@ -61,7 +61,7 @@ class UpdateProductAttributeEntityTest extends Injectable * * @param CatalogProductAttribute $productAttributeOriginal * @param CatalogProductAttribute $attribute - * @param CatalogAttributeSet $productTemplate + * @param CatalogAttributeSet $attributeSet * @param CatalogProductAttributeIndex $attributeIndex * @param CatalogProductAttributeNew $attributeNew * @param CatalogProductSimple $productSimple @@ -70,13 +70,13 @@ class UpdateProductAttributeEntityTest extends Injectable public function testUpdateProductAttribute( CatalogProductAttribute $productAttributeOriginal, CatalogProductAttribute $attribute, - CatalogAttributeSet $productTemplate, + CatalogAttributeSet $attributeSet, CatalogProductAttributeIndex $attributeIndex, CatalogProductAttributeNew $attributeNew, CatalogProductSimple $productSimple ) { //Precondition - $productTemplate->persist(); + $attributeSet->persist(); $productAttributeOriginal->persist(); $filter = [ @@ -91,7 +91,7 @@ class UpdateProductAttributeEntityTest extends Injectable $attribute = $this->prepareAttribute($attribute, $productAttributeOriginal); $productSimple->persist(); - return ['product' => $this->prepareProduct($productSimple, $attribute, $productTemplate)]; + return ['product' => $this->prepareProduct($productSimple, $attribute, $attributeSet)]; } /** @@ -99,13 +99,13 @@ class UpdateProductAttributeEntityTest extends Injectable * * @param CatalogProductSimple $product * @param CatalogProductAttribute $attribute - * @param CatalogAttributeSet $productTemplate + * @param CatalogAttributeSet $attributeSet * @return CatalogProductSimple */ - protected function prepareProduct($product, $attribute, $productTemplate) + protected function prepareProduct($product, $attribute, $attributeSet) { $data = [ - 'attribute_set_id' => ['attribute_set' => $productTemplate], + 'attribute_set_id' => ['attribute_set' => $attributeSet], 'custom_attribute' => $attribute ]; $data = array_merge($data, $product->getData()); diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.xml index 63dabf015796e34f589b4ac24a2ac9188da26507..e58233de491d59dc45764d5db260528f7abc077f 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/UpdateProductAttributeEntityTest.xml @@ -8,7 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Catalog\Test\TestCase\ProductAttribute\UpdateProductAttributeEntityTest" summary="Update Product Attribute" ticketId="MAGETWO-23459"> <variation name="UpdateProductAttributeEntityTestVariation1"> - <data name="productTemplate/dataset" xsi:type="string">custom_attribute_set</data> + <data name="attributeSet/dataset" xsi:type="string">custom_attribute_set</data> <data name="productAttributeOriginal/dataset" xsi:type="string">attribute_type_text_field</data> <data name="attribute/data/frontend_label" xsi:type="string">Text_Field_%isolation%</data> <data name="attribute/data/is_required" xsi:type="string">Yes</data> @@ -28,7 +28,7 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertAddedProductAttributeOnProductForm" /> </variation> <variation name="UpdateProductAttributeEntityTestVariation2"> - <data name="productTemplate/dataset" xsi:type="string">custom_attribute_set</data> + <data name="attributeSet/dataset" xsi:type="string">custom_attribute_set</data> <data name="productAttributeOriginal/dataset" xsi:type="string">attribute_type_dropdown</data> <data name="attribute/data/frontend_label" xsi:type="string">Dropdown_%isolation%</data> <data name="attribute/data/options/dataset" xsi:type="string">default</data> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestStep/AddAttributeToProductTemplateStep.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestStep/AddAttributeToAttributeSetStep.php similarity index 79% rename from dev/tests/functional/tests/app/Magento/Catalog/Test/TestStep/AddAttributeToProductTemplateStep.php rename to dev/tests/functional/tests/app/Magento/Catalog/Test/TestStep/AddAttributeToAttributeSetStep.php index 3d5aa19186cec9f6a342ae492fd60df73e1b6f38..44126f9a153115cf82bb4374a6f78da7ccee93c5 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestStep/AddAttributeToProductTemplateStep.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestStep/AddAttributeToAttributeSetStep.php @@ -18,7 +18,7 @@ use Magento\Mtf\TestStep\TestStepInterface; /** * Move attribute To attribute set. */ -class AddAttributeToProductTemplateStep implements TestStepInterface +class AddAttributeToAttributeSetStep implements TestStepInterface { /** * Catalog ProductSet Index page. @@ -46,7 +46,7 @@ class AddAttributeToProductTemplateStep implements TestStepInterface * * @var CatalogAttributeSet */ - protected $productTemplate; + protected $attributeSet; /** * Catalog Product Index page. @@ -62,32 +62,42 @@ class AddAttributeToProductTemplateStep implements TestStepInterface */ protected $catalogProductEdit; + /** + * Custom attribute value to set while product creation. + * + * @var mixed + */ + protected $attributeValue; + /** * @constructor * @param CatalogProductSetIndex $catalogProductSetIndex * @param CatalogProductSetEdit $catalogProductSetEdit * @param CatalogProductAttribute $attribute - * @param CatalogAttributeSet $productTemplate + * @param CatalogAttributeSet $attributeSet * @param FixtureFactory $fixtureFactory * @param CatalogProductIndex $catalogProductIndex * @param CatalogProductEdit $catalogProductEdit + * @param mixed $attributeValue [optional] */ public function __construct( CatalogProductSetIndex $catalogProductSetIndex, CatalogProductSetEdit $catalogProductSetEdit, CatalogProductAttribute $attribute, - CatalogAttributeSet $productTemplate, + CatalogAttributeSet $attributeSet, FixtureFactory $fixtureFactory, CatalogProductIndex $catalogProductIndex, - CatalogProductEdit $catalogProductEdit + CatalogProductEdit $catalogProductEdit, + $attributeValue = null ) { $this->catalogProductSetIndex = $catalogProductSetIndex; $this->catalogProductSetEdit = $catalogProductSetEdit; $this->attribute = $attribute; - $this->productTemplate = $productTemplate; + $this->attributeSet = $attributeSet; $this->fixtureFactory = $fixtureFactory; $this->catalogProductIndex = $catalogProductIndex; $this->catalogProductEdit = $catalogProductEdit; + $this->attributeValue = $attributeValue; } /** @@ -97,19 +107,23 @@ class AddAttributeToProductTemplateStep implements TestStepInterface */ public function run() { - $filterAttribute = ['set_name' => $this->productTemplate->getAttributeSetName()]; + $filterAttribute = ['set_name' => $this->attributeSet->getAttributeSetName()]; $this->catalogProductSetIndex->open()->getGrid()->searchAndOpen($filterAttribute); $this->catalogProductSetEdit->getAttributeSetEditBlock()->moveAttribute($this->attribute->getData()); $this->catalogProductSetEdit->getPageActions()->save(); // Create product with attribute set mentioned above: + $customAttribute = $this->attribute; + if ($this->attributeValue !== null) { + $customAttribute = ['value' => $this->attributeValue, 'attribute' => $customAttribute]; + } $product = $this->fixtureFactory->createByCode( 'catalogProductSimple', [ 'dataset' => 'product_with_category_with_anchor', 'data' => [ - 'attribute_set_id' => ['attribute_set' => $this->productTemplate], - 'custom_attribute' => $this->attribute + 'attribute_set_id' => ['attribute_set' => $this->attributeSet], + 'custom_attribute' => $customAttribute ], ] ); diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestStep/CreateProductTemplateStep.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestStep/CreateAttributeSetStep.php similarity index 62% rename from dev/tests/functional/tests/app/Magento/Catalog/Test/TestStep/CreateProductTemplateStep.php rename to dev/tests/functional/tests/app/Magento/Catalog/Test/TestStep/CreateAttributeSetStep.php index e8b106042af164484fbc0f73c6ad92deba48eafc..d844cccdc24e195a07befafdebf90515dfa0a46a 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestStep/CreateProductTemplateStep.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestStep/CreateAttributeSetStep.php @@ -12,24 +12,24 @@ use Magento\Mtf\TestStep\TestStepInterface; /** * Create product attribute template using handler. */ -class CreateProductTemplateStep implements TestStepInterface +class CreateAttributeSetStep implements TestStepInterface { /** * CatalogAttributeSet fixture. * * @var string */ - protected $productTemplate; + protected $attributeSet; /** * Preparing step properties. * * @constructor - * @param CatalogAttributeSet $productTemplate + * @param CatalogAttributeSet $attributeSet */ - public function __construct(CatalogAttributeSet $productTemplate) + public function __construct(CatalogAttributeSet $attributeSet) { - $this->productTemplate = $productTemplate; + $this->attributeSet = $attributeSet; } /** @@ -39,8 +39,8 @@ class CreateProductTemplateStep implements TestStepInterface */ public function run() { - $this->productTemplate->persist(); + $this->attributeSet->persist(); - return ['productTemplate' => $this->productTemplate]; + return ['attributeSet' => $this->attributeSet]; } } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestStep/SaveProductTemplateStep.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestStep/SaveAttributeSetStep.php similarity index 93% rename from dev/tests/functional/tests/app/Magento/Catalog/Test/TestStep/SaveProductTemplateStep.php rename to dev/tests/functional/tests/app/Magento/Catalog/Test/TestStep/SaveAttributeSetStep.php index 759f036f3f818a5e024b9ae80253c4d0895737eb..2b7e0ac641f20cbda67cd693cc3696d5e4ea62c4 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestStep/SaveProductTemplateStep.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestStep/SaveAttributeSetStep.php @@ -12,7 +12,7 @@ use Magento\Mtf\TestStep\TestStepInterface; /** * Save attributeSet on attribute set page. */ -class SaveProductTemplateStep implements TestStepInterface +class SaveAttributeSetStep implements TestStepInterface { /** * Catalog ProductSet Edit page. diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/di.xml index 92c41c11a06ef9e15ec3f1f2fa85775387f59ee3..aaf0ac2bcbda12b35e15d84c59dd1cd0c8c9e0fd 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/di.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/di.xml @@ -76,22 +76,22 @@ <argument name="severity" xsi:type="string">middle</argument> </arguments> </type> - <type name="Magento\Catalog\Test\Constraint\AssertProductTemplateSuccessSaveMessage"> + <type name="Magento\Catalog\Test\Constraint\AssertAttributeSetSuccessSaveMessage"> <arguments> <argument name="severity" xsi:type="string">high</argument> </arguments> </type> - <type name="Magento\Catalog\Test\Constraint\AssertProductTemplateForm"> + <type name="Magento\Catalog\Test\Constraint\AssertAttributeSetForm"> <arguments> <argument name="severity" xsi:type="string">high</argument> </arguments> </type> - <type name="Magento\Catalog\Test\Constraint\AssertProductTemplateInGrid"> + <type name="Magento\Catalog\Test\Constraint\AssertAttributeSetInGrid"> <arguments> <argument name="severity" xsi:type="string">high</argument> </arguments> </type> - <type name="Magento\Catalog\Test\Constraint\AssertProductTemplateOnProductForm"> + <type name="Magento\Catalog\Test\Constraint\AssertAttributeSetOnProductForm"> <arguments> <argument name="severity" xsi:type="string">high</argument> </arguments> @@ -126,7 +126,7 @@ <argument name="severity" xsi:type="string">high</argument> </arguments> </type> - <type name="Magento\Catalog\Test\Constraint\AssertProductTemplateGroupOnProductForm"> + <type name="Magento\Catalog\Test\Constraint\AssertAttributeSetGroupOnProductForm"> <arguments> <argument name="severity" xsi:type="string">high</argument> </arguments> @@ -136,7 +136,7 @@ <argument name="severity" xsi:type="string">high</argument> </arguments> </type> - <type name="Magento\Catalog\Test\Constraint\AssertProductTemplateSuccessDeleteMessage"> + <type name="Magento\Catalog\Test\Constraint\AssertAttributeSetSuccessDeleteMessage"> <arguments> <argument name="severity" xsi:type="string">high</argument> </arguments> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/testcase.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/testcase.xml index 4e02d8c777cdae0624fb21d771f32920a66a3c69..c1d721c45f35024071b54adffd8335758edacaa8 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/testcase.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/testcase.xml @@ -16,12 +16,12 @@ <step name="setDefaultAttributeValue" module="Magento_Catalog" next="saveProduct"/> <step name="saveProduct" module="Magento_Catalog"/> </scenario> - <scenario name="CreateProductAttributeEntityTest" firstStep="createProductTemplate"> - <step name="createProductTemplate" module="Magento_Catalog" next="openProductAttributesPage"/> + <scenario name="CreateProductAttributeEntityTest" firstStep="createAttributeSet"> + <step name="createAttributeSet" module="Magento_Catalog" next="openProductAttributesPage"/> <step name="openProductAttributesPage" module="Magento_Catalog" next="addNewAttribute"/> <step name="addNewAttribute" module="Magento_Catalog" next="fillAttributeForm"/> <step name="fillAttributeForm" module="Magento_Catalog" next="saveAttribute"/> - <step name="saveAttribute" module="Magento_Catalog" next="addAttributeToProductTemplate"/> - <step name="addAttributeToProductTemplate" module="Magento_Catalog"/> + <step name="saveAttribute" module="Magento_Catalog" next="addAttributeToAttributeSet"/> + <step name="addAttributeToAttributeSet" module="Magento_Catalog"/> </scenario> </config> diff --git a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Constraint/AssertCatalogPriceRuleAppliedShoppingCart.php b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Constraint/AssertCatalogPriceRuleAppliedShoppingCart.php index 7a4e4b605ef4b7c64a09c0ac6d613159167002c2..252a96620ece4f2838e057bd5ec1753d4f6729e1 100644 --- a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Constraint/AssertCatalogPriceRuleAppliedShoppingCart.php +++ b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Constraint/AssertCatalogPriceRuleAppliedShoppingCart.php @@ -58,6 +58,7 @@ class AssertCatalogPriceRuleAppliedShoppingCart extends AbstractConstraint . "\nActual: " . $actualPrice . "\n" ); } + $checkoutCartPage->getTotalsBlock()->waitForShippingPriceBlock(); $actualPrices['sub_total'] = $checkoutCartPage->getTotalsBlock()->getSubtotal(); $actualPrices['grand_total'] = $checkoutCartPage->getTotalsBlock()->getGrandTotal(); $expectedPrices['sub_total'] = $cartPrice['sub_total']; diff --git a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Constraint/AssertCatalogPriceRuleNoticeMessage.php b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Constraint/AssertCatalogPriceRuleNoticeMessage.php index 889735d7f2eabbe38d02c2ba382023820e2e5d6a..813711e273f3da69b8094cc4eae19b69d85cf782 100644 --- a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Constraint/AssertCatalogPriceRuleNoticeMessage.php +++ b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Constraint/AssertCatalogPriceRuleNoticeMessage.php @@ -28,7 +28,7 @@ class AssertCatalogPriceRuleNoticeMessage extends AbstractConstraint public function processAssert( CatalogRuleIndex $pageCatalogRuleIndex ) { - $actualMessage = $pageCatalogRuleIndex->getMessagesBlock()->getNoticeMessages(); + $actualMessage = $pageCatalogRuleIndex->getMessagesBlock()->getNoticeMessage(); \PHPUnit_Framework_Assert::assertEquals( self::NOTICE_MESSAGE_RULES . self::NOTICE_MESSAGE_APPLY, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Constraint/AssertCatalogPriceRuleSuccessDeleteMessage.php b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Constraint/AssertCatalogPriceRuleSuccessDeleteMessage.php index f8531c5540c3ff4acb4dd8bdff33042766153cec..9b0f07e848f450bf61528b61abbc72778ca9a58d 100644 --- a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Constraint/AssertCatalogPriceRuleSuccessDeleteMessage.php +++ b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Constraint/AssertCatalogPriceRuleSuccessDeleteMessage.php @@ -24,7 +24,7 @@ class AssertCatalogPriceRuleSuccessDeleteMessage extends AbstractConstraint */ public function processAssert(CatalogRuleIndex $pageCatalogRuleIndex) { - $actualMessage = $pageCatalogRuleIndex->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $pageCatalogRuleIndex->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_DELETE_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Constraint/AssertCatalogPriceRuleSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Constraint/AssertCatalogPriceRuleSuccessSaveMessage.php index a1cdb0e31bd9f1ebb4e32b957d011af5dd4224f4..23418a8638b558323ebc8f4c183b9598e933ba0a 100644 --- a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Constraint/AssertCatalogPriceRuleSuccessSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/Constraint/AssertCatalogPriceRuleSuccessSaveMessage.php @@ -25,9 +25,6 @@ class AssertCatalogPriceRuleSuccessSaveMessage extends AbstractConstraint public function processAssert(CatalogRuleIndex $pageCatalogRuleIndex) { $actualMessages = $pageCatalogRuleIndex->getMessagesBlock()->getSuccessMessages(); - if (!is_array($actualMessages)) { - $actualMessages = [$actualMessages]; - } \PHPUnit_Framework_Assert::assertContains( self::SUCCESS_MESSAGE, $actualMessages, diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertSearchTermSuccessDeleteMessage.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertSearchTermSuccessDeleteMessage.php index 0177e5d8860f9307eb70b795272d727d3ec36c6b..8531933cebe683d5c1baf866f8eb5a369d274afe 100644 --- a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertSearchTermSuccessDeleteMessage.php +++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertSearchTermSuccessDeleteMessage.php @@ -32,11 +32,13 @@ class AssertSearchTermSuccessDeleteMessage extends AbstractConstraint */ public function processAssert(CatalogSearchIndex $indexPage) { - $actualMessage = $indexPage->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $indexPage->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_DELETE_MESSAGE, $actualMessage, 'Wrong success message is displayed.' + . "\nExpected: " . self::SUCCESS_DELETE_MESSAGE + . "\nActual: " . $actualMessage ); } diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertSearchTermSuccessMassDeleteMessage.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertSearchTermSuccessMassDeleteMessage.php index 4a6a3623910a4d6edb8dbbac672d8ed230ef5f2c..425c019d942ecda02f9152cb924b06ef779e981f 100644 --- a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertSearchTermSuccessMassDeleteMessage.php +++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertSearchTermSuccessMassDeleteMessage.php @@ -28,12 +28,14 @@ class AssertSearchTermSuccessMassDeleteMessage extends AbstractConstraint */ public function processAssert(array $searchTerms, CatalogSearchIndex $indexPage) { - $actualMessage = $indexPage->getMessagesBlock()->getSuccessMessages(); - $successMessages = sprintf(self::SUCCESS_MESSAGE, count($searchTerms)); + $actualMessage = $indexPage->getMessagesBlock()->getSuccessMessage(); + $expectedMessage = sprintf(self::SUCCESS_MESSAGE, count($searchTerms)); \PHPUnit_Framework_Assert::assertEquals( - $successMessages, + $expectedMessage, $actualMessage, 'Wrong success message is displayed.' + . "\nExpected: " . $expectedMessage + . "\nActual: " . $actualMessage ); } diff --git a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertSearchTermSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertSearchTermSuccessSaveMessage.php index d80a6eab3d89d3f5164f81f97b6477f58637cc1b..7316f846b6cb67d5abe8de3e86c4f099845af5f1 100644 --- a/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertSearchTermSuccessSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/CatalogSearch/Test/Constraint/AssertSearchTermSuccessSaveMessage.php @@ -28,7 +28,7 @@ class AssertSearchTermSuccessSaveMessage extends AbstractConstraint */ public function processAssert(CatalogSearchIndex $indexPage) { - $actualMessage = $indexPage->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $indexPage->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart/Sidebar/Item.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart/Sidebar/Item.php index 43dbd23499a0d866f2fdf999c086716d20d79a4d..f49a19118ed2526cd7e4ec9666523bc5a5f8cf46 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart/Sidebar/Item.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart/Sidebar/Item.php @@ -47,6 +47,7 @@ class Item extends Sidebar /** @var \Magento\Ui\Test\Block\Adminhtml\Modal $modal */ $modal = $this->blockFactory->create('Magento\Ui\Test\Block\Adminhtml\Modal', ['element' => $element]); $modal->acceptAlert(); + $modal->waitModalWindowToDisappear(); } /** diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart/Totals.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart/Totals.php index 8b2bfcbd56d4f4f3b90a03d9ecdad7b39d322efd..738bb89e949b6476bf67fbb1407b2be3e06ae192 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart/Totals.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart/Totals.php @@ -251,4 +251,14 @@ class Totals extends Block sleep(1); $this->waitForElementNotVisible($this->blockWaitElement); } + + /** + * Wait for shipping block to appear + * + * @return bool|null + */ + public function waitForShippingPriceBlock() + { + $this->waitForElementVisible($this->shippingPriceBlockSelector, Locator::SELECTOR_CSS); + } } diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertAddedProductToCartSuccessMessage.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertAddedProductToCartSuccessMessage.php index af0f03c0247ee993f1d54f7ac3a4addcc2157507..80f275de861285aa1760d6a6c56760b0da46d187 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertAddedProductToCartSuccessMessage.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertAddedProductToCartSuccessMessage.php @@ -32,7 +32,7 @@ class AssertAddedProductToCartSuccessMessage extends AbstractConstraint { \PHPUnit_Framework_Assert::assertEquals( sprintf(self::SUCCESS_MESSAGE, $product->getName()), - $checkoutCart->getMessagesBlock()->getSuccessMessages() + $checkoutCart->getMessagesBlock()->getSuccessMessage() ); } diff --git a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/Constraint/AssertTermSuccessDeleteMessage.php b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/Constraint/AssertTermSuccessDeleteMessage.php index eb57e0ac4719d8257841954818bc18de7ad62d78..f3b0e8cbae186de1952c854463d71ea8ac28912d 100644 --- a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/Constraint/AssertTermSuccessDeleteMessage.php +++ b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/Constraint/AssertTermSuccessDeleteMessage.php @@ -30,7 +30,7 @@ class AssertTermSuccessDeleteMessage extends AbstractConstraint { \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_DELETE_MESSAGE, - $agreementIndex->getMessagesBlock()->getSuccessMessages(), + $agreementIndex->getMessagesBlock()->getSuccessMessage(), 'Wrong success delete message is displayed.' ); } diff --git a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/Constraint/AssertTermSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/Constraint/AssertTermSuccessSaveMessage.php index ba715ffa968962e59c6d8a4866341dd14fb1226a..c55619144c7033dd5d59d11b6be6acc2ec0fd9c8 100644 --- a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/Constraint/AssertTermSuccessSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/Constraint/AssertTermSuccessSaveMessage.php @@ -30,7 +30,7 @@ class AssertTermSuccessSaveMessage extends AbstractConstraint { \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_SAVE_MESSAGE, - $agreementIndex->getMessagesBlock()->getSuccessMessages(), + $agreementIndex->getMessagesBlock()->getSuccessMessage(), 'Wrong success message is displayed.' ); } diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/Constraint/AssertCmsBlockDeleteMessage.php b/dev/tests/functional/tests/app/Magento/Cms/Test/Constraint/AssertCmsBlockDeleteMessage.php index 965b7fe07cc7b0eabce9f99a47f54cca093bcdd9..edd10f3fe5086cc71f6098128dc4e7542fb17362 100644 --- a/dev/tests/functional/tests/app/Magento/Cms/Test/Constraint/AssertCmsBlockDeleteMessage.php +++ b/dev/tests/functional/tests/app/Magento/Cms/Test/Constraint/AssertCmsBlockDeleteMessage.php @@ -24,7 +24,7 @@ class AssertCmsBlockDeleteMessage extends AbstractConstraint */ public function processAssert(CmsBlockIndex $cmsBlockIndex) { - $actualMessage = $cmsBlockIndex->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $cmsBlockIndex->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_DELETE_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/Constraint/AssertCmsBlockSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/Cms/Test/Constraint/AssertCmsBlockSuccessSaveMessage.php index 1c2696d6ed3c527b3d1cb0addc79095bf025342e..374c9b98527b49f02235f1f2735f53885499c0b5 100644 --- a/dev/tests/functional/tests/app/Magento/Cms/Test/Constraint/AssertCmsBlockSuccessSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/Cms/Test/Constraint/AssertCmsBlockSuccessSaveMessage.php @@ -24,7 +24,7 @@ class AssertCmsBlockSuccessSaveMessage extends AbstractConstraint */ public function processAssert(CmsBlockIndex $cmsBlockIndex) { - $actualMessage = $cmsBlockIndex->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $cmsBlockIndex->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_SAVE_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/Constraint/AssertCmsPageDeleteMessage.php b/dev/tests/functional/tests/app/Magento/Cms/Test/Constraint/AssertCmsPageDeleteMessage.php index ff01fa41f99e1990308af033ed5ba5b4c94d5ae9..7139477fb9703e264b094d8aa8b065df77f50bcd 100644 --- a/dev/tests/functional/tests/app/Magento/Cms/Test/Constraint/AssertCmsPageDeleteMessage.php +++ b/dev/tests/functional/tests/app/Magento/Cms/Test/Constraint/AssertCmsPageDeleteMessage.php @@ -24,7 +24,7 @@ class AssertCmsPageDeleteMessage extends AbstractConstraint */ public function processAssert(CmsPageIndex $cmsIndex) { - $actualMessage = $cmsIndex->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $cmsIndex->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_DELETE_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/Constraint/AssertCmsPageDuplicateErrorMessage.php b/dev/tests/functional/tests/app/Magento/Cms/Test/Constraint/AssertCmsPageDuplicateErrorMessage.php index 97e5247f658a8ce1d47dd5fdd62aaffb5b14ad9c..bd0af6ef0a3a2f029d09298acd64e1090a508f0c 100644 --- a/dev/tests/functional/tests/app/Magento/Cms/Test/Constraint/AssertCmsPageDuplicateErrorMessage.php +++ b/dev/tests/functional/tests/app/Magento/Cms/Test/Constraint/AssertCmsPageDuplicateErrorMessage.php @@ -24,7 +24,7 @@ class AssertCmsPageDuplicateErrorMessage extends AbstractConstraint */ public function processAssert(CmsPageIndex $cmsIndex) { - $message = $cmsIndex->getMessagesBlock()->getErrorMessages(); + $message = $cmsIndex->getMessagesBlock()->getErrorMessage(); \PHPUnit_Framework_Assert::assertEquals( self::ERROR_SAVE_MESSAGE, $message, diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/Constraint/AssertCmsPageSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/Cms/Test/Constraint/AssertCmsPageSuccessSaveMessage.php index c57528db3735163ef8a94fdf34e6370ddaf8426b..957ec384c4325ab368452c357adffa37ffaadde8 100644 --- a/dev/tests/functional/tests/app/Magento/Cms/Test/Constraint/AssertCmsPageSuccessSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/Cms/Test/Constraint/AssertCmsPageSuccessSaveMessage.php @@ -24,7 +24,7 @@ class AssertCmsPageSuccessSaveMessage extends AbstractConstraint */ public function processAssert(CmsPageIndex $cmsIndex) { - $actualMessage = $cmsIndex->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $cmsIndex->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_SAVE_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Config.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Config.php index 846c920cd94396e9334c550295e5506257157133..ec16f30dfc1d2344bebc302d5ec4eb178ddc855a 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Config.php +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Config.php @@ -98,7 +98,7 @@ class Config extends Tab foreach ($attributesValue as $key => $value) { $attributesValue[$key] = array_merge($value, $attributes['attributes_data'][$key]); } - $this->_rootElement->find($this->createConfigurationsButton)->click(); + $this->createConfigurations(); $this->getAttributeBlock()->fillAttributes($attributesValue); if (!empty($attributes['matrix'])) { $this->generateVariations(); @@ -122,6 +122,16 @@ class Config extends Tab } } + /** + * Click 'Create Configurations' button. + * + * @return void + */ + public function createConfigurations() + { + $this->_rootElement->find($this->createConfigurationsButton)->click(); + } + /** * Generate variations. * diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Config/Attribute.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Config/Attribute.php index be8653668f1d5b4e9acda2c83d357a73b8d5e762..e12f036a49ba2848728bc4c03bdbf84cd90e3bd3 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Config/Attribute.php +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Config/Attribute.php @@ -181,7 +181,7 @@ class Attribute extends Form /** * @return \Magento\Ui\Test\Block\Adminhtml\DataGrid */ - protected function getAttributesGrid() + public function getAttributesGrid() { return $this->blockFactory->create( 'Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\AttributesGrid', diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Config/Attribute/AttributeSelector.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Config/Attribute/AttributeSelector.php index 4d2bf2cb8268168557df928f63a3cb0b8cde12c8..e41ef61382f754f87f1f142616f2d5974cd0d540 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Config/Attribute/AttributeSelector.php +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Config/Attribute/AttributeSelector.php @@ -7,7 +7,6 @@ namespace Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Tab\Super\Config\Attribute; use Magento\Mtf\Client\Element\SuggestElement; -use Magento\Catalog\Test\Fixture\CatalogProductAttribute; /** * Form Attribute Search on Product page. @@ -32,15 +31,4 @@ class AttributeSelector extends SuggestElement // that causes disappearing of result suggest list. } } - - /** - * Checking exist configurable attribute in search result. - * - * @param CatalogProductAttribute $productAttribute - * @return bool - */ - public function isExistAttributeInSearchResult(CatalogProductAttribute $productAttribute) - { - return $this->isExistValueInSearchResult($productAttribute->getFrontendLabel()); - } } diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductAttributeAbsenceInVariationsSearch.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductAttributeAbsenceInVariationsSearch.php index 1c7edf16fe5f56fa2bbca505492f728c8a8e3063..e2adc6353c3157e4cc0c94c9e2861764bd4d0a72 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductAttributeAbsenceInVariationsSearch.php +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductAttributeAbsenceInVariationsSearch.php @@ -11,29 +11,31 @@ use Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Tab\Super\Conf use Magento\Catalog\Test\Fixture\CatalogProductAttribute; use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex; use Magento\Catalog\Test\Page\Adminhtml\CatalogProductNew; +use Magento\ConfigurableProduct\Test\Fixture\ConfigurableProduct; use Magento\Mtf\Constraint\AbstractConstraint; /** - * Class AssertProductAttributeAbsenceInVariationsSearch - * Check that deleted attribute can't be added to product template on Product Page via Add Attribute control + * Check that deleted attribute can't be added to attribute set on Product Page via Add Attribute control. */ class AssertProductAttributeAbsenceInVariationsSearch extends AbstractConstraint { /** - * Label "Variations" tab + * Label "Variations" tab. */ const TAB_VARIATIONS = 'variations'; /** - * Assert that deleted attribute can't be added to product template on Product Page via Add Attribute control + * Assert that deleted attribute can't be added to attribute set on Product Page via Add Attribute control. * * @param CatalogProductAttribute $productAttribute + * @param ConfigurableProduct $assertProduct * @param CatalogProductIndex $productGrid * @param CatalogProductNew $newProductPage * @return void */ public function processAssert( CatalogProductAttribute $productAttribute, + ConfigurableProduct $assertProduct, CatalogProductIndex $productGrid, CatalogProductNew $newProductPage ) { @@ -41,18 +43,19 @@ class AssertProductAttributeAbsenceInVariationsSearch extends AbstractConstraint $productGrid->getGridPageActionBlock()->addProduct('simple'); /** @var VariationsTab $variationsTab */ + $newProductPage->getProductForm()->fill($assertProduct); $variationsTab = $newProductPage->getProductForm()->getTab(self::TAB_VARIATIONS); $variationsTab->showContent(); - /** @var AttributeBlock $attributesBlock */ - $attributesBlock = $variationsTab->getAttributeBlock(); + $variationsTab->createConfigurations(); + $attributesGrid = $variationsTab->getAttributeBlock()->getAttributesGrid(); \PHPUnit_Framework_Assert::assertFalse( - $attributesBlock->getAttributeSelector()->isExistAttributeInSearchResult($productAttribute), + $attributesGrid->isRowVisible(['frontend_label' => $productAttribute->getFrontendLabel()]), "Product attribute found in Attribute Search form." ); } /** - * Text absent Product Attribute in Attribute Search form + * Text absent Product Attribute in Attribute Search form. * * @return string */ diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductAttributeIsConfigurable.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductAttributeIsConfigurable.php index e088a33cf703d48927bed5a0bcb4ca8597713438..2c9d735450f50f9070d96233a2e35acafe70abae 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductAttributeIsConfigurable.php +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductAttributeIsConfigurable.php @@ -10,6 +10,7 @@ use Magento\Catalog\Test\Fixture\CatalogProductAttribute; use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex; use Magento\Catalog\Test\Page\Adminhtml\CatalogProductNew; use Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Tab\Super\Config as TabVariation; +use Magento\ConfigurableProduct\Test\Fixture\ConfigurableProduct; use Magento\Mtf\Constraint\AbstractConstraint; /** @@ -21,23 +22,27 @@ class AssertProductAttributeIsConfigurable extends AbstractConstraint * Assert check whether the attribute is used to create a configurable products. * * @param CatalogProductAttribute $attribute + * @param ConfigurableProduct $assertProduct * @param CatalogProductIndex $productGrid * @param CatalogProductNew $newProductPage */ public function processAssert( CatalogProductAttribute $attribute, + ConfigurableProduct $assertProduct, CatalogProductIndex $productGrid, CatalogProductNew $newProductPage ) { $productGrid->open(); $productGrid->getGridPageActionBlock()->addProduct('configurable'); $productBlockForm = $newProductPage->getProductForm(); + $productBlockForm->fill($assertProduct); $productBlockForm->openTab('variations'); - /** @var TabVariation $tabVariation */ - $tabVariation = $productBlockForm->getTab('variations'); - $configurableAttributeSelector = $tabVariation->getAttributeBlock()->getAttributeSelector(); + /** @var \Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Tab\Super\Config $variationsTab */ + $variationsTab = $productBlockForm->getTab('variations'); + $variationsTab->createConfigurations(); + $attributesGrid = $variationsTab->getAttributeBlock()->getAttributesGrid(); \PHPUnit_Framework_Assert::assertTrue( - $configurableAttributeSelector->isExistAttributeInSearchResult($attribute), + $attributesGrid->isRowVisible(['frontend_label' => $attribute->getFrontendLabel()]), "Product attribute is absent on the product page." ); } diff --git a/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Constraint/AssertCurrencySymbolSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Constraint/AssertCurrencySymbolSuccessSaveMessage.php index 912106f71bb7542d0f0ffb5339e73657b65d23f2..113e4774672ea446a80443a923e4ed79f42698bc 100644 --- a/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Constraint/AssertCurrencySymbolSuccessSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/CurrencySymbol/Test/Constraint/AssertCurrencySymbolSuccessSaveMessage.php @@ -25,7 +25,7 @@ class AssertCurrencySymbolSuccessSaveMessage extends AbstractConstraint */ public function processAssert(SystemCurrencySymbolIndex $currencySymbolIndex) { - $actualMessage = $currencySymbolIndex->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $currencySymbolIndex->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_SAVE_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Adminhtml/CustomerGrid.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Adminhtml/CustomerGrid.php index c82af6b00edfd7d847fc37ce5be745a4f7e4b243..93b3d1b7c16b73921e70c0ed31ad61e769b9544f 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Adminhtml/CustomerGrid.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Adminhtml/CustomerGrid.php @@ -39,10 +39,10 @@ class CustomerGrid extends DataGrid 'input' => 'select', ], 'entity_id_from' => [ - 'selector' => '[name="filters[entity_id][from]"]', + 'selector' => '[name="entity_id[from]"]', ], 'entity_id_to' => [ - 'selector' => '[name="filters[entity_id][to]"]', + 'selector' => '[name="entity_id[to]"]', ], ]; } diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertChangePasswordFailMessage.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertChangePasswordFailMessage.php index 48c58b1c316d96ceedc389c57252ce684f91e05a..cfe0d1f61cdddd23f3098dd98bee261a8d23130c 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertChangePasswordFailMessage.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertChangePasswordFailMessage.php @@ -30,7 +30,7 @@ class AssertChangePasswordFailMessage extends AbstractConstraint { \PHPUnit_Framework_Assert::assertEquals( self::FAIL_MESSAGE, - $customerAccountEdit->getMessages()->getErrorMessages() + $customerAccountEdit->getMessages()->getErrorMessage() ); } diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerAddressSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerAddressSuccessSaveMessage.php index 9dbf30c353e9d1fde84b182da0a63f35123390b7..195f0df3ca3f628f4930e199b4ca04a86d2db969 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerAddressSuccessSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerAddressSuccessSaveMessage.php @@ -28,7 +28,7 @@ class AssertCustomerAddressSuccessSaveMessage extends AbstractConstraint */ public function processAssert(CustomerAccountIndex $customerAccountIndex) { - $successMessage = $customerAccountIndex->getMessages()->getSuccessMessages(); + $successMessage = $customerAccountIndex->getMessages()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, $successMessage, diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerBackendDuplicateErrorMessage.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerBackendDuplicateErrorMessage.php index 27394f8e074ecc7fc0238a58285d8d4ed364fd16..f17dbafe7e21948bc48fa552780c794b0b54319a 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerBackendDuplicateErrorMessage.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerBackendDuplicateErrorMessage.php @@ -27,7 +27,7 @@ class AssertCustomerBackendDuplicateErrorMessage extends AbstractConstraint */ public function processAssert(CustomerIndex $customerIndexPage) { - $actualMessage = $customerIndexPage->getMessagesBlock()->getErrorMessages(); + $actualMessage = $customerIndexPage->getMessagesBlock()->getErrorMessage(); \PHPUnit_Framework_Assert::assertEquals( self::ERROR_SAVE_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerFailRegisterMessage.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerFailRegisterMessage.php index 2cb983b4bbc3a8b7a33b1acce819b91f35bf9fef..a37e68ed7f12f893060514bb9f2e0e6e4363f87a 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerFailRegisterMessage.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerFailRegisterMessage.php @@ -22,7 +22,7 @@ class AssertCustomerFailRegisterMessage extends AbstractConstraint */ public function processAssert(CustomerAccountCreate $registerPage) { - $errorMessage = $registerPage->getMessagesBlock()->getErrorMessages(); + $errorMessage = $registerPage->getMessagesBlock()->getErrorMessage(); \PHPUnit_Framework_Assert::assertNotEmpty( $errorMessage, 'No error message is displayed.' diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerForgotPasswordSuccessMessage.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerForgotPasswordSuccessMessage.php index 318b5e531a92e1ac37715a2e724bdac4f3277e78..c06a121ff20e3a051148efdfad3dcd347b25a0df 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerForgotPasswordSuccessMessage.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerForgotPasswordSuccessMessage.php @@ -29,14 +29,9 @@ class AssertCustomerForgotPasswordSuccessMessage extends AbstractConstraint CustomerAccountLogin $customerLogin, Customer $customer ) { - $message = sprintf( - self::SUCCESS_MESSAGE, - $customer->getEmail() - ); - \PHPUnit_Framework_Assert::assertEquals( - $message, - $customerLogin->getMessages()->getSuccessMessages(), + sprintf(self::SUCCESS_MESSAGE, $customer->getEmail()), + $customerLogin->getMessages()->getSuccessMessage(), 'Wrong forgot password message is displayed.' ); } diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerGroupAlreadyExists.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerGroupAlreadyExists.php index 6796c9aa0874f79897c424739b68817eed3595d5..50982fc8a6aa9c1d5d5ff41583972443127688fd 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerGroupAlreadyExists.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerGroupAlreadyExists.php @@ -24,7 +24,7 @@ class AssertCustomerGroupAlreadyExists extends AbstractConstraint */ public function processAssert(CustomerGroupNew $customerGroupNew) { - $actualMessage = $customerGroupNew->getMessagesBlock()->getErrorMessages(); + $actualMessage = $customerGroupNew->getMessagesBlock()->getErrorMessage(); \PHPUnit_Framework_Assert::assertEquals( self::ERROR_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerGroupSuccessDeleteMessage.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerGroupSuccessDeleteMessage.php index 81b3fc72b63d9cfdfaf3cbc15b50a6f8e3a40f97..8173d3cde87760debb60da3e9f866850f8e7785c 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerGroupSuccessDeleteMessage.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerGroupSuccessDeleteMessage.php @@ -24,12 +24,13 @@ class AssertCustomerGroupSuccessDeleteMessage extends AbstractConstraint */ public function processAssert(CustomerGroupIndex $customerGroupIndex) { + $actualMessage = $customerGroupIndex->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_DELETE_MESSAGE, - $customerGroupIndex->getMessagesBlock()->getSuccessMessages(), + $actualMessage, 'Wrong message is displayed.' . "\nExpected: " . self::SUCCESS_DELETE_MESSAGE - . "\nActual: " . $customerGroupIndex->getMessagesBlock()->getSuccessMessages() + . "\nActual: " . $actualMessage ); } diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerGroupSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerGroupSuccessSaveMessage.php index 9069acfce812b0c2bd116eb486d1a0faa36b312f..6ae95ea7f4d7ace5f8e3817ce3c6d9620df7ac7f 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerGroupSuccessSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerGroupSuccessSaveMessage.php @@ -24,7 +24,7 @@ class AssertCustomerGroupSuccessSaveMessage extends AbstractConstraint */ public function processAssert(CustomerGroupIndex $customerGroupIndex) { - $actualMessage = $customerGroupIndex->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $customerGroupIndex->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerInfoSuccessSavedMessage.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerInfoSuccessSavedMessage.php index 6396afca4ba5dc0faa10e3f0bd6987d3baed04cd..6a8d9c06ee2bef2d885867c8d20312b4539fa397 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerInfoSuccessSavedMessage.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerInfoSuccessSavedMessage.php @@ -28,7 +28,7 @@ class AssertCustomerInfoSuccessSavedMessage extends AbstractConstraint */ public function processAssert(CustomerAccountIndex $customerAccountIndex) { - $successMessage = $customerAccountIndex->getMessages()->getSuccessMessages(); + $successMessage = $customerAccountIndex->getMessages()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, $successMessage, diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerInvalidEmail.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerInvalidEmail.php index 37ad42ad921973e40c74b4549abf3923c876b6c7..922310e227e2cc99199bc056b2091ad8a593d38b 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerInvalidEmail.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerInvalidEmail.php @@ -29,7 +29,7 @@ class AssertCustomerInvalidEmail extends AbstractConstraint public function processAssert(Customer $customer, CustomerIndexNew $pageCustomerIndexNew) { $expectMessage = str_replace('%email%', $customer->getEmail(), self::ERROR_EMAIL_MESSAGE); - $actualMessage = $pageCustomerIndexNew->getMessagesBlock()->getErrorMessages(); + $actualMessage = $pageCustomerIndexNew->getMessagesBlock()->getErrorMessage(); \PHPUnit_Framework_Assert::assertEquals( $expectMessage, diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerMassDeleteSuccessMessage.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerMassDeleteSuccessMessage.php index c18c312e8855b412a9b97a9b724cd460ddc5aaed..3ac60cd83f990978dc131f01dae0a955d3843d51 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerMassDeleteSuccessMessage.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerMassDeleteSuccessMessage.php @@ -31,7 +31,7 @@ class AssertCustomerMassDeleteSuccessMessage extends AbstractConstraint { \PHPUnit_Framework_Assert::assertEquals( sprintf(self::SUCCESS_DELETE_MESSAGE, $customersQtyToDelete), - $customerIndexPage->getMessagesBlock()->getSuccessMessages(), + $customerIndexPage->getMessagesBlock()->getSuccessMessage(), 'Wrong delete message is displayed.' ); } diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerSuccessDeleteMessage.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerSuccessDeleteMessage.php index 632ab54f8f34e12617258325ffe2cca6bd08d478..36474ed8b9a1ae6c0721a5b911d429183f5fc6fd 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerSuccessDeleteMessage.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerSuccessDeleteMessage.php @@ -24,7 +24,7 @@ class AssertCustomerSuccessDeleteMessage extends AbstractConstraint */ public function processAssert(CustomerIndex $customerIndexPage) { - $actualMessage = $customerIndexPage->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $customerIndexPage->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::DELETE_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerSuccessRegisterMessage.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerSuccessRegisterMessage.php index bf70b9806347fbe9f410a2dba27ce1d283114b2f..7d6cc8d277861bf87b75b8009707228941cf4db2 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerSuccessRegisterMessage.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerSuccessRegisterMessage.php @@ -24,7 +24,7 @@ class AssertCustomerSuccessRegisterMessage extends AbstractConstraint */ public function processAssert(CustomerAccountCreate $registerPage) { - $actualMessage = $registerPage->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $registerPage->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerSuccessSaveMessage.php index 47e8faddaf56033fe026bbf131bc95de8a3e40fc..ca217f7a63e47a421ff0598b95f3ba59dcbfc493 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerSuccessSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertCustomerSuccessSaveMessage.php @@ -25,7 +25,7 @@ class AssertCustomerSuccessSaveMessage extends AbstractConstraint */ public function processAssert(CustomerIndex $pageCustomerIndex) { - $actualMessage = $pageCustomerIndex->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $pageCustomerIndex->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertMassActionSuccessUpdateMessage.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertMassActionSuccessUpdateMessage.php index 1d14f0995f6dd5a409bb5968facd1a5534bc2f6e..8b3c727bd0e94a018c6642ec688da37877720442 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertMassActionSuccessUpdateMessage.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Constraint/AssertMassActionSuccessUpdateMessage.php @@ -35,9 +35,8 @@ class AssertMassActionSuccessUpdateMessage extends AbstractConstraint public function processAssert($customer, CustomerIndex $pageCustomerIndex) { $customers = is_array($customer) ? $customer : [$customer]; - $customerCount = count($customers); - $actualMessage = $pageCustomerIndex->getMessagesBlock()->getSuccessMessages(); - \PHPUnit_Framework_Assert::assertEquals(sprintf(self::UPDATE_MESSAGE, $customerCount), $actualMessage); + $actualMessage = $pageCustomerIndex->getMessagesBlock()->getSuccessMessage(); + \PHPUnit_Framework_Assert::assertEquals(sprintf(self::UPDATE_MESSAGE, count($customers)), $actualMessage); } /** diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Page/Adminhtml/CustomerIndexEdit.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/Page/Adminhtml/CustomerIndexEdit.xml index 7dfacbc495c1259f286bfca6677d7339e280503a..d491bb75ab488143e45e401d04b970f631e4d37a 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Page/Adminhtml/CustomerIndexEdit.xml +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Page/Adminhtml/CustomerIndexEdit.xml @@ -7,11 +7,11 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/pages.xsd"> <page name="CustomerIndexEdit" area="Adminhtml" mca="customer/index/edit" module="Magento_Customer"> - <block name="titleBlock" class="Magento\Theme\Test\Block\Html\Title" locator=".page-title-wrapper .page-title" strategy="css selector"/> - <block name="messagesBlock" class="Magento\Backend\Test\Block\Messages" locator="#messages" strategy="css selector"/> - <block name="pageActionsBlock" class="Magento\Customer\Test\Block\Adminhtml\Edit\FormPageActions" locator=".page-main-actions" strategy="css selector"/> - <block name="customerForm" class="Magento\Customer\Test\Block\Adminhtml\Edit\CustomerForm" locator="[id='page:main-container']" strategy="css selector"/> - <block name="configureProductBlock" class="Magento\Catalog\Test\Block\Adminhtml\Product\Composite\Configure" locator="//*[@role='dialog' and ./*[@id='product_composite_configure'] and contains(@style,'display: block')]" strategy="xpath"/> - <block name="modalBlock" class="Magento\Ui\Test\Block\Adminhtml\Modal" locator="._show[data-role=modal]" strategy="css selector"/> + <block name="titleBlock" class="Magento\Theme\Test\Block\Html\Title" locator=".page-title-wrapper .page-title" strategy="css selector" /> + <block name="messagesBlock" class="Magento\Backend\Test\Block\Messages" locator="#messages" strategy="css selector" /> + <block name="pageActionsBlock" class="Magento\Customer\Test\Block\Adminhtml\Edit\FormPageActions" locator=".page-main-actions" strategy="css selector" /> + <block name="customerForm" class="Magento\Customer\Test\Block\Adminhtml\Edit\CustomerForm" locator="[id='page:main-container']" strategy="css selector" /> + <block name="configureProductBlock" class="Magento\Catalog\Test\Block\Adminhtml\Product\Composite\Configure" locator="[data-role='modal']._show" strategy="css selector" /> + <block name="modalBlock" class="Magento\Ui\Test\Block\Adminhtml\Modal" locator="._show[data-role=modal]" strategy="css selector" /> </page> </config> diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/MassAssignCustomerGroupTest.php b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/MassAssignCustomerGroupTest.php index d253c87f9ffad16877f91c2d79bc3127ab7112d8..fa144a9b396ebd58d5dd16d8d1246d547cc30f64 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/MassAssignCustomerGroupTest.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/MassAssignCustomerGroupTest.php @@ -91,7 +91,8 @@ class MassAssignCustomerGroupTest extends Injectable $this->customerIndex->open(); $this->customerIndex->getCustomerGridBlock()->massaction( [['email' => $customer->getEmail()]], - [$this->customersGridActions => $customerGroup->getCustomerGroupCode()] + [$this->customersGridActions => $customerGroup->getCustomerGroupCode()], + true ); } } diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerBackendEntityTest.php b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerBackendEntityTest.php index 1bb9544c621d6a0a1591fe8edd7e186776e4b462..95684cb07b8761464ca50aec34f25aa341fbade6 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerBackendEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerBackendEntityTest.php @@ -13,15 +13,16 @@ use Magento\Customer\Test\Page\Adminhtml\CustomerIndexEdit; use Magento\Mtf\TestCase\Injectable; /** - * Test Creation for UpdateCustomerBackendEntity + * Precondition: + * 1. Create customer. * - * General Flow: - * 1. Login to backend as admin - * 2. Navigate to CUSTOMERS->All Customers - * 3. Open from grid test customer - * 4. Edit some values, if addresses fields are not presented click 'Add New Address' button - * 5. Click 'Save' button - * 6. Perform all assertions + * Steps: + * 1. Login to backend as admin. + * 2. Navigate to CUSTOMERS->All Customers. + * 3. Open from grid test customer. + * 4. Edit some values, if addresses fields are not presented click 'Add New Address' button. + * 5. Click 'Save' button. + * 6. Perform all assertions. * * @ZephyrId MAGETWO-23881 */ @@ -33,18 +34,25 @@ class UpdateCustomerBackendEntityTest extends Injectable /* end tags */ /** + * Customer grid page. + * * @var CustomerIndex */ protected $customerIndexPage; /** + * Customer edit page. + * * @var CustomerIndexEdit */ protected $customerIndexEditPage; /** + * Inject pages. + * * @param CustomerIndex $customerIndexPage * @param CustomerIndexEdit $customerIndexEditPage + * @return void */ public function __inject( CustomerIndex $customerIndexPage, @@ -55,19 +63,19 @@ class UpdateCustomerBackendEntityTest extends Injectable } /** + * Run update customer test. + * * @param Customer $initialCustomer * @param Customer $customer - * @param Address $address + * @param Address $address [optional] + * @return void */ public function testUpdateCustomerBackendEntity( Customer $initialCustomer, Customer $customer, - Address $address + Address $address = null ) { - // Prepare data - $address = $address->hasData() ? $address : null; - - // Preconditions: + // Precondition $initialCustomer->persist(); // Steps diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerBackendEntityTest.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerBackendEntityTest.xml index afe288811e96d22ab5a8aea245054f54154d0b6e..0193f9cb8fa9f5aed64cf77921d61a11168941d5 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerBackendEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerBackendEntityTest.xml @@ -19,37 +19,13 @@ <data name="customer/data/dob" xsi:type="string">01/08/1986</data> <data name="customer/data/taxvat" xsi:type="string">123456789001</data> <data name="customer/data/gender" xsi:type="string">Male</data> - <data name="address/data/prefix" xsi:type="string">-</data> - <data name="address/data/firstname" xsi:type="string">-</data> - <data name="address/data/middlename" xsi:type="string">-</data> - <data name="address/data/lastname" xsi:type="string">-</data> - <data name="address/data/suffix" xsi:type="string">-</data> - <data name="address/data/company" xsi:type="string">-</data> - <data name="address/data/street" xsi:type="string">-</data> - <data name="address/data/city" xsi:type="string">-</data> - <data name="address/data/country_id" xsi:type="string">-</data> - <data name="address/data/region_id" xsi:type="string">-</data> - <data name="address/data/region" xsi:type="string">-</data> - <data name="address/data/postcode" xsi:type="string">-</data> - <data name="address/data/telephone" xsi:type="string">-</data> - <data name="address/data/fax" xsi:type="string">-</data> - <data name="address/data/vat_id" xsi:type="string">-</data> <constraint name="Magento\Customer\Test\Constraint\AssertCustomerSuccessSaveMessage" /> <constraint name="Magento\Customer\Test\Constraint\AssertCustomerForm" /> <constraint name="Magento\Customer\Test\Constraint\AssertCustomerInGrid" /> </variation> <variation name="UpdateCustomerBackendEntityTestVariation2"> <data name="initialCustomer/dataset" xsi:type="string">default</data> - <data name="customer/data/group_id/dataset" xsi:type="string">-</data> - <data name="customer/data/prefix" xsi:type="string">-</data> - <data name="customer/data/firstname" xsi:type="string">-</data> - <data name="customer/data/middlename" xsi:type="string">-</data> - <data name="customer/data/lastname" xsi:type="string">-</data> - <data name="customer/data/suffix" xsi:type="string">-</data> <data name="customer/data/email" xsi:type="string">-</data> - <data name="customer/data/dob" xsi:type="string">-</data> - <data name="customer/data/taxvat" xsi:type="string">-</data> - <data name="customer/data/gender" xsi:type="string">-</data> <data name="address/data/prefix" xsi:type="string">Prefix%isolation%_</data> <data name="address/data/firstname" xsi:type="string">Doe%isolation%</data> <data name="address/data/middlename" xsi:type="string">Middle Name %isolation%</data> @@ -60,10 +36,8 @@ <data name="address/data/city" xsi:type="string">Dothan</data> <data name="address/data/country_id" xsi:type="string">United States</data> <data name="address/data/region_id" xsi:type="string">Alabama</data> - <data name="address/data/region" xsi:type="string">-</data> <data name="address/data/postcode" xsi:type="string">36303</data> <data name="address/data/telephone" xsi:type="string">334-200-4060</data> - <data name="address/data/fax" xsi:type="string">555-666-777-8910</data> <data name="address/data/vat_id" xsi:type="string">U1234567890</data> <constraint name="Magento\Customer\Test\Constraint\AssertCustomerSuccessSaveMessage" /> <constraint name="Magento\Customer\Test\Constraint\AssertCustomerForm" /> @@ -90,11 +64,9 @@ <data name="address/data/street" xsi:type="string">39 Northgate Street</data> <data name="address/data/city" xsi:type="string">BICKTON</data> <data name="address/data/country_id" xsi:type="string">United Kingdom</data> - <data name="address/data/region_id" xsi:type="string">-</data> <data name="address/data/region" xsi:type="string">PINMINNOCH</data> <data name="address/data/postcode" xsi:type="string">KA26 1PF</data> <data name="address/data/telephone" xsi:type="string">999-777-111-2345</data> - <data name="address/data/fax" xsi:type="string">-</data> <data name="address/data/vat_id" xsi:type="string">987654321</data> <constraint name="Magento\Customer\Test\Constraint\AssertCustomerSuccessSaveMessage" /> <constraint name="Magento\Customer\Test\Constraint\AssertCustomerForm" /> diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerFrontendEntityTest.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerFrontendEntityTest.xml index 8d70104f70ab7b6fbe4dc11a009750e9e6498090..9398ab7ae74257ca7fc32ada8079b06dd2ae85aa 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerFrontendEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerFrontendEntityTest.xml @@ -19,9 +19,7 @@ <data name="address/data/city" xsi:type="string">City %isolation%</data> <data name="address/data/country_id" xsi:type="string">United States</data> <data name="address/data/region_id" xsi:type="string">Colorado</data> - <data name="address/data/region" xsi:type="string">-</data> <data name="address/data/telephone" xsi:type="string">555-888-111-999</data> - <data name="address/data/fax" xsi:type="string">161-999-8888</data> <data name="address/data/postcode" xsi:type="string">12345</data> <constraint name="Magento\Customer\Test\Constraint\AssertCustomerAddressSuccessSaveMessage" /> <constraint name="Magento\Customer\Test\Constraint\AssertCustomerDefaultAddresses" /> @@ -37,10 +35,8 @@ <data name="address/data/street" xsi:type="string">Some street %isolation%</data> <data name="address/data/city" xsi:type="string">City %isolation%</data> <data name="address/data/country_id" xsi:type="string">United Kingdom</data> - <data name="address/data/region_id" xsi:type="string">-</data> <data name="address/data/region" xsi:type="string">Region %isolation%</data> <data name="address/data/telephone" xsi:type="string">0123456789-02134567</data> - <data name="address/data/fax" xsi:type="string">5555-874-99634</data> <data name="address/data/postcode" xsi:type="string">12345</data> <constraint name="Magento\Customer\Test\Constraint\AssertCustomerAddressSuccessSaveMessage" /> <constraint name="Magento\Customer\Test\Constraint\AssertCustomerDefaultAddresses" /> @@ -57,9 +53,7 @@ <data name="address/data/city" xsi:type="string">Quintin</data> <data name="address/data/country_id" xsi:type="string">France</data> <data name="address/data/region_id" xsi:type="string">Côtes-d'Armor</data> - <data name="address/data/region" xsi:type="string">-</data> <data name="address/data/telephone" xsi:type="string">555-888-111-999</data> - <data name="address/data/fax" xsi:type="string">161-999-8888</data> <data name="address/data/postcode" xsi:type="string">12345</data> <constraint name="Magento\Customer\Test\Constraint\AssertCustomerAddressSuccessSaveMessage" /> <constraint name="Magento\Customer\Test\Constraint\AssertCustomerDefaultAddresses" /> @@ -75,9 +69,7 @@ <data name="address/data/city" xsi:type="string">Culver City</data> <data name="address/data/country_id" xsi:type="string">United States</data> <data name="address/data/region_id" xsi:type="string">California</data> - <data name="address/data/region" xsi:type="string">-</data> <data name="address/data/telephone" xsi:type="string">555-55-555-55</data> - <data name="address/data/fax" xsi:type="string">-</data> <data name="address/data/postcode" xsi:type="string">90230</data> <data name="tag" xsi:type="string">test_type:acceptance_test</data> <constraint name="Magento\Customer\Test\Constraint\AssertCustomerAddressSuccessSaveMessage" /> diff --git a/dev/tests/functional/tests/app/Magento/Directory/Test/Constraint/AssertCurrencyRateSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/Directory/Test/Constraint/AssertCurrencyRateSuccessSaveMessage.php index 3a9f7e82a3943e73ece72d72fbefb3bc2e720ca5..2ce8cb0878d660a9433f756c52e02432a5495215 100644 --- a/dev/tests/functional/tests/app/Magento/Directory/Test/Constraint/AssertCurrencyRateSuccessSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/Directory/Test/Constraint/AssertCurrencyRateSuccessSaveMessage.php @@ -24,7 +24,7 @@ class AssertCurrencyRateSuccessSaveMessage extends AbstractConstraint */ public function processAssert(SystemCurrencyIndex $currencyIndexPage) { - $actualMessage = $currencyIndexPage->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $currencyIndexPage->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Block/Adminhtml/Product/ProductForm.xml b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Block/Adminhtml/Product/ProductForm.xml index 1924503587941faaae969c94b103b69fb2eb541a..57aef81a070fa60cd4ba149a3d16509a29e09698 100644 --- a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Block/Adminhtml/Product/ProductForm.xml +++ b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Block/Adminhtml/Product/ProductForm.xml @@ -8,7 +8,7 @@ <tabs> <downloadable_information> <class>\Magento\Downloadable\Test\Block\Adminhtml\Catalog\Product\Edit\Tab\Downloadable</class> - <selector>#product_info_tabs_downloadable_items</selector> + <selector>#product_info_tabs_product-details</selector> <strategy>css selector</strategy> </downloadable_information> </tabs> diff --git a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Constraint/AbstractAssertTaxRuleIsAppliedToAllPricesDownloadable.php b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Constraint/AbstractAssertTaxRuleIsAppliedToAllPricesDownloadable.php index 20dd5579d0e28a11fb03d5f80fffd6a078c9e0d1..7fd9a4523240ac00dc671189ce795593fa8823b6 100644 --- a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Constraint/AbstractAssertTaxRuleIsAppliedToAllPricesDownloadable.php +++ b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Constraint/AbstractAssertTaxRuleIsAppliedToAllPricesDownloadable.php @@ -66,6 +66,7 @@ abstract class AbstractAssertTaxRuleIsAppliedToAllPricesDownloadable extends Abs $actualPrices = $this->getProductPagePrices($actualPrices); $catalogProductView->getViewBlock()->clickAddToCart(); $catalogProductView->getMessagesBlock()->waitSuccessMessage(); + $checkoutCart->open(); $actualPrices = $this->getCartPrices($product, $actualPrices); $actualPrices = $this->getTotals($actualPrices); //Prices verification diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Adminhtml/Product/Grouped/AssociatedProducts/Search/Grid.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Adminhtml/Product/Grouped/AssociatedProducts/Search/Grid.php index 55b341dc6d3b72224065b2c9b41e3bc05264834a..caa07b91ce7efd9d88bc031c324ca400c69d1d7c 100644 --- a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Adminhtml/Product/Grouped/AssociatedProducts/Search/Grid.php +++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Adminhtml/Product/Grouped/AssociatedProducts/Search/Grid.php @@ -37,7 +37,7 @@ class Grid extends GridInterface * * @var string */ - protected $selectItem = '[data-column=entity_id] input'; + protected $selectItem = '[data-column=entity_ids] input'; /** * Press 'Add Selected Products' button diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Catalog/Product/View.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Catalog/Product/View.php index fd8184a473a931c9b2504de28c5226000842ffd9..b17f829fac64ae116a64996321b7ac980f8f1e51 100644 --- a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Catalog/Product/View.php +++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Catalog/Product/View.php @@ -81,8 +81,7 @@ class View extends ParentView */ public function getOptions(FixtureInterface $product) { - $groupedOptions = $this->getGroupedProductBlock()->getOptions($product); - return ['grouped_options' => $groupedOptions] + parent::getOptions($product); + return ['grouped_options' => $this->getGroupedProductBlock()->getOptions($product)]; } /** diff --git a/dev/tests/functional/tests/app/Magento/Integration/Test/Block/Adminhtml/Integration/IntegrationGrid/ResourcesPopup.php b/dev/tests/functional/tests/app/Magento/Integration/Test/Block/Adminhtml/Integration/IntegrationGrid/ResourcesPopup.php index 9c25994a869647e89195d2c271c6adb4839318b7..2436c28e37cebc723b9d5b2fcb70b9ec26636ac6 100644 --- a/dev/tests/functional/tests/app/Magento/Integration/Test/Block/Adminhtml/Integration/IntegrationGrid/ResourcesPopup.php +++ b/dev/tests/functional/tests/app/Magento/Integration/Test/Block/Adminhtml/Integration/IntegrationGrid/ResourcesPopup.php @@ -23,7 +23,7 @@ class ResourcesPopup extends Form * * @var string */ - protected $allowButtonSelector = '[data-row-dialog="tokens"][role="button"]'; + protected $allowButtonSelector = '[data-row-dialog="tokens"][type="button"]'; /** * Selector for "Reauthorize" button. diff --git a/dev/tests/functional/tests/app/Magento/Integration/Test/Block/Adminhtml/Integration/IntegrationGrid/TokensPopup.php b/dev/tests/functional/tests/app/Magento/Integration/Test/Block/Adminhtml/Integration/IntegrationGrid/TokensPopup.php index e7307befb7482bb4d7774ddc5857989d9731aadc..2fecf03fc4db9effda32c84e59d5b4f0e8c02a1c 100644 --- a/dev/tests/functional/tests/app/Magento/Integration/Test/Block/Adminhtml/Integration/IntegrationGrid/TokensPopup.php +++ b/dev/tests/functional/tests/app/Magento/Integration/Test/Block/Adminhtml/Integration/IntegrationGrid/TokensPopup.php @@ -18,7 +18,7 @@ class TokensPopup extends Form * * @var string */ - protected $doneButtonSelector = '.action-primary[role="button"]'; + protected $doneButtonSelector = '.action-primary[type="button"]'; /** * Click Done button on Integration tokens popup window. diff --git a/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationNameDuplicationErrorMessage.php b/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationNameDuplicationErrorMessage.php index 99613bf462381746c8b9d377ae059439d3c30d60..c3d21a5f0a421ff473cb7633b0ba0f6d271d8186 100644 --- a/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationNameDuplicationErrorMessage.php +++ b/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationNameDuplicationErrorMessage.php @@ -29,7 +29,7 @@ class AssertIntegrationNameDuplicationErrorMessage extends AbstractConstraint Integration $integration ) { $expectedMessage = sprintf(self::ERROR_DUPLICATE_INTEGRATION_NAME, $integration->getName()); - $actualMessage = $integrationIndexPage->getMessagesBlock()->getErrorMessages(); + $actualMessage = $integrationIndexPage->getMessagesBlock()->getErrorMessage(); \PHPUnit_Framework_Assert::assertEquals( $expectedMessage, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationSuccessActivationMessage.php b/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationSuccessActivationMessage.php index ea11e6add5dcbc136dce6349d672232ee044bf1f..f4df100da9484332661344bfb24a1e64af984e43 100644 --- a/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationSuccessActivationMessage.php +++ b/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationSuccessActivationMessage.php @@ -30,7 +30,7 @@ class AssertIntegrationSuccessActivationMessage extends AbstractConstraint Integration $integration ) { $expectedMessage = sprintf(self::SUCCESS_ACTIVATION_MESSAGE, $integration->getName()); - $actualMessage = $integrationIndexPage->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $integrationIndexPage->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( $expectedMessage, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationSuccessDeleteMessage.php b/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationSuccessDeleteMessage.php index 65bc5bb66afabcfe808f4c5d400332055af1fbed..8cefafe433dccb6695dbd0cebf08bfa2b0a25002 100644 --- a/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationSuccessDeleteMessage.php +++ b/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationSuccessDeleteMessage.php @@ -28,7 +28,7 @@ class AssertIntegrationSuccessDeleteMessage extends AbstractConstraint public function processAssert(IntegrationIndex $integrationIndexPage, Integration $integration) { $expectedMessage = sprintf(self::SUCCESS_DELETE_MESSAGE, $integration->getName()); - $actualMessage = $integrationIndexPage->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $integrationIndexPage->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( $expectedMessage, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationSuccessReauthorizeMessage.php b/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationSuccessReauthorizeMessage.php index 485acdb7c321f81dd3f11af50947daa65b495731..71960784c17d593ac6b0666affe598b1eea57c1f 100644 --- a/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationSuccessReauthorizeMessage.php +++ b/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationSuccessReauthorizeMessage.php @@ -34,7 +34,7 @@ class AssertIntegrationSuccessReauthorizeMessage extends AbstractConstraint ) { \PHPUnit_Framework_Assert::assertEquals( sprintf(self::SUCCESS_REAUTHORIZE_MESSAGE, $integration->getName()), - $integrationIndexPage->getMessagesBlock()->getSuccessMessages(), + $integrationIndexPage->getMessagesBlock()->getSuccessMessage(), "Wrong success message is displayed." ); } diff --git a/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationSuccessSaveMessage.php index 02563ed4cc2db74013b04f758bf95adf939b65a8..ca55d860c72267072ce6fbac8f6bd427ae14f9ed 100644 --- a/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationSuccessSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationSuccessSaveMessage.php @@ -35,7 +35,7 @@ class AssertIntegrationSuccessSaveMessage extends AbstractConstraint ? $initialIntegration->getName() : $integration->getName(); $expectedMessage = sprintf(self::SUCCESS_SAVE_MESSAGE, $name); - $actualMessage = $integrationIndexPage->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $integrationIndexPage->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( $expectedMessage, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationSuccessSaveMessageNotPresent.php b/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationSuccessSaveMessageNotPresent.php index ac23f60261388be7ae31bb5bdb1b019c7f4327c9..ab9f15ae7b9d443c60afebaf19f7c53c3534cbfe 100644 --- a/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationSuccessSaveMessageNotPresent.php +++ b/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationSuccessSaveMessageNotPresent.php @@ -26,7 +26,7 @@ class AssertIntegrationSuccessSaveMessageNotPresent extends AbstractConstraint $noSuccessMessage = false; if ($integrationIndex->getMessagesBlock()->isVisible()) { try { - $integrationIndex->getMessagesBlock()->getSuccessMessages(); + $integrationIndex->getMessagesBlock()->getSuccessMessage(); } catch (\PHPUnit_Extensions_Selenium2TestCase_WebDriverException $e) { $noSuccessMessage = true; } diff --git a/dev/tests/functional/tests/app/Magento/Newsletter/Test/Constraint/AssertNewsletterSuccessCreateMessage.php b/dev/tests/functional/tests/app/Magento/Newsletter/Test/Constraint/AssertNewsletterSuccessCreateMessage.php index 0a71b2cc8ae57f78277e7df3e469c1f44bd9f3f2..0a006d9cb5d8162fd62289c790773edef75ce431 100644 --- a/dev/tests/functional/tests/app/Magento/Newsletter/Test/Constraint/AssertNewsletterSuccessCreateMessage.php +++ b/dev/tests/functional/tests/app/Magento/Newsletter/Test/Constraint/AssertNewsletterSuccessCreateMessage.php @@ -29,7 +29,7 @@ class AssertNewsletterSuccessCreateMessage extends AbstractConstraint */ public function processAssert(TemplateIndex $templateIndex) { - $actualMessage = $templateIndex->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $templateIndex->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Reports/Test/Constraint/AbstractAssertInvoiceReportResult.php b/dev/tests/functional/tests/app/Magento/Reports/Test/Constraint/AbstractAssertInvoiceReportResult.php index 0bf83c62bc8a22e1a9d4c797632e680857921a66..c8efec8aec2585d309722d6796d70e84a8cd95c5 100644 --- a/dev/tests/functional/tests/app/Magento/Reports/Test/Constraint/AbstractAssertInvoiceReportResult.php +++ b/dev/tests/functional/tests/app/Magento/Reports/Test/Constraint/AbstractAssertInvoiceReportResult.php @@ -55,7 +55,7 @@ abstract class AbstractAssertInvoiceReportResult extends AbstractConstraint protected function searchInInvoiceReportGrid(array $invoiceReport) { $this->salesInvoiceReport->open(); - $this->salesInvoiceReport->getMessagesBlock()->clickLinkInMessages('notice', 'here'); + $this->salesInvoiceReport->getMessagesBlock()->clickLinkInMessage('notice', 'here'); $this->salesInvoiceReport->getFilterForm()->viewsReport($invoiceReport); $this->salesInvoiceReport->getActionBlock()->showReport(); } diff --git a/dev/tests/functional/tests/app/Magento/Reports/Test/Constraint/AbstractAssertSalesReportResult.php b/dev/tests/functional/tests/app/Magento/Reports/Test/Constraint/AbstractAssertSalesReportResult.php index 16af632c450ab59a2e803b609454d6d832064d32..d4f5bdda3b2f6074bb6519263f70843d114d8c42 100644 --- a/dev/tests/functional/tests/app/Magento/Reports/Test/Constraint/AbstractAssertSalesReportResult.php +++ b/dev/tests/functional/tests/app/Magento/Reports/Test/Constraint/AbstractAssertSalesReportResult.php @@ -39,7 +39,7 @@ abstract class AbstractAssertSalesReportResult extends AbstractConstraint protected function searchInSalesReportGrid(array $salesReport) { $this->salesReportPage->open(); - $this->salesReportPage->getMessagesBlock()->clickLinkInMessages('notice', 'here'); + $this->salesReportPage->getMessagesBlock()->clickLinkInMessage('notice', 'here'); $this->salesReportPage->getFilterBlock()->viewsReport($salesReport); $this->salesReportPage->getActionBlock()->showReport(); } diff --git a/dev/tests/functional/tests/app/Magento/Reports/Test/TestCase/BestsellerProductsReportEntityTest.php b/dev/tests/functional/tests/app/Magento/Reports/Test/TestCase/BestsellerProductsReportEntityTest.php index 1ad8d1b3356f731e3c677d3bced986eabe846662..dc532d027d518fd5990f088304c2a3950aad4ad9 100644 --- a/dev/tests/functional/tests/app/Magento/Reports/Test/TestCase/BestsellerProductsReportEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/Reports/Test/TestCase/BestsellerProductsReportEntityTest.php @@ -64,7 +64,7 @@ class BestsellerProductsReportEntityTest extends Injectable // Preconditions $order->persist(); $this->bestsellers->open(); - $this->bestsellers->getMessagesBlock()->clickLinkInMessages('notice', 'here'); + $this->bestsellers->getMessagesBlock()->clickLinkInMessage('notice', 'here'); // Steps $this->bestsellers->getFilterBlock()->viewsReport($bestsellerReport); diff --git a/dev/tests/functional/tests/app/Magento/Reports/Test/TestCase/SalesInvoiceReportEntityTest.php b/dev/tests/functional/tests/app/Magento/Reports/Test/TestCase/SalesInvoiceReportEntityTest.php index 895f48a9ecac2c44f74b7f3171305e6f40cc327b..1bc9125d8c747158ddcbdee4c6c93b4f11a11816 100644 --- a/dev/tests/functional/tests/app/Magento/Reports/Test/TestCase/SalesInvoiceReportEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/Reports/Test/TestCase/SalesInvoiceReportEntityTest.php @@ -52,7 +52,7 @@ class SalesInvoiceReportEntityTest extends Injectable { // Preconditions $salesInvoiceReport->open(); - $salesInvoiceReport->getMessagesBlock()->clickLinkInMessages('notice', 'here'); + $salesInvoiceReport->getMessagesBlock()->clickLinkInMessage('notice', 'here'); $salesInvoiceReport->getFilterForm()->viewsReport($invoiceReport); $salesInvoiceReport->getActionBlock()->showReport(); $initialInvoiceResult = $salesInvoiceReport->getGridBlock()->getLastResult(); diff --git a/dev/tests/functional/tests/app/Magento/Reports/Test/TestCase/SalesOrderReportEntityTest.php b/dev/tests/functional/tests/app/Magento/Reports/Test/TestCase/SalesOrderReportEntityTest.php index ec395cc8e3fd6a3cb27e4188198d6482fc7de0ae..7dde2c26f72f28b2d6998a175aef9fc5d7a839e3 100644 --- a/dev/tests/functional/tests/app/Magento/Reports/Test/TestCase/SalesOrderReportEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/Reports/Test/TestCase/SalesOrderReportEntityTest.php @@ -69,7 +69,7 @@ class SalesOrderReportEntityTest extends Injectable { // Preconditions $this->salesReport->open(); - $this->salesReport->getMessagesBlock()->clickLinkInMessages('notice', 'here'); + $this->salesReport->getMessagesBlock()->clickLinkInMessage('notice', 'here'); $this->salesReport->getFilterBlock()->viewsReport($salesReport); $this->salesReport->getActionBlock()->showReport(); $initialSalesResult = $this->salesReport->getGridBlock()->getLastResult(); diff --git a/dev/tests/functional/tests/app/Magento/Reports/Test/TestCase/SalesRefundsReportEntityTest.php b/dev/tests/functional/tests/app/Magento/Reports/Test/TestCase/SalesRefundsReportEntityTest.php index f174f4243cd5f2e978ebd2963725c5d9f565a380..f41995615c7583b088f7a704c460ddcd4ccb28ae 100644 --- a/dev/tests/functional/tests/app/Magento/Reports/Test/TestCase/SalesRefundsReportEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/Reports/Test/TestCase/SalesRefundsReportEntityTest.php @@ -68,7 +68,7 @@ class SalesRefundsReportEntityTest extends Injectable { // Preconditions $this->refundsReport->open(); - $this->refundsReport->getMessagesBlock()->clickLinkInMessages('notice', 'here'); + $this->refundsReport->getMessagesBlock()->clickLinkInMessage('notice', 'here'); $this->refundsReport->getFilterBlock()->viewsReport($refundsReport); $this->refundsReport->getActionBlock()->showReport(); $initialRefundsResult = $this->refundsReport->getGridBlock()->getLastResult(); diff --git a/dev/tests/functional/tests/app/Magento/Reports/Test/TestCase/ViewedProductsReportEntityTest.php b/dev/tests/functional/tests/app/Magento/Reports/Test/TestCase/ViewedProductsReportEntityTest.php index 6a75582c9a76c7990bab54c1634aa83037147419..93e38fd650b7bec8268e647ef088076d2e235fad 100644 --- a/dev/tests/functional/tests/app/Magento/Reports/Test/TestCase/ViewedProductsReportEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/Reports/Test/TestCase/ViewedProductsReportEntityTest.php @@ -100,7 +100,7 @@ class ViewedProductsReportEntityTest extends Injectable $productsList = $this->prepareProducts($products); $this->openProducts($productsList, $total); $this->productReportView->open(); - $this->productReportView->getMessagesBlock()->clickLinkInMessages('notice', 'here'); + $this->productReportView->getMessagesBlock()->clickLinkInMessage('notice', 'here'); // Steps $this->productReportView->getFilterBlock()->viewsReport($viewsReport); diff --git a/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductRatingSuccessDeleteMessage.php b/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductRatingSuccessDeleteMessage.php index 55975ed6c27e89febdbe99e0f906d444bd072206..b8d61581e43905a953bbc15426ead2ecaa175f64 100644 --- a/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductRatingSuccessDeleteMessage.php +++ b/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductRatingSuccessDeleteMessage.php @@ -24,7 +24,7 @@ class AssertProductRatingSuccessDeleteMessage extends AbstractConstraint */ public function processAssert(RatingIndex $ratingIndex) { - $actualMessage = $ratingIndex->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $ratingIndex->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_DELETE_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductRatingSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductRatingSuccessSaveMessage.php index c443e4be423e41713febcca715cbbdeef2c1715f..355f480d1cac437a909ec9a52a559386d847de5a 100644 --- a/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductRatingSuccessSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductRatingSuccessSaveMessage.php @@ -24,7 +24,7 @@ class AssertProductRatingSuccessSaveMessage extends AbstractConstraint */ public function processAssert(RatingIndex $ratingIndex) { - $actualMessage = $ratingIndex->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $ratingIndex->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductReviewBackendSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductReviewBackendSuccessSaveMessage.php index f4491856b535a8a2aef8a886ec73818f861e8c94..851cd6baebfbda234ae7379053c931706a5e627f 100644 --- a/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductReviewBackendSuccessSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductReviewBackendSuccessSaveMessage.php @@ -30,7 +30,7 @@ class AssertProductReviewBackendSuccessSaveMessage extends AbstractConstraint { \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, - $reviewIndex->getMessagesBlock()->getSuccessMessages(), + $reviewIndex->getMessagesBlock()->getSuccessMessage(), 'Wrong success message is displayed.' ); } diff --git a/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductReviewMassActionSuccessDeleteMessage.php b/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductReviewMassActionSuccessDeleteMessage.php index cf57f87ba429c9e5774e75163ce75c5403ab5da9..7d7acd1c1b1fb6f6ec5c92042ad4f2bbca2f08dc 100644 --- a/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductReviewMassActionSuccessDeleteMessage.php +++ b/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductReviewMassActionSuccessDeleteMessage.php @@ -38,7 +38,7 @@ class AssertProductReviewMassActionSuccessDeleteMessage extends AbstractConstrai $deleteMessage = sprintf(self::SUCCESS_DELETE_MESSAGE, count($reviews)); \PHPUnit_Framework_Assert::assertEquals( $deleteMessage, - $reviewIndex->getMessagesBlock()->getSuccessMessages(), + $reviewIndex->getMessagesBlock()->getSuccessMessage(), 'Wrong success message is displayed.' ); } diff --git a/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductReviewMassActionSuccessMessage.php b/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductReviewMassActionSuccessMessage.php index af2b135f82f08f080aa13f8b48468612e25e5dbf..8bed779b1ad4e0cef91a51d8826006cd328a0896 100644 --- a/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductReviewMassActionSuccessMessage.php +++ b/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductReviewMassActionSuccessMessage.php @@ -34,7 +34,7 @@ class AssertProductReviewMassActionSuccessMessage extends AbstractConstraint $successMessage = sprintf(self::SUCCESS_MESSAGE, count($reviews)); \PHPUnit_Framework_Assert::assertEquals( $successMessage, - $reviewIndex->getMessagesBlock()->getSuccessMessages(), + $reviewIndex->getMessagesBlock()->getSuccessMessage(), 'Wrong success message is displayed.' ); } diff --git a/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertReviewCreationSuccessMessage.php b/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertReviewCreationSuccessMessage.php index a5b7e25733f420421ffd57e851a0a9fda9ffa063..c582f325845cbdaa18e2f85a4371a1ba0d44fa71 100644 --- a/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertReviewCreationSuccessMessage.php +++ b/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertReviewCreationSuccessMessage.php @@ -27,7 +27,7 @@ class AssertReviewCreationSuccessMessage extends AbstractConstraint */ public function processAssert(CatalogProductView $catalogProductView) { - $actualMessage = $catalogProductView->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $catalogProductView->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertReviewSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertReviewSuccessSaveMessage.php index 6804156e9d589738e0efe3b17a7d9bb8e5fbdae1..a8b1ebe03117763411dfb7e11833ac6278d539ad 100644 --- a/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertReviewSuccessSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertReviewSuccessSaveMessage.php @@ -24,7 +24,7 @@ class AssertReviewSuccessSaveMessage extends AbstractConstraint */ public function processAssert(ReviewIndex $reviewIndex) { - $actualMessage = $reviewIndex->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $reviewIndex->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/CreditMemo/Grid.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/CreditMemo/Grid.php index 0dad1ed84c3b2484dde3660cf131e98f63c9463f..9138b869cad40c889d84eeac1459e569f43ea568 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/CreditMemo/Grid.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/CreditMemo/Grid.php @@ -25,16 +25,16 @@ class Grid extends \Magento\Ui\Test\Block\Adminhtml\DataGrid */ protected $filters = [ 'id' => [ - 'selector' => 'input[name="filters[increment_id]"]', + 'selector' => 'input[name="increment_id"]', ], 'order_id' => [ - 'selector' => 'input[name="filters[order_increment_id]"]', + 'selector' => 'input[name="order_increment_id"]', ], 'grand_total_from' => [ - 'selector' => 'input[name="filters[base_grand_total][from]"]', + 'selector' => 'input[name="base_grand_total[from]"]', ], 'grand_total_to' => [ - 'selector' => 'input[name="filters[base_grand_total][to]"]', + 'selector' => 'input[name="base_grand_total[to]"]', ], ]; } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Invoice/Grid.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Invoice/Grid.php index 7c2761340796d9158f9de223a92c8dffe8e68b68..2a38e9d0d3426840fe551da97f0293446f65157b 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Invoice/Grid.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Invoice/Grid.php @@ -18,16 +18,16 @@ class Grid extends \Magento\Ui\Test\Block\Adminhtml\DataGrid */ protected $filters = [ 'id' => [ - 'selector' => 'input[name="filters[increment_id]"]', + 'selector' => 'input[name="increment_id"]', ], 'order_id' => [ - 'selector' => 'input[name="filters[order_increment_id]"]', + 'selector' => 'input[name="order_increment_id"]', ], 'grand_total_from' => [ - 'selector' => 'input[name="filters[grand_total][from]"]', + 'selector' => 'input[name="grand_total[from]"]', ], 'grand_total_to' => [ - 'selector' => 'input[name="filters[grand_total][to]"]', + 'selector' => 'input[name="grand_total[to]"]', ], ]; diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertInvoiceSuccessCreateMessage.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertInvoiceSuccessCreateMessage.php index ef323a4757680d2052e0bc3e283c946f87bc36b2..561694c682f30f520a12b25a8e5ef1266d58cfb4 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertInvoiceSuccessCreateMessage.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertInvoiceSuccessCreateMessage.php @@ -29,7 +29,7 @@ class AssertInvoiceSuccessCreateMessage extends AbstractConstraint { \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_CREATE_MESSAGE, - $salesOrderView->getMessagesBlock()->getSuccessMessages() + $salesOrderView->getMessagesBlock()->getSuccessMessage() ); } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertInvoiceWithShipmentSuccessMessage.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertInvoiceWithShipmentSuccessMessage.php index 871f4f3616077701974e5c91a224bca7c1b052cd..47d1bd6e6de6316778d36493440c9ee6346a6d65 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertInvoiceWithShipmentSuccessMessage.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertInvoiceWithShipmentSuccessMessage.php @@ -29,7 +29,7 @@ class AssertInvoiceWithShipmentSuccessMessage extends AbstractConstraint { \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, - $salesOrderView->getMessagesBlock()->getSuccessMessages() + $salesOrderView->getMessagesBlock()->getSuccessMessage() ); } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderCancelMassActionFailMessage.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderCancelMassActionFailMessage.php index 45b0e38c91731ea99677a353605816c59e37d1d4..da0c9e71baec2887923c6a499dba2c13a153c29b 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderCancelMassActionFailMessage.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderCancelMassActionFailMessage.php @@ -30,7 +30,7 @@ class AssertOrderCancelMassActionFailMessage extends AbstractConstraint { \PHPUnit_Framework_Assert::assertEquals( self::FAIL_CANCEL_MESSAGE, - $orderIndex->getMessagesBlock()->getErrorMessages() + $orderIndex->getMessagesBlock()->getErrorMessage() ); } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderCancelMassActionSuccessMessage.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderCancelMassActionSuccessMessage.php index 6aa1f29bcbd481b2bb8056a887030817b63420cc..30e2417ac69cca3a601e0117d42184e3934d49e1 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderCancelMassActionSuccessMessage.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderCancelMassActionSuccessMessage.php @@ -31,7 +31,7 @@ class AssertOrderCancelMassActionSuccessMessage extends AbstractConstraint { \PHPUnit_Framework_Assert::assertEquals( sprintf(self::SUCCESS_CANCEL_MESSAGE, $ordersCount), - $orderIndex->getMessagesBlock()->getSuccessMessages() + $orderIndex->getMessagesBlock()->getSuccessMessage() ); } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderCancelSuccessMessage.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderCancelSuccessMessage.php index fe5bc74d63c8d6c3e66e685cfc16dff1ab50f2e3..7672d7296106ab5be56509f5a50c5b680602baa6 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderCancelSuccessMessage.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderCancelSuccessMessage.php @@ -29,7 +29,7 @@ class AssertOrderCancelSuccessMessage extends AbstractConstraint { \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_CANCEL_MESSAGE, - $salesOrderView->getMessagesBlock()->getSuccessMessages() + $salesOrderView->getMessagesBlock()->getSuccessMessage() ); } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderMassOnHoldSuccessMessage.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderMassOnHoldSuccessMessage.php index 1f1508c0c422ae9e061dfcc4cd6f005bbd1a914b..d3ae442b81e92bf33285f8dcc9c4bd173818481a 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderMassOnHoldSuccessMessage.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderMassOnHoldSuccessMessage.php @@ -35,7 +35,7 @@ class AssertOrderMassOnHoldSuccessMessage extends AbstractConstraint { \PHPUnit_Framework_Assert::assertEquals( sprintf(self::SUCCESS_ON_HOLD_MESSAGE, $ordersCount), - $orderIndex->getMessagesBlock()->getSuccessMessages() + $orderIndex->getMessagesBlock()->getSuccessMessage() ); } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderOnHoldFailMessage.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderOnHoldFailMessage.php index f86e9757adf419d706b22e423ab14429ce580a44..7a016fc7be8cade905d5e680b0791d622e7c2e83 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderOnHoldFailMessage.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderOnHoldFailMessage.php @@ -30,7 +30,7 @@ class AssertOrderOnHoldFailMessage extends AbstractConstraint { \PHPUnit_Framework_Assert::assertEquals( self::FAIL_ON_HOLD_MESSAGE, - $orderIndex->getMessagesBlock()->getErrorMessages() + $orderIndex->getMessagesBlock()->getErrorMessage() ); } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderOnHoldSuccessMessage.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderOnHoldSuccessMessage.php index 38d9ff38c11a4c93434c20511d5361444194daca..befab64fec1ed4a51f3631bb6e6f4561793ac081 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderOnHoldSuccessMessage.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderOnHoldSuccessMessage.php @@ -44,7 +44,7 @@ class AssertOrderOnHoldSuccessMessage extends AbstractConstraint \PHPUnit_Framework_Assert::assertEquals( $successOnHoldMessage, - $orderIndex->getMessagesBlock()->getSuccessMessages() + $orderIndex->getMessagesBlock()->getSuccessMessage() ); } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderReleaseFailMessage.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderReleaseFailMessage.php index 26b1fadf28eff554b9c0fcff053e3bf0da886054..ccd34d2cc7492762471edbe00ef77a0cdc7b4fdb 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderReleaseFailMessage.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderReleaseFailMessage.php @@ -30,7 +30,7 @@ class AssertOrderReleaseFailMessage extends AbstractConstraint { \PHPUnit_Framework_Assert::assertEquals( self::FAIL_RELEASE_MESSAGE, - $orderIndex->getMessagesBlock()->getErrorMessages() + $orderIndex->getMessagesBlock()->getErrorMessage() ); } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderReleaseSuccessMessage.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderReleaseSuccessMessage.php index 5ceebe7a11de8d1341dca68553d6e67d882baa92..4de44d6b18a588817c64863ce55a9037eafe9074 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderReleaseSuccessMessage.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderReleaseSuccessMessage.php @@ -31,7 +31,7 @@ class AssertOrderReleaseSuccessMessage extends AbstractConstraint { \PHPUnit_Framework_Assert::assertEquals( sprintf(self::SUCCESS_RELEASE_MESSAGE, $ordersCount), - $orderIndex->getMessagesBlock()->getSuccessMessages() + $orderIndex->getMessagesBlock()->getSuccessMessage() ); } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderStatusDuplicateStatus.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderStatusDuplicateStatus.php index 4ab58755f5ea3ac1d3ae5cafabf22356400407e5..eeed99ee0c85b1071a28801bbb752a7918582a95 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderStatusDuplicateStatus.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderStatusDuplicateStatus.php @@ -25,7 +25,7 @@ class AssertOrderStatusDuplicateStatus extends AbstractConstraint */ public function processAssert(OrderStatusNew $orderStatusNewPage) { - $actualMessage = $orderStatusNewPage->getMessagesBlock()->getErrorMessages(); + $actualMessage = $orderStatusNewPage->getMessagesBlock()->getErrorMessage(); \PHPUnit_Framework_Assert::assertEquals( self::DUPLICATE_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderStatusSuccessAssignMessage.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderStatusSuccessAssignMessage.php index b20839bba30cd73e682177330a2bfb000b4f369e..cd9c9249ac485a2b8064fdb1c6c697f1701d0b2e 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderStatusSuccessAssignMessage.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderStatusSuccessAssignMessage.php @@ -30,7 +30,7 @@ class AssertOrderStatusSuccessAssignMessage extends AbstractConstraint { \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, - $orderStatusIndexPage->getMessagesBlock()->getSuccessMessages() + $orderStatusIndexPage->getMessagesBlock()->getSuccessMessage() ); } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderStatusSuccessCreateMessage.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderStatusSuccessCreateMessage.php index 0e6e63eb9f18507493187c9b7d1311d9455b25d4..f7f63595f92618b0c4238dfb54449be4380a0b4d 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderStatusSuccessCreateMessage.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderStatusSuccessCreateMessage.php @@ -29,7 +29,7 @@ class AssertOrderStatusSuccessCreateMessage extends AbstractConstraint */ public function processAssert(OrderStatusIndex $orderStatusIndexPage) { - $actualMessage = $orderStatusIndexPage->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $orderStatusIndexPage->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderStatusSuccessUnassignMessage.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderStatusSuccessUnassignMessage.php index 1526b66c4a76f56c4366a422b491f892e410160c..9ba8c02a704717ba2a910ad5dc45f66d8b24eed9 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderStatusSuccessUnassignMessage.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderStatusSuccessUnassignMessage.php @@ -30,7 +30,7 @@ class AssertOrderStatusSuccessUnassignMessage extends AbstractConstraint { \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, - $orderStatusIndexPage->getMessagesBlock()->getSuccessMessages() + $orderStatusIndexPage->getMessagesBlock()->getSuccessMessage() ); } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderSuccessCreateMessage.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderSuccessCreateMessage.php index 16315c537bf0f3b775190fd965ca7e762f1c8b17..cc24dcbabcb86005b93eddd4b23db7b5b4665586 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderSuccessCreateMessage.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderSuccessCreateMessage.php @@ -33,7 +33,7 @@ class AssertOrderSuccessCreateMessage extends AbstractConstraint { \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, - $salesOrderView->getMessagesBlock()->getSuccessMessages(), + $salesOrderView->getMessagesBlock()->getSuccessMessage(), 'Wrong success message is displayed.' ); } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertRefundSuccessCreateMessage.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertRefundSuccessCreateMessage.php index 9131c7e77eb032abfa73cb8be40aabbf6a8d012b..b425142c00a692683c48db88b643df029ec9ff78 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertRefundSuccessCreateMessage.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertRefundSuccessCreateMessage.php @@ -29,7 +29,7 @@ class AssertRefundSuccessCreateMessage extends AbstractConstraint { \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_CREATE_MESSAGE, - $salesOrderView->getMessagesBlock()->getSuccessMessages() + $salesOrderView->getMessagesBlock()->getSuccessMessage() ); } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Handler/OrderInjectable/Webapi.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Handler/OrderInjectable/Webapi.php index a1e89784737ae43635a12599a3ff534ed65c86c4..bdfbc3b5d157ddb23c3b4b9fab69c1abf2d27738 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Handler/OrderInjectable/Webapi.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Handler/OrderInjectable/Webapi.php @@ -31,6 +31,7 @@ class Webapi extends AbstractWebapi implements OrderInjectableInterface ], 'country_id' => [ 'United States' => 'US', + 'United Kingdom' => 'GB', ], ]; diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleSuccessDeleteMessage.php b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleSuccessDeleteMessage.php index 2cf4cfb37d7591c67c41fb0a4db26eec88ec3860..be22d6b72bb536097a5e8119def9748b75f70d61 100644 --- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleSuccessDeleteMessage.php +++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleSuccessDeleteMessage.php @@ -28,7 +28,7 @@ class AssertCartPriceRuleSuccessDeleteMessage extends AbstractConstraint */ public function processAssert(PromoQuoteIndex $promoQuoteIndex) { - $actualMessage = $promoQuoteIndex->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $promoQuoteIndex->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_DELETE_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleSuccessSaveMessage.php index 6c0484f965e26af8788efebd59abcd6a6527af5b..278952390ad481c88bfe0c9162dcf29ad02ac74b 100644 --- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleSuccessSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleSuccessSaveMessage.php @@ -24,7 +24,7 @@ class AssertCartPriceRuleSuccessSaveMessage extends AbstractConstraint */ public function processAssert(PromoQuoteIndex $promoQuoteIndex) { - $actualMessage = $promoQuoteIndex->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $promoQuoteIndex->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/CreateSalesRuleEntityTest.xml b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/CreateSalesRuleEntityTest.xml index 4c384ea3f8853265fa0ba9877a56492a871914dc..c75becfb6b45fd1b54a25031a6d17f0d94586d4c 100644 --- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/CreateSalesRuleEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/CreateSalesRuleEntityTest.xml @@ -249,7 +249,7 @@ <data name="salesRule/data/website_ids/0" xsi:type="string">Main Website</data> <data name="salesRule/data/customer_group_ids/0" xsi:type="string">NOT LOGGED IN</data> <data name="salesRule/data/coupon_type" xsi:type="string">No Coupon</data> - <data name="salesRule/data/conditions_serialized" xsi:type="string">{Product attribute combination:[Product Template|is|Default]}</data> + <data name="salesRule/data/conditions_serialized" xsi:type="string">{Product attribute combination:[Attribute Set|is|Default]}</data> <data name="salesRule/data/simple_action" xsi:type="string">Percent of product price discount</data> <data name="salesRule/data/discount_amount" xsi:type="string">50</data> <data name="salesRule/data/apply_to_shipping" xsi:type="string">No</data> diff --git a/dev/tests/functional/tests/app/Magento/Shipping/Test/Block/Adminhtml/Shipment/Grid.php b/dev/tests/functional/tests/app/Magento/Shipping/Test/Block/Adminhtml/Shipment/Grid.php index b77443423773ba216acc535fecde78adae54dd59..d094c186e3108382afd5d1f99df76409650fe124 100644 --- a/dev/tests/functional/tests/app/Magento/Shipping/Test/Block/Adminhtml/Shipment/Grid.php +++ b/dev/tests/functional/tests/app/Magento/Shipping/Test/Block/Adminhtml/Shipment/Grid.php @@ -27,16 +27,16 @@ class Grid extends GridInterface */ protected $filters = [ 'id' => [ - 'selector' => 'input[name="filters[increment_id]"]', + 'selector' => 'input[name="increment_id"]', ], 'order_id' => [ - 'selector' => 'input[name="filters[order_increment_id]"]', + 'selector' => 'input[name="order_increment_id"]', ], 'total_qty_from' => [ - 'selector' => 'input[name="filters[total_qty][from]"]', + 'selector' => 'input[name="total_qty[from]"', ], 'total_qty_to' => [ - 'selector' => 'input[name="filters[total_qty][to]"]', + 'selector' => 'input[name="total_qty][to]"', ], ]; } diff --git a/dev/tests/functional/tests/app/Magento/Shipping/Test/Constraint/AssertShipmentSuccessCreateMessage.php b/dev/tests/functional/tests/app/Magento/Shipping/Test/Constraint/AssertShipmentSuccessCreateMessage.php index f2fcaf7697c5692da1ad95d0698f796316879af3..4c09a5d1ca7da213006d86e9357268d88bb1e08f 100644 --- a/dev/tests/functional/tests/app/Magento/Shipping/Test/Constraint/AssertShipmentSuccessCreateMessage.php +++ b/dev/tests/functional/tests/app/Magento/Shipping/Test/Constraint/AssertShipmentSuccessCreateMessage.php @@ -29,7 +29,7 @@ class AssertShipmentSuccessCreateMessage extends AbstractConstraint { \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, - $salesOrderView->getMessagesBlock()->getSuccessMessages() + $salesOrderView->getMessagesBlock()->getSuccessMessage() ); } diff --git a/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapFailFolderSaveMessage.php b/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapFailFolderSaveMessage.php index da7884f1f17ee3aabcf65809fa4a9bde1d536ada..8f27a314d13b4840c3119afab5ccc32435f3026c 100644 --- a/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapFailFolderSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapFailFolderSaveMessage.php @@ -26,7 +26,7 @@ class AssertSitemapFailFolderSaveMessage extends AbstractConstraint */ public function processAssert(SitemapIndex $sitemapPage, Sitemap $sitemap) { - $actualMessage = $sitemapPage->getMessagesBlock()->getErrorMessages(); + $actualMessage = $sitemapPage->getMessagesBlock()->getErrorMessage(); \PHPUnit_Framework_Assert::assertEquals( sprintf(self::FAIL_FOLDER_MESSAGE, $sitemap->getSitemapPath()), $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapFailPathSaveMessage.php b/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapFailPathSaveMessage.php index 82217a2d958c40b30c02a1c9f56e0c3dbfc6e5f0..8a188d6880eb7f82a1de27045826921b43a994e1 100644 --- a/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapFailPathSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapFailPathSaveMessage.php @@ -26,7 +26,7 @@ class AssertSitemapFailPathSaveMessage extends AbstractConstraint */ public function processAssert(SitemapIndex $sitemapPage, Sitemap $sitemap) { - $actualMessage = $sitemapPage->getMessagesBlock()->getErrorMessages(); + $actualMessage = $sitemapPage->getMessagesBlock()->getErrorMessage(); \PHPUnit_Framework_Assert::assertEquals( sprintf(self::FAIL_PATH_MESSAGE, $sitemap->getSitemapFilename()), $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapSuccessDeleteMessage.php b/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapSuccessDeleteMessage.php index 0209c3f0a7659e98be796329a23705070ff61edb..f02734b53949517da91d125039602bce6c820fc8 100644 --- a/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapSuccessDeleteMessage.php +++ b/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapSuccessDeleteMessage.php @@ -24,7 +24,7 @@ class AssertSitemapSuccessDeleteMessage extends AbstractConstraint */ public function processAssert(SitemapIndex $sitemapPage) { - $actualMessage = $sitemapPage->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $sitemapPage->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_DELETE_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapSuccessGenerateMessage.php b/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapSuccessGenerateMessage.php index 77e58ce48e148638de09e08d987d87efd097bc31..b8178bf6b85ac1e5e97a1ae5ad88111db5d580a5 100644 --- a/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapSuccessGenerateMessage.php +++ b/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapSuccessGenerateMessage.php @@ -32,7 +32,7 @@ class AssertSitemapSuccessGenerateMessage extends AbstractConstraint SitemapIndex $sitemapPage, Sitemap $sitemap ) { - $actualMessage = $sitemapPage->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $sitemapPage->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( sprintf(self::SUCCESS_GENERATE_MESSAGE, $sitemap->getSitemapFilename()), $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapSuccessSaveMessage.php index e0e4efc80694dfa9901040e5b5ffec1610424782..e25e8eec6bdbbe10184d52e37db04e7b7e6920a3 100644 --- a/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapSuccessSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapSuccessSaveMessage.php @@ -24,7 +24,7 @@ class AssertSitemapSuccessSaveMessage extends AbstractConstraint */ public function processAssert(SitemapIndex $sitemapPage) { - $actualMessage = $sitemapPage->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $sitemapPage->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertStoreGroupSuccessDeleteMessage.php b/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertStoreGroupSuccessDeleteMessage.php index ea9be6f761b102f359cc1edd0a5ee16564c077f2..d74e39c143582c62bb18100953230a8dac75b1c2 100644 --- a/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertStoreGroupSuccessDeleteMessage.php +++ b/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertStoreGroupSuccessDeleteMessage.php @@ -30,7 +30,7 @@ class AssertStoreGroupSuccessDeleteMessage extends AbstractConstraint { \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_DELETE_MESSAGE, - $storeIndex->getMessagesBlock()->getSuccessMessages(), + $storeIndex->getMessagesBlock()->getSuccessMessage(), 'Wrong success delete message is displayed.' ); } diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertStoreGroupSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertStoreGroupSuccessSaveMessage.php index 5be639d9d9279bca28978d4af48012a9ab2722a8..f9d2aafc57a6ea4cb7d3ffbab491be53b7de6d33 100644 --- a/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertStoreGroupSuccessSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertStoreGroupSuccessSaveMessage.php @@ -30,7 +30,7 @@ class AssertStoreGroupSuccessSaveMessage extends AbstractConstraint { \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, - $storeIndex->getMessagesBlock()->getSuccessMessages(), + $storeIndex->getMessagesBlock()->getSuccessMessage(), 'Wrong success message is displayed.' ); } diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertStoreSuccessDeleteMessage.php b/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertStoreSuccessDeleteMessage.php index 82dd5459f8ba49c1d9e98ce71cd79d002438b07f..957357f71e5e55a055f6beda12fc65c822bfb35d 100644 --- a/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertStoreSuccessDeleteMessage.php +++ b/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertStoreSuccessDeleteMessage.php @@ -30,7 +30,7 @@ class AssertStoreSuccessDeleteMessage extends AbstractConstraint { \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_DELETE_MESSAGE, - $storeIndex->getMessagesBlock()->getSuccessMessages(), + $storeIndex->getMessagesBlock()->getSuccessMessage(), 'Wrong success delete message is displayed.' ); } diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertStoreSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertStoreSuccessSaveMessage.php index cf467e88cb587ebfe66c9c9049448a8eb1208b67..ac66a3412b7a499bf46dcbb1d977e205fcd98cfc 100644 --- a/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertStoreSuccessSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertStoreSuccessSaveMessage.php @@ -30,7 +30,7 @@ class AssertStoreSuccessSaveMessage extends AbstractConstraint { \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, - $storeIndex->getMessagesBlock()->getSuccessMessages(), + $storeIndex->getMessagesBlock()->getSuccessMessage(), 'Wrong success message is displayed.' ); } diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertWebsiteSuccessDeleteMessage.php b/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertWebsiteSuccessDeleteMessage.php index 11d54478e8df7fbb28c202d1b62fffb54a59e162..076d7daaa32616977e2a7edaff83673f7ce70492 100644 --- a/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertWebsiteSuccessDeleteMessage.php +++ b/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertWebsiteSuccessDeleteMessage.php @@ -30,7 +30,7 @@ class AssertWebsiteSuccessDeleteMessage extends AbstractConstraint { \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_DELETE_MESSAGE, - $storeIndex->getMessagesBlock()->getSuccessMessages(), + $storeIndex->getMessagesBlock()->getSuccessMessage(), 'Wrong success delete message is displayed.' ); } diff --git a/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertWebsiteSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertWebsiteSuccessSaveMessage.php index 2078e611262bc4022a42a8f0d37fc09d8534dbaf..60dde78e3eb59139ec70f184be88361a91943f3e 100644 --- a/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertWebsiteSuccessSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/Store/Test/Constraint/AssertWebsiteSuccessSaveMessage.php @@ -30,7 +30,7 @@ class AssertWebsiteSuccessSaveMessage extends AbstractConstraint { \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, - $storeIndex->getMessagesBlock()->getSuccessMessages(), + $storeIndex->getMessagesBlock()->getSuccessMessage(), 'Wrong success message is displayed.' ); } diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateSuccessDeleteMessage.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateSuccessDeleteMessage.php index f956e5c82b97bd87c08c3fec8f158fd995dfb9cb..f8ae7822c5783859ecd0a255a56c4ba7249c5cec 100644 --- a/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateSuccessDeleteMessage.php +++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateSuccessDeleteMessage.php @@ -24,7 +24,7 @@ class AssertTaxRateSuccessDeleteMessage extends AbstractConstraint */ public function processAssert(TaxRateIndex $taxRateIndex) { - $actualMessage = $taxRateIndex->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $taxRateIndex->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_DELETE_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateSuccessSaveMessage.php index 165e9a7aeb65f2be2fd5a9a13903e6e793fae7ee..79a9b63ea942da615336b45dd42d04ddf24e6bb4 100644 --- a/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateSuccessSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateSuccessSaveMessage.php @@ -24,7 +24,7 @@ class AssertTaxRateSuccessSaveMessage extends AbstractConstraint */ public function processAssert(TaxRateIndex $taxRateIndexPage) { - $actualMessage = $taxRateIndexPage->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $taxRateIndexPage->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRuleSuccessDeleteMessage.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRuleSuccessDeleteMessage.php index 44c3367d48e34c54f0f4b534f4f34c7600190691..5a7872a6373c2c5ca03ee0a43f8e0c10d37f5893 100644 --- a/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRuleSuccessDeleteMessage.php +++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRuleSuccessDeleteMessage.php @@ -24,7 +24,7 @@ class AssertTaxRuleSuccessDeleteMessage extends AbstractConstraint */ public function processAssert(TaxRuleIndex $taxRuleIndex) { - $actualMessage = $taxRuleIndex->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $taxRuleIndex->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_DELETE_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRuleSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRuleSuccessSaveMessage.php index 73e32f4f8b151902bef7d3702bc9462b25080852..8234673ee1cdefdc70911cbdfd531bba2f96fe62 100644 --- a/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRuleSuccessSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRuleSuccessSaveMessage.php @@ -28,7 +28,7 @@ class AssertTaxRuleSuccessSaveMessage extends AbstractConstraint */ public function processAssert(TaxRuleIndex $taxRuleIndex) { - $actualMessage = $taxRuleIndex->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $taxRuleIndex->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/ApplyTaxBasedOnVatIdTest.xml b/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/ApplyTaxBasedOnVatIdTest.xml index c54201720c84b9766e0fb00f52f673e9ee4ec7f6..52dea03715a3677a424eddae35e4a7bf4eee26ec 100644 --- a/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/ApplyTaxBasedOnVatIdTest.xml +++ b/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/ApplyTaxBasedOnVatIdTest.xml @@ -19,7 +19,7 @@ <data name="customerGroup" xsi:type="string">valid_intra_union_group</data> <data name="cart/data/subtotal" xsi:type="string">10</data> <data name="cart/data/tax_amount" xsi:type="string">2</data> - <data name="cart/data/grand_total" xsi:type="string">12</data> + <data name="cart/data/grand_total" xsi:type="string">17</data> <data name="prices" xsi:type="array"> <item name="grandTotal" xsi:type="string">17</item> </data> diff --git a/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/DataGrid.php b/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/DataGrid.php index 5757bf446e6eecf0bf13ea8c2e9253e3166ae137..13545de8f49237b9ec856cdd8426e59e3efa877a 100644 --- a/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/DataGrid.php +++ b/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/DataGrid.php @@ -128,6 +128,20 @@ class DataGrid extends Grid */ protected $alertModal = '._show[data-role=modal]'; + /** + * Locator for 'Sort' link. + * + * @var string + */ + protected $sortLink = "//th[contains(@class, '%s')]/span[contains(text(), '%s')]"; + + /** + * Current page input. + * + * @var string + */ + protected $currentPage = '#pageCurrent'; + /** * Clear all applied Filters. * @@ -239,23 +253,23 @@ class DataGrid extends Grid if ($this->_rootElement->find($this->noRecords)->isVisible()) { return; } - if (!is_array($action)) { - $action = [$action => '-']; - } - foreach ($items as $item) { - $this->searchAndSelect($item); - } + $this->selectItems($items); if ($massActionSelection) { $this->_rootElement->find($this->massActionToggleButton)->click(); $this->_rootElement ->find(sprintf($this->massActionToggleList, $massActionSelection), Locator::SELECTOR_XPATH) ->click(); } - $actionType = key($action); + $actionType = is_array($action) ? key($action) : $action; $this->_rootElement->find($this->massActionButton)->click(); $this->_rootElement ->find(sprintf($this->massActionToggleList, $actionType), Locator::SELECTOR_XPATH) ->click(); + if (is_array($action)) { + $this->_rootElement + ->find(sprintf($this->massActionToggleList, end($action)), Locator::SELECTOR_XPATH) + ->click(); + } if ($acceptAlert) { $element = $this->browser->find($this->alertModal); /** @var \Magento\Ui\Test\Block\Adminhtml\Modal $modal */ @@ -264,6 +278,49 @@ class DataGrid extends Grid } } + /** + * Select items without using grid search. + * + * @param array $items + * @return void + * @throws \Exception + */ + protected function selectItems(array $items) + { + $this->sortGridByField('ID'); + foreach ($items as $item) { + $this->_rootElement->find($this->currentPage)->setValue(''); + $this->waitLoader(); + $selectItem = $this->getRow($item)->find($this->selectItem); + do { + if ($selectItem->isVisible()) { + $selectItem->click(); + break; + } + } while ($this->nextPage()); + if (!$selectItem->isVisible()) { + throw new \Exception('Searched item was not found.'); + } + } + } + + /** + * Sort grid by field. + * + * @param string $field + * @param string $sort + * @return void + */ + public function sortGridByField($field, $sort = "desc") + { + $reverseSort = $sort == 'desc' ? 'asc' : 'desc'; + $sortBlock = $this->_rootElement->find(sprintf($this->sortLink, $reverseSort, $field), Locator::SELECTOR_XPATH); + if ($sortBlock->isVisible()) { + $sortBlock->click(); + $this->waitLoader(); + } + } + /** * @param string $columnLabel */ diff --git a/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/Modal.php b/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/Modal.php index 96ed46ae296cd0ec50cb90259929c9d87d068e5d..f2ecfee702bdf66380b8ce8a7a3a9a6af5e9222f 100644 --- a/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/Modal.php +++ b/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/Modal.php @@ -41,6 +41,13 @@ class Modal extends Block */ protected $inputFieldSelector = '[data-role="promptField"]'; + /** + * Modal overlay selector. + * + * @var string + */ + protected $modalOverlay = '.modals-overlay'; + /** * Press OK on an alert, confirm, prompt a dialog. * @@ -91,4 +98,18 @@ class Modal extends Block { $this->_rootElement->find($this->inputFieldSelector)->setValue($text); } + + /** + * Wait until modal window will disapper. + * + * @return void + */ + public function waitModalWindowToDisappear() + { + $this->browser->waitUntil( + function () { + return $this->browser->find($this->modalOverlay)->isVisible() == false ? true : null; + } + ); + } } diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteDeletedMessage.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteDeletedMessage.php index ac453e2ebdc40642ed3d948c5663aaec5bd9d9a7..c27afd627bfb8250014f6142b13b2a31afdda6a7 100644 --- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteDeletedMessage.php +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteDeletedMessage.php @@ -28,7 +28,7 @@ class AssertUrlRewriteDeletedMessage extends AbstractConstraint */ public function processAssert(UrlRewriteIndex $index) { - $actualMessage = $index->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $index->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_DELETE_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteSaveMessage.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteSaveMessage.php index 97d8c67ce5e53fe5a918ef914a5e8f9e258b1054..5d3e4a547d5f613cb57bf1a64cb800b71aac28ac 100644 --- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteSaveMessage.php @@ -25,7 +25,7 @@ class AssertUrlRewriteSaveMessage extends AbstractConstraint */ public function processAssert(UrlRewriteIndex $index) { - $actualMessage = $index->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $index->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Block/Adminhtml/Role/Tab/User/Grid.php b/dev/tests/functional/tests/app/Magento/User/Test/Block/Adminhtml/Role/Tab/User/Grid.php index ab1ea537ea6431ed7aaa7fd9b5a352b6b5bf0edc..ec0c365b817127c7f08b869a2e531d7090336e9c 100644 --- a/dev/tests/functional/tests/app/Magento/User/Test/Block/Adminhtml/Role/Tab/User/Grid.php +++ b/dev/tests/functional/tests/app/Magento/User/Test/Block/Adminhtml/Role/Tab/User/Grid.php @@ -30,5 +30,5 @@ class Grid extends AbstractGrid * * @var string */ - protected $selectItem = '.col-in_role_users > input'; + protected $selectItem = '.col-in_role_users input'; } diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertAccessTokensErrorRevokeMessage.php b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertAccessTokensErrorRevokeMessage.php index b8110526b398ecc7a2697da3dd0aac72c4881801..58920c5edeec0612f80af4e4759f7373889c51de 100644 --- a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertAccessTokensErrorRevokeMessage.php +++ b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertAccessTokensErrorRevokeMessage.php @@ -30,7 +30,7 @@ class AssertAccessTokensErrorRevokeMessage extends AbstractConstraint { \PHPUnit_Framework_Assert::assertEquals( self::ERROR_MESSAGE, - $userEdit->getMessagesBlock()->getErrorMessages() + $userEdit->getMessagesBlock()->getErrorMessage() ); } diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertImpossibleDeleteYourOwnAccount.php b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertImpossibleDeleteYourOwnAccount.php index 89169bcf80ef342c0cfb63250e486c3cfa793ffe..b66e275b4795c6e24c4c11bf5058c6b0d16dcd6e 100644 --- a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertImpossibleDeleteYourOwnAccount.php +++ b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertImpossibleDeleteYourOwnAccount.php @@ -24,7 +24,7 @@ class AssertImpossibleDeleteYourOwnAccount extends AbstractConstraint */ public function processAssert(UserEdit $userEdit) { - $errorMessage = $userEdit->getMessagesBlock()->getErrorMessages(); + $errorMessage = $userEdit->getMessagesBlock()->getErrorMessage(); \PHPUnit_Framework_Assert::assertEquals( self::ERROR_MESSAGE, $errorMessage, diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertImpossibleDeleteYourOwnRole.php b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertImpossibleDeleteYourOwnRole.php index c469966dc940a9b08cd70f1a051881c3d2495321..06d525e2b4a666ba0b6cb5237c19b61207a32b49 100644 --- a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertImpossibleDeleteYourOwnRole.php +++ b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertImpossibleDeleteYourOwnRole.php @@ -24,7 +24,7 @@ class AssertImpossibleDeleteYourOwnRole extends AbstractConstraint */ public function processAssert(UserRoleEditRole $rolePage) { - $errorMessage = $rolePage->getMessagesBlock()->getErrorMessages(); + $errorMessage = $rolePage->getMessagesBlock()->getErrorMessage(); \PHPUnit_Framework_Assert::assertEquals( self::ERROR_MESSAGE, $errorMessage, diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertRoleSuccessDeleteMessage.php b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertRoleSuccessDeleteMessage.php index 943acd3b521fcc50631d1c6310c82f77138297a2..8d828ceb237b860ed2d8c8cfb6a98e2928b02a0e 100644 --- a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertRoleSuccessDeleteMessage.php +++ b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertRoleSuccessDeleteMessage.php @@ -24,7 +24,7 @@ class AssertRoleSuccessDeleteMessage extends AbstractConstraint */ public function processAssert(UserRoleIndex $rolePage) { - $successMessage = $rolePage->getMessagesBlock()->getSuccessMessages(); + $successMessage = $rolePage->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_DELETE_MESSAGE, $successMessage, diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertRoleSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertRoleSuccessSaveMessage.php index 4487b76954a4f6b6d5ea4974bf30aed9712cee72..402234f7b48a36e3b267a29c93beaab13fa9aeec 100644 --- a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertRoleSuccessSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertRoleSuccessSaveMessage.php @@ -24,7 +24,7 @@ class AssertRoleSuccessSaveMessage extends AbstractConstraint */ public function processAssert(UserRoleIndex $rolePage) { - $successMessage = $rolePage->getMessagesBlock()->getSuccessMessages(); + $successMessage = $rolePage->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, $successMessage, diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserDuplicateMessage.php b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserDuplicateMessage.php index 66e1d6b432aa6447126165e1002b939895cdc8b0..99c6e89ad0a35e7194f2bc8e929f4e63fa5f9dcb 100644 --- a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserDuplicateMessage.php +++ b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserDuplicateMessage.php @@ -24,7 +24,7 @@ class AssertUserDuplicateMessage extends AbstractConstraint */ public function processAssert(UserEdit $userEdit) { - $failedMessage = $userEdit->getMessagesBlock()->getErrorMessages(); + $failedMessage = $userEdit->getMessagesBlock()->getErrorMessage(); \PHPUnit_Framework_Assert::assertEquals( self::ERROR_MESSAGE, $failedMessage, diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserFailedLoginByPermissionMessage.php b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserFailedLoginByPermissionMessage.php index db943e911a3d0c3c695cecd9e7372f4e86ebf869..2454f53eb0f6a0d6e3793e51dc387aae35a10dfe 100644 --- a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserFailedLoginByPermissionMessage.php +++ b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserFailedLoginByPermissionMessage.php @@ -32,7 +32,7 @@ class AssertUserFailedLoginByPermissionMessage extends AbstractConstraint \PHPUnit_Framework_Assert::assertEquals( self::FAILED_LOGIN_MESSAGE, - $adminAuth->getMessagesBlock()->getErrorMessages(), + $adminAuth->getMessagesBlock()->getErrorMessage(), 'Message "' . self::FAILED_LOGIN_MESSAGE . '" is not visible.' ); } diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserFailedLoginMessage.php b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserFailedLoginMessage.php index e01aa9a9cd0cdfe0af16c3c74c6f32cfdbe8f669..c57af1f5abb1a186b2c6136505812161a1aa0d1a 100644 --- a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserFailedLoginMessage.php +++ b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserFailedLoginMessage.php @@ -34,7 +34,7 @@ class AssertUserFailedLoginMessage extends AbstractConstraint \PHPUnit_Framework_Assert::assertEquals( self::FAILED_LOGIN_MESSAGE, - $adminAuth->getMessagesBlock()->getErrorMessages(), + $adminAuth->getMessagesBlock()->getErrorMessage(), 'Message "' . self::FAILED_LOGIN_MESSAGE . '" is not visible.' ); } diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserInvalidEmailHostnameMessage.php b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserInvalidEmailHostnameMessage.php index 74af3f80cd78f038dcd04a1e76d4a23dd0013fe3..117857a23fc2352dcb6c386ed83c6f276d3db8c8 100644 --- a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserInvalidEmailHostnameMessage.php +++ b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserInvalidEmailHostnameMessage.php @@ -33,7 +33,7 @@ class AssertUserInvalidEmailHostnameMessage extends AbstractConstraint $email = $user->getEmail(); $hostname = substr($email, strpos($email, '@')+1); $expectedMessage = sprintf(self::ERROR_MESSAGE, $hostname, $email); - $actualMessage = $userEdit->getMessagesBlock()->getErrorMessages(); + $actualMessage = $userEdit->getMessagesBlock()->getErrorMessage(); \PHPUnit_Framework_Assert::assertEquals( $expectedMessage, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserInvalidEmailMessage.php b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserInvalidEmailMessage.php index 431b9f13c71cc8838efebd393e61f2b311276733..f9c878f6889a98e16b770f931989a31e9392cf9f 100644 --- a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserInvalidEmailMessage.php +++ b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserInvalidEmailMessage.php @@ -31,7 +31,7 @@ class AssertUserInvalidEmailMessage extends AbstractConstraint public function processAssert(UserEdit $userEdit, User $user) { $expectedMessage = sprintf(self::ERROR_MESSAGE, $user->getEmail()); - $actualMessage = $userEdit->getMessagesBlock()->getErrorMessages(); + $actualMessage = $userEdit->getMessagesBlock()->getErrorMessage(); \PHPUnit_Framework_Assert::assertEquals( $expectedMessage, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserSuccessDeleteMessage.php b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserSuccessDeleteMessage.php index c6f7e9e69495c0d3530e7db93cd670b00490a279..a6ba344c97fb76200f62a6069b1dc0a9cbd98701 100644 --- a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserSuccessDeleteMessage.php +++ b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserSuccessDeleteMessage.php @@ -28,7 +28,7 @@ class AssertUserSuccessDeleteMessage extends AbstractConstraint */ public function processAssert(UserIndex $userIndex) { - $successMessage = $userIndex->getMessagesBlock()->getSuccessMessages(); + $successMessage = $userIndex->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, $successMessage, diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserSuccessSaveMessage.php index e8f4e5f55715a9968559d193c3c49c5e12cec5a3..8cf031d5694da7ca29d553d4ba72465bb4c75a14 100644 --- a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserSuccessSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserSuccessSaveMessage.php @@ -24,7 +24,7 @@ class AssertUserSuccessSaveMessage extends AbstractConstraint */ public function processAssert(UserIndex $userIndex) { - $successMessage = $userIndex->getMessagesBlock()->getSuccessMessages(); + $successMessage = $userIndex->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, $successMessage, diff --git a/dev/tests/functional/tests/app/Magento/Variable/Test/Constraint/AssertCustomVariableSuccessDeleteMessage.php b/dev/tests/functional/tests/app/Magento/Variable/Test/Constraint/AssertCustomVariableSuccessDeleteMessage.php index 596577190cab66e24fd31bac364975fdbcc263b2..d4a73859e76cb28fb4d397443b6876ef025fc614 100644 --- a/dev/tests/functional/tests/app/Magento/Variable/Test/Constraint/AssertCustomVariableSuccessDeleteMessage.php +++ b/dev/tests/functional/tests/app/Magento/Variable/Test/Constraint/AssertCustomVariableSuccessDeleteMessage.php @@ -24,7 +24,7 @@ class AssertCustomVariableSuccessDeleteMessage extends AbstractConstraint */ public function processAssert(SystemVariableIndex $systemVariableIndexPage) { - $actualMessage = $systemVariableIndexPage->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $systemVariableIndexPage->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_DELETE_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Variable/Test/Constraint/AssertCustomVariableSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/Variable/Test/Constraint/AssertCustomVariableSuccessSaveMessage.php index dd723c012ab74497e12a3fcb10f853d8ed8e49f7..67117ed950bacaefb62f16544f8f9a4a4a400421 100644 --- a/dev/tests/functional/tests/app/Magento/Variable/Test/Constraint/AssertCustomVariableSuccessSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/Variable/Test/Constraint/AssertCustomVariableSuccessSaveMessage.php @@ -24,7 +24,7 @@ class AssertCustomVariableSuccessSaveMessage extends AbstractConstraint */ public function processAssert(SystemVariableIndex $systemVariableIndexPage) { - $actualMessage = $systemVariableIndexPage->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $systemVariableIndexPage->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_SAVE_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Weee/Test/Repository/ConfigData.xml b/dev/tests/functional/tests/app/Magento/Weee/Test/Repository/ConfigData.xml index c78a826e8500caf6b191ff38d58a0c84d7d7c76e..95d06f6d4074a56ab81a458d552c424ab698bd47 100644 --- a/dev/tests/functional/tests/app/Magento/Weee/Test/Repository/ConfigData.xml +++ b/dev/tests/functional/tests/app/Magento/Weee/Test/Repository/ConfigData.xml @@ -92,19 +92,19 @@ <field name="tax/weee/display_list" xsi:type="array"> <item name="scope" xsi:type="string">tax</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string">Excluding FPT, FPT description, final price</item> + <item name="label" xsi:type="string">Excluding FPT. Including FPT description and final price</item> <item name="value" xsi:type="number">2</item> </field> <field name="tax/weee/display" xsi:type="array"> <item name="scope" xsi:type="string">tax</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string">Excluding FPT, FPT description, final price</item> + <item name="label" xsi:type="string">Excluding FPT. Including FPT description and final price</item> <item name="value" xsi:type="number">2</item> </field> <field name="tax/weee/display_sales" xsi:type="array"> <item name="scope" xsi:type="string">tax</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string">Excluding FPT, FPT description, final price</item> + <item name="label" xsi:type="string">Excluding FPT. Including FPT description and final price</item> <item name="value" xsi:type="number">2</item> </field> <field name="tax/weee/apply_vat" xsi:type="array"> @@ -242,19 +242,19 @@ <field name="tax/weee/display_list" xsi:type="array"> <item name="scope" xsi:type="string">tax</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string">Excluding FPT, FPT description, final price</item> + <item name="label" xsi:type="string">Excluding FPT. Including FPT description and final price</item> <item name="value" xsi:type="number">2</item> </field> <field name="tax/weee/display" xsi:type="array"> <item name="scope" xsi:type="string">tax</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string">Excluding FPT, FPT description, final price</item> + <item name="label" xsi:type="string">Excluding FPT. Including FPT description and final price</item> <item name="value" xsi:type="number">2</item> </field> <field name="tax/weee/display_sales" xsi:type="array"> <item name="scope" xsi:type="string">tax</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string">Excluding FPT, FPT description, final price</item> + <item name="label" xsi:type="string">Excluding FPT. Including FPT description and final price</item> <item name="value" xsi:type="number">2</item> </field> <field name="tax/weee/apply_vat" xsi:type="array"> @@ -392,19 +392,19 @@ <field name="tax/weee/display_list" xsi:type="array"> <item name="scope" xsi:type="string">tax</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string">Excluding FPT, FPT description, final price</item> + <item name="label" xsi:type="string">Excluding FPT. Including FPT description and final price</item> <item name="value" xsi:type="number">2</item> </field> <field name="tax/weee/display" xsi:type="array"> <item name="scope" xsi:type="string">tax</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string">Excluding FPT, FPT description, final price</item> + <item name="label" xsi:type="string">Excluding FPT. Including FPT description and final price</item> <item name="value" xsi:type="number">2</item> </field> <field name="tax/weee/display_sales" xsi:type="array"> <item name="scope" xsi:type="string">tax</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string">Excluding FPT, FPT description, final price</item> + <item name="label" xsi:type="string">Excluding FPT. Including FPT description and final price</item> <item name="value" xsi:type="number">2</item> </field> <field name="tax/weee/apply_vat" xsi:type="array"> @@ -467,19 +467,19 @@ <field name="tax/weee/display_list" xsi:type="array"> <item name="scope" xsi:type="string">tax</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string">Excluding FPT, FPT description, final price</item> + <item name="label" xsi:type="string">Excluding FPT. Including FPT description and final price</item> <item name="value" xsi:type="number">2</item> </field> <field name="tax/weee/display" xsi:type="array"> <item name="scope" xsi:type="string">tax</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string">Excluding FPT, FPT description, final price</item> + <item name="label" xsi:type="string">Excluding FPT. Including FPT description and final price</item> <item name="value" xsi:type="number">2</item> </field> <field name="tax/weee/display_sales" xsi:type="array"> <item name="scope" xsi:type="string">tax</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string">Excluding FPT, FPT description, final price</item> + <item name="label" xsi:type="string">Excluding FPT. Including FPT description and final price</item> <item name="value" xsi:type="number">2</item> </field> <field name="tax/weee/apply_vat" xsi:type="array"> @@ -542,19 +542,19 @@ <field name="tax/weee/display_list" xsi:type="array"> <item name="scope" xsi:type="string">tax</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string">Excluding FPT, FPT description, final price</item> + <item name="label" xsi:type="string">Excluding FPT. Including FPT description and final price</item> <item name="value" xsi:type="number">2</item> </field> <field name="tax/weee/display" xsi:type="array"> <item name="scope" xsi:type="string">tax</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string">Excluding FPT, FPT description, final price</item> + <item name="label" xsi:type="string">Excluding FPT. Including FPT description and final price</item> <item name="value" xsi:type="number">2</item> </field> <field name="tax/weee/display_sales" xsi:type="array"> <item name="scope" xsi:type="string">tax</item> <item name="scope_id" xsi:type="number">1</item> - <item name="label" xsi:type="string">Excluding FPT, FPT description, final price</item> + <item name="label" xsi:type="string">Excluding FPT. Including FPT description and final price</item> <item name="value" xsi:type="number">2</item> </field> <field name="tax/weee/apply_vat" xsi:type="array"> diff --git a/dev/tests/functional/tests/app/Magento/Weee/Test/TestCase/CreateTaxWithFptTest.php b/dev/tests/functional/tests/app/Magento/Weee/Test/TestCase/CreateTaxWithFptTest.php index 1bdedf647cb0b99bd7ccfff33cd1ed1782eec882..ce13fcc374129d215af42f18ccd4cb4c8423ba5a 100644 --- a/dev/tests/functional/tests/app/Magento/Weee/Test/TestCase/CreateTaxWithFptTest.php +++ b/dev/tests/functional/tests/app/Magento/Weee/Test/TestCase/CreateTaxWithFptTest.php @@ -24,15 +24,15 @@ use Magento\Mtf\TestCase\Injectable; * 7. Go to Stores > Attributes > Product and add new attribute. * 8. Select Fixed Product Tax type and fill attribute label. * 9. Save attribute. - * 10. Go to Stores > Attributes > Product Template. - * 11. Add new product template based on default. + * 10. Go to Stores > Attributes > Attribute Set. + * 11. Add new attribute set based on default. * 12. Add created FPT attribute to Product Details group and fill set name. * 13. Save attribute set. * * Steps: * 1. Go to Products > Catalog. * 2. Add new product. - * 3. Select created product template. + * 3. Select created attribute set. * 4. Fill data according to dataset. * 5. Save product. * 6. Go to Stores > Configuration. @@ -69,12 +69,12 @@ class CreateTaxWithFptTest extends Injectable $this->fixtureFactory = $fixtureFactory; $customer = $fixtureFactory->createByCode('customer', ['dataset' => 'johndoe_with_addresses']); $customer->persist(); - $productTemplate = $this->fixtureFactory + $attributeSet = $this->fixtureFactory ->createByCode('catalogAttributeSet', ['dataset' => 'custom_attribute_set_with_fpt']); - $productTemplate->persist(); + $attributeSet->persist(); return [ 'customer' => $customer, - 'productTemplate' => $productTemplate + 'attributeSet' => $attributeSet ]; } @@ -97,7 +97,7 @@ class CreateTaxWithFptTest extends Injectable * * @param string $configData * @param Customer $customer - * @param CatalogAttributeSet $productTemplate + * @param CatalogAttributeSet $attributeSet * @param array $productData * @return array */ @@ -105,12 +105,12 @@ class CreateTaxWithFptTest extends Injectable $productData, $configData, Customer $customer, - CatalogAttributeSet $productTemplate + CatalogAttributeSet $attributeSet ) { $this->fixtureFactory->createByCode('taxRule', ['dataset' => 'tax_rule_default'])->persist(); $product = $this->fixtureFactory->createByCode( 'catalogProductSimple', - ['dataset' => $productData, 'data' => ['attribute_set_id' => ['attribute_set' => $productTemplate]]] + ['dataset' => $productData, 'data' => ['attribute_set_id' => ['attribute_set' => $attributeSet]]] ); $product->persist(); $this->objectManager->create( diff --git a/dev/tests/functional/tests/app/Magento/Widget/Test/Constraint/AssertWidgetSuccessDeleteMessage.php b/dev/tests/functional/tests/app/Magento/Widget/Test/Constraint/AssertWidgetSuccessDeleteMessage.php index 57b6aa9da7af7d99f866c253d16378166dc0ac51..687205faabf60d5d45c33a0fac5919b919077af8 100644 --- a/dev/tests/functional/tests/app/Magento/Widget/Test/Constraint/AssertWidgetSuccessDeleteMessage.php +++ b/dev/tests/functional/tests/app/Magento/Widget/Test/Constraint/AssertWidgetSuccessDeleteMessage.php @@ -31,7 +31,7 @@ class AssertWidgetSuccessDeleteMessage extends AbstractConstraint */ public function processAssert(WidgetInstanceIndex $widgetInstanceIndex) { - $actualMessage = $widgetInstanceIndex->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $widgetInstanceIndex->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::DELETE_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Widget/Test/Constraint/AssertWidgetSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/Widget/Test/Constraint/AssertWidgetSuccessSaveMessage.php index dae56dc5d3e44a9c7bf7b249e3f288b7d480464d..4ebfac7c9cf6e9ed3a7c35597df11ae358323f26 100644 --- a/dev/tests/functional/tests/app/Magento/Widget/Test/Constraint/AssertWidgetSuccessSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/Widget/Test/Constraint/AssertWidgetSuccessSaveMessage.php @@ -31,7 +31,7 @@ class AssertWidgetSuccessSaveMessage extends AbstractConstraint */ public function processAssert(WidgetInstanceIndex $widgetInstanceIndex) { - $actualMessage = $widgetInstanceIndex->getMessagesBlock()->getSuccessMessages(); + $actualMessage = $widgetInstanceIndex->getMessagesBlock()->getSuccessMessage(); \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, $actualMessage, diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertAddProductToWishlistSuccessMessage.php b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertAddProductToWishlistSuccessMessage.php index ead94063b609e1b9b3f162859196441aded573db..3199d2a356ab8ed3932a1855a0dfe6872c75c970 100644 --- a/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertAddProductToWishlistSuccessMessage.php +++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertAddProductToWishlistSuccessMessage.php @@ -36,7 +36,7 @@ class AssertAddProductToWishlistSuccessMessage extends AbstractConstraint { \PHPUnit_Framework_Assert::assertEquals( sprintf(self::SUCCESS_MESSAGE, $product->getName()), - $wishlistIndex->getMessagesBlock()->getSuccessMessages(), + $wishlistIndex->getMessagesBlock()->getSuccessMessage(), "Expected success message doesn't match actual." ); } diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertMoveProductToWishlistSuccessMessage.php b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertMoveProductToWishlistSuccessMessage.php index 88a588fe6309f0f7aa70c7bf380598a8effad1ed..fe4fc287c831aa59088d443610f6899e2242ee61 100644 --- a/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertMoveProductToWishlistSuccessMessage.php +++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertMoveProductToWishlistSuccessMessage.php @@ -32,7 +32,7 @@ class AssertMoveProductToWishlistSuccessMessage extends AbstractConstraint { \PHPUnit_Framework_Assert::assertEquals( sprintf(self::SUCCESS_MESSAGE, $product->getName()), - $wishlistIndex->getMessagesBlock()->getSuccessMessages(), + $wishlistIndex->getMessagesBlock()->getSuccessMessage(), "Expected success move to wish list message doesn't match actual." ); } diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertWishlistShareMessage.php b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertWishlistShareMessage.php index 7013691e59cbf853b1fe18f596ea5375c3576638..5d7e9dc5f2bd40183194f8f3f448af95ec9632ab 100644 --- a/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertWishlistShareMessage.php +++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertWishlistShareMessage.php @@ -34,7 +34,7 @@ class AssertWishlistShareMessage extends AbstractConstraint { \PHPUnit_Framework_Assert::assertEquals( self::SUCCESS_MESSAGE, - $wishlistIndex->getMessagesBlock()->getSuccessMessages(), + $wishlistIndex->getMessagesBlock()->getSuccessMessage(), 'Wrong success message is displayed.' ); } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AttributeTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AttributeTest.php index 007c4939d78885013937f86f1424a8f2f8ab71e9..664fdee21987253770e0160a6d31e00009677cc3 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AttributeTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AttributeTest.php @@ -7,6 +7,7 @@ namespace Magento\Catalog\Controller\Adminhtml\Product; /** * @magentoAppArea adminhtml + * @magentoDbIsolation enabled */ class AttributeTest extends \Magento\TestFramework\TestCase\AbstractBackendController { diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Set/DeleteTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Set/DeleteTest.php index 6fdab58458c5d43ee1840d57a5d6e120487d090f..ddd37fc1cb63f24d3dc7d601856bc80a1d7a97ee 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Set/DeleteTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Set/DeleteTest.php @@ -21,7 +21,7 @@ class DeleteTest extends \Magento\TestFramework\TestCase\AbstractBackendControll $this->assertNull($this->getAttributeSetByName('empty_attribute_set')); $this->assertSessionMessages( - $this->equalTo(['The product template has been removed.']), + $this->equalTo(['The attribute set has been removed.']), MessageInterface::TYPE_SUCCESS ); $this->assertRedirect($this->stringContains('catalog/product_set/index/')); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Option/Type/File/ValidatorFileTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Option/Type/File/ValidatorFileTest.php index 611e8c839d477cf9ad31672dbf27f387b61d4d14..b005c52813a7b987df53f64d5083c8a43f1434d9 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Option/Type/File/ValidatorFileTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Option/Type/File/ValidatorFileTest.php @@ -16,7 +16,7 @@ class ValidatorFileTest extends \PHPUnit_Framework_TestCase protected $model; /** - * @var \Magento\Framework\ObjectManager + * @var \Magento\Framework\ObjectManagerInterface */ protected $objectManager; @@ -241,8 +241,8 @@ class ValidatorFileTest extends \PHPUnit_Framework_TestCase return [ 'type' => 'image/jpeg', 'title' => 'test.jpg', - 'quote_path' => 'pub/media/custom_options/quote/t/e/e1d601731b4b1a84163cd0e9370a4fcb.jpg', - 'order_path' => 'pub/media/custom_options/order/t/e/e1d601731b4b1a84163cd0e9370a4fcb.jpg', + 'quote_path' => 'custom_options/quote/t/e/e1d601731b4b1a84163cd0e9370a4fcb.jpg', + 'order_path' => 'custom_options/order/t/e/e1d601731b4b1a84163cd0e9370a4fcb.jpg', 'size' => '3300', 'width' => 136, 'height' => 131, diff --git a/dev/tests/integration/testsuite/Magento/Checkout/Block/Onepage/Payment/MethodsTest.php b/dev/tests/integration/testsuite/Magento/Checkout/Block/Onepage/Payment/MethodsTest.php deleted file mode 100644 index 8e9cd3f440d6c2634e201e33df39a75608548b9a..0000000000000000000000000000000000000000 --- a/dev/tests/integration/testsuite/Magento/Checkout/Block/Onepage/Payment/MethodsTest.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -/** - * Test class for \Magento\Checkout\Block\Onepage\Payment\Methods - */ -namespace Magento\Checkout\Block\Onepage\Payment; - -class MethodsTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var \Magento\Checkout\Block\Onepage\Payment\Methods - */ - protected $_block; - - protected function setUp() - { - parent::setUp(); - $this->_block = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( - 'Magento\Framework\View\LayoutInterface' - )->createBlock( - 'Magento\Checkout\Block\Onepage\Payment\Methods' - ); - } - - /** - * @magentoAppArea frontend - */ - public function testGetMethodTitleAndMethodLabelAfterHtml() - { - $expectedTitle = 'Free Method'; - $expectedLabel = 'Label After Html'; - $method = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( - 'Magento\Payment\Model\Method\Free' - ); - - $block = $this->_block->getLayout()->createBlock('Magento\Framework\View\Element\Text') - ->setMethodTitle($expectedTitle) - ->setMethodLabelAfterHtml($expectedLabel); - - $this->assertEquals('No Payment Information Required', $this->_block->getMethodTitle($method)); - $this->_block->setChild('payment.method.free', $block); - $actualTitle = $this->_block->getMethodTitle($method); - $actualLabel = $this->_block->getMethodLabelAfterHtml($method); - - $this->assertEquals($expectedTitle, $actualTitle); - $this->assertEquals($expectedLabel, $actualLabel); - } -} diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php index 65c3aae162bf6ebbf6a8e1a66613c99bb5f8cfac..077f18fbe2cf355d3e95bf698df3e7234d101647 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php @@ -587,7 +587,6 @@ class AccountManagementTest extends \PHPUnit_Framework_TestCase 'email' => $email, 'firstname' => $firstName, 'lastname' => $lastName, - 'created_in' => 'Admin', 'id' => null ] ); @@ -603,7 +602,6 @@ class AccountManagementTest extends \PHPUnit_Framework_TestCase $this->assertEquals($email, $customerAfter->getEmail()); $this->assertEquals($firstName, $customerAfter->getFirstname()); $this->assertEquals($lastName, $customerAfter->getLastname()); - $this->assertEquals('Admin', $customerAfter->getCreatedIn()); $this->accountManagement->authenticate( $customerAfter->getEmail(), 'aPassword' @@ -807,7 +805,6 @@ class AccountManagementTest extends \PHPUnit_Framework_TestCase $customerEntity->setEmail($email) ->setFirstname($firstName) ->setLastname($lastname) - ->setCreatedIn('Admin') ->setId(null); $customer = $this->accountManagement->createAccount($customerEntity, 'aPassword'); @@ -815,7 +812,6 @@ class AccountManagementTest extends \PHPUnit_Framework_TestCase $this->assertEquals($email, $customer->getEmail()); $this->assertEquals($firstName, $customer->getFirstname()); $this->assertEquals($lastname, $customer->getLastname()); - $this->assertEquals('Admin', $customer->getCreatedIn()); $this->accountManagement->authenticate( $customer->getEmail(), 'aPassword', diff --git a/dev/tests/integration/testsuite/Magento/Framework/Code/GeneratorTest.php b/dev/tests/integration/testsuite/Magento/Framework/Code/GeneratorTest.php index e31201caf943440ce75a00725b65c79cde471c29..81fcb128903e1059ea0190b5b6d63b137c448d9d 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Code/GeneratorTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Code/GeneratorTest.php @@ -95,7 +95,9 @@ class GeneratorTest extends \PHPUnit_Framework_TestCase // This test is only valid if the factory created the object if Autoloader did not pick it up automatically if (\Magento\Framework\Code\Generator::GENERATION_SUCCESS == $generatorResult) { $content = $this->_clearDocBlock( - file_get_contents($this->_ioObject->getResultFileName(self::CLASS_NAME_WITH_NAMESPACE . 'Factory')) + file_get_contents( + $this->_ioObject->generateResultFileName(self::CLASS_NAME_WITH_NAMESPACE . 'Factory') + ) ); $expectedContent = $this->_clearDocBlock( file_get_contents(__DIR__ . '/_expected/SourceClassWithNamespaceFactory.php.sample') @@ -120,7 +122,7 @@ class GeneratorTest extends \PHPUnit_Framework_TestCase // This test is only valid if the factory created the object if Autoloader did not pick it up automatically if (\Magento\Framework\Code\Generator::GENERATION_SUCCESS == $generatorResult) { $content = $this->_clearDocBlock( - file_get_contents($this->_ioObject->getResultFileName(self::CLASS_NAME_WITH_NAMESPACE . '\Proxy')) + file_get_contents($this->_ioObject->generateResultFileName(self::CLASS_NAME_WITH_NAMESPACE . '\Proxy')) ); $expectedContent = $this->_clearDocBlock( file_get_contents(__DIR__ . '/_expected/SourceClassWithNamespaceProxy.php.sample') @@ -142,7 +144,7 @@ class GeneratorTest extends \PHPUnit_Framework_TestCase if (\Magento\Framework\Code\Generator::GENERATION_SUCCESS == $generatorResult) { $content = $this->_clearDocBlock( file_get_contents( - $this->_ioObject->getResultFileName(self::CLASS_NAME_WITH_NAMESPACE . '\Interceptor') + $this->_ioObject->generateResultFileName(self::CLASS_NAME_WITH_NAMESPACE . '\Interceptor') ) ); $expectedContent = $this->_clearDocBlock( diff --git a/dev/tests/integration/testsuite/Magento/Checkout/Block/Onepage/BillingTest.php b/dev/tests/integration/testsuite/Magento/Paypal/Block/Express/Review/BillingTest.php similarity index 84% rename from dev/tests/integration/testsuite/Magento/Checkout/Block/Onepage/BillingTest.php rename to dev/tests/integration/testsuite/Magento/Paypal/Block/Express/Review/BillingTest.php index 86ac63afe57145019c36e4f111e5e398d0c12260..c256479cc7c833efa628eb58bc084554b87d2ce3 100644 --- a/dev/tests/integration/testsuite/Magento/Checkout/Block/Onepage/BillingTest.php +++ b/dev/tests/integration/testsuite/Magento/Paypal/Block/Express/Review/BillingTest.php @@ -3,7 +3,7 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Checkout\Block\Onepage; +namespace Magento\Paypal\Block\Express\Review; use Magento\Customer\Model\Context; use Magento\TestFramework\Helper\Bootstrap; @@ -13,7 +13,7 @@ use Magento\TestFramework\Helper\Bootstrap; */ class BillingTest extends \PHPUnit_Framework_TestCase { - /** @var \Magento\Checkout\Block\Onepage\Billing */ + /** @var \Magento\Paypal\Block\Express\Review\Billing */ protected $_block; /** @var \Magento\Customer\Api\AddressRepositoryInterface */ @@ -67,9 +67,9 @@ class BillingTest extends \PHPUnit_Framework_TestCase ->setValue(Context::CONTEXT_AUTH, true, false); $this->_block = $objectManager->get('Magento\Framework\View\LayoutInterface') ->createBlock( - 'Magento\Checkout\Block\Onepage\Billing', + 'Magento\Paypal\Block\Express\Review\Billing', '', - ['customerSession' => $customerSession, 'checkoutSession' => $checkoutSession] + ['customerSession' => $customerSession, 'resourceSession' => $checkoutSession] ); } @@ -136,19 +136,4 @@ class BillingTest extends \PHPUnit_Framework_TestCase $this->assertEquals(self::SAMPLE_FIRST_NAME, $this->_block->getFirstname()); $this->assertEquals(self::SAMPLE_LAST_NAME, $this->_block->getLastname()); } - - /** - * @magentoDataFixture Magento/Customer/_files/customer.php - * @magentoDataFixture Magento/Customer/_files/customer_address.php - */ - public function testGetAddressesHtmlSelect() - { - Bootstrap::getObjectManager()->get('Magento\Customer\Model\Session')->setCustomerId(1); - // @codingStandardsIgnoreStart - $expected = <<<OUTPUT -<select name="billing_address_id" id="billing:address-select" class="address-select" title="" ><option value="1" selected="selected" >John Smith, Green str, 67, CityM, Alabama 75477, United States</option><option value="" >New Address</option></select> -OUTPUT; - // @codingStandardsIgnoreEnd - $this->assertEquals($expected, $this->_block->getAddressesHtmlSelect('billing')); - } } diff --git a/dev/tests/integration/testsuite/Magento/Paypal/_files/ipn.php b/dev/tests/integration/testsuite/Magento/Paypal/_files/ipn.php index 5c27950d64f00760345068372d780397163c04f0..3949117079b68d8ecc8a93bcd86dac4a886b87ce 100644 --- a/dev/tests/integration/testsuite/Magento/Paypal/_files/ipn.php +++ b/dev/tests/integration/testsuite/Magento/Paypal/_files/ipn.php @@ -8,6 +8,7 @@ return [ 'mc_gross' => '100.00', 'invoice' => '100000001', 'payment_status' => 'Completed', + 'auth_status' => 'Completed', 'mc_currency' => 'USD', 'receiver_email' => 'merchant_2012050718_biz@example.com' ]; diff --git a/dev/tests/integration/testsuite/Magento/Paypal/_files/order_express.php b/dev/tests/integration/testsuite/Magento/Paypal/_files/order_express.php index cc659a62b1eb2361855aa61bfeb812ff92966c2d..9fbab06028d7988f983157325c5f8e64fdb38eec 100644 --- a/dev/tests/integration/testsuite/Magento/Paypal/_files/order_express.php +++ b/dev/tests/integration/testsuite/Magento/Paypal/_files/order_express.php @@ -18,30 +18,21 @@ $shippingAddress->setId(null)->setAddressType('shipping'); $payment = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create('Magento\Sales\Model\Order\Payment'); $payment->setMethod(\Magento\Paypal\Model\Config::METHOD_WPP_EXPRESS); -$order = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create('Magento\Sales\Model\Order'); -$order - ->setCustomerEmail('co@co.co') - ->setIncrementId( - '100000001' -)->setSubtotal( - 100 -)->setBaseSubtotal( - 100 -)->setBaseGrandTotal( - 100 -)->setBaseCurrencyCode( - 'USD' -)->setCustomerIsGuest( - true -)->setStoreId( - 1 -)->setEmailSent( - 1 -)->setBillingAddress( - $billingAddress -)->setShippingAddress( - $shippingAddress -)->setPayment( - $payment -); +$amount = 100; + +/** @var \Magento\Sales\Model\Order $order */ +$order = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(Magento\Sales\Model\Order::class); +$order->setCustomerEmail('co@co.co') + ->setIncrementId('100000001') + ->setSubtotal($amount) + ->setBaseSubtotal($amount) + ->setBaseGrandTotal($amount) + ->setGrandTotal($amount) + ->setBaseCurrencyCode('USD') + ->setCustomerIsGuest(true) + ->setStoreId(1) + ->setEmailSent(true) + ->setBillingAddress($billingAddress) + ->setShippingAddress($shippingAddress) + ->setPayment($payment); $order->save(); diff --git a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/I18nCollectPhrasesCommandTest.php b/dev/tests/integration/testsuite/Magento/Setup/Console/Command/I18nCollectPhrasesCommandTest.php index 924853df6bc0c75cb219ec88afb42317c33d4f1d..2d5e9026ceefe6e4853e08e3e3859b681e6ab6ea 100644 --- a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/I18nCollectPhrasesCommandTest.php +++ b/dev/tests/integration/testsuite/Magento/Setup/Console/Command/I18nCollectPhrasesCommandTest.php @@ -46,17 +46,19 @@ class I18nCollectPhrasesCommandTest extends \PHPUnit_Framework_TestCase public function testExecuteCsvOutput() { - $outputPath = BP . '/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/output/output.csv'; + $outputPath = BP . '/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/output/phrases.csv'; $this->tester->execute( [ - 'directory' => BP . '/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/', + 'directory' => BP . '/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/phrases/', '--output' => $outputPath, ] ); $handle = fopen($outputPath, 'r'); $output = fread($handle, filesize($outputPath)); - $expected = '"Hello world","Hello world"' . PHP_EOL . '"Foo bar","Foo bar"' . PHP_EOL; + $expected = file_get_contents( + BP . '/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/expectedPhrases.csv' + ); $this->assertEquals($expected, $output); unlink($outputPath); } diff --git a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/Magento/TestModule/Phrases.php b/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/Magento/TestModule/Phrases.php deleted file mode 100644 index d55885ff96f2b8da7acce4f97c505fa2a6b8aa76..0000000000000000000000000000000000000000 --- a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/Magento/TestModule/Phrases.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -$a = __("Hello world"); -$b = __("Foo bar"); diff --git a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/expectedPhrases.csv b/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/expectedPhrases.csv new file mode 100644 index 0000000000000000000000000000000000000000..43c331ecb48d6faa3e12d04eccb53d992779e907 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/expectedPhrases.csv @@ -0,0 +1,19 @@ +"simple text","simple text" +"simple text with 1 string literal placeholder %1","simple text with 1 string literal placeholder %1" +"simple text with 1 variable placeholder %1","simple text with 1 variable placeholder %1" +"simple text with multiple placeholders %1 %2","simple text with multiple placeholders %1 %2" +"first part second part","first part second part" +"first part second part third part","first part second part third part" +"first part second part with one string literal placeholder %1","first part second part with one string literal placeholder %1" +"first part of concat second part with one variable placeholder %1","first part of concat second part with one variable placeholder %1" +"first part of concat second part with two placeholders %1, %2","first part of concat second part with two placeholders %1, %2" +"first part of concat second part third part with one placeholder %1","first part of concat second part third part with one placeholder %1" +"first part of concat second part third part with two placeholders %1, %2","first part of concat second part third part with two placeholders %1, %2" +"string with escaped 'single quotes'","string with escaped 'single quotes'" +"string with placeholder in escaped single quotes '%1'","string with placeholder in escaped single quotes '%1'" +"string with ""double quotes""","string with ""double quotes""" +"string with placeholder in double quotes ""%1""","string with placeholder in double quotes ""%1""" +"string with 'single quotes'","string with 'single quotes'" +"string with placeholder in single quotes '%1'","string with placeholder in single quotes '%1'" +"string with escaped ""double quotes""","string with escaped ""double quotes""" +"string with placeholder in escaped double quotes ""%1""","string with placeholder in escaped double quotes ""%1""" diff --git a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/phrases/TestPhrases.php b/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/phrases/TestPhrases.php new file mode 100644 index 0000000000000000000000000000000000000000..f3306a521add5a671e626d3cd49c19c9a6640c5f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/phrases/TestPhrases.php @@ -0,0 +1,87 @@ +<?php +/*** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +// @codingStandardsIgnoreFile + +use Magento\Framework\Phrase; + +/** + * @SuppressWarnings(PHPMD) + */ +class TestPhrases +{ + public function awesomeFunction() + { + $str1 = 'str1'; + $str2 = 'str2'; + + // Simple + $simpleCases = [ + new Phrase('simple text'), + new Phrase('simple text with 1 string literal placeholder %1', 'arg'), + new Phrase('simple text with 1 variable placeholder %1', $str1), + new Phrase('simple text with multiple placeholders %1 %2', $str1, $str2), + ]; + + // Phrase objects + $phraseObjects = [ + // Single concatenation + new Phrase('first part' . ' second part'), + new Phrase('first part' . ' second part' . ' third part'), + + // Multiple concatenation + new Phrase('first part' . ' second part with one string literal placeholder %1', 'arg'), + new Phrase('first part of concat' . ' second part with one variable placeholder %1', $str1), + new Phrase('first part of concat' . ' second part with two placeholders %1, %2', $str1, $str2), + new Phrase('first part of concat' . ' second part' . ' third part with one placeholder %1', 'arg'), + new Phrase('first part of concat' . ' second part' . ' third part with two placeholders %1, %2', $str1, $str2), + + // Escaped quotes + new Phrase('string with escaped \'single quotes\''), + new Phrase('string with placeholder in escaped single quotes \'%1\'', 'arg'), + new Phrase('string with "double quotes"'), + new Phrase('string with placeholder in double quotes "%1"', 'arg'), + ]; + + $singleQuoteTranslateFunctions = [ + // Single concatenation + __('first part' . ' second part'), + __('first part' . ' second part' . ' third part'), + + // Multiple concatenation + __('first part' . ' second part with one string literal placeholder %1', 'arg'), + __('first part of concat' . ' second part with one variable placeholder %1', $str1), + __('first part of concat' . ' second part with two placeholders %1, %2', $str1, $str2), + __('first part of concat' . ' second part' . ' third part with one placeholder %1', 'arg'), + __('first part of concat' . ' second part' . ' third part with two placeholders %1, %2', $str1, $str2), + + // Escaped quotes + __('string with escaped \'single quotes\''), + __('string with placeholder in escaped single quotes \'%1\'', 'arg'), + __('string with "double quotes"'), + __('string with placeholder in double quotes "%1"', 'arg'), + ]; + + $doubleQuoteTranslateFunctions = [ + // Single concatenation + __("first part" . " second part"), + __("first part" . " second part" . " third part"), + + // Multiple concatenation + __("first part" . " second part with one string literal placeholder %1", "arg"), + __("first part of concat" . " second part with one variable placeholder %1", $str1), + __("first part of concat" . " second part with two placeholders %1, %2", $str1, $str2), + __("first part of concat" . " second part" . " third part with one placeholder %1", "arg"), + __("first part of concat" . " second part" . " third part with two placeholders %1, %2", $str1, $str2), + + // Escaped quotes + __("string with 'single quotes'"), + __("string with placeholder in single quotes '%1'", "arg"), + __("string with escaped \"double quotes\""), + __("string with placeholder in escaped double quotes \"%1\"", "arg"), + ]; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Setup/Module/I18n/Dictionary/_files/expected/with_context.csv b/dev/tests/integration/testsuite/Magento/Setup/Module/I18n/Dictionary/_files/expected/with_context.csv index 0895edb09f36d9517729c3538d70811015e50acb..6c873fee5c89b7146fd2b97044fb7c169f024562 100644 --- a/dev/tests/integration/testsuite/Magento/Setup/Module/I18n/Dictionary/_files/expected/with_context.csv +++ b/dev/tests/integration/testsuite/Magento/Setup/Module/I18n/Dictionary/_files/expected/with_context.csv @@ -1,9 +1,11 @@ Helper,Helper,module,Magento_FirstModule -Model,Model,module,"Magento_FirstModule,Magento_SecondModule" +Model,Model,module,Magento_FirstModule "Module template","Module template",module,Magento_FirstModule +Model,Model,module,Magento_SecondModule "Theme template","Theme template",theme,adminhtml/default/backend "Module js","Module js",module,Magento_FirstModule -"Lib js","Lib js",lib,"lib/web/mage/file.js,lib/web/varien/file.js" +"Lib js","Lib js",lib,lib/web/mage/file.js +"Lib js","Lib js",lib,lib/web/varien/file.js "Module layout label","Module layout label",module,Magento_FirstModule "Module layout title","Module layout title",module,Magento_FirstModule "Theme layout label","Theme layout label",theme,adminhtml/default/backend diff --git a/dev/tests/integration/testsuite/Magento/Sitemap/Helper/DataTest.php b/dev/tests/integration/testsuite/Magento/Sitemap/Helper/DataTest.php index 3eacb4c386420311d3587fe3e407eae85f5319ef..2579f660db11dc69b964c33e58cc132c8010b645 100644 --- a/dev/tests/integration/testsuite/Magento/Sitemap/Helper/DataTest.php +++ b/dev/tests/integration/testsuite/Magento/Sitemap/Helper/DataTest.php @@ -14,15 +14,6 @@ class DataTest extends \PHPUnit_Framework_TestCase protected function setUp() { - // TODO: Remove provided check after PHPMD will support PHP version 7 - $isSupported = version_compare( - '7.0.0', - preg_replace('#^([^~+-]+).*$#', '$1', PHP_VERSION), - '>' - ); - if (!$isSupported) { - $this->markTestSkipped('MAGETWO-40822: PHP7 incompatible'); - } $this->_helper = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( 'Magento\Sitemap\Helper\Data' ); diff --git a/dev/tests/integration/testsuite/Magento/Widget/Block/Adminhtml/Widget/Instance/Edit/Chooser/_files/design-abstraction_select.html b/dev/tests/integration/testsuite/Magento/Widget/Block/Adminhtml/Widget/Instance/Edit/Chooser/_files/design-abstraction_select.html index 15e322c12df580c58724b6193208e99bd8481cb8..ec08d09ec6bc5642bc18966ceda3196abb900ff4 100644 --- a/dev/tests/integration/testsuite/Magento/Widget/Block/Adminhtml/Widget/Instance/Edit/Chooser/_files/design-abstraction_select.html +++ b/dev/tests/integration/testsuite/Magento/Widget/Block/Adminhtml/Widget/Instance/Edit/Chooser/_files/design-abstraction_select.html @@ -6,9 +6,9 @@ --> <select name="design_abstractions" id="design_abstraction_select" class="design-abstraction-select" title="Design Abstraction Select"> <option value="">-- Please Select --</option> - <optgroup label="Custom Layouts"> + <optgroup data-optgroup-name="Custom Layouts" label="Custom Layouts"> <option value="customer_account" >Customer My Account (All Pages)</option> </optgroup> - <optgroup label="Page Layouts"> + <optgroup data-optgroup-name="Page Layouts" label="Page Layouts"> <option value="page_empty" >All Empty Layout Pages</option> </optgroup></select> diff --git a/dev/tests/static/framework/Magento/TestFramework/CodingStandard/Tool/CodeMessDetector.php b/dev/tests/static/framework/Magento/TestFramework/CodingStandard/Tool/CodeMessDetector.php index 6349d18bdced4120969be3672cd54cb77c49ddcd..ed5c2b33fdb300f95da2efff0e1ceb3835ad1575 100644 --- a/dev/tests/static/framework/Magento/TestFramework/CodingStandard/Tool/CodeMessDetector.php +++ b/dev/tests/static/framework/Magento/TestFramework/CodingStandard/Tool/CodeMessDetector.php @@ -46,9 +46,7 @@ class CodeMessDetector implements ToolInterface */ public function canRun() { - /** TODO: Remove provided check after PHPMD will support PHP version 7 */ - $isPhpVersionSupported = PHP_VERSION_ID < 70000; - return class_exists('PHPMD\TextUI\Command') && $isPhpVersionSupported; + return class_exists('PHPMD\TextUI\Command'); } /** diff --git a/dev/tests/static/framework/tests/unit/testsuite/Magento/TestFramework/CodingStandard/Tool/CodeMessDetectorTest.php b/dev/tests/static/framework/tests/unit/testsuite/Magento/TestFramework/CodingStandard/Tool/CodeMessDetectorTest.php index 196e065ee3e70fec05aa5ff56dfe847a2677d6e6..b3b7e590f57764f349feb000fd9c778aaa4863c4 100644 --- a/dev/tests/static/framework/tests/unit/testsuite/Magento/TestFramework/CodingStandard/Tool/CodeMessDetectorTest.php +++ b/dev/tests/static/framework/tests/unit/testsuite/Magento/TestFramework/CodingStandard/Tool/CodeMessDetectorTest.php @@ -14,15 +14,8 @@ class CodeMessDetectorTest extends \PHPUnit_Framework_TestCase 'some/report/file.xml' ); - /** TODO: Remove provided check after PHPMD will support PHP version 7 */ - $isPhpVersionSupported = version_compare( - '7.0.0', - preg_replace('#^([^~+-]+).*$#', '$1', PHP_VERSION), - '>' - ); - $this->assertEquals( - class_exists('PHPMD\TextUI\Command') && $isPhpVersionSupported, + class_exists('PHPMD\TextUI\Command'), $messDetector->canRun() ); } diff --git a/dev/tests/static/testsuite/Magento/Test/Js/_files/blacklist/magento.txt b/dev/tests/static/testsuite/Magento/Test/Js/_files/blacklist/magento.txt index 70168b63a4efb5f06f978a00c9896b0c1a6d5f12..7497804d68237b137475036e394951135630508e 100644 --- a/dev/tests/static/testsuite/Magento/Test/Js/_files/blacklist/magento.txt +++ b/dev/tests/static/testsuite/Magento/Test/Js/_files/blacklist/magento.txt @@ -105,15 +105,6 @@ app/code/Magento/Checkout/view/frontend/web/js/model/sidebar.js app/code/Magento/Checkout/view/frontend/web/js/model/step-navigator.js app/code/Magento/Checkout/view/frontend/web/js/model/totals.js app/code/Magento/Checkout/view/frontend/web/js/model/url-builder.js -app/code/Magento/Checkout/view/frontend/web/js/opc-billing-info.js -app/code/Magento/Checkout/view/frontend/web/js/opc-checkout-method.js -app/code/Magento/Checkout/view/frontend/web/js/opc-order-review.js -app/code/Magento/Checkout/view/frontend/web/js/opc-payment-info.js -app/code/Magento/Checkout/view/frontend/web/js/opc-shipping-info.js -app/code/Magento/Checkout/view/frontend/web/js/opc-shipping-method.js -app/code/Magento/Checkout/view/frontend/web/js/opcheckout.js -app/code/Magento/Checkout/view/frontend/web/js/payment-authentication.js -app/code/Magento/Checkout/view/frontend/web/js/payment.js app/code/Magento/Checkout/view/frontend/web/js/proceed-to-checkout.js app/code/Magento/Checkout/view/frontend/web/js/region-updater.js app/code/Magento/Checkout/view/frontend/web/js/shopping-cart.js @@ -219,6 +210,7 @@ app/code/Magento/Msrp/view/frontend/requirejs-config.js app/code/Magento/Multishipping/view/frontend/requirejs-config.js app/code/Magento/Multishipping/view/frontend/web/js/multi-shipping.js app/code/Magento/Multishipping/view/frontend/web/js/overview.js +app/code/Magento/Multishipping/view/frontend/web/js/payment.js app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/method-renderer/banktransfer-method.js app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/method-renderer/cashondelivery-method.js app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/method-renderer/checkmo-method.js @@ -688,15 +680,6 @@ vendor/magento/module-checkout/view/frontend/web/js/model/step-loader.js vendor/magento/module-checkout/view/frontend/web/js/model/step-navigator.js vendor/magento/module-checkout/view/frontend/web/js/model/totals.js vendor/magento/module-checkout/view/frontend/web/js/model/url-builder.js -vendor/magento/module-checkout/view/frontend/web/js/opc-billing-info.js -vendor/magento/module-checkout/view/frontend/web/js/opc-checkout-method.js -vendor/magento/module-checkout/view/frontend/web/js/opc-order-review.js -vendor/magento/module-checkout/view/frontend/web/js/opc-payment-info.js -vendor/magento/module-checkout/view/frontend/web/js/opc-shipping-info.js -vendor/magento/module-checkout/view/frontend/web/js/opc-shipping-method.js -vendor/magento/module-checkout/view/frontend/web/js/opcheckout.js -vendor/magento/module-checkout/view/frontend/web/js/payment-authentication.js -vendor/magento/module-checkout/view/frontend/web/js/payment.js vendor/magento/module-checkout/view/frontend/web/js/proceed-to-checkout.js vendor/magento/module-checkout/view/frontend/web/js/region-updater.js vendor/magento/module-checkout/view/frontend/web/js/shopping-cart.js diff --git a/dev/tests/static/testsuite/Magento/Test/Js/_files/jscs/.jscsrc b/dev/tests/static/testsuite/Magento/Test/Js/_files/jscs/.jscsrc index b8071503882e23246959a4b515edeb435a1f325c..0a4404817de4742085a59692e1a321fbb23cef13 100644 --- a/dev/tests/static/testsuite/Magento/Test/Js/_files/jscs/.jscsrc +++ b/dev/tests/static/testsuite/Magento/Test/Js/_files/jscs/.jscsrc @@ -75,6 +75,7 @@ "disallowTrailingComma": true, "disallowTrailingWhitespace": true, "disallowYodaConditions": true, + "maxErrors": null, "requireBlocksOnNewline": true, "requireDotNotation": "except_snake_case", "requireCamelCaseOrUpperCaseIdentifiers": true, diff --git a/dev/tests/static/testsuite/Magento/Test/Js/_files/jshint/blacklist/core.txt b/dev/tests/static/testsuite/Magento/Test/Js/_files/jshint/blacklist/core.txt index 9699f47c4bcccc9dd1009437092117fae86c0f25..2cb2aca38f906e767c139a830976538f18f337cc 100644 --- a/dev/tests/static/testsuite/Magento/Test/Js/_files/jshint/blacklist/core.txt +++ b/dev/tests/static/testsuite/Magento/Test/Js/_files/jshint/blacklist/core.txt @@ -4,7 +4,6 @@ module Magento_Catalog view/adminhtml/web/catalog/category/edit.js module Magento_Catalog view/adminhtml/web/catalog/product.js module Magento_Catalog view/adminhtml/web/catalog/product/composite/configure.js module Magento_Checkout view/frontend/web/js/opcheckout.js -module Magento_Checkout view/frontend/web/js/payment.js module Magento_Rule view/adminhtml/web/rules.js module Magento_Sales view/adminhtml/web/order/create/giftmessage.js module Magento_Sales view/adminhtml/web/order/create/scripts.js diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php index cf42cd0950a7a806535e76d213079ad68a03a6ee..cb80c5cf1519d361cff0ca0284d06fbad8d285c9 100755 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php @@ -3949,8 +3949,8 @@ return [ ['Magento\Catalog\Ui\Component\Listing\Filters'], ['Magento\Customer\Ui\Component\Listing\Filters'], ['Magento\Catalog\Block\Product\TemplateSelector'], - ['Magento\Downloadable\Controller\Adminhtml\Downloadable\Product\Edit\SuggestProductTemplates'], - ['Magento\Bundle\Controller\Adminhtml\Bundle\Product\Edit\SuggestProductTemplates'], + ['Magento\Downloadable\Controller\Adminhtml\Downloadable\Product\Edit\SuggestAttributeSets'], + ['Magento\Bundle\Controller\Adminhtml\Bundle\Product\Edit\SuggestAttributeSets'], ['Magento\ConfigurableProduct\Block\Adminhtml\Product\Edit\Tab\Super\Config\Attribute'], ['Magento\Wishlist\Model\Observer'], ['Magento\Swatches\Model\Observer', 'Magento\Swatches\Observer\*'], @@ -4102,4 +4102,5 @@ return [ ['Magento\GoogleOptimizer\Model\Observer\Block\Category\Tab', 'Magento\GoogleOptimizer\Observer\*'], ['Magento\Payment\Model\Observer', 'Magento\Payment\Observer\*'], ['Magento\Tax\Observer\AggregateSalesReportTaxData', 'Magento\Tax\Model\AggregateSalesReportTaxData'], + ['Magento\Developer\Console\Command\CssDeployCommand'] ]; diff --git a/dev/tools/grunt/assets/legacy-build/shim.js b/dev/tools/grunt/assets/legacy-build/shim.js index 7451340989672b85ac09ea11e40c786542261a98..e9226398fd1997b43ba023a8052dd61fabe94899 100644 --- a/dev/tools/grunt/assets/legacy-build/shim.js +++ b/dev/tools/grunt/assets/legacy-build/shim.js @@ -5,7 +5,7 @@ (function () { 'use strict'; - var globals = ['Prototype', 'Abstract', 'Try', 'Class', 'PeriodicalExecuter', 'Template', '$break', 'Enumerable', '$A', '$w', '$H', 'Hash', '$R', 'ObjectRange', 'Ajax', '$', 'Form', 'Field', '$F', 'Toggle', 'Insertion', '$continue', 'Position', 'Windows', 'Dialog', 'array', 'WindowUtilities', 'Builder', 'Effect', 'validateCreditCard', 'Validator', 'Validation', 'removeDelimiters', 'parseNumber', 'popWin', 'setLocation', 'setPLocation', 'setLanguageCode', 'decorateGeneric', 'decorateTable', 'decorateList', 'decorateDataList', 'parseSidUrl', 'formatCurrency', 'expandDetails', 'isIE', 'Varien', 'fireEvent', 'modulo', 'byteConvert', 'SessionError', 'varienLoader', 'varienLoaderHandler', 'setLoaderPosition', 'toggleSelectsUnderBlock', 'varienUpdater', 'confirmSetLocation', 'deleteConfirm', 'setElementDisable', 'toggleParentVis', 'toggleFieldsetVis', 'toggleVis', 'imagePreview', 'checkByProductPriceType', 'toggleSeveralValueElements', 'toggleValueElements', 'submitAndReloadArea', 'syncOnchangeValue', 'updateElementAtCursor', 'firebugEnabled', 'disableElement', 'enableElement', 'disableElements', 'enableElements', 'Cookie', 'Fieldset', 'Base64', 'sortNumeric', 'Element', '$$', 'Sizzle', 'Selector', 'Window']; + var globals = ['Prototype', 'Abstract', 'Try', 'Class', 'PeriodicalExecuter', 'Template', '$break', 'Enumerable', '$A', '$w', '$H', 'Hash', '$R', 'ObjectRange', 'Ajax', '$', 'Form', 'Field', '$F', 'Toggle', 'Insertion', '$continue', 'Position', 'Windows', 'Dialog', 'array', 'WindowUtilities', 'Builder', 'Effect', 'validateCreditCard', 'Validator', 'Validation', 'removeDelimiters', 'parseNumber', 'popWin', 'setLocation', 'setPLocation', 'setLanguageCode', 'decorateGeneric', 'decorateTable', 'decorateList', 'decorateDataList', 'parseSidUrl', 'formatCurrency', 'expandDetails', 'isIE', 'Varien', 'fireEvent', 'modulo', 'byteConvert', 'SessionError', 'varienLoader', 'varienLoaderHandler', 'setLoaderPosition', 'toggleSelectsUnderBlock', 'varienUpdater', 'setElementDisable', 'toggleParentVis', 'toggleFieldsetVis', 'toggleVis', 'imagePreview', 'checkByProductPriceType', 'toggleSeveralValueElements', 'toggleValueElements', 'submitAndReloadArea', 'syncOnchangeValue', 'updateElementAtCursor', 'firebugEnabled', 'disableElement', 'enableElement', 'disableElements', 'enableElements', 'Cookie', 'Fieldset', 'Base64', 'sortNumeric', 'Element', '$$', 'Sizzle', 'Selector', 'Window']; globals.forEach(function (prop) { /* jshint evil:true */ diff --git a/dev/tools/grunt/configs/combo.js b/dev/tools/grunt/configs/combo.js index cd3484eee7836c516e6cacd766fecc4410c71707..f86a47261b88c8bb28796dcce495c49df2aa0bce 100644 --- a/dev/tools/grunt/configs/combo.js +++ b/dev/tools/grunt/configs/combo.js @@ -16,10 +16,12 @@ module.exports = { var cmdPlus = /^win/.test(process.platform) ? ' & ' : ' && ', command = 'grunt --force clean:' + themeName + cmdPlus; - command = command + 'php bin/magento dev:css:deploy ' + theme[themeName].dsl + ' ' + theme[themeName].files.join(' ') + - ' --locale=' + theme[themeName].locale + - ' --area=' + theme[themeName].area + - ' --theme=' + theme[themeName].name; + command = command + 'php bin/magento dev:source_theme:deploy ' + + theme[themeName].files.join(' ') + + ' --type=less' + + ' --locale=' + theme[themeName].locale + + ' --area=' + theme[themeName].area + + ' --theme=' + theme[themeName].name; return command; }, diff --git a/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/EntityChildTestAbstract.php b/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/EntityChildTestAbstract.php index acbc463380d5292bab9de0851a1328ef4cebe3d3..5ea51a6d56024ca4645bcd6d5bbda4c691b65580 100644 --- a/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/EntityChildTestAbstract.php +++ b/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/EntityChildTestAbstract.php @@ -109,7 +109,7 @@ abstract class EntityChildTestAbstract extends \PHPUnit_Framework_TestCase //Mocking generation $this->ioObjectMock->expects($this->any()) - ->method('getResultFileName') + ->method('generateResultFileName') ->with($this->getResultClassName()) ->willReturn($resultFileName); $this->ioObjectMock->expects($this->once()) diff --git a/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/GenerateMapperTest.php b/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/GenerateMapperTest.php index a78b00f1ceebd60559f0a786342f965d83703b47..bdc11e49ddd360a0dfd281122ae7fef5b503a5c5 100644 --- a/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/GenerateMapperTest.php +++ b/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/GenerateMapperTest.php @@ -51,7 +51,7 @@ class GenerateMapperTest extends \PHPUnit_Framework_TestCase ); $sampleMapperCode = file_get_contents(__DIR__ . '/_files/SampleMapper.txt'); $this->ioObjectMock->expects($this->once()) - ->method('getResultFileName') + ->method('generateResultFileName') ->with('\Magento\Framework\Api\Code\Generator\SampleMapper') ->will($this->returnValue('SampleMapper.php')); $this->ioObjectMock->expects($this->once()) diff --git a/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/GenerateSearchResultsTest.php b/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/GenerateSearchResultsTest.php index 7ee5ff3acff604ad716f27d0886f6ac06c58fc33..1f7609b0e923ceff66ebb81d41786276b79d3700 100644 --- a/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/GenerateSearchResultsTest.php +++ b/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/GenerateSearchResultsTest.php @@ -52,7 +52,7 @@ class GenerateSearchResultsTest extends \PHPUnit_Framework_TestCase ); $sampleSearchResultBuilderCode = file_get_contents(__DIR__ . '/_files/SampleSearchResults.txt'); $this->ioObjectMock->expects($this->once()) - ->method('getResultFileName') + ->method('generateResultFileName') ->with('\Magento\Framework\Api\Code\Generator\SampleSearchResults') ->will($this->returnValue('SampleSearchResults.php')); $this->ioObjectMock->expects($this->once()) diff --git a/lib/internal/Magento/Framework/App/View/Asset/Publisher.php b/lib/internal/Magento/Framework/App/View/Asset/Publisher.php index e65564720bb670f1f55ec8b03b343755d451f249..45c18093ae6325afcbe357bb010985c1fcbc8d30 100644 --- a/lib/internal/Magento/Framework/App/View/Asset/Publisher.php +++ b/lib/internal/Magento/Framework/App/View/Asset/Publisher.php @@ -37,7 +37,8 @@ class Publisher } /** - * {@inheritdoc} + * @param Asset\LocalInterface $asset + * @return bool */ public function publish(Asset\LocalInterface $asset) { diff --git a/lib/internal/Magento/Framework/Code/Generator.php b/lib/internal/Magento/Framework/Code/Generator.php index edd02f6c2049282b6af2fa7f3b8e7d2559492857..2a572346e6a60bf2cb149a12f9c2a53d00e0b11d 100644 --- a/lib/internal/Magento/Framework/Code/Generator.php +++ b/lib/internal/Magento/Framework/Code/Generator.php @@ -104,25 +104,13 @@ class Generator new \Magento\Framework\Phrase(implode(' ', $errors)) ); } - $this->tryToIncludeFile($file, $className); + if (!$this->definedClasses->isClassLoadableFromMemory($className)) { + $this->_ioObject->includeFile($file); + } return self::GENERATION_SUCCESS; } } - /** - * Include file only if the class is not already defined in memory - * - * @param string $fileName - * @param string $className - * @return void - */ - public function tryToIncludeFile($fileName, $className) - { - if (!$this->definedClasses->isClassLoadableFromMemory($className)) { - include $fileName; - } - } - /** * Create entity generator * @@ -203,6 +191,16 @@ class Generator if (!$resultEntityType || !$sourceClassName) { return self::GENERATION_ERROR; } else if ($this->definedClasses->isClassLoadableFromDisc($resultClass)) { + $generatedFileName = $this->_ioObject->generateResultFileName($resultClass); + /** + * Must handle two edge cases: a competing process has generated the class and written it to disc already, + * or the class exists in committed code, despite matching pattern to be generated. + */ + if ($this->_ioObject->fileExists($generatedFileName) + && !$this->definedClasses->isClassLoadableFromMemory($resultClass) + ) { + $this->_ioObject->includeFile($generatedFileName); + } return self::GENERATION_SKIP; } else if (!isset($this->_generatedEntities[$resultEntityType])) { throw new \InvalidArgumentException('Unknown generation entity.'); diff --git a/lib/internal/Magento/Framework/Code/Generator/EntityAbstract.php b/lib/internal/Magento/Framework/Code/Generator/EntityAbstract.php index fee367f49ca8046d5088bdbda5167bbcab90f82f..aed8424282e8b3e7cfb5c292227752af728fd1c9 100644 --- a/lib/internal/Magento/Framework/Code/Generator/EntityAbstract.php +++ b/lib/internal/Magento/Framework/Code/Generator/EntityAbstract.php @@ -97,7 +97,7 @@ abstract class EntityAbstract if ($this->_validateData()) { $sourceCode = $this->_generateCode(); if ($sourceCode) { - $fileName = $this->_ioObject->getResultFileName($this->_getResultClassName()); + $fileName = $this->_ioObject->generateResultFileName($this->_getResultClassName()); $this->_ioObject->writeResultFile($fileName, $sourceCode); return $fileName; } else { @@ -252,9 +252,6 @@ abstract class EntityAbstract if (!$this->definedClasses->isClassLoadable($sourceClassName)) { $this->_addError('Source class ' . $sourceClassName . ' doesn\'t exist.'); return false; - } elseif ($this->definedClasses->isClassLoadableFromDisc($resultClassName)) { - $this->_addError('Result class ' . $resultClassName . ' already exists.'); - return false; } elseif ( /** * If makeResultFileDirectory only fails because the file is already created, diff --git a/lib/internal/Magento/Framework/Code/Generator/Io.php b/lib/internal/Magento/Framework/Code/Generator/Io.php index eb6cabeebf911acce56eeba33e087d8e731f15a4..365482c797c4ac937ede669be5e9246ca0d7d792 100644 --- a/lib/internal/Magento/Framework/Code/Generator/Io.php +++ b/lib/internal/Magento/Framework/Code/Generator/Io.php @@ -61,7 +61,7 @@ class Io */ public function getResultFileDirectory($className) { - $fileName = $this->getResultFileName($className); + $fileName = $this->generateResultFileName($className); $pathParts = explode('/', $fileName); unset($pathParts[count($pathParts) - 1]); @@ -72,7 +72,7 @@ class Io * @param string $className * @return string */ - public function getResultFileName($className) + public function generateResultFileName($className) { return $this->_generationDirectory . ltrim(str_replace(['\\', '_'], '/', $className), '/') . '.php'; } @@ -98,7 +98,7 @@ class Io try { $success = $this->filesystemDriver->rename($tmpFile, $fileName); } catch (FileSystemException $e) { - if (!file_exists($fileName)) { + if (!$this->fileExists($fileName)) { throw $e; } else { /** @@ -146,6 +146,18 @@ class Io return $this->filesystemDriver->isExists($fileName); } + /** + * Wrapper for include + * + * @param string $fileName + * @return mixed + * @codeCoverageIgnore + */ + public function includeFile($fileName) + { + return include $fileName; + } + /** * @param string $directory * @return bool diff --git a/lib/internal/Magento/Framework/Code/Test/Unit/Generator/EntityAbstractTest.php b/lib/internal/Magento/Framework/Code/Test/Unit/Generator/EntityAbstractTest.php index cf74e8a67f1573a8eb9ce202c35014f9ca6e263b..c10467f7cdf4bce65b4687cb90b9a700080a1ad7 100644 --- a/lib/internal/Magento/Framework/Code/Test/Unit/Generator/EntityAbstractTest.php +++ b/lib/internal/Magento/Framework/Code/Test/Unit/Generator/EntityAbstractTest.php @@ -103,39 +103,33 @@ class EntityAbstractTest extends \PHPUnit_Framework_TestCase { return [ 'no_source_class' => [ - '$errors' => ['Source class ' . self::SOURCE_CLASS . ' doesn\'t exist.'], - '$validationSuccess' => false, - '$sourceClassExists' => false, - ], - 'result_class_exists' => [ - '$errors' => ['Result class ' . self::RESULT_CLASS . ' already exists.'], - '$validationSuccess' => false, - '$sourceClassExists' => true, - '$resultClassExists' => true, + 'errors' => ['Source class ' . self::SOURCE_CLASS . ' doesn\'t exist.'], + 'validationSuccess' => false, + 'sourceClassExists' => false, ], 'cant_create_result_directory' => [ - '$errors' => ['Can\'t create directory ' . self::RESULT_DIRECTORY . '.'], - '$validationSuccess' => false, - '$sourceClassExists' => true, - '$resultClassExists' => false, - '$makeResultDirSuccess' => false, + 'errors' => ['Can\'t create directory ' . self::RESULT_DIRECTORY . '.'], + 'validationSuccess' => false, + 'sourceClassExists' => true, + 'resultClassExists' => false, + 'makeResultDirSuccess' => false, ], 'result_file_exists' => [ - '$errors' => [], - '$validationSuccess' => true, - '$sourceClassExists' => true, - '$resultClassExists' => false, - '$makeResultDirSuccess' => false, - '$resultFileExists' => true, + 'errors' => [], + 'validationSuccess' => true, + 'sourceClassExists' => true, + 'resultClassExists' => false, + 'makeResultDirSuccess' => false, + 'resultFileExists' => true, ], 'generate_no_data' => [ - '$errors' => ['Can\'t generate source code.'], - '$validationSuccess' => true, - '$sourceClassExists' => true, - '$resultClassExists' => false, - '$makeResultDirSuccess' => true, - '$resultFileExists' => true, - '$willWriteCode' => false, + 'errors' => ['Can\'t generate source code.'], + 'validationSuccess' => true, + 'sourceClassExists' => true, + 'resultClassExists' => false, + 'makeResultDirSuccess' => true, + 'resultFileExists' => true, + 'willWriteCode' => false, ], 'generate_ok' => [] ]; @@ -292,7 +286,7 @@ class EntityAbstractTest extends \PHPUnit_Framework_TestCase if ($willWriteCode) { $ioObject->expects($this->once())->method('writeResultFile')->with(self::RESULT_FILE, self::RESULT_CODE); } - $ioObject->expects($this->any())->method('getResultFileName')->willReturn(self::RESULT_FILE); + $ioObject->expects($this->any())->method('generateResultFileName')->willReturn(self::RESULT_FILE); return [ 'source_class' => $mocks['source_class'], diff --git a/lib/internal/Magento/Framework/Code/Test/Unit/Generator/IoTest.php b/lib/internal/Magento/Framework/Code/Test/Unit/Generator/IoTest.php index bd3a34bc4710363c71d0bbd892364ff6e06714cb..33b12746656a63722623aea045b237712ea6c75f 100644 --- a/lib/internal/Magento/Framework/Code/Test/Unit/Generator/IoTest.php +++ b/lib/internal/Magento/Framework/Code/Test/Unit/Generator/IoTest.php @@ -5,6 +5,10 @@ */ namespace Magento\Framework\Code\Test\Unit\Generator; +use Magento\Framework\Component\ComponentRegistrar; +use Magento\Framework\Exception\FileSystemException; +use Magento\Framework\Phrase; + class IoTest extends \PHPUnit_Framework_TestCase { /**#@+ @@ -16,8 +20,6 @@ class IoTest extends \PHPUnit_Framework_TestCase const CLASS_FILE_NAME = 'class/file/name'; - const FILE_NAME = 'test_file'; - const FILE_CONTENT = "content"; /**#@-*/ @@ -29,16 +31,18 @@ class IoTest extends \PHPUnit_Framework_TestCase */ protected $_generationDirectory; - /** - * @var \Magento\Framework\Code\Generator\Io - */ + /** @var \Magento\Framework\Code\Generator\Io */ protected $_object; - /** - * @var \Magento\Framework\Filesystem|\PHPUnit_Framework_MockObject_MockObject - */ + /** @var \Magento\Framework\Filesystem|\PHPUnit_Framework_MockObject_MockObject */ protected $_filesystemDriverMock; + /** @var string */ + protected $existingFile = '/Magento/Class/Exists.php'; + + /** @var string */ + protected $nonExistingFile = '/Magento/Class/Does/Not/Exists.php'; + protected function setUp() { $this->_generationDirectory = rtrim(self::GENERATION_DIRECTORY, '/') . '/'; @@ -68,26 +72,68 @@ class IoTest extends \PHPUnit_Framework_TestCase public function testGetResultFileName() { $expectedFileName = self::GENERATION_DIRECTORY . '/class/name.php'; - $this->assertEquals($expectedFileName, $this->_object->getResultFileName(self::CLASS_NAME)); + $this->assertEquals($expectedFileName, $this->_object->generateResultFileName(self::CLASS_NAME)); } - public function testWriteResultFile() + /** + * @dataProvider testWriteResultFileAlreadyExistsDataProvider + */ + public function testWriteResultFileAlreadyExists($resultFileName, $fileExists, $exceptionDuringRename, $success) { $this->_filesystemDriverMock->expects($this->once()) ->method('filePutContents') ->with( - $this->stringContains(self::FILE_NAME), + $this->stringContains($resultFileName), "<?php\n" . self::FILE_CONTENT )->willReturn(true); + $isExistsInvocationCount = $exceptionDuringRename ? 1 : 0; + $this->_filesystemDriverMock->expects($this->exactly($isExistsInvocationCount)) + ->method('isExists') + ->willReturn($fileExists); + + if (!$exceptionDuringRename) { + $renameMockEvent = $this->returnValue(true); + } else if ($fileExists) { + $renameMockEvent = $this->throwException(new FileSystemException(new Phrase('File already exists'))); + } else { + $exceptionMessage = 'Some error renaming file'; + $renameMockEvent = $this->throwException(new FileSystemException(new Phrase($exceptionMessage))); + $this->setExpectedException('\Magento\Framework\Exception\FileSystemException', $exceptionMessage); + } $this->_filesystemDriverMock->expects($this->once()) ->method('rename') ->with( - $this->stringContains(self::FILE_NAME), - self::FILE_NAME - )->willReturn(true); + $this->stringContains($resultFileName), + $resultFileName + )->will($renameMockEvent); //Throw exception or return true - $this->assertTrue($this->_object->writeResultFile(self::FILE_NAME, self::FILE_CONTENT)); + $this->assertSame($success, $this->_object->writeResultFile($resultFileName, self::FILE_CONTENT)); + } + + public function testWriteResultFileAlreadyExistsDataProvider() + { + return [ + 'Writing file succeeds: writeResultFile succeeds' => [ + 'resultFileName' => $this->nonExistingFile, + 'fileExists' => false, + 'exceptionDuringRename' => false, + 'success' => true + + ], + 'Writing file fails because class already exists on disc: writeResultFile succeeds' => [ + 'resultFileName' => $this->existingFile, + 'fileExists' => true, + 'exceptionDuringRename' => true, + 'success' => true + ], + 'Error renaming file, btu class does not exist on disc: writeResultFile throws exception and fails' => [ + 'resultFileName' => $this->nonExistingFile, + 'fileExists' => false, + 'exceptionDuringRename' => true, + 'success' => false + ] + ]; } public function testMakeGenerationDirectoryWritable() @@ -136,18 +182,31 @@ class IoTest extends \PHPUnit_Framework_TestCase $this->assertEquals($this->_generationDirectory, $this->_object->getGenerationDirectory()); } - public function testFileExists() + /** + * @dataProvider fileExistsDataProvider + * @param $fileName + * @param $exists + */ + public function testFileExists($fileName, $exists) { $this->_filesystemDriverMock->expects( $this->once() )->method( 'isExists' )->with( - $this->equalTo(self::FILE_NAME) + $this->equalTo($fileName) )->will( - $this->returnValue(false) + $this->returnValue($exists) ); - $this->assertFalse($this->_object->fileExists(self::FILE_NAME)); + $this->assertSame($exists, $this->_object->fileExists($fileName)); + } + + public function fileExistsDataProvider() + { + return [ + ['fileName' => $this->existingFile, 'exists' => true], + ['fileName' => $this->nonExistingFile, 'exists' => false] + ]; } } diff --git a/lib/internal/Magento/Framework/Code/Test/Unit/GeneratorTest.php b/lib/internal/Magento/Framework/Code/Test/Unit/GeneratorTest.php index 88a043753daa73776e941541651e7cc3b237e555..c289ba47967435ded674df11cc9af595e280909e 100644 --- a/lib/internal/Magento/Framework/Code/Test/Unit/GeneratorTest.php +++ b/lib/internal/Magento/Framework/Code/Test/Unit/GeneratorTest.php @@ -8,6 +8,10 @@ namespace Magento\Framework\Code\Test\Unit; +use Magento\Framework\Code\Generator; +use Magento\Framework\Code\Generator\DefinedClasses; +use Magento\Framework\Code\Generator\Io; + class GeneratorTest extends \PHPUnit_Framework_TestCase { /** @@ -27,34 +31,41 @@ class GeneratorTest extends \PHPUnit_Framework_TestCase ]; /** - * Model under test + * System under test * * @var \Magento\Framework\Code\Generator */ protected $model; - /** - * @var \PHPUnit_Framework_MockObject_MockObject|Generator\Io - */ + /** @var \PHPUnit_Framework_MockObject_MockObject|Io */ protected $ioObjectMock; + /** @var \Magento\Framework\Code\Generator\DefinedClasses | \PHPUnit_Framework_MockObject_MockObject */ + protected $definedClassesMock; + protected function setUp() { + $this->definedClassesMock = $this->getMock('\Magento\Framework\Code\Generator\DefinedClasses'); $this->ioObjectMock = $this->getMockBuilder('\Magento\Framework\Code\Generator\Io') ->disableOriginalConstructor() ->getMock(); - } - - protected function tearDown() - { - unset($this->model); + $this->model = $this->buildModel( + $this->ioObjectMock, + [ + 'factory' => '\Magento\Framework\ObjectManager\Code\Generator\Factory', + 'proxy' => '\Magento\Framework\ObjectManager\Code\Generator\Proxy', + 'interceptor' => '\Magento\Framework\Interception\Code\Generator\Interceptor' + ], + $this->definedClassesMock + ); } public function testGetGeneratedEntities() { - $this->model = new \Magento\Framework\Code\Generator( + $this->model = $this->buildModel( $this->ioObjectMock, - ['factory', 'proxy', 'interceptor'] + ['factory', 'proxy', 'interceptor'], + $this->definedClassesMock ); $this->assertEquals(array_values($this->expectedEntities), $this->model->getGeneratedEntities()); } @@ -65,14 +76,6 @@ class GeneratorTest extends \PHPUnit_Framework_TestCase */ public function testGenerateClass($className, $entityType) { - $this->model = new \Magento\Framework\Code\Generator( - $this->ioObjectMock, - [ - 'factory' => '\Magento\Framework\ObjectManager\Code\Generator\Factory', - 'proxy' => '\Magento\Framework\ObjectManager\Code\Generator\Proxy', - 'interceptor' => '\Magento\Framework\Interception\Code\Generator\Interceptor' - ] - ); $objectManagerMock = $this->getMock('Magento\Framework\ObjectManagerInterface'); $fullClassName = $className . $entityType; $entityGeneratorMock = $this->getMockBuilder('\Magento\Framework\Code\Generator\EntityAbstract') @@ -83,35 +86,8 @@ class GeneratorTest extends \PHPUnit_Framework_TestCase $this->model->generateClass($fullClassName); } - /** - * @dataProvider generateValidClassDataProvider - */ - public function testGenerateClassWithExistName($className, $entityType) - { - $definedClassesMock = $this->getMock('Magento\Framework\Code\Generator\DefinedClasses'); - $definedClassesMock->expects($this->any()) - ->method('isClassLoadableFromDisc') - ->willReturn(true); - $this->model = new \Magento\Framework\Code\Generator( - $this->ioObjectMock, - [ - 'factory' => '\Magento\Framework\ObjectManager\Code\Generator\Factory', - 'proxy' => '\Magento\Framework\ObjectManager\Code\Generator\Proxy', - 'interceptor' => '\Magento\Framework\Interception\Code\Generator\Interceptor' - ], - $definedClassesMock - ); - - $this->assertEquals( - \Magento\Framework\Code\Generator::GENERATION_SKIP, - $this->model->generateClass($className . $entityType) - ); - } - public function testGenerateClassWithWrongName() { - $this->model = new \Magento\Framework\Code\Generator($this->ioObjectMock); - $this->assertEquals( \Magento\Framework\Code\Generator::GENERATION_ERROR, $this->model->generateClass(self::SOURCE_CLASS) @@ -123,15 +99,6 @@ class GeneratorTest extends \PHPUnit_Framework_TestCase */ public function testGenerateClassWithError() { - $this->model = new \Magento\Framework\Code\Generator( - $this->ioObjectMock, - [ - 'factory' => '\Magento\Framework\ObjectManager\Code\Generator\Factory', - 'proxy' => '\Magento\Framework\ObjectManager\Code\Generator\Proxy', - 'interceptor' => '\Magento\Framework\Interception\Code\Generator\Interceptor' - ] - ); - $expectedEntities = array_values($this->expectedEntities); $resultClassName = self::SOURCE_CLASS . ucfirst(array_shift($expectedEntities)); $objectManagerMock = $this->getMock('Magento\Framework\ObjectManagerInterface'); @@ -143,6 +110,32 @@ class GeneratorTest extends \PHPUnit_Framework_TestCase $this->model->generateClass($resultClassName); } + /** + * @dataProvider trueFalseDataProvider + */ + public function testGenerateClassWithExistName($fileExists) + { + $this->definedClassesMock->expects($this->any()) + ->method('isClassLoadableFromDisc') + ->willReturn(true); + + $resultClassFileName = '/Magento/Path/To/Class.php'; + $this->ioObjectMock->expects($this->once())->method('generateResultFileName')->willReturn($resultClassFileName); + $this->ioObjectMock->expects($this->once())->method('fileExists')->willReturn($fileExists); + $includeFileInvokeCount = $fileExists ? 1 : 0; + $this->ioObjectMock->expects($this->exactly($includeFileInvokeCount))->method('includeFile'); + + $this->assertEquals( + \Magento\Framework\Code\Generator::GENERATION_SKIP, + $this->model->generateClass('Magento\GeneratedClass\Factory') + ); + } + + public function trueFalseDataProvider() + { + return [[true], [false]]; + } + /** * Data provider for generate class tests * @@ -160,4 +153,17 @@ class GeneratorTest extends \PHPUnit_Framework_TestCase } return $data; } + + /** + * Build SUT object + * + * @param Io $ioObject + * @param array $generatedEntities + * @param DefinedClasses $definedClasses + * @return Generator + */ + private function buildModel(Io $ioObject, array $generatedEntities, DefinedClasses $definedClasses) + { + return new Generator($ioObject, $generatedEntities, $definedClasses); + } } diff --git a/lib/internal/Magento/Framework/Interception/Test/Unit/Code/Generator/InterceptorTest.php b/lib/internal/Magento/Framework/Interception/Test/Unit/Code/Generator/InterceptorTest.php index 78f5759d9fa77707de1e1c1bb1cf39b5c4596fdc..97f1ff1b368d56130f72c8c61790f6e8e2a42f20 100644 --- a/lib/internal/Magento/Framework/Interception/Test/Unit/Code/Generator/InterceptorTest.php +++ b/lib/internal/Magento/Framework/Interception/Test/Unit/Code/Generator/InterceptorTest.php @@ -56,7 +56,7 @@ class InterceptorTest extends \PHPUnit_Framework_TestCase $this->classGeneratorMock->expects($this->once())->method('generate') ->will($this->returnValue('source code example')); $model->expects($this->once())->method('_validateData')->will($this->returnValue(true)); - $this->ioObjectMock->expects($this->any())->method('getResultFileName')->with('Exception_Interceptor'); + $this->ioObjectMock->expects($this->any())->method('generateResultFileName')->with('Exception_Interceptor'); $this->assertEquals('', $model->generate()); } } diff --git a/lib/internal/Magento/Framework/Module/DependencyChecker.php b/lib/internal/Magento/Framework/Module/DependencyChecker.php index 44f771fb6ca2083bb7363542cb11d2e2488d318a..71c811daf3c46c390e34299dd82647e052ddf8a9 100644 --- a/lib/internal/Magento/Framework/Module/DependencyChecker.php +++ b/lib/internal/Magento/Framework/Module/DependencyChecker.php @@ -33,6 +33,11 @@ class DependencyChecker */ private $graph; + /** + * @var PackageInfo + */ + protected $packageInfo; + /** * Constructor * @@ -44,8 +49,8 @@ class DependencyChecker { $this->enabledModuleList = $list->getNames(); $this->fullModuleList = $loader->load(); - $packageInfo = $packageInfoFactory->create(); - $this->graph = $this->createGraph($packageInfo); + $this->packageInfo = $packageInfoFactory->create(); + $this->graph = $this->createGraph(); } /** @@ -93,7 +98,11 @@ class DependencyChecker foreach ($moduleNames as $moduleName) { $dependenciesMissing = []; $paths = $this->graph->findPathsToReachableNodes($moduleName, $graphMode); - foreach (array_keys($this->fullModuleList) as $module) { + $modules = array_merge( + array_keys($this->fullModuleList), + $this->packageInfo->getNonExistingDependencies() + ); + foreach ($modules as $module) { if (isset($paths[$module])) { if ($isEnable && !in_array($module, $enabledModules)) { $dependenciesMissing[$module] = $paths[$module]; @@ -110,10 +119,9 @@ class DependencyChecker /** * Create the dependency graph * - * @param PackageInfo $packageInfo * @return Graph */ - private function createGraph(PackageInfo $packageInfo) + private function createGraph() { $nodes = []; $dependencies = []; @@ -121,13 +129,15 @@ class DependencyChecker // build the graph data foreach (array_keys($this->fullModuleList) as $moduleName) { $nodes[] = $moduleName; - foreach ($packageInfo->getRequire($moduleName) as $dependModuleName) { + foreach ($this->packageInfo->getRequire($moduleName) as $dependModuleName) { if ($dependModuleName) { $dependencies[] = [$moduleName, $dependModuleName]; } } } - $nodes = array_unique($nodes); + $nodes = array_unique( + array_merge($nodes, $this->packageInfo->getNonExistingDependencies()) + ); return new Graph($nodes, $dependencies); } diff --git a/lib/internal/Magento/Framework/Module/PackageInfo.php b/lib/internal/Magento/Framework/Module/PackageInfo.php index 97fd828c36d6c3f0540ff8d37808fa172c5f5213..1e2ed5064c8e69bb067e82ae2173ef01b5e1f59a 100644 --- a/lib/internal/Magento/Framework/Module/PackageInfo.php +++ b/lib/internal/Magento/Framework/Module/PackageInfo.php @@ -53,6 +53,11 @@ class PackageInfo */ private $componentRegistrar; + /** + * @var array + */ + protected $nonExistingDependencies = []; + /** * Constructor * @@ -104,7 +109,65 @@ class PackageInfo public function getModuleName($packageName) { $this->load(); - return isset($this->packageModuleMap[$packageName]) ? $this->packageModuleMap[$packageName] : ''; + + $moduleName = null; + if (isset($this->packageModuleMap[$packageName])) { + $moduleName = $this->packageModuleMap[$packageName]; + } elseif ($this->isMagentoPackage($packageName)) { + $moduleName = $this->convertPackageNameToModuleName($packageName); + $this->addNonExistingDependency($moduleName); + } + + return $moduleName; + } + + /** + * Add non existing dependency + * + * @param string $dependency + * @return void + */ + protected function addNonExistingDependency($dependency) + { + if (!isset($this->nonExistingDependencies[$dependency])) { + $this->nonExistingDependencies[$dependency] = $dependency; + } + } + + /** + * Return list of non existing dependencies + * + * @return array + */ + public function getNonExistingDependencies() + { + return $this->nonExistingDependencies; + } + + /** + * Build module name based on internal package name + * + * @param string $packageName + * @return string|null + */ + protected function convertPackageNameToModuleName($packageName) + { + $moduleName = str_replace('magento/module-', '', $packageName); + $moduleName = str_replace('-', ' ', $moduleName); + $moduleName = str_replace(' ', '', ucwords($moduleName)); + + return 'Magento_' . $moduleName; + } + + /** + * Check if package is internal magento module + * + * @param string $packageName + * @return bool + */ + protected function isMagentoPackage($packageName) + { + return strpos($packageName, 'magento/module-') === 0; } /** diff --git a/lib/internal/Magento/Framework/Module/Test/Unit/DependencyCheckerTest.php b/lib/internal/Magento/Framework/Module/Test/Unit/DependencyCheckerTest.php index eb09d4a41ac3bfdfae6e5d06cf44bfba8444b62a..0d7774d8ddad8fef157ddfc18fdf865d1ecd76c9 100644 --- a/lib/internal/Magento/Framework/Module/Test/Unit/DependencyCheckerTest.php +++ b/lib/internal/Magento/Framework/Module/Test/Unit/DependencyCheckerTest.php @@ -70,10 +70,12 @@ class DependencyCheckerTest extends \PHPUnit_Framework_TestCase public function testCheckDependenciesWhenDisableModules() { - $this->listMock - ->expects($this->any()) + $this->listMock->expects($this->any()) ->method('getNames') ->will($this->returnValue(['A', 'B', 'C', 'D', 'E'])); + $this->packageInfoMock->expects($this->atLeastOnce()) + ->method('getNonExistingDependencies') + ->willReturn([]); $this->checker = new DependencyChecker($this->listMock, $this->loaderMock, $this->packageInfoFactoryMock); $actual = $this->checker->checkDependenciesWhenDisableModules(['B', 'D']); @@ -83,6 +85,9 @@ class DependencyCheckerTest extends \PHPUnit_Framework_TestCase public function testCheckDependenciesWhenDisableModulesWithCurEnabledModules() { + $this->packageInfoMock->expects($this->atLeastOnce()) + ->method('getNonExistingDependencies') + ->willReturn([]); $this->checker = new DependencyChecker($this->listMock, $this->loaderMock, $this->packageInfoFactoryMock); $actual = $this->checker->checkDependenciesWhenDisableModules(['B', 'D'], ['C', 'D', 'E']); @@ -92,10 +97,12 @@ class DependencyCheckerTest extends \PHPUnit_Framework_TestCase public function testCheckDependenciesWhenEnableModules() { - $this->listMock - ->expects($this->any()) + $this->listMock->expects($this->any()) ->method('getNames') ->will($this->returnValue(['C'])); + $this->packageInfoMock->expects($this->atLeastOnce()) + ->method('getNonExistingDependencies') + ->willReturn([]); $this->checker = new DependencyChecker($this->listMock, $this->loaderMock, $this->packageInfoFactoryMock); $actual = $this->checker->checkDependenciesWhenEnableModules(['B', 'D']); $expected = [ @@ -107,6 +114,9 @@ class DependencyCheckerTest extends \PHPUnit_Framework_TestCase public function testCheckDependenciesWhenEnableModulesWithCurEnabledModules() { + $this->packageInfoMock->expects($this->atLeastOnce()) + ->method('getNonExistingDependencies') + ->willReturn([]); $this->checker = new DependencyChecker($this->listMock, $this->loaderMock, $this->packageInfoFactoryMock); $actual = $this->checker->checkDependenciesWhenEnableModules(['B', 'D'], ['C']); $expected = [ diff --git a/lib/internal/Magento/Framework/Module/Test/Unit/PackageInfoTest.php b/lib/internal/Magento/Framework/Module/Test/Unit/PackageInfoTest.php index 8a2512c485fd1f1d98cb02ab45019ebd9f3e4c43..4328b62c0c6ce30ee72ed23e5a9477f7f39b4859 100644 --- a/lib/internal/Magento/Framework/Module/Test/Unit/PackageInfoTest.php +++ b/lib/internal/Magento/Framework/Module/Test/Unit/PackageInfoTest.php @@ -57,6 +57,11 @@ class PackageInfoTest extends \PHPUnit_Framework_TestCase $this->assertEquals('C', $this->packageInfo->getModuleName('c')); $this->assertEquals('D', $this->packageInfo->getModuleName('d')); $this->assertEquals('E', $this->packageInfo->getModuleName('e')); + $this->assertEquals( + 'Magento_TestModuleName', + $this->packageInfo->getModuleName('magento/module-test-module-name') + ); + $this->assertArrayHasKey('Magento_TestModuleName', $this->packageInfo->getNonExistingDependencies()); } public function testGetPackageName() diff --git a/lib/internal/Magento/Framework/ObjectManager/Code/Generator/Repository.php b/lib/internal/Magento/Framework/ObjectManager/Code/Generator/Repository.php index 496ba2e8d173a62d6fbc89560d3925af7ff43234..6922234a56df3321cbbb4aba73a12acf97b9c072 100644 --- a/lib/internal/Magento/Framework/ObjectManager/Code/Generator/Repository.php +++ b/lib/internal/Magento/Framework/ObjectManager/Code/Generator/Repository.php @@ -467,20 +467,20 @@ class Repository extends \Magento\Framework\Code\Generator\EntityAbstract { $body = "\$collection = \$this->" . $this->_getSourceCollectionFactoryPropertyName() . "->create();\n" . "\$this->extensionAttributesJoinProcessor->process(\$collection);\n" - . "foreach (\$criteria->getFilterGroups() as \$filterGroup) {\n" + . "foreach (\$searchCriteria->getFilterGroups() as \$filterGroup) {\n" . " foreach (\$filterGroup->getFilters() as \$filter) {\n" . " \$condition = \$filter->getConditionType() ? \$filter->getConditionType() : 'eq';\n" . " \$collection->addFieldToFilter(\$filter->getField(), [\$condition => \$filter->getValue()]);\n" . " }\n" . "}\n" - . "\$collection->setCurPage(\$criteria->getCurrentPage());\n" - . "\$collection->setPageSize(\$criteria->getPageSize());\n" + . "\$collection->setCurPage(\$searchCriteria->getCurrentPage());\n" + . "\$collection->setPageSize(\$searchCriteria->getPageSize());\n" . "return \$collection;\n"; return [ 'name' => 'getList', 'parameters' => [ [ - 'name' => 'criteria', + 'name' => 'searchCriteria', 'type' => self::SEARCH_CRITERIA, ], ], @@ -490,7 +490,7 @@ class Repository extends \Magento\Framework\Code\Generator\EntityAbstract 'tags' => [ [ 'name' => 'param', - 'description' => self::SEARCH_CRITERIA . ' $criteria', + 'description' => self::SEARCH_CRITERIA . ' $searchCriteria', ], [ 'name' => 'return', diff --git a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/ConverterTest.php b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/ConverterTest.php index 10bafa24672ad8ed72d942d6de81262d8f2434e8..8578107b4cf70fffe960aa52b2b9d11e9bf07070 100644 --- a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/ConverterTest.php +++ b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/ConverterTest.php @@ -105,7 +105,7 @@ class ConverterTest extends \PHPUnit_Framework_TestCase //Mocking generation $this->ioObjectMock->expects($this->any()) - ->method('getResultFileName') + ->method('generateResultFileName') ->with(self::RESULT_CLASS_NAME) ->will($this->returnValue($resultFileName)); $this->ioObjectMock->expects($this->once()) diff --git a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/FactoryTest.php b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/FactoryTest.php index 80d63e0133df7c7f29651628d1e4285bd1748880..3a477ec43a52c4b6a56fcc4235554fdd8585288e 100644 --- a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/FactoryTest.php +++ b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/FactoryTest.php @@ -34,7 +34,7 @@ class FactoryTest extends \PHPUnit_Framework_TestCase ] ); - $this->ioObjectMock->expects($this->once())->method('getResultFileName') + $this->ioObjectMock->expects($this->once())->method('generateResultFileName') ->with('\Magento\Framework\ObjectManager\Code\Generator\SampleFactory') ->will($this->returnValue('sample_file.php')); $factoryCode = file_get_contents(__DIR__ . '/_files/SampleFactory.txt'); diff --git a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/GenerateRepositoryTest.php b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/GenerateRepositoryTest.php index a2744ca17becda4478dff35173d9982b33ba2ae3..27cea41af83218ebb2810b1763e897ab1d1710c7 100644 --- a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/GenerateRepositoryTest.php +++ b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/GenerateRepositoryTest.php @@ -54,7 +54,7 @@ class GenerateRepositoryTest extends \PHPUnit_Framework_TestCase ); $this->ioObjectMock->expects($this->once()) - ->method('getResultFileName') + ->method('generateResultFileName') ->with('\Magento\Framework\ObjectManager\Code\Generator\SampleRepository') ->willReturn('SampleRepository.php'); diff --git a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/ProxyTest.php b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/ProxyTest.php index 4fb66556991ccaec70b2e361094db556448a3e23..7eb9795742d1f7ce96b369e8c057e7d15b1d540e 100644 --- a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/ProxyTest.php +++ b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/ProxyTest.php @@ -34,7 +34,7 @@ class ProxyTest extends \PHPUnit_Framework_TestCase ); $sampleProxyCode = file_get_contents(__DIR__ . '/_files/SampleProxy.txt'); - $this->ioObjectMock->expects($this->once())->method('getResultFileName') + $this->ioObjectMock->expects($this->once())->method('generateResultFileName') ->with('\Magento\Framework\ObjectManager\Code\Generator\Sample_Proxy') ->will($this->returnValue('sample_file.php')); $this->ioObjectMock->expects($this->once())->method('writeResultFile') diff --git a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/_files/SampleRepository.txt b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/_files/SampleRepository.txt index d135ca64dd1fccfc3382920cd9d3a6d02daa6750..803d9828cf54dd50d5fcf56752d61d9f0937103f 100644 --- a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/_files/SampleRepository.txt +++ b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/Code/Generator/_files/SampleRepository.txt @@ -103,21 +103,21 @@ class SampleRepository implements \Magento\Framework\ObjectManager\Code\Generato /** * Find entities by criteria * - * @param \Magento\Framework\Api\SearchCriteria $criteria + * @param \Magento\Framework\Api\SearchCriteria $searchCriteria * @return \Magento\Framework\ObjectManager\Code\Generator\SampleInterface[] */ - public function getList(\Magento\Framework\Api\SearchCriteria $criteria) + public function getList(\Magento\Framework\Api\SearchCriteria $searchCriteria) { $collection = $this->sampleInterfaceSearchResultFactory->create(); $this->extensionAttributesJoinProcessor->process($collection); - foreach ($criteria->getFilterGroups() as $filterGroup) { + foreach ($searchCriteria->getFilterGroups() as $filterGroup) { foreach ($filterGroup->getFilters() as $filter) { $condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq'; $collection->addFieldToFilter($filter->getField(), [$condition => $filter->getValue()]); } } - $collection->setCurPage($criteria->getCurrentPage()); - $collection->setPageSize($criteria->getPageSize()); + $collection->setCurPage($searchCriteria->getCurrentPage()); + $collection->setPageSize($searchCriteria->getPageSize()); return $collection; } diff --git a/lib/internal/Magento/Framework/Pricing/Adjustment/Calculator.php b/lib/internal/Magento/Framework/Pricing/Adjustment/Calculator.php index cf7e2eda9be1d2ec37872b965d42ada8f75e6dbe..6140e7c2581be6d5ea2dbd15be8e352ec0eeb773 100644 --- a/lib/internal/Magento/Framework/Pricing/Adjustment/Calculator.php +++ b/lib/internal/Magento/Framework/Pricing/Adjustment/Calculator.php @@ -40,6 +40,7 @@ class Calculator implements CalculatorInterface public function getAmount($amount, SaleableInterface $saleableItem, $exclude = null, $context = []) { $baseAmount = $fullAmount = $amount; + $previousAdjustments = 0; $adjustments = []; foreach ($saleableItem->getPriceInfo()->getAdjustments() as $adjustment) { $code = $adjustment->getAdjustmentCode(); @@ -51,7 +52,7 @@ class Calculator implements CalculatorInterface $adjust = $adjustment->extractAdjustment($baseAmount, $saleableItem, $context); $baseAmount -= $adjust; $fullAmount = $adjustment->applyAdjustment($fullAmount, $saleableItem, $context); - $adjust = $fullAmount - $baseAmount; + $adjust = $fullAmount - $baseAmount - $previousAdjustments; if (!$toExclude) { $adjustments[$code] = $adjust; } @@ -63,6 +64,7 @@ class Calculator implements CalculatorInterface $adjust = $newAmount - $fullAmount; $adjustments[$code] = $adjust; $fullAmount = $newAmount; + $previousAdjustments += $adjust; } } diff --git a/lib/internal/Magento/Framework/Pricing/Test/Unit/Adjustment/CalculatorTest.php b/lib/internal/Magento/Framework/Pricing/Test/Unit/Adjustment/CalculatorTest.php index 9aa6eccbe0922a693cb25aab9a1a3e8195ac78ee..7865cf7db856610c537c797a992f0b68ee283710 100644 --- a/lib/internal/Magento/Framework/Pricing/Test/Unit/Adjustment/CalculatorTest.php +++ b/lib/internal/Magento/Framework/Pricing/Test/Unit/Adjustment/CalculatorTest.php @@ -40,39 +40,30 @@ class CalculatorTest extends \PHPUnit_Framework_TestCase */ public function testGetAmount() { - $amount = 10; - $fullAmount = $amount; - $newAmount = 15; - $taxAdjustmentCode = 'tax'; + $amountInclTax = 10; + $taxAdjustment = 2; + $weeeAdjustment = 5; + $totalAmount = $amountInclTax + $weeeAdjustment; + $weeeAdjustmentCode = 'weee'; - $adjustment = 5; + $taxAdjustmentCode = 'tax'; $expectedAdjustments = [ - $taxAdjustmentCode => $adjustment, - $weeeAdjustmentCode => $adjustment, + $weeeAdjustmentCode => $weeeAdjustment, + $taxAdjustmentCode => $taxAdjustment, ]; - $productMock = $this->getMockBuilder('Magento\Catalog\Model\Product') + $amountBaseMock = $this->getMockBuilder('Magento\Framework\Pricing\Amount\Base') ->disableOriginalConstructor() - ->setMethods(['getPriceInfo', '__wakeup']) ->getMock(); + $this->amountFactoryMock->expects($this->once()) + ->method('create') + ->with($this->equalTo($totalAmount), $this->equalTo($expectedAdjustments)) + ->will($this->returnValue($amountBaseMock)); - $taxAdjustmentMock = $this->getMockBuilder('Magento\Tax\Pricing\Adjustment') + $productMock = $this->getMockBuilder('Magento\Catalog\Model\Product') ->disableOriginalConstructor() + ->setMethods(['getPriceInfo', '__wakeup']) ->getMock(); - $taxAdjustmentMock->expects($this->once()) - ->method('getAdjustmentCode') - ->will($this->returnValue($taxAdjustmentCode)); - $taxAdjustmentMock->expects($this->once()) - ->method('isIncludedInBasePrice') - ->will($this->returnValue(true)); - $taxAdjustmentMock->expects($this->once()) - ->method('extractAdjustment') - ->with($this->equalTo($amount), $this->equalTo($productMock)) - ->will($this->returnValue($adjustment)); - $taxAdjustmentMock->expects($this->once()) - ->method('applyAdjustment') - ->with($this->equalTo($fullAmount), $this->equalTo($productMock)) - ->will($this->returnValue($amount)); $weeeAdjustmentMock = $this->getMockBuilder('Magento\Weee\Pricing\Adjustment') ->disableOriginalConstructor() @@ -85,15 +76,33 @@ class CalculatorTest extends \PHPUnit_Framework_TestCase ->will($this->returnValue(false)); $weeeAdjustmentMock->expects($this->once()) ->method('isIncludedInDisplayPrice') - ->with($this->equalTo($productMock)) ->will($this->returnValue(true)); $weeeAdjustmentMock->expects($this->once()) ->method('applyAdjustment') - ->with($this->equalTo($fullAmount), $this->equalTo($productMock)) - ->will($this->returnValue($newAmount)); + ->with($this->equalTo($amountInclTax), $this->equalTo($productMock)) + ->will($this->returnValue($weeeAdjustment + $amountInclTax)); - $adjustments = [$taxAdjustmentMock, $weeeAdjustmentMock]; + $taxAdjustmentMock = $this->getMockBuilder('Magento\Tax\Pricing\Adjustment') + ->disableOriginalConstructor() + ->getMock(); + $taxAdjustmentMock->expects($this->once()) + ->method('getAdjustmentCode') + ->will($this->returnValue($taxAdjustmentCode)); + $taxAdjustmentMock->expects($this->once()) + ->method('isIncludedInBasePrice') + ->will($this->returnValue(true)); + $taxAdjustmentMock->expects($this->once()) + ->method('extractAdjustment') + ->with($this->equalTo($amountInclTax), $this->equalTo($productMock)) + ->will($this->returnValue($taxAdjustment)); + $taxAdjustmentMock->expects($this->once()) + ->method('applyAdjustment') + ->with($this->equalTo($totalAmount), $this->equalTo($productMock)) + ->will($this->returnValue($totalAmount)); + $taxAdjustmentMock->expects($this->never()) + ->method('isIncludedInDisplayPrice'); + $adjustments = [$weeeAdjustmentMock, $taxAdjustmentMock]; $priceInfoMock = $this->getMockBuilder('\Magento\Framework\Pricing\PriceInfo\Base') ->disableOriginalConstructor() ->getMock(); @@ -105,15 +114,7 @@ class CalculatorTest extends \PHPUnit_Framework_TestCase ->method('getPriceInfo') ->will($this->returnValue($priceInfoMock)); - $amountBaseMock = $this->getMockBuilder('Magento\Framework\Pricing\Amount\Base') - ->disableOriginalConstructor() - ->getMock(); - - $this->amountFactoryMock->expects($this->once()) - ->method('create') - ->with($this->equalTo($newAmount), $this->equalTo($expectedAdjustments)) - ->will($this->returnValue($amountBaseMock)); - $result = $this->model->getAmount($amount, $productMock); + $result = $this->model->getAmount($amountInclTax, $productMock); $this->assertInstanceOf('Magento\Framework\Pricing\Amount\AmountInterface', $result); } diff --git a/lib/internal/Magento/Framework/TestFramework/Unit/Autoloader/ExtensionGeneratorAutoloader.php b/lib/internal/Magento/Framework/TestFramework/Unit/Autoloader/ExtensionGeneratorAutoloader.php index 9f14464d01c877ddbb5c8e097c5d5646d1922e3e..4382d23df89eeac89e54fddbaba8df862dcc6262 100644 --- a/lib/internal/Magento/Framework/TestFramework/Unit/Autoloader/ExtensionGeneratorAutoloader.php +++ b/lib/internal/Magento/Framework/TestFramework/Unit/Autoloader/ExtensionGeneratorAutoloader.php @@ -41,7 +41,7 @@ class ExtensionGeneratorAutoloader return false; } - $resultFileName = $this->generatorIo->getResultFileName($className); + $resultFileName = $this->generatorIo->generateResultFileName($className); if (!$this->generatorIo->fileExists($resultFileName)) { $this->generatorIo->makeResultFileDirectory($className); diff --git a/lib/internal/Magento/Framework/View/Asset/PreProcessor/AlternativeSource.php b/lib/internal/Magento/Framework/View/Asset/PreProcessor/AlternativeSource.php index d727bd9fa40598dba7c3cf65330c8da88155d361..95fe57227895b643dd4bbbbdc8596699fb692918 100644 --- a/lib/internal/Magento/Framework/View/Asset/PreProcessor/AlternativeSource.php +++ b/lib/internal/Magento/Framework/View/Asset/PreProcessor/AlternativeSource.php @@ -96,7 +96,7 @@ class AlternativeSource implements AlternativeSourceInterface } try { - $this->lockerProcess->lockProcess($this->lockName . sprintf('%x', crc32($path . $content))); + $this->lockerProcess->lockProcess($this->lockName); $module = $chain->getAsset()->getModule(); diff --git a/lib/internal/Magento/Framework/View/Element/Html/Select.php b/lib/internal/Magento/Framework/View/Element/Html/Select.php index ab54697632aceffbda35a6fee7debca60dc6e3d8..884c11fe91950eca05b450eb1a8ea6b12114a23a 100644 --- a/lib/internal/Magento/Framework/View/Element/Html/Select.php +++ b/lib/internal/Magento/Framework/View/Element/Html/Select.php @@ -125,6 +125,7 @@ class Select extends \Magento\Framework\View\Element\AbstractBlock * @return string * * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) */ protected function _toHtml() { @@ -151,9 +152,11 @@ class Select extends \Magento\Framework\View\Element\AbstractBlock $isArrayOption = true; foreach ($this->getOptions() as $key => $option) { + $optgroupName = ''; if ($isArrayOption && is_array($option)) { $value = $option['value']; $label = (string)$option['label']; + $optgroupName = isset($option['optgroup-name']) ? $option['optgroup-name'] : $label; $params = !empty($option['params']) ? $option['params'] : []; } else { $value = (string)$key; @@ -163,7 +166,7 @@ class Select extends \Magento\Framework\View\Element\AbstractBlock } if (is_array($value)) { - $html .= '<optgroup label="' . $label . '">'; + $html .= '<optgroup label="' . $label . '" data-optgroup-name="' . $optgroupName . '">'; foreach ($value as $keyGroup => $optionGroup) { if (!is_array($optionGroup)) { $optionGroup = ['value' => $keyGroup, 'label' => $optionGroup]; diff --git a/lib/internal/Magento/Framework/View/Template/Html/Minifier.php b/lib/internal/Magento/Framework/View/Template/Html/Minifier.php index af80583da16e7f37c084151650869ef3f7c39c89..6b9017a1972ce499a0fdd37a300e0d7d60386412 100644 --- a/lib/internal/Magento/Framework/View/Template/Html/Minifier.php +++ b/lib/internal/Magento/Framework/View/Template/Html/Minifier.php @@ -117,7 +117,7 @@ class Minifier implements MinifierInterface '</', preg_replace( '#((?:<\?php\s+(?!echo|print|if|elseif|else)[^\?]*)\?>)\s+#', - '$1', + '$1 ', preg_replace( '#(?<!' . implode('|', $this->inlineHtmlTags) . ')\> \<#', '><', diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Element/Html/SelectTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Element/Html/SelectTest.php index d3660f32178ac024283b682bc5d93f93f00a5e39..3321d1eeaf8b6d1b1c1136faceaf08239c8413db 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Element/Html/SelectTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Element/Html/SelectTest.php @@ -127,7 +127,7 @@ class SelectTest extends \PHPUnit_Framework_TestCase . '<option value="testValue" paramKey="paramValue" >testLabel</option>' . '<option value="selectedValue" selected="selected" paramKey="paramValue" ' . ' paramKey2="paramValue2" >selectedLabel</option>' - . '<optgroup label="groupLabel">' + . '<optgroup label="groupLabel" data-optgroup-name="groupLabel">' . '<option value="groupElementValue" >GroupElementLabel</option>' . '<option value="selectedGroupElementValue" selected="selected" >SelectedGroupElementLabel</option>' . '</optgroup>' diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Template/Html/MinifierTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Template/Html/MinifierTest.php index a93962b3ae7e689f4ef943e5273b9da9afd8cffc..e598a93c243a47b7cfdab23cad76c441f7d6c010 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Template/Html/MinifierTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Template/Html/MinifierTest.php @@ -117,7 +117,7 @@ class MinifierTest extends \PHPUnit_Framework_TestCase TEXT; $expectedContent = <<<TEXT -<?php /** * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ ?><?php ?><html><head><title>Test title</title></head><body><a href="http://somelink.com/text.html">Text Link</a> <img src="test.png" alt="some text" /><?php echo \$block->someMethod(); ?> <div style="width: 800px" class="<?php echo \$block->getClass() ?>" /><script> +<?php /** * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ ?> <?php ?> <html><head><title>Test title</title></head><body><a href="http://somelink.com/text.html">Text Link</a> <img src="test.png" alt="some text" /><?php echo \$block->someMethod(); ?> <div style="width: 800px" class="<?php echo \$block->getClass() ?>" /><script> //<![CDATA[ var someVar = 123; testFunctionCall(function () { diff --git a/lib/internal/Magento/Framework/Xml/Security.php b/lib/internal/Magento/Framework/Xml/Security.php index 1fade0a2aec7e0a48389168536a452559f1f0222..87c5f271a5bb5a422e4358c8d2a7541e3b713f13 100644 --- a/lib/internal/Magento/Framework/Xml/Security.php +++ b/lib/internal/Magento/Framework/Xml/Security.php @@ -21,7 +21,7 @@ class Security */ private function heuristicScan($xmlContent) { - return strpos($xmlContent, '<!ENTITY') !== false; + return strpos($xmlContent, '<!ENTITY') === false; } /** diff --git a/lib/web/fotorama/fotorama.js b/lib/web/fotorama/fotorama.js index 445fe7d30c52ce4d576a1aafa426b75276bb9e0d..9aba3a85f0065c04581c081c677b238b83eca923 100644 --- a/lib/web/fotorama/fotorama.js +++ b/lib/web/fotorama/fotorama.js @@ -2229,14 +2229,9 @@ fotoramaVersion = '4.6.4'; stageLeft = 0, fadeStack = []; - if (Modernizr.touch) { - $wrap[STAGE_FRAME_KEY] = $('<a class="' + stageFrameClass + '" target="_blank"></a>'); - } else { - $wrap[STAGE_FRAME_KEY] = $('<div class="' + stageFrameClass + '"></div>'); - } + $wrap[STAGE_FRAME_KEY] = $('<div class="' + stageFrameClass + '"></div>'); $wrap[NAV_THUMB_FRAME_KEY] = $($.Fotorama.jst.thumb()); - $wrap[NAV_DOT_FRAME_KEY] = $($.Fotorama.jst.dots()); toDeactivate[STAGE_FRAME_KEY] = []; diff --git a/lib/web/fotorama/fotorama.min.js b/lib/web/fotorama/fotorama.min.js new file mode 100644 index 0000000000000000000000000000000000000000..591010dd42366a66923f03716e0edc5f965009cc --- /dev/null +++ b/lib/web/fotorama/fotorama.min.js @@ -0,0 +1,5 @@ +/*! + * Fotorama 4.6.4 | http://fotorama.io/license/ + */ +fotoramaVersion="4.6.4",function(t,e,n,o,i){"use strict";function r(t){var e="bez_"+o.makeArray(arguments).join("_").replace(".","p");if("function"!=typeof o.easing[e]){var n=function(t,e){var n=[null,null],o=[null,null],i=[null,null],r=function(r,a){return i[a]=3*t[a],o[a]=3*(e[a]-t[a])-i[a],n[a]=1-i[a]-o[a],r*(i[a]+r*(o[a]+r*n[a]))},a=function(t){return i[0]+t*(2*o[0]+3*n[0]*t)},s=function(t){for(var e,n=t,o=0;++o<14&&(e=r(n,0)-t,!(Math.abs(e)<.001));)n-=e/a(n);return n};return function(t){return r(s(t),1)}};o.easing[e]=function(e,o,i,r,a){return r*n([t[0],t[1]],[t[2],t[3]])(o/a)+i}}return e}function a(){}function s(t,e,n){return Math.max(isNaN(e)?-1/0:e,Math.min(isNaN(n)?1/0:n,t))}function u(t,e){return t.match(/ma/)&&t.match(/-?\d+(?!d)/g)[t.match(/3d/)?"vertical"===e?13:12:"vertical"===e?5:4]}function l(t,e){return On?+u(t.css("transform"),e):+t.css("vertical"===e?"top":"left").replace("px","")}function c(t,e){var n={};if(On)switch(e){case"vertical":n.transform="translate3d(0, "+t+"px,0)";break;case"list":break;default:n.transform="translate3d("+t+"px,0,0)"}else"vertical"===e?n.top=t:n.left=t;return n}function d(t){return{"transition-duration":t+"ms"}}function f(t,e){return isNaN(t)?e:t}function h(t,e){return f(+String(t).replace(e||"px",""))}function m(t){return/%$/.test(t)?h(t,"%"):i}function p(t,e){return f(m(t)/100*e,h(t))}function v(t){return(!isNaN(h(t))||!isNaN(h(t,"%")))&&t}function g(t,e,n,o){return(t-(o||0))*(e+(n||0))}function w(t,e,n,o){return-Math.round(t/(e+(n||0))-(o||0))}function y(t){var e=t.data();if(!e.tEnd){var n=t[0],o={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",msTransition:"MSTransitionEnd",transition:"transitionend"};V(n,o[Tn.prefixed("transition")],function(t){e.tProp&&t.propertyName.match(e.tProp)&&e.onEndFn()}),e.tEnd=!0}}function b(t,e,n,o){var i,r=t.data();r&&(r.onEndFn=function(){i||(i=!0,clearTimeout(r.tT),n())},r.tProp=e,clearTimeout(r.tT),r.tT=setTimeout(function(){r.onEndFn()},1.5*o),y(t))}function x(t,e){var n=t.navdir||"horizontal";if(t.length){var o=t.data();On?(t.css(d(0)),o.onEndFn=a,clearTimeout(o.tT)):t.stop();var i=_(e,function(){return l(t,n)});return t.css(c(i,n)),i}}function _(){for(var t,e=0,n=arguments.length;n>e&&(t=e?arguments[e]():arguments[e],"number"!=typeof t);e++);return t}function C(t,e){return Math.round(t+(e-t)/1.5)}function k(){return k.p=k.p||("https:"===n.protocol?"https://":"http://"),k.p}function T(t){var n=e.createElement("a");return n.href=t,n}function P(t,e){if("string"!=typeof t)return t;t=T(t);var n,o;if(t.host.match(/youtube\.com/)&&t.search){if(n=t.search.split("v=")[1]){var i=n.indexOf("&");-1!==i&&(n=n.substring(0,i)),o="youtube"}}else t.host.match(/youtube\.com|youtu\.be/)?(n=t.pathname.replace(/^\/(embed\/|v\/)?/,"").replace(/\/.*/,""),o="youtube"):t.host.match(/vimeo\.com/)&&(o="vimeo",n=t.pathname.replace(/^\/(video\/)?/,"").replace(/\/.*/,""));return n&&o||!e||(n=t.href,o="custom"),n?{id:n,type:o,s:t.search.replace(/^\?/,""),p:k()}:!1}function S(t,e,n){var i,r,a=t.video;return"youtube"===a.type?(r=k()+"img.youtube.com/vi/"+a.id+"/default.jpg",i=r.replace(/\/default.jpg$/,"/hqdefault.jpg"),t.thumbsReady=!0):"vimeo"===a.type?o.ajax({url:k()+"vimeo.com/api/v2/video/"+a.id+".json",dataType:"jsonp",success:function(o){t.thumbsReady=!0,M(e,{img:o[0].thumbnail_large,thumb:o[0].thumbnail_small},t.i,n)}}):t.thumbsReady=!0,{img:i,thumb:r}}function M(t,e,n,i){for(var r=0,a=t.length;a>r;r++){var s=t[r];if(s.i===n&&s.thumbsReady){var u={videoReady:!0};u[to]=u[no]=u[eo]=!1,i.splice(r,1,o.extend({},s,u,e));break}}}function E(t){function e(t,e,i){var r=t.children("img").eq(0),a=t.attr("href"),s=t.attr("src"),u=r.attr("src"),l=e.video,c=i?P(a,l===!0):!1;c?a=!1:c=l,n(t,r,o.extend(e,{video:c,img:e.img||a||s||u,thumb:e.thumb||u||s||a}))}function n(t,e,n){var i=n.thumb&&n.img!==n.thumb,r=h(n.width||t.attr("width")),a=h(n.height||t.attr("height"));o.extend(n,{width:r,height:a,thumbratio:K(n.thumbratio||h(n.thumbwidth||e&&e.attr("width")||i||r)/h(n.thumbheight||e&&e.attr("height")||i||a))})}var i=[];return t.children().each(function(){var t=o(this),r=H(o.extend(t.data(),{id:t.attr("id")}));if(t.is("a, img"))e(t,r,!0);else{if(t.is(":empty"))return;n(t,null,o.extend(r,{html:this,_html:t.html()}))}i.push(r)}),i}function F(t){return 0===t.offsetWidth&&0===t.offsetHeight}function j(t){return!o.contains(e.documentElement,t)}function z(t,e,n,o){return z.i||(z.i=1,z.ii=[!0]),o=o||z.i,"undefined"==typeof z.ii[o]&&(z.ii[o]=!0),t()?e():z.ii[o]&&setTimeout(function(){z.ii[o]&&z(t,e,n,o)},n||100),z.i++}function N(t,e){var n=t.data(),o=n.measures;if(o&&(!n.l||n.l.W!==o.width||n.l.H!==o.height||n.l.r!==o.ratio||n.l.w!==e.w||n.l.h!==e.h)){var i=s(e.h,0,o.height),r=i*o.ratio;po.setRatio(t,r,i),n.l={W:o.width,H:o.height,r:o.ratio,w:e.w,h:e.h}}return!0}function $(t,e){var n=t[0];n.styleSheet?n.styleSheet.cssText=e:t.html(e)}function q(t,e,n,o){return e===n?!1:"vertical"===o?e>=t?"top":t>=n?"bottom":"top bottom":e>=t?"left":t>=n?"right":"left right"}function L(t,e,n){n=n||{},t.each(function(){var t,i=o(this),r=i.data();r.clickOn||(r.clickOn=!0,o.extend(oe(i,{onStart:function(e){t=e,(n.onStart||a).call(this,e)},onMove:n.onMove||a,onTouchEnd:n.onTouchEnd||a,onEnd:function(n){n.moved||e.call(this,t)}}),{noMove:!0}))})}function A(t,e){return'<div class="'+t+'">'+(e||"")+"</div>"}function I(t){return"."+t}function O(t){var e='<iframe src="'+t.p+t.type+".com/embed/"+t.id+'" frameborder="0" allowfullscreen></iframe>';return e}function D(t){for(var e=t.length;e;){var n=Math.floor(Math.random()*e--),o=t[e];t[e]=t[n],t[n]=o}return t}function R(t){return"[object Array]"==Object.prototype.toString.call(t)&&o.map(t,function(t){return o.extend({},t)})}function W(t,e,n){t.scrollLeft(e||0).scrollTop(n||0)}function H(t){if(t){var e={};return o.each(t,function(t,n){e[t.toLowerCase()]=n}),e}}function K(t){if(t){var e=+t;return isNaN(e)?(e=t.split("/"),+e[0]/+e[1]||i):e}}function V(t,e,n,o){e&&(t.addEventListener?t.addEventListener(e,n,!!o):t.attachEvent("on"+e,n))}function B(t,e){return t>e.max?t=e.max:t<e.min&&(t=e.min),t}function Q(t,e,n,o,i,r,a){var s,u,l;return"horizontal"===a?(u=t.thumbwidth,l=r.width()):(u=t.thumbheight,l=r.height()),s=(u+t.margin)*(n+1)>=l-o?"horizontal"===a?-i.position().left:-i.position().top:(u+t.margin)*n<=Math.abs(o)?"horizontal"===a?-i.position().left+l-(u+t.margin):-i.position().top+l-(u+t.margin):o,s=B(s,e),s||0}function X(t){return!!t.getAttribute("disabled")}function U(t){return{tabindex:-1*t+"",disabled:t}}function Y(t,e){V(t,"keyup",function(n){X(t)||13==n.keyCode&&e.call(t,n)})}function G(t,e){V(t,"focus",t.onfocusin=function(n){e.call(t,n)},!0)}function J(t,e){t.preventDefault?t.preventDefault():t.returnValue=!1,e&&t.stopPropagation&&t.stopPropagation()}function Z(t){return t?">":"<"}function te(t,e){var n=t.data(),i=Math.round(e.pos),r=function(){n&&n.sliding&&(n.sliding=!1),(e.onEnd||a)()};"undefined"!=typeof e.overPos&&e.overPos!==e.pos&&(i=e.overPos);var s=o.extend(c(i,e.direction),e.width&&{width:e.width},e.height&&{height:e.height});n&&n.sliding&&(n.sliding=!0),On?(t.css(o.extend(d(e.time),s)),e.time>10?b(t,"transform",r,e.time):r()):t.stop().animate(s,e.time,io,r)}function ee(t,e,n,i,r,s){var u="undefined"!=typeof s;if(u||(r.push(arguments),Array.prototype.push.call(arguments,r.length),!(r.length>1))){t=t||o(t),e=e||o(e);var l=t[0],c=e[0],d="crossfade"===i.method,f=function(){if(!f.done){f.done=!0;var t=(u||r.shift())&&r.shift();t&&ee.apply(this,t),(i.onEnd||a)(!!t)}},h=i.time/(s||1);n.removeClass(Ke+" "+He),t.stop().addClass(Ke),e.stop().addClass(He),d&&c&&t.fadeTo(0,0),t.fadeTo(d?h:0,1,d&&f),e.fadeTo(h,0,f),l&&d||c||f()}}function ne(t){var e=(t.touches||[])[0]||t;t._x=e.pageX,t._y=e.clientY,t._now=o.now()}function oe(t,n){function i(t){return f=o(t.target),b.checked=p=v=w=!1,c||b.flow||t.touches&&t.touches.length>1||t.which>1||lo&&lo.type!==t.type&&fo||(p=n.select&&f.is(n.select,y))?p:(m="touchstart"===t.type,v=f.is("a, a *",y),h=b.control,g=b.noMove||b.noSwipe||h?16:b.snap?0:4,ne(t),d=lo=t,co=t.type.replace(/down|start/,"move").replace(/Down/,"Move"),(n.onStart||a).call(y,t,{control:h,$target:f}),c=b.flow=!0,void((!m||b.go)&&J(t)))}function r(t){if(t.touches&&t.touches.length>1||Kn&&!t.isPrimary||co!==t.type||!c)return c&&s(),void(n.onTouchEnd||a)();ne(t);var e=Math.abs(t._x-d._x),o=Math.abs(t._y-d._y),i=e-o,r=(b.go||b.x||i>=0)&&!b.noSwipe,u=0>i;m&&!b.checked?(c=r)&&J(t):(J(t),(n.onMove||a).call(y,t,{touch:m})),!w&&Math.sqrt(Math.pow(e,2)+Math.pow(o,2))>g&&(w=!0),b.checked=b.checked||r||u}function s(t){(n.onTouchEnd||a)();var e=c;b.control=c=!1,e&&(b.flow=!1),!e||v&&!b.checked||(t&&J(t),fo=!0,clearTimeout(ho),ho=setTimeout(function(){fo=!1},1e3),(n.onEnd||a).call(y,{moved:w,$target:f,control:h,touch:m,startEvent:d,aborted:!t||"MSPointerCancel"===t.type}))}function u(){b.flow||setTimeout(function(){b.flow=!0},10)}function l(){b.flow&&setTimeout(function(){b.flow=!1},Bn)}var c,d,f,h,m,p,v,g,w,y=t[0],b={};return Kn?(V(y,"MSPointerDown",i),V(e,"MSPointerMove",r),V(e,"MSPointerCancel",s),V(e,"MSPointerUp",s)):(V(y,"touchstart",i),V(y,"touchmove",r),V(y,"touchend",s),V(e,"touchstart",u),V(e,"touchend",l),V(e,"touchcancel",l),qn.on("scroll",l),t.on("mousedown",i),Ln.on("mousemove",r).on("mouseup",s)),mo=Tn.touch?"a":"div",t.on("click",mo,function(t){b.checked&&J(t)}),b}function ie(t,e){function n(n,o){S=!0,l=d="vertical"===_?n._y:n._x,v=n._now,p=[[v,l]],f=h=F.noMove||o?0:x(t,(e.getPos||a)()),(e.onStart||a).call(M,n)}function i(e,o){w=F.min,y=F.max,b=F.snap,_=F.direction||"horizontal",t.navdir=_,k=e.altKey,S=P=!1,T=o.control,T||E.sliding||n(e)}function r(o,i){F.noSwipe||(S||n(o),d="vertical"===_?o._y:o._x,p.push([o._now,d]),h=f-(l-d),m=q(h,w,y,_),w>=h?h=C(h,w):h>=y&&(h=C(h,y)),F.noMove||(t.css(c(h,_)),P||(P=!0,i.touch||Kn||t.addClass(un)),(e.onMove||a).call(M,o,{pos:h,edge:m})))}function u(i){if(!F.noSwipe||!i.moved){S||n(i.startEvent,!0),i.touch||Kn||t.removeClass(un),g=o.now();for(var r,u,l,c,m,v,x,C,T,P=g-Bn,E=null,j=Qn,z=e.friction,N=p.length-1;N>=0;N--){if(r=p[N][0],u=Math.abs(r-P),null===E||l>u)E=r,c=p[N][1];else if(E===P||u>l)break;l=u}x=s(h,w,y);var $=c-d,q=$>=0,L=g-E,A=L>Bn,I=!A&&h!==f&&x===h;b&&(x=s(Math[I?q?"floor":"ceil":"round"](h/b)*b,w,y),w=y=x),I&&(b||x===h)&&(T=-($/L),j*=s(Math.abs(T),e.timeLow,e.timeHigh),m=Math.round(h+T*j/z),b||(x=m),(!q&&m>y||q&&w>m)&&(v=q?w:y,C=m-v,b||(x=v),C=s(x+.03*C,v-50,v+50),j=Math.abs((h-C)/(T/z)))),j*=k?10:1,(e.onEnd||a).call(M,o.extend(i,{moved:i.moved||A&&b,pos:h,newPos:x,overPos:C,time:j,dir:_}))}}var l,d,f,h,m,p,v,g,w,y,b,_,k,T,P,S,M=t[0],E=t.data(),F={};return F=o.extend(oe(e.$wrap,o.extend({},e,{onStart:i,onMove:r,onEnd:u})),F)}function re(t,e){var n,i,r,s=t[0],u={prevent:{}};return V(s,Vn,function(t){var s=t.wheelDeltaY||-1*t.deltaY||0,l=t.wheelDeltaX||-1*t.deltaX||0,c=Math.abs(l)&&!Math.abs(s),d=Z(0>l),f=i===d,h=o.now(),m=Bn>h-r;i=d,r=h,c&&u.ok&&(!u.prevent[d]||n)&&(J(t,!0),n&&f&&m||(e.shift&&(n=!0,clearTimeout(u.t),u.t=setTimeout(function(){n=!1},Xn)),(e.onEnd||a)(t,e.shift?d:l)))}),u}function ae(){o.each(o.Fotorama.instances,function(t,e){e.index=t})}function se(t){o.Fotorama.instances.push(t),ae()}function ue(t){o.Fotorama.instances.splice(t.index,1),ae()}var le="fotorama",ce="fotorama__fullscreen",de=le+"__wrap",fe=de+"--css2",he=de+"--css3",me=de+"--video",pe=de+"--fade",ve=de+"--slide",ge=de+"--no-controls",we=de+"--no-shadows",ye=de+"--pan-y",be=de+"--rtl",xe=de+"--no-captions",_e=de+"--toggle-arrows",Ce=le+"__stage",ke=Ce+"__frame",Te=ke+"--video",Pe=Ce+"__shaft",Se=le+"__grab",Me=le+"__pointer",Ee=le+"__arr",Fe=Ee+"--disabled",je=Ee+"--prev",ze=Ee+"--next",Ne=le+"__nav",$e=Ne+"-wrap",qe=Ne+"__shaft",Le=$e+"--vertical",Ae=$e+"--list",Ie=$e+"--horizontal",Oe=Ne+"--dots",De=Ne+"--thumbs",Re=Ne+"__frame",We=le+"__fade",He=We+"-front",Ke=We+"-rear",Ve=le+"__shadow",Be=Ve+"s",Qe=Be+"--left",Xe=Be+"--right",Ue=Be+"--top",Ye=Be+"--bottom",Ge=le+"__active",Je=le+"__select",Ze=le+"--hidden",tn=le+"--fullscreen",en=le+"__fullscreen-icon",nn=le+"__error",on=le+"__loading",rn=le+"__loaded",an=rn+"--full",sn=rn+"--img",un=le+"__grabbing",ln=le+"__img",cn=ln+"--full",dn=le+"__thumb",fn=dn+"__arr--left",hn=dn+"__arr--right",mn=dn+"-border",pn=le+"__html",vn=le+"-video-container",gn=le+"__video",wn=gn+"-play",yn=gn+"-close",bn=le+"__spinner",xn=le+"_horizontal_ratio",_n=le+"_vertical_ratio",Cn=o&&o.fn.jquery.split(".");if(!Cn||Cn[0]<1||1==Cn[0]&&Cn[1]<8)throw"Fotorama requires jQuery 1.8 or later and will not run without it.";var kn={},Tn=function(t,e,n){function o(t){g.cssText=t}function i(t,e){return typeof t===e}function r(t,e){return!!~(""+t).indexOf(e)}function a(t,e){for(var o in t){var i=t[o];if(!r(i,"-")&&g[i]!==n)return"pfx"==e?i:!0}return!1}function s(t,e,o){for(var r in t){var a=e[t[r]];if(a!==n)return o===!1?t[r]:i(a,"function")?a.bind(o||e):a}return!1}function u(t,e,n){var o=t.charAt(0).toUpperCase()+t.slice(1),r=(t+" "+b.join(o+" ")+o).split(" ");return i(e,"string")||i(e,"undefined")?a(r,e):(r=(t+" "+x.join(o+" ")+o).split(" "),s(r,e,n))}var l,c,d,f="2.8.3",h={},m=e.documentElement,p="modernizr",v=e.createElement(p),g=v.style,w=({}.toString," -webkit- -moz- -o- -ms- ".split(" ")),y="Webkit Moz O ms",b=y.split(" "),x=y.toLowerCase().split(" "),_={},C=[],k=C.slice,T=function(t,n,o,i){var r,a,s,u,l=e.createElement("div"),c=e.body,d=c||e.createElement("body");if(parseInt(o,10))for(;o--;)s=e.createElement("div"),s.id=i?i[o]:p+(o+1),l.appendChild(s);return r=["­",'<style id="s',p,'">',t,"</style>"].join(""),l.id=p,(c?l:d).innerHTML+=r,d.appendChild(l),c||(d.style.background="",d.style.overflow="hidden",u=m.style.overflow,m.style.overflow="hidden",m.appendChild(d)),a=n(l,t),c?l.parentNode.removeChild(l):(d.parentNode.removeChild(d),m.style.overflow=u),!!a},P={}.hasOwnProperty;d=i(P,"undefined")||i(P.call,"undefined")?function(t,e){return e in t&&i(t.constructor.prototype[e],"undefined")}:function(t,e){return P.call(t,e)},Function.prototype.bind||(Function.prototype.bind=function(t){var e=this;if("function"!=typeof e)throw new TypeError;var n=k.call(arguments,1),o=function(){if(this instanceof o){var i=function(){};i.prototype=e.prototype;var r=new i,a=e.apply(r,n.concat(k.call(arguments)));return Object(a)===a?a:r}return e.apply(t,n.concat(k.call(arguments)))};return o}),_.touch=function(){var n;return"ontouchstart"in t||t.DocumentTouch&&e instanceof DocumentTouch?n=!0:T(["@media (",w.join("touch-enabled),("),p,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(t){n=9===t.offsetTop}),n},_.csstransforms3d=function(){var t=!!u("perspective");return t&&"webkitPerspective"in m.style&&T("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(e){t=9===e.offsetLeft&&3===e.offsetHeight}),t},_.csstransitions=function(){return u("transition")};for(var S in _)d(_,S)&&(c=S.toLowerCase(),h[c]=_[S](),C.push((h[c]?"":"no-")+c));return h.addTest=function(t,e){if("object"==typeof t)for(var o in t)d(t,o)&&h.addTest(o,t[o]);else{if(t=t.toLowerCase(),h[t]!==n)return h;e="function"==typeof e?e():e,"undefined"!=typeof enableClasses&&enableClasses&&(m.className+=" "+(e?"":"no-")+t),h[t]=e}return h},o(""),v=l=null,h._version=f,h._prefixes=w,h._domPrefixes=x,h._cssomPrefixes=b,h.testProp=function(t){return a([t])},h.testAllProps=u,h.testStyles=T,h.prefixed=function(t,e,n){return e?u(t,e,n):u(t,"pfx")},h}(t,e),Pn={ok:!1,is:function(){return!1},request:function(){},cancel:function(){},event:"",prefix:""},Sn="webkit moz o ms khtml".split(" ");if("undefined"!=typeof e.cancelFullScreen)Pn.ok=!0;else for(var Mn=0,En=Sn.length;En>Mn;Mn++)if(Pn.prefix=Sn[Mn],"undefined"!=typeof e[Pn.prefix+"CancelFullScreen"]){Pn.ok=!0;break}Pn.ok&&(Pn.event=Pn.prefix+"fullscreenchange",Pn.is=function(){switch(this.prefix){case"":return e.fullScreen;case"webkit":return e.webkitIsFullScreen;default:return e[this.prefix+"FullScreen"]}},Pn.request=function(t){return""===this.prefix?t.requestFullScreen():t[this.prefix+"RequestFullScreen"]()},Pn.cancel=function(){return""===this.prefix?e.cancelFullScreen():e[this.prefix+"CancelFullScreen"]()});var Fn,jn={lines:12,length:5,width:2,radius:7,corners:1,rotate:15,color:"rgba(128, 128, 128, .75)",hwaccel:!0},zn={top:"auto",left:"auto",className:""};!function(t,e){Fn=e()}(this,function(){function t(t,n){var o,i=e.createElement(t||"div");for(o in n)i[o]=n[o];return i}function n(t){for(var e=1,n=arguments.length;n>e;e++)t.appendChild(arguments[e]);return t}function o(t,e,n,o){var i=["opacity",e,~~(100*t),n,o].join("-"),r=.01+n/o*100,a=Math.max(1-(1-t)/e*(100-r),t),s=f.substring(0,f.indexOf("Animation")).toLowerCase(),u=s&&"-"+s+"-"||"";return m[i]||(p.insertRule("@"+u+"keyframes "+i+"{0%{opacity:"+a+"}"+r+"%{opacity:"+t+"}"+(r+.01)+"%{opacity:1}"+(r+e)%100+"%{opacity:"+t+"}100%{opacity:"+a+"}}",p.cssRules.length),m[i]=1),i}function r(t,e){var n,o,r=t.style;for(e=e.charAt(0).toUpperCase()+e.slice(1),o=0;o<h.length;o++)if(n=h[o]+e,r[n]!==i)return n;return r[e]!==i?e:void 0}function a(t,e){for(var n in e)t.style[r(t,n)||n]=e[n];return t}function s(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var o in n)t[o]===i&&(t[o]=n[o])}return t}function u(t){for(var e={x:t.offsetLeft,y:t.offsetTop};t=t.offsetParent;)e.x+=t.offsetLeft,e.y+=t.offsetTop;return e}function l(t,e){return"string"==typeof t?t:t[e%t.length]}function c(t){return"undefined"==typeof this?new c(t):void(this.opts=s(t||{},c.defaults,v))}function d(){function e(e,n){return t("<"+e+' xmlns="urn:schemas-microsoft.com:vml" class="spin-vml">',n)}p.addRule(".spin-vml","behavior:url(#default#VML)"),c.prototype.lines=function(t,o){function i(){return a(e("group",{coordsize:c+" "+c,coordorigin:-u+" "+-u}),{width:c,height:c})}function r(t,r,s){n(f,n(a(i(),{rotation:360/o.lines*t+"deg",left:~~r}),n(a(e("roundrect",{arcsize:o.corners}),{width:u,height:o.width,left:o.radius,top:-o.width>>1,filter:s}),e("fill",{color:l(o.color,t),opacity:o.opacity}),e("stroke",{opacity:0}))))}var s,u=o.length+o.width,c=2*u,d=2*-(o.width+o.length)+"px",f=a(i(),{position:"absolute",top:d,left:d});if(o.shadow)for(s=1;s<=o.lines;s++)r(s,-2,"progid:DXImageTransform.Microsoft.Blur(pixelradius=2,makeshadow=1,shadowopacity=.3)");for(s=1;s<=o.lines;s++)r(s);return n(t,f)},c.prototype.opacity=function(t,e,n,o){var i=t.firstChild;o=o.shadow&&o.lines||0,i&&e+o<i.childNodes.length&&(i=i.childNodes[e+o],i=i&&i.firstChild,i=i&&i.firstChild,i&&(i.opacity=n))}}var f,h=["webkit","Moz","ms","O"],m={},p=function(){var o=t("style",{type:"text/css"});return n(e.getElementsByTagName("head")[0],o),o.sheet||o.styleSheet}(),v={lines:12,length:7,width:5,radius:10,rotate:0,corners:1,color:"#000",direction:1,speed:1,trail:100,opacity:.25,fps:20,zIndex:2e9,className:"spinner",top:"auto",left:"auto",position:"relative"};c.defaults={},s(c.prototype,{spin:function(e){this.stop();var n,o,i=this,r=i.opts,s=i.el=a(t(0,{className:r.className}),{position:r.position,width:0,zIndex:r.zIndex}),l=r.radius+r.length+r.width;if(e&&(e.insertBefore(s,e.firstChild||null),o=u(e),n=u(s),a(s,{left:("auto"==r.left?o.x-n.x+(e.offsetWidth>>1):parseInt(r.left,10)+l)+"px",top:("auto"==r.top?o.y-n.y+(e.offsetHeight>>1):parseInt(r.top,10)+l)+"px"})),s.setAttribute("role","progressbar"),i.lines(s,i.opts),!f){var c,d=0,h=(r.lines-1)*(1-r.direction)/2,m=r.fps,p=m/r.speed,v=(1-r.opacity)/(p*r.trail/100),g=p/r.lines;!function w(){d++;for(var t=0;t<r.lines;t++)c=Math.max(1-(d+(r.lines-t)*g)%p*v,r.opacity),i.opacity(s,t*r.direction+h,c,r);i.timeout=i.el&&setTimeout(w,~~(1e3/m))}()}return i},stop:function(){var t=this.el;return t&&(clearTimeout(this.timeout),t.parentNode&&t.parentNode.removeChild(t),this.el=i),this},lines:function(e,i){function r(e,n){return a(t(),{position:"absolute",width:i.length+i.width+"px",height:i.width+"px",background:e,boxShadow:n,transformOrigin:"left",transform:"rotate("+~~(360/i.lines*u+i.rotate)+"deg) translate("+i.radius+"px,0)",borderRadius:(i.corners*i.width>>1)+"px"})}for(var s,u=0,c=(i.lines-1)*(1-i.direction)/2;u<i.lines;u++)s=a(t(),{position:"absolute",top:1+~(i.width/2)+"px",transform:i.hwaccel?"translate3d(0,0,0)":"",opacity:i.opacity,animation:f&&o(i.opacity,i.trail,c+u*i.direction,i.lines)+" "+1/i.speed+"s linear infinite"}),i.shadow&&n(s,a(r("#000","0 0 4px #000"),{top:"2px"})),n(e,n(s,r(l(i.color,u),"0 0 1px rgba(0,0,0,.1)")));return e},opacity:function(t,e,n){e<t.childNodes.length&&(t.childNodes[e].style.opacity=n)}});var g=a(t("group"),{behavior:"url(#default#VML)"});return!r(g,"transform")&&g.adj?d():f=r(g,"animation"),c});var Nn,$n,qn=o(t),Ln=o(e),An="quirks"===n.hash.replace("#",""),In=Tn.csstransforms3d,On=In&&!An,Dn=In||"CSS1Compat"===e.compatMode,Rn=Pn.ok,Wn=navigator.userAgent.match(/Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone/i),Hn=!On||Wn,Kn=navigator.msPointerEnabled,Vn="onwheel"in e.createElement("div")?"wheel":e.onmousewheel!==i?"mousewheel":"DOMMouseScroll",Bn=250,Qn=300,Xn=1400,Un=5e3,Yn=2,Gn=64,Jn=500,Zn=333,to="$stageFrame",eo="$navDotFrame",no="$navThumbFrame",oo="auto",io=r([.1,0,.25,1]),ro=1200,ao=1,so={width:null,minwidth:null,maxwidth:"100%",height:null,minheight:null,maxheight:null,ratio:null,margin:Yn,nav:"dots",navposition:"bottom",navwidth:null,thumbwidth:Gn,thumbheight:Gn,thumbmargin:Yn,thumbborderwidth:Yn,allowfullscreen:!1,transition:"slide",clicktransition:null,transitionduration:Qn,captions:!0,startindex:0,loop:!1,autoplay:!1,stopautoplayontouch:!0,keyboard:!1,arrows:!0,click:!0,swipe:!1,trackpad:!1,shuffle:!1,direction:"ltr",shadows:!0,spinner:null,showcaption:!0,navdir:"horizontal",navarrows:!0,navtype:"thumbs"},uo={left:!0,right:!0,down:!1,up:!1,space:!1,home:!1,end:!1};z.stop=function(t){z.ii[t]=!1};var lo,co,fo,ho,mo,po=function(){function t(t,e,n){var o=e/n;1>=o?(t.parent().removeClass(xn),t.parent().addClass(_n)):(t.parent().removeClass(_n),t.parent().addClass(xn))}function e(t,e,n){var r=n;t.attr(r)||t.attr(r)===i||t.attr(r,e),t.find("["+r+"]").length&&t.find("["+r+"]").each(function(){o(this).attr(r,e)})}function n(t,e,n){var o,i=!1;return o=t.showCaption===n||t.showCaption===!0?!0:!1,e?(t.caption&&o&&(i=!0),i):!1}return{setRatio:t,setThumbAttr:e,isExpectedCaption:n}}(po||{},jQuery);jQuery.Fotorama=function(n,r){function a(){o.each(Do,function(t,e){if(!e.i){e.i=Mi++;var n=P(e.video,!0);if(n){var o={};e.video=n,e.img||e.thumb?e.thumbsReady=!0:o=S(e,Do,ki),M(Do,{img:o.img,thumb:o.thumb},e.i,ki)}}})}function u(t){return hi[t]||ki.fullScreen}function f(){if(Ni!==i)if("vertical"==r.navdir){var t=r.thumbwidth+r.thumbmargin;Ni.css("left",t),Ai.css("right",t),Qi.css("right",t),zi.css("width",zi.css("width")+t),$i.css("max-width",zi.width()-t)}else Ni.css("left",""),Ai.css("right",""),Qi.css("right",""),zi.css("width",zi.css("width")+t),$i.css("max-width","")}function m(t){var e,n="keydown."+le,o=le+Ti,i="keydown."+o,a="keyup."+o,s="resize."+o+" orientationchange."+o;t?(Ln.on(i,function(t){var n,o;Ko&&27===t.keyCode?(n=!0,Mo(Ko,!0,!0)):(ki.fullScreen||r.keyboard&&!ki.index)&&(27===t.keyCode?(n=!0,ki.cancelFullScreen()):t.shiftKey&&32===t.keyCode&&u("space")||37===t.keyCode&&u("left")||38===t.keyCode&&u("up")?(ki.longPress.progress(),o="<"):32===t.keyCode&&u("space")||39===t.keyCode&&u("right")||40===t.keyCode&&u("down")?(ki.longPress.progress(),o=">"):36===t.keyCode&&u("home")?(ki.longPress.progress(),o="<<"):35===t.keyCode&&u("end")&&(ki.longPress.progress(),o=">>")),(n||o)&&J(t),e={index:o,slow:t.altKey,user:!0},o&&(ki.longPress.inProgress?ki.showWhileLongPress(e):ki.show(e))}),t&&Ln.on(a,function(){ki.longPress.inProgress&&ki.showEndLongPress({user:!0}),ki.longPress.reset()}),ki.index||Ln.off(n).on(n,"textarea, input, select",function(t){!$n.hasClass(ce)&&t.stopPropagation()}),qn.on(s,ki.resize)):(Ln.off(i),qn.off(s))}function y(t){t!==y.f&&(t?(n.addClass(le+" "+Pi).before(ji).before(Fi),se(ki)):(ji.detach(),Fi.detach(),n.html(Ei.urtext).removeClass(Pi),ue(ki)),m(t),y.f=t)}function b(){Do=ki.data=Do||R(r.data)||E(n),Ro=ki.size=Do.length,Oo.ok&&r.shuffle&&D(Do),a(),Zi=oe(Zi),Ro&&y(!0)}function C(){var t=2>Ro||Ko;nr.noMove=t||ai,nr.noSwipe=t||!r.swipe,!ci&&$i.toggleClass(Se,!r.click&&!nr.noMove&&!nr.noSwipe),Kn&&zi.toggleClass(ye,!nr.noSwipe)}function k(t){t===!0&&(t=""),r.autoplay=Math.max(+t||Un,1.5*li)}function T(t){t.navarrows&&"thumbs"===t.nav?(Vi.show(),Bi.show()):(Vi.hide(),Bi.hide())}function F(t,e){return Math.floor(zi.width()/(e.thumbwidth+e.thumbmargin))}function X(){function t(t,n){e[t?"add":"remove"].push(n)}r.nav&&"dots"!==r.nav||(r.navdir="horizontal"),ki.options=r=H(r),ao=F(zi,r),ai="crossfade"===r.transition||"dissolve"===r.transition,ti=r.loop&&(Ro>2||ai&&(!ci||"slide"!==ci)),li=+r.transitionduration||Qn,fi="rtl"===r.direction,hi=o.extend({},r.keyboard&&uo,r.keyboard),T(r);var e={add:[],remove:[]};Ro>1?(ei=r.nav,oi="top"===r.navposition,e.remove.push(Je),Ii.toggle(r.arrows)):(ei=!1,Ii.hide()),Cn(),Ho=new Fn(o.extend(jn,r.spinner,zn,{direction:fi?-1:1})),Xn(),io(),Yn(),r.autoplay&&k(r.autoplay),si=h(r.thumbwidth)||Gn,ui=h(r.thumbheight)||Gn,or.ok=rr.ok=r.trackpad&&!Hn,C(),go(r,[er]),ni="thumbs"===ei,Oi.filter(":hidden")&&ei&&Oi.show(),ni?(Sn(Ro,"navThumb"),Wo=Hi,Ci=no,$(Fi,o.Fotorama.jst.style({w:si,h:ui,b:r.thumbborderwidth,m:r.thumbmargin,s:Ti,q:!Dn})),Di.addClass(De).removeClass(Oe)):"dots"===ei?(Sn(Ro,"navDot"),Wo=Wi,Ci=eo,Di.addClass(Oe).removeClass(De)):(Oi.hide(),ei=!1,Di.removeClass(De+" "+Oe)),ei&&(oi?Oi.insertBefore(Ni):Oi.insertAfter(Ni),In.nav=!1,In(Wo,Ri,"nav")),ii=r.allowfullscreen,ii?(Qi.prependTo(Ni),ri=Rn&&"native"===ii):(Qi.detach(),ri=!1),t(ai,pe),t(!ai,ve),t(!r.captions,xe),t(fi,be),t("always"!==r.arrows,_e),di=r.shadows&&!Hn,t(!di,we),zi.addClass(e.add.join(" ")).removeClass(e.remove.join(" ")),tr=o.extend({},r),f()}function ne(t){return 0>t?(Ro+t%Ro)%Ro:t>=Ro?t%Ro:t}function oe(t){return s(t,0,Ro-1)}function ae(t){return ti?ne(t):oe(t)}function We(t){return t>0||ti?t-1:!1}function He(t){return Ro-1>t||ti?t+1:!1}function Ke(){nr.min=ti?-1/0:-g(Ro-1,er.w,r.margin,Qo),nr.max=ti?1/0:-g(0,er.w,r.margin,Qo),nr.snap=er.w+r.margin}function Ve(){var t="vertical"===r.navdir,e=t?Ri.height():Ri.width(),n=t?er.h:er.nw;ir.min=Math.min(0,n-e),ir.max=0,ir.direction=r.navdir,Ri.toggleClass(Se,!(ir.noMove=ir.min===ir.max))}function un(t,e,n){if("number"==typeof t){t=new Array(t);var i=!0}return o.each(t,function(t,o){if(i&&(o=t),"number"==typeof o){var r=Do[ne(o)];if(r){var a="$"+e+"Frame",s=r[a];n.call(this,t,o,r,s,a,s&&s.data())}}})}function dn(t,e,n,o){(!mi||"*"===mi&&o===Zo)&&(t=v(r.width)||v(t)||Jn,e=v(r.height)||v(e)||Zn,ki.resize({width:t,ratio:r.ratio||n||t/e},0,o!==Zo&&"*"))}function xn(t,e,n,i){un(t,e,function(t,a,s,u,l,c){function d(t){var e=ne(a);wo(t,{index:e,src:b,frame:Do[e]})}function f(){g.remove(),o.Fotorama.cache[b]="error",s.html&&"stage"===e||!x||x===b?(!b||s.html||p?"stage"===e&&(u.trigger("f:load").removeClass(on+" "+nn).addClass(rn),d("load"),dn()):(u.trigger("f:error").removeClass(on).addClass(nn),d("error")),c.state="error",!(Ro>1&&Do[a]===s)||s.html||s.deleted||s.video||p||(s.deleted=!0,ki.splice(a,1))):(s[y]=b=x,xn([a],e,n,!0))}function h(){o.Fotorama.measures[b]=w.measures=o.Fotorama.measures[b]||{width:v.width,height:v.height,ratio:v.width/v.height},dn(w.measures.width,w.measures.height,w.measures.ratio,a),g.off("load error").addClass(ln+(p?" "+cn:"")).prependTo(u),u.hasClass(ke)&&!u.hasClass(vn)&&u.attr("href",g.attr("src")),N(g,(o.isFunction(n)?n():n)||er),o.Fotorama.cache[b]=c.state="loaded",setTimeout(function(){u.trigger("f:load").removeClass(on+" "+nn).addClass(rn+" "+(p?an:sn)),"stage"===e?d("load"):(s.thumbratio===oo||!s.thumbratio&&r.thumbratio===oo)&&(s.thumbratio=w.measures.ratio,Ao())},0)}function m(){var t=10;z(function(){return!xi||!t--&&!Hn},function(){h()})}if(u){var p=ki.fullScreen&&s.full&&s.full!==s.img&&!c.$full&&"stage"===e;if(!c.$img||i||p){var v=new Image,g=o(v),w=g.data();c[p?"$full":"$img"]=g;var y="stage"===e?p?"full":"img":"thumb",b=s[y],x=p?null:s["stage"===e?"thumb":"img"];if("navThumb"===e&&(u=c.$wrap),!b)return void f();o.Fotorama.cache[b]?!function _(){"error"===o.Fotorama.cache[b]?f():"loaded"===o.Fotorama.cache[b]?setTimeout(m,0):setTimeout(_,100)}():(o.Fotorama.cache[b]="*",g.on("load",m).on("error",f)),c.state="",v.src=b,c.data.caption&&(v.alt=c.data.caption||""),po.isExpectedCaption(s,r.showcaption)&&o(v).attr("aria-labelledby",s.labelledby)}}})}function _n(t){Ji.append(Ho.spin().el).appendTo(t)}function Cn(){Ji.detach(),Ho&&Ho.stop()}function kn(){var t=Vo[to];t&&!t.data().state&&(_n(t),t.on("f:load f:error",function(){t.off("f:load f:error"),Cn()}))}function Tn(t){Y(t,$o),G(t,function(){setTimeout(function(){W(Di)},0),co({time:li,guessIndex:o(this).data().eq,minMax:ir})})}function Sn(t,e){un(t,e,function(t,n,i,a,s,u){if(!a){a=i[s]=zi[s].clone(),u=a.data(),u.data=i;var l=a[0],c="labelledby"+o.now();"stage"===e?(i.html&&o('<div class="'+pn+'"></div>').append(i._html?o(i.html).removeAttr("id").html(i._html):i.html).appendTo(a),i.id&&(c=i.id||c),i.labelledby=c,po.isExpectedCaption(i,r.showcaption)&&o(o.Fotorama.jst.frameCaption({caption:i.caption,labelledby:c})).appendTo(a),i.video&&a.addClass(Te).append(Ui.clone()),G(l,function(){setTimeout(function(){W(Ni)},0),jo({index:u.eq,user:!0})}),qi=qi.add(a)):"navDot"===e?(Tn(l),Wi=Wi.add(a)):"navThumb"===e&&(Tn(l),u.$wrap=a.children(":first"),Hi=Hi.add(a),i.video&&u.$wrap.append(Ui.clone()))}})}function Mn(t,e){return t&&t.length&&N(t,e)}function En(t){un(t,"stage",function(t,e,n,i,a,s){if(i){var u=ne(e);s.eq=u,sr[to][u]=i.css(o.extend({left:ai?0:g(e,er.w,r.margin,Qo)},ai&&d(0))),j(i[0])&&(i.appendTo($i),Mo(n.$video)),Mn(s.$img,er),Mn(s.$full,er),!i.hasClass(ke)||"false"===i.attr("aria-hidden")&&i.hasClass(Ge)||i.attr("aria-hidden","true")}})}function An(t,e){var n,i;"thumbs"!==ei||isNaN(t)||(n=-t,i=-t+er.nw,"vertical"===r.navdir&&(t-=r.thumbheight,i=-t+er.h),Hi.each(function(){var t=o(this),a=t.data(),s=a.eq,u=function(){return{h:ui,w:a.w}},l=u(),c="vertical"===r.navdir?a.t>i:a.l>i;l.w=a.w,a.l+a.w<n||c||Mn(a.$img,l)||e&&xn([s],"navThumb",u)}))}function In(t,e,n){if(!In[n]){var i="nav"===n&&ni,a=0,s=0;e.append(t.filter(function(){for(var t,e=o(this),n=e.data(),i=0,r=Do.length;r>i;i++)if(n.data===Do[i]){t=!0,n.eq=i;break}return t||e.remove()&&!1}).sort(function(t,e){return o(t).data().eq-o(e).data().eq}).each(function(){var t=o(this),e=t.data();po.setThumbAttr(t,e.data.caption,"aria-label")}).each(function(){if(i){var t=o(this),e=t.data(),n=Math.round(ui*e.data.thumbratio)||si,u=Math.round(si/e.data.thumbratio)||ui;e.t=s,e.h=u,e.l=a,e.w=n,t.css({width:n}),s+=u+r.thumbmargin,a+=n+r.thumbmargin}})),In[n]=!0}}function Wn(t){return t-ur>er.w/3}function Vn(t){return!(ti||Zi+t&&Zi-Ro+t||Ko)}function Xn(){var t=Vn(0),e=Vn(1);Li.toggleClass(Fe,t).attr(U(t)),Ai.toggleClass(Fe,e).attr(U(e))}function Yn(){var t=!1,e=!1;if("thumbs"!==r.navtype||r.loop||(t=0==Zi?!0:!1,e=Zi==r.data.length-1?!0:!1),"slides"===r.navtype){var n=l(Ri,r.navdir);t=n>=ir.max?!0:!1,e=n<=ir.min?!0:!1}Vi.toggleClass(Fe,t).attr(U(t)),Bi.toggleClass(Fe,e).attr(U(e))}function io(){or.ok&&(or.prevent={"<":Vn(0),">":Vn(1)})}function so(t){var e,n,o,i,a=t.data();ni?(e=a.l,n=a.t,o=a.w,i=a.h):(e=t.position().left,o=t.width());var s={c:e+o/2,min:-e+10*r.thumbmargin,max:-e+er.w-o-10*r.thumbmargin},u={c:n+i/2,min:-n+10*r.thumbmargin,max:-n+er.h-i-10*r.thumbmargin};return"vertical"===r.navdir?u:s}function lo(t){var e=Vo[Ci].data();te(Ki,{time:1.2*t,pos:"vertical"===r.navdir?e.t:e.l,width:e.w,height:e.h,direction:r.navdir})}function co(t){var e,n,o,i,a,u,c,d,f=Do[t.guessIndex][Ci],h=r.navtype;f&&("thumbs"===h?(e=ir.min!==ir.max,o=t.minMax||e&&so(Vo[Ci]),i=e&&(t.keep&&co.t?co.l:s((t.coo||er.nw/2)-so(f).c,o.min,o.max)),a=e&&(t.keep&&co.l?co.l:s((t.coo||er.nw/2)-so(f).c,o.min,o.max)),u="vertical"===r.navdir?i:a,c=e&&s(u,ir.min,ir.max)||0,n=1.1*t.time,te(Ri,{time:n,pos:c,direction:r.navdir,onEnd:function(){An(c,!0),Yn()}}),So(Di,q(c,ir.min,ir.max,r.navdir)),co.l=u):(d=l(Ri,r.navdir),n=1.11*t.time,c=Q(r,ir,t.guessIndex,d,f,Oi,r.navdir),te(Ri,{time:n,pos:c,direction:r.navdir,onEnd:function(){An(c,!0),Yn() +}}),So(Di,q(c,ir.min,ir.max,r.navdir))))}function fo(){ho(Ci),ar[Ci].push(Vo[Ci].addClass(Ge).attr("data-active",!0))}function ho(t){for(var e=ar[t];e.length;)e.shift().removeClass(Ge).attr("data-active",!1)}function mo(t){var e=sr[t];o.each(Bo,function(t,n){delete e[ne(n)]}),o.each(e,function(t,n){delete e[t],n.detach()})}function vo(t){Qo=Xo=Zi;var e=Vo[to];e&&(ho(to),ar[to].push(e.addClass(Ge).attr("data-active",!0)),e.hasClass(ke)&&e.attr("aria-hidden","false"),t||ki.showStage.onEnd(!0),x($i,0,!0),mo(to),En(Bo),Ke(),Ve(),Y($i[0],function(){n.hasClass(tn)||(ki.requestFullScreen(),o(Xi).trigger("focus"))}))}function go(t,e){t&&o.each(e,function(e,n){n&&o.extend(n,{width:t.width||n.width,height:t.height,minwidth:t.minwidth,maxwidth:t.maxwidth,minheight:t.minheight,maxheight:t.maxheight,ratio:K(t.ratio)})})}function wo(t,e){n.trigger(le+":"+t,[ki,e])}function yo(){clearTimeout(bo.t),xi=1,r.stopautoplayontouch?ki.stopAutoplay():wi=!0}function bo(){xi&&(r.stopautoplayontouch||(xo(),_o()),bo.t=setTimeout(function(){xi=0},Qn+Bn))}function xo(){wi=!(!Ko&&!yi)}function _o(){if(clearTimeout(_o.t),z.stop(_o.w),!r.autoplay||wi)return void(ki.autoplay&&(ki.autoplay=!1,wo("stopautoplay")));ki.autoplay||(ki.autoplay=!0,wo("startautoplay"));var t=Zi,e=Vo[to].data();_o.w=z(function(){return e.state||t!==Zi},function(){_o.t=setTimeout(function(){if(!wi&&t===Zi){var e=Jo,n=Do[e][to].data();_o.w=z(function(){return n.state||e!==Jo},function(){wi||e!==Jo||ki.show(ti?Z(!fi):Jo)})}},r.autoplay)})}function Co(t){var e;return"object"!=typeof t?(e=t,t={}):e=t.index,e=">"===e?Xo+1:"<"===e?Xo-1:"<<"===e?0:">>"===e?Ro-1:e,e=isNaN(e)?i:e,e="undefined"==typeof e?Zi||0:e}function ko(t){ki.activeIndex=Zi=ae(t),Yo=We(Zi),Go=He(Zi),Jo=ne(Zi+(fi?-1:1)),Bo=[Zi,Yo,Go],Xo=ti?t:Zi}function To(t){var e=Math.abs(Uo-Xo),n=_(t.time,function(){return Math.min(li*(1+(e-1)/12),2*li)});return t.slow&&(n*=10),n}function Po(){ki.fullScreen&&(ki.fullScreen=!1,Rn&&Pn.cancel(Si),$n.removeClass(ce),Nn.removeClass(ce),n.removeClass(tn).insertAfter(ji),er=o.extend({},bi),Mo(Ko,!0,!0),No("x",!1),ki.resize(),xn(Bo,"stage"),W(qn,vi,pi),wo("fullscreenexit"))}function So(t,e){di&&(t.removeClass(Qe+" "+Xe),t.removeClass(Ue+" "+Ye),e&&!Ko&&t.addClass(e.replace(/^|\s/g," "+Be+"--")))}function Mo(t,e,n){e&&(zi.removeClass(me),Ko=!1,C()),t&&t!==Ko&&(t.remove(),wo("unloadvideo")),n&&(xo(),_o())}function Eo(t){zi.toggleClass(ge,t)}function Fo(t){if(!nr.flow){var e=t?t.pageX:Fo.x,n=e&&!Vn(Wn(e))&&r.click;Fo.p!==n&&Ni.toggleClass(Me,n)&&(Fo.p=n,Fo.x=e)}}function jo(t){clearTimeout(jo.t),r.clicktransition&&r.clicktransition!==r.transition?setTimeout(function(){var e=r.transition;ki.setOptions({transition:r.clicktransition}),ci=e,jo.t=setTimeout(function(){ki.show(t)},10)},0):ki.show(t)}function zo(t,e){var n=t.target,i=o(n);i.hasClass(wn)?ki.playVideo():n===Xi?ki.toggleFullScreen():Ko?n===Gi&&Mo(Ko,!0,!0):e?Eo():r.click&&jo({index:t.shiftKey||Z(Wn(t._x)),slow:t.altKey,user:!0})}function No(t,e){nr[t]=ir[t]=e}function $o(t){var e=o(this).data().eq;jo("thumbs"===r.navtype?{index:e,slow:t.altKey,user:!0,coo:t._x-Di.offset().left}:{index:e,slow:t.altKey,user:!0})}function qo(t){jo({index:Ii.index(this)?">":"<",slow:t.altKey,user:!0})}function Lo(t){G(t,function(){setTimeout(function(){W(Ni)},0),Eo(!1)})}function Ao(){if(b(),X(),!Ao.i){Ao.i=!0;var t=r.startindex;Zi=Qo=Xo=Uo=Zo=ae(t)||0}if(Ro){if(Io())return;Ko&&Mo(Ko,!0),Bo=[],mo(to),Ao.ok=!0,ki.show({index:Zi,time:0}),ki.resize()}else ki.destroy()}function Io(){return!Io.f===fi?(Io.f=fi,Zi=Ro-1-Zi,ki.reverse(),!0):void 0}function Oo(){Oo.ok&&(Oo.ok=!1,wo("ready"))}Nn=o("html"),$n=o("body");var Do,Ro,Wo,Ho,Ko,Vo,Bo,Qo,Xo,Uo,Yo,Go,Jo,Zo,ti,ei,ni,oi,ii,ri,ai,si,ui,li,ci,di,fi,hi,mi,pi,vi,gi,wi,yi,bi,xi,_i,Ci,ki=this,Ti=o.now(),Pi=le+Ti,Si=n[0],Mi=1,Ei=n.data(),Fi=o("<style></style>"),ji=o(A(Ze)),zi=n.find(I(de)),Ni=zi.find(I(Ce)),$i=(Ni[0],n.find(I(Pe))),qi=o(),Li=n.find(I(je)),Ai=n.find(I(ze)),Ii=n.find(I(Ee)),Oi=n.find(I($e)),Di=Oi.find(I(Ne)),Ri=Di.find(I(qe)),Wi=o(),Hi=o(),Ki=($i.data(),Ri.data(),n.find(I(mn))),Vi=n.find(I(fn)),Bi=n.find(I(hn)),Qi=n.find(I(en)),Xi=Qi[0],Ui=o(A(wn)),Yi=n.find(I(yn)),Gi=Yi[0],Ji=o(A(bn)),Zi=!1,tr={},er={},nr={},or={},ir={},rr={},ar={},sr={},ur=0,lr=[];zi[to]=o('<div class="'+ke+'"></div>'),zi[no]=o(o.Fotorama.jst.thumb()),zi[eo]=o(o.Fotorama.jst.dots()),ar[to]=[],ar[no]=[],ar[eo]=[],sr[to]={},zi.addClass(On?he:fe),Ei.fotorama=this,ki.startAutoplay=function(t){return ki.autoplay?this:(wi=yi=!1,k(t||r.autoplay),_o(),this)},ki.stopAutoplay=function(){return ki.autoplay&&(wi=yi=!0,_o()),this},ki.showSlide=function(t){var e,n=l(Ri,r.navdir),o=550,i="horizontal"===r.navdir?r.thumbwidth:r.thumbheight,a=function(){Yn()};"next"===t&&(e=n-(i+r.margin)*ao),"prev"===t&&(e=n+(i+r.margin)*ao),e=B(e,ir),An(e,!0),te(Ri,{time:o,pos:e,direction:r.navdir,onEnd:a})},ki.showWhileLongPress=function(t){if(!ki.longPress.singlePressInProgress){var e=Co(t);ko(e);var n=To(t)/50,o=Vo;ki.activeFrame=Vo=Do[Zi];var i=o===Vo&&!t.user;return ki.showNav(i,t,n),this}},ki.showEndLongPress=function(t){if(!ki.longPress.singlePressInProgress){var e=Co(t);ko(e);var n=To(t)/50,o=Vo;ki.activeFrame=Vo=Do[Zi];var i=o===Vo&&!t.user;return ki.showStage(i,t,n),gi="undefined"!=typeof Uo&&Uo!==Zi,Uo=Zi,this}},ki.showStage=function(t,e,n){Mo(Ko,Vo.i!==Do[ne(Qo)].i),Sn(Bo,"stage"),En(Hn?[Xo]:[Xo,We(Xo),He(Xo)]),No("go",!0),t||wo("show",{user:e.user,time:n}),wi=!0;var o=e.overPos,i=ki.showStage.onEnd=function(n){if(!i.ok){if(i.ok=!0,n||vo(!0),t||wo("showend",{user:e.user}),!n&&ci&&ci!==r.transition)return ki.setOptions({transition:ci}),void(ci=!1);kn(),xn(Bo,"stage"),No("go",!1),io(),Fo(),xo(),_o()}};if(ai){var a=Vo[to],s=Do[Uo]&&Zi!==Uo?Do[Uo][to]:null;ee(a,s,qi,{time:n,method:r.transition,onEnd:i},lr)}else te($i,{pos:-g(Xo,er.w,r.margin,Qo),overPos:o,time:n,onEnd:i});Xn()},ki.showNav=function(t,e,n){if(Yn(),ei){fo();var o=oe(Zi+s(Xo-Uo,-1,1));co({time:n,coo:o!==Zi&&e.coo,guessIndex:"undefined"!=typeof e.coo?o:Zi,keep:t}),ni&&lo(n)}},ki.show=function(t){ki.longPress.singlePressInProgress=!0;var e=Co(t);ko(e);var n=To(t),o=Vo;ki.activeFrame=Vo=Do[Zi];var i=o===Vo&&!t.user;return ki.showStage(i,t,n),ki.showNav(i,t,n),gi="undefined"!=typeof Uo&&Uo!==Zi,Uo=Zi,ki.longPress.singlePressInProgress=!1,this},ki.requestFullScreen=function(){return ii&&!ki.fullScreen&&(pi=qn.scrollTop(),vi=qn.scrollLeft(),W(qn),No("x",!0),bi=o.extend({},er),n.addClass(tn).appendTo($n.addClass(ce)),Nn.addClass(ce),Mo(Ko,!0,!0),ki.fullScreen=!0,ri&&Pn.request(Si),ki.resize(),xn(Bo,"stage"),kn(),wo("fullscreenenter")),this},ki.cancelFullScreen=function(){return ri&&Pn.is()?Pn.cancel(e):Po(),this},ki.toggleFullScreen=function(){return ki[(ki.fullScreen?"cancel":"request")+"FullScreen"]()},V(e,Pn.event,function(){!Do||Pn.is()||Ko||Po()}),ki.resize=function(e){if(!Do)return this;var n=arguments[1]||0,i=arguments[2];ao=F(zi,r),go(ki.fullScreen?{width:o(t).width(),maxwidth:null,minwidth:null,height:o(t).height(),maxheight:null,minheight:null}:H(e),[er,i||ki.fullScreen||r]);var a=er.width,u=er.height,l=er.ratio,c=qn.height()-(ei?Di.height():0);if(v(a)&&(zi.css({width:""}),zi.css({height:""}),Ni.css({width:""}),Ni.css({height:""}),Ni.css({"line-height":""}),$i.css({width:""}),$i.css({height:""}),Di.css({width:""}),Di.css({height:""}),zi.css({minWidth:er.minwidth||0,maxWidth:er.maxwidth||ro}),a=er.W=er.w=zi.width(),er.nw=ei&&p(r.navwidth,a)||a,$i.css({width:er.w,marginLeft:(er.W-er.w)/2}),u=p(u,c),u=u||l&&a/l)){if(a=Math.round(a),u=er.h=Math.round(s(u,p(er.minheight,c),p(er.maxheight,c))),Ni.css({width:a,height:u,"line-height":u+"px"}),"vertical"!==r.navdir||ki.fullscreen||Di.width(r.thumbwidth+2*r.thumbmargin),"horizontal"!==r.navdir||ki.fullscreen||Di.height(r.thumbheight+2*r.thumbmargin),"vertical"===r.navdir&&ki.fullScreen&&Ni.css("height",o(t).height()),"horizontal"===r.navdir&&ki.fullScreen&&Ni.css("height",o(t).height()-(r.thumbheight+2*r.thumbmargin)),ei){switch(r.navdir){case"vertical":Oi.removeClass(Ie),Oi.removeClass(Ae),Oi.addClass(Le),Di.stop().animate({height:er.h,width:r.thumbwidth},n);break;case"list":Oi.removeClass(Le),Oi.removeClass(Ie),Oi.addClass(Ae);break;default:Oi.removeClass(Le),Oi.removeClass(Ae),Oi.addClass(Ie),Di.stop().animate({width:er.nw},n)}vo(),co({guessIndex:Zi,time:n,keep:!0}),ni&&In.nav&&lo(n)}mi=i||!0,Oo.ok=!0,Oo()}return ur=Ni.offset().left,f(),this},ki.setOptions=function(t){return o.extend(r,t),Ao(),this},ki.shuffle=function(){return Do&&D(Do)&&Ao(),this},ki.longPress={threshold:1,count:0,thumbSlideTime:20,progress:function(){this.inProgress||(this.count++,this.inProgress=this.count>this.threshold)},end:function(){this.inProgress&&(this.isEnded=!0)},reset:function(){this.count=0,this.inProgress=!1,this.isEnded=!1}},ki.destroy=function(){return ki.cancelFullScreen(),ki.stopAutoplay(),Do=ki.data=null,y(),Bo=[],mo(to),Ao.ok=!1,this},ki.playVideo=function(){var t=Vo,e=t.video,n=Zi;return"object"==typeof e&&t.videoReady&&(ri&&ki.fullScreen&&ki.cancelFullScreen(),z(function(){return!Pn.is()||n!==Zi},function(){n===Zi&&(t.$video=t.$video||o(A(gn)).append(O(e)),t.$video.appendTo(t[to]),zi.addClass(me),Ko=t.$video,C(),Ii.blur(),Qi.blur(),wo("loadvideo"))})),this},ki.stopVideo=function(){return Mo(Ko,!0,!0),this},Ni.on("mousemove",Fo),nr=ie($i,{onStart:yo,onMove:function(t,e){So(Ni,e.edge)},onTouchEnd:bo,onEnd:function(t){So(Ni);var e=(Kn&&!_i||t.touch)&&r.arrows&&"always"!==r.arrows;if(t.moved||e&&t.pos!==t.newPos&&!t.control){var n=w(t.newPos,er.w,r.margin,Qo);ki.show({index:n,time:ai?li:t.time,overPos:t.overPos,user:!0})}else t.aborted||t.control||zo(t.startEvent,e)},timeLow:1,timeHigh:1,friction:2,select:"."+Je+", ."+Je+" *",$wrap:Ni,direction:"horizontal"}),ir=ie(Ri,{onStart:yo,onMove:function(t,e){So(Di,e.edge)},onTouchEnd:bo,onEnd:function(t){function e(){co.l=t.newPos,xo(),_o(),An(t.newPos,!0),Yn()}if(t.moved)t.pos!==t.newPos?(wi=!0,te(Ri,{time:t.time,pos:t.newPos,overPos:t.overPos,direction:r.navdir,onEnd:e}),An(t.newPos),di&&So(Di,q(t.newPos,ir.min,ir.max,t.dir))):e();else{var n=t.$target.closest("."+Re,Ri)[0];n&&$o.call(n,t.startEvent)}},timeLow:.5,timeHigh:2,friction:5,$wrap:Di,direction:r.navdir}),or=re(Ni,{shift:!0,onEnd:function(t,e){yo(),bo(),ki.show({index:e,slow:t.altKey})}}),rr=re(Di,{onEnd:function(t,e){yo(),bo();var n=x(Ri)+.25*e;Ri.css(c(s(n,ir.min,ir.max),r.navdir)),di&&So(Di,q(n,ir.min,ir.max,r.navdir)),rr.prevent={"<":n>=ir.max,">":n<=ir.min},clearTimeout(rr.t),rr.t=setTimeout(function(){co.l=n,An(n,!0)},Bn),An(n)}}),zi.hover(function(){setTimeout(function(){xi||Eo(!(_i=!0))},0)},function(){_i&&Eo(!(_i=!1))}),L(Ii,function(t){J(t),qo.call(this,t)},{onStart:function(){yo(),nr.control=!0},onTouchEnd:bo}),L(Vi,function(t){J(t),"thumbs"===r.navtype?ki.show("<"):ki.showSlide("prev")}),L(Bi,function(t){J(t),"thumbs"===r.navtype?ki.show(">"):ki.showSlide("next")}),Ii.each(function(){Y(this,function(t){qo.call(this,t)}),Lo(this)}),Y(Xi,function(){ki.toggleFullScreen(),o(Xi).trigger("focus")}),Lo(Xi),o.each("load push pop shift unshift reverse sort splice".split(" "),function(t,e){ki[e]=function(){return Do=Do||[],"load"!==e?Array.prototype[e].apply(Do,arguments):arguments[0]&&"object"==typeof arguments[0]&&arguments[0].length&&(Do=R(arguments[0])),Ao(),ki}}),Ao()},o.fn.fotorama=function(e){return this.each(function(){var n=this,i=o(this),r=i.data(),a=r.fotorama;a?a.setOptions(e,!0):z(function(){return!F(n)},function(){r.urtext=i.html(),new o.Fotorama(i,o.extend({},so,t.fotoramaDefaults,e,r))})})},o.Fotorama.instances=[],o.Fotorama.cache={},o.Fotorama.measures={},o=o||{},o.Fotorama=o.Fotorama||{},o.Fotorama.jst=o.Fotorama.jst||{},o.Fotorama.jst.dots=function(){{var t="";kn.escape}return t+='<div class="fotorama__nav__frame fotorama__nav__frame--dot" tabindex="0" role="button" data-gallery-role="nav-frame" data-nav-type="thumb" aria-label>\r\n <div class="fotorama__dot"></div>\r\n</div>'},o.Fotorama.jst.frameCaption=function(t){{var e,n="";kn.escape}return n+='<div class="fotorama__caption" aria-hidden="true">\r\n <div class="fotorama__caption__wrap" id="'+(null==(e=t.labelledby)?"":e)+'">'+(null==(e=t.caption)?"":e)+"</div>\r\n</div>\r\n"},o.Fotorama.jst.style=function(t){{var e,n="";kn.escape}return n+=".fotorama"+(null==(e=t.s)?"":e)+" .fotorama__nav--thumbs .fotorama__nav__frame{\r\npadding:"+(null==(e=t.m)?"":e)+"px;\r\nheight:"+(null==(e=t.h)?"":e)+"px}\r\n.fotorama"+(null==(e=t.s)?"":e)+" .fotorama__thumb-border{\r\nheight:"+(null==(e=t.h)?"":e)+"px;\r\nborder-width:"+(null==(e=t.b)?"":e)+"px;\r\nmargin-top:"+(null==(e=t.m)?"":e)+"px}"},o.Fotorama.jst.thumb=function(){{var t="";kn.escape}return t+='<div class="fotorama__nav__frame fotorama__nav__frame--thumb" tabindex="0" role="button" data-gallery-role="nav-frame" data-nav-type="thumb" aria-label>\r\n <div class="fotorama__thumb">\r\n </div>\r\n</div>'}}(window,document,location,"undefined"!=typeof jQuery&&jQuery); \ No newline at end of file diff --git a/lib/web/legacy-build.min.js b/lib/web/legacy-build.min.js index e6c723156294c1337da171abb4a71eafff53bc38..289cf49e76a13c09e121bca1233be56459494be7 100644 --- a/lib/web/legacy-build.min.js +++ b/lib/web/legacy-build.min.js @@ -5,4 +5,4 @@ var Prototype={Version:"1.7",Browser:(function(){var d=navigator.userAgent;var b * Released under the MIT, BSD, and GPL Licenses. * More information: http://sizzlejs.com/ */ -(function(){var w=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,p=0,g=Object.prototype.toString,u=false,o=true;[0,0].sort(function(){o=false;return 0});var d=function(L,B,I,D){I=I||[];var e=B=B||document;if(B.nodeType!==1&&B.nodeType!==9){return[]}if(!L||typeof L!=="string"){return I}var J=[],K,G,P,O,H,A,z=true,E=v(B),N=L;while((w.exec(""),K=w.exec(N))!==null){N=K[3];J.push(K[1]);if(K[2]){A=K[3];break}}if(J.length>1&&q.exec(L)){if(J.length===2&&h.relative[J[0]]){G=l(J[0]+J[1],B)}else{G=h.relative[J[0]]?[B]:d(J.shift(),B);while(J.length){L=J.shift();if(h.relative[L]){L+=J.shift()}G=l(L,G)}}}else{if(!D&&J.length>1&&B.nodeType===9&&!E&&h.match.ID.test(J[0])&&!h.match.ID.test(J[J.length-1])){var Q=d.find(J.shift(),B,E);B=Q.expr?d.filter(Q.expr,Q.set)[0]:Q.set[0]}if(B){var Q=D?{expr:J.pop(),set:b(D)}:d.find(J.pop(),J.length===1&&(J[0]==="~"||J[0]==="+")&&B.parentNode?B.parentNode:B,E);G=Q.expr?d.filter(Q.expr,Q.set):Q.set;if(J.length>0){P=b(G)}else{z=false}while(J.length){var C=J.pop(),F=C;if(!h.relative[C]){C=""}else{F=J.pop()}if(F==null){F=B}h.relative[C](P,F,E)}}else{P=J=[]}}if(!P){P=G}if(!P){throw"Syntax error, unrecognized expression: "+(C||L)}if(g.call(P)==="[object Array]"){if(!z){I.push.apply(I,P)}else{if(B&&B.nodeType===1){for(var M=0;P[M]!=null;M++){if(P[M]&&(P[M]===true||P[M].nodeType===1&&n(B,P[M]))){I.push(G[M])}}}else{for(var M=0;P[M]!=null;M++){if(P[M]&&P[M].nodeType===1){I.push(G[M])}}}}}else{b(P,I)}if(A){d(A,e,I,D);d.uniqueSort(I)}return I};d.uniqueSort=function(z){if(f){u=o;z.sort(f);if(u){for(var e=1;e<z.length;e++){if(z[e]===z[e-1]){z.splice(e--,1)}}}}return z};d.matches=function(e,z){return d(e,null,null,z)};d.find=function(F,e,G){var E,C;if(!F){return[]}for(var B=0,A=h.order.length;B<A;B++){var D=h.order[B],C;if((C=h.leftMatch[D].exec(F))){var z=C[1];C.splice(1,1);if(z.substr(z.length-1)!=="\\"){C[1]=(C[1]||"").replace(/\\/g,"");E=h.find[D](C,e,G);if(E!=null){F=F.replace(h.match[D],"");break}}}}if(!E){E=e.getElementsByTagName("*")}return{set:E,expr:F}};d.filter=function(I,H,L,B){var A=I,N=[],F=H,D,e,E=H&&H[0]&&v(H[0]);while(I&&H.length){for(var G in h.filter){if((D=h.match[G].exec(I))!=null){var z=h.filter[G],M,K;e=false;if(F==N){N=[]}if(h.preFilter[G]){D=h.preFilter[G](D,F,L,N,B,E);if(!D){e=M=true}else{if(D===true){continue}}}if(D){for(var C=0;(K=F[C])!=null;C++){if(K){M=z(K,D,C,F);var J=B^!!M;if(L&&M!=null){if(J){e=true}else{F[C]=false}}else{if(J){N.push(K);e=true}}}}}if(M!==undefined){if(!L){F=N}I=I.replace(h.match[G],"");if(!e){return[]}break}}}if(I==A){if(e==null){throw"Syntax error, unrecognized expression: "+I}else{break}}A=I}return F};var h=d.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(e){return e.getAttribute("href")}},relative:{"+":function(F,e,E){var C=typeof e==="string",G=C&&!/\W/.test(e),D=C&&!G;if(G&&!E){e=e.toUpperCase()}for(var B=0,A=F.length,z;B<A;B++){if((z=F[B])){while((z=z.previousSibling)&&z.nodeType!==1){}F[B]=D||z&&z.nodeName===e?z||false:z===e}}if(D){d.filter(e,F,true)}},">":function(E,z,F){var C=typeof z==="string";if(C&&!/\W/.test(z)){z=F?z:z.toUpperCase();for(var A=0,e=E.length;A<e;A++){var D=E[A];if(D){var B=D.parentNode;E[A]=B.nodeName===z?B:false}}}else{for(var A=0,e=E.length;A<e;A++){var D=E[A];if(D){E[A]=C?D.parentNode:D.parentNode===z}}if(C){d.filter(z,E,true)}}},"":function(B,z,D){var A=p++,e=y;if(!/\W/.test(z)){var C=z=D?z:z.toUpperCase();e=t}e("parentNode",z,A,B,C,D)},"~":function(B,z,D){var A=p++,e=y;if(typeof z==="string"&&!/\W/.test(z)){var C=z=D?z:z.toUpperCase();e=t}e("previousSibling",z,A,B,C,D)}},find:{ID:function(z,A,B){if(typeof A.getElementById!=="undefined"&&!B){var e=A.getElementById(z[1]);return e?[e]:[]}},NAME:function(A,D,E){if(typeof D.getElementsByName!=="undefined"){var z=[],C=D.getElementsByName(A[1]);for(var B=0,e=C.length;B<e;B++){if(C[B].getAttribute("name")===A[1]){z.push(C[B])}}return z.length===0?null:z}},TAG:function(e,z){return z.getElementsByTagName(e[1])}},preFilter:{CLASS:function(B,z,A,e,E,F){B=" "+B[1].replace(/\\/g,"")+" ";if(F){return B}for(var C=0,D;(D=z[C])!=null;C++){if(D){if(E^(D.className&&(" "+D.className+" ").indexOf(B)>=0)){if(!A){e.push(D)}}else{if(A){z[C]=false}}}}return false},ID:function(e){return e[1].replace(/\\/g,"")},TAG:function(z,e){for(var A=0;e[A]===false;A++){}return e[A]&&v(e[A])?z[1]:z[1].toUpperCase()},CHILD:function(e){if(e[1]=="nth"){var z=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(e[2]=="even"&&"2n"||e[2]=="odd"&&"2n+1"||!/\D/.test(e[2])&&"0n+"+e[2]||e[2]);e[2]=(z[1]+(z[2]||1))-0;e[3]=z[3]-0}e[0]=p++;return e},ATTR:function(C,z,A,e,D,E){var B=C[1].replace(/\\/g,"");if(!E&&h.attrMap[B]){C[1]=h.attrMap[B]}if(C[2]==="~="){C[4]=" "+C[4]+" "}return C},PSEUDO:function(C,z,A,e,D){if(C[1]==="not"){if((w.exec(C[3])||"").length>1||/^\w/.test(C[3])){C[3]=d(C[3],null,null,z)}else{var B=d.filter(C[3],z,A,true^D);if(!A){e.push.apply(e,B)}return false}}else{if(h.match.POS.test(C[0])||h.match.CHILD.test(C[0])){return true}}return C},POS:function(e){e.unshift(true);return e}},filters:{enabled:function(e){return e.disabled===false&&e.type!=="hidden"},disabled:function(e){return e.disabled===true},checked:function(e){return e.checked===true},selected:function(e){e.parentNode.selectedIndex;return e.selected===true},parent:function(e){return !!e.firstChild},empty:function(e){return !e.firstChild},has:function(A,z,e){return !!d(e[3],A).length},header:function(e){return/h\d/i.test(e.nodeName)},text:function(e){return"text"===e.type},radio:function(e){return"radio"===e.type},checkbox:function(e){return"checkbox"===e.type},file:function(e){return"file"===e.type},password:function(e){return"password"===e.type},submit:function(e){return"submit"===e.type},image:function(e){return"image"===e.type},reset:function(e){return"reset"===e.type},button:function(e){return"button"===e.type||e.nodeName.toUpperCase()==="BUTTON"},input:function(e){return/input|select|textarea|button/i.test(e.nodeName)}},setFilters:{first:function(z,e){return e===0},last:function(A,z,e,B){return z===B.length-1},even:function(z,e){return e%2===0},odd:function(z,e){return e%2===1},lt:function(A,z,e){return z<e[3]-0},gt:function(A,z,e){return z>e[3]-0},nth:function(A,z,e){return e[3]-0==z},eq:function(A,z,e){return e[3]-0==z}},filter:{PSEUDO:function(E,A,B,F){var z=A[1],C=h.filters[z];if(C){return C(E,B,A,F)}else{if(z==="contains"){return(E.textContent||E.innerText||"").indexOf(A[3])>=0}else{if(z==="not"){var D=A[3];for(var B=0,e=D.length;B<e;B++){if(D[B]===E){return false}}return true}}}},CHILD:function(e,B){var E=B[1],z=e;switch(E){case"only":case"first":while((z=z.previousSibling)){if(z.nodeType===1){return false}}if(E=="first"){return true}z=e;case"last":while((z=z.nextSibling)){if(z.nodeType===1){return false}}return true;case"nth":var A=B[2],H=B[3];if(A==1&&H==0){return true}var D=B[0],G=e.parentNode;if(G&&(G.sizcache!==D||!e.nodeIndex)){var C=0;for(z=G.firstChild;z;z=z.nextSibling){if(z.nodeType===1){z.nodeIndex=++C}}G.sizcache=D}var F=e.nodeIndex-H;if(A==0){return F==0}else{return(F%A==0&&F/A>=0)}}},ID:function(z,e){return z.nodeType===1&&z.getAttribute("id")===e},TAG:function(z,e){return(e==="*"&&z.nodeType===1)||z.nodeName===e},CLASS:function(z,e){return(" "+(z.className||z.getAttribute("class"))+" ").indexOf(e)>-1},ATTR:function(D,B){var A=B[1],e=h.attrHandle[A]?h.attrHandle[A](D):D[A]!=null?D[A]:D.getAttribute(A),E=e+"",C=B[2],z=B[4];return e==null?C==="!=":C==="="?E===z:C==="*="?E.indexOf(z)>=0:C==="~="?(" "+E+" ").indexOf(z)>=0:!z?E&&e!==false:C==="!="?E!=z:C==="^="?E.indexOf(z)===0:C==="$="?E.substr(E.length-z.length)===z:C==="|="?E===z||E.substr(0,z.length+1)===z+"-":false},POS:function(C,z,A,D){var e=z[2],B=h.setFilters[e];if(B){return B(C,A,z,D)}}}};var q=h.match.POS;for(var s in h.match){h.match[s]=new RegExp(h.match[s].source+/(?![^\[]*\])(?![^\(]*\))/.source);h.leftMatch[s]=new RegExp(/(^(?:.|\r|\n)*?)/.source+h.match[s].source)}var b=function(z,e){z=Array.prototype.slice.call(z,0);if(e){e.push.apply(e,z);return e}return z};try{Array.prototype.slice.call(document.documentElement.childNodes,0)}catch(r){b=function(C,B){var z=B||[];if(g.call(C)==="[object Array]"){Array.prototype.push.apply(z,C)}else{if(typeof C.length==="number"){for(var A=0,e=C.length;A<e;A++){z.push(C[A])}}else{for(var A=0;C[A];A++){z.push(C[A])}}}return z}}var f;if(document.documentElement.compareDocumentPosition){f=function(z,e){if(!z.compareDocumentPosition||!e.compareDocumentPosition){if(z==e){u=true}return 0}var A=z.compareDocumentPosition(e)&4?-1:z===e?0:1;if(A===0){u=true}return A}}else{if("sourceIndex" in document.documentElement){f=function(z,e){if(!z.sourceIndex||!e.sourceIndex){if(z==e){u=true}return 0}var A=z.sourceIndex-e.sourceIndex;if(A===0){u=true}return A}}else{if(document.createRange){f=function(B,z){if(!B.ownerDocument||!z.ownerDocument){if(B==z){u=true}return 0}var A=B.ownerDocument.createRange(),e=z.ownerDocument.createRange();A.setStart(B,0);A.setEnd(B,0);e.setStart(z,0);e.setEnd(z,0);var C=A.compareBoundaryPoints(Range.START_TO_END,e);if(C===0){u=true}return C}}}}(function(){var z=document.createElement("div"),A="script"+(new Date).getTime();z.innerHTML="<a name='"+A+"'/>";var e=document.documentElement;e.insertBefore(z,e.firstChild);if(!!document.getElementById(A)){h.find.ID=function(C,D,E){if(typeof D.getElementById!=="undefined"&&!E){var B=D.getElementById(C[1]);return B?B.id===C[1]||typeof B.getAttributeNode!=="undefined"&&B.getAttributeNode("id").nodeValue===C[1]?[B]:undefined:[]}};h.filter.ID=function(D,B){var C=typeof D.getAttributeNode!=="undefined"&&D.getAttributeNode("id");return D.nodeType===1&&C&&C.nodeValue===B}}e.removeChild(z);e=z=null})();(function(){var e=document.createElement("div");e.appendChild(document.createComment(""));if(e.getElementsByTagName("*").length>0){h.find.TAG=function(z,D){var C=D.getElementsByTagName(z[1]);if(z[1]==="*"){var B=[];for(var A=0;C[A];A++){if(C[A].nodeType===1){B.push(C[A])}}C=B}return C}}e.innerHTML="<a href='#'></a>";if(e.firstChild&&typeof e.firstChild.getAttribute!=="undefined"&&e.firstChild.getAttribute("href")!=="#"){h.attrHandle.href=function(z){return z.getAttribute("href",2)}}e=null})();if(document.querySelectorAll){(function(){var e=d,A=document.createElement("div");A.innerHTML="<p class='TEST'></p>";if(A.querySelectorAll&&A.querySelectorAll(".TEST").length===0){return}d=function(E,D,B,C){D=D||document;if(!C&&D.nodeType===9&&!v(D)){try{return b(D.querySelectorAll(E),B)}catch(F){}}return e(E,D,B,C)};for(var z in e){d[z]=e[z]}A=null})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var e=document.createElement("div");e.innerHTML="<div class='test e'></div><div class='test'></div>";if(e.getElementsByClassName("e").length===0){return}e.lastChild.className="e";if(e.getElementsByClassName("e").length===1){return}h.order.splice(1,0,"CLASS");h.find.CLASS=function(z,A,B){if(typeof A.getElementsByClassName!=="undefined"&&!B){return A.getElementsByClassName(z[1])}};e=null})()}function t(z,E,D,I,F,H){var G=z=="previousSibling"&&!H;for(var B=0,A=I.length;B<A;B++){var e=I[B];if(e){if(G&&e.nodeType===1){e.sizcache=D;e.sizset=B}e=e[z];var C=false;while(e){if(e.sizcache===D){C=I[e.sizset];break}if(e.nodeType===1&&!H){e.sizcache=D;e.sizset=B}if(e.nodeName===E){C=e;break}e=e[z]}I[B]=C}}}function y(z,E,D,I,F,H){var G=z=="previousSibling"&&!H;for(var B=0,A=I.length;B<A;B++){var e=I[B];if(e){if(G&&e.nodeType===1){e.sizcache=D;e.sizset=B}e=e[z];var C=false;while(e){if(e.sizcache===D){C=I[e.sizset];break}if(e.nodeType===1){if(!H){e.sizcache=D;e.sizset=B}if(typeof E!=="string"){if(e===E){C=true;break}}else{if(d.filter(E,[e]).length>0){C=e;break}}}e=e[z]}I[B]=C}}}var n=document.compareDocumentPosition?function(z,e){return z.compareDocumentPosition(e)&16}:function(z,e){return z!==e&&(z.contains?z.contains(e):true)};var v=function(e){return e.nodeType===9&&e.documentElement.nodeName!=="HTML"||!!e.ownerDocument&&e.ownerDocument.documentElement.nodeName!=="HTML"};var l=function(e,F){var B=[],C="",D,A=F.nodeType?[F]:F;while((D=h.match.PSEUDO.exec(e))){C+=D[0];e=e.replace(h.match.PSEUDO,"")}e=h.relative[e]?e+"*":e;for(var E=0,z=A.length;E<z;E++){d(e,A[E],B)}return d.filter(C,B)};window.Sizzle=d})();(function(e){var f=Prototype.Selector.extendElements;function b(g,h){return f(e(g,h||document))}function d(h,g){return e.matches(g,[h]).length==1}Prototype.Selector.engine=e;Prototype.Selector.select=b;Prototype.Selector.match=d})(Sizzle);window.Sizzle=Prototype._original_property;delete Prototype._original_property;var Form={reset:function(b){b=$(b);b.reset();return b},serializeElements:function(n,f){if(typeof f!="object"){f={hash:!!f}}else{if(Object.isUndefined(f.hash)){f.hash=true}}var g,l,b=false,h=f.submit,d,e;if(f.hash){e={};d=function(o,p,q){if(p in o){if(!Object.isArray(o[p])){o[p]=[o[p]]}o[p].push(q)}else{o[p]=q}return o}}else{e="";d=function(o,p,q){return o+(o?"&":"")+encodeURIComponent(p)+"="+encodeURIComponent(q)}}return n.inject(e,function(o,p){if(!p.disabled&&p.name){g=p.name;l=$(p).getValue();if(l!=null&&p.type!="file"&&(p.type!="submit"||(!b&&h!==false&&(!h||g==h)&&(b=true)))){o=d(o,g,l)}}return o})}};Form.Methods={serialize:function(d,b){return Form.serializeElements(Form.getElements(d),b)},getElements:function(g){var h=$(g).getElementsByTagName("*"),f,b=[],e=Form.Element.Serializers;for(var d=0;f=h[d];d++){b.push(f)}return b.inject([],function(l,n){if(e[n.tagName.toLowerCase()]){l.push(Element.extend(n))}return l})},getInputs:function(l,e,f){l=$(l);var b=l.getElementsByTagName("input");if(!e&&!f){return $A(b).map(Element.extend)}for(var g=0,n=[],h=b.length;g<h;g++){var d=b[g];if((e&&d.type!=e)||(f&&d.name!=f)){continue}n.push(Element.extend(d))}return n},disable:function(b){b=$(b);Form.getElements(b).invoke("disable");return b},enable:function(b){b=$(b);Form.getElements(b).invoke("enable");return b},findFirstElement:function(d){var e=$(d).getElements().findAll(function(f){return"hidden"!=f.type&&!f.disabled});var b=e.findAll(function(f){return f.hasAttribute("tabIndex")&&f.tabIndex>=0}).sortBy(function(f){return f.tabIndex}).first();return b?b:e.find(function(f){return/^(?:input|select|textarea)$/i.test(f.tagName)})},focusFirstElement:function(d){d=$(d);var b=d.findFirstElement();if(b){b.activate()}return d},request:function(d,b){d=$(d),b=Object.clone(b||{});var f=b.parameters,e=d.readAttribute("action")||"";if(e.blank()){e=window.location.href}b.parameters=d.serialize(true);if(f){if(Object.isString(f)){f=f.toQueryParams()}Object.extend(b.parameters,f)}if(d.hasAttribute("method")&&!b.method){b.method=d.method}return new Ajax.Request(e,b)}};Form.Element={focus:function(b){$(b).focus();return b},select:function(b){$(b).select();return b}};Form.Element.Methods={serialize:function(b){b=$(b);if(!b.disabled&&b.name){var d=b.getValue();if(d!=undefined){var e={};e[b.name]=d;return Object.toQueryString(e)}}return""},getValue:function(b){b=$(b);var d=b.tagName.toLowerCase();return Form.Element.Serializers[d](b)},setValue:function(b,d){b=$(b);var e=b.tagName.toLowerCase();Form.Element.Serializers[e](b,d);return b},clear:function(b){$(b).value="";return b},present:function(b){return $(b).value!=""},activate:function(b){b=$(b);try{b.focus();if(b.select&&(b.tagName.toLowerCase()!="input"||!(/^(?:button|reset|submit)$/i.test(b.type)))){b.select()}}catch(d){}return b},disable:function(b){b=$(b);b.disabled=true;return b},enable:function(b){b=$(b);b.disabled=false;return b}};var Field=Form.Element;var $F=Form.Element.Methods.getValue;Form.Element.Serializers=(function(){function d(n,o){switch(n.type.toLowerCase()){case"checkbox":case"radio":return h(n,o);default:return g(n,o)}}function h(n,o){if(Object.isUndefined(o)){return n.checked?n.value:null}else{n.checked=!!o}}function g(n,o){if(Object.isUndefined(o)){return n.value}else{n.value=o}}function b(p,s){if(Object.isUndefined(s)){return(p.type==="select-one"?e:f)(p)}var o,q,t=!Object.isArray(s);for(var n=0,r=p.length;n<r;n++){o=p.options[n];q=this.optionValue(o);if(t){if(q==s){o.selected=true;return}}else{o.selected=s.include(q)}}}function e(o){var n=o.selectedIndex;return n>=0?l(o.options[n]):null}function f(q){var n,r=q.length;if(!r){return null}for(var p=0,n=[];p<r;p++){var o=q.options[p];if(o.selected){n.push(l(o))}}return n}function l(n){return Element.hasAttribute(n,"value")?n.value:n.text}return{input:d,inputSelector:h,textarea:g,select:b,selectOne:e,selectMany:f,optionValue:l,button:g}})();Abstract.TimedObserver=Class.create(PeriodicalExecuter,{initialize:function($super,b,d,e){$super(e,d);this.element=$(b);this.lastValue=this.getValue()},execute:function(){var b=this.getValue();if(Object.isString(this.lastValue)&&Object.isString(b)?this.lastValue!=b:String(this.lastValue)!=String(b)){this.callback(this.element,b);this.lastValue=b}}});Form.Element.Observer=Class.create(Abstract.TimedObserver,{getValue:function(){return Form.Element.getValue(this.element)}});Form.Observer=Class.create(Abstract.TimedObserver,{getValue:function(){return Form.serialize(this.element)}});Abstract.EventObserver=Class.create({initialize:function(b,d){this.element=$(b);this.callback=d;this.lastValue=this.getValue();if(this.element.tagName.toLowerCase()=="form"){this.registerFormCallbacks()}else{this.registerCallback(this.element)}},onElementEvent:function(){var b=this.getValue();if(this.lastValue!=b){this.callback(this.element,b);this.lastValue=b}},registerFormCallbacks:function(){Form.getElements(this.element).each(this.registerCallback,this)},registerCallback:function(b){if(b.type){switch(b.type.toLowerCase()){case"checkbox":case"radio":Event.observe(b,"click",this.onElementEvent.bind(this));break;default:Event.observe(b,"change",this.onElementEvent.bind(this));break}}}});Form.Element.EventObserver=Class.create(Abstract.EventObserver,{getValue:function(){return Form.Element.getValue(this.element)}});Form.EventObserver=Class.create(Abstract.EventObserver,{getValue:function(){return Form.serialize(this.element)}});(function(){var J={KEY_BACKSPACE:8,KEY_TAB:9,KEY_RETURN:13,KEY_ESC:27,KEY_LEFT:37,KEY_UP:38,KEY_RIGHT:39,KEY_DOWN:40,KEY_DELETE:46,KEY_HOME:36,KEY_END:35,KEY_PAGEUP:33,KEY_PAGEDOWN:34,KEY_INSERT:45,cache:{}};var h=document.documentElement;var K="onmouseenter" in h&&"onmouseleave" in h;var b=function(L){return false};if(window.attachEvent){if(window.addEventListener){b=function(L){return !(L instanceof window.Event)}}else{b=function(L){return true}}}var y;function H(M,L){return M.which?(M.which===L+1):(M.button===L)}var u={0:1,1:4,2:2};function F(M,L){return M.button===u[L]}function I(M,L){switch(L){case 0:return M.which==1&&!M.metaKey;case 1:return M.which==2||(M.which==1&&M.metaKey);case 2:return M.which==3;default:return false}}if(window.attachEvent){if(!window.addEventListener){y=F}else{y=function(M,L){return b(M)?F(M,L):H(M,L)}}}else{if(Prototype.Browser.WebKit){y=I}else{y=H}}function C(L){return y(L,0)}function A(L){return y(L,1)}function t(L){return y(L,2)}function f(N){N=J.extend(N);var M=N.target,L=N.type,O=N.currentTarget;if(O&&O.tagName){if(L==="load"||L==="error"||(L==="click"&&O.tagName.toLowerCase()==="input"&&O.type==="radio")){M=O}}if(M.nodeType==Node.TEXT_NODE){M=M.parentNode}return Element.extend(M)}function v(M,N){var L=J.element(M);if(!N){return L}while(L){if(Object.isElement(L)&&Prototype.Selector.match(L,N)){return Element.extend(L)}L=L.parentNode}}function z(L){return{x:e(L),y:d(L)}}function e(N){var M=document.documentElement,L=document.body||{scrollLeft:0};return N.pageX||(N.clientX+(M.scrollLeft||L.scrollLeft)-(M.clientLeft||0))}function d(N){var M=document.documentElement,L=document.body||{scrollTop:0};return N.pageY||(N.clientY+(M.scrollTop||L.scrollTop)-(M.clientTop||0))}function w(L){J.extend(L);L.preventDefault();L.stopPropagation();L.stopped=true}J.Methods={isLeftClick:C,isMiddleClick:A,isRightClick:t,element:f,findElement:v,pointer:z,pointerX:e,pointerY:d,stop:w};var E=Object.keys(J.Methods).inject({},function(L,M){L[M]=J.Methods[M].methodize();return L});if(window.attachEvent){function o(M){var L;switch(M.type){case"mouseover":case"mouseenter":L=M.fromElement;break;case"mouseout":case"mouseleave":L=M.toElement;break;default:return null}return Element.extend(L)}var B={stopPropagation:function(){this.cancelBubble=true},preventDefault:function(){this.returnValue=false},inspect:function(){return"[object Event]"}};J.extend=function(M,L){if(!M){return false}if(!b(M)){return M}if(M._extendedByPrototype){return M}M._extendedByPrototype=Prototype.emptyFunction;var N=J.pointer(M);Object.extend(M,{target:M.srcElement||L,relatedTarget:o(M),pageX:N.x,pageY:N.y});Object.extend(M,E);Object.extend(M,B);return M}}else{J.extend=Prototype.K}if(window.addEventListener){J.prototype=window.Event.prototype||document.createEvent("HTMLEvents").__proto__;Object.extend(J.prototype,E)}function s(P,O,Q){var N=Element.retrieve(P,"prototype_event_registry");if(Object.isUndefined(N)){g.push(P);N=Element.retrieve(P,"prototype_event_registry",$H())}var L=N.get(O);if(Object.isUndefined(L)){L=[];N.set(O,L)}if(L.pluck("handler").include(Q)){return false}var M;if(O.include(":")){M=function(R){if(Object.isUndefined(R.eventName)){return false}if(R.eventName!==O){return false}J.extend(R,P);Q.call(P,R)}}else{if(!K&&(O==="mouseenter"||O==="mouseleave")){if(O==="mouseenter"||O==="mouseleave"){M=function(S){J.extend(S,P);var R=S.relatedTarget;while(R&&R!==P){try{R=R.parentNode}catch(T){R=P}}if(R===P){return}Q.call(P,S)}}}else{M=function(R){J.extend(R,P);Q.call(P,R)}}}M.handler=Q;L.push(M);return M}function n(){for(var L=0,M=g.length;L<M;L++){J.stopObserving(g[L]);g[L]=null}}var g=[];if(Prototype.Browser.IE){window.attachEvent("onunload",n)}if(Prototype.Browser.WebKit){window.addEventListener("unload",Prototype.emptyFunction,false)}var r=Prototype.K,l={mouseenter:"mouseover",mouseleave:"mouseout"};if(!K){r=function(L){return(l[L]||L)}}function D(O,N,P){O=$(O);var M=s(O,N,P);if(!M){return O}if(N.include(":")){if(O.addEventListener){O.addEventListener("dataavailable",M,false)}else{O.attachEvent("ondataavailable",M);O.attachEvent("onlosecapture",M)}}else{var L=r(N);if(O.addEventListener){O.addEventListener(L,M,false)}else{O.attachEvent("on"+L,M)}}return O}function q(R,O,S){R=$(R);var N=Element.retrieve(R,"prototype_event_registry");if(!N){return R}if(!O){N.each(function(U){var T=U.key;q(R,T)});return R}var P=N.get(O);if(!P){return R}if(!S){P.each(function(T){q(R,O,T.handler)});return R}var Q=P.length,M;while(Q--){if(P[Q].handler===S){M=P[Q];break}}if(!M){return R}if(O.include(":")){if(R.removeEventListener){R.removeEventListener("dataavailable",M,false)}else{R.detachEvent("ondataavailable",M);R.detachEvent("onlosecapture",M)}}else{var L=r(O);if(R.removeEventListener){R.removeEventListener(L,M,false)}else{R.detachEvent("on"+L,M)}}N.set(O,P.without(M));return R}function G(O,N,M,L){O=$(O);if(Object.isUndefined(L)){L=true}if(O==document&&document.createEvent&&!O.dispatchEvent){O=document.documentElement}var P;if(document.createEvent){P=document.createEvent("HTMLEvents");P.initEvent("dataavailable",L,true)}else{P=document.createEventObject();P.eventType=L?"ondataavailable":"onlosecapture"}P.eventName=N;P.memo=M||{};if(document.createEvent){O.dispatchEvent(P)}else{O.fireEvent(P.eventType,P)}return J.extend(P)}J.Handler=Class.create({initialize:function(N,M,L,O){this.element=$(N);this.eventName=M;this.selector=L;this.callback=O;this.handler=this.handleEvent.bind(this)},start:function(){J.observe(this.element,this.eventName,this.handler);return this},stop:function(){J.stopObserving(this.element,this.eventName,this.handler);return this},handleEvent:function(M){var L=J.findElement(M,this.selector);if(L){this.callback.call(this.element,M,L)}}});function p(N,M,L,O){N=$(N);if(Object.isFunction(L)&&Object.isUndefined(O)){O=L,L=null}return new J.Handler(N,M,L,O).start()}Object.extend(J,J.Methods);Object.extend(J,{fire:G,observe:D,stopObserving:q,on:p});Element.addMethods({fire:G,observe:D,stopObserving:q,on:p});Object.extend(document,{fire:G.methodize(),observe:D.methodize(),stopObserving:q.methodize(),on:p.methodize(),loaded:false});if(window.Event){Object.extend(window.Event,J)}else{window.Event=J}})();(function(){var e;function b(){if(document.loaded){return}if(e){window.clearTimeout(e)}document.loaded=true;document.fire("dom:loaded")}function d(){if(document.readyState==="complete"){document.stopObserving("readystatechange",d);b()}}if(document.addEventListener){document.addEventListener("DOMContentLoaded",b,false)}else{document.observe("readystatechange",d);if(window==top){var e=window.setInterval(function(){try{document.documentElement.doScroll("left")}catch(f){return}window.clearInterval(e);b()},5)}}Event.observe(window,"load",b)})();Element.addMethods();Hash.toQueryString=Object.toQueryString;var Toggle={display:Element.toggle};Element.Methods.childOf=Element.Methods.descendantOf;var Insertion={Before:function(b,d){return Element.insert(b,{before:d})},Top:function(b,d){return Element.insert(b,{top:d})},Bottom:function(b,d){return Element.insert(b,{bottom:d})},After:function(b,d){return Element.insert(b,{after:d})}};var $continue=new Error('"throw $continue" is deprecated, use "return" instead');var Position={includeScrollOffsets:false,prepare:function(){this.deltaX=window.pageXOffset||document.documentElement.scrollLeft||document.body.scrollLeft||0;this.deltaY=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0},within:function(d,b,e){if(this.includeScrollOffsets){return this.withinIncludingScrolloffsets(d,b,e)}this.xcomp=b;this.ycomp=e;this.offset=Element.cumulativeOffset(d);return(e>=this.offset[1]&&e<this.offset[1]+d.offsetHeight&&b>=this.offset[0]&&b<this.offset[0]+d.offsetWidth)},withinIncludingScrolloffsets:function(d,b,f){var e=Element.cumulativeScrollOffset(d);this.xcomp=b+e[0]-this.deltaX;this.ycomp=f+e[1]-this.deltaY;this.offset=Element.cumulativeOffset(d);return(this.ycomp>=this.offset[1]&&this.ycomp<this.offset[1]+d.offsetHeight&&this.xcomp>=this.offset[0]&&this.xcomp<this.offset[0]+d.offsetWidth)},overlap:function(d,b){if(!d){return 0}if(d=="vertical"){return((this.offset[1]+b.offsetHeight)-this.ycomp)/b.offsetHeight}if(d=="horizontal"){return((this.offset[0]+b.offsetWidth)-this.xcomp)/b.offsetWidth}},cumulativeOffset:Element.Methods.cumulativeOffset,positionedOffset:Element.Methods.positionedOffset,absolutize:function(b){Position.prepare();return Element.absolutize(b)},relativize:function(b){Position.prepare();return Element.relativize(b)},realOffset:Element.Methods.cumulativeScrollOffset,offsetParent:Element.Methods.getOffsetParent,page:Element.Methods.viewportOffset,clone:function(d,e,b){b=b||{};return Element.clonePosition(e,d,b)}};if(!document.getElementsByClassName){document.getElementsByClassName=function(d){function b(e){return e.blank()?null:"[contains(concat(' ', @class, ' '), ' "+e+" ')]"}d.getElementsByClassName=Prototype.BrowserFeatures.XPath?function(e,g){g=g.toString().strip();var f=/\s/.test(g)?$w(g).map(b).join(""):b(g);return f?document._getElementsByXPath(".//*"+f,e):[]}:function(g,h){h=h.toString().strip();var l=[],n=(/\s/.test(h)?$w(h):null);if(!n&&!h){return l}var e=$(g).getElementsByTagName("*");h=" "+h+" ";for(var f=0,p,o;p=e[f];f++){if(p.className&&(o=" "+p.className+" ")&&(o.include(h)||(n&&n.all(function(q){return !q.toString().blank()&&o.include(" "+q+" ")})))){l.push(Element.extend(p))}}return l};return function(f,e){return $(e||document.body).getElementsByClassName(f)}}(Element.Methods)}Element.ClassNames=Class.create();Element.ClassNames.prototype={initialize:function(b){this.element=$(b)},_each:function(b){this.element.className.split(/\s+/).select(function(d){return d.length>0})._each(b)},set:function(b){this.element.className=b},add:function(b){if(this.include(b)){return}this.set($A(this).concat(b).join(" "))},remove:function(b){if(!this.include(b)){return}this.set($A(this).without(b).join(" "))},toString:function(){return $A(this).join(" ")}};Object.extend(Element.ClassNames.prototype,Enumerable);(function(){window.Selector=Class.create({initialize:function(b){this.expression=b.strip()},findElements:function(b){return Prototype.Selector.select(this.expression,b)},match:function(b){return Prototype.Selector.match(b,this.expression)},toString:function(){return this.expression},inspect:function(){return"#<Selector: "+this.expression+">"}});Object.extend(Selector,{matchElements:function(h,l){var b=Prototype.Selector.match,f=[];for(var e=0,g=h.length;e<g;e++){var d=h[e];if(b(d,l)){f.push(Element.extend(d))}}return f},findElement:function(h,l,d){d=d||0;var b=0,f;for(var e=0,g=h.length;e<g;e++){f=h[e];if(Prototype.Selector.match(f,l)&&d===b++){return Element.extend(f)}}},findChildElements:function(d,e){var b=e.toArray().join(", ");return Prototype.Selector.select(b,d||document)}})})();var Window=Class.create();Window.keepMultiModalWindow=false;Window.hasEffectLib=(typeof Effect!="undefined");Window.resizeEffectDuration=0.4;Window.prototype={initialize:function(){var e;var d=0;if(arguments.length>0){if(typeof arguments[0]=="string"){e=arguments[0];d=1}else{e=arguments[0]?arguments[0].id:null}}if(!e){e="window_"+new Date().getTime()}if($(e)){alert("Window "+e+" is already registered in the DOM! Make sure you use setDestroyOnClose() or destroyOnClose: true in the constructor")}this.options=Object.extend({className:"dialog",windowClassName:null,blurClassName:null,minWidth:100,minHeight:20,resizable:true,closable:true,minimizable:true,maximizable:true,draggable:true,userData:null,showEffect:(Window.hasEffectLib?Effect.Appear:Element.show),hideEffect:(Window.hasEffectLib?Effect.Fade:Element.hide),showEffectOptions:{},hideEffectOptions:{},effectOptions:null,parent:document.body,title:" ",url:null,onload:Prototype.emptyFunction,width:200,height:300,opacity:1,recenterAuto:true,wiredDrag:false,closeOnEsc:true,closeCallback:null,destroyOnClose:false,gridX:1,gridY:1},arguments[d]||{});if(this.options.blurClassName){this.options.focusClassName=this.options.className}if(typeof this.options.top=="undefined"&&typeof this.options.bottom=="undefined"){this.options.top=this._round(Math.random()*500,this.options.gridY)}if(typeof this.options.left=="undefined"&&typeof this.options.right=="undefined"){this.options.left=this._round(Math.random()*500,this.options.gridX)}if(this.options.effectOptions){Object.extend(this.options.hideEffectOptions,this.options.effectOptions);Object.extend(this.options.showEffectOptions,this.options.effectOptions);if(this.options.showEffect==Element.Appear){this.options.showEffectOptions.to=this.options.opacity}}if(Window.hasEffectLib){if(this.options.showEffect==Effect.Appear){this.options.showEffectOptions.to=this.options.opacity}if(this.options.hideEffect==Effect.Fade){this.options.hideEffectOptions.from=this.options.opacity}}if(this.options.hideEffect==Element.hide){this.options.hideEffect=function(){Element.hide(this.element);if(this.options.destroyOnClose){this.destroy()}}.bind(this)}if(this.options.parent!=document.body){this.options.parent=$(this.options.parent)}this.element=this._createWindow(e);this.element.win=this;this.eventMouseDown=this._initDrag.bindAsEventListener(this);this.eventMouseUp=this._endDrag.bindAsEventListener(this);this.eventMouseMove=this._updateDrag.bindAsEventListener(this);this.eventOnLoad=this._getWindowBorderSize.bindAsEventListener(this);this.eventMouseDownContent=this.toFront.bindAsEventListener(this);this.eventResize=this._recenter.bindAsEventListener(this);this.eventKeyUp=this._keyUp.bindAsEventListener(this);this.topbar=$(this.element.id+"_top");this.bottombar=$(this.element.id+"_bottom");this.content=$(this.element.id+"_content");Event.observe(this.topbar,"mousedown",this.eventMouseDown);Event.observe(this.bottombar,"mousedown",this.eventMouseDown);Event.observe(this.content,"mousedown",this.eventMouseDownContent);Event.observe(window,"load",this.eventOnLoad);Event.observe(window,"resize",this.eventResize);Event.observe(window,"scroll",this.eventResize);Event.observe(document,"keyup",this.eventKeyUp);Event.observe(this.options.parent,"scroll",this.eventResize);if(this.options.draggable){var b=this;[this.topbar,this.topbar.up().previous(),this.topbar.up().next()].each(function(f){f.observe("mousedown",b.eventMouseDown);f.addClassName("top_draggable")});[this.bottombar.up(),this.bottombar.up().previous(),this.bottombar.up().next()].each(function(f){f.observe("mousedown",b.eventMouseDown);f.addClassName("bottom_draggable")})}if(this.options.resizable){this.sizer=$(this.element.id+"_sizer");Event.observe(this.sizer,"mousedown",this.eventMouseDown)}this.useLeft=null;this.useTop=null;if(typeof this.options.left!="undefined"){this.element.setStyle({left:parseFloat(this.options.left)+"px"});this.useLeft=true}else{this.element.setStyle({right:parseFloat(this.options.right)+"px"});this.useLeft=false}if(typeof this.options.top!="undefined"){this.element.setStyle({top:parseFloat(this.options.top)+"px"});this.useTop=true}else{this.element.setStyle({bottom:parseFloat(this.options.bottom)+"px"});this.useTop=false}this.storedLocation=null;this.setOpacity(this.options.opacity);if(this.options.zIndex){this.setZIndex(this.options.zIndex)}else{this.setZIndex(this.getMaxZIndex())}if(this.options.destroyOnClose){this.setDestroyOnClose(true)}this._getWindowBorderSize();this.width=this.options.width;this.height=this.options.height;this.visible=false;this.constraint=false;this.constraintPad={top:0,left:0,bottom:0,right:0};if(this.width&&this.height){this.setSize(this.options.width,this.options.height)}this.setTitle(this.options.title);Windows.register(this)},getMaxZIndex:function(){var b=0,d;var g=document.body.childNodes;for(d=0;d<g.length;d++){var e=g[d];var f=e.nodeType==1?parseInt(e.style.zIndex,10)||0:0;if(f<10000){b=Math.max(b,f)}}return b+10},destroy:function(){this._notify("onDestroy");Event.stopObserving(this.topbar,"mousedown",this.eventMouseDown);Event.stopObserving(this.bottombar,"mousedown",this.eventMouseDown);Event.stopObserving(this.content,"mousedown",this.eventMouseDownContent);Event.stopObserving(window,"load",this.eventOnLoad);Event.stopObserving(window,"resize",this.eventResize);Event.stopObserving(window,"scroll",this.eventResize);Event.stopObserving(this.content,"load",this.options.onload);Event.stopObserving(document,"keyup",this.eventKeyUp);if(this._oldParent){var e=this.getContent();var b=null;for(var d=0;d<e.childNodes.length;d++){b=e.childNodes[d];if(b.nodeType==1){break}b=null}if(b){this._oldParent.appendChild(b)}this._oldParent=null}if(this.sizer){Event.stopObserving(this.sizer,"mousedown",this.eventMouseDown)}if(this.options.url){this.content.src=null}if(this.iefix){Element.remove(this.iefix)}Element.remove(this.element);Windows.unregister(this)},setCloseCallback:function(b){this.options.closeCallback=b},getContent:function(){return this.content},setContent:function(n,l,e){var b=$(n);if(null==b){throw"Unable to find element '"+n+"' in DOM"}this._oldParent=b.parentNode;var h=null;var g=null;if(l){h=Element.getDimensions(b)}if(e){g=Position.cumulativeOffset(b)}var f=this.getContent();this.setHTMLContent("");f=this.getContent();f.appendChild(b);b.show();if(l){this.setSize(h.width,h.height)}if(e){this.setLocation(g[1]-this.heightN,g[0]-this.widthW)}},setHTMLContent:function(b){if(this.options.url){this.content.src=null;this.options.url=null;var d='<div id="'+this.getId()+'_content" class="'+this.options.className+'_content"> </div>';$(this.getId()+"_table_content").innerHTML=d;this.content=$(this.element.id+"_content")}this.getContent().innerHTML=b},setAjaxContent:function(d,b,f,e){this.showFunction=f?"showCenter":"show";this.showModal=e||false;b=b||{};this.setHTMLContent("");this.onComplete=b.onComplete;if(!this._onCompleteHandler){this._onCompleteHandler=this._setAjaxContent.bind(this)}b.onComplete=this._onCompleteHandler;new Ajax.Request(d,b);b.onComplete=this.onComplete},_setAjaxContent:function(b){Element.update(this.getContent(),b.responseText);if(this.onComplete){this.onComplete(b)}this.onComplete=null;this[this.showFunction](this.showModal)},setURL:function(b){if(this.options.url){this.content.src=null}this.options.url=b;var d="<iframe frameborder='0' name='"+this.getId()+"_content' id='"+this.getId()+"_content' src='"+b+"' width='"+this.width+"' height='"+this.height+"'> </iframe>";$(this.getId()+"_table_content").innerHTML=d;this.content=$(this.element.id+"_content")},getURL:function(){return this.options.url?this.options.url:null},refresh:function(){if(this.options.url){$(this.element.getAttribute("id")+"_content").src=this.options.url}},setCookie:function(d,e,t,g,b){d=d||this.element.id;this.cookie=[d,e,t,g,b];var r=WindowUtilities.getCookie(d);if(r){var s=r.split(",");var p=s[0].split(":");var o=s[1].split(":");var q=parseFloat(s[2]),l=parseFloat(s[3]);var n=s[4];var f=s[5];this.setSize(q,l);if(n=="true"){this.doMinimize=true}else{if(f=="true"){this.doMaximize=true}}this.useLeft=p[0]=="l";this.useTop=o[0]=="t";this.element.setStyle(this.useLeft?{left:p[1]}:{right:p[1]});this.element.setStyle(this.useTop?{top:o[1]}:{bottom:o[1]})}},getId:function(){return this.element.id},setDestroyOnClose:function(){this.options.destroyOnClose=true},setConstraint:function(b,d){this.constraint=b;this.constraintPad=Object.extend(this.constraintPad,d||{});if(this.useTop&&this.useLeft){this.setLocation(parseFloat(this.element.style.top),parseFloat(this.element.style.left))}},_initDrag:function(d){if(Event.element(d)==this.sizer&&this.isMinimized()){return}if(Event.element(d)!=this.sizer&&this.isMaximized()){return}if(Prototype.Browser.IE&&this.heightN==0){this._getWindowBorderSize()}this.pointer=[this._round(Event.pointerX(d),this.options.gridX),this._round(Event.pointerY(d),this.options.gridY)];if(this.options.wiredDrag){this.currentDrag=this._createWiredElement()}else{this.currentDrag=this.element}if(Event.element(d)==this.sizer){this.doResize=true;this.widthOrg=this.width;this.heightOrg=this.height;this.bottomOrg=parseFloat(this.element.getStyle("bottom"));this.rightOrg=parseFloat(this.element.getStyle("right"));this._notify("onStartResize")}else{this.doResize=false;var b=$(this.getId()+"_close");if(b&&Position.within(b,this.pointer[0],this.pointer[1])){this.currentDrag=null;return}this.toFront();if(!this.options.draggable){return}this._notify("onStartMove")}Event.observe(document,"mouseup",this.eventMouseUp,false);Event.observe(document,"mousemove",this.eventMouseMove,false);WindowUtilities.disableScreen("__invisible__","__invisible__",this.overlayOpacity);document.body.ondrag=function(){return false};document.body.onselectstart=function(){return false};this.currentDrag.show();Event.stop(d)},_round:function(d,b){return b==1?d:d=Math.floor(d/b)*b},_updateDrag:function(d){var b=[this._round(Event.pointerX(d),this.options.gridX),this._round(Event.pointerY(d),this.options.gridY)];var q=b[0]-this.pointer[0];var p=b[1]-this.pointer[1];if(this.doResize){var o=this.widthOrg+q;var f=this.heightOrg+p;q=this.width-this.widthOrg;p=this.height-this.heightOrg;if(this.useLeft){o=this._updateWidthConstraint(o)}else{this.currentDrag.setStyle({right:(this.rightOrg-q)+"px"})}if(this.useTop){f=this._updateHeightConstraint(f)}else{this.currentDrag.setStyle({bottom:(this.bottomOrg-p)+"px"})}this.setSize(o,f);this._notify("onResize")}else{this.pointer=b;if(this.useLeft){var e=parseFloat(this.currentDrag.getStyle("left"))+q;var n=this._updateLeftConstraint(e);this.pointer[0]+=n-e;this.currentDrag.setStyle({left:n+"px"})}else{this.currentDrag.setStyle({right:parseFloat(this.currentDrag.getStyle("right"))-q+"px"})}if(this.useTop){var l=parseFloat(this.currentDrag.getStyle("top"))+p;var g=this._updateTopConstraint(l);this.pointer[1]+=g-l;this.currentDrag.setStyle({top:g+"px"})}else{this.currentDrag.setStyle({bottom:parseFloat(this.currentDrag.getStyle("bottom"))-p+"px"})}this._notify("onMove")}if(this.iefix){this._fixIEOverlapping()}this._removeStoreLocation();Event.stop(d)},_endDrag:function(b){WindowUtilities.enableScreen("__invisible__");if(this.doResize){this._notify("onEndResize")}else{this._notify("onEndMove")}Event.stopObserving(document,"mouseup",this.eventMouseUp,false);Event.stopObserving(document,"mousemove",this.eventMouseMove,false);Event.stop(b);this._hideWiredElement();this._saveCookie();document.body.ondrag=null;document.body.onselectstart=null},_updateLeftConstraint:function(d){if(this.constraint&&this.useLeft&&this.useTop){var b=this.options.parent==document.body?WindowUtilities.getPageSize().windowWidth:this.options.parent.getDimensions().width;if(d<this.constraintPad.left){d=this.constraintPad.left}if(d+this.width+this.widthE+this.widthW>b-this.constraintPad.right){d=b-this.constraintPad.right-this.width-this.widthE-this.widthW}}return d},_updateTopConstraint:function(e){if(this.constraint&&this.useLeft&&this.useTop){var b=this.options.parent==document.body?WindowUtilities.getPageSize().windowHeight:this.options.parent.getDimensions().height;var d=this.height+this.heightN+this.heightS;if(e<this.constraintPad.top){e=this.constraintPad.top}if(e+d>b-this.constraintPad.bottom){e=b-this.constraintPad.bottom-d}}return e},_updateWidthConstraint:function(b){if(this.constraint&&this.useLeft&&this.useTop){var d=this.options.parent==document.body?WindowUtilities.getPageSize().windowWidth:this.options.parent.getDimensions().width;var e=parseFloat(this.element.getStyle("left"));if(e+b+this.widthE+this.widthW>d-this.constraintPad.right){b=d-this.constraintPad.right-e-this.widthE-this.widthW}}return b},_updateHeightConstraint:function(d){if(this.constraint&&this.useLeft&&this.useTop){var b=this.options.parent==document.body?WindowUtilities.getPageSize().windowHeight:this.options.parent.getDimensions().height;var e=parseFloat(this.element.getStyle("top"));if(e+d+this.heightN+this.heightS>b-this.constraintPad.bottom){d=b-this.constraintPad.bottom-e-this.heightN-this.heightS}}return d},_createWindow:function(b){var h=this.options.className;var f=document.createElement("div");f.setAttribute("id",b);f.className="dialog";if(this.options.windowClassName){f.className+=" "+this.options.windowClassName}var g;if(this.options.url){g='<iframe frameborder="0" name="'+b+'_content" id="'+b+'_content" src="'+this.options.url+'"> </iframe>'}else{g='<div id="'+b+'_content" class="'+h+'_content"> </div>'}var l=this.options.closable?"<div class='"+h+"_close' id='"+b+"_close' onclick='Windows.close(\""+b+"\", event)'> </div>":"";var n=this.options.minimizable?"<div class='"+h+"_minimize' id='"+b+"_minimize' onclick='Windows.minimize(\""+b+"\", event)'> </div>":"";var o=this.options.maximizable?"<div class='"+h+"_maximize' id='"+b+"_maximize' onclick='Windows.maximize(\""+b+"\", event)'> </div>":"";var e=this.options.resizable?"class='"+h+"_sizer' id='"+b+"_sizer'":"class='"+h+"_se'";var d="../themes/default/blank.gif";f.innerHTML=l+n+o+" <a href='#' id='"+b+"_focus_anchor'><!-- --></a> <table id='"+b+"_row1' class=\"top table_window\"> <tr> <td class='"+h+"_nw'></td> <td class='"+h+"_n'><div id='"+b+"_top' class='"+h+"_title title_window'>"+this.options.title+"</div></td> <td class='"+h+"_ne'></td> </tr> </table> <table id='"+b+"_row2' class=\"mid table_window\"> <tr> <td class='"+h+"_w'></td> <td id='"+b+"_table_content' class='"+h+"_content' valign='top'>"+g+"</td> <td class='"+h+"_e'></td> </tr> </table> <table id='"+b+"_row3' class=\"bot table_window\"> <tr> <td class='"+h+"_sw'></td> <td class='"+h+"_s'><div id='"+b+"_bottom' class='status_bar'><span style='float:left; width:1px; height:1px'></span></div></td> <td "+e+"></td> </tr> </table> ";Element.hide(f);this.options.parent.insertBefore(f,this.options.parent.firstChild);Event.observe($(b+"_content"),"load",this.options.onload);return f},changeClassName:function(b){var d=this.options.className;var e=this.getId();$A(["_close","_minimize","_maximize","_sizer","_content"]).each(function(f){this._toggleClassName($(e+f),d+f,b+f)}.bind(this));this._toggleClassName($(e+"_top"),d+"_title",b+"_title");$$("#"+e+" td").each(function(f){f.className=f.className.sub(d,b)});this.options.className=b},_toggleClassName:function(e,d,b){if(e){e.removeClassName(d);e.addClassName(b)}},setLocation:function(f,d){f=this._updateTopConstraint(f);d=this._updateLeftConstraint(d);var b=this.currentDrag||this.element;b.setStyle({top:f+"px"});b.setStyle({left:d+"px"});this.useLeft=true;this.useTop=true},getLocation:function(){var b={};if(this.useTop){b=Object.extend(b,{top:this.element.getStyle("top")})}else{b=Object.extend(b,{bottom:this.element.getStyle("bottom")})}if(this.useLeft){b=Object.extend(b,{left:this.element.getStyle("left")})}else{b=Object.extend(b,{right:this.element.getStyle("right")})}return b},getSize:function(){return{width:this.width,height:this.height}},setSize:function(f,d,b){f=parseFloat(f);d=parseFloat(d);if(!this.minimized&&f<this.options.minWidth){f=this.options.minWidth}if(!this.minimized&&d<this.options.minHeight){d=this.options.minHeight}if(this.options.maxHeight&&d>this.options.maxHeight){d=this.options.maxHeight}if(this.options.maxWidth&&f>this.options.maxWidth){f=this.options.maxWidth}if(this.useTop&&this.useLeft&&Window.hasEffectLib&&Effect.ResizeWindow&&b){new Effect.ResizeWindow(this,null,null,f,d,{duration:Window.resizeEffectDuration})}else{this.width=f;this.height=d;var h=this.currentDrag?this.currentDrag:this.element;h.setStyle({width:f+this.widthW+this.widthE+"px"});h.setStyle({height:d+this.heightN+this.heightS+"px"});if(!this.currentDrag||this.currentDrag==this.element){var g=$(this.element.id+"_content");g.setStyle({height:d+"px"});g.setStyle({width:f+"px"})}}},updateHeight:function(){this.setSize(this.width,this.content.scrollHeight,true)},updateWidth:function(){this.setSize(this.content.scrollWidth,this.height,true)},toFront:function(){if(this.element.style.zIndex<Windows.maxZIndex){this.setZIndex(Windows.maxZIndex+1)}if(this.iefix){this._fixIEOverlapping()}},getBounds:function(d){if(!this.width||!this.height||!this.visible){this.computeBounds()}var b=this.width;var e=this.height;if(!d){b+=this.widthW+this.widthE;e+=this.heightN+this.heightS}var f=Object.extend(this.getLocation(),{width:b+"px",height:e+"px"});return f},computeBounds:function(){if(!this.width||!this.height){var b=WindowUtilities._computeSize(this.content.innerHTML,this.content.id,this.width,this.height,0,this.options.className);if(this.height){this.width=b+5}else{this.height=b+5}}this.setSize(this.width,this.height);if(this.centered){this._center(this.centerTop,this.centerLeft)}},show:function(d){this.visible=true;if(d){if(typeof this.overlayOpacity=="undefined"){var b=this;setTimeout(function(){b.show(d)},10);return}Windows.addModalWindow(this);this.modal=true;this.setZIndex(Windows.maxZIndex+1);Windows.unsetOverflow(this)}else{if(!this.element.style.zIndex){this.setZIndex(Windows.maxZIndex+1)}}if(this.oldStyle){this.getContent().setStyle({overflow:this.oldStyle})}this.computeBounds();this._notify("onBeforeShow");if(this.options.showEffect!=Element.show&&this.options.showEffectOptions){this.options.showEffect(this.element,this.options.showEffectOptions)}else{this.options.showEffect(this.element)}this._checkIEOverlapping();WindowUtilities.focusedWindow=this;this._notify("onShow");$(this.element.id+"_focus_anchor").focus()},showCenter:function(b,e,d){this.centered=true;this.centerTop=e;this.centerLeft=d;this.show(b)},isVisible:function(){return this.visible},_center:function(e,d){var f=WindowUtilities.getWindowScroll(this.options.parent);var b=WindowUtilities.getPageSize(this.options.parent);if(typeof e=="undefined"){e=(b.windowHeight-(this.height+this.heightN+this.heightS))/2}e+=f.top;if(typeof d=="undefined"){d=(b.windowWidth-(this.width+this.widthW+this.widthE))/2}d+=f.left;this.setLocation(e,d);this.toFront()},_recenter:function(d){if(this.centered){var b=WindowUtilities.getPageSize(this.options.parent);var e=WindowUtilities.getWindowScroll(this.options.parent);if(this.pageSize&&this.pageSize.windowWidth==b.windowWidth&&this.pageSize.windowHeight==b.windowHeight&&this.windowScroll.left==e.left&&this.windowScroll.top==e.top){return}this.pageSize=b;this.windowScroll=e;if($("overlay_modal")){$("overlay_modal").setStyle({height:(b.pageHeight+"px")})}if(this.options.recenterAuto){this._center(this.centerTop,this.centerLeft)}}},hide:function(){this.visible=false;if(this.modal){Windows.removeModalWindow(this);Windows.resetOverflow()}this.oldStyle=this.getContent().getStyle("overflow")||"auto";this.getContent().setStyle({overflow:"hidden"});this.options.hideEffect(this.element,this.options.hideEffectOptions);if(this.iefix){this.iefix.hide()}if(!this.doNotNotifyHide){this._notify("onHide")}},close:function(){if(this.visible){if(this.options.closeCallback&&!this.options.closeCallback(this)){return}if(this.options.destroyOnClose){var b=this.destroy.bind(this);if(this.options.hideEffectOptions.afterFinish){var d=this.options.hideEffectOptions.afterFinish;this.options.hideEffectOptions.afterFinish=function(){d();b()}}else{this.options.hideEffectOptions.afterFinish=function(){b()}}}Windows.updateFocusedWindow();this.doNotNotifyHide=true;this.hide();this.doNotNotifyHide=false;this._notify("onClose")}},minimize:function(){if(this.resizing){return}var b=$(this.getId()+"_row2");if(!this.minimized){this.minimized=true;var f=b.getDimensions().height;this.r2Height=f;var e=this.element.getHeight()-f;if(this.useLeft&&this.useTop&&Window.hasEffectLib&&Effect.ResizeWindow){new Effect.ResizeWindow(this,null,null,null,this.height-f,{duration:Window.resizeEffectDuration})}else{this.height-=f;this.element.setStyle({height:e+"px"});b.hide()}if(!this.useTop){var d=parseFloat(this.element.getStyle("bottom"));this.element.setStyle({bottom:(d+f)+"px"})}}else{this.minimized=false;var f=this.r2Height;this.r2Height=null;if(this.useLeft&&this.useTop&&Window.hasEffectLib&&Effect.ResizeWindow){new Effect.ResizeWindow(this,null,null,null,this.height+f,{duration:Window.resizeEffectDuration})}else{var e=this.element.getHeight()+f;this.height+=f;this.element.setStyle({height:e+"px"});b.show()}if(!this.useTop){var d=parseFloat(this.element.getStyle("bottom"));this.element.setStyle({bottom:(d-f)+"px"})}this.toFront()}this._notify("onMinimize");this._saveCookie()},maximize:function(){if(this.isMinimized()||this.resizing){return}if(Prototype.Browser.IE&&this.heightN==0){this._getWindowBorderSize()}if(this.storedLocation!=null){this._restoreLocation();if(this.iefix){this.iefix.hide()}}else{this._storeLocation();Windows.unsetOverflow(this);var l=WindowUtilities.getWindowScroll(this.options.parent);var d=WindowUtilities.getPageSize(this.options.parent);var h=l.left;var g=l.top;if(this.options.parent!=document.body){l={top:0,left:0,bottom:0,right:0};var f=this.options.parent.getDimensions();d.windowWidth=f.width;d.windowHeight=f.height;g=0;h=0}if(this.constraint){d.windowWidth-=Math.max(0,this.constraintPad.left)+Math.max(0,this.constraintPad.right);d.windowHeight-=Math.max(0,this.constraintPad.top)+Math.max(0,this.constraintPad.bottom);h+=Math.max(0,this.constraintPad.left);g+=Math.max(0,this.constraintPad.top)}var e=d.windowWidth-this.widthW-this.widthE;var b=d.windowHeight-this.heightN-this.heightS;if(this.useLeft&&this.useTop&&Window.hasEffectLib&&Effect.ResizeWindow){new Effect.ResizeWindow(this,g,h,e,b,{duration:Window.resizeEffectDuration})}else{this.setSize(e,b);this.element.setStyle(this.useLeft?{left:h}:{right:h});this.element.setStyle(this.useTop?{top:g}:{bottom:g})}this.toFront();if(this.iefix){this._fixIEOverlapping()}}this._notify("onMaximize");this._saveCookie()},isMinimized:function(){return this.minimized},isMaximized:function(){return(this.storedLocation!=null)},setOpacity:function(b){if(Element.setOpacity){Element.setOpacity(this.element,b)}},setZIndex:function(b){this.element.setStyle({zIndex:b});Windows.updateZindex(b,this)},setTitle:function(b){if(!b||b==""){b=" "}Element.update(this.element.id+"_top",b)},getTitle:function(){return $(this.element.id+"_top").innerHTML},setStatusBar:function(d){var b=$(this.getId()+"_bottom");if(typeof(d)=="object"){if(this.bottombar.firstChild){this.bottombar.replaceChild(d,this.bottombar.firstChild)}else{this.bottombar.appendChild(d)}}else{this.bottombar.innerHTML=d}},_checkIEOverlapping:function(){if(!this.iefix&&(navigator.appVersion.indexOf("MSIE")>0)&&(navigator.userAgent.indexOf("Opera")<0)&&(this.element.getStyle("position")=="absolute")){new Insertion.After(this.element.id,'<iframe id="'+this.element.id+'_iefix" style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" src="javascript:false;" frameborder="0" scrolling="no"></iframe>');this.iefix=$(this.element.id+"_iefix")}if(this.iefix){setTimeout(this._fixIEOverlapping.bind(this),50)}},_fixIEOverlapping:function(){Position.clone(this.element,this.iefix);this.iefix.style.zIndex=this.element.style.zIndex-1;this.iefix.show()},_keyUp:function(b){if(27==b.keyCode&&this.options.closeOnEsc){this.close()}},_getWindowBorderSize:function(d){var e=this._createHiddenDiv(this.options.className+"_n");this.heightN=Element.getDimensions(e).height;e.parentNode.removeChild(e);var e=this._createHiddenDiv(this.options.className+"_s");this.heightS=Element.getDimensions(e).height;e.parentNode.removeChild(e);var e=this._createHiddenDiv(this.options.className+"_e");this.widthE=Element.getDimensions(e).width;e.parentNode.removeChild(e);var e=this._createHiddenDiv(this.options.className+"_w");this.widthW=Element.getDimensions(e).width;e.parentNode.removeChild(e);var e=document.createElement("div");e.className="overlay_"+this.options.className;document.body.appendChild(e);var b=this;setTimeout(function(){b.overlayOpacity=($(e).getStyle("opacity"));e.parentNode.removeChild(e)},10);if(Prototype.Browser.IE){this.heightS=$(this.getId()+"_row3").getDimensions().height;this.heightN=$(this.getId()+"_row1").getDimensions().height}if(Prototype.Browser.WebKit&&Prototype.Browser.WebKitVersion<420){this.setSize(this.width,this.height)}if(this.doMaximize){this.maximize()}if(this.doMinimize){this.minimize()}},_createHiddenDiv:function(d){var b=document.body;var e=document.createElement("div");e.setAttribute("id",this.element.id+"_tmp");e.className=d;e.style.display="none";e.innerHTML="";b.insertBefore(e,b.firstChild);return e},_storeLocation:function(){if(this.storedLocation==null){this.storedLocation={useTop:this.useTop,useLeft:this.useLeft,top:this.element.getStyle("top"),bottom:this.element.getStyle("bottom"),left:this.element.getStyle("left"),right:this.element.getStyle("right"),width:this.width,height:this.height}}},_restoreLocation:function(){if(this.storedLocation!=null){this.useLeft=this.storedLocation.useLeft;this.useTop=this.storedLocation.useTop;if(this.useLeft&&this.useTop&&Window.hasEffectLib&&Effect.ResizeWindow){new Effect.ResizeWindow(this,this.storedLocation.top,this.storedLocation.left,this.storedLocation.width,this.storedLocation.height,{duration:Window.resizeEffectDuration})}else{this.element.setStyle(this.useLeft?{left:this.storedLocation.left}:{right:this.storedLocation.right});this.element.setStyle(this.useTop?{top:this.storedLocation.top}:{bottom:this.storedLocation.bottom});this.setSize(this.storedLocation.width,this.storedLocation.height)}Windows.resetOverflow();this._removeStoreLocation()}},_removeStoreLocation:function(){this.storedLocation=null},_saveCookie:function(){if(this.cookie){var b="";if(this.useLeft){b+="l:"+(this.storedLocation?this.storedLocation.left:this.element.getStyle("left"))}else{b+="r:"+(this.storedLocation?this.storedLocation.right:this.element.getStyle("right"))}if(this.useTop){b+=",t:"+(this.storedLocation?this.storedLocation.top:this.element.getStyle("top"))}else{b+=",b:"+(this.storedLocation?this.storedLocation.bottom:this.element.getStyle("bottom"))}b+=","+(this.storedLocation?this.storedLocation.width:this.width);b+=","+(this.storedLocation?this.storedLocation.height:this.height);b+=","+this.isMinimized();b+=","+this.isMaximized();WindowUtilities.setCookie(b,this.cookie)}},_createWiredElement:function(){if(!this.wiredElement){if(Prototype.Browser.IE){this._getWindowBorderSize()}var d=document.createElement("div");d.className="wired_frame "+this.options.className+"_wired_frame";d.style.position="absolute";this.options.parent.insertBefore(d,this.options.parent.firstChild);this.wiredElement=$(d)}if(this.useLeft){this.wiredElement.setStyle({left:this.element.getStyle("left")})}else{this.wiredElement.setStyle({right:this.element.getStyle("right")})}if(this.useTop){this.wiredElement.setStyle({top:this.element.getStyle("top")})}else{this.wiredElement.setStyle({bottom:this.element.getStyle("bottom")})}var b=this.element.getDimensions();this.wiredElement.setStyle({width:b.width+"px",height:b.height+"px"});this.wiredElement.setStyle({zIndex:Windows.maxZIndex+30});return this.wiredElement},_hideWiredElement:function(){if(!this.wiredElement||!this.currentDrag){return}if(this.currentDrag==this.element){this.currentDrag=null}else{if(this.useLeft){this.element.setStyle({left:this.currentDrag.getStyle("left")})}else{this.element.setStyle({right:this.currentDrag.getStyle("right")})}if(this.useTop){this.element.setStyle({top:this.currentDrag.getStyle("top")})}else{this.element.setStyle({bottom:this.currentDrag.getStyle("bottom")})}this.currentDrag.hide();this.currentDrag=null;if(this.doResize){this.setSize(this.width,this.height)}}},_notify:function(b){if(this.options[b]){this.options[b](this)}else{Windows.notify(b,this)}}};var Windows={windows:[],modalWindows:[],observers:[],focusedWindow:null,maxZIndex:0,overlayShowEffectOptions:{duration:0.5},overlayHideEffectOptions:{duration:0.5},addObserver:function(b){this.removeObserver(b);this.observers.push(b)},removeObserver:function(b){this.observers=this.observers.reject(function(d){return d==b})},notify:function(b,d){this.observers.each(function(e){if(e[b]){e[b](b,d)}})},getWindow:function(b){return this.windows.detect(function(e){return e.getId()==b})},getFocusedWindow:function(){return this.focusedWindow},updateFocusedWindow:function(){this.focusedWindow=this.windows.length>=2?this.windows[this.windows.length-2]:null},register:function(b){this.windows.push(b)},addModalWindow:function(b){if(this.modalWindows.length==0){WindowUtilities.disableScreen(b.options.className,"overlay_modal",b.overlayOpacity,b.getId(),b.options.parent)}else{if(Window.keepMultiModalWindow){$("overlay_modal").style.zIndex=Windows.maxZIndex+1;Windows.maxZIndex+=1;WindowUtilities._hideSelect(this.modalWindows.last().getId())}else{this.modalWindows.last().element.hide()}WindowUtilities._showSelect(b.getId())}this.modalWindows.push(b)},removeModalWindow:function(b){this.modalWindows.pop();if(this.modalWindows.length==0){WindowUtilities.enableScreen()}else{if(Window.keepMultiModalWindow){this.modalWindows.last().toFront();WindowUtilities._showSelect(this.modalWindows.last().getId())}else{this.modalWindows.last().element.show()}}},register:function(b){this.windows.push(b)},unregister:function(b){this.windows=this.windows.reject(function(e){return e==b})},closeAll:function(){this.windows.each(function(b){Windows.close(b.getId())})},closeAllModalWindows:function(){WindowUtilities.enableScreen();this.modalWindows.each(function(b){if(b){b.close()}})},minimize:function(e,b){var d=this.getWindow(e);if(d&&d.visible){d.minimize()}Event.stop(b)},maximize:function(e,b){var d=this.getWindow(e);if(d&&d.visible){d.maximize()}Event.stop(b)},close:function(e,b){var d=this.getWindow(e);if(d){d.close()}if(b){Event.stop(b)}},blur:function(d){var b=this.getWindow(d);if(!b){return}if(b.options.blurClassName){b.changeClassName(b.options.blurClassName)}if(this.focusedWindow==b){this.focusedWindow=null}b._notify("onBlur")},focus:function(d){var b=this.getWindow(d);if(!b){return}if(this.focusedWindow){this.blur(this.focusedWindow.getId())}if(b.options.focusClassName){b.changeClassName(b.options.focusClassName)}this.focusedWindow=b;b._notify("onFocus")},unsetOverflow:function(b){this.windows.each(function(e){e.oldOverflow=e.getContent().getStyle("overflow")||"auto";e.getContent().setStyle({overflow:"hidden"})});if(b&&b.oldOverflow){b.getContent().setStyle({overflow:b.oldOverflow})}},resetOverflow:function(){this.windows.each(function(b){if(b.oldOverflow){b.getContent().setStyle({overflow:b.oldOverflow})}})},updateZindex:function(b,d){if(b>this.maxZIndex){this.maxZIndex=b;if(this.focusedWindow){this.blur(this.focusedWindow.getId())}}this.focusedWindow=d;if(this.focusedWindow){this.focus(this.focusedWindow.getId())}}};var Dialog={dialogId:null,onCompleteFunc:null,callFunc:null,parameters:null,confirm:function(f,e){if(f&&typeof f!="string"){Dialog._runAjaxRequest(f,e,Dialog.confirm);return}f=f||"";e=e||{};var h=e.okLabel?e.okLabel:"Ok";var b=e.cancelLabel?e.cancelLabel:"Cancel";e=Object.extend(e,e.windowParameters||{});e.windowParameters=e.windowParameters||{};e.className=e.className||"alert";var d="class ='"+(e.buttonClass?e.buttonClass+" ":"")+" ok_button'";var g="class ='"+(e.buttonClass?e.buttonClass+" ":"")+" cancel_button'";var f=" <div class='"+e.className+"_message'>"+f+"</div> <div class='"+e.className+"_buttons'> <button type='button' title='"+h+"' onclick='Dialog.okCallback()' "+d+"><span><span><span>"+h+"</span></span></span></button> <button type='button' title='"+b+"' onclick='Dialog.cancelCallback()' "+g+"><span><span><span>"+b+"</span></span></span></button> </div> ";return this._openDialog(f,e)},alert:function(e,d){if(e&&typeof e!="string"){Dialog._runAjaxRequest(e,d,Dialog.alert);return}e=e||"";d=d||{};var f=d.okLabel?d.okLabel:"Ok";d=Object.extend(d,d.windowParameters||{});d.windowParameters=d.windowParameters||{};d.className=d.className||"alert";var b="class ='"+(d.buttonClass?d.buttonClass+" ":"")+" ok_button'";var e=" <div class='"+d.className+"_message'>"+e+"</div> <div class='"+d.className+"_buttons'> <button type='button' title='"+f+"' onclick='Dialog.okCallback()' "+b+"><span><span><span>"+f+"</span></span></span></button> </div>";return this._openDialog(e,d)},info:function(d,b){if(d&&typeof d!="string"){Dialog._runAjaxRequest(d,b,Dialog.info);return}d=d||"";b=b||{};b=Object.extend(b,b.windowParameters||{});b.windowParameters=b.windowParameters||{};b.className=b.className||"alert";var d="<div id='modal_dialog_message' class='"+b.className+"_message'>"+d+"</div>";if(b.showProgress){d+="<div id='modal_dialog_progress' class='"+b.className+"_progress'> </div>"}b.ok=null;b.cancel=null;return this._openDialog(d,b)},setInfoMessage:function(b){$("modal_dialog_message").update(b)},closeInfo:function(){Windows.close(this.dialogId)},_openDialog:function(g,f){var e=f.className;if(!f.height&&!f.width){f.width=WindowUtilities.getPageSize(f.options.parent||document.body).pageWidth/2}if(f.id){this.dialogId=f.id}else{var d=new Date();this.dialogId="modal_dialog_"+d.getTime();f.id=this.dialogId}if(!f.height||!f.width){var b=WindowUtilities._computeSize(g,this.dialogId,f.width,f.height,5,e);if(f.height){f.width=b+5}else{f.height=b+5}}f.effectOptions=f.effectOptions;f.resizable=f.resizable||false;f.minimizable=f.minimizable||false;f.maximizable=f.maximizable||false;f.draggable=f.draggable||false;f.closable=f.closable||false;var h=new Window(f);h.getContent().innerHTML=g;h.showCenter(true,f.top,f.left);h.setDestroyOnClose();h.cancelCallback=f.onCancel||f.cancel;h.okCallback=f.onOk||f.ok;return h},_getAjaxContent:function(b){Dialog.callFunc(b.responseText,Dialog.parameters)},_runAjaxRequest:function(e,d,b){if(e.options==null){e.options={}}Dialog.onCompleteFunc=e.options.onComplete;Dialog.parameters=d;Dialog.callFunc=b;e.options.onComplete=Dialog._getAjaxContent;new Ajax.Request(e.url,e.options)},okCallback:function(){var b=Windows.focusedWindow;if(!b.okCallback||b.okCallback(b)){$$("#"+b.getId()+" input").each(function(d){d.onclick=null});b.close()}},cancelCallback:function(){var b=Windows.focusedWindow;$$("#"+b.getId()+" input").each(function(d){d.onclick=null});b.close();if(b.cancelCallback){b.cancelCallback(b)}}};if(Prototype.Browser.WebKit){var array=navigator.userAgent.match(new RegExp(/AppleWebKit\/([\d\.\+]*)/));Prototype.Browser.WebKitVersion=parseFloat(array[1])}var WindowUtilities={getWindowScroll:function(parent){var T,L,W,H;parent=parent||document.body;if(parent!=document.body){T=parent.scrollTop;L=parent.scrollLeft;W=parent.scrollWidth;H=parent.scrollHeight}else{var w=window;with(w.document){if(w.document.documentElement&&documentElement.scrollTop){T=documentElement.scrollTop;L=documentElement.scrollLeft}else{if(w.document.body){T=body.scrollTop;L=body.scrollLeft}}if(w.innerWidth){W=w.innerWidth;H=w.innerHeight}else{if(w.document.documentElement&&documentElement.clientWidth){W=documentElement.clientWidth;H=documentElement.clientHeight}else{W=body.offsetWidth;H=body.offsetHeight}}}}return{top:T,left:L,width:W,height:H}},getPageSize:function(f){f=f||document.body;var e,l;var g,d;if(f!=document.body){e=f.getWidth();l=f.getHeight();d=f.scrollWidth;g=f.scrollHeight}else{var h,b;if(window.innerHeight&&window.scrollMaxY){h=document.body.scrollWidth;b=window.innerHeight+window.scrollMaxY}else{if(document.body.scrollHeight>document.body.offsetHeight){h=document.body.scrollWidth;b=document.body.scrollHeight}else{h=document.body.offsetWidth;b=document.body.offsetHeight}}if(self.innerHeight){e=document.documentElement.clientWidth;l=self.innerHeight}else{if(document.documentElement&&document.documentElement.clientHeight){e=document.documentElement.clientWidth;l=document.documentElement.clientHeight}else{if(document.body){e=document.body.clientWidth;l=document.body.clientHeight}}}if(b<l){g=l}else{g=b}if(h<e){d=e}else{d=h}}return{pageWidth:d,pageHeight:g,windowWidth:e,windowHeight:l}},disableScreen:function(e,b,f,g,d){WindowUtilities.initLightbox(b,e,function(){this._disableScreen(e,b,f,g)}.bind(this),d||document.body)},_disableScreen:function(e,d,g,h){var f=$(d);var b=WindowUtilities.getPageSize(f.parentNode);if(h&&Prototype.Browser.IE){WindowUtilities._hideSelect();WindowUtilities._showSelect(h)}f.style.height=(b.pageHeight+"px");f.style.display="none";if(d=="overlay_modal"&&Window.hasEffectLib&&Windows.overlayShowEffectOptions){f.overlayOpacity=g;new Effect.Appear(f,Object.extend({from:0,to:g},Windows.overlayShowEffectOptions))}else{f.style.display="block"}},enableScreen:function(d){d=d||"overlay_modal";var b=$(d);if(b){if(d=="overlay_modal"&&Window.hasEffectLib&&Windows.overlayHideEffectOptions){new Effect.Fade(b,Object.extend({from:b.overlayOpacity,to:0},Windows.overlayHideEffectOptions))}else{b.style.display="none";b.parentNode.removeChild(b)}if(d!="__invisible__"){WindowUtilities._showSelect()}}},_hideSelect:function(b){if(Prototype.Browser.IE){b=b==null?"":"#"+b+" ";$$(b+"select").each(function(d){if(!WindowUtilities.isDefined(d.oldVisibility)){d.oldVisibility=d.style.visibility?d.style.visibility:"visible";d.style.visibility="hidden"}})}},_showSelect:function(b){if(Prototype.Browser.IE){b=b==null?"":"#"+b+" ";$$(b+"select").each(function(d){if(WindowUtilities.isDefined(d.oldVisibility)){try{d.style.visibility=d.oldVisibility}catch(f){d.style.visibility="visible"}d.oldVisibility=null}else{if(d.style.visibility){d.style.visibility="visible"}}})}},isDefined:function(b){return typeof(b)!="undefined"&&b!=null},initLightbox:function(g,e,b,d){if($(g)){Element.setStyle(g,{zIndex:Windows.maxZIndex+1});Windows.maxZIndex++;b()}else{var f=document.createElement("div");f.setAttribute("id",g);f.className="overlay_"+e;f.style.display="none";f.style.position="absolute";f.style.top="0";f.style.left="0";f.style.zIndex=Windows.maxZIndex+1;Windows.maxZIndex++;f.style.width="100%";d.insertBefore(f,d.firstChild);if(Prototype.Browser.WebKit&&g=="overlay_modal"){setTimeout(function(){b()},10)}else{b()}}},setCookie:function(d,b){document.cookie=b[0]+"="+escape(d)+((b[1])?"; expires="+b[1].toGMTString():"")+((b[2])?"; path="+b[2]:"")+((b[3])?"; domain="+b[3]:"")+((b[4])?"; secure":"")},getCookie:function(e){var d=document.cookie;var g=e+"=";var f=d.indexOf("; "+g);if(f==-1){f=d.indexOf(g);if(f!=0){return null}}else{f+=2}var b=document.cookie.indexOf(";",f);if(b==-1){b=d.length}return unescape(d.substring(f+g.length,b))},_computeSize:function(g,b,d,l,f,h){var o=document.body;var e=document.createElement("div");e.setAttribute("id",b);e.className=h+"_content";if(l){e.style.height=l+"px"}else{e.style.width=d+"px"}e.style.position="absolute";e.style.top="0";e.style.left="0";e.style.display="none";e.innerHTML=g;o.insertBefore(e,o.firstChild);var n;if(l){n=$(e).getDimensions().width+f}else{n=$(e).getDimensions().height+f}o.removeChild(e);return n}};var Builder={NODEMAP:{AREA:"map",CAPTION:"table",COL:"table",COLGROUP:"table",LEGEND:"fieldset",OPTGROUP:"select",OPTION:"select",PARAM:"object",TBODY:"table",TD:"table",TFOOT:"table",TH:"table",THEAD:"table",TR:"table"},node:function(b){b=b.toUpperCase();var l=this.NODEMAP[b]||"div";var d=document.createElement(l);try{d.innerHTML="<"+b+"></"+b+">"}catch(h){}var g=d.firstChild||null;if(g&&(g.tagName.toUpperCase()!=b)){g=g.getElementsByTagName(b)[0]}if(!g){g=document.createElement(b)}if(!g){return}if(arguments[1]){if(this._isStringOrNumber(arguments[1])||(arguments[1] instanceof Array)||arguments[1].tagName){this._children(g,arguments[1])}else{var f=this._attributes(arguments[1]);if(f.length){try{d.innerHTML="<"+b+" "+f+"></"+b+">"}catch(h){}g=d.firstChild||null;if(!g){g=document.createElement(b);for(attr in arguments[1]){g[attr=="class"?"className":attr]=arguments[1][attr]}}if(g.tagName.toUpperCase()!=b){g=d.getElementsByTagName(b)[0]}}}}if(arguments[2]){this._children(g,arguments[2])}return $(g)},_text:function(b){return document.createTextNode(b)},ATTR_MAP:{className:"class",htmlFor:"for"},_attributes:function(b){var d=[];for(attribute in b){d.push((attribute in this.ATTR_MAP?this.ATTR_MAP[attribute]:attribute)+'="'+b[attribute].toString().escapeHTML().gsub(/"/,""")+'"')}return d.join(" ")},_children:function(d,b){if(b.tagName){d.appendChild(b);return}if(typeof b=="object"){b.flatten().each(function(f){if(typeof f=="object"){d.appendChild(f)}else{if(Builder._isStringOrNumber(f)){d.appendChild(Builder._text(f))}}})}else{if(Builder._isStringOrNumber(b)){d.appendChild(Builder._text(b))}}},_isStringOrNumber:function(b){return(typeof b=="string"||typeof b=="number")},build:function(d){var b=this.node("div");$(b).update(d.strip());return b.down()},dump:function(d){if(typeof d!="object"&&typeof d!="function"){d=window}var b=("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);b.each(function(e){d[e]=function(){return Builder.node.apply(Builder,[e].concat($A(arguments)))}})}};String.prototype.parseColor=function(){var b="#";if(this.slice(0,4)=="rgb("){var e=this.slice(4,this.length-1).split(",");var d=0;do{b+=parseInt(e[d]).toColorPart()}while(++d<3)}else{if(this.slice(0,1)=="#"){if(this.length==4){for(var d=1;d<4;d++){b+=(this.charAt(d)+this.charAt(d)).toLowerCase()}}if(this.length==7){b=this.toLowerCase()}}}return(b.length==7?b:(arguments[0]||this))};Element.collectTextNodes=function(b){return $A($(b).childNodes).collect(function(d){return(d.nodeType==3?d.nodeValue:(d.hasChildNodes()?Element.collectTextNodes(d):""))}).flatten().join("")};Element.collectTextNodesIgnoreClass=function(b,d){return $A($(b).childNodes).collect(function(e){return(e.nodeType==3?e.nodeValue:((e.hasChildNodes()&&!Element.hasClassName(e,d))?Element.collectTextNodesIgnoreClass(e,d):""))}).flatten().join("")};Element.setContentZoom=function(b,d){b=$(b);b.setStyle({fontSize:(d/100)+"em"});if(Prototype.Browser.WebKit){window.scrollBy(0,0)}return b};Element.getInlineOpacity=function(b){return $(b).style.opacity||""};Element.forceRerendering=function(b){try{b=$(b);var f=document.createTextNode(" ");b.appendChild(f);b.removeChild(f)}catch(d){}};var Effect={_elementDoesNotExistError:{name:"ElementDoesNotExistError",message:"The specified DOM element does not exist, but is required for this effect to operate"},Transitions:{linear:Prototype.K,sinoidal:function(b){return(-Math.cos(b*Math.PI)/2)+0.5},reverse:function(b){return 1-b},flicker:function(b){var b=((-Math.cos(b*Math.PI)/4)+0.75)+Math.random()/4;return b>1?1:b},wobble:function(b){return(-Math.cos(b*Math.PI*(9*b))/2)+0.5},pulse:function(d,b){return(-Math.cos((d*((b||5)-0.5)*2)*Math.PI)/2)+0.5},spring:function(b){return 1-(Math.cos(b*4.5*Math.PI)*Math.exp(-b*6))},none:function(b){return 0},full:function(b){return 1}},DefaultOptions:{duration:1,fps:100,sync:false,from:0,to:1,delay:0,queue:"parallel"},tagifyText:function(b){var d="position:relative";if(Prototype.Browser.IE){d+=";zoom:1"}b=$(b);$A(b.childNodes).each(function(e){if(e.nodeType==3){e.nodeValue.toArray().each(function(f){b.insertBefore(new Element("span",{style:d}).update(f==" "?String.fromCharCode(160):f),e)});Element.remove(e)}})},multiple:function(d,e){var g;if(((typeof d=="object")||Object.isFunction(d))&&(d.length)){g=d}else{g=$(d).childNodes}var b=Object.extend({speed:0.1,delay:0},arguments[2]||{});var f=b.delay;$A(g).each(function(l,h){new e(l,Object.extend(b,{delay:h*b.speed+f}))})},PAIRS:{slide:["SlideDown","SlideUp"],blind:["BlindDown","BlindUp"],appear:["Appear","Fade"]},toggle:function(d,e){d=$(d);e=(e||"appear").toLowerCase();var b=Object.extend({queue:{position:"end",scope:(d.id||"global"),limit:1}},arguments[2]||{});Effect[d.visible()?Effect.PAIRS[e][1]:Effect.PAIRS[e][0]](d,b)}};Effect.DefaultOptions.transition=Effect.Transitions.sinoidal;Effect.ScopedQueue=Class.create(Enumerable,{initialize:function(){this.effects=[];this.interval=null},_each:function(b){this.effects._each(b)},add:function(d){var e=new Date().getTime();var b=Object.isString(d.options.queue)?d.options.queue:d.options.queue.position;switch(b){case"front":this.effects.findAll(function(f){return f.state=="idle"}).each(function(f){f.startOn+=d.finishOn;f.finishOn+=d.finishOn});break;case"with-last":e=this.effects.pluck("startOn").max()||e;break;case"end":e=this.effects.pluck("finishOn").max()||e;break}d.startOn+=e;d.finishOn+=e;if(!d.options.queue.limit||(this.effects.length<d.options.queue.limit)){this.effects.push(d)}if(!this.interval){this.interval=setInterval(this.loop.bind(this),15)}},remove:function(b){this.effects=this.effects.reject(function(d){return d==b});if(this.effects.length==0){clearInterval(this.interval);this.interval=null}},loop:function(){var e=new Date().getTime();for(var d=0,b=this.effects.length;d<b;d++){this.effects[d]&&this.effects[d].loop(e)}}});Effect.Queues={instances:$H(),get:function(b){if(!Object.isString(b)){return b}return this.instances.get(b)||this.instances.set(b,new Effect.ScopedQueue())}};Effect.Queue=Effect.Queues.get("global");Effect.Base=Class.create({position:null,start:function(b){function d(f,e){return((f[e+"Internal"]?"this.options."+e+"Internal(this);":"")+(f[e]?"this.options."+e+"(this);":""))}if(b&&b.transition===false){b.transition=Effect.Transitions.linear}this.options=Object.extend(Object.extend({},Effect.DefaultOptions),b||{});this.currentFrame=0;this.state="idle";this.startOn=this.options.delay*1000;this.finishOn=this.startOn+(this.options.duration*1000);this.fromToDelta=this.options.to-this.options.from;this.totalTime=this.finishOn-this.startOn;this.totalFrames=this.options.fps*this.options.duration;this.render=(function(){function e(g,f){if(g.options[f+"Internal"]){g.options[f+"Internal"](g)}if(g.options[f]){g.options[f](g)}}return function(f){if(this.state==="idle"){this.state="running";e(this,"beforeSetup");if(this.setup){this.setup()}e(this,"afterSetup")}if(this.state==="running"){f=(this.options.transition(f)*this.fromToDelta)+this.options.from;this.position=f;e(this,"beforeUpdate");if(this.update){this.update(f)}e(this,"afterUpdate")}}})();this.event("beforeStart");if(!this.options.sync){Effect.Queues.get(Object.isString(this.options.queue)?"global":this.options.queue.scope).add(this)}},loop:function(e){if(e>=this.startOn){if(e>=this.finishOn){this.render(1);this.cancel();this.event("beforeFinish");if(this.finish){this.finish()}this.event("afterFinish");return}var d=(e-this.startOn)/this.totalTime,b=(d*this.totalFrames).round();if(b>this.currentFrame){this.render(d);this.currentFrame=b}}},cancel:function(){if(!this.options.sync){Effect.Queues.get(Object.isString(this.options.queue)?"global":this.options.queue.scope).remove(this)}this.state="finished"},event:function(b){if(this.options[b+"Internal"]){this.options[b+"Internal"](this)}if(this.options[b]){this.options[b](this)}},inspect:function(){var b=$H();for(property in this){if(!Object.isFunction(this[property])){b.set(property,this[property])}}return"#<Effect:"+b.inspect()+",options:"+$H(this.options).inspect()+">"}});Effect.Parallel=Class.create(Effect.Base,{initialize:function(b){this.effects=b||[];this.start(arguments[1])},update:function(b){this.effects.invoke("render",b)},finish:function(b){this.effects.each(function(d){d.render(1);d.cancel();d.event("beforeFinish");if(d.finish){d.finish(b)}d.event("afterFinish")})}});Effect.Tween=Class.create(Effect.Base,{initialize:function(e,h,g){e=Object.isString(e)?$(e):e;var d=$A(arguments),f=d.last(),b=d.length==5?d[3]:null;this.method=Object.isFunction(f)?f.bind(e):Object.isFunction(e[f])?e[f].bind(e):function(l){e[f]=l};this.start(Object.extend({from:h,to:g},b||{}))},update:function(b){this.method(b)}});Effect.Event=Class.create(Effect.Base,{initialize:function(){this.start(Object.extend({duration:0},arguments[0]||{}))},update:Prototype.emptyFunction});Effect.Opacity=Class.create(Effect.Base,{initialize:function(d){this.element=$(d);if(!this.element){throw (Effect._elementDoesNotExistError)}if(Prototype.Browser.IE&&(!this.element.currentStyle.hasLayout)){this.element.setStyle({zoom:1})}var b=Object.extend({from:this.element.getOpacity()||0,to:1},arguments[1]||{});this.start(b)},update:function(b){this.element.setOpacity(b)}});Effect.Move=Class.create(Effect.Base,{initialize:function(d){this.element=$(d);if(!this.element){throw (Effect._elementDoesNotExistError)}var b=Object.extend({x:0,y:0,mode:"relative"},arguments[1]||{});this.start(b)},setup:function(){this.element.makePositioned();this.originalLeft=parseFloat(this.element.getStyle("left")||"0");this.originalTop=parseFloat(this.element.getStyle("top")||"0");if(this.options.mode=="absolute"){this.options.x=this.options.x-this.originalLeft;this.options.y=this.options.y-this.originalTop}},update:function(b){this.element.setStyle({left:(this.options.x*b+this.originalLeft).round()+"px",top:(this.options.y*b+this.originalTop).round()+"px"})}});Effect.MoveBy=function(d,b,e){return new Effect.Move(d,Object.extend({x:e,y:b},arguments[3]||{}))};Effect.Scale=Class.create(Effect.Base,{initialize:function(d,e){this.element=$(d);if(!this.element){throw (Effect._elementDoesNotExistError)}var b=Object.extend({scaleX:true,scaleY:true,scaleContent:true,scaleFromCenter:false,scaleMode:"box",scaleFrom:100,scaleTo:e},arguments[2]||{});this.start(b)},setup:function(){this.restoreAfterFinish=this.options.restoreAfterFinish||false;this.elementPositioning=this.element.getStyle("position");this.originalStyle={};["top","left","width","height","fontSize"].each(function(d){this.originalStyle[d]=this.element.style[d]}.bind(this));this.originalTop=this.element.offsetTop;this.originalLeft=this.element.offsetLeft;var b=this.element.getStyle("font-size")||"100%";["em","px","%","pt"].each(function(d){if(b.indexOf(d)>0){this.fontSize=parseFloat(b);this.fontSizeType=d}}.bind(this));this.factor=(this.options.scaleTo-this.options.scaleFrom)/100;this.dims=null;if(this.options.scaleMode=="box"){this.dims=[this.element.offsetHeight,this.element.offsetWidth]}if(/^content/.test(this.options.scaleMode)){this.dims=[this.element.scrollHeight,this.element.scrollWidth]}if(!this.dims){this.dims=[this.options.scaleMode.originalHeight,this.options.scaleMode.originalWidth]}},update:function(b){var d=(this.options.scaleFrom/100)+(this.factor*b);if(this.options.scaleContent&&this.fontSize){this.element.setStyle({fontSize:this.fontSize*d+this.fontSizeType})}this.setDimensions(this.dims[0]*d,this.dims[1]*d)},finish:function(b){if(this.restoreAfterFinish){this.element.setStyle(this.originalStyle)}},setDimensions:function(b,g){var h={};if(this.options.scaleX){h.width=g.round()+"px"}if(this.options.scaleY){h.height=b.round()+"px"}if(this.options.scaleFromCenter){var f=(b-this.dims[0])/2;var e=(g-this.dims[1])/2;if(this.elementPositioning=="absolute"){if(this.options.scaleY){h.top=this.originalTop-f+"px"}if(this.options.scaleX){h.left=this.originalLeft-e+"px"}}else{if(this.options.scaleY){h.top=-f+"px"}if(this.options.scaleX){h.left=-e+"px"}}}this.element.setStyle(h)}});Effect.Highlight=Class.create(Effect.Base,{initialize:function(d){this.element=$(d);if(!this.element){throw (Effect._elementDoesNotExistError)}var b=Object.extend({startcolor:"#ffff99"},arguments[1]||{});this.start(b)},setup:function(){if(this.element.getStyle("display")=="none"){this.cancel();return}this.oldStyle={};if(!this.options.keepBackgroundImage){this.oldStyle.backgroundImage=this.element.getStyle("background-image");this.element.setStyle({backgroundImage:"none"})}if(!this.options.endcolor){this.options.endcolor=this.element.getStyle("background-color").parseColor("#ffffff")}if(!this.options.restorecolor){this.options.restorecolor=this.element.getStyle("background-color")}this._base=$R(0,2).map(function(b){return parseInt(this.options.startcolor.slice(b*2+1,b*2+3),16)}.bind(this));this._delta=$R(0,2).map(function(b){return parseInt(this.options.endcolor.slice(b*2+1,b*2+3),16)-this._base[b]}.bind(this))},update:function(b){this.element.setStyle({backgroundColor:$R(0,2).inject("#",function(d,e,f){return d+((this._base[f]+(this._delta[f]*b)).round().toColorPart())}.bind(this))})},finish:function(){this.element.setStyle(Object.extend(this.oldStyle,{backgroundColor:this.options.restorecolor}))}});Effect.ScrollTo=function(e){var d=arguments[1]||{},b=document.viewport.getScrollOffsets(),f=$(e).cumulativeOffset();if(d.offset){f[1]+=d.offset}return new Effect.Tween(null,b.top,f[1],d,function(g){scrollTo(b.left,g.round())})};Effect.Fade=function(e){e=$(e);var b=e.getInlineOpacity();var d=Object.extend({from:e.getOpacity()||1,to:0,afterFinishInternal:function(f){if(f.options.to!=0){return}f.element.hide().setStyle({opacity:b})}},arguments[1]||{});return new Effect.Opacity(e,d)};Effect.Appear=function(d){d=$(d);var b=Object.extend({from:(d.getStyle("display")=="none"?0:d.getOpacity()||0),to:1,afterFinishInternal:function(e){e.element.forceRerendering()},beforeSetup:function(e){e.element.setOpacity(e.options.from).show()}},arguments[1]||{});return new Effect.Opacity(d,b)};Effect.Puff=function(d){d=$(d);var b={opacity:d.getInlineOpacity(),position:d.getStyle("position"),top:d.style.top,left:d.style.left,width:d.style.width,height:d.style.height};return new Effect.Parallel([new Effect.Scale(d,200,{sync:true,scaleFromCenter:true,scaleContent:true,restoreAfterFinish:true}),new Effect.Opacity(d,{sync:true,to:0})],Object.extend({duration:1,beforeSetupInternal:function(e){Position.absolutize(e.effects[0].element)},afterFinishInternal:function(e){e.effects[0].element.hide().setStyle(b)}},arguments[1]||{}))};Effect.BlindUp=function(b){b=$(b);b.makeClipping();return new Effect.Scale(b,0,Object.extend({scaleContent:false,scaleX:false,restoreAfterFinish:true,afterFinishInternal:function(d){d.element.hide().undoClipping()}},arguments[1]||{}))};Effect.BlindDown=function(d){d=$(d);var b=d.getDimensions();return new Effect.Scale(d,100,Object.extend({scaleContent:false,scaleX:false,scaleFrom:0,scaleMode:{originalHeight:b.height,originalWidth:b.width},restoreAfterFinish:true,afterSetup:function(e){e.element.makeClipping().setStyle({height:"0px"}).show()},afterFinishInternal:function(e){e.element.undoClipping()}},arguments[1]||{}))};Effect.SwitchOff=function(d){d=$(d);var b=d.getInlineOpacity();return new Effect.Appear(d,Object.extend({duration:0.4,from:0,transition:Effect.Transitions.flicker,afterFinishInternal:function(e){new Effect.Scale(e.element,1,{duration:0.3,scaleFromCenter:true,scaleX:false,scaleContent:false,restoreAfterFinish:true,beforeSetup:function(f){f.element.makePositioned().makeClipping()},afterFinishInternal:function(f){f.element.hide().undoClipping().undoPositioned().setStyle({opacity:b})}})}},arguments[1]||{}))};Effect.DropOut=function(d){d=$(d);var b={top:d.getStyle("top"),left:d.getStyle("left"),opacity:d.getInlineOpacity()};return new Effect.Parallel([new Effect.Move(d,{x:0,y:100,sync:true}),new Effect.Opacity(d,{sync:true,to:0})],Object.extend({duration:0.5,beforeSetup:function(e){e.effects[0].element.makePositioned()},afterFinishInternal:function(e){e.effects[0].element.hide().undoPositioned().setStyle(b)}},arguments[1]||{}))};Effect.Shake=function(f){f=$(f);var d=Object.extend({distance:20,duration:0.5},arguments[1]||{});var g=parseFloat(d.distance);var e=parseFloat(d.duration)/10;var b={top:f.getStyle("top"),left:f.getStyle("left")};return new Effect.Move(f,{x:g,y:0,duration:e,afterFinishInternal:function(h){new Effect.Move(h.element,{x:-g*2,y:0,duration:e*2,afterFinishInternal:function(l){new Effect.Move(l.element,{x:g*2,y:0,duration:e*2,afterFinishInternal:function(n){new Effect.Move(n.element,{x:-g*2,y:0,duration:e*2,afterFinishInternal:function(o){new Effect.Move(o.element,{x:g*2,y:0,duration:e*2,afterFinishInternal:function(p){new Effect.Move(p.element,{x:-g,y:0,duration:e,afterFinishInternal:function(q){q.element.undoPositioned().setStyle(b)}})}})}})}})}})}})};Effect.SlideDown=function(e){e=$(e).cleanWhitespace();var b=e.down().getStyle("bottom");var d=e.getDimensions();return new Effect.Scale(e,100,Object.extend({scaleContent:false,scaleX:false,scaleFrom:window.opera?0:1,scaleMode:{originalHeight:d.height,originalWidth:d.width},restoreAfterFinish:true,afterSetup:function(f){f.element.makePositioned();f.element.down().makePositioned();if(window.opera){f.element.setStyle({top:""})}f.element.makeClipping().setStyle({height:"0px"}).show()},afterUpdateInternal:function(f){f.element.down().setStyle({bottom:(f.dims[0]-f.element.clientHeight)+"px"})},afterFinishInternal:function(f){f.element.undoClipping().undoPositioned();f.element.down().undoPositioned().setStyle({bottom:b})}},arguments[1]||{}))};Effect.SlideUp=function(e){e=$(e).cleanWhitespace();var b=e.down().getStyle("bottom");var d=e.getDimensions();return new Effect.Scale(e,window.opera?0:1,Object.extend({scaleContent:false,scaleX:false,scaleMode:"box",scaleFrom:100,scaleMode:{originalHeight:d.height,originalWidth:d.width},restoreAfterFinish:true,afterSetup:function(f){f.element.makePositioned();f.element.down().makePositioned();if(window.opera){f.element.setStyle({top:""})}f.element.makeClipping().show()},afterUpdateInternal:function(f){f.element.down().setStyle({bottom:(f.dims[0]-f.element.clientHeight)+"px"})},afterFinishInternal:function(f){f.element.hide().undoClipping().undoPositioned();f.element.down().undoPositioned().setStyle({bottom:b})}},arguments[1]||{}))};Effect.Squish=function(b){return new Effect.Scale(b,window.opera?1:0,{restoreAfterFinish:true,beforeSetup:function(d){d.element.makeClipping()},afterFinishInternal:function(d){d.element.hide().undoClipping()}})};Effect.Grow=function(e){e=$(e);var d=Object.extend({direction:"center",moveTransition:Effect.Transitions.sinoidal,scaleTransition:Effect.Transitions.sinoidal,opacityTransition:Effect.Transitions.full},arguments[1]||{});var b={top:e.style.top,left:e.style.left,height:e.style.height,width:e.style.width,opacity:e.getInlineOpacity()};var l=e.getDimensions();var n,h;var g,f;switch(d.direction){case"top-left":n=h=g=f=0;break;case"top-right":n=l.width;h=f=0;g=-l.width;break;case"bottom-left":n=g=0;h=l.height;f=-l.height;break;case"bottom-right":n=l.width;h=l.height;g=-l.width;f=-l.height;break;case"center":n=l.width/2;h=l.height/2;g=-l.width/2;f=-l.height/2;break}return new Effect.Move(e,{x:n,y:h,duration:0.01,beforeSetup:function(o){o.element.hide().makeClipping().makePositioned()},afterFinishInternal:function(o){new Effect.Parallel([new Effect.Opacity(o.element,{sync:true,to:1,from:0,transition:d.opacityTransition}),new Effect.Move(o.element,{x:g,y:f,sync:true,transition:d.moveTransition}),new Effect.Scale(o.element,100,{scaleMode:{originalHeight:l.height,originalWidth:l.width},sync:true,scaleFrom:window.opera?1:0,transition:d.scaleTransition,restoreAfterFinish:true})],Object.extend({beforeSetup:function(p){p.effects[0].element.setStyle({height:"0px"}).show()},afterFinishInternal:function(p){p.effects[0].element.undoClipping().undoPositioned().setStyle(b)}},d))}})};Effect.Shrink=function(e){e=$(e);var d=Object.extend({direction:"center",moveTransition:Effect.Transitions.sinoidal,scaleTransition:Effect.Transitions.sinoidal,opacityTransition:Effect.Transitions.none},arguments[1]||{});var b={top:e.style.top,left:e.style.left,height:e.style.height,width:e.style.width,opacity:e.getInlineOpacity()};var h=e.getDimensions();var g,f;switch(d.direction){case"top-left":g=f=0;break;case"top-right":g=h.width;f=0;break;case"bottom-left":g=0;f=h.height;break;case"bottom-right":g=h.width;f=h.height;break;case"center":g=h.width/2;f=h.height/2;break}return new Effect.Parallel([new Effect.Opacity(e,{sync:true,to:0,from:1,transition:d.opacityTransition}),new Effect.Scale(e,window.opera?1:0,{sync:true,transition:d.scaleTransition,restoreAfterFinish:true}),new Effect.Move(e,{x:g,y:f,sync:true,transition:d.moveTransition})],Object.extend({beforeStartInternal:function(l){l.effects[0].element.makePositioned().makeClipping()},afterFinishInternal:function(l){l.effects[0].element.hide().undoClipping().undoPositioned().setStyle(b)}},d))};Effect.Pulsate=function(e){e=$(e);var d=arguments[1]||{},b=e.getInlineOpacity(),g=d.transition||Effect.Transitions.linear,f=function(h){return 1-g((-Math.cos((h*(d.pulses||5)*2)*Math.PI)/2)+0.5)};return new Effect.Opacity(e,Object.extend(Object.extend({duration:2,from:0,afterFinishInternal:function(h){h.element.setStyle({opacity:b})}},d),{transition:f}))};Effect.Fold=function(d){d=$(d);var b={top:d.style.top,left:d.style.left,width:d.style.width,height:d.style.height};d.makeClipping();return new Effect.Scale(d,5,Object.extend({scaleContent:false,scaleX:false,afterFinishInternal:function(e){new Effect.Scale(d,1,{scaleContent:false,scaleY:false,afterFinishInternal:function(f){f.element.hide().undoClipping().setStyle(b)}})}},arguments[1]||{}))};Effect.Morph=Class.create(Effect.Base,{initialize:function(e){this.element=$(e);if(!this.element){throw (Effect._elementDoesNotExistError)}var b=Object.extend({style:{}},arguments[1]||{});if(!Object.isString(b.style)){this.style=$H(b.style)}else{if(b.style.include(":")){this.style=b.style.parseStyle()}else{this.element.addClassName(b.style);this.style=$H(this.element.getStyles());this.element.removeClassName(b.style);var d=this.element.getStyles();this.style=this.style.reject(function(f){return f.value==d[f.key]});b.afterFinishInternal=function(f){f.element.addClassName(f.options.style);f.transforms.each(function(g){f.element.style[g.style]=""})}}}this.start(b)},setup:function(){function b(d){if(!d||["rgba(0, 0, 0, 0)","transparent"].include(d)){d="#ffffff"}d=d.parseColor();return $R(0,2).map(function(e){return parseInt(d.slice(e*2+1,e*2+3),16)})}this.transforms=this.style.map(function(l){var h=l[0],g=l[1],f=null;if(g.parseColor("#zzzzzz")!="#zzzzzz"){g=g.parseColor();f="color"}else{if(h=="opacity"){g=parseFloat(g);if(Prototype.Browser.IE&&(!this.element.currentStyle.hasLayout)){this.element.setStyle({zoom:1})}}else{if(Element.CSS_LENGTH.test(g)){var e=g.match(/^([\+\-]?[0-9\.]+)(.*)$/);g=parseFloat(e[1]);f=(e.length==3)?e[2]:null}}}var d=this.element.getStyle(h);return{style:h.camelize(),originalValue:f=="color"?b(d):parseFloat(d||0),targetValue:f=="color"?b(g):g,unit:f}}.bind(this)).reject(function(d){return((d.originalValue==d.targetValue)||(d.unit!="color"&&(isNaN(d.originalValue)||isNaN(d.targetValue))))})},update:function(b){var f={},d,e=this.transforms.length;while(e--){f[(d=this.transforms[e]).style]=d.unit=="color"?"#"+(Math.round(d.originalValue[0]+(d.targetValue[0]-d.originalValue[0])*b)).toColorPart()+(Math.round(d.originalValue[1]+(d.targetValue[1]-d.originalValue[1])*b)).toColorPart()+(Math.round(d.originalValue[2]+(d.targetValue[2]-d.originalValue[2])*b)).toColorPart():(d.originalValue+(d.targetValue-d.originalValue)*b).toFixed(3)+(d.unit===null?"":d.unit)}this.element.setStyle(f,true)}});Effect.Transform=Class.create({initialize:function(b){this.tracks=[];this.options=arguments[1]||{};this.addTracks(b)},addTracks:function(b){b.each(function(d){d=$H(d);var e=d.values().first();this.tracks.push($H({ids:d.keys().first(),effect:Effect.Morph,options:{style:e}}))}.bind(this));return this},play:function(){return new Effect.Parallel(this.tracks.map(function(b){var f=b.get("ids"),e=b.get("effect"),d=b.get("options");var g=[$(f)||$$(f)].flatten();return g.map(function(h){return new e(h,Object.extend({sync:true},d))})}).flatten(),this.options)}});Element.CSS_PROPERTIES=$w("backgroundColor backgroundPosition borderBottomColor borderBottomStyle borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth borderRightColor borderRightStyle borderRightWidth borderSpacing borderTopColor borderTopStyle borderTopWidth bottom clip color fontSize fontWeight height left letterSpacing lineHeight marginBottom marginLeft marginRight marginTop markerOffset maxHeight maxWidth minHeight minWidth opacity outlineColor outlineOffset outlineWidth paddingBottom paddingLeft paddingRight paddingTop right textIndent top width wordSpacing zIndex");Element.CSS_LENGTH=/^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;String.__parseStyleElement=document.createElement("div");String.prototype.parseStyle=function(){var d,b=$H();if(Prototype.Browser.WebKit){d=new Element("div",{style:this}).style}else{String.__parseStyleElement.innerHTML='<div style="'+this+'"></div>';d=String.__parseStyleElement.childNodes[0].style}Element.CSS_PROPERTIES.each(function(e){if(d[e]){b.set(e,d[e])}});if(Prototype.Browser.IE&&this.include("opacity")){b.set("opacity",this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1])}return b};if(document.defaultView&&document.defaultView.getComputedStyle){Element.getStyles=function(d){var b=document.defaultView.getComputedStyle($(d),null);return Element.CSS_PROPERTIES.inject({},function(e,f){e[f]=b[f];return e})}}else{Element.getStyles=function(d){d=$(d);var b=d.currentStyle,e;e=Element.CSS_PROPERTIES.inject({},function(f,g){f[g]=b[g];return f});if(!e.opacity){e.opacity=d.getOpacity()}return e}}Effect.Methods={morph:function(b,d){b=$(b);new Effect.Morph(b,Object.extend({style:d},arguments[2]||{}));return b},visualEffect:function(e,g,d){e=$(e);var f=g.dasherize().camelize(),b=f.charAt(0).toUpperCase()+f.substring(1);new Effect[b](e,d);return e},highlight:function(d,b){d=$(d);new Effect.Highlight(d,b);return d}};$w("fade appear grow shrink fold blindUp blindDown slideUp slideDown pulsate shake puff squish switchOff dropOut").each(function(b){Effect.Methods[b]=function(e,d){e=$(e);Effect[b.charAt(0).toUpperCase()+b.substring(1)](e,d);return e}});$w("getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles").each(function(b){Effect.Methods[b]=Element[b]});Element.addMethods(Effect.Methods);function validateCreditCard(e){var d="0123456789";var b="";for(i=0;i<e.length;i++){x=e.charAt(i);if(d.indexOf(x,0)!=-1){b+=x}}j=b.length/2;k=Math.floor(j);m=Math.ceil(j)-k;c=0;for(i=0;i<k;i++){a=b.charAt(i*2+m)*2;c+=a>9?Math.floor(a/10+a%10):a}for(i=0;i<k+m;i++){c+=b.charAt(i*2+1-m)*1}return(c%10==0)}var Validator=Class.create();Validator.prototype={initialize:function(e,d,f,b){if(typeof f=="function"){this.options=$H(b);this._test=f}else{this.options=$H(f);this._test=function(){return true}}this.error=d||"Validation failed.";this.className=e},test:function(b,d){return(this._test(b,d)&&this.options.all(function(e){return Validator.methods[e.key]?Validator.methods[e.key](b,d,e.value):true}))}};Validator.methods={pattern:function(b,e,d){return Validation.get("IsEmpty").test(b)||d.test(b)},minLength:function(b,e,d){return b.length>=d},maxLength:function(b,e,d){return b.length<=d},min:function(b,e,d){return b>=parseFloat(d)},max:function(b,e,d){return b<=parseFloat(d)},notOneOf:function(b,e,d){return $A(d).all(function(f){return b!=f})},oneOf:function(b,e,d){return $A(d).any(function(f){return b==f})},is:function(b,e,d){return b==d},isNot:function(b,e,d){return b!=d},equalToField:function(b,e,d){return b==$F(d)},notEqualToField:function(b,e,d){return b!=$F(d)},include:function(b,e,d){return $A(d).all(function(f){return Validation.get(f).test(b,e)})}};var Validation=Class.create();Validation.defaultOptions={onSubmit:true,stopOnFirst:false,immediate:false,focusOnError:true,useTitles:false,addClassNameToContainer:false,containerClassName:".input-box",onFormValidate:function(b,d){},onElementValidate:function(b,d){}};Validation.prototype={initialize:function(d,b){this.form=$(d);if(!this.form){return}this.options=Object.extend({onSubmit:Validation.defaultOptions.onSubmit,stopOnFirst:Validation.defaultOptions.stopOnFirst,immediate:Validation.defaultOptions.immediate,focusOnError:Validation.defaultOptions.focusOnError,useTitles:Validation.defaultOptions.useTitles,onFormValidate:Validation.defaultOptions.onFormValidate,onElementValidate:Validation.defaultOptions.onElementValidate},b||{});if(this.options.onSubmit){Event.observe(this.form,"submit",this.onSubmit.bind(this),false)}if(this.options.immediate){Form.getElements(this.form).each(function(e){if(e.tagName.toLowerCase()=="select"){Event.observe(e,"blur",this.onChange.bindAsEventListener(this))}if(e.type.toLowerCase()=="radio"||e.type.toLowerCase()=="checkbox"){Event.observe(e,"click",this.onChange.bindAsEventListener(this))}else{Event.observe(e,"change",this.onChange.bindAsEventListener(this))}},this)}},onChange:function(b){Validation.isOnChange=true;Validation.validate(Event.element(b),{useTitle:this.options.useTitles,onElementValidate:this.options.onElementValidate});Validation.isOnChange=false},onSubmit:function(b){if(!this.validate()){Event.stop(b)}},validate:function(){var b=false;var d=this.options.useTitles;var g=this.options.onElementValidate;try{if(this.options.stopOnFirst){b=Form.getElements(this.form).all(function(e){if(e.hasClassName("local-validation")&&!this.isElementInForm(e,this.form)){return true}return Validation.validate(e,{useTitle:d,onElementValidate:g})},this)}else{b=Form.getElements(this.form).collect(function(e){if(e.hasClassName("local-validation")&&!this.isElementInForm(e,this.form)){return true}if(e.hasClassName("validation-disabled")){return true}return Validation.validate(e,{useTitle:d,onElementValidate:g})},this).all()}}catch(f){}if(!b&&this.options.focusOnError){try{Form.getElements(this.form).findAll(function(e){return $(e).hasClassName("validation-failed")}).first().focus()}catch(f){}}this.options.onFormValidate(b,this.form);return b},reset:function(){Form.getElements(this.form).each(Validation.reset)},isElementInForm:function(e,d){var b=e.up("form");if(b==d){return true}return false}};Object.extend(Validation,{validate:function(e,b){b=Object.extend({useTitle:false,onElementValidate:function(f,g){}},b||{});e=$(e);var d=$w(e.className);return result=d.all(function(f){var g=Validation.test(f,e,b.useTitle);b.onElementValidate(g,e);return g})},insertAdvice:function(f,d){var b=$(f).up(".field-row");if(b){Element.insert(b,{after:d})}else{if(f.up("td.value")){f.up("td.value").insert({bottom:d})}else{if(f.advaiceContainer&&$(f.advaiceContainer)){$(f.advaiceContainer).update(d)}else{switch(f.type.toLowerCase()){case"checkbox":case"radio":var e=f.parentNode;if(e){Element.insert(e,{bottom:d})}else{Element.insert(f,{after:d})}break;default:Element.insert(f,{after:d})}}}}},showAdvice:function(e,d,b){if(!e.advices){e.advices=new Hash()}else{e.advices.each(function(f){if(!d||f.value.id!=d.id){this.hideAdvice(e,f.value)}}.bind(this))}e.advices.set(b,d);if(typeof Effect=="undefined"){d.style.display="block"}else{if(!d._adviceAbsolutize){new Effect.Appear(d,{duration:1})}else{Position.absolutize(d);d.show();d.setStyle({top:d._adviceTop,left:d._adviceLeft,width:d._adviceWidth,"z-index":1000});d.addClassName("advice-absolute")}}},hideAdvice:function(d,b){if(b!=null){new Effect.Fade(b,{duration:1,afterFinishInternal:function(){b.hide()}})}},updateCallback:function(elm,status){if(typeof elm.callbackFunction!="undefined"){eval(elm.callbackFunction+"('"+elm.id+"','"+status+"')")}},ajaxError:function(g,f){var e="validate-ajax";var d=Validation.getAdvice(e,g);if(d==null){d=this.createAdvice(e,g,false,f)}this.showAdvice(g,d,"validate-ajax");this.updateCallback(g,"failed");g.addClassName("validation-failed");g.addClassName("validate-ajax");if(Validation.defaultOptions.addClassNameToContainer&&Validation.defaultOptions.containerClassName!=""){var b=g.up(Validation.defaultOptions.containerClassName);if(b&&this.allowContainerClassName(g)){b.removeClassName("validation-passed");b.addClassName("validation-error")}}},allowContainerClassName:function(b){if(b.type=="radio"||b.type=="checkbox"){return b.hasClassName("change-container-classname")}return true},test:function(g,o,l){var d=Validation.get(g);var n="__advice"+g.camelize();try{if(Validation.isVisible(o)&&!d.test($F(o),o)){var f=Validation.getAdvice(g,o);if(f==null){f=this.createAdvice(g,o,l)}this.showAdvice(o,f,g);this.updateCallback(o,"failed");o[n]=1;if(!o.advaiceContainer){o.removeClassName("validation-passed");o.addClassName("validation-failed")}if(Validation.defaultOptions.addClassNameToContainer&&Validation.defaultOptions.containerClassName!=""){var b=o.up(Validation.defaultOptions.containerClassName);if(b&&this.allowContainerClassName(o)){b.removeClassName("validation-passed");b.addClassName("validation-error")}}return false}else{var f=Validation.getAdvice(g,o);this.hideAdvice(o,f);this.updateCallback(o,"passed");o[n]="";o.removeClassName("validation-failed");o.addClassName("validation-passed");if(Validation.defaultOptions.addClassNameToContainer&&Validation.defaultOptions.containerClassName!=""){var b=o.up(Validation.defaultOptions.containerClassName);if(b&&!b.down(".validation-failed")&&this.allowContainerClassName(o)){if(!Validation.get("IsEmpty").test(o.value)||!this.isVisible(o)){b.addClassName("validation-passed")}else{b.removeClassName("validation-passed")}b.removeClassName("validation-error")}}return true}}catch(h){throw (h)}},isVisible:function(b){while(b.tagName!="BODY"){if(!$(b).visible()){return false}b=b.parentNode}return true},getAdvice:function(b,d){return $("advice-"+b+"-"+Validation.getElmID(d))||$("advice-"+Validation.getElmID(d))},createAdvice:function(e,n,l,d){var b=Validation.get(e);var h=l?((n&&n.title)?n.title:b.error):b.error;if(d){h=d}if(jQuery.mage.__){h=jQuery.mage.__(h)}advice='<div class="validation-advice" id="advice-'+e+"-"+Validation.getElmID(n)+'" style="display:none">'+h+"</div>";Validation.insertAdvice(n,advice);advice=Validation.getAdvice(e,n);if($(n).hasClassName("absolute-advice")){var g=$(n).getDimensions();var f=Position.cumulativeOffset(n);advice._adviceTop=(f[1]+g.height)+"px";advice._adviceLeft=(f[0])+"px";advice._adviceWidth=(g.width)+"px";advice._adviceAbsolutize=true}return advice},getElmID:function(b){return b.id?b.id:b.name},reset:function(d){d=$(d);var b=$w(d.className);b.each(function(g){var h="__advice"+g.camelize();if(d[h]){var f=Validation.getAdvice(g,d);if(f){f.hide()}d[h]=""}d.removeClassName("validation-failed");d.removeClassName("validation-passed");if(Validation.defaultOptions.addClassNameToContainer&&Validation.defaultOptions.containerClassName!=""){var e=d.up(Validation.defaultOptions.containerClassName);if(e){e.removeClassName("validation-passed");e.removeClassName("validation-error")}}})},add:function(f,e,g,d){var b={};b[f]=new Validator(f,e,g,d);Object.extend(Validation.methods,b)},addAllThese:function(b){var d={};$A(b).each(function(e){d[e[0]]=new Validator(e[0],e[1],e[2],(e.length>3?e[3]:{}))});Object.extend(Validation.methods,d)},get:function(b){return Validation.methods[b]?Validation.methods[b]:Validation.methods._LikeNoIDIEverSaw_},methods:{_LikeNoIDIEverSaw_:new Validator("_LikeNoIDIEverSaw_","",{})}});Validation.add("IsEmpty","",function(b){return(b==""||(b==null)||(b.length==0)||/^\s+$/.test(b))});Validation.addAllThese([["validate-no-html-tags","HTML tags are not allowed",function(b){return !/<(\/)?\w+/.test(b)}],["validate-select","Please select an option.",function(b){return((b!="none")&&(b!=null)&&(b.length!=0))}],["required-entry","This is a required field.",function(b){return !Validation.get("IsEmpty").test(b)}],["validate-number","Please enter a valid number in this field.",function(b){return Validation.get("IsEmpty").test(b)||(!isNaN(parseNumber(b))&&/^\s*-?\d*(\.\d*)?\s*$/.test(b))}],["validate-number-range","The value is not within the specified range.",function(e,g){if(Validation.get("IsEmpty").test(e)){return true}var f=parseNumber(e);if(isNaN(f)){return false}var d=/^number-range-(-?[\d.,]+)?-(-?[\d.,]+)?$/,b=true;$w(g.className).each(function(l){var h=d.exec(l);if(h){b=b&&(h[1]==null||h[1]==""||f>=parseNumber(h[1]))&&(h[2]==null||h[2]==""||f<=parseNumber(h[2]))}});return b}],["validate-digits","Please use numbers only in this field. Please avoid spaces or other characters such as dots or commas.",function(b){return Validation.get("IsEmpty").test(b)||!/[^\d]/.test(b)}],["validate-digits-range","The value is not within the specified range.",function(e,g){if(Validation.get("IsEmpty").test(e)){return true}var f=parseNumber(e);if(isNaN(f)){return false}var d=/^digits-range-(-?\d+)?-(-?\d+)?$/,b=true;$w(g.className).each(function(l){var h=d.exec(l);if(h){b=b&&(h[1]==null||h[1]==""||f>=parseNumber(h[1]))&&(h[2]==null||h[2]==""||f<=parseNumber(h[2]))}});return b}],["validate-range","The value is not within the specified range.",function(f,l){var g,h;if(Validation.get("IsEmpty").test(f)){return true}else{if(Validation.get("validate-digits").test(f)){g=h=parseNumber(f)}else{var e=/^(-?\d+)?-(-?\d+)?$/.exec(f);if(e){g=parseNumber(e[1]);h=parseNumber(e[2]);if(g>h){return false}}else{return false}}}var d=/^range-(-?\d+)?-(-?\d+)?$/,b=true;$w(l.className).each(function(n){var q=d.exec(n);if(q){var p=parseNumber(q[1]);var o=parseNumber(q[2]);b=b&&(isNaN(p)||g>=p)&&(isNaN(o)||h<=o)}});return b}],["validate-alpha","Please use letters only (a-z or A-Z) in this field.",function(b){return Validation.get("IsEmpty").test(b)||/^[a-zA-Z]+$/.test(b)}],["validate-code","Please use only letters (a-z), numbers (0-9) or underscore (_) in this field, and the first character should be a letter.",function(b){return Validation.get("IsEmpty").test(b)||/^[a-z]+[a-z0-9_]+$/.test(b)}],["validate-alphanum","Please use only letters (a-z or A-Z) or numbers (0-9) in this field. No spaces or other characters are allowed.",function(b){return Validation.get("IsEmpty").test(b)||/^[a-zA-Z0-9]+$/.test(b)}],["validate-alphanum-with-spaces","Please use only letters (a-z or A-Z), numbers (0-9) or spaces only in this field.",function(b){return Validation.get("IsEmpty").test(b)||/^[a-zA-Z0-9 ]+$/.test(b)}],["validate-street",'Please use only letters (a-z or A-Z), numbers (0-9), spaces and "#" in this field.',function(b){return Validation.get("IsEmpty").test(b)||/^[ \w]{3,}([A-Za-z]\.)?([ \w]*\#\d+)?(\r\n| )[ \w]{3,}/.test(b)}],["validate-phoneStrict","Please enter a valid phone number (Ex: 123-456-7890).",function(b){return Validation.get("IsEmpty").test(b)||/^(\()?\d{3}(\))?(-|\s)?\d{3}(-|\s)\d{4}$/.test(b)}],["validate-phoneLax","Please enter a valid phone number (Ex: 123-456-7890).",function(b){return Validation.get("IsEmpty").test(b)||/^((\d[-. ]?)?((\(\d{3}\))|\d{3}))?[-. ]?\d{3}[-. ]?\d{4}$/.test(b)}],["validate-fax","Please enter a valid fax number (Ex: 123-456-7890).",function(b){return Validation.get("IsEmpty").test(b)||/^(\()?\d{3}(\))?(-|\s)?\d{3}(-|\s)\d{4}$/.test(b)}],["validate-date","Please enter a valid date.",function(b){var d=new Date(b);return Validation.get("IsEmpty").test(b)||!isNaN(d)}],["validate-date-range","Make sure the To Date is later than or the same as the From Date.",function(e,h){var d=/\bdate-range-(\w+)-(\w+)\b/.exec(h.className);if(!d||d[2]=="to"||Validation.get("IsEmpty").test(e)){return true}var f=new Date().getFullYear()+"";var b=function(l){l=l.split(/[.\/]/);if(l[2]&&l[2].length<4){l[2]=f.substr(0,l[2].length)+l[2]}return new Date(l.join("/")).getTime()};var g=Element.select(h.form,".validate-date-range.date-range-"+d[1]+"-to");return !g.length||Validation.get("IsEmpty").test(g[0].value)||b(e)<=b(g[0].value)}],["validate-email","Please enter a valid email address (Ex: johndoe@domain.com).",function(b){return Validation.get("IsEmpty").test(b)||/^([a-z0-9,!\#\$%&'\*\+\/=\?\^_`\{\|\}~-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z0-9,!\#\$%&'\*\+\/=\?\^_`\{\|\}~-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*@([a-z0-9-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z0-9-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*\.(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]){2,})$/i.test(b)}],["validate-emailSender","Please use only visible characters and spaces.",function(b){return Validation.get("IsEmpty").test(b)||/^[\S ]+$/.test(b)}],["validate-password","Please enter 6 or more characters. Leading or trailing spaces will be ignored.",function(b){var d=b.strip();return !(d.length>0&&d.length<6)}],["validate-admin-password","Please enter 7 or more characters, using both numeric and alphabetic.",function(b){var d=b.strip();if(0==d.length){return true}if(!(/[a-z]/i.test(b))||!(/[0-9]/.test(b))){return false}return !(d.length<7)}],["validate-cpassword","Please make sure your passwords match.",function(b){var d=$("confirmation")?$("confirmation"):$$(".validate-cpassword")[0];var g=false;if($("password")){g=$("password")}var h=$$(".validate-password");for(var e=0;e<h.size();e++){var f=h[e];if(f.up("form").id==d.up("form").id){g=f}}if($$(".validate-admin-password").size()){g=$$(".validate-admin-password")[0]}return(g.value==d.value)}],["validate-both-passwords","Please make sure your passwords match.",function(e,d){var b=$(d.form[d.name=="password"?"confirmation":"password"]),f=d.value==b.value;if(f&&b.hasClassName("validation-failed")){Validation.test(this.className,b)}return b.value==""||f}],["validate-url","Please enter a valid URL. Protocol is required (http://, https:// or ftp://)",function(b){b=(b||"").replace(/^\s+/,"").replace(/\s+$/,"");return Validation.get("IsEmpty").test(b)||/^(http|https|ftp):\/\/(([A-Z0-9]([A-Z0-9_-]*[A-Z0-9]|))(\.[A-Z0-9]([A-Z0-9_-]*[A-Z0-9]|))*)(:(\d+))?(\/[A-Z0-9~](([A-Z0-9_~-]|\.)*[A-Z0-9~]|))*\/?(.*)?$/i.test(b)}],["validate-clean-url",'Please enter a valid URL (Ex: "http://www.example.com" or "www.example.com").',function(b){return Validation.get("IsEmpty").test(b)||/^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+.(com|org|net|dk|at|us|tv|info|uk|co.uk|biz|se)$)(:(\d+))?\/?/i.test(b)||/^(www)((\.[A-Z0-9][A-Z0-9_-]*)+.(com|org|net|dk|at|us|tv|info|uk|co.uk|biz|se)$)(:(\d+))?\/?/i.test(b)}],["validate-identifier",'Please enter a valid URL Key (Ex: "example-page", "example-page.html" or "anotherlevel/example-page").',function(b){return Validation.get("IsEmpty").test(b)||/^[a-z0-9][a-z0-9_\/-]+(\.[a-z0-9_-]+)?$/.test(b)}],["validate-xml-identifier","Please enter a valid XML-identifier (Ex: something_1, block5, id-4).",function(b){return Validation.get("IsEmpty").test(b)||/^[A-Z][A-Z0-9_\/-]*$/i.test(b)}],["validate-ssn","Please enter a valid social security number (Ex: 123-45-6789).",function(b){return Validation.get("IsEmpty").test(b)||/^\d{3}-?\d{2}-?\d{4}$/.test(b)}],["validate-zip-us","Please enter a valid zip code (Ex: 90602 or 90602-1234).",function(b){return Validation.get("IsEmpty").test(b)||/(^\d{5}$)|(^\d{5}-\d{4}$)/.test(b)}],["validate-zip-international","Please enter a valid zip code.",function(b){return true}],["validate-date-au",'Please use this date format: dd/mm/yyyy (Ex: "17/03/2006" for the 17th of March, 2006).',function(b){if(Validation.get("IsEmpty").test(b)){return true}var e=/^(\d{2})\/(\d{2})\/(\d{4})$/;if(!e.test(b)){return false}var f=new Date(b.replace(e,"$2/$1/$3"));return(parseInt(RegExp.$2,10)==(1+f.getMonth()))&&(parseInt(RegExp.$1,10)==f.getDate())&&(parseInt(RegExp.$3,10)==f.getFullYear())}],["validate-currency-dollar","Please enter a valid $ amount (Ex: $100.00).",function(b){return Validation.get("IsEmpty").test(b)||/^\$?\-?([1-9]{1}[0-9]{0,2}(\,[0-9]{3})*(\.[0-9]{0,2})?|[1-9]{1}\d*(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|(\.[0-9]{1,2})?)$/.test(b)}],["validate-one-required","Please select one of the options above.",function(b,f){var e=f.parentNode;var d=e.getElementsByTagName("INPUT");return $A(d).any(function(g){return $F(g)})}],["validate-one-required-by-name","Please select one of the options.",function(d,g){var b=$$('input[name="'+g.name.replace(/([\\"])/g,"\\$1")+'"]');var e=1;for(var f=0;f<b.length;f++){if((b[f].type=="checkbox"||b[f].type=="radio")&&b[f].checked==true){e=0}if(Validation.isOnChange&&(b[f].type=="checkbox"||b[f].type=="radio")){Validation.reset(b[f])}}if(e==0){return true}else{return false}}],["validate-not-negative-number","Please enter a number 0 or greater in this field.",function(b){if(Validation.get("IsEmpty").test(b)){return true}b=parseNumber(b);return !isNaN(b)&&b>=0}],["validate-zero-or-greater","Please enter a number 0 or greater in this field.",function(b){return Validation.get("validate-not-negative-number").test(b)}],["validate-greater-than-zero","Please enter a number greater than 0 in this field.",function(b){if(Validation.get("IsEmpty").test(b)){return true}b=parseNumber(b);return !isNaN(b)&&b>0}],["validate-state","Please select State/Province.",function(b){return(b!=0||b=="")}],["validate-new-password","Please enter 6 or more characters. Leading or trailing spaces will be ignored.",function(b){if(!Validation.get("validate-password").test(b)){return false}if(Validation.get("IsEmpty").test(b)&&b!=""){return false}return true}],["validate-cc-number","Please enter a valid credit card number.",function(b,e){var d=$(e.id.substr(0,e.id.indexOf("_cc_number"))+"_cc_type");if(d&&typeof Validation.creditCartTypes.get(d.value)!="undefined"&&Validation.creditCartTypes.get(d.value)[2]==false){if(!Validation.get("IsEmpty").test(b)&&Validation.get("validate-digits").test(b)){return true}else{return false}}return validateCreditCard(b)}],["validate-cc-type","Credit card number does not match credit card type.",function(d,g){g.value=removeDelimiters(g.value);d=removeDelimiters(d);var f=$(g.id.substr(0,g.id.indexOf("_cc_number"))+"_cc_type");if(!f){return true}var e=f.value;if(typeof Validation.creditCartTypes.get(e)=="undefined"){return false}if(Validation.creditCartTypes.get(e)[0]==false){return true}var b="";Validation.creditCartTypes.each(function(h){if(h.value[0]&&d.match(h.value[0])){b=h.key;throw $break}});if(b!=e){return false}if(f.hasClassName("validation-failed")&&Validation.isOnChange){Validation.validate(f)}return true}],["validate-cc-type-select","Card type does not match credit card number.",function(d,e){var b=$(e.id.substr(0,e.id.indexOf("_cc_type"))+"_cc_number");if(Validation.isOnChange&&Validation.get("IsEmpty").test(b.value)){return true}if(Validation.get("validate-cc-type").test(b.value,b)){Validation.validate(b)}return Validation.get("validate-cc-type").test(b.value,b)}],["validate-cc-exp","Incorrect credit card expiration date.",function(b,l){var h=b;var g=$(l.id.substr(0,l.id.indexOf("_expiration"))+"_expiration_yr").value;var f=new Date();var e=f.getMonth()+1;var d=f.getFullYear();if(h<e&&g==d){return false}return true}],["validate-cc-cvn","Please enter a valid credit card verification number.",function(b,g){var f=$(g.id.substr(0,g.id.indexOf("_cc_cid"))+"_cc_type");if(!f){return true}var d=f.value;if(typeof Validation.creditCartTypes.get(d)=="undefined"){return false}var e=Validation.creditCartTypes.get(d)[1];if(b.match(e)){return true}return false}],["validate-ajax","",function(b,d){return true}],["validate-data","Please use only letters (a-z or A-Z), numbers (0-9) or underscore (_) in this field, and the first character should be a letter.",function(b){if(b!=""&&b){return/^[A-Za-z]+[A-Za-z0-9_]+$/.test(b)}return true}],["validate-css-length","Please input a valid CSS-length (Ex: 100px, 77pt, 20em, .5ex or 50%).",function(b){if(b!=""&&b){return/^[0-9\.]+(px|pt|em|ex|%)?$/.test(b)&&(!(/\..*\./.test(b)))&&!(/\.$/.test(b))}return true}],["validate-length","Text length does not meet the specified text range.",function(d,g){var e=new RegExp(/^maximum-length-[0-9]+$/);var f=new RegExp(/^minimum-length-[0-9]+$/);var b=true;$w(g.className).each(function(l,h){if(l.match(e)&&b){var n=l.split("-")[2];b=(d.length<=n)}if(l.match(f)&&b&&!Validation.get("IsEmpty").test(d)){var n=l.split("-")[2];b=(d.length>=n)}});return b}],["validate-percents","Please enter a number lower than 100.",{max:100}],["required-file","Please select a file.",function(d,e){var b=!Validation.get("IsEmpty").test(d);if(b===false){ovId=e.id+"_value";if($(ovId)){b=!Validation.get("IsEmpty").test($(ovId).value)}}return b}],["validate-cc-ukss","Please enter issue number or start date for switch/solo card type.",function(o,g){var b;if(g.id.match(/(.)+_cc_issue$/)){b=g.id.indexOf("_cc_issue")}else{if(g.id.match(/(.)+_start_month$/)){b=g.id.indexOf("_start_month")}else{b=g.id.indexOf("_start_year")}}var f=g.id.substr(0,b);var d=$(f+"_cc_type");if(!d){return true}var n=d.value;if(["SS","SM","SO"].indexOf(n)==-1){return true}$(f+"_cc_issue").advaiceContainer=$(f+"_start_month").advaiceContainer=$(f+"_start_year").advaiceContainer=$(f+"_cc_type_ss_div").down(".adv-container");var h=$(f+"_cc_issue").value;var l=$(f+"_start_month").value;var p=$(f+"_start_year").value;var e=(l&&p)?true:false;if(!e&&!h){return false}return true}]]);function removeDelimiters(b){b=b.replace(/\s/g,"");b=b.replace(/\-/g,"");return b}function parseNumber(b){if(typeof b!="string"){return parseFloat(b)}var e=b.indexOf(".");var d=b.indexOf(",");if(e!=-1&&d!=-1){if(d>e){b=b.replace(".","").replace(",",".")}else{b=b.replace(",","")}}else{if(d!=-1){b=b.replace(",",".")}}return parseFloat(b)}Validation.creditCartTypes=$H({SO:[new RegExp("^(6334[5-9]([0-9]{11}|[0-9]{13,14}))|(6767([0-9]{12}|[0-9]{14,15}))$"),new RegExp("^([0-9]{3}|[0-9]{4})?$"),true],SM:[new RegExp("(^(5[0678])[0-9]{11,18}$)|(^(6[^05])[0-9]{11,18}$)|(^(601)[^1][0-9]{9,16}$)|(^(6011)[0-9]{9,11}$)|(^(6011)[0-9]{13,16}$)|(^(65)[0-9]{11,13}$)|(^(65)[0-9]{15,18}$)|(^(49030)[2-9]([0-9]{10}$|[0-9]{12,13}$))|(^(49033)[5-9]([0-9]{10}$|[0-9]{12,13}$))|(^(49110)[1-2]([0-9]{10}$|[0-9]{12,13}$))|(^(49117)[4-9]([0-9]{10}$|[0-9]{12,13}$))|(^(49118)[0-2]([0-9]{10}$|[0-9]{12,13}$))|(^(4936)([0-9]{12}$|[0-9]{14,15}$))"),new RegExp("^([0-9]{3}|[0-9]{4})?$"),true],VI:[new RegExp("^4[0-9]{12}([0-9]{3})?$"),new RegExp("^[0-9]{3}$"),true],MC:[new RegExp("^5[1-5][0-9]{14}$"),new RegExp("^[0-9]{3}$"),true],AE:[new RegExp("^3[47][0-9]{13}$"),new RegExp("^[0-9]{4}$"),true],DI:[new RegExp("^6(011|4[4-9][0-9]|5[0-9]{2})[0-9]{12}$"),new RegExp("^[0-9]{3}$"),true],JCB:[new RegExp("^(3[0-9]{15}|(2131|1800)[0-9]{11})$"),new RegExp("^[0-9]{3,4}$"),true],OT:[false,new RegExp("^([0-9]{3}|[0-9]{4})?$"),false]});function popWin(d,e,b){var e=window.open(d,e,b);e.focus()}function setLocation(b){window.location.href=b}function setPLocation(d,b){if(b){window.opener.focus()}window.opener.location.href=d}function setLanguageCode(e,f){var b=window.location.href;var h="",g;if(g=b.match(/\#(.*)$/)){b=b.replace(/\#(.*)$/,"");h=g[0]}if(b.match(/[?]/)){var d=/([?&]store=)[a-z0-9_]*/;if(b.match(d)){b=b.replace(d,"$1"+e)}else{b+="&store="+e}var d=/([?&]from_store=)[a-z0-9_]*/;if(b.match(d)){b=b.replace(d,"")}}else{b+="?store="+e}if(typeof(f)!="undefined"){b+="&from_store="+f}b+=h;setLocation(b)}function decorateGeneric(h,e){var l=["odd","even","first","last"];var d={};var g=h.length;if(g){if(typeof(e)=="undefined"){e=l}if(!e.length){return}for(var b in l){d[l[b]]=false}for(var b in e){d[e[b]]=true}if(d.first){Element.addClassName(h[0],"first")}if(d.last){Element.addClassName(h[g-1],"last")}for(var f=0;f<g;f++){if((f+1)%2==0){if(d.even){Element.addClassName(h[f],"even")}}else{if(d.odd){Element.addClassName(h[f],"odd")}}}}}function decorateTable(h,e){var h=$(h);if(h){var b={tbody:false,"tbody tr":["odd","even","first","last"],"thead tr":["first","last"],"tfoot tr":["first","last"],"tr td":["last"]};if(typeof(e)!="undefined"){for(var d in e){b[d]=e[d]}}if(b.tbody){decorateGeneric(h.select("tbody"),b.tbody)}if(b["tbody tr"]){decorateGeneric(h.select("tbody tr"),b["tbody tr"])}if(b["thead tr"]){decorateGeneric(h.select("thead tr"),b["thead tr"])}if(b["tfoot tr"]){decorateGeneric(h.select("tfoot tr"),b["tfoot tr"])}if(b["tr td"]){var g=h.select("tr");if(g.length){for(var f=0;f<g.length;f++){decorateGeneric(g[f].getElementsByTagName("TD"),b["tr td"])}}}}}function decorateList(e,d){if($(e)){if(typeof(d)=="undefined"){var b=$(e).select("li")}else{var b=$(e).childElements()}decorateGeneric(b,["odd","even","last"])}}function decorateDataList(b){b=$(b);if(b){decorateGeneric(b.select("dt"),["odd","even","last"]);decorateGeneric(b.select("dd"),["odd","even","last"])}}function parseSidUrl(f,e){var d=f.indexOf("/?SID=");var b="";e=(e!=undefined)?e:"";if(d>-1){b="?"+f.substring(d+2);f=f.substring(0,d+1)}return f+e+b}function formatCurrency(n,q,g){var l=isNaN(q.precision=Math.abs(q.precision))?2:q.precision;var v=isNaN(q.requiredPrecision=Math.abs(q.requiredPrecision))?2:q.requiredPrecision;l=v;var t=isNaN(q.integerRequired=Math.abs(q.integerRequired))?1:q.integerRequired;var p=q.decimalSymbol==undefined?",":q.decimalSymbol;var e=q.groupSymbol==undefined?".":q.groupSymbol;var d=q.groupLength==undefined?3:q.groupLength;var u="";if(g==undefined||g==true){u=n<0?"-":(g?"+":"")}else{if(g==false){u=""}}var h=parseInt(n=Math.abs(+n||0).toFixed(l))+"";var f=(h.length<t)?(t-h.length):0;while(f){h="0"+h;f--}j=(j=h.length)>d?j%d:0;re=new RegExp("(\\d{"+d+"})(?=\\d)","g");var b=(j?h.substr(0,j)+e:"")+h.substr(j).replace(re,"$1"+e)+(l?p+Math.abs(n-h).toFixed(l).replace(/-/,0).slice(2):"");var o="";if(q.pattern.indexOf("{sign}")==-1){o=u+q.pattern}else{o=q.pattern.replace("{sign}",u)}return o.replace("%s",b).replace(/^\s\s*/,"").replace(/\s\s*$/,"")}function expandDetails(d,b){if(Element.hasClassName(d,"show-details")){$$(b).each(function(e){e.hide()});Element.removeClassName(d,"show-details")}else{$$(b).each(function(e){e.show()});Element.addClassName(d,"show-details")}}var isIE=navigator.appVersion.match(/MSIE/)=="MSIE";if(!window.Varien){var Varien=new Object()}Varien.showLoading=function(){var b=$("loading-process");b&&b.show()};Varien.hideLoading=function(){var b=$("loading-process");b&&b.hide()};Varien.GlobalHandlers={onCreate:function(){Varien.showLoading()},onComplete:function(){if(Ajax.activeRequestCount==0){Varien.hideLoading()}}};Ajax.Responders.register(Varien.GlobalHandlers);Varien.searchForm=Class.create();Varien.searchForm.prototype={initialize:function(d,e,b){this.form=$(d);this.field=$(e);this.emptyText=b;Event.observe(this.form,"submit",this.submit.bind(this));Event.observe(this.field,"focus",this.focus.bind(this));Event.observe(this.field,"blur",this.blur.bind(this));this.blur()},submit:function(b){if(this.field.value==this.emptyText||this.field.value==""){Event.stop(b);return false}return true},focus:function(b){if(this.field.value==this.emptyText){this.field.value=""}},blur:function(b){if(this.field.value==""){this.field.value=this.emptyText}}};Varien.DateElement=Class.create();Varien.DateElement.prototype={initialize:function(b,d,f,e){if(b=="id"){this.day=$(d+"day");this.month=$(d+"month");this.year=$(d+"year");this.full=$(d+"full");this.advice=$(d+"date-advice")}else{if(b=="container"){this.day=d.day;this.month=d.month;this.year=d.year;this.full=d.full;this.advice=d.advice}else{return}}this.required=f;this.format=e;this.day.addClassName("validate-custom");this.day.validate=this.validate.bind(this);this.month.addClassName("validate-custom");this.month.validate=this.validate.bind(this);this.year.addClassName("validate-custom");this.year.validate=this.validate.bind(this);this.setDateRange(false,false);this.year.setAttribute("autocomplete","off");this.advice.hide()},validate:function(){var l=false,o=parseInt(this.day.value,10)||0,f=parseInt(this.month.value,10)||0,h=parseInt(this.year.value,10)||0;if(this.day.value.strip().empty()&&this.month.value.strip().empty()&&this.year.value.strip().empty()){if(this.required){l="Please enter a date."}else{this.full.value=""}}else{if(!o||!f||!h){l="Please enter a valid full date."}else{var d=new Date,n=0,e=null;d.setYear(h);d.setMonth(f-1);d.setDate(32);n=32-d.getDate();if(!n||n>31){n=31}if(o<1||o>n){e="day";l="Please enter a valid day (1-%1)."}else{if(f<1||f>12){e="month";l="Please enter a valid month (1-12)."}else{if(o%10==o){this.day.value="0"+o}if(f%10==f){this.month.value="0"+f}this.full.value=this.format.replace(/%[mb]/i,this.month.value).replace(/%[de]/i,this.day.value).replace(/%y/i,this.year.value);var b=this.month.value+"/"+this.day.value+"/"+this.year.value;var g=new Date(b);if(isNaN(g)){l="Please enter a valid date."}else{this.setFullDate(g)}}}var p=false;if(!l&&!this.validateData()){e=this.validateDataErrorType;p=this.validateDataErrorText;l=p}}}if(l!==false){if(jQuery.mage.__){l=jQuery.mage.__(l)}if(!p){this.advice.innerHTML=l.replace("%1",n)}else{this.advice.innerHTML=this.errorTextModifier(l)}this.advice.show();return false}this.day.removeClassName("validation-failed");this.month.removeClassName("validation-failed");this.year.removeClassName("validation-failed");this.advice.hide();return true},validateData:function(){var d=this.fullDate.getFullYear();var b=new Date;this.curyear=b.getFullYear();return(d>=1900&&d<=this.curyear)},validateDataErrorType:"year",validateDataErrorText:"Please enter a valid year (1900-%1).",errorTextModifier:function(b){return b.replace("%1",this.curyear)},setDateRange:function(b,d){this.minDate=b;this.maxDate=d},setFullDate:function(b){this.fullDate=b}};Varien.DOB=Class.create();Varien.DOB.prototype={initialize:function(b,g,f){var e=$$(b)[0];var d={};d.day=Element.select(e,".dob-day input")[0];d.month=Element.select(e,".dob-month input")[0];d.year=Element.select(e,".dob-year input")[0];d.full=Element.select(e,".dob-full input")[0];d.advice=Element.select(e,".validation-advice")[0];new Varien.DateElement("container",d,g,f)}};Varien.dateRangeDate=Class.create();Varien.dateRangeDate.prototype=Object.extend(new Varien.DateElement(),{validateData:function(){var b=true;if(this.minDate||this.maxValue){if(this.minDate){this.minDate=new Date(this.minDate);this.minDate.setHours(0);if(isNaN(this.minDate)){this.minDate=new Date("1/1/1900")}b=b&&(this.fullDate>=this.minDate)}if(this.maxDate){this.maxDate=new Date(this.maxDate);this.minDate.setHours(0);if(isNaN(this.maxDate)){this.maxDate=new Date()}b=b&&(this.fullDate<=this.maxDate)}if(this.maxDate&&this.minDate){this.validateDataErrorText="Please enter a valid date between %s and %s"}else{if(this.maxDate){this.validateDataErrorText="Please enter a valid date less than or equal to %s"}else{if(this.minDate){this.validateDataErrorText="Please enter a valid date equal to or greater than %s"}else{this.validateDataErrorText=""}}}}return b},validateDataErrorText:"Date should be between %s and %s",errorTextModifier:function(b){if(this.minDate){b=b.sub("%s",this.dateFormat(this.minDate))}if(this.maxDate){b=b.sub("%s",this.dateFormat(this.maxDate))}return b},dateFormat:function(b){return(b.getMonth()+1)+"/"+b.getDate()+"/"+b.getFullYear()}});Varien.FileElement=Class.create();Varien.FileElement.prototype={initialize:function(b){this.fileElement=$(b);this.hiddenElement=$(b+"_value");this.fileElement.observe("change",this.selectFile.bind(this))},selectFile:function(b){this.hiddenElement.value=this.fileElement.getValue()}};Validation.addAllThese([["validate-custom"," ",function(b,d){return d.validate()}]]);Element.addMethods({getInnerText:function(b){b=$(b);if(b.innerText&&!Prototype.Browser.Opera){return b.innerText}return b.innerHTML.stripScripts().unescapeHTML().replace(/[\n\r\s]+/g," ").strip()}});function fireEvent(d,e){if(document.createEvent){var b=document.createEvent("HTMLEvents");b.initEvent(e,true,true);return d.dispatchEvent(b)}else{var b=document.createEventObject();return d.fireEvent("on"+e,b)}}function modulo(b,f){var e=f/10000;var d=b%f;if(Math.abs(d-f)<e||Math.abs(d)<e){d=0}return d}if((typeof Range!="undefined")&&!Range.prototype.createContextualFragment){Range.prototype.createContextualFragment=function(b){var e=document.createDocumentFragment(),d=document.createElement("div");e.appendChild(d);d.outerHTML=b;return e}}var byteConvert=function(b){if(isNaN(b)){return""}var d=["bytes","KB","MB","GB","TB","PB","EB","ZB","YB"];var f=Math.floor(Math.log(b)/Math.log(2));if(f<1){f=0}var e=Math.floor(f/10);b=b/Math.pow(2,10*e);if(b.toString().length>b.toFixed(2).toString().length){b=b.toFixed(2)}return b+" "+d[e]};var SessionError=Class.create();SessionError.prototype={initialize:function(b){this.errorText=b},toString:function(){return"Session Error:"+this.errorText}};Ajax.Request.addMethods({initialize:function($super,d,b){$super(b);this.transport=Ajax.getTransport();if(!d.match(new RegExp("[?&]isAjax=true",""))){d=d.match(new RegExp("\\?","g"))?d+"&isAjax=true":d+"?isAjax=true"}if(Object.isString(this.options.parameters)&&this.options.parameters.indexOf("form_key=")==-1){this.options.parameters+="&"+Object.toQueryString({form_key:FORM_KEY})}else{if(!this.options.parameters){this.options.parameters={form_key:FORM_KEY}}if(!this.options.parameters.form_key){this.options.parameters.form_key=FORM_KEY}}this.request(d)},respondToReadyState:function(b){var g=Ajax.Request.Events[b],d=new Ajax.Response(this);if(g=="Complete"){try{this._complete=true;if(d.responseText.isJSON()){var f=d.responseText.evalJSON();if(f.ajaxExpired&&f.ajaxRedirect){window.location.replace(f.ajaxRedirect);throw new SessionError("session expired")}}(this.options["on"+d.status]||this.options["on"+(this.success()?"Success":"Failure")]||Prototype.emptyFunction)(d,d.headerJSON)}catch(h){this.dispatchException(h);if(h instanceof SessionError){return}}var l=d.getHeader("Content-type");if(this.options.evalJS=="force"||(this.options.evalJS&&this.isSameOrigin()&&l&&l.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))){this.evalResponse()}}try{(this.options["on"+g]||Prototype.emptyFunction)(d,d.headerJSON);Ajax.Responders.dispatch("on"+g,this,d,d.headerJSON)}catch(h){this.dispatchException(h)}if(g=="Complete"){this.transport.onreadystatechange=Prototype.emptyFunction}}});Ajax.Updater.respondToReadyState=Ajax.Request.respondToReadyState;var varienLoader=new Class.create();varienLoader.prototype={initialize:function(b){this.callback=false;this.cache=$H();this.caching=b||false;this.url=false},getCache:function(b){if(this.cache.get(b)){return this.cache.get(b)}return false},load:function(b,d,f){this.url=b;this.callback=f;if(this.caching){var e=this.getCache(b);if(e){this.processResult(e);return}}if(typeof(d.updaterId)!="undefined"){new varienUpdater(d.updaterId,b,{evalScripts:true,onComplete:this.processResult.bind(this),onFailure:this._processFailure.bind(this)})}else{new Ajax.Request(b,{method:"post",parameters:d||{},onComplete:this.processResult.bind(this),onFailure:this._processFailure.bind(this)})}},_processFailure:function(b){location.href=BASE_URL},processResult:function(b){if(this.caching){this.cache.set(this.url,b)}if(this.callback){this.callback(b.responseText)}}};if(!window.varienLoaderHandler){var varienLoaderHandler=new Object()}varienLoaderHandler.handler={onCreate:function(b){if(b.options.loaderArea===false){return}jQuery("body").trigger("processStart")},onException:function(b){jQuery("body").trigger("processStop")},onComplete:function(b){jQuery("body").trigger("processStop")}};function setLoaderPosition(){var e=$("loading_mask_loader");if(e&&Prototype.Browser.IE){var d=e.getDimensions();var f=document.viewport.getDimensions();var b=document.viewport.getScrollOffsets();e.style.left=Math.floor(f.width/2+b.left-d.width/2)+"px";e.style.top=Math.floor(f.height/2+b.top-d.height/2)+"px";e.style.position="absolute"}}function toggleSelectsUnderBlock(f,b){if(Prototype.Browser.IE){var e=document.getElementsByTagName("select");for(var d=0;d<e.length;d++){if(b){if(e[d].needShowOnSuccess){e[d].needShowOnSuccess=false;e[d].style.visibility=""}}else{if(Element.visible(e[d])){e[d].style.visibility="hidden";e[d].needShowOnSuccess=true}}}}}Ajax.Responders.register(varienLoaderHandler.handler);var varienUpdater=Class.create(Ajax.Updater,{updateContent:function($super,b){if(b.isJSON()){var d=b.evalJSON();if(d.ajaxExpired&&d.ajaxRedirect){window.location.replace(d.ajaxRedirect)}}else{$super(b)}}});function setLocation(b){window.location.href=b}function confirmSetLocation(d,b){if(confirm(d)){setLocation(b)}return false}function deleteConfirm(d,b){confirmSetLocation(d,b)}function setElementDisable(d,b){if($(d)){$(d).disabled=b}}function toggleParentVis(b){b=$(b).parentNode;if(b.style.display=="none"){b.style.display=""}else{b.style.display="none"}}function toggleFieldsetVis(d){id=d;d=$(d);if(d.style.display=="none"){d.style.display=""}else{d.style.display="none"}d=d.parentNode.childElements();for(var b=0;b<d.length;b++){if(d[b].id!=undefined&&d[b].id==id&&d[(b-1)].classNames()=="entry-edit-head"){if(d[b-1].style.display=="none"){d[b-1].style.display=""}else{d[b-1].style.display="none"}}}}function toggleVis(b){b=$(b);if(b.style.display=="none"){b.style.display=""}else{b.style.display="none"}}function imagePreview(b){if($(b)){var d=window.open("","preview","width=400,height=400,resizable=1,scrollbars=1");d.document.open();d.document.write('<body style="padding:0;margin:0"><img src="'+$(b).src+'" id="image_preview"/></body>');d.document.close();Event.observe(d,"load",function(){var e=d.document.getElementById("image_preview");d.resizeTo(e.width+40,e.height+80)})}}function checkByProductPriceType(b){if(b.id=="price_type"){this.productPriceType=b.value;return false}else{if(b.id=="price"&&this.productPriceType==0){return false}return true}}Event.observe(window,"load",function(){if($("price_default")&&$("price_default").checked){$("price").disabled="disabled"}});function toggleSeveralValueElements(f,e,b,d){if(e&&f){if(Object.prototype.toString.call(e)!="[object Array]"){e=[e]}e.each(function(g){toggleValueElements(f,g,b,d)})}}function toggleValueElements(l,d,f,h){if(d&&l){var n=[l];if(typeof f!="undefined"){if(Object.prototype.toString.call(f)!="[object Array]"){f=[f]}for(var g=0;g<f.length;g++){n.push(f[g])}}var e=Element.select(d,["select","input","textarea","button","img"]).filter(function(o){return(o.readAttribute("type")!="hidden")});var b=(h!=undefined?h:l.checked);e.each(function(p){if(checkByProductPriceType(p)){var o=n.length;while(o--&&p!=n[o]){}if(o!=-1){return}p.disabled=b;if(b){p.addClassName("disabled")}else{p.removeClassName("disabled")}if(p.nodeName.toLowerCase()=="img"){b?p.hide():p.show()}}})}}function submitAndReloadArea(e,d){if($(e)){var b=$(e).select("input","select","textarea");var f=Form.serializeElements(b,true);d=d+(d.match(new RegExp("\\?"))?"&isAjax=true":"?isAjax=true");new Ajax.Request(d,{parameters:$H(f),loaderArea:e,onSuccess:function(l){try{if(l.responseText.isJSON()){var g=l.responseText.evalJSON();if(g.error){alert(g.message)}if(g.ajaxExpired&&g.ajaxRedirect){setLocation(g.ajaxRedirect)}}else{$(e).update(l.responseText)}}catch(h){$(e).update(l.responseText)}}})}}function syncOnchangeValue(d,e){var b={baseElem:d,distElem:e};Event.observe(d,"change",function(){if($(this.baseElem)&&$(this.distElem)){$(this.distElem).value=$(this.baseElem).value}}.bind(b))}function updateElementAtCursor(e,f,g){if(g==undefined){g=window.self}if(document.selection){e.focus();sel=g.document.selection.createRange();sel.text=f}else{if(e.selectionStart||e.selectionStart=="0"){var d=e.selectionStart;var b=e.selectionEnd;e.value=e.value.substring(0,d)+f+e.value.substring(b,e.value.length)}else{e.value+=f}}}function firebugEnabled(){if(window.console&&window.console.firebug){return true}return false}function disableElement(b){b.disabled=true;b.addClassName("disabled")}function enableElement(b){b.disabled=false;b.removeClassName("disabled")}function disableElements(b){$$("."+b).each(disableElement)}function enableElements(b){$$("."+b).each(enableElement)}var Cookie={all:function(){var d=document.cookie.split(";");var b={};d.each(function(f,e){var g=f.strip().split("=");b[unescape(g[0])]=unescape(g[1])});return b},read:function(d){var b=this.all();if(b[d]){return b[d]}return null},write:function(h,f,g){var b="";if(g){var e=new Date();e.setTime(e.getTime()+(g*1000));b="; expires="+e.toGMTString()}var d="/"+BASE_URL.split("/").slice(3).join("/");document.cookie=escape(h)+"="+escape(f)+b+"; path="+d},clear:function(b){this.write(b,"",-1)}};var Fieldset={cookiePrefix:"fh-",applyCollapse:function(b){if($(b+"-state")){collapsed=$(b+"-state").value==1?0:1}else{collapsed=$(b+"-head").collapsed}if(collapsed==1||collapsed===undefined){$(b+"-head").removeClassName("open");if($(b+"-head").up(".section-config")){$(b+"-head").up(".section-config").removeClassName("active")}$(b).hide()}else{$(b+"-head").addClassName("open");if($(b+"-head").up(".section-config")){$(b+"-head").up(".section-config").addClassName("active")}$(b).show()}},toggleCollapse:function(b,d){if($(b+"-state")){collapsed=$(b+"-state").value==1?0:1}else{collapsed=$(b+"-head").collapsed}if(collapsed==1||collapsed===undefined){if($(b+"-state")){$(b+"-state").value=1}$(b+"-head").collapsed=0}else{if($(b+"-state")){$(b+"-state").value=0}$(b+"-head").collapsed=1}this.applyCollapse(b);if(typeof d!="undefined"){this.saveState(d,{container:b,value:$(b+"-state").value})}},addToPrefix:function(b){this.cookiePrefix+=b+"-"},saveState:function(b,d){new Ajax.Request(b,{method:"get",parameters:Object.toQueryString(d),loaderArea:false})}};var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(e){var b="";var p,n,h,o,l,g,f;var d=0;if(typeof window.btoa==="function"){return window.btoa(e)}e=Base64._utf8_encode(e);while(d<e.length){p=e.charCodeAt(d++);n=e.charCodeAt(d++);h=e.charCodeAt(d++);o=p>>2;l=((p&3)<<4)|(n>>4);g=((n&15)<<2)|(h>>6);f=h&63;if(isNaN(n)){g=f=64}else{if(isNaN(h)){f=64}}b=b+this._keyStr.charAt(o)+this._keyStr.charAt(l)+this._keyStr.charAt(g)+this._keyStr.charAt(f)}return b},decode:function(e){var b="";var p,n,h;var o,l,g,f;var d=0;if(typeof window.atob==="function"){return window.atob(e)}e=e.replace(/[^A-Za-z0-9\+\/\=]/g,"");while(d<e.length){o=this._keyStr.indexOf(e.charAt(d++));l=this._keyStr.indexOf(e.charAt(d++));g=this._keyStr.indexOf(e.charAt(d++));f=this._keyStr.indexOf(e.charAt(d++));p=(o<<2)|(l>>4);n=((l&15)<<4)|(g>>2);h=((g&3)<<6)|f;b=b+String.fromCharCode(p);if(g!=64){b=b+String.fromCharCode(n)}if(f!=64){b=b+String.fromCharCode(h)}}b=Base64._utf8_decode(b);return b},mageEncode:function(b){return this.encode(b).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,",")},mageDecode:function(b){b=b.replace(/\-/g,"+").replace(/_/g,"/").replace(/,/g,"=");return this.decode(b)},idEncode:function(b){return this.encode(b).replace(/\+/g,":").replace(/\//g,"_").replace(/=/g,"-")},idDecode:function(b){b=b.replace(/\-/g,"=").replace(/_/g,"/").replace(/\:/g,"+");return this.decode(b)},_utf8_encode:function(d){d=d.replace(/\r\n/g,"\n");var b="";for(var f=0;f<d.length;f++){var e=d.charCodeAt(f);if(e<128){b+=String.fromCharCode(e)}else{if((e>127)&&(e<2048)){b+=String.fromCharCode((e>>6)|192);b+=String.fromCharCode((e&63)|128)}else{b+=String.fromCharCode((e>>12)|224);b+=String.fromCharCode(((e>>6)&63)|128);b+=String.fromCharCode((e&63)|128)}}}return b},_utf8_decode:function(b){var d="";var e=0;var f=c1=c2=0;while(e<b.length){f=b.charCodeAt(e);if(f<128){d+=String.fromCharCode(f);e++}else{if((f>191)&&(f<224)){c2=b.charCodeAt(e+1);d+=String.fromCharCode(((f&31)<<6)|(c2&63));e+=2}else{c2=b.charCodeAt(e+1);c3=b.charCodeAt(e+2);d+=String.fromCharCode(((f&15)<<12)|((c2&63)<<6)|(c3&63));e+=3}}}return d}};function sortNumeric(d,b){return d-b}(function(){var globals=["Prototype","Abstract","Try","Class","PeriodicalExecuter","Template","$break","Enumerable","$A","$w","$H","Hash","$R","ObjectRange","Ajax","$","Form","Field","$F","Toggle","Insertion","$continue","Position","Windows","Dialog","array","WindowUtilities","Builder","Effect","validateCreditCard","Validator","Validation","removeDelimiters","parseNumber","popWin","setLocation","setPLocation","setLanguageCode","decorateGeneric","decorateTable","decorateList","decorateDataList","parseSidUrl","formatCurrency","expandDetails","isIE","Varien","fireEvent","modulo","byteConvert","SessionError","varienLoader","varienLoaderHandler","setLoaderPosition","toggleSelectsUnderBlock","varienUpdater","confirmSetLocation","deleteConfirm","setElementDisable","toggleParentVis","toggleFieldsetVis","toggleVis","imagePreview","checkByProductPriceType","toggleSeveralValueElements","toggleValueElements","submitAndReloadArea","syncOnchangeValue","updateElementAtCursor","firebugEnabled","disableElement","enableElement","disableElements","enableElements","Cookie","Fieldset","Base64","sortNumeric","Element","$$","Sizzle","Selector","Window"];globals.forEach(function(prop){window[prop]=eval(prop)})})(); \ No newline at end of file +(function(){var w=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,p=0,g=Object.prototype.toString,u=false,o=true;[0,0].sort(function(){o=false;return 0});var d=function(L,B,I,D){I=I||[];var e=B=B||document;if(B.nodeType!==1&&B.nodeType!==9){return[]}if(!L||typeof L!=="string"){return I}var J=[],K,G,P,O,H,A,z=true,E=v(B),N=L;while((w.exec(""),K=w.exec(N))!==null){N=K[3];J.push(K[1]);if(K[2]){A=K[3];break}}if(J.length>1&&q.exec(L)){if(J.length===2&&h.relative[J[0]]){G=l(J[0]+J[1],B)}else{G=h.relative[J[0]]?[B]:d(J.shift(),B);while(J.length){L=J.shift();if(h.relative[L]){L+=J.shift()}G=l(L,G)}}}else{if(!D&&J.length>1&&B.nodeType===9&&!E&&h.match.ID.test(J[0])&&!h.match.ID.test(J[J.length-1])){var Q=d.find(J.shift(),B,E);B=Q.expr?d.filter(Q.expr,Q.set)[0]:Q.set[0]}if(B){var Q=D?{expr:J.pop(),set:b(D)}:d.find(J.pop(),J.length===1&&(J[0]==="~"||J[0]==="+")&&B.parentNode?B.parentNode:B,E);G=Q.expr?d.filter(Q.expr,Q.set):Q.set;if(J.length>0){P=b(G)}else{z=false}while(J.length){var C=J.pop(),F=C;if(!h.relative[C]){C=""}else{F=J.pop()}if(F==null){F=B}h.relative[C](P,F,E)}}else{P=J=[]}}if(!P){P=G}if(!P){throw"Syntax error, unrecognized expression: "+(C||L)}if(g.call(P)==="[object Array]"){if(!z){I.push.apply(I,P)}else{if(B&&B.nodeType===1){for(var M=0;P[M]!=null;M++){if(P[M]&&(P[M]===true||P[M].nodeType===1&&n(B,P[M]))){I.push(G[M])}}}else{for(var M=0;P[M]!=null;M++){if(P[M]&&P[M].nodeType===1){I.push(G[M])}}}}}else{b(P,I)}if(A){d(A,e,I,D);d.uniqueSort(I)}return I};d.uniqueSort=function(z){if(f){u=o;z.sort(f);if(u){for(var e=1;e<z.length;e++){if(z[e]===z[e-1]){z.splice(e--,1)}}}}return z};d.matches=function(e,z){return d(e,null,null,z)};d.find=function(F,e,G){var E,C;if(!F){return[]}for(var B=0,A=h.order.length;B<A;B++){var D=h.order[B],C;if((C=h.leftMatch[D].exec(F))){var z=C[1];C.splice(1,1);if(z.substr(z.length-1)!=="\\"){C[1]=(C[1]||"").replace(/\\/g,"");E=h.find[D](C,e,G);if(E!=null){F=F.replace(h.match[D],"");break}}}}if(!E){E=e.getElementsByTagName("*")}return{set:E,expr:F}};d.filter=function(I,H,L,B){var A=I,N=[],F=H,D,e,E=H&&H[0]&&v(H[0]);while(I&&H.length){for(var G in h.filter){if((D=h.match[G].exec(I))!=null){var z=h.filter[G],M,K;e=false;if(F==N){N=[]}if(h.preFilter[G]){D=h.preFilter[G](D,F,L,N,B,E);if(!D){e=M=true}else{if(D===true){continue}}}if(D){for(var C=0;(K=F[C])!=null;C++){if(K){M=z(K,D,C,F);var J=B^!!M;if(L&&M!=null){if(J){e=true}else{F[C]=false}}else{if(J){N.push(K);e=true}}}}}if(M!==undefined){if(!L){F=N}I=I.replace(h.match[G],"");if(!e){return[]}break}}}if(I==A){if(e==null){throw"Syntax error, unrecognized expression: "+I}else{break}}A=I}return F};var h=d.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(e){return e.getAttribute("href")}},relative:{"+":function(F,e,E){var C=typeof e==="string",G=C&&!/\W/.test(e),D=C&&!G;if(G&&!E){e=e.toUpperCase()}for(var B=0,A=F.length,z;B<A;B++){if((z=F[B])){while((z=z.previousSibling)&&z.nodeType!==1){}F[B]=D||z&&z.nodeName===e?z||false:z===e}}if(D){d.filter(e,F,true)}},">":function(E,z,F){var C=typeof z==="string";if(C&&!/\W/.test(z)){z=F?z:z.toUpperCase();for(var A=0,e=E.length;A<e;A++){var D=E[A];if(D){var B=D.parentNode;E[A]=B.nodeName===z?B:false}}}else{for(var A=0,e=E.length;A<e;A++){var D=E[A];if(D){E[A]=C?D.parentNode:D.parentNode===z}}if(C){d.filter(z,E,true)}}},"":function(B,z,D){var A=p++,e=y;if(!/\W/.test(z)){var C=z=D?z:z.toUpperCase();e=t}e("parentNode",z,A,B,C,D)},"~":function(B,z,D){var A=p++,e=y;if(typeof z==="string"&&!/\W/.test(z)){var C=z=D?z:z.toUpperCase();e=t}e("previousSibling",z,A,B,C,D)}},find:{ID:function(z,A,B){if(typeof A.getElementById!=="undefined"&&!B){var e=A.getElementById(z[1]);return e?[e]:[]}},NAME:function(A,D,E){if(typeof D.getElementsByName!=="undefined"){var z=[],C=D.getElementsByName(A[1]);for(var B=0,e=C.length;B<e;B++){if(C[B].getAttribute("name")===A[1]){z.push(C[B])}}return z.length===0?null:z}},TAG:function(e,z){return z.getElementsByTagName(e[1])}},preFilter:{CLASS:function(B,z,A,e,E,F){B=" "+B[1].replace(/\\/g,"")+" ";if(F){return B}for(var C=0,D;(D=z[C])!=null;C++){if(D){if(E^(D.className&&(" "+D.className+" ").indexOf(B)>=0)){if(!A){e.push(D)}}else{if(A){z[C]=false}}}}return false},ID:function(e){return e[1].replace(/\\/g,"")},TAG:function(z,e){for(var A=0;e[A]===false;A++){}return e[A]&&v(e[A])?z[1]:z[1].toUpperCase()},CHILD:function(e){if(e[1]=="nth"){var z=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(e[2]=="even"&&"2n"||e[2]=="odd"&&"2n+1"||!/\D/.test(e[2])&&"0n+"+e[2]||e[2]);e[2]=(z[1]+(z[2]||1))-0;e[3]=z[3]-0}e[0]=p++;return e},ATTR:function(C,z,A,e,D,E){var B=C[1].replace(/\\/g,"");if(!E&&h.attrMap[B]){C[1]=h.attrMap[B]}if(C[2]==="~="){C[4]=" "+C[4]+" "}return C},PSEUDO:function(C,z,A,e,D){if(C[1]==="not"){if((w.exec(C[3])||"").length>1||/^\w/.test(C[3])){C[3]=d(C[3],null,null,z)}else{var B=d.filter(C[3],z,A,true^D);if(!A){e.push.apply(e,B)}return false}}else{if(h.match.POS.test(C[0])||h.match.CHILD.test(C[0])){return true}}return C},POS:function(e){e.unshift(true);return e}},filters:{enabled:function(e){return e.disabled===false&&e.type!=="hidden"},disabled:function(e){return e.disabled===true},checked:function(e){return e.checked===true},selected:function(e){e.parentNode.selectedIndex;return e.selected===true},parent:function(e){return !!e.firstChild},empty:function(e){return !e.firstChild},has:function(A,z,e){return !!d(e[3],A).length},header:function(e){return/h\d/i.test(e.nodeName)},text:function(e){return"text"===e.type},radio:function(e){return"radio"===e.type},checkbox:function(e){return"checkbox"===e.type},file:function(e){return"file"===e.type},password:function(e){return"password"===e.type},submit:function(e){return"submit"===e.type},image:function(e){return"image"===e.type},reset:function(e){return"reset"===e.type},button:function(e){return"button"===e.type||e.nodeName.toUpperCase()==="BUTTON"},input:function(e){return/input|select|textarea|button/i.test(e.nodeName)}},setFilters:{first:function(z,e){return e===0},last:function(A,z,e,B){return z===B.length-1},even:function(z,e){return e%2===0},odd:function(z,e){return e%2===1},lt:function(A,z,e){return z<e[3]-0},gt:function(A,z,e){return z>e[3]-0},nth:function(A,z,e){return e[3]-0==z},eq:function(A,z,e){return e[3]-0==z}},filter:{PSEUDO:function(E,A,B,F){var z=A[1],C=h.filters[z];if(C){return C(E,B,A,F)}else{if(z==="contains"){return(E.textContent||E.innerText||"").indexOf(A[3])>=0}else{if(z==="not"){var D=A[3];for(var B=0,e=D.length;B<e;B++){if(D[B]===E){return false}}return true}}}},CHILD:function(e,B){var E=B[1],z=e;switch(E){case"only":case"first":while((z=z.previousSibling)){if(z.nodeType===1){return false}}if(E=="first"){return true}z=e;case"last":while((z=z.nextSibling)){if(z.nodeType===1){return false}}return true;case"nth":var A=B[2],H=B[3];if(A==1&&H==0){return true}var D=B[0],G=e.parentNode;if(G&&(G.sizcache!==D||!e.nodeIndex)){var C=0;for(z=G.firstChild;z;z=z.nextSibling){if(z.nodeType===1){z.nodeIndex=++C}}G.sizcache=D}var F=e.nodeIndex-H;if(A==0){return F==0}else{return(F%A==0&&F/A>=0)}}},ID:function(z,e){return z.nodeType===1&&z.getAttribute("id")===e},TAG:function(z,e){return(e==="*"&&z.nodeType===1)||z.nodeName===e},CLASS:function(z,e){return(" "+(z.className||z.getAttribute("class"))+" ").indexOf(e)>-1},ATTR:function(D,B){var A=B[1],e=h.attrHandle[A]?h.attrHandle[A](D):D[A]!=null?D[A]:D.getAttribute(A),E=e+"",C=B[2],z=B[4];return e==null?C==="!=":C==="="?E===z:C==="*="?E.indexOf(z)>=0:C==="~="?(" "+E+" ").indexOf(z)>=0:!z?E&&e!==false:C==="!="?E!=z:C==="^="?E.indexOf(z)===0:C==="$="?E.substr(E.length-z.length)===z:C==="|="?E===z||E.substr(0,z.length+1)===z+"-":false},POS:function(C,z,A,D){var e=z[2],B=h.setFilters[e];if(B){return B(C,A,z,D)}}}};var q=h.match.POS;for(var s in h.match){h.match[s]=new RegExp(h.match[s].source+/(?![^\[]*\])(?![^\(]*\))/.source);h.leftMatch[s]=new RegExp(/(^(?:.|\r|\n)*?)/.source+h.match[s].source)}var b=function(z,e){z=Array.prototype.slice.call(z,0);if(e){e.push.apply(e,z);return e}return z};try{Array.prototype.slice.call(document.documentElement.childNodes,0)}catch(r){b=function(C,B){var z=B||[];if(g.call(C)==="[object Array]"){Array.prototype.push.apply(z,C)}else{if(typeof C.length==="number"){for(var A=0,e=C.length;A<e;A++){z.push(C[A])}}else{for(var A=0;C[A];A++){z.push(C[A])}}}return z}}var f;if(document.documentElement.compareDocumentPosition){f=function(z,e){if(!z.compareDocumentPosition||!e.compareDocumentPosition){if(z==e){u=true}return 0}var A=z.compareDocumentPosition(e)&4?-1:z===e?0:1;if(A===0){u=true}return A}}else{if("sourceIndex" in document.documentElement){f=function(z,e){if(!z.sourceIndex||!e.sourceIndex){if(z==e){u=true}return 0}var A=z.sourceIndex-e.sourceIndex;if(A===0){u=true}return A}}else{if(document.createRange){f=function(B,z){if(!B.ownerDocument||!z.ownerDocument){if(B==z){u=true}return 0}var A=B.ownerDocument.createRange(),e=z.ownerDocument.createRange();A.setStart(B,0);A.setEnd(B,0);e.setStart(z,0);e.setEnd(z,0);var C=A.compareBoundaryPoints(Range.START_TO_END,e);if(C===0){u=true}return C}}}}(function(){var z=document.createElement("div"),A="script"+(new Date).getTime();z.innerHTML="<a name='"+A+"'/>";var e=document.documentElement;e.insertBefore(z,e.firstChild);if(!!document.getElementById(A)){h.find.ID=function(C,D,E){if(typeof D.getElementById!=="undefined"&&!E){var B=D.getElementById(C[1]);return B?B.id===C[1]||typeof B.getAttributeNode!=="undefined"&&B.getAttributeNode("id").nodeValue===C[1]?[B]:undefined:[]}};h.filter.ID=function(D,B){var C=typeof D.getAttributeNode!=="undefined"&&D.getAttributeNode("id");return D.nodeType===1&&C&&C.nodeValue===B}}e.removeChild(z);e=z=null})();(function(){var e=document.createElement("div");e.appendChild(document.createComment(""));if(e.getElementsByTagName("*").length>0){h.find.TAG=function(z,D){var C=D.getElementsByTagName(z[1]);if(z[1]==="*"){var B=[];for(var A=0;C[A];A++){if(C[A].nodeType===1){B.push(C[A])}}C=B}return C}}e.innerHTML="<a href='#'></a>";if(e.firstChild&&typeof e.firstChild.getAttribute!=="undefined"&&e.firstChild.getAttribute("href")!=="#"){h.attrHandle.href=function(z){return z.getAttribute("href",2)}}e=null})();if(document.querySelectorAll){(function(){var e=d,A=document.createElement("div");A.innerHTML="<p class='TEST'></p>";if(A.querySelectorAll&&A.querySelectorAll(".TEST").length===0){return}d=function(E,D,B,C){D=D||document;if(!C&&D.nodeType===9&&!v(D)){try{return b(D.querySelectorAll(E),B)}catch(F){}}return e(E,D,B,C)};for(var z in e){d[z]=e[z]}A=null})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var e=document.createElement("div");e.innerHTML="<div class='test e'></div><div class='test'></div>";if(e.getElementsByClassName("e").length===0){return}e.lastChild.className="e";if(e.getElementsByClassName("e").length===1){return}h.order.splice(1,0,"CLASS");h.find.CLASS=function(z,A,B){if(typeof A.getElementsByClassName!=="undefined"&&!B){return A.getElementsByClassName(z[1])}};e=null})()}function t(z,E,D,I,F,H){var G=z=="previousSibling"&&!H;for(var B=0,A=I.length;B<A;B++){var e=I[B];if(e){if(G&&e.nodeType===1){e.sizcache=D;e.sizset=B}e=e[z];var C=false;while(e){if(e.sizcache===D){C=I[e.sizset];break}if(e.nodeType===1&&!H){e.sizcache=D;e.sizset=B}if(e.nodeName===E){C=e;break}e=e[z]}I[B]=C}}}function y(z,E,D,I,F,H){var G=z=="previousSibling"&&!H;for(var B=0,A=I.length;B<A;B++){var e=I[B];if(e){if(G&&e.nodeType===1){e.sizcache=D;e.sizset=B}e=e[z];var C=false;while(e){if(e.sizcache===D){C=I[e.sizset];break}if(e.nodeType===1){if(!H){e.sizcache=D;e.sizset=B}if(typeof E!=="string"){if(e===E){C=true;break}}else{if(d.filter(E,[e]).length>0){C=e;break}}}e=e[z]}I[B]=C}}}var n=document.compareDocumentPosition?function(z,e){return z.compareDocumentPosition(e)&16}:function(z,e){return z!==e&&(z.contains?z.contains(e):true)};var v=function(e){return e.nodeType===9&&e.documentElement.nodeName!=="HTML"||!!e.ownerDocument&&e.ownerDocument.documentElement.nodeName!=="HTML"};var l=function(e,F){var B=[],C="",D,A=F.nodeType?[F]:F;while((D=h.match.PSEUDO.exec(e))){C+=D[0];e=e.replace(h.match.PSEUDO,"")}e=h.relative[e]?e+"*":e;for(var E=0,z=A.length;E<z;E++){d(e,A[E],B)}return d.filter(C,B)};window.Sizzle=d})();(function(e){var f=Prototype.Selector.extendElements;function b(g,h){return f(e(g,h||document))}function d(h,g){return e.matches(g,[h]).length==1}Prototype.Selector.engine=e;Prototype.Selector.select=b;Prototype.Selector.match=d})(Sizzle);window.Sizzle=Prototype._original_property;delete Prototype._original_property;var Form={reset:function(b){b=$(b);b.reset();return b},serializeElements:function(n,f){if(typeof f!="object"){f={hash:!!f}}else{if(Object.isUndefined(f.hash)){f.hash=true}}var g,l,b=false,h=f.submit,d,e;if(f.hash){e={};d=function(o,p,q){if(p in o){if(!Object.isArray(o[p])){o[p]=[o[p]]}o[p].push(q)}else{o[p]=q}return o}}else{e="";d=function(o,p,q){return o+(o?"&":"")+encodeURIComponent(p)+"="+encodeURIComponent(q)}}return n.inject(e,function(o,p){if(!p.disabled&&p.name){g=p.name;l=$(p).getValue();if(l!=null&&p.type!="file"&&(p.type!="submit"||(!b&&h!==false&&(!h||g==h)&&(b=true)))){o=d(o,g,l)}}return o})}};Form.Methods={serialize:function(d,b){return Form.serializeElements(Form.getElements(d),b)},getElements:function(g){var h=$(g).getElementsByTagName("*"),f,b=[],e=Form.Element.Serializers;for(var d=0;f=h[d];d++){b.push(f)}return b.inject([],function(l,n){if(e[n.tagName.toLowerCase()]){l.push(Element.extend(n))}return l})},getInputs:function(l,e,f){l=$(l);var b=l.getElementsByTagName("input");if(!e&&!f){return $A(b).map(Element.extend)}for(var g=0,n=[],h=b.length;g<h;g++){var d=b[g];if((e&&d.type!=e)||(f&&d.name!=f)){continue}n.push(Element.extend(d))}return n},disable:function(b){b=$(b);Form.getElements(b).invoke("disable");return b},enable:function(b){b=$(b);Form.getElements(b).invoke("enable");return b},findFirstElement:function(d){var e=$(d).getElements().findAll(function(f){return"hidden"!=f.type&&!f.disabled});var b=e.findAll(function(f){return f.hasAttribute("tabIndex")&&f.tabIndex>=0}).sortBy(function(f){return f.tabIndex}).first();return b?b:e.find(function(f){return/^(?:input|select|textarea)$/i.test(f.tagName)})},focusFirstElement:function(d){d=$(d);var b=d.findFirstElement();if(b){b.activate()}return d},request:function(d,b){d=$(d),b=Object.clone(b||{});var f=b.parameters,e=d.readAttribute("action")||"";if(e.blank()){e=window.location.href}b.parameters=d.serialize(true);if(f){if(Object.isString(f)){f=f.toQueryParams()}Object.extend(b.parameters,f)}if(d.hasAttribute("method")&&!b.method){b.method=d.method}return new Ajax.Request(e,b)}};Form.Element={focus:function(b){$(b).focus();return b},select:function(b){$(b).select();return b}};Form.Element.Methods={serialize:function(b){b=$(b);if(!b.disabled&&b.name){var d=b.getValue();if(d!=undefined){var e={};e[b.name]=d;return Object.toQueryString(e)}}return""},getValue:function(b){b=$(b);var d=b.tagName.toLowerCase();return Form.Element.Serializers[d](b)},setValue:function(b,d){b=$(b);var e=b.tagName.toLowerCase();Form.Element.Serializers[e](b,d);return b},clear:function(b){$(b).value="";return b},present:function(b){return $(b).value!=""},activate:function(b){b=$(b);try{b.focus();if(b.select&&(b.tagName.toLowerCase()!="input"||!(/^(?:button|reset|submit)$/i.test(b.type)))){b.select()}}catch(d){}return b},disable:function(b){b=$(b);b.disabled=true;return b},enable:function(b){b=$(b);b.disabled=false;return b}};var Field=Form.Element;var $F=Form.Element.Methods.getValue;Form.Element.Serializers=(function(){function d(n,o){switch(n.type.toLowerCase()){case"checkbox":case"radio":return h(n,o);default:return g(n,o)}}function h(n,o){if(Object.isUndefined(o)){return n.checked?n.value:null}else{n.checked=!!o}}function g(n,o){if(Object.isUndefined(o)){return n.value}else{n.value=o}}function b(p,s){if(Object.isUndefined(s)){return(p.type==="select-one"?e:f)(p)}var o,q,t=!Object.isArray(s);for(var n=0,r=p.length;n<r;n++){o=p.options[n];q=this.optionValue(o);if(t){if(q==s){o.selected=true;return}}else{o.selected=s.include(q)}}}function e(o){var n=o.selectedIndex;return n>=0?l(o.options[n]):null}function f(q){var n,r=q.length;if(!r){return null}for(var p=0,n=[];p<r;p++){var o=q.options[p];if(o.selected){n.push(l(o))}}return n}function l(n){return Element.hasAttribute(n,"value")?n.value:n.text}return{input:d,inputSelector:h,textarea:g,select:b,selectOne:e,selectMany:f,optionValue:l,button:g}})();Abstract.TimedObserver=Class.create(PeriodicalExecuter,{initialize:function($super,b,d,e){$super(e,d);this.element=$(b);this.lastValue=this.getValue()},execute:function(){var b=this.getValue();if(Object.isString(this.lastValue)&&Object.isString(b)?this.lastValue!=b:String(this.lastValue)!=String(b)){this.callback(this.element,b);this.lastValue=b}}});Form.Element.Observer=Class.create(Abstract.TimedObserver,{getValue:function(){return Form.Element.getValue(this.element)}});Form.Observer=Class.create(Abstract.TimedObserver,{getValue:function(){return Form.serialize(this.element)}});Abstract.EventObserver=Class.create({initialize:function(b,d){this.element=$(b);this.callback=d;this.lastValue=this.getValue();if(this.element.tagName.toLowerCase()=="form"){this.registerFormCallbacks()}else{this.registerCallback(this.element)}},onElementEvent:function(){var b=this.getValue();if(this.lastValue!=b){this.callback(this.element,b);this.lastValue=b}},registerFormCallbacks:function(){Form.getElements(this.element).each(this.registerCallback,this)},registerCallback:function(b){if(b.type){switch(b.type.toLowerCase()){case"checkbox":case"radio":Event.observe(b,"click",this.onElementEvent.bind(this));break;default:Event.observe(b,"change",this.onElementEvent.bind(this));break}}}});Form.Element.EventObserver=Class.create(Abstract.EventObserver,{getValue:function(){return Form.Element.getValue(this.element)}});Form.EventObserver=Class.create(Abstract.EventObserver,{getValue:function(){return Form.serialize(this.element)}});(function(){var J={KEY_BACKSPACE:8,KEY_TAB:9,KEY_RETURN:13,KEY_ESC:27,KEY_LEFT:37,KEY_UP:38,KEY_RIGHT:39,KEY_DOWN:40,KEY_DELETE:46,KEY_HOME:36,KEY_END:35,KEY_PAGEUP:33,KEY_PAGEDOWN:34,KEY_INSERT:45,cache:{}};var h=document.documentElement;var K="onmouseenter" in h&&"onmouseleave" in h;var b=function(L){return false};if(window.attachEvent){if(window.addEventListener){b=function(L){return !(L instanceof window.Event)}}else{b=function(L){return true}}}var y;function H(M,L){return M.which?(M.which===L+1):(M.button===L)}var u={0:1,1:4,2:2};function F(M,L){return M.button===u[L]}function I(M,L){switch(L){case 0:return M.which==1&&!M.metaKey;case 1:return M.which==2||(M.which==1&&M.metaKey);case 2:return M.which==3;default:return false}}if(window.attachEvent){if(!window.addEventListener){y=F}else{y=function(M,L){return b(M)?F(M,L):H(M,L)}}}else{if(Prototype.Browser.WebKit){y=I}else{y=H}}function C(L){return y(L,0)}function A(L){return y(L,1)}function t(L){return y(L,2)}function f(N){N=J.extend(N);var M=N.target,L=N.type,O=N.currentTarget;if(O&&O.tagName){if(L==="load"||L==="error"||(L==="click"&&O.tagName.toLowerCase()==="input"&&O.type==="radio")){M=O}}if(M.nodeType==Node.TEXT_NODE){M=M.parentNode}return Element.extend(M)}function v(M,N){var L=J.element(M);if(!N){return L}while(L){if(Object.isElement(L)&&Prototype.Selector.match(L,N)){return Element.extend(L)}L=L.parentNode}}function z(L){return{x:e(L),y:d(L)}}function e(N){var M=document.documentElement,L=document.body||{scrollLeft:0};return N.pageX||(N.clientX+(M.scrollLeft||L.scrollLeft)-(M.clientLeft||0))}function d(N){var M=document.documentElement,L=document.body||{scrollTop:0};return N.pageY||(N.clientY+(M.scrollTop||L.scrollTop)-(M.clientTop||0))}function w(L){J.extend(L);L.preventDefault();L.stopPropagation();L.stopped=true}J.Methods={isLeftClick:C,isMiddleClick:A,isRightClick:t,element:f,findElement:v,pointer:z,pointerX:e,pointerY:d,stop:w};var E=Object.keys(J.Methods).inject({},function(L,M){L[M]=J.Methods[M].methodize();return L});if(window.attachEvent){function o(M){var L;switch(M.type){case"mouseover":case"mouseenter":L=M.fromElement;break;case"mouseout":case"mouseleave":L=M.toElement;break;default:return null}return Element.extend(L)}var B={stopPropagation:function(){this.cancelBubble=true},preventDefault:function(){this.returnValue=false},inspect:function(){return"[object Event]"}};J.extend=function(M,L){if(!M){return false}if(!b(M)){return M}if(M._extendedByPrototype){return M}M._extendedByPrototype=Prototype.emptyFunction;var N=J.pointer(M);Object.extend(M,{target:M.srcElement||L,relatedTarget:o(M),pageX:N.x,pageY:N.y});Object.extend(M,E);Object.extend(M,B);return M}}else{J.extend=Prototype.K}if(window.addEventListener){J.prototype=window.Event.prototype||document.createEvent("HTMLEvents").__proto__;Object.extend(J.prototype,E)}function s(P,O,Q){var N=Element.retrieve(P,"prototype_event_registry");if(Object.isUndefined(N)){g.push(P);N=Element.retrieve(P,"prototype_event_registry",$H())}var L=N.get(O);if(Object.isUndefined(L)){L=[];N.set(O,L)}if(L.pluck("handler").include(Q)){return false}var M;if(O.include(":")){M=function(R){if(Object.isUndefined(R.eventName)){return false}if(R.eventName!==O){return false}J.extend(R,P);Q.call(P,R)}}else{if(!K&&(O==="mouseenter"||O==="mouseleave")){if(O==="mouseenter"||O==="mouseleave"){M=function(S){J.extend(S,P);var R=S.relatedTarget;while(R&&R!==P){try{R=R.parentNode}catch(T){R=P}}if(R===P){return}Q.call(P,S)}}}else{M=function(R){J.extend(R,P);Q.call(P,R)}}}M.handler=Q;L.push(M);return M}function n(){for(var L=0,M=g.length;L<M;L++){J.stopObserving(g[L]);g[L]=null}}var g=[];if(Prototype.Browser.IE){window.attachEvent("onunload",n)}if(Prototype.Browser.WebKit){window.addEventListener("unload",Prototype.emptyFunction,false)}var r=Prototype.K,l={mouseenter:"mouseover",mouseleave:"mouseout"};if(!K){r=function(L){return(l[L]||L)}}function D(O,N,P){O=$(O);var M=s(O,N,P);if(!M){return O}if(N.include(":")){if(O.addEventListener){O.addEventListener("dataavailable",M,false)}else{O.attachEvent("ondataavailable",M);O.attachEvent("onlosecapture",M)}}else{var L=r(N);if(O.addEventListener){O.addEventListener(L,M,false)}else{O.attachEvent("on"+L,M)}}return O}function q(R,O,S){R=$(R);var N=Element.retrieve(R,"prototype_event_registry");if(!N){return R}if(!O){N.each(function(U){var T=U.key;q(R,T)});return R}var P=N.get(O);if(!P){return R}if(!S){P.each(function(T){q(R,O,T.handler)});return R}var Q=P.length,M;while(Q--){if(P[Q].handler===S){M=P[Q];break}}if(!M){return R}if(O.include(":")){if(R.removeEventListener){R.removeEventListener("dataavailable",M,false)}else{R.detachEvent("ondataavailable",M);R.detachEvent("onlosecapture",M)}}else{var L=r(O);if(R.removeEventListener){R.removeEventListener(L,M,false)}else{R.detachEvent("on"+L,M)}}N.set(O,P.without(M));return R}function G(O,N,M,L){O=$(O);if(Object.isUndefined(L)){L=true}if(O==document&&document.createEvent&&!O.dispatchEvent){O=document.documentElement}var P;if(document.createEvent){P=document.createEvent("HTMLEvents");P.initEvent("dataavailable",L,true)}else{P=document.createEventObject();P.eventType=L?"ondataavailable":"onlosecapture"}P.eventName=N;P.memo=M||{};if(document.createEvent){O.dispatchEvent(P)}else{O.fireEvent(P.eventType,P)}return J.extend(P)}J.Handler=Class.create({initialize:function(N,M,L,O){this.element=$(N);this.eventName=M;this.selector=L;this.callback=O;this.handler=this.handleEvent.bind(this)},start:function(){J.observe(this.element,this.eventName,this.handler);return this},stop:function(){J.stopObserving(this.element,this.eventName,this.handler);return this},handleEvent:function(M){var L=J.findElement(M,this.selector);if(L){this.callback.call(this.element,M,L)}}});function p(N,M,L,O){N=$(N);if(Object.isFunction(L)&&Object.isUndefined(O)){O=L,L=null}return new J.Handler(N,M,L,O).start()}Object.extend(J,J.Methods);Object.extend(J,{fire:G,observe:D,stopObserving:q,on:p});Element.addMethods({fire:G,observe:D,stopObserving:q,on:p});Object.extend(document,{fire:G.methodize(),observe:D.methodize(),stopObserving:q.methodize(),on:p.methodize(),loaded:false});if(window.Event){Object.extend(window.Event,J)}else{window.Event=J}})();(function(){var e;function b(){if(document.loaded){return}if(e){window.clearTimeout(e)}document.loaded=true;document.fire("dom:loaded")}function d(){if(document.readyState==="complete"){document.stopObserving("readystatechange",d);b()}}if(document.addEventListener){document.addEventListener("DOMContentLoaded",b,false)}else{document.observe("readystatechange",d);if(window==top){var e=window.setInterval(function(){try{document.documentElement.doScroll("left")}catch(f){return}window.clearInterval(e);b()},5)}}Event.observe(window,"load",b)})();Element.addMethods();Hash.toQueryString=Object.toQueryString;var Toggle={display:Element.toggle};Element.Methods.childOf=Element.Methods.descendantOf;var Insertion={Before:function(b,d){return Element.insert(b,{before:d})},Top:function(b,d){return Element.insert(b,{top:d})},Bottom:function(b,d){return Element.insert(b,{bottom:d})},After:function(b,d){return Element.insert(b,{after:d})}};var $continue=new Error('"throw $continue" is deprecated, use "return" instead');var Position={includeScrollOffsets:false,prepare:function(){this.deltaX=window.pageXOffset||document.documentElement.scrollLeft||document.body.scrollLeft||0;this.deltaY=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0},within:function(d,b,e){if(this.includeScrollOffsets){return this.withinIncludingScrolloffsets(d,b,e)}this.xcomp=b;this.ycomp=e;this.offset=Element.cumulativeOffset(d);return(e>=this.offset[1]&&e<this.offset[1]+d.offsetHeight&&b>=this.offset[0]&&b<this.offset[0]+d.offsetWidth)},withinIncludingScrolloffsets:function(d,b,f){var e=Element.cumulativeScrollOffset(d);this.xcomp=b+e[0]-this.deltaX;this.ycomp=f+e[1]-this.deltaY;this.offset=Element.cumulativeOffset(d);return(this.ycomp>=this.offset[1]&&this.ycomp<this.offset[1]+d.offsetHeight&&this.xcomp>=this.offset[0]&&this.xcomp<this.offset[0]+d.offsetWidth)},overlap:function(d,b){if(!d){return 0}if(d=="vertical"){return((this.offset[1]+b.offsetHeight)-this.ycomp)/b.offsetHeight}if(d=="horizontal"){return((this.offset[0]+b.offsetWidth)-this.xcomp)/b.offsetWidth}},cumulativeOffset:Element.Methods.cumulativeOffset,positionedOffset:Element.Methods.positionedOffset,absolutize:function(b){Position.prepare();return Element.absolutize(b)},relativize:function(b){Position.prepare();return Element.relativize(b)},realOffset:Element.Methods.cumulativeScrollOffset,offsetParent:Element.Methods.getOffsetParent,page:Element.Methods.viewportOffset,clone:function(d,e,b){b=b||{};return Element.clonePosition(e,d,b)}};if(!document.getElementsByClassName){document.getElementsByClassName=function(d){function b(e){return e.blank()?null:"[contains(concat(' ', @class, ' '), ' "+e+" ')]"}d.getElementsByClassName=Prototype.BrowserFeatures.XPath?function(e,g){g=g.toString().strip();var f=/\s/.test(g)?$w(g).map(b).join(""):b(g);return f?document._getElementsByXPath(".//*"+f,e):[]}:function(g,h){h=h.toString().strip();var l=[],n=(/\s/.test(h)?$w(h):null);if(!n&&!h){return l}var e=$(g).getElementsByTagName("*");h=" "+h+" ";for(var f=0,p,o;p=e[f];f++){if(p.className&&(o=" "+p.className+" ")&&(o.include(h)||(n&&n.all(function(q){return !q.toString().blank()&&o.include(" "+q+" ")})))){l.push(Element.extend(p))}}return l};return function(f,e){return $(e||document.body).getElementsByClassName(f)}}(Element.Methods)}Element.ClassNames=Class.create();Element.ClassNames.prototype={initialize:function(b){this.element=$(b)},_each:function(b){this.element.className.split(/\s+/).select(function(d){return d.length>0})._each(b)},set:function(b){this.element.className=b},add:function(b){if(this.include(b)){return}this.set($A(this).concat(b).join(" "))},remove:function(b){if(!this.include(b)){return}this.set($A(this).without(b).join(" "))},toString:function(){return $A(this).join(" ")}};Object.extend(Element.ClassNames.prototype,Enumerable);(function(){window.Selector=Class.create({initialize:function(b){this.expression=b.strip()},findElements:function(b){return Prototype.Selector.select(this.expression,b)},match:function(b){return Prototype.Selector.match(b,this.expression)},toString:function(){return this.expression},inspect:function(){return"#<Selector: "+this.expression+">"}});Object.extend(Selector,{matchElements:function(h,l){var b=Prototype.Selector.match,f=[];for(var e=0,g=h.length;e<g;e++){var d=h[e];if(b(d,l)){f.push(Element.extend(d))}}return f},findElement:function(h,l,d){d=d||0;var b=0,f;for(var e=0,g=h.length;e<g;e++){f=h[e];if(Prototype.Selector.match(f,l)&&d===b++){return Element.extend(f)}}},findChildElements:function(d,e){var b=e.toArray().join(", ");return Prototype.Selector.select(b,d||document)}})})();var Window=Class.create();Window.keepMultiModalWindow=false;Window.hasEffectLib=(typeof Effect!="undefined");Window.resizeEffectDuration=0.4;Window.prototype={initialize:function(){var e;var d=0;if(arguments.length>0){if(typeof arguments[0]=="string"){e=arguments[0];d=1}else{e=arguments[0]?arguments[0].id:null}}if(!e){e="window_"+new Date().getTime()}if($(e)){alert("Window "+e+" is already registered in the DOM! Make sure you use setDestroyOnClose() or destroyOnClose: true in the constructor")}this.options=Object.extend({className:"dialog",windowClassName:null,blurClassName:null,minWidth:100,minHeight:20,resizable:true,closable:true,minimizable:true,maximizable:true,draggable:true,userData:null,showEffect:(Window.hasEffectLib?Effect.Appear:Element.show),hideEffect:(Window.hasEffectLib?Effect.Fade:Element.hide),showEffectOptions:{},hideEffectOptions:{},effectOptions:null,parent:document.body,title:" ",url:null,onload:Prototype.emptyFunction,width:200,height:300,opacity:1,recenterAuto:true,wiredDrag:false,closeOnEsc:true,closeCallback:null,destroyOnClose:false,gridX:1,gridY:1},arguments[d]||{});if(this.options.blurClassName){this.options.focusClassName=this.options.className}if(typeof this.options.top=="undefined"&&typeof this.options.bottom=="undefined"){this.options.top=this._round(Math.random()*500,this.options.gridY)}if(typeof this.options.left=="undefined"&&typeof this.options.right=="undefined"){this.options.left=this._round(Math.random()*500,this.options.gridX)}if(this.options.effectOptions){Object.extend(this.options.hideEffectOptions,this.options.effectOptions);Object.extend(this.options.showEffectOptions,this.options.effectOptions);if(this.options.showEffect==Element.Appear){this.options.showEffectOptions.to=this.options.opacity}}if(Window.hasEffectLib){if(this.options.showEffect==Effect.Appear){this.options.showEffectOptions.to=this.options.opacity}if(this.options.hideEffect==Effect.Fade){this.options.hideEffectOptions.from=this.options.opacity}}if(this.options.hideEffect==Element.hide){this.options.hideEffect=function(){Element.hide(this.element);if(this.options.destroyOnClose){this.destroy()}}.bind(this)}if(this.options.parent!=document.body){this.options.parent=$(this.options.parent)}this.element=this._createWindow(e);this.element.win=this;this.eventMouseDown=this._initDrag.bindAsEventListener(this);this.eventMouseUp=this._endDrag.bindAsEventListener(this);this.eventMouseMove=this._updateDrag.bindAsEventListener(this);this.eventOnLoad=this._getWindowBorderSize.bindAsEventListener(this);this.eventMouseDownContent=this.toFront.bindAsEventListener(this);this.eventResize=this._recenter.bindAsEventListener(this);this.eventKeyUp=this._keyUp.bindAsEventListener(this);this.topbar=$(this.element.id+"_top");this.bottombar=$(this.element.id+"_bottom");this.content=$(this.element.id+"_content");Event.observe(this.topbar,"mousedown",this.eventMouseDown);Event.observe(this.bottombar,"mousedown",this.eventMouseDown);Event.observe(this.content,"mousedown",this.eventMouseDownContent);Event.observe(window,"load",this.eventOnLoad);Event.observe(window,"resize",this.eventResize);Event.observe(window,"scroll",this.eventResize);Event.observe(document,"keyup",this.eventKeyUp);Event.observe(this.options.parent,"scroll",this.eventResize);if(this.options.draggable){var b=this;[this.topbar,this.topbar.up().previous(),this.topbar.up().next()].each(function(f){f.observe("mousedown",b.eventMouseDown);f.addClassName("top_draggable")});[this.bottombar.up(),this.bottombar.up().previous(),this.bottombar.up().next()].each(function(f){f.observe("mousedown",b.eventMouseDown);f.addClassName("bottom_draggable")})}if(this.options.resizable){this.sizer=$(this.element.id+"_sizer");Event.observe(this.sizer,"mousedown",this.eventMouseDown)}this.useLeft=null;this.useTop=null;if(typeof this.options.left!="undefined"){this.element.setStyle({left:parseFloat(this.options.left)+"px"});this.useLeft=true}else{this.element.setStyle({right:parseFloat(this.options.right)+"px"});this.useLeft=false}if(typeof this.options.top!="undefined"){this.element.setStyle({top:parseFloat(this.options.top)+"px"});this.useTop=true}else{this.element.setStyle({bottom:parseFloat(this.options.bottom)+"px"});this.useTop=false}this.storedLocation=null;this.setOpacity(this.options.opacity);if(this.options.zIndex){this.setZIndex(this.options.zIndex)}else{this.setZIndex(this.getMaxZIndex())}if(this.options.destroyOnClose){this.setDestroyOnClose(true)}this._getWindowBorderSize();this.width=this.options.width;this.height=this.options.height;this.visible=false;this.constraint=false;this.constraintPad={top:0,left:0,bottom:0,right:0};if(this.width&&this.height){this.setSize(this.options.width,this.options.height)}this.setTitle(this.options.title);Windows.register(this)},getMaxZIndex:function(){var b=0,d;var g=document.body.childNodes;for(d=0;d<g.length;d++){var e=g[d];var f=e.nodeType==1?parseInt(e.style.zIndex,10)||0:0;if(f<10000){b=Math.max(b,f)}}return b+10},destroy:function(){this._notify("onDestroy");Event.stopObserving(this.topbar,"mousedown",this.eventMouseDown);Event.stopObserving(this.bottombar,"mousedown",this.eventMouseDown);Event.stopObserving(this.content,"mousedown",this.eventMouseDownContent);Event.stopObserving(window,"load",this.eventOnLoad);Event.stopObserving(window,"resize",this.eventResize);Event.stopObserving(window,"scroll",this.eventResize);Event.stopObserving(this.content,"load",this.options.onload);Event.stopObserving(document,"keyup",this.eventKeyUp);if(this._oldParent){var e=this.getContent();var b=null;for(var d=0;d<e.childNodes.length;d++){b=e.childNodes[d];if(b.nodeType==1){break}b=null}if(b){this._oldParent.appendChild(b)}this._oldParent=null}if(this.sizer){Event.stopObserving(this.sizer,"mousedown",this.eventMouseDown)}if(this.options.url){this.content.src=null}if(this.iefix){Element.remove(this.iefix)}Element.remove(this.element);Windows.unregister(this)},setCloseCallback:function(b){this.options.closeCallback=b},getContent:function(){return this.content},setContent:function(n,l,e){var b=$(n);if(null==b){throw"Unable to find element '"+n+"' in DOM"}this._oldParent=b.parentNode;var h=null;var g=null;if(l){h=Element.getDimensions(b)}if(e){g=Position.cumulativeOffset(b)}var f=this.getContent();this.setHTMLContent("");f=this.getContent();f.appendChild(b);b.show();if(l){this.setSize(h.width,h.height)}if(e){this.setLocation(g[1]-this.heightN,g[0]-this.widthW)}},setHTMLContent:function(b){if(this.options.url){this.content.src=null;this.options.url=null;var d='<div id="'+this.getId()+'_content" class="'+this.options.className+'_content"> </div>';$(this.getId()+"_table_content").innerHTML=d;this.content=$(this.element.id+"_content")}this.getContent().innerHTML=b},setAjaxContent:function(d,b,f,e){this.showFunction=f?"showCenter":"show";this.showModal=e||false;b=b||{};this.setHTMLContent("");this.onComplete=b.onComplete;if(!this._onCompleteHandler){this._onCompleteHandler=this._setAjaxContent.bind(this)}b.onComplete=this._onCompleteHandler;new Ajax.Request(d,b);b.onComplete=this.onComplete},_setAjaxContent:function(b){Element.update(this.getContent(),b.responseText);if(this.onComplete){this.onComplete(b)}this.onComplete=null;this[this.showFunction](this.showModal)},setURL:function(b){if(this.options.url){this.content.src=null}this.options.url=b;var d="<iframe frameborder='0' name='"+this.getId()+"_content' id='"+this.getId()+"_content' src='"+b+"' width='"+this.width+"' height='"+this.height+"'> </iframe>";$(this.getId()+"_table_content").innerHTML=d;this.content=$(this.element.id+"_content")},getURL:function(){return this.options.url?this.options.url:null},refresh:function(){if(this.options.url){$(this.element.getAttribute("id")+"_content").src=this.options.url}},setCookie:function(d,e,t,g,b){d=d||this.element.id;this.cookie=[d,e,t,g,b];var r=WindowUtilities.getCookie(d);if(r){var s=r.split(",");var p=s[0].split(":");var o=s[1].split(":");var q=parseFloat(s[2]),l=parseFloat(s[3]);var n=s[4];var f=s[5];this.setSize(q,l);if(n=="true"){this.doMinimize=true}else{if(f=="true"){this.doMaximize=true}}this.useLeft=p[0]=="l";this.useTop=o[0]=="t";this.element.setStyle(this.useLeft?{left:p[1]}:{right:p[1]});this.element.setStyle(this.useTop?{top:o[1]}:{bottom:o[1]})}},getId:function(){return this.element.id},setDestroyOnClose:function(){this.options.destroyOnClose=true},setConstraint:function(b,d){this.constraint=b;this.constraintPad=Object.extend(this.constraintPad,d||{});if(this.useTop&&this.useLeft){this.setLocation(parseFloat(this.element.style.top),parseFloat(this.element.style.left))}},_initDrag:function(d){if(Event.element(d)==this.sizer&&this.isMinimized()){return}if(Event.element(d)!=this.sizer&&this.isMaximized()){return}if(Prototype.Browser.IE&&this.heightN==0){this._getWindowBorderSize()}this.pointer=[this._round(Event.pointerX(d),this.options.gridX),this._round(Event.pointerY(d),this.options.gridY)];if(this.options.wiredDrag){this.currentDrag=this._createWiredElement()}else{this.currentDrag=this.element}if(Event.element(d)==this.sizer){this.doResize=true;this.widthOrg=this.width;this.heightOrg=this.height;this.bottomOrg=parseFloat(this.element.getStyle("bottom"));this.rightOrg=parseFloat(this.element.getStyle("right"));this._notify("onStartResize")}else{this.doResize=false;var b=$(this.getId()+"_close");if(b&&Position.within(b,this.pointer[0],this.pointer[1])){this.currentDrag=null;return}this.toFront();if(!this.options.draggable){return}this._notify("onStartMove")}Event.observe(document,"mouseup",this.eventMouseUp,false);Event.observe(document,"mousemove",this.eventMouseMove,false);WindowUtilities.disableScreen("__invisible__","__invisible__",this.overlayOpacity);document.body.ondrag=function(){return false};document.body.onselectstart=function(){return false};this.currentDrag.show();Event.stop(d)},_round:function(d,b){return b==1?d:d=Math.floor(d/b)*b},_updateDrag:function(d){var b=[this._round(Event.pointerX(d),this.options.gridX),this._round(Event.pointerY(d),this.options.gridY)];var q=b[0]-this.pointer[0];var p=b[1]-this.pointer[1];if(this.doResize){var o=this.widthOrg+q;var f=this.heightOrg+p;q=this.width-this.widthOrg;p=this.height-this.heightOrg;if(this.useLeft){o=this._updateWidthConstraint(o)}else{this.currentDrag.setStyle({right:(this.rightOrg-q)+"px"})}if(this.useTop){f=this._updateHeightConstraint(f)}else{this.currentDrag.setStyle({bottom:(this.bottomOrg-p)+"px"})}this.setSize(o,f);this._notify("onResize")}else{this.pointer=b;if(this.useLeft){var e=parseFloat(this.currentDrag.getStyle("left"))+q;var n=this._updateLeftConstraint(e);this.pointer[0]+=n-e;this.currentDrag.setStyle({left:n+"px"})}else{this.currentDrag.setStyle({right:parseFloat(this.currentDrag.getStyle("right"))-q+"px"})}if(this.useTop){var l=parseFloat(this.currentDrag.getStyle("top"))+p;var g=this._updateTopConstraint(l);this.pointer[1]+=g-l;this.currentDrag.setStyle({top:g+"px"})}else{this.currentDrag.setStyle({bottom:parseFloat(this.currentDrag.getStyle("bottom"))-p+"px"})}this._notify("onMove")}if(this.iefix){this._fixIEOverlapping()}this._removeStoreLocation();Event.stop(d)},_endDrag:function(b){WindowUtilities.enableScreen("__invisible__");if(this.doResize){this._notify("onEndResize")}else{this._notify("onEndMove")}Event.stopObserving(document,"mouseup",this.eventMouseUp,false);Event.stopObserving(document,"mousemove",this.eventMouseMove,false);Event.stop(b);this._hideWiredElement();this._saveCookie();document.body.ondrag=null;document.body.onselectstart=null},_updateLeftConstraint:function(d){if(this.constraint&&this.useLeft&&this.useTop){var b=this.options.parent==document.body?WindowUtilities.getPageSize().windowWidth:this.options.parent.getDimensions().width;if(d<this.constraintPad.left){d=this.constraintPad.left}if(d+this.width+this.widthE+this.widthW>b-this.constraintPad.right){d=b-this.constraintPad.right-this.width-this.widthE-this.widthW}}return d},_updateTopConstraint:function(e){if(this.constraint&&this.useLeft&&this.useTop){var b=this.options.parent==document.body?WindowUtilities.getPageSize().windowHeight:this.options.parent.getDimensions().height;var d=this.height+this.heightN+this.heightS;if(e<this.constraintPad.top){e=this.constraintPad.top}if(e+d>b-this.constraintPad.bottom){e=b-this.constraintPad.bottom-d}}return e},_updateWidthConstraint:function(b){if(this.constraint&&this.useLeft&&this.useTop){var d=this.options.parent==document.body?WindowUtilities.getPageSize().windowWidth:this.options.parent.getDimensions().width;var e=parseFloat(this.element.getStyle("left"));if(e+b+this.widthE+this.widthW>d-this.constraintPad.right){b=d-this.constraintPad.right-e-this.widthE-this.widthW}}return b},_updateHeightConstraint:function(d){if(this.constraint&&this.useLeft&&this.useTop){var b=this.options.parent==document.body?WindowUtilities.getPageSize().windowHeight:this.options.parent.getDimensions().height;var e=parseFloat(this.element.getStyle("top"));if(e+d+this.heightN+this.heightS>b-this.constraintPad.bottom){d=b-this.constraintPad.bottom-e-this.heightN-this.heightS}}return d},_createWindow:function(b){var h=this.options.className;var f=document.createElement("div");f.setAttribute("id",b);f.className="dialog";if(this.options.windowClassName){f.className+=" "+this.options.windowClassName}var g;if(this.options.url){g='<iframe frameborder="0" name="'+b+'_content" id="'+b+'_content" src="'+this.options.url+'"> </iframe>'}else{g='<div id="'+b+'_content" class="'+h+'_content"> </div>'}var l=this.options.closable?"<div class='"+h+"_close' id='"+b+"_close' onclick='Windows.close(\""+b+"\", event)'> </div>":"";var n=this.options.minimizable?"<div class='"+h+"_minimize' id='"+b+"_minimize' onclick='Windows.minimize(\""+b+"\", event)'> </div>":"";var o=this.options.maximizable?"<div class='"+h+"_maximize' id='"+b+"_maximize' onclick='Windows.maximize(\""+b+"\", event)'> </div>":"";var e=this.options.resizable?"class='"+h+"_sizer' id='"+b+"_sizer'":"class='"+h+"_se'";var d="../themes/default/blank.gif";f.innerHTML=l+n+o+" <a href='#' id='"+b+"_focus_anchor'><!-- --></a> <table id='"+b+"_row1' class=\"top table_window\"> <tr> <td class='"+h+"_nw'></td> <td class='"+h+"_n'><div id='"+b+"_top' class='"+h+"_title title_window'>"+this.options.title+"</div></td> <td class='"+h+"_ne'></td> </tr> </table> <table id='"+b+"_row2' class=\"mid table_window\"> <tr> <td class='"+h+"_w'></td> <td id='"+b+"_table_content' class='"+h+"_content' valign='top'>"+g+"</td> <td class='"+h+"_e'></td> </tr> </table> <table id='"+b+"_row3' class=\"bot table_window\"> <tr> <td class='"+h+"_sw'></td> <td class='"+h+"_s'><div id='"+b+"_bottom' class='status_bar'><span style='float:left; width:1px; height:1px'></span></div></td> <td "+e+"></td> </tr> </table> ";Element.hide(f);this.options.parent.insertBefore(f,this.options.parent.firstChild);Event.observe($(b+"_content"),"load",this.options.onload);return f},changeClassName:function(b){var d=this.options.className;var e=this.getId();$A(["_close","_minimize","_maximize","_sizer","_content"]).each(function(f){this._toggleClassName($(e+f),d+f,b+f)}.bind(this));this._toggleClassName($(e+"_top"),d+"_title",b+"_title");$$("#"+e+" td").each(function(f){f.className=f.className.sub(d,b)});this.options.className=b},_toggleClassName:function(e,d,b){if(e){e.removeClassName(d);e.addClassName(b)}},setLocation:function(f,d){f=this._updateTopConstraint(f);d=this._updateLeftConstraint(d);var b=this.currentDrag||this.element;b.setStyle({top:f+"px"});b.setStyle({left:d+"px"});this.useLeft=true;this.useTop=true},getLocation:function(){var b={};if(this.useTop){b=Object.extend(b,{top:this.element.getStyle("top")})}else{b=Object.extend(b,{bottom:this.element.getStyle("bottom")})}if(this.useLeft){b=Object.extend(b,{left:this.element.getStyle("left")})}else{b=Object.extend(b,{right:this.element.getStyle("right")})}return b},getSize:function(){return{width:this.width,height:this.height}},setSize:function(f,d,b){f=parseFloat(f);d=parseFloat(d);if(!this.minimized&&f<this.options.minWidth){f=this.options.minWidth}if(!this.minimized&&d<this.options.minHeight){d=this.options.minHeight}if(this.options.maxHeight&&d>this.options.maxHeight){d=this.options.maxHeight}if(this.options.maxWidth&&f>this.options.maxWidth){f=this.options.maxWidth}if(this.useTop&&this.useLeft&&Window.hasEffectLib&&Effect.ResizeWindow&&b){new Effect.ResizeWindow(this,null,null,f,d,{duration:Window.resizeEffectDuration})}else{this.width=f;this.height=d;var h=this.currentDrag?this.currentDrag:this.element;h.setStyle({width:f+this.widthW+this.widthE+"px"});h.setStyle({height:d+this.heightN+this.heightS+"px"});if(!this.currentDrag||this.currentDrag==this.element){var g=$(this.element.id+"_content");g.setStyle({height:d+"px"});g.setStyle({width:f+"px"})}}},updateHeight:function(){this.setSize(this.width,this.content.scrollHeight,true)},updateWidth:function(){this.setSize(this.content.scrollWidth,this.height,true)},toFront:function(){if(this.element.style.zIndex<Windows.maxZIndex){this.setZIndex(Windows.maxZIndex+1)}if(this.iefix){this._fixIEOverlapping()}},getBounds:function(d){if(!this.width||!this.height||!this.visible){this.computeBounds()}var b=this.width;var e=this.height;if(!d){b+=this.widthW+this.widthE;e+=this.heightN+this.heightS}var f=Object.extend(this.getLocation(),{width:b+"px",height:e+"px"});return f},computeBounds:function(){if(!this.width||!this.height){var b=WindowUtilities._computeSize(this.content.innerHTML,this.content.id,this.width,this.height,0,this.options.className);if(this.height){this.width=b+5}else{this.height=b+5}}this.setSize(this.width,this.height);if(this.centered){this._center(this.centerTop,this.centerLeft)}},show:function(d){this.visible=true;if(d){if(typeof this.overlayOpacity=="undefined"){var b=this;setTimeout(function(){b.show(d)},10);return}Windows.addModalWindow(this);this.modal=true;this.setZIndex(Windows.maxZIndex+1);Windows.unsetOverflow(this)}else{if(!this.element.style.zIndex){this.setZIndex(Windows.maxZIndex+1)}}if(this.oldStyle){this.getContent().setStyle({overflow:this.oldStyle})}this.computeBounds();this._notify("onBeforeShow");if(this.options.showEffect!=Element.show&&this.options.showEffectOptions){this.options.showEffect(this.element,this.options.showEffectOptions)}else{this.options.showEffect(this.element)}this._checkIEOverlapping();WindowUtilities.focusedWindow=this;this._notify("onShow");$(this.element.id+"_focus_anchor").focus()},showCenter:function(b,e,d){this.centered=true;this.centerTop=e;this.centerLeft=d;this.show(b)},isVisible:function(){return this.visible},_center:function(e,d){var f=WindowUtilities.getWindowScroll(this.options.parent);var b=WindowUtilities.getPageSize(this.options.parent);if(typeof e=="undefined"){e=(b.windowHeight-(this.height+this.heightN+this.heightS))/2}e+=f.top;if(typeof d=="undefined"){d=(b.windowWidth-(this.width+this.widthW+this.widthE))/2}d+=f.left;this.setLocation(e,d);this.toFront()},_recenter:function(d){if(this.centered){var b=WindowUtilities.getPageSize(this.options.parent);var e=WindowUtilities.getWindowScroll(this.options.parent);if(this.pageSize&&this.pageSize.windowWidth==b.windowWidth&&this.pageSize.windowHeight==b.windowHeight&&this.windowScroll.left==e.left&&this.windowScroll.top==e.top){return}this.pageSize=b;this.windowScroll=e;if($("overlay_modal")){$("overlay_modal").setStyle({height:(b.pageHeight+"px")})}if(this.options.recenterAuto){this._center(this.centerTop,this.centerLeft)}}},hide:function(){this.visible=false;if(this.modal){Windows.removeModalWindow(this);Windows.resetOverflow()}this.oldStyle=this.getContent().getStyle("overflow")||"auto";this.getContent().setStyle({overflow:"hidden"});this.options.hideEffect(this.element,this.options.hideEffectOptions);if(this.iefix){this.iefix.hide()}if(!this.doNotNotifyHide){this._notify("onHide")}},close:function(){if(this.visible){if(this.options.closeCallback&&!this.options.closeCallback(this)){return}if(this.options.destroyOnClose){var b=this.destroy.bind(this);if(this.options.hideEffectOptions.afterFinish){var d=this.options.hideEffectOptions.afterFinish;this.options.hideEffectOptions.afterFinish=function(){d();b()}}else{this.options.hideEffectOptions.afterFinish=function(){b()}}}Windows.updateFocusedWindow();this.doNotNotifyHide=true;this.hide();this.doNotNotifyHide=false;this._notify("onClose")}},minimize:function(){if(this.resizing){return}var b=$(this.getId()+"_row2");if(!this.minimized){this.minimized=true;var f=b.getDimensions().height;this.r2Height=f;var e=this.element.getHeight()-f;if(this.useLeft&&this.useTop&&Window.hasEffectLib&&Effect.ResizeWindow){new Effect.ResizeWindow(this,null,null,null,this.height-f,{duration:Window.resizeEffectDuration})}else{this.height-=f;this.element.setStyle({height:e+"px"});b.hide()}if(!this.useTop){var d=parseFloat(this.element.getStyle("bottom"));this.element.setStyle({bottom:(d+f)+"px"})}}else{this.minimized=false;var f=this.r2Height;this.r2Height=null;if(this.useLeft&&this.useTop&&Window.hasEffectLib&&Effect.ResizeWindow){new Effect.ResizeWindow(this,null,null,null,this.height+f,{duration:Window.resizeEffectDuration})}else{var e=this.element.getHeight()+f;this.height+=f;this.element.setStyle({height:e+"px"});b.show()}if(!this.useTop){var d=parseFloat(this.element.getStyle("bottom"));this.element.setStyle({bottom:(d-f)+"px"})}this.toFront()}this._notify("onMinimize");this._saveCookie()},maximize:function(){if(this.isMinimized()||this.resizing){return}if(Prototype.Browser.IE&&this.heightN==0){this._getWindowBorderSize()}if(this.storedLocation!=null){this._restoreLocation();if(this.iefix){this.iefix.hide()}}else{this._storeLocation();Windows.unsetOverflow(this);var l=WindowUtilities.getWindowScroll(this.options.parent);var d=WindowUtilities.getPageSize(this.options.parent);var h=l.left;var g=l.top;if(this.options.parent!=document.body){l={top:0,left:0,bottom:0,right:0};var f=this.options.parent.getDimensions();d.windowWidth=f.width;d.windowHeight=f.height;g=0;h=0}if(this.constraint){d.windowWidth-=Math.max(0,this.constraintPad.left)+Math.max(0,this.constraintPad.right);d.windowHeight-=Math.max(0,this.constraintPad.top)+Math.max(0,this.constraintPad.bottom);h+=Math.max(0,this.constraintPad.left);g+=Math.max(0,this.constraintPad.top)}var e=d.windowWidth-this.widthW-this.widthE;var b=d.windowHeight-this.heightN-this.heightS;if(this.useLeft&&this.useTop&&Window.hasEffectLib&&Effect.ResizeWindow){new Effect.ResizeWindow(this,g,h,e,b,{duration:Window.resizeEffectDuration})}else{this.setSize(e,b);this.element.setStyle(this.useLeft?{left:h}:{right:h});this.element.setStyle(this.useTop?{top:g}:{bottom:g})}this.toFront();if(this.iefix){this._fixIEOverlapping()}}this._notify("onMaximize");this._saveCookie()},isMinimized:function(){return this.minimized},isMaximized:function(){return(this.storedLocation!=null)},setOpacity:function(b){if(Element.setOpacity){Element.setOpacity(this.element,b)}},setZIndex:function(b){this.element.setStyle({zIndex:b});Windows.updateZindex(b,this)},setTitle:function(b){if(!b||b==""){b=" "}Element.update(this.element.id+"_top",b)},getTitle:function(){return $(this.element.id+"_top").innerHTML},setStatusBar:function(d){var b=$(this.getId()+"_bottom");if(typeof(d)=="object"){if(this.bottombar.firstChild){this.bottombar.replaceChild(d,this.bottombar.firstChild)}else{this.bottombar.appendChild(d)}}else{this.bottombar.innerHTML=d}},_checkIEOverlapping:function(){if(!this.iefix&&(navigator.appVersion.indexOf("MSIE")>0)&&(navigator.userAgent.indexOf("Opera")<0)&&(this.element.getStyle("position")=="absolute")){new Insertion.After(this.element.id,'<iframe id="'+this.element.id+'_iefix" style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" src="javascript:false;" frameborder="0" scrolling="no"></iframe>');this.iefix=$(this.element.id+"_iefix")}if(this.iefix){setTimeout(this._fixIEOverlapping.bind(this),50)}},_fixIEOverlapping:function(){Position.clone(this.element,this.iefix);this.iefix.style.zIndex=this.element.style.zIndex-1;this.iefix.show()},_keyUp:function(b){if(27==b.keyCode&&this.options.closeOnEsc){this.close()}},_getWindowBorderSize:function(d){var e=this._createHiddenDiv(this.options.className+"_n");this.heightN=Element.getDimensions(e).height;e.parentNode.removeChild(e);var e=this._createHiddenDiv(this.options.className+"_s");this.heightS=Element.getDimensions(e).height;e.parentNode.removeChild(e);var e=this._createHiddenDiv(this.options.className+"_e");this.widthE=Element.getDimensions(e).width;e.parentNode.removeChild(e);var e=this._createHiddenDiv(this.options.className+"_w");this.widthW=Element.getDimensions(e).width;e.parentNode.removeChild(e);var e=document.createElement("div");e.className="overlay_"+this.options.className;document.body.appendChild(e);var b=this;setTimeout(function(){b.overlayOpacity=($(e).getStyle("opacity"));e.parentNode.removeChild(e)},10);if(Prototype.Browser.IE){this.heightS=$(this.getId()+"_row3").getDimensions().height;this.heightN=$(this.getId()+"_row1").getDimensions().height}if(Prototype.Browser.WebKit&&Prototype.Browser.WebKitVersion<420){this.setSize(this.width,this.height)}if(this.doMaximize){this.maximize()}if(this.doMinimize){this.minimize()}},_createHiddenDiv:function(d){var b=document.body;var e=document.createElement("div");e.setAttribute("id",this.element.id+"_tmp");e.className=d;e.style.display="none";e.innerHTML="";b.insertBefore(e,b.firstChild);return e},_storeLocation:function(){if(this.storedLocation==null){this.storedLocation={useTop:this.useTop,useLeft:this.useLeft,top:this.element.getStyle("top"),bottom:this.element.getStyle("bottom"),left:this.element.getStyle("left"),right:this.element.getStyle("right"),width:this.width,height:this.height}}},_restoreLocation:function(){if(this.storedLocation!=null){this.useLeft=this.storedLocation.useLeft;this.useTop=this.storedLocation.useTop;if(this.useLeft&&this.useTop&&Window.hasEffectLib&&Effect.ResizeWindow){new Effect.ResizeWindow(this,this.storedLocation.top,this.storedLocation.left,this.storedLocation.width,this.storedLocation.height,{duration:Window.resizeEffectDuration})}else{this.element.setStyle(this.useLeft?{left:this.storedLocation.left}:{right:this.storedLocation.right});this.element.setStyle(this.useTop?{top:this.storedLocation.top}:{bottom:this.storedLocation.bottom});this.setSize(this.storedLocation.width,this.storedLocation.height)}Windows.resetOverflow();this._removeStoreLocation()}},_removeStoreLocation:function(){this.storedLocation=null},_saveCookie:function(){if(this.cookie){var b="";if(this.useLeft){b+="l:"+(this.storedLocation?this.storedLocation.left:this.element.getStyle("left"))}else{b+="r:"+(this.storedLocation?this.storedLocation.right:this.element.getStyle("right"))}if(this.useTop){b+=",t:"+(this.storedLocation?this.storedLocation.top:this.element.getStyle("top"))}else{b+=",b:"+(this.storedLocation?this.storedLocation.bottom:this.element.getStyle("bottom"))}b+=","+(this.storedLocation?this.storedLocation.width:this.width);b+=","+(this.storedLocation?this.storedLocation.height:this.height);b+=","+this.isMinimized();b+=","+this.isMaximized();WindowUtilities.setCookie(b,this.cookie)}},_createWiredElement:function(){if(!this.wiredElement){if(Prototype.Browser.IE){this._getWindowBorderSize()}var d=document.createElement("div");d.className="wired_frame "+this.options.className+"_wired_frame";d.style.position="absolute";this.options.parent.insertBefore(d,this.options.parent.firstChild);this.wiredElement=$(d)}if(this.useLeft){this.wiredElement.setStyle({left:this.element.getStyle("left")})}else{this.wiredElement.setStyle({right:this.element.getStyle("right")})}if(this.useTop){this.wiredElement.setStyle({top:this.element.getStyle("top")})}else{this.wiredElement.setStyle({bottom:this.element.getStyle("bottom")})}var b=this.element.getDimensions();this.wiredElement.setStyle({width:b.width+"px",height:b.height+"px"});this.wiredElement.setStyle({zIndex:Windows.maxZIndex+30});return this.wiredElement},_hideWiredElement:function(){if(!this.wiredElement||!this.currentDrag){return}if(this.currentDrag==this.element){this.currentDrag=null}else{if(this.useLeft){this.element.setStyle({left:this.currentDrag.getStyle("left")})}else{this.element.setStyle({right:this.currentDrag.getStyle("right")})}if(this.useTop){this.element.setStyle({top:this.currentDrag.getStyle("top")})}else{this.element.setStyle({bottom:this.currentDrag.getStyle("bottom")})}this.currentDrag.hide();this.currentDrag=null;if(this.doResize){this.setSize(this.width,this.height)}}},_notify:function(b){if(this.options[b]){this.options[b](this)}else{Windows.notify(b,this)}}};var Windows={windows:[],modalWindows:[],observers:[],focusedWindow:null,maxZIndex:0,overlayShowEffectOptions:{duration:0.5},overlayHideEffectOptions:{duration:0.5},addObserver:function(b){this.removeObserver(b);this.observers.push(b)},removeObserver:function(b){this.observers=this.observers.reject(function(d){return d==b})},notify:function(b,d){this.observers.each(function(e){if(e[b]){e[b](b,d)}})},getWindow:function(b){return this.windows.detect(function(e){return e.getId()==b})},getFocusedWindow:function(){return this.focusedWindow},updateFocusedWindow:function(){this.focusedWindow=this.windows.length>=2?this.windows[this.windows.length-2]:null},register:function(b){this.windows.push(b)},addModalWindow:function(b){if(this.modalWindows.length==0){WindowUtilities.disableScreen(b.options.className,"overlay_modal",b.overlayOpacity,b.getId(),b.options.parent)}else{if(Window.keepMultiModalWindow){$("overlay_modal").style.zIndex=Windows.maxZIndex+1;Windows.maxZIndex+=1;WindowUtilities._hideSelect(this.modalWindows.last().getId())}else{this.modalWindows.last().element.hide()}WindowUtilities._showSelect(b.getId())}this.modalWindows.push(b)},removeModalWindow:function(b){this.modalWindows.pop();if(this.modalWindows.length==0){WindowUtilities.enableScreen()}else{if(Window.keepMultiModalWindow){this.modalWindows.last().toFront();WindowUtilities._showSelect(this.modalWindows.last().getId())}else{this.modalWindows.last().element.show()}}},register:function(b){this.windows.push(b)},unregister:function(b){this.windows=this.windows.reject(function(e){return e==b})},closeAll:function(){this.windows.each(function(b){Windows.close(b.getId())})},closeAllModalWindows:function(){WindowUtilities.enableScreen();this.modalWindows.each(function(b){if(b){b.close()}})},minimize:function(e,b){var d=this.getWindow(e);if(d&&d.visible){d.minimize()}Event.stop(b)},maximize:function(e,b){var d=this.getWindow(e);if(d&&d.visible){d.maximize()}Event.stop(b)},close:function(e,b){var d=this.getWindow(e);if(d){d.close()}if(b){Event.stop(b)}},blur:function(d){var b=this.getWindow(d);if(!b){return}if(b.options.blurClassName){b.changeClassName(b.options.blurClassName)}if(this.focusedWindow==b){this.focusedWindow=null}b._notify("onBlur")},focus:function(d){var b=this.getWindow(d);if(!b){return}if(this.focusedWindow){this.blur(this.focusedWindow.getId())}if(b.options.focusClassName){b.changeClassName(b.options.focusClassName)}this.focusedWindow=b;b._notify("onFocus")},unsetOverflow:function(b){this.windows.each(function(e){e.oldOverflow=e.getContent().getStyle("overflow")||"auto";e.getContent().setStyle({overflow:"hidden"})});if(b&&b.oldOverflow){b.getContent().setStyle({overflow:b.oldOverflow})}},resetOverflow:function(){this.windows.each(function(b){if(b.oldOverflow){b.getContent().setStyle({overflow:b.oldOverflow})}})},updateZindex:function(b,d){if(b>this.maxZIndex){this.maxZIndex=b;if(this.focusedWindow){this.blur(this.focusedWindow.getId())}}this.focusedWindow=d;if(this.focusedWindow){this.focus(this.focusedWindow.getId())}}};var Dialog={dialogId:null,onCompleteFunc:null,callFunc:null,parameters:null,confirm:function(f,e){if(f&&typeof f!="string"){Dialog._runAjaxRequest(f,e,Dialog.confirm);return}f=f||"";e=e||{};var h=e.okLabel?e.okLabel:"Ok";var b=e.cancelLabel?e.cancelLabel:"Cancel";e=Object.extend(e,e.windowParameters||{});e.windowParameters=e.windowParameters||{};e.className=e.className||"alert";var d="class ='"+(e.buttonClass?e.buttonClass+" ":"")+" ok_button'";var g="class ='"+(e.buttonClass?e.buttonClass+" ":"")+" cancel_button'";var f=" <div class='"+e.className+"_message'>"+f+"</div> <div class='"+e.className+"_buttons'> <button type='button' title='"+h+"' onclick='Dialog.okCallback()' "+d+"><span><span><span>"+h+"</span></span></span></button> <button type='button' title='"+b+"' onclick='Dialog.cancelCallback()' "+g+"><span><span><span>"+b+"</span></span></span></button> </div> ";return this._openDialog(f,e)},alert:function(e,d){if(e&&typeof e!="string"){Dialog._runAjaxRequest(e,d,Dialog.alert);return}e=e||"";d=d||{};var f=d.okLabel?d.okLabel:"Ok";d=Object.extend(d,d.windowParameters||{});d.windowParameters=d.windowParameters||{};d.className=d.className||"alert";var b="class ='"+(d.buttonClass?d.buttonClass+" ":"")+" ok_button'";var e=" <div class='"+d.className+"_message'>"+e+"</div> <div class='"+d.className+"_buttons'> <button type='button' title='"+f+"' onclick='Dialog.okCallback()' "+b+"><span><span><span>"+f+"</span></span></span></button> </div>";return this._openDialog(e,d)},info:function(d,b){if(d&&typeof d!="string"){Dialog._runAjaxRequest(d,b,Dialog.info);return}d=d||"";b=b||{};b=Object.extend(b,b.windowParameters||{});b.windowParameters=b.windowParameters||{};b.className=b.className||"alert";var d="<div id='modal_dialog_message' class='"+b.className+"_message'>"+d+"</div>";if(b.showProgress){d+="<div id='modal_dialog_progress' class='"+b.className+"_progress'> </div>"}b.ok=null;b.cancel=null;return this._openDialog(d,b)},setInfoMessage:function(b){$("modal_dialog_message").update(b)},closeInfo:function(){Windows.close(this.dialogId)},_openDialog:function(g,f){var e=f.className;if(!f.height&&!f.width){f.width=WindowUtilities.getPageSize(f.options.parent||document.body).pageWidth/2}if(f.id){this.dialogId=f.id}else{var d=new Date();this.dialogId="modal_dialog_"+d.getTime();f.id=this.dialogId}if(!f.height||!f.width){var b=WindowUtilities._computeSize(g,this.dialogId,f.width,f.height,5,e);if(f.height){f.width=b+5}else{f.height=b+5}}f.effectOptions=f.effectOptions;f.resizable=f.resizable||false;f.minimizable=f.minimizable||false;f.maximizable=f.maximizable||false;f.draggable=f.draggable||false;f.closable=f.closable||false;var h=new Window(f);h.getContent().innerHTML=g;h.showCenter(true,f.top,f.left);h.setDestroyOnClose();h.cancelCallback=f.onCancel||f.cancel;h.okCallback=f.onOk||f.ok;return h},_getAjaxContent:function(b){Dialog.callFunc(b.responseText,Dialog.parameters)},_runAjaxRequest:function(e,d,b){if(e.options==null){e.options={}}Dialog.onCompleteFunc=e.options.onComplete;Dialog.parameters=d;Dialog.callFunc=b;e.options.onComplete=Dialog._getAjaxContent;new Ajax.Request(e.url,e.options)},okCallback:function(){var b=Windows.focusedWindow;if(!b.okCallback||b.okCallback(b)){$$("#"+b.getId()+" input").each(function(d){d.onclick=null});b.close()}},cancelCallback:function(){var b=Windows.focusedWindow;$$("#"+b.getId()+" input").each(function(d){d.onclick=null});b.close();if(b.cancelCallback){b.cancelCallback(b)}}};if(Prototype.Browser.WebKit){var array=navigator.userAgent.match(new RegExp(/AppleWebKit\/([\d\.\+]*)/));Prototype.Browser.WebKitVersion=parseFloat(array[1])}var WindowUtilities={getWindowScroll:function(parent){var T,L,W,H;parent=parent||document.body;if(parent!=document.body){T=parent.scrollTop;L=parent.scrollLeft;W=parent.scrollWidth;H=parent.scrollHeight}else{var w=window;with(w.document){if(w.document.documentElement&&documentElement.scrollTop){T=documentElement.scrollTop;L=documentElement.scrollLeft}else{if(w.document.body){T=body.scrollTop;L=body.scrollLeft}}if(w.innerWidth){W=w.innerWidth;H=w.innerHeight}else{if(w.document.documentElement&&documentElement.clientWidth){W=documentElement.clientWidth;H=documentElement.clientHeight}else{W=body.offsetWidth;H=body.offsetHeight}}}}return{top:T,left:L,width:W,height:H}},getPageSize:function(f){f=f||document.body;var e,l;var g,d;if(f!=document.body){e=f.getWidth();l=f.getHeight();d=f.scrollWidth;g=f.scrollHeight}else{var h,b;if(window.innerHeight&&window.scrollMaxY){h=document.body.scrollWidth;b=window.innerHeight+window.scrollMaxY}else{if(document.body.scrollHeight>document.body.offsetHeight){h=document.body.scrollWidth;b=document.body.scrollHeight}else{h=document.body.offsetWidth;b=document.body.offsetHeight}}if(self.innerHeight){e=document.documentElement.clientWidth;l=self.innerHeight}else{if(document.documentElement&&document.documentElement.clientHeight){e=document.documentElement.clientWidth;l=document.documentElement.clientHeight}else{if(document.body){e=document.body.clientWidth;l=document.body.clientHeight}}}if(b<l){g=l}else{g=b}if(h<e){d=e}else{d=h}}return{pageWidth:d,pageHeight:g,windowWidth:e,windowHeight:l}},disableScreen:function(e,b,f,g,d){WindowUtilities.initLightbox(b,e,function(){this._disableScreen(e,b,f,g)}.bind(this),d||document.body)},_disableScreen:function(e,d,g,h){var f=$(d);var b=WindowUtilities.getPageSize(f.parentNode);if(h&&Prototype.Browser.IE){WindowUtilities._hideSelect();WindowUtilities._showSelect(h)}f.style.height=(b.pageHeight+"px");f.style.display="none";if(d=="overlay_modal"&&Window.hasEffectLib&&Windows.overlayShowEffectOptions){f.overlayOpacity=g;new Effect.Appear(f,Object.extend({from:0,to:g},Windows.overlayShowEffectOptions))}else{f.style.display="block"}},enableScreen:function(d){d=d||"overlay_modal";var b=$(d);if(b){if(d=="overlay_modal"&&Window.hasEffectLib&&Windows.overlayHideEffectOptions){new Effect.Fade(b,Object.extend({from:b.overlayOpacity,to:0},Windows.overlayHideEffectOptions))}else{b.style.display="none";b.parentNode.removeChild(b)}if(d!="__invisible__"){WindowUtilities._showSelect()}}},_hideSelect:function(b){if(Prototype.Browser.IE){b=b==null?"":"#"+b+" ";$$(b+"select").each(function(d){if(!WindowUtilities.isDefined(d.oldVisibility)){d.oldVisibility=d.style.visibility?d.style.visibility:"visible";d.style.visibility="hidden"}})}},_showSelect:function(b){if(Prototype.Browser.IE){b=b==null?"":"#"+b+" ";$$(b+"select").each(function(d){if(WindowUtilities.isDefined(d.oldVisibility)){try{d.style.visibility=d.oldVisibility}catch(f){d.style.visibility="visible"}d.oldVisibility=null}else{if(d.style.visibility){d.style.visibility="visible"}}})}},isDefined:function(b){return typeof(b)!="undefined"&&b!=null},initLightbox:function(g,e,b,d){if($(g)){Element.setStyle(g,{zIndex:Windows.maxZIndex+1});Windows.maxZIndex++;b()}else{var f=document.createElement("div");f.setAttribute("id",g);f.className="overlay_"+e;f.style.display="none";f.style.position="absolute";f.style.top="0";f.style.left="0";f.style.zIndex=Windows.maxZIndex+1;Windows.maxZIndex++;f.style.width="100%";d.insertBefore(f,d.firstChild);if(Prototype.Browser.WebKit&&g=="overlay_modal"){setTimeout(function(){b()},10)}else{b()}}},setCookie:function(d,b){document.cookie=b[0]+"="+escape(d)+((b[1])?"; expires="+b[1].toGMTString():"")+((b[2])?"; path="+b[2]:"")+((b[3])?"; domain="+b[3]:"")+((b[4])?"; secure":"")},getCookie:function(e){var d=document.cookie;var g=e+"=";var f=d.indexOf("; "+g);if(f==-1){f=d.indexOf(g);if(f!=0){return null}}else{f+=2}var b=document.cookie.indexOf(";",f);if(b==-1){b=d.length}return unescape(d.substring(f+g.length,b))},_computeSize:function(g,b,d,l,f,h){var o=document.body;var e=document.createElement("div");e.setAttribute("id",b);e.className=h+"_content";if(l){e.style.height=l+"px"}else{e.style.width=d+"px"}e.style.position="absolute";e.style.top="0";e.style.left="0";e.style.display="none";e.innerHTML=g;o.insertBefore(e,o.firstChild);var n;if(l){n=$(e).getDimensions().width+f}else{n=$(e).getDimensions().height+f}o.removeChild(e);return n}};var Builder={NODEMAP:{AREA:"map",CAPTION:"table",COL:"table",COLGROUP:"table",LEGEND:"fieldset",OPTGROUP:"select",OPTION:"select",PARAM:"object",TBODY:"table",TD:"table",TFOOT:"table",TH:"table",THEAD:"table",TR:"table"},node:function(b){b=b.toUpperCase();var l=this.NODEMAP[b]||"div";var d=document.createElement(l);try{d.innerHTML="<"+b+"></"+b+">"}catch(h){}var g=d.firstChild||null;if(g&&(g.tagName.toUpperCase()!=b)){g=g.getElementsByTagName(b)[0]}if(!g){g=document.createElement(b)}if(!g){return}if(arguments[1]){if(this._isStringOrNumber(arguments[1])||(arguments[1] instanceof Array)||arguments[1].tagName){this._children(g,arguments[1])}else{var f=this._attributes(arguments[1]);if(f.length){try{d.innerHTML="<"+b+" "+f+"></"+b+">"}catch(h){}g=d.firstChild||null;if(!g){g=document.createElement(b);for(attr in arguments[1]){g[attr=="class"?"className":attr]=arguments[1][attr]}}if(g.tagName.toUpperCase()!=b){g=d.getElementsByTagName(b)[0]}}}}if(arguments[2]){this._children(g,arguments[2])}return $(g)},_text:function(b){return document.createTextNode(b)},ATTR_MAP:{className:"class",htmlFor:"for"},_attributes:function(b){var d=[];for(attribute in b){d.push((attribute in this.ATTR_MAP?this.ATTR_MAP[attribute]:attribute)+'="'+b[attribute].toString().escapeHTML().gsub(/"/,""")+'"')}return d.join(" ")},_children:function(d,b){if(b.tagName){d.appendChild(b);return}if(typeof b=="object"){b.flatten().each(function(f){if(typeof f=="object"){d.appendChild(f)}else{if(Builder._isStringOrNumber(f)){d.appendChild(Builder._text(f))}}})}else{if(Builder._isStringOrNumber(b)){d.appendChild(Builder._text(b))}}},_isStringOrNumber:function(b){return(typeof b=="string"||typeof b=="number")},build:function(d){var b=this.node("div");$(b).update(d.strip());return b.down()},dump:function(d){if(typeof d!="object"&&typeof d!="function"){d=window}var b=("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);b.each(function(e){d[e]=function(){return Builder.node.apply(Builder,[e].concat($A(arguments)))}})}};String.prototype.parseColor=function(){var b="#";if(this.slice(0,4)=="rgb("){var e=this.slice(4,this.length-1).split(",");var d=0;do{b+=parseInt(e[d]).toColorPart()}while(++d<3)}else{if(this.slice(0,1)=="#"){if(this.length==4){for(var d=1;d<4;d++){b+=(this.charAt(d)+this.charAt(d)).toLowerCase()}}if(this.length==7){b=this.toLowerCase()}}}return(b.length==7?b:(arguments[0]||this))};Element.collectTextNodes=function(b){return $A($(b).childNodes).collect(function(d){return(d.nodeType==3?d.nodeValue:(d.hasChildNodes()?Element.collectTextNodes(d):""))}).flatten().join("")};Element.collectTextNodesIgnoreClass=function(b,d){return $A($(b).childNodes).collect(function(e){return(e.nodeType==3?e.nodeValue:((e.hasChildNodes()&&!Element.hasClassName(e,d))?Element.collectTextNodesIgnoreClass(e,d):""))}).flatten().join("")};Element.setContentZoom=function(b,d){b=$(b);b.setStyle({fontSize:(d/100)+"em"});if(Prototype.Browser.WebKit){window.scrollBy(0,0)}return b};Element.getInlineOpacity=function(b){return $(b).style.opacity||""};Element.forceRerendering=function(b){try{b=$(b);var f=document.createTextNode(" ");b.appendChild(f);b.removeChild(f)}catch(d){}};var Effect={_elementDoesNotExistError:{name:"ElementDoesNotExistError",message:"The specified DOM element does not exist, but is required for this effect to operate"},Transitions:{linear:Prototype.K,sinoidal:function(b){return(-Math.cos(b*Math.PI)/2)+0.5},reverse:function(b){return 1-b},flicker:function(b){var b=((-Math.cos(b*Math.PI)/4)+0.75)+Math.random()/4;return b>1?1:b},wobble:function(b){return(-Math.cos(b*Math.PI*(9*b))/2)+0.5},pulse:function(d,b){return(-Math.cos((d*((b||5)-0.5)*2)*Math.PI)/2)+0.5},spring:function(b){return 1-(Math.cos(b*4.5*Math.PI)*Math.exp(-b*6))},none:function(b){return 0},full:function(b){return 1}},DefaultOptions:{duration:1,fps:100,sync:false,from:0,to:1,delay:0,queue:"parallel"},tagifyText:function(b){var d="position:relative";if(Prototype.Browser.IE){d+=";zoom:1"}b=$(b);$A(b.childNodes).each(function(e){if(e.nodeType==3){e.nodeValue.toArray().each(function(f){b.insertBefore(new Element("span",{style:d}).update(f==" "?String.fromCharCode(160):f),e)});Element.remove(e)}})},multiple:function(d,e){var g;if(((typeof d=="object")||Object.isFunction(d))&&(d.length)){g=d}else{g=$(d).childNodes}var b=Object.extend({speed:0.1,delay:0},arguments[2]||{});var f=b.delay;$A(g).each(function(l,h){new e(l,Object.extend(b,{delay:h*b.speed+f}))})},PAIRS:{slide:["SlideDown","SlideUp"],blind:["BlindDown","BlindUp"],appear:["Appear","Fade"]},toggle:function(d,e){d=$(d);e=(e||"appear").toLowerCase();var b=Object.extend({queue:{position:"end",scope:(d.id||"global"),limit:1}},arguments[2]||{});Effect[d.visible()?Effect.PAIRS[e][1]:Effect.PAIRS[e][0]](d,b)}};Effect.DefaultOptions.transition=Effect.Transitions.sinoidal;Effect.ScopedQueue=Class.create(Enumerable,{initialize:function(){this.effects=[];this.interval=null},_each:function(b){this.effects._each(b)},add:function(d){var e=new Date().getTime();var b=Object.isString(d.options.queue)?d.options.queue:d.options.queue.position;switch(b){case"front":this.effects.findAll(function(f){return f.state=="idle"}).each(function(f){f.startOn+=d.finishOn;f.finishOn+=d.finishOn});break;case"with-last":e=this.effects.pluck("startOn").max()||e;break;case"end":e=this.effects.pluck("finishOn").max()||e;break}d.startOn+=e;d.finishOn+=e;if(!d.options.queue.limit||(this.effects.length<d.options.queue.limit)){this.effects.push(d)}if(!this.interval){this.interval=setInterval(this.loop.bind(this),15)}},remove:function(b){this.effects=this.effects.reject(function(d){return d==b});if(this.effects.length==0){clearInterval(this.interval);this.interval=null}},loop:function(){var e=new Date().getTime();for(var d=0,b=this.effects.length;d<b;d++){this.effects[d]&&this.effects[d].loop(e)}}});Effect.Queues={instances:$H(),get:function(b){if(!Object.isString(b)){return b}return this.instances.get(b)||this.instances.set(b,new Effect.ScopedQueue())}};Effect.Queue=Effect.Queues.get("global");Effect.Base=Class.create({position:null,start:function(b){function d(f,e){return((f[e+"Internal"]?"this.options."+e+"Internal(this);":"")+(f[e]?"this.options."+e+"(this);":""))}if(b&&b.transition===false){b.transition=Effect.Transitions.linear}this.options=Object.extend(Object.extend({},Effect.DefaultOptions),b||{});this.currentFrame=0;this.state="idle";this.startOn=this.options.delay*1000;this.finishOn=this.startOn+(this.options.duration*1000);this.fromToDelta=this.options.to-this.options.from;this.totalTime=this.finishOn-this.startOn;this.totalFrames=this.options.fps*this.options.duration;this.render=(function(){function e(g,f){if(g.options[f+"Internal"]){g.options[f+"Internal"](g)}if(g.options[f]){g.options[f](g)}}return function(f){if(this.state==="idle"){this.state="running";e(this,"beforeSetup");if(this.setup){this.setup()}e(this,"afterSetup")}if(this.state==="running"){f=(this.options.transition(f)*this.fromToDelta)+this.options.from;this.position=f;e(this,"beforeUpdate");if(this.update){this.update(f)}e(this,"afterUpdate")}}})();this.event("beforeStart");if(!this.options.sync){Effect.Queues.get(Object.isString(this.options.queue)?"global":this.options.queue.scope).add(this)}},loop:function(e){if(e>=this.startOn){if(e>=this.finishOn){this.render(1);this.cancel();this.event("beforeFinish");if(this.finish){this.finish()}this.event("afterFinish");return}var d=(e-this.startOn)/this.totalTime,b=(d*this.totalFrames).round();if(b>this.currentFrame){this.render(d);this.currentFrame=b}}},cancel:function(){if(!this.options.sync){Effect.Queues.get(Object.isString(this.options.queue)?"global":this.options.queue.scope).remove(this)}this.state="finished"},event:function(b){if(this.options[b+"Internal"]){this.options[b+"Internal"](this)}if(this.options[b]){this.options[b](this)}},inspect:function(){var b=$H();for(property in this){if(!Object.isFunction(this[property])){b.set(property,this[property])}}return"#<Effect:"+b.inspect()+",options:"+$H(this.options).inspect()+">"}});Effect.Parallel=Class.create(Effect.Base,{initialize:function(b){this.effects=b||[];this.start(arguments[1])},update:function(b){this.effects.invoke("render",b)},finish:function(b){this.effects.each(function(d){d.render(1);d.cancel();d.event("beforeFinish");if(d.finish){d.finish(b)}d.event("afterFinish")})}});Effect.Tween=Class.create(Effect.Base,{initialize:function(e,h,g){e=Object.isString(e)?$(e):e;var d=$A(arguments),f=d.last(),b=d.length==5?d[3]:null;this.method=Object.isFunction(f)?f.bind(e):Object.isFunction(e[f])?e[f].bind(e):function(l){e[f]=l};this.start(Object.extend({from:h,to:g},b||{}))},update:function(b){this.method(b)}});Effect.Event=Class.create(Effect.Base,{initialize:function(){this.start(Object.extend({duration:0},arguments[0]||{}))},update:Prototype.emptyFunction});Effect.Opacity=Class.create(Effect.Base,{initialize:function(d){this.element=$(d);if(!this.element){throw (Effect._elementDoesNotExistError)}if(Prototype.Browser.IE&&(!this.element.currentStyle.hasLayout)){this.element.setStyle({zoom:1})}var b=Object.extend({from:this.element.getOpacity()||0,to:1},arguments[1]||{});this.start(b)},update:function(b){this.element.setOpacity(b)}});Effect.Move=Class.create(Effect.Base,{initialize:function(d){this.element=$(d);if(!this.element){throw (Effect._elementDoesNotExistError)}var b=Object.extend({x:0,y:0,mode:"relative"},arguments[1]||{});this.start(b)},setup:function(){this.element.makePositioned();this.originalLeft=parseFloat(this.element.getStyle("left")||"0");this.originalTop=parseFloat(this.element.getStyle("top")||"0");if(this.options.mode=="absolute"){this.options.x=this.options.x-this.originalLeft;this.options.y=this.options.y-this.originalTop}},update:function(b){this.element.setStyle({left:(this.options.x*b+this.originalLeft).round()+"px",top:(this.options.y*b+this.originalTop).round()+"px"})}});Effect.MoveBy=function(d,b,e){return new Effect.Move(d,Object.extend({x:e,y:b},arguments[3]||{}))};Effect.Scale=Class.create(Effect.Base,{initialize:function(d,e){this.element=$(d);if(!this.element){throw (Effect._elementDoesNotExistError)}var b=Object.extend({scaleX:true,scaleY:true,scaleContent:true,scaleFromCenter:false,scaleMode:"box",scaleFrom:100,scaleTo:e},arguments[2]||{});this.start(b)},setup:function(){this.restoreAfterFinish=this.options.restoreAfterFinish||false;this.elementPositioning=this.element.getStyle("position");this.originalStyle={};["top","left","width","height","fontSize"].each(function(d){this.originalStyle[d]=this.element.style[d]}.bind(this));this.originalTop=this.element.offsetTop;this.originalLeft=this.element.offsetLeft;var b=this.element.getStyle("font-size")||"100%";["em","px","%","pt"].each(function(d){if(b.indexOf(d)>0){this.fontSize=parseFloat(b);this.fontSizeType=d}}.bind(this));this.factor=(this.options.scaleTo-this.options.scaleFrom)/100;this.dims=null;if(this.options.scaleMode=="box"){this.dims=[this.element.offsetHeight,this.element.offsetWidth]}if(/^content/.test(this.options.scaleMode)){this.dims=[this.element.scrollHeight,this.element.scrollWidth]}if(!this.dims){this.dims=[this.options.scaleMode.originalHeight,this.options.scaleMode.originalWidth]}},update:function(b){var d=(this.options.scaleFrom/100)+(this.factor*b);if(this.options.scaleContent&&this.fontSize){this.element.setStyle({fontSize:this.fontSize*d+this.fontSizeType})}this.setDimensions(this.dims[0]*d,this.dims[1]*d)},finish:function(b){if(this.restoreAfterFinish){this.element.setStyle(this.originalStyle)}},setDimensions:function(b,g){var h={};if(this.options.scaleX){h.width=g.round()+"px"}if(this.options.scaleY){h.height=b.round()+"px"}if(this.options.scaleFromCenter){var f=(b-this.dims[0])/2;var e=(g-this.dims[1])/2;if(this.elementPositioning=="absolute"){if(this.options.scaleY){h.top=this.originalTop-f+"px"}if(this.options.scaleX){h.left=this.originalLeft-e+"px"}}else{if(this.options.scaleY){h.top=-f+"px"}if(this.options.scaleX){h.left=-e+"px"}}}this.element.setStyle(h)}});Effect.Highlight=Class.create(Effect.Base,{initialize:function(d){this.element=$(d);if(!this.element){throw (Effect._elementDoesNotExistError)}var b=Object.extend({startcolor:"#ffff99"},arguments[1]||{});this.start(b)},setup:function(){if(this.element.getStyle("display")=="none"){this.cancel();return}this.oldStyle={};if(!this.options.keepBackgroundImage){this.oldStyle.backgroundImage=this.element.getStyle("background-image");this.element.setStyle({backgroundImage:"none"})}if(!this.options.endcolor){this.options.endcolor=this.element.getStyle("background-color").parseColor("#ffffff")}if(!this.options.restorecolor){this.options.restorecolor=this.element.getStyle("background-color")}this._base=$R(0,2).map(function(b){return parseInt(this.options.startcolor.slice(b*2+1,b*2+3),16)}.bind(this));this._delta=$R(0,2).map(function(b){return parseInt(this.options.endcolor.slice(b*2+1,b*2+3),16)-this._base[b]}.bind(this))},update:function(b){this.element.setStyle({backgroundColor:$R(0,2).inject("#",function(d,e,f){return d+((this._base[f]+(this._delta[f]*b)).round().toColorPart())}.bind(this))})},finish:function(){this.element.setStyle(Object.extend(this.oldStyle,{backgroundColor:this.options.restorecolor}))}});Effect.ScrollTo=function(e){var d=arguments[1]||{},b=document.viewport.getScrollOffsets(),f=$(e).cumulativeOffset();if(d.offset){f[1]+=d.offset}return new Effect.Tween(null,b.top,f[1],d,function(g){scrollTo(b.left,g.round())})};Effect.Fade=function(e){e=$(e);var b=e.getInlineOpacity();var d=Object.extend({from:e.getOpacity()||1,to:0,afterFinishInternal:function(f){if(f.options.to!=0){return}f.element.hide().setStyle({opacity:b})}},arguments[1]||{});return new Effect.Opacity(e,d)};Effect.Appear=function(d){d=$(d);var b=Object.extend({from:(d.getStyle("display")=="none"?0:d.getOpacity()||0),to:1,afterFinishInternal:function(e){e.element.forceRerendering()},beforeSetup:function(e){e.element.setOpacity(e.options.from).show()}},arguments[1]||{});return new Effect.Opacity(d,b)};Effect.Puff=function(d){d=$(d);var b={opacity:d.getInlineOpacity(),position:d.getStyle("position"),top:d.style.top,left:d.style.left,width:d.style.width,height:d.style.height};return new Effect.Parallel([new Effect.Scale(d,200,{sync:true,scaleFromCenter:true,scaleContent:true,restoreAfterFinish:true}),new Effect.Opacity(d,{sync:true,to:0})],Object.extend({duration:1,beforeSetupInternal:function(e){Position.absolutize(e.effects[0].element)},afterFinishInternal:function(e){e.effects[0].element.hide().setStyle(b)}},arguments[1]||{}))};Effect.BlindUp=function(b){b=$(b);b.makeClipping();return new Effect.Scale(b,0,Object.extend({scaleContent:false,scaleX:false,restoreAfterFinish:true,afterFinishInternal:function(d){d.element.hide().undoClipping()}},arguments[1]||{}))};Effect.BlindDown=function(d){d=$(d);var b=d.getDimensions();return new Effect.Scale(d,100,Object.extend({scaleContent:false,scaleX:false,scaleFrom:0,scaleMode:{originalHeight:b.height,originalWidth:b.width},restoreAfterFinish:true,afterSetup:function(e){e.element.makeClipping().setStyle({height:"0px"}).show()},afterFinishInternal:function(e){e.element.undoClipping()}},arguments[1]||{}))};Effect.SwitchOff=function(d){d=$(d);var b=d.getInlineOpacity();return new Effect.Appear(d,Object.extend({duration:0.4,from:0,transition:Effect.Transitions.flicker,afterFinishInternal:function(e){new Effect.Scale(e.element,1,{duration:0.3,scaleFromCenter:true,scaleX:false,scaleContent:false,restoreAfterFinish:true,beforeSetup:function(f){f.element.makePositioned().makeClipping()},afterFinishInternal:function(f){f.element.hide().undoClipping().undoPositioned().setStyle({opacity:b})}})}},arguments[1]||{}))};Effect.DropOut=function(d){d=$(d);var b={top:d.getStyle("top"),left:d.getStyle("left"),opacity:d.getInlineOpacity()};return new Effect.Parallel([new Effect.Move(d,{x:0,y:100,sync:true}),new Effect.Opacity(d,{sync:true,to:0})],Object.extend({duration:0.5,beforeSetup:function(e){e.effects[0].element.makePositioned()},afterFinishInternal:function(e){e.effects[0].element.hide().undoPositioned().setStyle(b)}},arguments[1]||{}))};Effect.Shake=function(f){f=$(f);var d=Object.extend({distance:20,duration:0.5},arguments[1]||{});var g=parseFloat(d.distance);var e=parseFloat(d.duration)/10;var b={top:f.getStyle("top"),left:f.getStyle("left")};return new Effect.Move(f,{x:g,y:0,duration:e,afterFinishInternal:function(h){new Effect.Move(h.element,{x:-g*2,y:0,duration:e*2,afterFinishInternal:function(l){new Effect.Move(l.element,{x:g*2,y:0,duration:e*2,afterFinishInternal:function(n){new Effect.Move(n.element,{x:-g*2,y:0,duration:e*2,afterFinishInternal:function(o){new Effect.Move(o.element,{x:g*2,y:0,duration:e*2,afterFinishInternal:function(p){new Effect.Move(p.element,{x:-g,y:0,duration:e,afterFinishInternal:function(q){q.element.undoPositioned().setStyle(b)}})}})}})}})}})}})};Effect.SlideDown=function(e){e=$(e).cleanWhitespace();var b=e.down().getStyle("bottom");var d=e.getDimensions();return new Effect.Scale(e,100,Object.extend({scaleContent:false,scaleX:false,scaleFrom:window.opera?0:1,scaleMode:{originalHeight:d.height,originalWidth:d.width},restoreAfterFinish:true,afterSetup:function(f){f.element.makePositioned();f.element.down().makePositioned();if(window.opera){f.element.setStyle({top:""})}f.element.makeClipping().setStyle({height:"0px"}).show()},afterUpdateInternal:function(f){f.element.down().setStyle({bottom:(f.dims[0]-f.element.clientHeight)+"px"})},afterFinishInternal:function(f){f.element.undoClipping().undoPositioned();f.element.down().undoPositioned().setStyle({bottom:b})}},arguments[1]||{}))};Effect.SlideUp=function(e){e=$(e).cleanWhitespace();var b=e.down().getStyle("bottom");var d=e.getDimensions();return new Effect.Scale(e,window.opera?0:1,Object.extend({scaleContent:false,scaleX:false,scaleMode:"box",scaleFrom:100,scaleMode:{originalHeight:d.height,originalWidth:d.width},restoreAfterFinish:true,afterSetup:function(f){f.element.makePositioned();f.element.down().makePositioned();if(window.opera){f.element.setStyle({top:""})}f.element.makeClipping().show()},afterUpdateInternal:function(f){f.element.down().setStyle({bottom:(f.dims[0]-f.element.clientHeight)+"px"})},afterFinishInternal:function(f){f.element.hide().undoClipping().undoPositioned();f.element.down().undoPositioned().setStyle({bottom:b})}},arguments[1]||{}))};Effect.Squish=function(b){return new Effect.Scale(b,window.opera?1:0,{restoreAfterFinish:true,beforeSetup:function(d){d.element.makeClipping()},afterFinishInternal:function(d){d.element.hide().undoClipping()}})};Effect.Grow=function(e){e=$(e);var d=Object.extend({direction:"center",moveTransition:Effect.Transitions.sinoidal,scaleTransition:Effect.Transitions.sinoidal,opacityTransition:Effect.Transitions.full},arguments[1]||{});var b={top:e.style.top,left:e.style.left,height:e.style.height,width:e.style.width,opacity:e.getInlineOpacity()};var l=e.getDimensions();var n,h;var g,f;switch(d.direction){case"top-left":n=h=g=f=0;break;case"top-right":n=l.width;h=f=0;g=-l.width;break;case"bottom-left":n=g=0;h=l.height;f=-l.height;break;case"bottom-right":n=l.width;h=l.height;g=-l.width;f=-l.height;break;case"center":n=l.width/2;h=l.height/2;g=-l.width/2;f=-l.height/2;break}return new Effect.Move(e,{x:n,y:h,duration:0.01,beforeSetup:function(o){o.element.hide().makeClipping().makePositioned()},afterFinishInternal:function(o){new Effect.Parallel([new Effect.Opacity(o.element,{sync:true,to:1,from:0,transition:d.opacityTransition}),new Effect.Move(o.element,{x:g,y:f,sync:true,transition:d.moveTransition}),new Effect.Scale(o.element,100,{scaleMode:{originalHeight:l.height,originalWidth:l.width},sync:true,scaleFrom:window.opera?1:0,transition:d.scaleTransition,restoreAfterFinish:true})],Object.extend({beforeSetup:function(p){p.effects[0].element.setStyle({height:"0px"}).show()},afterFinishInternal:function(p){p.effects[0].element.undoClipping().undoPositioned().setStyle(b)}},d))}})};Effect.Shrink=function(e){e=$(e);var d=Object.extend({direction:"center",moveTransition:Effect.Transitions.sinoidal,scaleTransition:Effect.Transitions.sinoidal,opacityTransition:Effect.Transitions.none},arguments[1]||{});var b={top:e.style.top,left:e.style.left,height:e.style.height,width:e.style.width,opacity:e.getInlineOpacity()};var h=e.getDimensions();var g,f;switch(d.direction){case"top-left":g=f=0;break;case"top-right":g=h.width;f=0;break;case"bottom-left":g=0;f=h.height;break;case"bottom-right":g=h.width;f=h.height;break;case"center":g=h.width/2;f=h.height/2;break}return new Effect.Parallel([new Effect.Opacity(e,{sync:true,to:0,from:1,transition:d.opacityTransition}),new Effect.Scale(e,window.opera?1:0,{sync:true,transition:d.scaleTransition,restoreAfterFinish:true}),new Effect.Move(e,{x:g,y:f,sync:true,transition:d.moveTransition})],Object.extend({beforeStartInternal:function(l){l.effects[0].element.makePositioned().makeClipping()},afterFinishInternal:function(l){l.effects[0].element.hide().undoClipping().undoPositioned().setStyle(b)}},d))};Effect.Pulsate=function(e){e=$(e);var d=arguments[1]||{},b=e.getInlineOpacity(),g=d.transition||Effect.Transitions.linear,f=function(h){return 1-g((-Math.cos((h*(d.pulses||5)*2)*Math.PI)/2)+0.5)};return new Effect.Opacity(e,Object.extend(Object.extend({duration:2,from:0,afterFinishInternal:function(h){h.element.setStyle({opacity:b})}},d),{transition:f}))};Effect.Fold=function(d){d=$(d);var b={top:d.style.top,left:d.style.left,width:d.style.width,height:d.style.height};d.makeClipping();return new Effect.Scale(d,5,Object.extend({scaleContent:false,scaleX:false,afterFinishInternal:function(e){new Effect.Scale(d,1,{scaleContent:false,scaleY:false,afterFinishInternal:function(f){f.element.hide().undoClipping().setStyle(b)}})}},arguments[1]||{}))};Effect.Morph=Class.create(Effect.Base,{initialize:function(e){this.element=$(e);if(!this.element){throw (Effect._elementDoesNotExistError)}var b=Object.extend({style:{}},arguments[1]||{});if(!Object.isString(b.style)){this.style=$H(b.style)}else{if(b.style.include(":")){this.style=b.style.parseStyle()}else{this.element.addClassName(b.style);this.style=$H(this.element.getStyles());this.element.removeClassName(b.style);var d=this.element.getStyles();this.style=this.style.reject(function(f){return f.value==d[f.key]});b.afterFinishInternal=function(f){f.element.addClassName(f.options.style);f.transforms.each(function(g){f.element.style[g.style]=""})}}}this.start(b)},setup:function(){function b(d){if(!d||["rgba(0, 0, 0, 0)","transparent"].include(d)){d="#ffffff"}d=d.parseColor();return $R(0,2).map(function(e){return parseInt(d.slice(e*2+1,e*2+3),16)})}this.transforms=this.style.map(function(l){var h=l[0],g=l[1],f=null;if(g.parseColor("#zzzzzz")!="#zzzzzz"){g=g.parseColor();f="color"}else{if(h=="opacity"){g=parseFloat(g);if(Prototype.Browser.IE&&(!this.element.currentStyle.hasLayout)){this.element.setStyle({zoom:1})}}else{if(Element.CSS_LENGTH.test(g)){var e=g.match(/^([\+\-]?[0-9\.]+)(.*)$/);g=parseFloat(e[1]);f=(e.length==3)?e[2]:null}}}var d=this.element.getStyle(h);return{style:h.camelize(),originalValue:f=="color"?b(d):parseFloat(d||0),targetValue:f=="color"?b(g):g,unit:f}}.bind(this)).reject(function(d){return((d.originalValue==d.targetValue)||(d.unit!="color"&&(isNaN(d.originalValue)||isNaN(d.targetValue))))})},update:function(b){var f={},d,e=this.transforms.length;while(e--){f[(d=this.transforms[e]).style]=d.unit=="color"?"#"+(Math.round(d.originalValue[0]+(d.targetValue[0]-d.originalValue[0])*b)).toColorPart()+(Math.round(d.originalValue[1]+(d.targetValue[1]-d.originalValue[1])*b)).toColorPart()+(Math.round(d.originalValue[2]+(d.targetValue[2]-d.originalValue[2])*b)).toColorPart():(d.originalValue+(d.targetValue-d.originalValue)*b).toFixed(3)+(d.unit===null?"":d.unit)}this.element.setStyle(f,true)}});Effect.Transform=Class.create({initialize:function(b){this.tracks=[];this.options=arguments[1]||{};this.addTracks(b)},addTracks:function(b){b.each(function(d){d=$H(d);var e=d.values().first();this.tracks.push($H({ids:d.keys().first(),effect:Effect.Morph,options:{style:e}}))}.bind(this));return this},play:function(){return new Effect.Parallel(this.tracks.map(function(b){var f=b.get("ids"),e=b.get("effect"),d=b.get("options");var g=[$(f)||$$(f)].flatten();return g.map(function(h){return new e(h,Object.extend({sync:true},d))})}).flatten(),this.options)}});Element.CSS_PROPERTIES=$w("backgroundColor backgroundPosition borderBottomColor borderBottomStyle borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth borderRightColor borderRightStyle borderRightWidth borderSpacing borderTopColor borderTopStyle borderTopWidth bottom clip color fontSize fontWeight height left letterSpacing lineHeight marginBottom marginLeft marginRight marginTop markerOffset maxHeight maxWidth minHeight minWidth opacity outlineColor outlineOffset outlineWidth paddingBottom paddingLeft paddingRight paddingTop right textIndent top width wordSpacing zIndex");Element.CSS_LENGTH=/^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;String.__parseStyleElement=document.createElement("div");String.prototype.parseStyle=function(){var d,b=$H();if(Prototype.Browser.WebKit){d=new Element("div",{style:this}).style}else{String.__parseStyleElement.innerHTML='<div style="'+this+'"></div>';d=String.__parseStyleElement.childNodes[0].style}Element.CSS_PROPERTIES.each(function(e){if(d[e]){b.set(e,d[e])}});if(Prototype.Browser.IE&&this.include("opacity")){b.set("opacity",this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1])}return b};if(document.defaultView&&document.defaultView.getComputedStyle){Element.getStyles=function(d){var b=document.defaultView.getComputedStyle($(d),null);return Element.CSS_PROPERTIES.inject({},function(e,f){e[f]=b[f];return e})}}else{Element.getStyles=function(d){d=$(d);var b=d.currentStyle,e;e=Element.CSS_PROPERTIES.inject({},function(f,g){f[g]=b[g];return f});if(!e.opacity){e.opacity=d.getOpacity()}return e}}Effect.Methods={morph:function(b,d){b=$(b);new Effect.Morph(b,Object.extend({style:d},arguments[2]||{}));return b},visualEffect:function(e,g,d){e=$(e);var f=g.dasherize().camelize(),b=f.charAt(0).toUpperCase()+f.substring(1);new Effect[b](e,d);return e},highlight:function(d,b){d=$(d);new Effect.Highlight(d,b);return d}};$w("fade appear grow shrink fold blindUp blindDown slideUp slideDown pulsate shake puff squish switchOff dropOut").each(function(b){Effect.Methods[b]=function(e,d){e=$(e);Effect[b.charAt(0).toUpperCase()+b.substring(1)](e,d);return e}});$w("getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles").each(function(b){Effect.Methods[b]=Element[b]});Element.addMethods(Effect.Methods);function validateCreditCard(e){var d="0123456789";var b="";for(i=0;i<e.length;i++){x=e.charAt(i);if(d.indexOf(x,0)!=-1){b+=x}}j=b.length/2;k=Math.floor(j);m=Math.ceil(j)-k;c=0;for(i=0;i<k;i++){a=b.charAt(i*2+m)*2;c+=a>9?Math.floor(a/10+a%10):a}for(i=0;i<k+m;i++){c+=b.charAt(i*2+1-m)*1}return(c%10==0)}var Validator=Class.create();Validator.prototype={initialize:function(e,d,f,b){if(typeof f=="function"){this.options=$H(b);this._test=f}else{this.options=$H(f);this._test=function(){return true}}this.error=d||"Validation failed.";this.className=e},test:function(b,d){return(this._test(b,d)&&this.options.all(function(e){return Validator.methods[e.key]?Validator.methods[e.key](b,d,e.value):true}))}};Validator.methods={pattern:function(b,e,d){return Validation.get("IsEmpty").test(b)||d.test(b)},minLength:function(b,e,d){return b.length>=d},maxLength:function(b,e,d){return b.length<=d},min:function(b,e,d){return b>=parseFloat(d)},max:function(b,e,d){return b<=parseFloat(d)},notOneOf:function(b,e,d){return $A(d).all(function(f){return b!=f})},oneOf:function(b,e,d){return $A(d).any(function(f){return b==f})},is:function(b,e,d){return b==d},isNot:function(b,e,d){return b!=d},equalToField:function(b,e,d){return b==$F(d)},notEqualToField:function(b,e,d){return b!=$F(d)},include:function(b,e,d){return $A(d).all(function(f){return Validation.get(f).test(b,e)})}};var Validation=Class.create();Validation.defaultOptions={onSubmit:true,stopOnFirst:false,immediate:false,focusOnError:true,useTitles:false,addClassNameToContainer:false,containerClassName:".input-box",onFormValidate:function(b,d){},onElementValidate:function(b,d){}};Validation.prototype={initialize:function(d,b){this.form=$(d);if(!this.form){return}this.options=Object.extend({onSubmit:Validation.defaultOptions.onSubmit,stopOnFirst:Validation.defaultOptions.stopOnFirst,immediate:Validation.defaultOptions.immediate,focusOnError:Validation.defaultOptions.focusOnError,useTitles:Validation.defaultOptions.useTitles,onFormValidate:Validation.defaultOptions.onFormValidate,onElementValidate:Validation.defaultOptions.onElementValidate},b||{});if(this.options.onSubmit){Event.observe(this.form,"submit",this.onSubmit.bind(this),false)}if(this.options.immediate){Form.getElements(this.form).each(function(e){if(e.tagName.toLowerCase()=="select"){Event.observe(e,"blur",this.onChange.bindAsEventListener(this))}if(e.type.toLowerCase()=="radio"||e.type.toLowerCase()=="checkbox"){Event.observe(e,"click",this.onChange.bindAsEventListener(this))}else{Event.observe(e,"change",this.onChange.bindAsEventListener(this))}},this)}},onChange:function(b){Validation.isOnChange=true;Validation.validate(Event.element(b),{useTitle:this.options.useTitles,onElementValidate:this.options.onElementValidate});Validation.isOnChange=false},onSubmit:function(b){if(!this.validate()){Event.stop(b)}},validate:function(){var b=false;var d=this.options.useTitles;var g=this.options.onElementValidate;try{if(this.options.stopOnFirst){b=Form.getElements(this.form).all(function(e){if(e.hasClassName("local-validation")&&!this.isElementInForm(e,this.form)){return true}return Validation.validate(e,{useTitle:d,onElementValidate:g})},this)}else{b=Form.getElements(this.form).collect(function(e){if(e.hasClassName("local-validation")&&!this.isElementInForm(e,this.form)){return true}if(e.hasClassName("validation-disabled")){return true}return Validation.validate(e,{useTitle:d,onElementValidate:g})},this).all()}}catch(f){}if(!b&&this.options.focusOnError){try{Form.getElements(this.form).findAll(function(e){return $(e).hasClassName("validation-failed")}).first().focus()}catch(f){}}this.options.onFormValidate(b,this.form);return b},reset:function(){Form.getElements(this.form).each(Validation.reset)},isElementInForm:function(e,d){var b=e.up("form");if(b==d){return true}return false}};Object.extend(Validation,{validate:function(e,b){b=Object.extend({useTitle:false,onElementValidate:function(f,g){}},b||{});e=$(e);var d=$w(e.className);return result=d.all(function(f){var g=Validation.test(f,e,b.useTitle);b.onElementValidate(g,e);return g})},insertAdvice:function(f,d){var b=$(f).up(".field-row");if(b){Element.insert(b,{after:d})}else{if(f.up("td.value")){f.up("td.value").insert({bottom:d})}else{if(f.advaiceContainer&&$(f.advaiceContainer)){$(f.advaiceContainer).update(d)}else{switch(f.type.toLowerCase()){case"checkbox":case"radio":var e=f.parentNode;if(e){Element.insert(e,{bottom:d})}else{Element.insert(f,{after:d})}break;default:Element.insert(f,{after:d})}}}}},showAdvice:function(e,d,b){if(!e.advices){e.advices=new Hash()}else{e.advices.each(function(f){if(!d||f.value.id!=d.id){this.hideAdvice(e,f.value)}}.bind(this))}e.advices.set(b,d);if(typeof Effect=="undefined"){d.style.display="block"}else{if(!d._adviceAbsolutize){new Effect.Appear(d,{duration:1})}else{Position.absolutize(d);d.show();d.setStyle({top:d._adviceTop,left:d._adviceLeft,width:d._adviceWidth,"z-index":1000});d.addClassName("advice-absolute")}}},hideAdvice:function(d,b){if(b!=null){new Effect.Fade(b,{duration:1,afterFinishInternal:function(){b.hide()}})}},updateCallback:function(elm,status){if(typeof elm.callbackFunction!="undefined"){eval(elm.callbackFunction+"('"+elm.id+"','"+status+"')")}},ajaxError:function(g,f){var e="validate-ajax";var d=Validation.getAdvice(e,g);if(d==null){d=this.createAdvice(e,g,false,f)}this.showAdvice(g,d,"validate-ajax");this.updateCallback(g,"failed");g.addClassName("validation-failed");g.addClassName("validate-ajax");if(Validation.defaultOptions.addClassNameToContainer&&Validation.defaultOptions.containerClassName!=""){var b=g.up(Validation.defaultOptions.containerClassName);if(b&&this.allowContainerClassName(g)){b.removeClassName("validation-passed");b.addClassName("validation-error")}}},allowContainerClassName:function(b){if(b.type=="radio"||b.type=="checkbox"){return b.hasClassName("change-container-classname")}return true},test:function(g,o,l){var d=Validation.get(g);var n="__advice"+g.camelize();try{if(Validation.isVisible(o)&&!d.test($F(o),o)){var f=Validation.getAdvice(g,o);if(f==null){f=this.createAdvice(g,o,l)}this.showAdvice(o,f,g);this.updateCallback(o,"failed");o[n]=1;if(!o.advaiceContainer){o.removeClassName("validation-passed");o.addClassName("validation-failed")}if(Validation.defaultOptions.addClassNameToContainer&&Validation.defaultOptions.containerClassName!=""){var b=o.up(Validation.defaultOptions.containerClassName);if(b&&this.allowContainerClassName(o)){b.removeClassName("validation-passed");b.addClassName("validation-error")}}return false}else{var f=Validation.getAdvice(g,o);this.hideAdvice(o,f);this.updateCallback(o,"passed");o[n]="";o.removeClassName("validation-failed");o.addClassName("validation-passed");if(Validation.defaultOptions.addClassNameToContainer&&Validation.defaultOptions.containerClassName!=""){var b=o.up(Validation.defaultOptions.containerClassName);if(b&&!b.down(".validation-failed")&&this.allowContainerClassName(o)){if(!Validation.get("IsEmpty").test(o.value)||!this.isVisible(o)){b.addClassName("validation-passed")}else{b.removeClassName("validation-passed")}b.removeClassName("validation-error")}}return true}}catch(h){throw (h)}},isVisible:function(b){while(b.tagName!="BODY"){if(!$(b).visible()){return false}b=b.parentNode}return true},getAdvice:function(b,d){return $("advice-"+b+"-"+Validation.getElmID(d))||$("advice-"+Validation.getElmID(d))},createAdvice:function(e,n,l,d){var b=Validation.get(e);var h=l?((n&&n.title)?n.title:b.error):b.error;if(d){h=d}if(jQuery.mage.__){h=jQuery.mage.__(h)}advice='<div class="validation-advice" id="advice-'+e+"-"+Validation.getElmID(n)+'" style="display:none">'+h+"</div>";Validation.insertAdvice(n,advice);advice=Validation.getAdvice(e,n);if($(n).hasClassName("absolute-advice")){var g=$(n).getDimensions();var f=Position.cumulativeOffset(n);advice._adviceTop=(f[1]+g.height)+"px";advice._adviceLeft=(f[0])+"px";advice._adviceWidth=(g.width)+"px";advice._adviceAbsolutize=true}return advice},getElmID:function(b){return b.id?b.id:b.name},reset:function(d){d=$(d);var b=$w(d.className);b.each(function(g){var h="__advice"+g.camelize();if(d[h]){var f=Validation.getAdvice(g,d);if(f){f.hide()}d[h]=""}d.removeClassName("validation-failed");d.removeClassName("validation-passed");if(Validation.defaultOptions.addClassNameToContainer&&Validation.defaultOptions.containerClassName!=""){var e=d.up(Validation.defaultOptions.containerClassName);if(e){e.removeClassName("validation-passed");e.removeClassName("validation-error")}}})},add:function(f,e,g,d){var b={};b[f]=new Validator(f,e,g,d);Object.extend(Validation.methods,b)},addAllThese:function(b){var d={};$A(b).each(function(e){d[e[0]]=new Validator(e[0],e[1],e[2],(e.length>3?e[3]:{}))});Object.extend(Validation.methods,d)},get:function(b){return Validation.methods[b]?Validation.methods[b]:Validation.methods._LikeNoIDIEverSaw_},methods:{_LikeNoIDIEverSaw_:new Validator("_LikeNoIDIEverSaw_","",{})}});Validation.add("IsEmpty","",function(b){return(b==""||(b==null)||(b.length==0)||/^\s+$/.test(b))});Validation.addAllThese([["validate-no-html-tags","HTML tags are not allowed",function(b){return !/<(\/)?\w+/.test(b)}],["validate-select","Please select an option.",function(b){return((b!="none")&&(b!=null)&&(b.length!=0))}],["required-entry","This is a required field.",function(b){return !Validation.get("IsEmpty").test(b)}],["validate-number","Please enter a valid number in this field.",function(b){return Validation.get("IsEmpty").test(b)||(!isNaN(parseNumber(b))&&/^\s*-?\d*(\.\d*)?\s*$/.test(b))}],["validate-number-range","The value is not within the specified range.",function(e,g){if(Validation.get("IsEmpty").test(e)){return true}var f=parseNumber(e);if(isNaN(f)){return false}var d=/^number-range-(-?[\d.,]+)?-(-?[\d.,]+)?$/,b=true;$w(g.className).each(function(l){var h=d.exec(l);if(h){b=b&&(h[1]==null||h[1]==""||f>=parseNumber(h[1]))&&(h[2]==null||h[2]==""||f<=parseNumber(h[2]))}});return b}],["validate-digits","Please use numbers only in this field. Please avoid spaces or other characters such as dots or commas.",function(b){return Validation.get("IsEmpty").test(b)||!/[^\d]/.test(b)}],["validate-digits-range","The value is not within the specified range.",function(e,g){if(Validation.get("IsEmpty").test(e)){return true}var f=parseNumber(e);if(isNaN(f)){return false}var d=/^digits-range-(-?\d+)?-(-?\d+)?$/,b=true;$w(g.className).each(function(l){var h=d.exec(l);if(h){b=b&&(h[1]==null||h[1]==""||f>=parseNumber(h[1]))&&(h[2]==null||h[2]==""||f<=parseNumber(h[2]))}});return b}],["validate-range","The value is not within the specified range.",function(f,l){var g,h;if(Validation.get("IsEmpty").test(f)){return true}else{if(Validation.get("validate-digits").test(f)){g=h=parseNumber(f)}else{var e=/^(-?\d+)?-(-?\d+)?$/.exec(f);if(e){g=parseNumber(e[1]);h=parseNumber(e[2]);if(g>h){return false}}else{return false}}}var d=/^range-(-?\d+)?-(-?\d+)?$/,b=true;$w(l.className).each(function(n){var q=d.exec(n);if(q){var p=parseNumber(q[1]);var o=parseNumber(q[2]);b=b&&(isNaN(p)||g>=p)&&(isNaN(o)||h<=o)}});return b}],["validate-alpha","Please use letters only (a-z or A-Z) in this field.",function(b){return Validation.get("IsEmpty").test(b)||/^[a-zA-Z]+$/.test(b)}],["validate-code","Please use only letters (a-z), numbers (0-9) or underscore (_) in this field, and the first character should be a letter.",function(b){return Validation.get("IsEmpty").test(b)||/^[a-z]+[a-z0-9_]+$/.test(b)}],["validate-alphanum","Please use only letters (a-z or A-Z) or numbers (0-9) in this field. No spaces or other characters are allowed.",function(b){return Validation.get("IsEmpty").test(b)||/^[a-zA-Z0-9]+$/.test(b)}],["validate-alphanum-with-spaces","Please use only letters (a-z or A-Z), numbers (0-9) or spaces only in this field.",function(b){return Validation.get("IsEmpty").test(b)||/^[a-zA-Z0-9 ]+$/.test(b)}],["validate-street",'Please use only letters (a-z or A-Z), numbers (0-9), spaces and "#" in this field.',function(b){return Validation.get("IsEmpty").test(b)||/^[ \w]{3,}([A-Za-z]\.)?([ \w]*\#\d+)?(\r\n| )[ \w]{3,}/.test(b)}],["validate-phoneStrict","Please enter a valid phone number (Ex: 123-456-7890).",function(b){return Validation.get("IsEmpty").test(b)||/^(\()?\d{3}(\))?(-|\s)?\d{3}(-|\s)\d{4}$/.test(b)}],["validate-phoneLax","Please enter a valid phone number (Ex: 123-456-7890).",function(b){return Validation.get("IsEmpty").test(b)||/^((\d[-. ]?)?((\(\d{3}\))|\d{3}))?[-. ]?\d{3}[-. ]?\d{4}$/.test(b)}],["validate-fax","Please enter a valid fax number (Ex: 123-456-7890).",function(b){return Validation.get("IsEmpty").test(b)||/^(\()?\d{3}(\))?(-|\s)?\d{3}(-|\s)\d{4}$/.test(b)}],["validate-date","Please enter a valid date.",function(b){var d=new Date(b);return Validation.get("IsEmpty").test(b)||!isNaN(d)}],["validate-date-range","Make sure the To Date is later than or the same as the From Date.",function(e,h){var d=/\bdate-range-(\w+)-(\w+)\b/.exec(h.className);if(!d||d[2]=="to"||Validation.get("IsEmpty").test(e)){return true}var f=new Date().getFullYear()+"";var b=function(l){l=l.split(/[.\/]/);if(l[2]&&l[2].length<4){l[2]=f.substr(0,l[2].length)+l[2]}return new Date(l.join("/")).getTime()};var g=Element.select(h.form,".validate-date-range.date-range-"+d[1]+"-to");return !g.length||Validation.get("IsEmpty").test(g[0].value)||b(e)<=b(g[0].value)}],["validate-email","Please enter a valid email address (Ex: johndoe@domain.com).",function(b){return Validation.get("IsEmpty").test(b)||/^([a-z0-9,!\#\$%&'\*\+\/=\?\^_`\{\|\}~-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z0-9,!\#\$%&'\*\+\/=\?\^_`\{\|\}~-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*@([a-z0-9-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z0-9-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*\.(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]){2,})$/i.test(b)}],["validate-emailSender","Please use only visible characters and spaces.",function(b){return Validation.get("IsEmpty").test(b)||/^[\S ]+$/.test(b)}],["validate-password","Please enter 6 or more characters. Leading or trailing spaces will be ignored.",function(b){var d=b.strip();return !(d.length>0&&d.length<6)}],["validate-admin-password","Please enter 7 or more characters, using both numeric and alphabetic.",function(b){var d=b.strip();if(0==d.length){return true}if(!(/[a-z]/i.test(b))||!(/[0-9]/.test(b))){return false}return !(d.length<7)}],["validate-cpassword","Please make sure your passwords match.",function(b){var d=$("confirmation")?$("confirmation"):$$(".validate-cpassword")[0];var g=false;if($("password")){g=$("password")}var h=$$(".validate-password");for(var e=0;e<h.size();e++){var f=h[e];if(f.up("form").id==d.up("form").id){g=f}}if($$(".validate-admin-password").size()){g=$$(".validate-admin-password")[0]}return(g.value==d.value)}],["validate-both-passwords","Please make sure your passwords match.",function(e,d){var b=$(d.form[d.name=="password"?"confirmation":"password"]),f=d.value==b.value;if(f&&b.hasClassName("validation-failed")){Validation.test(this.className,b)}return b.value==""||f}],["validate-url","Please enter a valid URL. Protocol is required (http://, https:// or ftp://)",function(b){b=(b||"").replace(/^\s+/,"").replace(/\s+$/,"");return Validation.get("IsEmpty").test(b)||/^(http|https|ftp):\/\/(([A-Z0-9]([A-Z0-9_-]*[A-Z0-9]|))(\.[A-Z0-9]([A-Z0-9_-]*[A-Z0-9]|))*)(:(\d+))?(\/[A-Z0-9~](([A-Z0-9_~-]|\.)*[A-Z0-9~]|))*\/?(.*)?$/i.test(b)}],["validate-clean-url",'Please enter a valid URL (Ex: "http://www.example.com" or "www.example.com").',function(b){return Validation.get("IsEmpty").test(b)||/^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+.(com|org|net|dk|at|us|tv|info|uk|co.uk|biz|se)$)(:(\d+))?\/?/i.test(b)||/^(www)((\.[A-Z0-9][A-Z0-9_-]*)+.(com|org|net|dk|at|us|tv|info|uk|co.uk|biz|se)$)(:(\d+))?\/?/i.test(b)}],["validate-identifier",'Please enter a valid URL Key (Ex: "example-page", "example-page.html" or "anotherlevel/example-page").',function(b){return Validation.get("IsEmpty").test(b)||/^[a-z0-9][a-z0-9_\/-]+(\.[a-z0-9_-]+)?$/.test(b)}],["validate-xml-identifier","Please enter a valid XML-identifier (Ex: something_1, block5, id-4).",function(b){return Validation.get("IsEmpty").test(b)||/^[A-Z][A-Z0-9_\/-]*$/i.test(b)}],["validate-ssn","Please enter a valid social security number (Ex: 123-45-6789).",function(b){return Validation.get("IsEmpty").test(b)||/^\d{3}-?\d{2}-?\d{4}$/.test(b)}],["validate-zip-us","Please enter a valid zip code (Ex: 90602 or 90602-1234).",function(b){return Validation.get("IsEmpty").test(b)||/(^\d{5}$)|(^\d{5}-\d{4}$)/.test(b)}],["validate-zip-international","Please enter a valid zip code.",function(b){return true}],["validate-date-au",'Please use this date format: dd/mm/yyyy (Ex: "17/03/2006" for the 17th of March, 2006).',function(b){if(Validation.get("IsEmpty").test(b)){return true}var e=/^(\d{2})\/(\d{2})\/(\d{4})$/;if(!e.test(b)){return false}var f=new Date(b.replace(e,"$2/$1/$3"));return(parseInt(RegExp.$2,10)==(1+f.getMonth()))&&(parseInt(RegExp.$1,10)==f.getDate())&&(parseInt(RegExp.$3,10)==f.getFullYear())}],["validate-currency-dollar","Please enter a valid $ amount (Ex: $100.00).",function(b){return Validation.get("IsEmpty").test(b)||/^\$?\-?([1-9]{1}[0-9]{0,2}(\,[0-9]{3})*(\.[0-9]{0,2})?|[1-9]{1}\d*(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|(\.[0-9]{1,2})?)$/.test(b)}],["validate-one-required","Please select one of the options above.",function(b,f){var e=f.parentNode;var d=e.getElementsByTagName("INPUT");return $A(d).any(function(g){return $F(g)})}],["validate-one-required-by-name","Please select one of the options.",function(d,g){var b=$$('input[name="'+g.name.replace(/([\\"])/g,"\\$1")+'"]');var e=1;for(var f=0;f<b.length;f++){if((b[f].type=="checkbox"||b[f].type=="radio")&&b[f].checked==true){e=0}if(Validation.isOnChange&&(b[f].type=="checkbox"||b[f].type=="radio")){Validation.reset(b[f])}}if(e==0){return true}else{return false}}],["validate-not-negative-number","Please enter a number 0 or greater in this field.",function(b){if(Validation.get("IsEmpty").test(b)){return true}b=parseNumber(b);return !isNaN(b)&&b>=0}],["validate-zero-or-greater","Please enter a number 0 or greater in this field.",function(b){return Validation.get("validate-not-negative-number").test(b)}],["validate-greater-than-zero","Please enter a number greater than 0 in this field.",function(b){if(Validation.get("IsEmpty").test(b)){return true}b=parseNumber(b);return !isNaN(b)&&b>0}],["validate-state","Please select State/Province.",function(b){return(b!=0||b=="")}],["validate-new-password","Please enter 6 or more characters. Leading or trailing spaces will be ignored.",function(b){if(!Validation.get("validate-password").test(b)){return false}if(Validation.get("IsEmpty").test(b)&&b!=""){return false}return true}],["validate-cc-number","Please enter a valid credit card number.",function(b,e){var d=$(e.id.substr(0,e.id.indexOf("_cc_number"))+"_cc_type");if(d&&typeof Validation.creditCartTypes.get(d.value)!="undefined"&&Validation.creditCartTypes.get(d.value)[2]==false){if(!Validation.get("IsEmpty").test(b)&&Validation.get("validate-digits").test(b)){return true}else{return false}}return validateCreditCard(b)}],["validate-cc-type","Credit card number does not match credit card type.",function(d,g){g.value=removeDelimiters(g.value);d=removeDelimiters(d);var f=$(g.id.substr(0,g.id.indexOf("_cc_number"))+"_cc_type");if(!f){return true}var e=f.value;if(typeof Validation.creditCartTypes.get(e)=="undefined"){return false}if(Validation.creditCartTypes.get(e)[0]==false){return true}var b="";Validation.creditCartTypes.each(function(h){if(h.value[0]&&d.match(h.value[0])){b=h.key;throw $break}});if(b!=e){return false}if(f.hasClassName("validation-failed")&&Validation.isOnChange){Validation.validate(f)}return true}],["validate-cc-type-select","Card type does not match credit card number.",function(d,e){var b=$(e.id.substr(0,e.id.indexOf("_cc_type"))+"_cc_number");if(Validation.isOnChange&&Validation.get("IsEmpty").test(b.value)){return true}if(Validation.get("validate-cc-type").test(b.value,b)){Validation.validate(b)}return Validation.get("validate-cc-type").test(b.value,b)}],["validate-cc-exp","Incorrect credit card expiration date.",function(b,l){var h=b;var g=$(l.id.substr(0,l.id.indexOf("_expiration"))+"_expiration_yr").value;var f=new Date();var e=f.getMonth()+1;var d=f.getFullYear();if(h<e&&g==d){return false}return true}],["validate-cc-cvn","Please enter a valid credit card verification number.",function(b,g){var f=$(g.id.substr(0,g.id.indexOf("_cc_cid"))+"_cc_type");if(!f){return true}var d=f.value;if(typeof Validation.creditCartTypes.get(d)=="undefined"){return false}var e=Validation.creditCartTypes.get(d)[1];if(b.match(e)){return true}return false}],["validate-ajax","",function(b,d){return true}],["validate-data","Please use only letters (a-z or A-Z), numbers (0-9) or underscore (_) in this field, and the first character should be a letter.",function(b){if(b!=""&&b){return/^[A-Za-z]+[A-Za-z0-9_]+$/.test(b)}return true}],["validate-css-length","Please input a valid CSS-length (Ex: 100px, 77pt, 20em, .5ex or 50%).",function(b){if(b!=""&&b){return/^[0-9\.]+(px|pt|em|ex|%)?$/.test(b)&&(!(/\..*\./.test(b)))&&!(/\.$/.test(b))}return true}],["validate-length","Text length does not meet the specified text range.",function(d,g){var e=new RegExp(/^maximum-length-[0-9]+$/);var f=new RegExp(/^minimum-length-[0-9]+$/);var b=true;$w(g.className).each(function(l,h){if(l.match(e)&&b){var n=l.split("-")[2];b=(d.length<=n)}if(l.match(f)&&b&&!Validation.get("IsEmpty").test(d)){var n=l.split("-")[2];b=(d.length>=n)}});return b}],["validate-percents","Please enter a number lower than 100.",{max:100}],["required-file","Please select a file.",function(d,e){var b=!Validation.get("IsEmpty").test(d);if(b===false){ovId=e.id+"_value";if($(ovId)){b=!Validation.get("IsEmpty").test($(ovId).value)}}return b}],["validate-cc-ukss","Please enter issue number or start date for switch/solo card type.",function(o,g){var b;if(g.id.match(/(.)+_cc_issue$/)){b=g.id.indexOf("_cc_issue")}else{if(g.id.match(/(.)+_start_month$/)){b=g.id.indexOf("_start_month")}else{b=g.id.indexOf("_start_year")}}var f=g.id.substr(0,b);var d=$(f+"_cc_type");if(!d){return true}var n=d.value;if(["SS","SM","SO"].indexOf(n)==-1){return true}$(f+"_cc_issue").advaiceContainer=$(f+"_start_month").advaiceContainer=$(f+"_start_year").advaiceContainer=$(f+"_cc_type_ss_div").down(".adv-container");var h=$(f+"_cc_issue").value;var l=$(f+"_start_month").value;var p=$(f+"_start_year").value;var e=(l&&p)?true:false;if(!e&&!h){return false}return true}]]);function removeDelimiters(b){b=b.replace(/\s/g,"");b=b.replace(/\-/g,"");return b}function parseNumber(b){if(typeof b!="string"){return parseFloat(b)}var e=b.indexOf(".");var d=b.indexOf(",");if(e!=-1&&d!=-1){if(d>e){b=b.replace(".","").replace(",",".")}else{b=b.replace(",","")}}else{if(d!=-1){b=b.replace(",",".")}}return parseFloat(b)}Validation.creditCartTypes=$H({SO:[new RegExp("^(6334[5-9]([0-9]{11}|[0-9]{13,14}))|(6767([0-9]{12}|[0-9]{14,15}))$"),new RegExp("^([0-9]{3}|[0-9]{4})?$"),true],SM:[new RegExp("(^(5[0678])[0-9]{11,18}$)|(^(6[^05])[0-9]{11,18}$)|(^(601)[^1][0-9]{9,16}$)|(^(6011)[0-9]{9,11}$)|(^(6011)[0-9]{13,16}$)|(^(65)[0-9]{11,13}$)|(^(65)[0-9]{15,18}$)|(^(49030)[2-9]([0-9]{10}$|[0-9]{12,13}$))|(^(49033)[5-9]([0-9]{10}$|[0-9]{12,13}$))|(^(49110)[1-2]([0-9]{10}$|[0-9]{12,13}$))|(^(49117)[4-9]([0-9]{10}$|[0-9]{12,13}$))|(^(49118)[0-2]([0-9]{10}$|[0-9]{12,13}$))|(^(4936)([0-9]{12}$|[0-9]{14,15}$))"),new RegExp("^([0-9]{3}|[0-9]{4})?$"),true],VI:[new RegExp("^4[0-9]{12}([0-9]{3})?$"),new RegExp("^[0-9]{3}$"),true],MC:[new RegExp("^5[1-5][0-9]{14}$"),new RegExp("^[0-9]{3}$"),true],AE:[new RegExp("^3[47][0-9]{13}$"),new RegExp("^[0-9]{4}$"),true],DI:[new RegExp("^6(011|4[4-9][0-9]|5[0-9]{2})[0-9]{12}$"),new RegExp("^[0-9]{3}$"),true],JCB:[new RegExp("^(3[0-9]{15}|(2131|1800)[0-9]{11})$"),new RegExp("^[0-9]{3,4}$"),true],OT:[false,new RegExp("^([0-9]{3}|[0-9]{4})?$"),false]});function popWin(d,e,b){var e=window.open(d,e,b);e.focus()}function setLocation(b){window.location.href=b}function setPLocation(d,b){if(b){window.opener.focus()}window.opener.location.href=d}function setLanguageCode(e,f){var b=window.location.href;var h="",g;if(g=b.match(/\#(.*)$/)){b=b.replace(/\#(.*)$/,"");h=g[0]}if(b.match(/[?]/)){var d=/([?&]store=)[a-z0-9_]*/;if(b.match(d)){b=b.replace(d,"$1"+e)}else{b+="&store="+e}var d=/([?&]from_store=)[a-z0-9_]*/;if(b.match(d)){b=b.replace(d,"")}}else{b+="?store="+e}if(typeof(f)!="undefined"){b+="&from_store="+f}b+=h;setLocation(b)}function decorateGeneric(h,e){var l=["odd","even","first","last"];var d={};var g=h.length;if(g){if(typeof(e)=="undefined"){e=l}if(!e.length){return}for(var b in l){d[l[b]]=false}for(var b in e){d[e[b]]=true}if(d.first){Element.addClassName(h[0],"first")}if(d.last){Element.addClassName(h[g-1],"last")}for(var f=0;f<g;f++){if((f+1)%2==0){if(d.even){Element.addClassName(h[f],"even")}}else{if(d.odd){Element.addClassName(h[f],"odd")}}}}}function decorateTable(h,e){var h=$(h);if(h){var b={tbody:false,"tbody tr":["odd","even","first","last"],"thead tr":["first","last"],"tfoot tr":["first","last"],"tr td":["last"]};if(typeof(e)!="undefined"){for(var d in e){b[d]=e[d]}}if(b.tbody){decorateGeneric(h.select("tbody"),b.tbody)}if(b["tbody tr"]){decorateGeneric(h.select("tbody tr"),b["tbody tr"])}if(b["thead tr"]){decorateGeneric(h.select("thead tr"),b["thead tr"])}if(b["tfoot tr"]){decorateGeneric(h.select("tfoot tr"),b["tfoot tr"])}if(b["tr td"]){var g=h.select("tr");if(g.length){for(var f=0;f<g.length;f++){decorateGeneric(g[f].getElementsByTagName("TD"),b["tr td"])}}}}}function decorateList(e,d){if($(e)){if(typeof(d)=="undefined"){var b=$(e).select("li")}else{var b=$(e).childElements()}decorateGeneric(b,["odd","even","last"])}}function decorateDataList(b){b=$(b);if(b){decorateGeneric(b.select("dt"),["odd","even","last"]);decorateGeneric(b.select("dd"),["odd","even","last"])}}function parseSidUrl(f,e){var d=f.indexOf("/?SID=");var b="";e=(e!=undefined)?e:"";if(d>-1){b="?"+f.substring(d+2);f=f.substring(0,d+1)}return f+e+b}function formatCurrency(n,q,g){var l=isNaN(q.precision=Math.abs(q.precision))?2:q.precision;var v=isNaN(q.requiredPrecision=Math.abs(q.requiredPrecision))?2:q.requiredPrecision;l=v;var t=isNaN(q.integerRequired=Math.abs(q.integerRequired))?1:q.integerRequired;var p=q.decimalSymbol==undefined?",":q.decimalSymbol;var e=q.groupSymbol==undefined?".":q.groupSymbol;var d=q.groupLength==undefined?3:q.groupLength;var u="";if(g==undefined||g==true){u=n<0?"-":(g?"+":"")}else{if(g==false){u=""}}var h=parseInt(n=Math.abs(+n||0).toFixed(l))+"";var f=(h.length<t)?(t-h.length):0;while(f){h="0"+h;f--}j=(j=h.length)>d?j%d:0;re=new RegExp("(\\d{"+d+"})(?=\\d)","g");var b=(j?h.substr(0,j)+e:"")+h.substr(j).replace(re,"$1"+e)+(l?p+Math.abs(n-h).toFixed(l).replace(/-/,0).slice(2):"");var o="";if(q.pattern.indexOf("{sign}")==-1){o=u+q.pattern}else{o=q.pattern.replace("{sign}",u)}return o.replace("%s",b).replace(/^\s\s*/,"").replace(/\s\s*$/,"")}function expandDetails(d,b){if(Element.hasClassName(d,"show-details")){$$(b).each(function(e){e.hide()});Element.removeClassName(d,"show-details")}else{$$(b).each(function(e){e.show()});Element.addClassName(d,"show-details")}}var isIE=navigator.appVersion.match(/MSIE/)=="MSIE";if(!window.Varien){var Varien=new Object()}Varien.showLoading=function(){var b=$("loading-process");b&&b.show()};Varien.hideLoading=function(){var b=$("loading-process");b&&b.hide()};Varien.GlobalHandlers={onCreate:function(){Varien.showLoading()},onComplete:function(){if(Ajax.activeRequestCount==0){Varien.hideLoading()}}};Ajax.Responders.register(Varien.GlobalHandlers);Varien.searchForm=Class.create();Varien.searchForm.prototype={initialize:function(d,e,b){this.form=$(d);this.field=$(e);this.emptyText=b;Event.observe(this.form,"submit",this.submit.bind(this));Event.observe(this.field,"focus",this.focus.bind(this));Event.observe(this.field,"blur",this.blur.bind(this));this.blur()},submit:function(b){if(this.field.value==this.emptyText||this.field.value==""){Event.stop(b);return false}return true},focus:function(b){if(this.field.value==this.emptyText){this.field.value=""}},blur:function(b){if(this.field.value==""){this.field.value=this.emptyText}}};Varien.DateElement=Class.create();Varien.DateElement.prototype={initialize:function(b,d,f,e){if(b=="id"){this.day=$(d+"day");this.month=$(d+"month");this.year=$(d+"year");this.full=$(d+"full");this.advice=$(d+"date-advice")}else{if(b=="container"){this.day=d.day;this.month=d.month;this.year=d.year;this.full=d.full;this.advice=d.advice}else{return}}this.required=f;this.format=e;this.day.addClassName("validate-custom");this.day.validate=this.validate.bind(this);this.month.addClassName("validate-custom");this.month.validate=this.validate.bind(this);this.year.addClassName("validate-custom");this.year.validate=this.validate.bind(this);this.setDateRange(false,false);this.year.setAttribute("autocomplete","off");this.advice.hide()},validate:function(){var l=false,o=parseInt(this.day.value,10)||0,f=parseInt(this.month.value,10)||0,h=parseInt(this.year.value,10)||0;if(this.day.value.strip().empty()&&this.month.value.strip().empty()&&this.year.value.strip().empty()){if(this.required){l="Please enter a date."}else{this.full.value=""}}else{if(!o||!f||!h){l="Please enter a valid full date."}else{var d=new Date,n=0,e=null;d.setYear(h);d.setMonth(f-1);d.setDate(32);n=32-d.getDate();if(!n||n>31){n=31}if(o<1||o>n){e="day";l="Please enter a valid day (1-%1)."}else{if(f<1||f>12){e="month";l="Please enter a valid month (1-12)."}else{if(o%10==o){this.day.value="0"+o}if(f%10==f){this.month.value="0"+f}this.full.value=this.format.replace(/%[mb]/i,this.month.value).replace(/%[de]/i,this.day.value).replace(/%y/i,this.year.value);var b=this.month.value+"/"+this.day.value+"/"+this.year.value;var g=new Date(b);if(isNaN(g)){l="Please enter a valid date."}else{this.setFullDate(g)}}}var p=false;if(!l&&!this.validateData()){e=this.validateDataErrorType;p=this.validateDataErrorText;l=p}}}if(l!==false){if(jQuery.mage.__){l=jQuery.mage.__(l)}if(!p){this.advice.innerHTML=l.replace("%1",n)}else{this.advice.innerHTML=this.errorTextModifier(l)}this.advice.show();return false}this.day.removeClassName("validation-failed");this.month.removeClassName("validation-failed");this.year.removeClassName("validation-failed");this.advice.hide();return true},validateData:function(){var d=this.fullDate.getFullYear();var b=new Date;this.curyear=b.getFullYear();return(d>=1900&&d<=this.curyear)},validateDataErrorType:"year",validateDataErrorText:"Please enter a valid year (1900-%1).",errorTextModifier:function(b){return b.replace("%1",this.curyear)},setDateRange:function(b,d){this.minDate=b;this.maxDate=d},setFullDate:function(b){this.fullDate=b}};Varien.DOB=Class.create();Varien.DOB.prototype={initialize:function(b,g,f){var e=$$(b)[0];var d={};d.day=Element.select(e,".dob-day input")[0];d.month=Element.select(e,".dob-month input")[0];d.year=Element.select(e,".dob-year input")[0];d.full=Element.select(e,".dob-full input")[0];d.advice=Element.select(e,".validation-advice")[0];new Varien.DateElement("container",d,g,f)}};Varien.dateRangeDate=Class.create();Varien.dateRangeDate.prototype=Object.extend(new Varien.DateElement(),{validateData:function(){var b=true;if(this.minDate||this.maxValue){if(this.minDate){this.minDate=new Date(this.minDate);this.minDate.setHours(0);if(isNaN(this.minDate)){this.minDate=new Date("1/1/1900")}b=b&&(this.fullDate>=this.minDate)}if(this.maxDate){this.maxDate=new Date(this.maxDate);this.minDate.setHours(0);if(isNaN(this.maxDate)){this.maxDate=new Date()}b=b&&(this.fullDate<=this.maxDate)}if(this.maxDate&&this.minDate){this.validateDataErrorText="Please enter a valid date between %s and %s"}else{if(this.maxDate){this.validateDataErrorText="Please enter a valid date less than or equal to %s"}else{if(this.minDate){this.validateDataErrorText="Please enter a valid date equal to or greater than %s"}else{this.validateDataErrorText=""}}}}return b},validateDataErrorText:"Date should be between %s and %s",errorTextModifier:function(b){if(this.minDate){b=b.sub("%s",this.dateFormat(this.minDate))}if(this.maxDate){b=b.sub("%s",this.dateFormat(this.maxDate))}return b},dateFormat:function(b){return(b.getMonth()+1)+"/"+b.getDate()+"/"+b.getFullYear()}});Varien.FileElement=Class.create();Varien.FileElement.prototype={initialize:function(b){this.fileElement=$(b);this.hiddenElement=$(b+"_value");this.fileElement.observe("change",this.selectFile.bind(this))},selectFile:function(b){this.hiddenElement.value=this.fileElement.getValue()}};Validation.addAllThese([["validate-custom"," ",function(b,d){return d.validate()}]]);Element.addMethods({getInnerText:function(b){b=$(b);if(b.innerText&&!Prototype.Browser.Opera){return b.innerText}return b.innerHTML.stripScripts().unescapeHTML().replace(/[\n\r\s]+/g," ").strip()}});function fireEvent(d,e){if(document.createEvent){var b=document.createEvent("HTMLEvents");b.initEvent(e,true,true);return d.dispatchEvent(b)}else{var b=document.createEventObject();return d.fireEvent("on"+e,b)}}function modulo(b,f){var e=f/10000;var d=b%f;if(Math.abs(d-f)<e||Math.abs(d)<e){d=0}return d}if((typeof Range!="undefined")&&!Range.prototype.createContextualFragment){Range.prototype.createContextualFragment=function(b){var e=document.createDocumentFragment(),d=document.createElement("div");e.appendChild(d);d.outerHTML=b;return e}}var byteConvert=function(b){if(isNaN(b)){return""}var d=["bytes","KB","MB","GB","TB","PB","EB","ZB","YB"];var f=Math.floor(Math.log(b)/Math.log(2));if(f<1){f=0}var e=Math.floor(f/10);b=b/Math.pow(2,10*e);if(b.toString().length>b.toFixed(2).toString().length){b=b.toFixed(2)}return b+" "+d[e]};var SessionError=Class.create();SessionError.prototype={initialize:function(b){this.errorText=b},toString:function(){return"Session Error:"+this.errorText}};Ajax.Request.addMethods({initialize:function($super,d,b){$super(b);this.transport=Ajax.getTransport();if(!d.match(new RegExp("[?&]isAjax=true",""))){d=d.match(new RegExp("\\?","g"))?d+"&isAjax=true":d+"?isAjax=true"}if(Object.isString(this.options.parameters)&&this.options.parameters.indexOf("form_key=")==-1){this.options.parameters+="&"+Object.toQueryString({form_key:FORM_KEY})}else{if(!this.options.parameters){this.options.parameters={form_key:FORM_KEY}}if(!this.options.parameters.form_key){this.options.parameters.form_key=FORM_KEY}}this.request(d)},respondToReadyState:function(b){var g=Ajax.Request.Events[b],d=new Ajax.Response(this);if(g=="Complete"){try{this._complete=true;if(d.responseText.isJSON()){var f=d.responseText.evalJSON();if(f.ajaxExpired&&f.ajaxRedirect){window.location.replace(f.ajaxRedirect);throw new SessionError("session expired")}}(this.options["on"+d.status]||this.options["on"+(this.success()?"Success":"Failure")]||Prototype.emptyFunction)(d,d.headerJSON)}catch(h){this.dispatchException(h);if(h instanceof SessionError){return}}var l=d.getHeader("Content-type");if(this.options.evalJS=="force"||(this.options.evalJS&&this.isSameOrigin()&&l&&l.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))){this.evalResponse()}}try{(this.options["on"+g]||Prototype.emptyFunction)(d,d.headerJSON);Ajax.Responders.dispatch("on"+g,this,d,d.headerJSON)}catch(h){this.dispatchException(h)}if(g=="Complete"){this.transport.onreadystatechange=Prototype.emptyFunction}}});Ajax.Updater.respondToReadyState=Ajax.Request.respondToReadyState;var varienLoader=new Class.create();varienLoader.prototype={initialize:function(b){this.callback=false;this.cache=$H();this.caching=b||false;this.url=false},getCache:function(b){if(this.cache.get(b)){return this.cache.get(b)}return false},load:function(b,d,f){this.url=b;this.callback=f;if(this.caching){var e=this.getCache(b);if(e){this.processResult(e);return}}if(typeof(d.updaterId)!="undefined"){new varienUpdater(d.updaterId,b,{evalScripts:true,onComplete:this.processResult.bind(this),onFailure:this._processFailure.bind(this)})}else{new Ajax.Request(b,{method:"post",parameters:d||{},onComplete:this.processResult.bind(this),onFailure:this._processFailure.bind(this)})}},_processFailure:function(b){location.href=BASE_URL},processResult:function(b){if(this.caching){this.cache.set(this.url,b)}if(this.callback){this.callback(b.responseText)}}};if(!window.varienLoaderHandler){var varienLoaderHandler=new Object()}varienLoaderHandler.handler={onCreate:function(b){if(b.options.loaderArea===false){return}jQuery("body").trigger("processStart")},onException:function(b){jQuery("body").trigger("processStop")},onComplete:function(b){jQuery("body").trigger("processStop")}};function setLoaderPosition(){var e=$("loading_mask_loader");if(e&&Prototype.Browser.IE){var d=e.getDimensions();var f=document.viewport.getDimensions();var b=document.viewport.getScrollOffsets();e.style.left=Math.floor(f.width/2+b.left-d.width/2)+"px";e.style.top=Math.floor(f.height/2+b.top-d.height/2)+"px";e.style.position="absolute"}}function toggleSelectsUnderBlock(f,b){if(Prototype.Browser.IE){var e=document.getElementsByTagName("select");for(var d=0;d<e.length;d++){if(b){if(e[d].needShowOnSuccess){e[d].needShowOnSuccess=false;e[d].style.visibility=""}}else{if(Element.visible(e[d])){e[d].style.visibility="hidden";e[d].needShowOnSuccess=true}}}}}Ajax.Responders.register(varienLoaderHandler.handler);var varienUpdater=Class.create(Ajax.Updater,{updateContent:function($super,b){if(b.isJSON()){var d=b.evalJSON();if(d.ajaxExpired&&d.ajaxRedirect){window.location.replace(d.ajaxRedirect)}}else{$super(b)}}});function setLocation(b){window.location.href=b}function setElementDisable(d,b){if($(d)){$(d).disabled=b}}function toggleParentVis(b){b=$(b).parentNode;if(b.style.display=="none"){b.style.display=""}else{b.style.display="none"}}function toggleFieldsetVis(d){id=d;d=$(d);if(d.style.display=="none"){d.style.display=""}else{d.style.display="none"}d=d.parentNode.childElements();for(var b=0;b<d.length;b++){if(d[b].id!=undefined&&d[b].id==id&&d[(b-1)].classNames()=="entry-edit-head"){if(d[b-1].style.display=="none"){d[b-1].style.display=""}else{d[b-1].style.display="none"}}}}function toggleVis(b){b=$(b);if(b.style.display=="none"){b.style.display=""}else{b.style.display="none"}}function imagePreview(b){if($(b)){var d=window.open("","preview","width=400,height=400,resizable=1,scrollbars=1");d.document.open();d.document.write('<body style="padding:0;margin:0"><img src="'+$(b).src+'" id="image_preview"/></body>');d.document.close();Event.observe(d,"load",function(){var e=d.document.getElementById("image_preview");d.resizeTo(e.width+40,e.height+80)})}}function checkByProductPriceType(b){if(b.id=="price_type"){this.productPriceType=b.value;return false}else{if(b.id=="price"&&this.productPriceType==0){return false}return true}}Event.observe(window,"load",function(){if($("price_default")&&$("price_default").checked){$("price").disabled="disabled"}});function toggleSeveralValueElements(f,e,b,d){if(e&&f){if(Object.prototype.toString.call(e)!="[object Array]"){e=[e]}e.each(function(g){toggleValueElements(f,g,b,d)})}}function toggleValueElements(l,d,f,h){if(d&&l){var n=[l];if(typeof f!="undefined"){if(Object.prototype.toString.call(f)!="[object Array]"){f=[f]}for(var g=0;g<f.length;g++){n.push(f[g])}}var e=Element.select(d,["select","input","textarea","button","img"]).filter(function(o){return(o.readAttribute("type")!="hidden")});var b=(h!=undefined?h:l.checked);e.each(function(p){if(checkByProductPriceType(p)){var o=n.length;while(o--&&p!=n[o]){}if(o!=-1){return}p.disabled=b;if(b){p.addClassName("disabled")}else{p.removeClassName("disabled")}if(p.nodeName.toLowerCase()=="img"){b?p.hide():p.show()}}})}}function submitAndReloadArea(e,d){if($(e)){var b=$(e).select("input","select","textarea");var f=Form.serializeElements(b,true);d=d+(d.match(new RegExp("\\?"))?"&isAjax=true":"?isAjax=true");new Ajax.Request(d,{parameters:$H(f),loaderArea:e,onSuccess:function(l){try{if(l.responseText.isJSON()){var g=l.responseText.evalJSON();if(g.error){alert(g.message)}if(g.ajaxExpired&&g.ajaxRedirect){setLocation(g.ajaxRedirect)}}else{$(e).update(l.responseText)}}catch(h){$(e).update(l.responseText)}}})}}function syncOnchangeValue(d,e){var b={baseElem:d,distElem:e};Event.observe(d,"change",function(){if($(this.baseElem)&&$(this.distElem)){$(this.distElem).value=$(this.baseElem).value}}.bind(b))}function updateElementAtCursor(e,f,g){if(g==undefined){g=window.self}if(document.selection){e.focus();sel=g.document.selection.createRange();sel.text=f}else{if(e.selectionStart||e.selectionStart=="0"){var d=e.selectionStart;var b=e.selectionEnd;e.value=e.value.substring(0,d)+f+e.value.substring(b,e.value.length)}else{e.value+=f}}}function firebugEnabled(){if(window.console&&window.console.firebug){return true}return false}function disableElement(b){b.disabled=true;b.addClassName("disabled")}function enableElement(b){b.disabled=false;b.removeClassName("disabled")}function disableElements(b){$$("."+b).each(disableElement)}function enableElements(b){$$("."+b).each(enableElement)}var Cookie={all:function(){var d=document.cookie.split(";");var b={};d.each(function(f,e){var g=f.strip().split("=");b[unescape(g[0])]=unescape(g[1])});return b},read:function(d){var b=this.all();if(b[d]){return b[d]}return null},write:function(h,f,g){var b="";if(g){var e=new Date();e.setTime(e.getTime()+(g*1000));b="; expires="+e.toGMTString()}var d="/"+BASE_URL.split("/").slice(3).join("/");document.cookie=escape(h)+"="+escape(f)+b+"; path="+d},clear:function(b){this.write(b,"",-1)}};var Fieldset={cookiePrefix:"fh-",applyCollapse:function(b){if($(b+"-state")){collapsed=$(b+"-state").value==1?0:1}else{collapsed=$(b+"-head").collapsed}if(collapsed==1||collapsed===undefined){$(b+"-head").removeClassName("open");if($(b+"-head").up(".section-config")){$(b+"-head").up(".section-config").removeClassName("active")}$(b).hide()}else{$(b+"-head").addClassName("open");if($(b+"-head").up(".section-config")){$(b+"-head").up(".section-config").addClassName("active")}$(b).show()}},toggleCollapse:function(b,d){if($(b+"-state")){collapsed=$(b+"-state").value==1?0:1}else{collapsed=$(b+"-head").collapsed}if(collapsed==1||collapsed===undefined){if($(b+"-state")){$(b+"-state").value=1}$(b+"-head").collapsed=0}else{if($(b+"-state")){$(b+"-state").value=0}$(b+"-head").collapsed=1}this.applyCollapse(b);if(typeof d!="undefined"){this.saveState(d,{container:b,value:$(b+"-state").value})}},addToPrefix:function(b){this.cookiePrefix+=b+"-"},saveState:function(b,d){new Ajax.Request(b,{method:"get",parameters:Object.toQueryString(d),loaderArea:false})}};var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(e){var b="";var p,n,h,o,l,g,f;var d=0;if(typeof window.btoa==="function"){return window.btoa(e)}e=Base64._utf8_encode(e);while(d<e.length){p=e.charCodeAt(d++);n=e.charCodeAt(d++);h=e.charCodeAt(d++);o=p>>2;l=((p&3)<<4)|(n>>4);g=((n&15)<<2)|(h>>6);f=h&63;if(isNaN(n)){g=f=64}else{if(isNaN(h)){f=64}}b=b+this._keyStr.charAt(o)+this._keyStr.charAt(l)+this._keyStr.charAt(g)+this._keyStr.charAt(f)}return b},decode:function(e){var b="";var p,n,h;var o,l,g,f;var d=0;if(typeof window.atob==="function"){return window.atob(e)}e=e.replace(/[^A-Za-z0-9\+\/\=]/g,"");while(d<e.length){o=this._keyStr.indexOf(e.charAt(d++));l=this._keyStr.indexOf(e.charAt(d++));g=this._keyStr.indexOf(e.charAt(d++));f=this._keyStr.indexOf(e.charAt(d++));p=(o<<2)|(l>>4);n=((l&15)<<4)|(g>>2);h=((g&3)<<6)|f;b=b+String.fromCharCode(p);if(g!=64){b=b+String.fromCharCode(n)}if(f!=64){b=b+String.fromCharCode(h)}}b=Base64._utf8_decode(b);return b},mageEncode:function(b){return this.encode(b).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,",")},mageDecode:function(b){b=b.replace(/\-/g,"+").replace(/_/g,"/").replace(/,/g,"=");return this.decode(b)},idEncode:function(b){return this.encode(b).replace(/\+/g,":").replace(/\//g,"_").replace(/=/g,"-")},idDecode:function(b){b=b.replace(/\-/g,"=").replace(/_/g,"/").replace(/\:/g,"+");return this.decode(b)},_utf8_encode:function(d){d=d.replace(/\r\n/g,"\n");var b="";for(var f=0;f<d.length;f++){var e=d.charCodeAt(f);if(e<128){b+=String.fromCharCode(e)}else{if((e>127)&&(e<2048)){b+=String.fromCharCode((e>>6)|192);b+=String.fromCharCode((e&63)|128)}else{b+=String.fromCharCode((e>>12)|224);b+=String.fromCharCode(((e>>6)&63)|128);b+=String.fromCharCode((e&63)|128)}}}return b},_utf8_decode:function(b){var d="";var e=0;var f=c1=c2=0;while(e<b.length){f=b.charCodeAt(e);if(f<128){d+=String.fromCharCode(f);e++}else{if((f>191)&&(f<224)){c2=b.charCodeAt(e+1);d+=String.fromCharCode(((f&31)<<6)|(c2&63));e+=2}else{c2=b.charCodeAt(e+1);c3=b.charCodeAt(e+2);d+=String.fromCharCode(((f&15)<<12)|((c2&63)<<6)|(c3&63));e+=3}}}return d}};function sortNumeric(d,b){return d-b}(function(){var globals=["Prototype","Abstract","Try","Class","PeriodicalExecuter","Template","$break","Enumerable","$A","$w","$H","Hash","$R","ObjectRange","Ajax","$","Form","Field","$F","Toggle","Insertion","$continue","Position","Windows","Dialog","array","WindowUtilities","Builder","Effect","validateCreditCard","Validator","Validation","removeDelimiters","parseNumber","popWin","setLocation","setPLocation","setLanguageCode","decorateGeneric","decorateTable","decorateList","decorateDataList","parseSidUrl","formatCurrency","expandDetails","isIE","Varien","fireEvent","modulo","byteConvert","SessionError","varienLoader","varienLoaderHandler","setLoaderPosition","toggleSelectsUnderBlock","varienUpdater","setElementDisable","toggleParentVis","toggleFieldsetVis","toggleVis","imagePreview","checkByProductPriceType","toggleSeveralValueElements","toggleValueElements","submitAndReloadArea","syncOnchangeValue","updateElementAtCursor","firebugEnabled","disableElement","enableElement","disableElements","enableElements","Cookie","Fieldset","Base64","sortNumeric","Element","$$","Sizzle","Selector","Window"];globals.forEach(function(prop){window[prop]=eval(prop)})})(); \ No newline at end of file diff --git a/lib/web/mage/adminhtml/tools.js b/lib/web/mage/adminhtml/tools.js index d936857d8daeec06dd2223537645ebee03d87418..336fc2d4d0c9e0365c855ef793c98cba2d9dcedf 100644 --- a/lib/web/mage/adminhtml/tools.js +++ b/lib/web/mage/adminhtml/tools.js @@ -6,17 +6,6 @@ function setLocation(url){ window.location.href = url; } -function confirmSetLocation(message, url){ - if( confirm(message) ) { - setLocation(url); - } - return false; -} - -function deleteConfirm(message, url) { - confirmSetLocation(message, url); -} - function setElementDisable(element, disable){ if($(element)){ $(element).disabled = disable; diff --git a/lib/web/mage/gallery/gallery.js b/lib/web/mage/gallery/gallery.js index 245f08f824bd9cb0ab063778b0b328e1d96a59a2..75594a9dfd0c5f0a7980b3fcd3830946e4afd24e 100644 --- a/lib/web/mage/gallery/gallery.js +++ b/lib/web/mage/gallery/gallery.js @@ -90,13 +90,15 @@ define([ this.initApi(); this.setupBreakpoints(); this.initFullscreenSettings(); - this.settings.$element.on('click', '.fotorama__stage__frame', function () { - $('[data-gallery-role="gallery"]').data('fotorama').requestFullScreen(); - $('[data-gallery-role="fotorama__fullscreen-icon"]').css({ - opacity: 1, - visibility: 'visible', - display: 'block' - }); + this.settings.$element.on('mouseup', '.fotorama__stage__frame', function () { + if (!$(this).parents('.fotorama__shadows--left').length) { + $('[data-gallery-role="gallery"]').data('fotorama').requestFullScreen(); + $('[data-gallery-role="fotorama__fullscreen-icon"]').css({ + opacity: 1, + visibility: 'visible', + display: 'block' + }); + } }); }, diff --git a/lib/web/mage/utils/compare.js b/lib/web/mage/utils/compare.js index 2cae7362a2109dc86c5f403b3ea661a8913ef38f..c079b087a9d6083cda62277ffe8fac99aaaac5a0 100644 --- a/lib/web/mage/utils/compare.js +++ b/lib/web/mage/utils/compare.js @@ -66,7 +66,8 @@ define([ } /** - * + * @param {String} prefix + * @param {String} part */ function getPath(prefix, part) { return prefix ? prefix + '.' + part : part; @@ -84,7 +85,7 @@ define([ } /** - * + * @param {Array} changes */ function getContainers(changes) { var containers = {}, @@ -108,7 +109,11 @@ define([ } /** - * + * @param {String} path + * @param {String} name + * @param {String} type + * @param {String} newValue + * @param {String} oldValue */ function addChange(path, name, type, newValue, oldValue) { var data; @@ -130,7 +135,11 @@ define([ } /** - * + * @param {String} ns + * @param {String} name + * @param {String} type + * @param {String} iterator + * @param {String} placeholder */ function setAll(ns, name, type, iterator, placeholder) { var key; @@ -156,7 +165,10 @@ define([ /*eslint-disable max-depth*/ /** - * + * @param {Object} old + * @param {Object} current + * @param {String} ns + * @param {String} name */ function compare(old, current, ns, name) { var key, diff --git a/lib/web/mage/validation.js b/lib/web/mage/validation.js index 98240eb8cfa40797c4efd0e6c222397857ddb7bd..982a7ecf73ea05d3536eb3c831184ba5f1b7a008 100644 --- a/lib/web/mage/validation.js +++ b/lib/web/mage/validation.js @@ -1224,6 +1224,17 @@ }, 'Please enter a valid number.' ], + 'required-swatch-entry': [ + function (value, element) { + var empty = $(element).closest('table') + .find('input.required-option') + .filter(function(i, el){ + return $.mage.isEmpty(el.value); + }) + .length; + return empty === 0; + }, 'Admin is a required field in the each row.' + ], 'validate-item-quantity': [ function (value, element, params) { // obtain values for validation diff --git a/lib/web/mage/validation/url.js b/lib/web/mage/validation/url.js index 5361d9522787650bd470d9941153527b192ff781..40fe32c9a5bc9d08207fe8bd3a969b35ff4eb164 100644 --- a/lib/web/mage/validation/url.js +++ b/lib/web/mage/validation/url.js @@ -35,6 +35,8 @@ define([], function () { path.indexOf('vbscript:') !== -1) { return false; } + + return true; }, /** @@ -44,7 +46,7 @@ define([], function () { * @returns {String} */ sanitize: function (path) { - return path.Replace('[^-A-Za-z0-9+&@#/%?=~_|!:,.;\(\)]', ''); + return path.replace('[^-A-Za-z0-9+&@#/%?=~_|!:,.;\(\)]', ''); } }; }); diff --git a/package.json b/package.json index 8869196abeffc1653e34681226e7293a9c71c179..2caa552da3e04113e5edd6a2b733c29a358e5042 100644 --- a/package.json +++ b/package.json @@ -21,9 +21,9 @@ "grunt-contrib-jasmine": "^0.8.1", "grunt-contrib-less": "^0.12.0", "grunt-contrib-watch": "^0.6.1", - "grunt-eslint": "^17.0.0", + "grunt-eslint": "17.3.1", "grunt-exec": "^0.4.6", - "grunt-jscs": "^2.1.0", + "grunt-jscs": "2.2.0", "grunt-replace": "^0.9.2", "grunt-styledocco": "^0.1.4", "grunt-template-jasmine-requirejs": "^0.2.3", diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx index 45bd1d57a1e6bb44efcbea4d81a98f7ea9422134..af73293f01a30ce66daa74a2fdf6bfa3fb0f4376 100644 --- a/setup/performance-toolkit/benchmark.jmx +++ b/setup/performance-toolkit/benchmark.jmx @@ -7,50 +7,246 @@ --> <jmeterTestPlan version="1.2" properties="2.8" jmeter="2.13 r1665067"> <hashTree> - <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Toolkit" enabled="true"> + <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Performance Toolkit" enabled="true"> <stringProp name="TestPlan.comments"></stringProp> <boolProp name="TestPlan.functional_mode">false</boolProp> <boolProp name="TestPlan.serialize_threadgroups">false</boolProp> + <stringProp name="TestPlan.user_define_classpath"></stringProp> <elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true"> <collectionProp name="Arguments.arguments"> - <elementProp name="host" elementType="Argument"> - <stringProp name="Argument.name">host</stringProp> - <stringProp name="Argument.value">${__P(host,localhost)}</stringProp> + <elementProp name="abandonedCartByGuest" elementType="Argument"> + <stringProp name="Argument.name">abandonedCartByGuest</stringProp> + <stringProp name="Argument.value">${__P(abandonedCartByGuest,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="abandonedCartByCustomer" elementType="Argument"> + <stringProp name="Argument.name">abandonedCartByCustomer</stringProp> + <stringProp name="Argument.value">${__P(abandonedCartByCustomer,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="admin_delay" elementType="Argument"> + <stringProp name="Argument.name">admin_delay</stringProp> + <stringProp name="Argument.value">${__P(admin_delay,150)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="admin_enabled" elementType="Argument"> + <stringProp name="Argument.name">admin_enabled</stringProp> + <stringProp name="Argument.value">${__P(admin_enabled,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="admin_password" elementType="Argument"> + <stringProp name="Argument.name">admin_password</stringProp> + <stringProp name="Argument.value">${__P(admin_password,123123q)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="admin_path" elementType="Argument"> + <stringProp name="Argument.name">admin_path</stringProp> + <stringProp name="Argument.value">${__P(admin_path,admin)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="admin_user" elementType="Argument"> + <stringProp name="Argument.name">admin_user</stringProp> + <stringProp name="Argument.value">${__P(admin_user,admin)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="adminBrowseCustomersGridScenario1_ViewOddGridPages" elementType="Argument"> + <stringProp name="Argument.name">adminBrowseCustomersGridScenario1_ViewOddGridPages</stringProp> + <stringProp name="Argument.value">${__P(adminBrowseCustomersGridScenario1_ViewOddGridPages,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="adminBrowseCustomersGridScenario2_ViewEvenGridPages" elementType="Argument"> + <stringProp name="Argument.name">adminBrowseCustomersGridScenario2_ViewEvenGridPages</stringProp> + <stringProp name="Argument.value">${__P(adminBrowseCustomersGridScenario2_ViewEvenGridPages,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="adminBrowseCustomersGridScenario3_Filtering" elementType="Argument"> + <stringProp name="Argument.name">adminBrowseCustomersGridScenario3_Filtering</stringProp> + <stringProp name="Argument.value">${__P(adminBrowseCustomersGridScenario3_Filtering,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="adminBrowseCustomersGridScenario4_Sorting" elementType="Argument"> + <stringProp name="Argument.name">adminBrowseCustomersGridScenario4_Sorting</stringProp> + <stringProp name="Argument.value">${__P(adminBrowseCustomersGridScenario4_Sorting,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="adminBrowseCustomersGridScenario5_FilteringAndSorting" elementType="Argument"> + <stringProp name="Argument.name">adminBrowseCustomersGridScenario5_FilteringAndSorting</stringProp> + <stringProp name="Argument.value">${__P(adminBrowseCustomersGridScenario5_FilteringAndSorting,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="adminBrowseOrdersGridScenario1_ViewOddGridPages" elementType="Argument"> + <stringProp name="Argument.name">adminBrowseOrdersGridScenario1_ViewOddGridPages</stringProp> + <stringProp name="Argument.value">${__P(adminBrowseOrdersGridScenario1_ViewOddGridPages,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="adminBrowseOrdersGridScenario2_ViewEvenGridPages" elementType="Argument"> + <stringProp name="Argument.name">adminBrowseOrdersGridScenario2_ViewEvenGridPages</stringProp> + <stringProp name="Argument.value">${__P(adminBrowseOrdersGridScenario2_ViewEvenGridPages,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="adminBrowseOrdersGridScenario3_Filtering" elementType="Argument"> + <stringProp name="Argument.name">adminBrowseOrdersGridScenario3_Filtering</stringProp> + <stringProp name="Argument.value">${__P(adminBrowseOrdersGridScenario3_Filtering,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="adminBrowseOrdersGridScenario4_Sorting" elementType="Argument"> + <stringProp name="Argument.name">adminBrowseOrdersGridScenario4_Sorting</stringProp> + <stringProp name="Argument.value">${__P(adminBrowseOrdersGridScenario4_Sorting,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="adminBrowseOrdersGridScenario5_FilteringAndSorting" elementType="Argument"> + <stringProp name="Argument.name">adminBrowseOrdersGridScenario5_FilteringAndSorting</stringProp> + <stringProp name="Argument.value">${__P(adminBrowseOrdersGridScenario5_FilteringAndSorting,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="adminBrowseProductsGridScenario1_ViewOddGridPages" elementType="Argument"> + <stringProp name="Argument.name">adminBrowseProductsGridScenario1_ViewOddGridPages</stringProp> + <stringProp name="Argument.value">${__P(adminBrowseProductsGridScenario1_ViewOddGridPages,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="adminBrowseProductsGridScenario2_ViewEvenGridPages" elementType="Argument"> + <stringProp name="Argument.name">adminBrowseProductsGridScenario2_ViewEvenGridPages</stringProp> + <stringProp name="Argument.value">${__P(adminBrowseProductsGridScenario2_ViewEvenGridPages,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="adminBrowseProductsGridScenario3_Filtering" elementType="Argument"> + <stringProp name="Argument.name">adminBrowseProductsGridScenario3_Filtering</stringProp> + <stringProp name="Argument.value">${__P(adminBrowseProductsGridScenario3_Filtering,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="adminBrowseProductsGridScenario4_Sorting" elementType="Argument"> + <stringProp name="Argument.name">adminBrowseProductsGridScenario4_Sorting</stringProp> + <stringProp name="Argument.value">${__P(adminBrowseProductsGridScenario4_Sorting,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="adminBrowseProductsGridScenario5_FilteringAndSorting" elementType="Argument"> + <stringProp name="Argument.name">adminBrowseProductsGridScenario5_FilteringAndSorting</stringProp> + <stringProp name="Argument.value">${__P(adminBrowseProductsGridScenario5_FilteringAndSorting,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="adminCreateOrder" elementType="Argument"> + <stringProp name="Argument.name">adminCreateOrder</stringProp> + <stringProp name="Argument.value">${__P(adminCreateOrder,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="adminCreateProduct" elementType="Argument"> + <stringProp name="Argument.name">adminCreateProduct</stringProp> + <stringProp name="Argument.value">${__P(adminCreateProduct,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="adminEditOrder" elementType="Argument"> + <stringProp name="Argument.name">adminEditOrder</stringProp> + <stringProp name="Argument.value">${__P(adminEditOrder,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="adminEditProduct" elementType="Argument"> + <stringProp name="Argument.name">adminEditProduct</stringProp> + <stringProp name="Argument.value">${__P(adminEditProduct,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="adminExportCustomers" elementType="Argument"> + <stringProp name="Argument.name">adminExportCustomers</stringProp> + <stringProp name="Argument.value">${__P(adminExportCustomers,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="adminExportProducts" elementType="Argument"> + <stringProp name="Argument.name">adminExportProducts</stringProp> + <stringProp name="Argument.value">${__P(adminExportProducts,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="adminImportCustomerBehavior" elementType="Argument"> + <stringProp name="Argument.name">adminImportCustomerBehavior</stringProp> + <stringProp name="Argument.value">${__P(adminImportCustomerBehavior,)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="adminImportCustomerFilePath" elementType="Argument"> + <stringProp name="Argument.name">adminImportCustomerFilePath</stringProp> + <stringProp name="Argument.value">${__P(adminImportCustomerFilePath,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="adminImportCustomers" elementType="Argument"> + <stringProp name="Argument.name">adminImportCustomers</stringProp> + <stringProp name="Argument.value">${__P(adminImportCustomers,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="adminImportProductBehavior" elementType="Argument"> + <stringProp name="Argument.name">adminImportProductBehavior</stringProp> + <stringProp name="Argument.value">${__P(adminImportProductBehavior,)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="adminImportProductFilePath" elementType="Argument"> + <stringProp name="Argument.name">adminImportProductFilePath</stringProp> + <stringProp name="Argument.value">${__P(adminImportProductFilePath,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="adminImportProductFilePath-2" elementType="Argument"> + <stringProp name="Argument.name">adminImportProductFilePath-2</stringProp> + <stringProp name="Argument.value">${__P(adminImportProductFilePath-2,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="adminImportProducts" elementType="Argument"> + <stringProp name="Argument.name">adminImportProducts</stringProp> + <stringProp name="Argument.value">${__P(adminImportProducts,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="bamboo_build_number" elementType="Argument"> + <stringProp name="Argument.name">bamboo_build_number</stringProp> + <stringProp name="Argument.value">${__P(bamboo_build_number,)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> <elementProp name="base_path" elementType="Argument"> <stringProp name="Argument.name">base_path</stringProp> - <stringProp name="Argument.value">${__P(base_path,/)}</stringProp> + <stringProp name="Argument.value">${__P(base_path,)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> - <elementProp name="report_save_path" elementType="Argument"> - <stringProp name="Argument.name">report_save_path</stringProp> - <stringProp name="Argument.value">${__P(report_save_path,./)}</stringProp> + <elementProp name="cache_indicator" elementType="Argument"> + <stringProp name="Argument.name">cache_indicator</stringProp> + <stringProp name="Argument.value">${__P(cache_indicator,0)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> - <elementProp name="ramp_period" elementType="Argument"> - <stringProp name="Argument.name">ramp_period</stringProp> - <stringProp name="Argument.value">${__P(ramp_period,300)}</stringProp> + <elementProp name="catalogBrowsingByGuest" elementType="Argument"> + <stringProp name="Argument.name">catalogBrowsingByGuest</stringProp> + <stringProp name="Argument.value">${__P(catalogBrowsingByGuest,0)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> - <elementProp name="orders" elementType="Argument"> - <stringProp name="Argument.name">orders</stringProp> - <stringProp name="Argument.value">${__P(orders,0)}</stringProp> + <elementProp name="catalogBrowsingByCustomer" elementType="Argument"> + <stringProp name="Argument.name">catalogBrowsingByCustomer</stringProp> + <stringProp name="Argument.value">${__P(catalogBrowsingByCustomer,0)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> - <elementProp name="users" elementType="Argument"> - <stringProp name="Argument.name">users</stringProp> - <stringProp name="Argument.value">${__P(users,100)}</stringProp> + <elementProp name="checkoutByGuest" elementType="Argument"> + <stringProp name="Argument.name">checkoutByGuest</stringProp> + <stringProp name="Argument.value">${__P(checkoutByGuest,0)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> - <elementProp name="view_product_add_to_cart_percent" elementType="Argument"> - <stringProp name="Argument.name">view_product_add_to_cart_percent</stringProp> - <stringProp name="Argument.value">${__P(view_product_add_to_cart_percent,62)}</stringProp> + <elementProp name="checkoutByCustomer" elementType="Argument"> + <stringProp name="Argument.name">checkoutByCustomer</stringProp> + <stringProp name="Argument.value">${__P(checkoutByCustomer,0)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> - <elementProp name="view_catalog_percent" elementType="Argument"> - <stringProp name="Argument.name">view_catalog_percent</stringProp> - <stringProp name="Argument.value">${__P(view_catalog_percent,30)}</stringProp> + <elementProp name="customer_checkout_percent" elementType="Argument"> + <stringProp name="Argument.name">customer_checkout_percent</stringProp> + <stringProp name="Argument.value">${__P(customer_checkout_percent,4)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="customer_limit" elementType="Argument"> + <stringProp name="Argument.name">customer_limit</stringProp> + <stringProp name="Argument.value">${__P(customer_limit,20)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="customer_password" elementType="Argument"> + <stringProp name="Argument.name">customer_password</stringProp> + <stringProp name="Argument.value">123123q</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="customers_page_size" elementType="Argument"> + <stringProp name="Argument.name">customers_page_size</stringProp> + <stringProp name="Argument.value">${__P(customers_page_size,20)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="dashboard_enabled" elementType="Argument"> + <stringProp name="Argument.name">dashboard_enabled</stringProp> + <stringProp name="Argument.value">${__P(dashboard_enabled,0)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> <elementProp name="guest_checkout_percent" elementType="Argument"> @@ -58,9 +254,9 @@ <stringProp name="Argument.value">${__P(guest_checkout_percent,4)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> - <elementProp name="customer_checkout_percent" elementType="Argument"> - <stringProp name="Argument.name">customer_checkout_percent</stringProp> - <stringProp name="Argument.value">${__P(customer_checkout_percent,4)}</stringProp> + <elementProp name="host" elementType="Argument"> + <stringProp name="Argument.name">host</stringProp> + <stringProp name="Argument.value">${__P(host,)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> <elementProp name="loops" elementType="Argument"> @@ -68,695 +264,643 @@ <stringProp name="Argument.value">${__P(loops,1)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> - <elementProp name="customer_password" elementType="Argument"> - <stringProp name="Argument.name">customer_password</stringProp> - <stringProp name="Argument.value">123123q</stringProp> + <elementProp name="orders" elementType="Argument"> + <stringProp name="Argument.name">orders</stringProp> + <stringProp name="Argument.value">${__P(orders,0)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> - <elementProp name="url_suffix" elementType="Argument"> - <stringProp name="Argument.name">url_suffix</stringProp> - <stringProp name="Argument.value">.html</stringProp> + <elementProp name="orders_page_size" elementType="Argument"> + <stringProp name="Argument.name">orders_page_size</stringProp> + <stringProp name="Argument.value">${__P(orders_page_size,20)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> - <elementProp name="admin_path" elementType="Argument"> - <stringProp name="Argument.name">admin_path</stringProp> - <stringProp name="Argument.value">${__P(admin_path,admin)}</stringProp> + <elementProp name="products_page_size" elementType="Argument"> + <stringProp name="Argument.name">products_page_size</stringProp> + <stringProp name="Argument.value">${__P(products_page_size,20)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> - <elementProp name="admin-user" elementType="Argument"> - <stringProp name="Argument.name">admin-user</stringProp> - <stringProp name="Argument.value">${__P(admin-user,admin)}</stringProp> + <elementProp name="ramp_period" elementType="Argument"> + <stringProp name="Argument.name">ramp_period</stringProp> + <stringProp name="Argument.value">${__P(ramp_period,0)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> - <elementProp name="admin-password" elementType="Argument"> - <stringProp name="Argument.name">admin-password</stringProp> - <stringProp name="Argument.value">${__P(admin-password,123123q)}</stringProp> + <elementProp name="redis_host" elementType="Argument"> + <stringProp name="Argument.name">redis_host</stringProp> + <stringProp name="Argument.value">${__P(redis_host,)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> - <elementProp name="website_id" elementType="Argument"> - <stringProp name="Argument.name">website_id</stringProp> - <stringProp name="Argument.value">1</stringProp> + <elementProp name="report_save_path" elementType="Argument"> + <stringProp name="Argument.name">report_save_path</stringProp> + <stringProp name="Argument.value">${__P(report_save_path,./)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="response_time_file_name" elementType="Argument"> + <stringProp name="Argument.name">response_time_file_name</stringProp> + <stringProp name="Argument.value">${__P(response_time_file_name,production.csv)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="scenario" elementType="Argument"> + <stringProp name="Argument.name">scenario</stringProp> + <stringProp name="Argument.value">${__P(scenario,)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="setupAndTearDownThread" elementType="Argument"> + <stringProp name="Argument.name">setupAndTearDownThread</stringProp> + <stringProp name="Argument.value">${__P(setupAndTearDownThread,1)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="sprint_identifier" elementType="Argument"> + <stringProp name="Argument.name">sprint_identifier</stringProp> + <stringProp name="Argument.value">${__P(sprint_identifier,)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="start_time" elementType="Argument"> + <stringProp name="Argument.name">start_time</stringProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="starting_index" elementType="Argument"> + <stringProp name="Argument.name">starting_index</stringProp> + <stringProp name="Argument.value">${__P(starting_index,0)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + <elementProp name="test_duration" elementType="Argument"> + <stringProp name="Argument.name">test_duration</stringProp> + <stringProp name="Argument.value">${__P(test_duration,900)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> <elementProp name="think_time_deviation" elementType="Argument"> <stringProp name="Argument.name">think_time_deviation</stringProp> - <stringProp name="Argument.value">${__P(think_time_deviation, 1000)}</stringProp> + <stringProp name="Argument.value">${__P(think_time_deviation,1000)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> <elementProp name="think_time_delay_offset" elementType="Argument"> <stringProp name="Argument.name">think_time_delay_offset</stringProp> - <stringProp name="Argument.value">${__P(think_time_delay_offset, 2000)}</stringProp> + <stringProp name="Argument.value">${__P(think_time_delay_offset,2000)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> - </collectionProp> - </elementProp> - <stringProp name="TestPlan.user_define_classpath"></stringProp> - <boolProp name="TestPlan.tearDown_on_shutdown">true</boolProp> - </TestPlan> - <hashTree> - <ConfigTestElement guiclass="HttpDefaultsGui" testclass="ConfigTestElement" testname="HTTP Request Defaults" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true"> - <collectionProp name="Arguments.arguments"/> - </elementProp> - <stringProp name="HTTPSampler.domain">${host}</stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding">utf-8</stringProp> - <stringProp name="HTTPSampler.path"></stringProp> - <stringProp name="HTTPSampler.implementation">HttpClient4</stringProp> - <stringProp name="HTTPSampler.concurrentPool">4</stringProp> - </ConfigTestElement> - <hashTree/> - <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> - <collectionProp name="HeaderManager.headers"> - <elementProp name="Accept-Language" elementType="Header"> - <stringProp name="Header.name">Accept-Language</stringProp> - <stringProp name="Header.value">en-US,en;q=0.5</stringProp> + <elementProp name="url_suffix" elementType="Argument"> + <stringProp name="Argument.name">url_suffix</stringProp> + <stringProp name="Argument.value">.html</stringProp> + <stringProp name="Argument.metadata">=</stringProp> </elementProp> - <elementProp name="Accept" elementType="Header"> - <stringProp name="Header.name">Accept</stringProp> - <stringProp name="Header.value">text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8</stringProp> + <elementProp name="users" elementType="Argument"> + <stringProp name="Argument.name">users</stringProp> + <stringProp name="Argument.value">${__P(users,100)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> </elementProp> - <elementProp name="User-Agent" elementType="Header"> - <stringProp name="Header.name">User-Agent</stringProp> - <stringProp name="Header.value">Mozilla/5.0 (Windows NT 6.1; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0</stringProp> + <elementProp name="view_catalog_percent" elementType="Argument"> + <stringProp name="Argument.name">view_catalog_percent</stringProp> + <stringProp name="Argument.value">${__P(view_catalog_percent,62)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> </elementProp> - <elementProp name="Accept-Encoding" elementType="Header"> - <stringProp name="Header.name">Accept-Encoding</stringProp> - <stringProp name="Header.value">gzip, deflate</stringProp> + <elementProp name="view_product_add_to_cart_percent" elementType="Argument"> + <stringProp name="Argument.name">view_product_add_to_cart_percent</stringProp> + <stringProp name="Argument.value">${__P(view_product_add_to_cart_percent,30)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> </elementProp> - </collectionProp> - </HeaderManager> - <hashTree/> - <CookieManager guiclass="CookiePanel" testclass="CookieManager" testname="HTTP Cookie Manager" enabled="true"> - <collectionProp name="CookieManager.cookies"> - <elementProp name="product_list_limit" elementType="Cookie" testname="product_list_limit"> - <stringProp name="Cookie.value">30</stringProp> - <stringProp name="Cookie.domain">${host}</stringProp> - <stringProp name="Cookie.path">/</stringProp> - <boolProp name="Cookie.secure">false</boolProp> - <longProp name="Cookie.expires">0</longProp> - <boolProp name="Cookie.path_specified">true</boolProp> - <boolProp name="Cookie.domain_specified">true</boolProp> + <elementProp name="website_id" elementType="Argument"> + <stringProp name="Argument.name">website_id</stringProp> + <stringProp name="Argument.value">1</stringProp> + <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> - <boolProp name="CookieManager.clearEachIteration">true</boolProp> - </CookieManager> - <hashTree/> - <SetupThreadGroup guiclass="SetupThreadGroupGui" testclass="SetupThreadGroup" testname="setUp Thread Group" enabled="true"> - <stringProp name="ThreadGroup.on_sample_error">stoptest</stringProp> - <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true"> - <boolProp name="LoopController.continue_forever">false</boolProp> - <stringProp name="LoopController.loops">1</stringProp> + </elementProp> + </TestPlan> + <hashTree> + <ConfigTestElement guiclass="HttpDefaultsGui" testclass="ConfigTestElement" testname="HTTP Request Defaults" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain">${host}</stringProp> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol">http</stringProp> + <stringProp name="HTTPSampler.contentEncoding">utf-8</stringProp> + <stringProp name="HTTPSampler.path"/> + <stringProp name="HTTPSampler.implementation">Java</stringProp> + <stringProp name="HTTPSampler.concurrentPool">4</stringProp> + </ConfigTestElement> + <hashTree/> + + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="Accept-Language" elementType="Header"> + <stringProp name="Header.name">Accept-Language</stringProp> + <stringProp name="Header.value">en-US,en;q=0.5</stringProp> </elementProp> - <stringProp name="ThreadGroup.num_threads">1</stringProp> - <stringProp name="ThreadGroup.ramp_time">1</stringProp> - <longProp name="ThreadGroup.start_time">1384333221000</longProp> - <longProp name="ThreadGroup.end_time">1384333221000</longProp> - <boolProp name="ThreadGroup.scheduler">false</boolProp> - <stringProp name="ThreadGroup.duration"></stringProp> - <stringProp name="ThreadGroup.delay"></stringProp> - </SetupThreadGroup> - <hashTree> - <CookieManager guiclass="CookiePanel" testclass="CookieManager" testname="HTTP Cookie Manager" enabled="true"> - <collectionProp name="CookieManager.cookies"> - <elementProp name="product_list_limit" elementType="Cookie" testname="product_list_limit"> - <stringProp name="Cookie.value">30</stringProp> - <stringProp name="Cookie.domain">${host}</stringProp> - <stringProp name="Cookie.path">/</stringProp> - <boolProp name="Cookie.secure">false</boolProp> - <longProp name="Cookie.expires">0</longProp> - <boolProp name="Cookie.path_specified">true</boolProp> - <boolProp name="Cookie.domain_specified">true</boolProp> - </elementProp> - </collectionProp> - <boolProp name="CookieManager.clearEachIteration">true</boolProp> - </CookieManager> - <hashTree/> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="BeanShell Sampler: Clear properties" enabled="true"> - <stringProp name="BeanShellSampler.query">props.remove("category_url_key"); -props.remove("category_name"); -props.remove("simple_products_list"); -props.remove("configurable_products_list"); -props.remove("users"); -props.remove("customer_emails_list");</stringProp> - <stringProp name="BeanShellSampler.filename"></stringProp> - <stringProp name="BeanShellSampler.parameters"></stringProp> - <boolProp name="BeanShellSampler.resetInterpreter">false</boolProp> - </BeanShellSampler> - <hashTree/> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="BeanShell Sampler: validate user defined variables" enabled="true"> - <stringProp name="BeanShellSampler.query">Boolean stopTestOnError (String error) { + <elementProp name="Accept" elementType="Header"> + <stringProp name="Header.name">Accept</stringProp> + <stringProp name="Header.value">text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8</stringProp> + </elementProp> + <elementProp name="User-Agent" elementType="Header"> + <stringProp name="Header.name">User-Agent</stringProp> + <stringProp name="Header.value">Mozilla/5.0 (Windows NT 6.1; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0</stringProp> + </elementProp> + <elementProp name="Accept-Encoding" elementType="Header"> + <stringProp name="Header.name">Accept-Encoding</stringProp> + <stringProp name="Header.value">gzip, deflate</stringProp> + </elementProp> + </collectionProp> + </HeaderManager> + <hashTree/> + + <CookieManager guiclass="CookiePanel" testclass="CookieManager" testname="HTTP Cookie Manager" enabled="true"> + <collectionProp name="CookieManager.cookies"> + <elementProp name="product_list_limit" elementType="Cookie" testname="product_list_limit"> + <stringProp name="Cookie.value">30</stringProp> + <stringProp name="Cookie.domain">${host}</stringProp> + <stringProp name="Cookie.path">/</stringProp> + <boolProp name="Cookie.secure">false</boolProp> + <longProp name="Cookie.expires">0</longProp> + <boolProp name="Cookie.path_specified">true</boolProp> + <boolProp name="Cookie.domain_specified">true</boolProp> + </elementProp> + </collectionProp> + <boolProp name="CookieManager.clearEachIteration">true</boolProp> + </CookieManager> + <hashTree/> + + <SetupThreadGroup guiclass="SetupThreadGroupGui" testclass="SetupThreadGroup" testname="setUp Thread Group" enabled="true"> + <stringProp name="ThreadGroup.on_sample_error">stoptest</stringProp> + <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true"> + <boolProp name="LoopController.continue_forever">false</boolProp> + <stringProp name="LoopController.loops">1</stringProp> + </elementProp> + <stringProp name="ThreadGroup.num_threads">${setupAndTearDownThread}</stringProp> + <stringProp name="ThreadGroup.ramp_time">1</stringProp> + <longProp name="ThreadGroup.start_time">1384333221000</longProp> + <longProp name="ThreadGroup.end_time">1384333221000</longProp> + <boolProp name="ThreadGroup.scheduler">false</boolProp> + <stringProp name="ThreadGroup.duration"/> + <stringProp name="ThreadGroup.delay"/> + </SetupThreadGroup> + <hashTree> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - BeanShell Sampler: Clear properties" enabled="true"> + <stringProp name="BeanShellSampler.query">props.remove("category_url_key"); +props.remove("category_name"); +props.remove("simple_products_list"); +props.remove("configurable_products_list"); +props.remove("users"); +props.remove("customer_emails_list"); + +/* This is only used when admin is enabled. */ +props.put("activeAdminThread", ""); + +/* Set the environment - at this time '01' or '02' */ +String path = "${host}"; +String environment = path.substring(4, 6); +props.put("environment", environment);</stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">false</boolProp> + </BeanShellSampler> + <hashTree/> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - BeanShell Sampler: validate user defined variables" enabled="true"> + <stringProp name="BeanShellSampler.query">Boolean stopTestOnError (String error) { log.error(error); System.out.println(error); SampleResult.setStopTest(true); return false; } -if ("${host}" == "1") { - return stopTestOnError("\"host\" parameter is not defined. Please define host parameter as: \"-Jhost=example.com\""); +if ("${host}" == "1") { + return stopTestOnError("\"host\" parameter is not defined. Please define host parameter as: \"-Jhost=example.com\""); } -if (${users} < 10) { - return stopTestOnError("\"users\" parameter is invalid. Its value must be 10 or greater"); +String path = "${base_path}"; +String slash = "/"; +if (!slash.equals(path.substring(path.length() -1)) || !slash.equals(path.substring(0, 1))) { + return stopTestOnError("\"base_path\" parameter is invalid. It must start and end with \"/\""); } +</stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">false</boolProp> + </BeanShellSampler> + <hashTree/> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="SetUp - Login" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}${admin_path}</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert login form shown" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1397214398">Welcome</stringProp> + <stringProp name="-515240035"><title>Magento Admin</title></stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form key" enabled="true"> + <stringProp name="RegexExtractor.useHeaders">false</stringProp> + <stringProp name="RegexExtractor.refname">admin_form_key</stringProp> + <stringProp name="RegexExtractor.regex"><input name="form_key" type="hidden" value="([^'"]+)" /></stringProp> + <stringProp name="RegexExtractor.template">$1$</stringProp> + <stringProp name="RegexExtractor.default"/> + <stringProp name="RegexExtractor.match_number">1</stringProp> + </RegexExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert form_key extracted" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="2845929">^.+$</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">1</intProp> + <stringProp name="Assertion.scope">variable</stringProp> + <stringProp name="Scope.variable">admin_form_key</stringProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="SetUp - Login Submit Form" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="dummy" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value"/> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">dummy</stringProp> + </elementProp> + <elementProp name="form_key" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${admin_form_key}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">form_key</stringProp> + </elementProp> + <elementProp name="login[password]" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">${admin_password}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">login[password]</stringProp> + </elementProp> + <elementProp name="login[username]" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">${admin_user}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">login[username]</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}${admin_path}/admin/dashboard/</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <stringProp name="HTTPSampler.implementation">Java</stringProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">Implementation needs to be set to Java as per http://stackoverflow.com/questions/19636282/jmeter-error-in-redirect-url-for-get</stringProp> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert logged-in" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1847038912"><title>Dashboard / Magento Admin</title></stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="SetUp - HTTP Request: Admin - Enable All Cache Types" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="form_key" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">${admin_form_key}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">form_key</stringProp> + </elementProp> + <elementProp name="massaction_prepare_key" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">types</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">massaction_prepare_key</stringProp> + </elementProp> + <elementProp name="types" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">config,layout,block_html,collections,db_ddl,eav,config_integration,full_page,translate,config_webservice,config_integration_api</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">types</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}${admin_path}/admin/cache/massEnable</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">Begin by enabling all cache types</stringProp> + </HTTPSamplerProxy> + <hashTree/> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="SetUp - HTTP Request: Admin - Refresh All Cache Types" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="form_key" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">${admin_form_key}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">form_key</stringProp> + </elementProp> + <elementProp name="massaction_prepare_key" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">types</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">massaction_prepare_key</stringProp> + </elementProp> + <elementProp name="types" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">config,layout,block_html,collections,db_ddl,eav,config_integration,full_page,translate,config_webservice,config_integration_api</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">types</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}${admin_path}/admin/cache/massRefresh</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">Refresh all cache types</stringProp> + </HTTPSamplerProxy> + <hashTree/> + <IfController guiclass="IfControllerPanel" testclass="IfController" testname="If Controller: Disable cache type?" enabled="true"> + <stringProp name="IfController.condition">"${cache_indicator}" == "1" || "${cache_indicator}" == "2"</stringProp> + <boolProp name="IfController.evaluateAll">false</boolProp> + </IfController> + <hashTree> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - BeanShell Sampler: resolve cache types" enabled="true"> + <stringProp name="BeanShellSampler.query">// Default to disable all cache types +vars.put("cache_types", "config,layout,block_html,collections,db_ddl,eav,config_integration,full_page,translate,config_webservice,config_integration_api"); -String path = "${base_path}"; -String slash = "/"; -if (!slash.equals(path.substring(path.length() -1)) || !slash.equals(path.substring(0, 1))) { - return stopTestOnError("\"base_path\" parameter is invalid. It must start and end with \"/\""); +if ("${cache_indicator}" == "1") { + // Only disable Full Page Cache + vars.put("cache_types", "full_page"); } </stringProp> - <stringProp name="BeanShellSampler.filename"></stringProp> - <stringProp name="BeanShellSampler.parameters"></stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> <boolProp name="BeanShellSampler.resetInterpreter">false</boolProp> </BeanShellSampler> <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP Request: Open main page (for category extract)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true"> - <collectionProp name="Arguments.arguments"/> - </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol"></stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> - <stringProp name="HTTPSampler.path">${base_path}</stringProp> - <stringProp name="HTTPSampler.method">GET</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - <stringProp name="TestPlan.comments">Site - Get Category 1</stringProp> - </HTTPSamplerProxy> - <hashTree> - <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor: Extarct first category url key" enabled="true"> - <stringProp name="RegexExtractor.useHeaders">false</stringProp> - <stringProp name="RegexExtractor.refname">category_url_key</stringProp> - <stringProp name="RegexExtractor.regex"><a href="http://${host}${base_path}(index.php/)?([^'"]+)${url_suffix}" class="level-top" ></stringProp> - <stringProp name="RegexExtractor.template">$2$</stringProp> - <stringProp name="RegexExtractor.default"></stringProp> - <stringProp name="RegexExtractor.match_number">1</stringProp> - <stringProp name="Scope.variable">simple_product_1_url_key</stringProp> - </RegexExtractor> - <hashTree/> - <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor: Extarct first category name" enabled="true"> - <stringProp name="RegexExtractor.useHeaders">false</stringProp> - <stringProp name="RegexExtractor.refname">category_name</stringProp> - <stringProp name="RegexExtractor.regex"><a href="http://${host}${base_path}(index.php/)?${category_url_key}${url_suffix}" class="level-top" ><span>([^'"]+)</span></stringProp> - <stringProp name="RegexExtractor.template">$2$</stringProp> - <stringProp name="RegexExtractor.default"></stringProp> - <stringProp name="RegexExtractor.match_number">1</stringProp> - <stringProp name="Scope.variable">simple_product_1_url_key</stringProp> - </RegexExtractor> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Responce Assertion: Assert category url" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="484395188">^[a-z0-9-]+$</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">1</intProp> - <stringProp name="Assertion.scope">variable</stringProp> - <stringProp name="Scope.variable">category_url_key</stringProp> - </ResponseAssertion> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Responce Assertion: Assert category name" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="2845929">^.+$</stringProp> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="SetUp - HTTP Request: Admin - Disable Specific Cache Types" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="form_key" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">${admin_form_key}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">form_key</stringProp> + </elementProp> + <elementProp name="massaction_prepare_key" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">types</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">massaction_prepare_key</stringProp> + </elementProp> + <elementProp name="types" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">${cache_types}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">types</stringProp> + </elementProp> </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">1</intProp> - <stringProp name="Assertion.scope">variable</stringProp> - <stringProp name="Scope.variable">category_name</stringProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="BeanShell Sampler: Collect category" enabled="true"> - <stringProp name="BeanShellSampler.query">props.put("category_url_key", vars.get("category_url_key")); -props.put("category_name", vars.get("category_name"));</stringProp> - <stringProp name="BeanShellSampler.filename"></stringProp> - <stringProp name="BeanShellSampler.parameters"></stringProp> - <boolProp name="BeanShellSampler.resetInterpreter">false</boolProp> - </BeanShellSampler> - <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP Request: Search simple products" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true"> - <collectionProp name="Arguments.arguments"/> </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol"></stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> - <stringProp name="HTTPSampler.path">${base_path}catalogsearch/result/index/?limit=30&q=Simple</stringProp> - <stringProp name="HTTPSampler.method">GET</stringProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}${admin_path}/admin/cache/massDisable</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.BROWSER_COMPATIBLE_MULTIPART">true</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> + <stringProp name="HTTPSampler.embedded_url_re"/> </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Responce Assertion: Assert search result" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="-68828613">Search results for: 'Simple'</stringProp> - <stringProp name="1647182604"><div class="search results"></stringProp> + <hashTree/> + </hashTree> + <IfController guiclass="IfControllerPanel" testclass="IfController" testname="If Controller - Cache Validation - All Enabled" enabled="true"> + <stringProp name="IfController.condition">"${cache_indicator}" == "0"</stringProp> + <boolProp name="IfController.evaluateAll">false</boolProp> + </IfController> + <hashTree> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="SetUp - HTTP Request - Cache Validation - All Enabled" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="form_key" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${admin_form_key}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">form_key</stringProp> + <stringProp name="Argument.desc">true</stringProp> + </elementProp> </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor: Extract product url keys" enabled="true"> - <stringProp name="RegexExtractor.useHeaders">false</stringProp> - <stringProp name="RegexExtractor.refname">simple_products_url_keys</stringProp> - <stringProp name="RegexExtractor.regex"><a class="product-item-link"\s*href="http://${host}${base_path}(index.php/)?([^'"]+)${url_suffix}"></stringProp> - <stringProp name="RegexExtractor.template">$2$</stringProp> - <stringProp name="RegexExtractor.default"></stringProp> - <stringProp name="RegexExtractor.match_number">-1</stringProp> - </RegexExtractor> - <hashTree/> - </hashTree> - <ForeachController guiclass="ForeachControlPanel" testclass="ForeachController" testname="ForEach Controller: Simple products loop (search result)" enabled="true"> - <stringProp name="ForeachController.inputVal">simple_products_url_keys</stringProp> - <stringProp name="ForeachController.returnVal">simple_products_url_key</stringProp> - <boolProp name="ForeachController.useSeparator">true</boolProp> - </ForeachController> - <hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP Request: Open Simple product" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"/> - </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> - <stringProp name="HTTPSampler.path">${base_path}${simple_products_url_key}${url_suffix}</stringProp> - <stringProp name="HTTPSampler.method">GET</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <XPathExtractor guiclass="XPathExtractorGui" testclass="XPathExtractor" testname="XPath Extractor: Extarct product id" enabled="true"> - <stringProp name="XPathExtractor.default"></stringProp> - <stringProp name="XPathExtractor.refname">simple_product_id</stringProp> - <stringProp name="XPathExtractor.xpathQuery">.//input[@type="hidden" and @name="product"]/@value</stringProp> - <boolProp name="XPathExtractor.validate">false</boolProp> - <boolProp name="XPathExtractor.tolerant">true</boolProp> - <boolProp name="XPathExtractor.namespace">false</boolProp> - </XPathExtractor> - <hashTree/> - <XPathExtractor guiclass="XPathExtractorGui" testclass="XPathExtractor" testname="XPath Extractor: Extarct product title" enabled="true"> - <stringProp name="XPathExtractor.default"></stringProp> - <stringProp name="XPathExtractor.refname">simple_product_title</stringProp> - <stringProp name="XPathExtractor.xpathQuery">.//*[@data-ui-id='page-title-wrapper']/text()</stringProp> - <boolProp name="XPathExtractor.validate">false</boolProp> - <boolProp name="XPathExtractor.tolerant">true</boolProp> - <boolProp name="XPathExtractor.namespace">false</boolProp> - </XPathExtractor> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Responce Assertion: Assert id" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="89649215">^\d+$</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">1</intProp> - <stringProp name="Assertion.scope">variable</stringProp> - <stringProp name="Scope.variable">simple_product_id</stringProp> - </ResponseAssertion> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Responce Assertion: Assert title" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="2845929">^.+$</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">1</intProp> - <stringProp name="Assertion.scope">variable</stringProp> - <stringProp name="Scope.variable">simple_product_title</stringProp> - </ResponseAssertion> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Responce Assertion: Assert url key" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="484395188">^[a-z0-9-]+$</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">1</intProp> - <stringProp name="Assertion.scope">variable</stringProp> - <stringProp name="Scope.variable">simple_products_url_key</stringProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <CounterConfig guiclass="CounterConfigGui" testclass="CounterConfig" testname="Counter" enabled="true"> - <stringProp name="CounterConfig.start">1</stringProp> - <stringProp name="CounterConfig.end"></stringProp> - <stringProp name="CounterConfig.incr">1</stringProp> - <stringProp name="CounterConfig.name">simple_products_counter</stringProp> - <stringProp name="CounterConfig.format"></stringProp> - <boolProp name="CounterConfig.per_user">false</boolProp> - </CounterConfig> - <hashTree/> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="BeanShell Sampler: Collect simple product" enabled="true"> - <stringProp name="BeanShellSampler.query">import java.util.ArrayList; -import java.util.HashMap; - -// If it is first iteration of cycle then recreate productList -if (1 == Integer.parseInt(vars.get("simple_products_counter"))) { - productList = new ArrayList(); - props.put("simple_products_list", productList); -} else { - productList = props.get("simple_products_list"); -} - -// Create product map -Map productMap = new HashMap(); -productMap.put("id", vars.get("simple_product_id")); -productMap.put("title", vars.get("simple_product_title")); -productMap.put("url_key", vars.get("simple_products_url_key")); - -// Collect products map in products list -productList.add(productMap); </stringProp> - <stringProp name="BeanShellSampler.filename"></stringProp> - <stringProp name="BeanShellSampler.parameters"></stringProp> - <boolProp name="BeanShellSampler.resetInterpreter">false</boolProp> - </BeanShellSampler> - <hashTree/> - </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP Request: Search configurable products" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true"> - <collectionProp name="Arguments.arguments"/> </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol"></stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> - <stringProp name="HTTPSampler.path">${base_path}catalogsearch/result/index/?limit=30&q=Configurable</stringProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}${admin_path}/admin/cache/</stringProp> <stringProp name="HTTPSampler.method">GET</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.BROWSER_COMPATIBLE_MULTIPART">true</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> + <stringProp name="HTTPSampler.embedded_url_re"/> </HTTPSamplerProxy> <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Responce Assertion: Assert search result" enabled="true"> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion - Cache Validation - All Enabled" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="-1354477292">Search results for: 'Configurable'</stringProp> - <stringProp name="1647182604"><div class="search results"></stringProp> + <stringProp name="860336383">TRANSLATE(?s).+?<span>Enabled</span></stringProp> + <stringProp name="1466502763">CONFIG(?s).+?<span>Enabled</span></stringProp> + <stringProp name="-1659688004">LAYOUT_GENERAL_CACHE_TAG(?s).+?<span>Enabled</span></stringProp> + <stringProp name="-21423984">BLOCK_HTML(?s).+?<span>Enabled</span></stringProp> + <stringProp name="593884002">COLLECTION_DATA(?s).+?<span>Enabled</span></stringProp> + <stringProp name="-751452301">EAV(?s).+?<span>Enabled</span></stringProp> + <stringProp name="1611481748">FPC(?s).+?<span>Enabled</span></stringProp> + <stringProp name="846147458">DB_DDL(?s).+?<span>Enabled</span></stringProp> + <stringProp name="-534412103">INTEGRATION(?s).+?<span>Enabled</span></stringProp> + <stringProp name="-72935653">INTEGRATION_API_CONFIG(?s).+?<span>Enabled</span></stringProp> + <stringProp name="330643820">WEBSERVICE(?s).+?<span>Enabled</span></stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> <intProp name="Assertion.test_type">2</intProp> </ResponseAssertion> <hashTree/> - <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor: Extract product url keys" enabled="true"> - <stringProp name="RegexExtractor.useHeaders">false</stringProp> - <stringProp name="RegexExtractor.refname">configurable_products_url_keys</stringProp> - <stringProp name="RegexExtractor.regex"><a class="product-item-link"\s*href="http://${host}${base_path}(index.php/)?([^'"]+)${url_suffix}">\s*Configurable</stringProp> - <stringProp name="RegexExtractor.template">$2$</stringProp> - <stringProp name="RegexExtractor.default"></stringProp> - <stringProp name="RegexExtractor.match_number">-1</stringProp> - </RegexExtractor> - <hashTree/> - </hashTree> - <ForeachController guiclass="ForeachControlPanel" testclass="ForeachController" testname="ForEach Controller: Configurable products loop (search result)" enabled="true"> - <stringProp name="ForeachController.inputVal">configurable_products_url_keys</stringProp> - <stringProp name="ForeachController.returnVal">configurable_products_url_key</stringProp> - <boolProp name="ForeachController.useSeparator">true</boolProp> - </ForeachController> - <hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP Request: Open Configurable product" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"/> - </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> - <stringProp name="HTTPSampler.path">${base_path}${configurable_products_url_key}${url_suffix}</stringProp> - <stringProp name="HTTPSampler.method">GET</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <XPathExtractor guiclass="XPathExtractorGui" testclass="XPathExtractor" testname="XPath Extractor: Extarct product id" enabled="true"> - <stringProp name="XPathExtractor.default"></stringProp> - <stringProp name="XPathExtractor.refname">configurable_product_id</stringProp> - <stringProp name="XPathExtractor.xpathQuery">.//input[@type="hidden" and @name="product"]/@value</stringProp> - <boolProp name="XPathExtractor.validate">false</boolProp> - <boolProp name="XPathExtractor.tolerant">true</boolProp> - <boolProp name="XPathExtractor.namespace">false</boolProp> - </XPathExtractor> - <hashTree/> - <XPathExtractor guiclass="XPathExtractorGui" testclass="XPathExtractor" testname="XPath Extractor: Extarct product title" enabled="true"> - <stringProp name="XPathExtractor.default"></stringProp> - <stringProp name="XPathExtractor.refname">configurable_product_title</stringProp> - <stringProp name="XPathExtractor.xpathQuery">.//*[@data-ui-id='page-title-wrapper']/text()</stringProp> - <boolProp name="XPathExtractor.validate">false</boolProp> - <boolProp name="XPathExtractor.tolerant">true</boolProp> - <boolProp name="XPathExtractor.namespace">false</boolProp> - </XPathExtractor> - <hashTree/> - <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor: Extarct product attribute id" enabled="true"> - <stringProp name="RegexExtractor.useHeaders">false</stringProp> - <stringProp name="RegexExtractor.refname">configurable_product_attribute_id</stringProp> - <stringProp name="RegexExtractor.regex">"attributes":\{"(\d+)"</stringProp> - <stringProp name="RegexExtractor.template">$1$</stringProp> - <stringProp name="RegexExtractor.default"></stringProp> - <stringProp name="RegexExtractor.match_number">1</stringProp> - </RegexExtractor> - <hashTree/> - <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor: Extarct product attribute option id" enabled="true"> - <stringProp name="RegexExtractor.useHeaders">false</stringProp> - <stringProp name="RegexExtractor.refname">configurable_product_attribute_option_id</stringProp> - <stringProp name="RegexExtractor.regex">"options":\[\{"id":"(\d+)"</stringProp> - <stringProp name="RegexExtractor.template">$1$</stringProp> - <stringProp name="RegexExtractor.default"></stringProp> - <stringProp name="RegexExtractor.match_number">1</stringProp> - </RegexExtractor> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Responce Assertion: Assert id" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="89649215">^\d+$</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">1</intProp> - <stringProp name="Assertion.scope">variable</stringProp> - <stringProp name="Scope.variable">configurable_product_id</stringProp> - </ResponseAssertion> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Responce Assertion: Assert title" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="2845929">^.+$</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">1</intProp> - <stringProp name="Assertion.scope">variable</stringProp> - <stringProp name="Scope.variable">configurable_product_title</stringProp> - </ResponseAssertion> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Responce Assertion: Assert url key" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="484395188">^[a-z0-9-]+$</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">1</intProp> - <stringProp name="Assertion.scope">variable</stringProp> - <stringProp name="Scope.variable">configurable_products_url_key</stringProp> - </ResponseAssertion> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion: Assert attribute id" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="89649215">^\d+$</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">1</intProp> - <stringProp name="Assertion.scope">variable</stringProp> - <stringProp name="Scope.variable">configurable_product_attribute_id</stringProp> - </ResponseAssertion> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion: Assert attribute option id" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="89649215">^\d+$</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">1</intProp> - <stringProp name="Assertion.scope">variable</stringProp> - <stringProp name="Scope.variable">configurable_product_attribute_option_id</stringProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <CounterConfig guiclass="CounterConfigGui" testclass="CounterConfig" testname="Counter" enabled="true"> - <stringProp name="CounterConfig.start">1</stringProp> - <stringProp name="CounterConfig.end"></stringProp> - <stringProp name="CounterConfig.incr">1</stringProp> - <stringProp name="CounterConfig.name">configurable_products_counter</stringProp> - <stringProp name="CounterConfig.format"></stringProp> - <boolProp name="CounterConfig.per_user">false</boolProp> - </CounterConfig> - <hashTree/> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="BeanShell Sampler: Collect configurable product" enabled="true"> - <stringProp name="BeanShellSampler.query">import java.util.ArrayList; -import java.util.HashMap; - -// If it is first iteration of cycle then recreate productList -if (1 == Integer.parseInt(vars.get("configurable_products_counter"))) { - productList = new ArrayList(); - props.put("configurable_products_list", productList); -} else { - productList = props.get("configurable_products_list"); -} - -// Create product map -Map productMap = new HashMap(); -productMap.put("id", vars.get("configurable_product_id")); -productMap.put("title", vars.get("configurable_product_title")); -productMap.put("url_key", vars.get("configurable_products_url_key")); -productMap.put("attribute_id", vars.get("configurable_product_attribute_id")); -productMap.put("attribute_option_id", vars.get("configurable_product_attribute_option_id")); - -// Collect products map in products list -productList.add(productMap); </stringProp> - <stringProp name="BeanShellSampler.filename"></stringProp> - <stringProp name="BeanShellSampler.parameters"></stringProp> - <boolProp name="BeanShellSampler.resetInterpreter">false</boolProp> - </BeanShellSampler> - <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Admin - Login" enabled="true"> + </hashTree> + <IfController guiclass="IfControllerPanel" testclass="IfController" testname="If Controller - Cache Validation - Only FPC Disabled" enabled="true"> + <stringProp name="IfController.condition">"${cache_indicator}" == "1"</stringProp> + <boolProp name="IfController.evaluateAll">false</boolProp> + </IfController> + <hashTree> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="SetUp - HTTP Request - Cache Validation - Only FPC Disabled" enabled="true"> <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"/> + <collectionProp name="Arguments.arguments"> + <elementProp name="form_key" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${admin_form_key}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">form_key</stringProp> + <stringProp name="Argument.desc">true</stringProp> + </elementProp> + </collectionProp> </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> - <stringProp name="HTTPSampler.path">${base_path}${admin_path}</stringProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}${admin_path}/admin/cache/</stringProp> <stringProp name="HTTPSampler.method">GET</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.BROWSER_COMPATIBLE_MULTIPART">true</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> + <stringProp name="HTTPSampler.embedded_url_re"/> </HTTPSamplerProxy> <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert login form shown" enabled="true"> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion - Cache Validation - All Disabled" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="-1397214398">Welcome</stringProp> - <stringProp name="-515240035"><title>Magento Admin</title></stringProp> + <stringProp name="860336383">TRANSLATE(?s).+?<span>Enabled</span></stringProp> + <stringProp name="1466502763">CONFIG(?s).+?<span>Enabled</span></stringProp> + <stringProp name="-1659688004">LAYOUT_GENERAL_CACHE_TAG(?s).+?<span>Enabled</span></stringProp> + <stringProp name="-21423984">BLOCK_HTML(?s).+?<span>Enabled</span></stringProp> + <stringProp name="593884002">COLLECTION_DATA(?s).+?<span>Enabled</span></stringProp> + <stringProp name="-751452301">EAV(?s).+?<span>Enabled</span></stringProp> + <stringProp name="-2075232047">FPC(?s).+?<span>Disabled</span></stringProp> + <stringProp name="846147458">DB_DDL(?s).+?<span>Enabled</span></stringProp> + <stringProp name="-534412103">INTEGRATION(?s).+?<span>Enabled</span></stringProp> + <stringProp name="-72935653">INTEGRATION_API_CONFIG(?s).+?<span>Enabled</span></stringProp> + <stringProp name="330643820">WEBSERVICE(?s).+?<span>Enabled</span></stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> <intProp name="Assertion.test_type">2</intProp> </ResponseAssertion> <hashTree/> - <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form key" enabled="true"> - <stringProp name="RegexExtractor.useHeaders">false</stringProp> - <stringProp name="RegexExtractor.refname">admin_form_key</stringProp> - <stringProp name="RegexExtractor.regex"><input name="form_key" type="hidden" value="([^'"]+)" /></stringProp> - <stringProp name="RegexExtractor.template">$1$</stringProp> - <stringProp name="RegexExtractor.default"></stringProp> - <stringProp name="RegexExtractor.match_number">1</stringProp> - </RegexExtractor> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert form_key extracted" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="2845929">^.+$</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">1</intProp> - <stringProp name="Assertion.scope">variable</stringProp> - <stringProp name="Scope.variable">admin_form_key</stringProp> - </ResponseAssertion> - <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Admin - Login Submit Form" enabled="true"> + </hashTree> + <IfController guiclass="IfControllerPanel" testclass="IfController" testname="If Controller - Cache Validation - All Disabled" enabled="true"> + <stringProp name="IfController.condition">"${cache_indicator}" == "2"</stringProp> + <boolProp name="IfController.evaluateAll">false</boolProp> + </IfController> + <hashTree> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="SetUp - HTTP Request - Cache Validation - All Disabled" enabled="true"> <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> <collectionProp name="Arguments.arguments"> - <elementProp name="dummy" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value"></stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">dummy</stringProp> - </elementProp> <elementProp name="form_key" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> <stringProp name="Argument.value">${admin_form_key}</stringProp> <stringProp name="Argument.metadata">=</stringProp> <boolProp name="HTTPArgument.use_equals">true</boolProp> <stringProp name="Argument.name">form_key</stringProp> - </elementProp> - <elementProp name="login[password]" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">true</boolProp> - <stringProp name="Argument.value">${admin-password}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">login[password]</stringProp> - </elementProp> - <elementProp name="login[username]" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">true</boolProp> - <stringProp name="Argument.value">${admin-user}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">login[username]</stringProp> + <stringProp name="Argument.desc">true</stringProp> </elementProp> </collectionProp> </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> - <stringProp name="HTTPSampler.path">${base_path}${admin_path}</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}${admin_path}/admin/cache/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.BROWSER_COMPATIBLE_MULTIPART">true</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> + <stringProp name="HTTPSampler.embedded_url_re"/> </HTTPSamplerProxy> <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert logged-in" enabled="true"> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion - Cache Validation - All Disabled" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="1847038912"><title>Dashboard / Magento Admin</title></stringProp> + <stringProp name="409065414">TRANSLATE(?s).+?<span>Disabled</span></stringProp> + <stringProp name="2020354010">CONFIG(?s).+?<span>Disabled</span></stringProp> + <stringProp name="-402279255">LAYOUT_GENERAL_CACHE_TAG(?s).+?<span>Disabled</span></stringProp> + <stringProp name="-1155702187">BLOCK_HTML(?s).+?<span>Disabled</span></stringProp> + <stringProp name="738976195">COLLECTION_DATA(?s).+?<span>Disabled</span></stringProp> + <stringProp name="1983223762">EAV(?s).+?<span>Disabled</span></stringProp> + <stringProp name="-2075232047">FPC(?s).+?<span>Disabled</span></stringProp> + <stringProp name="-30791261">DB_DDL(?s).+?<span>Disabled</span></stringProp> + <stringProp name="121535308">INTEGRATION(?s).+?<span>Disabled</span></stringProp> + <stringProp name="1542403370">INTEGRATION_API_CONFIG(?s).+?<span>Disabled</span></stringProp> + <stringProp name="1168465145">WEBSERVICE(?s).+?<span>Disabled</span></stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> @@ -764,2814 +908,6506 @@ productList.add(productMap); </stringProp> </ResponseAssertion> <hashTree/> </hashTree> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Admin - Open Customer Grid" enabled="true"> + </hashTree> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="SetUp - HTTP Request: Open main page (for category extract)" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + <stringProp name="TestPlan.comments">Site - Get Category 1</stringProp> + </HTTPSamplerProxy> + <hashTree> + <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor: Extract first category url key" enabled="true"> + <stringProp name="RegexExtractor.useHeaders">false</stringProp> + <stringProp name="RegexExtractor.refname">category_url_key</stringProp> + <stringProp name="RegexExtractor.regex"><a href="http://${host}${base_path}(index.php/)?([^'"]+)${url_suffix}" class="level-top" ></stringProp> + <stringProp name="RegexExtractor.template">$2$</stringProp> + <stringProp name="RegexExtractor.default"/> + <stringProp name="RegexExtractor.match_number">1</stringProp> + <stringProp name="Scope.variable">simple_product_1_url_key</stringProp> + </RegexExtractor> + <hashTree/> + <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor: Extract first category name" enabled="true"> + <stringProp name="RegexExtractor.useHeaders">false</stringProp> + <stringProp name="RegexExtractor.refname">category_name</stringProp> + <stringProp name="RegexExtractor.regex"><a href="http://${host}${base_path}(index.php/)?${category_url_key}${url_suffix}" class="level-top" ><span>([^'"]+)</span></stringProp> + <stringProp name="RegexExtractor.template">$2$</stringProp> + <stringProp name="RegexExtractor.default"/> + <stringProp name="RegexExtractor.match_number">1</stringProp> + <stringProp name="Scope.variable">simple_product_1_url_key</stringProp> + </RegexExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion: Assert category url" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="484395188">^[a-z0-9-]+$</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">1</intProp> + <stringProp name="Assertion.scope">variable</stringProp> + <stringProp name="Scope.variable">category_url_key</stringProp> + </ResponseAssertion> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion: Assert category name" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="2845929">^.+$</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">1</intProp> + <stringProp name="Assertion.scope">variable</stringProp> + <stringProp name="Scope.variable">category_name</stringProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - BeanShell Sampler: Collect category" enabled="true"> + <stringProp name="BeanShellSampler.query">props.put("category_url_key", vars.get("category_url_key")); +props.put("category_name", vars.get("category_name"));</stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">false</boolProp> + </BeanShellSampler> + <hashTree/> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="SetUp - HTTP Request: Search simple products" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}catalogsearch/result/?limit=30&q=Simple</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion: Assert search result" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1297547762">(?i)Search results for: 'Simple'</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor: Extract product url keys" enabled="true"> + <stringProp name="RegexExtractor.useHeaders">false</stringProp> + <stringProp name="RegexExtractor.refname">simple_products_url_keys</stringProp> + <stringProp name="RegexExtractor.regex"><a class="product-item-link"(?s).+?href="http://${host}${base_path}(index.php/)?([^'"]+)${url_suffix}">(?s).+?Simple</stringProp> + <stringProp name="RegexExtractor.template">$2$</stringProp> + <stringProp name="RegexExtractor.default"/> + <stringProp name="RegexExtractor.match_number">-1</stringProp> + </RegexExtractor> + <hashTree/> + </hashTree> + <ForeachController guiclass="ForeachControlPanel" testclass="ForeachController" testname="ForEach Controller: Simple products loop (search result)" enabled="true"> + <stringProp name="ForeachController.inputVal">simple_products_url_keys</stringProp> + <stringProp name="ForeachController.returnVal">simple_products_url_key</stringProp> + <boolProp name="ForeachController.useSeparator">true</boolProp> + </ForeachController> + <hashTree> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="SetUp - HTTP Request: Open Simple product" enabled="true"> <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> <collectionProp name="Arguments.arguments"/> </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> - <stringProp name="HTTPSampler.path">${base_path}${admin_path}/customer/index/</stringProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}${simple_products_url_key}${url_suffix}</stringProp> <stringProp name="HTTPSampler.method">GET</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> + <stringProp name="HTTPSampler.embedded_url_re"/> </HTTPSamplerProxy> <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert Customer Grid" enabled="true"> + <XPathExtractor guiclass="XPathExtractorGui" testclass="XPathExtractor" testname="XPath Extractor: Extract product id" enabled="true"> + <stringProp name="XPathExtractor.default"/> + <stringProp name="XPathExtractor.refname">simple_product_id</stringProp> + <stringProp name="XPathExtractor.xpathQuery">.//input[@type="hidden" and @name="product"]/@value</stringProp> + <boolProp name="XPathExtractor.validate">false</boolProp> + <boolProp name="XPathExtractor.tolerant">true</boolProp> + <boolProp name="XPathExtractor.namespace">false</boolProp> + </XPathExtractor> + <hashTree/> + <XPathExtractor guiclass="XPathExtractorGui" testclass="XPathExtractor" testname="XPath Extractor: Extract product title" enabled="true"> + <stringProp name="XPathExtractor.default"/> + <stringProp name="XPathExtractor.refname">simple_product_title</stringProp> + <stringProp name="XPathExtractor.xpathQuery">.//*[@data-ui-id='page-title-wrapper']/text()</stringProp> + <boolProp name="XPathExtractor.validate">false</boolProp> + <boolProp name="XPathExtractor.tolerant">true</boolProp> + <boolProp name="XPathExtractor.namespace">false</boolProp> + </XPathExtractor> + <hashTree/> + <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor: Extract uenc" enabled="true"> + <stringProp name="RegexExtractor.useHeaders">false</stringProp> + <stringProp name="RegexExtractor.refname">simple_product_uenc</stringProp> + <stringProp name="RegexExtractor.regex">${base_path}checkout/cart/add/uenc/([^/]+)/product/</stringProp> + <stringProp name="RegexExtractor.template">$1$</stringProp> + <stringProp name="RegexExtractor.default"/> + <stringProp name="RegexExtractor.match_number">1</stringProp> + <stringProp name="Scope.variable">simple_product_1_url_key</stringProp> + </RegexExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion: Assert id" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="-679437259">Customers</stringProp> - <stringProp name="495525733"><title>Customers / Customers / Magento Admin</title></stringProp> + <stringProp name="89649215">^\d+$</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> + <intProp name="Assertion.test_type">1</intProp> + <stringProp name="Assertion.scope">variable</stringProp> + <stringProp name="Scope.variable">simple_product_id</stringProp> </ResponseAssertion> <hashTree/> - </hashTree> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="Admin - Prepare Customers search Data" enabled="true"> - <stringProp name="BeanShellSampler.query">import org.apache.jmeter.protocol.http.util.Base64Encoder; -String searchData = "customer_since[locale]=en_US&website_id=1"; -vars.put("searchData", new String(Base64Encoder.encode(searchData)));</stringProp> - <stringProp name="BeanShellSampler.filename"></stringProp> - <stringProp name="BeanShellSampler.parameters"></stringProp> - <boolProp name="BeanShellSampler.resetInterpreter">false</boolProp> - </BeanShellSampler> - <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Admin - Search Customers" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"> - <elementProp name="ajax" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">true</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">ajax</stringProp> - </elementProp> - <elementProp name="isAjax" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">true</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">isAjax</stringProp> - </elementProp> - <elementProp name="form_key" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">${admin_form_key}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">form_key</stringProp> - </elementProp> - <elementProp name="internal_customer" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value"></stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">internal_customer</stringProp> - </elementProp> - </collectionProp> - </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> - <stringProp name="HTTPSampler.path">${base_path}${admin_path}/customer/index/grid/limit/${users}/filter/${searchData}</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion: Assert title" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="-1083053965">We couldn't find any records.</stringProp> + <stringProp name="2845929">^.+$</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">6</intProp> + <intProp name="Assertion.test_type">1</intProp> + <stringProp name="Assertion.scope">variable</stringProp> + <stringProp name="Scope.variable">simple_product_title</stringProp> </ResponseAssertion> <hashTree/> - <XPathAssertion guiclass="XPathAssertionGui" testclass="XPathAssertion" testname="XPath Assertion" enabled="true"> - <boolProp name="XPath.negate">false</boolProp> - <stringProp name="XPath.xpath">//table[@id='customerGrid_table']//tr[@data-role='row']</stringProp> - <boolProp name="XPath.validate">false</boolProp> - <boolProp name="XPath.whitespace">false</boolProp> - <boolProp name="XPath.tolerant">true</boolProp> - <boolProp name="XPath.namespace">false</boolProp> - <boolProp name="XPath.show_warnings">true</boolProp> - <boolProp name="XPath.report_errors">true</boolProp> - </XPathAssertion> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion: Assert url key" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="484395188">^[a-z0-9-]+$</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">1</intProp> + <stringProp name="Assertion.scope">variable</stringProp> + <stringProp name="Scope.variable">simple_products_url_key</stringProp> + </ResponseAssertion> <hashTree/> - <XPathExtractor guiclass="XPathExtractorGui" testclass="XPathExtractor" testname="XPath Extractor" enabled="true"> - <stringProp name="XPathExtractor.default"></stringProp> - <stringProp name="XPathExtractor.refname">customer_emails</stringProp> - <stringProp name="XPathExtractor.xpathQuery">//*[@id='customerGrid_table']//td[@data-column='email']/text()</stringProp> - <boolProp name="XPathExtractor.validate">false</boolProp> - <boolProp name="XPathExtractor.tolerant">true</boolProp> - <boolProp name="XPathExtractor.namespace">false</boolProp> - <boolProp name="XPathExtractor.show_warnings">true</boolProp> - <boolProp name="XPathExtractor.report_errors">true</boolProp> - </XPathExtractor> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion: Assert uenc" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="824150030">^[\w\,]+$</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">1</intProp> + <stringProp name="Assertion.scope">variable</stringProp> + <stringProp name="Scope.variable">simple_product_uenc</stringProp> + </ResponseAssertion> <hashTree/> </hashTree> - <ForeachController guiclass="ForeachControlPanel" testclass="ForeachController" testname="ForEach Controller: customer emails loop (search result)" enabled="true"> - <stringProp name="ForeachController.inputVal">customer_emails</stringProp> - <stringProp name="ForeachController.returnVal">customer_email</stringProp> - <boolProp name="ForeachController.useSeparator">true</boolProp> - </ForeachController> - <hashTree> - <CounterConfig guiclass="CounterConfigGui" testclass="CounterConfig" testname="Counter" enabled="true"> - <stringProp name="CounterConfig.start">1</stringProp> - <stringProp name="CounterConfig.end"></stringProp> - <stringProp name="CounterConfig.incr">1</stringProp> - <stringProp name="CounterConfig.name">email_counter</stringProp> - <stringProp name="CounterConfig.format"></stringProp> - <boolProp name="CounterConfig.per_user">false</boolProp> - </CounterConfig> - <hashTree/> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="BeanShell Sampler: Collect customer emails" enabled="true"> - <stringProp name="BeanShellSampler.query">import java.util.ArrayList; + <CounterConfig guiclass="CounterConfigGui" testclass="CounterConfig" testname="Counter" enabled="true"> + <stringProp name="CounterConfig.start">1</stringProp> + <stringProp name="CounterConfig.end"/> + <stringProp name="CounterConfig.incr">1</stringProp> + <stringProp name="CounterConfig.name">simple_products_counter</stringProp> + <stringProp name="CounterConfig.format"/> + <boolProp name="CounterConfig.per_user">false</boolProp> + </CounterConfig> + <hashTree/> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - BeanShell Sampler: Collect simple product" enabled="true"> + <stringProp name="BeanShellSampler.query">import java.util.ArrayList; +import java.util.HashMap; -// If it is first iteration of cycle then recreate emailsList -if (1 == Integer.parseInt(vars.get("email_counter"))) { - emailsList = new ArrayList(); - props.put("customer_emails_list", emailsList); +// If it is first iteration of cycle then recreate productList +if (1 == Integer.parseInt(vars.get("simple_products_counter"))) { + productList = new ArrayList(); + props.put("simple_products_list", productList); } else { - emailsList = props.get("customer_emails_list"); -} -emailsList.add(vars.get("customer_email"));</stringProp> - <stringProp name="BeanShellSampler.filename"></stringProp> - <stringProp name="BeanShellSampler.parameters"></stringProp> - <boolProp name="BeanShellSampler.resetInterpreter">false</boolProp> - </BeanShellSampler> - <hashTree/> - </hashTree> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="BeanShell Sampler: Validate properties and count users" enabled="true"> - <stringProp name="BeanShellSampler.query">Boolean stopTestOnError (String error) { - log.error(error); - System.out.println(error); - SampleResult.setStopTest(true); - return false; + productList = props.get("simple_products_list"); } -if (props.get("simple_products_list") == null) { - return stopTestOnError("Cannot find simple products. Test stopped."); -} -if (props.get("configurable_products_list") == null) { - return stopTestOnError("Cannot find configurable products. Test stopped."); -} -if (props.get("customer_emails_list") == null) { - return stopTestOnError("Cannot find customer emails. Test stopped."); -} -int orders = Integer.parseInt(vars.get("orders")); +// Create product map +Map productMap = new HashMap(); +productMap.put("id", vars.get("simple_product_id")); +productMap.put("title", vars.get("simple_product_title")); +productMap.put("url_key", vars.get("simple_products_url_key")); +productMap.put("uenc", vars.get("simple_product_uenc")); -if (orders > 0) { - int checkout_sum = Integer.parseInt(vars.get("guest_checkout_percent")) + Integer.parseInt(vars.get("customer_checkout_percent")); - checkout_sum = checkout_sum > 0 ? checkout_sum : 1; - int users = orders * (100 / checkout_sum); - props.put("users", users); -} else { - props.put("users", Integer.parseInt(vars.get("users"))); -} -</stringProp> - <stringProp name="BeanShellSampler.filename"></stringProp> - <stringProp name="BeanShellSampler.parameters"></stringProp> +// Collect products map in products list +productList.add(productMap);</stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> <boolProp name="BeanShellSampler.resetInterpreter">false</boolProp> </BeanShellSampler> <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="WarmUp Add To Cart" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"> - <elementProp name="product" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">1</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">product</stringProp> - </elementProp> - <elementProp name="related_product" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value"></stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">related_product</stringProp> - </elementProp> - <elementProp name="qty" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">1</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">qty</stringProp> - </elementProp> - </collectionProp> - </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${base_path}checkout/cart/add</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree/> </hashTree> - <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Category Product browsing" enabled="true"> - <stringProp name="ThreadGroup.on_sample_error">startnextloop</stringProp> - <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true"> - <boolProp name="LoopController.continue_forever">false</boolProp> - <stringProp name="LoopController.loops">${loops}</stringProp> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="SetUp - HTTP Request: Search configurable products" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true"> + <collectionProp name="Arguments.arguments"/> </elementProp> - <stringProp name="ThreadGroup.num_threads">${__javaScript(Math.round(props.get("users")*${view_catalog_percent}/100>>0))}</stringProp> - <stringProp name="ThreadGroup.ramp_time">${ramp_period}</stringProp> - <longProp name="ThreadGroup.start_time">1304708488000</longProp> - <longProp name="ThreadGroup.end_time">1304708488000</longProp> - <boolProp name="ThreadGroup.scheduler">false</boolProp> - <stringProp name="ThreadGroup.duration"></stringProp> - <stringProp name="ThreadGroup.delay"></stringProp> - </ThreadGroup> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}catalogsearch/result/?limit=30&q=Configurable</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> <hashTree> - <CookieManager guiclass="CookiePanel" testclass="CookieManager" testname="HTTP Cookie Manager" enabled="true"> - <collectionProp name="CookieManager.cookies"> - <elementProp name="product_list_limit" elementType="Cookie" testname="product_list_limit"> - <stringProp name="Cookie.value">30</stringProp> - <stringProp name="Cookie.domain">${host}</stringProp> - <stringProp name="Cookie.path">/</stringProp> - <boolProp name="Cookie.secure">false</boolProp> - <longProp name="Cookie.expires">0</longProp> - <boolProp name="Cookie.path_specified">true</boolProp> - <boolProp name="Cookie.domain_specified">true</boolProp> - </elementProp> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion: Assert search result" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1354477292">Search results for: 'Configurable'</stringProp> + <stringProp name="1647182604"><div class="search results"></stringProp> </collectionProp> - <boolProp name="CookieManager.clearEachIteration">true</boolProp> - </CookieManager> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> <hashTree/> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="Get arguments(CatProdBrows)" enabled="true"> - <stringProp name="TestPlan.comments">Passing arguments between threads</stringProp> - <stringProp name="BeanShellSampler.query">number = (int)(Math.random() * props.get("simple_products_list").size()); -simpleList = props.get("simple_products_list").get(number); -vars.put("simple_product_1_url_key", simpleList.get("url_key")); -vars.put("simple_product_1_name", simpleList.get("title")); - -do { - number1 = (int)(Math.random() * props.get("simple_products_list").size()); -} while(number == number1); -simpleList = props.get("simple_products_list").get(number1); -vars.put("simple_product_2_url_key", simpleList.get("url_key")); -vars.put("simple_product_2_name", simpleList.get("title")); - -number = (int)(Math.random() * props.get("configurable_products_list").size()); -configurableList = props.get("configurable_products_list").get(number); -vars.put("configurable_product_1_url_key", configurableList.get("url_key")); -vars.put("configurable_product_1_name", configurableList.get("title")); - -vars.put("category_url_key", props.get("category_url_key")); -vars.put("category_name", props.get("category_name"));</stringProp> - <stringProp name="BeanShellSampler.filename"></stringProp> - <stringProp name="BeanShellSampler.parameters"></stringProp> - <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> - </BeanShellSampler> + <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor: Extract product url keys" enabled="true"> + <stringProp name="RegexExtractor.useHeaders">false</stringProp> + <stringProp name="RegexExtractor.refname">configurable_products_url_keys</stringProp> + <stringProp name="RegexExtractor.regex"><a class="product-item-link"(?s).+?href="http://${host}${base_path}(index.php/)?([^'"]+)${url_suffix}">(?s).+?Configurable</stringProp> + <stringProp name="RegexExtractor.template">$2$</stringProp> + <stringProp name="RegexExtractor.default"/> + <stringProp name="RegexExtractor.match_number">-1</stringProp> + </RegexExtractor> <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Open Home Page(CatProdBrows)" enabled="true"> + </hashTree> + <ForeachController guiclass="ForeachControlPanel" testclass="ForeachController" testname="ForEach Controller: Configurable products loop (search result)" enabled="true"> + <stringProp name="ForeachController.inputVal">configurable_products_url_keys</stringProp> + <stringProp name="ForeachController.returnVal">configurable_products_url_key</stringProp> + <boolProp name="ForeachController.useSeparator">true</boolProp> + </ForeachController> + <hashTree> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="SetUp - HTTP Request: Open Configurable product" enabled="true"> <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> <collectionProp name="Arguments.arguments"/> </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${base_path}</stringProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}${configurable_products_url_key}${url_suffix}</stringProp> <stringProp name="HTTPSampler.method">GET</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> + <stringProp name="HTTPSampler.embedded_url_re"/> </HTTPSamplerProxy> <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="571386695"><title>Home page</title></stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> + <XPathExtractor guiclass="XPathExtractorGui" testclass="XPathExtractor" testname="XPath Extractor: Extract product id" enabled="true"> + <stringProp name="XPathExtractor.default"/> + <stringProp name="XPathExtractor.refname">configurable_product_id</stringProp> + <stringProp name="XPathExtractor.xpathQuery">.//input[@type="hidden" and @name="product"]/@value</stringProp> + <boolProp name="XPathExtractor.validate">false</boolProp> + <boolProp name="XPathExtractor.tolerant">true</boolProp> + <boolProp name="XPathExtractor.namespace">false</boolProp> + </XPathExtractor> <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> - <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Open Category(CatProdBrows)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"/> - </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${base_path}${category_url_key}${url_suffix}</stringProp> - <stringProp name="HTTPSampler.method">GET</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="1210004667"><span class="base" data-ui-id="page-title">${category_name}</span></stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">6</intProp> - </ResponseAssertion> + <XPathExtractor guiclass="XPathExtractorGui" testclass="XPathExtractor" testname="XPath Extractor: Extract product title" enabled="true"> + <stringProp name="XPathExtractor.default"/> + <stringProp name="XPathExtractor.refname">configurable_product_title</stringProp> + <stringProp name="XPathExtractor.xpathQuery">.//*[@data-ui-id='page-title-wrapper']/text()</stringProp> + <boolProp name="XPathExtractor.validate">false</boolProp> + <boolProp name="XPathExtractor.tolerant">true</boolProp> + <boolProp name="XPathExtractor.namespace">false</boolProp> + </XPathExtractor> <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> - <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Simple Product 1 View(CatProdBrows)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"/> - </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${base_path}${simple_product_1_url_key}${url_suffix}</stringProp> - <stringProp name="HTTPSampler.method">GET</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="1254853024"><title>${simple_product_1_name}</stringProp> - <stringProp name="-1787050162"><span>In stock</span></stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> + <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor: Extract uenc" enabled="true"> + <stringProp name="RegexExtractor.useHeaders">false</stringProp> + <stringProp name="RegexExtractor.refname">configurable_product_uenc</stringProp> + <stringProp name="RegexExtractor.regex">${base_path}checkout/cart/add/uenc/([^/]+)/product/</stringProp> + <stringProp name="RegexExtractor.template">$1$</stringProp> + <stringProp name="RegexExtractor.default"/> + <stringProp name="RegexExtractor.match_number">1</stringProp> + <stringProp name="Scope.variable">simple_product_1_url_key</stringProp> + </RegexExtractor> <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> - <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Simple Product 2 View(CatProdBrows)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"/> - </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${base_path}${simple_product_2_url_key}${url_suffix}</stringProp> - <stringProp name="HTTPSampler.method">GET</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor: Extract product attribute id" enabled="true"> + <stringProp name="RegexExtractor.useHeaders">false</stringProp> + <stringProp name="RegexExtractor.refname">configurable_product_attribute_id</stringProp> + <stringProp name="RegexExtractor.regex">"spConfig": \{"attributes":\{"(\d+)"</stringProp> + <stringProp name="RegexExtractor.template">$1$</stringProp> + <stringProp name="RegexExtractor.default"/> + <stringProp name="RegexExtractor.match_number">1</stringProp> + </RegexExtractor> + <hashTree/> + <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor: Extract product attribute option id" enabled="true"> + <stringProp name="RegexExtractor.useHeaders">false</stringProp> + <stringProp name="RegexExtractor.refname">configurable_product_attribute_option_id</stringProp> + <stringProp name="RegexExtractor.regex">"options":\[\{"id":"(\d+)"</stringProp> + <stringProp name="RegexExtractor.template">$1$</stringProp> + <stringProp name="RegexExtractor.default"/> + <stringProp name="RegexExtractor.match_number">1</stringProp> + </RegexExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion: Assert id" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="2142356705"><title>${simple_product_2_name}</stringProp> - <stringProp name="-1787050162"><span>In stock</span></stringProp> + <stringProp name="89649215">^\d+$</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> + <intProp name="Assertion.test_type">1</intProp> + <stringProp name="Assertion.scope">variable</stringProp> + <stringProp name="Scope.variable">configurable_product_id</stringProp> </ResponseAssertion> <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> - <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Configurable Product 1 View(CatProdBrows)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"/> - </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${base_path}${configurable_product_1_url_key}${url_suffix}</stringProp> - <stringProp name="HTTPSampler.method">GET</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion: Assert title" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="199922279"><title>${configurable_product_1_name}</stringProp> - <stringProp name="-1787050162"><span>In stock</span></stringProp> + <stringProp name="2845929">^.+$</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> + <intProp name="Assertion.test_type">1</intProp> + <stringProp name="Assertion.scope">variable</stringProp> + <stringProp name="Scope.variable">configurable_product_title</stringProp> </ResponseAssertion> <hashTree/> - </hashTree> - </hashTree> - <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Product browsing and adding items to the cart" enabled="true"> - <stringProp name="ThreadGroup.on_sample_error">startnextloop</stringProp> - <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true"> - <boolProp name="LoopController.continue_forever">false</boolProp> - <stringProp name="LoopController.loops">${loops}</stringProp> - </elementProp> - <stringProp name="ThreadGroup.num_threads">${__javaScript(Math.round(props.get("users")*${view_product_add_to_cart_percent}/100>>0))}</stringProp> - <stringProp name="ThreadGroup.ramp_time">${ramp_period}</stringProp> - <longProp name="ThreadGroup.start_time">1304708488000</longProp> - <longProp name="ThreadGroup.end_time">1304708488000</longProp> - <boolProp name="ThreadGroup.scheduler">false</boolProp> - <stringProp name="ThreadGroup.duration"></stringProp> - <stringProp name="ThreadGroup.delay"></stringProp> - </ThreadGroup> - <hashTree> - <CookieManager guiclass="CookiePanel" testclass="CookieManager" testname="HTTP Cookie Manager" enabled="true"> - <collectionProp name="CookieManager.cookies"> - <elementProp name="product_list_limit" elementType="Cookie" testname="product_list_limit"> - <stringProp name="Cookie.value">30</stringProp> - <stringProp name="Cookie.domain">${host}</stringProp> - <stringProp name="Cookie.path">/</stringProp> - <boolProp name="Cookie.secure">false</boolProp> - <longProp name="Cookie.expires">0</longProp> - <boolProp name="Cookie.path_specified">true</boolProp> - <boolProp name="Cookie.domain_specified">true</boolProp> - </elementProp> - </collectionProp> - <boolProp name="CookieManager.clearEachIteration">true</boolProp> - </CookieManager> - <hashTree/> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="Get arguments(BrowsAddToCart)" enabled="true"> - <stringProp name="TestPlan.comments">Passing arguments between threads</stringProp> - <stringProp name="BeanShellSampler.query">number = (int)(Math.random() * props.get("simple_products_list").size()); -simpleList = props.get("simple_products_list").get(number); -vars.put("simple_product_1_url_key", simpleList.get("url_key")); -vars.put("simple_product_1_name", simpleList.get("title")); -vars.put("simple_product_1_id", simpleList.get("id")); - -do { - number1 = (int)(Math.random() * props.get("simple_products_list").size()); -} while(number == number1); -simpleList = props.get("simple_products_list").get(number1); -vars.put("simple_product_2_url_key", simpleList.get("url_key")); -vars.put("simple_product_2_name", simpleList.get("title")); -vars.put("simple_product_2_id", simpleList.get("id")); - -number = (int)(Math.random() * props.get("configurable_products_list").size()); -configurableList = props.get("configurable_products_list").get(number); -vars.put("configurable_product_1_url_key", configurableList.get("url_key")); -vars.put("configurable_product_1_name", configurableList.get("title")); -vars.put("configurable_product_1_id", configurableList.get("id")); -vars.put("configurable_attribute_id", configurableList.get("attribute_id")); -vars.put("configurable_option_id", configurableList.get("attribute_option_id")); - -vars.put("category_url_key", props.get("category_url_key")); -vars.put("category_name", props.get("category_name"));</stringProp> - <stringProp name="BeanShellSampler.filename"></stringProp> - <stringProp name="BeanShellSampler.parameters"></stringProp> - <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> - </BeanShellSampler> - <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Open Home Page(BrowsAddToCart)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"/> - </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${base_path}</stringProp> - <stringProp name="HTTPSampler.method">GET</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion: Assert url key" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="571386695"><title>Home page</title></stringProp> + <stringProp name="484395188">^[a-z0-9-]+$</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> + <intProp name="Assertion.test_type">1</intProp> + <stringProp name="Assertion.scope">variable</stringProp> + <stringProp name="Scope.variable">configurable_products_url_key</stringProp> </ResponseAssertion> <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> - <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Open Category(BrowsAddToCart)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"/> - </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${base_path}${category_url_key}${url_suffix}</stringProp> - <stringProp name="HTTPSampler.method">GET</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion: Assert attribute id" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="1210004667"><span class="base" data-ui-id="page-title">${category_name}</span></stringProp> + <stringProp name="89649215">^\d+$</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">6</intProp> + <intProp name="Assertion.test_type">1</intProp> + <stringProp name="Assertion.scope">variable</stringProp> + <stringProp name="Scope.variable">configurable_product_attribute_id</stringProp> </ResponseAssertion> <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> - <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Simple Product 1 View(BrowsAddToCart)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"/> - </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${base_path}${simple_product_1_url_key}${url_suffix}</stringProp> - <stringProp name="HTTPSampler.method">GET</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion: Assert attribute option id" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="1254853024"><title>${simple_product_1_name}</stringProp> - <stringProp name="-1787050162"><span>In stock</span></stringProp> + <stringProp name="89649215">^\d+$</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> + <intProp name="Assertion.test_type">1</intProp> + <stringProp name="Assertion.scope">variable</stringProp> + <stringProp name="Scope.variable">configurable_product_attribute_option_id</stringProp> </ResponseAssertion> <hashTree/> - <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form action" enabled="true"> - <stringProp name="RegexExtractor.useHeaders">false</stringProp> - <stringProp name="RegexExtractor.refname">simple_product_1_form_action</stringProp> - <stringProp name="RegexExtractor.regex"><form action="([^'"]+)"\s*method="post"\s*id="product_addtocart_form"></stringProp> - <stringProp name="RegexExtractor.template">$1$</stringProp> - <stringProp name="RegexExtractor.default"></stringProp> - <stringProp name="RegexExtractor.match_number">1</stringProp> - </RegexExtractor> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert form_action extracted" enabled="true"> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion: Assert uenc" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="2845929">^.+$</stringProp> + <stringProp name="824150030">^[\w\,]+$</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> <intProp name="Assertion.test_type">1</intProp> <stringProp name="Assertion.scope">variable</stringProp> - <stringProp name="Scope.variable">simple_product_1_form_action</stringProp> + <stringProp name="Scope.variable">configurable_product_uenc</stringProp> </ResponseAssertion> <hashTree/> </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> + <CounterConfig guiclass="CounterConfigGui" testclass="CounterConfig" testname="Counter" enabled="true"> + <stringProp name="CounterConfig.start">1</stringProp> + <stringProp name="CounterConfig.end"/> + <stringProp name="CounterConfig.incr">1</stringProp> + <stringProp name="CounterConfig.name">configurable_products_counter</stringProp> + <stringProp name="CounterConfig.format"/> + <boolProp name="CounterConfig.per_user">false</boolProp> + </CounterConfig> <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Simple Product 1 Add To Cart(BrowsAddToCart)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"> - <elementProp name="product" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">${simple_product_1_id}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">product</stringProp> - </elementProp> - <elementProp name="related_product" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value"></stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">related_product</stringProp> - </elementProp> - <elementProp name="qty" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">1</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">qty</stringProp> - </elementProp> - <elementProp name="isAjax" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">true</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">isAjax</stringProp> - </elementProp> - <elementProp name="ajax" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">true</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">ajax</stringProp> - </elementProp> - </collectionProp> - </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${simple_product_1_form_action}</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="210217247">You added ${simple_product_1_name} to your shopping cart.</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="518066445"><div>* This product is out of stock.</div></stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">6</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - BeanShell Sampler: Collect configurable product" enabled="true"> + <stringProp name="BeanShellSampler.query">import java.util.ArrayList; +import java.util.HashMap; + +// If it is first iteration of cycle then recreate productList +if (1 == Integer.parseInt(vars.get("configurable_products_counter"))) { + productList = new ArrayList(); + props.put("configurable_products_list", productList); +} else { + productList = props.get("configurable_products_list"); +} + +// Create product map +Map productMap = new HashMap(); +productMap.put("id", vars.get("configurable_product_id")); +productMap.put("title", vars.get("configurable_product_title")); +productMap.put("url_key", vars.get("configurable_products_url_key")); +productMap.put("uenc", vars.get("configurable_product_uenc")); +productMap.put("attribute_id", vars.get("configurable_product_attribute_id")); +productMap.put("attribute_option_id", vars.get("configurable_product_attribute_option_id")); + +// Collect products map in products list +productList.add(productMap); </stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">false</boolProp> + </BeanShellSampler> <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Simple Product 2 View(BrowsAddToCart)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"/> - </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${base_path}${simple_product_2_url_key}${url_suffix}</stringProp> - <stringProp name="HTTPSampler.method">GET</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="2142356705"><title>${simple_product_2_name}</stringProp> - <stringProp name="-1787050162"><span>In stock</span></stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form action" enabled="true"> - <stringProp name="RegexExtractor.useHeaders">false</stringProp> - <stringProp name="RegexExtractor.refname">simple_product_2_form_action</stringProp> - <stringProp name="RegexExtractor.regex"><form action="([^'"]+)"\s*method="post"\s*id="product_addtocart_form"></stringProp> - <stringProp name="RegexExtractor.template">$1$</stringProp> - <stringProp name="RegexExtractor.default"></stringProp> - <stringProp name="RegexExtractor.match_number">1</stringProp> - </RegexExtractor> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert form_action extracted" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="2845929">^.+$</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">1</intProp> - <stringProp name="Assertion.scope">variable</stringProp> - <stringProp name="Scope.variable">simple_product_2_form_action</stringProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> + </hashTree> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="SetUp - Open Customer Grid" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}${admin_path}/customer/index/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <BeanShellPreProcessor guiclass="TestBeanGUI" testclass="BeanShellPreProcessor" testname="BeanShell PreProcessor" enabled="true"> + <stringProp name="filename"/> + <stringProp name="parameters"/> + <boolProp name="resetInterpreter">true</boolProp> + <stringProp name="script">import org.apache.jmeter.protocol.http.control.CookieManager; +import org.apache.jmeter.protocol.http.control.Cookie; +CookieManager manager = sampler.getCookieManager(); +Cookie cookie = new Cookie("adminhtml",vars.get("COOKIE_adminhtml"),vars.get("host"),"/",false,0); +manager.add(cookie); </stringProp> + </BeanShellPreProcessor> <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Simple Product 2 Add To Cart(BrowsAddToCart)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"> - <elementProp name="product" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">${simple_product_2_id}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">product</stringProp> - </elementProp> - <elementProp name="related_product" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value"></stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">related_product</stringProp> - </elementProp> - <elementProp name="qty" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">1</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">qty</stringProp> - </elementProp> - <elementProp name="isAjax" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">true</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">isAjax</stringProp> - </elementProp> - <elementProp name="ajax" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">true</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">ajax</stringProp> - </elementProp> - </collectionProp> - </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${simple_product_2_form_action}</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="221533374">You added ${simple_product_2_name} to your shopping cart.</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="518066445"><div>* This product is out of stock.</div></stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">6</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert Customer Grid" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-679437259">Customers</stringProp> + <stringProp name="495525733"><title>Customers / Customers / Magento Admin</title></stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Configurable Product 1 View(BrowsAddToCart)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="SetUp - Search Customers" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="namespace" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">customer_listing</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">namespace</stringProp> </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${base_path}${configurable_product_1_url_key}${url_suffix}</stringProp> - <stringProp name="HTTPSampler.method">GET</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="199922279"><title>${configurable_product_1_name}</stringProp> - <stringProp name="-1787050162"><span>In stock</span></stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form action" enabled="true"> - <stringProp name="RegexExtractor.useHeaders">false</stringProp> - <stringProp name="RegexExtractor.refname">configurable_product_form_action</stringProp> - <stringProp name="RegexExtractor.regex"><form action="([^'"]+)"\s*method="post"\s*id="product_addtocart_form"></stringProp> - <stringProp name="RegexExtractor.template">$1$</stringProp> - <stringProp name="RegexExtractor.default"></stringProp> - <stringProp name="RegexExtractor.match_number">1</stringProp> - </RegexExtractor> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert form_action extracted" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="2845929">^.+$</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">1</intProp> - <stringProp name="Assertion.scope">variable</stringProp> - <stringProp name="Scope.variable">configurable_product_form_action</stringProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> - <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Configurable Product 1 Add To Cart(BrowsAddToCart)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"> - <elementProp name="product" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">${configurable_product_1_id}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">product</stringProp> - </elementProp> - <elementProp name="related_product" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value"></stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">related_product</stringProp> - </elementProp> - <elementProp name="qty" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">1</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">qty</stringProp> - </elementProp> - <elementProp name="super_attribute[${configurable_attribute_id}]" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">${configurable_option_id}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">super_attribute[${configurable_attribute_id}]</stringProp> - </elementProp> - <elementProp name="isAjax" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">true</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">isAjax</stringProp> - </elementProp> - <elementProp name="ajax" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">true</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">ajax</stringProp> - </elementProp> - </collectionProp> + <elementProp name="search" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value"/> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">search</stringProp> </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${configurable_product_form_action}</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="-1346272328">You added ${configurable_product_1_name} to your shopping cart.</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="-815931116"><div>* We don't have as many &quot;${configurable_product_1_name}&quot; as you requested.</div></stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">6</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - </hashTree> - <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Guest Checkout" enabled="true"> - <stringProp name="ThreadGroup.on_sample_error">startnextloop</stringProp> - <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true"> - <boolProp name="LoopController.continue_forever">false</boolProp> - <stringProp name="LoopController.loops">${loops}</stringProp> - </elementProp> - <stringProp name="ThreadGroup.num_threads">${__javaScript(Math.round(props.get("users")*${guest_checkout_percent}/100>>0))}</stringProp> - <stringProp name="ThreadGroup.ramp_time">${ramp_period}</stringProp> - <longProp name="ThreadGroup.start_time">1304708488000</longProp> - <longProp name="ThreadGroup.end_time">1304708488000</longProp> - <boolProp name="ThreadGroup.scheduler">false</boolProp> - <stringProp name="ThreadGroup.duration"></stringProp> - <stringProp name="ThreadGroup.delay"></stringProp> - </ThreadGroup> + <elementProp name="filters[placeholder]" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">customer_since[locale]=en_US&website_id=1</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">filters[placeholder]</stringProp> + </elementProp> + <elementProp name="paging[pageSize]" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">${customers_page_size}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">paging[pageSize]</stringProp> + </elementProp> + <elementProp name="paging[current]" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">1</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">paging[current]</stringProp> + </elementProp> + <elementProp name="sorting[field]" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">entity_id</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sorting[field]</stringProp> + </elementProp> + <elementProp name="sorting[direction]" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">asc</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sorting[direction]</stringProp> + </elementProp> + <elementProp name="isAjax" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">true</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">isAjax</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}${admin_path}/mui/index/render/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert total records is not 0" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="827137952">\"totalRecords\":0</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">20</intProp> + </ResponseAssertion> + <hashTree/> + <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract customer emails" enabled="true"> + <stringProp name="RegexExtractor.useHeaders">false</stringProp> + <stringProp name="RegexExtractor.refname">customer_emails</stringProp> + <stringProp name="RegexExtractor.regex">\"email\":\"([^"]+)</stringProp> + <stringProp name="RegexExtractor.template">$1$</stringProp> + <stringProp name="RegexExtractor.default"/> + <stringProp name="RegexExtractor.match_number">-1</stringProp> + </RegexExtractor> + <hashTree/> + <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract customer ids" enabled="true"> + <stringProp name="RegexExtractor.useHeaders">false</stringProp> + <stringProp name="RegexExtractor.refname">customer_ids</stringProp> + <stringProp name="RegexExtractor.regex">\"entity_id\":\"([^"]+)</stringProp> + <stringProp name="RegexExtractor.template">$1$</stringProp> + <stringProp name="RegexExtractor.default"/> + <stringProp name="RegexExtractor.match_number">-1</stringProp> + </RegexExtractor> + <hashTree/> + </hashTree> + <ForeachController guiclass="ForeachControlPanel" testclass="ForeachController" testname="ForEach Controller: customer emails loop (search result)" enabled="true"> + <stringProp name="ForeachController.inputVal">customer_emails</stringProp> + <stringProp name="ForeachController.returnVal">customer_email</stringProp> + <boolProp name="ForeachController.useSeparator">true</boolProp> + </ForeachController> <hashTree> - <CookieManager guiclass="CookiePanel" testclass="CookieManager" testname="HTTP Cookie Manager" enabled="true"> - <collectionProp name="CookieManager.cookies"> - <elementProp name="product_list_limit" elementType="Cookie" testname="product_list_limit"> - <stringProp name="Cookie.value">30</stringProp> - <stringProp name="Cookie.domain">${host}</stringProp> - <stringProp name="Cookie.path">/</stringProp> - <boolProp name="Cookie.secure">false</boolProp> - <longProp name="Cookie.expires">0</longProp> - <boolProp name="Cookie.path_specified">true</boolProp> - <boolProp name="Cookie.domain_specified">true</boolProp> - </elementProp> - </collectionProp> - <boolProp name="CookieManager.clearEachIteration">true</boolProp> - </CookieManager> + <CounterConfig guiclass="CounterConfigGui" testclass="CounterConfig" testname="Counter" enabled="true"> + <stringProp name="CounterConfig.start">1</stringProp> + <stringProp name="CounterConfig.end"/> + <stringProp name="CounterConfig.incr">1</stringProp> + <stringProp name="CounterConfig.name">email_counter</stringProp> + <stringProp name="CounterConfig.format"/> + <boolProp name="CounterConfig.per_user">false</boolProp> + </CounterConfig> <hashTree/> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="Get arguments(GuestChkt)" enabled="true"> - <stringProp name="TestPlan.comments">Passing arguments between threads</stringProp> - <stringProp name="BeanShellSampler.query">number = (int)(Math.random() * props.get("simple_products_list").size()); -simpleList = props.get("simple_products_list").get(number); -vars.put("simple_product_1_url_key", simpleList.get("url_key")); -vars.put("simple_product_1_name", simpleList.get("title")); -vars.put("simple_product_1_id", simpleList.get("id")); + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - BeanShell Sampler: Collect customer emails" enabled="true"> + <stringProp name="BeanShellSampler.query">import java.util.ArrayList; -do { - number1 = (int)(Math.random() * props.get("simple_products_list").size()); -} while(number == number1); -simpleList = props.get("simple_products_list").get(number1); -vars.put("simple_product_2_url_key", simpleList.get("url_key")); -vars.put("simple_product_2_name", simpleList.get("title")); -vars.put("simple_product_2_id", simpleList.get("id")); - -number = (int)(Math.random() * props.get("configurable_products_list").size()); -configurableList = props.get("configurable_products_list").get(number); -vars.put("configurable_product_1_url_key", configurableList.get("url_key")); -vars.put("configurable_product_1_name", configurableList.get("title")); -vars.put("configurable_product_1_id", configurableList.get("id")); -vars.put("configurable_attribute_id", configurableList.get("attribute_id")); -vars.put("configurable_option_id", configurableList.get("attribute_option_id")); - -vars.put("category_url_key", props.get("category_url_key")); -vars.put("category_name", props.get("category_name"));</stringProp> - <stringProp name="BeanShellSampler.filename"></stringProp> - <stringProp name="BeanShellSampler.parameters"></stringProp> - <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> +// If it is first iteration of cycle then recreate emailsList +if (1 == Integer.parseInt(vars.get("email_counter"))) { + emailsList = new ArrayList(); + props.put("customer_emails_list", emailsList); +} else { + emailsList = props.get("customer_emails_list"); +} +emailsList.add(vars.get("customer_email"));</stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">false</boolProp> </BeanShellSampler> <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Open Home Page(GuestChkt)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"/> - </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${base_path}</stringProp> - <stringProp name="HTTPSampler.method">GET</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="571386695"><title>Home page</title></stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> + </hashTree> + <ForeachController guiclass="ForeachControlPanel" testclass="ForeachController" testname="ForEach Controller: customer ids loop (search result)" enabled="true"> + <stringProp name="ForeachController.inputVal">customer_ids</stringProp> + <stringProp name="ForeachController.returnVal">customer_id</stringProp> + <boolProp name="ForeachController.useSeparator">true</boolProp> + </ForeachController> + <hashTree> + <CounterConfig guiclass="CounterConfigGui" testclass="CounterConfig" testname="Counter" enabled="true"> + <stringProp name="CounterConfig.start">1</stringProp> + <stringProp name="CounterConfig.end"/> + <stringProp name="CounterConfig.incr">1</stringProp> + <stringProp name="CounterConfig.name">id_counter</stringProp> + <stringProp name="CounterConfig.format"/> + <boolProp name="CounterConfig.per_user">false</boolProp> + </CounterConfig> <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Open Category(GuestChkt)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"/> - </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${base_path}${category_url_key}${url_suffix}</stringProp> - <stringProp name="HTTPSampler.method">GET</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="1210004667"><span class="base" data-ui-id="page-title">${category_name}</span></stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">6</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - BeanShell Sampler: Collect customer ids" enabled="true"> + <stringProp name="BeanShellSampler.query">import java.util.ArrayList; + +// If it is first iteration of cycle then recreate idsList +if (1 == Integer.parseInt(vars.get("id_counter"))) { + idsList = new ArrayList(); + props.put("customer_ids_list", idsList); +} else { + idsList = props.get("customer_ids_list"); +} +idsList.add(vars.get("customer_id"));</stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">false</boolProp> + </BeanShellSampler> <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Simple Product 1 View(GuestChkt)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"/> - </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${base_path}${simple_product_1_url_key}${url_suffix}</stringProp> - <stringProp name="HTTPSampler.method">GET</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="1254853024"><title>${simple_product_1_name}</stringProp> - <stringProp name="-1787050162"><span>In stock</span></stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form action" enabled="true"> - <stringProp name="RegexExtractor.useHeaders">false</stringProp> - <stringProp name="RegexExtractor.refname">simple_product_1_form_action</stringProp> - <stringProp name="RegexExtractor.regex"><form action="([^'"]+)"\s*method="post"\s*id="product_addtocart_form"></stringProp> - <stringProp name="RegexExtractor.template">$1$</stringProp> - <stringProp name="RegexExtractor.default"></stringProp> - <stringProp name="RegexExtractor.match_number">1</stringProp> - </RegexExtractor> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert form_action extracted" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="2845929">^.+$</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">1</intProp> - <stringProp name="Assertion.scope">variable</stringProp> - <stringProp name="Scope.variable">simple_product_1_form_action</stringProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> + </hashTree> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - BeanShell Sampler: Validate properties and count users" enabled="true"> + <stringProp name="BeanShellSampler.query">Boolean stopTestOnError (String error) { + log.error(error); + System.out.println(error); + SampleResult.setStopTest(true); + return false; +} + +if (props.get("simple_products_list") == null) { + return stopTestOnError("Cannot find simple products. Test stopped."); +} +if (props.get("configurable_products_list") == null) { + return stopTestOnError("Cannot find configurable products. Test stopped."); +} +if (props.get("customer_emails_list") == null) { + return stopTestOnError("Cannot find customer emails. Test stopped."); +} +int orders = Integer.parseInt(vars.get("orders")); + + +if (orders > 0) { + int checkout_sum = Integer.parseInt(vars.get("guest_checkout_percent")) + Integer.parseInt(vars.get("customer_checkout_percent")); + checkout_sum = checkout_sum > 0 ? checkout_sum : 1; + int users = orders * (100 / checkout_sum); + props.put("users", users); +} else { + props.put("users", Integer.parseInt(vars.get("users"))); +} +</stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">false</boolProp> + </BeanShellSampler> + <hashTree/> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="SetUp - WarmUp Add To Cart" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="product" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">1</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">product</stringProp> + </elementProp> + <elementProp name="related_product" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value"/> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">related_product</stringProp> + </elementProp> + <elementProp name="qty" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">1</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">qty</stringProp> + </elementProp> + <elementProp name="form_key" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${form_key}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">form_key</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}checkout/cart/add</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree/> + </hashTree> + + <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Catalog Browsing By Guest" enabled="true"> + <stringProp name="ThreadGroup.on_sample_error">continue</stringProp> + <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true"> + <boolProp name="LoopController.continue_forever">false</boolProp> + <stringProp name="LoopController.loops">${loops}</stringProp> + </elementProp> + <stringProp name="ThreadGroup.num_threads">${__javaScript(Math.round(props.get("users")*${view_catalog_percent}/100>>0))}</stringProp> + <stringProp name="ThreadGroup.ramp_time">${ramp_period}</stringProp> + <longProp name="ThreadGroup.start_time">1437409133000</longProp> + <longProp name="ThreadGroup.end_time">1437409133000</longProp> + <boolProp name="ThreadGroup.scheduler">false</boolProp> + <stringProp name="ThreadGroup.duration"/> + <stringProp name="ThreadGroup.delay"/> + </ThreadGroup> + <hashTree> + <RandomVariableConfig guiclass="TestBeanGUI" testclass="RandomVariableConfig" testname="Random Variable 1" enabled="true"> + <stringProp name="variableName">rv1</stringProp> + <stringProp name="outputFormat">'.'</stringProp> + <stringProp name="minimumValue">1</stringProp> + <stringProp name="maximumValue">999999</stringProp> + <stringProp name="randomSeed">1</stringProp> + <boolProp name="perThread">true</boolProp> + </RandomVariableConfig> + <hashTree/> + + <RandomVariableConfig guiclass="TestBeanGUI" testclass="RandomVariableConfig" testname="Random Variable 2" enabled="true"> + <stringProp name="variableName">rv2</stringProp> + <stringProp name="outputFormat">'.'</stringProp> + <stringProp name="minimumValue">1</stringProp> + <stringProp name="maximumValue">999999</stringProp> + <stringProp name="randomSeed">2</stringProp> + <boolProp name="perThread">true</boolProp> + </RandomVariableConfig> + <hashTree/> + + <RandomVariableConfig guiclass="TestBeanGUI" testclass="RandomVariableConfig" testname="Random Variable 3" enabled="true"> + <stringProp name="variableName">rv3</stringProp> + <stringProp name="outputFormat">'.'</stringProp> + <stringProp name="minimumValue">1</stringProp> + <stringProp name="maximumValue">999999</stringProp> + <stringProp name="randomSeed">3</stringProp> + <boolProp name="perThread">true</boolProp> + </RandomVariableConfig> + <hashTree/> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="Get arguments${__property(activeAdminThread)}(CatProdBrows)" enabled="true"> + <stringProp name="TestPlan.comments">Passing arguments between threads</stringProp> + <stringProp name="BeanShellSampler.query">number = (int)(${rv1} * props.get("simple_products_list").size()); +simpleList = props.get("simple_products_list").get(number); +vars.put("simple_product_1_url_key", simpleList.get("url_key")); +vars.put("simple_product_1_name", simpleList.get("title")); +vars.put("simple_product_1_id", simpleList.get("id")); + +number1 = (int)(${rv2} * props.get("simple_products_list").size()); +simpleList = props.get("simple_products_list").get(number1); +vars.put("simple_product_2_url_key", simpleList.get("url_key")); +vars.put("simple_product_2_name", simpleList.get("title")); +vars.put("simple_product_2_id", simpleList.get("id")); + +number = (int)(${rv3} * props.get("configurable_products_list").size()); +configurableList = props.get("configurable_products_list").get(number); +vars.put("configurable_product_1_url_key", configurableList.get("url_key")); +vars.put("configurable_product_1_name", configurableList.get("title")); +vars.put("configurable_product_1_id", configurableList.get("id")); + +vars.put("category_url_key", props.get("category_url_key")); +vars.put("category_name", props.get("category_name")); +vars.put("testLabel", "CatProdBrows");</stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Open Home Page${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="571386695"><title>Home page</title></stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Simple Product 1 Add To Cart(GuestChkt)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"> - <elementProp name="product" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">${simple_product_1_id}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">product</stringProp> - </elementProp> - <elementProp name="related_product" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value"></stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">related_product</stringProp> - </elementProp> - <elementProp name="qty" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">1</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">qty</stringProp> - </elementProp> - <elementProp name="isAjax" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">true</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">isAjax</stringProp> - </elementProp> - <elementProp name="ajax" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">true</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">ajax</stringProp> - </elementProp> - </collectionProp> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Customer All Section Load${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value"/> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${simple_product_1_form_action}</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="210217247">You added ${simple_product_1_name} to your shopping cart.</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="518066445"><div>* This product is out of stock.</div></stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">6</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">false</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-2001627678">\"messages\":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Open Category${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}${category_url_key}${url_suffix}</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1210004667"><span class="base" data-ui-id="page-title">${category_name}</span></stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">6</intProp> + </ResponseAssertion> + <hashTree/> + <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor: Extract category id" enabled="true"> + <stringProp name="RegexExtractor.useHeaders">false</stringProp> + <stringProp name="RegexExtractor.refname">category_id</stringProp> + <stringProp name="RegexExtractor.regex"><li class="item category([^'"]+)">\s*<strong>${category_name}</strong>\s*</li></stringProp> + <stringProp name="RegexExtractor.template">$1$</stringProp> + <stringProp name="RegexExtractor.default"/> + <stringProp name="RegexExtractor.match_number">1</stringProp> + <stringProp name="Scope.variable">simple_product_1_url_key</stringProp> + </RegexExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion: Assert category id" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1191417111">^[0-9]+$</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">1</intProp> + <stringProp name="Assertion.scope">variable</stringProp> + <stringProp name="Scope.variable">category_id</stringProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Customer Section Load${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">banner</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">false</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1898134910">\"banner\":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Simple Product 1 View${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}${simple_product_1_url_key}${url_suffix}</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1254853024"><title>${simple_product_1_name}</stringProp> + <stringProp name="-1787050162"><span>In stock</span></stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Customer Section Load${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">banner</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">false</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1898134910">\"banner\":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Ajax Review Simple Product 1(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}review/product/listAjax/id/${simple_product_1_id}/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="49586">200</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_code</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Simple Product 2 View${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}${simple_product_2_url_key}${url_suffix}</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="2142356705"><title>${simple_product_2_name}</stringProp> + <stringProp name="-1787050162"><span>In stock</span></stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Customer Section Load${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">banner</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">false</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1898134910">\"banner\":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Ajax Review Simple Product 2(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}review/product/listAjax/id/${simple_product_2_id}/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="49586">200</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_code</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Configurable Product 1 View${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}${configurable_product_1_url_key}${url_suffix}</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="199922279"><title>${configurable_product_1_name}</stringProp> + <stringProp name="-1787050162"><span>In stock</span></stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Customer Section Load${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">banner</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">false</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1898134910">\"banner\":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Ajax Review Configurable Product 1(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}review/product/listAjax/id/${configurable_product_1_id}/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="49586">200</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_code</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + </hashTree> + + <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Abandoned Cart By Guest" enabled="true"> + <stringProp name="ThreadGroup.on_sample_error">continue</stringProp> + <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true"> + <boolProp name="LoopController.continue_forever">false</boolProp> + <stringProp name="LoopController.loops">${loops}</stringProp> + </elementProp> + <stringProp name="ThreadGroup.num_threads">${__javaScript(Math.round(props.get("users")*${view_product_add_to_cart_percent}/100>>0))}</stringProp> + <stringProp name="ThreadGroup.ramp_time">${ramp_period}</stringProp> + <longProp name="ThreadGroup.start_time">1437411475000</longProp> + <longProp name="ThreadGroup.end_time">1437411475000</longProp> + <boolProp name="ThreadGroup.scheduler">false</boolProp> + <stringProp name="ThreadGroup.duration"/> + <stringProp name="ThreadGroup.delay"/> + </ThreadGroup> + <hashTree> + <RandomVariableConfig guiclass="TestBeanGUI" testclass="RandomVariableConfig" testname="Random Variable 1" enabled="true"> + <stringProp name="variableName">rv1</stringProp> + <stringProp name="outputFormat">'.'</stringProp> + <stringProp name="minimumValue">1</stringProp> + <stringProp name="maximumValue">999999</stringProp> + <stringProp name="randomSeed">1</stringProp> + <boolProp name="perThread">true</boolProp> + </RandomVariableConfig> + <hashTree/> + + <RandomVariableConfig guiclass="TestBeanGUI" testclass="RandomVariableConfig" testname="Random Variable 2" enabled="true"> + <stringProp name="variableName">rv2</stringProp> + <stringProp name="outputFormat">'.'</stringProp> + <stringProp name="minimumValue">1</stringProp> + <stringProp name="maximumValue">999999</stringProp> + <stringProp name="randomSeed">2</stringProp> + <boolProp name="perThread">true</boolProp> + </RandomVariableConfig> + <hashTree/> + + <RandomVariableConfig guiclass="TestBeanGUI" testclass="RandomVariableConfig" testname="Random Variable 3" enabled="true"> + <stringProp name="variableName">rv3</stringProp> + <stringProp name="outputFormat">'.'</stringProp> + <stringProp name="minimumValue">1</stringProp> + <stringProp name="maximumValue">999999</stringProp> + <stringProp name="randomSeed">3</stringProp> + <boolProp name="perThread">true</boolProp> + </RandomVariableConfig> + <hashTree/> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="Get arguments${__property(activeAdminThread)}(BrowsAddToCart)" enabled="true"> + <stringProp name="TestPlan.comments">Passing arguments between threads</stringProp> + <stringProp name="BeanShellSampler.query">number = (int)(${rv1} * props.get("simple_products_list").size()); +simpleList = props.get("simple_products_list").get(number); +vars.put("simple_product_1_url_key", simpleList.get("url_key")); +vars.put("simple_product_1_name", simpleList.get("title")); +vars.put("simple_product_1_id", simpleList.get("id")); +vars.put("simple_product_1_uenc", simpleList.get("uenc")); + +number1 = (int)(${rv2} * props.get("simple_products_list").size()); +simpleList = props.get("simple_products_list").get(number1); +vars.put("simple_product_2_url_key", simpleList.get("url_key")); +vars.put("simple_product_2_name", simpleList.get("title")); +vars.put("simple_product_2_id", simpleList.get("id")); +vars.put("simple_product_2_uenc", simpleList.get("uenc")); + +number = (int)(${rv3} * props.get("configurable_products_list").size()); +configurableList = props.get("configurable_products_list").get(number); +vars.put("configurable_product_1_url_key", configurableList.get("url_key")); +vars.put("configurable_product_1_name", configurableList.get("title")); +vars.put("configurable_product_1_id", configurableList.get("id")); +vars.put("configurable_attribute_id", configurableList.get("attribute_id")); +vars.put("configurable_option_id", configurableList.get("attribute_option_id")); +vars.put("configurable_product_1_uenc", simpleList.get("uenc")); + +vars.put("category_url_key", props.get("category_url_key")); +vars.put("category_name", props.get("category_name")); +vars.put("testLabel", "BrowsAddToCart"); +vars.put("loadType", "Guest");</stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Open Home Page${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="571386695"><title>Home page</title></stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Simple Product 2 View(GuestChkt)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Customer All Section Load${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value"/> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${base_path}${simple_product_2_url_key}${url_suffix}</stringProp> - <stringProp name="HTTPSampler.method">GET</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="2142356705"><title>${simple_product_2_name}</stringProp> - <stringProp name="-1787050162"><span>In stock</span></stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form action" enabled="true"> - <stringProp name="RegexExtractor.useHeaders">false</stringProp> - <stringProp name="RegexExtractor.refname">simple_product_2_form_action</stringProp> - <stringProp name="RegexExtractor.regex"><form action="([^'"]+)"\s*method="post"\s*id="product_addtocart_form"></stringProp> - <stringProp name="RegexExtractor.template">$1$</stringProp> - <stringProp name="RegexExtractor.default"></stringProp> - <stringProp name="RegexExtractor.match_number">1</stringProp> - </RegexExtractor> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert form_action extracted" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="2845929">^.+$</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">1</intProp> - <stringProp name="Assertion.scope">variable</stringProp> - <stringProp name="Scope.variable">simple_product_2_form_action</stringProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">false</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-2001627678">\"messages\":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Ajax Load Login Form${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="blocks" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">["customer_form_login"]</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">blocks</stringProp> + </elementProp> + <elementProp name="handles" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">["default","customer_account_login"]</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">handles</stringProp> + </elementProp> + <elementProp name="originalRequest" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">{"route":"customer","controller":"account","action":"login","uri":"/customer/account/login/"}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">originalRequest</stringProp> + </elementProp> + <elementProp name="ajax" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">true</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">ajax</stringProp> + </elementProp> + <elementProp name="isAjax" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">true</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">isAjax</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}page_cache/block/render/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="940598773">"customer_form_login"</stringProp> + <stringProp name="1951684663">Registered Customers</stringProp> + <stringProp name="474011748">form_key</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form key" enabled="true"> + <stringProp name="RegexExtractor.useHeaders">false</stringProp> + <stringProp name="RegexExtractor.refname">form_key</stringProp> + <stringProp name="RegexExtractor.regex"><input name=\\"form_key\\" type=\\"hidden\\" value=\\"([^'"]+)\\" \\/></stringProp> + <stringProp name="RegexExtractor.template">$1$</stringProp> + <stringProp name="RegexExtractor.default"/> + <stringProp name="RegexExtractor.match_number">1</stringProp> + </RegexExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert form_key extracted" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="2845929">^.+$</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">1</intProp> + <stringProp name="Assertion.scope">variable</stringProp> + <stringProp name="Scope.variable">form_key</stringProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Open Category${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}${category_url_key}${url_suffix}</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1210004667"><span class="base" data-ui-id="page-title">${category_name}</span></stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">6</intProp> + </ResponseAssertion> + <hashTree/> + <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor: Extract category id" enabled="true"> + <stringProp name="RegexExtractor.useHeaders">false</stringProp> + <stringProp name="RegexExtractor.refname">category_id</stringProp> + <stringProp name="RegexExtractor.regex"><li class="item category([^'"]+)">\s*<strong>${category_name}</strong>\s*</li></stringProp> + <stringProp name="RegexExtractor.template">$1$</stringProp> + <stringProp name="RegexExtractor.default"/> + <stringProp name="RegexExtractor.match_number">1</stringProp> + <stringProp name="Scope.variable">simple_product_1_url_key</stringProp> + </RegexExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion: Assert category id" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1191417111">^[0-9]+$</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">1</intProp> + <stringProp name="Assertion.scope">variable</stringProp> + <stringProp name="Scope.variable">category_id</stringProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Customer Section Load${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">banner</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">false</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1898134910">\"banner\":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Simple Product 1 View${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}${simple_product_1_url_key}${url_suffix}</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1254853024"><title>${simple_product_1_name}</stringProp> + <stringProp name="-1787050162"><span>In stock</span></stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Customer Section Load${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">banner</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">false</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1898134910">\"banner\":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Ajax Review Simple Product 1(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}review/product/listAjax/id/${simple_product_1_id}/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="49586">200</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_code</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Simple Product 1 Add To Cart${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="product" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${simple_product_1_id}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">product</stringProp> + </elementProp> + <elementProp name="related_product" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value"/> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">related_product</stringProp> + </elementProp> + <elementProp name="qty" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">1</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">qty</stringProp> + </elementProp> + <elementProp name="form_key" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${form_key}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">form_key</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}checkout/cart/add/uenc/${simple_product_1_uenc}/product/${simple_product_1_id}/</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + + <hashTree> + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">X-Requested-With</stringProp> + <stringProp name="Header.value">XMLHttpRequest</stringProp> + </elementProp> + </collectionProp> + </HeaderManager> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Load ${loadType}${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">cart,banner,messages</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">true</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">X-Requested-With</stringProp> + <stringProp name="Header.value">XMLHttpRequest</stringProp> + </elementProp> + </collectionProp> + </HeaderManager> + <hashTree/> + + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="210217247">You added ${simple_product_1_name} to your shopping cart.</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="2057973164">This product is out of stock.</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">6</intProp> + </ResponseAssertion> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-350323027">\"summary_count\":1</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Simple Product 2 View${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}${simple_product_2_url_key}${url_suffix}</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="2142356705"><title>${simple_product_2_name}</stringProp> + <stringProp name="-1787050162"><span>In stock</span></stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Customer Section Load${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">banner</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">false</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1898134910">\"banner\":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Ajax Review Simple Product 2(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}review/product/listAjax/id/${simple_product_2_id}/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="49586">200</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_code</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Simple Product 2 Add To Cart${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="product" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${simple_product_2_id}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">product</stringProp> + </elementProp> + <elementProp name="related_product" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value"/> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">related_product</stringProp> + </elementProp> + <elementProp name="qty" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">1</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">qty</stringProp> + </elementProp> + <elementProp name="form_key" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${form_key}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">form_key</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}checkout/cart/add/uenc/${simple_product_2_uenc}/product/${simple_product_2_id}/</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">X-Requested-With</stringProp> + <stringProp name="Header.value">XMLHttpRequest</stringProp> + </elementProp> + </collectionProp> + </HeaderManager> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Load ${loadType}2${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">cart,banner,messages</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + <stringProp name="Argument.desc">true</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">true</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + <stringProp name="Argument.desc">true</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + <stringProp name="Argument.desc">true</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">X-Requested-With</stringProp> + <stringProp name="Header.value">XMLHttpRequest</stringProp> + </elementProp> + </collectionProp> + </HeaderManager> + <hashTree/> + + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="221533374">You added ${simple_product_2_name} to your shopping cart.</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="2057973164">This product is out of stock.</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">6</intProp> + </ResponseAssertion> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-350323026">\"summary_count\":2</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Configurable Product 1 View${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}${configurable_product_1_url_key}${url_suffix}</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="199922279"><title>${configurable_product_1_name}</stringProp> + <stringProp name="-1787050162"><span>In stock</span></stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Customer Section Load${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">banner</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">false</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1898134910">\"banner\":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Ajax Review Configurable Product 1(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}review/product/listAjax/id/${configurable_product_1_id}/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="49586">200</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_code</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Configurable Product 1 Add To Cart${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="product" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${configurable_product_1_id}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">product</stringProp> + </elementProp> + <elementProp name="related_product" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value"/> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">related_product</stringProp> + </elementProp> + <elementProp name="qty" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">1</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">qty</stringProp> + </elementProp> + <elementProp name="super_attribute[${configurable_attribute_id}]" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${configurable_option_id}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">super_attribute[${configurable_attribute_id}]</stringProp> + </elementProp> + <elementProp name="form_key" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${form_key}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">form_key</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}checkout/cart/add/uenc/${configurable_product_1_uenc}/product/${configurable_product_1_id}/</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">X-Requested-With</stringProp> + <stringProp name="Header.value">XMLHttpRequest</stringProp> + </elementProp> + </collectionProp> + </HeaderManager> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Load ${loadType}3${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">cart,banner,messages</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + <stringProp name="Argument.desc">true</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">true</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + <stringProp name="Argument.desc">true</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + <stringProp name="Argument.desc">true</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">X-Requested-With</stringProp> + <stringProp name="Header.value">XMLHttpRequest</stringProp> + </elementProp> + </collectionProp> + </HeaderManager> + <hashTree/> + + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1346272328">You added ${configurable_product_1_name} to your shopping cart.</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-108122347">We don't have as many &quot;${configurable_product_1_name}&quot; as you requested.</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">6</intProp> + </ResponseAssertion> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-350323025">\"summary_count\":3</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + </hashTree> + + <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Checkout By Guest" enabled="true"> + <stringProp name="ThreadGroup.on_sample_error">continue</stringProp> + <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true"> + <boolProp name="LoopController.continue_forever">false</boolProp> + <stringProp name="LoopController.loops">${loops}</stringProp> + </elementProp> + <stringProp name="ThreadGroup.num_threads">${__javaScript(Math.round(props.get("users")*${guest_checkout_percent}/100>>0))}</stringProp> + <stringProp name="ThreadGroup.ramp_time">${ramp_period}</stringProp> + <longProp name="ThreadGroup.start_time">1437409133000</longProp> + <longProp name="ThreadGroup.end_time">1437409133000</longProp> + <boolProp name="ThreadGroup.scheduler">false</boolProp> + <stringProp name="ThreadGroup.duration"/> + <stringProp name="ThreadGroup.delay"/> + </ThreadGroup> + <hashTree> + <RandomVariableConfig guiclass="TestBeanGUI" testclass="RandomVariableConfig" testname="Random Variable 1" enabled="true"> + <stringProp name="variableName">rv1</stringProp> + <stringProp name="outputFormat">'.'</stringProp> + <stringProp name="minimumValue">1</stringProp> + <stringProp name="maximumValue">999999</stringProp> + <stringProp name="randomSeed">1</stringProp> + <boolProp name="perThread">true</boolProp> + </RandomVariableConfig> + <hashTree/> + + <RandomVariableConfig guiclass="TestBeanGUI" testclass="RandomVariableConfig" testname="Random Variable 2" enabled="true"> + <stringProp name="variableName">rv2</stringProp> + <stringProp name="outputFormat">'.'</stringProp> + <stringProp name="minimumValue">1</stringProp> + <stringProp name="maximumValue">999999</stringProp> + <stringProp name="randomSeed">2</stringProp> + <boolProp name="perThread">true</boolProp> + </RandomVariableConfig> + <hashTree/> + + <RandomVariableConfig guiclass="TestBeanGUI" testclass="RandomVariableConfig" testname="Random Variable 3" enabled="true"> + <stringProp name="variableName">rv3</stringProp> + <stringProp name="outputFormat">'.'</stringProp> + <stringProp name="minimumValue">1</stringProp> + <stringProp name="maximumValue">999999</stringProp> + <stringProp name="randomSeed">3</stringProp> + <boolProp name="perThread">true</boolProp> + </RandomVariableConfig> + <hashTree/> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="Get arguments${__property(activeAdminThread)}(GuestChkt)" enabled="true"> + <stringProp name="TestPlan.comments">Passing arguments between threads</stringProp> + <stringProp name="BeanShellSampler.query">number = (int)(${rv1} * props.get("simple_products_list").size()); +simpleList = props.get("simple_products_list").get(number); +vars.put("simple_product_1_url_key", simpleList.get("url_key")); +vars.put("simple_product_1_name", simpleList.get("title")); +vars.put("simple_product_1_id", simpleList.get("id")); +vars.put("simple_product_1_uenc", simpleList.get("uenc")); + +number1 = (int)(${rv2} * props.get("simple_products_list").size()); +simpleList = props.get("simple_products_list").get(number1); +vars.put("simple_product_2_url_key", simpleList.get("url_key")); +vars.put("simple_product_2_name", simpleList.get("title")); +vars.put("simple_product_2_id", simpleList.get("id")); +vars.put("simple_product_2_uenc", simpleList.get("uenc")); + +number = (int)(${rv3} * props.get("configurable_products_list").size()); +configurableList = props.get("configurable_products_list").get(number); +vars.put("configurable_product_1_url_key", configurableList.get("url_key")); +vars.put("configurable_product_1_name", configurableList.get("title")); +vars.put("configurable_product_1_id", configurableList.get("id")); +vars.put("configurable_attribute_id", configurableList.get("attribute_id")); +vars.put("configurable_option_id", configurableList.get("attribute_option_id")); +vars.put("configurable_product_1_uenc", simpleList.get("uenc")); + +vars.put("category_url_key", props.get("category_url_key")); +vars.put("category_name", props.get("category_name")); +vars.put("testLabel", "GuestChkt"); +vars.put("loadType", "Guest");</stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Open Home Page${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="571386695"><title>Home page</title></stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Simple Product 2 Add To Cart(GuestChkt)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"> - <elementProp name="product" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">${simple_product_2_id}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">product</stringProp> - </elementProp> - <elementProp name="related_product" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value"></stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">related_product</stringProp> - </elementProp> - <elementProp name="qty" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">1</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">qty</stringProp> - </elementProp> - <elementProp name="isAjax" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">true</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">isAjax</stringProp> - </elementProp> - <elementProp name="ajax" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">true</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">ajax</stringProp> - </elementProp> - </collectionProp> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Customer All Section Load${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value"/> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">false</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-2001627678">\"messages\":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Ajax Load Login Form${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="blocks" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">["customer_form_login"]</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">blocks</stringProp> + </elementProp> + <elementProp name="handles" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">["default","customer_account_login"]</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">handles</stringProp> + </elementProp> + <elementProp name="originalRequest" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">{"route":"customer","controller":"account","action":"login","uri":"/customer/account/login/"}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">originalRequest</stringProp> + </elementProp> + <elementProp name="ajax" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">true</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">ajax</stringProp> + </elementProp> + <elementProp name="isAjax" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">true</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">isAjax</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}page_cache/block/render/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="940598773">"customer_form_login"</stringProp> + <stringProp name="1951684663">Registered Customers</stringProp> + <stringProp name="474011748">form_key</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form key" enabled="true"> + <stringProp name="RegexExtractor.useHeaders">false</stringProp> + <stringProp name="RegexExtractor.refname">form_key</stringProp> + <stringProp name="RegexExtractor.regex"><input name=\\"form_key\\" type=\\"hidden\\" value=\\"([^'"]+)\\" \\/></stringProp> + <stringProp name="RegexExtractor.template">$1$</stringProp> + <stringProp name="RegexExtractor.default"/> + <stringProp name="RegexExtractor.match_number">1</stringProp> + </RegexExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert form_key extracted" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="2845929">^.+$</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">1</intProp> + <stringProp name="Assertion.scope">variable</stringProp> + <stringProp name="Scope.variable">form_key</stringProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Open Category${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}${category_url_key}${url_suffix}</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1210004667"><span class="base" data-ui-id="page-title">${category_name}</span></stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">6</intProp> + </ResponseAssertion> + <hashTree/> + <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor: Extract category id" enabled="true"> + <stringProp name="RegexExtractor.useHeaders">false</stringProp> + <stringProp name="RegexExtractor.refname">category_id</stringProp> + <stringProp name="RegexExtractor.regex"><li class="item category([^'"]+)">\s*<strong>${category_name}</strong>\s*</li></stringProp> + <stringProp name="RegexExtractor.template">$1$</stringProp> + <stringProp name="RegexExtractor.default"/> + <stringProp name="RegexExtractor.match_number">1</stringProp> + <stringProp name="Scope.variable">simple_product_1_url_key</stringProp> + </RegexExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion: Assert category id" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1191417111">^[0-9]+$</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">1</intProp> + <stringProp name="Assertion.scope">variable</stringProp> + <stringProp name="Scope.variable">category_id</stringProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Customer Section Load${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">banner</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">false</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1898134910">\"banner\":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Simple Product 1 View${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}${simple_product_1_url_key}${url_suffix}</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1254853024"><title>${simple_product_1_name}</stringProp> + <stringProp name="-1787050162"><span>In stock</span></stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Customer Section Load${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">banner</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">false</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1898134910">\"banner\":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Ajax Review Simple Product 1(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}review/product/listAjax/id/${simple_product_1_id}/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="49586">200</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_code</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Simple Product 1 Add To Cart${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="product" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${simple_product_1_id}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">product</stringProp> + </elementProp> + <elementProp name="related_product" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value"/> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">related_product</stringProp> + </elementProp> + <elementProp name="qty" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">1</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">qty</stringProp> + </elementProp> + <elementProp name="form_key" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${form_key}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">form_key</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}checkout/cart/add/uenc/${simple_product_1_uenc}/product/${simple_product_1_id}/</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + + <hashTree> + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">X-Requested-With</stringProp> + <stringProp name="Header.value">XMLHttpRequest</stringProp> + </elementProp> + </collectionProp> + </HeaderManager> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Load ${loadType}${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">cart,banner,messages</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">true</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">X-Requested-With</stringProp> + <stringProp name="Header.value">XMLHttpRequest</stringProp> + </elementProp> + </collectionProp> + </HeaderManager> + <hashTree/> + + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="210217247">You added ${simple_product_1_name} to your shopping cart.</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="2057973164">This product is out of stock.</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">6</intProp> + </ResponseAssertion> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-350323027">\"summary_count\":1</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Simple Product 2 View${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}${simple_product_2_url_key}${url_suffix}</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="2142356705"><title>${simple_product_2_name}</stringProp> + <stringProp name="-1787050162"><span>In stock</span></stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Customer Section Load${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">banner</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">false</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1898134910">\"banner\":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Ajax Review Simple Product 2(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}review/product/listAjax/id/${simple_product_2_id}/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="49586">200</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_code</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Simple Product 2 Add To Cart${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="product" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${simple_product_2_id}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">product</stringProp> + </elementProp> + <elementProp name="related_product" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value"/> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">related_product</stringProp> + </elementProp> + <elementProp name="qty" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">1</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">qty</stringProp> + </elementProp> + <elementProp name="form_key" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${form_key}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">form_key</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}checkout/cart/add/uenc/${simple_product_2_uenc}/product/${simple_product_2_id}/</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">X-Requested-With</stringProp> + <stringProp name="Header.value">XMLHttpRequest</stringProp> + </elementProp> + </collectionProp> + </HeaderManager> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Load ${loadType}2${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">cart,banner,messages</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + <stringProp name="Argument.desc">true</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">true</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + <stringProp name="Argument.desc">true</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + <stringProp name="Argument.desc">true</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">X-Requested-With</stringProp> + <stringProp name="Header.value">XMLHttpRequest</stringProp> + </elementProp> + </collectionProp> + </HeaderManager> + <hashTree/> + + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="221533374">You added ${simple_product_2_name} to your shopping cart.</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="2057973164">This product is out of stock.</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">6</intProp> + </ResponseAssertion> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-350323026">\"summary_count\":2</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Configurable Product 1 View${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}${configurable_product_1_url_key}${url_suffix}</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="199922279"><title>${configurable_product_1_name}</stringProp> + <stringProp name="-1787050162"><span>In stock</span></stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Customer Section Load${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">banner</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">false</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1898134910">\"banner\":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Ajax Review Configurable Product 1(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}review/product/listAjax/id/${configurable_product_1_id}/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="49586">200</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_code</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Configurable Product 1 Add To Cart${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="product" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${configurable_product_1_id}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">product</stringProp> + </elementProp> + <elementProp name="related_product" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value"/> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">related_product</stringProp> + </elementProp> + <elementProp name="qty" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">1</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">qty</stringProp> + </elementProp> + <elementProp name="super_attribute[${configurable_attribute_id}]" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${configurable_option_id}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">super_attribute[${configurable_attribute_id}]</stringProp> + </elementProp> + <elementProp name="form_key" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${form_key}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">form_key</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}checkout/cart/add/uenc/${configurable_product_1_uenc}/product/${configurable_product_1_id}/</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">X-Requested-With</stringProp> + <stringProp name="Header.value">XMLHttpRequest</stringProp> + </elementProp> + </collectionProp> + </HeaderManager> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Load ${loadType}3${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">cart,banner,messages</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + <stringProp name="Argument.desc">true</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">true</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + <stringProp name="Argument.desc">true</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + <stringProp name="Argument.desc">true</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">X-Requested-With</stringProp> + <stringProp name="Header.value">XMLHttpRequest</stringProp> + </elementProp> + </collectionProp> + </HeaderManager> + <hashTree/> + + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1346272328">You added ${configurable_product_1_name} to your shopping cart.</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-108122347">We don't have as many &quot;${configurable_product_1_name}&quot; as you requested.</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">6</intProp> + </ResponseAssertion> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-350323025">\"summary_count\":3</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout start${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}checkout/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1403911775"><title>Checkout</title></stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-179817969"><title>Shopping Cart</title></stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">6</intProp> + </ResponseAssertion> + <hashTree/> + <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract Cart Id" enabled="true"> + <stringProp name="RegexExtractor.useHeaders">false</stringProp> + <stringProp name="RegexExtractor.refname">cart_id</stringProp> + <stringProp name="RegexExtractor.regex">"quoteData":{"entity_id":"([^'"]+)",</stringProp> + <stringProp name="RegexExtractor.template">$1$</stringProp> + <stringProp name="RegexExtractor.default"/> + <stringProp name="RegexExtractor.match_number">1</stringProp> + </RegexExtractor> + <hashTree/> + <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form key" enabled="true"> + <stringProp name="RegexExtractor.useHeaders">false</stringProp> + <stringProp name="RegexExtractor.refname">form_key</stringProp> + <stringProp name="RegexExtractor.regex"><input name="form_key" type="hidden" value="([^'"]+)" /></stringProp> + <stringProp name="RegexExtractor.template">$1$</stringProp> + <stringProp name="RegexExtractor.default"/> + <stringProp name="RegexExtractor.match_number">1</stringProp> + </RegexExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert Cart Id extracted" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="2845929">^.+$</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">1</intProp> + <stringProp name="Assertion.scope">variable</stringProp> + <stringProp name="Scope.variable">cart_id</stringProp> + </ResponseAssertion> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert form_key extracted" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="2845929">^.+$</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">1</intProp> + <stringProp name="Assertion.scope">variable</stringProp> + <stringProp name="Scope.variable">form_key</stringProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Customer Section Load${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">banner</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">false</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1898134910">\"banner\":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout Estimate Shipping Methods ${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"address":{"country_id":"US"}}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}/rest/default/V1/guest-carts/${cart_id}/estimate-shipping-methods</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Referer</stringProp> + <stringProp name="Header.value">${base_path}checkout/onepage/</stringProp> + </elementProp> + <elementProp name="Content-Type" elementType="Header"> + <stringProp name="Header.name">Content-Type</stringProp> + <stringProp name="Header.value">application/json; charset=UTF-8</stringProp> + </elementProp> + <elementProp name="X-Requested-With" elementType="Header"> + <stringProp name="Header.name">X-Requested-With</stringProp> + <stringProp name="Header.value">XMLHttpRequest</stringProp> + </elementProp> + <elementProp name="Accept" elementType="Header"> + <stringProp name="Header.name">Accept</stringProp> + <stringProp name="Header.value">application/json</stringProp> + </elementProp> + </collectionProp> + </HeaderManager> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert success" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1224567411">"available":true</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout Email Available ${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"customerEmail":"test@example.com"}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}rest/default/V1/customers/isEmailAvailable</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Referer</stringProp> + <stringProp name="Header.value">${base_path}checkout/onepage/</stringProp> + </elementProp> + <elementProp name="Content-Type" elementType="Header"> + <stringProp name="Header.name">Content-Type</stringProp> + <stringProp name="Header.value">application/json; charset=UTF-8</stringProp> + </elementProp> + <elementProp name="X-Requested-With" elementType="Header"> + <stringProp name="Header.name">X-Requested-With</stringProp> + <stringProp name="Header.value">XMLHttpRequest</stringProp> + </elementProp> + <elementProp name="Accept" elementType="Header"> + <stringProp name="Header.name">Accept</stringProp> + <stringProp name="Header.value">application/json</stringProp> + </elementProp> + </collectionProp> + </HeaderManager> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="3569038">true</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">8</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout Estimate Shipping Methods ${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"address":{"country_id":"US","postcode":"95630"}}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}/rest/default/V1/guest-carts/${cart_id}/estimate-shipping-methods</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Referer</stringProp> + <stringProp name="Header.value">${base_path}checkout/onepage/</stringProp> + </elementProp> + <elementProp name="Content-Type" elementType="Header"> + <stringProp name="Header.name">Content-Type</stringProp> + <stringProp name="Header.value">application/json; charset=UTF-8</stringProp> + </elementProp> + <elementProp name="X-Requested-With" elementType="Header"> + <stringProp name="Header.name">X-Requested-With</stringProp> + <stringProp name="Header.value">XMLHttpRequest</stringProp> + </elementProp> + <elementProp name="Accept" elementType="Header"> + <stringProp name="Header.name">Accept</stringProp> + <stringProp name="Header.value">application/json</stringProp> + </elementProp> + </collectionProp> + </HeaderManager> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert success" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1224567411">"available":true</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout Billing/Shipping Information ${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"addressInformation":{"shipping_address":{"countryId":"US","regionId":"12","regionCode":"CA","region":"California","street":["10441 Jefferson Blvd ste 200"],"company":"","telephone":"3109450345","fax":"","postcode":"90232","city":"Culver City","firstname":"Name","lastname":"Lastname"},"shipping_method_code":"flatrate","shipping_carrier_code":"flatrate"}}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}rest/default/V1/carts/${cart_id}/shipping-information</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Referer</stringProp> + <stringProp name="Header.value">${base_path}checkout/onepage/</stringProp> + </elementProp> + <elementProp name="Content-Type" elementType="Header"> + <stringProp name="Header.name">Content-Type</stringProp> + <stringProp name="Header.value">application/json; charset=UTF-8</stringProp> + </elementProp> + <elementProp name="X-Requested-With" elementType="Header"> + <stringProp name="Header.name">X-Requested-With</stringProp> + <stringProp name="Header.value">XMLHttpRequest</stringProp> + </elementProp> + <elementProp name="Accept" elementType="Header"> + <stringProp name="Header.name">Accept</stringProp> + <stringProp name="Header.value">application/json</stringProp> + </elementProp> + </collectionProp> + </HeaderManager> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert success" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1494218646">{"payment_methods":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Customer Section Load${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">banner</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">true</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1898134910">\"banner\":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout Payment Info/Place Order ${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"cartId":"${cart_id}","email":"test@example.com","paymentMethod":{"method":"checkmo","po_number":null,"additional_data":null},"billingAddress":{"countryId":"US","regionId":"12","regionCode":"CA","region":"California","street":["10441 Jefferson Blvd ste 200"],"company":"","telephone":"3109450345","fax":"","postcode":"90232","city":"Culver City","firstname":"Name","lastname":"Lastname"}}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}/rest/default/V1/guest-carts/${cart_id}/payment-information</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Referer</stringProp> + <stringProp name="Header.value">${base_path}checkout/onepage/</stringProp> + </elementProp> + <elementProp name="Content-Type" elementType="Header"> + <stringProp name="Header.name">Content-Type</stringProp> + <stringProp name="Header.value">application/json; charset=UTF-8</stringProp> + </elementProp> + <elementProp name="X-Requested-With" elementType="Header"> + <stringProp name="Header.name">X-Requested-With</stringProp> + <stringProp name="Header.value">XMLHttpRequest</stringProp> + </elementProp> + <elementProp name="Accept" elementType="Header"> + <stringProp name="Header.name">Accept</stringProp> + <stringProp name="Header.value">application/json</stringProp> + </elementProp> + </collectionProp> + </HeaderManager> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert success" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-297987887">"[0-9]+"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + <com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor guiclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.gui.JSONPathExtractorGui" testclass="com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor" testname="Extract cart id" enabled="true"> + <stringProp name="VAR">order_id</stringProp> + <stringProp name="JSONPATH">$</stringProp> + <stringProp name="DEFAULT"/> + <stringProp name="VARIABLE"/> + <stringProp name="SUBJECT">BODY</stringProp> + </com.atlantbh.jmeter.plugins.jsonutils.jsonpathextractor.JSONPathExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="89649215">^\d+$</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">1</intProp> + <stringProp name="Assertion.scope">variable</stringProp> + <stringProp name="Scope.variable">order_id</stringProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout success${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}checkout/onepage/success/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert success" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="494863233">Thank you for your purchase!</stringProp> + <stringProp name="1635682758">Your order # is</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Customer Section Load${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">banner</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">false</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1898134910">\"banner\":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + </hashTree> + + <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Checkout By Customer" enabled="true"> + <stringProp name="ThreadGroup.on_sample_error">continue</stringProp> + <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true"> + <boolProp name="LoopController.continue_forever">false</boolProp> + <stringProp name="LoopController.loops">${loops}</stringProp> + </elementProp> + <stringProp name="ThreadGroup.num_threads">${__javaScript(Math.round(props.get("users")*${customer_checkout_percent}/100>>0))}</stringProp> + <stringProp name="ThreadGroup.ramp_time">${ramp_period}</stringProp> + <longProp name="ThreadGroup.start_time">1437177203000</longProp> + <longProp name="ThreadGroup.end_time">1437177203000</longProp> + <boolProp name="ThreadGroup.scheduler">false</boolProp> + <stringProp name="ThreadGroup.duration"/> + <stringProp name="ThreadGroup.delay"/> + </ThreadGroup> + <hashTree> + <RandomVariableConfig guiclass="TestBeanGUI" testclass="RandomVariableConfig" testname="Random Variable 1" enabled="true"> + <stringProp name="variableName">rv1</stringProp> + <stringProp name="outputFormat">'.'</stringProp> + <stringProp name="minimumValue">1</stringProp> + <stringProp name="maximumValue">999999</stringProp> + <stringProp name="randomSeed">1</stringProp> + <boolProp name="perThread">true</boolProp> + </RandomVariableConfig> + <hashTree/> + + <RandomVariableConfig guiclass="TestBeanGUI" testclass="RandomVariableConfig" testname="Random Variable 2" enabled="true"> + <stringProp name="variableName">rv2</stringProp> + <stringProp name="outputFormat">'.'</stringProp> + <stringProp name="minimumValue">1</stringProp> + <stringProp name="maximumValue">999999</stringProp> + <stringProp name="randomSeed">2</stringProp> + <boolProp name="perThread">true</boolProp> + </RandomVariableConfig> + <hashTree/> + + <RandomVariableConfig guiclass="TestBeanGUI" testclass="RandomVariableConfig" testname="Random Variable 3" enabled="true"> + <stringProp name="variableName">rv3</stringProp> + <stringProp name="outputFormat">'.'</stringProp> + <stringProp name="minimumValue">1</stringProp> + <stringProp name="maximumValue">999999</stringProp> + <stringProp name="randomSeed">3</stringProp> + <boolProp name="perThread">true</boolProp> + </RandomVariableConfig> + <hashTree/> + + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="Get arguments${__property(activeAdminThread)}(CustomerChkt)" enabled="true"> + <stringProp name="TestPlan.comments">Passing arguments between threads</stringProp> + <stringProp name="BeanShellSampler.query">import org.apache.jmeter.samplers.SampleResult; + +number = (int)(${rv1} * props.get("simple_products_list").size()); +simpleList = props.get("simple_products_list").get(number); +vars.put("simple_product_1_url_key", simpleList.get("url_key")); +vars.put("simple_product_1_name", simpleList.get("title")); +vars.put("simple_product_1_id", simpleList.get("id")); +vars.put("simple_product_1_uenc", simpleList.get("uenc")); + +number1 = (int)(${rv2} * props.get("simple_products_list").size()); +simpleList = props.get("simple_products_list").get(number1); +vars.put("simple_product_2_url_key", simpleList.get("url_key")); +vars.put("simple_product_2_name", simpleList.get("title")); +vars.put("simple_product_2_id", simpleList.get("id")); +vars.put("simple_product_2_uenc", simpleList.get("uenc")); + +number = (int)(${rv3} * props.get("configurable_products_list").size()); +configurableList = props.get("configurable_products_list").get(number); +vars.put("configurable_product_1_url_key", configurableList.get("url_key")); +vars.put("configurable_product_1_name", configurableList.get("title")); +vars.put("configurable_product_1_id", configurableList.get("id")); +vars.put("configurable_attribute_id", configurableList.get("attribute_id")); +vars.put("configurable_option_id", configurableList.get("attribute_option_id")); +vars.put("configurable_product_1_uenc", simpleList.get("uenc")); + +vars.put("category_url_key", props.get("category_url_key")); +vars.put("category_name", props.get("category_name")); + +emails_index = 0; +if (!props.containsKey("customer_emails_index")) { + props.put("customer_emails_index", emails_index); +} + +try { + emails_index = props.get("customer_emails_index"); + emails_list = props.get("customer_emails_list"); + if (emails_index == emails_list.size()) { + emails_index=0; + } + vars.put("customer_email", emails_list.get(emails_index)); + props.put("customer_emails_index", ++emails_index); +} +catch (java.lang.Exception e) { + log.error("Caught Exception in 'Customer Checkout' thread."); + log.info("Using default email address - user_1@example.com"); + vars.put("customer_email", "user_1@example.com"); +} +vars.put("testLabel", "CustomerChkt"); +vars.put("loadType", "Customer");</stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> + </BeanShellSampler> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Open Home Page${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="571386695"><title>Home page</title></stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Customer All Section Load${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value"/> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">false</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-2001627678">\"messages\":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Open Login Page${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/account/login/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="637394530"><title>Customer Login</title></stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Customer Section Load${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">banner</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">false</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1898134910">\"banner\":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Ajax Load Login Form${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="blocks" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">["customer_form_login"]</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">blocks</stringProp> + </elementProp> + <elementProp name="handles" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">["default","customer_account_login"]</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">handles</stringProp> + </elementProp> + <elementProp name="originalRequest" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">{"route":"customer","controller":"account","action":"login","uri":"/customer/account/login/"}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">originalRequest</stringProp> + </elementProp> + <elementProp name="ajax" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">true</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">ajax</stringProp> + </elementProp> + <elementProp name="isAjax" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">true</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">isAjax</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}page_cache/block/render/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="940598773">"customer_form_login"</stringProp> + <stringProp name="1951684663">Registered Customers</stringProp> + <stringProp name="474011748">form_key</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form key" enabled="true"> + <stringProp name="RegexExtractor.useHeaders">false</stringProp> + <stringProp name="RegexExtractor.refname">form_key</stringProp> + <stringProp name="RegexExtractor.regex"><input name=\\"form_key\\" type=\\"hidden\\" value=\\"([^'"]+)\\" \\/></stringProp> + <stringProp name="RegexExtractor.template">$1$</stringProp> + <stringProp name="RegexExtractor.default"/> + <stringProp name="RegexExtractor.match_number">1</stringProp> + </RegexExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert form_key extracted" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="2845929">^.+$</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">1</intProp> + <stringProp name="Assertion.scope">variable</stringProp> + <stringProp name="Scope.variable">form_key</stringProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Login${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="form_key" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">${form_key}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">form_key</stringProp> + </elementProp> + <elementProp name="login[username]" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">${customer_email}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">login[username]</stringProp> + </elementProp> + <elementProp name="login[password]" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">${customer_password}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">login[password]</stringProp> + </elementProp> + <elementProp name="send" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value"/> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">send</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/account/loginPost/</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1312950388"><title>My Account</title></stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Customer Section Load${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">banner</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">false</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1898134910">\"banner\":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Open Category${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}${category_url_key}${url_suffix}</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1210004667"><span class="base" data-ui-id="page-title">${category_name}</span></stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">6</intProp> + </ResponseAssertion> + <hashTree/> + <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor: Extract category id" enabled="true"> + <stringProp name="RegexExtractor.useHeaders">false</stringProp> + <stringProp name="RegexExtractor.refname">category_id</stringProp> + <stringProp name="RegexExtractor.regex"><li class="item category([^'"]+)">\s*<strong>${category_name}</strong>\s*</li></stringProp> + <stringProp name="RegexExtractor.template">$1$</stringProp> + <stringProp name="RegexExtractor.default"/> + <stringProp name="RegexExtractor.match_number">1</stringProp> + <stringProp name="Scope.variable">simple_product_1_url_key</stringProp> + </RegexExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion: Assert category id" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1191417111">^[0-9]+$</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">1</intProp> + <stringProp name="Assertion.scope">variable</stringProp> + <stringProp name="Scope.variable">category_id</stringProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Customer Section Load${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">banner</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">false</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1898134910">\"banner\":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Simple Product 1 View${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}${simple_product_1_url_key}${url_suffix}</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="1254853024"><title>${simple_product_1_name}</stringProp> + <stringProp name="-1787050162"><span>In stock</span></stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Customer Section Load${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">banner</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">false</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1898134910">\"banner\":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Ajax Review Simple Product 1(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}review/product/listAjax/id/${simple_product_1_id}/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="49586">200</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_code</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Simple Product 1 Add To Cart${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="product" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${simple_product_1_id}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">product</stringProp> + </elementProp> + <elementProp name="related_product" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value"/> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">related_product</stringProp> + </elementProp> + <elementProp name="qty" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">1</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">qty</stringProp> + </elementProp> + <elementProp name="form_key" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${form_key}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">form_key</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}checkout/cart/add/uenc/${simple_product_1_uenc}/product/${simple_product_1_id}/</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + + <hashTree> + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">X-Requested-With</stringProp> + <stringProp name="Header.value">XMLHttpRequest</stringProp> + </elementProp> + </collectionProp> + </HeaderManager> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Load ${loadType}${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">cart,banner,messages</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">true</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">X-Requested-With</stringProp> + <stringProp name="Header.value">XMLHttpRequest</stringProp> + </elementProp> + </collectionProp> + </HeaderManager> + <hashTree/> + + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="210217247">You added ${simple_product_1_name} to your shopping cart.</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="2057973164">This product is out of stock.</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">6</intProp> + </ResponseAssertion> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-350323027">\"summary_count\":1</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Simple Product 2 View${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}${simple_product_2_url_key}${url_suffix}</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="2142356705"><title>${simple_product_2_name}</stringProp> + <stringProp name="-1787050162"><span>In stock</span></stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Customer Section Load${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">banner</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">false</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1898134910">\"banner\":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Ajax Review Simple Product 2(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}review/product/listAjax/id/${simple_product_2_id}/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="49586">200</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_code</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Simple Product 2 Add To Cart${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="product" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${simple_product_2_id}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">product</stringProp> + </elementProp> + <elementProp name="related_product" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value"/> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">related_product</stringProp> + </elementProp> + <elementProp name="qty" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">1</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">qty</stringProp> + </elementProp> + <elementProp name="form_key" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${form_key}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">form_key</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}checkout/cart/add/uenc/${simple_product_2_uenc}/product/${simple_product_2_id}/</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">X-Requested-With</stringProp> + <stringProp name="Header.value">XMLHttpRequest</stringProp> + </elementProp> + </collectionProp> + </HeaderManager> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Load ${loadType}2${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">cart,banner,messages</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + <stringProp name="Argument.desc">true</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">true</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + <stringProp name="Argument.desc">true</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + <stringProp name="Argument.desc">true</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">X-Requested-With</stringProp> + <stringProp name="Header.value">XMLHttpRequest</stringProp> + </elementProp> + </collectionProp> + </HeaderManager> + <hashTree/> + + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="221533374">You added ${simple_product_2_name} to your shopping cart.</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="2057973164">This product is out of stock.</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">6</intProp> + </ResponseAssertion> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-350323026">\"summary_count\":2</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Configurable Product 1 View${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}${configurable_product_1_url_key}${url_suffix}</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="199922279"><title>${configurable_product_1_name}</stringProp> + <stringProp name="-1787050162"><span>In stock</span></stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Customer Section Load${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">banner</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">false</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1898134910">\"banner\":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Ajax Review Configurable Product 1(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}review/product/listAjax/id/${configurable_product_1_id}/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="49586">200</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_code</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Configurable Product 1 Add To Cart${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="product" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${configurable_product_1_id}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">product</stringProp> + </elementProp> + <elementProp name="related_product" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value"/> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">related_product</stringProp> + </elementProp> + <elementProp name="qty" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">1</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">qty</stringProp> + </elementProp> + <elementProp name="super_attribute[${configurable_attribute_id}]" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${configurable_option_id}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">super_attribute[${configurable_attribute_id}]</stringProp> + </elementProp> + <elementProp name="form_key" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${form_key}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">form_key</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}checkout/cart/add/uenc/${configurable_product_1_uenc}/product/${configurable_product_1_id}/</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">X-Requested-With</stringProp> + <stringProp name="Header.value">XMLHttpRequest</stringProp> + </elementProp> + </collectionProp> + </HeaderManager> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Load ${loadType}3${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">cart,banner,messages</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> + <stringProp name="Argument.desc">true</stringProp> + </elementProp> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">true</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + <stringProp name="Argument.desc">true</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + <stringProp name="Argument.desc">true</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">X-Requested-With</stringProp> + <stringProp name="Header.value">XMLHttpRequest</stringProp> + </elementProp> + </collectionProp> + </HeaderManager> + <hashTree/> + + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1346272328">You added ${configurable_product_1_name} to your shopping cart.</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-108122347">We don't have as many &quot;${configurable_product_1_name}&quot; as you requested.</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">6</intProp> + </ResponseAssertion> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-350323025">\"summary_count\":3</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout start${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}checkout/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1403911775"><title>Checkout</title></stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-179817969"><title>Shopping Cart</title></stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">6</intProp> + </ResponseAssertion> + <hashTree/> + <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract Cart Id" enabled="true"> + <stringProp name="RegexExtractor.useHeaders">false</stringProp> + <stringProp name="RegexExtractor.refname">cart_id</stringProp> + <stringProp name="RegexExtractor.regex">"quoteData":{"entity_id":"([^'"]+)",</stringProp> + <stringProp name="RegexExtractor.template">$1$</stringProp> + <stringProp name="RegexExtractor.default"/> + <stringProp name="RegexExtractor.match_number">1</stringProp> + </RegexExtractor> + <hashTree/> + <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form key" enabled="true"> + <stringProp name="RegexExtractor.useHeaders">false</stringProp> + <stringProp name="RegexExtractor.refname">form_key</stringProp> + <stringProp name="RegexExtractor.regex"><input name="form_key" type="hidden" value="([^'"]+)" /></stringProp> + <stringProp name="RegexExtractor.template">$1$</stringProp> + <stringProp name="RegexExtractor.default"/> + <stringProp name="RegexExtractor.match_number">1</stringProp> + </RegexExtractor> + <hashTree/> + <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract Address Id" enabled="true"> + <stringProp name="RegexExtractor.useHeaders">false</stringProp> + <stringProp name="RegexExtractor.refname">address_id</stringProp> + <stringProp name="RegexExtractor.regex">"default_billing":"([^'"]+)",</stringProp> + <stringProp name="RegexExtractor.template">$1$</stringProp> + <stringProp name="RegexExtractor.default"/> + <stringProp name="RegexExtractor.match_number">1</stringProp> + </RegexExtractor> + <hashTree/> + <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract Customer Id" enabled="true"> + <stringProp name="RegexExtractor.useHeaders">false</stringProp> + <stringProp name="RegexExtractor.refname">customer_id</stringProp> + <stringProp name="RegexExtractor.regex">"customer_id":([^'",]+),</stringProp> + <stringProp name="RegexExtractor.template">$1$</stringProp> + <stringProp name="RegexExtractor.default"/> + <stringProp name="RegexExtractor.match_number">1</stringProp> + </RegexExtractor> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert Cart Id extracted" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="2845929">^.+$</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">1</intProp> + <stringProp name="Assertion.scope">variable</stringProp> + <stringProp name="Scope.variable">cart_id</stringProp> + </ResponseAssertion> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert form_key extracted" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="2845929">^.+$</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">1</intProp> + <stringProp name="Assertion.scope">variable</stringProp> + <stringProp name="Scope.variable">form_key</stringProp> + </ResponseAssertion> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert Address Id extracted" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="576002869">[0-9]+$</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">1</intProp> + <stringProp name="Assertion.scope">variable</stringProp> + <stringProp name="Scope.variable">address_id</stringProp> + </ResponseAssertion> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert Customer Id extracted" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="576002869">[0-9]+$</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">1</intProp> + <stringProp name="Assertion.scope">variable</stringProp> + <stringProp name="Scope.variable">customer_id</stringProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Customer Section Load${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">banner</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${simple_product_2_form_action}</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="221533374">You added ${simple_product_2_name} to your shopping cart.</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="518066445"><div>* This product is out of stock.</div></stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">6</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> - <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Configurable Product 1 View(GuestChkt)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"/> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">false</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${base_path}${configurable_product_1_url_key}${url_suffix}</stringProp> - <stringProp name="HTTPSampler.method">GET</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="199922279"><title>${configurable_product_1_name}</stringProp> - <stringProp name="-1787050162"><span>In stock</span></stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form action" enabled="true"> - <stringProp name="RegexExtractor.useHeaders">false</stringProp> - <stringProp name="RegexExtractor.refname">configurable_product_form_action</stringProp> - <stringProp name="RegexExtractor.regex"><form action="([^'"]+)"\s*method="post"\s*id="product_addtocart_form"></stringProp> - <stringProp name="RegexExtractor.template">$1$</stringProp> - <stringProp name="RegexExtractor.default"></stringProp> - <stringProp name="RegexExtractor.match_number">1</stringProp> - </RegexExtractor> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert form_action extracted" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="2845929">^.+$</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">1</intProp> - <stringProp name="Assertion.scope">variable</stringProp> - <stringProp name="Scope.variable">configurable_product_form_action</stringProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> - <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Configurable Product 1 Add To Cart(GuestChkt)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"> - <elementProp name="product" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">${configurable_product_1_id}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">product</stringProp> - </elementProp> - <elementProp name="related_product" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value"></stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">related_product</stringProp> - </elementProp> - <elementProp name="qty" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">1</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">qty</stringProp> - </elementProp> - <elementProp name="super_attribute[${configurable_attribute_id}]" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">${configurable_option_id}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">super_attribute[${configurable_attribute_id}]</stringProp> - </elementProp> - <elementProp name="isAjax" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">true</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">isAjax</stringProp> - </elementProp> - <elementProp name="ajax" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">true</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">ajax</stringProp> - </elementProp> - </collectionProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${configurable_product_form_action}</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="-1346272328">You added ${configurable_product_1_name} to your shopping cart.</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="-815931116"><div>* We don't have as many &quot;${configurable_product_1_name}&quot; as you requested.</div></stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">6</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> - <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout start(GuestChkt)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"/> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1898134910">\"banner\":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout Billing/Shipping Information${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"addressInformation":{"shipping_address":{"customerAddressId":"${address_id}","countryId":"US","regionId":5,"regionCode":"AR","region":"Arkansas","customerId":"${customer_id}","street":["123 Freedom Blvd. #123"],"telephone":"022-333-4455","postcode":"123123","city":"Fayetteville","firstname":"Anthony","lastname":"Nealy"},"shipping_method_code":"flatrate","shipping_carrier_code":"flatrate"}}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${base_path}checkout/index/</stringProp> - <stringProp name="HTTPSampler.method">GET</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="-1403911775"><title>Checkout</title></stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="-179817969"><title>Shopping Cart</title></stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">6</intProp> - </ResponseAssertion> - <hashTree/> - <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract Cart Id" enabled="true"> - <stringProp name="RegexExtractor.useHeaders">false</stringProp> - <stringProp name="RegexExtractor.refname">cart_id</stringProp> - <stringProp name="RegexExtractor.regex">"quoteData":{"entity_id":"([^'"]+)",</stringProp> - <stringProp name="RegexExtractor.template">$1$</stringProp> - <stringProp name="RegexExtractor.default"></stringProp> - <stringProp name="RegexExtractor.match_number">1</stringProp> - </RegexExtractor> - <hashTree/> - <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form key" enabled="true"> - <stringProp name="RegexExtractor.useHeaders">false</stringProp> - <stringProp name="RegexExtractor.refname">form_key</stringProp> - <stringProp name="RegexExtractor.regex"><input name="form_key" type="hidden" value="([^'"]+)" /></stringProp> - <stringProp name="RegexExtractor.template">$1$</stringProp> - <stringProp name="RegexExtractor.default"></stringProp> - <stringProp name="RegexExtractor.match_number">1</stringProp> - </RegexExtractor> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert Cart Id extracted" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="2845929">^.+$</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">1</intProp> - <stringProp name="Assertion.scope">variable</stringProp> - <stringProp name="Scope.variable">cart_id</stringProp> - </ResponseAssertion> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert form_key extracted" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="2845929">^.+$</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">1</intProp> - <stringProp name="Assertion.scope">variable</stringProp> - <stringProp name="Scope.variable">form_key</stringProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> - <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout shipping information" enabled="true"> - <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> - <collectionProp name="Arguments.arguments"> - <elementProp name="" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"addressInformation":{"shipping_address":{"countryId":"US","regionId":"12","regionCode":"CA","region"
 -:"California","street":["10441 Jefferson Blvd","ste 200"],"company":"","telephone":"1-310-945-0345","fax"
 -:"","postcode":"90232","city":"Culver City","firstname":"Firstname","lastname":"Lastname","saveInAddressBook"
 -:false},"shipping_method_code":"flatrate","shipping_carrier_code":"flatrate"}}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - </elementProp> - </collectionProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}/rest/default/V1/carts/mine/shipping-information</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Referer</stringProp> + <stringProp name="Header.value">${host}${base_path}checkout/onepage</stringProp> </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> - <stringProp name="HTTPSampler.path">${base_path}rest/default/V1/carts/${cart_id}/shipping-information</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> - <collectionProp name="HeaderManager.headers"> - <elementProp name="" elementType="Header"> - <stringProp name="Header.name">Referer</stringProp> - <stringProp name="Header.value">http://mage2.com/checkout/index/</stringProp> - </elementProp> - <elementProp name="Content-Type" elementType="Header"> - <stringProp name="Header.name">Content-Type</stringProp> - <stringProp name="Header.value">application/json; charset=UTF-8</stringProp> - </elementProp> - <elementProp name="X-Requested-With" elementType="Header"> - <stringProp name="Header.name">X-Requested-With</stringProp> - <stringProp name="Header.value">XMLHttpRequest</stringProp> - </elementProp> - <elementProp name="Accept" elementType="Header"> - <stringProp name="Header.name">Accept</stringProp> - <stringProp name="Header.value">application/json</stringProp> - </elementProp> - </collectionProp> - </HeaderManager> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert success" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="-1494218646">{"payment_methods":</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> - <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout payment information" enabled="true"> - <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> - <collectionProp name="Arguments.arguments"> - <elementProp name="" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"cartId":"${cart_id}","email":"user@example.com","paymentMethod":{"method":"checkmo","po_number":null,"cc_owner":null,"cc_number":null,"cc_type":null,"cc_exp_year":null,"cc_exp_month":null,"additional_data":null},"billingAddress":{"countryId"
 -:"US","regionId":"12","regionCode":"CA","region":"California","street":["10441 Jefferson Blvd","ste 200"
 -],"company":"","telephone":"1-310-945-0345","fax":"","postcode":"90232","city":"Culver City","firstname"
 -:"Firstname","lastname":"Lastname","saveInAddressBook":false}}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - </elementProp> - </collectionProp> + <elementProp name="Content-Type" elementType="Header"> + <stringProp name="Header.name">Content-Type</stringProp> + <stringProp name="Header.value">application/json; charset=UTF-8</stringProp> </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> - <stringProp name="HTTPSampler.path">${base_path}rest/default/V1/guest-carts/${cart_id}/payment-information</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> - <collectionProp name="HeaderManager.headers"> - <elementProp name="" elementType="Header"> - <stringProp name="Header.name">Referer</stringProp> - <stringProp name="Header.value">http://mage2.com/checkout/index/</stringProp> - </elementProp> - <elementProp name="" elementType="Header"> - <stringProp name="Header.name">Content-Type</stringProp> - <stringProp name="Header.value">application/json; charset=UTF-8 </stringProp> - </elementProp> - <elementProp name="" elementType="Header"> - <stringProp name="Header.name">Accept</stringProp> - <stringProp name="Header.value">application/json</stringProp> - </elementProp> - <elementProp name="" elementType="Header"> - <stringProp name="Header.name">X-Requested-With</stringProp> - <stringProp name="Header.value">XMLHttpRequest</stringProp> - </elementProp> - </collectionProp> - </HeaderManager> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert success" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="-1412623327">^"\d+"$</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">1</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> - <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout success(GuestChkt)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"/> + <elementProp name="X-Requested-With" elementType="Header"> + <stringProp name="Header.name">X-Requested-With</stringProp> + <stringProp name="Header.value">XMLHttpRequest</stringProp> + </elementProp> + <elementProp name="Accept" elementType="Header"> + <stringProp name="Header.name">Accept</stringProp> + <stringProp name="Header.value">application/json</stringProp> + </elementProp> + </collectionProp> + </HeaderManager> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert success" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-740937264">{"payment_methods"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Customer Section Load${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">banner</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${base_path}checkout/onepage/success/</stringProp> - <stringProp name="HTTPSampler.method">GET</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert success" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="494863233">Thank you for your purchase!</stringProp> - <stringProp name="1635682758">Your order # is</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - </hashTree> - <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Customer Checkout" enabled="true"> - <stringProp name="ThreadGroup.on_sample_error">startnextloop</stringProp> - <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true"> - <boolProp name="LoopController.continue_forever">false</boolProp> - <stringProp name="LoopController.loops">${loops}</stringProp> - </elementProp> - <stringProp name="ThreadGroup.num_threads">${__javaScript(Math.round(props.get("users")*${customer_checkout_percent}/100>>0))}</stringProp> - <stringProp name="ThreadGroup.ramp_time">${ramp_period}</stringProp> - <longProp name="ThreadGroup.start_time">1304708488000</longProp> - <longProp name="ThreadGroup.end_time">1304708488000</longProp> - <boolProp name="ThreadGroup.scheduler">false</boolProp> - <stringProp name="ThreadGroup.duration"></stringProp> - <stringProp name="ThreadGroup.delay"></stringProp> - </ThreadGroup> - <hashTree> - <CookieManager guiclass="CookiePanel" testclass="CookieManager" testname="HTTP Cookie Manager" enabled="true"> - <collectionProp name="CookieManager.cookies"> - <elementProp name="product_list_limit" elementType="Cookie" testname="product_list_limit"> - <stringProp name="Cookie.value">30</stringProp> - <stringProp name="Cookie.domain">${host}</stringProp> - <stringProp name="Cookie.path">/</stringProp> - <boolProp name="Cookie.secure">false</boolProp> - <longProp name="Cookie.expires">0</longProp> - <boolProp name="Cookie.path_specified">true</boolProp> - <boolProp name="Cookie.domain_specified">true</boolProp> - </elementProp> - </collectionProp> - <boolProp name="CookieManager.clearEachIteration">true</boolProp> - </CookieManager> - <hashTree/> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="Get arguments(CustomerChkt)" enabled="true"> - <stringProp name="TestPlan.comments">Passing arguments between threads</stringProp> - <stringProp name="BeanShellSampler.query">import org.apache.jmeter.samplers.SampleResult; - -number = (int)(Math.random() * props.get("simple_products_list").size()); -simpleList = props.get("simple_products_list").get(number); -vars.put("simple_product_1_url_key", simpleList.get("url_key")); -vars.put("simple_product_1_name", simpleList.get("title")); -vars.put("simple_product_1_id", simpleList.get("id")); - -do { - number1 = (int)(Math.random() * props.get("simple_products_list").size()); -} while(number == number1); -simpleList = props.get("simple_products_list").get(number1); -vars.put("simple_product_2_url_key", simpleList.get("url_key")); -vars.put("simple_product_2_name", simpleList.get("title")); -vars.put("simple_product_2_id", simpleList.get("id")); - -number = (int)(Math.random() * props.get("configurable_products_list").size()); -configurableList = props.get("configurable_products_list").get(number); -vars.put("configurable_product_1_url_key", configurableList.get("url_key")); -vars.put("configurable_product_1_name", configurableList.get("title")); -vars.put("configurable_product_1_id", configurableList.get("id")); -vars.put("configurable_attribute_id", configurableList.get("attribute_id")); -vars.put("configurable_option_id", configurableList.get("attribute_option_id")); - -vars.put("category_url_key", props.get("category_url_key")); -vars.put("category_name", props.get("category_name")); - -emailsCount = props.get("customer_emails_list").size(); -print(emailsCount); -if (emailsCount < 1) { - log.error("You have to increase customers qty for running 'Customer Checkout' thread."); - System.out.println("You have to increase customers qty for running 'Customer Checkout' thread."); - SampleResult.setStopTest(true); -} else { - emails = props.get("customer_emails_list"); - email = emails.get(emailsCount - 1); - emails.remove(email); - props.put("customer_emails_list", emails); - vars.put("customer_email", email); -}</stringProp> - <stringProp name="BeanShellSampler.filename"></stringProp> - <stringProp name="BeanShellSampler.parameters"></stringProp> - <boolProp name="BeanShellSampler.resetInterpreter">true</boolProp> - </BeanShellSampler> - <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Open Home Page(CustomerChkt)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"/> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">true</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${base_path}</stringProp> - <stringProp name="HTTPSampler.method">GET</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="571386695"><title>Home page</title></stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> - <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Open Category(CustomerChkt)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"/> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${base_path}${category_url_key}${url_suffix}</stringProp> - <stringProp name="HTTPSampler.method">GET</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="1210004667"><span class="base" data-ui-id="page-title">${category_name}</span></stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">6</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> - <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Simple Product 1 View(CustomerChkt)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"/> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1898134910">\"banner\":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout Payment Info/Place Order${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> + <collectionProp name="Arguments.arguments"> + <elementProp name="" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">{"cartId":"${cart_id}","paymentMethod":{"method":"checkmo","po_number":null,"additional_data":null},"billingAddress":{"customerAddressId":"${address_id}","countryId":"US","regionId":5,"regionCode":"AR","region":"Arkansas","customerId":"${customer_id}","street":["123 Freedom Blvd. #123"],"telephone":"022-333-4455","postcode":"123123","city":"Fayetteville","firstname":"Anthony","lastname":"Nealy"}}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${base_path}${simple_product_1_url_key}${url_suffix}</stringProp> - <stringProp name="HTTPSampler.method">GET</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="1254853024"><title>${simple_product_1_name}</stringProp> - <stringProp name="-1787050162"><span>In stock</span></stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form action" enabled="true"> - <stringProp name="RegexExtractor.useHeaders">false</stringProp> - <stringProp name="RegexExtractor.refname">simple_product_1_form_action</stringProp> - <stringProp name="RegexExtractor.regex"><form action="([^'"]+)"\s*method="post"\s*id="product_addtocart_form"></stringProp> - <stringProp name="RegexExtractor.template">$1$</stringProp> - <stringProp name="RegexExtractor.default"></stringProp> - <stringProp name="RegexExtractor.match_number">1</stringProp> - </RegexExtractor> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert form_action extracted" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="2845929">^.+$</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">1</intProp> - <stringProp name="Assertion.scope">variable</stringProp> - <stringProp name="Scope.variable">simple_product_1_form_action</stringProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> - <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Simple Product 1 Add To Cart(CustomerChkt)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"> - <elementProp name="product" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">${simple_product_1_id}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">product</stringProp> - </elementProp> - <elementProp name="related_product" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value"></stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">related_product</stringProp> - </elementProp> - <elementProp name="qty" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">1</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">qty</stringProp> - </elementProp> - <elementProp name="isAjax" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">true</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">isAjax</stringProp> - </elementProp> - <elementProp name="ajax" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">true</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">ajax</stringProp> - </elementProp> - </collectionProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}rest/default/V1/carts/mine/payment-information</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> + <collectionProp name="HeaderManager.headers"> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Referer</stringProp> + <stringProp name="Header.value">${host}${base_path}checkout/onepage</stringProp> </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${simple_product_1_form_action}</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="210217247">You added ${simple_product_1_name} to your shopping cart.</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="518066445"><div>* This product is out of stock.</div></stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">6</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> - <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Simple Product 2 View(CustomerChkt)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"/> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Content-Type</stringProp> + <stringProp name="Header.value">application/json; charset=UTF-8 </stringProp> </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${base_path}${simple_product_2_url_key}${url_suffix}</stringProp> - <stringProp name="HTTPSampler.method">GET</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="2142356705"><title>${simple_product_2_name}</stringProp> - <stringProp name="-1787050162"><span>In stock</span></stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form action" enabled="true"> - <stringProp name="RegexExtractor.useHeaders">false</stringProp> - <stringProp name="RegexExtractor.refname">simple_product_2_form_action</stringProp> - <stringProp name="RegexExtractor.regex"><form action="([^'"]+)"\s*method="post"\s*id="product_addtocart_form"></stringProp> - <stringProp name="RegexExtractor.template">$1$</stringProp> - <stringProp name="RegexExtractor.default"></stringProp> - <stringProp name="RegexExtractor.match_number">1</stringProp> - </RegexExtractor> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert form_action extracted" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="2845929">^.+$</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">1</intProp> - <stringProp name="Assertion.scope">variable</stringProp> - <stringProp name="Scope.variable">simple_product_2_form_action</stringProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> - <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Simple Product 2 Add To Cart(CustomerChkt)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"> - <elementProp name="product" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">${simple_product_2_id}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">product</stringProp> - </elementProp> - <elementProp name="related_product" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value"></stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">related_product</stringProp> - </elementProp> - <elementProp name="qty" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">1</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">qty</stringProp> - </elementProp> - <elementProp name="isAjax" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">true</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">isAjax</stringProp> - </elementProp> - <elementProp name="ajax" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">true</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">ajax</stringProp> - </elementProp> - </collectionProp> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">Accept</stringProp> + <stringProp name="Header.value">application/json</stringProp> </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${simple_product_2_form_action}</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="221533374">You added ${simple_product_2_name} to your shopping cart.</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="518066445"><div>* This product is out of stock.</div></stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">6</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> - <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Configurable Product 1 View(CustomerChkt)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"/> + <elementProp name="" elementType="Header"> + <stringProp name="Header.name">X-Requested-With</stringProp> + <stringProp name="Header.value">XMLHttpRequest</stringProp> + </elementProp> + </collectionProp> + </HeaderManager> + <hashTree/> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert order number" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-297987887">"[0-9]+"</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> + <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> + <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> + </GaussianRandomTimer> + <hashTree/> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout success${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"/> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}checkout/onepage/success/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert success" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="494863233">Thank you for your purchase!</stringProp> + <stringProp name="-1590086334">Your order number is</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Customer Section Load${__property(activeAdminThread)}(${testLabel})" enabled="true"> + <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> + <collectionProp name="Arguments.arguments"> + <elementProp name="sections" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">banner</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">sections</stringProp> </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${base_path}${configurable_product_1_url_key}${url_suffix}</stringProp> - <stringProp name="HTTPSampler.method">GET</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="199922279"><title>${configurable_product_1_name}</stringProp> - <stringProp name="-1787050162"><span>In stock</span></stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form action" enabled="true"> - <stringProp name="RegexExtractor.useHeaders">false</stringProp> - <stringProp name="RegexExtractor.refname">configurable_product_form_action</stringProp> - <stringProp name="RegexExtractor.regex"><form action="([^'"]+)"\s*method="post"\s*id="product_addtocart_form"></stringProp> - <stringProp name="RegexExtractor.template">$1$</stringProp> - <stringProp name="RegexExtractor.default"></stringProp> - <stringProp name="RegexExtractor.match_number">1</stringProp> - </RegexExtractor> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert form_action extracted" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="2845929">^.+$</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">1</intProp> - <stringProp name="Assertion.scope">variable</stringProp> - <stringProp name="Scope.variable">configurable_product_form_action</stringProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> - <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Configurable Product 1 Add To Cart(CustomerChkt)" enabled="true"> + <elementProp name="update_section_id" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">true</boolProp> + <stringProp name="Argument.value">false</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">update_section_id</stringProp> + </elementProp> + <elementProp name="_" elementType="HTTPArgument"> + <boolProp name="HTTPArgument.always_encode">false</boolProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> + <stringProp name="Argument.metadata">=</stringProp> + <boolProp name="HTTPArgument.use_equals">true</boolProp> + <stringProp name="Argument.name">_</stringProp> + </elementProp> + </collectionProp> + </elementProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}customer/section/load/</stringProp> + <stringProp name="HTTPSampler.method">GET</stringProp> + <boolProp name="HTTPSampler.follow_redirects">true</boolProp> + <boolProp name="HTTPSampler.auto_redirects">false</boolProp> + <boolProp name="HTTPSampler.use_keepalive">true</boolProp> + <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> + <boolProp name="HTTPSampler.monitor">false</boolProp> + <stringProp name="HTTPSampler.embedded_url_re"/> + </HTTPSamplerProxy> + <hashTree> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="-1898134910">\"banner\":</stringProp> + </collectionProp> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">2</intProp> + </ResponseAssertion> + <hashTree/> + </hashTree> + </hashTree> + + <PostThreadGroup guiclass="PostThreadGroupGui" testclass="PostThreadGroup" testname="tearDown Thread Group" enabled="true"> + <stringProp name="ThreadGroup.on_sample_error">stoptest</stringProp> + <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true"> + <boolProp name="LoopController.continue_forever">false</boolProp> + <stringProp name="LoopController.loops">1</stringProp> + </elementProp> + <stringProp name="ThreadGroup.num_threads">1</stringProp> + <stringProp name="ThreadGroup.ramp_time">1</stringProp> + <longProp name="ThreadGroup.start_time">1395324075000</longProp> + <longProp name="ThreadGroup.end_time">1395324075000</longProp> + <boolProp name="ThreadGroup.scheduler">false</boolProp> + <stringProp name="ThreadGroup.duration"/> + <stringProp name="ThreadGroup.delay"/> + </PostThreadGroup> + <hashTree> + <IfController guiclass="IfControllerPanel" testclass="IfController" testname="If Controller: Dashboard enabled?" enabled="true"> + <stringProp name="IfController.condition">"${dashboard_enabled}" == "1"</stringProp> + <boolProp name="IfController.evaluateAll">false</boolProp> + </IfController> + <hashTree> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Trigger End Event" enabled="true"> <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> <collectionProp name="Arguments.arguments"> - <elementProp name="product" elementType="HTTPArgument"> + <elementProp name="environment" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">${configurable_product_1_id}</stringProp> + <stringProp name="Argument.value">${__property(environment)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">product</stringProp> + <stringProp name="Argument.name">environment</stringProp> </elementProp> - <elementProp name="related_product" elementType="HTTPArgument"> + <elementProp name="startTime" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value"></stringProp> + <stringProp name="Argument.value">${start_time}</stringProp> <stringProp name="Argument.metadata">=</stringProp> <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">related_product</stringProp> + <stringProp name="Argument.name">startTime</stringProp> </elementProp> - <elementProp name="qty" elementType="HTTPArgument"> + <elementProp name="endTime" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">1</stringProp> + <stringProp name="Argument.value">${__time(yyyy-MM-dd'T'HH:mm:ss.SSSZ)}</stringProp> <stringProp name="Argument.metadata">=</stringProp> <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">qty</stringProp> + <stringProp name="Argument.name">endTime</stringProp> </elementProp> - <elementProp name="super_attribute[${configurable_attribute_id}]" elementType="HTTPArgument"> + <elementProp name="stats_server" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">${configurable_option_id}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">super_attribute[${configurable_attribute_id}]</stringProp> - </elementProp> - <elementProp name="isAjax" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">true</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">isAjax</stringProp> - </elementProp> - <elementProp name="ajax" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">true</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">ajax</stringProp> - </elementProp> - </collectionProp> - </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${configurable_product_form_action}</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="-1346272328">You added ${configurable_product_1_name} to your shopping cart.</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="-815931116"><div>* We don't have as many &quot;${configurable_product_1_name}&quot; as you requested.</div></stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">6</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> - <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout start(CustomerChkt)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"/> - </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${base_path}checkout/index/</stringProp> - <stringProp name="HTTPSampler.method">GET</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="-1403911775"><title>Checkout</title></stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="-179817969"><title>Shopping Cart</title></stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">6</intProp> - </ResponseAssertion> - <hashTree/> - <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract Cart Id" enabled="true"> - <stringProp name="RegexExtractor.useHeaders">false</stringProp> - <stringProp name="RegexExtractor.refname">cart_id</stringProp> - <stringProp name="RegexExtractor.regex">"quoteData":{"entity_id":"([^'"]+)",</stringProp> - <stringProp name="RegexExtractor.template">$1$</stringProp> - <stringProp name="RegexExtractor.default"></stringProp> - <stringProp name="RegexExtractor.match_number">1</stringProp> - </RegexExtractor> - <hashTree/> - <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Extract form key" enabled="true"> - <stringProp name="RegexExtractor.useHeaders">false</stringProp> - <stringProp name="RegexExtractor.refname">form_key</stringProp> - <stringProp name="RegexExtractor.regex"><input name="form_key" type="hidden" value="([^'"]+)" /></stringProp> - <stringProp name="RegexExtractor.template">$1$</stringProp> - <stringProp name="RegexExtractor.default"></stringProp> - <stringProp name="RegexExtractor.match_number">1</stringProp> - </RegexExtractor> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert Cart Id extracted" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="2845929">^.+$</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">1</intProp> - <stringProp name="Assertion.scope">variable</stringProp> - <stringProp name="Scope.variable">cart_id</stringProp> - </ResponseAssertion> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert form_key extracted" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="2845929">^.+$</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">1</intProp> - <stringProp name="Assertion.scope">variable</stringProp> - <stringProp name="Scope.variable">form_key</stringProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> - <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Login(CustomerChkt)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"> - <elementProp name="context" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">true</boolProp> - <stringProp name="Argument.name">context</stringProp> - <stringProp name="Argument.value">checkout</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - </elementProp> - <elementProp name="login[username]" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">true</boolProp> - <stringProp name="Argument.value">${customer_email}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">login[username]</stringProp> - </elementProp> - <elementProp name="login[password]" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">true</boolProp> - <stringProp name="Argument.value">${customer_password}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">login[password]</stringProp> - </elementProp> - <elementProp name="form_key" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">true</boolProp> - <stringProp name="Argument.value">${form_key}</stringProp> + <stringProp name="Argument.value">${redis_host}</stringProp> <stringProp name="Argument.metadata">=</stringProp> <boolProp name="HTTPArgument.use_equals">true</boolProp> - <stringProp name="Argument.name">form_key</stringProp> - </elementProp> - </collectionProp> - </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> - <stringProp name="HTTPSampler.path">${base_path}customer/account/loginPost/</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree/> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> - <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout shipping information" enabled="true"> - <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> - <collectionProp name="Arguments.arguments"> - <elementProp name="" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"addressInformation":{"shipping_address":{"countryId":"US","regionId":"12","regionCode":"CA","region"
 -:"California","street":["10441 Jefferson Blvd","ste 200"],"company":"","telephone":"1-310-945-0345","fax"
 -:"","postcode":"90232","city":"Culver City","firstname":"Firstname","lastname":"Lastname","saveInAddressBook"
 -:false},"shipping_method_code":"flatrate","shipping_carrier_code":"flatrate"}}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> - </elementProp> - </collectionProp> - </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> - <stringProp name="HTTPSampler.path">${base_path}rest/default/V1/carts/mine/shipping-information</stringProp> - <stringProp name="HTTPSampler.method">POST</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> - <collectionProp name="HeaderManager.headers"> - <elementProp name="" elementType="Header"> - <stringProp name="Header.name">Referer</stringProp> - <stringProp name="Header.value">http://mage2.com/checkout/index/</stringProp> - </elementProp> - <elementProp name="Content-Type" elementType="Header"> - <stringProp name="Header.name">Content-Type</stringProp> - <stringProp name="Header.value">application/json; charset=UTF-8</stringProp> - </elementProp> - <elementProp name="X-Requested-With" elementType="Header"> - <stringProp name="Header.name">X-Requested-With</stringProp> - <stringProp name="Header.value">XMLHttpRequest</stringProp> - </elementProp> - <elementProp name="Accept" elementType="Header"> - <stringProp name="Header.name">Accept</stringProp> - <stringProp name="Header.value">application/json</stringProp> - </elementProp> - </collectionProp> - </HeaderManager> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert success" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="-1494218646">{"payment_methods":</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> - <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout payment information" enabled="true"> - <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> - <collectionProp name="Arguments.arguments"> - <elementProp name="" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"cartId":"${cart_id}","paymentMethod":{"method":"checkmo","po_number":null,"cc_owner":null,"cc_number":null
 -,"cc_type":null,"cc_exp_year":null,"cc_exp_month":null,"additional_data":null},"billingAddress":{"countryId"
 -:"US","regionId":"12","regionCode":"CA","region":"California","street":["10441 Jefferson Blvd","ste 200"
 -],"company":"","telephone":"1-310-945-0345","fax":"","postcode":"90232","city":"Culver City","firstname"
 -:"Firstname","lastname":"Lastname","saveInAddressBook":false}}</stringProp> - <stringProp name="Argument.metadata">=</stringProp> + <stringProp name="Argument.name">stats_server</stringProp> </elementProp> </collectionProp> </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> - <stringProp name="HTTPSampler.path">${base_path}rest/default/V1/carts/mine/payment-information</stringProp> + <stringProp name="HTTPSampler.domain"/> + <stringProp name="HTTPSampler.port"/> + <stringProp name="HTTPSampler.connect_timeout"/> + <stringProp name="HTTPSampler.response_timeout"/> + <stringProp name="HTTPSampler.protocol"/> + <stringProp name="HTTPSampler.contentEncoding"/> + <stringProp name="HTTPSampler.path">${base_path}DeploymentEvent.php</stringProp> <stringProp name="HTTPSampler.method">POST</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> + <stringProp name="HTTPSampler.embedded_url_re"/> </HTTPSamplerProxy> - <hashTree> - <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> - <collectionProp name="HeaderManager.headers"> - <elementProp name="" elementType="Header"> - <stringProp name="Header.name">Referer</stringProp> - <stringProp name="Header.value">http://mage2.com/checkout/index/</stringProp> - </elementProp> - <elementProp name="" elementType="Header"> - <stringProp name="Header.name">Content-Type</stringProp> - <stringProp name="Header.value">application/json; charset=UTF-8 </stringProp> - </elementProp> - <elementProp name="" elementType="Header"> - <stringProp name="Header.name">Accept</stringProp> - <stringProp name="Header.value">application/json</stringProp> - </elementProp> - <elementProp name="" elementType="Header"> - <stringProp name="Header.name">X-Requested-With</stringProp> - <stringProp name="Header.value">XMLHttpRequest</stringProp> - </elementProp> - </collectionProp> - </HeaderManager> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert success" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="-1412623327">^"\d+"$</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">1</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <GaussianRandomTimer guiclass="GaussianRandomTimerGui" testclass="GaussianRandomTimer" testname="Random Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${think_time_delay_offset}</stringProp> - <stringProp name="RandomTimer.range">${think_time_deviation}</stringProp> - </GaussianRandomTimer> <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout success(CustomerChkt)" enabled="true"> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true"> - <collectionProp name="Arguments.arguments"/> - </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding"></stringProp> - <stringProp name="HTTPSampler.path">${base_path}checkout/onepage/success/</stringProp> - <stringProp name="HTTPSampler.method">GET</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert success" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="494863233">Thank you for your purchase!</stringProp> - <stringProp name="-1590086334">Your order number is</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - </hashTree> - <PostThreadGroup guiclass="PostThreadGroupGui" testclass="PostThreadGroup" testname="tearDown Thread Group" enabled="true"> - <stringProp name="ThreadGroup.on_sample_error">stoptest</stringProp> - <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true"> - <boolProp name="LoopController.continue_forever">false</boolProp> - <stringProp name="LoopController.loops">1</stringProp> - </elementProp> - <stringProp name="ThreadGroup.num_threads">1</stringProp> - <stringProp name="ThreadGroup.ramp_time">1</stringProp> - <longProp name="ThreadGroup.start_time">1395324075000</longProp> - <longProp name="ThreadGroup.end_time">1395324075000</longProp> - <boolProp name="ThreadGroup.scheduler">false</boolProp> - <stringProp name="ThreadGroup.duration"></stringProp> - <stringProp name="ThreadGroup.delay"></stringProp> - </PostThreadGroup> - <hashTree> - <CookieManager guiclass="CookiePanel" testclass="CookieManager" testname="HTTP Cookie Manager" enabled="true"> - <collectionProp name="CookieManager.cookies"> - <elementProp name="product_list_limit" elementType="Cookie" testname="product_list_limit"> - <stringProp name="Cookie.value">30</stringProp> - <stringProp name="Cookie.domain">${host}</stringProp> - <stringProp name="Cookie.path">/</stringProp> - <boolProp name="Cookie.secure">false</boolProp> - <longProp name="Cookie.expires">0</longProp> - <boolProp name="Cookie.path_specified">true</boolProp> - <boolProp name="Cookie.domain_specified">true</boolProp> - </elementProp> + <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert curl call was successful" enabled="true"> + <collectionProp name="Asserion.test_strings"> + <stringProp name="185669135">Errors:</stringProp> </collectionProp> - <boolProp name="CookieManager.clearEachIteration">true</boolProp> - </CookieManager> - <hashTree/> - <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="BeanShell Sampler: Clear properties" enabled="true"> - <stringProp name="BeanShellSampler.query">props.remove("category_url_key"); -props.remove("category_name"); -props.remove("simple_products_list"); -props.remove("configurable_products_list"); -props.remove("users"); -props.remove("customer_emails_list");</stringProp> - <stringProp name="BeanShellSampler.filename"></stringProp> - <stringProp name="BeanShellSampler.parameters"></stringProp> - <boolProp name="BeanShellSampler.resetInterpreter">false</boolProp> - </BeanShellSampler> + <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> + <boolProp name="Assertion.assume_success">false</boolProp> + <intProp name="Assertion.test_type">6</intProp> + </ResponseAssertion> <hashTree/> </hashTree> - <ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="View Results Tree" enabled="true"> - <boolProp name="ResultCollector.error_logging">false</boolProp> - <objProp> - <name>saveConfig</name> - <value class="SampleSaveConfiguration"> - <time>true</time> - <latency>true</latency> - <timestamp>true</timestamp> - <success>true</success> - <label>true</label> - <code>true</code> - <message>true</message> - <threadName>true</threadName> - <dataType>true</dataType> - <encoding>false</encoding> - <assertions>true</assertions> - <subresults>true</subresults> - <responseData>false</responseData> - <samplerData>false</samplerData> - <xml>false</xml> - <fieldNames>false</fieldNames> - <responseHeaders>false</responseHeaders> - <requestHeaders>false</requestHeaders> - <responseDataOnError>false</responseDataOnError> - <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage> - <assertionsResultsToSave>0</assertionsResultsToSave> - <bytes>true</bytes> - <hostname>true</hostname> - <threadCounts>true</threadCounts> - <sampleCount>true</sampleCount> - </value> - </objProp> - <stringProp name="filename">${report_save_path}/view-results-tree.log</stringProp> - </ResultCollector> - <hashTree/> - <ResultCollector guiclass="TableVisualizer" testclass="ResultCollector" testname="Detailed URLs report" enabled="true"> - <boolProp name="ResultCollector.error_logging">false</boolProp> - <objProp> - <name>saveConfig</name> - <value class="SampleSaveConfiguration"> - <time>true</time> - <latency>false</latency> - <timestamp>false</timestamp> - <success>false</success> - <label>true</label> - <code>false</code> - <message>false</message> - <threadName>false</threadName> - <dataType>false</dataType> - <encoding>false</encoding> - <assertions>false</assertions> - <subresults>false</subresults> - <responseData>false</responseData> - <samplerData>false</samplerData> - <xml>false</xml> - <fieldNames>true</fieldNames> - <responseHeaders>false</responseHeaders> - <requestHeaders>false</requestHeaders> - <responseDataOnError>false</responseDataOnError> - <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage> - <assertionsResultsToSave>0</assertionsResultsToSave> - <url>true</url> - <hostname>true</hostname> - <threadCounts>true</threadCounts> - <sampleCount>true</sampleCount> - </value> - </objProp> - <stringProp name="filename">${report_save_path}/detailed-urls-report.log</stringProp> - </ResultCollector> - <hashTree/> - <ResultCollector guiclass="SummaryReport" testclass="ResultCollector" testname="Summary Report" enabled="true"> - <boolProp name="ResultCollector.error_logging">false</boolProp> - <objProp> - <name>saveConfig</name> - <value class="SampleSaveConfiguration"> - <time>true</time> - <latency>true</latency> - <timestamp>true</timestamp> - <success>true</success> - <label>true</label> - <code>true</code> - <message>true</message> - <threadName>true</threadName> - <dataType>true</dataType> - <encoding>false</encoding> - <assertions>true</assertions> - <subresults>true</subresults> - <responseData>false</responseData> - <samplerData>false</samplerData> - <xml>false</xml> - <fieldNames>false</fieldNames> - <responseHeaders>false</responseHeaders> - <requestHeaders>false</requestHeaders> - <responseDataOnError>false</responseDataOnError> - <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage> - <assertionsResultsToSave>0</assertionsResultsToSave> - <bytes>true</bytes> - <hostname>true</hostname> - <threadCounts>true</threadCounts> - <sampleCount>true</sampleCount> - </value> - </objProp> - <stringProp name="filename">${report_save_path}/summary-report.log</stringProp> - </ResultCollector> + <CookieManager guiclass="CookiePanel" testclass="CookieManager" testname="HTTP Cookie Manager" enabled="true"> + <collectionProp name="CookieManager.cookies"> + <elementProp name="product_list_limit" elementType="Cookie" testname="product_list_limit"> + <stringProp name="Cookie.value">30</stringProp> + <stringProp name="Cookie.domain">${host}</stringProp> + <stringProp name="Cookie.path">/</stringProp> + <boolProp name="Cookie.secure">false</boolProp> + <longProp name="Cookie.expires">0</longProp> + <boolProp name="Cookie.path_specified">true</boolProp> + <boolProp name="Cookie.domain_specified">true</boolProp> + </elementProp> + </collectionProp> + <boolProp name="CookieManager.clearEachIteration">true</boolProp> + </CookieManager> + <hashTree/> + <BeanShellSampler guiclass="BeanShellSamplerGui" testclass="BeanShellSampler" testname="SetUp - BeanShell Sampler: Clear properties" enabled="true"> + <stringProp name="BeanShellSampler.query">props.remove("category_url_key"); +props.remove("category_name"); +props.remove("simple_products_list"); +props.remove("configurable_products_list"); +props.remove("users"); +props.remove("customer_emails_list");</stringProp> + <stringProp name="BeanShellSampler.filename"/> + <stringProp name="BeanShellSampler.parameters"/> + <boolProp name="BeanShellSampler.resetInterpreter">false</boolProp> + </BeanShellSampler> <hashTree/> </hashTree> + + <ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="View Results Tree" enabled="true"> + <boolProp name="ResultCollector.error_logging">false</boolProp> + <objProp> + <name>saveConfig</name> + <value class="SampleSaveConfiguration"> + <time>true</time> + <latency>true</latency> + <timestamp>true</timestamp> + <success>true</success> + <label>true</label> + <code>true</code> + <message>true</message> + <threadName>true</threadName> + <dataType>true</dataType> + <encoding>false</encoding> + <assertions>true</assertions> + <subresults>true</subresults> + <responseData>false</responseData> + <samplerData>false</samplerData> + <xml>false</xml> + <fieldNames>false</fieldNames> + <responseHeaders>false</responseHeaders> + <requestHeaders>false</requestHeaders> + <responseDataOnError>false</responseDataOnError> + <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage> + <assertionsResultsToSave>0</assertionsResultsToSave> + <bytes>true</bytes> + <threadCounts>true</threadCounts> + </value> + </objProp> + <objProp> + <name/> + <value class="SampleSaveConfiguration"> + <time>true</time> + <latency>true</latency> + <timestamp>true</timestamp> + <success>true</success> + <label>true</label> + <code>true</code> + <message>true</message> + <threadName>true</threadName> + <dataType>true</dataType> + <encoding>false</encoding> + <assertions>true</assertions> + <subresults>true</subresults> + <responseData>false</responseData> + <samplerData>false</samplerData> + <xml>true</xml> + <fieldNames>false</fieldNames> + <responseHeaders>false</responseHeaders> + <requestHeaders>true</requestHeaders> + <responseDataOnError>false</responseDataOnError> + <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage> + <assertionsResultsToSave>0</assertionsResultsToSave> + <bytes>true</bytes> + <hostname>true</hostname> + <threadCounts>true</threadCounts> + <sampleCount>true</sampleCount> + </value> + </objProp> + <stringProp name="filename"/> + </ResultCollector> + <hashTree/> + + <ResultCollector guiclass="TableVisualizer" testclass="ResultCollector" testname="Detailed URLs report" enabled="true"> + <boolProp name="ResultCollector.error_logging">false</boolProp> + <objProp> + <name>saveConfig</name> + <value class="SampleSaveConfiguration"> + <time>true</time> + <latency>false</latency> + <timestamp>false</timestamp> + <success>false</success> + <label>true</label> + <code>false</code> + <message>false</message> + <threadName>false</threadName> + <dataType>false</dataType> + <encoding>false</encoding> + <assertions>false</assertions> + <subresults>false</subresults> + <responseData>false</responseData> + <samplerData>false</samplerData> + <xml>false</xml> + <fieldNames>true</fieldNames> + <responseHeaders>false</responseHeaders> + <requestHeaders>false</requestHeaders> + <responseDataOnError>false</responseDataOnError> + <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage> + <assertionsResultsToSave>0</assertionsResultsToSave> + <url>true</url> + <hostname>true</hostname> + <threadCounts>true</threadCounts> + <sampleCount>true</sampleCount> + </value> + </objProp> + <stringProp name="filename">${report_save_path}/detailed-urls-report.log</stringProp> + </ResultCollector> + <hashTree/> + + <ResultCollector guiclass="SummaryReport" testclass="ResultCollector" testname="Summary Report" enabled="true"> + <boolProp name="ResultCollector.error_logging">false</boolProp> + <objProp> + <name>saveConfig</name> + <value class="SampleSaveConfiguration"> + <time>true</time> + <latency>true</latency> + <timestamp>true</timestamp> + <success>true</success> + <label>true</label> + <code>true</code> + <message>true</message> + <threadName>true</threadName> + <dataType>true</dataType> + <encoding>false</encoding> + <assertions>true</assertions> + <subresults>true</subresults> + <responseData>false</responseData> + <samplerData>false</samplerData> + <xml>false</xml> + <fieldNames>false</fieldNames> + <responseHeaders>false</responseHeaders> + <requestHeaders>false</requestHeaders> + <responseDataOnError>false</responseDataOnError> + <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage> + <assertionsResultsToSave>0</assertionsResultsToSave> + <bytes>true</bytes> + <hostname>true</hostname> + <threadCounts>true</threadCounts> + <sampleCount>true</sampleCount> + </value> + </objProp> + <stringProp name="filename">${report_save_path}/summary-report.log</stringProp> + </ResultCollector> + <hashTree/> + </hashTree> + <WorkBench guiclass="WorkBenchGui" testclass="WorkBench" testname="WorkBench" enabled="true"> + <boolProp name="WorkBench.save">true</boolProp> + </WorkBench> </hashTree> </jmeterTestPlan> diff --git a/setup/src/Magento/Setup/Controller/Connect.php b/setup/src/Magento/Setup/Controller/Connect.php index b5a400262717c5c4ae6a1c6da7fa2f0b70e4c067..7ff039e3f4bcc85d05427b13f0c056fa08e7f08b 100644 --- a/setup/src/Magento/Setup/Controller/Connect.php +++ b/setup/src/Magento/Setup/Controller/Connect.php @@ -42,7 +42,10 @@ class Connect extends AbstractActionController */ public function saveAuthJsonAction() { - $params = Json::decode($this->getRequest()->getContent(), Json::TYPE_ARRAY); + $params = []; + if ($this->getRequest()->getContent()) { + $params = Json::decode($this->getRequest()->getContent(), Json::TYPE_ARRAY); + } try { $userName = isset($params['username']) ? $params['username'] : ''; $password = isset($params['password']) ? $params['password'] : ''; diff --git a/setup/src/Magento/Setup/Module/I18n/Locale.php b/setup/src/Magento/Setup/Module/I18n/Locale.php index e3bb79e9adb2fd6007dfef92bb711394aa85244e..053ee398a2f71e061d7efee256fe6e686b54e473 100644 --- a/setup/src/Magento/Setup/Module/I18n/Locale.php +++ b/setup/src/Magento/Setup/Module/I18n/Locale.php @@ -30,9 +30,7 @@ class Locale */ public function __construct($locale) { - if ($locale == self::DEFAULT_SYSTEM_LOCALE) { - throw new \InvalidArgumentException('Target locale is system default locale.'); - } elseif (!preg_match('/[a-z]{2}_[A-Z]{2}/', $locale)) { + if (!preg_match('/[a-z]{2}_[A-Z]{2}/', $locale)) { throw new \InvalidArgumentException('Target locale must match the following format: "aa_AA".'); } $this->_locale = $locale; diff --git a/setup/src/Magento/Setup/Module/I18n/Parser/Adapter/Php/Tokenizer/PhraseCollector.php b/setup/src/Magento/Setup/Module/I18n/Parser/Adapter/Php/Tokenizer/PhraseCollector.php index ee7ecd15e0c5fdc8ed9f24c2eb4a3092dffe0371..96f7c84fd7e7a611579f13e153d37f0cd1b87af9 100644 --- a/setup/src/Magento/Setup/Module/I18n/Parser/Adapter/Php/Tokenizer/PhraseCollector.php +++ b/setup/src/Magento/Setup/Module/I18n/Parser/Adapter/Php/Tokenizer/PhraseCollector.php @@ -139,7 +139,7 @@ class PhraseCollector if ($phraseTokens) { /** @var \Magento\Setup\Module\I18n\Parser\Adapter\Php\Tokenizer\Token $phraseToken */ foreach ($phraseTokens as $phraseToken) { - if ($phraseToken->isConstantEncapsedString()) { + if ($phraseToken->isConstantEncapsedString() || $phraseToken->isConcatenateOperator()) { $phrase[] = $phraseToken->getValue(); } } diff --git a/setup/src/Magento/Setup/Module/I18n/Parser/Adapter/Php/Tokenizer/Token.php b/setup/src/Magento/Setup/Module/I18n/Parser/Adapter/Php/Tokenizer/Token.php index a36b8b1e885307150ba4ef9d95ccd8381bfd2137..0477da1bcd3ce5f490c19c7e058e35d89b92f0f2 100644 --- a/setup/src/Magento/Setup/Module/I18n/Parser/Adapter/Php/Tokenizer/Token.php +++ b/setup/src/Magento/Setup/Module/I18n/Parser/Adapter/Php/Tokenizer/Token.php @@ -166,6 +166,14 @@ class Token return $this->getValue() == ';'; } + /** + * @return bool + */ + public function isConcatenateOperator() + { + return $this->getValue() == '.'; + } + /** * Is namespace separator * diff --git a/setup/src/Magento/Setup/Module/I18n/Parser/Contextual.php b/setup/src/Magento/Setup/Module/I18n/Parser/Contextual.php index d759eb11b2be3620a1e4855b9a8f0c4e9082071f..cbeca7d79d6d8535ee674b36212f85af5833a0e2 100644 --- a/setup/src/Magento/Setup/Module/I18n/Parser/Contextual.php +++ b/setup/src/Magento/Setup/Module/I18n/Parser/Contextual.php @@ -63,7 +63,7 @@ class Contextual extends AbstractParser */ protected function _addPhrase($phraseData, $contextType, $contextValue) { - $phraseKey = $contextType . stripslashes($phraseData['phrase']); + $phraseKey = $contextType . $contextValue. stripslashes($phraseData['phrase']); if (isset($this->_phrases[$phraseKey])) { /** @var \Magento\Setup\Module\I18n\Dictionary\Phrase $phrase */ diff --git a/setup/src/Magento/Setup/Test/Unit/Module/I18n/LocaleTest.php b/setup/src/Magento/Setup/Test/Unit/Module/I18n/LocaleTest.php index 09914f7863146d54f3256457a71523da26c7889e..9eec9b6901456d87eacd5ed8014f9cdbabe78fee 100644 --- a/setup/src/Magento/Setup/Test/Unit/Module/I18n/LocaleTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Module/I18n/LocaleTest.php @@ -9,15 +9,6 @@ use \Magento\Setup\Module\I18n\Locale; class LocaleTest extends \PHPUnit_Framework_TestCase { - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Target locale is system default locale. - */ - public function testLocaleIsSystemDefaultLocaleException() - { - new Locale('en_US'); - } - /** * @expectedException \InvalidArgumentException * @expectedExceptionMessage Target locale must match the following format: "aa_AA". diff --git a/setup/src/Magento/Setup/Test/Unit/Module/I18n/Parser/Adapter/Php/Tokenizer/PhraseCollectorTest.php b/setup/src/Magento/Setup/Test/Unit/Module/I18n/Parser/Adapter/Php/Tokenizer/PhraseCollectorTest.php index 954bcc013ade66bfdd3c10c10597fe205f6f5e58..b4f7d60a1ca113b43c289ed4cc57e0bfc471a2b7 100644 --- a/setup/src/Magento/Setup/Test/Unit/Module/I18n/Parser/Adapter/Php/Tokenizer/PhraseCollectorTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Module/I18n/Parser/Adapter/Php/Tokenizer/PhraseCollectorTest.php @@ -204,4 +204,23 @@ class PhraseCollectorTest extends \PHPUnit_Framework_TestCase ->willReturn($line); return $token; } + + public function testCollectPhrases() + { + $firstPart = "'first part'"; + $firstPartToken = new Token(\T_CONSTANT_ENCAPSED_STRING, $firstPart); + $concatenationToken = new Token('.', '.'); + $secondPart = "' second part'"; + $secondPartToken = new Token(\T_CONSTANT_ENCAPSED_STRING, $secondPart); + $phraseTokens = [$firstPartToken, $concatenationToken, $secondPartToken]; + $phraseString = "'first part' . ' second part'"; + + $reflectionMethod = new \ReflectionMethod( + '\Magento\Setup\Module\I18n\Parser\Adapter\Php\Tokenizer\PhraseCollector', + '_collectPhrase' + ); + + $reflectionMethod->setAccessible(true); + $this->assertSame($phraseString, $reflectionMethod->invoke($this->phraseCollector, $phraseTokens)); + } } diff --git a/setup/src/Magento/Setup/Test/Unit/Module/I18n/Parser/Adapter/Php/Tokenizer/TokenTest.php b/setup/src/Magento/Setup/Test/Unit/Module/I18n/Parser/Adapter/Php/Tokenizer/TokenTest.php index 26bcea7516dd2495526e0b75202c3082591a77c6..c29edab1c442d5d96398424fd00be82251c223af 100644 --- a/setup/src/Magento/Setup/Test/Unit/Module/I18n/Parser/Adapter/Php/Tokenizer/TokenTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Module/I18n/Parser/Adapter/Php/Tokenizer/TokenTest.php @@ -118,4 +118,16 @@ class TokenTest extends \PHPUnit_Framework_TestCase ] ); } + + public function testIsConcatenateOperatorTrue() + { + $token = new \Magento\Setup\Module\I18n\Parser\Adapter\Php\Tokenizer\Token('.', '.'); + $this->assertTrue($token->isConcatenateOperator()); + } + + public function testIsConcatenateOperatorFalse() + { + $token = new \Magento\Setup\Module\I18n\Parser\Adapter\Php\Tokenizer\Token(',', ','); + $this->assertFalse($token->isConcatenateOperator()); + } }