Passed
Push — master ( 9b0780...47580e )
by Christian
11:03 queued 10s
created

createSalesChannelContext()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 33
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 28
nc 1
nop 0
dl 0
loc 33
rs 9.472
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace Shopware\Storefront\Test\Page;
4
5
use PHPUnit\Framework\TestCase;
6
use Shopware\Core\Checkout\Cart\CartRuleLoader;
7
use Shopware\Core\Checkout\Cart\Exception\CustomerNotLoggedInException;
8
use Shopware\Core\Checkout\Cart\LineItem\LineItem;
9
use Shopware\Core\Checkout\Cart\SalesChannel\CartService;
10
use Shopware\Core\Checkout\Customer\CustomerEntity;
11
use Shopware\Core\Content\Product\Aggregate\ProductVisibility\ProductVisibilityDefinition;
12
use Shopware\Core\Content\Product\ProductEntity;
13
use Shopware\Core\Defaults;
14
use Shopware\Core\Framework\Api\Util\AccessKeyHelper;
15
use Shopware\Core\Framework\Context;
16
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
17
use Shopware\Core\Framework\Routing\Exception\MissingRequestParameterException;
18
use Shopware\Core\Framework\Struct\Struct;
19
use Shopware\Core\Framework\Test\TestCaseBase\TaxAddToSalesChannelTestBehaviour;
20
use Shopware\Core\Framework\Test\TestCaseHelper\ReflectionHelper;
21
use Shopware\Core\Framework\Uuid\Uuid;
22
use Shopware\Core\System\SalesChannel\Context\SalesChannelContextFactory;
23
use Shopware\Core\System\SalesChannel\Context\SalesChannelContextService;
24
use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepositoryInterface;
25
use Shopware\Core\System\SalesChannel\SalesChannelContext;
26
use Shopware\Storefront\Page\PageLoadedEvent;
27
use Shopware\Storefront\Pagelet\PageletLoadedEvent;
28
use Symfony\Component\DependencyInjection\ContainerInterface;
29
use Symfony\Component\HttpFoundation\Request;
30
31
trait StorefrontPageTestBehaviour
32
{
33
    use TaxAddToSalesChannelTestBehaviour;
34
35
    public static function assertPageEvent(
36
        string $expectedClass,
37
        PageLoadedEvent $event,
38
        SalesChannelContext $salesChannelContext,
39
        Request $request,
40
        Struct $page
41
    ): void {
42
        TestCase::assertInstanceOf($expectedClass, $event);
43
        TestCase::assertSame($salesChannelContext, $event->getSalesChannelContext());
44
        TestCase::assertSame($salesChannelContext->getContext(), $event->getContext());
45
        TestCase::assertSame($request, $event->getRequest());
46
        TestCase::assertSame($page, $event->getPage());
47
    }
48
49
    public static function assertPageletEvent(
50
        string $expectedClass,
51
        PageletLoadedEvent $event,
52
        SalesChannelContext $salesChannelContext,
53
        Request $request,
54
        Struct $page
55
    ): void {
56
        TestCase::assertInstanceOf($expectedClass, $event);
57
        TestCase::assertSame($salesChannelContext, $event->getSalesChannelContext());
58
        TestCase::assertSame($salesChannelContext->getContext(), $event->getContext());
59
        TestCase::assertSame($request, $event->getRequest());
60
        TestCase::assertSame($page, $event->getPagelet());
61
    }
62
63
    abstract protected function getPageLoader();
64
65
    protected function assertLoginRequirement(array $queryParams = []): void
66
    {
67
        $request = new Request($queryParams);
68
        $context = $this->createSalesChannelContextWithNavigation();
69
        $this->expectException(CustomerNotLoggedInException::class);
0 ignored issues
show
Bug introduced by
It seems like expectException() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

69
        $this->/** @scrutinizer ignore-call */ 
70
               expectException(CustomerNotLoggedInException::class);
Loading history...
70
        $this->getPageLoader()->load($request, $context);
71
    }
72
73
    protected function expectParamMissingException(string $paramName): void
74
    {
75
        $this->expectException(MissingRequestParameterException::class);
76
        $this->expectExceptionMessage('Parameter "' . $paramName . '" is missing');
0 ignored issues
show
Bug introduced by
It seems like expectExceptionMessage() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

76
        $this->/** @scrutinizer ignore-call */ 
77
               expectExceptionMessage('Parameter "' . $paramName . '" is missing');
Loading history...
77
    }
78
79
    protected function placeRandomOrder(SalesChannelContext $context): string
80
    {
81
        $product = $this->getRandomProduct($context);
82
83
        $lineItem = (new LineItem($product->getId(), LineItem::PRODUCT_LINE_ITEM_TYPE, $product->getId()))
84
            ->setRemovable(true)
85
            ->setStackable(true);
86
87
        $cartService = $this->getContainer()->get(CartService::class);
88
        $cart = $cartService->getCart($context->getToken(), $context);
89
        $cart->add($lineItem);
90
91
        return $cartService->order($cart, $context);
92
    }
93
94
    protected function getRandomProduct(SalesChannelContext $context, ?int $stock = 1, ?bool $isCloseout = false, ?array $config = []): ProductEntity
95
    {
96
        $id = Uuid::randomHex();
97
        $productNumber = Uuid::randomHex();
98
        $productRepository = $this->getContainer()->get('product.repository');
99
100
        $data = [
101
            'id' => $id,
102
            'productNumber' => $productNumber,
103
            'stock' => $stock,
104
            'name' => StorefrontPageTestConstants::PRODUCT_NAME,
105
            'price' => [['currencyId' => Defaults::CURRENCY, 'gross' => 15, 'net' => 10, 'linked' => false]],
106
            'manufacturer' => ['name' => 'test'],
107
            'tax' => ['id' => Uuid::randomHex(), 'name' => 'test', 'taxRate' => 15],
108
            'active' => true,
109
            'isCloseout' => $isCloseout,
110
            'categories' => [
111
                ['id' => Uuid::randomHex(), 'name' => 'asd'],
112
            ],
113
            'visibilities' => [
114
                ['salesChannelId' => $context->getSalesChannel()->getId(), 'visibility' => ProductVisibilityDefinition::VISIBILITY_ALL],
115
            ],
116
        ];
117
118
        $data = array_merge_recursive($data, $config);
119
120
        $productRepository->create([$data], $context->getContext());
121
        $this->addTaxDataToSalesChannel($context, $data['tax']);
122
123
        /** @var SalesChannelRepositoryInterface $storefrontProductRepository */
124
        $storefrontProductRepository = $this->getContainer()->get('sales_channel.product.repository');
125
        $searchResult = $storefrontProductRepository->search(new Criteria([$id]), $context);
126
127
        return $searchResult->first();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $searchResult->first() could return the type null which is incompatible with the type-hinted return Shopware\Core\Content\Product\ProductEntity. Consider adding an additional type-check to rule them out.
Loading history...
128
    }
129
130
    protected function createSalesChannelContextWithNavigation(): SalesChannelContext
131
    {
132
        $paymentMethodId = $this->getValidPaymentMethodId();
0 ignored issues
show
Bug introduced by
It seems like getValidPaymentMethodId() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

132
        /** @scrutinizer ignore-call */ 
133
        $paymentMethodId = $this->getValidPaymentMethodId();
Loading history...
133
        $shippingMethodId = $this->getAvailableShippingMethod()->getId();
0 ignored issues
show
Bug introduced by
It seems like getAvailableShippingMethod() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

133
        $shippingMethodId = $this->/** @scrutinizer ignore-call */ getAvailableShippingMethod()->getId();
Loading history...
134
        $countryId = $this->getValidCountryId();
0 ignored issues
show
Bug introduced by
It seems like getValidCountryId() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

134
        /** @scrutinizer ignore-call */ 
135
        $countryId = $this->getValidCountryId();
Loading history...
135
        $snippetSetId = $this->getSnippetSetIdForLocale('en-GB');
0 ignored issues
show
Bug introduced by
It seems like getSnippetSetIdForLocale() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

135
        /** @scrutinizer ignore-call */ 
136
        $snippetSetId = $this->getSnippetSetIdForLocale('en-GB');
Loading history...
136
        $data = [
137
            'typeId' => Defaults::SALES_CHANNEL_TYPE_STOREFRONT,
138
            'name' => 'store front',
139
            'accessKey' => AccessKeyHelper::generateAccessKey('sales-channel'),
140
            'languageId' => Defaults::LANGUAGE_SYSTEM,
141
            'snippetSetId' => $snippetSetId,
142
            'currencyId' => Defaults::CURRENCY,
143
            'currencyVersionId' => Defaults::LIVE_VERSION,
144
            'paymentMethodId' => $paymentMethodId,
145
            'paymentMethodVersionId' => Defaults::LIVE_VERSION,
146
            'shippingMethodId' => $shippingMethodId,
147
            'shippingMethodVersionId' => Defaults::LIVE_VERSION,
148
            'navigationCategoryId' => $this->getValidCategoryId(),
0 ignored issues
show
Bug introduced by
It seems like getValidCategoryId() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

148
            'navigationCategoryId' => $this->/** @scrutinizer ignore-call */ getValidCategoryId(),
Loading history...
149
            'navigationCategoryVersionId' => Defaults::LIVE_VERSION,
150
            'countryId' => $countryId,
151
            'countryVersionId' => Defaults::LIVE_VERSION,
152
            'currencies' => [['id' => Defaults::CURRENCY]],
153
            'languages' => [['id' => Defaults::LANGUAGE_SYSTEM]],
154
            'paymentMethods' => [['id' => $paymentMethodId]],
155
            'shippingMethods' => [['id' => $shippingMethodId]],
156
            'countries' => [['id' => $countryId]],
157
            'domains' => [
158
                ['url' => 'http://test.com/' . Uuid::randomHex(), 'currencyId' => Defaults::CURRENCY, 'languageId' => Defaults::LANGUAGE_SYSTEM, 'snippetSetId' => $snippetSetId],
159
            ],
160
        ];
161
162
        return $this->createContext($data, []);
163
    }
164
165
    protected function createSalesChannelContextWithLoggedInCustomerAndWithNavigation(): SalesChannelContext
166
    {
167
        $paymentMethodId = $this->getValidPaymentMethodId();
168
        $shippingMethodId = $this->getAvailableShippingMethod()->getId();
169
        $countryId = $this->getValidCountryId();
170
        $snippetSetId = $this->getSnippetSetIdForLocale('en-GB');
171
        $data = [
172
            'typeId' => Defaults::SALES_CHANNEL_TYPE_STOREFRONT,
173
            'name' => 'store front',
174
            'accessKey' => AccessKeyHelper::generateAccessKey('sales-channel'),
175
            'languageId' => Defaults::LANGUAGE_SYSTEM,
176
            'snippetSetId' => $snippetSetId,
177
            'currencyId' => Defaults::CURRENCY,
178
            'currencyVersionId' => Defaults::LIVE_VERSION,
179
            'paymentMethodId' => $paymentMethodId,
180
            'paymentMethodVersionId' => Defaults::LIVE_VERSION,
181
            'shippingMethodId' => $shippingMethodId,
182
            'shippingMethodVersionId' => Defaults::LIVE_VERSION,
183
            'navigationCategoryId' => $this->getValidCategoryId(),
184
            'countryId' => $countryId,
185
            'countryVersionId' => Defaults::LIVE_VERSION,
186
            'currencies' => [['id' => Defaults::CURRENCY]],
187
            'languages' => [['id' => Defaults::LANGUAGE_SYSTEM]],
188
            'paymentMethods' => [['id' => $paymentMethodId]],
189
            'shippingMethods' => [['id' => $shippingMethodId]],
190
            'countries' => [['id' => $countryId]],
191
            'domains' => [
192
                ['url' => 'http://test.com/' . Uuid::randomHex(), 'currencyId' => Defaults::CURRENCY, 'languageId' => Defaults::LANGUAGE_SYSTEM, 'snippetSetId' => $snippetSetId],
193
            ],
194
        ];
195
196
        return $this->createContext($data, [
197
            SalesChannelContextService::CUSTOMER_ID => $this->createCustomer()->getId(),
198
        ]);
199
    }
200
201
    protected function createSalesChannelContext(): SalesChannelContext
202
    {
203
        $paymentMethodId = $this->getValidPaymentMethodId();
204
        $shippingMethodId = $this->getAvailableShippingMethod()->getId();
205
        $countryId = $this->getValidCountryId();
206
        $snippetSetId = $this->getSnippetSetIdForLocale('en-GB');
207
        $data = [
208
            'typeId' => Defaults::SALES_CHANNEL_TYPE_STOREFRONT,
209
            'name' => 'store front',
210
            'accessKey' => AccessKeyHelper::generateAccessKey('sales-channel'),
211
            'languageId' => Defaults::LANGUAGE_SYSTEM,
212
            'snippetSetId' => $snippetSetId,
213
            'currencyId' => Defaults::CURRENCY,
214
            'currencyVersionId' => Defaults::LIVE_VERSION,
215
            'paymentMethodId' => $paymentMethodId,
216
            'paymentMethodVersionId' => Defaults::LIVE_VERSION,
217
            'shippingMethodId' => $shippingMethodId,
218
            'shippingMethodVersionId' => Defaults::LIVE_VERSION,
219
            'navigationCategoryId' => $this->getValidCategoryId(),
220
            'navigationCategoryVersionId' => Defaults::LIVE_VERSION,
221
            'countryId' => $countryId,
222
            'countryVersionId' => Defaults::LIVE_VERSION,
223
            'currencies' => [['id' => Defaults::CURRENCY]],
224
            'languages' => [['id' => Defaults::LANGUAGE_SYSTEM]],
225
            'paymentMethods' => [['id' => $paymentMethodId]],
226
            'shippingMethods' => [['id' => $shippingMethodId]],
227
            'countries' => [['id' => $countryId]],
228
            'domains' => [
229
                ['url' => 'http://test.com/' . Uuid::randomHex(), 'currencyId' => Defaults::CURRENCY, 'languageId' => Defaults::LANGUAGE_SYSTEM, 'snippetSetId' => $snippetSetId],
230
            ],
231
        ];
232
233
        return $this->createContext($data, []);
234
    }
235
236
    protected function catchEvent(string $eventName, &$eventResult): void
237
    {
238
        $this->getContainer()->get('event_dispatcher')->addListener($eventName, static function ($event) use (&$eventResult): void {
239
            $eventResult = $event;
240
        });
241
    }
242
243
    abstract protected function getContainer(): ContainerInterface;
244
245
    private function createCustomer(): CustomerEntity
246
    {
247
        $customerId = Uuid::randomHex();
248
        $addressId = Uuid::randomHex();
249
250
        $data = [
251
            [
252
                'id' => $customerId,
253
                'salesChannelId' => Defaults::SALES_CHANNEL,
254
                'defaultShippingAddress' => [
255
                    'id' => $addressId,
256
                    'firstName' => 'Max',
257
                    'lastName' => 'Mustermann',
258
                    'street' => 'Musterstraße 1',
259
                    'city' => 'Schöppingen',
260
                    'zipcode' => '12345',
261
                    'salutationId' => $this->getValidSalutationId(),
0 ignored issues
show
Bug introduced by
It seems like getValidSalutationId() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

261
                    'salutationId' => $this->/** @scrutinizer ignore-call */ getValidSalutationId(),
Loading history...
262
                    'country' => ['id' => $this->getValidCountryId()],
263
                ],
264
                'defaultBillingAddressId' => $addressId,
265
                'defaultPaymentMethodId' => $this->getValidPaymentMethodId(),
266
                'groupId' => Defaults::FALLBACK_CUSTOMER_GROUP,
267
                'email' => '[email protected]',
268
                'password' => 'password',
269
                'firstName' => 'Max',
270
                'lastName' => 'Mustermann',
271
                'salutationId' => $this->getValidSalutationId(),
272
                'customerNumber' => '12345',
273
            ],
274
        ];
275
276
        $repo = $this->getContainer()->get('customer.repository');
277
278
        $repo->create($data, Context::createDefaultContext());
279
280
        return $repo->search(new Criteria([$customerId]), Context::createDefaultContext())->first();
281
    }
282
283
    private function createContext(array $salesChannel, array $options): SalesChannelContext
284
    {
285
        $factory = $this->getContainer()->get(SalesChannelContextFactory::class);
286
        $salesChannelRepository = $this->getContainer()->get('sales_channel.repository');
287
288
        $salesChannelId = Uuid::randomHex();
289
        $salesChannel['id'] = $salesChannelId;
290
        $salesChannel['customerGroupId'] = Defaults::FALLBACK_CUSTOMER_GROUP;
291
292
        $salesChannelRepository->create([$salesChannel], Context::createDefaultContext());
293
294
        $context = $factory->create(Uuid::randomHex(), $salesChannelId, $options);
295
296
        $ruleLoader = $this->getContainer()->get(CartRuleLoader::class);
297
        $rulesProperty = ReflectionHelper::getProperty(CartRuleLoader::class, 'rules');
298
        $rulesProperty->setValue($ruleLoader, null);
299
        $ruleLoader->loadByToken($context, $context->getToken());
300
301
        return $context;
302
    }
303
}
304