Fix Stripe authorization lifecycle timing
This commit is contained in:
1 parent
21038d68ca
commit
61ea299b0e
5 files changed
+157
-19
No files matched your search
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
namespace Bookstore\Core\Tests\Unit\Order;
|
||||
|
||||
use Bookstore\Core\Order\OrderStatuses;
|
||||
use Bookstore\Core\Order\SupplierOrderJob;
|
||||
use Bookstore\Core\Tests\TestCase;
|
||||
use Brain\Monkey\Actions;
|
||||
use Brain\Monkey\Functions;
|
||||
use Mockery;
|
||||
|
||||
class SupplierOrderJobTest extends TestCase
|
||||
{
|
||||
public function test_registers_after_stripe_has_saved_its_response(): void
|
||||
{
|
||||
Actions\expectAdded('wc_gateway_stripe_process_response')
|
||||
->with([SupplierOrderJob::class, 'accept_stripe_authorization'], 10, 2)
|
||||
->once();
|
||||
Actions\expectAdded('woocommerce_order_status_' . OrderStatuses::AUTHORIZED)->once();
|
||||
Actions\expectAdded('bsc_submit_supplier_order')->once();
|
||||
|
||||
SupplierOrderJob::register();
|
||||
}
|
||||
|
||||
public function test_promotes_a_saved_uncaptured_stripe_authorization(): void
|
||||
{
|
||||
Functions\expect('apply_filters')->once()->andReturn([
|
||||
'pass' => true,
|
||||
'reason' => 'test pass',
|
||||
]);
|
||||
$order = Mockery::mock(\WC_Order::class);
|
||||
$order->shouldReceive('has_status')->with('on-hold')->once()->andReturn(true);
|
||||
$order->shouldReceive('get_payment_method')->once()->andReturn('stripe');
|
||||
$order->shouldReceive('get_meta')->with('_stripe_charge_captured')->once()->andReturn('no');
|
||||
$order->shouldReceive('add_order_note')->once();
|
||||
$order->shouldReceive('update_status')
|
||||
->with(OrderStatuses::AUTHORIZED, Mockery::type('string'))
|
||||
->once();
|
||||
|
||||
SupplierOrderJob::accept_stripe_authorization((object) ['captured' => false], $order);
|
||||
}
|
||||
|
||||
public function test_ignores_an_on_hold_stripe_order_without_persisted_uncaptured_state(): void
|
||||
{
|
||||
$order = Mockery::mock(\WC_Order::class);
|
||||
$order->shouldReceive('has_status')->with('on-hold')->once()->andReturn(true);
|
||||
$order->shouldReceive('get_payment_method')->once()->andReturn('stripe');
|
||||
$order->shouldReceive('get_meta')->with('_stripe_charge_captured')->once()->andReturn('');
|
||||
$order->shouldNotReceive('update_status');
|
||||
|
||||
SupplierOrderJob::accept_stripe_authorization((object) [], $order);
|
||||
}
|
||||
|
||||
public function test_ignores_non_authorization_stripe_responses(): void
|
||||
{
|
||||
$order = Mockery::mock(\WC_Order::class);
|
||||
$order->shouldReceive('has_status')->with('on-hold')->once()->andReturn(false);
|
||||
$order->shouldNotReceive('get_payment_method');
|
||||
$order->shouldNotReceive('get_meta');
|
||||
$order->shouldNotReceive('update_status');
|
||||
|
||||
SupplierOrderJob::accept_stripe_authorization((object) ['captured' => true], $order);
|
||||
}
|
||||
|
||||
public function test_capture_success_requires_stripes_persisted_confirmation(): void
|
||||
{
|
||||
$order = Mockery::mock(\WC_Order::class);
|
||||
$order->shouldReceive('update_status')->with('processing', Mockery::type('string'))->once();
|
||||
$order->shouldReceive('get_id')->once()->andReturn(42);
|
||||
|
||||
$reloaded = Mockery::mock(\WC_Order::class);
|
||||
$reloaded->shouldReceive('get_meta')->with('_stripe_charge_captured')->once()->andReturn('yes');
|
||||
$reloaded->shouldReceive('update_status')
|
||||
->with(OrderStatuses::SUPPLIER_ORDERED, Mockery::type('string'))
|
||||
->once();
|
||||
Functions\expect('wc_get_order')->with(42)->once()->andReturn($reloaded);
|
||||
|
||||
$this->invokePrivate('capture_and_complete', $order);
|
||||
}
|
||||
|
||||
public function test_capture_without_stripe_confirmation_routes_to_review(): void
|
||||
{
|
||||
$order = Mockery::mock(\WC_Order::class);
|
||||
$order->shouldReceive('update_status')->with('processing', Mockery::type('string'))->once();
|
||||
$order->shouldReceive('get_id')->once()->andReturn(43);
|
||||
|
||||
$reloaded = Mockery::mock(\WC_Order::class);
|
||||
$reloaded->shouldReceive('get_meta')->with('_stripe_charge_captured')->once()->andReturn('no');
|
||||
$reloaded->shouldReceive('update_status')
|
||||
->with(OrderStatuses::EXCEPTION, Mockery::type('string'))
|
||||
->once();
|
||||
Functions\expect('wc_get_order')->with(43)->once()->andReturn($reloaded);
|
||||
|
||||
$this->invokePrivate('capture_and_complete', $order);
|
||||
}
|
||||
|
||||
public function test_release_is_recorded_as_requested_not_as_a_confirmed_void(): void
|
||||
{
|
||||
$order = Mockery::mock(\WC_Order::class);
|
||||
$order->shouldReceive('update_meta_data')
|
||||
->with('_bsc_stripe_release_requested', 'yes')
|
||||
->once();
|
||||
$order->shouldReceive('save')->once();
|
||||
$order->shouldReceive('update_status')->with('cancelled', Mockery::type('string'))->once();
|
||||
$order->shouldReceive('update_status')
|
||||
->with(OrderStatuses::EXCEPTION, Mockery::on(
|
||||
static fn (string $note): bool => str_contains($note, 'verify')
|
||||
))
|
||||
->once();
|
||||
|
||||
$this->invokePrivate('fail_and_release', $order, 'Unavailable.');
|
||||
}
|
||||
|
||||
private function invokePrivate(string $method, mixed ...$arguments): mixed
|
||||
{
|
||||
$reflection = new \ReflectionMethod(SupplierOrderJob::class, $method);
|
||||
return $reflection->invoke(null, ...$arguments);
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,12 @@ if (!class_exists(\WC_Cart::class)) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!class_exists(\WC_Order::class)) {
|
||||
class WC_Order
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
if (!class_exists(\WP_Error::class)) {
|
||||
class WP_Error
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user