Skip to content

Commit

Permalink
Use environment variables only for integration test dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
jeromegamez committed May 27, 2024
1 parent f646b54 commit 0c48ae5
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 177 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
/vendor
/docs/_build
/docs/*.pyc
/tests/_fixtures/test_*
/tests/.env

/.firebaserc
/.php-cs-fixer.cache
Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@
"phpunit/phpunit": "^10.5.20",
"rector/rector": "^1.0.5",
"shipmonk/composer-dependency-analyser": "^1.5.3",
"symfony/var-dumper": "^6.3.5 || ^7.0.7"
"symfony/var-dumper": "^6.3.5 || ^7.0.7",
"vlucas/phpdotenv": "^5.6"
},
"suggest": {
"google/cloud-firestore": "^1.0 to use the Firestore component"
Expand Down
1 change: 1 addition & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
beStrictAboutOutputDuringTests="true"
bootstrap="tests/bootstrap.php"
colors="true"
>
<testsuites>
Expand Down
6 changes: 6 additions & 0 deletions tests/.env.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
GOOGLE_APPLICATION_CREDENTIALS=
FIREBASE_TENANT_ID=
TEST_FIREBASE_APP_ID=
TEST_FIREBASE_RTDB_URI=
TEST_FIREBASE_TENANT_ID=
TEST_REGISTRATION_TOKENS=
46 changes: 14 additions & 32 deletions tests/Integration/ServiceAccountTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,56 +4,40 @@

namespace Kreait\Firebase\Tests\Integration;

use Beste\Json;
use Kreait\Firebase\Factory;
use Kreait\Firebase\Tests\IntegrationTestCase;
use Kreait\Firebase\Util;
use PHPUnit\Framework\Attributes\DoesNotPerformAssertions;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;

use function assert;

/**
* @internal
*/
final class ServiceAccountTest extends TestCase
final class ServiceAccountTest extends IntegrationTestCase
{
/**
* @var non-empty-string
*/
private static string $credentialsPath;
private static bool $credentialsPathIsTemporary = false;

public static function setUpBeforeClass(): void
{
$credentialsFromEnvironment = Util::getenv('GOOGLE_APPLICATION_CREDENTIALS');
parent::setUpBeforeClass();

if ($credentialsFromEnvironment !== null && str_starts_with($credentialsFromEnvironment, '{')) {
// Don't overwrite the fixtures file
$credentialsPath = __DIR__.'/test_credentials.json';
self::$credentialsPathIsTemporary = true;

$result = file_put_contents($credentialsPath, $credentialsFromEnvironment);

if ($result === false) {
self::fail("Unable to write credentials to file `{$credentialsPath}`");
}

Util::putenv('GOOGLE_APPLICATION_CREDENTIALS', $credentialsPath);
} elseif (!file_exists($credentialsPath = __DIR__.'/../_fixtures/test_credentials.json')) {
self::markTestSkipped('The integration tests require credentials');
}

self::$credentialsPath = $credentialsPath;
self::$credentialsPath = sys_get_temp_dir().DIRECTORY_SEPARATOR.'test_credentials.json';
file_put_contents(self::$credentialsPath, json_encode(self::$serviceAccount));
Util::putenv('GOOGLE_APPLICATION_CREDENTIALS', self::$credentialsPath);
}

public static function tearDownAfterClass(): void
{
if (self::$credentialsPathIsTemporary) {
unlink(self::$credentialsPath);
}
unlink(self::$credentialsPath);
}

#[Test]
#[DoesNotPerformAssertions]
public function withPathToServiceAccount(): void
{
$factory = (new Factory())->withServiceAccount(self::$credentialsPath);
Expand All @@ -62,6 +46,7 @@ public function withPathToServiceAccount(): void
}

#[Test]
#[DoesNotPerformAssertions]
public function withJsonString(): void
{
$json = file_get_contents(self::$credentialsPath);
Expand All @@ -73,19 +58,16 @@ public function withJsonString(): void
}

#[Test]
#[DoesNotPerformAssertions]
public function withArray(): void
{
$json = file_get_contents(self::$credentialsPath);
assert($json !== false && $json !== '');

$array = Json::decode($json, true);

$factory = (new Factory())->withServiceAccount($array);
$factory = (new Factory())->withServiceAccount(self::$serviceAccount);

$this->assertFunctioningConnection($factory);
}

#[Test]
#[DoesNotPerformAssertions]
public function withGoogleApplicationCredentialsAsFilePath(): void
{
Util::putenv('GOOGLE_APPLICATION_CREDENTIALS', self::$credentialsPath);
Expand All @@ -94,6 +76,7 @@ public function withGoogleApplicationCredentialsAsFilePath(): void
}

#[Test]
#[DoesNotPerformAssertions]
public function withGoogleApplicationCredentialsAsJsonString(): void
{
$json = file_get_contents(self::$credentialsPath);
Expand All @@ -111,7 +94,6 @@ private function assertFunctioningConnection(Factory $factory): void

try {
$user = $auth->createAnonymousUser();
$this->addToAssertionCount(1);
} finally {
if ($user !== null) {
$auth->deleteUser($user->uid);
Expand Down
155 changes: 12 additions & 143 deletions tests/IntegrationTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,9 @@
use Beste\Json;
use Kreait\Firebase\Factory;
use Kreait\Firebase\Util;
use Throwable;

use function array_rand;
use function bin2hex;
use function file_exists;
use function file_get_contents;
use function is_array;
use function mb_strtolower;
use function random_bytes;

Expand Down Expand Up @@ -54,23 +50,19 @@ abstract class IntegrationTestCase extends FirebaseTestCase

public static function setUpBeforeClass(): void
{
$credentials = self::credentialsFromEnvironment() ?? self::credentialsFromFile();
$credentials = self::credentialsFromEnvironment();

if (!$credentials) {
self::markTestSkipped('The integration tests require credentials');
}

if (str_starts_with($credentials, '{')) {
self::$serviceAccount = Json::decode($credentials, true);
} else {
self::$serviceAccount = Json::decodeFile($credentials, true);
}
self::$serviceAccount = Json::decode($credentials, true);

self::$factory = (new Factory())->withServiceAccount(self::$serviceAccount);
self::$registrationTokens = self::registrationTokens();
self::$rtdbUrl = self::rtdbUrl();
self::$tenantId = self::tenantId();
self::$appId = self::appId();
self::$registrationTokens = self::registrationTokensFromEnvironment();
self::$rtdbUrl = Util::getenv('TEST_FIREBASE_RTDB_URI');
self::$tenantId = Util::getenv('TEST_FIREBASE_TENANT_ID');
self::$appId = Util::getenv('TEST_FIREBASE_APP_ID');
}

/**
Expand Down Expand Up @@ -112,18 +104,6 @@ protected static function databaseIsEmulated(): bool
return Util::rtdbEmulatorHost() !== null;
}

/**
* @return non-empty-string|null
*/
private static function credentialsFromFile(): ?string
{
$credentialsPath = self::$fixturesDir.'/test_credentials.json';

return file_exists($credentialsPath)
? $credentialsPath
: null;
}

/**
* @return non-empty-string|null
*/
Expand All @@ -137,124 +117,13 @@ private static function credentialsFromEnvironment(): ?string
/**
* @return list<non-empty-string>
*/
private static function registrationTokens(): array
{
$registrationTokens = self::registrationTokensFromEnvironment() ?? self::registrationTokensFromFile();
$registrationTokens = array_map(trim(...), $registrationTokens);
$registrationTokens = array_filter($registrationTokens);

return array_values($registrationTokens);
}

/**
* @return array<string>
*/
private static function registrationTokensFromFile(): array
{
$tokens = [];

$path = self::$fixturesDir.'/test_devices.json';

if (!file_exists($path)) {
return $tokens;
}

try {
if ($contents = file_get_contents($path)) {
$tokens = Json::decode($contents, true);
}
} catch (Throwable) {
}

return array_map(strval(...), $tokens);
}

/**
* @return array<string>|null
*/
private static function registrationTokensFromEnvironment(): ?array
{
if (!($tokens = Util::getenv('TEST_REGISTRATION_TOKENS'))) {
return null;
}

try {
$tokens = Json::decode($tokens, true);
} catch (Throwable) {
return null;
}

if (!is_array($tokens)) {
return null;
}

return array_map(strval(...), $tokens);
}

/**
* @return non-empty-string|null
*/
private static function rtdbUrl(): ?string
{
return self::setting('TEST_FIREBASE_RTDB_URI', 'test_rtdb.json');
}

/**
* @return non-empty-string|null
*/
private static function tenantId(): ?string
{
return self::setting('TEST_FIREBASE_TENANT_ID', 'test_tenant.json');
}

/**
* @return non-empty-string|null
*/
private static function appId(): ?string
{
return self::setting('TEST_FIREBASE_APP_ID', 'test_app.json');
}

/**
* @param non-empty-string $envName
* @param non-empty-string $envFile
*
* @return non-empty-string|null
*/
private static function setting(string $envName, string $envFile): ?string
private static function registrationTokensFromEnvironment(): array
{
return self::settingFromEnv($envName) ?? self::settingFromFile($envFile);
}

/**
* @return non-empty-string|null
*/
private static function settingFromFile(string $envFile): ?string
{
$path = self::$fixturesDir.'/'.$envFile;

if (!file_exists($path)) {
return null;
}

try {
if ($contents = file_get_contents($path)) {
return Json::decode($contents, true);
}

return null;
} catch (Throwable) {
return null;
}
}
$tokens = Json::decode(Util::getenv('TEST_REGISTRATION_TOKENS') ?? '', true);
$tokens = array_map(strval(...), $tokens);
$tokens = array_map(trim(...), $tokens);
$tokens = array_filter($tokens, fn($token) => $token !== '');

/**
* @param non-empty-string $envKey
*
* @return non-empty-string|null
*/
private static function settingFromEnv(string $envKey): ?string
{
return Util::getenv($envKey);
return array_values($tokens);
}
}
10 changes: 10 additions & 0 deletions tests/bootstrap.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

require_once __DIR__.'/../vendor/autoload.php';

// Unsafe is needed because google/auth uses getenv/putenv to determine the Application Credentials
$dotenv = Dotenv\Dotenv::createUnsafeImmutable(__DIR__);
$dotenv->safeLoad();
$dotenv->required('GOOGLE_APPLICATION_CREDENTIALS');

0 comments on commit 0c48ae5

Please sign in to comment.