Skip to content

Commit

Permalink
Merge branch 'next-37095/avoid-negative-review-offset' into 'trunk'
Browse files Browse the repository at this point in the history
NEXT-37095 - avoid negative offset in review call

See merge request shopware/6/product/platform!14207
  • Loading branch information
tobiasberge committed Jul 19, 2024
2 parents 678ce7c + 41191f3 commit f7ae5a6
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 34 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
title: Avoid negative reviews offset
issue: NEXT-37095
---
# Storefront
* Changed `Shopware\Storefront\Page\Product\Review\ProductReviewLoader::createCriteria` to avoid negative offset for review pagination.
2 changes: 1 addition & 1 deletion src/Storefront/Page/Product/Review/ProductReviewLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ private function createCriteria(Request $request, SalesChannelContext $context):
{
$limit = (int) $request->get('limit', self::LIMIT);
$page = (int) $request->get('p', self::DEFAULT_PAGE);
$offset = $limit * ($page - 1);
$offset = max(0, $limit * ($page - 1));

$criteria = new Criteria();
$criteria->setLimit($limit);
Expand Down
166 changes: 133 additions & 33 deletions tests/unit/Storefront/Page/Product/Review/ProductReviewLoaderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ public function testExceptionWithoutProductId(): void
$request = new Request([], [], []);
$salesChannelContext = $this->getSalesChannelContext();

$productReviewLoader = $this->getProductReviewLoader(null, $request, $salesChannelContext);
$productReviewRouteMock = $this->createMock(ProductReviewRoute::class);

$productReviewLoader = $this->getProductReviewLoader($productReviewRouteMock);

$this->expectException(RoutingException::class);

Expand All @@ -73,12 +75,94 @@ public function testItLoadsReviewsWithProductId(): void
$review,
]);

$productReviewLoader = $this->getProductReviewLoader($reviews, $request, $salesChannelContext);
$productReviewRouteMock = $this->createMock(ProductReviewRoute::class);
$productReviewLoader = $this->getProductReviewLoader($productReviewRouteMock);

$reviewResult = $this->getDefaultResult($reviews, $request, $salesChannelContext);

$productReviewRouteMock
->method('load')
->willReturn(
new ProductReviewRouteResponse($reviewResult)
);

$result = $productReviewLoader->load($request, $salesChannelContext);

static::assertInstanceOf(ProductReviewEntity::class, $result->first());
static::assertEquals($result->first()->getId(), $reviewId);
static::assertCount(1, $result);
static::assertNull($result->getCustomerReview());
}

public function testItLoadsReviewsPagination(): void
{
$reviewId = Uuid::randomHex();
$productId = Uuid::randomHex();
$request = new Request([], [], ['productId' => $productId, 'p' => 2]);
$salesChannelContext = $this->getSalesChannelContext(false);

$review = $this->getReviewEntity($reviewId);

$reviews = new ProductReviewCollection([
$review,
]);

$productReviewRouteMock = $this->createMock(ProductReviewRoute::class);
$productReviewLoader = $this->getProductReviewLoader($productReviewRouteMock);

$reviewResult = $this->getDefaultResult($reviews, $request, $salesChannelContext);

$criteria = $this->createCriteria($request, $salesChannelContext);

$productReviewRouteMock
->method('load')
->with($productId, $request, $salesChannelContext, $criteria)
->willReturn(
new ProductReviewRouteResponse($reviewResult)
);

$result = $productReviewLoader->load($request, $salesChannelContext);

$firstResult = $result->first();
static::assertInstanceOf(ProductReviewEntity::class, $firstResult);
static::assertEquals($firstResult->getId(), $reviewId);
static::assertEquals($result->getCriteria()->getOffset(), 10);
static::assertCount(1, $result);
static::assertNull($result->getCustomerReview());
}

