mirror of
https://github.com/Sylius/Sylius.git
synced 2026-07-14 17:10:53 +00:00
[ApiBundle] Add contract tests for Promotion resources
This commit is contained in:
parent
1c32900ec5
commit
214f066b08
11 changed files with 407 additions and 18 deletions
|
|
@ -40,7 +40,6 @@ final class PromotionDocumentationModifier implements DocumentationModifierInter
|
|||
return $docs->withPaths($paths);
|
||||
}
|
||||
|
||||
|
||||
public function addDescription(Paths $paths, string $path, string $method): void
|
||||
{
|
||||
$pathItem = $paths->getPath($path);
|
||||
|
|
@ -51,7 +50,7 @@ final class PromotionDocumentationModifier implements DocumentationModifierInter
|
|||
"%s\n\n Allowed rule types: `%s` \n\n Allowed action types: `%s`",
|
||||
$operation->getDescription(),
|
||||
implode('`, `', array_keys($this->ruleTypes)),
|
||||
implode('`, `', array_keys($this->actionTypes))
|
||||
implode('`, `', array_keys($this->actionTypes)),
|
||||
);
|
||||
|
||||
$operation = $operation->withDescription($description);
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ api_platform:
|
|||
Sylius\Bundle\ApiBundle\Exception\TranslationLocaleMismatchException: 422
|
||||
Sylius\Bundle\ApiBundle\Exception\ZoneCannotBeRemoved: 422
|
||||
Sylius\Bundle\ApiBundle\Exception\CannotRemoveMenuTaxonException: 409
|
||||
Sylius\Bundle\ApiBundle\Exception\PromotionCannotBeRemoved: 422
|
||||
Sylius\Bundle\LocaleBundle\Checker\Exception\LocaleIsUsedException: 422
|
||||
Sylius\Bundle\UserBundle\Exception\UserNotFoundException: 404
|
||||
Symfony\Component\Serializer\Exception\UnexpectedValueException: 400
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ declare(strict_types=1);
|
|||
namespace Sylius\Tests\Api\Admin;
|
||||
|
||||
use Sylius\Component\Core\Model\PromotionInterface;
|
||||
use Sylius\Component\Core\Promotion\Action\FixedDiscountPromotionActionCommand;
|
||||
use Sylius\Component\Promotion\Checker\Rule\CartQuantityRuleChecker;
|
||||
use Sylius\Tests\Api\JsonApiTestCase;
|
||||
use Sylius\Tests\Api\Utils\AdminUserLoginTrait;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
|
@ -25,7 +27,7 @@ final class PromotionsTest extends JsonApiTestCase
|
|||
/** @test */
|
||||
public function it_gets_a_promotion(): void
|
||||
{
|
||||
$fixtures = $this->loadFixturesFromFiles(['authentication/api_administrator.yaml', 'channel.yaml', 'promotion.yaml']);
|
||||
$fixtures = $this->loadFixturesFromFiles(['authentication/api_administrator.yaml', 'channel.yaml', 'promotion/promotion.yaml']);
|
||||
$header = array_merge($this->logInAdminUser('api@example.com'), self::CONTENT_TYPE_HEADER);
|
||||
|
||||
/** @var PromotionInterface $promotion */
|
||||
|
|
@ -47,7 +49,7 @@ final class PromotionsTest extends JsonApiTestCase
|
|||
/** @test */
|
||||
public function it_gets_promotions(): void
|
||||
{
|
||||
$this->loadFixturesFromFiles(['authentication/api_administrator.yaml', 'channel.yaml', 'promotion.yaml']);
|
||||
$this->loadFixturesFromFiles(['authentication/api_administrator.yaml', 'channel.yaml', 'promotion/promotion.yaml']);
|
||||
$header = array_merge($this->logInAdminUser('api@example.com'), self::CONTENT_TYPE_HEADER);
|
||||
|
||||
$this->client->request(method: 'GET', uri: '/api/v2/admin/promotions', server: $header);
|
||||
|
|
@ -61,6 +63,105 @@ final class PromotionsTest extends JsonApiTestCase
|
|||
|
||||
/** @test */
|
||||
public function it_creates_promotion(): void
|
||||
{
|
||||
$this->loadFixturesFromFiles(['authentication/api_administrator.yaml', 'channel.yaml']);
|
||||
$header = array_merge($this->logInAdminUser('api@example.com'), self::CONTENT_TYPE_HEADER);
|
||||
|
||||
$this->client->request(
|
||||
method: 'POST',
|
||||
uri: '/api/v2/admin/promotions',
|
||||
server: $header,
|
||||
content: json_encode([
|
||||
'name' => 'T-Shirts discount',
|
||||
'code' => 'tshirts_discount',
|
||||
'channels' => [
|
||||
'/api/v2/admin/channels/WEB',
|
||||
],
|
||||
'description' => 'T-Shirts discount',
|
||||
'priority' => 22,
|
||||
'appliesToDiscounted' => false,
|
||||
'exclusive' => true,
|
||||
"usageLimit" => 3,
|
||||
"couponBased" => true,
|
||||
'startsAt' => '2023-10-04 12:30:00',
|
||||
'endsAt' => '2023-11-04 12:30:00',
|
||||
'translations' => ['en_US' => [
|
||||
'label' => 'T-Shirts discount',
|
||||
]],
|
||||
'rules' => [
|
||||
[
|
||||
'type' => CartQuantityRuleChecker::TYPE,
|
||||
'configuration' => [
|
||||
'count' => 6
|
||||
],
|
||||
],
|
||||
],
|
||||
'actions' => [
|
||||
[
|
||||
'type' => FixedDiscountPromotionActionCommand::TYPE,
|
||||
'configuration' => [
|
||||
'WEB' => [
|
||||
'amount' => 1000,
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
], JSON_THROW_ON_ERROR),
|
||||
);
|
||||
|
||||
$this->assertResponse(
|
||||
$this->client->getResponse(),
|
||||
'admin/promotion/post_promotion_response',
|
||||
Response::HTTP_CREATED,
|
||||
);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_does_not_create_a_promotion_without_required_data(): void
|
||||
{
|
||||
$this->loadFixturesFromFiles(['authentication/api_administrator.yaml']);
|
||||
$header = array_merge($this->logInAdminUser('api@example.com'), self::CONTENT_TYPE_HEADER);
|
||||
|
||||
$this->client->request(
|
||||
method: 'POST',
|
||||
uri: '/api/v2/admin/promotions',
|
||||
server: $header,
|
||||
content: json_encode([], JSON_THROW_ON_ERROR),
|
||||
);
|
||||
|
||||
$this->assertResponse(
|
||||
$this->client->getResponse(),
|
||||
'admin/promotion/post_promotion_without_required_data_response',
|
||||
Response::HTTP_UNPROCESSABLE_ENTITY,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/** @test */
|
||||
public function it_does_not_create_a_promotion_with_taken_code(): void
|
||||
{
|
||||
$this->loadFixturesFromFiles(['authentication/api_administrator.yaml', 'channel.yaml', 'promotion/promotion.yaml']);
|
||||
$header = array_merge($this->logInAdminUser('api@example.com'), self::CONTENT_TYPE_HEADER);
|
||||
|
||||
$this->client->request(
|
||||
method: 'POST',
|
||||
uri: '/api/v2/admin/promotions',
|
||||
server: $header,
|
||||
content: json_encode([
|
||||
'name' => '50% Off on your first order',
|
||||
'code' => '50_off',
|
||||
], JSON_THROW_ON_ERROR),
|
||||
);
|
||||
|
||||
$this->assertResponse(
|
||||
$this->client->getResponse(),
|
||||
'admin/promotion/post_promotion_with_taken_code_response',
|
||||
Response::HTTP_UNPROCESSABLE_ENTITY,
|
||||
);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_does_not_create_a_promotion_with_end_date_earlier_than_start_date(): void
|
||||
{
|
||||
$this->loadFixturesFromFiles(['authentication/api_administrator.yaml']);
|
||||
$header = array_merge($this->logInAdminUser('api@example.com'), self::CONTENT_TYPE_HEADER);
|
||||
|
|
@ -72,17 +173,135 @@ final class PromotionsTest extends JsonApiTestCase
|
|||
content: json_encode([
|
||||
'name' => 'T-Shirts discount',
|
||||
'code' => 'tshirts_discount',
|
||||
'appliesToDiscounted' => false,
|
||||
'startsAt' => '2023-12-04 12:30:00',
|
||||
'endsAt' => '2023-11-04 12:30:00',
|
||||
], JSON_THROW_ON_ERROR),
|
||||
);
|
||||
|
||||
$this->assertResponse(
|
||||
$this->client->getResponse(),
|
||||
'admin/promotion/post_promotion_with_invalid_dates_response',
|
||||
Response::HTTP_UNPROCESSABLE_ENTITY,
|
||||
);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_updates_promotion(): void
|
||||
{
|
||||
$fixtures = $this->loadFixturesFromFiles(['authentication/api_administrator.yaml', 'channel.yaml', 'promotion/promotion.yaml']);
|
||||
$header = array_merge($this->logInAdminUser('api@example.com'), self::CONTENT_TYPE_HEADER);
|
||||
|
||||
/** @var PromotionInterface $promotion */
|
||||
$promotion = $fixtures['promotion_50_off'];
|
||||
|
||||
$this->client->request(
|
||||
method: 'PUT',
|
||||
uri: sprintf('/api/v2/admin/promotions/%s', $promotion->getCode()),
|
||||
server: $header,
|
||||
content: json_encode([
|
||||
'name' => 'Christmas',
|
||||
'code' => 'new_code',
|
||||
'appliesToDiscounted' => true,
|
||||
'exclusive' => true,
|
||||
"usageLimit" => 11,
|
||||
"couponBased" => false,
|
||||
'rules' => [
|
||||
[
|
||||
'type' => CartQuantityRuleChecker::TYPE,
|
||||
'configuration' => [
|
||||
'count' => 1
|
||||
],
|
||||
],
|
||||
],
|
||||
'actions' => [
|
||||
[
|
||||
'type' => FixedDiscountPromotionActionCommand::TYPE,
|
||||
'configuration' => [
|
||||
'WEB' => [
|
||||
'amount' => 2,
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
'channels' => [
|
||||
'/api/v2/admin/channels/MOBILE',
|
||||
],
|
||||
'translations' => ['en_US' => [
|
||||
'label' => 'T-Shirts discount',
|
||||
'@id' => sprintf('/api/v2/admin/promotion-translations/%s', $promotion->getTranslation('en_US')->getId()),
|
||||
'label' => 'Christmas',
|
||||
]],
|
||||
], JSON_THROW_ON_ERROR),
|
||||
);
|
||||
|
||||
$this->assertResponse(
|
||||
$this->client->getResponse(),
|
||||
'admin/promotion/post_promotion_response',
|
||||
Response::HTTP_CREATED,
|
||||
'admin/promotion/put_promotion_response',
|
||||
Response::HTTP_OK,
|
||||
);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_updates_promotion_with_null_priority(): void
|
||||
{
|
||||
$fixtures = $this->loadFixturesFromFiles(['authentication/api_administrator.yaml', 'channel.yaml', 'promotion/promotion.yaml']);
|
||||
$header = array_merge($this->logInAdminUser('api@example.com'), self::CONTENT_TYPE_HEADER);
|
||||
|
||||
/** @var PromotionInterface $promotion */
|
||||
$promotion = $fixtures['promotion_50_off'];
|
||||
|
||||
$this->client->request(
|
||||
method: 'PUT',
|
||||
uri: sprintf('/api/v2/admin/promotions/%s', $promotion->getCode()),
|
||||
server: $header,
|
||||
content: json_encode([
|
||||
'priority' => null,
|
||||
], JSON_THROW_ON_ERROR),
|
||||
);
|
||||
|
||||
$this->assertResponse(
|
||||
$this->client->getResponse(),
|
||||
'admin/promotion/put_promotion_with_null_priority_response',
|
||||
Response::HTTP_OK,
|
||||
);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_deletes_a_promotion(): void
|
||||
{
|
||||
$fixtures = $this->loadFixturesFromFiles(['authentication/api_administrator.yaml', 'channel.yaml', 'promotion/promotion.yaml']);
|
||||
$header = array_merge($this->logInAdminUser('api@example.com'), self::CONTENT_TYPE_HEADER);
|
||||
|
||||
/** @var PromotionInterface $promotion */
|
||||
$promotion = $fixtures['promotion_50_off'];
|
||||
|
||||
$this->client->request(
|
||||
method: 'DELETE',
|
||||
uri: sprintf('/api/v2/admin/promotions/%s', $promotion->getCode()),
|
||||
server: $header,
|
||||
);
|
||||
|
||||
$this->assertResponseCode($this->client->getResponse(), Response::HTTP_NO_CONTENT);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_does_not_delete_the_promotion_in_use(): void
|
||||
{
|
||||
$fixtures = $this->loadFixturesFromFiles([
|
||||
'authentication/api_administrator.yaml',
|
||||
'channel.yaml',
|
||||
'promotion/promotion.yaml',
|
||||
'promotion/promotion_order.yaml',
|
||||
]);
|
||||
$header = array_merge($this->logInAdminUser('api@example.com'), self::CONTENT_TYPE_HEADER);
|
||||
/** @var PromotionInterface $promotion */
|
||||
$promotion = $fixtures['promotion_50_off'];
|
||||
|
||||
$this->client->request(
|
||||
method: 'DELETE',
|
||||
uri: sprintf('/api/v2/admin/promotions/%s', $promotion->getCode()),
|
||||
server: $header,
|
||||
);
|
||||
|
||||
$this->assertResponseCode($this->client->getResponse(), Response::HTTP_UNPROCESSABLE_ENTITY);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
Sylius\Component\Core\Model\Order:
|
||||
order:
|
||||
channel: "@channel_web"
|
||||
currencyCode: "USD"
|
||||
localeCode: "en_US"
|
||||
state: "new"
|
||||
tokenValue: "token"
|
||||
promotions: ['@promotion_50_off']
|
||||
|
|
@ -2,21 +2,45 @@
|
|||
"@context": "\/api\/v2\/contexts\/Promotion",
|
||||
"@id": "\/api\/v2\/admin\/promotions\/tshirts_discount",
|
||||
"@type": "Promotion",
|
||||
"channels": [],
|
||||
"channels": [
|
||||
"\/api\/v2\/admin\/channels\/WEB"
|
||||
],
|
||||
"id":"@integer@",
|
||||
"code": "tshirts_discount",
|
||||
"name": "T-Shirts discount",
|
||||
"description": null,
|
||||
"priority": 0,
|
||||
"exclusive": false,
|
||||
"usageLimit": null,
|
||||
"description": "T-Shirts discount",
|
||||
"priority": 22,
|
||||
"exclusive": true,
|
||||
"usageLimit": 3,
|
||||
"used": 0,
|
||||
"startsAt": null,
|
||||
"endsAt": null,
|
||||
"couponBased": false,
|
||||
"startsAt": "2023-10-04 12:30:00",
|
||||
"endsAt": "2023-11-04 12:30:00",
|
||||
"couponBased": true,
|
||||
"coupons": [],
|
||||
"rules": [],
|
||||
"actions": [],
|
||||
"rules": [
|
||||
{
|
||||
"@id": "\/api\/v2\/admin\/promotion-rules\/@integer@",
|
||||
"@type": "PromotionRule",
|
||||
"id": @integer@,
|
||||
"type": "cart_quantity",
|
||||
"configuration": {
|
||||
"count": 6
|
||||
}
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"@id": "\/api\/v2\/admin\/promotion-actions\/@integer@",
|
||||
"@type": "PromotionAction",
|
||||
"id": @integer@,
|
||||
"type": "order_fixed_discount",
|
||||
"configuration": {
|
||||
"WEB": {
|
||||
"amount": 1000
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"appliesToDiscounted": false,
|
||||
"createdAt": @string@,
|
||||
"updatedAt": @string@,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"@context": "\/api\/v2\/contexts\/ConstraintViolationList",
|
||||
"@type": "ConstraintViolationList",
|
||||
"hydra:title": "An error occurred",
|
||||
"hydra:description": "endsAt: End date cannot be set prior start date.",
|
||||
"violations": [
|
||||
{
|
||||
"propertyPath": "endsAt",
|
||||
"message": "End date cannot be set prior start date.",
|
||||
"code": null
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"@context": "\/api\/v2\/contexts\/ConstraintViolationList",
|
||||
"@type": "ConstraintViolationList",
|
||||
"hydra:title": "An error occurred",
|
||||
"hydra:description": "code: The promotion with given code already exists.",
|
||||
"violations": [
|
||||
{
|
||||
"propertyPath": "code",
|
||||
"message": "The promotion with given code already exists.",
|
||||
"code": @string@
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"@context": "\/api\/v2\/contexts\/ConstraintViolationList",
|
||||
"@type": "ConstraintViolationList",
|
||||
"hydra:title": "An error occurred",
|
||||
"hydra:description": "code: Please enter promotion code.\nname: Please enter promotion name.",
|
||||
"violations": [
|
||||
{
|
||||
"propertyPath": "code",
|
||||
"message": "Please enter promotion code.",
|
||||
"code": @string@
|
||||
},
|
||||
{
|
||||
"propertyPath": "name",
|
||||
"message": "Please enter promotion name.",
|
||||
"code": @string@
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
{
|
||||
"@context": "\/api\/v2\/contexts\/Promotion",
|
||||
"@id": "\/api\/v2\/admin\/promotions\/50_off",
|
||||
"@type": "Promotion",
|
||||
"channels": [
|
||||
"\/api\/v2\/admin\/channels\/MOBILE"
|
||||
],
|
||||
"id": @integer@,
|
||||
"code": "50_off",
|
||||
"name": "Christmas",
|
||||
"description": "Get 50% off of your first purchase",
|
||||
"priority": 1,
|
||||
"exclusive": true,
|
||||
"usageLimit": 11,
|
||||
"used": 0,
|
||||
"startsAt": null,
|
||||
"endsAt": null,
|
||||
"couponBased": false,
|
||||
"coupons": [],
|
||||
"rules": [
|
||||
{
|
||||
"@id": "\/api\/v2\/admin\/promotion-rules\/@integer@",
|
||||
"@type": "PromotionRule",
|
||||
"id": @integer@,
|
||||
"type": "cart_quantity",
|
||||
"configuration": {
|
||||
"count": 1
|
||||
}
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"@id": "\/api\/v2\/admin\/promotion-actions\/@integer@",
|
||||
"@type": "PromotionAction",
|
||||
"id": @integer@,
|
||||
"type": "order_fixed_discount",
|
||||
"configuration": {
|
||||
"WEB": {
|
||||
"amount": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"appliesToDiscounted": true,
|
||||
"createdAt": @date@,
|
||||
"updatedAt": @date@,
|
||||
"translations": {
|
||||
"en_US": {
|
||||
"@id": "\/api\/v2\/admin\/promotion-translations\/@integer@",
|
||||
"@type": "PromotionTranslation",
|
||||
"id": @integer@,
|
||||
"label": "Christmas"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"@context": "\/api\/v2\/contexts\/Promotion",
|
||||
"@id": "\/api\/v2\/admin\/promotions\/50_off",
|
||||
"@type": "Promotion",
|
||||
"channels": [
|
||||
"\/api\/v2\/admin\/channels\/MOBILE"
|
||||
],
|
||||
"id": @integer@,
|
||||
"code": "50_off",
|
||||
"name": "50% Off on your first order",
|
||||
"description": "Get 50% off of your first purchase",
|
||||
"priority": 2,
|
||||
"exclusive": true,
|
||||
"usageLimit": 1,
|
||||
"used": 0,
|
||||
"startsAt": null,
|
||||
"endsAt": null,
|
||||
"couponBased": false,
|
||||
"coupons": [
|
||||
|
||||
],
|
||||
"rules": [
|
||||
|
||||
],
|
||||
"actions": [
|
||||
|
||||
],
|
||||
"appliesToDiscounted": false,
|
||||
"createdAt": @date@,
|
||||
"updatedAt": @date@,
|
||||
"translations": {
|
||||
"en_US": {
|
||||
"@id": "\/api\/v2\/admin\/promotion-translations\/@integer@",
|
||||
"@type": "PromotionTranslation",
|
||||
"id": @integer@,
|
||||
"label": "-50% on first order!"
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue