Skip to content
This repository was archived by the owner on Feb 26, 2025. It is now read-only.

Commit 48ae836

Browse files
authored
Merge pull request #3 from answear/create-tests-2-bm
Add tests
2 parents 057c716 + 87ff5c0 commit 48ae836

File tree

10 files changed

+535
-16
lines changed

10 files changed

+535
-16
lines changed

.github/workflows/phpunit.yml

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ jobs:
1212
matrix:
1313
php-version:
1414
- "7.4"
15+
- "8.0"
1516
deps:
1617
- "normal"
1718
include:

.github/workflows/static-analysis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
matrix:
1313
php-version:
1414
- "7.4"
15-
15+
- "8.0"
1616
steps:
1717
- name: "Checkout"
1818
uses: "actions/checkout@v2"

composer.json

+13-13
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,23 @@
44
"type": "symfony-bundle",
55
"license": "MIT",
66
"require": {
7-
"php": "^7.4 || ^8.0",
7+
"php": ">=7.4|^8.0",
88
"ext-json": "*",
9-
"marc-mabe/php-enum": "^4.3",
10-
"symfony/http-kernel": "^4.4 || ^5.0",
11-
"webmozart/assert": "^1.3",
12-
"php-http/guzzle6-adapter": "^1.1",
13-
"symfony/serializer": "^4.4",
14-
"symfony/property-access": "^4.4"
9+
"guzzlehttp/guzzle": "^6.0|^7.0",
10+
"marc-mabe/php-enum": "^3.0|^4.3",
11+
"symfony/http-kernel": "^4.4|^5.1.5",
12+
"symfony/serializer": "^4.4|^5.0",
13+
"webmozart/assert": "^1.10"
1514
},
1615
"require-dev": {
16+
"friendsofphp/php-cs-fixer": "^2.19",
17+
"matthiasnoback/symfony-config-test": "^4.2",
18+
"phpro/grumphp": "^1.4.0",
19+
"phpstan/phpstan": "^0.12.97",
20+
"phpstan/phpstan-webmozart-assert": "^0.12.16",
21+
"phpunit/phpunit": "^9.5",
1722
"roave/security-advisories": "dev-master",
18-
"phpunit/phpunit": "^8.0",
19-
"symfony/phpunit-bridge": "^5.0",
20-
"phpro/grumphp": "^0.20",
21-
"friendsofphp/php-cs-fixer": "^2.16",
22-
"phpstan/phpstan": "^0.12.32",
23-
"phpstan/phpstan-webmozart-assert": "^0.12.2"
23+
"symfony/phpunit-bridge": "^5.3"
2424
},
2525
"autoload": {
2626
"psr-4": {

src/Service/Client.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Answear\GetdressedMeBundle\Service;
66

77
use Answear\GetdressedMeBundle\Exception\ServiceUnavailable;
8+
use GuzzleHttp\ClientInterface;
89
use GuzzleHttp\Exception\GuzzleException;
910
use GuzzleHttp\RequestOptions;
1011
use Psr\Http\Message\ResponseInterface;
@@ -19,10 +20,10 @@ public function __construct(ConfigProvider $configProvider)
1920
$this->configProvider = $configProvider;
2021
}
2122

22-
public function request(string $endpoint): ResponseInterface
23+
public function request(string $endpoint, ?ClientInterface $client = null): ResponseInterface
2324
{
2425
try {
25-
$client = new \GuzzleHttp\Client(
26+
$client = $client ?? new \GuzzleHttp\Client(
2627
[
2728
RequestOptions::TIMEOUT => $this->configProvider->getRequestTimeout(),
2829
RequestOptions::CONNECT_TIMEOUT => $this->configProvider->getConnectionTimeout(),

tests/DataFixtures/getdressedme.json

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
{
2+
"outfits": [
3+
[
4+
{
5+
"clientProductId": "21249",
6+
"productName": "Answear - some product",
7+
"productNameLang": "hu",
8+
"productPageUrl": "https://yoursite.dev/p/answear-hatizsak-21249",
9+
"mainImageUrl": "https://img.yoursite.dev/i/855x1290/WZ18-PKD016_90X_F1.jpg?v=1552489483",
10+
"price": 65990.0,
11+
"priceCurrency": "HUF",
12+
"salePrice": 65990.0
13+
},
14+
{
15+
"clientProductId": "33855",
16+
"productName": "Somebrand - product",
17+
"productNameLang": "hu",
18+
"productPageUrl": "https://yoursite.dev/p/somebrand-prod-33855",
19+
"mainImageUrl": "https://img.yoursite.dev/i/855x1290/XX-OBDN31_99X_F1.jpg?v=1552489483",
20+
"price": 18990.0,
21+
"priceCurrency": "HUF",
22+
"salePrice": 18990.0
23+
}
24+
],
25+
[
26+
{
27+
"clientProductId": "21249",
28+
"productName": "Answear - H\u00e1tizs\u00e1k",
29+
"productNameLang": "hu",
30+
"productPageUrl": "https://yoursite.dev/p/answear-hatizsak-21249",
31+
"mainImageUrl": "https://img.yoursite.dev/i/855x1290/WZ18-PKD016_90X_F1.jpg?v=1552489483",
32+
"price": 65990.0,
33+
"priceCurrency": "HUF",
34+
"salePrice": 65990.0
35+
},
36+
{
37+
"clientProductId": "33259",
38+
"productName": "SomeBrand - Mokaszin",
39+
"productNameLang": "hu",
40+
"productPageUrl": "https://yoursite.dev/p/SomeBrand-mokaszin-33259",
41+
"mainImageUrl": "https://img.yoursite.dev/i/855x1290/XX-OBD2UU_83X_F1.jpg?v=1552489483",
42+
"price": 3490.0,
43+
"priceCurrency": "HUF",
44+
"salePrice": 3490.0
45+
},
46+
{
47+
"clientProductId": "43921",
48+
"productName": "Some brand Y - Farmer",
49+
"productNameLang": "hu",
50+
"productPageUrl": "https://yoursite.dev/p/some-brand-y-farmer-43921",
51+
"mainImageUrl": "https://img.yoursite.dev/i/855x1290/SS18-SJD088_55X_F1.jpg?v=1552489483",
52+
"price": 11990.0,
53+
"priceCurrency": "HUF",
54+
"salePrice": 11990.0
55+
},
56+
{
57+
"clientProductId": "10185",
58+
"productName": "Some brand X - Pul\u00f3ver",
59+
"productNameLang": "hu",
60+
"productPageUrl": "https://yoursite.dev/p/some-brand-pulover-10185",
61+
"mainImageUrl": "https://img.yoursite.dev/i/855x1290/XX-SWD07J_99X_F1.jpg?v=1552489483",
62+
"price": 14990.0,
63+
"priceCurrency": "HUF",
64+
"salePrice": 14990.0
65+
}
66+
],
67+
[
68+
{
69+
"clientProductId": "21249",
70+
"productName": "Answear - product",
71+
"productNameLang": "hu",
72+
"productPageUrl": "https://yoursite.dev/p/answear-product-21249",
73+
"mainImageUrl": "https://img.yoursite.dev/i/855x1290/WZ18-PKD016_90X_F1.jpg?v=1552489483",
74+
"price": 65990.0,
75+
"priceCurrency": "HUF",
76+
"salePrice": 65990.0
77+
},
78+
{
79+
"clientProductId": "3757",
80+
"productName": "SomeBrand - xxx",
81+
"productNameLang": "hu",
82+
"productPageUrl": "https://yoursite.dev/p/SomeBrand-product-3757",
83+
"mainImageUrl": "https://img.yoursite.dev/i/855x1290/XX-OBD3JZ_99X_F1.jpg?v=1552489483",
84+
"price": 9490.0,
85+
"priceCurrency": "HUF",
86+
"salePrice": 4990.0
87+
}
88+
]
89+
],
90+
"product": {
91+
"clientProductId": "18877",
92+
"productName": "Some brand - product",
93+
"productNameLang": "hu",
94+
"productPageUrl": "https://yoursite.dev/p/some-product-18877",
95+
"mainImageUrl": "https://img.yoursite.dev/i/855x1290/XX-KUD03K_99X_F1.jpg?v=1552489483",
96+
"price": 23990.0,
97+
"priceCurrency": "HUF",
98+
"salePrice": 15990.0
99+
}
100+
}
+117
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Answear\GetdressedMeBundle\Tests\Response;
6+
7+
use Answear\GetdressedMeBundle\Enum\OutfitsResponsePropertyEnum;
8+
use Answear\GetdressedMeBundle\Enum\ProductPropertyEnum;
9+
use Answear\GetdressedMeBundle\Response\OutfitsResponse;
10+
use Answear\GetdressedMeBundle\ValueObject\Product;
11+
use PHPUnit\Framework\TestCase;
12+
use Webmozart\Assert\InvalidArgumentException;
13+
14+
class OutfitsResponseTest extends TestCase
15+
{
16+
/**
17+
* @test
18+
*/
19+
public function validObjectCreation(): void
20+
{
21+
$outfitsResponse = OutfitsResponse::fromArray($this->getValidData());
22+
self::assertInstanceOf(OutfitsResponse::class, $outfitsResponse);
23+
24+
self::assertEquals($this->getExpectedProduct(), $this->getComparisonArrayProduct($outfitsResponse->getProduct()));
25+
26+
$outfits = $outfitsResponse->getOutfits();
27+
self::assertCount(3, $outfits);
28+
self::assertCount(2, $outfits[0]->getProducts());
29+
self::assertCount(4, $outfits[1]->getProducts());
30+
self::assertCount(2, $outfits[2]->getProducts());
31+
}
32+
33+
/**
34+
* @test
35+
* @dataProvider invalidDataProvider
36+
*/
37+
public function invalidObjectCreation(array $invalidData): void
38+
{
39+
$this->expectException(InvalidArgumentException::class);
40+
41+
OutfitsResponse::fromArray($invalidData);
42+
}
43+
44+
public function getValidData(): array
45+
{
46+
$jsonFile = __DIR__ . '/../DataFixtures/getdressedme.json';
47+
48+
return \json_decode(file_get_contents($jsonFile), true, 512, JSON_THROW_ON_ERROR);
49+
}
50+
51+
public function invalidDataProvider(): iterable
52+
{
53+
yield 'no outfits key' => [
54+
[OutfitsResponsePropertyEnum::PRODUCT => $this->getProductData()],
55+
];
56+
57+
yield 'outfits not array' => [
58+
[
59+
OutfitsResponsePropertyEnum::PRODUCT => $this->getProductData(),
60+
OutfitsResponsePropertyEnum::OUTFITS => 'invalid type',
61+
],
62+
];
63+
64+
yield 'no product key' => [
65+
[OutfitsResponsePropertyEnum::OUTFITS => []],
66+
];
67+
68+
yield 'product not array' => [
69+
[
70+
OutfitsResponsePropertyEnum::PRODUCT => 'invalid type',
71+
OutfitsResponsePropertyEnum::OUTFITS => [],
72+
],
73+
];
74+
}
75+
76+
private function getProductData(): array
77+
{
78+
return [
79+
ProductPropertyEnum::CLIENT_PRODUCT_ID => '123',
80+
ProductPropertyEnum::PRODUCT_NAME => 'My product name',
81+
ProductPropertyEnum::PRODUCT_NAME_LANG => 'pl',
82+
ProductPropertyEnum::PRODUCT_PAGE_URL => 'https://my-site.local/my-product-123',
83+
ProductPropertyEnum::MAIN_IMAGE_URL => 'https://img.my-site.local/my-product-123.jpg',
84+
ProductPropertyEnum::PRICE => 123.99,
85+
ProductPropertyEnum::PRICE_CURRENCY => 'PLN',
86+
ProductPropertyEnum::SALE_PRICE => 123.99,
87+
];
88+
}
89+
90+
private function getExpectedProduct(): array
91+
{
92+
return [
93+
ProductPropertyEnum::CLIENT_PRODUCT_ID => '18877',
94+
ProductPropertyEnum::PRODUCT_NAME => 'Some brand - product',
95+
ProductPropertyEnum::PRODUCT_NAME_LANG => 'hu',
96+
ProductPropertyEnum::PRODUCT_PAGE_URL => 'https://yoursite.dev/p/some-product-18877',
97+
ProductPropertyEnum::MAIN_IMAGE_URL => 'https://img.yoursite.dev/i/855x1290/XX-KUD03K_99X_F1.jpg?v=1552489483',
98+
ProductPropertyEnum::PRICE => 23990.0,
99+
ProductPropertyEnum::PRICE_CURRENCY => 'HUF',
100+
ProductPropertyEnum::SALE_PRICE => 15990.0,
101+
];
102+
}
103+
104+
private function getComparisonArrayProduct(Product $product): array
105+
{
106+
return [
107+
ProductPropertyEnum::CLIENT_PRODUCT_ID => $product->getClientProductId(),
108+
ProductPropertyEnum::PRODUCT_NAME => $product->getProductName(),
109+
ProductPropertyEnum::PRODUCT_NAME_LANG => $product->getProductNameLang(),
110+
ProductPropertyEnum::PRODUCT_PAGE_URL => $product->getProductPageUrl(),
111+
ProductPropertyEnum::MAIN_IMAGE_URL => $product->getMainImageUrl(),
112+
ProductPropertyEnum::PRICE => $product->getPrice(),
113+
ProductPropertyEnum::PRICE_CURRENCY => $product->getPriceCurrency(),
114+
ProductPropertyEnum::SALE_PRICE => $product->getSalePrice(),
115+
];
116+
}
117+
}

tests/Service/ClientTest.php

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Answear\GetdressedMeBundle\Tests\Service;
6+
7+
use Answear\GetdressedMeBundle\Exception\ServiceUnavailable;
8+
use Answear\GetdressedMeBundle\Service\Client;
9+
use Answear\GetdressedMeBundle\Service\ConfigProvider;
10+
use GuzzleHttp\ClientInterface;
11+
use GuzzleHttp\Exception\TransferException;
12+
use PHPUnit\Framework\TestCase;
13+
use Psr\Http\Message\ResponseInterface;
14+
15+
class ClientTest extends TestCase
16+
{
17+
/**
18+
* @test
19+
*/
20+
public function sendsValidRequest(): void
21+
{
22+
$httpClient = $this->createMock(ClientInterface::class);
23+
$httpClient->expects($this->once())
24+
->method('request')
25+
->willReturn($this->createMock(ResponseInterface::class));
26+
27+
$client = $this->createClient();
28+
$client->request('/v1/outfits?store_id=yourstoreid&id=123', $httpClient);
29+
}
30+
31+
/**
32+
* @test
33+
*/
34+
public function serviceUnavailable(): void
35+
{
36+
$this->expectException(ServiceUnavailable::class);
37+
$this->expectExceptionMessage('some error');
38+
39+
$httpClient = $this->createMock(ClientInterface::class);
40+
$httpClient->expects($this->once())
41+
->method('request')
42+
->willThrowException(new TransferException('some error'));
43+
44+
$client = $this->createClient();
45+
$client->request('/v1/outfits?store_id=yourstoreid&id=123', $httpClient);
46+
}
47+
48+
private function createClient(): Client
49+
{
50+
$configProvider = $this->createMock(ConfigProvider::class);
51+
$configProvider->expects($this->once())
52+
->method('getApiUrl')
53+
->willReturn('https://your-api-url.getdressed.me');
54+
$configProvider->expects($this->once())
55+
->method('getBearerToken')
56+
->willReturn('SomeToken');
57+
58+
return new Client($configProvider);
59+
}
60+
}

0 commit comments

Comments
 (0)