Files
api/services/nginx/app/tests/Unit/Invoicing/EconomicAuthTokenFallbackTest.php
T

179 lines
6.9 KiB
PHP

<?php
app_require('traits/economic_endpoint_t.php');
app_require('modules/economic/economic_m.php');
use traits\economic_endpoint_t;
if (!class_exists('EconomicEndpointGrantFallbackProbe')) {
class EconomicEndpointGrantFallbackProbe
{
use economic_endpoint_t {
resolve_agreement_grant_token as public resolveAgreementGrantToken;
resolve_app_secret_token as public resolveAppSecretToken;
assert_successful_response as public assertSuccessfulResponse;
}
}
}
if (!class_exists('EconomicMLegacyGrantFallbackProbe')) {
class EconomicMLegacyGrantFallbackProbe extends economic_m
{
public function __construct()
{
// No-op: tests inject private token fields directly.
}
public function configureTokens(string $appSecretToken, string $primaryGrant, string $secondaryGrant = ''): void
{
$this->setPrivateTokenField('app_token', $appSecretToken);
$this->setPrivateTokenField('appAccessGrant', $primaryGrant);
$this->setPrivateTokenField('appAccessGrant2', $secondaryGrant);
}
public function resolveAgreementGrantToken(bool $authToken2): string
{
return $this->resolve_agreement_grant_token($authToken2);
}
public function resolveAppSecretToken(): string
{
return $this->resolve_app_secret_token();
}
public function assertSuccessfulResponse(int $httpStatusCode, string|false $response): string
{
return $this->assert_successful_response($httpStatusCode, $response);
}
private function setPrivateTokenField(string $fieldName, string $value): void
{
$reflection = new ReflectionProperty(economic_m::class, $fieldName);
$reflection->setAccessible(true);
$reflection->setValue($this, $value);
}
}
}
beforeEach(function (): void {
global $ECONOMIC_API;
$ECONOMIC_API = [
'app_secret_token' => 'test-secret',
'app_access_grant' => 'primary-grant',
'app_access_grant2' => 'secondary-grant',
];
});
it('uses grant #2 in economic_endpoint_t when explicitly requested and configured', function (): void {
$probe = new EconomicEndpointGrantFallbackProbe();
expect($probe->resolveAgreementGrantToken(true))->toBe('secondary-grant');
expect($probe->resolveAgreementGrantToken(false))->toBe('primary-grant');
});
it('falls back to grant #1 in economic_endpoint_t when grant #2 is missing', function (): void {
global $ECONOMIC_API;
$ECONOMIC_API['app_access_grant2'] = '';
$probe = new EconomicEndpointGrantFallbackProbe();
expect($probe->resolveAgreementGrantToken(true))->toBe('primary-grant');
expect($probe->resolveAgreementGrantToken(false))->toBe('primary-grant');
});
it('throws for missing required primary grant in economic_endpoint_t', function (): void {
global $ECONOMIC_API;
$ECONOMIC_API['app_access_grant'] = '';
$probe = new EconomicEndpointGrantFallbackProbe();
expect(fn() => $probe->resolveAgreementGrantToken(false))
->toThrow(RuntimeException::class, 'Missing e-conomic agreement grant token');
});
it('throws for missing app secret in economic_endpoint_t', function (): void {
global $ECONOMIC_API;
$ECONOMIC_API['app_secret_token'] = '';
$probe = new EconomicEndpointGrantFallbackProbe();
expect(fn() => $probe->resolveAppSecretToken())
->toThrow(RuntimeException::class, 'Missing e-conomic app secret token');
});
it('uses grant #2 in legacy economic_m when available', function (): void {
$probe = new EconomicMLegacyGrantFallbackProbe();
$probe->configureTokens('test-secret', 'primary-grant', 'secondary-grant');
expect($probe->resolveAgreementGrantToken(true))->toBe('secondary-grant');
expect($probe->resolveAgreementGrantToken(false))->toBe('primary-grant');
});
it('falls back to grant #1 in legacy economic_m when grant #2 is missing', function (): void {
$probe = new EconomicMLegacyGrantFallbackProbe();
$probe->configureTokens('test-secret', 'primary-grant', '');
expect($probe->resolveAgreementGrantToken(true))->toBe('primary-grant');
});
it('throws for missing required primary grant in legacy economic_m', function (): void {
$probe = new EconomicMLegacyGrantFallbackProbe();
$probe->configureTokens('test-secret', '', 'secondary-grant');
expect(fn() => $probe->resolveAgreementGrantToken(false))
->toThrow(RuntimeException::class, 'Missing e-conomic agreement grant token');
});
it('throws for missing app secret in legacy economic_m', function (): void {
$probe = new EconomicMLegacyGrantFallbackProbe();
$probe->configureTokens('', 'primary-grant', 'secondary-grant');
expect(fn() => $probe->resolveAppSecretToken())
->toThrow(RuntimeException::class, 'Missing e-conomic app secret token');
});
it('throws deterministic upstream exceptions for non-2xx endpoint trait responses', function (): void {
$probe = new EconomicEndpointGrantFallbackProbe();
$errorPayload = json_encode([
'message' => 'Could not parse query string filter.',
'errors' => ['Filtering is not allowed on property \'invalidField\'.'],
'logId' => 'abc123',
'httpStatusCode' => 400,
]);
expect(fn() => $probe->assertSuccessfulResponse(400, $errorPayload))
->toThrow(RuntimeException::class, 'Could not parse query string filter.');
expect(fn() => $probe->assertSuccessfulResponse(502, 'Gateway timeout'))
->toThrow(RuntimeException::class, 'HTTP 502');
});
it('throws deterministic upstream exceptions for non-2xx legacy economic_m responses', function (): void {
$probe = new EconomicMLegacyGrantFallbackProbe();
$probe->configureTokens('test-secret', 'primary-grant', 'secondary-grant');
$errorPayload = json_encode([
'message' => 'Could not parse query string filter.',
'errors' => ['Filtering is not allowed on property \'invalidField\'.'],
'logId' => 'abc123',
'httpStatusCode' => 400,
]);
expect(fn() => $probe->assertSuccessfulResponse(400, $errorPayload))
->toThrow(RuntimeException::class, 'Could not parse query string filter.');
expect(fn() => $probe->assertSuccessfulResponse(500, '<html>server error</html>'))
->toThrow(RuntimeException::class, 'HTTP 500');
});
it('returns raw payload unchanged on successful HTTP statuses', function (): void {
$endpointProbe = new EconomicEndpointGrantFallbackProbe();
$legacyProbe = new EconomicMLegacyGrantFallbackProbe();
$legacyProbe->configureTokens('test-secret', 'primary-grant', 'secondary-grant');
$payload = '{"collection":[{"customerNumber":1000}],"pagination":{"results":1}}';
expect($endpointProbe->assertSuccessfulResponse(200, $payload))->toBe($payload);
expect($legacyProbe->assertSuccessfulResponse(200, $payload))->toBe($payload);
});