Tie Parcel2Go shipping to pending Etsy orders
Deploy HickLab3D Dashboard / Deploy to production (push) Successful in 26s

This commit is contained in:
Hickmeister
2026-10-11 17:11:43 +01:00
parent 55c987ef47
commit 1c80811713
8 changed files with 199 additions and 71 deletions
+69 -9
View File
@@ -3,6 +3,7 @@
namespace Tests\Feature;
use App\Models\EtsyConnection;
use App\Models\IntegrationSetting;
use App\Models\User;
use Illuminate\Foundation\Testing\LazilyRefreshDatabase;
use Illuminate\Support\Facades\Http;
@@ -65,6 +66,7 @@ class IntegrationsTest extends TestCase
public function test_shipping_quote_sends_parcel_to_parcel2go(): void
{
$this->pendingEtsyOrder();
Http::preventStrayRequests();
Http::fake([
'https://auth.example.test/token' => Http::response(['access_token' => 'test-token']),
@@ -75,11 +77,11 @@ class IntegrationsTest extends TestCase
]);
config()->set('services.parcel2go', ['client_id' => 'id', 'client_secret' => 'secret', 'auth_url' => 'https://auth.example.test/token', 'base_url' => 'https://shipping.example.test/api']);
$admin = User::factory()->create(['role' => 'admin']);
$details = ['collection_postcode' => 'SW1A 1AA', 'delivery_postcode' => 'M1 1AE', 'weight' => 2, 'length' => 10, 'width' => 10, 'height' => 10, 'value' => 30];
$details = ['receipt_id' => 77, 'delivery_postcode' => 'SW1A 1AA', 'weight' => 2, 'length' => 10, 'width' => 10, 'height' => 10];
$this->actingAs($admin)->post(route('shipping.quote'), $details)->assertRedirect(route('shipping'));
$this->actingAs($admin)->get(route('shipping'))->assertOk()->assertSee('Evri')->assertSee('£5.50');
Http::assertSent(fn ($request) => $request->url() === 'https://shipping.example.test/api/quotes' && $request['Parcels'][0]['Weight'] === 2);
$this->actingAs($admin)->get(route('shipping'))->assertOk()->assertSee('Evri')->assertSee('£5.50')->assertDontSee('name="delivery_postcode"', false);
Http::assertSent(fn ($request) => $request->url() === 'https://shipping.example.test/api/quotes' && $request['Parcels'][0]['Weight'] === 2 && $request['DeliveryAddress']['Postcode'] === 'M1 1AE' && $request['CollectionAddress']['Postcode'] === 'SW1A 1AA');
}
public function test_shipping_page_works_with_public_api_scope_without_profile_access(): void
@@ -89,7 +91,7 @@ class IntegrationsTest extends TestCase
return $request['scope'] === 'public-api'
? Http::response(['access_token' => 'test-token'])
: Http::response(['error' => 'invalid_scope'], 400);
}]);
}, 'https://shipping.example.test/api/me/orders/detail' => Http::response([], 403)]);
config()->set('services.parcel2go', [
'client_id' => 'id', 'client_secret' => 'secret',
'auth_url' => 'https://auth.example.test/token',
@@ -98,8 +100,45 @@ class IntegrationsTest extends TestCase
]);
$this->actingAs(User::factory()->create(['role' => 'admin']))->get(route('shipping'))
->assertOk()->assertSee('Parcel2Go connected for quotes and collections')
->assertOk()->assertSee('Pending Etsy orders')->assertSee('Parcel2Go denied shipment history')
->assertDontSee('Parcel2Go is unavailable');
Http::assertSentCount(2);
}
public function test_shipping_shows_existing_shipments_when_basic_access_can_read_history(): void
{
Http::preventStrayRequests();
Http::fake([
'https://auth.example.test/token' => Http::response(['access_token' => 'test-token']),
'https://shipping.example.test/api/me/orders/detail' => Http::response(['Orders' => [[
'OrderLineId' => 123, 'Courier' => 'Evri', 'Service' => 'Standard',
'Tracking' => ['Delivered' => true], 'DeliveryAddress' => ['ContactName' => 'Buyer'],
'EstimatedDeliveryDate' => '2026-10-15', 'Hash' => 'hash',
]]]),
]);
config()->set('services.parcel2go', [
'client_id' => 'id', 'client_secret' => 'secret',
'auth_url' => 'https://auth.example.test/token',
'base_url' => 'https://shipping.example.test/api',
'scope' => 'public-api',
]);
$this->actingAs(User::factory()->create(['role' => 'admin']))->get(route('shipping'))
->assertOk()->assertSee('Existing shipments')->assertSee('Delivered')->assertSee('Buyer')
->assertDontSee('Parcel2Go denied shipment history');
Http::assertSentCount(2);
}
public function test_shipping_rejects_a_quote_for_an_order_that_is_not_pending(): void
{
$this->pendingEtsyOrder();
Http::preventStrayRequests();
$admin = User::factory()->create(['role' => 'admin']);
$this->actingAs($admin)->post(route('shipping.quote'), [
'receipt_id' => 999, 'weight' => 2, 'length' => 10, 'width' => 10, 'height' => 10,
'delivery_postcode' => 'SW1A 1AA',
])->assertRedirect(route('shipping'))->assertSessionHasErrors('quote');
Http::assertSentCount(1);
}
@@ -110,7 +149,7 @@ class IntegrationsTest extends TestCase
return $request['scope'] === 'public-api'
? Http::response(['access_token' => 'test-token'])
: Http::response(['error' => 'invalid_scope'], 400);
}]);
}, 'https://shipping.example.test/api/me/orders/detail' => Http::response([], 403)]);
config()->set('services.parcel2go', [
'client_id' => 'id', 'client_secret' => 'secret',
'auth_url' => 'https://auth.example.test/token',
@@ -119,10 +158,9 @@ class IntegrationsTest extends TestCase
]);
$this->actingAs(User::factory()->create(['role' => 'admin']))->get(route('shipping'))
->assertOk()->assertSee('Parcel2Go rejected the selected API access')
->assertDontSee('Parcel2Go connected, but account history is unavailable')
->assertOk()->assertSee('Parcel2Go denied shipment history')
->assertDontSee('Parcel2Go is unavailable');
Http::assertSentCount(2);
Http::assertSentCount(3);
}
public function test_shipping_label_is_downloaded_for_an_order_in_account_history(): void
@@ -142,6 +180,7 @@ class IntegrationsTest extends TestCase
public function test_collection_booking_uses_quoted_service_and_available_date(): void
{
$this->pendingEtsyOrder();
Http::preventStrayRequests();
Http::fake([
'https://auth.example.test/token' => Http::response(['access_token' => 'test-token']),
@@ -153,6 +192,7 @@ class IntegrationsTest extends TestCase
config()->set('services.parcel2go', ['client_id' => 'id', 'client_secret' => 'secret', 'auth_url' => 'https://auth.example.test/token', 'base_url' => 'https://shipping.example.test/api']);
$session = [
'shipping_quote' => ['collection_postcode' => 'SW1A 1AA', 'delivery_postcode' => 'M1 1AE', 'weight' => 2, 'length' => 10, 'width' => 10, 'height' => 10, 'value' => 30],
'shipping_receipt_id' => 77,
'shipping_selected_service' => 'evri-collection',
'shipping_quotes' => [['Service' => ['Slug' => 'evri-collection', 'CollectionType' => 'Collection']]],
'shipping_collection_dates' => [['CollectionDate' => '2026-10-15T10:00:00Z']],
@@ -249,4 +289,24 @@ class IntegrationsTest extends TestCase
])->assertUnprocessable()->assertJsonValidationErrors('targetTemperature');
Http::assertNothingSent();
}
private function pendingEtsyOrder(): void
{
config()->set('services.etsy', ['keystring' => 'key', 'shared_secret' => 'secret']);
EtsyConnection::create([
'shop_id' => 42, 'shop_name' => 'HickLab3D',
'access_token' => '123.token', 'refresh_token' => '123.refresh',
'expires_at' => now()->addHour(),
]);
IntegrationSetting::create([
'provider' => 'parcel2go',
'settings' => ['collection_postcode' => 'SW1A 1AA'],
]);
Http::fake([
'https://api.etsy.com/v3/application/shops/42/receipts*' => Http::response(['results' => [[
'receipt_id' => 77, 'name' => 'Buyer', 'zip' => 'M1 1AE', 'city' => 'Manchester', 'country_iso' => 'GB',
'grandtotal' => ['amount' => 3000, 'divisor' => 100, 'currency_code' => 'GBP'],
]]]),
]);
}
}