ClientTest::testCreateMethod()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 6
c 1
b 0
f 0
dl 0
loc 11
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
4
namespace Elmage\TextNg\Test\Unit;
5
6
use Elmage\TextNg\Authentication\ApiKeyAuthentication;
7
use Elmage\TextNg\Client;
8
use Elmage\TextNg\Configuration;
9
use Elmage\TextNg\Enum\DeliveryReportReq;
10
use Elmage\TextNg\Enum\Param;
11
use Elmage\TextNg\Enum\Route;
12
use Elmage\TextNg\Exception\InvalidParamException;
13
use Elmage\TextNg\Exception\SendingLimitException;
14
use Elmage\TextNg\HttpClient;
15
use Elmage\TextNg\Test\TestCase;
16
use GuzzleHttp\Psr7\Response;
17
use PHPUnit\Framework\MockObject\MockObject;
18
use Psr\Http\Message\ResponseInterface;
19
use Psr\Http\Message\StreamInterface;
20
21
class ClientTest extends TestCase
22
{
23
    /** @var MockObject|HttpClient */
24
    private $http;
25
26
    /** @var Client */
27
    private $client;
28
29
    public static function setUpBeforeClass(): void
30
    {
31
        date_default_timezone_set('Africa/Lagos');
32
    }
33
34
    protected function setUp(): void
35
    {
36
        $this->http = $this->getMockBuilder(HttpClient::class)
37
            ->disableOriginalConstructor()
38
            ->getMock();
39
40
        $this->http->expects($this->any())
41
            ->method('getSender')
42
            ->willReturn('Test');
43
44
        $this->client = new Client($this->http);
45
    }
46
47
    protected function tearDown(): void
48
    {
49
        $this->http = null;
50
        $this->client = null;
51
    }
52
53
    public function testGetBalance()
54
    {
55
        $resText = '{"D":{"details":[' .
56
            '{"key":"TEST_KEY","unitsbalance":"20","time":"2000-01-01 01:10:15","status":"successful"}' .
57
            ']}}';
58
59
        $this->http->expects($this->any())
60
            ->method('get')
61
            ->with('/smsbalance/', [Param::CHECK_BALANCE => 1])
62
            ->willReturn($this->getMockResponse(
63
                $resText
64
            ));
65
66
        $actual = $this->client->getBalance();
67
        $this->assertIsArray($actual, "Array expected, got " . gettype($actual));
68
69
        $keys = ["unitsbalance", "time", "status"];
70
        foreach ($keys as $key) {
71
            $this->assertArrayHasKey($key, $actual, "Expected array to contain {$key}");
72
        }
73
74
        $this->assertArrayNotHasKey(Param::API_KEY, $actual, "Array should not contain API key.");
75
    }
76
77
    /**
78
     * @dataProvider provideForTestSendSMS
79
     */
80
    public function testSendSMS(int $route, string $phone, string $message, string $sender, string $bypasscode)
81
    {
82
        $this->http->expects($this->any())
83
            ->method('post')
84
            ->with('/pushsms/', [
85
                Param::ROUTE => $route,
86
                Param::PHONE => $phone,
87
                Param::MESSAGE => $message,
88
                Param::SENDER => $sender,
89
                Param::BYPASSCODE => $bypasscode
90
            ])
91
            ->willReturn($this->getMockResponse(
92
                '5 units used|| Status:Successful|| Route:5|| Type:single number|| Reference:4567ygfrthyi'
93
            ));
94
95
        $actual = $this->client->sendOTP($route, $phone, $message, $bypasscode);
96
97
        $this->assertIsArray($actual, "Array expected, got " . gettype($actual));
98
99
        $keys = ["units_used", "status", "type", "reference", "route"];
100
101
        foreach ($keys as $key) {
102
            $this->assertArrayHasKey($key, $actual, "Expected array to contain {$key}");
103
        }
104
    }
105
106
    public function provideForTestSendSMS(): array
107
    {
108
        return [
109
            //route phone     message          sender  bypasscode
110
            [3, '0806754345', "Otp is 675543", "Test", "2345678909"],
111
            [4, '0806754345', "Otp is 675543", "Test", "2345678909"],
112
            [5, '0806754345', "Otp is 675543", "Test", "2345678909"],
113
            [6, '0806754345', "Otp is 675543", "Test", "2345678909"],
114
        ];
115
    }
116
117
118
    /**
119
     * @dataProvider provideForTestCreateCustomer
120
     */
121
    public function testCreateCustomer(
122
        string $customerName,
123
        string $customerPhone,
124
        string $categoryID,
125
        string $response,
126
        array $keys = []
127
    )
128
    {
129
        $this->http->expects($this->any())
130
            ->method('get')
131
            ->with('/addcustomer/', [
132
                Param::CUSTOMER_NAME => $customerName,
133
                Param::CUSTOMER_PHONE => $customerPhone,
134
                Param::CATEGORY_ID => $categoryID,
135
            ])
136
            ->willReturn($this->getMockResponse($response));
137
138
        $actual = $this->client->createCustomer($customerName, $customerPhone, $categoryID);
139
        $this->assertIsArray($actual, "Array expected, got " . gettype($actual));
140
141
        foreach ($keys as $key) {
142
            $this->assertArrayHasKey($key, $actual, "Expected array to contain {$key}");
143
        }
144
    }
145
146
    public function provideForTestCreateCustomer(): array
147
    {
148
        return [
149
            //route phone     message          sender  bypasscode
150
            [
151
                "Chidi",
152
                '08060000000',
153
                "675543987",
154
                '{"D":{"details":[
155
                {"customerphone":"08060000000","customername":"Chidi","catid":"675543987","status":"successful"}
156
                ]}}',
157
                ['customerphone', 'customername', 'catid', 'status']
158
            ],