public function testNegativeOffsetDefaultsToZero(): void
{
$reviewId = Uuid::randomHex();
$productId = Uuid::randomHex();
$request = new Request([], [], ['productId' => $productId, 'p' => -2]);
$salesChannelContext = $this->getSalesChannelContext(false);

$review = $this->getReviewEntity($reviewId);

$reviews = new ProductReviewCollection([
$review,
]);

$productReviewRouteMock = $this->createMock(ProductReviewRoute::class);
$productReviewLoader = $this->getProductReviewLoader($productReviewRouteMock);

$reviewResult = $this->getDefaultResult($reviews, $request, $salesChannelContext);

$criteria = $this->createCriteria($request, $salesChannelContext);

$productReviewRouteMock
->method('load')
->with($productId, $request, $salesChannelContext, $criteria)
->willReturn(
new ProductReviewRouteResponse($reviewResult)
);

$result = $productReviewLoader->load($request, $salesChannelContext);

static::assertInstanceOf(ProductReviewEntity::class, $result->first());
static::assertEquals($result->first()->getId(), $reviewId);
static::assertEquals($result->getCriteria()->getOffset(), 0);
static::assertCount(1, $result);
static::assertNull($result->getCustomerReview());
}
Expand All @@ -96,7 +180,16 @@ public function testItLoadsReviewsWithParentId(): void
$review,
]);

$productReviewLoader = $this->getProductReviewLoader($reviews, $request, $salesChannelContext);
$productReviewRouteMock = $this->createMock(ProductReviewRoute::class);
$productReviewLoader = $this->getProductReviewLoader($productReviewRouteMock);

$reviewResult = $this->getDefaultResult($reviews, $request, $salesChannelContext);

$productReviewRouteMock
->method('load')
->willReturn(
new ProductReviewRouteResponse($reviewResult)
);

$result = $productReviewLoader->load($request, $salesChannelContext);

Expand All @@ -120,7 +213,17 @@ public function testItLoadsReviewsWithPointsFilter(): void
$review,
]);

$productReviewLoader = $this->getProductReviewLoader($reviews, $request, $salesChannelContext);
$productReviewRouteMock = $this->createMock(ProductReviewRoute::class);
$productReviewLoader = $this->getProductReviewLoader($productReviewRouteMock);

$reviewResult = $this->getDefaultResult($reviews, $request, $salesChannelContext);

$productReviewRouteMock
->method('load')
->willReturn(
new ProductReviewRouteResponse($reviewResult)
);


$result = $productReviewLoader->load($request, $salesChannelContext);

Expand All @@ -142,41 +245,38 @@ private function getReviewEntity(string $reviewId): ProductReviewEntity
}

private function getProductReviewLoader(
?ProductReviewCollection $reviews,
Request $request,
SalesChannelContext $salesChannelContext
ProductReviewRoute $productReviewRouteMock
): ProductReviewLoader {
$productReviewRouteMock = $this->createMock(ProductReviewRoute::class);

$criteria = $this->createCriteria($request, $salesChannelContext);

if ($reviews !== null) {
$reviewResult = new EntitySearchResult(
ProductReviewDefinition::ENTITY_NAME,
1,
$reviews,
new AggregationResultCollection(
[
'ratingMatrix' => new TermsResult('ratingMatrix', []),
]
),
$criteria,
Context::createDefaultContext()
);

$productReviewRouteMock
->method('load')
->willReturn(
new ProductReviewRouteResponse($reviewResult)
);
}

return new ProductReviewLoader(
$productReviewRouteMock,
$this->createMock(EventDispatcherInterface::class)
);
}

/**
* @return EntitySearchResult<ProductReviewCollection>
*/
private function getDefaultResult(
ProductReviewCollection $reviews,
Request $request,
SalesChannelContext $salesChannelContext
): EntitySearchResult {
$criteria = $this->createCriteria($request, $salesChannelContext);

return new EntitySearchResult(
ProductReviewDefinition::ENTITY_NAME,
1,
$reviews,
new AggregationResultCollection(
[
'ratingMatrix' => new TermsResult('ratingMatrix', []),
]
),
$criteria,
Context::createDefaultContext()
);
}

private function getSalesChannelContext(bool $setCustomer = true): SalesChannelContext
{
$salesChannelEntity = new SalesChannelEntity();
Expand Down Expand Up @@ -211,7 +311,7 @@ private function createCriteria(Request $request, SalesChannelContext $context):
{
$limit = (int) $request->get('limit', 10);
$page = (int) $request->get('p', 1);
$offset = $limit * ($page - 1);
$offset = max(0, $limit * ($page - 1));

$criteria = new Criteria();
$criteria->setLimit($limit);
Expand Down

0 comments on commit f7ae5a6

Please sign in to comment.