Files
mareike/tests/Unit/EventPaymentModuleRegistryTest.php
T

184 lines
7.6 KiB
PHP

<?php
namespace Tests\Unit;
use App\EventPaymentModules\EventPaymentModuleRegistry;
use App\EventPaymentModules\Modules\AccountTransferPaymentModule;
use App\EventPaymentModules\Modules\SepaDirectDebitPaymentModule;
use App\EventPaymentModules\Modules\UndefinedPaymentModule;
use App\EventPaymentModules\ProvidesGiroCode;
use App\Models\PaymentMethod;
use PHPUnit\Framework\TestCase;
class EventPaymentModuleRegistryTest extends TestCase
{
public function test_for_slug_resolves_known_modules(): void
{
$this->assertInstanceOf(
AccountTransferPaymentModule::class,
EventPaymentModuleRegistry::forSlug(PaymentMethod::PAYMENT_ACCOUNT_TRANSACTION)
);
$this->assertInstanceOf(
UndefinedPaymentModule::class,
EventPaymentModuleRegistry::forSlug(PaymentMethod::PAYMENT_NOT_DEFINED)
);
$this->assertInstanceOf(
SepaDirectDebitPaymentModule::class,
EventPaymentModuleRegistry::forSlug(PaymentMethod::PAYMENT_SEPA_DIRECT_DEBIT)
);
}
public function test_sepa_direct_debit_requires_a_valid_configuration(): void
{
$module = new SepaDirectDebitPaymentModule();
$valid = [
'account_owner' => 'Test e.V.',
'iban' => 'DE02120300000000202051',
'creditor_id' => 'DE98ZZZ09999999999',
'pre_notification_days' => '5',
];
$this->assertSame(['account_owner', 'iban', 'creditor_id', 'pre_notification_days'], $module->requiredOptionKeys());
$this->assertSame([], $module->configurationErrors($valid));
$this->assertTrue($module->isConfigurationComplete($valid));
// Befüllt, aber ungültig -- reicht nicht.
foreach ([
'iban' => 'DE02120300000000202015',
'creditor_id' => 'DE97ZZZ09999999999',
'pre_notification_days' => '1',
] as $key => $value) {
$config = array_merge($valid, [$key => $value]);
$this->assertArrayHasKey($key, $module->configurationErrors($config), $key);
$this->assertFalse($module->isConfigurationComplete($config), $key);
}
foreach (['15', '2.5', 'fünf'] as $days) {
$this->assertArrayHasKey('pre_notification_days', $module->configurationErrors(
array_merge($valid, ['pre_notification_days' => $days])
), $days);
}
// Leere Felder sind Sache der Pflichtfeld-Prüfung, nicht der Inhaltsprüfung.
$this->assertSame([], $module->configurationErrors([]));
$this->assertFalse($module->isConfigurationComplete(array_merge($valid, ['creditor_id' => ''])));
}
public function test_sepa_direct_debit_defaults(): void
{
$defaults = PaymentMethod::defaults()[PaymentMethod::PAYMENT_SEPA_DIRECT_DEBIT];
$this->assertSame('SEPA-Lastschrift', $defaults['name']);
$this->assertSame(5, $defaults['configuration']['pre_notification_days']);
$this->assertSame('file-signature', $defaults['configuration']['icon']);
}
public function test_for_slug_returns_null_for_unknown(): void
{
$this->assertNull(EventPaymentModuleRegistry::forSlug('DOES_NOT_EXIST'));
}
public function test_slugs_lists_all_registered_modules(): void
{
$slugs = EventPaymentModuleRegistry::slugs();
$this->assertContains(PaymentMethod::PAYMENT_ACCOUNT_TRANSACTION, $slugs);
$this->assertContains(PaymentMethod::PAYMENT_NOT_DEFINED, $slugs);
$this->assertContains(PaymentMethod::PAYMENT_SEPA_DIRECT_DEBIT, $slugs);
}
public function test_module_option_helpers(): void
{
$module = new AccountTransferPaymentModule();
$this->assertSame(['account_owner', 'iban'], $module->requiredOptionKeys());
// Rückgabe folgt der Schema-Reihenfolge, unbekannte Keys werden verworfen.
$this->assertSame(
['account_owner' => 'Kasse', 'iban' => 'DE123'],
$module->sanitizeConfiguration(['iban' => 'DE123', 'account_owner' => 'Kasse', 'evil' => 'x'])
);
$this->assertFalse($module->isConfigurationComplete(['iban' => 'DE123']));
$this->assertTrue($module->isConfigurationComplete(['iban' => 'DE123', 'account_owner' => 'Kasse']));
}
public function test_participant_options_per_module(): void
{
// Überweisung: keine payer-seitigen Eingaben im Anmeldeformular.
$this->assertSame([], (new AccountTransferPaymentModule())->participantInputOptions());
// Sonstiges (Barzahlung vor Ort): ebenfalls keine payer-seitigen Eingaben -- die Zahlungsart
// beschreibt sich allein über den vom Veranstalter gepflegten Freitext.
$this->assertSame([], (new UndefinedPaymentModule())->getParticipantOptions());
}
public function test_system_participant_options_stay_in_the_schema(): void
{
$module = new AccountTransferPaymentModule();
// Die Zahler-Konto-Felder trägt der Zahlungsimport nach, gefragt wird beim Anmelden nicht
// danach. Im Schema müssen sie trotzdem stehen -- sonst wirft sanitizeParticipantOptions()
// sie beim nächsten Durchlauf als unbekannte Schlüssel weg.
$names = array_column($module->getParticipantOptions(), 'name');
$this->assertSame(['payer_account_owner', 'payer_iban'], $names);
$this->assertSame(
['payer_iban' => 'DE02120300000000202051'],
$module->sanitizeParticipantOptions(['payer_iban' => 'DE02120300000000202051', 'evil' => 'x'])
);
// Kein Pflichtfeld -- eine Anmeldung ohne Zahlungseingang bleibt vollständig.
$this->assertTrue($module->participantOptionsComplete([]));
}
public function test_participant_option_helpers(): void
{
// Anonymes Modul mit einer Pflicht-Teilnehmereingabe.
$module = new class extends \App\EventPaymentModules\AbstractEventPaymentModule {
public static function slug(): string
{
return 'TEST';
}
public function defaultName(): string
{
return 'Test';
}
public function getOptions(): array
{
return [];
}
public function getParticipantOptions(): array
{
return [['name' => 'iban', 'label' => 'IBAN', 'type' => 'string', 'required' => true]];
}
protected function invoiceClosingStatement(\App\EventPaymentModules\DTO\CreateInvoiceRequest $request): string
{
return '';
}
};
// sanitize verwirft unbekannte Keys, complete verlangt Pflichtfeld non-empty.
$this->assertSame(['iban' => 'DE1'], $module->sanitizeParticipantOptions(['iban' => 'DE1', 'evil' => 'x']));
$this->assertFalse($module->participantOptionsComplete([]));
$this->assertFalse($module->participantOptionsComplete(['iban' => '']));
$this->assertTrue($module->participantOptionsComplete(['iban' => 'DE1']));
}
public function test_only_account_transfer_provides_giro_code(): void
{
$this->assertInstanceOf(ProvidesGiroCode::class, new AccountTransferPaymentModule());
$this->assertNotInstanceOf(ProvidesGiroCode::class, new UndefinedPaymentModule());
}
public function test_defaults_are_built_from_modules(): void
{
$defaults = PaymentMethod::defaults();
$this->assertSame('Überweisung auf Veranstaltungskonto', $defaults[PaymentMethod::PAYMENT_ACCOUNT_TRANSACTION]['name']);
$this->assertArrayHasKey(PaymentMethod::PAYMENT_NOT_DEFINED, $defaults);
}
}