159
            [
160
                "Samuel",
161
                '08060000001',
162
                "675543987",
163
                '{"D":{"details":[
164
                {"customerphone":"08060000001","customername":"Samuel","catid":"675543876",
165
                "status":"error-customerphone-exists-in-category"}
166
                ]}}',
167
                ['customerphone', 'customername', 'catid', 'status']
168
            ],
169
            [
170
                "Grace",
171
                '08060000002',
172
                "675543987",
173
                '{"D":{"details":[{"status":"customerphone-not-exists"}]}}',
174
                ['status']
175
            ]
176
        ];
177
    }
178
179
180
    /**
181
     * @dataProvider provideForTestRemoveCustomer
182
     */
183
    public function testRemoveCustomer(
184
        string $customerPhone,
185
        string $categoryID,
186
        string $response,
187
        array $keys = []
188
    )
189
    {
190
        $this->http->expects($this->any())
191
            ->method('get')
192
            ->with('/removecustomer/', [
193
                Param::CUSTOMER_PHONE => $customerPhone,
194
                Param::CATEGORY_ID => $categoryID,
195
            ])
196
            ->willReturn($this->getMockResponse($response));
197
198
        $actual = $this->client->removeCustomer($customerPhone, $categoryID);
199
        $this->assertIsArray($actual, "Array expected, got " . gettype($actual));
200
201
        foreach ($keys as $key) {
202
            $this->assertArrayHasKey($key, $actual, "Expected array to contain {$key}");
203
        }
204
    }
205
206
    public function provideForTestRemoveCustomer(): array
207
    {
208
        return [
209
            //route phone     message          sender  bypasscode
210
            [
211
                '08060000000',
212
                "675543987",
213
                '{"D":{"details":[
214
                {"customerphone":"08060000000","customername":"Chidi","catid":"675543987","status":"successful"}
215
                ]}}',
216
                ['customerphone', 'customername', 'catid', 'status']
217
            ],
218
            [
219
                '08060000001',
220
                "675543987",
221
                '{"D":{"details":[
222
                {"customerphone":"08060000001","customername":"Samuel","catid":"675543876",
223
                "status":"error-customerphone-does-not-exists-in-category"}
224
                ]}}',
225
                ['customerphone', 'customername', 'catid', 'status']
226
            ],
227
            [
228
                '08060000002',
229
                "675543987",
230
                '{"D":{"details":[{"status":"customerphone-not-exists"}]}}',
231
                ['status']
232
            ]
233
        ];
234
    }
235
236
237
    public function testSendSMSErrorCase()
