mirror of
https://github.com/Sylius/Sylius.git
synced 2026-07-15 01:20:59 +00:00
[API] Upgrade Product Association resource to API Platform 3 (#16749)
| Q | A |-----------------|----- | Branch? | api-platform-3 | Bug fix? | no | New feature? | no | BC breaks? | no | Deprecations? | no | Related tickets | | License | MIT TODO: - [ ] adjust Behat scenarios <!-- - Bug fixes must be submitted against the 1.13 branch - Features and deprecations must be submitted against the 1.14 branch - Features, removing deprecations and BC breaks must be submitted against the 2.0 branch - Make sure that the correct base branch is set To be sure you are not breaking any Backward Compatibilities, check the documentation: https://docs.sylius.com/en/latest/book/organization/backward-compatibility-promise.html -->
This commit is contained in:
commit
299b0f2eb5
16 changed files with 163 additions and 342 deletions
|
|
@ -9,7 +9,7 @@ Feature: Adding associations to an existing product
|
|||
And the store has "LG G3", "LG headphones" and "LG earphones" products
|
||||
And I am logged in as an administrator
|
||||
|
||||
@ui @mink:chromedriver @no-api
|
||||
@no-api @ui @mink:chromedriver
|
||||
Scenario: Adding an association to an existing product
|
||||
When I want to modify the "LG G3" product
|
||||
And I associate as "Accessories" the "LG headphones" and "LG earphones" products
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ Feature: Adding a new product with associations
|
|||
And the store has "LG headphones", "LG earphones", "LG G4" and "LG G5" products
|
||||
And I am logged in as an administrator
|
||||
|
||||
@ui @mink:chromedriver @no-api
|
||||
@no-api @ui @mink:chromedriver
|
||||
Scenario: Adding a new product with associations
|
||||
When I want to create a new simple product
|
||||
And I specify its code as "lg_g3"
|
||||
|
|
@ -25,7 +25,7 @@ Feature: Adding a new product with associations
|
|||
And this product should also have an association "Alternatives" with products "LG G4" and "LG G5"
|
||||
And the product "LG G3" should appear in the store
|
||||
|
||||
@ui @mink:chromedriver @no-api
|
||||
@no-api @ui @mink:chromedriver
|
||||
Scenario: Adding a new product with associations after changing associated items
|
||||
When I want to create a new simple product
|
||||
And I specify its code as "lg_g3"
|
||||
|
|
@ -40,7 +40,7 @@ Feature: Adding a new product with associations
|
|||
And this product should not have an association "Accessories" with product "LG earphones"
|
||||
And the product "LG G3" should appear in the store
|
||||
|
||||
@ui @mink:chromedriver @no-api
|
||||
@no-api @ui @mink:chromedriver
|
||||
Scenario: Adding a new product with association with numeric code
|
||||
Given the store has 123 product association type
|
||||
When I want to create a new simple product
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ Feature: Changing associations of an existing product
|
|||
And the store has "LG G3", "LG headphones" and "LG earphones" products
|
||||
And I am logged in as an administrator
|
||||
|
||||
@ui @mink:chromedriver @no-api
|
||||
@no-api @ui @mink:chromedriver
|
||||
Scenario: Changing associated products of a product association
|
||||
Given the product "LG G3" has an association "Accessories" with product "LG headphones"
|
||||
When I want to modify the "LG G3" product
|
||||
|
|
@ -30,7 +30,7 @@ Feature: Changing associations of an existing product
|
|||
When I change this product association's product to the "LG earphones" product
|
||||
Then this association should only have product "LG earphones"
|
||||
|
||||
@ui @mink:chromedriver @no-api
|
||||
@no-api @ui @mink:chromedriver
|
||||
Scenario: Removing an associated product of a product association
|
||||
Given the product "LG G3" has an association "Accessories" with products "LG headphones" and "LG earphones"
|
||||
When I want to modify the "LG G3" product
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ Feature: Preventing a potential XSS attack while selecting similar product
|
|||
And the store has "<script>alert('xss')</script>" and "LG headphones" products
|
||||
And I am logged in as an administrator
|
||||
|
||||
@ui @mink:chromedriver @no-api
|
||||
@no-api @ui @mink:chromedriver
|
||||
Scenario: Preventing a potential XSS attack while editing product
|
||||
When I want to create a new simple product
|
||||
Then I should be able to associate as "Accessories" the "LG headphones" product
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ Feature: Viewing details of a product with variants
|
|||
And I should see product's meta keywords is "shield"
|
||||
And I should see product's short description is "good shield"
|
||||
|
||||
@todo-api @ui
|
||||
@api @ui
|
||||
Scenario: Viewing association types
|
||||
Given the store has a "Glass shield" product
|
||||
And the product "Iron Shield" has an association "Similar" with product "Glass shield"
|
||||
|
|
|
|||
|
|
@ -17,28 +17,28 @@ Feature: Viewing product's associations
|
|||
And the product "LG G3" has also an association "Alternatives" with products "LG G4" and "LG G5"
|
||||
And the product "LG Gram" has an association "Alternatives" with products "LG AC Adapter" and "LG headphones"
|
||||
|
||||
@ui @api
|
||||
@api @ui
|
||||
Scenario: Viewing a detailed page with product's associations in default locale
|
||||
Given I am browsing channel "Smartphone Store"
|
||||
When I view product "LG G3"
|
||||
Then I should see the product association "Accessories" with products "LG headphones" and "LG earphones"
|
||||
And I should also see the product association "Alternatives" with products "LG G4" and "LG G5"
|
||||
|
||||
@ui @api
|
||||
@api @ui
|
||||
Scenario: Viewing a detailed page with product's associations after locale change
|
||||
Given I am browsing channel "Smartphone Store"
|
||||
When I view product "LG G3" in the "Polish (Poland)" locale
|
||||
Then I should see the product association "Akcesoria" with products "LG headphones" and "LG earphones"
|
||||
And I should also see the product association "Alternatywy" with products "LG G4" and "LG G5"
|
||||
|
||||
@ui @api
|
||||
@api @ui
|
||||
Scenario: Viewing a detailed page with product's associations within current channel
|
||||
Given I am browsing channel "Notebook Store"
|
||||
When I view product "LG Gram"
|
||||
Then I should see the product association "Alternatives" with product "LG AC Adapter"
|
||||
And I should not see the product association "Alternatives" with product "LG headphones"
|
||||
|
||||
@ui @api
|
||||
@api @ui
|
||||
Scenario: Viewing a detailed page with enabled associated products only
|
||||
Given the "LG G4" product is disabled
|
||||
And I am browsing channel "Smartphone Store"
|
||||
|
|
@ -47,7 +47,7 @@ Feature: Viewing product's associations
|
|||
And I should also see the product association "Alternatives" with product "LG G5"
|
||||
And I should not see the product association "Alternatives" with product "LG G4"
|
||||
|
||||
@ui @api
|
||||
@api @ui
|
||||
Scenario: Viewing a detailed page while an empty association exists
|
||||
Given products "LG G4" and "LG G5" are disabled
|
||||
And I am browsing channel "Smartphone Store"
|
||||
|
|
|
|||
|
|
@ -17,15 +17,15 @@ use ApiPlatform\Doctrine\Orm\Extension\QueryItemExtensionInterface;
|
|||
use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface;
|
||||
use ApiPlatform\Metadata\Operation;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Sylius\Bundle\ApiBundle\Context\UserContextInterface;
|
||||
use Sylius\Bundle\ApiBundle\SectionResolver\ShopApiSection;
|
||||
use Sylius\Bundle\ApiBundle\Serializer\ContextKeys;
|
||||
use Sylius\Component\Core\Model\AdminUserInterface;
|
||||
use Sylius\Bundle\CoreBundle\SectionResolver\SectionProviderInterface;
|
||||
use Sylius\Component\Product\Model\ProductAssociationInterface;
|
||||
use Webmozart\Assert\Assert;
|
||||
|
||||
final readonly class EnabledProductsExtension implements QueryItemExtensionInterface
|
||||
{
|
||||
public function __construct(private UserContextInterface $userContext)
|
||||
public function __construct(private SectionProviderInterface $sectionProvider)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -45,8 +45,7 @@ final readonly class EnabledProductsExtension implements QueryItemExtensionInter
|
|||
return;
|
||||
}
|
||||
|
||||
$user = $this->userContext->getUser();
|
||||
if ($user instanceof AdminUserInterface && in_array('ROLE_API_ACCESS', $user->getRoles(), true)) {
|
||||
if (!$this->sectionProvider->getSection() instanceof ShopApiSection) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,8 +15,5 @@
|
|||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="https://api-platform.com/schema/metadata/properties-3.0 https://api-platform.com/schema/metadata/properties-3.0.xsd"
|
||||
>
|
||||
<property resource="Sylius\Component\Product\Model\ProductAssociation" name="id" identifier="true" writable="false"/>
|
||||
<property resource="Sylius\Component\Product\Model\ProductAssociation" name="type" required="true"/>
|
||||
<property resource="Sylius\Component\Product\Model\ProductAssociation" name="owner" required="true"/>
|
||||
<property resource="Sylius\Component\Product\Model\ProductAssociation" name="associatedProducts" required="true"/>
|
||||
<property resource="Sylius\Component\Product\Model\ProductAssociation" name="id" identifier="true" />
|
||||
</properties>
|
||||
|
|
|
|||
|
|
@ -17,17 +17,8 @@
|
|||
xsi:schemaLocation="https://api-platform.com/schema/metadata/resources-3.0 https://api-platform.com/schema/metadata/resources-3.0.xsd"
|
||||
>
|
||||
<resource class="Sylius\Component\Product\Model\ProductAssociation">
|
||||
<validationContext>
|
||||
<values>
|
||||
<value name="groups">
|
||||
<values>
|
||||
<value>sylius</value>
|
||||
</values>
|
||||
</value>
|
||||
</values>
|
||||
</validationContext>
|
||||
|
||||
<operations>
|
||||
<!-- Admin operations-->
|
||||
<operation class="ApiPlatform\Metadata\GetCollection" uriTemplate="/admin/product-associations">
|
||||
<normalizationContext>
|
||||
<values>
|
||||
|
|
@ -39,10 +30,22 @@
|
|||
</values>
|
||||
</normalizationContext>
|
||||
<filters>
|
||||
<filter>sylius.api.product_association_filter</filter>
|
||||
<filter>sylius_api.search_filter.admin.product_association</filter>
|
||||
</filters>
|
||||
</operation>
|
||||
|
||||
<operation class="ApiPlatform\Metadata\Get" uriTemplate="/admin/product-associations/{id}">
|
||||
<normalizationContext>
|
||||
<values>
|
||||
<value name="groups">
|
||||
<values>
|
||||
<value>sylius:admin:product_association:show</value>
|
||||
</values>
|
||||
</value>
|
||||
</values>
|
||||
</normalizationContext>
|
||||
</operation>
|
||||
|
||||
<operation class="ApiPlatform\Metadata\Post" uriTemplate="/admin/product-associations">
|
||||
<denormalizationContext>
|
||||
<values>
|
||||
|
|
@ -62,18 +65,15 @@
|
|||
</value>
|
||||
</values>
|
||||
</normalizationContext>
|
||||
</operation>
|
||||
|
||||
<operation class="ApiPlatform\Metadata\Get" uriTemplate="/admin/product-associations/{id}">
|
||||
<normalizationContext>
|
||||
<validationContext>
|
||||
<values>
|
||||
<value name="groups">
|
||||
<values>
|
||||
<value>sylius:admin:product_association:show</value>
|
||||
<value>sylius</value>
|
||||
</values>
|
||||
</value>
|
||||
</values>
|
||||
</normalizationContext>
|
||||
</validationContext>
|
||||
</operation>
|
||||
|
||||
<operation class="ApiPlatform\Metadata\Put" uriTemplate="/admin/product-associations/{id}">
|
||||
|
|
@ -95,10 +95,20 @@
|
|||
</value>
|
||||
</values>
|
||||
</normalizationContext>
|
||||
<validationContext>
|
||||
<values>
|
||||
<value name="groups">
|
||||
<values>
|
||||
<value>sylius</value>
|
||||
</values>
|
||||
</value>
|
||||
</values>
|
||||
</validationContext>
|
||||
</operation>
|
||||
|
||||
<operation class="ApiPlatform\Metadata\Delete" uriTemplate="/admin/product-associations/{id}" />
|
||||
|
||||
<!-- Shop operations-->
|
||||
<operation class="ApiPlatform\Metadata\Get" uriTemplate="/shop/product-associations/{id}">
|
||||
<normalizationContext>
|
||||
<values>
|
||||
|
|
@ -110,8 +120,6 @@
|
|||
</values>
|
||||
</normalizationContext>
|
||||
</operation>
|
||||
|
||||
</operations>
|
||||
</resource>
|
||||
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -1,105 +0,0 @@
|
|||
<?xml version="1.0" ?>
|
||||
|
||||
<!--
|
||||
|
||||
This file is part of the Sylius package.
|
||||
|
||||
(c) Sylius Sp. z o.o.
|
||||
|
||||
For the full copyright and license information, please view the LICENSE
|
||||
file that was distributed with this source code.
|
||||
|
||||
-->
|
||||
|
||||
<resources xmlns="https://api-platform.com/schema/metadata"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="https://api-platform.com/schema/metadata https://api-platform.com/schema/metadata/metadata-2.0.xsd"
|
||||
>
|
||||
<resource class="%sylius.model.product_association.class%" shortName="ProductAssociation">
|
||||
<attribute name="validation_groups">sylius</attribute>
|
||||
|
||||
<collectionOperations>
|
||||
<collectionOperation name="admin_get">
|
||||
<attribute name="method">GET</attribute>
|
||||
<attribute name="path">/admin/product-associations</attribute>
|
||||
<attribute name="filters">
|
||||
<attribute>sylius.api.product_association_filter</attribute>
|
||||
</attribute>
|
||||
<attribute name="normalization_context">
|
||||
<attribute name="groups">
|
||||
<attribute>admin:product_association:index</attribute>
|
||||
<attribute>sylius:admin:product_association:index</attribute>
|
||||
</attribute>
|
||||
</attribute>
|
||||
</collectionOperation>
|
||||
|
||||
<collectionOperation name="admin_post">
|
||||
<attribute name="method">POST</attribute>
|
||||
<attribute name="path">/admin/product-associations</attribute>
|
||||
<attribute name="denormalization_context">
|
||||
<attribute name="groups">
|
||||
<attribute>admin:product_association:create</attribute>
|
||||
<attribute>sylius:admin:product_association:create</attribute>
|
||||
</attribute>
|
||||
</attribute>
|
||||
<attribute name="normalization_context">
|
||||
<attribute name="groups">
|
||||
<attribute>admin:product_association:show</attribute>
|
||||
<attribute>sylius:admin:product_association:show</attribute>
|
||||
</attribute>
|
||||
</attribute>
|
||||
</collectionOperation>
|
||||
</collectionOperations>
|
||||
|
||||
<itemOperations>
|
||||
<itemOperation name="admin_get">
|
||||
<attribute name="method">GET</attribute>
|
||||
<attribute name="path">/admin/product-associations/{id}</attribute>
|
||||
<attribute name="normalization_context">
|
||||
<attribute name="groups">
|
||||
<attribute>admin:product_association:show</attribute>
|
||||
<attribute>sylius:admin:product_association:show</attribute>
|
||||
</attribute>
|
||||
</attribute>
|
||||
</itemOperation>
|
||||
|
||||
<itemOperation name="admin_put">
|
||||
<attribute name="method">PUT</attribute>
|
||||
<attribute name="path">/admin/product-associations/{id}</attribute>
|
||||
<attribute name="denormalization_context">
|
||||
<attribute name="groups">
|
||||
<attribute>admin:product_association:update</attribute>
|
||||
<attribute>sylius:admin:product_association:update</attribute>
|
||||
</attribute>
|
||||
</attribute>
|
||||
<attribute name="normalization_context">
|
||||
<attribute name="groups">
|
||||
<attribute>admin:product_association:show</attribute>
|
||||
<attribute>sylius:admin:product_association:show</attribute>
|
||||
</attribute>
|
||||
</attribute>
|
||||
</itemOperation>
|
||||
|
||||
<itemOperation name="admin_delete">
|
||||
<attribute name="method">DELETE</attribute>
|
||||
<attribute name="path">/admin/product-associations/{id}</attribute>
|
||||
</itemOperation>
|
||||
|
||||
<itemOperation name="shop_get">
|
||||
<attribute name="method">GET</attribute>
|
||||
<attribute name="path">/shop/product-associations/{id}</attribute>
|
||||
<attribute name="normalization_context">
|
||||
<attribute name="groups">
|
||||
<attribute>shop:product_association:show</attribute>
|
||||
<attribute>sylius:shop:product_association:show</attribute>
|
||||
</attribute>
|
||||
</attribute>
|
||||
</itemOperation>
|
||||
</itemOperations>
|
||||
|
||||
<property name="id" identifier="true" writable="false" />
|
||||
<property name="type" identifier="false" required="true" />
|
||||
<property name="owner" required="true" />
|
||||
<property name="associatedProducts" required="true" />
|
||||
</resource>
|
||||
</resources>
|
||||
|
|
@ -17,37 +17,27 @@
|
|||
>
|
||||
<class name="Sylius\Component\Product\Model\ProductAssociation">
|
||||
<attribute name="id">
|
||||
<group>shop:product_association:show</group>
|
||||
<group>sylius:shop:product_association:show</group>
|
||||
</attribute>
|
||||
|
||||
<attribute name="type">
|
||||
<group>admin:product_association:index</group>
|
||||
<group>sylius:admin:product_association:index</group>
|
||||
<group>admin:product_association:show</group>
|
||||
<group>sylius:admin:product_association:show</group>
|
||||
<group>admin:product_association:create</group>
|
||||
<group>sylius:admin:product_association:create</group>
|
||||
<group>shop:product_association:show</group>
|
||||
<group>sylius:shop:product_association:show</group>
|
||||
</attribute>
|
||||
|
||||
<attribute name="owner">
|
||||
<group>admin:product_association:index</group>
|
||||
<group>sylius:admin:product_association:index</group>
|
||||
<group>admin:product_association:show</group>
|
||||
<group>sylius:admin:product_association:show</group>
|
||||
<group>admin:product_association:create</group>
|
||||
<group>sylius:admin:product_association:create</group>
|
||||
</attribute>
|
||||
|
||||
<attribute name="associatedProducts">
|
||||
<group>admin:product_association:index</group>
|
||||
<group>sylius:admin:product_association:index</group>
|
||||
<group>admin:product_association:show</group>
|
||||
<group>sylius:admin:product_association:show</group>
|
||||
<group>admin:product_association:create</group>
|
||||
<group>sylius:admin:product_association:create</group>
|
||||
<group>admin:product_association:update</group>
|
||||
<group>sylius:admin:product_association:update</group>
|
||||
<group>shop:product_association:show</group>
|
||||
<group>sylius:shop:product_association:show</group>
|
||||
</attribute>
|
||||
</class>
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@
|
|||
</service>
|
||||
|
||||
<service id="sylius_api.doctrine.orm.query_extension.shop.product_association.enabled_products" class="Sylius\Bundle\ApiBundle\Doctrine\ORM\QueryExtension\Shop\ProductAssociation\EnabledProductsExtension">
|
||||
<argument type="service" id="Sylius\Bundle\ApiBundle\Context\UserContextInterface" />
|
||||
<argument type="service" id="sylius.section_resolver.uri_based_section_resolver" />
|
||||
<tag name="api_platform.doctrine.orm.query_extension.item" />
|
||||
</service>
|
||||
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@
|
|||
<tag name="api_platform.filter" />
|
||||
</service>
|
||||
|
||||
<service id="sylius.api.product_association_filter" parent="api_platform.doctrine.orm.search_filter" public="true">
|
||||
<service id="sylius_api.search_filter.admin.product_association" parent="api_platform.doctrine.orm.search_filter" public="true">
|
||||
<argument type="collection">
|
||||
<argument key="owner.code">partial</argument>
|
||||
<argument key="type.code">partial</argument>
|
||||
|
|
|
|||
|
|
@ -17,28 +17,28 @@ use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface;
|
|||
use ApiPlatform\Metadata\Get;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use PhpSpec\ObjectBehavior;
|
||||
use Sylius\Bundle\ApiBundle\Context\UserContextInterface;
|
||||
use Sylius\Bundle\ApiBundle\SectionResolver\AdminApiSection;
|
||||
use Sylius\Bundle\ApiBundle\SectionResolver\ShopApiSection;
|
||||
use Sylius\Bundle\ApiBundle\Serializer\ContextKeys;
|
||||
use Sylius\Component\Core\Model\AdminUserInterface;
|
||||
use Sylius\Bundle\CoreBundle\SectionResolver\SectionProviderInterface;
|
||||
use Sylius\Component\Core\Model\ChannelInterface;
|
||||
use Sylius\Component\Core\Model\ProductVariantInterface;
|
||||
use Sylius\Component\Product\Model\ProductAssociationInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
|
||||
final class EnabledProductsExtensionSpec extends ObjectBehavior
|
||||
{
|
||||
function let(UserContextInterface $userContext): void
|
||||
function let(SectionProviderInterface $sectionProvider): void
|
||||
{
|
||||
$this->beConstructedWith($userContext);
|
||||
$this->beConstructedWith($sectionProvider);
|
||||
}
|
||||
|
||||
function it_does_nothing_if_current_resource_is_not_a_product_association(
|
||||
UserContextInterface $userContext,
|
||||
SectionProviderInterface $sectionProvider,
|
||||
QueryBuilder $queryBuilder,
|
||||
QueryNameGeneratorInterface $queryNameGenerator,
|
||||
): void {
|
||||
$userContext->getUser()->shouldNotBeCalled();
|
||||
$sectionProvider->getSection()->shouldNotBeCalled();
|
||||
$queryBuilder->getRootAliases()->shouldNotBeCalled();
|
||||
|
||||
$this->applyToItem(
|
||||
|
|
@ -50,16 +50,13 @@ final class EnabledProductsExtensionSpec extends ObjectBehavior
|
|||
);
|
||||
}
|
||||
|
||||
function it_does_nothing_if_current_user_is_an_admin_user(
|
||||
UserContextInterface $userContext,
|
||||
AdminUserInterface $adminUser,
|
||||
function it_does_nothing_if_section_is_not_shop_api(
|
||||
SectionProviderInterface $sectionProvider,
|
||||
QueryBuilder $queryBuilder,
|
||||
QueryNameGeneratorInterface $queryNameGenerator,
|
||||
AdminApiSection $section,
|
||||
): void {
|
||||
$userContext->getUser()->willReturn($adminUser);
|
||||
$adminUser->getRoles()->willReturn(['ROLE_API_ACCESS']);
|
||||
|
||||
$queryBuilder->getRootAliases()->shouldNotBeCalled();
|
||||
$sectionProvider->getSection()->willReturn($section);
|
||||
|
||||
$this->applyToItem(
|
||||
$queryBuilder,
|
||||
|
|
@ -71,14 +68,13 @@ final class EnabledProductsExtensionSpec extends ObjectBehavior
|
|||
}
|
||||
|
||||
function it_applies_conditions_for_customer(
|
||||
UserContextInterface $userContext,
|
||||
UserInterface $user,
|
||||
SectionProviderInterface $sectionProvider,
|
||||
QueryBuilder $queryBuilder,
|
||||
QueryNameGeneratorInterface $queryNameGenerator,
|
||||
ChannelInterface $channel,
|
||||
ShopApiSection $section,
|
||||
): void {
|
||||
$userContext->getUser()->willReturn($user);
|
||||
$user->getRoles()->willReturn([]);
|
||||
$sectionProvider->getSection()->willReturn($section);
|
||||
|
||||
$queryNameGenerator->generateParameterName('enabled')->shouldBeCalled()->willReturn('enabled');
|
||||
$queryNameGenerator->generateParameterName('channel')->shouldBeCalled()->willReturn('channel');
|
||||
|
|
|
|||
|
|
@ -19,8 +19,34 @@ use Symfony\Component\HttpFoundation\Response;
|
|||
|
||||
final class ProductAssociationsTest extends JsonApiTestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->setUpAdminContext();
|
||||
$this->setUpDefaultGetHeaders();
|
||||
$this->setUpDefaultPostHeaders();
|
||||
$this->setUpDefaultPutHeaders();
|
||||
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_gets_product_association(): void
|
||||
public function it_gets_product_associations(): void
|
||||
{
|
||||
$this->loadFixturesFromFiles([
|
||||
'product/product_with_many_locales.yaml',
|
||||
'authentication/api_administrator.yaml',
|
||||
]);
|
||||
|
||||
$this->requestGet('/api/v2/admin/product-associations');
|
||||
|
||||
$this->assertResponse(
|
||||
$this->client->getResponse(),
|
||||
'admin/product_association/get_product_association_collection_response',
|
||||
);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_gets_a_product_association(): void
|
||||
{
|
||||
$fixtures = $this->loadFixturesFromFiles([
|
||||
'authentication/api_administrator.yaml',
|
||||
|
|
@ -29,20 +55,12 @@ final class ProductAssociationsTest extends JsonApiTestCase
|
|||
|
||||
/** @var ProductAssociationInterface $association */
|
||||
$association = $fixtures['product_association'];
|
||||
$this->client->request(
|
||||
method: 'GET',
|
||||
uri: sprintf('/api/v2/admin/product-associations/%s', $association->getId()),
|
||||
server: $this
|
||||
->headerBuilder()
|
||||
->withJsonLdAccept()
|
||||
->withAdminUserAuthorization('api@example.com')
|
||||
->build(),
|
||||
);
|
||||
|
||||
$this->requestGet(sprintf('/api/v2/admin/product-associations/%s', $association->getId()));
|
||||
|
||||
$this->assertResponse(
|
||||
$this->client->getResponse(),
|
||||
'admin/product_association/get_product_association_response',
|
||||
Response::HTTP_OK,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -54,70 +72,29 @@ final class ProductAssociationsTest extends JsonApiTestCase
|
|||
'product/product_with_many_locales.yaml',
|
||||
]);
|
||||
|
||||
$this->client->request(
|
||||
method: 'GET',
|
||||
uri: '/api/v2/admin/product-associations/nope',
|
||||
server: $this
|
||||
->headerBuilder()
|
||||
->withJsonLdAccept()
|
||||
->withAdminUserAuthorization('api@example.com')
|
||||
->build(),
|
||||
);
|
||||
$this->requestGet('/api/v2/admin/product-associations/wrong_id');
|
||||
|
||||
$response = $this->client->getResponse();
|
||||
|
||||
$this->assertSame(Response::HTTP_NOT_FOUND, $response->getStatusCode());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_returns_product_association_collection(): void
|
||||
public function it_creates_a_product_association(): void
|
||||
{
|
||||
$this->loadFixturesFromFiles([
|
||||
'product/product_with_many_locales.yaml',
|
||||
'authentication/api_administrator.yaml',
|
||||
]);
|
||||
|
||||
$this->client->request(
|
||||
method: 'GET',
|
||||
uri: '/api/v2/admin/product-associations',
|
||||
server: $this
|
||||
->headerBuilder()
|
||||
->withJsonLdAccept()
|
||||
->withAdminUserAuthorization('api@example.com')
|
||||
->build(),
|
||||
);
|
||||
|
||||
$this->assertResponse(
|
||||
$this->client->getResponse(),
|
||||
'admin/product_association/get_product_association_collection_response',
|
||||
Response::HTTP_OK,
|
||||
);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_creates_product_association(): void
|
||||
{
|
||||
$this->loadFixturesFromFiles([
|
||||
'product/products_with_associations.yaml',
|
||||
'authentication/api_administrator.yaml',
|
||||
]);
|
||||
|
||||
$this->client->request(
|
||||
method: 'POST',
|
||||
uri: '/api/v2/admin/product-associations',
|
||||
server: $this
|
||||
->headerBuilder()
|
||||
->withJsonLdContentType()
|
||||
->withJsonLdAccept()
|
||||
->withAdminUserAuthorization('api@example.com')
|
||||
->build(),
|
||||
content: json_encode([
|
||||
$this->requestPost(
|
||||
'/api/v2/admin/product-associations',
|
||||
[
|
||||
'type' => '/api/v2/admin/product-association-types/similar_products',
|
||||
'owner' => '/api/v2/admin/products/CUP',
|
||||
'associatedProducts' => [
|
||||
'/api/v2/admin/products/MUG',
|
||||
],
|
||||
], \JSON_THROW_ON_ERROR),
|
||||
],
|
||||
);
|
||||
|
||||
$this->assertResponse(
|
||||
|
|
@ -127,94 +104,15 @@ final class ProductAssociationsTest extends JsonApiTestCase
|
|||
);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_updates_product_association(): void
|
||||
{
|
||||
$fixtures = $this->loadFixturesFromFiles([
|
||||
'product/products_with_associations.yaml',
|
||||
'authentication/api_administrator.yaml',
|
||||
]);
|
||||
|
||||
/** @var ProductAssociationInterface $association */
|
||||
$association = $fixtures['product_association'];
|
||||
$this->client->request(
|
||||
method: 'PUT',
|
||||
uri: sprintf('/api/v2/admin/product-associations/%s', $association->getId()),
|
||||
server: $this
|
||||
->headerBuilder()
|
||||
->withJsonLdContentType()
|
||||
->withJsonLdAccept()
|
||||
->withAdminUserAuthorization('api@example.com')
|
||||
->build(),
|
||||
content: json_encode([
|
||||
'associatedProducts' => [
|
||||
'/api/v2/admin/products/TANKARD',
|
||||
],
|
||||
], \JSON_THROW_ON_ERROR),
|
||||
);
|
||||
|
||||
$this->assertResponse(
|
||||
$this->client->getResponse(),
|
||||
'admin/product_association/put_product_association_response',
|
||||
Response::HTTP_OK,
|
||||
);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_deletes_product_association(): void
|
||||
{
|
||||
$fixtures = $this->loadFixturesFromFiles([
|
||||
'product/products_with_associations.yaml',
|
||||
'authentication/api_administrator.yaml',
|
||||
]);
|
||||
|
||||
$header = $this
|
||||
->headerBuilder()
|
||||
->withJsonLdAccept()
|
||||
->withAdminUserAuthorization('api@example.com')
|
||||
->build()
|
||||
;
|
||||
|
||||
/** @var ProductAssociationInterface $association */
|
||||
$association = $fixtures['product_association'];
|
||||
$associationId = $association->getId();
|
||||
|
||||
$this->client->request(
|
||||
method: 'DELETE',
|
||||
uri: sprintf('/api/v2/admin/product-associations/%s', $associationId),
|
||||
server: $header,
|
||||
);
|
||||
|
||||
$this->assertResponseCode($this->client->getResponse(), Response::HTTP_NO_CONTENT);
|
||||
|
||||
$this->client->request(
|
||||
method: 'GET',
|
||||
uri: sprintf('/api/v2/admin/product-associations/%s', $associationId),
|
||||
server: $header,
|
||||
);
|
||||
|
||||
$this->assertResponseCode($this->client->getResponse(), Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_does_not_create_product_association_without_required_data(): void
|
||||
{
|
||||
$this->loadFixturesFromFiles([
|
||||
'product/products_with_associations.yaml',
|
||||
'authentication/api_administrator.yaml',
|
||||
'product/products_with_associations.yaml',
|
||||
]);
|
||||
|
||||
$this->client->request(
|
||||
method: 'POST',
|
||||
uri: '/api/v2/admin/product-associations',
|
||||
server: $this
|
||||
->headerBuilder()
|
||||
->withJsonLdContentType()
|
||||
->withJsonLdAccept()
|
||||
->withAdminUserAuthorization('api@example.com')
|
||||
->build(),
|
||||
content: '{}',
|
||||
);
|
||||
$this->requestPost('/api/v2/admin/product-associations', []);
|
||||
|
||||
$this->assertResponse(
|
||||
$this->client->getResponse(),
|
||||
|
|
@ -227,26 +125,19 @@ final class ProductAssociationsTest extends JsonApiTestCase
|
|||
public function it_does_not_create_duplicated_product_association(): void
|
||||
{
|
||||
$fixtures = $this->loadFixturesFromFiles([
|
||||
'product/products_with_associations.yaml',
|
||||
'authentication/api_administrator.yaml',
|
||||
'product/products_with_associations.yaml',
|
||||
]);
|
||||
|
||||
/** @var ProductAssociationInterface $association */
|
||||
$association = $fixtures['product_association'];
|
||||
|
||||
$this->client->request(
|
||||
method: 'POST',
|
||||
uri: '/api/v2/admin/product-associations',
|
||||
server: $this
|
||||
->headerBuilder()
|
||||
->withJsonLdContentType()
|
||||
->withJsonLdAccept()
|
||||
->withAdminUserAuthorization('api@example.com')
|
||||
->build(),
|
||||
content: json_encode([
|
||||
$this->requestPost(
|
||||
'/api/v2/admin/product-associations',
|
||||
[
|
||||
'type' => sprintf('/api/v2/admin/product-association-types/%s', $association->getType()->getCode()),
|
||||
'owner' => sprintf('/api/v2/admin/products/%s', $association->getOwner()->getCode()),
|
||||
], \JSON_THROW_ON_ERROR),
|
||||
],
|
||||
);
|
||||
|
||||
$this->assertResponse(
|
||||
|
|
@ -255,4 +146,51 @@ final class ProductAssociationsTest extends JsonApiTestCase
|
|||
Response::HTTP_UNPROCESSABLE_ENTITY,
|
||||
);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_updates_a_product_association(): void
|
||||
{
|
||||
$fixtures = $this->loadFixturesFromFiles([
|
||||
'authentication/api_administrator.yaml',
|
||||
'product/products_with_associations.yaml',
|
||||
]);
|
||||
|
||||
/** @var ProductAssociationInterface $association */
|
||||
$association = $fixtures['product_association'];
|
||||
|
||||
$this->requestPut(
|
||||
sprintf('/api/v2/admin/product-associations/%s', $association->getId()),
|
||||
[
|
||||
'associatedProducts' => [
|
||||
'/api/v2/admin/products/TANKARD',
|
||||
],
|
||||
],
|
||||
);
|
||||
|
||||
$this->assertResponse(
|
||||
$this->client->getResponse(),
|
||||
'admin/product_association/put_product_association_response',
|
||||
);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_deletes_a_product_association(): void
|
||||
{
|
||||
$fixtures = $this->loadFixturesFromFiles([
|
||||
'authentication/api_administrator.yaml',
|
||||
'product/products_with_associations.yaml',
|
||||
]);
|
||||
|
||||
/** @var ProductAssociationInterface $association */
|
||||
$association = $fixtures['product_association'];
|
||||
$associationId = $association->getId();
|
||||
|
||||
$this->requestDelete(sprintf('/api/v2/admin/product-associations/%s', $associationId));
|
||||
|
||||
$this->assertResponseCode($this->client->getResponse(), Response::HTTP_NO_CONTENT);
|
||||
|
||||
$this->requestGet(sprintf('/api/v2/admin/product-associations/%s', $associationId));
|
||||
|
||||
$this->assertResponseCode($this->client->getResponse(), Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
|
@ -19,6 +19,13 @@ use Symfony\Component\HttpFoundation\Response;
|
|||
|
||||
final class ProductAssociationsTest extends JsonApiTestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->setUpDefaultGetHeaders();
|
||||
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_gets_product_association(): void
|
||||
{
|
||||
|
|
@ -26,16 +33,12 @@ final class ProductAssociationsTest extends JsonApiTestCase
|
|||
|
||||
/** @var ProductAssociationInterface $association */
|
||||
$association = $fixtures['product_association'];
|
||||
$this->client->request(
|
||||
method: 'GET',
|
||||
uri: sprintf('/api/v2/shop/product-associations/%s', $association->getId()),
|
||||
server: self::CONTENT_TYPE_HEADER,
|
||||
);
|
||||
|
||||
$this->requestGet(sprintf('/api/v2/shop/product-associations/%s', $association->getId()));
|
||||
|
||||
$this->assertResponse(
|
||||
$this->client->getResponse(),
|
||||
'shop/product_association/get_product_association_response',
|
||||
Response::HTTP_OK,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -44,14 +47,9 @@ final class ProductAssociationsTest extends JsonApiTestCase
|
|||
{
|
||||
$this->loadFixturesFromFile('product/product_with_many_locales.yaml');
|
||||
|
||||
$this->client->request(
|
||||
method: 'GET',
|
||||
uri: sprintf('/api/v2/shop/product-associations/%s', 'wrong input'),
|
||||
server: self::CONTENT_TYPE_HEADER,
|
||||
);
|
||||
$this->requestGet(sprintf('/api/v2/shop/product-associations/%s', 'wrong_id'));
|
||||
|
||||
$response = $this->client->getResponse();
|
||||
|
||||
$this->assertSame(Response::HTTP_NOT_FOUND, $response->getStatusCode());
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue