mirror of
https://github.com/Sylius/Sylius.git
synced 2026-07-14 17:10:53 +00:00
Resolve conflicts between 2.1 and 2.2
This commit is contained in:
commit
16ee26b052
222 changed files with 2400 additions and 770 deletions
8
.github/workflows/matrix.json
vendored
8
.github/workflows/matrix.json
vendored
|
|
@ -27,14 +27,6 @@
|
|||
"mariadb": "11.4.7",
|
||||
"dbal": "^3.0",
|
||||
"state_machine_adapter": "symfony_workflow"
|
||||
},
|
||||
{
|
||||
"php": "8.5",
|
||||
"symfony": "^7.3",
|
||||
"mariadb": "11.4.7",
|
||||
"dbal": "^3.0",
|
||||
"state_machine_adapter": "symfony_workflow",
|
||||
"api_platform": "~4.1.7"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -2,5 +2,29 @@
|
|||
|
||||
### Deprecations
|
||||
|
||||
1. Not injecting a `tagged_iterator` with the tag `sylius_shop.modifier.address_form_values` into the constructor of `Sylius\Bundle\ShopBundle\Twig\Component\Checkout\Address\FormComponent` is deprecated since Sylius 2.2 and will be required in Sylius 3.0.
|
||||
|
||||
This change enables extending the checkout address form with custom fields or logic by registering services tagged with `sylius_shop.modifier.address_form_values`, which implement the `AddressFormValuesModifierInterface`.
|
||||
|
||||
```php
|
||||
public function __construct(
|
||||
OrderRepositoryInterface $repository,
|
||||
FormFactoryInterface $formFactory,
|
||||
string $resourceClass,
|
||||
string $formClass,
|
||||
protected readonly CustomerContextInterface $customerContext,
|
||||
protected readonly UserRepositoryInterface $shopUserRepository,
|
||||
protected readonly AddressRepositoryInterface $addressRepository,
|
||||
+ protected readonly ?iterable $addressFormValuesModifiers = null,
|
||||
)
|
||||
```
|
||||
|
||||
1. Direct usage of `loader.svg` and `loader.gif` assets is deprecated.
|
||||
Use `@SyliusAdmin/shared/helper/loader.html.twig` or `@SyliusShop/shared/macro/loader.html.twig` instead.
|
||||
|
||||
### Translations
|
||||
|
||||
1. The `TranslationLocaleProvider` now ensures that the default locale (configured as `locale` in `config/parameters.yaml`)
|
||||
is always placed at the beginning of the returned locales array.
|
||||
Other locales remain in the same order as returned by the repository.
|
||||
|
||||
|
|
|
|||
41
UPGRADE-API-2.2.md
Normal file
41
UPGRADE-API-2.2.md
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# UPGRADE FROM `2.1` TO `2.2`
|
||||
|
||||
## HTTP Status Code Changes
|
||||
|
||||
### Missing Required Fields Validation
|
||||
|
||||
The HTTP status code for missing required fields in API requests has been changed from `400 Bad Request` to `422 Unprocessable Content` to follow REST API best practices and RFC 9110 semantics.
|
||||
|
||||
Additionally, the redundant `code` field has been removed from the error response body, as the status code is already available in the HTTP response headers.
|
||||
|
||||
**Before:**
|
||||
```json
|
||||
{
|
||||
"@context": "/api/v2/contexts/Error",
|
||||
"@type": "hydra:Error",
|
||||
"status": 400,
|
||||
"detail": "Request does not have the following required fields specified: email."
|
||||
}
|
||||
```
|
||||
|
||||
**After:**
|
||||
```json
|
||||
{
|
||||
"@context": "/api/v2/contexts/Error",
|
||||
"@type": "hydra:Error",
|
||||
"status": 422,
|
||||
"detail": "Request does not have the following required fields specified: email."
|
||||
}
|
||||
```
|
||||
|
||||
**Breaking changes:**
|
||||
1. HTTP status code changed: `400` → `422`
|
||||
2. Response body field `code` removed (was redundant with HTTP status header)
|
||||
|
||||
**Affected endpoints:** All POST/PATCH endpoints that validate required fields (e.g., `/api/v2/shop/customers`, `/api/v2/shop/orders/{token}/items`, etc.)
|
||||
|
||||
**Migration guide:**
|
||||
- If your API client checks `response.status === 400` for missing fields, change it to `response.status === 422`
|
||||
- If your API client reads `response.data.code`, use `response.status` (HTTP header) instead
|
||||
|
||||
**References:** RFC 9110 (400 = syntactic errors, 422 = semantic/validation errors)
|
||||
|
|
@ -31,9 +31,9 @@
|
|||
"ext-json": "*",
|
||||
"ext-simplexml": "*",
|
||||
"ext-sodium": "*",
|
||||
"api-platform/doctrine-orm": "^4.1.7",
|
||||
"api-platform/state": "^4.1.7",
|
||||
"api-platform/symfony": "^4.1.7",
|
||||
"api-platform/doctrine-orm": "^4.2.1",
|
||||
"api-platform/state": "^4.2.1",
|
||||
"api-platform/symfony": "^4.2.1",
|
||||
"babdev/pagerfanta-bundle": "^4.4",
|
||||
"behat/transliterator": "^1.5",
|
||||
"doctrine/collections": "^2.2",
|
||||
|
|
@ -214,7 +214,6 @@
|
|||
"mockery/mockery": "^1.6",
|
||||
"nyholm/psr7": "^1.8",
|
||||
"phparkitect/phparkitect": "^0.6",
|
||||
"phpspec/prophecy-phpunit": "^2.2",
|
||||
"phpstan/extension-installer": "^1.4",
|
||||
"phpstan/phpstan": "^2.0",
|
||||
"phpstan/phpstan-doctrine": "^2.0",
|
||||
|
|
|
|||
|
|
@ -67,3 +67,13 @@ Feature: Editing a zone
|
|||
And I save my changes
|
||||
Then I should be notified that it has been successfully edited
|
||||
And this zone name should be "EU"
|
||||
|
||||
@api @ui
|
||||
Scenario: Setting zone to the highest priority
|
||||
Given the store has a zone "European Union" with code "EU" and priority 0
|
||||
And it has the "France" country member
|
||||
When I want to modify the zone named "European Union"
|
||||
And I set its priority to "5"
|
||||
And I save my changes
|
||||
Then I should be notified that it has been successfully edited
|
||||
And the "European Union" zone should have priority 5
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
@managing_zones
|
||||
Feature: Editing a zone
|
||||
In order to change my my tax and shipping configuration
|
||||
As an Administrator
|
||||
I want to be able to edit a zone
|
||||
|
||||
Background:
|
||||
Given the store also has country "France"
|
||||
And the store has a zone "North America" with code "NA" and priority 2
|
||||
And the store has a zone "South America" with code "SA" and priority 1
|
||||
And the store has a zone "Australia" with code "AU" and priority 0
|
||||
And I am logged in as an administrator
|
||||
|
||||
@api @ui
|
||||
Scenario: Zones are sorted by priority in descending order by default
|
||||
When I want to see all zones in store
|
||||
Then I should see 3 zones in the list
|
||||
Then the first zone on the list should have name "North America"
|
||||
Then the last zone on the list should have name "Australia"
|
||||
|
||||
@api @ui
|
||||
Scenario: Zone's default priority is 0 which puts it at the bottom of the list
|
||||
Given the store has a zone "European Union" with code "EU"
|
||||
When I want to see all zones in store
|
||||
Then I should see 4 zones in the list
|
||||
And the last zone on the list should have name "European Union"
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
@managing_shipping_methods
|
||||
Feature: Validating delivery time range on shipping method form
|
||||
In order to avoid invalid delivery time configuration
|
||||
As an Administrator
|
||||
I want to be prevented from saving a shipping method when maximum delivery time is less than minimum
|
||||
|
||||
Background:
|
||||
Given the store operates on a channel named "Web-US" in "USD" currency
|
||||
And the store is available in "English (United States)"
|
||||
And the store has a zone "United States" with code "US"
|
||||
And I am logged in as an administrator
|
||||
|
||||
@ui @mink:chromedriver
|
||||
Scenario: Trying to add a shipping method with invalid delivery time range
|
||||
When I want to create a new shipping method
|
||||
And I specify its code as "DELIVERY_TIME_INVALID"
|
||||
And I name it "Delivery Time Invalid" in "English (United States)"
|
||||
And I define it for the zone named "United States"
|
||||
And I choose "Flat rate per shipment" calculator
|
||||
And I specify its amount as 10 for "Web-US" channel
|
||||
And I fill in "Minimum delivery time (days)" with "5"
|
||||
And I fill in "Maximum delivery time (days)" with "3"
|
||||
And I try to add it
|
||||
Then I should be notified that Maximum delivery time must be greater than or equal to the minimum.
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
@applying_taxes
|
||||
Feature: Apply taxes based on zone priority
|
||||
In order to pay correct taxes when a country belongs to multiple zones
|
||||
As a Customer
|
||||
I want the zone with higher priority to be used for tax calculation
|
||||
|
||||
Background:
|
||||
Given the store operates on a single channel
|
||||
Given the store operates in "France" and "Belgium"
|
||||
And there is a zone "The Rest of the World" containing all other countries
|
||||
And the store has a zone "European Union" with code "EU" and priority 2
|
||||
And it has the "France" country member
|
||||
And it also has the "Belgium" country member
|
||||
And default tax zone is "RoW"
|
||||
And the store has "No tax" tax rate of 0% for "Clothes" for the rest of the world
|
||||
And the store has "VAT" tax rate of 23% for "Clothes" within the "European Union" zone
|
||||
And the store has a product "T-Shirt" priced at "$100.00"
|
||||
And it belongs to "Clothes" tax category
|
||||
And I am a logged in customer
|
||||
|
||||
@api @ui
|
||||
Scenario: Applying tax from the higher priority zone
|
||||
Given I added product "T-Shirt" to the cart
|
||||
And I addressed the cart to "Belgium"
|
||||
When I check the details of my cart
|
||||
Then my cart total should be "$123.00"
|
||||
And my cart taxes should be "$23.00"
|
||||
|
||||
@api @ui
|
||||
Scenario: Applying tax from new zone zone when it has higher priority
|
||||
Given the store has a zone "Benelux countries" with code "BC" and priority 3
|
||||
And it also has the "Belgium" country member
|
||||
And the store has "VAT" tax rate of 0% for "Clothes" within the "Benelux countries" zone
|
||||
And I added product "T-Shirt" to the cart
|
||||
And I addressed the cart to "Belgium"
|
||||
When I check the details of my cart
|
||||
Then my cart total should be "$100.00"
|
||||
And there should be no taxes charged
|
||||
|
||||
@api @ui
|
||||
Scenario: Applying tax from current zone when the new one has lower priority
|
||||
Given the store has a zone "Benelux countries" with code "GU" and priority 1
|
||||
And it also has the "Belgium" country member
|
||||
And the store has "VAT" tax rate of 0% for "Clothes" within the "Benelux countries" zone
|
||||
And I added product "T-Shirt" to the cart
|
||||
And I addressed the cart to "Belgium"
|
||||
When I check the details of my cart
|
||||
Then my cart total should be "$123.00"
|
||||
And my cart taxes should be "$23.00"
|
||||
|
|
@ -129,6 +129,14 @@ final readonly class ManagingZonesContext implements Context
|
|||
$this->client->addRequestData('scope', $scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When I set its priority to :priority
|
||||
*/
|
||||
public function iSetsItsPriorityTo(int $priority): void
|
||||
{
|
||||
$this->client->addRequestData('priority', $priority);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When I (try to) add it
|
||||
*/
|
||||
|
|
@ -496,6 +504,37 @@ final readonly class ManagingZonesContext implements Context
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^the (first|last) zone on the list should have ([^"]+) "([^"]+)"$/
|
||||
*/
|
||||
public function theFirstZoneOnTheListShouldHave(string $togglePosition, string $field, string $value): void
|
||||
{
|
||||
$items = $this->responseChecker->getValue($this->client->getLastResponse(), 'hydra:member');
|
||||
if ('first' === $togglePosition) {
|
||||
$item = reset($items);
|
||||
} else {
|
||||
$item = end($items);
|
||||
}
|
||||
|
||||
Assert::same($item[$field], $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then the :zone zone should have priority :priority
|
||||
*/
|
||||
public function theZoneShouldHavePriority(ZoneInterface $zone, int $priority): void
|
||||
{
|
||||
Assert::true(
|
||||
$this->responseChecker->hasItemWithValues(
|
||||
$this->client->index(Resources::ZONES),
|
||||
[
|
||||
'name' => $zone->getName(),
|
||||
'priority' => $priority,
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
private function removeZoneMember(CountryInterface|ProvinceInterface|ZoneInterface $objectToRemove): void
|
||||
{
|
||||
$members = $this->client->getContent()['members'];
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ use Sylius\Behat\Context\Ui\Admin\Helper\SecurePasswordTrait;
|
|||
use Sylius\Behat\Service\SharedStorageInterface;
|
||||
use Sylius\Component\Core\Model\CustomerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request as HttpRequest;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Webmozart\Assert\Assert;
|
||||
|
||||
final class RegistrationContext implements Context
|
||||
|
|
@ -206,7 +207,7 @@ final class RegistrationContext implements Context
|
|||
$content['hydra:description'],
|
||||
'Request does not have the following required fields specified: ' . implode(', ', $fields) . '.',
|
||||
);
|
||||
Assert::same($this->shopClient->getLastResponse()->getStatusCode(), 400);
|
||||
Assert::same($this->shopClient->getLastResponse()->getStatusCode(), Response::HTTP_UNPROCESSABLE_ENTITY);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -84,12 +84,17 @@ final readonly class ZoneContext implements Context
|
|||
* @Given the store has (also) a zone :zoneName
|
||||
* @Given the store has a zone :zoneName with code :code
|
||||
* @Given the store also has a zone :zoneName with code :code
|
||||
* @Given the store has a zone :zoneName with code :code and priority :priority
|
||||
*/
|
||||
public function theStoreHasAZoneWithCode(string $zoneName, ?string $code = null): void
|
||||
public function theStoreHasAZoneWithCode(string $zoneName, ?string $code = null, ?int $priority = 0): void
|
||||
{
|
||||
$this->saveZone($this->createZone($zoneName, $code, Scope::ALL), 'zone');
|
||||
$zone = $this->createZone($zoneName, $code, Scope::ALL);
|
||||
$zone->setPriority($priority);
|
||||
|
||||
$this->saveZone($zone, 'zone');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @Given the store has zones :firstName, :secondName and :thirdName
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ declare(strict_types=1);
|
|||
namespace Sylius\Behat\Context\Ui\Admin;
|
||||
|
||||
use Behat\Behat\Context\Context;
|
||||
use Behat\Step\When;
|
||||
use Sylius\Behat\Element\Admin\ShippingMethod\FormElementInterface;
|
||||
use Sylius\Behat\Page\Admin\ShippingMethod\CreatePageInterface;
|
||||
use Sylius\Behat\Page\Admin\ShippingMethod\IndexPageInterface;
|
||||
|
|
@ -124,6 +125,12 @@ final readonly class ManagingShippingMethodsContext implements Context
|
|||
$this->shippingMethodFormElement->chooseCalculator($calculatorName);
|
||||
}
|
||||
|
||||
#[When('I fill in :label with :value')]
|
||||
public function iFillInWith(string $label, string $value): void
|
||||
{
|
||||
$this->shippingMethodFormElement->setField($label, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When I check (also) the :shippingMethodName shipping method
|
||||
*/
|
||||
|
|
@ -625,4 +632,12 @@ final readonly class ManagingShippingMethodsContext implements Context
|
|||
{
|
||||
Assert::same($this->shippingMethodFormElement->getValidationMessage($element), $expectedMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then I should be notified that Maximum delivery time must be greater than or equal to the minimum.
|
||||
*/
|
||||
public function iShouldBeNotifiedThatMaxDeliveryIsGreaterOrEqualMin(): void
|
||||
{
|
||||
$this->assertFieldValidationMessage('max_delivery_time_days', 'Maximum delivery time must be greater than or equal to the minimum.');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,6 +132,14 @@ final class ManagingZonesContext implements Context
|
|||
$this->formElement->selectScope($scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When I set its priority to :priority
|
||||
*/
|
||||
public function iSetItsPriorityTo(int $priority): void
|
||||
{
|
||||
$this->formElement->prioritizeIt($priority);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When I add it
|
||||
* @When I try to add it
|
||||
|
|
@ -338,4 +346,45 @@ final class ManagingZonesContext implements Context
|
|||
|
||||
throw new \InvalidArgumentException(sprintf('Member "%s" should not be selectable.', $name));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then the first zone on the list should have :field :value
|
||||
*/
|
||||
public function theFirstZoneOnTheListShouldHave(string $field, string $value): void
|
||||
{
|
||||
$fields = $this->indexPage->getColumnFields($field);
|
||||
$actualValue = reset($fields);
|
||||
|
||||
Assert::same(
|
||||
$actualValue,
|
||||
$value,
|
||||
sprintf('Expected first zone\'s %s to be "%s", but it is "%s".', $field, $value, $actualValue),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then the last zone on the list should have :field :value
|
||||
*/
|
||||
public function theLastZoneOnTheListShouldHave(string $field, string $value): void
|
||||
{
|
||||
$fields = $this->indexPage->getColumnFields($field);
|
||||
$actualValue = end($fields);
|
||||
|
||||
Assert::same(
|
||||
$actualValue,
|
||||
$value,
|
||||
sprintf('Expected last zone\'s %s to be "%s", but it is "%s".', $field, $value, $actualValue),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @Given the :zone zone should have priority :priority
|
||||
*/
|
||||
public function theZoneShouldHavePriority(ZoneInterface $zone, int $priority)
|
||||
{
|
||||
$this->iWantToModifyAZoneNamed($zone);
|
||||
|
||||
Assert::same($this->formElement->getPriority(), $priority);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -164,6 +164,8 @@ class FormElement extends BaseFormElement implements FormElementInterface
|
|||
'last_rule' => '[data-test-rules] [data-test-entry-row]:last-child',
|
||||
'last_rule_amount' => '[data-test-rules] [data-test-entry-row]:last-child [id$="_configuration_%channelCode%_amount"]',
|
||||
'last_rule_weight' => '[data-test-rules] [data-test-entry-row]:last-child [id$="_configuration_weight"]',
|
||||
'max_delivery_time_days' => '#sylius_admin_shipping_method_maxDeliveryTimeDays',
|
||||
'min_delivery_time_days' => '#sylius_admin_shipping_method_minDeliveryTimeDays',
|
||||
'name' => '#sylius_admin_shipping_method_translations_%localeCode%_name',
|
||||
'position' => '#sylius_admin_shipping_method_position',
|
||||
'zone' => '#sylius_admin_shipping_method_zone',
|
||||
|
|
|
|||
|
|
@ -31,6 +31,11 @@ class FormElement extends BaseFormElement implements FormElementInterface
|
|||
return $this->getElement('name')->getValue();
|
||||
}
|
||||
|
||||
public function getPriority(): int
|
||||
{
|
||||
return (int) $this->getElement('priority')->getValue();
|
||||
}
|
||||
|
||||
public function getType(): string
|
||||
{
|
||||
return $this->getElement('type')->getValue();
|
||||
|
|
@ -67,6 +72,11 @@ class FormElement extends BaseFormElement implements FormElementInterface
|
|||
$this->waitForElement(5, 'zone_member_added');
|
||||
}
|
||||
|
||||
public function prioritizeIt(int $priority): void
|
||||
{
|
||||
$this->getElement('priority')->setValue($priority);
|
||||
}
|
||||
|
||||
public function removeMember(string $member): void
|
||||
{
|
||||
$this->getElement('zone_member_delete', ['%name%' => $member])->click();
|
||||
|
|
@ -100,6 +110,7 @@ class FormElement extends BaseFormElement implements FormElementInterface
|
|||
'code' => '[data-test-code]',
|
||||
'form_validation_message' => 'form > div.alert.alert-danger.d-block',
|
||||
'name' => '[data-test-name]',
|
||||
'priority' => '#sylius_admin_zone_priority',
|
||||
'scope' => '[data-test-scope]',
|
||||
'type' => '[data-test-type]',
|
||||
'zone_member' => '[data-test-zone-member]:contains("%name%")',
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ interface FormElementInterface extends BaseFormElementInterface
|
|||
{
|
||||
public function getName(): string;
|
||||
|
||||
public function getPriority(): int;
|
||||
|
||||
public function nameIt(string $name): void;
|
||||
|
||||
public function getType(): string;
|
||||
|
|
@ -31,6 +33,8 @@ interface FormElementInterface extends BaseFormElementInterface
|
|||
|
||||
public function addMember(): void;
|
||||
|
||||
public function prioritizeIt(int $priority): void;
|
||||
|
||||
public function getScope(): string;
|
||||
|
||||
public function selectScope(string $scope): void;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ use Sylius\Bundle\ResourceBundle\Form\Type\AbstractResourceType;
|
|||
use Sylius\Component\Addressing\Model\ZoneInterface;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
|
|
@ -46,6 +47,10 @@ final class ZoneType extends AbstractResourceType
|
|||
->add('type', ZoneTypeChoiceType::class, [
|
||||
'disabled' => true,
|
||||
])
|
||||
->add('priority', IntegerType::class, [
|
||||
'label' => 'sylius.form.zone.priority',
|
||||
'required' => true,
|
||||
])
|
||||
;
|
||||
|
||||
if (!empty($this->scopeChoices)) {
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ class ZoneRepository extends EntityRepository implements ZoneRepositoryInterface
|
|||
->andWhere($queryBuilder->expr()->eq('o.type', ':type'))
|
||||
->setParameter('type', $type)
|
||||
->setMaxResults(1)
|
||||
->addOrderBy('o.priority', 'DESC')
|
||||
;
|
||||
|
||||
return $queryBuilder->getQuery()->getOneOrNullResult();
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
<field name="name" column="name" type="string" />
|
||||
<field name="type" column="type" type="string" length="8" />
|
||||
<field name="scope" column="scope" type="string" nullable="true"/>
|
||||
<field name="priority" column="priority" type="integer" />
|
||||
|
||||
<one-to-many field="members" target-entity="Sylius\Component\Addressing\Model\ZoneMemberInterface" mapped-by="belongsTo" orphan-removal="true">
|
||||
<cascade>
|
||||
|
|
|
|||
|
|
@ -30,5 +30,6 @@ sylius:
|
|||
zone: Area
|
||||
scope: Gebied
|
||||
select: Kies
|
||||
priority: Prioriteit
|
||||
zone_member:
|
||||
select: Kies
|
||||
|
|
|
|||
|
|
@ -38,5 +38,6 @@ sylius:
|
|||
all: الكل
|
||||
select: اختر
|
||||
select_scope: اختر النطاق
|
||||
priority: الأولوية
|
||||
zone_member:
|
||||
select: اختر
|
||||
|
|
|
|||
|
|
@ -38,5 +38,6 @@ sylius:
|
|||
all: Усе
|
||||
select: Выберыце
|
||||
select_scope: Выбярыце сферу ўжывання
|
||||
priority: Прыярытэт
|
||||
zone_member:
|
||||
select: Выберыце
|
||||
|
|
|
|||
|
|
@ -38,5 +38,6 @@ sylius:
|
|||
all: Всички
|
||||
select: Изберете
|
||||
select_scope: Изберете обхват
|
||||
priority: Приоритет
|
||||
zone_member:
|
||||
select: Изберете
|
||||
|
|
|
|||
|
|
@ -38,5 +38,6 @@ sylius:
|
|||
all: Totes
|
||||
select: Tria
|
||||
select_scope: Seleccioneu l'àmbit
|
||||
priority: Prioritat
|
||||
zone_member:
|
||||
select: Tria
|
||||
|
|
|
|||
|
|
@ -37,5 +37,6 @@ sylius:
|
|||
scopes:
|
||||
all: 'Všechny'
|
||||
select: 'Vybrat'
|
||||
priority: 'Priorita'
|
||||
zone_member:
|
||||
select: 'Vybrat'
|
||||
|
|
|
|||
|
|
@ -38,5 +38,6 @@ sylius:
|
|||
all: Alle
|
||||
select: Vælg
|
||||
select_scope: Vælg omfang
|
||||
priority: Prioritet
|
||||
zone_member:
|
||||
select: Vælg
|
||||
|
|
|
|||
|
|
@ -38,5 +38,6 @@ sylius:
|
|||
all: 'Alle'
|
||||
select: 'Zone auswählen'
|
||||
select_scope: 'Geltungsbereich auswählen'
|
||||
priority: 'Priorität'
|
||||
zone_member:
|
||||
select: 'Mitglied auswählen'
|
||||
|
|
|
|||
|
|
@ -37,5 +37,6 @@ sylius:
|
|||
scopes:
|
||||
all: 'Alle'
|
||||
select: 'Auswählen'
|
||||
priority: 'Priorität'
|
||||
zone_member:
|
||||
select: 'Auswählen'
|
||||
|
|
|
|||
|
|
@ -37,5 +37,6 @@ sylius:
|
|||
scopes:
|
||||
all: 'Alle'
|
||||
select: 'Auswählen'
|
||||
priority: 'Priorität'
|
||||
zone_member:
|
||||
select: 'Auswählen'
|
||||
|
|
|
|||
|
|
@ -38,5 +38,6 @@ sylius:
|
|||
all: Όλα
|
||||
select: Επιλέξτε
|
||||
select_scope: Επιλέξτε πεδίο
|
||||
priority: Προτεραιότητα
|
||||
zone_member:
|
||||
select: Επιλέξτε
|
||||
|
|
|
|||
|
|
@ -34,5 +34,6 @@ sylius:
|
|||
scopes:
|
||||
all: All
|
||||
select: Select
|
||||
priority: Priority
|
||||
zone_member:
|
||||
select: Select
|
||||
|
|
|
|||
|
|
@ -36,5 +36,6 @@ sylius:
|
|||
scopes:
|
||||
all: All
|
||||
select: Choose
|
||||
priority: Priority
|
||||
zone_member:
|
||||
select: Choose
|
||||
|
|
|
|||
|
|
@ -38,5 +38,6 @@ sylius:
|
|||
all: Todos
|
||||
select: Seleccionar
|
||||
select_scope: Seleccione ámbito
|
||||
priority: Prioridad
|
||||
zone_member:
|
||||
select: Selección
|
||||
|
|
|
|||
|
|
@ -38,5 +38,6 @@ sylius:
|
|||
all: Kõik
|
||||
select: Vali
|
||||
select_scope: Valige
|
||||
priority: Prioriteet
|
||||
zone_member:
|
||||
select: Vali
|
||||
|
|
|
|||
|
|
@ -38,5 +38,6 @@ sylius:
|
|||
all: همه
|
||||
select: انتخاب
|
||||
select_scope: انتخاب محدوده
|
||||
priority: اولویت
|
||||
zone_member:
|
||||
select: انتخاب
|
||||
|
|
|
|||
|
|
@ -38,5 +38,6 @@ sylius:
|
|||
all: Kaikki
|
||||
select: Valitse
|
||||
select_scope: Valitse alue
|
||||
priority: Prioriteetti
|
||||
zone_member:
|
||||
select: Valitse
|
||||
|
|
|
|||
|
|
@ -37,5 +37,6 @@ sylius:
|
|||
scopes:
|
||||
all: Tous
|
||||
select: Sélectionner
|
||||
priority: Priorité
|
||||
zone_member:
|
||||
select: Sélectionner
|
||||
|
|
|
|||
|
|
@ -38,5 +38,6 @@ sylius:
|
|||
all: Tout
|
||||
select: Sélectionner
|
||||
select_scope: Sélectionner la portée
|
||||
priority: Priorité
|
||||
zone_member:
|
||||
select: Sélectionner
|
||||
|
|
|
|||
|
|
@ -38,5 +38,6 @@ sylius:
|
|||
all: Tous
|
||||
select: Choisir
|
||||
select_scope: Choisissez la portée
|
||||
priority: Priorité
|
||||
zone_member:
|
||||
select: Choisir
|
||||
|
|
|
|||
|
|
@ -38,5 +38,6 @@ sylius:
|
|||
all: הכל
|
||||
select: בחירה
|
||||
select_scope: בחרו תחום
|
||||
priority: עדיפות
|
||||
zone_member:
|
||||
select: בחירה
|
||||
|
|
|
|||
|
|
@ -37,5 +37,6 @@ sylius:
|
|||
scopes:
|
||||
all: 'सभी'
|
||||
select: 'चयन करें'
|
||||
priority: 'प्राथमिकता'
|
||||
zone_member:
|
||||
select: 'चयन करें'
|
||||
|
|
|
|||
|
|
@ -38,5 +38,6 @@ sylius:
|
|||
all: Sve
|
||||
select: Odaberite
|
||||
select_scope: Odaberite doseg
|
||||
priority: Prioritet
|
||||
zone_member:
|
||||
select: Odaberite
|
||||
|
|
|
|||
|
|
@ -38,5 +38,6 @@ sylius:
|
|||
all: Mind
|
||||
select: Válassza ki
|
||||
select_scope: Hatókör kiválasztása
|
||||
priority: Prioritás
|
||||
zone_member:
|
||||
select: Válassza ki
|
||||
|
|
|
|||
|
|
@ -38,5 +38,6 @@ sylius:
|
|||
all: Semua
|
||||
select: Pilih
|
||||
select_scope: Pilih lingkup
|
||||
priority: Prioritas
|
||||
zone_member:
|
||||
select: Pilih
|
||||
|
|
|
|||
|
|
@ -38,5 +38,6 @@ sylius:
|
|||
all: Allt
|
||||
select: Vallisti
|
||||
select_scope: Velja umfang
|
||||
priority: Forgangur
|
||||
zone_member:
|
||||
select: Vallisti
|
||||
|
|
|
|||
|
|
@ -37,5 +37,6 @@ sylius:
|
|||
scopes:
|
||||
all: 'Tutti'
|
||||
select: 'Seleziona'
|
||||
priority: 'Priorità'
|
||||
zone_member:
|
||||
select: 'Seleziona'
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ sylius:
|
|||
scopes:
|
||||
all: 'すべて'
|
||||
select: '選択'
|
||||
priority: '優先度'
|
||||
zone_member:
|
||||
select: '選択'
|
||||
|
||||
|
|
|
|||
|
|
@ -37,5 +37,6 @@ sylius:
|
|||
scopes:
|
||||
all: '전체'
|
||||
select: '선택'
|
||||
priority: '우선순위'
|
||||
zone_member:
|
||||
select: '선택'
|
||||
|
|
|
|||
|
|
@ -38,5 +38,6 @@ sylius:
|
|||
all: Visi
|
||||
select: Pasirinkite
|
||||
select_scope: Pasirinkite sritį
|
||||
priority: Prioritetas
|
||||
zone_member:
|
||||
select: Pasirinkite
|
||||
|
|
|
|||
|
|
@ -34,3 +34,4 @@ sylius:
|
|||
scopes:
|
||||
all: Visas
|
||||
select_scope: Izvēlēties tvērumu
|
||||
priority: Prioritāte
|
||||
|
|
|
|||
|
|
@ -38,5 +38,6 @@ sylius:
|
|||
all: Сите
|
||||
select: Изберете
|
||||
select_scope: Изберете опсег
|
||||
priority: Приоритет
|
||||
zone_member:
|
||||
select: Изберете
|
||||
|
|
|
|||
|
|
@ -38,5 +38,6 @@ sylius:
|
|||
all: Бүгд
|
||||
select: Сонгох
|
||||
select_scope: Бүс сонгох
|
||||
priority: Эрэмбэ
|
||||
zone_member:
|
||||
select: Сонгох
|
||||
|
|
|
|||
|
|
@ -38,5 +38,6 @@ sylius:
|
|||
all: Semua
|
||||
select: Pilih
|
||||
select_scope: Pilih skop
|
||||
priority: Keutamaan
|
||||
zone_member:
|
||||
select: Pilih
|
||||
|
|
|
|||
|
|
@ -37,5 +37,6 @@ sylius:
|
|||
scopes:
|
||||
all: 'Alle'
|
||||
select: 'Selecteer'
|
||||
priority: 'Prioriteit'
|
||||
zone_member:
|
||||
select: 'Selecteer'
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ sylius:
|
|||
scopes:
|
||||
all: 'Alle'
|
||||
select: 'Velg'
|
||||
priority: 'Prioritet'
|
||||
zone_member:
|
||||
select: 'Velg'
|
||||
|
||||
|
|
|
|||
|
|
@ -38,5 +38,6 @@ sylius:
|
|||
all: Wszystko
|
||||
select: Wybierz
|
||||
select_scope: Wybierz zakres
|
||||
priority: Priorytet
|
||||
zone_member:
|
||||
select: Wybierz
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ sylius:
|
|||
scopes:
|
||||
all: 'Todos'
|
||||
select: 'Selecionar'
|
||||
priority: 'Prioridade'
|
||||
zone_member:
|
||||
select: 'Selecionar'
|
||||
|
||||
|
|
|
|||
|
|
@ -38,5 +38,6 @@ sylius:
|
|||
all: Todos(as)
|
||||
select: Selecione
|
||||
select_scope: Selecione o escopo
|
||||
priority: Prioridade
|
||||
zone_member:
|
||||
select: Selecione
|
||||
|
|
|
|||
|
|
@ -37,5 +37,6 @@ sylius:
|
|||
scopes:
|
||||
all: 'Toate'
|
||||
select: 'Selectați'
|
||||
priority: 'Prioritate'
|
||||
zone_member:
|
||||
select: 'Selectați'
|
||||
|
|
|
|||
|
|
@ -38,5 +38,6 @@ sylius:
|
|||
all: Все
|
||||
select: Выбрать
|
||||
select_scope: Выберите область
|
||||
priority: Приоритет
|
||||
zone_member:
|
||||
select: Выбрать
|
||||
|
|
|
|||
|
|
@ -37,5 +37,6 @@ sylius:
|
|||
scopes:
|
||||
all: 'Všetko'
|
||||
select: 'Vybrať'
|
||||
priority: 'Priorita'
|
||||
zone_member:
|
||||
select: 'Vybrať'
|
||||
|
|
|
|||
|
|
@ -36,5 +36,6 @@ sylius:
|
|||
scope: Področje
|
||||
select: Izberite
|
||||
select_scope: Izberite področje
|
||||
priority: Prednost
|
||||
zone_member:
|
||||
select: Izberite
|
||||
|
|
|
|||
|
|
@ -37,5 +37,6 @@ sylius:
|
|||
all: Të gjitha
|
||||
select: Zgjidh
|
||||
select_scope: Zgjidh zonën
|
||||
priority: Prioriteti
|
||||
zone_member:
|
||||
select: Zgjidh
|
||||
|
|
|
|||
|
|
@ -35,5 +35,6 @@ sylius:
|
|||
scope: Обухват
|
||||
select: Изаберите
|
||||
select_scope: Изабери обухват
|
||||
priority: Приоритет
|
||||
zone_member:
|
||||
select: Изаберите
|
||||
|
|
|
|||
|
|
@ -38,5 +38,6 @@ sylius:
|
|||
all: Sve
|
||||
select: Izaberite
|
||||
select_scope: Izaberite adresu isporuke
|
||||
priority: Prioritet
|
||||
zone_member:
|
||||
select: Izaberite
|
||||
|
|
|
|||
|
|
@ -37,5 +37,6 @@ sylius:
|
|||
scopes:
|
||||
all: Alla
|
||||
select: Välj
|
||||
priority: Prioritet
|
||||
zone_member:
|
||||
select: Välj
|
||||
|
|
|
|||
|
|
@ -38,5 +38,6 @@ sylius:
|
|||
all: ทั้งหมด
|
||||
select: เลือก
|
||||
select_scope: เลือกขอบเขต
|
||||
priority: ลำดับความสำคัญ
|
||||
zone_member:
|
||||
select: เลือก
|
||||
|
|
|
|||
|
|
@ -38,5 +38,6 @@ sylius:
|
|||
all: Tümü
|
||||
select: Seçiniz
|
||||
select_scope: Ölçek seçiniz
|
||||
priority: Öncelik
|
||||
zone_member:
|
||||
select: Seçiniz
|
||||
|
|
|
|||
|
|
@ -38,5 +38,6 @@ sylius:
|
|||
all: Всі(-е)
|
||||
select: Виберіть
|
||||
select_scope: Виберіть покриття
|
||||
priority: Пріоритет
|
||||
zone_member:
|
||||
select: Виберіть
|
||||
|
|
|
|||
|
|
@ -38,5 +38,6 @@ sylius:
|
|||
all: Tất cả
|
||||
select: Chọn
|
||||
select_scope: Chọn phạm vi
|
||||
priority: Ưu tiên
|
||||
zone_member:
|
||||
select: Chọn
|
||||
|
|
|
|||
|
|
@ -37,5 +37,6 @@ sylius:
|
|||
scopes:
|
||||
all: '所有'
|
||||
select: '选择'
|
||||
priority: '优先级'
|
||||
zone_member:
|
||||
select: '选择'
|
||||
|
|
|
|||
|
|
@ -37,5 +37,6 @@ sylius:
|
|||
all: 全部
|
||||
select: 請選擇
|
||||
select_scope: 選擇範圍
|
||||
priority: 優先順序
|
||||
zone_member:
|
||||
select: 請選擇
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@
|
|||
"doctrine/doctrine-bundle": "^2.13",
|
||||
"doctrine/orm": "^2.18 || ^3.3",
|
||||
"matthiasnoback/symfony-dependency-injection-test": "^6.0",
|
||||
"phpspec/prophecy-phpunit": "^2.2",
|
||||
"phpunit/phpunit": "^11.5",
|
||||
"symfony/browser-kit": "^6.4 || ^7.2",
|
||||
"symfony/dependency-injection": "^6.4.1 || ^7.2",
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -15,9 +15,7 @@ namespace Tests\Sylius\Bundle\AddressingBundle\Form\Type;
|
|||
|
||||
use PHPUnit\Framework\Assert;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use Prophecy\PhpUnit\ProphecyTrait;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Prophecy\Prophecy\ProphecyInterface;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Sylius\Bundle\AddressingBundle\Form\Type\CountryChoiceType;
|
||||
use Sylius\Component\Addressing\Model\CountryInterface;
|
||||
use Sylius\Resource\Doctrine\Persistence\RepositoryInterface;
|
||||
|
|
@ -27,48 +25,37 @@ use Symfony\Component\Form\Test\TypeTestCase;
|
|||
|
||||
final class CountryChoiceTypeTest extends TypeTestCase
|
||||
{
|
||||
use ProphecyTrait;
|
||||
private RepositoryInterface&MockObject $countryRepository;
|
||||
|
||||
private ObjectProphecy $countryRepository;
|
||||
private CountryInterface&MockObject $france;
|
||||
|
||||
/** @var ProphecyInterface|CountryInterface */
|
||||
private $france;
|
||||
private CountryInterface&MockObject $poland;
|
||||
|
||||
/** @var ProphecyInterface|CountryInterface */
|
||||
private $poland;
|
||||
|
||||
/** @var ProphecyInterface|CountryInterface */
|
||||
private $austria;
|
||||
private CountryInterface&MockObject $austria;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->countryRepository = $this->prophesize(RepositoryInterface::class);
|
||||
$this->countryRepository = $this->createMock(RepositoryInterface::class);
|
||||
|
||||
/** @var ProphecyInterface|CountryInterface $france */
|
||||
$france = $this->prophesize(CountryInterface::class);
|
||||
$france->getCode()->willReturn('FR');
|
||||
$france->getName()->willReturn('France');
|
||||
$this->france = $france;
|
||||
$this->france = $this->createMock(CountryInterface::class);
|
||||
$this->france->method('getCode')->willReturn('FR');
|
||||
$this->france->method('getName')->willReturn('France');
|
||||
|
||||
/** @var ProphecyInterface|CountryInterface $poland */
|
||||
$poland = $this->prophesize(CountryInterface::class);
|
||||
$poland->getCode()->willReturn('PL');
|
||||
$poland->getName()->willReturn('Poland');
|
||||
$this->poland = $poland;
|
||||
$this->poland = $this->createMock(CountryInterface::class);
|
||||
$this->poland->method('getCode')->willReturn('PL');
|
||||
$this->poland->method('getName')->willReturn('Poland');
|
||||
|
||||
/** @var ProphecyInterface|CountryInterface $austria */
|
||||
$austria = $this->prophesize(CountryInterface::class);
|
||||
$austria->getCode()->willReturn('AT');
|
||||
$austria->getName()->willReturn('Austria');
|
||||
$austria->isEnabled()->willReturn(false);
|
||||
$this->austria = $austria;
|
||||
$this->austria = $this->createMock(CountryInterface::class);
|
||||
$this->austria->method('getCode')->willReturn('AT');
|
||||
$this->austria->method('getName')->willReturn('Austria');
|
||||
$this->austria->method('isEnabled')->willReturn(false);
|
||||
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
protected function getExtensions(): array
|
||||
{
|
||||
$type = new CountryChoiceType($this->countryRepository->reveal());
|
||||
$type = new CountryChoiceType($this->countryRepository);
|
||||
|
||||
return [
|
||||
new PreloadedExtension([$type], []),
|
||||
|
|
@ -78,10 +65,14 @@ final class CountryChoiceTypeTest extends TypeTestCase
|
|||
#[Test]
|
||||
public function it_returns_only_enabled_countries_by_default(): void
|
||||
{
|
||||
$this->countryRepository->findBy(['enabled' => true])->willReturn([
|
||||
$this->france->reveal(),
|
||||
$this->poland->reveal(),
|
||||
]);
|
||||
$this->countryRepository
|
||||
->expects($this->once())
|
||||
->method('findBy')
|
||||
->with(['enabled' => true])
|
||||
->willReturn([
|
||||
$this->france,
|
||||
$this->poland,
|
||||
]);
|
||||
|
||||
$this->assertChoicesLabels(['France', 'Poland']);
|
||||
}
|
||||
|
|
@ -89,11 +80,14 @@ final class CountryChoiceTypeTest extends TypeTestCase
|
|||
#[Test]
|
||||
public function it_returns_all_countries_when_option_enabled_is_false(): void
|
||||
{
|
||||
$this->countryRepository->findAll()->willReturn([
|
||||
$this->france->reveal(),
|
||||
$this->poland->reveal(),
|
||||
$this->austria->reveal(),
|
||||
]);
|
||||
$this->countryRepository
|
||||
->expects($this->once())
|
||||
->method('findAll')
|
||||
->willReturn([
|
||||
$this->france,
|
||||
$this->poland,
|
||||
$this->austria,
|
||||
]);
|
||||
|
||||
$this->assertChoicesLabels(['Austria', 'France', 'Poland'], ['enabled' => false]);
|
||||
}
|
||||
|
|
@ -101,10 +95,14 @@ final class CountryChoiceTypeTest extends TypeTestCase
|
|||
#[Test]
|
||||
public function it_returns_enabled_countries_in_an_alphabetical_order(): void
|
||||
{
|
||||
$this->countryRepository->findBy(['enabled' => true])->willReturn([
|
||||
$this->poland->reveal(),
|
||||
$this->france->reveal(),
|
||||
]);
|
||||
$this->countryRepository
|
||||
->expects($this->once())
|
||||
->method('findBy')
|
||||
->with(['enabled' => true])
|
||||
->willReturn([
|
||||
$this->poland,
|
||||
$this->france,
|
||||
]);
|
||||
|
||||
$this->assertChoicesLabels(['France', 'Poland']);
|
||||
}
|
||||
|
|
@ -112,11 +110,14 @@ final class CountryChoiceTypeTest extends TypeTestCase
|
|||
#[Test]
|
||||
public function it_returns_all_countries_in_an_alphabetical_order(): void
|
||||
{
|
||||
$this->countryRepository->findAll()->willReturn([
|
||||
$this->poland->reveal(),
|
||||
$this->france->reveal(),
|
||||
$this->austria->reveal(),
|
||||
]);
|
||||
$this->countryRepository
|
||||
->expects($this->once())
|
||||
->method('findAll')
|
||||
->willReturn([
|
||||
$this->poland,
|
||||
$this->france,
|
||||
$this->austria,
|
||||
]);
|
||||
|
||||
$this->assertChoicesLabels(['Austria', 'France', 'Poland'], ['enabled' => false]);
|
||||
}
|
||||
|
|
@ -124,11 +125,14 @@ final class CountryChoiceTypeTest extends TypeTestCase
|
|||
#[Test]
|
||||
public function it_returns_all_filtered_out_countries(): void
|
||||
{
|
||||
$this->countryRepository->findAll()->willReturn([
|
||||
$this->france->reveal(),
|
||||
$this->poland->reveal(),
|
||||
$this->austria->reveal(),
|
||||
]);
|
||||
$this->countryRepository
|
||||
->expects($this->once())
|
||||
->method('findAll')
|
||||
->willReturn([
|
||||
$this->france,
|
||||
$this->poland,
|
||||
$this->austria,
|
||||
]);
|
||||
|
||||
$this->assertChoicesLabels(['Poland'], ['choice_filter' => static fn (?CountryInterface $country): bool => $country !== null && $country->getName() === 'Poland', 'enabled' => false]);
|
||||
}
|
||||
|
|
@ -136,10 +140,14 @@ final class CountryChoiceTypeTest extends TypeTestCase
|
|||
#[Test]
|
||||
public function it_returns_enabled_filtered_out_countries(): void
|
||||
{
|
||||
$this->countryRepository->findBy(['enabled' => true])->willReturn([
|
||||
$this->france->reveal(),
|
||||
$this->poland->reveal(),
|
||||
]);
|
||||
$this->countryRepository
|
||||
->expects($this->once())
|
||||
->method('findBy')
|
||||
->with(['enabled' => true])
|
||||
->willReturn([
|
||||
$this->france,
|
||||
$this->poland,
|
||||
]);
|
||||
|
||||
$this->assertChoicesLabels(['Poland'], ['choice_filter' => static fn (?CountryInterface $country): bool => $country !== null && $country->getName() === 'Poland']);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,9 +15,7 @@ namespace Tests\Sylius\Bundle\AddressingBundle\Form\Type;
|
|||
|
||||
use PHPUnit\Framework\Assert;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use Prophecy\PhpUnit\ProphecyTrait;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Prophecy\Prophecy\ProphecyInterface;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Sylius\Bundle\AddressingBundle\Form\Type\ZoneChoiceType;
|
||||
use Sylius\Component\Addressing\Model\Scope as AddressingScope;
|
||||
use Sylius\Component\Addressing\Model\ZoneInterface;
|
||||
|
|
@ -28,39 +26,31 @@ use Symfony\Component\Form\Test\TypeTestCase;
|
|||
|
||||
final class ZoneChoiceTypeTest extends TypeTestCase
|
||||
{
|
||||
use ProphecyTrait;
|
||||
private RepositoryInterface&MockObject $zoneRepository;
|
||||
|
||||
private ObjectProphecy $zoneRepository;
|
||||
private ZoneInterface&MockObject $zoneAllScopes;
|
||||
|
||||
/** @var ProphecyInterface|ZoneInterface */
|
||||
private $zoneAllScopes;
|
||||
private ZoneInterface&MockObject $zoneTaxScope;
|
||||
|
||||
/** @var ProphecyInterface|ZoneInterface */
|
||||
private $zoneTaxScope;
|
||||
|
||||
/** @var ProphecyInterface|ZoneInterface */
|
||||
private $zoneShippingScope;
|
||||
private ZoneInterface&MockObject $zoneShippingScope;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->zoneRepository = $this->prophesize(RepositoryInterface::class);
|
||||
$this->zoneRepository = $this->createMock(RepositoryInterface::class);
|
||||
|
||||
/** @var ProphecyInterface|ZoneInterface $zoneAllScopes */
|
||||
$zoneAllScopes = $this->prophesize(ZoneInterface::class);
|
||||
$zoneAllScopes->getCode()->willReturn('all');
|
||||
$zoneAllScopes->getName()->willReturn('All');
|
||||
$zoneAllScopes = $this->createMock(ZoneInterface::class);
|
||||
$zoneAllScopes->method('getCode')->willReturn('all');
|
||||
$zoneAllScopes->method('getName')->willReturn('All');
|
||||
$this->zoneAllScopes = $zoneAllScopes;
|
||||
|
||||
/** @var ProphecyInterface|ZoneInterface $zoneTaxScope */
|
||||
$zoneTaxScope = $this->prophesize(ZoneInterface::class);
|
||||
$zoneTaxScope->getCode()->willReturn('tax');
|
||||
$zoneTaxScope->getName()->willReturn('Tax');
|
||||
$zoneTaxScope = $this->createMock(ZoneInterface::class);
|
||||
$zoneTaxScope->method('getCode')->willReturn('tax');
|
||||
$zoneTaxScope->method('getName')->willReturn('Tax');
|
||||
$this->zoneTaxScope = $zoneTaxScope;
|
||||
|
||||
/** @var ProphecyInterface|ZoneInterface $zoneShippingScope */
|
||||
$zoneShippingScope = $this->prophesize(ZoneInterface::class);
|
||||
$zoneShippingScope->getCode()->willReturn('shipping');
|
||||
$zoneShippingScope->getName()->willReturn('Shipping');
|
||||
$zoneShippingScope = $this->createMock(ZoneInterface::class);
|
||||
$zoneShippingScope->method('getCode')->willReturn('shipping');
|
||||
$zoneShippingScope->method('getName')->willReturn('Shipping');
|
||||
$this->zoneShippingScope = $zoneShippingScope;
|
||||
|
||||
parent::setUp();
|
||||
|
|
@ -74,7 +64,7 @@ final class ZoneChoiceTypeTest extends TypeTestCase
|
|||
'shipping' => 'Shipping',
|
||||
];
|
||||
|
||||
$type = new ZoneChoiceType($this->zoneRepository->reveal(), $scopeTypes);
|
||||
$type = new ZoneChoiceType($this->zoneRepository, $scopeTypes);
|
||||
|
||||
return [
|
||||
new PreloadedExtension([$type], []),
|
||||
|
|
@ -84,10 +74,10 @@ final class ZoneChoiceTypeTest extends TypeTestCase
|
|||
#[Test]
|
||||
public function it_returns_all_scopes_by_default(): void
|
||||
{
|
||||
$this->zoneRepository->findBy([])->willReturn([
|
||||
$this->zoneAllScopes->reveal(),
|
||||
$this->zoneTaxScope->reveal(),
|
||||
$this->zoneShippingScope->reveal(),
|
||||
$this->zoneRepository->method('findBy')->with([])->willReturn([
|
||||
$this->zoneAllScopes,
|
||||
$this->zoneTaxScope,
|
||||
$this->zoneShippingScope,
|
||||
]);
|
||||
|
||||
$this->assertChoicesLabels(['All', 'Tax', 'Shipping']);
|
||||
|
|
@ -96,10 +86,10 @@ final class ZoneChoiceTypeTest extends TypeTestCase
|
|||
#[Test]
|
||||
public function it_returns_all_scopes_when_zone_scope_set_to_all(): void
|
||||
{
|
||||
$this->zoneRepository->findBy([])->willReturn([
|
||||
$this->zoneAllScopes->reveal(),
|
||||
$this->zoneTaxScope->reveal(),
|
||||
$this->zoneShippingScope->reveal(),
|
||||
$this->zoneRepository->method('findBy')->with([])->willReturn([
|
||||
$this->zoneAllScopes,
|
||||
$this->zoneTaxScope,
|
||||
$this->zoneShippingScope,
|
||||
]);
|
||||
|
||||
$this->assertChoicesLabels(['All', 'Tax', 'Shipping'], ['zone_scope' => AddressingScope::ALL]);
|
||||
|
|
@ -108,9 +98,9 @@ final class ZoneChoiceTypeTest extends TypeTestCase
|
|||
#[Test]
|
||||
public function it_returns_tax_scopes_when_zone_scope_set_to_tax(): void
|
||||
{
|
||||
$this->zoneRepository->findBy(['scope' => ['tax', AddressingScope::ALL]])->willReturn([
|
||||
$this->zoneAllScopes->reveal(),
|
||||
$this->zoneTaxScope->reveal(),
|
||||
$this->zoneRepository->method('findBy')->with(['scope' => ['tax', AddressingScope::ALL]])->willReturn([
|
||||
$this->zoneAllScopes,
|
||||
$this->zoneTaxScope,
|
||||
]);
|
||||
|
||||
$this->assertChoicesLabels(['All', 'Tax'], ['zone_scope' => 'tax']);
|
||||
|
|
@ -119,9 +109,9 @@ final class ZoneChoiceTypeTest extends TypeTestCase
|
|||
#[Test]
|
||||
public function it_returns_shipping_scopes_when_zone_scope_set_to_shipping(): void
|
||||
{
|
||||
$this->zoneRepository->findBy(['scope' => ['shipping', AddressingScope::ALL]])->willReturn([
|
||||
$this->zoneAllScopes->reveal(),
|
||||
$this->zoneShippingScope->reveal(),
|
||||
$this->zoneRepository->method('findBy')->with(['scope' => ['shipping', AddressingScope::ALL]])->willReturn([
|
||||
$this->zoneAllScopes,
|
||||
$this->zoneShippingScope,
|
||||
]);
|
||||
|
||||
$this->assertChoicesLabels(['All', 'Shipping'], ['zone_scope' => 'shipping']);
|
||||
|
|
|
|||
|
|
@ -15,3 +15,11 @@ sylius_twig_hooks:
|
|||
image:
|
||||
template: '@SyliusAdmin/shared/crud/common/sidebar/logo/image.html.twig'
|
||||
priority: 0
|
||||
|
||||
'sylius_admin.common.component.sidebar.menu':
|
||||
search:
|
||||
template: '@SyliusAdmin/shared/crud/common/sidebar/search.html.twig'
|
||||
priority: 100
|
||||
items:
|
||||
template: '@SyliusAdmin/shared/crud/common/sidebar/menu/items.html.twig'
|
||||
priority: 0
|
||||
|
|
|
|||
|
|
@ -44,6 +44,12 @@ sylius_twig_hooks:
|
|||
enabled:
|
||||
template: '@SyliusAdmin/shipping_method/form/general/enabled.html.twig'
|
||||
priority: 200
|
||||
min_delivery_time_days:
|
||||
template: '@SyliusAdmin/shipping_method/form/general/min_delivery_time_days.html.twig'
|
||||
priority: 150
|
||||
max_delivery_time_days:
|
||||
template: '@SyliusAdmin/shipping_method/form/general/max_delivery_time_days.html.twig'
|
||||
priority: 125
|
||||
zone:
|
||||
template: '@SyliusAdmin/shipping_method/form/general/zone.html.twig'
|
||||
priority: 100
|
||||
|
|
|
|||
|
|
@ -46,6 +46,12 @@ sylius_twig_hooks:
|
|||
enabled:
|
||||
template: '@SyliusAdmin/shipping_method/form/general/enabled.html.twig'
|
||||
priority: 200
|
||||
min_delivery_time_days:
|
||||
template: '@SyliusAdmin/shipping_method/form/general/min_delivery_time_days.html.twig'
|
||||
priority: 150
|
||||
max_delivery_time_days:
|
||||
template: '@SyliusAdmin/shipping_method/form/general/max_delivery_time_days.html.twig'
|
||||
priority: 125
|
||||
zone:
|
||||
template: '@SyliusAdmin/shipping_method/form/general/zone.html.twig'
|
||||
priority: 100
|
||||
|
|
|
|||
|
|
@ -43,3 +43,6 @@ sylius_twig_hooks:
|
|||
scope:
|
||||
template: '@SyliusAdmin/zone/form/sections/general/scope.html.twig'
|
||||
priority: 0
|
||||
priority:
|
||||
template: '@SyliusAdmin/zone/form/sections/general/priority.html.twig'
|
||||
priority: -100
|
||||
|
|
|
|||
|
|
@ -45,3 +45,6 @@ sylius_twig_hooks:
|
|||
scope:
|
||||
template: '@SyliusAdmin/zone/form/sections/general/scope.html.twig'
|
||||
priority: 0
|
||||
priority:
|
||||
template: '@SyliusAdmin/zone/form/sections/general/priority.html.twig'
|
||||
priority: -100
|
||||
|
|
|
|||
|
|
@ -5,7 +5,18 @@ sylius_grid:
|
|||
name: doctrine/orm
|
||||
options:
|
||||
class: "%sylius.model.zone.class%"
|
||||
sorting:
|
||||
priority: desc
|
||||
fields:
|
||||
priority:
|
||||
type: twig
|
||||
label: sylius.ui.priority
|
||||
sortable: ~
|
||||
options:
|
||||
template: "@SyliusAdmin/zone/grid/field/priority.html.twig"
|
||||
vars:
|
||||
th_class: "w-1 text-center"
|
||||
td_class: "text-center"
|
||||
name:
|
||||
type: twig
|
||||
label: sylius.ui.name
|
||||
|
|
|
|||
|
|
@ -51,7 +51,6 @@
|
|||
"doctrine/orm": "^2.18 || ^3.3",
|
||||
"matthiasnoback/symfony-dependency-injection-test": "^6.0",
|
||||
"php-http/message-factory": "^1.1",
|
||||
"phpspec/prophecy-phpunit": "^2.2",
|
||||
"phpunit/phpunit": "^11.5",
|
||||
"symfony/dependency-injection": "^6.4.1 || ^7.2",
|
||||
"symfony/dotenv": "^6.4 || ^7.2"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
<div class="collapse navbar-collapse" id="sidebar-menu">
|
||||
{% include '@SyliusAdmin/shared/crud/common/sidebar/search.html.twig' %}
|
||||
{{ knp_menu_render('sylius_admin.main', {'template': '@SyliusAdmin/shared/crud/common/sidebar/menu/menu.html.twig', 'currentClass': 'active'}) }}
|
||||
{% hook 'menu' %}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
{{ knp_menu_render('sylius_admin.main', {'template': '@SyliusAdmin/shared/crud/common/sidebar/menu/menu.html.twig', 'currentClass': 'active'}) }}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
<div class="col-12 col-lg-6">
|
||||
{{ form_row(hookable_metadata.context.form.maxDeliveryTimeDays) }}
|
||||
</div>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
<div class="col-12 col-lg-6">
|
||||
{{ form_row(hookable_metadata.context.form.minDeliveryTimeDays) }}
|
||||
</div>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
<div class="col-12 col-md-6">
|
||||
{{ form_row(hookable_metadata.context.form.priority, sylius_test_form_attribute('priority')) }}
|
||||
</div>
|
||||
|
|
@ -0,0 +1 @@
|
|||
<span class="badge bg-blue-lt">{{ data }}</span>
|
||||
|
|
@ -15,10 +15,8 @@ namespace Tests\Sylius\Bundle\AdminBundle\Notification;
|
|||
|
||||
use GuzzleHttp\Exception\ConnectException;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\PhpUnit\ProphecyTrait;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Psr\Clock\ClockInterface;
|
||||
use Psr\Http\Client\ClientInterface;
|
||||
use Psr\Http\Message\RequestFactoryInterface;
|
||||
|
|
@ -34,19 +32,17 @@ use Symfony\Contracts\Cache\CacheInterface;
|
|||
|
||||
final class HubNotificationProviderTest extends TestCase
|
||||
{
|
||||
use ProphecyTrait;
|
||||
private ClientInterface&MockObject $client;
|
||||
|
||||
private ClientInterface|ObjectProphecy $client;
|
||||
private RequestStack&MockObject $requestStack;
|
||||
|
||||
private ObjectProphecy|RequestStack $requestStack;
|
||||
private RequestFactoryInterface&MockObject $requestFactory;
|
||||
|
||||
private ObjectProphecy|RequestFactoryInterface $requestFactory;
|
||||
private StreamFactoryInterface&MockObject $streamFactory;
|
||||
|
||||
private ObjectProphecy|StreamFactoryInterface $streamFactory;
|
||||
private CacheInterface&MockObject $cache;
|
||||
|
||||
private CacheInterface|ObjectProphecy $cache;
|
||||
|
||||
private ClockInterface|ObjectProphecy $clock;
|
||||
private ClockInterface&MockObject $clock;
|
||||
|
||||
private HubNotificationProvider $hubNotificationsProvider;
|
||||
|
||||
|
|
@ -56,20 +52,20 @@ final class HubNotificationProviderTest extends TestCase
|
|||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->client = $this->prophesize(ClientInterface::class);
|
||||
$this->requestStack = $this->prophesize(RequestStack::class);
|
||||
$this->requestFactory = $this->prophesize(RequestFactoryInterface::class);
|
||||
$this->streamFactory = $this->prophesize(StreamFactoryInterface::class);
|
||||
$this->cache = $this->prophesize(CacheInterface::class);
|
||||
$this->clock = $this->prophesize(ClockInterface::class);
|
||||
$this->client = $this->createMock(ClientInterface::class);
|
||||
$this->requestStack = $this->createMock(RequestStack::class);
|
||||
$this->requestFactory = $this->createMock(RequestFactoryInterface::class);
|
||||
$this->streamFactory = $this->createMock(StreamFactoryInterface::class);
|
||||
$this->cache = $this->createMock(CacheInterface::class);
|
||||
$this->clock = $this->createMock(ClockInterface::class);
|
||||
|
||||
$this->hubNotificationsProvider = new HubNotificationProvider(
|
||||
$this->client->reveal(),
|
||||
$this->requestStack->reveal(),
|
||||
$this->requestFactory->reveal(),
|
||||
$this->streamFactory->reveal(),
|
||||
$this->cache->reveal(),
|
||||
$this->clock->reveal(),
|
||||
$this->client,
|
||||
$this->requestStack,
|
||||
$this->requestFactory,
|
||||
$this->streamFactory,
|
||||
$this->cache,
|
||||
$this->clock,
|
||||
self::$hubUri,
|
||||
'prod',
|
||||
true,
|
||||
|
|
@ -80,20 +76,51 @@ final class HubNotificationProviderTest extends TestCase
|
|||
#[Test]
|
||||
public function it_returns_an_empty_array_if_client_exception_occurs(): void
|
||||
{
|
||||
$request = $this->prophesize(RequestInterface::class);
|
||||
$stream = $this->prophesize(StreamInterface::class);
|
||||
$request = $this->createMock(RequestInterface::class);
|
||||
$stream = $this->createMock(StreamInterface::class);
|
||||
|
||||
$this->cache->get('latest_sylius_version', Argument::type('callable'))->will(fn ($args) => $args[1]());
|
||||
$this->cache
|
||||
->expects($this->once())
|
||||
->method('get')
|
||||
->with('latest_sylius_version', $this->isType('callable'))
|
||||
->willReturnCallback(fn ($key, $callback) => $callback());
|
||||
|
||||
$this->requestStack->getCurrentRequest()->willReturn(new Request());
|
||||
$this->clock->now()->willReturn(new \DateTimeImmutable());
|
||||
$this->streamFactory->createStream(Argument::cetera())->willReturn($stream);
|
||||
$this->requestStack
|
||||
->expects($this->once())
|
||||
->method('getCurrentRequest')
|
||||
->willReturn(new Request());
|
||||
|
||||
$this->requestFactory->createRequest(Argument::cetera())->willReturn($request);
|
||||
$request->withHeader('Content-Type', 'application/json')->willReturn($request);
|
||||
$request->withBody($stream)->willReturn($request);
|
||||
$this->clock
|
||||
->expects($this->once())
|
||||
->method('now')
|
||||
->willReturn(new \DateTimeImmutable());
|
||||
|
||||
$this->client->sendRequest(Argument::cetera())->willThrow(ConnectException::class);
|
||||
$this->streamFactory
|
||||
->expects($this->once())
|
||||
->method('createStream')
|
||||
->willReturn($stream);
|
||||
|
||||
$this->requestFactory
|
||||
->expects($this->once())
|
||||
->method('createRequest')
|
||||
->willReturn($request);
|
||||
|
||||
$request
|
||||
->expects($this->once())
|
||||
->method('withHeader')
|
||||
->with('Content-Type', 'application/json')
|
||||
->willReturn($request);
|
||||
|
||||
$request
|
||||
->expects($this->once())
|
||||
->method('withBody')
|
||||
->with($stream)
|
||||
->willReturn($request);
|
||||
|
||||
$this->client
|
||||
->expects($this->once())
|
||||
->method('sendRequest')
|
||||
->willThrowException(new ConnectException('Connection failed', $this->createMock(\Psr\Http\Message\RequestInterface::class)));
|
||||
|
||||
$this->assertEmpty($this->hubNotificationsProvider->getNotifications());
|
||||
}
|
||||
|
|
@ -101,25 +128,63 @@ final class HubNotificationProviderTest extends TestCase
|
|||
#[Test]
|
||||
public function it_returns_an_empty_array_if_the_current_version_is_the_same_as_latest(): void
|
||||
{
|
||||
$request = $this->prophesize(RequestInterface::class);
|
||||
$stream = $this->prophesize(StreamInterface::class);
|
||||
$externalResponse = $this->prophesize(ResponseInterface::class);
|
||||
$request = $this->createMock(RequestInterface::class);
|
||||
$stream = $this->createMock(StreamInterface::class);
|
||||
$externalResponse = $this->createMock(ResponseInterface::class);
|
||||
|
||||
$this->cache->get('latest_sylius_version', Argument::type('callable'))->will(fn ($args) => $args[1]());
|
||||
$this->cache
|
||||
->expects($this->once())
|
||||
->method('get')
|
||||
->with('latest_sylius_version', $this->isType('callable'))
|
||||
->willReturnCallback(fn ($key, $callback) => $callback());
|
||||
|
||||
$this->requestStack->getCurrentRequest()->willReturn(new Request());
|
||||
$this->clock->now()->willReturn(new \DateTimeImmutable());
|
||||
$this->streamFactory->createStream(Argument::cetera())->willReturn($stream);
|
||||
$this->requestStack
|
||||
->expects($this->once())
|
||||
->method('getCurrentRequest')
|
||||
->willReturn(new Request());
|
||||
|
||||
$this->clock
|
||||
->expects($this->once())
|
||||
->method('now')
|
||||
->willReturn(new \DateTimeImmutable());
|
||||
|
||||
$this->streamFactory
|
||||
->expects($this->once())
|
||||
->method('createStream')
|
||||
->willReturn($stream);
|
||||
|
||||
$content = json_encode(['version' => SyliusCoreBundle::VERSION]);
|
||||
$stream->getContents()->willReturn($content);
|
||||
$stream
|
||||
->expects($this->once())
|
||||
->method('getContents')
|
||||
->willReturn($content);
|
||||
|
||||
$this->requestFactory->createRequest(Argument::cetera())->willReturn($request);
|
||||
$request->withHeader('Content-Type', 'application/json')->willReturn($request);
|
||||
$request->withBody($stream)->willReturn($request);
|
||||
$this->requestFactory
|
||||
->expects($this->once())
|
||||
->method('createRequest')
|
||||
->willReturn($request);
|
||||
|
||||
$externalResponse->getBody()->willReturn($stream->reveal());
|
||||
$this->client->sendRequest(Argument::cetera())->willReturn($externalResponse->reveal());
|
||||
$request
|
||||
->expects($this->once())
|
||||
->method('withHeader')
|
||||
->with('Content-Type', 'application/json')
|
||||
->willReturn($request);
|
||||
|
||||
$request
|
||||
->expects($this->once())
|
||||
->method('withBody')
|
||||
->with($stream)
|
||||
->willReturn($request);
|
||||
|
||||
$externalResponse
|
||||
->expects($this->once())
|
||||
->method('getBody')
|
||||
->willReturn($stream);
|
||||
|
||||
$this->client
|
||||
->expects($this->once())
|
||||
->method('sendRequest')
|
||||
->willReturn($externalResponse);
|
||||
|
||||
$this->assertEmpty($this->hubNotificationsProvider->getNotifications());
|
||||
}
|
||||
|
|
@ -127,25 +192,63 @@ final class HubNotificationProviderTest extends TestCase
|
|||
#[Test]
|
||||
public function it_returns_a_notification_if_the_current_version_is_different_than_latest(): void
|
||||
{
|
||||
$request = $this->prophesize(RequestInterface::class);
|
||||
$stream = $this->prophesize(StreamInterface::class);
|
||||
$externalResponse = $this->prophesize(ResponseInterface::class);
|
||||
$request = $this->createMock(RequestInterface::class);
|
||||
$stream = $this->createMock(StreamInterface::class);
|
||||
$externalResponse = $this->createMock(ResponseInterface::class);
|
||||
|
||||
$this->cache->get('latest_sylius_version', Argument::type('callable'))->will(fn ($args) => $args[1]());
|
||||
$this->cache
|
||||
->expects($this->once())
|
||||
->method('get')
|
||||
->with('latest_sylius_version', $this->isType('callable'))
|
||||
->willReturnCallback(fn ($key, $callback) => $callback());
|
||||
|
||||
$this->requestStack->getCurrentRequest()->willReturn(new Request());
|
||||
$this->clock->now()->willReturn(new \DateTimeImmutable());
|
||||
$this->streamFactory->createStream(Argument::cetera())->willReturn($stream);
|
||||
$this->requestStack
|
||||
->expects($this->once())
|
||||
->method('getCurrentRequest')
|
||||
->willReturn(new Request());
|
||||
|
||||
$this->clock
|
||||
->expects($this->once())
|
||||
->method('now')
|
||||
->willReturn(new \DateTimeImmutable());
|
||||
|
||||
$this->streamFactory
|
||||
->expects($this->once())
|
||||
->method('createStream')
|
||||
->willReturn($stream);
|
||||
|
||||
$content = json_encode(['version' => '1.0.0']);
|
||||
$stream->getContents()->willReturn($content);
|
||||
$stream
|
||||
->expects($this->once())
|
||||
->method('getContents')
|
||||
->willReturn($content);
|
||||
|
||||
$this->requestFactory->createRequest(Argument::cetera())->willReturn($request);
|
||||
$request->withHeader('Content-Type', 'application/json')->willReturn($request);
|
||||
$request->withBody($stream)->willReturn($request);
|
||||
$this->requestFactory
|
||||
->expects($this->once())
|
||||
->method('createRequest')
|
||||
->willReturn($request);
|
||||
|
||||
$externalResponse->getBody()->willReturn($stream->reveal());
|
||||
$this->client->sendRequest(Argument::cetera())->willReturn($externalResponse->reveal());
|
||||
$request
|
||||
->expects($this->once())
|
||||
->method('withHeader')
|
||||
->with('Content-Type', 'application/json')
|
||||
->willReturn($request);
|
||||
|
||||
$request
|
||||
->expects($this->once())
|
||||
->method('withBody')
|
||||
->with($stream)
|
||||
->willReturn($request);
|
||||
|
||||
$externalResponse
|
||||
->expects($this->once())
|
||||
->method('getBody')
|
||||
->willReturn($stream);
|
||||
|
||||
$this->client
|
||||
->expects($this->once())
|
||||
->method('sendRequest')
|
||||
->willReturn($externalResponse);
|
||||
|
||||
$notifications = $this->hubNotificationsProvider->getNotifications();
|
||||
|
||||
|
|
|
|||
|
|
@ -14,17 +14,14 @@ declare(strict_types=1);
|
|||
namespace Tests\Sylius\Bundle\AdminBundle\Twig\Component\Shared\Navbar;
|
||||
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\PhpUnit\ProphecyTrait;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Sylius\Bundle\AdminBundle\Notification\NotificationProviderInterface;
|
||||
use Sylius\Bundle\AdminBundle\Twig\Component\Shared\Navbar\NotificationsComponent;
|
||||
|
||||
final class NotificationsComponentTest extends TestCase
|
||||
{
|
||||
use ProphecyTrait;
|
||||
|
||||
private NotificationProviderInterface|ObjectProphecy $notificationProvider;
|
||||
private NotificationProviderInterface&MockObject $notificationProvider;
|
||||
|
||||
private NotificationsComponent $notificationsComponent;
|
||||
|
||||
|
|
@ -34,15 +31,15 @@ final class NotificationsComponentTest extends TestCase
|
|||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->notificationProvider = $this->prophesize(NotificationProviderInterface::class);
|
||||
$this->notificationProvider = $this->createMock(NotificationProviderInterface::class);
|
||||
|
||||
$this->notificationsComponent = new NotificationsComponent($this->notificationProvider->reveal(), true);
|
||||
$this->notificationsComponent = new NotificationsComponent($this->notificationProvider, true);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function it_gets_notifications_from_provider(): void
|
||||
{
|
||||
$this->notificationProvider->getNotifications()->willReturn(['version' => ['message' => 'sylius.ui.notifications.new_version_of_sylius_available']]);
|
||||
$this->notificationProvider->method('getNotifications')->willReturn(['version' => ['message' => 'sylius.ui.notifications.new_version_of_sylius_available']]);
|
||||
|
||||
$notifications = $this->notificationsComponent->getNotifications();
|
||||
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ api_platform:
|
|||
ApiPlatform\Metadata\Exception\InvalidArgumentException: 400
|
||||
ApiPlatform\Validator\Exception\ValidationException: 422
|
||||
Doctrine\ORM\OptimisticLockException: 409
|
||||
Symfony\Component\Serializer\Exception\MissingConstructorArgumentsException: 422
|
||||
Symfony\Component\Serializer\Exception\ExceptionInterface: 400
|
||||
|
||||
# Sylius exception to status code mapping
|
||||
|
|
@ -71,7 +72,6 @@ api_platform:
|
|||
Sylius\Component\Payment\Exception\InvalidPaymentRequestPayloadException: 422
|
||||
Sylius\Component\Promotion\Exception\FailedGenerationException: 422
|
||||
Symfony\Component\Serializer\Exception\UnexpectedValueException: 400
|
||||
Symfony\Component\Serializer\Exception\MissingConstructorArgumentsException: 400
|
||||
Sylius\Bundle\ApiBundle\CommandHandler\Checkout\Exception\OrderTotalHasChangedException: 409
|
||||
Sylius\Bundle\ApiBundle\Serializer\Exception\InvalidAmountTypeException: 400
|
||||
defaults:
|
||||
|
|
|
|||
|
|
@ -41,6 +41,12 @@
|
|||
<group>sylius:admin:zone:index</group>
|
||||
<group>sylius:admin:zone:show</group>
|
||||
</attribute>
|
||||
<attribute name="priority">
|
||||
<group>sylius:admin:zone:create</group>
|
||||
<group>sylius:admin:zone:index</group>
|
||||
<group>sylius:admin:zone:show</group>
|
||||
<group>sylius:admin:zone:update</group>
|
||||
</attribute>
|
||||
<attribute name="createdAt">
|
||||
<group>sylius:admin:zone:index</group>
|
||||
<group>sylius:admin:zone:show</group>
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ final readonly class CommandNormalizer implements NormalizerInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* @return array{code: int, message: string}
|
||||
* @return array{message: string}
|
||||
*/
|
||||
public function normalize(mixed $object, ?string $format = null, array $context = []): array
|
||||
{
|
||||
|
|
@ -50,7 +50,6 @@ final readonly class CommandNormalizer implements NormalizerInterface
|
|||
$data = $this->objectNormalizer->normalize($object, $format, $context);
|
||||
|
||||
return [
|
||||
'code' => 400,
|
||||
'message' => $data['message'],
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@
|
|||
"require": {
|
||||
"php": "^8.2",
|
||||
"doctrine/dbal": "^3.9",
|
||||
"api-platform/doctrine-orm": "^4.1.7",
|
||||
"api-platform/symfony": "^4.1.7",
|
||||
"api-platform/doctrine-orm": "^4.2.1",
|
||||
"api-platform/symfony": "^4.2.1",
|
||||
"lexik/jwt-authentication-bundle": "^3.1",
|
||||
"sylius/core-bundle": "^2.0",
|
||||
"sylius/payum-bundle": "^2.0",
|
||||
|
|
@ -38,7 +38,6 @@
|
|||
"matthiasnoback/symfony-dependency-injection-test": "^6.0",
|
||||
"nelmio/alice": "^3.13",
|
||||
"phparkitect/phparkitect": "^0.6",
|
||||
"phpspec/prophecy-phpunit": "^2.2",
|
||||
"phpunit/phpunit": "^11.5",
|
||||
"symfony/browser-kit": "^6.4 || ^7.2",
|
||||
"symfony/debug-bundle": "^6.4 || ^7.2",
|
||||
|
|
|
|||
|
|
@ -14,9 +14,8 @@ declare(strict_types=1);
|
|||
namespace Tests\Sylius\Bundle\ApiBundle\ApiPlatform\Routing;
|
||||
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\PhpUnit\ProphecyTrait;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Sylius\Bundle\ApiBundle\ApiPlatform\Routing\ApiLoader;
|
||||
use Symfony\Component\Config\Loader\LoaderInterface;
|
||||
use Symfony\Component\Config\Loader\LoaderResolverInterface;
|
||||
|
|
@ -24,18 +23,16 @@ use Symfony\Component\Routing\RouteCollection;
|
|||
|
||||
final class ApiLoaderTest extends TestCase
|
||||
{
|
||||
use ProphecyTrait;
|
||||
|
||||
private LoaderInterface|ObjectProphecy $baseApiLoader;
|
||||
private LoaderInterface&MockObject $baseApiLoader;
|
||||
|
||||
private LoaderInterface $apiLoader;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->baseApiLoader = $this->prophesize(LoaderInterface::class);
|
||||
$this->baseApiLoader = $this->createMock(LoaderInterface::class);
|
||||
|
||||
$this->apiLoader = new ApiLoader(
|
||||
$this->baseApiLoader->reveal(),
|
||||
$this->baseApiLoader,
|
||||
[
|
||||
'sylius_api_shop_currency_get',
|
||||
'sylius_api_shop_currency_get_collection',
|
||||
|
|
@ -52,24 +49,33 @@ final class ApiLoaderTest extends TestCase
|
|||
#[Test]
|
||||
public function it_removes_routes_from_route_collection_loaded_by_base_api_loader(): void
|
||||
{
|
||||
$routeCollection = $this->prophesize(RouteCollection::class);
|
||||
$routeCollection = $this->createMock(RouteCollection::class);
|
||||
|
||||
$this->baseApiLoader
|
||||
->expects($this->once())
|
||||
->method('load')
|
||||
->with('.', 'api_platform')
|
||||
->willReturn($routeCollection);
|
||||
|
||||
$this->baseApiLoader->load('.', 'api_platform')->willReturn($routeCollection);
|
||||
$routeCollection
|
||||
->remove([
|
||||
->expects($this->once())
|
||||
->method('remove')
|
||||
->with([
|
||||
'sylius_api_shop_currency_get',
|
||||
'sylius_api_shop_currency_get_collection',
|
||||
])
|
||||
->shouldBeCalled()
|
||||
;
|
||||
]);
|
||||
|
||||
$this->assertSame($routeCollection->reveal(), $this->apiLoader->load('.', 'api_platform'));
|
||||
$this->assertSame($routeCollection, $this->apiLoader->load('.', 'api_platform'));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function it_uses_base_api_loader_for_supports_method(): void
|
||||
{
|
||||
$this->baseApiLoader->supports('.', 'api_platform')->willReturn(true);
|
||||
$this->baseApiLoader
|
||||
->expects($this->once())
|
||||
->method('supports')
|
||||
->with('.', 'api_platform')
|
||||
->willReturn(true);
|
||||
|
||||
$this->assertTrue($this->apiLoader->supports('.', 'api_platform'));
|
||||
}
|
||||
|
|
@ -77,20 +83,26 @@ final class ApiLoaderTest extends TestCase
|
|||
#[Test]
|
||||
public function it_uses_base_api_loader_to_get_resolver(): void
|
||||
{
|
||||
$loaderResolver = $this->prophesize(LoaderResolverInterface::class);
|
||||
$loaderResolver = $this->createMock(LoaderResolverInterface::class);
|
||||
|
||||
$this->baseApiLoader->getResolver()->willReturn($loaderResolver);
|
||||
$this->baseApiLoader
|
||||
->expects($this->once())
|
||||
->method('getResolver')
|
||||
->willReturn($loaderResolver);
|
||||
|
||||
$this->assertSame($loaderResolver->reveal(), $this->apiLoader->getResolver());
|
||||
$this->assertSame($loaderResolver, $this->apiLoader->getResolver());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function it_uses_base_api_loader_to_set_resolver(): void
|
||||
{
|
||||
$loaderResolver = $this->prophesize(LoaderResolverInterface::class);
|
||||
$loaderResolver = $this->createMock(LoaderResolverInterface::class);
|
||||
|
||||
$this->baseApiLoader->setResolver($loaderResolver->reveal())->shouldBeCalled();
|
||||
$this->baseApiLoader
|
||||
->expects($this->once())
|
||||
->method('setResolver')
|
||||
->with($loaderResolver);
|
||||
|
||||
$this->apiLoader->setResolver($loaderResolver->reveal());
|
||||
$this->apiLoader->setResolver($loaderResolver);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ final class FooApiCommandTest extends ApiTestCase
|
|||
|
||||
$this->assertResponseHeaderSame('content-type', 'application/problem+json; charset=utf-8');
|
||||
|
||||
$this->assertResponseStatusCodeSame(Response::HTTP_BAD_REQUEST);
|
||||
$this->assertResponseStatusCodeSame(Response::HTTP_UNPROCESSABLE_ENTITY);
|
||||
$this->assertJsonContains([
|
||||
'hydra:description' => 'Request does not have the following required fields specified: bar.',
|
||||
'hydra:title' => 'An error occurred',
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ namespace Sylius\Bundle\ApiBundle\Application\Tests;
|
|||
|
||||
use ApiPlatform\Symfony\Bundle\Test\ApiTestCase;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
final class MergingConfigsTest extends ApiTestCase
|
||||
{
|
||||
|
|
@ -79,7 +80,7 @@ final class MergingConfigsTest extends ApiTestCase
|
|||
],
|
||||
]);
|
||||
|
||||
self::assertResponseStatusCodeSame(400);
|
||||
self::assertResponseStatusCodeSame(Response::HTTP_UNPROCESSABLE_ENTITY);
|
||||
|
||||
static::createClient()->request('POST', '/api/v2/shop/bar', [
|
||||
'json' => [
|
||||
|
|
|
|||
|
|
@ -14,9 +14,8 @@ declare(strict_types=1);
|
|||
namespace Tests\Sylius\Bundle\ApiBundle\CommandHandler;
|
||||
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\PhpUnit\ProphecyTrait;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Sylius\Bundle\ApiBundle\Command\Payment\AddPaymentRequest;
|
||||
use Sylius\Bundle\ApiBundle\CommandHandler\Payment\AddPaymentRequestHandler;
|
||||
use Sylius\Bundle\ApiBundle\Exception\PaymentMethodNotFoundException;
|
||||
|
|
@ -33,38 +32,36 @@ use Sylius\Component\Payment\Repository\PaymentRequestRepositoryInterface;
|
|||
|
||||
final class AddPaymentRequestHandlerTest extends TestCase
|
||||
{
|
||||
use ProphecyTrait;
|
||||
private PaymentMethodRepositoryInterface&MockObject $paymentMethodRepository;
|
||||
|
||||
private ObjectProphecy|PaymentMethodRepositoryInterface $paymentMethodRepository;
|
||||
private PaymentRepositoryInterface&MockObject $paymentRepository;
|
||||
|
||||
private ObjectProphecy|PaymentRepositoryInterface $paymentRepository;
|
||||
private PaymentRequestFactoryInterface&MockObject $paymentRequestFactory;
|
||||
|
||||
private ObjectProphecy|PaymentRequestFactoryInterface $paymentRequestFactory;
|
||||
private PaymentRequestRepositoryInterface&MockObject $paymentRequestRepository;
|
||||
|
||||
private ObjectProphecy|PaymentRequestRepositoryInterface $paymentRequestRepository;
|
||||
private DefaultActionProviderInterface&MockObject $defaultActionProvider;
|
||||
|
||||
private DefaultActionProviderInterface|ObjectProphecy $defaultActionProvider;
|
||||
|
||||
private DefaultPayloadProviderInterface|ObjectProphecy $defaultPayloadProvider;
|
||||
private DefaultPayloadProviderInterface&MockObject $defaultPayloadProvider;
|
||||
|
||||
private AddPaymentRequestHandler $addPaymentRequestHandler;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->paymentMethodRepository = $this->prophesize(PaymentMethodRepositoryInterface::class);
|
||||
$this->paymentRepository = $this->prophesize(PaymentRepositoryInterface::class);
|
||||
$this->paymentRequestFactory = $this->prophesize(PaymentRequestFactoryInterface::class);
|
||||
$this->paymentRequestRepository = $this->prophesize(PaymentRequestRepositoryInterface::class);
|
||||
$this->defaultActionProvider = $this->prophesize(DefaultActionProviderInterface::class);
|
||||
$this->defaultPayloadProvider = $this->prophesize(DefaultPayloadProviderInterface::class);
|
||||
$this->paymentMethodRepository = $this->createMock(PaymentMethodRepositoryInterface::class);
|
||||
$this->paymentRepository = $this->createMock(PaymentRepositoryInterface::class);
|
||||
$this->paymentRequestFactory = $this->createMock(PaymentRequestFactoryInterface::class);
|
||||
$this->paymentRequestRepository = $this->createMock(PaymentRequestRepositoryInterface::class);
|
||||
$this->defaultActionProvider = $this->createMock(DefaultActionProviderInterface::class);
|
||||
$this->defaultPayloadProvider = $this->createMock(DefaultPayloadProviderInterface::class);
|
||||
|
||||
$this->addPaymentRequestHandler = new AddPaymentRequestHandler(
|
||||
$this->paymentMethodRepository->reveal(),
|
||||
$this->paymentRepository->reveal(),
|
||||
$this->paymentRequestFactory->reveal(),
|
||||
$this->paymentRequestRepository->reveal(),
|
||||
$this->defaultActionProvider->reveal(),
|
||||
$this->defaultPayloadProvider->reveal(),
|
||||
$this->paymentMethodRepository,
|
||||
$this->paymentRepository,
|
||||
$this->paymentRequestFactory,
|
||||
$this->paymentRequestRepository,
|
||||
$this->defaultActionProvider,
|
||||
$this->defaultPayloadProvider,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -73,7 +70,7 @@ final class AddPaymentRequestHandlerTest extends TestCase
|
|||
{
|
||||
self::expectException(PaymentNotFoundException::class);
|
||||
|
||||
$this->paymentRepository->findOneByOrderToken(1, 'token')->willReturn(null);
|
||||
$this->paymentRepository->method('findOneByOrderToken')->with(1, 'token')->willReturn(null);
|
||||
|
||||
$this->addPaymentRequestHandler->__invoke(new AddPaymentRequest('token', 1, 'bank_transfer'));
|
||||
}
|
||||
|
|
@ -83,10 +80,10 @@ final class AddPaymentRequestHandlerTest extends TestCase
|
|||
{
|
||||
self::expectException(PaymentMethodNotFoundException::class);
|
||||
|
||||
$payment = $this->prophesize(PaymentInterface::class);
|
||||
$payment = $this->createMock(PaymentInterface::class);
|
||||
|
||||
$this->paymentRepository->findOneByOrderToken(1, 'token')->willReturn($payment->reveal());
|
||||
$this->paymentMethodRepository->findOneBy(['code' => 'bank_transfer'])->willReturn(null);
|
||||
$this->paymentRepository->method('findOneByOrderToken')->with(1, 'token')->willReturn($payment);
|
||||
$this->paymentMethodRepository->method('findOneBy')->with(['code' => 'bank_transfer'])->willReturn(null);
|
||||
|
||||
$this->addPaymentRequestHandler->__invoke(new AddPaymentRequest('token', 1, 'bank_transfer'));
|
||||
}
|
||||
|
|
@ -94,21 +91,21 @@ final class AddPaymentRequestHandlerTest extends TestCase
|
|||
#[Test]
|
||||
public function it_creates_a_payment_request(): void
|
||||
{
|
||||
$payment = $this->prophesize(PaymentInterface::class);
|
||||
$paymentMethod = $this->prophesize(PaymentMethodInterface::class);
|
||||
$paymentRequest = $this->prophesize(PaymentRequestInterface::class);
|
||||
$payment = $this->createMock(PaymentInterface::class);
|
||||
$paymentMethod = $this->createMock(PaymentMethodInterface::class);
|
||||
$paymentRequest = $this->createMock(PaymentRequestInterface::class);
|
||||
|
||||
$this->paymentRepository->findOneByOrderToken(1, 'token')->willReturn($payment->reveal());
|
||||
$this->paymentMethodRepository->findOneBy(['code' => 'bank_transfer'])->willReturn($paymentMethod->reveal());
|
||||
$this->defaultActionProvider->getAction($paymentRequest)->willReturn('authorize');
|
||||
$this->defaultPayloadProvider->getPayload($paymentRequest)->willReturn(['foo' => 'bar']);
|
||||
$this->paymentRepository->method('findOneByOrderToken')->with(1, 'token')->willReturn($payment);
|
||||
$this->paymentMethodRepository->method('findOneBy')->with(['code' => 'bank_transfer'])->willReturn($paymentMethod);
|
||||
$this->defaultActionProvider->method('getAction')->with($paymentRequest)->willReturn('authorize');
|
||||
$this->defaultPayloadProvider->method('getPayload')->with($paymentRequest)->willReturn(['foo' => 'bar']);
|
||||
|
||||
$this->paymentRequestFactory->create($payment->reveal(), $paymentMethod->reveal())->willReturn($paymentRequest->reveal());
|
||||
$paymentRequest->setAction('authorize')->shouldBeCalled();
|
||||
$paymentRequest->setPayload(['foo' => 'bar'])->shouldBeCalled();
|
||||
$this->paymentRequestFactory->method('create')->with($payment, $paymentMethod)->willReturn($paymentRequest);
|
||||
$paymentRequest->expects($this->once())->method('setAction')->with('authorize');
|
||||
$paymentRequest->expects($this->once())->method('setPayload')->with(['foo' => 'bar']);
|
||||
|
||||
self::assertSame(
|
||||
$paymentRequest->reveal(),
|
||||
$paymentRequest,
|
||||
$this->addPaymentRequestHandler->__invoke(
|
||||
new AddPaymentRequest('token', 1, 'bank_transfer'),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -20,10 +20,8 @@ use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInter
|
|||
use ApiPlatform\Metadata\UriVariablesConverterInterface;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\PhpUnit\ProphecyTrait;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Sylius\Bundle\ApiBundle\Command\Catalog\AddProductReview;
|
||||
use Sylius\Bundle\ApiBundle\Converter\IriToIdentifierConverter;
|
||||
use Sylius\Bundle\ApiBundle\Converter\IriToIdentifierConverterInterface;
|
||||
|
|
@ -33,26 +31,24 @@ use Symfony\Component\Routing\RouterInterface;
|
|||
|
||||
final class IriToIdentifierConverterTest extends TestCase
|
||||
{
|
||||
use ProphecyTrait;
|
||||
private RouterInterface&MockObject $router;
|
||||
|
||||
private ObjectProphecy|RouterInterface $router;
|
||||
private ResourceMetadataCollectionFactoryInterface&MockObject $metadataFactory;
|
||||
|
||||
private ObjectProphecy|ResourceMetadataCollectionFactoryInterface $metadataFactory;
|
||||
|
||||
private ObjectProphecy|UriVariablesConverterInterface $uriVariablesConverter;
|
||||
private UriVariablesConverterInterface&MockObject $uriVariablesConverter;
|
||||
|
||||
private IriToIdentifierConverterInterface $converter;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->router = $this->prophesize(RouterInterface::class);
|
||||
$this->metadataFactory = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class);
|
||||
$this->uriVariablesConverter = $this->prophesize(UriVariablesConverterInterface::class);
|
||||
$this->router = $this->createMock(RouterInterface::class);
|
||||
$this->metadataFactory = $this->createMock(ResourceMetadataCollectionFactoryInterface::class);
|
||||
$this->uriVariablesConverter = $this->createMock(UriVariablesConverterInterface::class);
|
||||
|
||||
$this->converter = new IriToIdentifierConverter(
|
||||
$this->router->reveal(),
|
||||
$this->metadataFactory->reveal(),
|
||||
$this->uriVariablesConverter->reveal(),
|
||||
$this->router,
|
||||
$this->metadataFactory,
|
||||
$this->uriVariablesConverter,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -60,7 +56,9 @@ final class IriToIdentifierConverterTest extends TestCase
|
|||
#[Test]
|
||||
public function it_treats_non_string_values_as_not_identifiers(mixed $invalidValue): void
|
||||
{
|
||||
$this->router->match(Argument::any())->shouldNotBeCalled();
|
||||
$this->router
|
||||
->expects($this->never())
|
||||
->method('match');
|
||||
|
||||
$this->assertFalse($this->converter->isIdentifier($invalidValue));
|
||||
}
|
||||
|
|
@ -68,7 +66,11 @@ final class IriToIdentifierConverterTest extends TestCase
|
|||
#[Test]
|
||||
public function it_treats_not_matched_strings_as_not_identifiers(): void
|
||||
{
|
||||
$this->router->match('test')->willThrow(new SymfonyRouteNotFoundException());
|
||||
$this->router
|
||||
->expects($this->once())
|
||||
->method('match')
|
||||
->with('test')
|
||||
->willThrowException(new SymfonyRouteNotFoundException());
|
||||
|
||||
$this->assertFalse($this->converter->isIdentifier('test'));
|
||||
}
|
||||
|
|
@ -76,7 +78,11 @@ final class IriToIdentifierConverterTest extends TestCase
|
|||
#[Test]
|
||||
public function it_treats_strings_matched_on_routes_with_no_resource_class_parameter_as_not_identifiers(): void
|
||||
{
|
||||
$this->router->match('test')->willReturn([]);
|
||||
$this->router
|
||||
->expects($this->once())
|
||||
->method('match')
|
||||
->with('test')
|
||||
->willReturn([]);
|
||||
|
||||
$this->assertFalse($this->converter->isIdentifier('test'));
|
||||
}
|
||||
|
|
@ -84,9 +90,13 @@ final class IriToIdentifierConverterTest extends TestCase
|
|||
#[Test]
|
||||
public function it_treats_strings_matched_on_routes_with_resource_class_parameter_as_identifiers(): void
|
||||
{
|
||||
$this->router->match('test')->willReturn([
|
||||
'_api_resource_class' => 'test',
|
||||
]);
|
||||
$this->router
|
||||
->expects($this->once())
|
||||
->method('match')
|
||||
->with('test')
|
||||
->willReturn([
|
||||
'_api_resource_class' => 'test',
|
||||
]);
|
||||
|
||||
$this->assertTrue($this->converter->isIdentifier('test'));
|
||||
}
|
||||
|
|
@ -96,9 +106,11 @@ final class IriToIdentifierConverterTest extends TestCase
|
|||
public function it_sanitizes_url_before_matching_for_various_characters(string $rawUrl): void
|
||||
{
|
||||
$sanitized = filter_var($rawUrl, \FILTER_SANITIZE_URL);
|
||||
$this->router->match(Argument::that(fn ($arg) => $arg === $sanitized))
|
||||
->willReturn(['_api_resource_class' => 'test'])
|
||||
->shouldBeCalled();
|
||||
$this->router
|
||||
->expects($this->once())
|
||||
->method('match')
|
||||
->with($sanitized)
|
||||
->willReturn(['_api_resource_class' => 'test']);
|
||||
|
||||
$this->assertTrue($this->converter->isIdentifier($rawUrl));
|
||||
}
|
||||
|
|
@ -109,9 +121,11 @@ final class IriToIdentifierConverterTest extends TestCase
|
|||
{
|
||||
$sanitized = filter_var($rawUrl, \FILTER_SANITIZE_URL);
|
||||
|
||||
$this->router->match(Argument::that(fn ($arg) => $arg === $sanitized))
|
||||
->willThrow(new SymfonyRouteNotFoundException())
|
||||
->shouldBeCalled();
|
||||
$this->router
|
||||
->expects($this->once())
|
||||
->method('match')
|
||||
->with($sanitized)
|
||||
->willThrowException(new SymfonyRouteNotFoundException());
|
||||
|
||||
$this->assertFalse($this->converter->isIdentifier($rawUrl));
|
||||
}
|
||||
|
|
@ -122,9 +136,11 @@ final class IriToIdentifierConverterTest extends TestCase
|
|||
$rawUrl = "api/v2/produc\nts/2";
|
||||
$sanitized = filter_var($rawUrl, \FILTER_SANITIZE_URL);
|
||||
|
||||
$this->router->match(Argument::that(fn ($arg) => $arg === $sanitized))
|
||||
->willReturn(['_api_resource_class' => 'test'])
|
||||
->shouldBeCalled();
|
||||
$this->router
|
||||
->expects($this->once())
|
||||
->method('match')
|
||||
->with($sanitized)
|
||||
->willReturn(['_api_resource_class' => 'test']);
|
||||
|
||||
$this->assertTrue($this->converter->isIdentifier($rawUrl));
|
||||
}
|
||||
|
|
@ -135,9 +151,11 @@ final class IriToIdentifierConverterTest extends TestCase
|
|||
$rawUrl = "api/v2/produc\nts/3";
|
||||
$sanitized = filter_var($rawUrl, \FILTER_SANITIZE_URL);
|
||||
|
||||
$this->router->match(Argument::that(fn ($arg) => $arg === $sanitized))
|
||||
->willThrow(new SymfonyRouteNotFoundException())
|
||||
->shouldBeCalled();
|
||||
$this->router
|
||||
->expects($this->once())
|
||||
->method('match')
|
||||
->with($sanitized)
|
||||
->willThrowException(new SymfonyRouteNotFoundException());
|
||||
|
||||
$this->assertFalse($this->converter->isIdentifier($rawUrl));
|
||||
}
|
||||
|
|
@ -148,7 +166,11 @@ final class IriToIdentifierConverterTest extends TestCase
|
|||
self::expectException(ApiRouteNotFoundException::class);
|
||||
self::expectExceptionMessage('No route matches "/users/3".');
|
||||
|
||||
$this->router->match('/users/3')->willThrow(new SymfonyRouteNotFoundException())->shouldBeCalledTimes(1);
|
||||
$this->router
|
||||
->expects($this->once())
|
||||
->method('match')
|
||||
->with('/users/3')
|
||||
->willThrowException(new SymfonyRouteNotFoundException());
|
||||
|
||||
$this->converter->getIdentifier('/users/3');
|
||||
}
|
||||
|
|
@ -159,9 +181,13 @@ final class IriToIdentifierConverterTest extends TestCase
|
|||
self::expectException(InvalidArgumentException::class);
|
||||
self::expectExceptionMessage('No resource associated to "/users/3".');
|
||||
|
||||
$this->router->match('/users/3')->willReturn([
|
||||
'_api_operation_name' => 'get',
|
||||
])->shouldBeCalledTimes(1);
|
||||
$this->router
|
||||
->expects($this->once())
|
||||
->method('match')
|
||||
->with('/users/3')
|
||||
->willReturn([
|
||||
'_api_operation_name' => 'get',
|
||||
]);
|
||||
|
||||
$this->converter->getIdentifier('/users/3');
|
||||
}
|
||||
|
|
@ -172,9 +198,13 @@ final class IriToIdentifierConverterTest extends TestCase
|
|||
self::expectException(InvalidArgumentException::class);
|
||||
self::expectExceptionMessage('No resource associated to "/users/3".');
|
||||
|
||||
$this->router->match('/users/3')->willReturn([
|
||||
'_api_resource_class' => AddProductReview::class,
|
||||
])->shouldBeCalledTimes(1);
|
||||
$this->router
|
||||
->expects($this->once())
|
||||
->method('match')
|
||||
->with('/users/3')
|
||||
->willReturn([
|
||||
'_api_resource_class' => AddProductReview::class,
|
||||
]);
|
||||
|
||||
$this->converter->getIdentifier('/users/3');
|
||||
}
|
||||
|
|
@ -185,51 +215,81 @@ final class IriToIdentifierConverterTest extends TestCase
|
|||
self::expectException(InvalidArgumentException::class);
|
||||
self::expectExceptionMessage('IriToIdentifierConverter does not support subresources');
|
||||
|
||||
$operation = $this->prophesize(HttpOperation::class);
|
||||
$operation->getClass()->willReturn(AddProductReview::class);
|
||||
$operation->getUriVariables()->willReturn([
|
||||
'id' => new Link('id', identifiers: ['id'], compositeIdentifier: true),
|
||||
'nextId' => new Link('nextId', identifiers: ['nextId'], compositeIdentifier: true),
|
||||
]);
|
||||
$operation = $this->createMock(HttpOperation::class);
|
||||
$operation
|
||||
->expects($this->any())
|
||||
->method('getClass')
|
||||
->willReturn(AddProductReview::class);
|
||||
|
||||
$this->router->match('/users/3/nexts/5')->willReturn([
|
||||
'_api_resource_class' => AddProductReview::class,
|
||||
'_api_operation_name' => 'get',
|
||||
'id' => 3,
|
||||
'nextId' => 5,
|
||||
])->shouldBeCalledTimes(1);
|
||||
$operation
|
||||
->expects($this->once())
|
||||
->method('getUriVariables')
|
||||
->willReturn([
|
||||
'id' => new Link('id', identifiers: ['id'], compositeIdentifier: true),
|
||||
'nextId' => new Link('nextId', identifiers: ['nextId'], compositeIdentifier: true),
|
||||
]);
|
||||
|
||||
$this->uriVariablesConverter->convert(
|
||||
['id' => 3, 'nextId' => 5],
|
||||
AddProductReview::class,
|
||||
Argument::cetera(),
|
||||
)->willReturn(['3', '5']);
|
||||
$this->router
|
||||
->expects($this->once())
|
||||
->method('match')
|
||||
->with('/users/3/nexts/5')
|
||||
->willReturn([
|
||||
'_api_resource_class' => AddProductReview::class,
|
||||
'_api_operation_name' => 'get',
|
||||
'id' => 3,
|
||||
'nextId' => 5,
|
||||
]);
|
||||
|
||||
$this->converter->getIdentifier('/users/3/nexts/5', $operation->reveal());
|
||||
$this->uriVariablesConverter
|
||||
->expects($this->once())
|
||||
->method('convert')
|
||||
->with(
|
||||
['id' => 3, 'nextId' => 5],
|
||||
AddProductReview::class,
|
||||
$this->anything(),
|
||||
)
|
||||
->willReturn(['3', '5']);
|
||||
|
||||
$this->converter->getIdentifier('/users/3/nexts/5', $operation);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function it_gets_identifier(): void
|
||||
{
|
||||
$operation = $this->prophesize(HttpOperation::class);
|
||||
$operation->getClass()->willReturn(AddProductReview::class);
|
||||
$operation->getUriVariables()->willReturn([
|
||||
'id' => new Link('id', identifiers: ['id'], compositeIdentifier: true),
|
||||
]);
|
||||
$operation = $this->createMock(HttpOperation::class);
|
||||
$operation
|
||||
->expects($this->any())
|
||||
->method('getClass')
|
||||
->willReturn(AddProductReview::class);
|
||||
|
||||
$this->router->match('/users/3')->willReturn([
|
||||
'_api_resource_class' => AddProductReview::class,
|
||||
'_api_operation_name' => 'get',
|
||||
'id' => 3,
|
||||
])->shouldBeCalledTimes(1);
|
||||
$operation
|
||||
->expects($this->once())
|
||||
->method('getUriVariables')
|
||||
->willReturn([
|
||||
'id' => new Link('id', identifiers: ['id'], compositeIdentifier: true),
|
||||
]);
|
||||
|
||||
$this->uriVariablesConverter->convert(
|
||||
['id' => 3],
|
||||
AddProductReview::class,
|
||||
Argument::cetera(),
|
||||
)->willReturn(['3']);
|
||||
$this->router
|
||||
->expects($this->once())
|
||||
->method('match')
|
||||
->with('/users/3')
|
||||
->willReturn([
|
||||
'_api_resource_class' => AddProductReview::class,
|
||||
'_api_operation_name' => 'get',
|
||||
'id' => 3,
|
||||
]);
|
||||
|
||||
$this->assertSame('3', $this->converter->getIdentifier('/users/3', $operation->reveal()));
|
||||
$this->uriVariablesConverter
|
||||
->expects($this->once())
|
||||
->method('convert')
|
||||
->with(
|
||||
['id' => 3],
|
||||
AddProductReview::class,
|
||||
$this->anything(),
|
||||
)
|
||||
->willReturn(['3']);
|
||||
|
||||
$this->assertSame('3', $this->converter->getIdentifier('/users/3', $operation));
|
||||
}
|
||||
|
||||
public static function invalidIdentifierValues(): iterable
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue