From c63f95a4ee33195b5a0bf562d2e57ad77545f106 Mon Sep 17 00:00:00 2001 From: Tyler King Date: Fri, 10 Jul 2020 15:39:05 -0230 Subject: [PATCH] Modifications to recent PRs. - Added test cases for new doGraphQL for ApiHelper service - Modified how errors are pulled in for doGraphQL --- src/ShopifyApp/Actions/GetPlanUrl.php | 2 - .../Objects/Enums/ChargeInterval.php | 3 +- src/ShopifyApp/Objects/Enums/PlanInterval.php | 3 +- src/ShopifyApp/Services/ApiHelper.php | 40 +++++++++------ .../database/factories/PlanFactory.php | 4 ++ tests/Actions/GetPlanUrlTest.php | 23 ++++++++- tests/Services/ApiHelperTest.php | 51 ++++++++++++++----- tests/Stubs/Api.php | 25 +++++++++ tests/fixtures/empty_with_error_graphql.json | 5 ++ .../graphql_app_subscription_create.json | 11 ++++ 10 files changed, 130 insertions(+), 37 deletions(-) create mode 100644 tests/fixtures/empty_with_error_graphql.json create mode 100644 tests/fixtures/graphql_app_subscription_create.json diff --git a/src/ShopifyApp/Actions/GetPlanUrl.php b/src/ShopifyApp/Actions/GetPlanUrl.php index cbe6c6dd..fb0360fb 100644 --- a/src/ShopifyApp/Actions/GetPlanUrl.php +++ b/src/ShopifyApp/Actions/GetPlanUrl.php @@ -71,7 +71,6 @@ public function __invoke(ShopId $shopId, NullablePlanId $planId): string // Confirmation URL $confirmation_url = null; - switch ($plan->getInterval()->toNative()) { case ChargeInterval::ANNUAL()->toNative(): $api = $shop->apiHelper()->createChargeGraphQL( @@ -80,7 +79,6 @@ public function __invoke(ShopId $shopId, NullablePlanId $planId): string $confirmation_url = $api['confirmationUrl']; break; - default: $api = $shop->apiHelper()->createCharge( ChargeType::fromNative($plan->getType()->toNative()), diff --git a/src/ShopifyApp/Objects/Enums/ChargeInterval.php b/src/ShopifyApp/Objects/Enums/ChargeInterval.php index 2c47e087..2229d923 100644 --- a/src/ShopifyApp/Objects/Enums/ChargeInterval.php +++ b/src/ShopifyApp/Objects/Enums/ChargeInterval.php @@ -6,8 +6,7 @@ use Funeralzone\ValueObjects\ValueObject; /** - * Class ChargeInterval - * @package Osiset\ShopifyApp\Objects\Enums + * Charge interval with annual support. * * @method static ChargeInterval EVERY_30_DAYS() * @method static ChargeInterval ANNUAL() diff --git a/src/ShopifyApp/Objects/Enums/PlanInterval.php b/src/ShopifyApp/Objects/Enums/PlanInterval.php index 13860123..6023dd26 100644 --- a/src/ShopifyApp/Objects/Enums/PlanInterval.php +++ b/src/ShopifyApp/Objects/Enums/PlanInterval.php @@ -6,8 +6,7 @@ use Funeralzone\ValueObjects\ValueObject; /** - * Class PlanInterval - * @package Osiset\ShopifyApp\Objects\Enums + * Plan interval with annual support. * * @method static PlanInterval EVERY_30_DAYS() * @method static PlanInterval ANNUAL() diff --git a/src/ShopifyApp/Services/ApiHelper.php b/src/ShopifyApp/Services/ApiHelper.php index 356f6323..61ce2623 100644 --- a/src/ShopifyApp/Services/ApiHelper.php +++ b/src/ShopifyApp/Services/ApiHelper.php @@ -149,6 +149,7 @@ public function getAccessData(string $code): ResponseAccess /** * {@inheritdoc} + * TODO: Convert to GraphQL. */ public function getScriptTags(array $params = []): ResponseAccess { @@ -173,6 +174,7 @@ public function getScriptTags(array $params = []): ResponseAccess /** * {@inheritdoc} + * TODO: Convert to GraphQL. */ public function createScriptTag(array $payload): ResponseAccess { @@ -188,6 +190,7 @@ public function createScriptTag(array $payload): ResponseAccess /** * {@inheritdoc} + * TODO: Convert to GraphQL. */ public function getCharge(ChargeType $chargeType, ChargeReference $chargeRef): ResponseAccess { @@ -205,6 +208,7 @@ public function getCharge(ChargeType $chargeType, ChargeReference $chargeRef): R /** * {@inheritdoc} + * TODO: Convert to GraphQL. */ public function activateCharge(ChargeType $chargeType, ChargeReference $chargeRef): ResponseAccess { @@ -222,6 +226,7 @@ public function activateCharge(ChargeType $chargeType, ChargeReference $chargeRe /** * {@inheritdoc} + * TODO: Convert to GraphQL (merge createChargeGraphQL). */ public function createCharge(ChargeType $chargeType, PlanDetailsTransfer $payload): ResponseAccess { @@ -271,19 +276,19 @@ public function createChargeGraphQL(PlanDetailsTransfer $payload): ResponseAcces } '; $variables = [ - "name" => $payload->name, - "returnUrl" => $payload->returnUrl, - "trialDays" => $payload->trialDays, - "test" => $payload->test, - "lineItems" => [ + 'name' => $payload->name, + 'returnUrl' => $payload->returnUrl, + 'trialDays' => $payload->trialDays, + 'test' => $payload->test, + 'lineItems' => [ [ - "plan" => [ - "appRecurringPricingDetails" => [ - "price" => [ - "amount" => $payload->price, - "currencyCode" => "USD", + 'plan' => [ + 'appRecurringPricingDetails' => [ + 'price' => [ + 'amount' => $payload->price, + 'currencyCode' => 'USD', ], - "interval" => $payload->interval + 'interval' => $payload->interval, ], ] ] @@ -297,6 +302,7 @@ public function createChargeGraphQL(PlanDetailsTransfer $payload): ResponseAcces /** * {@inheritdoc} + * TODO: Convert to GraphQL. */ public function getWebhooks(array $params = []): ResponseAccess { @@ -321,6 +327,7 @@ public function getWebhooks(array $params = []): ResponseAccess /** * {@inheritdoc} + * TODO: Convert to GraphQL. */ public function createWebhook(array $payload): ResponseAccess { @@ -336,6 +343,7 @@ public function createWebhook(array $payload): ResponseAccess /** * {@inheritdoc} + * TODO: Convert to GraphQL. */ public function deleteWebhook(int $webhookId): ResponseAccess { @@ -350,6 +358,7 @@ public function deleteWebhook(int $webhookId): ResponseAccess /** * {@inheritdoc} + * TODO: Convert to GraphQL. */ public function createUsageCharge(UsageChargeDetailsTransfer $payload) { @@ -419,8 +428,8 @@ protected function doRequest(ApiMethod $method, string $path, array $payload = n /** * Fire the request using the GraphQL API Instance. * - * @param string $query The query of GraphQL - * @param array $payload The option payload to using on the query + * @param string $query The query of GraphQL + * @param array $payload The option payload to using on the query * * @throws Exception * @@ -429,10 +438,9 @@ protected function doRequest(ApiMethod $method, string $path, array $payload = n protected function doRequestGraphQL(string $query, array $payload = null) { $response = $this->api->graph($query, $payload); - if ($response['errors'] !== false) { - $message = isset($response['body']['errors']) && is_array($response['body']['errors']) - ? $response['body']['errors'][0]['message'] : 'Unknown error'; + $message = is_array($response['errors']) + ? $response['errors'][0]['message'] : $response['errors']; // Request error somewhere, throw the exception throw new Exception($message); diff --git a/src/ShopifyApp/resources/database/factories/PlanFactory.php b/src/ShopifyApp/resources/database/factories/PlanFactory.php index f4df1d5e..66ea92a9 100644 --- a/src/ShopifyApp/resources/database/factories/PlanFactory.php +++ b/src/ShopifyApp/resources/database/factories/PlanFactory.php @@ -41,3 +41,7 @@ $factory->state(Plan::class, 'type_onetime', [ 'type' => PlanType::ONETIME()->toNative(), ]); + +$factory->state(Plan::class, 'interval_annual', [ + 'interval' => PlanInterval::ANNUAL()->toNative(), +]); diff --git a/tests/Actions/GetPlanUrlTest.php b/tests/Actions/GetPlanUrlTest.php index 9ac648b4..6e63ac41 100644 --- a/tests/Actions/GetPlanUrlTest.php +++ b/tests/Actions/GetPlanUrlTest.php @@ -17,7 +17,7 @@ public function setUp(): void $this->action = $this->app->make(GetPlanUrl::class); } - public function testRun(): void + public function testRun30Days(): void { // Create a plan factory(Plan::class)->states(['installable', 'type_recurring'])->create(); @@ -37,4 +37,25 @@ public function testRun(): void $this->assertNotEmpty($result); } + + public function testRunAnnual(): void + { + // Create a plan + factory(Plan::class)->states(['installable', 'type_recurring', 'interval_annual'])->create(); + + // Create the shop with no plan + $shop = factory($this->model)->create(); + + // Setup API stub + $this->setApiStub(); + ApiStub::stubResponses(['graphql_app_subscription_create']); + + $result = call_user_func( + $this->action, + $shop->getId(), + NullablePlanId::fromNative(null) + ); + + $this->assertNotEmpty($result); + } } diff --git a/tests/Services/ApiHelperTest.php b/tests/Services/ApiHelperTest.php index 3ee96042..f5616679 100644 --- a/tests/Services/ApiHelperTest.php +++ b/tests/Services/ApiHelperTest.php @@ -2,6 +2,7 @@ namespace Osiset\ShopifyApp\Test\Services; +use Exception; use Osiset\ShopifyApp\Test\TestCase; use Osiset\BasicShopifyAPI\ResponseAccess; use Osiset\BasicShopifyAPI\BasicShopifyAPI; @@ -9,6 +10,7 @@ use Osiset\ShopifyApp\Exceptions\ApiException; use Osiset\ShopifyApp\Objects\Enums\ChargeType; use Osiset\ShopifyApp\Test\Stubs\Api as ApiStub; +use Osiset\ShopifyApp\Objects\Enums\PlanInterval; use Osiset\ShopifyApp\Objects\Values\ChargeReference; use Osiset\ShopifyApp\Contracts\ApiHelper as IApiHelper; use Osiset\ShopifyApp\Objects\Transfers\PlanDetails as PlanDetailsTransfer; @@ -137,17 +139,17 @@ public function testCreateCharge(): void $this->setApiStub(); ApiStub::stubResponses(['post_recurring_application_charges']); + // Build the details object + $transfer = new PlanDetailsTransfer(); + $transfer->name = 'Test'; + $transfer->price = 12.00; + $transfer->interval = PlanInterval::EVERY_30_DAYS()->toNative(); + $transfer->test = true; + $transfer->trialDays = 7; + $data = $shop->apiHelper()->createCharge( ChargeType::RECURRING(), - new PlanDetailsTransfer( - 'Test', - 12.00, - true, - 7, - null, - null, - null - ) + $transfer ); $this->assertInstanceOf(ResponseAccess::class, $data); $this->assertEquals('Basic Plan', $data['name']); @@ -205,12 +207,12 @@ public function testCreateUsageCharge(): void $this->setApiStub(); ApiStub::stubResponses(['post_recurring_application_charges_usage_charges']); - $tranfer = new UsageChargeDetailsTransfer(); - $tranfer->chargeReference = new ChargeReference(1); - $tranfer->price = 12.00; - $tranfer->description = 'Hello!'; + $transfer = new UsageChargeDetailsTransfer(); + $transfer->chargeReference = new ChargeReference(1); + $transfer->price = 12.00; + $transfer->description = 'Hello!'; - $data = $shop->apiHelper()->createUsageCharge($tranfer); + $data = $shop->apiHelper()->createUsageCharge($transfer); $this->assertInstanceOf(ResponseAccess::class, $data); } @@ -227,4 +229,25 @@ public function testErrors(): void $shop->apiHelper()->deleteWebhook(1); } + + public function testErrorsGraphQL(): void + { + $this->expectException(Exception::class); + + // Create a shop + $shop = factory($this->model)->create(); + + // Response stubbing + $this->setApiStub(); + ApiStub::stubResponses(['empty_with_error_graphql']); + + $transfer = new PlanDetailsTransfer(); + $transfer->name = 'Test'; + $transfer->price = 12.00; + $transfer->interval = PlanInterval::ANNUAL()->toNative(); + $transfer->test = true; + $transfer->trialDays = 7; + + $shop->apiHelper()->createChargeGraphQL($transfer); + } } diff --git a/tests/Stubs/Api.php b/tests/Stubs/Api.php index f6769f1b..3015570c 100644 --- a/tests/Stubs/Api.php +++ b/tests/Stubs/Api.php @@ -41,6 +41,31 @@ public function rest(string $method, string $path, array $params = null, array $ ]; } + public function graph(string $query, array $variables = [], bool $sync = true): array + { + try { + $filename = array_shift(self::$stubFiles); + $response = json_decode(file_get_contents(__DIR__."/../fixtures/{$filename}.json"), true); + } catch (ErrorException $error) { + throw new Exception('Missing fixture for GraphQL call'); + } + + $errors = false; + $exception = null; + if (isset($response['errors'])) { + $errors = $response['errors']; + $exception = new Exception(); + } + + return [ + 'errors' => $errors, + 'exception' => $exception, + 'response' => $response, + 'status' => 200, + 'body' => new ResponseAccess($response), + ]; + } + public function requestAccess(string $code): ResponseAccess { return new ResponseAccess( diff --git a/tests/fixtures/empty_with_error_graphql.json b/tests/fixtures/empty_with_error_graphql.json new file mode 100644 index 00000000..24e36c48 --- /dev/null +++ b/tests/fixtures/empty_with_error_graphql.json @@ -0,0 +1,5 @@ +{ + "errors": [{ + "message": "Error!" + }] +} diff --git a/tests/fixtures/graphql_app_subscription_create.json b/tests/fixtures/graphql_app_subscription_create.json new file mode 100644 index 00000000..d4387bd0 --- /dev/null +++ b/tests/fixtures/graphql_app_subscription_create.json @@ -0,0 +1,11 @@ +{ + "data": { + "appSubscriptionCreate": { + "userErrors": [], + "confirmationUrl": "https://domain.myshopify.com/admin/charges/4019552312/confirm_recurring_application_charge?signature=BAh7BzoHaWRsKwc4gJXvOhJhdXRvX2FjdGl2YXRlVA%3D%3D--74e39487ff00313ca4409dea7ab00081001c45d5", + "appSubscription": { + "id": "gid://shopify/AppSubscription/4019552312" + } + } + } +}