238
    {
239
        $this->http->expects($this->any())
240
            ->method('post')
241
            ->with('/pushsms/', [
242
                Param::ROUTE => Route::RECOMMENDED,
243
                Param::PHONE => "0806",
244
                Param::MESSAGE => "TEST",
245
                Param::SENDER => "Test",
246
                Param::BYPASSCODE => "test"
247
            ])
248
            ->willReturn($this->getMockResponse('ERROR insufficient units'));
249
250
        $actual = $this->client->sendSMS(Route::RECOMMENDED, ["0806"], "TEST", "test");
251
252
        $this->assertIsArray($actual, "Array expected, got " . gettype($actual));
253
254
        $keys = ["status", "message"];
255
        foreach ($keys as $key) {
256
            $this->assertArrayHasKey($key, $actual, "Expected array to contain {$key}");
257
        }
258
    }
259
260
    public function testSendSMSThrowsInvalidParamExceptions()
261
    {
262
        $this->expectException(InvalidParamException::class);
263
        $this->client->sendSMS(7, ["0806709"], "Sample Message", "088776");
264
    }
265
266
267
    public function testSendSMSThrowsSendingLimitExceptions()
268
    {
269
        $this->expectException(SendingLimitException::class);
270
        $this->client->sendSMS(Route::RECOMMENDED, range(100, 100500), "Sample Message", "088776");
271
    }
272
273
    public function testGetDeliveryReport()
274
    {
275
        $ref = "9837092678";
276
277
        $this->http->expects($this->any())
278
            ->method('get')
279
            ->with('/deliveryreport/', [
280
                Param::USED_ROUTE => Route::RECOMMENDED,
281
                Param::REFERENCE => $ref,
282
                Param::REQ => DeliveryReportReq::ALL
283
            ])
284
            ->willReturn($this->getMockResponse(
285
                '{"D":{"details":[{"number":"234XXXXXXXXX","status":"DELIVERED","track_id":"xxxxxxxxxx"},
286
                {"number":"234XXXXXXXXX","status":"DELIVRD","track_id":"xxxxxxxxxx"},
287
                {"number":"234XXXXXXXXX","status":"SENT-VIA-BYPASS","track_id":"xxxxxxxxxx"},
288
                {"number":"234XXXXXXXXX","status":"SENT-BUT-PENDING","track_id":"xxxxxxxxxx"},
289
                {"number":"234XXXXXXXXX","status":"BLOCKED","track_id":"xxxxxxxxxx"}]}}'
290
            ));
291
292
        $actual = $this->client->getDeliveryReport($ref, DeliveryReportReq::ALL, Route::RECOMMENDED);
293
294
        $this->assertIsArray($actual, "Array expected, got " . gettype($actual));
295
        $this->assertArrayHasKey("data", $actual, "Expected array to contain 'details'");
296
297
        $this->assertIsArray($actual['data'], "Array expected, got " . gettype($actual['data']));
298
299
        $test_data = $actual['data'][0];
300
        $keys = ["number", "status", "track_id"];
301
302
        foreach ($keys as $key) {
303
            $this->assertArrayHasKey($key, $test_data, "Expected array item to contain {$key}");
304
        }
305
306
        $this->expectException(InvalidParamException::class);
307
        $this->client->getDeliveryReport($ref, DeliveryReportReq::ALL, 10);
308
    }
309
310
311
    public function testCreateMethod()
312
    {
313
        $config = new Configuration(new ApiKeyAuthentication("TEST"), "Test");
314
        $client = Client::create($config);
315
316
        $this->assertInstanceOf(Client::class, $client);
317
        $this->assertInstanceOf(HttpClient::class, $client->getHttpClient());
318
319
        $client->setSender("Test2");
320
321
        $this->assertEquals("Test2", $client->getHttpClient()->getSender());
322
    }
323
    /*------------------------------------------------------------------------------
324
    | PRIVATE METHODS
325
    /*------------------------------------------------------------------------------*/
326
327
328
    /**
329
     * @param $data
330
     * @return MockObject|ResponseInterface
331
     */
332
    private function getMockResponse($data)
333
    {
334
        $response = $this->createMock(ResponseInterface::class);
335
        $stream = $this->createMock(StreamInterface::class);
336
337
        if (is_array($data)) {
338
            $data = json_encode((object)$data);
339
        }
340
341
        $response->expects($this->any())
342
            ->method('getBody')
343
            ->willReturn($stream);
344
        $stream->expects($this->any())
345
            ->method('__toString')
346
            ->willReturn($data);
347
348
        return $response;
349
    }
350
}
351