Skip to content

Commit e1f3f2d

Browse files
authored
Add dedicated test coverage for ExpoPushConnector (#80)
### Summary Added `tests/Unit/ExpoPushConnectorTest.php`, a dedicated test suite covering `ExpoPushConnector`'s `resolveBaseUrl()`, `defaultAuth()`, `defaultHeaders()`, `resolveLimits()`, and `resolveRateLimitStore()` methods. No production code was changed. Closes #68
1 parent 64bc833 commit e1f3f2d

1 file changed

Lines changed: 107 additions & 0 deletions

File tree

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
<?php
2+
3+
namespace Dru1x\ExpoPush\Tests\Unit;
4+
5+
use Dru1x\ExpoPush\ExpoPushConnector;
6+
use PHPUnit\Framework\Attributes\Test;
7+
use PHPUnit\Framework\TestCase;
8+
use Saloon\Http\Auth\TokenAuthenticator;
9+
use Saloon\RateLimitPlugin\Exceptions\LimitException;
10+
use Saloon\RateLimitPlugin\Limit;
11+
use Saloon\RateLimitPlugin\Stores\MemoryStore;
12+
13+
class ExpoPushConnectorTest extends TestCase
14+
{
15+
#[Test]
16+
public function resolves_the_expo_push_api_base_url(): void
17+
{
18+
$connector = new ExpoPushConnector();
19+
20+
$this->assertSame('https://exp.host/--/api/v2/push', $connector->resolveBaseUrl());
21+
}
22+
23+
#[Test]
24+
public function applies_bearer_token_authentication_when_a_token_is_provided(): void
25+
{
26+
$connector = new ExpoPushConnector('my-token');
27+
28+
$authenticator = $connector->getAuthenticator();
29+
30+
$this->assertInstanceOf(TokenAuthenticator::class, $authenticator);
31+
$this->assertSame('my-token', $authenticator->token);
32+
$this->assertSame('Bearer', $authenticator->prefix);
33+
}
34+
35+
#[Test]
36+
public function applies_no_authentication_when_no_token_is_provided(): void
37+
{
38+
$connector = new ExpoPushConnector();
39+
40+
$this->assertNull($connector->getAuthenticator());
41+
}
42+
43+
#[Test]
44+
public function default_headers_include_accept_encoding_and_user_agent(): void
45+
{
46+
$connector = new ExpoPushConnector();
47+
48+
$this->assertSame('gzip, deflate', $connector->headers()->get('Accept-Encoding'));
49+
$this->assertStringStartsWith('expo-server-sdk-php/', (string)$connector->headers()->get('User-Agent'));
50+
$this->assertStringContainsString('(dru1x)', (string)$connector->headers()->get('User-Agent'));
51+
}
52+
53+
#[Test]
54+
public function default_headers_do_not_leak_an_authorization_header_when_no_token_is_provided(): void
55+
{
56+
$connector = new ExpoPushConnector();
57+
58+
$this->assertNull($connector->headers()->get('Authorization'));
59+
}
60+
61+
#[Test]
62+
public function rate_limit_allows_six_requests_per_second_and_sleeps_when_exceeded(): void
63+
{
64+
$connector = new ExpoPushConnector();
65+
66+
$limit = $this->findLimit($connector, 'expo-push-limit');
67+
68+
$this->assertSame(6, $limit->getAllow());
69+
$this->assertSame(1, $limit->getReleaseInSeconds());
70+
$this->assertTrue($limit->getShouldSleep());
71+
}
72+
73+
#[Test]
74+
public function uses_a_memory_store_by_default(): void
75+
{
76+
$connector = new ExpoPushConnector();
77+
78+
$this->assertInstanceOf(MemoryStore::class, $connector->rateLimitStore());
79+
}
80+
81+
#[Test]
82+
public function uses_the_provided_rate_limit_store_when_given(): void
83+
{
84+
$store = new MemoryStore();
85+
86+
$connector = new ExpoPushConnector(rateLimitStore: $store);
87+
88+
$this->assertSame($store, $connector->rateLimitStore());
89+
}
90+
91+
// Internals ----
92+
93+
private function findLimit(ExpoPushConnector $connector, string $name): Limit
94+
{
95+
try {
96+
foreach ($connector->getLimits() as $limit) {
97+
if (str_ends_with($limit->getName(), ":{$name}")) {
98+
return $limit;
99+
}
100+
}
101+
} catch (LimitException $e) {
102+
$this->fail($e->getMessage());
103+
}
104+
105+
$this->fail("Limit \"$name\" not found.");
106+
}
107+
}

0 commit comments

Comments
 (0)