1010namespace Symfonycasts \TailwindBundle \Tests ;
1111
1212use PHPUnit \Framework \TestCase ;
13- use Symfony \Component \HttpClient \HttpClient ;
13+ use Symfony \Component \HttpClient \MockHttpClient ;
14+ use Symfony \Component \HttpClient \Response \MockResponse ;
1415use Symfonycasts \TailwindBundle \TailwindVersionFinder ;
1516
1617class TailwindVersionFinderTest extends TestCase
1718{
19+ private const TOKEN_ENV_VARS = ['GITHUB_TOKEN ' , 'GH_TOKEN ' , 'COMPOSER_AUTH ' , 'COMPOSER_HOME ' , 'HOME ' ];
20+
21+ /** @var array<string, array{0: mixed, 1: mixed, 2: string|false}> */
22+ private array $ envBackup = [];
23+
24+ protected function setUp (): void
25+ {
26+ foreach (self ::TOKEN_ENV_VARS as $ name ) {
27+ $ this ->envBackup [$ name ] = [$ _SERVER [$ name ] ?? null , $ _ENV [$ name ] ?? null , getenv ($ name )];
28+ }
29+ }
30+
31+ protected function tearDown (): void
32+ {
33+ foreach ($ this ->envBackup as $ name => [$ server , $ env , $ getenv ]) {
34+ if (null !== $ server ) {
35+ $ _SERVER [$ name ] = $ server ;
36+ } else {
37+ unset($ _SERVER [$ name ]);
38+ }
39+
40+ if (null !== $ env ) {
41+ $ _ENV [$ name ] = $ env ;
42+ } else {
43+ unset($ _ENV [$ name ]);
44+ }
45+
46+ if (false !== $ getenv ) {
47+ putenv ("$ name= $ getenv " );
48+ } else {
49+ putenv ($ name );
50+ }
51+ }
52+ }
53+
1854 /**
1955 * @dataProvider versionProvider
2056 */
2157 public function testGetLatestVersion (string $ version , int $ expectedMajor ): void
2258 {
23- $ options = [];
24-
25- if ($ _SERVER ['GITHUB_TOKEN ' ] ?? null ) {
26- $ options ['auth_bearer ' ] = $ _SERVER ['GITHUB_TOKEN ' ];
27- }
28-
29- $ versionDetector = new TailwindVersionFinder (HttpClient::create ($ options ));
30- $ latestVersion = $ versionDetector ->latestVersionFor ($ version );
59+ $ latestVersion = (new TailwindVersionFinder ())->latestVersionFor ($ version );
3160
3261 $ this ->assertStringStartsWith ('v ' .$ expectedMajor .'. ' , $ latestVersion );
3362 }
@@ -49,4 +78,90 @@ public function testThrowsOnUnparsableVersion(): void
4978
5079 (new TailwindVersionFinder ())->latestVersionFor ('nope ' );
5180 }
81+
82+ public function testNoAuthorizationHeaderWithoutToken (): void
83+ {
84+ $ this ->clearTokenEnv ();
85+
86+ $ this ->assertNull ($ this ->captureAuthorizationHeader ());
87+ }
88+
89+ public function testUsesGitHubTokenEnvVar (): void
90+ {
91+ $ this ->clearTokenEnv ();
92+ $ _SERVER ['GITHUB_TOKEN ' ] = 'secret-token ' ;
93+
94+ $ this ->assertSame ('Bearer secret-token ' , $ this ->captureAuthorizationHeader ());
95+ }
96+
97+ public function testUsesGhTokenEnvVar (): void
98+ {
99+ $ this ->clearTokenEnv ();
100+ $ _SERVER ['GH_TOKEN ' ] = 'gh-secret ' ;
101+
102+ $ this ->assertSame ('Bearer gh-secret ' , $ this ->captureAuthorizationHeader ());
103+ }
104+
105+ public function testUsesComposerAuthEnvVar (): void
106+ {
107+ $ this ->clearTokenEnv ();
108+ $ _SERVER ['COMPOSER_AUTH ' ] = json_encode (['github-oauth ' => ['github.com ' => 'composer-env-token ' ]]);
109+
110+ $ this ->assertSame ('Bearer composer-env-token ' , $ this ->captureAuthorizationHeader ());
111+ }
112+
113+ public function testUsesComposerAuthJsonFile (): void
114+ {
115+ $ this ->clearTokenEnv ();
116+
117+ $ composerHome = sys_get_temp_dir ().'/tailwind-token-test- ' .uniqid ();
118+ mkdir ($ composerHome , 0777 , true );
119+ file_put_contents (
120+ $ composerHome .'/auth.json ' ,
121+ json_encode (['github-oauth ' => ['github.com ' => 'composer-file-token ' ]])
122+ );
123+ $ _SERVER ['COMPOSER_HOME ' ] = $ composerHome ;
124+
125+ try {
126+ $ this ->assertSame ('Bearer composer-file-token ' , $ this ->captureAuthorizationHeader ());
127+ } finally {
128+ unlink ($ composerHome .'/auth.json ' );
129+ rmdir ($ composerHome );
130+ }
131+ }
132+
133+ /**
134+ * Removes every token source from the environment so a test starts from a
135+ * known, token-less state (CI sets GITHUB_TOKEN).
136+ */
137+ private function clearTokenEnv (): void
138+ {
139+ foreach (self ::TOKEN_ENV_VARS as $ name ) {
140+ unset($ _SERVER [$ name ], $ _ENV [$ name ]);
141+ putenv ($ name );
142+ }
143+ }
144+
145+ /**
146+ * Runs latestVersionFor() against a mocked GitHub API and returns the
147+ * Authorization header that was sent (or null if none).
148+ */
149+ private function captureAuthorizationHeader (): ?string
150+ {
151+ $ sentAuthorization = null ;
152+
153+ $ client = new MockHttpClient (static function (string $ method , string $ url , array $ options ) use (&$ sentAuthorization ): MockResponse {
154+ foreach ($ options ['headers ' ] ?? [] as $ header ) {
155+ if (str_starts_with ($ header , 'Authorization: ' )) {
156+ $ sentAuthorization = substr ($ header , \strlen ('Authorization: ' ));
157+ }
158+ }
159+
160+ return new MockResponse (json_encode ([['tag_name ' => 'v4.0.0 ' ]]));
161+ });
162+
163+ (new TailwindVersionFinder ($ client ))->latestVersionFor ('4 ' );
164+
165+ return $ sentAuthorization ;
166+ }
52167}
0 commit comments