116 lines
4.0 KiB
PHP
116 lines
4.0 KiB
PHP
<?php
|
|
|
|
use AKSRT\Ledger\AssetType;
|
|
use AKSRT\Ledger\LedgerCommand;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
final class LedgerCommandTest extends TestCase {
|
|
public function test_transfer_splits_principal_fee_and_net_receipt(): void {
|
|
$command = LedgerCommand::transfer(
|
|
'client-transfer:1:550e8400-e29b-41d4-a716-446655440000',
|
|
'transfer',
|
|
10,
|
|
20,
|
|
AssetType::BALANCE,
|
|
1000,
|
|
125
|
|
);
|
|
|
|
self::assertSame([-875, -125, 875], array_column($command->entries, 'delta_minor'));
|
|
self::assertSame(['transfer_out', 'fee', 'transfer_in'], array_column($command->entries, 'entry_type'));
|
|
self::assertSame(1000, $command->metadata['gross_minor']);
|
|
self::assertSame(125, $command->metadata['fee_minor']);
|
|
self::assertSame(875, $command->metadata['net_minor']);
|
|
self::assertSame(-125, array_sum(array_column($command->entries, 'delta_minor')));
|
|
}
|
|
|
|
public function test_transfer_rejects_net_below_one_minor_unit(): void {
|
|
$this->expectException(InvalidArgumentException::class);
|
|
LedgerCommand::transfer('transfer:key', 'transfer', 1, 2, AssetType::POINTS, 10, 10);
|
|
}
|
|
|
|
public function test_transfer_rejects_negative_fee_before_arithmetic(): void {
|
|
$this->expectException(InvalidArgumentException::class);
|
|
LedgerCommand::transfer('transfer:key', 'transfer', 1, 2, AssetType::POINTS, PHP_INT_MAX, -1);
|
|
}
|
|
|
|
public function test_validation_returns_400_for_bad_operation_key(): void {
|
|
$command = new LedgerCommand('bad key', 'credit', [[
|
|
'user_id' => 1,
|
|
'asset' => 'points',
|
|
'delta_minor' => 1,
|
|
'entry_type' => 'credit',
|
|
]]);
|
|
$error = $command->validate();
|
|
self::assertInstanceOf(WP_Error::class, $error);
|
|
self::assertSame('aksrt_ledger_operation_key', $error->get_error_code());
|
|
self::assertSame(400, $error->get_error_data()['status']);
|
|
}
|
|
|
|
public function test_payload_hash_is_stable_for_metadata_key_order(): void {
|
|
$entries = [['user_id' => 1, 'asset' => 'points', 'delta_minor' => 2, 'entry_type' => 'credit']];
|
|
$first = new LedgerCommand('stable:key', 'credit', $entries, '', '', 0, ['b' => 2, 'a' => 1]);
|
|
$second = new LedgerCommand('stable:key', 'credit', $entries, '', '', 0, ['a' => 1, 'b' => 2]);
|
|
self::assertSame($first->payload_hash(), $second->payload_hash());
|
|
}
|
|
|
|
public function test_payload_hash_changes_with_business_payload(): void {
|
|
$first = new LedgerCommand('stable:key', 'credit', [[
|
|
'user_id' => 1,
|
|
'asset' => 'points',
|
|
'delta_minor' => 2,
|
|
'entry_type' => 'credit',
|
|
]]);
|
|
$second = new LedgerCommand('stable:key', 'credit', [[
|
|
'user_id' => 1,
|
|
'asset' => 'points',
|
|
'delta_minor' => 3,
|
|
'entry_type' => 'credit',
|
|
]]);
|
|
self::assertNotSame($first->payload_hash(), $second->payload_hash());
|
|
}
|
|
|
|
public function test_validation_rejects_empty_entries_and_invalid_asset(): void {
|
|
$empty = new LedgerCommand('empty:key', 'credit', []);
|
|
self::assertSame('aksrt_ledger_entries', $empty->validate()->get_error_code());
|
|
|
|
$invalid = new LedgerCommand('asset:key', 'credit', [[
|
|
'user_id' => 1,
|
|
'asset' => 'cash',
|
|
'delta_minor' => 1,
|
|
'entry_type' => 'credit',
|
|
]]);
|
|
self::assertSame('aksrt_ledger_asset', $invalid->validate()->get_error_code());
|
|
}
|
|
|
|
public function test_validation_requires_integer_non_zero_entry_values(): void {
|
|
foreach (['1', 0, PHP_INT_MIN] as $delta) {
|
|
$command = new LedgerCommand('entry:key', 'credit', [[
|
|
'user_id' => 1,
|
|
'asset' => 'points',
|
|
'delta_minor' => $delta,
|
|
'entry_type' => 'credit',
|
|
]]);
|
|
self::assertSame('aksrt_ledger_entry', $command->validate()->get_error_code());
|
|
}
|
|
}
|
|
|
|
public function test_validation_rejects_negative_actor_and_invalid_entry_type(): void {
|
|
$actor = new LedgerCommand('actor:key', 'credit', [[
|
|
'user_id' => 1,
|
|
'asset' => 'points',
|
|
'delta_minor' => 1,
|
|
'entry_type' => 'credit',
|
|
]], '', '', -1);
|
|
self::assertSame('aksrt_ledger_actor', $actor->validate()->get_error_code());
|
|
|
|
$type = new LedgerCommand('type:key', 'credit', [[
|
|
'user_id' => 1,
|
|
'asset' => 'points',
|
|
'delta_minor' => 1,
|
|
'entry_type' => 'Bad Type',
|
|
]]);
|
|
self::assertSame('aksrt_ledger_entry', $type->validate()->get_error_code());
|
|
}
|
|
}
|