Passed
Pull Request — master (#100)
by
unknown
23:41 queued 21:10
created

ApiCountryTest   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 124
Duplicated Lines 0 %

Importance

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