From 92f24eccffdab3beafc0957a14f2603a5a0d0669 Mon Sep 17 00:00:00 2001 From: Elze Kool Date: Tue, 26 Sep 2017 14:47:19 +0200 Subject: [PATCH 001/210] Handle transparncy correctly for watermark The watermark functionality uses imagecopymerge for copying the watermark into the image, this function loses the alpha information. Therefor use imagecopy for 100% opacity and use imagefilter in other cases. Resolves: #10661 --- .../Magento/Framework/Image/Adapter/Gd2.php | 80 +++++++++++++++++-- 1 file changed, 72 insertions(+), 8 deletions(-) diff --git a/lib/internal/Magento/Framework/Image/Adapter/Gd2.php b/lib/internal/Magento/Framework/Image/Adapter/Gd2.php index 444ab7113d429..de48e234a58d2 100644 --- a/lib/internal/Magento/Framework/Image/Adapter/Gd2.php +++ b/lib/internal/Magento/Framework/Image/Adapter/Gd2.php @@ -404,7 +404,7 @@ public function rotate($angle) */ public function watermark($imagePath, $positionX = 0, $positionY = 0, $opacity = 30, $tile = false) { - list($watermarkSrcWidth, $watermarkSrcHeight, $watermarkFileType, ) = $this->_getImageOptions($imagePath); + list($watermarkSrcWidth, $watermarkSrcHeight, $watermarkFileType,) = $this->_getImageOptions($imagePath); $this->_getFileAttributes(); $watermark = call_user_func( $this->_getCallback('create', $watermarkFileType, 'Unsupported watermark image format.'), @@ -465,7 +465,7 @@ public function watermark($imagePath, $positionX = 0, $positionY = 0, $opacity = } elseif ($this->getWatermarkPosition() == self::POSITION_CENTER) { $positionX = $this->_imageSrcWidth / 2 - imagesx($watermark) / 2; $positionY = $this->_imageSrcHeight / 2 - imagesy($watermark) / 2; - imagecopymerge( + $this->imagecopymergeWithAlphaFix( $this->_imageHandler, $watermark, $positionX, @@ -478,7 +478,7 @@ public function watermark($imagePath, $positionX = 0, $positionY = 0, $opacity = ); } elseif ($this->getWatermarkPosition() == self::POSITION_TOP_RIGHT) { $positionX = $this->_imageSrcWidth - imagesx($watermark); - imagecopymerge( + $this->imagecopymergeWithAlphaFix( $this->_imageHandler, $watermark, $positionX, @@ -490,7 +490,7 @@ public function watermark($imagePath, $positionX = 0, $positionY = 0, $opacity = $this->getWatermarkImageOpacity() ); } elseif ($this->getWatermarkPosition() == self::POSITION_TOP_LEFT) { - imagecopymerge( + $this->imagecopymergeWithAlphaFix( $this->_imageHandler, $watermark, $positionX, @@ -504,7 +504,7 @@ public function watermark($imagePath, $positionX = 0, $positionY = 0, $opacity = } elseif ($this->getWatermarkPosition() == self::POSITION_BOTTOM_RIGHT) { $positionX = $this->_imageSrcWidth - imagesx($watermark); $positionY = $this->_imageSrcHeight - imagesy($watermark); - imagecopymerge( + $this->imagecopymergeWithAlphaFix( $this->_imageHandler, $watermark, $positionX, @@ -517,7 +517,7 @@ public function watermark($imagePath, $positionX = 0, $positionY = 0, $opacity = ); } elseif ($this->getWatermarkPosition() == self::POSITION_BOTTOM_LEFT) { $positionY = $this->_imageSrcHeight - imagesy($watermark); - imagecopymerge( + $this->imagecopymergeWithAlphaFix( $this->_imageHandler, $watermark, $positionX, @@ -531,7 +531,7 @@ public function watermark($imagePath, $positionX = 0, $positionY = 0, $opacity = } if ($tile === false && $merged === false) { - imagecopymerge( + $this->imagecopymergeWithAlphaFix( $this->_imageHandler, $watermark, $positionX, @@ -547,7 +547,7 @@ public function watermark($imagePath, $positionX = 0, $positionY = 0, $opacity = $offsetY = $positionY; while ($offsetY <= $this->_imageSrcHeight + imagesy($watermark)) { while ($offsetX <= $this->_imageSrcWidth + imagesx($watermark)) { - imagecopymerge( + $this->imagecopymergeWithAlphaFix( $this->_imageHandler, $watermark, $offsetX, @@ -778,4 +778,68 @@ protected function _createEmptyImage($width, $height) $this->imageDestroy(); $this->_imageHandler = $image; } + + /** + * Fix an issue with the usage of imagecopymerge where the alpha channel is lost + * + * @param resource $dst_im + * @param resource $src_im + * @param int $dst_x + * @param int $dst_y + * @param int $src_x + * @param int $src_y + * @param int $src_w + * @param int $src_h + * @param int $pct + * + * @return bool + */ + private function imagecopymergeWithAlphaFix( + $dst_im, + $src_im, + $dst_x, + $dst_y, + $src_x, + $src_y, + $src_w, + $src_h, + $pct + ) { + if ($pct >= 100) { + return imagecopy($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h); + } + + if ($pct < 0) { + return false; + } + + $sizeX = imagesx($src_im); + $sizeY = imagesy($src_im); + if (false === $sizeX || false === $sizeY) { + return false; + } + + $tmpImg = imagecreatetruecolor($src_w, $src_h); + if (false === $tmpImg) { + return false; + } + + if (false === imagealphablending($tmpImg, false)) { + return false; + } + + if (false === imagecopy($tmpImg, $src_im, 0, 0, 0, 0, $sizeX, $sizeY)) { + return false; + } + + $transparancy = 127 - (($pct*127)/100); + if (false === imagefilter($tmpImg, IMG_FILTER_COLORIZE, 0, 0, 0, $transparancy)) { + return false; + } + + $result = imagecopy($dst_im, $tmpImg, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h); + imagedestroy($tmpImg); + + return $result; + } } From 32558577099d2cdc3dd56cf5d84f814ab3184987 Mon Sep 17 00:00:00 2001 From: Denis Ristic Date: Wed, 11 Oct 2017 13:07:34 +0200 Subject: [PATCH 002/210] Database backup doesn't include triggers #9036 ADDED getTableTriggersSql() and now it returns valid SQL with drop & create queries for triggers --- app/code/Magento/Backup/Model/Db.php | 1 + .../Magento/Backup/Model/ResourceModel/Db.php | 25 +++++++++++++ .../Backup/Model/ResourceModel/Helper.php | 37 +++++++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/app/code/Magento/Backup/Model/Db.php b/app/code/Magento/Backup/Model/Db.php index 776141249f92b..98b04149cc7ea 100644 --- a/app/code/Magento/Backup/Model/Db.php +++ b/app/code/Magento/Backup/Model/Db.php @@ -173,6 +173,7 @@ public function createBackup(\Magento\Framework\Backup\Db\BackupInterface $backu } } $backup->write($this->getResource()->getTableForeignKeysSql()); + $backup->write($this->getResource()->getTableTriggersSql()); $backup->write($this->getResource()->getFooter()); $this->getResource()->commitTransaction(); diff --git a/app/code/Magento/Backup/Model/ResourceModel/Db.php b/app/code/Magento/Backup/Model/ResourceModel/Db.php index 3fbaf44ebb063..5ba3230e8c463 100644 --- a/app/code/Magento/Backup/Model/ResourceModel/Db.php +++ b/app/code/Magento/Backup/Model/ResourceModel/Db.php @@ -114,6 +114,31 @@ public function getTableForeignKeysSql($tableName = null) return $fkScript; } + /** + * Return triggers fro table(s) + * + * @param string|null $tableName + * @param bool $addDropIfExists + * @return string + */ + public function getTableTriggersSql($tableName = null, $addDropIfExists = true) + { + $triggerScript = ''; + if (!$tableName) { + $tables = $this->getTables(); + foreach ($tables as $table) { + $tableTriggerScript = $this->_resourceHelper->getTableTriggersSql($table, $addDropIfExists); + if (!empty($tableTriggerScript)) { + $triggerScript .= "\n" . $tableTriggerScript; + } + } + } else { + $triggerScript = $this->getTableTriggersSql($tableName, $addDropIfExists); + } + return $triggerScript; + + } + /** * Retrieve table status * diff --git a/app/code/Magento/Backup/Model/ResourceModel/Helper.php b/app/code/Magento/Backup/Model/ResourceModel/Helper.php index b5418865339c3..5f1db6ae7ca60 100644 --- a/app/code/Magento/Backup/Model/ResourceModel/Helper.php +++ b/app/code/Magento/Backup/Model/ResourceModel/Helper.php @@ -337,4 +337,41 @@ public function restoreTransactionIsolationLevel() { $this->getConnection()->query('SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ'); } + + /** + * Get create script for triggers + * + * @param string $tableName + * @param boolean $addDropIfExists + * @param boolean $stripDefiner + * @return string + */ + public function getTableTriggersSql($tableName, $addDropIfExists = false, $stripDefiner = true) + { + $script = "--\n-- Triggers structure for table `{$tableName}`\n--\n"; + $triggers = $this->getConnection()->query('SHOW TRIGGERS LIKE \''. $tableName . '\'')->fetchAll(); + + if (!$triggers) { + return ''; + } + foreach ($triggers as $trigger) { + if ($addDropIfExists) { + $script .= 'DROP TRIGGER IF EXISTS ' . $trigger['Trigger'] . ";\n"; + } + $script .= "delimiter ;;\n"; + + $triggerData = $this->getConnection()->query('SHOW CREATE TRIGGER '. $trigger['Trigger'])->fetch(); + if ($stripDefiner) { + $cleanedScript = preg_replace('/DEFINER=[^\s]*/', '', $triggerData['SQL Original Statement']); + $script .= $cleanedScript . "\n"; + } else { + $script .= $triggerData['SQL Original Statement'] . "\n"; + } + $script .= ";;\n"; + $script .= "delimiter ;\n"; + } + + return $script; + + } } From f1bcf38e7ce0202bde7be843ba1c46d20687ab43 Mon Sep 17 00:00:00 2001 From: Denis Ristic Date: Thu, 12 Oct 2017 10:13:13 +0200 Subject: [PATCH 003/210] FIXED PhpCS violations --- app/code/Magento/Backup/Model/ResourceModel/Db.php | 1 - app/code/Magento/Backup/Model/ResourceModel/Helper.php | 1 - 2 files changed, 2 deletions(-) diff --git a/app/code/Magento/Backup/Model/ResourceModel/Db.php b/app/code/Magento/Backup/Model/ResourceModel/Db.php index 5ba3230e8c463..f50a3c5b091ad 100644 --- a/app/code/Magento/Backup/Model/ResourceModel/Db.php +++ b/app/code/Magento/Backup/Model/ResourceModel/Db.php @@ -136,7 +136,6 @@ public function getTableTriggersSql($tableName = null, $addDropIfExists = true) $triggerScript = $this->getTableTriggersSql($tableName, $addDropIfExists); } return $triggerScript; - } /** diff --git a/app/code/Magento/Backup/Model/ResourceModel/Helper.php b/app/code/Magento/Backup/Model/ResourceModel/Helper.php index 5f1db6ae7ca60..6d7084a87546c 100644 --- a/app/code/Magento/Backup/Model/ResourceModel/Helper.php +++ b/app/code/Magento/Backup/Model/ResourceModel/Helper.php @@ -372,6 +372,5 @@ public function getTableTriggersSql($tableName, $addDropIfExists = false, $strip } return $script; - } } From f2446b637679ed7d39dd73b54c13f2bd0d3e45a6 Mon Sep 17 00:00:00 2001 From: Elze Kool Date: Sun, 19 Nov 2017 10:52:08 +0100 Subject: [PATCH 004/210] Fix handling of watermark with alpha for Imagick When adding a watermark that already has an alpha channel this was reset because the overal opacity was set for the image. Instead we should multiply the original alpha with the requested opacity --- .../Framework/Image/Adapter/ImageMagick.php | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/lib/internal/Magento/Framework/Image/Adapter/ImageMagick.php b/lib/internal/Magento/Framework/Image/Adapter/ImageMagick.php index 50b9a5a013273..29f3c85dc1205 100644 --- a/lib/internal/Magento/Framework/Image/Adapter/ImageMagick.php +++ b/lib/internal/Magento/Framework/Image/Adapter/ImageMagick.php @@ -269,15 +269,17 @@ public function watermark($imagePath, $positionX = 0, $positionY = 0, $opacity = ); } - if (method_exists($watermark, 'setImageOpacity')) { - // available from imagick 6.3.1 - $watermark->setImageOpacity($opacity); - } else { - // go to each pixel and make it transparent - $watermark->paintTransparentImage($watermark->getImagePixelColor(0, 0), 1, 65530); - $watermark->evaluateImage(\Imagick::EVALUATE_SUBTRACT, 1 - $opacity, \Imagick::CHANNEL_ALPHA); + if (method_exists($watermark, 'getImageAlphaChannel')) { + // available from imagick 6.4.0 + if ($watermark->getImageAlphaChannel() == 0) { + $watermark->setImageAlphaChannel(\Imagick::ALPHACHANNEL_OPAQUE); + } } + $compositeChannels = \Imagick::CHANNEL_ALL; + $watermark->evaluateImage(\Imagick::EVALUATE_MULTIPLY, $opacity, \Imagick::CHANNEL_OPACITY); + $compositeChannels &= ~(\Imagick::CHANNEL_OPACITY); + switch ($this->getWatermarkPosition()) { case self::POSITION_STRETCH: $watermark->sampleImage($this->_imageSrcWidth, $this->_imageSrcHeight); @@ -309,14 +311,14 @@ public function watermark($imagePath, $positionX = 0, $positionY = 0, $opacity = $offsetY = $positionY; while ($offsetY <= $this->_imageSrcHeight + $watermark->getImageHeight()) { while ($offsetX <= $this->_imageSrcWidth + $watermark->getImageWidth()) { - $this->_imageHandler->compositeImage($watermark, \Imagick::COMPOSITE_OVER, $offsetX, $offsetY); + $this->_imageHandler->compositeImage($watermark, \Imagick::COMPOSITE_OVER, $offsetX, $offsetY, $compositeChannels); $offsetX += $watermark->getImageWidth(); } $offsetX = $positionX; $offsetY += $watermark->getImageHeight(); } } else { - $this->_imageHandler->compositeImage($watermark, \Imagick::COMPOSITE_OVER, $positionX, $positionY); + $this->_imageHandler->compositeImage($watermark, \Imagick::COMPOSITE_OVER, $positionX, $positionY, $compositeChannels); } } catch (\ImagickException $e) { throw new \Exception('Unable to create watermark.', $e->getCode(), $e); From 519f3e1c608e0ee0105f8cec0244b822c3d17cee Mon Sep 17 00:00:00 2001 From: Elze Kool Date: Sun, 19 Nov 2017 10:54:57 +0100 Subject: [PATCH 005/210] Handle non true color images with GD2 --- .../Magento/Framework/Image/Adapter/Gd2.php | 87 ++++++++++--------- 1 file changed, 47 insertions(+), 40 deletions(-) diff --git a/lib/internal/Magento/Framework/Image/Adapter/Gd2.php b/lib/internal/Magento/Framework/Image/Adapter/Gd2.php index de48e234a58d2..6817c01b19cbf 100644 --- a/lib/internal/Magento/Framework/Image/Adapter/Gd2.php +++ b/lib/internal/Magento/Framework/Image/Adapter/Gd2.php @@ -465,7 +465,7 @@ public function watermark($imagePath, $positionX = 0, $positionY = 0, $opacity = } elseif ($this->getWatermarkPosition() == self::POSITION_CENTER) { $positionX = $this->_imageSrcWidth / 2 - imagesx($watermark) / 2; $positionY = $this->_imageSrcHeight / 2 - imagesy($watermark) / 2; - $this->imagecopymergeWithAlphaFix( + $this->copyImageWithAlphaPercentage( $this->_imageHandler, $watermark, $positionX, @@ -478,7 +478,7 @@ public function watermark($imagePath, $positionX = 0, $positionY = 0, $opacity = ); } elseif ($this->getWatermarkPosition() == self::POSITION_TOP_RIGHT) { $positionX = $this->_imageSrcWidth - imagesx($watermark); - $this->imagecopymergeWithAlphaFix( + $this->copyImageWithAlphaPercentage( $this->_imageHandler, $watermark, $positionX, @@ -490,7 +490,7 @@ public function watermark($imagePath, $positionX = 0, $positionY = 0, $opacity = $this->getWatermarkImageOpacity() ); } elseif ($this->getWatermarkPosition() == self::POSITION_TOP_LEFT) { - $this->imagecopymergeWithAlphaFix( + $this->copyImageWithAlphaPercentage( $this->_imageHandler, $watermark, $positionX, @@ -504,7 +504,7 @@ public function watermark($imagePath, $positionX = 0, $positionY = 0, $opacity = } elseif ($this->getWatermarkPosition() == self::POSITION_BOTTOM_RIGHT) { $positionX = $this->_imageSrcWidth - imagesx($watermark); $positionY = $this->_imageSrcHeight - imagesy($watermark); - $this->imagecopymergeWithAlphaFix( + $this->copyImageWithAlphaPercentage( $this->_imageHandler, $watermark, $positionX, @@ -517,7 +517,7 @@ public function watermark($imagePath, $positionX = 0, $positionY = 0, $opacity = ); } elseif ($this->getWatermarkPosition() == self::POSITION_BOTTOM_LEFT) { $positionY = $this->_imageSrcHeight - imagesy($watermark); - $this->imagecopymergeWithAlphaFix( + $this->copyImageWithAlphaPercentage( $this->_imageHandler, $watermark, $positionX, @@ -531,7 +531,7 @@ public function watermark($imagePath, $positionX = 0, $positionY = 0, $opacity = } if ($tile === false && $merged === false) { - $this->imagecopymergeWithAlphaFix( + $this->copyImageWithAlphaPercentage( $this->_imageHandler, $watermark, $positionX, @@ -547,7 +547,7 @@ public function watermark($imagePath, $positionX = 0, $positionY = 0, $opacity = $offsetY = $positionY; while ($offsetY <= $this->_imageSrcHeight + imagesy($watermark)) { while ($offsetX <= $this->_imageSrcWidth + imagesx($watermark)) { - $this->imagecopymergeWithAlphaFix( + $this->copyImageWithAlphaPercentage( $this->_imageHandler, $watermark, $offsetX, @@ -780,64 +780,71 @@ protected function _createEmptyImage($width, $height) } /** - * Fix an issue with the usage of imagecopymerge where the alpha channel is lost + * Copy source image onto destination image with given alpha percentage * - * @param resource $dst_im - * @param resource $src_im - * @param int $dst_x - * @param int $dst_y - * @param int $src_x - * @param int $src_y - * @param int $src_w - * @param int $src_h - * @param int $pct + * @internal The arguments and functionality is the same as imagecopymerge + * but with proper handling of alpha transparency + * + * @param resource $destinationImage + * @param resource $sourceImage + * @param int $destinationX + * @param int $destinationY + * @param int $sourceX + * @param int $sourceY + * @param int $sourceWidth + * @param int $sourceHeight + * @param int $alphaPercentage * * @return bool */ - private function imagecopymergeWithAlphaFix( - $dst_im, - $src_im, - $dst_x, - $dst_y, - $src_x, - $src_y, - $src_w, - $src_h, - $pct + private function copyImageWithAlphaPercentage( + $destinationImage, + $sourceImage, + $destinationX, + $destinationY, + $sourceX, + $sourceY, + $sourceWidth, + $sourceHeight, + $alphaPercentage ) { - if ($pct >= 100) { - return imagecopy($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h); + if (imageistruecolor($destinationImage) === false || imageistruecolor($sourceImage) === false) { + return imagecopymerge($destinationImage, $sourceImage, $destinationX, $destinationY, $sourceX, $sourceY, $sourceWidth, $sourceHeight, $alphaPercentage); + } + + if ($alphaPercentage >= 100) { + return imagecopy($destinationImage, $sourceImage, $destinationX, $destinationY, $sourceX, $sourceY, $sourceWidth, $sourceHeight); } - if ($pct < 0) { + if ($alphaPercentage < 0) { return false; } - $sizeX = imagesx($src_im); - $sizeY = imagesy($src_im); - if (false === $sizeX || false === $sizeY) { + $sizeX = imagesx($sourceImage); + $sizeY = imagesy($sourceImage); + if ($sizeX === false || $sizeY === false || $sizeX === 0 || $sizeY === 0) { return false; } - $tmpImg = imagecreatetruecolor($src_w, $src_h); - if (false === $tmpImg) { + $tmpImg = imagecreatetruecolor($sourceWidth, $sourceHeight); + if ($tmpImg === false) { return false; } - if (false === imagealphablending($tmpImg, false)) { + if (imagealphablending($tmpImg, false) === false) { return false; } - if (false === imagecopy($tmpImg, $src_im, 0, 0, 0, 0, $sizeX, $sizeY)) { + if (imagecopy($tmpImg, $sourceImage, 0, 0, 0, 0, $sizeX, $sizeY) === false) { return false; } - $transparancy = 127 - (($pct*127)/100); - if (false === imagefilter($tmpImg, IMG_FILTER_COLORIZE, 0, 0, 0, $transparancy)) { + $transparency = 127 - (($alphaPercentage*127)/100); + if (imagefilter($tmpImg, IMG_FILTER_COLORIZE, 0, 0, 0, $transparency) === false) { return false; } - $result = imagecopy($dst_im, $tmpImg, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h); + $result = imagecopy($destinationImage, $tmpImg, $destinationX, $destinationY, $sourceX, $sourceY, $sourceWidth, $sourceHeight); imagedestroy($tmpImg); return $result; From 00a5c3a2f53c5c880210157fa44648688c212070 Mon Sep 17 00:00:00 2001 From: Elze Kool Date: Sun, 19 Nov 2017 11:03:45 +0100 Subject: [PATCH 006/210] Add integration test for watermark with alpha Added integration tests for handling alpha transparency in watermarks. Renamed the current test for watermarks as it only tests if the watermark is correctly places --- .../Framework/Image/Adapter/InterfaceTest.php | 97 +++++++++++++++++- .../Image/_files/watermark_alpha.png | Bin 0 -> 202 bytes .../_files/watermark_alpha_base_image.jpg | Bin 0 -> 1252 bytes 3 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Framework/Image/_files/watermark_alpha.png create mode 100644 dev/tests/integration/testsuite/Magento/Framework/Image/_files/watermark_alpha_base_image.jpg diff --git a/dev/tests/integration/testsuite/Magento/Framework/Image/Adapter/InterfaceTest.php b/dev/tests/integration/testsuite/Magento/Framework/Image/Adapter/InterfaceTest.php index 420803d9530bd..bc8281d55ac4f 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Image/Adapter/InterfaceTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Image/Adapter/InterfaceTest.php @@ -337,6 +337,97 @@ public function rotateDataProvider() ); } + /** + * Test if alpha transparency is correctly handled + * + * @param string $image + * @param string $watermark + * @param int $alphaPercentage + * @param array $comparePoint1 + * @param array $comparePoint2 + * @param string $adapterType + * + * @dataProvider imageWatermarkWithAlphaTransparencyDataProvider + * @depends testOpen + * @depends testImageSize + */ + public function testWatermarkWithAlphaTransparency( + $image, + $watermark, + $alphaPercentage, + $comparePoint1, + $comparePoint2, + $adapterType + ) { + $imageAdapter = $this->_getAdapter($adapterType); + $imageAdapter->open($image); + + $watermarkAdapter = $this->_getAdapter($adapterType); + $watermarkAdapter->open($watermark); + + list($comparePoint1X, $comparePoint1Y) = $comparePoint1; + list($comparePoint2X, $comparePoint2Y) = $comparePoint2; + + $imageAdapter + ->setWatermarkImageOpacity($alphaPercentage) + ->setWatermarkPosition(\Magento\Framework\Image\Adapter\AbstractAdapter::POSITION_TOP_LEFT) + ->watermark($watermark); + + $comparePoint1Color = $imageAdapter->getColorAt($comparePoint1X, $comparePoint1Y); + unset($comparePoint1Color['alpha']); + + $comparePoint2Color = $imageAdapter->getColorAt($comparePoint2X, $comparePoint2Y); + unset($comparePoint2Color['alpha']); + + $result = $this->_compareColors($comparePoint1Color, $comparePoint2Color); + $message = sprintf( + '%s should be different to %s due to alpha transparency', + join(',', $comparePoint1Color), + join(',', $comparePoint2Color) + ); + $this->assertFalse($result, $message); + } + + public function imageWatermarkWithAlphaTransparencyDataProvider() + { + return $this->_prepareData( + [ + // Watermark with alpha channel, 25% + [ + $this->_getFixture('watermark_alpha_base_image.jpg'), + $this->_getFixture('watermark_alpha.png'), + 25, + [ 23, 3 ], + [ 23, 30 ] + ], + // Watermark with alpha channel, 50% + [ + $this->_getFixture('watermark_alpha_base_image.jpg'), + $this->_getFixture('watermark_alpha.png'), + 50, + [ 23, 3 ], + [ 23, 30 ] + ], + // Watermark with no alpha channel, 50% + [ + $this->_getFixture('watermark_alpha_base_image.jpg'), + $this->_getFixture('watermark.png'), + 50, + [ 3, 3 ], + [ 23,3 ] + ], + // Watermark with no alpha channel, 100% + [ + $this->_getFixture('watermark_alpha_base_image.jpg'), + $this->_getFixture('watermark.png'), + 100, + [ 3, 3 ], + [ 3, 60 ] + ], + ] + ); + } + /** * Checks if watermark exists on the right position * @@ -350,10 +441,10 @@ public function rotateDataProvider() * @param int $colorY * @param string $adapterType * - * @dataProvider imageWatermarkDataProvider + * @dataProvider imageWatermarkPositionDataProvider * @depends testOpen */ - public function testWatermark( + public function testWatermarkPosition( $image, $watermark, $width, @@ -387,7 +478,7 @@ public function testWatermark( $this->assertFalse($result, $message); } - public function imageWatermarkDataProvider() + public function imageWatermarkPositionDataProvider() { return $this->_prepareData( [ diff --git a/dev/tests/integration/testsuite/Magento/Framework/Image/_files/watermark_alpha.png b/dev/tests/integration/testsuite/Magento/Framework/Image/_files/watermark_alpha.png new file mode 100644 index 0000000000000000000000000000000000000000..af05a14a99fdd34e8f5edb8740fec06d5d3ccd8e GIT binary patch literal 202 zcmeAS@N?(olHy`uVBq!ia0vp^ra-L5!3HE#mRxoPQk(@Ik;M!Qd`Cc-ajG_-G*Ga{ z)5S3)qV??+N8W}29+r!mD>>IZ;B(A)*dwZU)WvhN{cn*sD!z*o(hYBaX|T8OYF!)x zC0v<~f9c2zEb#4rG3|h{?V@O=_dve49hdvcf+;{E!bpqj-Alo{ixw<%FNyy2M`r1v jKrJYt)L2~QvYr23A7_64ts-NfI~Y7&{an^LB{Ts5PkTog literal 0 HcmV?d00001 diff --git a/dev/tests/integration/testsuite/Magento/Framework/Image/_files/watermark_alpha_base_image.jpg b/dev/tests/integration/testsuite/Magento/Framework/Image/_files/watermark_alpha_base_image.jpg new file mode 100644 index 0000000000000000000000000000000000000000..361ff523d2130ccfccd86a935f2f72053420e766 GIT binary patch literal 1252 zcmex=5A1R0qH8UG()kY`|EWCgkw?FU=d^$QZ#gA6AnydS1J@SYMi)`L)mHLLD8U# zA5@H!ikdjN#Ka{erBv0_H8izMOwG(KEUlbfT;1F~JiUTLLc_u%BBPR1Qq$5iGP89XZ3R<7E#dCS&q+js2Tb?ESsqsNY) zIC<*Qo&Gyn;}30F zQ~&r*t#8`A{jHf1{~3<&_%&;lyyWMS{r&ngle#q4UEZRxsEdJA{Ny^wlCZ4555KO} zda$DEYZc?`A7NAb|5W#{Tyy#Qhqc=BKfcQchdMvD%bWi3>1UllSJ7K#ts;RAtR!NY zSztTP#_zG)x->?VKW@E)Z9UhejsF??3%{Dqs`@9oH2FV++~ZeSD{9iuUixRVFSSc! z(QdyBi@G!zNW{#O!L~%M{@#9V%j%|uudlvfU;i*F%>Ls$yJegG;ei>--}7@<{PF2$ zHoA(0XWkMCbY&nF7iEL(Fs=LW>)O=&iL=m&O7n5;31I*bWi&6d@8C@Z=nEn4v08E$z Aw*UYD literal 0 HcmV?d00001 From 503204c04627454ebe7e59e076089de640b8fe8b Mon Sep 17 00:00:00 2001 From: Elze Kool Date: Sun, 19 Nov 2017 21:20:44 +0100 Subject: [PATCH 007/210] Fix issues with static tests --- .../Magento/Framework/Image/Adapter/Gd2.php | 40 +++++++++++++++++-- .../Framework/Image/Adapter/ImageMagick.php | 16 +++++++- 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/lib/internal/Magento/Framework/Image/Adapter/Gd2.php b/lib/internal/Magento/Framework/Image/Adapter/Gd2.php index 6817c01b19cbf..a36e41a526466 100644 --- a/lib/internal/Magento/Framework/Image/Adapter/Gd2.php +++ b/lib/internal/Magento/Framework/Image/Adapter/Gd2.php @@ -5,6 +5,9 @@ */ namespace Magento\Framework\Image\Adapter; +/** + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) + */ class Gd2 extends \Magento\Framework\Image\Adapter\AbstractAdapter { /** @@ -796,6 +799,9 @@ protected function _createEmptyImage($width, $height) * @param int $alphaPercentage * * @return bool + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ private function copyImageWithAlphaPercentage( $destinationImage, @@ -809,11 +815,30 @@ private function copyImageWithAlphaPercentage( $alphaPercentage ) { if (imageistruecolor($destinationImage) === false || imageistruecolor($sourceImage) === false) { - return imagecopymerge($destinationImage, $sourceImage, $destinationX, $destinationY, $sourceX, $sourceY, $sourceWidth, $sourceHeight, $alphaPercentage); + return imagecopymerge( + $destinationImage, + $sourceImage, + $destinationX, + $destinationY, + $sourceX, + $sourceY, + $sourceWidth, + $sourceHeight, + $alphaPercentage + ); } if ($alphaPercentage >= 100) { - return imagecopy($destinationImage, $sourceImage, $destinationX, $destinationY, $sourceX, $sourceY, $sourceWidth, $sourceHeight); + return imagecopy( + $destinationImage, + $sourceImage, + $destinationX, + $destinationY, + $sourceX, + $sourceY, + $sourceWidth, + $sourceHeight + ); } if ($alphaPercentage < 0) { @@ -844,7 +869,16 @@ private function copyImageWithAlphaPercentage( return false; } - $result = imagecopy($destinationImage, $tmpImg, $destinationX, $destinationY, $sourceX, $sourceY, $sourceWidth, $sourceHeight); + $result = imagecopy( + $destinationImage, + $tmpImg, + $destinationX, + $destinationY, + $sourceX, + $sourceY, + $sourceWidth, + $sourceHeight + ); imagedestroy($tmpImg); return $result; diff --git a/lib/internal/Magento/Framework/Image/Adapter/ImageMagick.php b/lib/internal/Magento/Framework/Image/Adapter/ImageMagick.php index 29f3c85dc1205..5d9ef49c7d285 100644 --- a/lib/internal/Magento/Framework/Image/Adapter/ImageMagick.php +++ b/lib/internal/Magento/Framework/Image/Adapter/ImageMagick.php @@ -311,14 +311,26 @@ public function watermark($imagePath, $positionX = 0, $positionY = 0, $opacity = $offsetY = $positionY; while ($offsetY <= $this->_imageSrcHeight + $watermark->getImageHeight()) { while ($offsetX <= $this->_imageSrcWidth + $watermark->getImageWidth()) { - $this->_imageHandler->compositeImage($watermark, \Imagick::COMPOSITE_OVER, $offsetX, $offsetY, $compositeChannels); + $this->_imageHandler->compositeImage( + $watermark, + \Imagick::COMPOSITE_OVER, + $offsetX, + $offsetY, + $compositeChannels + ); $offsetX += $watermark->getImageWidth(); } $offsetX = $positionX; $offsetY += $watermark->getImageHeight(); } } else { - $this->_imageHandler->compositeImage($watermark, \Imagick::COMPOSITE_OVER, $positionX, $positionY, $compositeChannels); + $this->_imageHandler->compositeImage( + $watermark, + \Imagick::COMPOSITE_OVER, + $positionX, + $positionY, + $compositeChannels + ); } } catch (\ImagickException $e) { throw new \Exception('Unable to create watermark.', $e->getCode(), $e); From 2abaf8c50a8a8b72b5c9045fb816dd5c3ec59ea5 Mon Sep 17 00:00:00 2001 From: Carlos Lizaga Date: Tue, 21 Nov 2017 17:36:16 +0100 Subject: [PATCH 008/210] Added translate.test.js for Jasmine compatibility unit testing. Removed transtale-test.js from jsTestDriver suite. --- .../mage/translate/translate-test.js | 47 ------------------- .../jasmine/tests/lib/mage/translate.test.js | 45 ++++++++++++++++++ 2 files changed, 45 insertions(+), 47 deletions(-) delete mode 100644 dev/tests/js/JsTestDriver/testsuite/mage/translate/translate-test.js create mode 100644 dev/tests/js/jasmine/tests/lib/mage/translate.test.js diff --git a/dev/tests/js/JsTestDriver/testsuite/mage/translate/translate-test.js b/dev/tests/js/JsTestDriver/testsuite/mage/translate/translate-test.js deleted file mode 100644 index a9bbc7fb10d2d..0000000000000 --- a/dev/tests/js/JsTestDriver/testsuite/mage/translate/translate-test.js +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -TranslateTest = TestCase('TranslateTest'); -TranslateTest.prototype.testTranslateExist = function() { - assertNotUndefined(jQuery.mage.translate); -}; -TranslateTest.prototype.testTranslationParametersOneArgument = function() { - jQuery.mage.translate.add('Hello World!'); - assertEquals( - 'Hello World!', - jQuery.mage.translate.translate('Hello World!')); -}; -TranslateTest.prototype.testTranslationParametersArray = function() { - jQuery.mage.translate.add(['Hello World!', 'Bonjour tout le monde!']); - assertEquals( - 'Hello World!', - jQuery.mage.translate.translate('Hello World!')); -}; -TranslateTest.prototype.testTranslationParametersObject = function() { - var translation = {'Hello World!': 'Bonjour tout le monde!'}; - jQuery.mage.translate.add(translation); - assertEquals( - translation['Hello World!'], - jQuery.mage.translate.translate('Hello World!')); - - translation = { - 'Hello World!': 'Hallo Welt!', - 'Some text with symbols!-+"%#*': 'Ein Text mit Symbolen!-+"%#*' - }; - jQuery.mage.translate.add(translation); - jQuery.each(translation, function(key) { - assertEquals(translation[key], jQuery.mage.translate.translate(key)); - }); -}; -TranslateTest.prototype.testTranslationParametersTwoArguments = function() { - jQuery.mage.translate.add('Hello World!', 'Bonjour tout le monde!'); - assertEquals( - 'Bonjour tout le monde!', - jQuery.mage.translate.translate('Hello World!')); -}; -TranslateTest.prototype.testTranslationAlias = function() { - var translation = {'Hello World!': 'Bonjour tout le monde!'}; - jQuery.mage.translate.add(translation); - assertEquals(translation['Hello World!'], jQuery.mage.__('Hello World!')); -}; diff --git a/dev/tests/js/jasmine/tests/lib/mage/translate.test.js b/dev/tests/js/jasmine/tests/lib/mage/translate.test.js new file mode 100644 index 0000000000000..10b4e77f3e315 --- /dev/null +++ b/dev/tests/js/jasmine/tests/lib/mage/translate.test.js @@ -0,0 +1,45 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'jquery', + 'mage/translate' +], function ($) { + 'use strict'; + + describe('Test for mage/translate jQuery plugin', function () { + it('works with one string as parameter', function () { + $.mage.translate.add('Hello World!'); + expect('Hello World!').toEqual($.mage.translate.translate('Hello World!')); + }); + it('works with one array as parameter', function () { + $.mage.translate.add(['Hello World!', 'Bonjour tout le monde!']); + expect('Hello World!').toEqual($.mage.translate.translate('Hello World!')); + }); + it('works with one object as parameter', function () { + var translation = {'Hello World!': 'Bonjour tout le monde!'}; + $.mage.translate.add(translation); + expect(translation['Hello World!']).toEqual($.mage.translate.translate('Hello World!')); + + translation = { + 'Hello World!': 'Hallo Welt!', + 'Some text with symbols!-+"%#*': 'Ein Text mit Symbolen!-+"%#*' + }; + + $.mage.translate.add(translation); + $.each(translation, function (key) { + expect(translation[key]).toEqual($.mage.translate.translate(key)); + }); + }); + it('works with two string as parameter', function () { + $.mage.translate.add('Hello World!', 'Bonjour tout le monde!'); + expect('Bonjour tout le monde!').toEqual($.mage.translate.translate('Hello World!')); + }); + it('works with translation alias __', function () { + $.mage.translate.add('Hello World!'); + expect('Hello World!').toEqual($.mage.__('Hello World!')); + }); + }); + +}); \ No newline at end of file From 16916212d3815d33dcd601eb72d8408099a8c287 Mon Sep 17 00:00:00 2001 From: Carlos Lizaga Date: Wed, 22 Nov 2017 16:59:22 +0100 Subject: [PATCH 009/210] Fix translate.test to be eslint friendly --- dev/tests/js/jasmine/tests/lib/mage/translate.test.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/dev/tests/js/jasmine/tests/lib/mage/translate.test.js b/dev/tests/js/jasmine/tests/lib/mage/translate.test.js index 10b4e77f3e315..c87cfa227c1aa 100644 --- a/dev/tests/js/jasmine/tests/lib/mage/translate.test.js +++ b/dev/tests/js/jasmine/tests/lib/mage/translate.test.js @@ -2,6 +2,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +/* eslint-disable max-nested-callbacks */ define([ 'jquery', 'mage/translate' @@ -18,7 +19,10 @@ define([ expect('Hello World!').toEqual($.mage.translate.translate('Hello World!')); }); it('works with one object as parameter', function () { - var translation = {'Hello World!': 'Bonjour tout le monde!'}; + var translation = { + 'Hello World!': 'Bonjour tout le monde!' + }; + $.mage.translate.add(translation); expect(translation['Hello World!']).toEqual($.mage.translate.translate('Hello World!')); @@ -42,4 +46,4 @@ define([ }); }); -}); \ No newline at end of file +}); From ea56695cb6b5e39f9dfd86302a4daa41f5dd31da Mon Sep 17 00:00:00 2001 From: Carlos Lizaga Date: Wed, 22 Nov 2017 17:50:00 +0100 Subject: [PATCH 010/210] Added accordion.test.js for Jasmine testing. Removed accordion.js and index.html for jsTestDriver test. --- .../testsuite/mage/accordion/accordion.js | 57 ------------- .../testsuite/mage/accordion/index.html | 31 ------- .../jasmine/tests/lib/mage/accordion.test.js | 81 +++++++++++++++++++ 3 files changed, 81 insertions(+), 88 deletions(-) delete mode 100644 dev/tests/js/JsTestDriver/testsuite/mage/accordion/accordion.js delete mode 100644 dev/tests/js/JsTestDriver/testsuite/mage/accordion/index.html create mode 100644 dev/tests/js/jasmine/tests/lib/mage/accordion.test.js diff --git a/dev/tests/js/JsTestDriver/testsuite/mage/accordion/accordion.js b/dev/tests/js/JsTestDriver/testsuite/mage/accordion/accordion.js deleted file mode 100644 index 562c5c096b654..0000000000000 --- a/dev/tests/js/JsTestDriver/testsuite/mage/accordion/accordion.js +++ /dev/null @@ -1,57 +0,0 @@ -/** - * @category mage.js - * @package test - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -/* - - */ -test( "Initialization", function() { - expect(2); - var accordion = $("
"); - accordion.accordion(); - ok( accordion.is(':mage-accordion'), "widget instantiated" ); - accordion.accordion('destroy'); - ok( !accordion.is(':mage-accordion'), "widget destroyed" ); -}); - - - -test( "One-collapsible element", function() { - expect(4); - var accordion = $('
'); - var title1 = $('
').appendTo(accordion); - var content1 = $('
').appendTo(accordion); - var title2 = $('
').appendTo(accordion); - var content2 = $('
').appendTo(accordion); - accordion.appendTo("body"); - - accordion.accordion(); - ok( content1.is(':visible'), "content visible" ); - ok( content2.is(':hidden'), "content hidden" ); - title2.trigger('click'); - ok( content1.is(':hidden'), "content hidden" ); - ok( content2.is(':visible'), "content visible" ); - accordion.accordion('destroy'); - -}); - -test( "Multi-collapsible elements", function() { - expect(4); - var accordion = $('
'); - var title1 = $('
').appendTo(accordion); - var content1 = $('
').appendTo(accordion); - var title2 = $('
').appendTo(accordion); - var content2 = $('
').appendTo(accordion); - accordion.appendTo("body"); - - accordion.accordion({multipleCollapsible:true}); - ok( content1.is(':visible'), "content visible" ); - ok( content2.is(':hidden'), "content hidden" ); - title2.trigger('click'); - ok( content1.is(':visible'), "content visible" ); - ok( content2.is(':visible'), "content visible" ); - accordion.accordion('destroy'); -}); diff --git a/dev/tests/js/JsTestDriver/testsuite/mage/accordion/index.html b/dev/tests/js/JsTestDriver/testsuite/mage/accordion/index.html deleted file mode 100644 index 093284c6f4fa8..0000000000000 --- a/dev/tests/js/JsTestDriver/testsuite/mage/accordion/index.html +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - Accordion Widget: QUnit Tests - - - - - - - - - - - - -
-
-
- - diff --git a/dev/tests/js/jasmine/tests/lib/mage/accordion.test.js b/dev/tests/js/jasmine/tests/lib/mage/accordion.test.js new file mode 100644 index 0000000000000..a35367946349a --- /dev/null +++ b/dev/tests/js/jasmine/tests/lib/mage/accordion.test.js @@ -0,0 +1,81 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'jquery', + 'mage/accordion' +], function ($) { + 'use strict'; + + describe('Test for mage/accordion jQuery plugin', function () { + it('check if accordion can be initialized', function () { + var accordion = $("
"); + + accordion.accordion(); + expect(accordion.is(':mage-accordion')).toBeTruthy(); + + accordion.accordion('destroy'); + expect(accordion.is(':mage-accordion')).toBeFalsy(); + }); + it('check one-collapsible element accordion', function () { + var accordion = $('
'), + title1 = $('
').appendTo(accordion), + content1 = $('
').appendTo(accordion), + title2 = $('
').appendTo(accordion), + content2 = $('
').appendTo(accordion); + + accordion.appendTo("body"); + + accordion.accordion(); + + expect(accordion.is(':mage-accordion')).toBeTruthy(); + + expect(content1.is(':visible')).toBeTruthy(); + expect(content2.is(':hidden')).toBeTruthy(); + + title2.trigger('click'); + + expect(content1.is(':hidden')).toBeTruthy(); + expect(content2.is(':visible')).toBeTruthy(); + + title1.trigger('click'); + + expect(content1.is(':visible')).toBeTruthy(); + expect(content2.is(':hidden')).toBeTruthy(); + + accordion.accordion('destroy'); + + expect(accordion.is(':mage-accordion')).toBeFalsy(); + }); + it('check multi-collapsible element accordion', function () { + var accordion = $('
'); + + $('
').appendTo(accordion); + + var content1 = $('
').appendTo(accordion), + title2 = $('
').appendTo(accordion), + content2 = $('
').appendTo(accordion); + + accordion.appendTo("body"); + + accordion.accordion({ + multipleCollapsible: true + }); + + expect(accordion.is(':mage-accordion')).toBeTruthy(); + + expect(content1.is(':visible')).toBeTruthy(); + expect(content2.is(':hidden')).toBeTruthy(); + + title2.trigger('click'); + + expect(content1.is(':visible')).toBeTruthy(); + expect(content2.is(':visible')).toBeTruthy(); + + accordion.accordion('destroy'); + + expect(accordion.is(':mage-accordion')).toBeFalsy(); + }); + }); +}); From 126a1e30be2b23a03063935d9199725d770d84c2 Mon Sep 17 00:00:00 2001 From: Carlos Lizaga Date: Wed, 22 Nov 2017 18:20:36 +0100 Subject: [PATCH 011/210] Eslint upgrades. --- .../js/jasmine/tests/lib/mage/accordion.test.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/dev/tests/js/jasmine/tests/lib/mage/accordion.test.js b/dev/tests/js/jasmine/tests/lib/mage/accordion.test.js index a35367946349a..12ca91a4ae002 100644 --- a/dev/tests/js/jasmine/tests/lib/mage/accordion.test.js +++ b/dev/tests/js/jasmine/tests/lib/mage/accordion.test.js @@ -25,7 +25,7 @@ define([ title2 = $('
').appendTo(accordion), content2 = $('
').appendTo(accordion); - accordion.appendTo("body"); + accordion.appendTo('body'); accordion.accordion(); @@ -49,15 +49,14 @@ define([ expect(accordion.is(':mage-accordion')).toBeFalsy(); }); it('check multi-collapsible element accordion', function () { - var accordion = $('
'); - - $('
').appendTo(accordion); - - var content1 = $('
').appendTo(accordion), + var accordion = $('
'), + content1 = $('
').appendTo(accordion), title2 = $('
').appendTo(accordion), content2 = $('
').appendTo(accordion); - accordion.appendTo("body"); + $('
').appendTo(accordion); + + accordion.appendTo('body'); accordion.accordion({ multipleCollapsible: true From b3fedbc6ed90ef99f1be17c6d77d2cb0ea50fa74 Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko Date: Wed, 22 Nov 2017 19:53:45 +0200 Subject: [PATCH 012/210] Added decorate.test.js for Jasmine testing. Removed decorate-test.js --- .../testsuite/mage/decorate-test.js | 141 ------------ .../jasmine/tests/lib/mage/decorate.test.js | 202 ++++++++++++++++++ 2 files changed, 202 insertions(+), 141 deletions(-) delete mode 100644 dev/tests/js/JsTestDriver/testsuite/mage/decorate-test.js create mode 100644 dev/tests/js/jasmine/tests/lib/mage/decorate.test.js diff --git a/dev/tests/js/JsTestDriver/testsuite/mage/decorate-test.js b/dev/tests/js/JsTestDriver/testsuite/mage/decorate-test.js deleted file mode 100644 index 96bad35a17e2e..0000000000000 --- a/dev/tests/js/JsTestDriver/testsuite/mage/decorate-test.js +++ /dev/null @@ -1,141 +0,0 @@ -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -DecoratorTest = TestCase('DecoratorTest'); -DecoratorTest.prototype.testDecoratorList = function () { - /*:DOC +=
    -
  • item1
  • -
  • item2
  • -
  • item3
  • -
  • item4
  • -
- */ - var list = $('#list'); - list.decorate('list'); - assertTrue($(list.find('li')[0]).hasClass('odd')); - assertFalse($(list.find('li')[0]).hasClass('even')); - assertTrue($(list.find('li')[1]).hasClass('even')); - assertFalse($(list.find('li')[1]).hasClass('odd')); - assertTrue($(list.find('li')[2]).hasClass('odd')); - assertFalse($(list.find('li')[2]).hasClass('even')); - assertTrue($(list.find('li')[3]).hasClass('even')); - assertFalse($(list.find('li')[3]).hasClass('odd')); - assertTrue($(list.find('li')[3]).hasClass('last')); -}; - -DecoratorTest.prototype.testDecoratorGeneral = function () { - /*:DOC +=
-
item1
-
item2
-
item3
-
item4
-
- */ - var itemClass = '.item'; - $(itemClass).decorate('generic'); - assertTrue($($(itemClass)[0]).hasClass('odd')); - assertFalse($($(itemClass)[0]).hasClass('even')); - assertTrue($($(itemClass)[0]).hasClass('first')); - assertFalse($($(itemClass)[0]).hasClass('last')); - - assertFalse($($(itemClass)[1]).hasClass('odd')); - assertTrue($($(itemClass)[1]).hasClass('even')); - assertFalse($($(itemClass)[1]).hasClass('first')); - assertFalse($($(itemClass)[1]).hasClass('last')); - - assertTrue($($(itemClass)[2]).hasClass('odd')); - assertFalse($($(itemClass)[2]).hasClass('even')); - assertFalse($($(itemClass)[2]).hasClass('first')); - assertFalse($($(itemClass)[2]).hasClass('last')); - - assertFalse($($(itemClass)[3]).hasClass('odd')); - assertTrue($($(itemClass)[3]).hasClass('even')); - assertFalse($($(itemClass)[3]).hasClass('first')); - assertTrue($($(itemClass)[3]).hasClass('last')); -}; - -DecoratorTest.prototype.testDecoratorTable = function (){ - /*:DOC += - - - - - - - - - - - - - - - - - - - - - - -
MonthSavings
Sum$180
January$100
February$80
- */ - var tableId = '#foo'; - $(tableId).decorate('table'); - assertTrue($(tableId).find('thead tr').hasClass('first')); - assertTrue($(tableId).find('thead tr').hasClass('last')); - assertFalse($(tableId).find('thead tr').hasClass('odd')); - assertFalse($(tableId).find('thead tr').hasClass('even')); - - assertTrue($(tableId).find('tfoot tr').hasClass('first')); - assertTrue($(tableId).find('tfoot tr').hasClass('last')); - assertFalse($(tableId).find('tfoot tr').hasClass('odd')); - assertFalse($(tableId).find('tfoot tr').hasClass('even')); - - assertFalse($(tableId).find('tfoot tr td').last().hasClass('first')); - assertTrue($(tableId).find('tfoot tr td').last().hasClass('last')); - assertFalse($(tableId).find('tfoot tr td').last().hasClass('odd')); - assertFalse($(tableId).find('tfoot tr td').last().hasClass('even')); - - assertTrue($(tableId).find('tbody tr').first().hasClass('first')); - assertTrue($(tableId).find('tbody tr').first().hasClass('odd')); - assertFalse($(tableId).find('tbody tr').first().hasClass('last')); - assertFalse($(tableId).find('tbody tr').first().hasClass('even')); - assertFalse($(tableId).find('tbody tr').last().hasClass('first')); - assertFalse($(tableId).find('tbody tr').last().hasClass('odd')); - assertTrue($(tableId).find('tbody tr').last().hasClass('last')); - assertTrue($(tableId).find('tbody tr').last().hasClass('even')); - - assertFalse($(tableId).find('tbody tr td').last().hasClass('first')); - assertFalse($(tableId).find('tbody tr td').last().hasClass('odd')); - assertTrue($(tableId).find('tbody tr td').last().hasClass('last')); - assertFalse($(tableId).find('tbody tr td').last().hasClass('even')); -}; - -DecoratorTest.prototype.testDecoratorDataList = function () { - /*:DOC +=
-
item
-
item
-
item
-
item
-
- */ - var listId = '#data-list'; - $(listId).decorate('dataList'); - assertTrue($(listId).find('dt').first().hasClass('odd')); - assertFalse($(listId).find('dt').first().hasClass('even')); - assertFalse($(listId).find('dt').first().hasClass('last')); - - assertTrue($(listId).find('dt').last().hasClass('even')); - assertFalse($(listId).find('dt').last().hasClass('odd')); - assertTrue($(listId).find('dt').last().hasClass('last')); - - assertTrue($(listId).find('dd').first().hasClass('odd')); - assertFalse($(listId).find('dd').first().hasClass('even')); - assertFalse($(listId).find('dd').first().hasClass('last')); - - assertTrue($(listId).find('dd').last().hasClass('even')); - assertFalse($(listId).find('dd').last().hasClass('odd')); - assertTrue($(listId).find('dd').last().hasClass('last')); -}; diff --git a/dev/tests/js/jasmine/tests/lib/mage/decorate.test.js b/dev/tests/js/jasmine/tests/lib/mage/decorate.test.js new file mode 100644 index 0000000000000..9b488c417674d --- /dev/null +++ b/dev/tests/js/jasmine/tests/lib/mage/decorate.test.js @@ -0,0 +1,202 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +/* eslint-disable max-nested-callbacks */ +define([ + 'mage/decorate', + 'jquery' +], function (decorate, $) { + 'use strict'; + + describe('mage/decorate', function () { + describe('"list" method', function () { + var listId = 'testList'; + + beforeEach(function () { + var list = $('
'); + + $('body').append(list); + }); + + afterEach(function () { + $('#' + listId).remove(); + }); + + it('Check correct class decoration', function () { + var $list = $('#' + listId); + + $list.decorate('list'); + expect($list.find('li:first').hasClass('first')).toBe(false); + expect($list.find('li:first').hasClass('odd')).toBe(true); + expect($list.find('li:last').hasClass('last')).toBe(true); + expect($list.find('li:odd').hasClass('even')).toBe(true); + expect($list.find('li:even').hasClass('odd')).toBe(true); + }); + }); + + describe('"generic" method', function () { + var listId = 'testList'; + + beforeEach(function () { + var list = $('
'); + + $('body').append(list); + }); + + afterEach(function () { + $('#' + listId).remove(); + }); + + it('Check correct class decoration with default params', function () { + var $list = $('#' + listId); + + $list.find('li').decorate('generic'); + expect($list.find('li:first').hasClass('first')).toBe(true); + expect($list.find('li:first').hasClass('odd')).toBe(true); + expect($list.find('li:last').hasClass('last')).toBe(true); + expect($list.find('li:odd').hasClass('even')).toBe(true); + expect($list.find('li:even').hasClass('odd')).toBe(true); + }); + + it('Check correct class decoration with custom params', function () { + var $list = $('#' + listId); + + $list.find('li').decorate('generic', ['last', 'first']); + expect($list.find('li:first').hasClass('first')).toBe(true); + expect($list.find('li:first').hasClass('odd')).toBe(false); + expect($list.find('li:last').hasClass('last')).toBe(true); + expect($list.find('li:odd').hasClass('even')).toBe(false); + expect($list.find('li:even').hasClass('odd')).toBe(false); + }); + + it('Check correct class decoration with empty items', function () { + var $list = $('#' + listId); + + $list.find('span').decorate('generic', ['last', 'first']); + expect($list.find('li:first').hasClass('first')).toBe(false); + expect($list.find('li:first').hasClass('odd')).toBe(false); + expect($list.find('li:last').hasClass('last')).toBe(false); + expect($list.find('li:odd').hasClass('even')).toBe(false); + expect($list.find('li:even').hasClass('odd')).toBe(false); + }); + }); + + describe('"table" method', function () { + var tableId = 'testTable'; + + beforeEach(function () { + var table = $('' + + '' + + '' + + '' + + '' + + '' + + '>' + + '' + + '
'); + + $('body').append(table); + }); + + afterEach(function () { + $('#' + tableId).remove(); + }); + + it('Check correct class decoration with default params', function () { + var $table = $('#' + tableId); + + $table.decorate('table'); + expect($table.find('tbody tr:first').hasClass('first')).toBe(true); + expect($table.find('tbody tr:first').hasClass('odd')).toBe(true); + expect($table.find('tbody tr:odd').hasClass('even')).toBe(true); + expect($table.find('tbody tr:even').hasClass('odd')).toBe(true); + expect($table.find('tbody tr:last').hasClass('last')).toBe(true); + expect($table.find('thead tr:first').hasClass('first')).toBe(true); + expect($table.find('thead tr:last').hasClass('last')).toBe(true); + expect($table.find('tfoot tr:first').hasClass('first')).toBe(true); + expect($table.find('tfoot tr:last').hasClass('last')).toBe(true); + expect($table.find('tr td:last').hasClass('last')).toBe(true); + expect($table.find('tr td:first').hasClass('first')).toBe(false); + }); + + it('Check correct class decoration with custom params', function () { + var $table = $('#' + tableId); + + $table.decorate('table', { + 'tbody': ['first'], + 'tbody tr': ['first'], + 'thead tr': ['first'], + 'tfoot tr': ['last'], + 'tr td': ['first'] + }); + expect($table.find('tbody:first').hasClass('first')).toBe(true); + expect($table.find('tbody tr:first').hasClass('first')).toBe(true); + expect($table.find('tbody tr:first').hasClass('odd')).toBe(false); + expect($table.find('tbody tr:odd').hasClass('even')).toBe(false); + expect($table.find('tbody tr:even').hasClass('odd')).toBe(false); + expect($table.find('tbody tr:last').hasClass('last')).toBe(false); + expect($table.find('thead tr:first').hasClass('first')).toBe(true); + expect($table.find('thead tr:last').hasClass('last')).toBe(false); + expect($table.find('tfoot tr:first').hasClass('first')).toBe(false); + expect($table.find('tfoot tr:last').hasClass('last')).toBe(true); + expect($table.find('tr td:last').hasClass('last')).toBe(false); + expect($table.find('tr td:first').hasClass('first')).toBe(true); + }); + }); + + describe('"dataList" method', function () { + var listId = 'testDataList'; + + beforeEach(function () { + var list = $('
'); + + $('body').append(list); + }); + + afterEach(function () { + $('#' + listId).remove(); + }); + + it('Check correct class decoration', function () { + var $list = $('#' + listId); + + $list.decorate('dataList'); + expect($list.find('dt:first').hasClass('first')).toBe(false); + expect($list.find('dt:first').hasClass('odd')).toBe(true); + expect($list.find('dt:odd').hasClass('even')).toBe(true); + expect($list.find('dt:even').hasClass('odd')).toBe(true); + expect($list.find('dt:last').hasClass('last')).toBe(true); + expect($list.find('dd:first').hasClass('first')).toBe(false); + expect($list.find('dd:first').hasClass('odd')).toBe(true); + expect($list.find('dd:odd').hasClass('even')).toBe(true); + expect($list.find('dd:even').hasClass('odd')).toBe(true); + expect($list.find('dd:last').hasClass('last')).toBe(true); + }); + }); + + describe('Call decorate with fake method', function () { + var listId = 'testDataList'; + + beforeEach(function () { + var list = $('
'); + + $('body').append(list); + }); + + afterEach(function () { + $('#' + listId).remove(); + }); + + it('Check error message', function () { + var $list = $('#' + listId); + + spyOn(jQuery, 'error'); + $list.decorate('customMethod'); + + expect(jQuery.error).toHaveBeenCalledWith('Method customMethod does not exist on jQuery.decorate'); + }); + }); + }); +}); From 0117f8648080ea88848e1614ffbc62cd38cb2f38 Mon Sep 17 00:00:00 2001 From: Carlos Lizaga Date: Tue, 21 Nov 2017 17:36:16 +0100 Subject: [PATCH 013/210] Added translate.test.js for Jasmine compatibility unit testing. Removed transtale-test.js from jsTestDriver suite. --- .../mage/translate/translate-test.js | 47 ------------------- .../jasmine/tests/lib/mage/translate.test.js | 45 ++++++++++++++++++ 2 files changed, 45 insertions(+), 47 deletions(-) delete mode 100644 dev/tests/js/JsTestDriver/testsuite/mage/translate/translate-test.js create mode 100644 dev/tests/js/jasmine/tests/lib/mage/translate.test.js diff --git a/dev/tests/js/JsTestDriver/testsuite/mage/translate/translate-test.js b/dev/tests/js/JsTestDriver/testsuite/mage/translate/translate-test.js deleted file mode 100644 index a9bbc7fb10d2d..0000000000000 --- a/dev/tests/js/JsTestDriver/testsuite/mage/translate/translate-test.js +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -TranslateTest = TestCase('TranslateTest'); -TranslateTest.prototype.testTranslateExist = function() { - assertNotUndefined(jQuery.mage.translate); -}; -TranslateTest.prototype.testTranslationParametersOneArgument = function() { - jQuery.mage.translate.add('Hello World!'); - assertEquals( - 'Hello World!', - jQuery.mage.translate.translate('Hello World!')); -}; -TranslateTest.prototype.testTranslationParametersArray = function() { - jQuery.mage.translate.add(['Hello World!', 'Bonjour tout le monde!']); - assertEquals( - 'Hello World!', - jQuery.mage.translate.translate('Hello World!')); -}; -TranslateTest.prototype.testTranslationParametersObject = function() { - var translation = {'Hello World!': 'Bonjour tout le monde!'}; - jQuery.mage.translate.add(translation); - assertEquals( - translation['Hello World!'], - jQuery.mage.translate.translate('Hello World!')); - - translation = { - 'Hello World!': 'Hallo Welt!', - 'Some text with symbols!-+"%#*': 'Ein Text mit Symbolen!-+"%#*' - }; - jQuery.mage.translate.add(translation); - jQuery.each(translation, function(key) { - assertEquals(translation[key], jQuery.mage.translate.translate(key)); - }); -}; -TranslateTest.prototype.testTranslationParametersTwoArguments = function() { - jQuery.mage.translate.add('Hello World!', 'Bonjour tout le monde!'); - assertEquals( - 'Bonjour tout le monde!', - jQuery.mage.translate.translate('Hello World!')); -}; -TranslateTest.prototype.testTranslationAlias = function() { - var translation = {'Hello World!': 'Bonjour tout le monde!'}; - jQuery.mage.translate.add(translation); - assertEquals(translation['Hello World!'], jQuery.mage.__('Hello World!')); -}; diff --git a/dev/tests/js/jasmine/tests/lib/mage/translate.test.js b/dev/tests/js/jasmine/tests/lib/mage/translate.test.js new file mode 100644 index 0000000000000..10b4e77f3e315 --- /dev/null +++ b/dev/tests/js/jasmine/tests/lib/mage/translate.test.js @@ -0,0 +1,45 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'jquery', + 'mage/translate' +], function ($) { + 'use strict'; + + describe('Test for mage/translate jQuery plugin', function () { + it('works with one string as parameter', function () { + $.mage.translate.add('Hello World!'); + expect('Hello World!').toEqual($.mage.translate.translate('Hello World!')); + }); + it('works with one array as parameter', function () { + $.mage.translate.add(['Hello World!', 'Bonjour tout le monde!']); + expect('Hello World!').toEqual($.mage.translate.translate('Hello World!')); + }); + it('works with one object as parameter', function () { + var translation = {'Hello World!': 'Bonjour tout le monde!'}; + $.mage.translate.add(translation); + expect(translation['Hello World!']).toEqual($.mage.translate.translate('Hello World!')); + + translation = { + 'Hello World!': 'Hallo Welt!', + 'Some text with symbols!-+"%#*': 'Ein Text mit Symbolen!-+"%#*' + }; + + $.mage.translate.add(translation); + $.each(translation, function (key) { + expect(translation[key]).toEqual($.mage.translate.translate(key)); + }); + }); + it('works with two string as parameter', function () { + $.mage.translate.add('Hello World!', 'Bonjour tout le monde!'); + expect('Bonjour tout le monde!').toEqual($.mage.translate.translate('Hello World!')); + }); + it('works with translation alias __', function () { + $.mage.translate.add('Hello World!'); + expect('Hello World!').toEqual($.mage.__('Hello World!')); + }); + }); + +}); \ No newline at end of file From 3a907c2be5becbf42ae7cc14cc4d431f7e6a14e4 Mon Sep 17 00:00:00 2001 From: Carlos Lizaga Date: Wed, 22 Nov 2017 16:59:22 +0100 Subject: [PATCH 014/210] Fix translate.test to be eslint friendly --- dev/tests/js/jasmine/tests/lib/mage/translate.test.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/dev/tests/js/jasmine/tests/lib/mage/translate.test.js b/dev/tests/js/jasmine/tests/lib/mage/translate.test.js index 10b4e77f3e315..c87cfa227c1aa 100644 --- a/dev/tests/js/jasmine/tests/lib/mage/translate.test.js +++ b/dev/tests/js/jasmine/tests/lib/mage/translate.test.js @@ -2,6 +2,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +/* eslint-disable max-nested-callbacks */ define([ 'jquery', 'mage/translate' @@ -18,7 +19,10 @@ define([ expect('Hello World!').toEqual($.mage.translate.translate('Hello World!')); }); it('works with one object as parameter', function () { - var translation = {'Hello World!': 'Bonjour tout le monde!'}; + var translation = { + 'Hello World!': 'Bonjour tout le monde!' + }; + $.mage.translate.add(translation); expect(translation['Hello World!']).toEqual($.mage.translate.translate('Hello World!')); @@ -42,4 +46,4 @@ define([ }); }); -}); \ No newline at end of file +}); From 821bdaaba4923fa4e6fdc4749ea5c625dcfd0fe0 Mon Sep 17 00:00:00 2001 From: Carlos Lizaga Date: Wed, 22 Nov 2017 17:50:00 +0100 Subject: [PATCH 015/210] Added accordion.test.js for Jasmine testing. Removed accordion.js and index.html for jsTestDriver test. --- .../testsuite/mage/accordion/accordion.js | 57 ------------- .../testsuite/mage/accordion/index.html | 31 ------- .../jasmine/tests/lib/mage/accordion.test.js | 81 +++++++++++++++++++ 3 files changed, 81 insertions(+), 88 deletions(-) delete mode 100644 dev/tests/js/JsTestDriver/testsuite/mage/accordion/accordion.js delete mode 100644 dev/tests/js/JsTestDriver/testsuite/mage/accordion/index.html create mode 100644 dev/tests/js/jasmine/tests/lib/mage/accordion.test.js diff --git a/dev/tests/js/JsTestDriver/testsuite/mage/accordion/accordion.js b/dev/tests/js/JsTestDriver/testsuite/mage/accordion/accordion.js deleted file mode 100644 index 562c5c096b654..0000000000000 --- a/dev/tests/js/JsTestDriver/testsuite/mage/accordion/accordion.js +++ /dev/null @@ -1,57 +0,0 @@ -/** - * @category mage.js - * @package test - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -/* - - */ -test( "Initialization", function() { - expect(2); - var accordion = $("
"); - accordion.accordion(); - ok( accordion.is(':mage-accordion'), "widget instantiated" ); - accordion.accordion('destroy'); - ok( !accordion.is(':mage-accordion'), "widget destroyed" ); -}); - - - -test( "One-collapsible element", function() { - expect(4); - var accordion = $('
'); - var title1 = $('
').appendTo(accordion); - var content1 = $('
').appendTo(accordion); - var title2 = $('
').appendTo(accordion); - var content2 = $('
').appendTo(accordion); - accordion.appendTo("body"); - - accordion.accordion(); - ok( content1.is(':visible'), "content visible" ); - ok( content2.is(':hidden'), "content hidden" ); - title2.trigger('click'); - ok( content1.is(':hidden'), "content hidden" ); - ok( content2.is(':visible'), "content visible" ); - accordion.accordion('destroy'); - -}); - -test( "Multi-collapsible elements", function() { - expect(4); - var accordion = $('
'); - var title1 = $('
').appendTo(accordion); - var content1 = $('
').appendTo(accordion); - var title2 = $('
').appendTo(accordion); - var content2 = $('
').appendTo(accordion); - accordion.appendTo("body"); - - accordion.accordion({multipleCollapsible:true}); - ok( content1.is(':visible'), "content visible" ); - ok( content2.is(':hidden'), "content hidden" ); - title2.trigger('click'); - ok( content1.is(':visible'), "content visible" ); - ok( content2.is(':visible'), "content visible" ); - accordion.accordion('destroy'); -}); diff --git a/dev/tests/js/JsTestDriver/testsuite/mage/accordion/index.html b/dev/tests/js/JsTestDriver/testsuite/mage/accordion/index.html deleted file mode 100644 index 093284c6f4fa8..0000000000000 --- a/dev/tests/js/JsTestDriver/testsuite/mage/accordion/index.html +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - Accordion Widget: QUnit Tests - - - - - - - - - - - - -
-
-
- - diff --git a/dev/tests/js/jasmine/tests/lib/mage/accordion.test.js b/dev/tests/js/jasmine/tests/lib/mage/accordion.test.js new file mode 100644 index 0000000000000..a35367946349a --- /dev/null +++ b/dev/tests/js/jasmine/tests/lib/mage/accordion.test.js @@ -0,0 +1,81 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'jquery', + 'mage/accordion' +], function ($) { + 'use strict'; + + describe('Test for mage/accordion jQuery plugin', function () { + it('check if accordion can be initialized', function () { + var accordion = $("
"); + + accordion.accordion(); + expect(accordion.is(':mage-accordion')).toBeTruthy(); + + accordion.accordion('destroy'); + expect(accordion.is(':mage-accordion')).toBeFalsy(); + }); + it('check one-collapsible element accordion', function () { + var accordion = $('
'), + title1 = $('
').appendTo(accordion), + content1 = $('
').appendTo(accordion), + title2 = $('
').appendTo(accordion), + content2 = $('
').appendTo(accordion); + + accordion.appendTo("body"); + + accordion.accordion(); + + expect(accordion.is(':mage-accordion')).toBeTruthy(); + + expect(content1.is(':visible')).toBeTruthy(); + expect(content2.is(':hidden')).toBeTruthy(); + + title2.trigger('click'); + + expect(content1.is(':hidden')).toBeTruthy(); + expect(content2.is(':visible')).toBeTruthy(); + + title1.trigger('click'); + + expect(content1.is(':visible')).toBeTruthy(); + expect(content2.is(':hidden')).toBeTruthy(); + + accordion.accordion('destroy'); + + expect(accordion.is(':mage-accordion')).toBeFalsy(); + }); + it('check multi-collapsible element accordion', function () { + var accordion = $('
'); + + $('
').appendTo(accordion); + + var content1 = $('
').appendTo(accordion), + title2 = $('
').appendTo(accordion), + content2 = $('
').appendTo(accordion); + + accordion.appendTo("body"); + + accordion.accordion({ + multipleCollapsible: true + }); + + expect(accordion.is(':mage-accordion')).toBeTruthy(); + + expect(content1.is(':visible')).toBeTruthy(); + expect(content2.is(':hidden')).toBeTruthy(); + + title2.trigger('click'); + + expect(content1.is(':visible')).toBeTruthy(); + expect(content2.is(':visible')).toBeTruthy(); + + accordion.accordion('destroy'); + + expect(accordion.is(':mage-accordion')).toBeFalsy(); + }); + }); +}); From 2846c785b9b9962dfaafd8fdbb81f9d2fe4851a5 Mon Sep 17 00:00:00 2001 From: Carlos Lizaga Date: Wed, 22 Nov 2017 18:20:36 +0100 Subject: [PATCH 016/210] Eslint upgrades. --- .../js/jasmine/tests/lib/mage/accordion.test.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/dev/tests/js/jasmine/tests/lib/mage/accordion.test.js b/dev/tests/js/jasmine/tests/lib/mage/accordion.test.js index a35367946349a..12ca91a4ae002 100644 --- a/dev/tests/js/jasmine/tests/lib/mage/accordion.test.js +++ b/dev/tests/js/jasmine/tests/lib/mage/accordion.test.js @@ -25,7 +25,7 @@ define([ title2 = $('
').appendTo(accordion), content2 = $('
').appendTo(accordion); - accordion.appendTo("body"); + accordion.appendTo('body'); accordion.accordion(); @@ -49,15 +49,14 @@ define([ expect(accordion.is(':mage-accordion')).toBeFalsy(); }); it('check multi-collapsible element accordion', function () { - var accordion = $('
'); - - $('
').appendTo(accordion); - - var content1 = $('
').appendTo(accordion), + var accordion = $('
'), + content1 = $('
').appendTo(accordion), title2 = $('
').appendTo(accordion), content2 = $('
').appendTo(accordion); - accordion.appendTo("body"); + $('
').appendTo(accordion); + + accordion.appendTo('body'); accordion.accordion({ multipleCollapsible: true From f4712cdda55a88ebd2c455cdb7840dae31a3334a Mon Sep 17 00:00:00 2001 From: Carlos Lizaga Date: Wed, 22 Nov 2017 19:09:46 +0100 Subject: [PATCH 017/210] Eslint improvements and logical fixes for unit testing. --- .../js/jasmine/tests/lib/mage/accordion.test.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/dev/tests/js/jasmine/tests/lib/mage/accordion.test.js b/dev/tests/js/jasmine/tests/lib/mage/accordion.test.js index 12ca91a4ae002..19a54d95cf704 100644 --- a/dev/tests/js/jasmine/tests/lib/mage/accordion.test.js +++ b/dev/tests/js/jasmine/tests/lib/mage/accordion.test.js @@ -10,7 +10,7 @@ define([ describe('Test for mage/accordion jQuery plugin', function () { it('check if accordion can be initialized', function () { - var accordion = $("
"); + var accordion = $('
'); accordion.accordion(); expect(accordion.is(':mage-accordion')).toBeTruthy(); @@ -50,12 +50,11 @@ define([ }); it('check multi-collapsible element accordion', function () { var accordion = $('
'), + title1 = $('
').appendTo(accordion), content1 = $('
').appendTo(accordion), title2 = $('
').appendTo(accordion), content2 = $('
').appendTo(accordion); - $('
').appendTo(accordion); - accordion.appendTo('body'); accordion.accordion({ @@ -63,17 +62,18 @@ define([ }); expect(accordion.is(':mage-accordion')).toBeTruthy(); - expect(content1.is(':visible')).toBeTruthy(); expect(content2.is(':hidden')).toBeTruthy(); - title2.trigger('click'); + $(title1).trigger('click'); + expect(content1.is(':visible')).toBeTruthy(); + expect(content2.is(':hidden')).toBeTruthy(); + $(title2).trigger('click'); expect(content1.is(':visible')).toBeTruthy(); expect(content2.is(':visible')).toBeTruthy(); accordion.accordion('destroy'); - expect(accordion.is(':mage-accordion')).toBeFalsy(); }); }); From f0a18772bae4a7197fcce729ed33dfa168301731 Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko Date: Wed, 22 Nov 2017 18:53:45 +0100 Subject: [PATCH 018/210] Added decorate.test.js for Jasmine testing. Removed decorate-test.js (cherry picked from commit b3fedbc) --- .../testsuite/mage/decorate-test.js | 141 ------------ .../jasmine/tests/lib/mage/decorate.test.js | 202 ++++++++++++++++++ 2 files changed, 202 insertions(+), 141 deletions(-) delete mode 100644 dev/tests/js/JsTestDriver/testsuite/mage/decorate-test.js create mode 100644 dev/tests/js/jasmine/tests/lib/mage/decorate.test.js diff --git a/dev/tests/js/JsTestDriver/testsuite/mage/decorate-test.js b/dev/tests/js/JsTestDriver/testsuite/mage/decorate-test.js deleted file mode 100644 index 96bad35a17e2e..0000000000000 --- a/dev/tests/js/JsTestDriver/testsuite/mage/decorate-test.js +++ /dev/null @@ -1,141 +0,0 @@ -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -DecoratorTest = TestCase('DecoratorTest'); -DecoratorTest.prototype.testDecoratorList = function () { - /*:DOC +=
    -
  • item1
  • -
  • item2
  • -
  • item3
  • -
  • item4
  • -
- */ - var list = $('#list'); - list.decorate('list'); - assertTrue($(list.find('li')[0]).hasClass('odd')); - assertFalse($(list.find('li')[0]).hasClass('even')); - assertTrue($(list.find('li')[1]).hasClass('even')); - assertFalse($(list.find('li')[1]).hasClass('odd')); - assertTrue($(list.find('li')[2]).hasClass('odd')); - assertFalse($(list.find('li')[2]).hasClass('even')); - assertTrue($(list.find('li')[3]).hasClass('even')); - assertFalse($(list.find('li')[3]).hasClass('odd')); - assertTrue($(list.find('li')[3]).hasClass('last')); -}; - -DecoratorTest.prototype.testDecoratorGeneral = function () { - /*:DOC +=
-
item1
-
item2
-
item3
-
item4
-
- */ - var itemClass = '.item'; - $(itemClass).decorate('generic'); - assertTrue($($(itemClass)[0]).hasClass('odd')); - assertFalse($($(itemClass)[0]).hasClass('even')); - assertTrue($($(itemClass)[0]).hasClass('first')); - assertFalse($($(itemClass)[0]).hasClass('last')); - - assertFalse($($(itemClass)[1]).hasClass('odd')); - assertTrue($($(itemClass)[1]).hasClass('even')); - assertFalse($($(itemClass)[1]).hasClass('first')); - assertFalse($($(itemClass)[1]).hasClass('last')); - - assertTrue($($(itemClass)[2]).hasClass('odd')); - assertFalse($($(itemClass)[2]).hasClass('even')); - assertFalse($($(itemClass)[2]).hasClass('first')); - assertFalse($($(itemClass)[2]).hasClass('last')); - - assertFalse($($(itemClass)[3]).hasClass('odd')); - assertTrue($($(itemClass)[3]).hasClass('even')); - assertFalse($($(itemClass)[3]).hasClass('first')); - assertTrue($($(itemClass)[3]).hasClass('last')); -}; - -DecoratorTest.prototype.testDecoratorTable = function (){ - /*:DOC += - - - - - - - - - - - - - - - - - - - - - - -
MonthSavings
Sum$180
January$100
February$80
- */ - var tableId = '#foo'; - $(tableId).decorate('table'); - assertTrue($(tableId).find('thead tr').hasClass('first')); - assertTrue($(tableId).find('thead tr').hasClass('last')); - assertFalse($(tableId).find('thead tr').hasClass('odd')); - assertFalse($(tableId).find('thead tr').hasClass('even')); - - assertTrue($(tableId).find('tfoot tr').hasClass('first')); - assertTrue($(tableId).find('tfoot tr').hasClass('last')); - assertFalse($(tableId).find('tfoot tr').hasClass('odd')); - assertFalse($(tableId).find('tfoot tr').hasClass('even')); - - assertFalse($(tableId).find('tfoot tr td').last().hasClass('first')); - assertTrue($(tableId).find('tfoot tr td').last().hasClass('last')); - assertFalse($(tableId).find('tfoot tr td').last().hasClass('odd')); - assertFalse($(tableId).find('tfoot tr td').last().hasClass('even')); - - assertTrue($(tableId).find('tbody tr').first().hasClass('first')); - assertTrue($(tableId).find('tbody tr').first().hasClass('odd')); - assertFalse($(tableId).find('tbody tr').first().hasClass('last')); - assertFalse($(tableId).find('tbody tr').first().hasClass('even')); - assertFalse($(tableId).find('tbody tr').last().hasClass('first')); - assertFalse($(tableId).find('tbody tr').last().hasClass('odd')); - assertTrue($(tableId).find('tbody tr').last().hasClass('last')); - assertTrue($(tableId).find('tbody tr').last().hasClass('even')); - - assertFalse($(tableId).find('tbody tr td').last().hasClass('first')); - assertFalse($(tableId).find('tbody tr td').last().hasClass('odd')); - assertTrue($(tableId).find('tbody tr td').last().hasClass('last')); - assertFalse($(tableId).find('tbody tr td').last().hasClass('even')); -}; - -DecoratorTest.prototype.testDecoratorDataList = function () { - /*:DOC +=
-
item
-
item
-
item
-
item
-
- */ - var listId = '#data-list'; - $(listId).decorate('dataList'); - assertTrue($(listId).find('dt').first().hasClass('odd')); - assertFalse($(listId).find('dt').first().hasClass('even')); - assertFalse($(listId).find('dt').first().hasClass('last')); - - assertTrue($(listId).find('dt').last().hasClass('even')); - assertFalse($(listId).find('dt').last().hasClass('odd')); - assertTrue($(listId).find('dt').last().hasClass('last')); - - assertTrue($(listId).find('dd').first().hasClass('odd')); - assertFalse($(listId).find('dd').first().hasClass('even')); - assertFalse($(listId).find('dd').first().hasClass('last')); - - assertTrue($(listId).find('dd').last().hasClass('even')); - assertFalse($(listId).find('dd').last().hasClass('odd')); - assertTrue($(listId).find('dd').last().hasClass('last')); -}; diff --git a/dev/tests/js/jasmine/tests/lib/mage/decorate.test.js b/dev/tests/js/jasmine/tests/lib/mage/decorate.test.js new file mode 100644 index 0000000000000..9b488c417674d --- /dev/null +++ b/dev/tests/js/jasmine/tests/lib/mage/decorate.test.js @@ -0,0 +1,202 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +/* eslint-disable max-nested-callbacks */ +define([ + 'mage/decorate', + 'jquery' +], function (decorate, $) { + 'use strict'; + + describe('mage/decorate', function () { + describe('"list" method', function () { + var listId = 'testList'; + + beforeEach(function () { + var list = $('
'); + + $('body').append(list); + }); + + afterEach(function () { + $('#' + listId).remove(); + }); + + it('Check correct class decoration', function () { + var $list = $('#' + listId); + + $list.decorate('list'); + expect($list.find('li:first').hasClass('first')).toBe(false); + expect($list.find('li:first').hasClass('odd')).toBe(true); + expect($list.find('li:last').hasClass('last')).toBe(true); + expect($list.find('li:odd').hasClass('even')).toBe(true); + expect($list.find('li:even').hasClass('odd')).toBe(true); + }); + }); + + describe('"generic" method', function () { + var listId = 'testList'; + + beforeEach(function () { + var list = $('
'); + + $('body').append(list); + }); + + afterEach(function () { + $('#' + listId).remove(); + }); + + it('Check correct class decoration with default params', function () { + var $list = $('#' + listId); + + $list.find('li').decorate('generic'); + expect($list.find('li:first').hasClass('first')).toBe(true); + expect($list.find('li:first').hasClass('odd')).toBe(true); + expect($list.find('li:last').hasClass('last')).toBe(true); + expect($list.find('li:odd').hasClass('even')).toBe(true); + expect($list.find('li:even').hasClass('odd')).toBe(true); + }); + + it('Check correct class decoration with custom params', function () { + var $list = $('#' + listId); + + $list.find('li').decorate('generic', ['last', 'first']); + expect($list.find('li:first').hasClass('first')).toBe(true); + expect($list.find('li:first').hasClass('odd')).toBe(false); + expect($list.find('li:last').hasClass('last')).toBe(true); + expect($list.find('li:odd').hasClass('even')).toBe(false); + expect($list.find('li:even').hasClass('odd')).toBe(false); + }); + + it('Check correct class decoration with empty items', function () { + var $list = $('#' + listId); + + $list.find('span').decorate('generic', ['last', 'first']); + expect($list.find('li:first').hasClass('first')).toBe(false); + expect($list.find('li:first').hasClass('odd')).toBe(false); + expect($list.find('li:last').hasClass('last')).toBe(false); + expect($list.find('li:odd').hasClass('even')).toBe(false); + expect($list.find('li:even').hasClass('odd')).toBe(false); + }); + }); + + describe('"table" method', function () { + var tableId = 'testTable'; + + beforeEach(function () { + var table = $('' + + '' + + '' + + '' + + '' + + '' + + '>' + + '' + + '
'); + + $('body').append(table); + }); + + afterEach(function () { + $('#' + tableId).remove(); + }); + + it('Check correct class decoration with default params', function () { + var $table = $('#' + tableId); + + $table.decorate('table'); + expect($table.find('tbody tr:first').hasClass('first')).toBe(true); + expect($table.find('tbody tr:first').hasClass('odd')).toBe(true); + expect($table.find('tbody tr:odd').hasClass('even')).toBe(true); + expect($table.find('tbody tr:even').hasClass('odd')).toBe(true); + expect($table.find('tbody tr:last').hasClass('last')).toBe(true); + expect($table.find('thead tr:first').hasClass('first')).toBe(true); + expect($table.find('thead tr:last').hasClass('last')).toBe(true); + expect($table.find('tfoot tr:first').hasClass('first')).toBe(true); + expect($table.find('tfoot tr:last').hasClass('last')).toBe(true); + expect($table.find('tr td:last').hasClass('last')).toBe(true); + expect($table.find('tr td:first').hasClass('first')).toBe(false); + }); + + it('Check correct class decoration with custom params', function () { + var $table = $('#' + tableId); + + $table.decorate('table', { + 'tbody': ['first'], + 'tbody tr': ['first'], + 'thead tr': ['first'], + 'tfoot tr': ['last'], + 'tr td': ['first'] + }); + expect($table.find('tbody:first').hasClass('first')).toBe(true); + expect($table.find('tbody tr:first').hasClass('first')).toBe(true); + expect($table.find('tbody tr:first').hasClass('odd')).toBe(false); + expect($table.find('tbody tr:odd').hasClass('even')).toBe(false); + expect($table.find('tbody tr:even').hasClass('odd')).toBe(false); + expect($table.find('tbody tr:last').hasClass('last')).toBe(false); + expect($table.find('thead tr:first').hasClass('first')).toBe(true); + expect($table.find('thead tr:last').hasClass('last')).toBe(false); + expect($table.find('tfoot tr:first').hasClass('first')).toBe(false); + expect($table.find('tfoot tr:last').hasClass('last')).toBe(true); + expect($table.find('tr td:last').hasClass('last')).toBe(false); + expect($table.find('tr td:first').hasClass('first')).toBe(true); + }); + }); + + describe('"dataList" method', function () { + var listId = 'testDataList'; + + beforeEach(function () { + var list = $('
'); + + $('body').append(list); + }); + + afterEach(function () { + $('#' + listId).remove(); + }); + + it('Check correct class decoration', function () { + var $list = $('#' + listId); + + $list.decorate('dataList'); + expect($list.find('dt:first').hasClass('first')).toBe(false); + expect($list.find('dt:first').hasClass('odd')).toBe(true); + expect($list.find('dt:odd').hasClass('even')).toBe(true); + expect($list.find('dt:even').hasClass('odd')).toBe(true); + expect($list.find('dt:last').hasClass('last')).toBe(true); + expect($list.find('dd:first').hasClass('first')).toBe(false); + expect($list.find('dd:first').hasClass('odd')).toBe(true); + expect($list.find('dd:odd').hasClass('even')).toBe(true); + expect($list.find('dd:even').hasClass('odd')).toBe(true); + expect($list.find('dd:last').hasClass('last')).toBe(true); + }); + }); + + describe('Call decorate with fake method', function () { + var listId = 'testDataList'; + + beforeEach(function () { + var list = $('
'); + + $('body').append(list); + }); + + afterEach(function () { + $('#' + listId).remove(); + }); + + it('Check error message', function () { + var $list = $('#' + listId); + + spyOn(jQuery, 'error'); + $list.decorate('customMethod'); + + expect(jQuery.error).toHaveBeenCalledWith('Method customMethod does not exist on jQuery.decorate'); + }); + }); + }); +}); From 64bf208aea55998942fe2035a9679e1f470bed8d Mon Sep 17 00:00:00 2001 From: Carlos Lizaga Date: Wed, 22 Nov 2017 19:26:54 +0100 Subject: [PATCH 019/210] Eslint improvements and logical fixes for unit testing. --- .../js/jasmine/tests/lib/mage/accordion.test.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/dev/tests/js/jasmine/tests/lib/mage/accordion.test.js b/dev/tests/js/jasmine/tests/lib/mage/accordion.test.js index 12ca91a4ae002..19a54d95cf704 100644 --- a/dev/tests/js/jasmine/tests/lib/mage/accordion.test.js +++ b/dev/tests/js/jasmine/tests/lib/mage/accordion.test.js @@ -10,7 +10,7 @@ define([ describe('Test for mage/accordion jQuery plugin', function () { it('check if accordion can be initialized', function () { - var accordion = $("
"); + var accordion = $('
'); accordion.accordion(); expect(accordion.is(':mage-accordion')).toBeTruthy(); @@ -50,12 +50,11 @@ define([ }); it('check multi-collapsible element accordion', function () { var accordion = $('
'), + title1 = $('
').appendTo(accordion), content1 = $('
').appendTo(accordion), title2 = $('
').appendTo(accordion), content2 = $('
').appendTo(accordion); - $('
').appendTo(accordion); - accordion.appendTo('body'); accordion.accordion({ @@ -63,17 +62,18 @@ define([ }); expect(accordion.is(':mage-accordion')).toBeTruthy(); - expect(content1.is(':visible')).toBeTruthy(); expect(content2.is(':hidden')).toBeTruthy(); - title2.trigger('click'); + $(title1).trigger('click'); + expect(content1.is(':visible')).toBeTruthy(); + expect(content2.is(':hidden')).toBeTruthy(); + $(title2).trigger('click'); expect(content1.is(':visible')).toBeTruthy(); expect(content2.is(':visible')).toBeTruthy(); accordion.accordion('destroy'); - expect(accordion.is(':mage-accordion')).toBeFalsy(); }); }); From 8595da68070577bea09a342f68711f90e059fe6a Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko Date: Wed, 22 Nov 2017 21:02:10 +0200 Subject: [PATCH 020/210] Fix decorate.test.js --- dev/tests/js/jasmine/tests/lib/mage/decorate.test.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dev/tests/js/jasmine/tests/lib/mage/decorate.test.js b/dev/tests/js/jasmine/tests/lib/mage/decorate.test.js index 9b488c417674d..898bcf8b51128 100644 --- a/dev/tests/js/jasmine/tests/lib/mage/decorate.test.js +++ b/dev/tests/js/jasmine/tests/lib/mage/decorate.test.js @@ -192,10 +192,9 @@ define([ it('Check error message', function () { var $list = $('#' + listId); - spyOn(jQuery, 'error'); + spyOn($, 'error'); $list.decorate('customMethod'); - - expect(jQuery.error).toHaveBeenCalledWith('Method customMethod does not exist on jQuery.decorate'); + expect($.error).toHaveBeenCalledWith('Method customMethod does not exist on jQuery.decorate'); }); }); }); From 2adf9e8634b4336002d2bcc39e22ffe0387239d4 Mon Sep 17 00:00:00 2001 From: Carlos Lizaga Date: Thu, 23 Nov 2017 17:19:58 +0100 Subject: [PATCH 021/210] Fixed unsafe comparison with a literal. No need to eslint eqeqeq. Fixed enable method. It was not enabling and activating the collapsible. This was detected on Jasmine unit testing. Minor repositioning to this.options.disabled on disable method for consistency purposes with enable method. --- lib/web/mage/collapsible.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/web/mage/collapsible.js b/lib/web/mage/collapsible.js index 0d8cf836c198e..49624fbeb159a 100644 --- a/lib/web/mage/collapsible.js +++ b/lib/web/mage/collapsible.js @@ -243,7 +243,7 @@ define([ }); // For collapsible widget only (not tabs or accordion) - if (this.header.parent().attr('role') != 'presentation') { //eslint-disable-line eqeqeq + if (this.header.parent().attr('role') !== 'presentation') { this.header .parent() .attr('role', 'tablist'); @@ -316,9 +316,9 @@ define([ * Disable. */ disable: function () { + this.options.disabled = true; this._off(this.trigger); this.forceDeactivate(); - this.options.disabled = true; if (this.options.disabledState) { this.element.addClass(this.options.disabledState); @@ -330,12 +330,14 @@ define([ * Enable. */ enable: function () { - this._on(this.trigger, this.events); this.options.disabled = false; + this._on(this.trigger, this.events); + this.forceActivate(); if (this.options.disabledState) { this.element.removeClass(this.options.disabledState); } + this.trigger.attr('tabIndex', 0); }, /** From 9b28fe25ec7da23e5c1e75499e2984e3019289f2 Mon Sep 17 00:00:00 2001 From: Carlos Lizaga Date: Thu, 23 Nov 2017 18:13:38 +0100 Subject: [PATCH 022/210] that - this consistency and splat complete function to be Jasmine friendly. --- lib/web/mage/collapsible.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/web/mage/collapsible.js b/lib/web/mage/collapsible.js index 49624fbeb159a..267734605f141 100644 --- a/lib/web/mage/collapsible.js +++ b/lib/web/mage/collapsible.js @@ -519,7 +519,7 @@ define([ that = this; if (url) { - this.xhr = $.get({ + that.xhr = $.get({ url: url, dataType: 'html' }, function () { @@ -535,7 +535,8 @@ define([ setTimeout(function () { that.content.html(response); }, 1); - }).complete(function (jqXHR, status) { + }); + that.xhr.complete(function (jqXHR, status) { setTimeout(function () { if (status === 'abort') { that.content.stop(false, true); From 4127a8c6bc8b0a7fd4e071ea4f2ea42ee92d5622 Mon Sep 17 00:00:00 2001 From: Carlos Lizaga Date: Thu, 23 Nov 2017 18:14:49 +0100 Subject: [PATCH 023/210] Added collapsible.test.js and removed JsTestDriver equivalent. --- .../testsuite/mage/collapsible/content.html | 14 - .../testsuite/mage/collapsible/index.html | 31 --- .../mage/collapsible/test-collapsible.js | 180 ------------- .../tests/lib/mage/collapsible.test.js | 247 ++++++++++++++++++ 4 files changed, 247 insertions(+), 225 deletions(-) delete mode 100644 dev/tests/js/JsTestDriver/testsuite/mage/collapsible/content.html delete mode 100644 dev/tests/js/JsTestDriver/testsuite/mage/collapsible/index.html delete mode 100644 dev/tests/js/JsTestDriver/testsuite/mage/collapsible/test-collapsible.js create mode 100644 dev/tests/js/jasmine/tests/lib/mage/collapsible.test.js diff --git a/dev/tests/js/JsTestDriver/testsuite/mage/collapsible/content.html b/dev/tests/js/JsTestDriver/testsuite/mage/collapsible/content.html deleted file mode 100644 index e81938dfbeaba..0000000000000 --- a/dev/tests/js/JsTestDriver/testsuite/mage/collapsible/content.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - -

Test text

- - diff --git a/dev/tests/js/JsTestDriver/testsuite/mage/collapsible/index.html b/dev/tests/js/JsTestDriver/testsuite/mage/collapsible/index.html deleted file mode 100644 index ccfd4d97f0331..0000000000000 --- a/dev/tests/js/JsTestDriver/testsuite/mage/collapsible/index.html +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - Unit test - - - - - - - - - - - -
-
-
- - - diff --git a/dev/tests/js/JsTestDriver/testsuite/mage/collapsible/test-collapsible.js b/dev/tests/js/JsTestDriver/testsuite/mage/collapsible/test-collapsible.js deleted file mode 100644 index 1a22e5a79eb1d..0000000000000 --- a/dev/tests/js/JsTestDriver/testsuite/mage/collapsible/test-collapsible.js +++ /dev/null @@ -1,180 +0,0 @@ -/** - * @category mage.collapsible - * @package test - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -/* - Test if the collapsible widget gets initialized when is called and destroy function works - */ -test('initialization & destroy', function() { - expect(2); - var group = $('
'); - group.collapsible(); - ok( group.is(':mage-collapsible'), "widget instantiated" ); - group.collapsible('destroy'); - ok( !group.is(':mage-collapsible'), "widget destroyed" ); -}); - -/* - Test enable, disable, activate, deactivate functions - */ -test('Enable, disable, activate, deactivate methods', function() { - expect(5); - var group = $('
'); - var title = $('
'); - var content = $('
'); - title.appendTo(group); - content.appendTo(group); - group.appendTo("body"); - group.collapsible(); - group.collapsible("deactivate"); - ok(content.is(':hidden'), "Content is collapsed"); - group.collapsible("activate"); - ok(content.is(':visible'), "Content is expanded"); - group.collapsible("disable"); - ok(content.is(':hidden'), "Content is collapsed"); - group.collapsible("activate"); - ok(content.is(':hidden'), "Content is collapsed"); - group.collapsible("enable"); - group.collapsible("activate"); - ok(content.is(':visible'), "Content is expanded"); - group.collapsible('destroy'); -}); - -/* - Test if the widget gets expanded/collapsed when the title is clicked - */ -test('Collapse and expand', function() { - expect(3); - var group = $('
'); - var title = $('
'); - var content = $('
'); - title.appendTo(group); - content.appendTo(group); - group.appendTo("body"); - group.collapsible(); - group.collapsible("deactivate"); - ok(content.is(':hidden'), "Content is collapsed"); - title.trigger("click"); - ok(content.is(':visible'), "Content gets expanded on click title"); - title.trigger("click"); - ok(content.is(':hidden'), "Content gets collapsed on click again"); - group.collapsible('destroy'); -}); - - -/* - Test state Classes - */ -test('State classes', function() { - expect(3); - var group = $('
'); - var title = $('
'); - var content = $('
'); - title.appendTo(group); - content.appendTo(group); - group.collapsible({openedState:"opened", closedState:"closed", disabledState:"disabled"}); - ok( group.hasClass("closed")); - title.trigger("click"); - ok( group.hasClass("opened")); - group.collapsible("disable"); - ok( group.hasClass("disabled")); - group.collapsible('destroy'); -}); - -/* - Test if icons are added to title when widget gets initialized and are removed when gets destroyed - */ -test('Create & destroy icons', function() { - expect(2); - var group = $('
'); - var title = $('
'); - var content = $('
'); - title.appendTo(group); - content.appendTo(group); - group.collapsible({icons: {header:"minus",activeHeader:"plus"}}); - ok(title.children("[data-role=icons]").length, "Icons added to title" ); - group.collapsible('destroy'); - ok(!title.children("[data-role=icons]").length, "Icons removed from title" ); -}); - -/* - Test if icon classes are changed when content gets expanded/collapsed - */ -test('Change icons when content gets expanded/collapsed', function() { - expect(2); - var group = $('
'); - var title = $('
'); - var content = $('
'); - title.appendTo(group); - content.appendTo(group); - group.collapsible({icons: {header:"minus",activeHeader:"plus"}}); - group.collapsible("deactivate"); - var icons = group.collapsible("option","icons"); - ok(title.children("[data-role=icons]").hasClass(icons.header), "When content is collapsed,header has the right class for icons" ); - title.trigger("click"); - ok(title.children("[data-role=icons]").hasClass(icons.activeHeader), "When content is expanded,header has the right class for icons" ); - group.collapsible('destroy'); -}); - - -/* - Test if content gets expanded/collapsed when certain keys are pressed - */ -asyncTest( "keyboard support", function() { - - expect( 5 ); - var group = $('
'); - var title = $('
'); - var content = $('
'); - title.appendTo(group); - content.appendTo(group); - group.appendTo("body"); - group.collapsible(); - group.collapsible("deactivate"); - - title.on("focus",function(ev){ - ok(content.is(':hidden'), "Content is collapsed"); - title.trigger($.Event( 'keydown', { keyCode: $.ui.keyCode.ENTER } )); - ok(content.is(':visible'), "Content is expanded"); - title.trigger($.Event( 'keydown', { keyCode: $.ui.keyCode.ENTER } )); - ok(content.is(':hidden'), "Content is collapsed"); - title.trigger($.Event( 'keydown', { keyCode: $.ui.keyCode.SPACE } )); - ok(content.is(':visible'), "Content is expanded"); - title.trigger($.Event( 'keydown', { keyCode: $.ui.keyCode.SPACE } )); - ok(content.is(':hidden'), "Content is collapsed"); - group.collapsible('destroy'); - start(); - } ); - - setTimeout(function(){ - title.focus(); - },10); - -}); - -/* - Test if content gets updated via Ajax when title is clicked - */ -test('Update content via ajax', function() { - expect(2); - var group = $('
'); - var title = $('
'); - var content = $('
'); - var ajax = $(''); - title.appendTo(group); - content.appendTo(group); - ajax.appendTo(content); - group.appendTo("body"); - group.collapsible({ajaxContent : true}); - group.collapsible("deactivate"); - ok(!content.children("p").length, "Content has no data"); - title.trigger("click"); - ok(content.children("p"), "Content gets data from content.html"); - group.collapsible('destroy'); -}); - - - diff --git a/dev/tests/js/jasmine/tests/lib/mage/collapsible.test.js b/dev/tests/js/jasmine/tests/lib/mage/collapsible.test.js new file mode 100644 index 0000000000000..8bb8cd1cafe78 --- /dev/null +++ b/dev/tests/js/jasmine/tests/lib/mage/collapsible.test.js @@ -0,0 +1,247 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +/* eslint-disable max-nested-callbacks */ + +define([ + 'jquery', + 'jquery/ui', + 'mage/collapsible' +], function ($) { + 'use strict'; + + describe('Test for mage/collapsible jQuery plugin', function () { + it('check if collapsible can be initialized and destroyed', function () { + var group = $('
'); + + group.collapsible(); + expect(group.is(':mage-collapsible')).toBeTruthy(); + + group.collapsible('destroy'); + expect(group.is(':mage-collapsible')).toBeFalsy(); + }); + + describe('Test enable, disable, activate and deactivate methods', function () { + var group = $('
'), + content = $('
').appendTo(group); + + $('
').prependTo(group); + + beforeEach(function () { + group.appendTo('body'); + }); + + afterEach(function () { + group.remove(); + }); + + it('check enable and disable methods', function () { + group.collapsible(); + expect(group.is(':mage-collapsible')).toBeTruthy(); + + group.collapsible('disable'); + expect(content.is(':hidden')).toBeTruthy(); + + group.collapsible('enable'); + expect(content.is(':visible')).toBeTruthy(); + + group.collapsible('destroy'); + expect(group.is(':mage-collapsible')).toBeFalsy(); + }); + + it('check activate and deactivate methods', function () { + group.collapsible(); + expect(group.is(':mage-collapsible')).toBeTruthy(); + + group.collapsible('deactivate'); + expect(content.is(':hidden')).toBeTruthy(); + + group.collapsible('activate'); + expect(content.is(':visible')).toBeTruthy(); + + group.collapsible('destroy'); + expect(group.is(':mage-collapsible')).toBeFalsy(); + }); + }); + + it('check if the widget gets expanded/collapsed when the title is clicked', function () { + var group = $('
'), + title = $('
').appendTo(group), + content = $('
').appendTo(group); + + group.appendTo('body'); + + group.collapsible(); + expect(group.is(':mage-collapsible')).toBeTruthy(); + + group.collapsible('deactivate'); + expect(content.is(':hidden')).toBeTruthy(); + + title.trigger('click'); + expect(content.is(':visible')).toBeTruthy(); + + title.trigger('click'); + expect(content.is(':hidden')).toBeTruthy(); + + group.collapsible('destroy'); + expect(group.is(':mage-collapsible')).toBeFalsy(); + }); + + it('check state classes', function () { + var group = $('
'), + title = $('
').appendTo(group); + + $('
').appendTo(group); + + group.appendTo('body'); + + group.collapsible({ + openedState: 'opened', + closedState: 'closed', + disabledState: 'disabled' + }); + expect(group.is(':mage-collapsible')).toBeTruthy(); + expect(group.hasClass('closed')).toBeTruthy(); + + title.trigger('click'); + expect(group.hasClass('opened')).toBeTruthy(); + + group.collapsible('disable'); + expect(group.hasClass('disabled')).toBeTruthy(); + + group.collapsible('destroy'); + expect(group.is(':mage-collapsible')).toBeFalsy(); + }); + + it('check if icons are added to title when initialized and removed when destroyed', function () { + var group = $('
'), + title = $('
').appendTo(group); + + $('
').appendTo(group); + + group.appendTo('body'); + + group.collapsible({ + icons: { + header: 'minus', + activeHeader: 'plus' + } + }); + expect(group.is(':mage-collapsible')).toBeTruthy(); + expect(title.children('[data-role=icons]').length).toBeTruthy(); + + group.collapsible('destroy'); + expect(group.is(':mage-collapsible')).toBeFalsy(); + expect(title.children('[data-role=icons]').length).toBeFalsy(); + }); + + it('check if icon classes are changed when content gets expanded/collapsed', function () { + var group = $('
'), + title = $('
').appendTo(group), + content = $('
').appendTo(group), + icons; + + group.appendTo('body'); + + group.collapsible({ + icons: { + header: 'minus', + activeHeader: 'plus' + } + }); + expect(group.is(':mage-collapsible')).toBeTruthy(); + + icons = group.collapsible('option', 'icons'); + group.collapsible('deactivate'); + expect(content.is(':hidden')).toBeTruthy(); + expect(title.children('[data-role=icons]').hasClass(icons.header)).toBeTruthy(); + + title.trigger('click'); + expect(title.children('[data-role=icons]').hasClass(icons.activeHeader)).toBeTruthy(); + + group.collapsible('destroy'); + expect(group.is(':mage-collapsible')).toBeFalsy(); + }); + + it('check keyboard support', function () { + var group = $('
'), + title = $('
').appendTo(group), + content = $('
').appendTo(group); + + group.appendTo('body'); + + group.collapsible(); + expect(group.is(':mage-collapsible')).toBeTruthy(); + + group.collapsible('deactivate'); + expect(content.is(':hidden')).toBeTruthy(); + + title.on('focus', function () { + title.trigger($.Event('keydown', { + keyCode: $.ui.keyCode.ENTER + })); + expect(content.is(':visible')).toBeTruthy(); + + title.trigger($.Event('keydown', { + keyCode: $.ui.keyCode.ENTER + })); + expect(content.is(':hidden')).toBeTruthy(); + + title.trigger($.Event('keydown', { + keyCode: $.ui.keyCode.SPACE + })); + expect(content.is(':visible')).toBeTruthy(); + + title.trigger($.Event('keydown', { + keyCode: $.ui.keyCode.SPACE + })); + expect(content.is(':hidden')).toBeTruthy(); + }); + + setTimeout(function () { + title.focus(); + }, 10); + + group.collapsible('destroy'); + expect(group.is(':mage-collapsible')).toBeFalsy(); + }); + + it('check if content gets updated via Ajax when title is clicked', function () { + var group = $('
'), + title = $('
').appendTo(group), + content = $('
').appendTo(group); + + $('').appendTo(group); + + $.get = jasmine.createSpy().and.callFake(function () { + var d = $.Deferred(); + + d.promise().success = function () { + }; + + d.promise().complete = function () { + }; + + return d.promise(); + }); + + group.appendTo('body'); + + group.collapsible({ + ajaxContent: true + }); + expect(group.is(':mage-collapsible')).toBeTruthy(); + + group.collapsible('deactivate'); + expect(content.is(':hidden')).toBeTruthy(); + expect(content.children('p').length).toBeFalsy(); + + title.trigger('click'); + expect(content.children('p')).toBeTruthy(); + + group.collapsible('destroy'); + expect(group.is(':mage-collapsible')).toBeFalsy(); + }); + }); +}); From 6366f83500d2a3645d0bc0577201fc655c952abd Mon Sep 17 00:00:00 2001 From: Carlos Lizaga Date: Thu, 23 Nov 2017 20:49:36 +0100 Subject: [PATCH 024/210] jscs:disable jsDoc --- dev/tests/js/jasmine/tests/lib/mage/collapsible.test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/tests/js/jasmine/tests/lib/mage/collapsible.test.js b/dev/tests/js/jasmine/tests/lib/mage/collapsible.test.js index 8bb8cd1cafe78..fb1518442c87d 100644 --- a/dev/tests/js/jasmine/tests/lib/mage/collapsible.test.js +++ b/dev/tests/js/jasmine/tests/lib/mage/collapsible.test.js @@ -3,6 +3,7 @@ * See COPYING.txt for license details. */ /* eslint-disable max-nested-callbacks */ +/* jscs:disable jsDoc */ define([ 'jquery', From c98720f551534b53f2e8f7b475aaac0473a43750 Mon Sep 17 00:00:00 2001 From: Carlos Lizaga Date: Fri, 24 Nov 2017 15:12:05 +0100 Subject: [PATCH 025/210] Added dropdown.test.js and removed JsTestDriver equivalent. --- .../testsuite/mage/dropdown/index.html | 30 -- .../testsuite/mage/dropdown/test-dropdown.js | 270 -------------- .../jasmine/tests/lib/mage/dropdown.test.js | 351 ++++++++++++++++++ 3 files changed, 351 insertions(+), 300 deletions(-) delete mode 100644 dev/tests/js/JsTestDriver/testsuite/mage/dropdown/index.html delete mode 100644 dev/tests/js/JsTestDriver/testsuite/mage/dropdown/test-dropdown.js create mode 100644 dev/tests/js/jasmine/tests/lib/mage/dropdown.test.js diff --git a/dev/tests/js/JsTestDriver/testsuite/mage/dropdown/index.html b/dev/tests/js/JsTestDriver/testsuite/mage/dropdown/index.html deleted file mode 100644 index 3d6ed5a7c1d28..0000000000000 --- a/dev/tests/js/JsTestDriver/testsuite/mage/dropdown/index.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - Unit test - - - - - - - - - - - - -
-
-
- - diff --git a/dev/tests/js/JsTestDriver/testsuite/mage/dropdown/test-dropdown.js b/dev/tests/js/JsTestDriver/testsuite/mage/dropdown/test-dropdown.js deleted file mode 100644 index e67c92b3d4018..0000000000000 --- a/dev/tests/js/JsTestDriver/testsuite/mage/dropdown/test-dropdown.js +++ /dev/null @@ -1,270 +0,0 @@ -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -/* - testing if dialog opens when the triggerEvent is triggered - */ -test( "triggerEvent", function() { - expect(2); - var opener = $('
'); - var dialog = $('
'); - dialog.dropdownDialog({"triggerEvent":"click", "triggerTarget":opener}); - opener.trigger("click"); - equal(dialog.dropdownDialog("isOpen"), true, "Dropdown opens when click opener"); - dialog.dropdownDialog( "destroy" ); - - dialog.dropdownDialog({"triggerEvent":null, "triggerTarget":opener}); - opener.trigger("click"); - equal(dialog.dropdownDialog("isOpen"), false, "Dropdown doesn't open when click opener"); - dialog.dropdownDialog( "destroy" ); - -}); - -/* - testing if a specified class is added to the trigger - */ -test( "triggerClass", function() { - expect(2); - var opener = $('
'); - var dialog = $('
'); - dialog.dropdownDialog({"triggerTarget":opener,"triggerClass":"active"}); - dialog.dropdownDialog("open"); - ok( opener.hasClass("active"), "Class added to opener when dialog opens" ); - dialog.dropdownDialog("close"); - dialog.dropdownDialog( "destroy" ); - - dialog.dropdownDialog({"triggerEvent":opener, "triggerClass":null}); - dialog.dropdownDialog("open"); - ok( !opener.hasClass("active"), "Class added to opener when dialog opens" ); - dialog.dropdownDialog("close"); - dialog.dropdownDialog( "destroy" ); - -}); - -/* - testing if a specified class is added to the element which the dialog appends to - */ -test( "parentClass", function() { - expect(2); - var parent = $('
'); - var dialog = $('
'); - - dialog.dropdownDialog({"parentClass":"active","appendTo":parent}); - dialog.dropdownDialog("open"); - ok( parent.hasClass("active"), "Class is added to parent when dialog opens" ); - dialog.dropdownDialog("close"); - dialog.dropdownDialog( "destroy" ); - - dialog.dropdownDialog({"parentClass":null,"appendTo":parent}); - dialog.dropdownDialog("open"); - ok( !parent.hasClass("active"), "No class is added to parent when dialog opens" ); - dialog.dropdownDialog("close"); - dialog.dropdownDialog( "destroy" ); - -}); - -/* - testing if a specified class is added to the element that becomes dialog - */ -test( "dialogContentClass", function() { - expect(2); - var dialog = $('
'); - - dialog.dropdownDialog({"dialogContentClass":"active"}); - dialog.dropdownDialog("open"); - ok( $('.ui-dialog-content').hasClass("active"), "Class is added to dialog content when dialog opens" ); - dialog.dropdownDialog("close"); - dialog.dropdownDialog( "destroy" ); - - dialog.dropdownDialog({"dialogContentClass": null}); - dialog.dropdownDialog("open"); - ok( !$('.ui-dialog-content').hasClass("active"), "No class is added to dialog content" ); - dialog.dropdownDialog("close"); - dialog.dropdownDialog( "destroy" ); -}); - -/* - testing if a specified class is added to dialog - */ -test( "defaultDialogClass", function() { - expect(3); - var dialog = $('
'); - - dialog.dropdownDialog({"defaultDialogClass":"custom"}); - ok( $('.ui-dialog').hasClass("custom"), "Class is added to dialog" ); - ok( !$('.ui-dialog').hasClass("mage-dropdown-dialog"), "Default class has been overwritten" ); - dialog.dropdownDialog( "destroy" ); - - dialog.dropdownDialog({}); - ok( $('.ui-dialog').hasClass("mage-dropdown-dialog"), "Default class hasn't been overwritten" ); - dialog.dropdownDialog( "destroy" ); -}); - -/* - testing if the specified trigger actually opens the dialog - */ -test( "triggerTarget", function() { - expect(2); - var opener = $('
'); - var dialog = $('
'); - - dialog.dropdownDialog({"triggerTarget":opener}); - opener.trigger("click"); - equal(dialog.dropdownDialog("isOpen"), true, "Dropdown opens when click opener"); - dialog.dropdownDialog("close"); - dialog.dropdownDialog( "destroy" ); - - dialog.dropdownDialog({"triggerTarget":null}); - opener.trigger("click"); - equal(dialog.dropdownDialog("isOpen"), false, "Dropdown doesn't open when click opener"); - dialog.dropdownDialog( "destroy" ); -}); - -/* - testing if the dialog gets closed when clicking outside of it - */ -test( "closeOnClickOutside", function() { - expect(2); - var outside = $('
').attr({"id":"outside"}); - var dialog = $('
').attr({"id":"dialog"}); - outside.appendTo("#qunit-fixture"); - dialog.appendTo("#qunit-fixture"); - - dialog.dropdownDialog({"closeOnClickOutside":true}); - dialog.dropdownDialog("open"); - outside.trigger("click"); - equal(dialog.dropdownDialog("isOpen"), false, "Dropdown closes when click outside dropdown"); - dialog.dropdownDialog( "destroy" ); - - dialog.dropdownDialog({"closeOnClickOutside":false}); - dialog.dropdownDialog("open"); - outside.trigger("click"); - equal(dialog.dropdownDialog("isOpen"), true, "Dropdown doesn't close when click outside dropdown"); - dialog.dropdownDialog( "destroy" ); -}); - -/* - testing if the dialog gets closed when mouse leaves the dialog area - */ -asyncTest( "closeOnMouseLeave true", function() { - expect(1); - var outside = $('
').attr({"id":"outside"}); - var dialog = $('
').attr({"id":"dialog"}); - var opener = $('
').attr({"id":"opener"}); - outside.appendTo("#qunit-fixture"); - dialog.appendTo("#qunit-fixture"); - opener.appendTo("#qunit-fixture"); - - dialog.dropdownDialog({"closeOnMouseLeave":true}); - dialog.dropdownDialog("open"); - dialog.trigger("mouseenter"); - dialog.trigger("mouseleave"); - - setTimeout(function() { - equal(dialog.dropdownDialog("isOpen"), false, "Dropdown closes when mouseleave the dropdown area"); - dialog.dropdownDialog( "destroy" ); - start(); - }, 3000); - -}); - -/* - testing if the dialog gets closed when mouse leaves the dialog area - */ -asyncTest( "closeOnMouseLeave false", function() { - expect(1); - var outside = $('
').attr({"id":"outside"}); - var dialog = $('
').attr({"id":"dialog"}); - var opener = $('
').attr({"id":"opener"}); - outside.appendTo("#qunit-fixture"); - dialog.appendTo("#qunit-fixture"); - opener.appendTo("#qunit-fixture"); - - dialog.dropdownDialog({"closeOnMouseLeave":false}); - dialog.dropdownDialog("open"); - dialog.trigger("mouseenter"); - dialog.trigger("mouseleave"); - - setTimeout(function() { - equal(dialog.dropdownDialog("isOpen"), true, "Dropdown doesn't close when mouseleave the dropdown area"); - dialog.dropdownDialog( "destroy" ); - start(); - }, 3000); - -}); - -/* - testing if the dialog gets closed with the specified delay - */ -asyncTest( "timeout", function() { - expect(2); - var outside = $('
').attr({"id":"outside"}); - var dialog = $('
').attr({"id":"dialog"}); - var opener = $('
').attr({"id":"opener"}); - outside.appendTo("#qunit-fixture"); - dialog.appendTo("#qunit-fixture"); - opener.appendTo("#qunit-fixture"); - - dialog.dropdownDialog({"timeout":2000}); - dialog.dropdownDialog("open"); - dialog.trigger("mouseenter"); - dialog.trigger("mouseleave"); - equal(dialog.dropdownDialog("isOpen"), true, "Dropdown doesn't close when mouseleave the dropdown area"); - setTimeout(function() { - equal(dialog.dropdownDialog("isOpen"), false, "Dropdown closes when mouseleave the dropdown area, after timeout passed"); - dialog.dropdownDialog( "destroy" ); - start(); - }, 3000); - -}); - -/* - testing if the title bar is prevented from being created - */ -test( "createTitileBar", function() { - expect(2); - var dialog = $('
'); - dialog.dropdownDialog({"createTitleBar":true}); - ok(($(".ui-dialog").find(".ui-dialog-titlebar").length > 0), "Title bar is created"); - dialog.dropdownDialog( "destroy" ); - - dialog.dropdownDialog({"createTitleBar":false}); - ok($(".ui-dialog").find(".ui-dialog-titlebar").length <= 0, "Title bar isn't created"); - dialog.dropdownDialog( "destroy" ); -}); - -/* - testing if the position function gets disabled - */ -test( "autoPosition", function() { - expect(2); - var dialog = $('
'); - dialog.dropdownDialog({"autoPosition":false}); - dialog.dropdownDialog("open"); - ok(($(".ui-dialog").css("top") === 'auto'), "_position function disabled"); - dialog.dropdownDialog( "destroy" ); - - dialog.dropdownDialog({"autoPosition":true}); - dialog.dropdownDialog("open"); - ok(($(".ui-dialog").css("top") !== '0px'), "_position function enabled"); - dialog.dropdownDialog( "destroy" ); -}); - -/* - testing if the size function gets disabled - */ -test( "autoSize", function() { - expect(2); - var dialog = $('
'); - dialog.dropdownDialog({"autoSize":true, width:"300"}); - dialog.dropdownDialog("open"); - ok(($(".ui-dialog").css("width") === '300px'), "_size function enabled"); - dialog.dropdownDialog( "destroy" ); - - dialog.dropdownDialog({"autoSize":false, width:"300"}); - dialog.dropdownDialog("open"); - ok($(".ui-dialog").css("width") !== '300px', "_size function disabled"); - dialog.dropdownDialog( "destroy" ); -}); diff --git a/dev/tests/js/jasmine/tests/lib/mage/dropdown.test.js b/dev/tests/js/jasmine/tests/lib/mage/dropdown.test.js new file mode 100644 index 0000000000000..70e608d5bfefd --- /dev/null +++ b/dev/tests/js/jasmine/tests/lib/mage/dropdown.test.js @@ -0,0 +1,351 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +/* eslint-disable max-nested-callbacks */ + +define([ + 'jquery', + 'mage/dropdown' +], function ($) { + 'use strict'; + + describe('Test for mage/dropdown jQuery plugin', function () { + it('check if dialog opens when the triggerEvent is triggered', function () { + var opener = $('
'), + dialog = $('
'); + + dialog.dropdownDialog({ + 'triggerEvent': 'click', + 'triggerTarget': opener + }); + + opener.trigger('click'); + expect(dialog.dropdownDialog('isOpen')).toBeTruthy(); + + dialog.dropdownDialog('destroy'); + + dialog.dropdownDialog({ + 'triggerEvent': null, + 'triggerTarget': opener + }); + + opener.trigger('click'); + expect(dialog.dropdownDialog('isOpen')).toBeFalsy(); + dialog.dropdownDialog('destroy'); + }); + + it('check if a specified class is added to the trigger', function () { + var opener = $('
'), + dialog = $('
'); + + dialog.dropdownDialog({ + 'triggerClass': 'active', + 'triggerTarget': opener + }); + + dialog.dropdownDialog('open'); + expect(opener.hasClass('active')).toBeTruthy(); + + dialog.dropdownDialog('close'); + dialog.dropdownDialog('destroy'); + + dialog.dropdownDialog({ + 'triggerClass': null, + 'triggerTarget': opener + }); + + dialog.dropdownDialog('open'); + expect(opener.hasClass('active')).toBeFalsy(); + + dialog.dropdownDialog('close'); + dialog.dropdownDialog('destroy'); + }); + + it('check if a specified class is added to the element which the dialog appends to', function () { + var parent = $('
'), + dialog = $('
'); + + dialog.dropdownDialog({ + 'parentClass': 'active', + 'appendTo': parent + }); + + dialog.dropdownDialog('open'); + expect(parent.hasClass('active')).toBeTruthy(); + + dialog.dropdownDialog('close'); + dialog.dropdownDialog('destroy'); + + dialog.dropdownDialog({ + 'parentClass': null, + 'appendTo': parent + }); + + dialog.dropdownDialog('open'); + expect(parent.hasClass('active')).toBeFalsy(); + + dialog.dropdownDialog('close'); + dialog.dropdownDialog('destroy'); + }); + + it('check if a specified class is added to the element that becomes dialog', function () { + var dialog = $('
'), + content; + + dialog.dropdownDialog({ + 'dialogContentClass': 'active' + }); + + content = $('.ui-dialog-content'); + dialog.dropdownDialog('open'); + expect(content.hasClass('active')).toBeTruthy(); + + dialog.dropdownDialog('close'); + dialog.dropdownDialog('destroy'); + + dialog.dropdownDialog({ + 'dialogContentClass': null + }); + + dialog.dropdownDialog('open'); + expect(content.hasClass('active')).toBeFalsy(); + + dialog.dropdownDialog('close'); + dialog.dropdownDialog('destroy'); + }); + + it('check if a specified class is added to dialog', function () { + var dialog = $('
'), + uiClass = '.ui-dialog', + ui; + + dialog.dropdownDialog({ + 'defaultDialogClass': 'custom' + }); + + ui = $(uiClass); + expect(ui.hasClass('custom')).toBeTruthy(); + expect(ui.hasClass('mage-dropdown-dialog')).toBeFalsy(); + + dialog.dropdownDialog('destroy'); + + dialog.dropdownDialog({}); + ui = $(uiClass); + expect(ui.hasClass('mage-dropdown-dialog')).toBeTruthy(); + + dialog.dropdownDialog('destroy'); + }); + + it('check if the specified trigger actually opens the dialog', function () { + var opener = $('
'), + dialog = $('
'); + + dialog.dropdownDialog({ + 'triggerTarget': opener + }); + + opener.trigger('click'); + expect(dialog.dropdownDialog('isOpen')).toBeTruthy(); + + dialog.dropdownDialog('close'); + dialog.dropdownDialog('destroy'); + + dialog.dropdownDialog({ + 'triggerTarget': null + }); + + opener.trigger('click'); + expect(dialog.dropdownDialog('isOpen')).toBeFalsy(); + + dialog.dropdownDialog('destroy'); + }); + + it('check if the dialog gets closed when clicking outside of it', function () { + var container = $('
'), + outside = $('
').attr('id', 'outside').appendTo(container), + dialog = $('
').attr('id', 'dialog').appendTo(container); + + container.appendTo('body'); + + dialog.dropdownDialog({ + 'closeOnClickOutside': true + }); + + dialog.dropdownDialog('open'); + outside.trigger('click'); + expect(dialog.dropdownDialog('isOpen')).toBeFalsy(); + + dialog.dropdownDialog('destroy'); + + dialog.dropdownDialog({ + 'closeOnClickOutside': false + }); + + dialog.dropdownDialog('open'); + outside.trigger('click'); + expect(dialog.dropdownDialog('isOpen')).toBeTruthy(); + + dialog.dropdownDialog('destroy'); + }); + + it('check if the dialog gets closed when mouse leaves the dialog area', function () { + var container = $('
'), + dialog = $('
').attr('id', 'dialog').appendTo(container); + + $('
').attr('id', 'outside').appendTo(container); + $('
').attr('id', 'opener').appendTo(container); + + container.appendTo('body'); + + jasmine.clock().install(); + + dialog.dropdownDialog({ + 'closeOnMouseLeave': true + }); + + dialog.dropdownDialog('open'); + dialog.trigger('mouseenter'); + expect(dialog.dropdownDialog('isOpen')).toBeTruthy(); + + dialog.trigger('mouseleave'); + + jasmine.clock().tick(10); + + expect(dialog.dropdownDialog('isOpen')).toBeFalsy(); + dialog.dropdownDialog('destroy'); + + jasmine.clock().uninstall(); + }); + + it('check if the dialog does not close when mouse leaves the dialog area', function () { + var container = $('
'), + dialog = $('
').attr('id', 'dialog').appendTo(container); + + $('
').attr('id', 'outside').appendTo(container); + $('
').attr('id', 'opener').appendTo(container); + + container.appendTo('body'); + + jasmine.clock().install(); + + dialog.dropdownDialog({ + 'closeOnMouseLeave': false + }); + + dialog.dropdownDialog('open'); + dialog.trigger('mouseenter'); + dialog.trigger('mouseleave'); + jasmine.clock().tick(10); + expect(dialog.dropdownDialog('isOpen')).toBeTruthy(); + dialog.dropdownDialog('destroy'); + + jasmine.clock().uninstall(); + }); + + it('check if the dialog gets closed with the specified delay', function () { + var container = $('
'), + dialog = $('
').attr('id', 'dialog').appendTo(container); + + $('
').attr('id', 'outside').appendTo(container); + $('
').attr('id', 'opener').appendTo(container); + + container.appendTo('body'); + + jasmine.clock().install(); + + dialog.dropdownDialog({ + 'timeout': 5 + }); + + dialog.dropdownDialog('open'); + dialog.trigger('mouseenter'); + dialog.trigger('mouseleave'); + expect(dialog.dropdownDialog('isOpen')).toBeTruthy(); + + jasmine.clock().tick(10); + expect(dialog.dropdownDialog('isOpen')).toBeFalsy(); + dialog.dropdownDialog('destroy'); + + jasmine.clock().uninstall(); + }); + + it('check if the title bar is prevented from being created', function () { + var dialog = $('
'), + uiClass = '.ui-dialog', + ui; + + dialog.dropdownDialog({ + 'createTitleBar': true + }); + + ui = $(uiClass); + expect(ui.find('.ui-dialog-titlebar').length > 0).toBeTruthy(); + + dialog.dropdownDialog('destroy'); + + dialog.dropdownDialog({ + 'createTitleBar': false + }); + + ui = $(uiClass); + expect(ui.find('.ui-dialog-titlebar').length <= 0).toBeTruthy(); + + dialog.dropdownDialog('destroy'); + }); + + it('check if the position function gets disabled', function () { + var dialog = $('
'), + uiClass = '.ui-dialog', + ui; + + dialog.dropdownDialog({ + 'autoPosition': false + }); + + ui = $(uiClass); + dialog.dropdownDialog('open'); + expect(ui.css('top') === 'auto').toBeTruthy(); + + dialog.dropdownDialog('destroy'); + + dialog.dropdownDialog({ + 'autoPosition': true + }); + + ui = $(uiClass); + dialog.dropdownDialog('open'); + expect(ui.css('top') !== '0px').toBeTruthy(); + + dialog.dropdownDialog('destroy'); + }); + + it('check if the size function gets disabled', function () { + var dialog = $('
'), + uiClass = '.ui-dialog', + ui; + + dialog.dropdownDialog({ + 'autoSize': true, + 'width': '300' + }); + + ui = $(uiClass); + dialog.dropdownDialog('open'); + expect(ui.css('width') === '300px').toBeTruthy(); + + dialog.dropdownDialog('destroy'); + + dialog.dropdownDialog({ + 'autoSize': false, + 'width': '300' + }); + + ui = $(uiClass); + dialog.dropdownDialog('open'); + expect(ui.css('width') === '300px').toBeFalsy(); + + dialog.dropdownDialog('destroy'); + }); + }); +}); From de225a907f56477b767eae81134154e0398a3bf0 Mon Sep 17 00:00:00 2001 From: Carlos Lizaga Date: Fri, 24 Nov 2017 17:24:15 +0100 Subject: [PATCH 026/210] Backend jquery-ui version has a diferent behavior on create that will add ui-dialog-titlebar anyway. This test is only valid with frontend's version @TODO: Re-design Jasmine settings to match a selective architecture for testing in order to split them. --- .../jasmine/tests/lib/mage/dropdown.test.js | 39 +++++++++++-------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/dev/tests/js/jasmine/tests/lib/mage/dropdown.test.js b/dev/tests/js/jasmine/tests/lib/mage/dropdown.test.js index 70e608d5bfefd..1034ad263d9fe 100644 --- a/dev/tests/js/jasmine/tests/lib/mage/dropdown.test.js +++ b/dev/tests/js/jasmine/tests/lib/mage/dropdown.test.js @@ -270,29 +270,34 @@ define([ jasmine.clock().uninstall(); }); - it('check if the title bar is prevented from being created', function () { - var dialog = $('
'), - uiClass = '.ui-dialog', - ui; + // Backend jquery-ui version has a diferent behavior on create that will add ui-dialog-titlebar anyway. + // This test is only valid with frontend's version + // @TODO: Re-design Jasmine settings to match a selective architecture for testing in order to split them. + if ($.ui.version !== '1.9.2') { + it('check if the title bar is prevented from being created', function () { + var dialog = $('
'), + uiClass = '.ui-dialog', + ui; - dialog.dropdownDialog({ - 'createTitleBar': true - }); + dialog.dropdownDialog({ + 'createTitleBar': true + }); - ui = $(uiClass); - expect(ui.find('.ui-dialog-titlebar').length > 0).toBeTruthy(); + ui = $(uiClass); + expect(ui.find('.ui-dialog-titlebar').length > 0).toBeTruthy(); - dialog.dropdownDialog('destroy'); + dialog.dropdownDialog('destroy'); - dialog.dropdownDialog({ - 'createTitleBar': false - }); + dialog.dropdownDialog({ + 'createTitleBar': false + }); - ui = $(uiClass); - expect(ui.find('.ui-dialog-titlebar').length <= 0).toBeTruthy(); + ui = $(uiClass); + expect(ui.find('.ui-dialog-titlebar').length <= 0).toBeTruthy(); - dialog.dropdownDialog('destroy'); - }); + dialog.dropdownDialog('destroy'); + }); + } it('check if the position function gets disabled', function () { var dialog = $('
'), From 9f148224e7540d089e1d38a1d22be725ca5cfb27 Mon Sep 17 00:00:00 2001 From: Carlos Lizaga Date: Fri, 1 Dec 2017 17:24:28 +0100 Subject: [PATCH 027/210] Added form.test.js and removed JsTestDriver equivalent. Modified if documentation to be more friendly with developers. --- .../testsuite/mage/form/form-test.js | 241 ---------------- .../jasmine/tests/lib/mage/dropdown.test.js | 9 +- .../js/jasmine/tests/lib/mage/form.test.js | 262 ++++++++++++++++++ 3 files changed, 268 insertions(+), 244 deletions(-) delete mode 100644 dev/tests/js/JsTestDriver/testsuite/mage/form/form-test.js create mode 100644 dev/tests/js/jasmine/tests/lib/mage/form.test.js diff --git a/dev/tests/js/JsTestDriver/testsuite/mage/form/form-test.js b/dev/tests/js/JsTestDriver/testsuite/mage/form/form-test.js deleted file mode 100644 index 83bdefd399eaf..0000000000000 --- a/dev/tests/js/JsTestDriver/testsuite/mage/form/form-test.js +++ /dev/null @@ -1,241 +0,0 @@ -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -FormTest = TestCase('FormTest'); -FormTest.prototype.setUp = function() { - /*:DOC +=
*/ -}; -FormTest.prototype.tearDown = function() { - var formInstance = jQuery('#form').data('form'); - if(formInstance && formInstance.destroy) { - formInstance.destroy(); - } -}; -FormTest.prototype.testInit = function() { - var form = jQuery('#form').form(); - assertTrue(form.is(':mage-form')); -}; -FormTest.prototype.testRollback = function() { - var form = jQuery('#form').form(), - initialFormAttrs = { - action: form.prop('action'), - target: form.prop('target'), - method: form.prop('method') - }; - - form.data("form").oldAttributes = initialFormAttrs; - form.prop({ - action: 'new/action/url', - target: '_blank', - method: 'POST' - }); - - assertNotEquals(form.prop('action'), initialFormAttrs.action); - assertNotEquals(form.prop('target'), initialFormAttrs.target); - assertNotEquals(form.prop('method'), initialFormAttrs.method); - form.data("form")._rollback(); - assertEquals(form.prop('action'), initialFormAttrs.action); - assertEquals(form.prop('target'), initialFormAttrs.target); - assertEquals(form.prop('method'), initialFormAttrs.method); -}; -FormTest.prototype.testGetHandlers = function() { - var form = jQuery('#form').form(), - handlersData = form.form('option', 'handlersData'), - handlers = []; - $.each(handlersData, function(key) { - handlers.push(key); - }); - assertEquals(handlers.join(' '), form.data("form")._getHandlers().join(' ')); -}; -FormTest.prototype.testStoreAttribute = function() { - var form = jQuery('#form').form(), - initialFormAttrs = { - action: form.attr('action'), - target: form.attr('target'), - method: form.attr('method') - }; - form.data("form")._storeAttribute('action'); - form.data("form")._storeAttribute('target'); - form.data("form")._storeAttribute('method'); - - assertEquals(form.data("form").oldAttributes.action, initialFormAttrs.action); - assertEquals(form.data("form").oldAttributes.target, initialFormAttrs.target); - assertEquals(form.data("form").oldAttributes.method, initialFormAttrs.method); -}; -FormTest.prototype.testBind = function() { - var form = jQuery('#form').form(), - submitted = false, - handlersData = form.form('option', 'handlersData'); - - form.on('submit', function(e) { - submitted = true; - e.stopImmediatePropagation(); - e.preventDefault(); - }); - $.each(handlersData, function(key) { - form.trigger(key); - assertTrue(submitted); - submitted = false; - }); - form.off('submit'); -}; -FormTest.prototype.testGetActionUrl = function() { - var form = jQuery('#form').form(), - action = form.attr('action'), - testUrl = 'new/action/url', - testArgs = { - args: {arg: 'value'} - }; - - form.data("form")._storeAttribute('action'); - assertEquals(form.data("form")._getActionUrl(testArgs), action + '/arg/value/'); - assertEquals(form.data("form")._getActionUrl(testUrl), testUrl); - assertEquals(form.data("form")._getActionUrl(), action); -}; -FormTest.prototype.testProcessData = function() { - var form = jQuery('#form').form(), - initialFormAttrs = { - action: form.attr('action'), - target: form.attr('target'), - method: form.attr('method') - }, - testSimpleData = { - action: 'new/action/url', - target: '_blank', - method: 'POST' - }, - testActionArgsData = { - action: { - args: { - arg: 'value' - } - } - }; - var processedData = form.data("form")._processData(testSimpleData); - - assertEquals(form.data("form").oldAttributes.action, initialFormAttrs.action); - assertEquals(form.data("form").oldAttributes.target, initialFormAttrs.target); - assertEquals(form.data("form").oldAttributes.method, initialFormAttrs.method); - - assertEquals(processedData.action, testSimpleData.action); - assertEquals(processedData.target, testSimpleData.target); - assertEquals(processedData.method, testSimpleData.method); - - form.data("form")._rollback(); - - processedData = form.data("form")._processData(testActionArgsData); - form.data("form")._storeAttribute('action'); - var newActionUrl = form.data("form")._getActionUrl(testActionArgsData.action); - - assertEquals(processedData.action, newActionUrl); -}; -FormTest.prototype.testBeforeSubmit = function() { - /*:DOC +=
*/ - var testHandler = { - action: { - args: { - arg1: 'value1' - } - } - }, - form = jQuery('#form').form({handlersData: { - testHandler: testHandler - } - }), - beforeSubmitData = { - action: { - args: { - arg2: 'value2' - } - }, - target: '_blank' - }, - eventData = { - method: 'POST' - }, - resultData = $.extend( - true, - {}, - testHandler, - beforeSubmitData, - eventData - ); - form.data("form")._storeAttribute('action'); - - var testForm = jQuery('#test-form'); - resultData = form.data("form")._processData(resultData); - testForm.prop(resultData); - - form.on('beforeSubmit', function(e, data) { - jQuery.extend(data, beforeSubmitData); - }); - form.on('submit', function(e) { - e.stopImmediatePropagation(); - e.preventDefault(); - }); - form.data("form")._beforeSubmit('testHandler', eventData); - - assertEquals(testForm.prop('action'), form.prop('action')); - assertEquals(testForm.prop('target'), form.prop('target')); - assertEquals(testForm.prop('method'), form.prop('method')); -}; -FormTest.prototype.testSubmit = function() { - var form = jQuery('#form').form({ - handlersData: { - save: {} - } - }), - formSubmitted = false; - - form.data("form")._storeAttribute('action'); - form.data("form")._storeAttribute('target'); - form.data("form")._storeAttribute('method'); - form - .on('submit', function(e) { - e.preventDefault(); - e.stopImmediatePropagation(); - e.preventDefault(); - formSubmitted = true; - }) - .prop({ - action: 'new/action/url', - target: '_blank', - method: 'POST' - }); - - form.data("form")._submit({type: 'save'}); - - assertEquals(form.attr('action'), form.data("form").oldAttributes.action); - assertEquals(form.attr('target'), form.data("form").oldAttributes.target); - assertEquals(form.attr('method'), form.data("form").oldAttributes.method); - assertTrue(formSubmitted); - form.off('submit'); -}; -FormTest.prototype.testBuildURL = function() { - var dataProvider = [ - { - params: ['http://domain.com//', {'key[one]': 'value 1', 'key2': '# value'}], - expected: 'http://domain.com/key[one]/value%201/key2/%23%20value/' - }, - { - params: ['http://domain.com', {'key[one]': 'value 1', 'key2': '# value'}], - expected: 'http://domain.com/key[one]/value%201/key2/%23%20value/' - }, - { - params: ['http://domain.com?some=param', {'key[one]': 'value 1', 'key2': '# value'}], - expected: 'http://domain.com?some=param&key[one]=value%201&key2=%23%20value' - }, - { - params: ['http://domain.com?some=param&', {'key[one]': 'value 1', 'key2': '# value'}], - expected: 'http://domain.com?some=param&key[one]=value%201&key2=%23%20value' - } - ], - method = jQuery.mage.form._proto._buildURL, - quantity = dataProvider.length; - - expectAsserts(quantity); - for (var i = 0; i < quantity; i++) { - assertEquals(dataProvider[i].expected, method.apply(null, dataProvider[i].params)); - } -}; diff --git a/dev/tests/js/jasmine/tests/lib/mage/dropdown.test.js b/dev/tests/js/jasmine/tests/lib/mage/dropdown.test.js index 1034ad263d9fe..7279047adc53a 100644 --- a/dev/tests/js/jasmine/tests/lib/mage/dropdown.test.js +++ b/dev/tests/js/jasmine/tests/lib/mage/dropdown.test.js @@ -270,9 +270,12 @@ define([ jasmine.clock().uninstall(); }); - // Backend jquery-ui version has a diferent behavior on create that will add ui-dialog-titlebar anyway. - // This test is only valid with frontend's version - // @TODO: Re-design Jasmine settings to match a selective architecture for testing in order to split them. + /* + * jQuery ui version 1.9.2 belongs to the adminhtml. + * + * This test will fail on backend since backend's jquery.ui will + * add ui-dialog-titlebar class anyway on create. + */ if ($.ui.version !== '1.9.2') { it('check if the title bar is prevented from being created', function () { var dialog = $('
'), diff --git a/dev/tests/js/jasmine/tests/lib/mage/form.test.js b/dev/tests/js/jasmine/tests/lib/mage/form.test.js new file mode 100644 index 0000000000000..0f26516b4811e --- /dev/null +++ b/dev/tests/js/jasmine/tests/lib/mage/form.test.js @@ -0,0 +1,262 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +/* eslint-disable max-nested-callbacks */ +/* jscs:disable jsDoc */ + +define([ + 'jquery', + 'mage/backend/form' +], function ($) { + 'use strict'; + + /* + * jQuery ui version 1.9.2 belongs to the adminhtml. + * + * This test will fail on frontend since mage/backend/form only belongs to backend. + */ + if ($.ui.version === '1.9.2') { + describe('Test for mage/form jQuery plugin', function () { + var id = 'edit_form', + elementId = '#' + id; + + beforeEach(function () { + var element = jQuery('
'); + + element.appendTo('body'); + }); + + afterEach(function () { + $(elementId).remove(); + }); + + it('check if form can be initialized', function () { + var form = $(elementId).form(); + + expect(form.is(':mage-form')).toBeTruthy(); + }); + + it('check get handlers', function () { + var form = $(elementId).form(), + handlersData = form.form('option', 'handlersData'), + handlers = []; + + $.each(handlersData, function (key) { + handlers.push(key); + }); + expect(handlers.join(' ')).toBe(form.data('form')._getHandlers().join(' ')); + }); + + it('check store attribute', function () { + var form = $(elementId).form(), + initialFormAttrs = { + action: form.attr('action'), + target: form.attr('target'), + method: form.attr('method') + }; + + form.data('form')._storeAttribute('action'); + form.data('form')._storeAttribute('target'); + form.data('form')._storeAttribute('method'); + + expect(form.data('form').oldAttributes.action).toBe(initialFormAttrs.action); + expect(form.data('form').oldAttributes.target).toBe(initialFormAttrs.target); + expect(form.data('form').oldAttributes.method).toBe(initialFormAttrs.method); + }); + + it('check bind', function () { + var form = $(elementId).form(), + submitted = false, + handlersData = form.form('option', 'handlersData'); + + form.on('submit', function (e) { + submitted = true; + e.stopImmediatePropagation(); + e.preventDefault(); + }); + + $.each(handlersData, function (key) { + form.trigger(key); + expect(submitted).toBeTruthy(); + submitted = false; + }); + + form.off('submit'); + }); + + it('check get action URL', function () { + var form = $(elementId).form(), + action = form.attr('action'), + testUrl = 'new/action/url', + testArgs = { + args: { + arg: 'value' + } + }; + + form.data('form')._storeAttribute('action'); + expect(form.data('form')._getActionUrl(testArgs)).toBe(action + '/arg/value/'); + expect(form.data('form')._getActionUrl(testUrl)).toBe(testUrl); + expect(form.data('form')._getActionUrl()).toBe(action); + }); + + it('check process data', function () { + var form = $(elementId).form(), + initialFormAttrs = { + action: form.attr('action'), + target: form.attr('target'), + method: form.attr('method') + }, + testSimpleData = { + action: 'new/action/url', + target: '_blank', + method: 'POST' + }, + testActionArgsData = { + action: { + args: { + arg: 'value' + } + } + }, + processedData = form.data('form')._processData(testSimpleData); + + expect(form.data('form').oldAttributes.action).toBe(initialFormAttrs.action); + expect(form.data('form').oldAttributes.target).toBe(initialFormAttrs.target); + expect(form.data('form').oldAttributes.method).toBe(initialFormAttrs.method); + expect(processedData.action).toBe(testSimpleData.action); + expect(processedData.target).toBe(testSimpleData.target); + expect(processedData.method).toBe(testSimpleData.method); + + form.data('form')._rollback(); + processedData = form.data('form')._processData(testActionArgsData); + form.data('form')._storeAttribute('action'); + expect(processedData.action).toBe(form.data('form')._getActionUrl(testActionArgsData.action)); + }); + + it('check before submit', function () { + var testForm = $('
').appendTo('body'), + testHandler = { + action: { + args: { + arg1: 'value1' + } + } + }, + form = $(elementId).form({ + handlersData: { + testHandler: testHandler + } + }), + beforeSubmitData = { + action: { + args: { + arg2: 'value2' + } + }, + target: '_blank' + }, + eventData = { + method: 'POST' + }, + resultData = $.extend(true, {}, testHandler, beforeSubmitData, eventData); + + form.data('form')._storeAttribute('action'); + resultData = form.data('form')._processData(resultData); + testForm.prop(resultData); + + form.on('beforeSubmit', function (e, data) { + $.extend(data, beforeSubmitData); + }); + + form.on('submit', function (e) { + e.stopImmediatePropagation(); + e.preventDefault(); + }); + + form.data('form')._beforeSubmit('testHandler', eventData); + expect(testForm.prop('action')).toBe(form.prop('action')); + expect(testForm.prop('target')).toBe(form.prop('target')); + expect(testForm.prop('method')).toBe(form.prop('method')); + }); + + it('check submit', function () { + var formSubmitted = false, + form = $(elementId).form({ + handlersData: { + save: {} + } + }); + + form.data('form')._storeAttribute('action'); + form.data('form')._storeAttribute('target'); + form.data('form')._storeAttribute('method'); + + form.on('submit', function (e) { + e.preventDefault(); + e.stopImmediatePropagation(); + e.preventDefault(); + formSubmitted = true; + }).prop({ + action: 'new/action/url', + target: '_blank', + method: 'POST' + }); + + form.data('form')._submit({ + type: 'save' + }); + + expect(form.attr('action')).toBe(form.data('form').oldAttributes.action); + expect(form.attr('target')).toBe(form.data('form').oldAttributes.target); + expect(form.attr('method')).toBe(form.data('form').oldAttributes.method); + expect(formSubmitted).toBeTruthy(); + + form.off('submit'); + }); + + it('check build URL', function () { + var dataProvider = [ + { + params: ['http://domain.com//', { + 'key[one]': 'value 1', + 'key2': '# value' + }], + expected: 'http://domain.com/key[one]/value%201/key2/%23%20value/' + }, + { + params: ['http://domain.com', { + 'key[one]': 'value 1', + 'key2': '# value' + }], + expected: 'http://domain.com/key[one]/value%201/key2/%23%20value/' + }, + { + params: ['http://domain.com?some=param', { + 'key[one]': 'value 1', + 'key2': '# value' + }], + expected: 'http://domain.com?some=param&key[one]=value%201&key2=%23%20value' + }, + { + params: ['http://domain.com?some=param&', { + 'key[one]': 'value 1', + 'key2': '# value' + }], + expected: 'http://domain.com?some=param&key[one]=value%201&key2=%23%20value' + } + ], + method = $.mage.form._proto._buildURL, + quantity = dataProvider.length, + i = 0; + + expect(quantity).toBeTruthy(); + + for (i; i < quantity; i++) { + expect(dataProvider[i].expected).toBe(method.apply(null, dataProvider[i].params)); + } + }); + }); + } +}); From ad90a47b36983f354fd2958279742809fc8e4886 Mon Sep 17 00:00:00 2001 From: Carlos Lizaga Date: Fri, 1 Dec 2017 17:27:22 +0100 Subject: [PATCH 028/210] jQuery consistency. --- dev/tests/js/jasmine/tests/lib/mage/form.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/js/jasmine/tests/lib/mage/form.test.js b/dev/tests/js/jasmine/tests/lib/mage/form.test.js index 0f26516b4811e..6202f93da999a 100644 --- a/dev/tests/js/jasmine/tests/lib/mage/form.test.js +++ b/dev/tests/js/jasmine/tests/lib/mage/form.test.js @@ -22,7 +22,7 @@ define([ elementId = '#' + id; beforeEach(function () { - var element = jQuery('
'); + var element = $('
'); element.appendTo('body'); }); From 32d30a537e6fa40ad28c8474cdab89ac43fe82ae Mon Sep 17 00:00:00 2001 From: Scott Buchanan Date: Fri, 1 Dec 2017 20:15:52 -0500 Subject: [PATCH 029/210] allow more flexible static file version --- nginx.conf.sample | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nginx.conf.sample b/nginx.conf.sample index 7257c329df24b..1e20a51a511d3 100644 --- a/nginx.conf.sample +++ b/nginx.conf.sample @@ -100,7 +100,7 @@ location /static/ { # Remove signature of the static files that is used to overcome the browser cache location ~ ^/static/version { - rewrite ^/static/(version\d*/)?(.*)$ /static/$2 last; + rewrite ^/static/(version[^/]+/)?(.*)$ /static/$2 last; } location ~* \.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2)$ { From 7759827ff277157d3cf1ae93b1392a73bc2538de Mon Sep 17 00:00:00 2001 From: Dmytro Poperechnyy Date: Fri, 8 Dec 2017 18:35:08 +0200 Subject: [PATCH 030/210] MAGETWO-81802: Magento 2.2.0rc23: Customer Grid Indexer not working --- .../Magento/Framework/Indexer/Handler/AttributeHandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Indexer/Handler/AttributeHandler.php b/lib/internal/Magento/Framework/Indexer/Handler/AttributeHandler.php index 94f34ec7ba3b2..4b74ce50c9ed6 100644 --- a/lib/internal/Magento/Framework/Indexer/Handler/AttributeHandler.php +++ b/lib/internal/Magento/Framework/Indexer/Handler/AttributeHandler.php @@ -35,7 +35,7 @@ public function prepareSql(SourceProviderInterface $source, $alias, $fieldInfo) 'left' ); } else { - $source->addAttributeToSelect($fieldInfo['origin'], 'left'); + $source->addFieldToSelect($fieldInfo['origin'], 'left'); } } } From 15928fbd8c42590187f0613f889cc27d6afabe0d Mon Sep 17 00:00:00 2001 From: RomanKis Date: Mon, 11 Dec 2017 16:21:21 +0200 Subject: [PATCH 031/210] 8624: Stock status not coming back after qty update --- .../Model/Stock/StockItemRepository.php | 30 +++++++++-- .../Model/Stock/StockItemRepositoryTest.php | 2 +- .../Magento/Catalog/Model/ProductTest.php | 32 ++++++++++++ .../_files/product_simple_out_of_stock.php | 51 +++++++++++++++++++ .../product_simple_out_of_stock_rollback.php | 25 +++++++++ .../ByStockItemRepositoryTest.php | 2 +- .../ByQuantityAndStockStatusTest.php | 2 +- .../ByProductModel/ByStockDataTest.php | 2 +- .../ByProductModel/ByStockItemTest.php | 2 +- .../ByQuantityAndStockStatusTest.php | 2 +- .../ByProductRepository/ByStockDataTest.php | 2 +- .../ByProductRepository/ByStockItemTest.php | 2 +- .../ByProductModel/ByStockItemTest.php | 2 +- .../ByProductRepository/ByStockItemTest.php | 2 +- .../Framework/Data/AbstractSearchResult.php | 1 + 15 files changed, 144 insertions(+), 15 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_out_of_stock.php create mode 100644 dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_out_of_stock_rollback.php diff --git a/app/code/Magento/CatalogInventory/Model/Stock/StockItemRepository.php b/app/code/Magento/CatalogInventory/Model/Stock/StockItemRepository.php index e5154a10f0a19..a675709e504b2 100644 --- a/app/code/Magento/CatalogInventory/Model/Stock/StockItemRepository.php +++ b/app/code/Magento/CatalogInventory/Model/Stock/StockItemRepository.php @@ -145,7 +145,7 @@ public function __construct( /** * @inheritdoc */ - public function save(\Magento\CatalogInventory\Api\Data\StockItemInterface $stockItem) + public function save(StockItemInterface $stockItem) { try { /** @var \Magento\Catalog\Model\Product $product */ @@ -161,10 +161,7 @@ public function save(\Magento\CatalogInventory\Api\Data\StockItemInterface $stoc $typeId = $product->getTypeId() ?: $product->getTypeInstance()->getTypeId(); $isQty = $this->stockConfiguration->isQty($typeId); if ($isQty) { - $isInStock = $this->stockStateProvider->verifyStock($stockItem); - if ($stockItem->getManageStock() && !$isInStock) { - $stockItem->setIsInStock(false)->setStockStatusChangedAutomaticallyFlag(true); - } + $this->changeIsInStockIfNecessary($stockItem); // if qty is below notify qty, update the low stock date to today date otherwise set null $stockItem->setLowStockDate(null); if ($this->stockStateProvider->verifyNotification($stockItem)) { @@ -260,4 +257,27 @@ private function getStockRegistryStorage() } return $this->stockRegistryStorage; } + + /** + * Change is_in_stock value if necessary. + * + * @param StockItemInterface $stockItem + * + * @return void + */ + private function changeIsInStockIfNecessary(StockItemInterface $stockItem) + { + $isInStock = $this->stockStateProvider->verifyStock($stockItem); + if ($stockItem->getManageStock() && !$isInStock) { + $stockItem->setIsInStock(false)->setStockStatusChangedAutomaticallyFlag(true); + } + + if ($stockItem->getManageStock() + && $isInStock + && !$stockItem->getIsInStock() + && $stockItem->getOrigData(\Magento\CatalogInventory\Api\Data\StockItemInterface::QTY) == 0 + ) { + $stockItem->setIsInStock(true)->setStockStatusChangedAutomaticallyFlag(true); + } + } } diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemRepositoryTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemRepositoryTest.php index 293874bb32b9f..6b1770ff7d403 100644 --- a/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemRepositoryTest.php +++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/Stock/StockItemRepositoryTest.php @@ -276,7 +276,7 @@ public function testSave() ->method('verifyStock') ->with($this->stockItemMock) ->willReturn(false); - $this->stockItemMock->expects($this->once())->method('getManageStock')->willReturn(true); + $this->stockItemMock->expects($this->exactly(2))->method('getManageStock')->willReturn(true); $this->stockItemMock->expects($this->once())->method('setIsInStock')->with(false)->willReturnSelf(); $this->stockItemMock->expects($this->once()) ->method('setStockStatusChangedAutomaticallyFlag') diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php index 99a1e9309f6e9..078a83bcf6314 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php @@ -549,4 +549,36 @@ public function testGetOptions() } } } + + /** + * @magentoDataFixture Magento/Catalog/_files/product_simple_out_of_stock.php + */ + public function testSaveWithDifferentQty() + { + //if save (out of stock product with qty 0) with new qty > 0 it should become in stock. + //if set out of stock for product with qty > 0 it should become out of stock + $product = $this->productRepository->get('simple-out-of-stock'); + $stockItem = $product->getExtensionAttributes()->getStockItem(); + $this->assertEquals(false, $stockItem->getIsInStock()); + $stockData = [ + 'qty' => 5, + 'is_in_stock' => 0, + ]; + $product->setStockData($stockData); + $product->save(); + + $product = $this->productRepository->get('simple-out-of-stock'); + $stockItem = $product->getExtensionAttributes()->getStockItem(); + $this->assertEquals(true, $stockItem->getIsInStock()); + $stockData = [ + 'qty' => 3, + 'is_in_stock' => 0, + ]; + $product->setStockData($stockData); + $product->save(); + + $product = $this->productRepository->get('simple-out-of-stock'); + $stockItem = $product->getExtensionAttributes()->getStockItem(); + $this->assertEquals(false, $stockItem->getIsInStock()); + } } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_out_of_stock.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_out_of_stock.php new file mode 100644 index 0000000000000..729ea2ab982b7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_out_of_stock.php @@ -0,0 +1,51 @@ +reinitialize(); + +/** @var \Magento\TestFramework\ObjectManager $objectManager */ +$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + +/** @var \Magento\Catalog\Api\CategoryLinkManagementInterface $categoryLinkManagement */ +$categoryLinkManagement = $objectManager->get(\Magento\Catalog\Api\CategoryLinkManagementInterface::class); + +/** @var $product \Magento\Catalog\Model\Product */ +$product = $objectManager->create(\Magento\Catalog\Model\Product::class); +$product->isObjectNew(true); +$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE) + ->setId(1) + ->setAttributeSetId(4) + ->setWebsiteIds([1]) + ->setName('Simple Product') + ->setSku('simple-out-of-stock') + ->setPrice(10) + ->setWeight(1) + ->setShortDescription("Short description") + ->setTaxClassId(0) + ->setDescription('Description with html tag') + ->setMetaTitle('meta title') + ->setMetaKeyword('meta keyword') + ->setMetaDescription('meta description') + ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) + ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) + ->setStockData( + [ + 'use_config_manage_stock' => 1, + 'qty' => 0, + 'is_qty_decimal' => 0, + 'is_in_stock' => 0, + ] + )->setCanSaveCustomOptions(true) + ->setHasOptions(true); + +/** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepositoryFactory */ +$productRepository = $objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); +$productRepository->save($product); + +$categoryLinkManagement->assignProductToCategories( + $product->getSku(), + [2] +); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_out_of_stock_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_out_of_stock_rollback.php new file mode 100644 index 0000000000000..2bb2858687ff7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_out_of_stock_rollback.php @@ -0,0 +1,25 @@ +getInstance()->reinitialize(); + +/** @var \Magento\Framework\Registry $registry */ +$registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(\Magento\Framework\Registry::class); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +/** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ +$productRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() + ->get(\Magento\Catalog\Api\ProductRepositoryInterface::class); +try { + $product = $productRepository->get('simple-out-of-stock', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { +} +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/ByStockItemRepositoryTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/ByStockItemRepositoryTest.php index ae67d3fa1eddc..dfe21a61c866b 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/ByStockItemRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/ByStockItemRepositoryTest.php @@ -40,7 +40,7 @@ class ByStockItemRepositoryTest extends \PHPUnit\Framework\TestCase private $stockItemData = [ StockItemInterface::QTY => 555, StockItemInterface::MANAGE_STOCK => true, - StockItemInterface::IS_IN_STOCK => false, + StockItemInterface::IS_IN_STOCK => true, ]; public function setUp() diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductModel/ByQuantityAndStockStatusTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductModel/ByQuantityAndStockStatusTest.php index 6864b9a345602..ec5dc7c5b0ce7 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductModel/ByQuantityAndStockStatusTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductModel/ByQuantityAndStockStatusTest.php @@ -53,7 +53,7 @@ class ByQuantityAndStockStatusTest extends \PHPUnit\Framework\TestCase private $stockItemData = [ StockItemInterface::QTY => 555, StockItemInterface::MANAGE_STOCK => true, - StockItemInterface::IS_IN_STOCK => false, + StockItemInterface::IS_IN_STOCK => true, ]; public function setUp() diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductModel/ByStockDataTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductModel/ByStockDataTest.php index eae20bda1a94a..7638936c34a6a 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductModel/ByStockDataTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductModel/ByStockDataTest.php @@ -53,7 +53,7 @@ class ByStockDataTest extends \PHPUnit\Framework\TestCase private $stockItemData = [ StockItemInterface::QTY => 555, StockItemInterface::MANAGE_STOCK => true, - StockItemInterface::IS_IN_STOCK => false, + StockItemInterface::IS_IN_STOCK => true, ]; public function setUp() diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductModel/ByStockItemTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductModel/ByStockItemTest.php index 25b9817bcf572..d5dae31b89158 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductModel/ByStockItemTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductModel/ByStockItemTest.php @@ -59,7 +59,7 @@ class ByStockItemTest extends \PHPUnit\Framework\TestCase private $stockItemData = [ StockItemInterface::QTY => 555, StockItemInterface::MANAGE_STOCK => true, - StockItemInterface::IS_IN_STOCK => false, + StockItemInterface::IS_IN_STOCK => true, ]; public function setUp() diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductRepository/ByQuantityAndStockStatusTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductRepository/ByQuantityAndStockStatusTest.php index 6269d7a20f4fc..fc1d787df531d 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductRepository/ByQuantityAndStockStatusTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductRepository/ByQuantityAndStockStatusTest.php @@ -59,7 +59,7 @@ class ByQuantityAndStockStatusTest extends \PHPUnit\Framework\TestCase private $stockItemData = [ StockItemInterface::QTY => 555, StockItemInterface::MANAGE_STOCK => true, - StockItemInterface::IS_IN_STOCK => false, + StockItemInterface::IS_IN_STOCK => true, ]; public function setUp() diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductRepository/ByStockDataTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductRepository/ByStockDataTest.php index fa7cc39f7584f..9050aaf6c8855 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductRepository/ByStockDataTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductRepository/ByStockDataTest.php @@ -59,7 +59,7 @@ class ByStockDataTest extends \PHPUnit\Framework\TestCase private $stockItemData = [ StockItemInterface::QTY => 555, StockItemInterface::MANAGE_STOCK => true, - StockItemInterface::IS_IN_STOCK => false, + StockItemInterface::IS_IN_STOCK => true, ]; public function setUp() diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductRepository/ByStockItemTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductRepository/ByStockItemTest.php index 857457325c755..1884a46e21680 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductRepository/ByStockItemTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductCreate/ByProductRepository/ByStockItemTest.php @@ -70,7 +70,7 @@ class ByStockItemTest extends \PHPUnit\Framework\TestCase private $stockItemData = [ StockItemInterface::QTY => 555, StockItemInterface::MANAGE_STOCK => true, - StockItemInterface::IS_IN_STOCK => false, + StockItemInterface::IS_IN_STOCK => true, ]; public function setUp() diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductUpdate/ByProductModel/ByStockItemTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductUpdate/ByProductModel/ByStockItemTest.php index 2a4b7937f7163..5a726170a0128 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductUpdate/ByProductModel/ByStockItemTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductUpdate/ByProductModel/ByStockItemTest.php @@ -42,7 +42,7 @@ class ByStockItemTest extends \PHPUnit\Framework\TestCase private $stockItemData = [ StockItemInterface::QTY => 555, StockItemInterface::MANAGE_STOCK => true, - StockItemInterface::IS_IN_STOCK => false, + StockItemInterface::IS_IN_STOCK => true, ]; public function setUp() diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductUpdate/ByProductRepository/ByStockItemTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductUpdate/ByProductRepository/ByStockItemTest.php index 81871d3398c1e..3053b8d6acff6 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductUpdate/ByProductRepository/ByStockItemTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Model/StockItemSave/OnProductUpdate/ByProductRepository/ByStockItemTest.php @@ -48,7 +48,7 @@ class ByStockItemTest extends \PHPUnit\Framework\TestCase private $stockItemData = [ StockItemInterface::QTY => 555, StockItemInterface::MANAGE_STOCK => true, - StockItemInterface::IS_IN_STOCK => false, + StockItemInterface::IS_IN_STOCK => true, ]; public function setUp() diff --git a/lib/internal/Magento/Framework/Data/AbstractSearchResult.php b/lib/internal/Magento/Framework/Data/AbstractSearchResult.php index f9272683005ce..bcedf16e3f5be 100644 --- a/lib/internal/Magento/Framework/Data/AbstractSearchResult.php +++ b/lib/internal/Magento/Framework/Data/AbstractSearchResult.php @@ -235,6 +235,7 @@ protected function load() if (is_array($data)) { foreach ($data as $row) { $item = $this->createDataObject(['data' => $row]); + $item->setOrigData(); $this->addItem($item); } } From 188ecb36ed86fbd7df58a4826040078eefaad2c6 Mon Sep 17 00:00:00 2001 From: RomanKis Date: Tue, 12 Dec 2017 13:22:24 +0200 Subject: [PATCH 032/210] 8624: Stock status not coming back after qty update --- .../testsuite/Magento/Catalog/Model/ProductTest.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php index 078a83bcf6314..da91ed96435aa 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php @@ -557,7 +557,7 @@ public function testSaveWithDifferentQty() { //if save (out of stock product with qty 0) with new qty > 0 it should become in stock. //if set out of stock for product with qty > 0 it should become out of stock - $product = $this->productRepository->get('simple-out-of-stock'); + $product = $this->productRepository->get('simple-out-of-stock', true, null, true); $stockItem = $product->getExtensionAttributes()->getStockItem(); $this->assertEquals(false, $stockItem->getIsInStock()); $stockData = [ @@ -567,7 +567,11 @@ public function testSaveWithDifferentQty() $product->setStockData($stockData); $product->save(); - $product = $this->productRepository->get('simple-out-of-stock'); + /** @var \Magento\CatalogInventory\Model\StockRegistryStorage $stockRegistryStorage */ + $stockRegistryStorage = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() + ->get(\Magento\CatalogInventory\Model\StockRegistryStorage::class); + $stockRegistryStorage->removeStockItem($product->getId()); + $product = $this->productRepository->get('simple-out-of-stock', true, null, true); $stockItem = $product->getExtensionAttributes()->getStockItem(); $this->assertEquals(true, $stockItem->getIsInStock()); $stockData = [ @@ -577,7 +581,8 @@ public function testSaveWithDifferentQty() $product->setStockData($stockData); $product->save(); - $product = $this->productRepository->get('simple-out-of-stock'); + $stockRegistryStorage->removeStockItem($product->getId()); + $product = $this->productRepository->get('simple-out-of-stock', true, null, true); $stockItem = $product->getExtensionAttributes()->getStockItem(); $this->assertEquals(false, $stockItem->getIsInStock()); } From 944adbf1150ac7dedc40b3f4c4eebbe28f30ee9f Mon Sep 17 00:00:00 2001 From: Mohammad HAJ SALEM Date: Tue, 12 Dec 2017 16:22:17 +0100 Subject: [PATCH 033/210] :bug: add fallback for Product_links position attribute if position index was not set in API request --- .../Model/Product/Link/SaveHandler.php | 73 ++++++++++++++++++- 1 file changed, 70 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php b/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php index 13c6a13a50407..72bfaeba8d0b8 100644 --- a/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php +++ b/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php @@ -31,18 +31,28 @@ class SaveHandler private $linkResource; /** + * @var linkTypeProvider + */ + private $linkTypeProvider; + + /** + * SaveHandler constructor. * @param MetadataPool $metadataPool * @param Link $linkResource * @param ProductLinkRepositoryInterface $productLinkRepository + * @param \Magento\Catalog\Model\Product\LinkTypeProvider $linkTypeProvider */ public function __construct( MetadataPool $metadataPool, Link $linkResource, - ProductLinkRepositoryInterface $productLinkRepository - ) { + ProductLinkRepositoryInterface $productLinkRepository, + \Magento\Catalog\Model\Product\LinkTypeProvider $linkTypeProvider + ) + { $this->metadataPool = $metadataPool; $this->linkResource = $linkResource; $this->productLinkRepository = $productLinkRepository; + $this->linkTypeProvider = $linkTypeProvider; } /** @@ -55,12 +65,36 @@ public function execute($entityType, $entity) { $link = $entity->getData($this->metadataPool->getMetadata($entityType)->getLinkField()); if ($this->linkResource->hasProductLinks($link)) { - /** @var \Magento\Catalog\Api\Data\ProductInterface $entity*/ + /** @var \Magento\Catalog\Api\Data\ProductInterface $entity */ foreach ($this->productLinkRepository->getList($entity) as $link) { $this->productLinkRepository->delete($link); } } $productLinks = $entity->getProductLinks(); + + // Build links per type + $linksByType = []; + foreach ($productLinks as $link) { + $linksByType[$link->getLinkType()][] = $link; + } + + // Do check + $hasPositionLinkType = $this->isPositionsSet($linksByType); + + + // Bug fix for API if the Position was not set to force set Position attribute in "catalog_product_link_attribute_int" + // set Positions attribute values + foreach ($hasPositionLinkType as $linkType => $hasPosition) { + if (!$hasPosition) { + array_walk($linksByType[$linkType], function ($productLink, $position) { + $productLink->setPosition(++$position); + }); + } + } + + // Flatten multi-dimensional linksByType in ProductLinks + $productLinks = array_reduce($linksByType, 'array_merge', []); + if (count($productLinks) > 0) { foreach ($entity->getProductLinks() as $link) { $this->productLinkRepository->save($link); @@ -68,4 +102,37 @@ public function execute($entityType, $entity) } return $entity; } + + /** + * Check if the position is set for all product links per link type. + * array with boolean per type + * + * @param $linksByType + * @return array + */ + private function isPositionsSet($linksByType) + { + $linkTypes = $this->linkTypeProvider->getLinkTypes(); + + // Initialize isPositionSet for existent link types + $isPositionSet = []; + foreach (array_keys($linkTypes) as $typeName) { + if (array_key_exists($typeName, $linksByType)) { + $isPositionSet[$typeName] = count($linksByType[$typeName]) > 0; + } + } + + + // Check if at least on link without position exists per Link type + foreach ($linksByType as $type => $links) { + foreach ($links as $link) { + if (!array_key_exists('position', $link->getData())) { + $isPositionSet[$type] = false; + break; + } + } + } + + return $isPositionSet; + } } From aa5bc4f00e1847546c42cb0b12e1736395c5f0fe Mon Sep 17 00:00:00 2001 From: Mohammad HAJ SALEM Date: Wed, 13 Dec 2017 08:13:12 +0100 Subject: [PATCH 034/210] :ok_hand: shortening variable name --- .../Magento/Catalog/Model/Product/Link/SaveHandler.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php b/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php index 72bfaeba8d0b8..e9321e9d10902 100644 --- a/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php +++ b/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php @@ -18,7 +18,7 @@ class SaveHandler /** * @var ProductLinkRepositoryInterface */ - protected $productLinkRepository; + protected $productLinkRepo; /** * @var MetadataPool @@ -39,19 +39,19 @@ class SaveHandler * SaveHandler constructor. * @param MetadataPool $metadataPool * @param Link $linkResource - * @param ProductLinkRepositoryInterface $productLinkRepository + * @param ProductLinkRepositoryInterface $productLinkRepo * @param \Magento\Catalog\Model\Product\LinkTypeProvider $linkTypeProvider */ public function __construct( MetadataPool $metadataPool, Link $linkResource, - ProductLinkRepositoryInterface $productLinkRepository, + ProductLinkRepositoryInterface $productLinkRepo, \Magento\Catalog\Model\Product\LinkTypeProvider $linkTypeProvider ) { $this->metadataPool = $metadataPool; $this->linkResource = $linkResource; - $this->productLinkRepository = $productLinkRepository; + $this->productLinkRepo = $productLinkRepo; $this->linkTypeProvider = $linkTypeProvider; } From 828f18bbd2f495ec9fcaac32eaf5b7b73bda429c Mon Sep 17 00:00:00 2001 From: Mohammad HAJ SALEM Date: Wed, 13 Dec 2017 08:20:56 +0100 Subject: [PATCH 035/210] :bug: fix variable re-naming --- app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php b/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php index e9321e9d10902..9f0f17f7339f1 100644 --- a/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php +++ b/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php @@ -66,8 +66,8 @@ public function execute($entityType, $entity) $link = $entity->getData($this->metadataPool->getMetadata($entityType)->getLinkField()); if ($this->linkResource->hasProductLinks($link)) { /** @var \Magento\Catalog\Api\Data\ProductInterface $entity */ - foreach ($this->productLinkRepository->getList($entity) as $link) { - $this->productLinkRepository->delete($link); + foreach ($this->productLinkRepo->getList($entity) as $link) { + $this->productLinkRepo->delete($link); } } $productLinks = $entity->getProductLinks(); @@ -97,7 +97,7 @@ public function execute($entityType, $entity) if (count($productLinks) > 0) { foreach ($entity->getProductLinks() as $link) { - $this->productLinkRepository->save($link); + $this->productLinkRepo->save($link); } } return $entity; From 005e3eb9068437c9cbe2e9bbd59d3adad4f03e39 Mon Sep 17 00:00:00 2001 From: Mohammad HAJ SALEM Date: Wed, 13 Dec 2017 08:26:17 +0100 Subject: [PATCH 036/210] :ok_hand: drop multiple empty lines --- app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php b/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php index 9f0f17f7339f1..ff22abc90911b 100644 --- a/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php +++ b/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php @@ -81,7 +81,6 @@ public function execute($entityType, $entity) // Do check $hasPositionLinkType = $this->isPositionsSet($linksByType); - // Bug fix for API if the Position was not set to force set Position attribute in "catalog_product_link_attribute_int" // set Positions attribute values foreach ($hasPositionLinkType as $linkType => $hasPosition) { @@ -122,7 +121,6 @@ private function isPositionsSet($linksByType) } } - // Check if at least on link without position exists per Link type foreach ($linksByType as $type => $links) { foreach ($links as $link) { From 27cc0b615d86c5d5e4ec826bbc9a3354b94c443a Mon Sep 17 00:00:00 2001 From: Mohammad HAJ SALEM Date: Wed, 13 Dec 2017 08:29:50 +0100 Subject: [PATCH 037/210] :ok_hand: closing parenthesis and the opening brace of a multi-line function on the same line --- app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php b/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php index ff22abc90911b..5983504715a31 100644 --- a/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php +++ b/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php @@ -47,8 +47,7 @@ public function __construct( Link $linkResource, ProductLinkRepositoryInterface $productLinkRepo, \Magento\Catalog\Model\Product\LinkTypeProvider $linkTypeProvider - ) - { + ) { $this->metadataPool = $metadataPool; $this->linkResource = $linkResource; $this->productLinkRepo = $productLinkRepo; From 12653a128052645ff308311b039005d10c7128e4 Mon Sep 17 00:00:00 2001 From: Mohammad HAJ SALEM Date: Wed, 13 Dec 2017 08:29:50 +0100 Subject: [PATCH 038/210] :ok_hand: closing parenthesis and the opening brace of a multi-line function on the same line --- app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php b/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php index ff22abc90911b..abf465ac270bd 100644 --- a/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php +++ b/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php @@ -47,8 +47,7 @@ public function __construct( Link $linkResource, ProductLinkRepositoryInterface $productLinkRepo, \Magento\Catalog\Model\Product\LinkTypeProvider $linkTypeProvider - ) - { + ) { $this->metadataPool = $metadataPool; $this->linkResource = $linkResource; $this->productLinkRepo = $productLinkRepo; @@ -81,8 +80,7 @@ public function execute($entityType, $entity) // Do check $hasPositionLinkType = $this->isPositionsSet($linksByType); - // Bug fix for API if the Position was not set to force set Position attribute in "catalog_product_link_attribute_int" - // set Positions attribute values + // Set array position as a fallback position if necessary foreach ($hasPositionLinkType as $linkType => $hasPosition) { if (!$hasPosition) { array_walk($linksByType[$linkType], function ($productLink, $position) { From fa6782f3a22f1185ebd4e71e915962f2a57c199f Mon Sep 17 00:00:00 2001 From: nmalevanec Date: Wed, 13 Dec 2017 13:52:25 +0200 Subject: [PATCH 039/210] 6486: magento/magento2#6486: Unable to save certain product properties via Rest API --- .../Catalog/Model/ProductRepository.php | 3 +++ .../Api/ProductRepositoryInterfaceTest.php | 26 +++++++++++++++++++ .../Catalog/Model/ProductRepositoryTest.php | 21 +++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/app/code/Magento/Catalog/Model/ProductRepository.php b/app/code/Magento/Catalog/Model/ProductRepository.php index 83feea903f993..0ecbad55d74d9 100644 --- a/app/code/Magento/Catalog/Model/ProductRepository.php +++ b/app/code/Magento/Catalog/Model/ProductRepository.php @@ -329,6 +329,9 @@ protected function initializeProductData(array $productData, $createNew) unset($productData['media_gallery']); if ($createNew) { $product = $this->productFactory->create(); + if (!isset($productData['product_type'])) { + $product->setTypeId(Product\Type::TYPE_SIMPLE); + } if ($this->storeManager->hasSingleStore()) { $product->setWebsiteIds([$this->storeManager->getStore(true)->getWebsiteId()]); } diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php index cb33edce3af39..7b7ec5e628d88 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php @@ -303,6 +303,32 @@ public function testCreateInvalidPriceFormat() } } + /** + * Test that Product Repository can correctly create simple product, if product type not specified in request. + * + * @return void + */ + public function testCreateWithoutSpecifiedType() + { + $price = 3.62; + $weight = 12.2; + $sku = 'simple_product_without_specified_type'; + $product = [ + 'sku' => '' . $sku . '', + 'name' => 'Simple Product Without Specified Type', + 'price' => $price, + 'weight' => $weight, + 'attribute_set_id' => 4, + ]; + $response = $this->saveProduct($product); + $this->assertSame($sku, $response[ProductInterface::SKU]); + $this->assertSame(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE, $response[ProductInterface::TYPE_ID]); + $this->assertSame($price, $response[ProductInterface::PRICE]); + $this->assertSame($weight, $response[ProductInterface::WEIGHT]); + //Clean up. + $this->deleteProduct($product[ProductInterface::SKU]); + } + /** * @param array $fixtureProduct * diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php index 9518e9c0cdf4f..330487b757f61 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php @@ -49,4 +49,25 @@ public function testUpdateProductSku() $updatedProduct->load($productId); self::assertSame($newSku, $updatedProduct->getSku()); } + + /** + * Check Product Repository able to correctly create product without specified type. + * + * @magentoDbIsolation enabled + */ + public function testCreateWithoutSpecifiedType() + { + /** @var Product $product */ + $product = Bootstrap::getObjectManager()->get(ProductFactory::class)->create(); + $product->setName('Simple without specified type'); + $product->setSku('simple_without_specified_type'); + $product->setPrice(1.12); + $product->setWeight(1.23); + $product->setAttributeSetId(4); + $product = $this->productRepository->save($product); + + self::assertSame('1.1200', $product->getPrice()); + self::assertSame('1.2300', $product->getWeight()); + self::assertSame('simple', $product->getTypeId()); + } } From 9e51c51c81ff5fed99f65c2a106d7d597ad24c25 Mon Sep 17 00:00:00 2001 From: Mohammad HAJ SALEM Date: Wed, 13 Dec 2017 22:10:17 +0100 Subject: [PATCH 040/210] :ok_hand: reset protected variable naming --- .../Catalog/Model/Product/Link/SaveHandler.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php b/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php index abf465ac270bd..10c89bdd1f813 100644 --- a/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php +++ b/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php @@ -18,7 +18,7 @@ class SaveHandler /** * @var ProductLinkRepositoryInterface */ - protected $productLinkRepo; + protected $productLinkRepository; /** * @var MetadataPool @@ -39,18 +39,18 @@ class SaveHandler * SaveHandler constructor. * @param MetadataPool $metadataPool * @param Link $linkResource - * @param ProductLinkRepositoryInterface $productLinkRepo + * @param ProductLinkRepositoryInterface $productLinkRepository * @param \Magento\Catalog\Model\Product\LinkTypeProvider $linkTypeProvider */ public function __construct( MetadataPool $metadataPool, Link $linkResource, - ProductLinkRepositoryInterface $productLinkRepo, + ProductLinkRepositoryInterface $productLinkRepository, \Magento\Catalog\Model\Product\LinkTypeProvider $linkTypeProvider ) { $this->metadataPool = $metadataPool; $this->linkResource = $linkResource; - $this->productLinkRepo = $productLinkRepo; + $this->productLinkRepository = $productLinkRepository; $this->linkTypeProvider = $linkTypeProvider; } @@ -65,8 +65,8 @@ public function execute($entityType, $entity) $link = $entity->getData($this->metadataPool->getMetadata($entityType)->getLinkField()); if ($this->linkResource->hasProductLinks($link)) { /** @var \Magento\Catalog\Api\Data\ProductInterface $entity */ - foreach ($this->productLinkRepo->getList($entity) as $link) { - $this->productLinkRepo->delete($link); + foreach ($this->productLinkRepository->getList($entity) as $link) { + $this->productLinkRepository->delete($link); } } $productLinks = $entity->getProductLinks(); @@ -94,7 +94,7 @@ public function execute($entityType, $entity) if (count($productLinks) > 0) { foreach ($entity->getProductLinks() as $link) { - $this->productLinkRepo->save($link); + $this->productLinkRepository->save($link); } } return $entity; From ccaf7487bb5a75bb7f843c8260e58334fa4cfab7 Mon Sep 17 00:00:00 2001 From: Mohammad HAJ SALEM Date: Wed, 13 Dec 2017 22:22:31 +0100 Subject: [PATCH 041/210] :ok_hand: rename isPositionsSet function to isPositionSet to keep consistency --- app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php b/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php index 10c89bdd1f813..1d581566148fd 100644 --- a/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php +++ b/app/code/Magento/Catalog/Model/Product/Link/SaveHandler.php @@ -78,7 +78,7 @@ public function execute($entityType, $entity) } // Do check - $hasPositionLinkType = $this->isPositionsSet($linksByType); + $hasPositionLinkType = $this->isPositionSet($linksByType); // Set array position as a fallback position if necessary foreach ($hasPositionLinkType as $linkType => $hasPosition) { @@ -107,7 +107,7 @@ public function execute($entityType, $entity) * @param $linksByType * @return array */ - private function isPositionsSet($linksByType) + private function isPositionSet($linksByType) { $linkTypes = $this->linkTypeProvider->getLinkTypes(); From 2dd2b7dea4bb227708a0047a9d875846316c8ffc Mon Sep 17 00:00:00 2001 From: Dmytro Poperechnyy Date: Thu, 14 Dec 2017 10:18:59 +0200 Subject: [PATCH 042/210] MAGETWO-81802: Magento 2.2.0rc23: Customer Grid Indexer not working - Add unit test; --- .../Unit/Handler/AttributeHandlerTest.php | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 lib/internal/Magento/Framework/Indexer/Test/Unit/Handler/AttributeHandlerTest.php diff --git a/lib/internal/Magento/Framework/Indexer/Test/Unit/Handler/AttributeHandlerTest.php b/lib/internal/Magento/Framework/Indexer/Test/Unit/Handler/AttributeHandlerTest.php new file mode 100644 index 0000000000000..82b178e0ff487 --- /dev/null +++ b/lib/internal/Magento/Framework/Indexer/Test/Unit/Handler/AttributeHandlerTest.php @@ -0,0 +1,57 @@ +source = $this->getMockBuilder(SourceProviderInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $objectManager = new ObjectManager($this); + + $this->subject = $objectManager->getObject( + AttributeHandler::class, + [] + ); + } + + public function testPrepareSql() + { + $alias = 'e'; + $fieldInfo = [ + 'name' => 'is_approved', + 'origin' => 'is_approved', + 'type' => 'searchable', + 'dataType' => 'varchar', + 'entity' => 'customer', + 'bind' => null + ]; + $this->source->expects($this->once()) + ->method('addFieldToSelect') + ->with('is_approved', 'left') + ->willReturnSelf(); + + $this->subject->prepareSql($this->source, $alias, $fieldInfo); + } +} From 5bac54fc879f5551b8187c0250b5874efdb74391 Mon Sep 17 00:00:00 2001 From: RomanKis Date: Thu, 14 Dec 2017 18:22:31 +0200 Subject: [PATCH 043/210] magento/magento2#8114: "Save Block"-button on Add New Block silently ignores clicks if the content is empty. --- .../Magento/Ui/view/base/web/templates/content/content.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Ui/view/base/web/templates/content/content.html b/app/code/Magento/Ui/view/base/web/templates/content/content.html index 8cf47120865dc..62e5959a02559 100644 --- a/app/code/Magento/Ui/view/base/web/templates/content/content.html +++ b/app/code/Magento/Ui/view/base/web/templates/content/content.html @@ -17,3 +17,5 @@
+ +