Passed
Push — master ( 129279...a1bd08 )
by Eric
02:55
created

ApiCountryTest::testCountriesBadResponse()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 7
nc 1
nop 1
dl 0
loc 11
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * This file is part of the Numverify API Client for PHP.
7
 *
8
 * (c) 2024 Eric Sizemore <[email protected]>
9
 * (c) 2018-2021 Mark Rogoyski <[email protected]>
10
 *
11
 * @license The MIT License
12
 *
13
 * For the full copyright and license information, please view the LICENSE.md
14
 * file that was distributed with this source code.
15
 */
16
17
namespace Numverify\Tests;
18
19
use GuzzleHttp\{
20
    ClientInterface,
21
    HandlerStack,
22
    Handler\MockHandler,
23
    Psr7\Response
24
};
25
use Iterator;
26
use Numverify\{
27
    Api,
28
    Country\Collection,
29
    Country\Country,
30
    Exception\NumverifyApiFailureException
31
};
32
use PHPUnit\Framework\{
33
    Attributes\CoversClass,
34
    Attributes\DataProvider,
35
    Attributes\TestDox,
36
    MockObject\MockObject,
37
    TestCase
38
};
39
40
/**
41
 * @internal
42
 */
43
#[CoversClass(Collection::class)]
44
#[CoversClass(Country::class)]
45
#[CoversClass(Api::class)]
46
#[CoversClass(NumverifyApiFailureException::class)]
47
class ApiCountryTest extends TestCase
48
{
49
    private const ACCESS_KEY = 'SomeAccessKey';
50
51
    #[DataProvider('dataProviderForHttp')]
52
    #[TestDox('getCountries returns the correct count, with $useHttps.')]
53
    public function testCountriesApiReturnsNumberOfCountries(bool $useHttps): void
54
    {
55
        $countryCollection = $this->aClient(useHttps: $useHttps)->getCountries();
56
        self::assertCount(3, $countryCollection);
57
    }
58
59
    #[DataProvider('dataProviderForHttp')]
60
    #[TestDox('getCountries returns a Collection containing Country instances, with $useHttps.')]
61
    public function testCountriesReturnsCollectionOfCountries(bool $useHttps): void
62
    {
63
        $countryCollection = $this->aClient(useHttps: $useHttps)->getCountries();
64
        self::assertInstanceOf(Collection::class, $countryCollection); // @phpstan-ignore-line
65
        self::assertContainsOnlyInstancesOf(Country::class, $countryCollection);
66
    }
67
68
    #[DataProvider('dataProviderForHttp')]
69
    #[TestDox('getCountries returns expected country information with $useHttps.')]
70
    public function testCountriesReturnsExpectedCountries(bool $useHttps): void
71
    {
72
        $expectedCountries = ['JP' => false, 'GB' => false, 'US' => false];
73
        $countryCollection = $this->aClient(useHttps: $useHttps)->getCountries();
74
75
        foreach ($countryCollection as $countryCode => $country) {
76
            /** @var string $countryCode */
77
            $expectedCountries[$countryCode] = true;
78
            self::assertInstanceOf(Country::class, $country); // @phpstan-ignore-line
79
        }
80
81
        foreach ($expectedCountries as $expectedCountry) {
82
            self::assertTrue($expectedCountry);
83
        }
84
    }
85
86
    #[DataProvider('dataProviderForHttp')]
87
    #[TestDox('Given an invalid api access key, getCountries returns expected error information with $useHttps.')]
88
    public function testCountriesInvalidAccessKey(bool $useHttps): void
89
    {
90
        $mockHandler = new MockHandler([
91
            new Response(200, body: '{
92
                "success":false,
93
                "error":{
94
                    "code":101,
95
                    "type":"invalid_access_key",
96
                    "info":"You have not supplied a valid API Access Key. [Technical Support: [email protected]]"
97
                }
98
            }', reason: 'Type:invalid_access_key Code:101 Info:You have not supplied a valid API Access Key. [Technical Support: [email protected]]'),
99
        ]);
100
101
        $stub = $this->aClient('InvalidAccessKey', $useHttps, null, $mockHandler);
102
103
        $this->expectException(NumverifyApiFailureException::class);
104
        $this->expectExceptionMessage('Type:invalid_access_key Code:101 Info:You have not supplied a valid API Access Key. [Technical Support: [email protected]]');
105
        $stub->getCountries();
106
    }
107
108
    #[DataProvider('dataProviderForHttp')]
109
    #[TestDox('Given a 500 server error response, getCountries returns appropriate exception with $useHttps.')]
110
    public function testCountriesServerError(bool $useHttps): void
111
    {
112
        $mockHandler = new MockHandler([
113
            new Response(500),
114
        ]);
115
        $stub = $this->aClient(self::ACCESS_KEY, $useHttps, null, $mockHandler);
116
117
        $this->expectException(NumverifyApiFailureException::class);
118
        $stub->getCountries();
119
    }
120
121
    #[DataProvider('dataProviderForHttp')]
122
    #[TestDox('Given a non-200 response, getCountries returns appropriate exception with $useHttps.')]
123
    public function testCountriesBadResponse(bool $useHttps): void
124
    {
125
        $mockHandler = new MockHandler([
126
            new Response(202),
127
        ]);
128
        $stub = $this->aClient(self::ACCESS_KEY, $useHttps, null, $mockHandler);
129
130
        $this->expectException(NumverifyApiFailureException::class);
131
        $stub->getCountries();
132
    }
133
134
    /**
135
     * @psalm-suppress PossiblyUnusedMethod
136
     */
137
    public static function dataProviderForHttp(): Iterator
138
    {
139
        yield [true];
140
        yield [false];
141
    }
142
143
    /**
144
     * Creates a mock client for testing.
145
     */
146
    private function aClient(
147
        string $accessKey = self::ACCESS_KEY,
148
        bool $useHttps = false,
149
        ?ClientInterface $client = null,
150
        ?MockHandler $mockHandler = null
151
    ): Api&MockObject {
152
        // Create a mock
153
        $mockHandler ??= new MockHandler([
154
            new Response(200, body: '{
155
                "JP":{"country_name":"Japan","dialling_code":"+81"},
156
                "GB":{"country_name":"United Kingdom","dialling_code":"+44"},
157
                "US":{"country_name":"United States","dialling_code":"+1"}
158
            }'),
159
        ]);
160
        $handlerStack = HandlerStack::create($mockHandler);
161
162
        return $this
163
            ->getMockBuilder(Api::class)
164
            ->setConstructorArgs([$accessKey, $useHttps, $client, ['handler' => $handlerStack]])
165
            ->onlyMethods([])
166
            ->getMock();
167
    }
168
}
169