diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 91b2707b..92189c1a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,6 @@ jobs: max-parallel: 3 matrix: php: - - '8.0' - '8.1' - '8.2' - '8.3' @@ -20,33 +19,17 @@ jobs: normalize: [ false ] validate: [ false ] laravel: - - '8.22' - - '9.0' - - '10.0' - - '11.0.3' - - '12.0' + - '10.48.29' + - '11.45.1' + - '12.19.3' exclude: - - php: '8.0' - laravel: '9.0' - - php: '8.0' - laravel: '10.0' - php: '8.1' - laravel: '8.22' + laravel: '11.45.1' - php: '8.1' - laravel: '9.0' - - php: '8.2' - laravel: '8.22' - - php: '8.2' - laravel: '9.0' - - php: '8.3' - laravel: '8.22' - - php: '8.3' - laravel: '9.0' - - php: '8.4' - laravel: '12.0' + laravel: '12.19.3' include: - - php: '8.0' - laravel: '9.39.0' + - php: '8.1' + laravel: '10.48.29' analysis: true coverage: 'xdebug' normalize: true @@ -69,9 +52,6 @@ jobs: if: matrix.validate == true run: composer validate --strict - - name: Install Laravel legacy factories support - if: matrix.laravel != '7.0' - run: composer require "laravel/legacy-factories:^1.1" --dev --no-interaction --no-update #- name: Install Laravel and Orchestra Testbench # run: composer require "illuminate/contracts:${{ matrix.laravel }}" --no-interaction --no-update @@ -94,14 +74,13 @@ jobs: run: composer install --prefer-dist --no-progress - name: Normalize composer file - if: matrix.normalize == true && matrix.php != '8.0' + if: matrix.normalize == true run: composer normalize --dry-run - name: Run test suite - run: vendor/bin/phpunit -v + run: vendor/bin/phpunit - name: Run static code analysis - if: matrix.analysis == true run: vendor/bin/phpstan --memory-limit=-1 - name: Upload coverage results diff --git a/.phpunit.cache/test-results b/.phpunit.cache/test-results new file mode 100644 index 00000000..8645e4b8 --- /dev/null +++ b/.phpunit.cache/test-results @@ -0,0 +1 @@ +{"version":1,"defects":[],"times":{"Osiset\\ShopifyApp\\Test\\Actions\\ActivatePlanTest::testRunRecurring":0.026,"Osiset\\ShopifyApp\\Test\\Actions\\ActivatePlanTest::testRunOnetime":0.005,"Osiset\\ShopifyApp\\Test\\Actions\\ActivateUsageChargeTest::testRun":0.004,"Osiset\\ShopifyApp\\Test\\Actions\\ActivateUsageChargeTest::testRunWithoutRecurringCharge":0.004,"Osiset\\ShopifyApp\\Test\\Actions\\ActivateUsageChargeTest::testRunWithLimitReached":0.004,"Osiset\\ShopifyApp\\Test\\Actions\\AfterAuthorizeTest::testRunDispatch":0.005,"Osiset\\ShopifyApp\\Test\\Actions\\AfterAuthorizeTest::testRunDispatchCustomConnection":0.003,"Osiset\\ShopifyApp\\Test\\Actions\\AfterAuthorizeTest::testRunInline":0.013,"Osiset\\ShopifyApp\\Test\\Actions\\AfterAuthorizeTest::testRunNoJobs":0.003,"Osiset\\ShopifyApp\\Test\\Actions\\AuthenticateShopTest::testShouldGoToLoginForInvalid":0.004,"Osiset\\ShopifyApp\\Test\\Actions\\AuthenticateShopTest::testShouldGoToAuthRedirectForInvalidHmac":0.005,"Osiset\\ShopifyApp\\Test\\Actions\\AuthenticateShopTest::testRuns":0.004,"Osiset\\ShopifyApp\\Test\\Actions\\AuthenticateShopTest::testManagedAppInstall":0.004,"Osiset\\ShopifyApp\\Test\\Actions\\CancelChargeTest::testCancel":0.003,"Osiset\\ShopifyApp\\Test\\Actions\\CancelChargeTest::testCancelOfNonRecurringNonOnetime":0.003,"Osiset\\ShopifyApp\\Test\\Actions\\CancelCurrentPlanTest::testCancelWithNoPlan":0.002,"Osiset\\ShopifyApp\\Test\\Actions\\CancelCurrentPlanTest::testCancelWithPlanButNoCharge":0.003,"Osiset\\ShopifyApp\\Test\\Actions\\CreateScriptsTest::testShouldNotCreateIfExists":0.003,"Osiset\\ShopifyApp\\Test\\Actions\\CreateScriptsTest::testShouldCreateOnlyNewOnesAndDeleteUnusedScripts":0.003,"Osiset\\ShopifyApp\\Test\\Actions\\CreateScriptsTest::testShouldCreate":0.003,"Osiset\\ShopifyApp\\Test\\Actions\\CreateWebhooksTest::testShouldNotCreateIfExists":0.003,"Osiset\\ShopifyApp\\Test\\Actions\\CreateWebhooksTest::testShouldCreate":0.003,"Osiset\\ShopifyApp\\Test\\Actions\\DeleteWebhooksTest::testShouldDelete":0.003,"Osiset\\ShopifyApp\\Test\\Actions\\DispatchScriptsTest::testRunDispatchOnNoScripts":0.022,"Osiset\\ShopifyApp\\Test\\Actions\\DispatchScriptsTest::testRunDispatch":0.003,"Osiset\\ShopifyApp\\Test\\Actions\\DispatchScriptsTest::testRunDispatchCustomConnection":0.003,"Osiset\\ShopifyApp\\Test\\Actions\\DispatchScriptsTest::testRunDispatchNow":0.005,"Osiset\\ShopifyApp\\Test\\Actions\\DispatchWebhooksTest::testRunDispatchOnNoScripts":0.002,"Osiset\\ShopifyApp\\Test\\Actions\\DispatchWebhooksTest::testRunDispatch":0.003,"Osiset\\ShopifyApp\\Test\\Actions\\DispatchWebhooksTest::testRunDispatchCustomConnection":0.004,"Osiset\\ShopifyApp\\Test\\Actions\\DispatchWebhooksTest::testRunDispatchNow":0.003,"Osiset\\ShopifyApp\\Test\\Actions\\GetPlanUrlTest::testRun30Days":0.003,"Osiset\\ShopifyApp\\Test\\Actions\\GetPlanUrlTest::testRunAnnual":0.003,"Osiset\\ShopifyApp\\Test\\Actions\\InstallShopTest::testNoShopShouldBeMade":0.003,"Osiset\\ShopifyApp\\Test\\Actions\\InstallShopTest::testWithoutCode":0.003,"Osiset\\ShopifyApp\\Test\\Actions\\InstallShopTest::testWithCode":0.004,"Osiset\\ShopifyApp\\Test\\Actions\\InstallShopTest::testWithCodeSoftDeletedShop":0.004,"Osiset\\ShopifyApp\\Test\\Actions\\InstallShopTest::testManagedAppInstall":0.005,"Osiset\\ShopifyApp\\Test\\Actions\\VerifyThemeSupportTest::testStoreWithUndefinedMainTheme":1.284,"Osiset\\ShopifyApp\\Test\\Actions\\VerifyThemeSupportTest::testStoreWithFullExtensionSupport":0.007,"Osiset\\ShopifyApp\\Test\\Actions\\VerifyThemeSupportTest::testStoreWithPartialExtensionSupport":0.003,"Osiset\\ShopifyApp\\Test\\Actions\\VerifyThemeSupportTest::testStoreWithoutExtensionSupport":0.002,"Osiset\\ShopifyApp\\Test\\Console\\AddVariablesCommandTest::testItShouldRun":0.008,"Osiset\\ShopifyApp\\Test\\Console\\AddVariablesCommandTest::testItShouldRunWithAlwaysNo":0.004,"Osiset\\ShopifyApp\\Test\\Console\\AddVariablesCommandTest::testItShouldRunWithForce":0.047,"Osiset\\ShopifyApp\\Test\\Console\\AddVariablesCommandTest::testItShouldRunWithoutForceAndNo":0.004,"Osiset\\ShopifyApp\\Test\\Console\\AddVariablesCommandTest::testItShouldRunWithoutForceAndYes":0.003,"Osiset\\ShopifyApp\\Test\\Console\\AddVariablesCommandTest::testItShouldRunWithMissingEnv":0.002,"Osiset\\ShopifyApp\\Test\\Console\\WebhookJobMakeCommandTest::testItShouldRun":0.004,"Osiset\\ShopifyApp\\Test\\Console\\WebhookJobMakeCommandTest::testShouldMakeUrlFromName":0.002,"Osiset\\ShopifyApp\\Test\\Directives\\SessionTokenTest::testDirective":0.003,"Osiset\\ShopifyApp\\Test\\Http\\Middleware\\AuthProxyTest::testRuns":0.007,"Osiset\\ShopifyApp\\Test\\Http\\Middleware\\AuthProxyTest::testDeniesForMissingShop":0.005,"Osiset\\ShopifyApp\\Test\\Http\\Middleware\\AuthProxyTest::testDoesNotRunForInvalidSignature":0.002,"Osiset\\ShopifyApp\\Test\\Http\\Middleware\\AuthProxyTest::testQueryStringArrayFormatParsedProperly":0.002,"Osiset\\ShopifyApp\\Test\\Http\\Middleware\\AuthWebhookTest::testDenysForMissingShopHeader":0.002,"Osiset\\ShopifyApp\\Test\\Http\\Middleware\\AuthWebhookTest::testDenysForMissingHmacHeader":0.002,"Osiset\\ShopifyApp\\Test\\Http\\Middleware\\AuthWebhookTest::testRuns":0.002,"Osiset\\ShopifyApp\\Test\\Http\\Middleware\\BillableTest::testEnabledBillingWithUnpaidShop":0.005,"Osiset\\ShopifyApp\\Test\\Http\\Middleware\\BillableTest::testEnabledBillingWithPaidShop":0.003,"Osiset\\ShopifyApp\\Test\\Http\\Middleware\\BillableTest::testEnabledBillingWithGrandfatheredShop":0.003,"Osiset\\ShopifyApp\\Test\\Http\\Middleware\\BillableTest::testEnabledBillingWithFreemiumShop":0.003,"Osiset\\ShopifyApp\\Test\\Http\\Middleware\\BillableTest::testDisabledBillingShouldPassOn":0.002,"Osiset\\ShopifyApp\\Test\\Http\\Middleware\\IframeProtectionTest::testIframeProtectionWithAuthorizedShop":0.004,"Osiset\\ShopifyApp\\Test\\Http\\Middleware\\IframeProtectionTest::testIframeProtectionWithUnauthorizedShop":0.002,"Osiset\\ShopifyApp\\Test\\Http\\Middleware\\IframeProtectionTest::testIframeProtectionWithExistingAncestorsInConfig":0.003,"Osiset\\ShopifyApp\\Test\\Http\\Middleware\\VerifyScopesTest::testMissingScopes":0.01,"Osiset\\ShopifyApp\\Test\\Http\\Middleware\\VerifyScopesTest::testMatchingScopes":0.003,"Osiset\\ShopifyApp\\Test\\Http\\Middleware\\VerifyScopesTest::testScopeApiFailure":0.009,"Osiset\\ShopifyApp\\Test\\Http\\Middleware\\VerifyShopifyTest::testHmacFail":0.003,"Osiset\\ShopifyApp\\Test\\Http\\Middleware\\VerifyShopifyTest::testSkipAuthenticateAndBillingRoutes":0.003,"Osiset\\ShopifyApp\\Test\\Http\\Middleware\\VerifyShopifyTest::testMissingToken":0.003,"Osiset\\ShopifyApp\\Test\\Http\\Middleware\\VerifyShopifyTest::testMissingTokenAjax":0.003,"Osiset\\ShopifyApp\\Test\\Http\\Middleware\\VerifyShopifyTest::testTokenProcessingAndLoginShop":0.006,"Osiset\\ShopifyApp\\Test\\Http\\Middleware\\VerifyShopifyTest::testTokenProcessingAndNotInstalledShop":0.003,"Osiset\\ShopifyApp\\Test\\Http\\Middleware\\VerifyShopifyTest::testTokenProcessingAndNotInstalledShopAjax":0.003,"Osiset\\ShopifyApp\\Test\\Http\\Middleware\\VerifyShopifyTest::testInvalidToken":0.003,"Osiset\\ShopifyApp\\Test\\Http\\Middleware\\VerifyShopifyTest::testInvalidTokenAjax":0.002,"Osiset\\ShopifyApp\\Test\\Http\\Middleware\\VerifyShopifyTest::testTokenProcessingAndMissMatchingShops":0.003,"Osiset\\ShopifyApp\\Test\\Http\\Middleware\\VerifyShopifyTest::testNotNativeAppBridgeWithTokenProcessingAndLoginShop":0.003,"Osiset\\ShopifyApp\\Test\\Http\\Middleware\\VerifyShopifyTest::testAccessingForbiddenMiddlewareRouteFromBrowserReceivedAccessError":0.006,"Osiset\\ShopifyApp\\Test\\Http\\Requests\\StoreUsageChargeTest::testFailsWithNoCode":0.009,"Osiset\\ShopifyApp\\Test\\Http\\Requests\\StoreUsageChargeTest::testFailsForInvalidSignature":0.002,"Osiset\\ShopifyApp\\Test\\Http\\Requests\\StoreUsageChargeTest::testPasses":0.002,"Osiset\\ShopifyApp\\Test\\Macros\\TokenRedirectTest::testTokenRedirect":0.002,"Osiset\\ShopifyApp\\Test\\Macros\\TokenRouteTest::testTokenRoute":0.002,"Osiset\\ShopifyApp\\Test\\Messaging\\Jobs\\AppUninstalledTest::testJobSoftDeletesShopAndCharges":0.006,"Osiset\\ShopifyApp\\Test\\Objects\\Transfers\\ChargeTest::testGetThrowsAnError":0.002,"Osiset\\ShopifyApp\\Test\\Objects\\Transfers\\ChargeTest::testSetThrowsAnError":0.002,"Osiset\\ShopifyApp\\Test\\Objects\\Transfers\\ChargeTest::testToArray":0.002,"Osiset\\ShopifyApp\\Test\\Objects\\Values\\MainThemeTest::testGetMainThemeId":0.002,"Osiset\\ShopifyApp\\Test\\Objects\\Values\\MainThemeTest::testGetMainThemeName":0.002,"Osiset\\ShopifyApp\\Test\\Objects\\Values\\MainThemeTest::testGetMainThemeRole":0.002,"Osiset\\ShopifyApp\\Test\\Objects\\Values\\SessionTokenTest::testShouldProcessForValidCheckoutExtensionToken":0.004,"Osiset\\ShopifyApp\\Test\\Objects\\Values\\SessionTokenTest::testShouldProcessForValidToken":0.002,"Osiset\\ShopifyApp\\Test\\Objects\\Values\\SessionTokenTest::testShouldProcessForExpiredTokenStillInLeewayPeriod":0.002,"Osiset\\ShopifyApp\\Test\\Objects\\Values\\SessionTokenTest::testShouldThrowExceptionForExpiredTokenOutOfLeewayPeriod":0.002,"Osiset\\ShopifyApp\\Test\\Objects\\Values\\SessionTokenTest::testShouldProcessForNotBeforeTokenStillInLeewayPeriod":0.002,"Osiset\\ShopifyApp\\Test\\Objects\\Values\\SessionTokenTest::testShouldThrowExceptionForNotBeforeTokenOutOfLeewayPeriod":0.002,"Osiset\\ShopifyApp\\Test\\Objects\\Values\\SessionTokenTest::testShouldProcessForIssuedAtTokenStillInLeewayPeriod":0.002,"Osiset\\ShopifyApp\\Test\\Objects\\Values\\SessionTokenTest::testShouldThrowExceptionForIssuedAtTokenOutOfLeewayPeriod":0.002,"Osiset\\ShopifyApp\\Test\\Objects\\Values\\SessionTokenTest::testShouldThrowExceptionForMalformedToken":0.002,"Osiset\\ShopifyApp\\Test\\Objects\\Values\\SessionTokenTest::testShouldThrowExceptionForInvalidToken":0.002,"Osiset\\ShopifyApp\\Test\\Objects\\Values\\SessionTokenTest::testShouldThrowExceptionForExpiredToken":0.002,"Osiset\\ShopifyApp\\Test\\Objects\\Values\\ShopDomainTest::testAddsMyshopifyDomainIfNotContainsPeriod":0.003,"Osiset\\ShopifyApp\\Test\\Objects\\Values\\ShopDomainTest::testDoesNotAddMyshopifyDomainIfContainsPeriod":0.003,"Osiset\\ShopifyApp\\Test\\Objects\\Values\\ShopDomainTest::testStripsTheProtocol":0.003,"Osiset\\ShopifyApp\\Test\\Objects\\Values\\ShopDomainTest::testDoesNotAcceptNonMyshopifyDomains":0.003,"Osiset\\ShopifyApp\\Test\\Objects\\Values\\ShopDomainTest::testDoesNotAcceptNonMyshopifyDomainsWithSinglePeriod":0.002,"Osiset\\ShopifyApp\\Test\\Services\\ApiHelperTest::testMake":0.002,"Osiset\\ShopifyApp\\Test\\Services\\ApiHelperTest::testSetAndGetApi":0.002,"Osiset\\ShopifyApp\\Test\\Services\\ApiHelperTest::testWithApi":0.004,"Osiset\\ShopifyApp\\Test\\Services\\ApiHelperTest::testBuildAuthUrl":0.002,"Osiset\\ShopifyApp\\Test\\Services\\ApiHelperTest::testGetScriptTags":0.003,"Osiset\\ShopifyApp\\Test\\Services\\ApiHelperTest::testCreateScriptTags":0.003,"Osiset\\ShopifyApp\\Test\\Services\\ApiHelperTest::testDeleteScriptTag":0.002,"Osiset\\ShopifyApp\\Test\\Services\\ApiHelperTest::testGetCharge":0.003,"Osiset\\ShopifyApp\\Test\\Services\\ApiHelperTest::testActivateCharge":0.003,"Osiset\\ShopifyApp\\Test\\Services\\ApiHelperTest::testCreateCharge":0.003,"Osiset\\ShopifyApp\\Test\\Services\\ApiHelperTest::testGetWebhooks":0.002,"Osiset\\ShopifyApp\\Test\\Services\\ApiHelperTest::testCreateWebhook":0.002,"Osiset\\ShopifyApp\\Test\\Services\\ApiHelperTest::testDeleteWebhook":0.003,"Osiset\\ShopifyApp\\Test\\Services\\ApiHelperTest::testCreateUsageCharge":0.002,"Osiset\\ShopifyApp\\Test\\Services\\ApiHelperTest::testErrors":0.003,"Osiset\\ShopifyApp\\Test\\Services\\ChargeHelperTest::testUseAndGetCharge":0.003,"Osiset\\ShopifyApp\\Test\\Services\\ChargeHelperTest::testRetrieveCharge":0.003,"Osiset\\ShopifyApp\\Test\\Services\\ChargeHelperTest::testTrial":0.003,"Osiset\\ShopifyApp\\Test\\Services\\ChargeHelperTest::testNonTrial":0.006,"Osiset\\ShopifyApp\\Test\\Services\\ChargeHelperTest::testTrialCancelled":0.004,"Osiset\\ShopifyApp\\Test\\Services\\ChargeHelperTest::testBeginEndPeriod":0.003,"Osiset\\ShopifyApp\\Test\\Services\\ChargeHelperTest::testChargeForPlan":0.004,"Osiset\\ShopifyApp\\Test\\Services\\ChargeHelperTest::testDetails":0.004,"Osiset\\ShopifyApp\\Test\\Services\\ChargeHelperTest::testDetails2":0.004,"Osiset\\ShopifyApp\\Test\\Services\\CookieHelperTest::testSameSiteCookie":0.004,"Osiset\\ShopifyApp\\Test\\Services\\CookieHelperTest::testSetCookiePolicy":0.002,"Osiset\\ShopifyApp\\Test\\Services\\ThemeHelperTest::testThemeIsReady":0.003,"Osiset\\ShopifyApp\\Test\\Services\\ThemeHelperTest::testThemeIsReadyFailure":0.003,"Osiset\\ShopifyApp\\Test\\Services\\ThemeHelperTest::testTemplateJsonFiles":0.003,"Osiset\\ShopifyApp\\Test\\Services\\ThemeHelperTest::testMainSections":0.003,"Osiset\\ShopifyApp\\Test\\Services\\ThemeHelperTest::testSectionsWithAppBlock":0.003,"Osiset\\ShopifyApp\\Test\\Storage\\Commands\\ChargeTest::testMake":0.003,"Osiset\\ShopifyApp\\Test\\Storage\\Commands\\ChargeTest::testDelete":0.003,"Osiset\\ShopifyApp\\Test\\Storage\\Commands\\ChargeTest::testMakeUsage":0.002,"Osiset\\ShopifyApp\\Test\\Storage\\Commands\\ChargeTest::testCancel":0.003,"Osiset\\ShopifyApp\\Test\\Storage\\Commands\\ShopTest::testMake":0.002,"Osiset\\ShopifyApp\\Test\\Storage\\Commands\\ShopTest::testSetToPlan":0.003,"Osiset\\ShopifyApp\\Test\\Storage\\Commands\\ShopTest::testSetAccessToken":0.003,"Osiset\\ShopifyApp\\Test\\Storage\\Commands\\ShopTest::testClean":0.003,"Osiset\\ShopifyApp\\Test\\Storage\\Commands\\ShopTest::testSoftDeleteAndRestore":0.003,"Osiset\\ShopifyApp\\Test\\Storage\\Commands\\ShopTest::testSetAsFreemium":0.003,"Osiset\\ShopifyApp\\Test\\Storage\\Commands\\ShopTest::testSetNamespace":0.003,"Osiset\\ShopifyApp\\Test\\Storage\\Models\\ChargeTest::testModel":0.006,"Osiset\\ShopifyApp\\Test\\Storage\\Models\\PlanTest::testModel":0.003,"Osiset\\ShopifyApp\\Test\\Storage\\Queries\\ChargeTest::testChargeGetById":0.003,"Osiset\\ShopifyApp\\Test\\Storage\\Queries\\ChargeTest::testChargeGetByChargeReference":0.003,"Osiset\\ShopifyApp\\Test\\Storage\\Queries\\ChargeTest::testPlangetByReferenceAndShopId":0.003,"Osiset\\ShopifyApp\\Test\\Storage\\Queries\\PlanTest::testPlanGetById":0.002,"Osiset\\ShopifyApp\\Test\\Storage\\Queries\\PlanTest::testPlanGetDefault":0.002,"Osiset\\ShopifyApp\\Test\\Storage\\Queries\\PlanTest::testPlanGetAll":0.002,"Osiset\\ShopifyApp\\Test\\Storage\\Queries\\ShopTest::testShopGetById":0.002,"Osiset\\ShopifyApp\\Test\\Storage\\Queries\\ShopTest::testShopGetByDomain":0.003,"Osiset\\ShopifyApp\\Test\\Storage\\Queries\\ShopTest::testShopGetAll":0.002,"Osiset\\ShopifyApp\\Test\\Traits\\ApiControllerTest::testApiWithoutToken":0.01,"Osiset\\ShopifyApp\\Test\\Traits\\ApiControllerTest::testApiWithToken":0.005,"Osiset\\ShopifyApp\\Test\\Traits\\ApiControllerTest::testApiGetSelf":0.003,"Osiset\\ShopifyApp\\Test\\Traits\\ApiControllerTest::testApiGetPlans":0.003,"Osiset\\ShopifyApp\\Test\\Traits\\AuthControllerTest::testAuthRedirectsToShopifyWhenNoCode":0.009,"Osiset\\ShopifyApp\\Test\\Traits\\AuthControllerTest::testAuthAcceptsShopWithCode":0.005,"Osiset\\ShopifyApp\\Test\\Traits\\AuthControllerTest::testAuthThrowExceptionForBadHmac":0.008,"Osiset\\ShopifyApp\\Test\\Traits\\AuthControllerTest::testAuthThrowExceptionForMissingShopAndAuthenticatedUser":0.003,"Osiset\\ShopifyApp\\Test\\Traits\\BillingControllerTest::testSendsShopToBillingScreen":0.006,"Osiset\\ShopifyApp\\Test\\Traits\\BillingControllerTest::testReactFrontendShopAcceptsBilling":0.005,"Osiset\\ShopifyApp\\Test\\Traits\\BillingControllerTest::testBladeFrontendShopAcceptsBilling":0.005,"Osiset\\ShopifyApp\\Test\\Traits\\BillingControllerTest::testUsageChargeSuccess":0.007,"Osiset\\ShopifyApp\\Test\\Traits\\BillingControllerTest::testReturnToSettingScreenNoPlan":0.004,"Osiset\\ShopifyApp\\Test\\Traits\\BillingControllerTest::testUsageChargeSuccessWithShopParam":0.005,"Osiset\\ShopifyApp\\Test\\Traits\\BillingControllerTest::testUsageChargeFailWithoutShopParam":0.004,"Osiset\\ShopifyApp\\Test\\Traits\\HomeControllerTest::testHomeRoute":0.005,"Osiset\\ShopifyApp\\Test\\Traits\\HomeControllerTest::testHomeRouteHostAdmin":0.008,"Osiset\\ShopifyApp\\Test\\Traits\\ShopAccessibleTest::testSuccess":0.004,"Osiset\\ShopifyApp\\Test\\Traits\\ShopModelTest::testModel":0.004,"Osiset\\ShopifyApp\\Test\\Traits\\ShopModelTest::testOfflineToken":0.003,"Osiset\\ShopifyApp\\Test\\Traits\\ShopModelTest::testNamespacingAndFreemium":0.003,"Osiset\\ShopifyApp\\Test\\Traits\\WebhookControllerTest::testSuccess":0.004,"Osiset\\ShopifyApp\\Test\\Traits\\WebhookControllerTest::testFailure":0.003,"Osiset\\ShopifyApp\\Test\\Traits\\WebhookControllerTest::testHandleWithCustomClassMapping":0.003,"Osiset\\ShopifyApp\\Test\\Traits\\WebhookControllerTest::testHandleDispatchesJobWithCustomConnection":0.003,"Osiset\\ShopifyApp\\Test\\UtilTest::testHmacCreator":0.002,"Osiset\\ShopifyApp\\Test\\UtilTest::testRegisterPackageRoutes":0.002,"Osiset\\ShopifyApp\\Test\\UtilTest::testRouteNames":0.002,"Osiset\\ShopifyApp\\Test\\UtilTest::testGetShopifyConfig":0.002,"Osiset\\ShopifyApp\\Test\\UtilTest::testGraphQLWebhookTopic":0.002,"Osiset\\ShopifyApp\\Test\\UtilTest::testUseNativeAppBridgeIsTrue":0.002,"Osiset\\ShopifyApp\\Test\\UtilTest::testUseNativeAppBridgeIsFalse":0.002,"Osiset\\ShopifyApp\\Test\\UtilTest::testHasAppLegacySupport":0.002}} \ No newline at end of file diff --git a/composer.json b/composer.json index bcfd78de..9718ffe1 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,7 @@ { "name": "kyon147/laravel-shopify", "description": "Shopify package for Laravel to aide in app development", + "license": "MIT", "keywords": [ "api", "callback-url", @@ -16,36 +17,52 @@ "shopify-app", "webhook" ], - "license": "MIT", "authors": [ { "name": "Luke (Kyon147)", "email": "support@appydesign.co.uk" } ], + "support": { + "issues": "https://github.com/Kyon147/laravel-shopify/issues", + "forum": "https://github.com/Kyon147/laravel-shopify/discussions", + "wiki": "https://github.com/Kyon147/laravel-shopify/wiki", + "source": "https://github.com/Kyon147/laravel-shopify" + }, "require": { - "php": "^8.0 || ^8.1 || ^8.2 || ^8.3 || ^8.4", + "php": ">=8.1", "ext-json": "*", "funeralzone/valueobjects": "^0.5", + "gnikyt/basic-shopify-api": "^11.0", "jenssegers/agent": "^2.6", - "laravel/framework": "^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0", - "gnikyt/basic-shopify-api": "^9.0 || ^10.0 || ^11.0" + "laravel/framework": "^10.0 || ^11.0 || ^12.0" }, "require-dev": { - "laravel/legacy-factories": "^v1.3.0", "ergebnis/composer-normalize": "^2.8", "friendsofphp/php-cs-fixer": "^3.0", + "laravel/legacy-factories": "^1.3.0", "mockery/mockery": "^1.0", - "orchestra/database": "~3.8 || ~4.0 || ~5.0 || ~6.0 || ~7.0 || ~8.0 || ~9.0", - "orchestra/testbench": "~3.8 || ~4.0 || ~5.0 || ~6.0 || ~7.0 || ~8.0 || ~9.0", - "phpstan/phpstan": "^0.12", - "phpunit/phpunit": "~8.0 || ^9.0 || ^10.0 || ^11.0" + "orchestra/testbench": "^8.0 || ^9.0", + "phpstan/phpstan": "^2.1", + "phpunit/phpunit": "^8.0 || ^9.0 || ^10.0 || ^11.0" + }, + "minimum-stability": "dev", + "prefer-stable": true, + "autoload": { + "psr-4": { + "Osiset\\ShopifyApp\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "Osiset\\ShopifyApp\\Test\\": "tests/" + } }, "config": { - "sort-packages": true, "allow-plugins": { "ergebnis/composer-normalize": true - } + }, + "sort-packages": true }, "extra": { "laravel": { @@ -54,28 +71,10 @@ ] } }, - "autoload": { - "psr-4": { - "Osiset\\ShopifyApp\\": "src/" - } - }, - "autoload-dev": { - "psr-4": { - "Osiset\\ShopifyApp\\Test\\": "tests/" - } - }, - "minimum-stability": "dev", - "prefer-stable": true, "scripts": { "lint": "vendor/bin/php-cs-fixer fix", "test": "vendor/bin/phpunit", "test-html-cov": "vendor/bin/phpunit --coverage-html ./build/html/", "test-no-cov": "vendor/bin/phpunit --no-coverage" - }, - "support": { - "issues": "https://github.com/Kyon147/laravel-shopify/issues", - "forum": "https://github.com/Kyon147/laravel-shopify/discussions", - "wiki": "https://github.com/Kyon147/laravel-shopify/wiki", - "source": "https://github.com/Kyon147/laravel-shopify" } } diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon new file mode 100644 index 00000000..a83d6975 --- /dev/null +++ b/phpstan-baseline.neon @@ -0,0 +1,19 @@ +parameters: + ignoreErrors: + - + message: '#^Deprecated in PHP 8\.4\: Parameter \#3 \$params \(array\) is implicitly nullable via default value null\.$#' + identifier: parameter.implicitlyNullable + count: 1 + path: tests/Stubs/Api.php + + - + message: '#^Deprecated in PHP 8\.4\: Parameter \#2 \$requestInstance \(Illuminate\\Http\\Request\) is implicitly nullable via default value null\.$#' + identifier: parameter.implicitlyNullable + count: 1 + path: tests/TestCase.php + + - + message: '#^Deprecated in PHP 8\.4\: Parameter \#3 \$cb \(Closure\) is implicitly nullable via default value null\.$#' + identifier: parameter.implicitlyNullable + count: 1 + path: tests/TestCase.php diff --git a/phpstan.neon b/phpstan.neon index 7539d708..834a0bb6 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,8 +1,12 @@ +includes: + - phpstan-baseline.neon + parameters: level: 1 paths: - src - tests + reportUnmatchedIgnoredErrors: false ignoreErrors: - '#Access to an undefined property Osiset\\ShopifyApp\\Storage\\Models\\.*::\$.*\.#' - '#Access to an undefined property Osiset\\ShopifyApp\\Test\\Stubs\\.*::\$.*\.#' diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 9fc87217..29467741 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,20 +1,29 @@ - - + + + tests + + + + + + + + + src/ @@ -26,20 +35,5 @@ src/Messaging/Events/ src/ShopifyAppProvider.php - - - - - - - - tests - - - - - - - - + diff --git a/src/Actions/FetchMainTheme.php b/src/Actions/FetchMainTheme.php new file mode 100644 index 00000000..9814ac21 --- /dev/null +++ b/src/Actions/FetchMainTheme.php @@ -0,0 +1,34 @@ +api()->graph('{ + themes(first: 1, roles: MAIN) { + nodes { + id + name + } + } + }'); + + if (blank(data_get($response['body']->toArray(), 'data.themes.userErrors'))) { + return data_get($response['body']->toArray(), 'data.themes.nodes.0', []); + } + + Log::error('Fetching main theme error: '.json_encode(data_get($response['body']->toArray(), 'data.themes.userErrors'))); + + return []; + } +} diff --git a/src/Actions/FetchThemeAssets.php b/src/Actions/FetchThemeAssets.php new file mode 100644 index 00000000..5d35d14d --- /dev/null +++ b/src/Actions/FetchThemeAssets.php @@ -0,0 +1,49 @@ + $filenames + */ + public function handle(ShopModel $shop, string $mainThemeId, array $filenames): array + { + $response = $shop->api()->graph('query ($id: ID!, $filenames: [String!]) { + theme(id: $id) { + id + name + role + files(filenames: $filenames) { + nodes { + filename + body { + ... on OnlineStoreThemeFileBodyText { + content + } + } + } + } + } + }', [ + 'id' => $mainThemeId, + 'filenames' => $filenames, + ]); + + if (blank(data_get($response['body']->toArray(), 'data.theme.userErrors'))) { + return array_map(fn (array $data) => [ + 'filename' => $data['filename'], + 'content' => $data['body']['content'] ?? '', + ], data_get($response['body']->toArray(), 'data.theme.files.nodes')); + } + + Log::error('Fetching settings data error: '.json_encode(data_get($response['body']->toArray(), 'data.theme.userErrors'))); + + return []; + } +} diff --git a/src/Actions/VerifyThemeSupport.php b/src/Actions/VerifyThemeSupport.php index d51b0ccf..161e4dd6 100644 --- a/src/Actions/VerifyThemeSupport.php +++ b/src/Actions/VerifyThemeSupport.php @@ -1,45 +1,144 @@ cacheInterval = (string) Str::of(Util::getShopifyConfig('theme_support.cache_interval')) + ->plural() + ->ucfirst() + ->start('add'); + + $this->cacheDuration = (int) Util::getShopifyConfig('theme_support.cache_duration'); } public function __invoke(ShopId $shopId): int { - $this->themeHelper->extractStoreMainTheme($shopId); + $shop = $this->shopQuery->getById($shopId); - if ($this->themeHelper->themeIsReady()) { - $templateJSONFiles = $this->themeHelper->templateJSONFiles(); - $templateMainSections = $this->themeHelper->mainSections($templateJSONFiles); - $sectionsWithAppBlock = $this->themeHelper->sectionsWithAppBlock($templateMainSections); + /** @var array{id: string, name: string} */ + $mainTheme = Cache::remember( + "mainTheme.{$shop->getId()->toNative()}", + now()->{$this->cacheInterval}($this->cacheDuration), + fn () => $this->fetchMainTheme->handle($shop) + ); - $hasTemplates = count($templateJSONFiles) > 0; - $allTemplatesHasRightType = count($templateJSONFiles) === count($sectionsWithAppBlock); - $templatesСountWithRightType = count($sectionsWithAppBlock); + if (isset($mainTheme['id'])) { + /** @var array */ + $assets = Cache::remember( + "assets.{$mainTheme['id']}.{$shop->getId()->toNative()}", + now()->{$this->cacheInterval}($this->cacheDuration), + fn () => $this->fetchThemeAssets->handle( + shop: $shop, + mainThemeId: $mainTheme['id'], + filenames: self::ASSET_FILE_NAMES + ) + ); + $templateMainSections = $this->mainSections( + shop: $shop, + mainTheme: $mainTheme, + assets: $assets + ); + $sectionsWithAppBlock = $this->sectionsWithAppBlock($templateMainSections); - switch (true) { - case $hasTemplates && $allTemplatesHasRightType: - return ThemeSupportLevel::FULL; + $hasTemplates = count($assets) > 0; + $allTemplatesHasRightType = count($assets) === count($sectionsWithAppBlock); + $hasTemplatesCountWithRightType = count($sectionsWithAppBlock) > 0; - case $templatesСountWithRightType: - return ThemeSupportLevel::PARTIAL; - - default: - return ThemeSupportLevel::UNSUPPORTED; - } + return match (true) { + $hasTemplates && $allTemplatesHasRightType => ThemeSupportLevel::FULL, + $hasTemplatesCountWithRightType => ThemeSupportLevel::PARTIAL, + default => ThemeSupportLevel::UNSUPPORTED + }; } return ThemeSupportLevel::UNSUPPORTED; } + + /** + * @param array{id: string} $mainTheme + * @param array{content: string} $assets + * + * @return array + */ + private function mainSections(ShopModel $shop, array $mainTheme, array $assets): array + { + $filenamesForMainSections = array_filter( + array_map(function ($asset) { + $content = $asset['content']; + + if (! $this->json_validate($content)) { + $content = preg_replace("#(/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/)|([\s\t]//.*)|(^//.*)#", '', $content); + } + + $assetContent = json_decode($content, true); + + + $mainAsset = array_filter($assetContent['sections'], function ($value, $key) { + return $key == self::MAIN_ROLE || str_starts_with($value['type'], self::MAIN_ROLE); + }, ARRAY_FILTER_USE_BOTH); + + if ($mainAsset) { + return 'sections/'.end($mainAsset)['type'].'.liquid'; + } + }, $assets) + ); + + return Cache::remember( + "mainSections.{$mainTheme['id']}.".sha1(implode('|', $filenamesForMainSections)), + now()->{$this->cacheInterval}($this->cacheDuration), + fn () => $this->fetchThemeAssets->handle( + shop: $shop, + mainThemeId: $mainTheme['id'], + filenames: [...$filenamesForMainSections] + ) + ); + } + + private function sectionsWithAppBlock(array $templateMainSections): array + { + return array_filter(array_map(function ($file) { + $acceptsAppBlock = false; + + preg_match('/\{\%-?\s+schema\s+-?\%\}([\s\S]*?)\{\%-?\s+endschema\s+-?\%\}/m', $file['content'], $matches); + $schema = json_decode($matches[1] ?? '{}', true); + + if ($schema && isset($schema['blocks'])) { + $acceptsAppBlock = in_array('@app', array_column($schema['blocks'], 'type')); + } + + return $acceptsAppBlock ? $file : null; + }, $templateMainSections)); + } + + + private function json_validate(string $string): bool + { + json_decode($string); + + return json_last_error() === JSON_ERROR_NONE; + } } diff --git a/src/Objects/Values/MainTheme.php b/src/Objects/Values/MainTheme.php deleted file mode 100644 index 6b467774..00000000 --- a/src/Objects/Values/MainTheme.php +++ /dev/null @@ -1,96 +0,0 @@ -id = $id; - $this->name = $name; - $this->role = $role; - } - - /** - * {@inheritDoc} - */ - public static function fromNative($native) - { - return new static( - NullableThemeId::fromNative(Arr::get($native, 'id')), - NullableThemeName::fromNative(Arr::get($native, 'name')), - NullableThemeRole::fromNative(Arr::get($native, 'role')) - ); - } - - /** - * Get theme id - * - * @return ThemeId - */ - public function getId() - { - return $this->id; - } - - /** - * Get theme name - * - * @return ThemeName - */ - public function getName() - { - return $this->name; - } - - /** - * Get theme role - * - * @return ThemeRole - */ - public function getRole() - { - return $this->role; - } -} diff --git a/src/Services/ThemeHelper.php b/src/Services/ThemeHelper.php deleted file mode 100644 index d0a5dbb3..00000000 --- a/src/Services/ThemeHelper.php +++ /dev/null @@ -1,245 +0,0 @@ -shopQuery = $shopQuery; - - $this->cacheInterval = (string) Str::of(Util::getShopifyConfig('theme_support.cache_interval')) - ->plural() - ->ucfirst() - ->start('add'); - - $this->cacheDuration = Util::getShopifyConfig('theme_support.cache_duration'); - } - - /** - * Determine if theme is set and ready for testing. - * - * @return bool - */ - public function themeIsReady(): bool - { - return (bool) $this->mainTheme->getId()->toNative(); - } - - /** - * Extract store's main theme. - * - * @param ShopId $shopId The shop ID. - * - * @return void - */ - public function extractStoreMainTheme(ShopId $shopId): void - { - $this->shop = $this->shopQuery->getById($shopId); - - $themesResponse = $this->shop->api()->rest('GET', '/admin/themes.json'); - if (!$themesResponse['errors'] && isset($themesResponse['body']['themes'])) { - $themes = $themesResponse['body']['themes']->toArray(); - $key = array_search(self::MAIN_ROLE, array_column($themes, self::THEME_FIELD)); - - $this->mainTheme = MainTheme::fromNative($themes[$key]); - $this->extractThemeAssets(); - } else { - $this->mainTheme = MainTheme::fromNative([]); - } - } - - /** - * Extract main theme's assets. - * - * @return void - */ - private function extractThemeAssets(): void - { - $this->assets = Cache::remember( - "assets_{$this->mainTheme->getId()->toNative()}", - now()->{$this->cacheInterval}($this->cacheDuration), - function () { - return $this->shop->api()->rest( - 'GET', - "/admin/themes/{$this->mainTheme->getId()->toNative()}/assets.json" - )['body']['assets']->toArray(); - } - ); - } - - /** - * Check if JSON template files exist for - * the template specified in `APP_BLOCK_TEMPLATES`. - * - * @return array - */ - public function templateJSONFiles(): array - { - return array_filter($this->assets, function ($asset) { - $match = false; - $blockTemplates = Util::getShopifyConfig('theme_support.templates'); - - foreach ($blockTemplates as $template) { - if ($asset['key'] == "templates/$template.json") { - $match = true; - - break; - } - } - - return $match; - }); - } - - /** - * Retrieve the body of JSON templates and find what section is set as `main`. - * - * @param array $templateJSONFiles The template files to filter through. - * - * @return array - */ - public function mainSections(array $templateJSONFiles): array - { - return array_filter(array_map(function ($file) { - $assetResponse = $this->fetchAsset($file); - $asset = $assetResponse['body']['asset']->toArray(); - $assetValue = json_decode($asset['value'], true); - - $mainAsset = array_filter($assetValue['sections'], function ($value, $key) { - return $key == self::MAIN_ROLE || str_starts_with($value['type'], self::MAIN_ROLE); - }, ARRAY_FILTER_USE_BOTH); - - if ($mainAsset) { - return array_merge(...array_filter($this->assets, function ($asset) use ($mainAsset) { - return $asset['key'] === 'sections/'.end($mainAsset)['type'].'.liquid'; - })); - } - }, $templateJSONFiles)); - } - - /** - * Request the contents of each section then check - * if it has a schema that contains a block of type '@app'. - * - * @param array $templateMainSections The template's main sections to filter through. - * - * @return array - */ - public function sectionsWithAppBlock(array $templateMainSections): array - { - return array_filter(array_map(function ($file) { - $acceptsAppBlock = false; - - $assetResponse = $this->fetchAsset($file); - $asset = $assetResponse['body']['asset']->toArray(); - - preg_match('/\{\%\s+schema\s+\%\}([\s\S]*?)\{\%\s+endschema\s+\%\}/m', $asset['value'], $matches); - if (!empty($matches) && isset($matches[1])) { - $schema = json_decode($matches[1], true); - if ($schema && isset($schema['blocks'])) { - $acceptsAppBlock = in_array('@app', array_column($schema['blocks'], 'type')); - } - } - - return $acceptsAppBlock ? $file : null; - }, $templateMainSections)); - } - - /** - * Fetch a theme's asset. - * - * @param array $file The theme file information to fetch or retrieve from cache. - * - * @return array - */ - private function fetchAsset(array $file): array - { - return Cache::remember( - "asset_{$this->mainTheme->getId()->toNative()}_{$file['key']}", - now()->{$this->cacheInterval}($this->cacheDuration), - function () use ($file) { - return $this->shop->api()->rest( - 'GET', - "/admin/themes/{$this->mainTheme->getId()->toNative()}/assets", - [ - 'asset' => ['key' => $file['key']], - ] - ); - } - ); - } -} diff --git a/src/ShopifyAppProvider.php b/src/ShopifyAppProvider.php index 0102d220..d94a68a7 100644 --- a/src/ShopifyAppProvider.php +++ b/src/ShopifyAppProvider.php @@ -42,7 +42,6 @@ use Osiset\ShopifyApp\Messaging\Jobs\WebhookInstaller; use Osiset\ShopifyApp\Services\ApiHelper; use Osiset\ShopifyApp\Services\ChargeHelper; -use Osiset\ShopifyApp\Services\ThemeHelper; use Osiset\ShopifyApp\Storage\Commands\Charge as ChargeCommand; use Osiset\ShopifyApp\Storage\Commands\Shop as ShopCommand; use Osiset\ShopifyApp\Storage\Observers\Shop as ShopObserver; @@ -189,13 +188,6 @@ public function register() ); }); - $this->app->bind(VerifyThemeSupportAction::class, function ($app) { - return new VerifyThemeSupportAction( - $app->make(IShopQuery::class), - $app->make(ThemeHelper::class) - ); - }); - $this->app->bind(ActivateUsageChargeAction::class, function ($app) { return new ActivateUsageChargeAction( $app->make(ChargeHelper::class), diff --git a/src/Util.php b/src/Util.php index dbe266f9..0f8ffe7c 100644 --- a/src/Util.php +++ b/src/Util.php @@ -60,12 +60,12 @@ public static function createHmac(array $opts, string $secret): Hmac * Array parameters such as `name[]=value1&name[]=value2` becomes `['name[]' => ['value1', 'value2']] in Shopify. * See: https://github.com/rack/rack/blob/f9ad97fd69a6b3616d0a99e6bedcfb9de2f81f6c/lib/rack/query_parser.rb#L36 * - * @param string $queryString The query string. + * @param string|null $queryString The query string. * @param string|null $delimiter The delimiter. * * @return mixed */ - public static function parseQueryString(string $queryString, ?string $delimiter = null): array + public static function parseQueryString(?string $queryString = null, ?string $delimiter = null): array { $commonSeparator = [';' => '/[;]\s*/', ';,' => '/[;,]\s*/', '&' => '/[&]\s*/']; $defaultSeparator = '/[&;]\s*/'; diff --git a/src/resources/database/factories/ChargeFactory.php b/src/resources/database/factories/ChargeFactory.php index a53e6cf6..812184df 100644 --- a/src/resources/database/factories/ChargeFactory.php +++ b/src/resources/database/factories/ChargeFactory.php @@ -12,7 +12,7 @@ $factory->define($chargeModel, function (Faker $faker) { return [ 'charge_id' => $faker->randomNumber(8), - 'name' => $faker->word, + 'name' => $faker->word(), 'price' => $faker->randomFloat(), 'status' => ChargeStatus::ACCEPTED()->toNative(), ]; diff --git a/src/resources/database/factories/PlanFactory.php b/src/resources/database/factories/PlanFactory.php index 062f952a..c2c37370 100644 --- a/src/resources/database/factories/PlanFactory.php +++ b/src/resources/database/factories/PlanFactory.php @@ -10,7 +10,7 @@ $factory->define($planModel, function (Faker $faker) { return [ - 'name' => $faker->word, + 'name' => $faker->word(), 'price' => $faker->randomFloat(), ]; }); @@ -18,7 +18,7 @@ $factory->state($planModel, 'usage', function ($faker) { return [ 'capped_amount' => $faker->randomFloat(), - 'terms' => $faker->sentence, + 'terms' => $faker->sentence(), ]; }); diff --git a/src/resources/database/factories/ShopFactory.php b/src/resources/database/factories/ShopFactory.php index d5af07e8..93cb75c5 100644 --- a/src/resources/database/factories/ShopFactory.php +++ b/src/resources/database/factories/ShopFactory.php @@ -7,9 +7,9 @@ $factory->define($model, function (Faker $faker) { return [ - 'name' => "{$faker->domainWord}.myshopify.com", - 'password' => str_replace('-', '', $faker->uuid), - 'email' => $faker->email, + 'name' => "{$faker->domainWord()}.myshopify.com", + 'password' => str_replace('-', '', $faker->uuid()), + 'email' => $faker->email(), ]; }); diff --git a/src/resources/database/migrations/2022_06_09_104819_add_theme_support_level_to_users_table.php b/src/resources/database/migrations/2022_06_09_104819_add_theme_support_level_to_users_table.php index 48cdfe0c..a2096eef 100644 --- a/src/resources/database/migrations/2022_06_09_104819_add_theme_support_level_to_users_table.php +++ b/src/resources/database/migrations/2022_06_09_104819_add_theme_support_level_to_users_table.php @@ -15,7 +15,7 @@ class AddThemeSupportLevelToUsersTable extends Migration public function up() { Schema::table(Util::getShopsTable(), function (Blueprint $table) { - $table->integer('theme_support_level')->nullable(); + $table->integer('theme_support_level')->nullable()->after('plan_id'); }); } diff --git a/tests/Actions/VerifyThemeSupportTest.php b/tests/Actions/VerifyThemeSupportTest.php index 8d84d4c4..d8b7e889 100644 --- a/tests/Actions/VerifyThemeSupportTest.php +++ b/tests/Actions/VerifyThemeSupportTest.php @@ -3,27 +3,21 @@ namespace Osiset\ShopifyApp\Test\Actions; use Osiset\ShopifyApp\Actions\VerifyThemeSupport; -use Osiset\ShopifyApp\Contracts\Queries\Shop as IShopQuery; use Osiset\ShopifyApp\Objects\Enums\ThemeSupportLevel; -use Osiset\ShopifyApp\Objects\Values\ShopId; -use Osiset\ShopifyApp\Services\ThemeHelper; +use Osiset\ShopifyApp\Test\Stubs\Api as ApiStub; use Osiset\ShopifyApp\Test\TestCase; class VerifyThemeSupportTest extends TestCase { - public function setUp(): void - { - parent::setUp(); - } - public function testStoreWithUndefinedMainTheme(): void { + $this->fakeGraphqlApi(['empty_theme']); $shop = factory($this->model)->create(); $action = $this->app->make(VerifyThemeSupport::class); $result = call_user_func( $action, - ShopId::fromNative($shop->id) + $shop->getId() ); $this->assertNotNull($result); @@ -32,13 +26,13 @@ public function testStoreWithUndefinedMainTheme(): void public function testStoreWithFullExtensionSupport(): void { + $this->fakeGraphqlApi(['main_theme', 'theme_with_one_asset', 'theme_with_one_section']); $shop = factory($this->model)->create(); - $themeHelperStub = $this->createThemeHelperStub(ThemeSupportLevel::FULL); - $action = new VerifyThemeSupport($this->app->make(IShopQuery::class), $themeHelperStub); + $action = $this->app->make(VerifyThemeSupport::class); $result = call_user_func( $action, - ShopId::fromNative($shop->id) + $shop->getId() ); $this->assertNotNull($result); @@ -48,12 +42,12 @@ public function testStoreWithFullExtensionSupport(): void public function testStoreWithPartialExtensionSupport(): void { $shop = factory($this->model)->create(); - $themeHelperStub = $this->createThemeHelperStub(ThemeSupportLevel::PARTIAL); - $action = new VerifyThemeSupport($this->app->make(IShopQuery::class), $themeHelperStub); + $this->fakeGraphqlApi(['main_theme', 'theme_with_three_assets', 'theme_with_one_section']); + $action = $this->app->make(VerifyThemeSupport::class); $result = call_user_func( $action, - ShopId::fromNative($shop->id) + $shop->getId() ); $this->assertNotNull($result); @@ -63,12 +57,12 @@ public function testStoreWithPartialExtensionSupport(): void public function testStoreWithoutExtensionSupport(): void { $shop = factory($this->model)->create(); - $themeHelperStub = $this->createThemeHelperStub(ThemeSupportLevel::UNSUPPORTED); - $action = new VerifyThemeSupport($this->app->make(IShopQuery::class), $themeHelperStub); + $this->fakeGraphqlApi(['main_theme', 'theme_with_empty_assets', 'theme_with_empty_sections']); + $action = $this->app->make(VerifyThemeSupport::class); $result = call_user_func( $action, - ShopId::fromNative($shop->id) + $shop->getId() ); $this->assertNotNull($result); @@ -77,30 +71,11 @@ public function testStoreWithoutExtensionSupport(): void /** * Create ThemeHelper stub - * - * @param int $level - * - * @return ThemeHelper */ - protected function createThemeHelperStub(int $level): ThemeHelper + protected function fakeGraphqlApi(array $responses): void { - $themeHelperStub = $this->createStub(ThemeHelper::class); - - $defaultThemeResponse = []; - - if ($level === ThemeSupportLevel::FULL) { - $defaultThemeResponse = [0, 1, 2, 3]; - } - - $themeHelperStub->method('themeIsReady')->willReturn(true); - $themeHelperStub->method('templateJSONFiles')->willReturn($defaultThemeResponse); - $themeHelperStub->method('mainSections')->willReturn($defaultThemeResponse); - $themeHelperStub->method('sectionsWithAppBlock')->willReturn( - $level === ThemeSupportLevel::PARTIAL - ? array_merge($defaultThemeResponse, [random_int(1, 99)]) - : $defaultThemeResponse - ); + $this->setApiStub(); - return $themeHelperStub; + ApiStub::stubResponses($responses); } } diff --git a/tests/Http/Middleware/VerifyShopifyTest.php b/tests/Http/Middleware/VerifyShopifyTest.php index 6f45ebb0..1b1df313 100644 --- a/tests/Http/Middleware/VerifyShopifyTest.php +++ b/tests/Http/Middleware/VerifyShopifyTest.php @@ -164,6 +164,7 @@ public function testTokenProcessingAndNotInstalledShop(): void [ 'token' => $this->buildToken(), 'shop' => 'non-existent.myshopify.com', + 'host' => 'loremipsum', ], // Request Params null, diff --git a/tests/Objects/Values/MainThemeTest.php b/tests/Objects/Values/MainThemeTest.php deleted file mode 100644 index 13fb10e9..00000000 --- a/tests/Objects/Values/MainThemeTest.php +++ /dev/null @@ -1,58 +0,0 @@ -mainTheme = MainTheme::fromNative([ - 'id' => self::THEME_ID, - 'name' => self::THEME_NAME, - 'role' => self::THEME_ROLE, - ]); - } - - public function testGetMainThemeId() - { - $themeId = $this->mainTheme->getId(); - - $this->assertInstanceOf(NullableThemeId::class, $themeId); - $this->assertEquals($themeId->toNative(), self::THEME_ID); - } - - public function testGetMainThemeName() - { - $themeName = $this->mainTheme->getName(); - - $this->assertInstanceOf(NullableThemeName::class, $themeName); - $this->assertEquals($themeName->toNative(), self::THEME_NAME); - } - - public function testGetMainThemeRole() - { - $themeRole = $this->mainTheme->getRole(); - - $this->assertInstanceOf(NullableThemeRole::class, $themeRole); - $this->assertEquals($themeRole->toNative(), self::THEME_ROLE); - } -} diff --git a/tests/Services/ThemeHelperTest.php b/tests/Services/ThemeHelperTest.php deleted file mode 100644 index 618ab9d1..00000000 --- a/tests/Services/ThemeHelperTest.php +++ /dev/null @@ -1,158 +0,0 @@ -helper = $this->app->make(ThemeHelper::class); - $this->shop = factory($this->model)->create(); - } - - public function testThemeIsReady(): void - { - // Response stubbing - $this->setApiStub(); - ApiStub::stubResponses(['get_themes', 'get_theme_assets']); - - // Run extraction - $this->helper->extractStoreMainTheme($this->shop->getId()); - - $this->assertTrue($this->helper->themeIsReady()); - } - - public function testThemeIsReadyFailure(): void - { - // Response stubbing - $this->setApiStub(); - ApiStub::stubResponses(['empty_with_error']); - - // Run extraction - $this->helper->extractStoreMainTheme($this->shop->getId()); - - $this->assertFalse($this->helper->themeIsReady()); - } - - public function testTemplateJsonFiles(): void - { - // Response stubbing - $this->setApiStub(); - ApiStub::stubResponses(['get_themes', 'get_theme_assets']); - - // Run extraction - $this->helper->extractStoreMainTheme($this->shop->getId()); - - // No config defined, so the match should be empty - $this->assertEmpty($this->helper->templateJSONFiles()); - - // Define config, retest - $this->app['config']->set( - 'shopify-app.theme_support.templates', - [ - 'shop', // Matches fixture data for `templates/shop.json` - ] - ); - $this->assertNotEmpty($this->helper->templateJSONFiles()); - } - - public function testMainSections(): void - { - // Response stubbing - $this->setApiStub(); - ApiStub::stubResponses(['get_themes', 'get_theme_assets', 'get_theme_asset_template_json']); - - // Define config - $this->app['config']->set( - 'shopify-app.theme_support.templates', - [ - 'shop', // Matches fixture data for `templates/shop.json` - ] - ); - - // Run extraction - $this->helper->extractStoreMainTheme($this->shop->getId()); - - // Get the main sections... - // `templates/shop.json`'s content in `get_theme_asset_template_json` fixture - // has a main of `product` which converts to `sections/product.liquid` which also - // exists in `get_theme_assets` fixture - $jsonFiles = $this->helper->templateJSONFiles(); - $mainSections = $this->helper->mainSections($jsonFiles); - - $this->assertNotEmpty($mainSections); - } - - public function testSectionsWithAppBlock(): void - { - // Response stubbing - $this->setApiStub(); - ApiStub::stubResponses([ - 'get_themes', - 'get_theme_assets', - 'get_theme_asset_template_json', - 'get_theme_asset_product_section', - ]); - - // Define config - $this->app['config']->set( - 'shopify-app.theme_support.templates', - [ - 'shop', // Matches fixture data for `templates/shop.json` - ] - ); - - // Run extraction - $this->helper->extractStoreMainTheme($this->shop->getId()); - $jsonFiles = $this->helper->templateJSONFiles(); - $mainSections = $this->helper->mainSections($jsonFiles); - $sectionsWithApp = $this->helper->sectionsWithAppBlock($mainSections); - - $this->assertNotEmpty($sectionsWithApp); - } - - public function testSectionsWithAppBlockHandlesMissingSchema(): void - { - // Response stubbing - $this->setApiStub(); - ApiStub::stubResponses([ - 'get_themes', - 'get_theme_assets', - 'get_theme_asset_no_schema', - ]); - - // Define config to include a template - $this->app['config']->set( - 'shopify-app.theme_support.templates', - [ - 'asset', - ] - ); - - // Run extraction - $this->helper->extractStoreMainTheme($this->shop->getId()); - $jsonFiles = $this->helper->templateJSONFiles(); - $mainSections = $this->helper->mainSections($jsonFiles); - $sectionsWithApp = $this->helper->sectionsWithAppBlock($mainSections); - - // Assert no sections are returned and no error occurs - $this->assertEmpty($sectionsWithApp); - } -} diff --git a/tests/Stubs/Kernel.php b/tests/Stubs/Kernel.php index ccdd1328..d3eaed34 100644 --- a/tests/Stubs/Kernel.php +++ b/tests/Stubs/Kernel.php @@ -7,7 +7,6 @@ use Illuminate\Auth\Middleware\Authorize; use Illuminate\Routing\Middleware\SubstituteBindings; use Illuminate\Routing\Middleware\ThrottleRequests; -use Orchestra\Testbench\Http\Middleware\RedirectIfAuthenticated; use Osiset\ShopifyApp\Http\Middleware\AuthProxy; use Osiset\ShopifyApp\Http\Middleware\AuthWebhook; use Osiset\ShopifyApp\Http\Middleware\Billable; @@ -27,7 +26,6 @@ class Kernel extends \Orchestra\Testbench\Foundation\Http\Kernel 'auth.basic' => AuthenticateWithBasicAuth::class, 'bindings' => SubstituteBindings::class, 'can' => Authorize::class, - 'guest' => RedirectIfAuthenticated::class, 'throttle' => ThrottleRequests::class, // Added for testing diff --git a/tests/TestCase.php b/tests/TestCase.php index 39f8e39b..2d2a1b13 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -10,7 +10,6 @@ use Illuminate\Support\Carbon; use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\Request as FacadesRequest; -use Orchestra\Database\ConsoleServiceProvider; use Orchestra\Testbench\TestCase as OrchestraTestCase; use Osiset\ShopifyApp\Contracts\ShopModel; use Osiset\ShopifyApp\Objects\Values\Hmac; @@ -78,10 +77,8 @@ public function setUp(): void protected function getPackageProviders($app): array { - // ConsoleServiceProvider required to make migrations work return [ ShopifyAppProvider::class, - ConsoleServiceProvider::class, ]; } diff --git a/tests/fixtures/empty_theme.json b/tests/fixtures/empty_theme.json new file mode 100644 index 00000000..6299fa3c --- /dev/null +++ b/tests/fixtures/empty_theme.json @@ -0,0 +1,7 @@ +{ + "data": { + "themes": { + "nodes": [] + } + } +} diff --git a/tests/fixtures/empty_with_error.json b/tests/fixtures/empty_with_error.json deleted file mode 100644 index f186dba4..00000000 --- a/tests/fixtures/empty_with_error.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "errors": true -} diff --git a/tests/fixtures/get_theme_asset_product_section.json b/tests/fixtures/get_theme_asset_product_section.json deleted file mode 100644 index 830a45bd..00000000 --- a/tests/fixtures/get_theme_asset_product_section.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "asset": { - "key": "sections/product.liquid", - "public_url": null, - "value": "
\r\n {%- for block in section.blocks -%}\r\n {% render block %}\r\n {%- endfor -%}\r\n<\/div>\r\n\r\n{% schema %}\r\n{\r\n \"name\": \"t:sections.apps.name\",\r\n \"tag\": \"section\",\r\n \"class\": \"section\",\r\n \"settings\": [\r\n {\r\n \"type\": \"checkbox\",\r\n \"id\": \"include_margins\",\r\n \"default\": true,\r\n \"label\": \"t:sections.apps.settings.include_margins.label\"\r\n }\r\n ],\r\n \"blocks\": [\r\n {\r\n \"type\": \"@app\"\r\n }\r\n ],\r\n \"presets\": [\r\n {\r\n \"name\": \"t:sections.apps.presets.name\"\r\n }\r\n ]\r\n}\r\n{% endschema %}", - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "content_type": "application/x-liquid", - "size": 1068, - "checksum": null, - "theme_id": 828155753 - } - } diff --git a/tests/fixtures/get_theme_asset_template_json.json b/tests/fixtures/get_theme_asset_template_json.json deleted file mode 100644 index 025710ed..00000000 --- a/tests/fixtures/get_theme_asset_template_json.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "asset": { - "key": "templates/shop.json", - "public_url": null, - "value": "{\"name\":\"Shop template\",\"wrapper\":\"div#div_id.div_class[attribute-one=value]\",\"sections\":{\"main\":{\"type\":\"product\"}},\"order\":[\"main\"]}", - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "content_type": "application/json", - "size": 1068, - "checksum": null, - "theme_id": 828155753 - } -} diff --git a/tests/fixtures/get_theme_assets.json b/tests/fixtures/get_theme_assets.json deleted file mode 100644 index 067d0a9a..00000000 --- a/tests/fixtures/get_theme_assets.json +++ /dev/null @@ -1,284 +0,0 @@ -{ - "assets": [ - { - "key": "layout/theme.liquid", - "public_url": null, - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "content_type": "application/x-liquid", - "size": 3252, - "checksum": null, - "theme_id": 828155753 - }, - { - "key": "assets/sidebar-devider.gif", - "public_url": "https://cdn.shopify.com/s/files/1/0005/4838/0009/t/1/assets/sidebar-devider.gif?v=1278963110", - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "content_type": "image/gif", - "size": 1016, - "checksum": null, - "theme_id": 828155753 - }, - { - "key": "assets/bg-body-pink.gif", - "public_url": "https://cdn.shopify.com/s/files/1/0005/4838/0009/t/1/assets/bg-body-pink.gif?v=1278963110", - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "content_type": "image/gif", - "size": 1562, - "checksum": null, - "theme_id": 828155753 - }, - { - "key": "assets/bg-content.gif", - "public_url": "https://cdn.shopify.com/s/files/1/0005/4838/0009/t/1/assets/bg-content.gif?v=1278963110", - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "content_type": "image/gif", - "size": 134, - "checksum": null, - "theme_id": 828155753 - }, - { - "key": "sections/header_section.liquid", - "public_url": null, - "created_at": "2017-04-28T10:30:00-04:00", - "updated_at": "2017-04-28T10:30:00-04:00", - "content_type": "application/x-liquid", - "size": 998, - "checksum": null, - "theme_id": 828155753 - }, - { - "key": "assets/shop.css.liquid", - "public_url": "https://cdn.shopify.com/s/files/1/0005/4838/0009/t/1/assets/shop.css.liquid?v=1278963110", - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "content_type": "application/x-liquid", - "size": 14675, - "checksum": null, - "theme_id": 828155753 - }, - { - "key": "assets/shop.js", - "public_url": "https://cdn.shopify.com/s/files/1/0005/4838/0009/t/1/assets/shop.js?v=1278963110", - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "content_type": "application/javascript", - "size": 348, - "checksum": null, - "theme_id": 828155753 - }, - { - "key": "assets/bg-main.gif", - "public_url": "https://cdn.shopify.com/s/files/1/0005/4838/0009/t/1/assets/bg-main.gif?v=1278963110", - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "content_type": "image/gif", - "size": 297, - "checksum": null, - "theme_id": 828155753 - }, - { - "key": "sections/content_section.liquid", - "public_url": null, - "created_at": "2016-02-11T14:31:50-05:00", - "updated_at": "2016-02-11T14:31:50-05:00", - "content_type": "application/x-liquid", - "size": 997, - "checksum": null, - "theme_id": 828155753 - }, - { - "key": "templates/page.liquid", - "public_url": null, - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "content_type": "application/x-liquid", - "size": 147, - "checksum": null, - "theme_id": 828155753 - }, - { - "key": "assets/bg-body-green.gif", - "public_url": "https://cdn.shopify.com/s/files/1/0005/4838/0009/t/1/assets/bg-body-green.gif?v=1278963110", - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "content_type": "image/gif", - "size": 1542, - "checksum": null, - "theme_id": 828155753 - }, - { - "key": "assets/shop.css", - "public_url": "https://cdn.shopify.com/s/files/1/0005/4838/0009/t/1/assets/shop.css?v=1278963110", - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "content_type": "text/css", - "size": 14058, - "checksum": null, - "theme_id": 828155753 - }, - { - "key": "config/settings_schema.json", - "public_url": null, - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "content_type": "application/json", - "size": 4570, - "checksum": null, - "theme_id": 828155753 - }, - { - "key": "sections/product.liquid", - "public_url": null, - "created_at": "2016-02-14T16:31:41-05:00", - "updated_at": "2016-02-14T16:31:41-05:00", - "content_type": "application/x-liquid", - "size": 2440, - "checksum": null, - "theme_id": 828155753 - }, - { - "key": "templates/blog.liquid", - "public_url": null, - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "content_type": "application/x-liquid", - "size": 786, - "checksum": null, - "theme_id": 828155753 - }, - { - "key": "templates/article.liquid", - "public_url": null, - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "content_type": "application/x-liquid", - "size": 2486, - "checksum": null, - "theme_id": 828155753 - }, - { - "key": "templates/product.liquid", - "public_url": null, - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "content_type": "application/x-liquid", - "size": 2796, - "checksum": null, - "theme_id": 828155753 - }, - { - "key": "sections/footer_section.liquid", - "public_url": null, - "created_at": "2017-04-28T10:30:00-04:00", - "updated_at": "2017-04-28T10:30:00-04:00", - "content_type": "application/x-liquid", - "size": 999, - "checksum": null, - "theme_id": 828155753 - }, - { - "key": "assets/bg-footer.gif", - "public_url": "https://cdn.shopify.com/s/files/1/0005/4838/0009/t/1/assets/bg-footer.gif?v=1278963110", - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "content_type": "image/gif", - "size": 1434, - "checksum": null, - "theme_id": 828155753 - }, - { - "key": "assets/bg-sidebar.gif", - "public_url": "https://cdn.shopify.com/s/files/1/0005/4838/0009/t/1/assets/bg-sidebar.gif?v=1278963110", - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "content_type": "image/gif", - "size": 124, - "checksum": null, - "theme_id": 828155753 - }, - { - "key": "assets/bg-body-orange.gif", - "public_url": "https://cdn.shopify.com/s/files/1/0005/4838/0009/t/1/assets/bg-body-orange.gif?v=1278963110", - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "content_type": "image/gif", - "size": 1548, - "checksum": null, - "theme_id": 828155753 - }, - { - "key": "templates/collection.liquid", - "public_url": null, - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "content_type": "application/x-liquid", - "size": 946, - "checksum": null, - "theme_id": 828155753 - }, - { - "key": "assets/sidebar-menu.jpg", - "public_url": "https://cdn.shopify.com/s/files/1/0005/4838/0009/t/1/assets/sidebar-menu.jpg?v=1278963110", - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "content_type": "image/jpeg", - "size": 1609, - "checksum": null, - "theme_id": 828155753 - }, - { - "key": "templates/cart.liquid", - "public_url": null, - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "content_type": "application/x-liquid", - "size": 2047, - "checksum": null, - "theme_id": 828155753 - }, - { - "key": "config/settings_data.json", - "public_url": null, - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "content_type": "application/json", - "size": 4570, - "checksum": null, - "theme_id": 828155753 - }, - { - "key": "templates/index.liquid", - "public_url": null, - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "content_type": "application/x-liquid", - "size": 1068, - "checksum": null, - "theme_id": 828155753 - }, - { - "key": "templates/shop.json", - "public_url": null, - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "content_type": "application/json", - "size": 1068, - "checksum": null, - "theme_id": 828155753 - }, - { - "key": "assets/bg-body.gif", - "public_url": "https://cdn.shopify.com/s/files/1/0005/4838/0009/t/1/assets/bg-body.gif?v=1278963110", - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "content_type": "image/gif", - "size": 1571, - "checksum": null, - "theme_id": 828155753 - } - ] -} diff --git a/tests/fixtures/get_themes.json b/tests/fixtures/get_themes.json deleted file mode 100644 index 453c7211..00000000 --- a/tests/fixtures/get_themes.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "themes": [ - { - "id": 828155753, - "name": "Comfort", - "created_at": "2022-07-02T01:51:59-04:00", - "updated_at": "2022-07-02T01:51:59-04:00", - "role": "main", - "theme_store_id": null, - "previewable": true, - "processing": false, - "admin_graphql_api_id": "gid://shopify/Theme/828155753" - }, - { - "id": 976877075, - "name": "Preview of Parallax", - "created_at": "2022-07-02T01:51:59-04:00", - "updated_at": "2022-07-02T01:51:59-04:00", - "role": "demo", - "theme_store_id": 688, - "previewable": true, - "processing": false, - "admin_graphql_api_id": "gid://shopify/Theme/976877075" - }, - { - "id": 752253240, - "name": "Sandbox", - "created_at": "2022-07-02T01:51:59-04:00", - "updated_at": "2022-07-02T01:51:59-04:00", - "role": "unpublished", - "theme_store_id": null, - "previewable": true, - "processing": false, - "admin_graphql_api_id": "gid://shopify/Theme/752253240" - } - ] -} diff --git a/tests/fixtures/main_theme.json b/tests/fixtures/main_theme.json new file mode 100644 index 00000000..38a258ad --- /dev/null +++ b/tests/fixtures/main_theme.json @@ -0,0 +1,12 @@ +{ + "data": { + "themes": { + "nodes": [ + { + "id": "gid:\/\/shopify\/OnlineStoreTheme\/123456789", + "name": "Dawn" + } + ] + } + } +} diff --git a/tests/fixtures/theme_sections.json b/tests/fixtures/theme_sections.json new file mode 100644 index 00000000..24d4e1f6 --- /dev/null +++ b/tests/fixtures/theme_sections.json @@ -0,0 +1,16 @@ +{ + "data": { + "theme": { + "files": { + "nodes": [ + { + "filename": "sections\/main-product.liquid", + "body": { + "content": "\n {{ 'section-main-product.css' | asset_url | stylesheet_tag }}\n {{ 'component-accordion.css' | asset_url | stylesheet_tag }}\n {{ 'component-price.css' | asset_url | stylesheet_tag }}\n {{ 'component-slider.css' | asset_url | stylesheet_tag }}\n {{ 'component-rating.css' | asset_url | stylesheet_tag }}\n {{ 'component-deferred-media.css' | asset_url | stylesheet_tag }}\n\n {% unless product.has_only_default_variant %}\n {{ 'component-product-variant-picker.css' | asset_url | stylesheet_tag }}\n {{ 'component-swatch-input.css' | asset_url | stylesheet_tag }}\n {{ 'component-swatch.css' | asset_url | stylesheet_tag }}\n {% endunless %}\n {%- if product.quantity_price_breaks_configured? -%}\n {{ 'component-volume-pricing.css' | asset_url | stylesheet_tag }}\n {%- endif -%}\n\n {%- style -%}\n .section-{{ section.id }}-padding {\n padding-top: {{ section.settings.padding_top | times: 0.75 | round: 0 }}px;\n padding-bottom: {{ section.settings.padding_bottom | times: 0.75 | round: 0 }}px;\n }\n\n @media screen and (min-width: 750px) {\n .section-{{ section.id }}-padding {\n padding-top: {{ section.settings.padding_top }}px;\n padding-bottom: {{ section.settings.padding_bottom }}px;\n }\n }\n {%- endstyle -%}\n\n