Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 36 additions & 2 deletions Inventory/Model/SourceItem/Validator/SkuValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

namespace Magento\Inventory\Model\SourceItem\Validator;

use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Validation\ValidationResult;
use Magento\Framework\Validation\ValidationResultFactory;
use Magento\Inventory\Model\Validators\NoSpaceBeforeAndAfterString;
Expand Down Expand Up @@ -34,19 +36,28 @@ class SkuValidator implements SourceItemValidatorInterface
*/
private $noSpaceBeforeAndAfterString;

/**
* @var ProductRepositoryInterface
*/
private $productRepository;

/**
* @param ValidationResultFactory $validationResultFactory
* @param NotAnEmptyString $notAnEmptyString
* @param NoSpaceBeforeAndAfterString $noSpaceBeforeAndAfterString
* @param ProductRepositoryInterface $productRepository
*/
public function __construct(
ValidationResultFactory $validationResultFactory,
NotAnEmptyString $notAnEmptyString,
NoSpaceBeforeAndAfterString $noSpaceBeforeAndAfterString
NoSpaceBeforeAndAfterString $noSpaceBeforeAndAfterString,
?ProductRepositoryInterface $productRepository = null
) {
$this->validationResultFactory = $validationResultFactory;
$this->notAnEmptyString = $notAnEmptyString;
$this->noSpaceBeforeAndAfterString = $noSpaceBeforeAndAfterString;
$this->productRepository = $productRepository ?:
\Magento\Framework\App\ObjectManager::getInstance()->get(ProductRepositoryInterface::class);
}

/**
Expand All @@ -57,9 +68,32 @@ public function validate(SourceItemInterface $source): ValidationResult
$value = $source->getSku();
$errors = [
$this->notAnEmptyString->execute(SourceItemInterface::SKU, (string)$value),
$this->noSpaceBeforeAndAfterString->execute(SourceItemInterface::SKU, (string)$value)
$this->noSpaceBeforeAndAfterString->execute(SourceItemInterface::SKU, (string)$value),
$this->validateSkuExists((string)$value)
];
$errors = array_merge(...$errors);
return $this->validationResultFactory->create(['errors' => $errors]);
}

/**
* Validate that product with given SKU exists
*
* @param string $sku
* @return array
*/
private function validateSkuExists(string $sku): array
{
$errors = [];
if (empty($sku)) {
return $errors;
}

try {
$this->productRepository->get($sku);
} catch (NoSuchEntityException $e) {
$errors[] = __('Product with SKU "%1" does not exist.', $sku);
}

return $errors;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

namespace Magento\Inventory\Test\Unit\Model\SourceItem\Validator;

use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Phrase;
use Magento\Framework\Validation\ValidationResult;
use Magento\Framework\Validation\ValidationResultFactory;
Expand Down Expand Up @@ -35,6 +38,11 @@ class SkuValidatorTest extends TestCase
*/
private $noSpaceBeforeAndAfterString;

/**
* @var ProductRepositoryInterface|MockObject
*/
private $productRepository;

/**
* @var SourceItem|MockObject
*/
Expand All @@ -50,12 +58,14 @@ protected function setUp(): void
$this->validationResultFactory = $this->createMock(ValidationResultFactory::class);
$this->notAnEmptyString = $this->createMock(NotAnEmptyString::class);
$this->noSpaceBeforeAndAfterString = $this->createMock(NoSpaceBeforeAndAfterString::class);
$this->productRepository = $this->createMock(ProductRepositoryInterface::class);
$this->sourceItemMock = $this->getMockBuilder(SourceItem::class)->disableOriginalConstructor()
->onlyMethods(['getSku', 'getSourceCode', 'getQuantity', 'getStatus', 'getData', 'setData'])->getMock();
$this->skuValidator = new SkuValidator(
$this->validationResultFactory,
$this->notAnEmptyString,
$this->noSpaceBeforeAndAfterString
$this->noSpaceBeforeAndAfterString,
$this->productRepository
);
}

Expand Down Expand Up @@ -98,9 +108,14 @@ public function testValidate(array $source): void
$errors = [$source['execute']];
$errors = array_merge(...$errors);
$this->noSpaceBeforeAndAfterString->method('execute')->willReturn($source['execute']);
$this->validationResultFactory->method('create')->with(
['errors' => $errors]
)->willReturn(new ValidationResult($errors));

// Mock product repository to return existing product
$product = $this->createMock(ProductInterface::class);
$this->productRepository->method('get')->willReturn($product);

$this->validationResultFactory->method('create')->with(
['errors' => $errors]
)->willReturn(new ValidationResult($errors));
$result = $this->skuValidator->validate($this->sourceItemMock);
if ($source['is_string_whitespace']) {
foreach ($result->getErrors() as $error) {
Expand All @@ -110,4 +125,40 @@ public function testValidate(array $source): void
$this->assertEmpty($result->getErrors());
}
}

/**
* Test validation when SKU does not exist
*
* @return void
*/
public function testValidateNonExistentSku(): void
{
$sku = 'non_existent_sku';
$this->sourceItemMock->expects($this->atLeastOnce())->method('getSku')
->willReturn($sku);

$this->notAnEmptyString->method('execute')->willReturn([]);
$this->noSpaceBeforeAndAfterString->method('execute')->willReturn([]);

// Mock product repository to throw NoSuchEntityException
$this->productRepository->expects($this->once())
->method('get')
->with($sku)
->willThrowException(new NoSuchEntityException(__('Product not found')));

$expectedError = __('Product with SKU "%1" does not exist.', $sku);
$errors = [$expectedError];

$this->validationResultFactory->method('create')->with(
['errors' => $errors]
)->willReturn(new ValidationResult($errors));

$result = $this->skuValidator->validate($this->sourceItemMock);

$this->assertCount(1, $result->getErrors());
$errorMessage = $result->getErrors()[0];
$this->assertInstanceOf(Phrase::class, $errorMessage);
$this->assertEquals('Product with SKU "%1" does not exist.', $errorMessage->getText());
$this->assertEquals(['non_existent_sku'], $errorMessage->getArguments());
}
}