From 8d94ab750b06ec1a3d5f05f15f6cc227fc038b61 Mon Sep 17 00:00:00 2001 From: Artur Tagisow Date: Mon, 18 Jul 2022 10:41:35 +0200 Subject: [PATCH 01/89] ci: simplify getting middleware url --- .../workflows/deploy-vue-storefront-cloud.yml | 30 +++++-------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/.github/workflows/deploy-vue-storefront-cloud.yml b/.github/workflows/deploy-vue-storefront-cloud.yml index e9c4d5c55..c778e1a7d 100644 --- a/.github/workflows/deploy-vue-storefront-cloud.yml +++ b/.github/workflows/deploy-vue-storefront-cloud.yml @@ -13,9 +13,10 @@ jobs: outputs: environment-name: ${{ steps.determine-environment.outputs.name }} environment-code: ${{ steps.determine-environment.outputs.code }} + environment-middleware-url: ${{ steps.determine-environment.outputs.middleware-url}} deployment_id: ${{ steps.deployment.outputs.deployment_id }} steps: - - name: Determine environment name + - name: Determine environment-specific variables id: determine-environment shell: bash run: | @@ -24,18 +25,22 @@ jobs: if [ $REF = 'refs/heads/main' ]; then ENVNAME='production' ENVCODE='demo-magento2' + MIDDLEWARE_URL='https://demo-magento2.europe-west1.gcp.vuestorefront.cloud/api/' elif [ $REF = 'refs/heads/develop' ]; then ENVNAME='dev' ENVCODE='demo-magento2-dev' + MIDDLEWARE_URL='https://demo-magento2-dev.europe-west1.gcp.storefrontcloud.io/api/' elif [[ $REF = refs/heads/release* ]]; then ENVNAME='canary' ENVCODE='demo-magento2-canary' + MIDDLEWARE_URL='https://demo-magento2-canary.europe-west1.gcp.storefrontcloud.io/api/' elif [ $REF = 'refs/heads/enterprise' ]; then ENVNAME='enterprise' ENVCODE='demo-magento2-enterprise' + MIDDLEWARE_URL='https://demo-magento2-enterprise.europe-west1.gcp.storefrontcloud.io/api/' else echo 'unrecognized branch name' @@ -44,6 +49,7 @@ jobs: echo ::set-output name=name::$ENVNAME echo ::set-output name=code::$ENVCODE + echo ::set-output name=middleware-url::$MIDDLEWARE_URL - name: Create GitHub deployment id: deployment @@ -56,26 +62,6 @@ jobs: needs: create-deployment runs-on: ubuntu-latest steps: - - name: Set env VSF_MIDDLEWARE_URL - run: | - REF=${{ github.ref }} - - if [ $REF = 'refs/heads/main' ]; then - echo "VSF_MIDDLEWARE_URL=https://demo-magento2.europe-west1.gcp.vuestorefront.cloud/api/" >> $GITHUB_ENV - - elif [ $REF = 'refs/heads/develop' ]; then - echo "VSF_MIDDLEWARE_URL=https://demo-magento2-dev.europe-west1.gcp.storefrontcloud.io/api/" >> $GITHUB_ENV - - elif [[ $REF = refs/heads/release* ]]; then - echo "VSF_MIDDLEWARE_URL=https://demo-magento2-canary.europe-west1.gcp.storefrontcloud.io/api/" >> $GITHUB_ENV - - elif [ $REF = 'refs/heads/enterprise' ]; then - echo "VSF_MIDDLEWARE_URL=https://demo-magento2-enterprise.europe-west1.gcp.storefrontcloud.io/api/" >> $GITHUB_ENV - - else - echo "https://demo-magento2-dev.europe-west1.gcp.storefrontcloud.io/api/" >> $GITHUB_ENV - exit 1 - fi - name: Checkout code uses: actions/checkout@v1 @@ -102,7 +88,7 @@ jobs: NPM_REGISTRY: https://registrynpm.storefrontcloud.io VSF_STORE_URL: '' - VSF_MIDDLEWARE_URL: ${{ env.VSF_MIDDLEWARE_URL }} + VSF_MIDDLEWARE_URL: ${{ needs.create-deployment.outputs.environment-middleware-url }} VSF_MAGENTO_BASE_URL: https://magento2-instance.vuestorefront.io/ VSF_MAGENTO_GRAPHQL_URL: https://magento2-instance.vuestorefront.io/graphql From 4b85cc2d86b98b7b05243ac114ead42892faadc5 Mon Sep 17 00:00:00 2001 From: Marcin Kwiatkowski Date: Fri, 15 Jul 2022 15:32:58 +0200 Subject: [PATCH 02/89] fix: fixed checkout issues --- packages/theme/modules/checkout/pages/Checkout/Billing.vue | 2 +- packages/theme/modules/checkout/pages/Checkout/ThankYou.vue | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/theme/modules/checkout/pages/Checkout/Billing.vue b/packages/theme/modules/checkout/pages/Checkout/Billing.vue index 69a6acd53..a1369dc56 100644 --- a/packages/theme/modules/checkout/pages/Checkout/Billing.vue +++ b/packages/theme/modules/checkout/pages/Checkout/Billing.vue @@ -55,7 +55,7 @@ class="form" >

@@ -103,7 +103,7 @@ export default defineComponent({ const route = useRoute(); const companyDetails = ref({ - name: 'Divante Headquarter', + name: 'Vue Storefront Headquarter', street: 'St. Dmowskiego 17, 53-534', city: 'Wroclaw, Poland', email: 'demo@vuestorefront.io', From e232fe4f13a518aed143c7e726d572e56f291603 Mon Sep 17 00:00:00 2001 From: Beniamin Sinca Date: Fri, 15 Jul 2022 11:17:40 +0100 Subject: [PATCH 03/89] Fix bug when media_gallery array is empty In `getGallery` rather check the length of an array to get an accurate bool value than simple the array which will always return true. --- .../theme/modules/catalog/product/getters/productGetters.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/theme/modules/catalog/product/getters/productGetters.ts b/packages/theme/modules/catalog/product/getters/productGetters.ts index 524255fee..209f52e94 100644 --- a/packages/theme/modules/catalog/product/getters/productGetters.ts +++ b/packages/theme/modules/catalog/product/getters/productGetters.ts @@ -92,11 +92,11 @@ export const getPrice = (product: ProductInterface): Price => { export const getGallery = (product: Product, maxGallerySize = 4): MediaGalleryItem[] => { const images = []; - if (!product?.media_gallery && !product?.configurable_product_options_selection?.media_gallery) { + if (!product?.media_gallery.length && !product?.configurable_product_options_selection?.media_gallery.length) { return images; } - const selectedGallery = product.configurable_product_options_selection?.media_gallery + const selectedGallery = product.configurable_product_options_selection?.media_gallery.length ? product.configurable_product_options_selection.media_gallery : product.media_gallery; From aa23604fb4cfe0d50674f3e15cdc2693b7a7af39 Mon Sep 17 00:00:00 2001 From: Bartosz Herba Date: Fri, 15 Jul 2022 16:07:11 +0200 Subject: [PATCH 04/89] fix: store modal invalid action handler name --- packages/theme/components/StoreSwitcher/StoresModal.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/theme/components/StoreSwitcher/StoresModal.vue b/packages/theme/components/StoreSwitcher/StoresModal.vue index 525c2a75c..691dd862b 100644 --- a/packages/theme/components/StoreSwitcher/StoresModal.vue +++ b/packages/theme/components/StoreSwitcher/StoresModal.vue @@ -41,7 +41,7 @@ {{ $t('Cancel') }} From ba1c4d28da39769a8a1994cf8fa3a1e5c417e724 Mon Sep 17 00:00:00 2001 From: Marcin Kwiatkowski Date: Tue, 19 Jul 2022 17:48:33 +0200 Subject: [PATCH 05/89] build: removed getBaseUrl function from proxyUtils --- .../theme/helpers/integrationPlugin/_proxyUtils.ts | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/packages/theme/helpers/integrationPlugin/_proxyUtils.ts b/packages/theme/helpers/integrationPlugin/_proxyUtils.ts index 7e147b4d0..54e970f0b 100644 --- a/packages/theme/helpers/integrationPlugin/_proxyUtils.ts +++ b/packages/theme/helpers/integrationPlugin/_proxyUtils.ts @@ -1,4 +1,3 @@ -import { IncomingMessage } from 'node:http'; import { Context as NuxtContext } from '@nuxt/types'; import { merge } from 'lodash-es'; @@ -10,17 +9,6 @@ interface CreateProxiedApiParams { tag: string; } -export const getBaseUrl = (req: IncomingMessage, basePath: string | undefined = '/'): string => { - if (!req) return `${basePath}api/`; - const { headers } = req; - // eslint-disable-next-line global-require, unicorn/prefer-module - const isHttps = require('is-https')(req); - const scheme = isHttps ? 'https' : 'http'; - const host = headers['x-forwarded-host'] || headers.host; - - return `${scheme}://${host}${basePath}api/`; -}; - export const createProxiedApi = ({ givenApi, client, tag }: CreateProxiedApiParams) => new Proxy(givenApi, { get: (target, prop, receiver) => { const functionName = String(prop); @@ -41,7 +29,6 @@ export const getIntegrationConfig = (context: NuxtContext, configuration: any) = const cookie = getCookies(context); const initialConfig = merge({ axios: { - baseURL: getBaseUrl(context?.req, context?.base), headers: { ...(cookie ? { cookie } : {}), }, From e807662f167a28c551d43d81bcd0d967ebba9bcf Mon Sep 17 00:00:00 2001 From: GitHub actions Date: Thu, 14 Jul 2022 10:49:03 +0000 Subject: [PATCH 06/89] chore: release 1.0.0 --- internals/eslint-import/package.json | 2 +- internals/eslint-jest/package.json | 2 +- internals/eslint-typescript/package.json | 2 +- internals/eslint-vue/package.json | 2 +- internals/eslint/package.json | 2 +- packages/api-client/package.json | 2 +- packages/composables/package.json | 4 ++-- packages/load-tests/package.json | 2 +- packages/theme/package.json | 4 ++-- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/internals/eslint-import/package.json b/internals/eslint-import/package.json index 9ddecee01..168493894 100644 --- a/internals/eslint-import/package.json +++ b/internals/eslint-import/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/eslint-config-import", - "version": "1.0.0-rc.10", + "version": "1.0.0", "author": "Heitor Ramon Ribeiro ", "license": "MIT", "scripts": { diff --git a/internals/eslint-jest/package.json b/internals/eslint-jest/package.json index 315690f2b..16cdc9441 100644 --- a/internals/eslint-jest/package.json +++ b/internals/eslint-jest/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/eslint-config-jest", - "version": "1.0.0-rc.10", + "version": "1.0.0", "author": "Heitor Ramon Ribeiro ", "license": "MIT", "scripts": { diff --git a/internals/eslint-typescript/package.json b/internals/eslint-typescript/package.json index 7a85e108c..5ebdfc6c2 100644 --- a/internals/eslint-typescript/package.json +++ b/internals/eslint-typescript/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/eslint-config-typescript", - "version": "1.0.0-rc.10", + "version": "1.0.0", "author": "Heitor Ramon Ribeiro ", "license": "MIT", "scripts": { diff --git a/internals/eslint-vue/package.json b/internals/eslint-vue/package.json index 282e2461b..f0d8c7cfa 100644 --- a/internals/eslint-vue/package.json +++ b/internals/eslint-vue/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/eslint-config-vue", - "version": "1.0.0-rc.10", + "version": "1.0.0", "author": "Heitor Ramon Ribeiro ", "license": "MIT", "scripts": { diff --git a/internals/eslint/package.json b/internals/eslint/package.json index 327efbc5a..0c0256a19 100644 --- a/internals/eslint/package.json +++ b/internals/eslint/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/eslint-config-base", - "version": "1.0.0-rc.10", + "version": "1.0.0", "author": "Heitor Ramon Ribeiro ", "license": "MIT", "scripts": { diff --git a/packages/api-client/package.json b/packages/api-client/package.json index a861c06a2..ef197d4a6 100644 --- a/packages/api-client/package.json +++ b/packages/api-client/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/magento-api", - "version": "1.0.0-rc.10", + "version": "1.0.0", "sideEffects": false, "homepage": "https://github.com/vuestorefront/magento2", "bugs": { diff --git a/packages/composables/package.json b/packages/composables/package.json index 76c6a8d42..322b7e5f6 100644 --- a/packages/composables/package.json +++ b/packages/composables/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/magento", - "version": "1.0.0-rc.10", + "version": "1.0.0", "license": "MIT", "homepage": "https://github.com/vuestorefront/magento2", "bugs": { @@ -29,7 +29,7 @@ }, "dependencies": { "@vue-storefront/core": "~2.5.6", - "@vue-storefront/magento-api": "^1.0.0-rc.10", + "@vue-storefront/magento-api": "^1.0.0", "@vue/composition-api": "^1.4.1", "cookie-universal": "^2.1.5", "vue": "^2.6.14", diff --git a/packages/load-tests/package.json b/packages/load-tests/package.json index 63d5a94ba..aa8b7738f 100644 --- a/packages/load-tests/package.json +++ b/packages/load-tests/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/magento-load-tests", - "version": "1.0.0-rc.10", + "version": "1.0.0", "description": "Load tests for Magento 2 - VSF integration", "main": "index.js", "repository": "https://github.com/vuestorefront/magento2", diff --git a/packages/theme/package.json b/packages/theme/package.json index 18927de8e..42f7cf336 100644 --- a/packages/theme/package.json +++ b/packages/theme/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/magento-theme", - "version": "1.0.0-rc.10", + "version": "1.0.0", "private": true, "license": "MIT", "homepage": "https://github.com/vuestorefront/magento2", @@ -38,7 +38,7 @@ "@pinia/nuxt": "^0.1.9", "@storefront-ui/vue": "^0.13.3", "@vue-storefront/cache": "~2.7.1", - "@vue-storefront/magento-api": "^1.0.0-rc.10", + "@vue-storefront/magento-api": "^1.0.0", "@vue-storefront/middleware": "~2.7.1", "@vue-storefront/nuxt": "~2.7.1", "@vue-storefront/redis-cache": "^1.0.1", From 6d3ae26f9494eb20a0aadc9406fbfcad937d7ea2 Mon Sep 17 00:00:00 2001 From: Artur Tagisow Date: Mon, 18 Jul 2022 14:52:40 +0200 Subject: [PATCH 07/89] fix: don't inclue query params in urlPathToFind this commit was made because if you went to a category and changed to the 2nd page, the currently active category's name would not appear after hard refreshing the page this was happening because activeCategory used route.value.fullPath, which includes the query params. So after the regex pipeline from urlPathToFind, the value passed to findActiveCategory() was "men?page=2" (expected query-param free "men") it was possible to fix this by adding another regex to the pipeline but it's cleaner to just use route.value.path as that's the intention of the implementation M2-1035 --- .../modules/catalog/category/helpers/useTraverseCategory.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/theme/modules/catalog/category/helpers/useTraverseCategory.ts b/packages/theme/modules/catalog/category/helpers/useTraverseCategory.ts index d10799158..cf1c75865 100644 --- a/packages/theme/modules/catalog/category/helpers/useTraverseCategory.ts +++ b/packages/theme/modules/catalog/category/helpers/useTraverseCategory.ts @@ -18,7 +18,7 @@ export function useTraverseCategory() { const loadCategoryTree = () => categoryStore.load(); const activeCategory = computed(() => { // on localhost the default store is localhost:3000/default/ but in a multi-store Magento instance this can change - const urlPathToFind = route.value.fullPath + const urlPathToFind = route.value.path .replace(context.app.localePath('/c'), '') .replace(/^\//, '') .replace('.html', ''); From f74f7f483ed66a3f6b22df66af15ed499a303c8e Mon Sep 17 00:00:00 2001 From: Artur Tagisow Date: Mon, 18 Jul 2022 15:04:14 +0200 Subject: [PATCH 08/89] fix: show pagination arrows after category refresh before this commit pagination arrows on the category page would be hidden if you hard refreshed the page the culprit was the on-interaction prop on the LazyHydrate component M2-1034 --- packages/theme/modules/catalog/pages/category.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/theme/modules/catalog/pages/category.vue b/packages/theme/modules/catalog/pages/category.vue index 604f0f8b9..1602260bd 100644 --- a/packages/theme/modules/catalog/pages/category.vue +++ b/packages/theme/modules/catalog/pages/category.vue @@ -63,7 +63,7 @@ v-if="!$fetchState.pending" class="products__display-opt" > - + {{ $t('Show') }} - + Date: Mon, 18 Jul 2022 14:00:38 +0200 Subject: [PATCH 09/89] fix: images in product gallery are overlayed with main image - M2-1036 - added display:block for sf-image-loaded fixes the issue in the Safari browser --- .../catalog/product/components/product-types/styles.scss | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/theme/modules/catalog/product/components/product-types/styles.scss b/packages/theme/modules/catalog/product/components/product-types/styles.scss index 93258a5cd..f20fd78ee 100644 --- a/packages/theme/modules/catalog/product/components/product-types/styles.scss +++ b/packages/theme/modules/catalog/product/components/product-types/styles.scss @@ -161,6 +161,12 @@ } } +::v-deep .sf-gallery__thumbs { + .sf-image-loaded { + display: block; + } +} + @keyframes moveicon { 0% { transform: translate3d(0, 0, 0) rotate(90deg) scale(1, -1); From 8ee9ed55889160747be9fd650a7f2f1ca023dddd Mon Sep 17 00:00:00 2001 From: Artur Tagisow Date: Tue, 19 Jul 2022 10:20:38 +0200 Subject: [PATCH 10/89] test: fix tests on release branch --- .../category/helpers/__tests__/useTraverseCategory.spec.ts | 2 +- packages/theme/tests/unit/mocks/useRoute.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/theme/modules/catalog/category/helpers/__tests__/useTraverseCategory.spec.ts b/packages/theme/modules/catalog/category/helpers/__tests__/useTraverseCategory.spec.ts index d27317be9..ea9699f9a 100644 --- a/packages/theme/modules/catalog/category/helpers/__tests__/useTraverseCategory.spec.ts +++ b/packages/theme/modules/catalog/category/helpers/__tests__/useTraverseCategory.spec.ts @@ -19,7 +19,7 @@ jest.mock('@nuxtjs/composition-api', () => { return { ...originalModule, useContext: jest.fn(() => ({ app: { localePath: (suffix: unknown) => `/default${suffix}` } })), - useRoute: jest.fn(() => ({ value: { fullPath: '/default/c/what-is-new.html' } })), + useRoute: jest.fn(() => ({ value: { path: '/default/c/what-is-new.html' } })), }; }); diff --git a/packages/theme/tests/unit/mocks/useRoute.ts b/packages/theme/tests/unit/mocks/useRoute.ts index 0d26bba3a..0200fb334 100644 --- a/packages/theme/tests/unit/mocks/useRoute.ts +++ b/packages/theme/tests/unit/mocks/useRoute.ts @@ -1,5 +1,6 @@ export const useRouteMock = (extend = {}) => ({ value: { + path: '/default/c/gear.html', fullPath: '/default/c/gear.html', }, ...extend, From ebd9ae17558b72ab8b3cee782d0ffa402b6a3b14 Mon Sep 17 00:00:00 2001 From: Matt Maribojoc Date: Mon, 18 Jul 2022 08:27:27 -0400 Subject: [PATCH 11/89] docs: add vsf theme --- docs/.vuepress/config.js | 65 ++++------ docs/.vuepress/theme/index.js | 3 - docs/.vuepress/theme/layouts/Layout.vue | 162 ------------------------ docs/package.json | 3 +- docs/yarn.lock | 10 ++ 5 files changed, 36 insertions(+), 207 deletions(-) delete mode 100644 docs/.vuepress/theme/index.js delete mode 100644 docs/.vuepress/theme/layouts/Layout.vue diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index dde7c0a95..f253a89e3 100755 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -7,19 +7,25 @@ module.exports = { head: [ ['link', { rel: 'icon', href: '/favicon.png' }], // Google Tag Manager - ['script', {}, [` + [ + 'script', + {}, + [ + ` (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','${GTM_TAG}'); - `]], + `, + ], + ], ], /** * Ref:https://v1.vuepress.vuejs.org/config/#configurewebpack */ - configureWebpack: (config) => { + configureWebpack: (config) => { // Add support for webp images config.module.rules.push({ test: /\.(webp)(\?.*)?$/, @@ -28,52 +34,29 @@ module.exports = { loader: 'url-loader', options: { limit: 10000, - name: 'assets/img/[name].[hash:8].[ext]' - } - } - ] + name: 'assets/img/[name].[hash:8].[ext]', + }, + }, + ], }); // Fix image loading. Ref: https://github.com/vuejs/vue-loader/issues/1612#issuecomment-559366730 config.module.rules = config.module.rules.map((rule) => { - rule.use = rule.use && rule.use.map((useRule) => { - if (useRule.loader === 'url-loader') { - useRule.options.esModule = false; - } + rule.use = + rule.use && + rule.use.map((useRule) => { + if (useRule.loader === 'url-loader') { + useRule.options.esModule = false; + } - return useRule; - }); + return useRule; + }); return rule; }); }, - /** - * Ref:https://v1.vuepress.vuejs.org/plugin/ - */ - plugins: [ - '@vuepress/plugin-back-to-top', - [ - '@vuepress/plugin-medium-zoom', - { - // This selector excludes images from the "Integrations" page - selector: 'main :not(.tile-image) > img', - }, - ], - '@vuepress/active-header-links', - '@vuepress/search', - ], - - /** - * Ref: https://v1.vuepress.vuejs.org/config/#markdown - */ - markdown: { - extendMarkdown: md => { - md.use(require('markdown-it-video'), { - youtube: { width: 740, height: 416.25 }, // 16:9 ratio, where 740px is the width of the page content - }); - } - }, + theme: 'vsf-docs', themeConfig: { GTM_TAG, @@ -120,8 +103,8 @@ module.exports = { ['/getting-started/configuration', 'Configuration'], ['/getting-started/layouts-and-routing', 'Layouts and Routing'], ['/getting-started/theme', 'Theme'], - ['/getting-started/internationalization', 'Internationalization'] - ] + ['/getting-started/internationalization', 'Internationalization'], + ], }, { title: 'Composition', diff --git a/docs/.vuepress/theme/index.js b/docs/.vuepress/theme/index.js deleted file mode 100644 index cc636ec82..000000000 --- a/docs/.vuepress/theme/index.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - extend: '@vuepress/theme-default' -}; diff --git a/docs/.vuepress/theme/layouts/Layout.vue b/docs/.vuepress/theme/layouts/Layout.vue deleted file mode 100644 index ef47d49f3..000000000 --- a/docs/.vuepress/theme/layouts/Layout.vue +++ /dev/null @@ -1,162 +0,0 @@ - - - diff --git a/docs/package.json b/docs/package.json index 776ac02e6..9f3519043 100755 --- a/docs/package.json +++ b/docs/package.json @@ -28,6 +28,7 @@ }, "dependencies": { "sass-loader": "^8.0.2", - "vue-multiselect": "^2.1.6" + "vue-multiselect": "^2.1.6", + "vuepress-theme-vsf-docs": "^1.0.13" } } diff --git a/docs/yarn.lock b/docs/yarn.lock index 23a06de7c..2b144ec85 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -8336,6 +8336,16 @@ vuepress-plugin-smooth-scroll@^0.0.3: dependencies: smoothscroll-polyfill "^0.4.3" +vuepress-theme-vsf-docs@^1.0.13: + version "1.0.13" + resolved "https://registry.yarnpkg.com/vuepress-theme-vsf-docs/-/vuepress-theme-vsf-docs-1.0.13.tgz#949aa0adb1aa9de98774c19a4887e64994838aec" + integrity sha512-vvjA88XVu+a/DjyChzF4karIztDCqcmLbsfgyFPGGAIAmOx28g11xVx1Wg5nXzl89hDbSWyLzKtLoSP7g/JZyQ== + dependencies: + "@vuepress/plugin-active-header-links" "1.9.7" + "@vuepress/plugin-nprogress" "1.9.7" + "@vuepress/plugin-search" "1.9.7" + vuepress-plugin-container "^2.0.2" + vuepress@^1.9.7: version "1.9.7" resolved "https://registry.yarnpkg.com/vuepress/-/vuepress-1.9.7.tgz#2cd6709a2228f5cef588115aaeabf820ab9ed7cc" From e8b5b321d3df56badfa072c307848de40a9f4231 Mon Sep 17 00:00:00 2001 From: Matt Maribojoc Date: Mon, 18 Jul 2022 09:05:14 -0400 Subject: [PATCH 12/89] docs: update installation --- docs/.vuepress/config.js | 15 +++++++------ docs/getting-started/introduction.md | 28 ++++++++++++------------- docs/guide/environments.md | 21 ------------------- docs/index.md | 20 +++++++++++++++++- docs/installation-setup/installation.md | 2 -- 5 files changed, 39 insertions(+), 47 deletions(-) delete mode 100644 docs/guide/environments.md diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index f253a89e3..d7efe31dd 100755 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -76,18 +76,17 @@ module.exports = { ], sidebar: [ { - title: 'Essentials', + title: '', collapsable: false, children: [ ['/', 'Introduction'], - ['/guide/environments', 'Demo environments'], ['/guide/supported-features', 'Supported features'], ['/guide/about', 'About'], ], }, { title: 'Installation & Setup', - collapsable: false, + collapsable: true, children: [ ['/installation-setup/installation', 'Installation'], ['/installation-setup/configure-magento', 'Configuring Magento'], @@ -96,7 +95,7 @@ module.exports = { }, { title: 'Getting started', - collapsable: false, + collapsable: true, children: [ ['/getting-started/introduction', 'Introduction'], ['/getting-started/project-structure', 'Project structure'], @@ -108,7 +107,7 @@ module.exports = { }, { title: 'Composition', - collapsable: false, + collapsable: true, children: [ ['/composition/composables', 'Composables'], ['/composition/list-of-composables', 'List of composables'], @@ -116,7 +115,7 @@ module.exports = { }, { title: 'Modules', - collapsable: false, + collapsable: true, sidebarDepth: 2, children: [ { @@ -131,7 +130,7 @@ module.exports = { }, { title: 'Guides', - collapsable: false, + collapsable: true, children: [ ['/guide/global-state-management', 'Global state management'], ['/guide/image-optimization', 'Image optimization'], @@ -142,7 +141,7 @@ module.exports = { }, { title: 'Performance', - collapsable: false, + collapsable: true, children: [ ['/guide/graphql-get', 'Varnish & GET for GraphQL Queries'], ['/guide/ssr', 'Server Side Rendering Cache'], diff --git a/docs/getting-started/introduction.md b/docs/getting-started/introduction.md index 55386a17e..bad4cc914 100644 --- a/docs/getting-started/introduction.md +++ b/docs/getting-started/introduction.md @@ -2,17 +2,19 @@ Without a proper understanding of the framework you're using, you might spend weeks or even months doing something that someone else has already done. That's why before we can dive deep into the project itself, we need to understand what powers it all under the hood. -@[youtube](MCN1rRwuIGs) + ## It's all Nuxt.js We didn't want to reinvent the wheel and introduce yet another framework that solves the same issues as its predecessors, which took them years to mature. That's why... - - -Vue Storefront is essentially a [Nuxt.js](https://nuxtjs.org/) project with some plugins and modules preinstalled, as well as a ready-to-use e-commerce theme. Nuxt.js handles most of the front-end work and [Server Side Rendering](https://nuxtjs.org/docs/concepts/server-side-rendering/), while Vue Storefront adds the e-commerce specific bits and integrations to various platforms. - - +> Vue Storefront is essentially a [Nuxt.js](https://nuxtjs.org/) project with some plugins and modules preinstalled, as well as a ready-to-use e-commerce theme. Nuxt.js handles most of the front-end work and [Server Side Rendering](https://nuxtjs.org/docs/concepts/server-side-rendering/), while Vue Storefront adds the e-commerce specific bits and integrations to various platforms. Some of the plugins and modules that come with the fresh installation were created by the Nuxt.js community, and others come from our core team specifically for Vue Storefront projects. @@ -26,17 +28,13 @@ You might be wondering why we choose Nuxt.js as our foundation. After all, it wa When you start using any new framework, you expect it to: -* have **plugins that solve common issues**, such as analytics, SEO, internationalization, etc., -* be **versatile and flexible** enough to allow extending it and creating custom integrations, -* have **active and diverse community**, which answers questions, writes articles, and promotes the framework. +- have **plugins that solve common issues**, such as analytics, SEO, internationalization, etc., +- be **versatile and flexible** enough to allow extending it and creating custom integrations, +- have **active and diverse community**, which answers questions, writes articles, and promotes the framework. Creating such an ecosystem from scratch takes years. But because we based Vue Storefront on Nuxt.js — the biggest Vue.js framework — it ticks all the boxes. Nuxt.js has a vast library of [ready-to-use modules](https://modules.nuxtjs.org/) and an active community of thousands of developers on the [Nuxt.js Discord server](https://discord.com/invite/ps2h6QT). It's also flexible enough to make it e-commerce ready with just a few plugins and modules. - - -Combining general-purpose modules from Nuxt.js and e-commerce specific modules from Vue Storefront significantly shortens the time-to-market. It allows you to focus on what's specific to your project. - - +> Combining general-purpose modules from Nuxt.js and e-commerce specific modules from Vue Storefront significantly shortens the time-to-market. It allows you to focus on what's specific to your project. ## Start with Vue.js @@ -46,4 +44,4 @@ We also encourage reading [Nuxt.js 2 documentation](https://nuxtjs.org/docs/). I ## What's next -Now that you understand what Vue Storefront is, it's time to understand the [Project structure](./project-structure.html) and learn how to navigate it and which files do what. +Now that you understand what Vue Storefront is, go to the [Installation](./installation.html) guide to set up a project. diff --git a/docs/guide/environments.md b/docs/guide/environments.md deleted file mode 100644 index 66dc8cf4e..000000000 --- a/docs/guide/environments.md +++ /dev/null @@ -1,21 +0,0 @@ -# Demo environments - -We have three demo environments where you can see and test Magento 2 integration for Vue Storefront in action. If you find a bug in any of them, please [create an issue](https://github.com/vuestorefront/magento2/issues/new/choose) in our repository to let us know about it. - -## Production environment - -In the production environment, you can see the latest **released and stable** version of the integration. It should be visually and feature-wise identical to the new project installed using our CLI. - -[Production demo](https://demo-magento2.europe-west1.gcp.vuestorefront.cloud) - -## Staging environment - -In the staging environment, we are testing new releases. It should be **relatively stable**, but you might still encounter some bugs. - -[Staging demo](https://demo-magento2-canary.europe-west1.gcp.storefrontcloud.io) - -## Development environment - -In the development environment, we are testing the `develop` branch, which might contain unfinished or experimental features. It might be **unstable** both visually and feature-wise. - -[Development environment](https://demo-magento2-dev.europe-west1.gcp.storefrontcloud.io) diff --git a/docs/index.md b/docs/index.md index 07a8791d9..f93021fdb 100644 --- a/docs/index.md +++ b/docs/index.md @@ -18,4 +18,22 @@ To get started, see the following guides: ## Demo -If you want to see the integration in action, check out our [demo environments](/guide/environments.html). +If you want to see the integration in action, we have three demo environments where you can see and test Magento 2 integration for Vue Storefront in action. If you find a bug in any of them, please [create an issue](https://github.com/vuestorefront/magento2/issues/new/choose) in our repository to let us know about it. + +### Production environment + +In the production environment, you can see the latest **released and stable** version of the integration. It should be visually and feature-wise identical to the new project installed using our CLI. + +[Production demo](https://demo-magento2.europe-west1.gcp.vuestorefront.cloud) + +### Staging environment + +In the staging environment, we are testing new releases. It should be **relatively stable**, but you might still encounter some bugs. + +[Staging demo](https://demo-magento2-canary.europe-west1.gcp.storefrontcloud.io) + +### Development environment + +In the development environment, we are testing the `develop` branch, which might contain unfinished or experimental features. It might be **unstable** both visually and feature-wise. + +[Development environment](https://demo-magento2-dev.europe-west1.gcp.storefrontcloud.io) diff --git a/docs/installation-setup/installation.md b/docs/installation-setup/installation.md index 4ae833ca9..f0cfe6bc7 100644 --- a/docs/installation-setup/installation.md +++ b/docs/installation-setup/installation.md @@ -1,7 +1,5 @@ # Installation -[[toc]] - ## Prerequisites Before proceeding, make sure you have [Node 16](https://nodejs.org/en/) installed. You can check this by running the following command: From 706d23b888b16b2f444747251d3ad22bde462113 Mon Sep 17 00:00:00 2001 From: Matt Maribojoc Date: Mon, 18 Jul 2022 09:50:59 -0400 Subject: [PATCH 13/89] docs: update theme for integration logos --- docs/installation-setup/installation.md | 2 +- docs/package.json | 2 +- docs/yarn.lock | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/installation-setup/installation.md b/docs/installation-setup/installation.md index f0cfe6bc7..ad4db862c 100644 --- a/docs/installation-setup/installation.md +++ b/docs/installation-setup/installation.md @@ -18,7 +18,7 @@ The easiest way to get started with Vue Storefront is to set up your project usi npx @vue-storefront/cli generate store ``` -It will ask you to enter the project's name and select the e-commerce platform you wish to use. Once selected, the CLI will create project files in the directory matching your project name. +It will ask you to enter the project's name and select `Magento 2` as your e-commerce platform. Once selected, the CLI will create project files in the directory matching your project name. ::: warning CLI will use the project name you enter to create a new directory, so avoid using special characters and spaces. diff --git a/docs/package.json b/docs/package.json index 9f3519043..9af3adf50 100755 --- a/docs/package.json +++ b/docs/package.json @@ -29,6 +29,6 @@ "dependencies": { "sass-loader": "^8.0.2", "vue-multiselect": "^2.1.6", - "vuepress-theme-vsf-docs": "^1.0.13" + "vuepress-theme-vsf-docs": "^1.0.14" } } diff --git a/docs/yarn.lock b/docs/yarn.lock index 2b144ec85..d63d8ffdc 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -8336,10 +8336,10 @@ vuepress-plugin-smooth-scroll@^0.0.3: dependencies: smoothscroll-polyfill "^0.4.3" -vuepress-theme-vsf-docs@^1.0.13: - version "1.0.13" - resolved "https://registry.yarnpkg.com/vuepress-theme-vsf-docs/-/vuepress-theme-vsf-docs-1.0.13.tgz#949aa0adb1aa9de98774c19a4887e64994838aec" - integrity sha512-vvjA88XVu+a/DjyChzF4karIztDCqcmLbsfgyFPGGAIAmOx28g11xVx1Wg5nXzl89hDbSWyLzKtLoSP7g/JZyQ== +vuepress-theme-vsf-docs@^1.0.14: + version "1.0.14" + resolved "https://registry.yarnpkg.com/vuepress-theme-vsf-docs/-/vuepress-theme-vsf-docs-1.0.14.tgz#87e9a4fd079f34548140cad7647d4cf04a02dc59" + integrity sha512-m57TPCuaA8iyEsk/Kvgg0Wi+ByLqPXgbPF7dwGSgqjGlcIjjW2bMoaFrI7yNNLxnKdfyYXhgR0rLsPVQTPmwgw== dependencies: "@vuepress/plugin-active-header-links" "1.9.7" "@vuepress/plugin-nprogress" "1.9.7" From 78ffb244910c52d1751cff71d623a6c6766ded7b Mon Sep 17 00:00:00 2001 From: Marcin Kwiatkowski Date: Tue, 19 Jul 2022 20:26:26 +0200 Subject: [PATCH 14/89] build: enabled redis --- .github/workflows/deploy-vue-storefront-cloud.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-vue-storefront-cloud.yml b/.github/workflows/deploy-vue-storefront-cloud.yml index c778e1a7d..fdd14e225 100644 --- a/.github/workflows/deploy-vue-storefront-cloud.yml +++ b/.github/workflows/deploy-vue-storefront-cloud.yml @@ -100,7 +100,7 @@ jobs: VSF_IMAGE_PROVIDER_BASE_URL: https://res-4.cloudinary.com/dnozky7on/image/upload/ VSF_IMAGE_PROVIDER_DOMAIN: https://res-4.cloudinary.com - VSF_REDIS_ENABLED: false + VSF_REDIS_ENABLED: true VSF_REDIS_HOST: redis # VSF cloud specific VSF_REDIS_PORT: 6379 VSF_REDIS_KEY_PREFIX: ${{ github.sha }} From 24c8ea1bd28d07a7b425d6fd2ea342e471807828 Mon Sep 17 00:00:00 2001 From: Artur Tagisow Date: Mon, 18 Jul 2022 11:31:10 +0200 Subject: [PATCH 15/89] ci: poll farmer for pod deployment status ci: add polling farmer for deploy status ci: fix extra parentheses --- .github/workflows/deployment-template.yml | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/.github/workflows/deployment-template.yml b/.github/workflows/deployment-template.yml index ded9778b4..c869c15c0 100644 --- a/.github/workflows/deployment-template.yml +++ b/.github/workflows/deployment-template.yml @@ -28,9 +28,17 @@ jobs: exit 1 fi - # the above curl only *asks* for the container to be deployed - # we don't know when the newly built Docker image replaces the old one - # but it takes less than 5 minutes - - name: 'Wait for container deployed on VSF Cloud to come online' - run: 'sleep 300' - shell: 'bash' + - name: 'Poll for Farmer pod deployment status' + timeout-minutes: 5 + run: | + query_deploy_check_endpoint () { + NAMESPACE=${{ inputs.environment-code }}-europe-west1-gcp-storefrontcloud-io + curl -s \ + -H 'X-User-Id: ${{ secrets.cloud-username }}' \ + -H 'X-Api-Key: ${{ secrets.cloud-password }}' \ + -H 'Content-Type: application/json' \ + https://farmer.storefrontcloud.io/deploy_check/$NAMESPACE/${{ github.sha }} + } + until $( query_deploy_check_endpoint | tee /dev/stderr | grep -q '{"code":200,"ready":"1","deployed":"1"}' ); do + sleep 10; + done; From 2e7912fac1fceb5b5ecbc5c1a355f5a14ff2f839 Mon Sep 17 00:00:00 2001 From: Bartosz Herba Date: Thu, 21 Jul 2022 14:25:47 +0200 Subject: [PATCH 16/89] fix: update vue dependencies - lock dependencies on the last working version to avoid upgrade issues --- packages/theme/package.json | 7 +++++-- yarn.lock | 30 +++++++++++++++--------------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/packages/theme/package.json b/packages/theme/package.json index 42f7cf336..4e8384b89 100644 --- a/packages/theme/package.json +++ b/packages/theme/package.json @@ -57,9 +57,12 @@ "pinia": "^2.0.14", "pm2": "^5.2.0", "vee-validate": "^3.4.14", - "vue": "^2.6.14", + "vue": "2.6.14", + "vue-demi": "0.13.1", "vue-lazy-hydration": "^2.0.0-beta.4", - "vue-scrollto": "^2.20.0" + "vue-scrollto": "^2.20.0", + "vue-server-renderer": "2.6.14", + "vue-template-compiler": "2.6.14" }, "devDependencies": { "@babel/core": "^7.18.6", diff --git a/yarn.lock b/yarn.lock index e1048f0be..d2aa78933 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1905,7 +1905,7 @@ tslib "~2.3.0" value-or-promise "1.0.11" -"@graphql-typed-document-node/core@^3.0.0": +"@graphql-typed-document-node/core@^3.1.1": version "3.1.1" resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.1.1.tgz#076d78ce99822258cf813ecc1e7fa460fa74d052" integrity sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg== @@ -5116,11 +5116,6 @@ resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.31.tgz#c90de7126d833dcd3a4c7534d534be2fb41faa4e" integrity sha512-ymN2pj6zEjiKJZbrf98UM2pfDd6F2H7ksKw7NDt/ZZ1fh5Ei39X5tABugtT03ZRlWd9imccoK0hE8hpjpU7irQ== -"@vue/shared@3.2.37": - version "3.2.37" - resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.37.tgz#8e6adc3f2759af52f0e85863dfb0b711ecc5c702" - integrity sha512-4rSJemR2NQIo9Klm1vabqWjD8rs/ZaJSzMxkMNeJS6lHiUjjUeYFbooN19NgFjztubEKh3WlZUeOLVdbbUWHsw== - "@vue/test-utils@^1.1.0", "@vue/test-utils@^1.3.0": version "1.3.0" resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-1.3.0.tgz#d563decdcd9c68a7bca151d4179a2bfd6d5c3e15" @@ -11344,7 +11339,7 @@ graphql-sse@^1.0.1: resolved "https://registry.yarnpkg.com/graphql-sse/-/graphql-sse-1.0.6.tgz#4f98e0a06f2020542ed054399116108491263224" integrity sha512-y2mVBN2KwNrzxX2KBncQ6kzc6JWvecxuBernrl0j65hsr6MAS3+Yn8PTFSOgRmtolxugepxveyZVQEuaNEbw3w== -graphql-tag@^2.11.0, graphql-tag@^2.12.3, graphql-tag@^2.12.6: +graphql-tag@^2.11.0, graphql-tag@^2.12.6: version "2.12.6" resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.12.6.tgz#d441a569c1d2537ef10ca3d1633b48725329b5f1" integrity sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg== @@ -20530,10 +20525,10 @@ trim-newlines@^3.0.0: resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw== -ts-invariant@^0.9.4: - version "0.9.4" - resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.9.4.tgz#42ac6c791aade267dd9dc65276549df5c5d71cac" - integrity sha512-63jtX/ZSwnUNi/WhXjnK8kz4cHHpYS60AnmA6ixz17l7E12a5puCWFlNpkne5Rl0J8TBPVHpGjsj4fxs8ObVLQ== +ts-invariant@^0.10.3: + version "0.10.3" + resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.10.3.tgz#3e048ff96e91459ffca01304dbc7f61c1f642f6c" + integrity sha512-uivwYcQaxAucv1CzRp2n/QdYPo4ILf9VXgH19zEIjFx2EJufV16P0JtJVpYHy89DItG6Kwj2oIUjrcK5au+4tQ== dependencies: tslib "^2.1.0" @@ -21376,6 +21371,11 @@ vue-demi@*: resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.12.1.tgz#f7e18efbecffd11ab069d1472d7a06e319b4174c" integrity sha512-QL3ny+wX8c6Xm1/EZylbgzdoDolye+VpCXRhI2hug9dJTP3OUJ3lmiKN3CsVV3mOJKwFi0nsstbgob0vG7aoIw== +vue-demi@0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.13.1.tgz#7604904c88be338418a10abbc94d5b8caa14cb8c" + integrity sha512-xmkJ56koG3ptpLnpgmIzk9/4nFf4CqduSJbUM0OdPoU87NwRuZ6x49OLhjSa/fC15fV+5CbEnrxU4oyE022svg== + vue-demi@^0.12.1: version "0.12.4" resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.12.4.tgz#420dd17628f95f1bbce1102ad3c51074713a8049" @@ -21474,7 +21474,7 @@ vue-scrollto@^2.20.0: dependencies: bezier-easing "2.1.0" -vue-server-renderer@^2.6.12: +vue-server-renderer@2.6.14, vue-server-renderer@^2.6.12: version "2.6.14" resolved "https://registry.yarnpkg.com/vue-server-renderer/-/vue-server-renderer-2.6.14.tgz#c8bffff152df6b47b858818ef8d524d2fc351654" integrity sha512-HifYRa/LW7cKywg9gd4ZtvtRuBlstQBao5ZCWlg40fyB4OPoGfEXAzxb0emSLv4pBDOHYx0UjpqvxpiQFEuoLA== @@ -21496,7 +21496,7 @@ vue-style-loader@^4.1.0, vue-style-loader@^4.1.3: hash-sum "^1.0.2" loader-utils "^1.0.2" -vue-template-compiler@^2.6.12, vue-template-compiler@^2.6.14, vue-template-compiler@^2.6.x: +vue-template-compiler@2.6.14, vue-template-compiler@^2.6.12, vue-template-compiler@^2.6.14, vue-template-compiler@^2.6.x: version "2.6.14" resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.6.14.tgz#a2f0e7d985670d42c9c9ee0d044fed7690f4f763" integrity sha512-ODQS1SyMbjKoO1JBJZojSw6FE4qnh9rIpUZn2EUT86FKizx9uH5z6uXiIrm4/Nb/gwxTi/o17ZDEGWAXHvtC7g== @@ -21514,7 +21514,7 @@ vue2-leaflet@^2.5.2: resolved "https://registry.yarnpkg.com/vue2-leaflet/-/vue2-leaflet-2.7.1.tgz#2f95c287621bf778f10804c88223877f5c049257" integrity sha512-K7HOlzRhjt3Z7+IvTqEavIBRbmCwSZSCVUlz9u4Rc+3xGCLsHKz4TAL4diAmfHElCQdPPVdZdJk8wPUt2fu6WQ== -vue@^2.6.11, vue@^2.6.12, vue@^2.6.14: +vue@2.6.14, vue@^2.6.11, vue@^2.6.12, vue@^2.6.14: version "2.6.14" resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.14.tgz#e51aa5250250d569a3fbad3a8a5a687d6036e235" integrity sha512-x2284lgYvjOMj3Za7kqzRcUSxBboHqtgRE2zlos1qWaOye5yUmHn42LB1250NJBLRwEcdrB0JRwyPTEPhfQjiQ== @@ -22237,7 +22237,7 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== -zen-observable-ts@^1.2.0: +zen-observable-ts@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-1.2.5.tgz#6c6d9ea3d3a842812c6e9519209365a122ba8b58" integrity sha512-QZWQekv6iB72Naeake9hS1KxHlotfRpe+WGNbNx5/ta+R3DNjVO2bswf63gXlWDcs+EMd7XY8HfVQyP1X6T4Zg== From ad6b0098607cce3fe86b5395a5ac866ac38bd821 Mon Sep 17 00:00:00 2001 From: Marcin Kwiatkowski Date: Thu, 14 Jul 2022 15:57:44 +0200 Subject: [PATCH 17/89] docs: addd 1.0.0 release notes --- docs/index.md | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/docs/index.md b/docs/index.md index f93021fdb..07a8791d9 100644 --- a/docs/index.md +++ b/docs/index.md @@ -18,22 +18,4 @@ To get started, see the following guides: ## Demo -If you want to see the integration in action, we have three demo environments where you can see and test Magento 2 integration for Vue Storefront in action. If you find a bug in any of them, please [create an issue](https://github.com/vuestorefront/magento2/issues/new/choose) in our repository to let us know about it. - -### Production environment - -In the production environment, you can see the latest **released and stable** version of the integration. It should be visually and feature-wise identical to the new project installed using our CLI. - -[Production demo](https://demo-magento2.europe-west1.gcp.vuestorefront.cloud) - -### Staging environment - -In the staging environment, we are testing new releases. It should be **relatively stable**, but you might still encounter some bugs. - -[Staging demo](https://demo-magento2-canary.europe-west1.gcp.storefrontcloud.io) - -### Development environment - -In the development environment, we are testing the `develop` branch, which might contain unfinished or experimental features. It might be **unstable** both visually and feature-wise. - -[Development environment](https://demo-magento2-dev.europe-west1.gcp.storefrontcloud.io) +If you want to see the integration in action, check out our [demo environments](/guide/environments.html). From a2d8394fe3251f55d50c6755b7d80b6605aa8903 Mon Sep 17 00:00:00 2001 From: Artur Tagisow <5359825+sethidden@users.noreply.github.com> Date: Tue, 19 Jul 2022 11:18:15 +0200 Subject: [PATCH 18/89] ci: align release branch name convention [ci skip] --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 71f1323d2..786daab63 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -5,12 +5,12 @@ on: branches: - main - develop - - release-** + - release/* pull_request: branches: - main - develop - - release-** + - release/* concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} From d078d5297f68a6be241fdb003a2a08a1e7b382c4 Mon Sep 17 00:00:00 2001 From: Marcin Kwiatkowski Date: Wed, 20 Jul 2022 07:01:50 +0200 Subject: [PATCH 19/89] docs: updated migration guides --- docs/migration-guides/index.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/migration-guides/index.md b/docs/migration-guides/index.md index bba312dbc..f8daf93f6 100644 --- a/docs/migration-guides/index.md +++ b/docs/migration-guides/index.md @@ -1,7 +1,13 @@ # Migration guides -- [1.0.0-rc.7](./1.0.0-rc.7/) -- [1.0.0-rc.8](./1.0.0-rc.8/) -- [1.0.0-rc.9](./1.0.0-rc.9/) -- [1.0.0-rc.10](./1.0.0-rc.10/) - [1.0.0](./1.0.0/) +- [1.0.0-rc.10](./1.0.0-rc.10/) +- [1.0.0-rc.9](./1.0.0-rc.9/) +- [1.0.0-rc.8](./1.0.0-rc.8/) +- [1.0.0-rc.7](./1.0.0-rc.7/) + + + + + + From 3e9d1115690d361a8804512f0d4d9356d67fe81c Mon Sep 17 00:00:00 2001 From: Marcin Kwiatkowski Date: Wed, 20 Jul 2022 10:05:18 +0200 Subject: [PATCH 20/89] chore: updated npm versions of vsf packages --- packages/api-client/package.json | 2 +- packages/composables/package.json | 4 ++-- packages/theme/package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/api-client/package.json b/packages/api-client/package.json index ef197d4a6..7c263a0f2 100644 --- a/packages/api-client/package.json +++ b/packages/api-client/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/magento-api", - "version": "1.0.0", + "version": "1.0.1", "sideEffects": false, "homepage": "https://github.com/vuestorefront/magento2", "bugs": { diff --git a/packages/composables/package.json b/packages/composables/package.json index 322b7e5f6..1d3f49bc9 100644 --- a/packages/composables/package.json +++ b/packages/composables/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/magento", - "version": "1.0.0", + "version": "1.0.1", "license": "MIT", "homepage": "https://github.com/vuestorefront/magento2", "bugs": { @@ -29,7 +29,7 @@ }, "dependencies": { "@vue-storefront/core": "~2.5.6", - "@vue-storefront/magento-api": "^1.0.0", + "@vue-storefront/magento-api": "^1.0.1", "@vue/composition-api": "^1.4.1", "cookie-universal": "^2.1.5", "vue": "^2.6.14", diff --git a/packages/theme/package.json b/packages/theme/package.json index 4e8384b89..e6824a035 100644 --- a/packages/theme/package.json +++ b/packages/theme/package.json @@ -38,7 +38,7 @@ "@pinia/nuxt": "^0.1.9", "@storefront-ui/vue": "^0.13.3", "@vue-storefront/cache": "~2.7.1", - "@vue-storefront/magento-api": "^1.0.0", + "@vue-storefront/magento-api": "^1.0.1", "@vue-storefront/middleware": "~2.7.1", "@vue-storefront/nuxt": "~2.7.1", "@vue-storefront/redis-cache": "^1.0.1", From cc73739ac3c60950e3d00859437735a104b1d370 Mon Sep 17 00:00:00 2001 From: Filip Sobol Date: Wed, 20 Jul 2022 12:13:17 +0200 Subject: [PATCH 21/89] docs: fix formatting in `Override queries` guide --- docs/guide/override-queries.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/guide/override-queries.md b/docs/guide/override-queries.md index 988a97552..e04ecfe1a 100644 --- a/docs/guide/override-queries.md +++ b/docs/guide/override-queries.md @@ -82,6 +82,7 @@ Make sure you have `graphgl-tag` installed as dependency prior using this sample }, }, }; +``` 4. Now you can restart your dev environment and view the updated data queried. From ca33842387737d169a520ac5b44800df41c05e1b Mon Sep 17 00:00:00 2001 From: Marcin Kwiatkowski Date: Thu, 21 Jul 2022 14:37:01 +0200 Subject: [PATCH 22/89] chore: release 1.0.1 --- docs/migration-guides/1.0.1/index.md | 7 +++++++ docs/migration-guides/index.md | 1 + internals/eslint-import/package.json | 2 +- internals/eslint-jest/package.json | 2 +- internals/eslint-typescript/package.json | 2 +- internals/eslint-vue/package.json | 2 +- internals/eslint/package.json | 2 +- packages/load-tests/package.json | 2 +- packages/theme/package.json | 2 +- 9 files changed, 15 insertions(+), 7 deletions(-) create mode 100644 docs/migration-guides/1.0.1/index.md diff --git a/docs/migration-guides/1.0.1/index.md b/docs/migration-guides/1.0.1/index.md new file mode 100644 index 000000000..c1a5ea12f --- /dev/null +++ b/docs/migration-guides/1.0.1/index.md @@ -0,0 +1,7 @@ +# Vue Storefront for Magento 1.0.1 release notes + +## Docs +- docs: fix formatting in Override queries guide [#1289](https://github.com/vuestorefront/magento2/pull/1289) + +## Bugfix +- fix: fixed the Vue version in package.json to avoid upgrading to Vue 2.7 [#1294](https://github.com/vuestorefront/magento2/pull/1294) diff --git a/docs/migration-guides/index.md b/docs/migration-guides/index.md index f8daf93f6..332ff57ec 100644 --- a/docs/migration-guides/index.md +++ b/docs/migration-guides/index.md @@ -1,5 +1,6 @@ # Migration guides +- [1.0.1](./1.0.1/) - [1.0.0](./1.0.0/) - [1.0.0-rc.10](./1.0.0-rc.10/) - [1.0.0-rc.9](./1.0.0-rc.9/) diff --git a/internals/eslint-import/package.json b/internals/eslint-import/package.json index 168493894..61a67f11f 100644 --- a/internals/eslint-import/package.json +++ b/internals/eslint-import/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/eslint-config-import", - "version": "1.0.0", + "version": "1.0.1", "author": "Heitor Ramon Ribeiro ", "license": "MIT", "scripts": { diff --git a/internals/eslint-jest/package.json b/internals/eslint-jest/package.json index 16cdc9441..4d215697a 100644 --- a/internals/eslint-jest/package.json +++ b/internals/eslint-jest/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/eslint-config-jest", - "version": "1.0.0", + "version": "1.0.1", "author": "Heitor Ramon Ribeiro ", "license": "MIT", "scripts": { diff --git a/internals/eslint-typescript/package.json b/internals/eslint-typescript/package.json index 5ebdfc6c2..dd6184a71 100644 --- a/internals/eslint-typescript/package.json +++ b/internals/eslint-typescript/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/eslint-config-typescript", - "version": "1.0.0", + "version": "1.0.1", "author": "Heitor Ramon Ribeiro ", "license": "MIT", "scripts": { diff --git a/internals/eslint-vue/package.json b/internals/eslint-vue/package.json index f0d8c7cfa..046195b9b 100644 --- a/internals/eslint-vue/package.json +++ b/internals/eslint-vue/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/eslint-config-vue", - "version": "1.0.0", + "version": "1.0.1", "author": "Heitor Ramon Ribeiro ", "license": "MIT", "scripts": { diff --git a/internals/eslint/package.json b/internals/eslint/package.json index 0c0256a19..6510e16f5 100644 --- a/internals/eslint/package.json +++ b/internals/eslint/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/eslint-config-base", - "version": "1.0.0", + "version": "1.0.1", "author": "Heitor Ramon Ribeiro ", "license": "MIT", "scripts": { diff --git a/packages/load-tests/package.json b/packages/load-tests/package.json index aa8b7738f..4d2c02840 100644 --- a/packages/load-tests/package.json +++ b/packages/load-tests/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/magento-load-tests", - "version": "1.0.0", + "version": "1.0.1", "description": "Load tests for Magento 2 - VSF integration", "main": "index.js", "repository": "https://github.com/vuestorefront/magento2", diff --git a/packages/theme/package.json b/packages/theme/package.json index e6824a035..5e86d3d98 100644 --- a/packages/theme/package.json +++ b/packages/theme/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/magento-theme", - "version": "1.0.0", + "version": "1.0.1", "private": true, "license": "MIT", "homepage": "https://github.com/vuestorefront/magento2", From 1def1e2f575bd1bd3f6796094af58de734d90661 Mon Sep 17 00:00:00 2001 From: Bartosz Herba Date: Thu, 21 Jul 2022 11:22:18 +0200 Subject: [PATCH 23/89] fix: images are not loaded properly with ipx - add images extensions for a proper rendering --- packages/theme/pages/Home.vue | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/theme/pages/Home.vue b/packages/theme/pages/Home.vue index 26a782f55..826b28ea3 100644 --- a/packages/theme/pages/Home.vue +++ b/packages/theme/pages/Home.vue @@ -100,7 +100,7 @@ export default defineComponent({ title: app.i18n.t('Colorful summer dresses are already in store'), subtitle: app.i18n.t('SUMMER COLLECTION {year}', { year }), buttonText: app.i18n.t('Learn more'), - imageSrc: '/homepage/bannerB', + imageSrc: '/homepage/bannerB.webp', imageWidth: isDesktop ? 1240 : 328, imageHeight: isDesktop ? 400 : 224, imageConfig: { @@ -120,9 +120,9 @@ export default defineComponent({ buttonText: app.i18n.t('Shop now'), image: { mobile: - '/homepage/bannerB', + '/homepage/bannerB.webp', desktop: - '/homepage/bannerF', + '/homepage/bannerF.webp', }, imageConfig: { fit: 'cover', @@ -141,7 +141,7 @@ export default defineComponent({ 'Find stunning women\'s cocktail dresses and party dresses. Stand out in lace and metallic cocktail dresses from all your favorite brands.', ), buttonText: app.i18n.t('Shop now'), - image: '/homepage/bannerE', + image: '/homepage/bannerE.webp', imageConfig: { fit: 'cover', width: isDesktop ? 496 : 328, @@ -155,7 +155,7 @@ export default defineComponent({ slot: 'banner-C', subtitle: app.i18n.t('T-Shirts'), title: app.i18n.t('The Office Life'), - image: '/homepage/bannerC', + image: '/homepage/bannerC.webp', imageConfig: { fit: 'cover', width: isDesktop ? 332 : 328, @@ -169,7 +169,7 @@ export default defineComponent({ slot: 'banner-D', subtitle: app.i18n.t('Summer Sandals'), title: app.i18n.t('Eco Sandals'), - image: '/homepage/bannerG', + image: '/homepage/bannerG.webp', imageConfig: { fit: 'cover', width: isDesktop ? 332 : 328, @@ -184,7 +184,7 @@ export default defineComponent({ title: app.i18n.t('Subscribe to Newsletters'), description: app.i18n.t('Be aware of upcoming sales and events. Receive gifts and special offers!'), buttonText: app.i18n.t('Subscribe'), - imageSrc: '/homepage/newsletter', + imageSrc: '/homepage/newsletter.webp', imageWidth: isDesktop ? 1240 : 400, imageHeight: isDesktop ? 202 : 200, imageConfig: { From 0f6a89ae4e307d9f1f4bb0bc2dab97d15b3e8732 Mon Sep 17 00:00:00 2001 From: Bartosz Herba Date: Wed, 20 Jul 2022 11:37:08 +0200 Subject: [PATCH 24/89] fix: env export for windows os environments --- packages/theme/.env.example | 2 ++ packages/theme/nuxt.config.js | 2 +- packages/theme/package.json | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/theme/.env.example b/packages/theme/.env.example index d1fc42c14..a9f09937a 100644 --- a/packages/theme/.env.example +++ b/packages/theme/.env.example @@ -27,3 +27,5 @@ VSF_RECAPTCHA_HIDE_BADGE= VSF_RECAPTCHA_SIZE=invisible VSF_RECAPTCHA_MIN_SCORE=0.5 VSF_RECAPTCHA_VERSION=3 + +NODE_TLS_REJECT_UNAUTHORIZED=0 diff --git a/packages/theme/nuxt.config.js b/packages/theme/nuxt.config.js index f72d586c8..2a305497f 100755 --- a/packages/theme/nuxt.config.js +++ b/packages/theme/nuxt.config.js @@ -285,7 +285,7 @@ export default () => { }; } - if (process.env.NODE_ENV === 'development' || process.env.IS_ENV_LOCAL) { + if (process.env.NODE_ENV === 'development' || process.env.VSF_NUXT_APP_ENV === 'development') { baseConfig.server = { https: { key: fs.readFileSync(path.resolve(__dirname, 'localhost-key.pem')), diff --git a/packages/theme/package.json b/packages/theme/package.json index 5e86d3d98..82d6c8839 100644 --- a/packages/theme/package.json +++ b/packages/theme/package.json @@ -10,14 +10,14 @@ "scripts": { "build": "nuxt build --modern=client", "build:analyze": "nuxt build -a --modern=client", - "dev": "export NODE_TLS_REJECT_UNAUTHORIZED=0 && nuxt --env.NODE_TLS_REJECT_UNAUTHORIZED=0", + "dev": "nuxt --env.NODE_TLS_REJECT_UNAUTHORIZED=0", "dev:debug": "node --inspect ../../node_modules/.bin/nuxt dev", "generate": "nuxt generate", "lint": "eslint . --ext .ts,.vue", "lint:fix": "eslint . --ext .ts,.vue --fix", "precommit": "lint-staged", "start": "nuxt start --modern=client", - "start:local": "export NODE_TLS_REJECT_UNAUTHORIZED=0 && export IS_ENV_LOCAL=1 && nuxt start --modern=client --env.NODE_TLS_REJECT_UNAUTHORIZED=0", + "start:local": "nuxt start --modern=client --env.NODE_TLS_REJECT_UNAUTHORIZED=0", "test": "jest", "test:watch": "jest --watch", "test:coverage": "jest --coverage", From c4fb496c205a5c01b11b6270985f1bfbb88b61d4 Mon Sep 17 00:00:00 2001 From: Bartosz Herba Date: Mon, 18 Jul 2022 10:01:49 +0200 Subject: [PATCH 25/89] feat: load tests - add magento store config load test - add create empty guest cart load test - add magento create customer --- .../src/mutation/addProductsToCart.js | 191 ++++++++++++++++++ .../load-tests/src/mutation/createCustomer.js | 45 +++++ .../src/mutation/createEmptyCart.js | 7 + .../load-tests/src/query/storeConfig.gql.js | 17 ++ .../tests/magento/addSimpleProductToCart.js | 52 +++++ .../src/tests/magento/createCustomer.js | 51 +++++ .../src/tests/magento/createEmptyGuestCart.js | 46 +++++ .../src/tests/magento/storeConfig.js | 41 ++++ .../src/tests/magento/utils/customerData.js | 16 ++ .../src/tests/magento/utils/getHeaders.js | 5 + .../src/tests/middleware/createCustomer.js | 48 +++++ .../tests/middleware/createEmptyGuestCart.js | 47 +++++ .../src/tests/middleware/storeConfig.js | 40 ++++ .../tests/middleware/utils/customerData.js | 16 ++ .../src/tests/middleware/utils/getHeaders.js | 7 + packages/load-tests/src/utils/getCookies.js | 7 + 16 files changed, 636 insertions(+) create mode 100644 packages/load-tests/src/mutation/addProductsToCart.js create mode 100644 packages/load-tests/src/mutation/createCustomer.js create mode 100644 packages/load-tests/src/mutation/createEmptyCart.js create mode 100644 packages/load-tests/src/query/storeConfig.gql.js create mode 100644 packages/load-tests/src/tests/magento/addSimpleProductToCart.js create mode 100644 packages/load-tests/src/tests/magento/createCustomer.js create mode 100644 packages/load-tests/src/tests/magento/createEmptyGuestCart.js create mode 100644 packages/load-tests/src/tests/magento/storeConfig.js create mode 100644 packages/load-tests/src/tests/magento/utils/customerData.js create mode 100644 packages/load-tests/src/tests/magento/utils/getHeaders.js create mode 100644 packages/load-tests/src/tests/middleware/createCustomer.js create mode 100644 packages/load-tests/src/tests/middleware/createEmptyGuestCart.js create mode 100644 packages/load-tests/src/tests/middleware/storeConfig.js create mode 100644 packages/load-tests/src/tests/middleware/utils/customerData.js create mode 100644 packages/load-tests/src/tests/middleware/utils/getHeaders.js create mode 100644 packages/load-tests/src/utils/getCookies.js diff --git a/packages/load-tests/src/mutation/addProductsToCart.js b/packages/load-tests/src/mutation/addProductsToCart.js new file mode 100644 index 000000000..97b581093 --- /dev/null +++ b/packages/load-tests/src/mutation/addProductsToCart.js @@ -0,0 +1,191 @@ +export const AddProductsToCart = ` +mutation addProductsToCart($cartId: String!, $cartItems: [CartItemInput!]!) { + addProductsToCart(cartId,: $cartId, cartItems,: $cartItems) { + cart { + id + email + is_virtual + applied_coupons { + code + } + prices { + subtotal_excluding_tax { + value + }, + subtotal_including_tax { + value + }, + applied_taxes { + amount { + value + }, + label + } + discounts { + amount { + value + }, + label + } + grand_total { + value + } + } + items { + uid + product { + uid + __typename + sku + name + stock_status + only_x_left_in_stock + rating_summary + thumbnail { + url + position + disabled + label + } + url_key + url_rewrites { + url + } + price_range { + maximum_price { + final_price { + currency + value + } + regular_price { + currency + value + } + } + minimum_price { + final_price { + currency + value + } + regular_price { + currency + value + } + } + } + categories { + uid + name + url_suffix + url_path + breadcrumbs { + category_name, + category_url_path + } + } + review_count + reviews { + items { + average_rating + ratings_breakdown { + name + value + } + } + } + } + prices { + row_total { + value + } + row_total_including_tax { + value + } + total_item_discount { + value + } + } + quantity + ... on ConfigurableCartItem { + configurable_options { + configurable_product_option_uid + option_label + configurable_product_option_value_uid + value_label + } + configured_variant { + sku + thumbnail { + url + } + } + } + ... on BundleCartItem { + bundle_options { + uid + label + type + values { + id + label + price + quantity + } + } + } + } + total_quantity + shipping_addresses { + firstname + lastname + street + city + company + region { + code + region_id + label + } + postcode + telephone + country { + code + label + } + selected_shipping_method { + carrier_code + carrier_title + method_code + method_title + amount { + value + currency + } + } + } + billing_address { + firstname + lastname + street + city + company + region { + code + region_id + label + } + postcode + telephone + country { + code + label + } + } + } + user_errors { + code + message + } + } + } +`; diff --git a/packages/load-tests/src/mutation/createCustomer.js b/packages/load-tests/src/mutation/createCustomer.js new file mode 100644 index 000000000..aab1d7a13 --- /dev/null +++ b/packages/load-tests/src/mutation/createCustomer.js @@ -0,0 +1,45 @@ +export const CreateCustomer = ` + mutation createCustomer($input: CustomerCreateInput!) { + createCustomerV2(input: $input) { + customer { + date_of_birth + default_billing + default_shipping + email + firstname + is_subscribed + lastname + middlename + prefix + suffix + taxvat + addresses { + city + country_code + default_billing + default_shipping + extension_attributes { + attribute_code + value + } + firstname + id + lastname + postcode + prefix + region { + region_code + region_id + region + } + street + suffix + telephone + vat_id + } + } + } + } +`; + +export default CreateCustomer; diff --git a/packages/load-tests/src/mutation/createEmptyCart.js b/packages/load-tests/src/mutation/createEmptyCart.js new file mode 100644 index 000000000..28d399306 --- /dev/null +++ b/packages/load-tests/src/mutation/createEmptyCart.js @@ -0,0 +1,7 @@ +export const CreateEmptyCartMutation = ` + mutation { + createEmptyCart + } +`; + +export default CreateEmptyCartMutation; diff --git a/packages/load-tests/src/query/storeConfig.gql.js b/packages/load-tests/src/query/storeConfig.gql.js new file mode 100644 index 000000000..367c7886a --- /dev/null +++ b/packages/load-tests/src/query/storeConfig.gql.js @@ -0,0 +1,17 @@ +export const StoreConfigQuery = ` + query storeConfig { + storeConfig { + store_code, + default_title, + store_name, + default_display_currency_code, + locale, + header_logo_src, + logo_width, + logo_height, + logo_alt + } + } +`; + +export const StoreConfigQueryString = 'query=query%20storeConfig%20%7B%0A%20%20%20%20storeConfig%20%7B%0A%20%20%20%20%20%20%20%20store_code,%0A%20%20%20%20%20%20%20%20default_title,%0A%20%20%20%20%20%20%20%20store_name,%0A%20%20%20%20%20%20%20%20default_display_currency_code,%0A%20%20%20%20%20%20%20%20locale,%0A%20%20%20%20%20%20%20%20header_logo_src,%0A%20%20%20%20%20%20%20%20logo_width,%0A%20%20%20%20%20%20%20%20logo_height,%0A%20%20%20%20%20%20%20%20logo_alt%0A%20%20%20%20%7D%0A%20%20%7D&variables=%7B%7D&operationName=storeConfig'; diff --git a/packages/load-tests/src/tests/magento/addSimpleProductToCart.js b/packages/load-tests/src/tests/magento/addSimpleProductToCart.js new file mode 100644 index 000000000..9f6de3f65 --- /dev/null +++ b/packages/load-tests/src/tests/magento/addSimpleProductToCart.js @@ -0,0 +1,52 @@ +// Creator: k6 Browser Recorder 0.6.2 (+ handmade cleanups) +import { group, check } from 'k6'; +import http from 'k6/http'; + +import getHeaders from './utils/getHeaders.js'; +import { AddProductsToCart } from '../../mutation/addProductsToCart.js'; +import CreateEmptyGuestCart from './createEmptyGuestCart.js'; + +/** + * @type {import('k6/options').Options} + */ +export const options = { + vus: 150, + duration: '1m', +}; + +const { BASE_URL } = __ENV; +let response; + +if (BASE_URL === undefined) { + throw new Error('BASE_URL is not set'); +} + +export default function main() { + const params = { + headers: getHeaders(), + }; + + group('[Magento] addSimpleProductToGuestCart', () => { + const { cartId } = CreateEmptyGuestCart(); + + group('add a simple product to the cart', () => { + response = http.post( + `${BASE_URL}`, + JSON.stringify({ + query: AddProductsToCart, + variables: { + cartId, + cartItems: [{ quantity: Math.floor(Math.random() * 10), sku: '24-WG02' }], + }, + }), + params, + ); + + check(response, { + 'is status 200': (r) => r.status === 200, + 'does not have errors': (r) => !r.json().errors, + 'includes cart data': (r) => r.body.includes('addProductsToCart'), + }); + }); + }); +} diff --git a/packages/load-tests/src/tests/magento/createCustomer.js b/packages/load-tests/src/tests/magento/createCustomer.js new file mode 100644 index 000000000..b4d7c831a --- /dev/null +++ b/packages/load-tests/src/tests/magento/createCustomer.js @@ -0,0 +1,51 @@ +// Creator: k6 Browser Recorder 0.6.2 (+ handmade cleanups) +import { group, check } from 'k6'; +import http from 'k6/http'; + +import getHeaders from './utils/getHeaders.js'; +import { CreateCustomer } from '../../mutation/createCustomer.js'; +import { customerData } from './utils/customerData.js'; + +/** + * @type {import('k6/options').Options} + */ +export const options = { + vus: 150, + duration: '1m', +}; + +const { BASE_URL } = __ENV; +let response; + +if (BASE_URL === undefined) { + throw new Error('BASE_URL is not set'); +} + +export default function main() { + const params = { + headers: getHeaders(), + }; + + group('[Magento] create a customer account', () => { + response = http.post( + `${BASE_URL}`, + JSON.stringify({ + query: CreateCustomer, + variables: { + input: { + email: customerData.getEmail(), + password: 'Abcd123!', + firstname: 'Load', + lastname: 'Test', + }, + }, + }), + params, + ); + + check(response, { + 'is status 200': (r) => r.status === 200, + 'does not have errors': (r) => !r.json().errors, + }); + }); +} diff --git a/packages/load-tests/src/tests/magento/createEmptyGuestCart.js b/packages/load-tests/src/tests/magento/createEmptyGuestCart.js new file mode 100644 index 000000000..64e850e4c --- /dev/null +++ b/packages/load-tests/src/tests/magento/createEmptyGuestCart.js @@ -0,0 +1,46 @@ +// Creator: k6 Browser Recorder 0.6.2 (+ handmade cleanups) +import { sleep, group, check } from 'k6'; +import http from 'k6/http'; + +import jsonpath from 'https://jslib.k6.io/jsonpath/1.0.2/index.js'; +import getHeaders from './utils/getHeaders.js'; +import { CreateEmptyCartMutation } from '../../mutation/createEmptyCart.js'; + +/** + * @type {import('k6/options').Options} + */ +export const options = { + vus: 150, + duration: '1m', +}; + +const { BASE_URL } = __ENV; +const vars = {}; +let response; +if (BASE_URL === undefined) { + throw new Error('BASE_URL is not set'); +} + +export default function main() { + const params = { + headers: getHeaders(), + }; + + group('[Magento] create an empty cart', () => { + response = http.post( + `${BASE_URL}`, + JSON.stringify({ query: CreateEmptyCartMutation }), + params, + ); + sleep(0.2); + [vars.cartId] = jsonpath.query(response.json(), '$.data.createEmptyCart'); + + check(response, { + 'is status 200': (r) => r.status === 200, + 'does not have errors': (r) => !r.json().errors, + 'includes cart id': () => vars.cartId, + }); + }); + + return { cartId: vars.cartId }; +} diff --git a/packages/load-tests/src/tests/magento/storeConfig.js b/packages/load-tests/src/tests/magento/storeConfig.js new file mode 100644 index 000000000..1e1285d92 --- /dev/null +++ b/packages/load-tests/src/tests/magento/storeConfig.js @@ -0,0 +1,41 @@ +// Creator: k6 Browser Recorder 0.6.2 (+ handmade cleanups) +import { sleep, check, group } from 'k6'; +import http from 'k6/http'; + +import getHeaders from './utils/getHeaders.js'; +import { StoreConfigQueryString } from '../../query/storeConfig.gql.js'; + +/** + * @type {import('k6/options').Options} + */ +export const options = { + vus: 150, + duration: '1m', +}; + +const { BASE_URL } = __ENV; + +if (BASE_URL === undefined) { + throw new Error('BASE_URL is not set'); +} + +export default function main() { + const params = { + headers: getHeaders(), + }; + + group('[Magento] storeConfig', () => { + const response = http.get( + `${BASE_URL}/graphql?${StoreConfigQueryString}`, + params, + ); + + sleep(0.5); + + check(response, { + 'is status 200': (r) => r.status === 200, + 'does not have errors': (r) => !r.json().errors, + 'includes storeConfig data': (r) => r.body.includes('storeConfig'), + }); + }); +} diff --git a/packages/load-tests/src/tests/magento/utils/customerData.js b/packages/load-tests/src/tests/magento/utils/customerData.js new file mode 100644 index 000000000..59ed2defb --- /dev/null +++ b/packages/load-tests/src/tests/magento/utils/customerData.js @@ -0,0 +1,16 @@ +const chars = 'abcdefghijklmnopqrstuvwxyz1234567890'; + +export const getEmail = (length = 15) => { + let string = ''; + for (let i = 0; i < length; i++) { + string += chars[Math.floor(Math.random() * chars.length)]; + } + + return `${string}@gmail.com`; +}; + +export const customerData = { + getEmail, +}; + +export default customerData; diff --git a/packages/load-tests/src/tests/magento/utils/getHeaders.js b/packages/load-tests/src/tests/magento/utils/getHeaders.js new file mode 100644 index 000000000..7f21f7703 --- /dev/null +++ b/packages/load-tests/src/tests/magento/utils/getHeaders.js @@ -0,0 +1,5 @@ +const getHeaders = () => ({ + 'Content-Type': 'application/json', +}); + +export default getHeaders; diff --git a/packages/load-tests/src/tests/middleware/createCustomer.js b/packages/load-tests/src/tests/middleware/createCustomer.js new file mode 100644 index 000000000..c85a174ce --- /dev/null +++ b/packages/load-tests/src/tests/middleware/createCustomer.js @@ -0,0 +1,48 @@ +// Creator: k6 Browser Recorder 0.6.2 (+ handmade cleanups) +import { sleep, group, check } from 'k6'; +import http from 'k6/http'; + +import getHeaders from './utils/getHeaders.js'; +import { customerData } from './utils/customerData.js'; + +/** + * @type {import('k6/options').Options} + */ +export const options = { + vus: 150, + duration: '1m', +}; + +const { BASE_URL } = __ENV; +let response; + +if (BASE_URL === undefined) { + throw new Error('BASE_URL is not set'); +} + +export default function main() { + const params = { + headers: getHeaders(), + }; + + group('[Middleware] create a customer account', () => { + response = http.post( + `${BASE_URL}/magento/createCustomer`, + JSON.stringify([{ + email: customerData.getEmail(), + password: 'Abcd123!', + firstname: 'Load', + lastname: 'Test', + recaptchaToken: '12345', + }]), + params, + ); + + sleep(2); + + check(response, { + 'is status 200': (r) => r.status === 200, + 'does not have errors': (r) => !r.json().errors, + }); + }); +} diff --git a/packages/load-tests/src/tests/middleware/createEmptyGuestCart.js b/packages/load-tests/src/tests/middleware/createEmptyGuestCart.js new file mode 100644 index 000000000..6eae6a2f0 --- /dev/null +++ b/packages/load-tests/src/tests/middleware/createEmptyGuestCart.js @@ -0,0 +1,47 @@ +// Creator: k6 Browser Recorder 0.6.2 (+ handmade cleanups) +import { sleep, group, check } from 'k6'; +import http from 'k6/http'; + +import jsonpath from 'https://jslib.k6.io/jsonpath/1.0.2/index.js'; +import getHeaders from './utils/getHeaders.js'; + +/** + * @type {import('k6/options').Options} + */ +export const options = { + vus: 1, + duration: '1s', +}; + +const { BASE_URL } = __ENV; +const vars = {}; +let response; +if (BASE_URL === undefined) { + throw new Error('BASE_URL is not set'); +} + +export default function main() { + const params = { + headers: getHeaders(), + }; + + group('[Middleware] create an empty cart', () => { + response = http.post( + `${BASE_URL}/magento/createEmptyCart`, + '[]', + params, + ); + + sleep(1); + + [vars.cartId] = jsonpath.query(response.json(), '$.data.createEmptyCart'); + + check(response, { + 'is status 200': (r) => r.status === 200, + 'does not have errors': (r) => !r.json().errors, + 'includes cart id': () => vars.cartId, + }); + }); + + return { cartId: vars.cartId }; +} diff --git a/packages/load-tests/src/tests/middleware/storeConfig.js b/packages/load-tests/src/tests/middleware/storeConfig.js new file mode 100644 index 000000000..96a128a89 --- /dev/null +++ b/packages/load-tests/src/tests/middleware/storeConfig.js @@ -0,0 +1,40 @@ +// Creator: k6 Browser Recorder 0.6.2 (+ handmade cleanups) +import { sleep, check, group } from 'k6'; +import http from 'k6/http'; +import getHeaders from './utils/getHeaders.js'; + +/** + * @type {import('k6/options').Options} + */ +export const options = { + vus: 150, + duration: '1m', +}; + +const { BASE_URL } = __ENV; + +if (BASE_URL === undefined) { + throw new Error('BASE_URL is not set'); +} + +export default function main() { + const params = { + headers: getHeaders(), + }; + + group('[Middleware] storeConfig', () => { + const response = http.post( + `${BASE_URL}/git magento/customQuery`, + '[{"query":"\\n query storeConfig {\\n storeConfig {\\n store_code,\\n default_title,\\n store_name,\\n default_display_currency_code,\\n locale,\\n header_logo_src,\\n logo_width,\\n logo_height,\\n logo_alt\\n }\\n }\\n"}]', + params, + ); + + sleep(0.5); + + check(response, { + 'is status 200': (r) => r.status === 200, + 'does not have errors': (r) => !r.json().errors, + 'includes storeConfig data': (r) => r.body.includes('storeConfig'), + }); + }); +} diff --git a/packages/load-tests/src/tests/middleware/utils/customerData.js b/packages/load-tests/src/tests/middleware/utils/customerData.js new file mode 100644 index 000000000..59ed2defb --- /dev/null +++ b/packages/load-tests/src/tests/middleware/utils/customerData.js @@ -0,0 +1,16 @@ +const chars = 'abcdefghijklmnopqrstuvwxyz1234567890'; + +export const getEmail = (length = 15) => { + let string = ''; + for (let i = 0; i < length; i++) { + string += chars[Math.floor(Math.random() * chars.length)]; + } + + return `${string}@gmail.com`; +}; + +export const customerData = { + getEmail, +}; + +export default customerData; diff --git a/packages/load-tests/src/tests/middleware/utils/getHeaders.js b/packages/load-tests/src/tests/middleware/utils/getHeaders.js new file mode 100644 index 000000000..b70f2919c --- /dev/null +++ b/packages/load-tests/src/tests/middleware/utils/getHeaders.js @@ -0,0 +1,7 @@ +const getHeaders = () => ({ + 'content-type': 'application/json', + accept: 'application/json, text/plain, */*', + cookie: 'vsf-store=default; vsf-locale=default; vsf-currency=USD', +}); + +export default getHeaders; diff --git a/packages/load-tests/src/utils/getCookies.js b/packages/load-tests/src/utils/getCookies.js new file mode 100644 index 000000000..fefd5d14f --- /dev/null +++ b/packages/load-tests/src/utils/getCookies.js @@ -0,0 +1,7 @@ +const getCookies = () => ({ + 'vsf-store': 'default', + 'vsf-locale': 'default', + 'vsf-currency': 'USD', +}); + +export default getCookies; From f40cbbd0124b4e2f579334740aa0b7029c43653a Mon Sep 17 00:00:00 2001 From: Artur Tagisow Date: Fri, 22 Jul 2022 14:16:22 +0200 Subject: [PATCH 26/89] ci: stop using personal access token for deployment api our approach to reporting deployment status changed so we no longer need the personal access token workaround. In the past, it was needed because the deploy-template.yml workflow was called by the parent deploy-vue-storefront-cloud workflow, which is prevented by: https://github.com/chrnorm/deployment-action/tree/3afecce166a0a2f92d3a9e7351a9908a72121c24#notes using a personal access token is also not secure since if stolen it could be used to push to the deployment status of every repo I have access to (including vsf org). --- .github/workflows/deploy-vue-storefront-cloud.yml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy-vue-storefront-cloud.yml b/.github/workflows/deploy-vue-storefront-cloud.yml index fdd14e225..7f807a837 100644 --- a/.github/workflows/deploy-vue-storefront-cloud.yml +++ b/.github/workflows/deploy-vue-storefront-cloud.yml @@ -10,6 +10,10 @@ on: jobs: create-deployment: runs-on: ubuntu-latest + + permissions: + deployments: write + outputs: environment-name: ${{ steps.determine-environment.outputs.name }} environment-code: ${{ steps.determine-environment.outputs.code }} @@ -55,7 +59,7 @@ jobs: id: deployment uses: chrnorm/deployment-action@v2 with: - token: ${{ secrets.DEPLOYMENT_PERSONAL_ACCESS_TOKEN }} + token: ${{ github.token }} environment: ${{ steps.determine-environment.outputs.name }} initial-status: in_progress build: @@ -130,6 +134,10 @@ jobs: finalize-deployment: runs-on: ubuntu-latest + + permissions: + deployments: write + needs: [create-deployment, build, deploy] if: always() steps: @@ -137,7 +145,7 @@ jobs: if: ${{ !(contains(join(needs.*.result, ','), 'failure') || contains(join(needs.*.result, ','), 'cancelled')) }} uses: chrnorm/deployment-status@v2 with: - token: ${{ secrets.DEPLOYMENT_PERSONAL_ACCESS_TOKEN }} + token: ${{ github.token }} deployment-id: ${{ needs.create-deployment.outputs.deployment_id }} state: success @@ -145,6 +153,6 @@ jobs: if: ${{ contains(join(needs.*.result, ','), 'failure') || contains(join(needs.*.result, ','), 'cancelled') }} uses: chrnorm/deployment-status@v2 with: - token: ${{ secrets.DEPLOYMENT_PERSONAL_ACCESS_TOKEN }} + token: ${{ github.token }} deployment-id: ${{ needs.create-deployment.outputs.deployment_id }} state: failure From daadd6d042e2c1210f6785fa1b05efe452d22ddf Mon Sep 17 00:00:00 2001 From: Bartosz Herba Date: Mon, 18 Jul 2022 10:01:49 +0200 Subject: [PATCH 27/89] fix: product review form offscreen issue --- .../catalog/product/components/ProductAddReviewForm.vue | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/theme/modules/catalog/product/components/ProductAddReviewForm.vue b/packages/theme/modules/catalog/product/components/ProductAddReviewForm.vue index 92bedc9b8..f04bc17fb 100644 --- a/packages/theme/modules/catalog/product/components/ProductAddReviewForm.vue +++ b/packages/theme/modules/catalog/product/components/ProductAddReviewForm.vue @@ -308,6 +308,12 @@ export default defineComponent({ margin-right: 0; margin-bottom: 0; } + textarea { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + width: 100%; + } } } } From 5e332e37c277f2eeefdcdc39e60cfc4c94d28c78 Mon Sep 17 00:00:00 2001 From: Shankar Konar Date: Mon, 25 Jul 2022 14:17:57 +0530 Subject: [PATCH 28/89] fix: feedback changes --- .../modules/catalog/product/components/ProductAddReviewForm.vue | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/theme/modules/catalog/product/components/ProductAddReviewForm.vue b/packages/theme/modules/catalog/product/components/ProductAddReviewForm.vue index f04bc17fb..173aa0613 100644 --- a/packages/theme/modules/catalog/product/components/ProductAddReviewForm.vue +++ b/packages/theme/modules/catalog/product/components/ProductAddReviewForm.vue @@ -309,8 +309,6 @@ export default defineComponent({ margin-bottom: 0; } textarea { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; box-sizing: border-box; width: 100%; } From f1505e536b296322a0b4c6180e641164cf2d0484 Mon Sep 17 00:00:00 2001 From: Shankar Konar Date: Fri, 22 Jul 2022 20:42:27 +0530 Subject: [PATCH 29/89] fix: command correction according to markshust script --- docs/installation-setup/configure-magento.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/installation-setup/configure-magento.md b/docs/installation-setup/configure-magento.md index f394b7eff..5fb5d71a2 100644 --- a/docs/installation-setup/configure-magento.md +++ b/docs/installation-setup/configure-magento.md @@ -70,11 +70,11 @@ For security reasons, Magento 2, by default, allows maximum GraphQL query comple To install the Magento 2 GraphQL Config module, run the following commands on your Magento installation: ```bash -composer require caravelx/module-graphql-config -php bin/magento module:enable Caravel_GraphQlConfig -php bin/magento setup:upgrade -php bin/magento setup:di:compile -php bin/magento setup:static-content:deploy +bin/composer require caravelx/module-graphql-config +bin/magento module:enable Caravel_GraphQlConfig +bin/magento setup:upgrade +bin/magento setup:di:compile +bin/magento setup:static-content:deploy -f ``` Then go to the admin panel, find the configuration panel of the `GraphQL CustomConfig` module, and set: From aa47addc6e94df1827799554ec708e14f042467c Mon Sep 17 00:00:00 2001 From: Bartosz Herba Date: Mon, 25 Jul 2022 13:45:21 +0200 Subject: [PATCH 30/89] test: browsing product load test --- .eslintignore | 1 + .../src/scenarios/browsingProduct.js | 298 ++++++++++++++ .../load-tests/src/scenarios/searchProduct.js | 370 ------------------ .../src/scenarios/utils/setDefaultCookies.js | 8 + 4 files changed, 307 insertions(+), 370 deletions(-) create mode 100644 packages/load-tests/src/scenarios/browsingProduct.js delete mode 100644 packages/load-tests/src/scenarios/searchProduct.js create mode 100644 packages/load-tests/src/scenarios/utils/setDefaultCookies.js diff --git a/.eslintignore b/.eslintignore index 0fc6ca764..2a24330f7 100755 --- a/.eslintignore +++ b/.eslintignore @@ -5,4 +5,5 @@ packages/api-client/server packages/composables packages/api-client/lib packages/theme/static/sw.js +packages/load-tests/* .eslintrc.js diff --git a/packages/load-tests/src/scenarios/browsingProduct.js b/packages/load-tests/src/scenarios/browsingProduct.js new file mode 100644 index 000000000..da6aa49f6 --- /dev/null +++ b/packages/load-tests/src/scenarios/browsingProduct.js @@ -0,0 +1,298 @@ +// Creator: k6 Browser Recorder 0.6.2 + +import { check, sleep, group } from 'k6'; +import http from 'k6/http'; + +import jsonpath from 'https://jslib.k6.io/jsonpath/1.0.2/index.js'; +import { setDefaultCookies } from './utils/setDefaultCookies.js'; + +export const options = { + vus: 200, + duration: '5m', + thresholds: { + http_req_failed: ['rate<0.01'], // http errors should be less than 1% + http_req_duration: ['p(80)<250'], // 80% of requests should be below 250ms + }, +}; + +const { BASE_URL } = __ENV; + +if (BASE_URL === undefined) { + throw new Error('BASE_URL is not set'); +} + +const headers = { + accept: 'application/json, text/plain, */*', + 'content-type': 'application/json', + 'upgrade-insecure-requests': '1', + 'sec-ch-ua': '".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"macOS"', +}; + +const executeCommonChecks = (res) => { + check(res, { + 'is status 200': (r) => r.status === 200, + 'has no errors': (r) => !r.json().errors, + }); +}; + +export default function main() { + let res; + + const vars = {}; + setDefaultCookies(BASE_URL); + + group('Browsing for a product', () => { + group('Visit the homepage', () => { + res = http.get( + `${BASE_URL}/default`, + { + headers, + }, + ); + + check(res, { + 'is status 200': (r) => r.status === 200, + }); + + sleep(0.9); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + '[{"query":"\\n query storeConfig {\\n storeConfig {\\n store_code,\\n default_title,\\n store_name,\\n default_display_currency_code,\\n locale,\\n header_logo_src,\\n logo_width,\\n logo_height,\\n logo_alt\\n }\\n }\\n"}]', + { + headers, + }, + ); + + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + '[{"query":"\\n query getStoresAndCurrencies {\\n availableStores {\\n store_code\\n }\\n currency {\\n available_currency_codes\\n }\\n }\\n"}]', + { + headers, + }, + ); + + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + '[{"query":"\\n query getStoresAndCurrencies {\\n availableStores {\\n store_code\\n }\\n currency {\\n available_currency_codes\\n }\\n }\\n"}]', + { + headers, + }, + ); + + executeCommonChecks(res); + + sleep(2.2); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + '[{"query":"\\n query categoryList {\\n categories {\\n items {\\n ...CategoryFields\\n children {\\n ...CategoryFields\\n children {\\n ...CategoryFields\\n children {\\n ...CategoryFields\\n }\\n }\\n }\\n }\\n }\\n }\\n \\n fragment CategoryFields on CategoryTree {\\n is_anchor\\n name\\n position\\n product_count\\n uid\\n url_path\\n url_suffix\\n include_in_menu\\n }\\n\\n"}]', + { + headers, + }, + ); + + executeCommonChecks(res); + }); + + group('Go to the Men category page', () => { + res = http.post( + `${BASE_URL}/api/magento/route`, + '["/men.html",null]', + { + headers, + }, + ); + check(res, { + 'is status 200': (r) => r.status === 200, + }); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + '[{"query":"\\n query categoryList {\\n categories {\\n items {\\n ...CategoryFields\\n children {\\n ...CategoryFields\\n children {\\n ...CategoryFields\\n children {\\n ...CategoryFields\\n }\\n }\\n }\\n }\\n }\\n }\\n \\n fragment CategoryFields on CategoryTree {\\n is_anchor\\n name\\n position\\n product_count\\n uid\\n url_path\\n url_suffix\\n include_in_menu\\n }\\n\\n"}]', + { + headers, + }, + ); + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + '[{"query":"\\n query getCategoryContentData($filters: CategoryFilterInput) {\\n categoryList(filters: $filters) {\\n uid\\n display_mode\\n landing_page\\n cms_block {\\n identifier\\n content\\n }\\n }\\n }\\n","queryVariables":{"filters":{"category_uid":{"eq":"MTE="}}}}]', + { + headers, + }, + ); + executeCommonChecks(res); + + [vars.uid1] = jsonpath.query(res.json(), '$.data.categoryList[0].uid'); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + `[{"query":"\\n query getFacetData($search: String = \\"\\", $filter: ProductAttributeFilterInput, $pageSize: Int = 10, $currentPage: Int = 1, $sort: ProductAttributeSortInput) {\\n products(search: $search, filter: $filter, pageSize: $pageSize, currentPage: $currentPage, sort: $sort) {\\n items {\\n __typename\\n uid\\n sku\\n name\\n stock_status\\n only_x_left_in_stock\\n thumbnail {\\n url\\n position\\n disabled\\n label\\n }\\n url_key\\n url_rewrites {\\n url\\n }\\n price_range {\\n maximum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n minimum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n }\\n }\\n page_info {\\n current_page\\n page_size\\n total_pages\\n }\\n total_count\\n }\\n }\\n","queryVariables":{"pageSize":10,"search":"","filter":{"category_uid":{"in":["${vars.uid1}"]}},"sort":{},"currentPage":1}}]`, + { + headers, + }, + ); + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + `[{"query":"\\n query getProductFiltersByCategory($categoryIdFilter: FilterEqualTypeInput!) {\\n products(filter: { category_uid: $categoryIdFilter }) {\\n aggregations {\\n label\\n count\\n attribute_code\\n options {\\n count\\n label\\n value\\n __typename\\n }\\n position\\n __typename\\n }\\n __typename\\n }\\n }\\n","queryVariables":{"categoryIdFilter":{"eq":"${vars.uid1}"}}}]`, + { + headers, + }, + ); + executeCommonChecks(res); + sleep(3); + }); + + group('Sort by name ASC', () => { + res = http.post( + `${BASE_URL}/api/magento/route`, + '["/men.html",null]', + { + headers, + }, + ); + check(res, { + 'is status 200': (r) => r.status === 200, + }); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + `[{"query":"\\n query getCategoryContentData($filters: CategoryFilterInput) {\\n categoryList(filters: $filters) {\\n uid\\n display_mode\\n landing_page\\n cms_block {\\n identifier\\n content\\n }\\n }\\n }\\n","queryVariables":{"filters":{"category_uid":{"eq":"${vars.uid1}"}}}}]`, + { + headers, + }, + ); + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + `[{"query":"\\n query getFacetData($search: String = \\"\\", $filter: ProductAttributeFilterInput, $pageSize: Int = 10, $currentPage: Int = 1, $sort: ProductAttributeSortInput) {\\n products(search: $search, filter: $filter, pageSize: $pageSize, currentPage: $currentPage, sort: $sort) {\\n items {\\n __typename\\n uid\\n sku\\n name\\n stock_status\\n only_x_left_in_stock\\n thumbnail {\\n url\\n position\\n disabled\\n label\\n }\\n url_key\\n url_rewrites {\\n url\\n }\\n price_range {\\n maximum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n minimum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n }\\n }\\n page_info {\\n current_page\\n page_size\\n total_pages\\n }\\n total_count\\n }\\n }\\n","queryVariables":{"pageSize":10,"search":"","filter":{"category_uid":{"in":["${vars.uid1}"]}},"sort":{"name":"DESC"},"currentPage":1}}]`, + { + headers, + }, + ); + executeCommonChecks(res); + sleep(3); + }); + + group('Sort by Price ASC', () => { + res = http.post( + `${BASE_URL}/api/magento/route`, + '["/men.html",null]', + { + headers, + }, + ); + check(res, { + 'is status 200': (r) => r.status === 200, + }); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + `[{"query":"\\n query getCategoryContentData($filters: CategoryFilterInput) {\\n categoryList(filters: $filters) {\\n uid\\n display_mode\\n landing_page\\n cms_block {\\n identifier\\n content\\n }\\n }\\n }\\n","queryVariables":{"filters":{"category_uid":{"eq":"${vars.uid1}"}}}}]`, + { + headers, + }, + ); + executeCommonChecks(res); + [vars.uid2] = jsonpath.query(res.json(), '$.data.categoryList[0].uid'); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + `[{"query":"\\n query getFacetData($search: String = \\"\\", $filter: ProductAttributeFilterInput, $pageSize: Int = 10, $currentPage: Int = 1, $sort: ProductAttributeSortInput) {\\n products(search: $search, filter: $filter, pageSize: $pageSize, currentPage: $currentPage, sort: $sort) {\\n items {\\n __typename\\n uid\\n sku\\n name\\n stock_status\\n only_x_left_in_stock\\n thumbnail {\\n url\\n position\\n disabled\\n label\\n }\\n url_key\\n url_rewrites {\\n url\\n }\\n price_range {\\n maximum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n minimum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n }\\n }\\n page_info {\\n current_page\\n page_size\\n total_pages\\n }\\n total_count\\n }\\n }\\n","queryVariables":{"pageSize":10,"search":"","filter":{"category_uid":{"in":["${vars.uid1}"]}},"sort":{"price":"ASC"},"currentPage":1}}]`, + { + headers, + }, + ); + executeCommonChecks(res); + sleep(3); + }); + + group('Filter list by the price', () => { + res = http.post( + `${BASE_URL}/api/magento/route`, + '["/men.html",null]', + { + headers, + }, + ); + check(res, { + 'is status 200': (r) => r.status === 200, + }); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + `[{"query":"\\n query getCategoryContentData($filters: CategoryFilterInput) {\\n categoryList(filters: $filters) {\\n uid\\n display_mode\\n landing_page\\n cms_block {\\n identifier\\n content\\n }\\n }\\n }\\n","queryVariables":{"filters":{"category_uid":{"eq":"${vars.uid2}"}}}}]`, + { + headers, + }, + ); + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + `[{"query":"\\n query getFacetData($search: String = \\"\\", $filter: ProductAttributeFilterInput, $pageSize: Int = 10, $currentPage: Int = 1, $sort: ProductAttributeSortInput) {\\n products(search: $search, filter: $filter, pageSize: $pageSize, currentPage: $currentPage, sort: $sort) {\\n items {\\n __typename\\n uid\\n sku\\n name\\n stock_status\\n only_x_left_in_stock\\n thumbnail {\\n url\\n position\\n disabled\\n label\\n }\\n url_key\\n url_rewrites {\\n url\\n }\\n price_range {\\n maximum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n minimum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n }\\n }\\n page_info {\\n current_page\\n page_size\\n total_pages\\n }\\n total_count\\n }\\n }\\n","queryVariables":{"pageSize":10,"search":"","filter":{"price":{"from":40,"to":50},"category_uid":{"in":["${vars.uid2}"]}},"sort":{"price":"ASC"},"currentPage":1}}]`, + { + headers, + }, + ); + executeCommonChecks(res); + sleep(1.6); + }); + + group('Visit selected product', () => { + res = http.post( + `${BASE_URL}/api/magento/productDetail`, + '[{"filter":{"sku":{"eq":"MH06"}},"configurations":[]},{"productDetail":"productDetail"}]', + { + headers, + }, + ); + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + '[{"query":"\\n query getProductPriceBySku(\\n $filter: ProductAttributeFilterInput,\\n $configurations: [ID!]\\n ) {\\n products(filter: $filter) {\\n items {\\n price_range {\\n ...PriceRangeFields\\n }\\n\\n ... on ConfigurableProduct {\\n price_range {\\n maximum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n minimum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n }\\n\\n configurable_product_options_selection(configurableOptionValueUids: $configurations) {\\n options_available_for_selection {\\n attribute_code\\n option_value_uids\\n }\\n media_gallery {\\n disabled\\n label\\n position\\n url\\n }\\n variant {\\n uid\\n sku\\n name\\n price_range {\\n ...PriceRangeFields\\n }\\n }\\n }\\n }\\n\\n ... on BundleProduct {\\n items {\\n position\\n required\\n sku\\n title\\n type\\n uid\\n options {\\n can_change_quantity\\n is_default\\n position\\n uid\\n quantity\\n product {\\n uid\\n sku\\n name\\n price_range {\\n ...PriceRangeFields\\n }\\n }\\n }\\n }\\n }\\n\\n ... on GroupedProduct {\\n items {\\n position\\n qty\\n product {\\n uid\\n sku\\n name\\n stock_status\\n only_x_left_in_stock\\n price_range {\\n maximum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n minimum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n }\\n thumbnail {\\n url\\n position\\n disabled\\n label\\n }\\n }\\n }\\n }\\n\\n }\\n }\\n }\\n \\n fragment PriceRangeFields on PriceRange {\\n maximum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n minimum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n }\\n\\n","queryVariables":{"filter":{"sku":{"eq":"MH06"}},"configurations":[]}}]', + { + headers, + }, + ); + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/upsellProduct`, + '[{"filter":{"sku":{"eq":"MH06"}}},null]', + { + headers, + }, + ); + + res = http.post( + `${BASE_URL}/api/magento/relatedProduct`, + '[{"filter":{"sku":{"eq":"MH06"}}},null]', + { + headers, + }, + ); + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/productReviewRatingsMetadata`, + '[null]', + { + headers, + }, + ); + }); + }); +} diff --git a/packages/load-tests/src/scenarios/searchProduct.js b/packages/load-tests/src/scenarios/searchProduct.js deleted file mode 100644 index c7384d1fc..000000000 --- a/packages/load-tests/src/scenarios/searchProduct.js +++ /dev/null @@ -1,370 +0,0 @@ -// Creator: k6 Browser Recorder 0.6.2 (+ handmade cleanups) -import { sleep, group } from 'k6'; -import http from 'k6/http'; - -import jsonpath from 'https://jslib.k6.io/jsonpath/1.0.2/index.js'; - -/** - * @type {import('k6/options').Options} - */ -export const options = { - vus: 200, - duration: '5m', - ext: { - loadimpact: { - name: 'Search products', - note: 'Guest user browsing through a product', - // eslint-disable-next-line unicorn/numeric-separators-style - projectID: 3591701, - }, - }, -}; - -const { BASE_URL } = __ENV; - -if (BASE_URL === undefined) { - throw new Error('BASE_URL is not set'); -} - -export default function main() { - let response; - - const vars = {}; - - group(`page_1 - ${BASE_URL}/default`, () => { - response = http.get(`${BASE_URL}/default`); - sleep(0.5); - - response = http.post( - `${BASE_URL}/api/magento/customQuery`, - `[{"query":" - query storeConfig { - storeConfig { - store_code, - default_title, - store_name, - default_display_currency_code, - locale, - header_logo_src, - logo_width, - logo_height, - logo_alt - } - } -"}]`, - ); - - response = http.post( - `${BASE_URL}/api/magento/customQuery`, - `[{"query":" - query getStoresAndCurrencies { - availableStores { - store_code - } - currency { - available_currency_codes - } - } -"}]`, - ); - sleep(2.6); - - response = http.post( - `${BASE_URL}/api/magento/route`, - '["/women/tops-women/jackets-women.html",null]', - ); - - [vars.uid1] = jsonpath.query(response.json(), '$.data.route.uid'); - - response = http.post( - `${BASE_URL}/api/magento/customQuery`, - `[{"query":" - query categoryList { - categories { - items { - ...CategoryFields - children { - ...CategoryFields - children { - ...CategoryFields - children { - ...CategoryFields - } - } - } - } - } - } - - fragment CategoryFields on CategoryTree { - is_anchor - name - position - product_count - uid - url_path - url_suffix - include_in_menu - } - -"}]`, - ); - - response = http.post( - `${BASE_URL}/api/magento/customQuery`, - `[{"query":" - query getCategoryContentData($filters: CategoryFilterInput) { - categoryList(filters: $filters) { - uid - display_mode - landing_page - cms_block { - identifier - content - } - } - } -","queryVariables":{"filters":{"category_uid":{"eq":"${vars.uid1}"}}}}]`, - ); - - response = http.post( - `${BASE_URL}/api/magento/customQuery`, - `[{"query":" - query getFacetData($search: String = \\"\\", $filter: ProductAttributeFilterInput, $pageSize: Int = 10, $currentPage: Int = 1, $sort: ProductAttributeSortInput) { - products(search: $search, filter: $filter, pageSize: $pageSize, currentPage: $currentPage, sort: $sort) { - items { - __typename - uid - sku - name - stock_status - only_x_left_in_stock - thumbnail { - url - position - disabled - label - } - url_key - url_rewrites { - url - } - price_range { - maximum_price { - final_price { - currency - value - } - regular_price { - currency - value - } - } - minimum_price { - final_price { - currency - value - } - regular_price { - currency - value - } - } - } - } - page_info { - current_page - page_size - total_pages - } - total_count - } - } -","queryVariables":{"pageSize":10,"search":"","filter":{"category_uid":{"in":["${vars.uid1}"]}},"sort":{},"currentPage":1}}]`, - ); - sleep(0.5); - - response = http.post( - `${BASE_URL}/api/magento/customQuery`, - `[{"query":" - query getProductFiltersByCategory($categoryIdFilter: FilterEqualTypeInput!) { - products(filter: { category_uid: $categoryIdFilter }) { - aggregations { - label - count - attribute_code - options { - count - label - value - __typename - } - position - __typename - } - __typename - } - } -","queryVariables":{"categoryIdFilter":{"eq":"${vars.uid1}"}}}]`, - ); - sleep(1.8); - - response = http.post( - `${BASE_URL}/api/magento/productDetail`, - '[{"filter":{"sku":{"eq":"WJ12"}},"configurations":[]},{"productDetail":"productDetail"}]', - ); - - response = http.post( - `${BASE_URL}/api/magento/customQuery`, - `[{"query":" - query getProductPriceBySku($sku: String) { - products(filter: {sku: {eq: $sku}}) { - items { - price_range { - ...PriceRangeFields - } - - ... on BundleProduct { - items { - position - required - sku - title - type - uid - options { - can_change_quantity - is_default - position - uid - quantity - product { - uid - sku - name - price_range { - maximum_price { - final_price { - currency - value - } - regular_price { - currency - value - } - } - minimum_price { - final_price { - currency - value - } - regular_price { - currency - value - } - } - } - } - } - } - } - - ... on GroupedProduct { - items { - position - qty - product { - uid - sku - name - stock_status - only_x_left_in_stock - price_range { - maximum_price { - final_price { - currency - value - } - regular_price { - currency - value - } - } - minimum_price { - final_price { - currency - value - } - regular_price { - currency - value - } - } - } - thumbnail { - url - position - disabled - label - } - } - } - } - - } - } - } - - fragment PriceRangeFields on PriceRange { - maximum_price { - final_price { - currency - value - } - regular_price { - currency - value - } - } - minimum_price { - final_price { - currency - value - } - regular_price { - currency - value - } - } - } - -","queryVariables":{"sku":"WJ12"}}]`, - ); - - response = http.post( - `${BASE_URL}/api/magento/upsellProduct`, - '[{"filter":{"sku":{"eq":"WJ12"}}},null]', - ); - - response = http.post( - `${BASE_URL}/api/magento/relatedProduct`, - '[{"filter":{"sku":{"eq":"WJ12"}}},null]', - ); - - response = http.post( - `${BASE_URL}/api/magento/productReviewRatingsMetadata`, - '[null]', - ); - sleep(2.3); - - response = http.post( - `${BASE_URL}/api/magento/productReview`, - '[{"filter":{"sku":{"eq":"WJ12"}}},null]', - ); - - response = http.post( - `${BASE_URL}/api/magento/productReviewRatingsMetadata`, - '[null]', - ); - }); -} diff --git a/packages/load-tests/src/scenarios/utils/setDefaultCookies.js b/packages/load-tests/src/scenarios/utils/setDefaultCookies.js new file mode 100644 index 000000000..328461ac0 --- /dev/null +++ b/packages/load-tests/src/scenarios/utils/setDefaultCookies.js @@ -0,0 +1,8 @@ +import http from 'k6/http'; + +export const setDefaultCookies = (url) => { + const jar = http.cookieJar(); + jar.set(url, 'vsf-store', 'default'); + jar.set(url, 'vsf-locale', 'default'); + jar.set(url, 'vsf-currency', 'USD'); +}; From c35c3e14c9d57255f39be0b3eba7a8b3e9241e50 Mon Sep 17 00:00:00 2001 From: Bartosz Herba Date: Tue, 26 Jul 2022 08:43:58 +0200 Subject: [PATCH 31/89] test: add search product load tests --- .eslintignore | 1 - .../{ => tests}/scenarios/browsingProduct.js | 3 +- .../src/tests/scenarios/searchProduct.js | 125 ++++++++++++++++++ .../scenarios/utils/setDefaultCookies.js | 1 + 4 files changed, 127 insertions(+), 3 deletions(-) rename packages/load-tests/src/{ => tests}/scenarios/browsingProduct.js (99%) create mode 100644 packages/load-tests/src/tests/scenarios/searchProduct.js rename packages/load-tests/src/{ => tests}/scenarios/utils/setDefaultCookies.js (91%) diff --git a/.eslintignore b/.eslintignore index 2a24330f7..0fc6ca764 100755 --- a/.eslintignore +++ b/.eslintignore @@ -5,5 +5,4 @@ packages/api-client/server packages/composables packages/api-client/lib packages/theme/static/sw.js -packages/load-tests/* .eslintrc.js diff --git a/packages/load-tests/src/scenarios/browsingProduct.js b/packages/load-tests/src/tests/scenarios/browsingProduct.js similarity index 99% rename from packages/load-tests/src/scenarios/browsingProduct.js rename to packages/load-tests/src/tests/scenarios/browsingProduct.js index da6aa49f6..264bb2f0b 100644 --- a/packages/load-tests/src/scenarios/browsingProduct.js +++ b/packages/load-tests/src/tests/scenarios/browsingProduct.js @@ -42,8 +42,7 @@ export default function main() { const vars = {}; setDefaultCookies(BASE_URL); - - group('Browsing for a product', () => { + group(`Browsing for a product - page ${BASE_URL}`, () => { group('Visit the homepage', () => { res = http.get( `${BASE_URL}/default`, diff --git a/packages/load-tests/src/tests/scenarios/searchProduct.js b/packages/load-tests/src/tests/scenarios/searchProduct.js new file mode 100644 index 000000000..80fba2341 --- /dev/null +++ b/packages/load-tests/src/tests/scenarios/searchProduct.js @@ -0,0 +1,125 @@ +// Creator: k6 Browser Recorder 0.6.2 + +import { check, sleep, group } from 'k6'; +import http from 'k6/http'; +import { setDefaultCookies } from './utils/setDefaultCookies.js'; + +export const options = { + vus: 200, + duration: '5m', + thresholds: { + http_req_failed: ['rate<0.01'], // http errors should be less than 1% + http_req_duration: ['p(80)<250'], // 80% of requests should be below 250ms + }, +}; + +const { BASE_URL } = __ENV; + +if (BASE_URL === undefined) { + throw new Error('BASE_URL is not set'); +} + +const headers = { + accept: 'application/json, text/plain, */*', + 'content-type': 'application/json', + 'upgrade-insecure-requests': '1', + 'sec-ch-ua': '".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"macOS"', +}; + +const executeCommonChecks = (res) => { + check(res, { + 'is status 200': (r) => r.status === 200, + 'has no errors': (r) => !r.json().errors, + }); +}; + +export default function main() { + let res; + setDefaultCookies(BASE_URL); + + group( + `Search Product - page ${BASE_URL}`, + () => { + group('Visit the homepage', () => { + res = http.get( + `${BASE_URL}/default`, + { headers }, + ); + check(res, { + 'is status 200': (r) => r.status === 200, + }); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + '[{"query":"\\n query storeConfig {\\n storeConfig {\\n store_code,\\n default_title,\\n store_name,\\n default_display_currency_code,\\n locale,\\n header_logo_src,\\n logo_width,\\n logo_height,\\n logo_alt\\n }\\n }\\n"}]', + { headers }, + ); + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + '[{"query":"\\n query getStoresAndCurrencies {\\n availableStores {\\n store_code\\n }\\n currency {\\n available_currency_codes\\n }\\n }\\n"}]', + { headers }, + ); + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + '[{"query":"\\n query getStoresAndCurrencies {\\n availableStores {\\n store_code\\n }\\n currency {\\n available_currency_codes\\n }\\n }\\n"}]', + { headers }, + ); + executeCommonChecks(res); + sleep(4.1); + }); + + group('Search for a product', () => { + res = http.post( + `${BASE_URL}/api/magento/products`, + '[{"pageSize":12,"search":"erika"},{"products":"products"}]', + { headers }, + ); + executeCommonChecks(res); + sleep(1.9); + }); + + group('Visit the found product', () => { + res = http.post( + `${BASE_URL}/api/magento/productDetail`, + '[{"filter":{"sku":{"eq":"WSH12"}},"configurations":[]},{"productDetail":"productDetail"}]', + { headers }, + ); + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + '[{"query":"\\n query getProductPriceBySku(\\n $filter: ProductAttributeFilterInput,\\n $configurations: [ID!]\\n ) {\\n products(filter: $filter) {\\n items {\\n price_range {\\n ...PriceRangeFields\\n }\\n\\n ... on ConfigurableProduct {\\n price_range {\\n maximum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n minimum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n }\\n\\n configurable_product_options_selection(configurableOptionValueUids: $configurations) {\\n options_available_for_selection {\\n attribute_code\\n option_value_uids\\n }\\n media_gallery {\\n disabled\\n label\\n position\\n url\\n }\\n variant {\\n uid\\n sku\\n name\\n price_range {\\n ...PriceRangeFields\\n }\\n }\\n }\\n }\\n\\n ... on BundleProduct {\\n items {\\n position\\n required\\n sku\\n title\\n type\\n uid\\n options {\\n can_change_quantity\\n is_default\\n position\\n uid\\n quantity\\n product {\\n uid\\n sku\\n name\\n price_range {\\n ...PriceRangeFields\\n }\\n }\\n }\\n }\\n }\\n\\n ... on GroupedProduct {\\n items {\\n position\\n qty\\n product {\\n uid\\n sku\\n name\\n stock_status\\n only_x_left_in_stock\\n price_range {\\n maximum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n minimum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n }\\n thumbnail {\\n url\\n position\\n disabled\\n label\\n }\\n }\\n }\\n }\\n\\n }\\n }\\n }\\n \\n fragment PriceRangeFields on PriceRange {\\n maximum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n minimum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n }\\n\\n","queryVariables":{"filter":{"sku":{"eq":"WSH12"}},"configurations":[]}}]', + { headers }, + ); + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/relatedProduct`, + '[{"filter":{"sku":{"eq":"WSH12"}}},null]', + { headers }, + ); + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/upsellProduct`, + '[{"filter":{"sku":{"eq":"WSH12"}}},null]', + { headers }, + ); + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/productReviewRatingsMetadata`, + '[null]', + { headers }, + ); + executeCommonChecks(res); + }); + }, + ); +} diff --git a/packages/load-tests/src/scenarios/utils/setDefaultCookies.js b/packages/load-tests/src/tests/scenarios/utils/setDefaultCookies.js similarity index 91% rename from packages/load-tests/src/scenarios/utils/setDefaultCookies.js rename to packages/load-tests/src/tests/scenarios/utils/setDefaultCookies.js index 328461ac0..2b143868d 100644 --- a/packages/load-tests/src/scenarios/utils/setDefaultCookies.js +++ b/packages/load-tests/src/tests/scenarios/utils/setDefaultCookies.js @@ -1,3 +1,4 @@ +/* eslint-disable */ import http from 'k6/http'; export const setDefaultCookies = (url) => { From 03eb09fc114f472ffab4982f1d7e0c8701661f52 Mon Sep 17 00:00:00 2001 From: Bartosz Herba Date: Tue, 26 Jul 2022 11:35:53 +0200 Subject: [PATCH 32/89] test: add buy product as a guest user load test --- .../src/tests/magento/createCustomer.js | 2 +- .../tests/scenarios/buyProductAsAGuestUser.js | 448 ++++++++++++++++++ .../{tests/magento => }/utils/customerData.js | 0 3 files changed, 449 insertions(+), 1 deletion(-) create mode 100644 packages/load-tests/src/tests/scenarios/buyProductAsAGuestUser.js rename packages/load-tests/src/{tests/magento => }/utils/customerData.js (100%) diff --git a/packages/load-tests/src/tests/magento/createCustomer.js b/packages/load-tests/src/tests/magento/createCustomer.js index b4d7c831a..a382e3ab9 100644 --- a/packages/load-tests/src/tests/magento/createCustomer.js +++ b/packages/load-tests/src/tests/magento/createCustomer.js @@ -4,7 +4,7 @@ import http from 'k6/http'; import getHeaders from './utils/getHeaders.js'; import { CreateCustomer } from '../../mutation/createCustomer.js'; -import { customerData } from './utils/customerData.js'; +import { customerData } from '../../utils/customerData.js'; /** * @type {import('k6/options').Options} diff --git a/packages/load-tests/src/tests/scenarios/buyProductAsAGuestUser.js b/packages/load-tests/src/tests/scenarios/buyProductAsAGuestUser.js new file mode 100644 index 000000000..bf9437d8b --- /dev/null +++ b/packages/load-tests/src/tests/scenarios/buyProductAsAGuestUser.js @@ -0,0 +1,448 @@ +// Creator: k6 Browser Recorder 0.6.2 +import { check, sleep, group } from 'k6'; +import http from 'k6/http'; +import jsonpath from 'https://jslib.k6.io/jsonpath/1.0.2/index.js'; +import { setDefaultCookies } from './utils/setDefaultCookies.js'; + +export const options = { + vus: 200, + duration: '5m', + thresholds: { + http_req_failed: ['rate<0.01'], // http errors should be less than 1% + http_req_duration: ['p(80)<250'], // 80% of requests should be below 250ms + }, +}; + +const { BASE_URL } = __ENV; + +if (BASE_URL === undefined) { + throw new Error('BASE_URL is not set'); +} + +const headers = { + accept: 'application/json, text/plain, */*', + 'content-type': 'application/json', + 'upgrade-insecure-requests': '1', + 'sec-ch-ua': '".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"macOS"', +}; + +const executeCommonChecks = (res) => { + check(res, { + 'is status 200': (r) => r.status === 200, + 'has no errors': (r) => !r.json().errors, + }); +}; + +export default function main() { + let res; + + const vars = {}; + setDefaultCookies(BASE_URL); + + group(`Buy product as a guest user - page ${BASE_URL}`, () => { + group('Visit the homepage', () => { + res = http.get( + `${BASE_URL}/default`, + { + headers, + }, + ); + sleep(0.8); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + '[{"query":"\\n query storeConfig {\\n storeConfig {\\n store_code,\\n default_title,\\n store_name,\\n default_display_currency_code,\\n locale,\\n header_logo_src,\\n logo_width,\\n logo_height,\\n logo_alt\\n }\\n }\\n"}]', + { + headers, + }, + ); + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + '[{"query":"\\n query getStoresAndCurrencies {\\n availableStores {\\n store_code\\n }\\n currency {\\n available_currency_codes\\n }\\n }\\n"}]', + { + headers, + }, + ); + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + '[{"query":"\\n query getStoresAndCurrencies {\\n availableStores {\\n store_code\\n }\\n currency {\\n available_currency_codes\\n }\\n }\\n"}]', + { + headers, + }, + ); + executeCommonChecks(res); + sleep(2.7); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + '[{"query":"\\n query categoryList {\\n categories {\\n items {\\n ...CategoryFields\\n children {\\n ...CategoryFields\\n children {\\n ...CategoryFields\\n children {\\n ...CategoryFields\\n }\\n }\\n }\\n }\\n }\\n }\\n \\n fragment CategoryFields on CategoryTree {\\n is_anchor\\n name\\n position\\n product_count\\n uid\\n url_path\\n url_suffix\\n include_in_menu\\n }\\n\\n"}]', + { + headers, + }, + ); + executeCommonChecks(res); + }); + + group('Select the a category', () => { + res = http.post( + `${BASE_URL}/api/magento/route`, + '["/women.html",null]', + { + headers, + }, + ); + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + '[{"query":"\\n query categoryList {\\n categories {\\n items {\\n ...CategoryFields\\n children {\\n ...CategoryFields\\n children {\\n ...CategoryFields\\n children {\\n ...CategoryFields\\n }\\n }\\n }\\n }\\n }\\n }\\n \\n fragment CategoryFields on CategoryTree {\\n is_anchor\\n name\\n position\\n product_count\\n uid\\n url_path\\n url_suffix\\n include_in_menu\\n }\\n\\n"}]', + { + headers, + }, + ); + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + '[{"query":"\\n query getCategoryContentData($filters: CategoryFilterInput) {\\n categoryList(filters: $filters) {\\n uid\\n display_mode\\n landing_page\\n cms_block {\\n identifier\\n content\\n }\\n }\\n }\\n","queryVariables":{"filters":{"category_uid":{"eq":"MjA="}}}}]', + { + headers, + }, + ); + executeCommonChecks(res); + [vars.uid1] = jsonpath.query(res.json(), '$.data.categoryList[0].uid'); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + `[{"query":"\\n query getFacetData($search: String = \\"\\", $filter: ProductAttributeFilterInput, $pageSize: Int = 10, $currentPage: Int = 1, $sort: ProductAttributeSortInput) {\\n products(search: $search, filter: $filter, pageSize: $pageSize, currentPage: $currentPage, sort: $sort) {\\n items {\\n __typename\\n uid\\n sku\\n name\\n stock_status\\n only_x_left_in_stock\\n thumbnail {\\n url\\n position\\n disabled\\n label\\n }\\n url_key\\n url_rewrites {\\n url\\n }\\n price_range {\\n maximum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n minimum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n }\\n }\\n page_info {\\n current_page\\n page_size\\n total_pages\\n }\\n total_count\\n }\\n }\\n","queryVariables":{"pageSize":10,"search":"","filter":{"category_uid":{"in":["${vars.uid1}"]}},"sort":{},"currentPage":1}}]`, + { + headers, + }, + ); + executeCommonChecks(res); + sleep(0.5); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + `[{"query":"\\n query getProductFiltersByCategory($categoryIdFilter: FilterEqualTypeInput!) {\\n products(filter: { category_uid: $categoryIdFilter }) {\\n aggregations {\\n label\\n count\\n attribute_code\\n options {\\n count\\n label\\n value\\n __typename\\n }\\n position\\n __typename\\n }\\n __typename\\n }\\n }\\n","queryVariables":{"categoryIdFilter":{"eq":"${vars.uid1}"}}}]`, + { + headers, + }, + ); + executeCommonChecks(res); + sleep(2.1); + }); + + group('configure the product', () => { + res = http.post( + `${BASE_URL}/api/magento/productDetail`, + '[{"filter":{"sku":{"eq":"WSH11"}},"configurations":[]},{"productDetail":"productDetail"}]', + { + headers, + }, + ); + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + '[{"query":"\\n query getProductPriceBySku(\\n $filter: ProductAttributeFilterInput,\\n $configurations: [ID!]\\n ) {\\n products(filter: $filter) {\\n items {\\n price_range {\\n ...PriceRangeFields\\n }\\n\\n ... on ConfigurableProduct {\\n price_range {\\n maximum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n minimum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n }\\n\\n configurable_product_options_selection(configurableOptionValueUids: $configurations) {\\n options_available_for_selection {\\n attribute_code\\n option_value_uids\\n }\\n media_gallery {\\n disabled\\n label\\n position\\n url\\n }\\n variant {\\n uid\\n sku\\n name\\n price_range {\\n ...PriceRangeFields\\n }\\n }\\n }\\n }\\n\\n ... on BundleProduct {\\n items {\\n position\\n required\\n sku\\n title\\n type\\n uid\\n options {\\n can_change_quantity\\n is_default\\n position\\n uid\\n quantity\\n product {\\n uid\\n sku\\n name\\n price_range {\\n ...PriceRangeFields\\n }\\n }\\n }\\n }\\n }\\n\\n ... on GroupedProduct {\\n items {\\n position\\n qty\\n product {\\n uid\\n sku\\n name\\n stock_status\\n only_x_left_in_stock\\n price_range {\\n maximum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n minimum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n }\\n thumbnail {\\n url\\n position\\n disabled\\n label\\n }\\n }\\n }\\n }\\n\\n }\\n }\\n }\\n \\n fragment PriceRangeFields on PriceRange {\\n maximum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n minimum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n }\\n\\n","queryVariables":{"filter":{"sku":{"eq":"WSH11"}},"configurations":[]}}]', + { + headers, + }, + ); + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/upsellProduct`, + '[{"filter":{"sku":{"eq":"WSH11"}}},null]', + { + headers, + }, + ); + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/relatedProduct`, + '[{"filter":{"sku":{"eq":"WSH11"}}},null]', + { + headers, + }, + ); + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/productReviewRatingsMetadata`, + '[null]', + { + headers, + }, + ); + executeCommonChecks(res); + sleep(1.1); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + '[{"query":"\\n query getProductPriceBySku(\\n $filter: ProductAttributeFilterInput,\\n $configurations: [ID!]\\n ) {\\n products(filter: $filter) {\\n items {\\n price_range {\\n ...PriceRangeFields\\n }\\n\\n ... on ConfigurableProduct {\\n price_range {\\n maximum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n minimum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n }\\n\\n configurable_product_options_selection(configurableOptionValueUids: $configurations) {\\n options_available_for_selection {\\n attribute_code\\n option_value_uids\\n }\\n media_gallery {\\n disabled\\n label\\n position\\n url\\n }\\n variant {\\n uid\\n sku\\n name\\n price_range {\\n ...PriceRangeFields\\n }\\n }\\n }\\n }\\n\\n ... on BundleProduct {\\n items {\\n position\\n required\\n sku\\n title\\n type\\n uid\\n options {\\n can_change_quantity\\n is_default\\n position\\n uid\\n quantity\\n product {\\n uid\\n sku\\n name\\n price_range {\\n ...PriceRangeFields\\n }\\n }\\n }\\n }\\n }\\n\\n ... on GroupedProduct {\\n items {\\n position\\n qty\\n product {\\n uid\\n sku\\n name\\n stock_status\\n only_x_left_in_stock\\n price_range {\\n maximum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n minimum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n }\\n thumbnail {\\n url\\n position\\n disabled\\n label\\n }\\n }\\n }\\n }\\n\\n }\\n }\\n }\\n \\n fragment PriceRangeFields on PriceRange {\\n maximum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n minimum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n }\\n\\n","queryVariables":{"filter":{"sku":{"eq":"WSH11"}},"configurations":["Y29uZmlndXJhYmxlLzkzLzU4"]}}]', + { + headers, + }, + ); + executeCommonChecks(res); + + [vars.index01] = jsonpath.query( + res.json(), + '$.data.products.items[0].configurable_product_options_selection.options_available_for_selection[1].option_value_uids[0]', + ); + + [vars.index11] = jsonpath.query( + res.json(), + '$.data.products.items[0].configurable_product_options_selection.options_available_for_selection[0].option_value_uids[1]', + ); + + sleep(1.6); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + `[{"query":"\\n query getProductPriceBySku(\\n $filter: ProductAttributeFilterInput,\\n $configurations: [ID!]\\n ) {\\n products(filter: $filter) {\\n items {\\n price_range {\\n ...PriceRangeFields\\n }\\n\\n ... on ConfigurableProduct {\\n price_range {\\n maximum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n minimum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n }\\n\\n configurable_product_options_selection(configurableOptionValueUids: $configurations) {\\n options_available_for_selection {\\n attribute_code\\n option_value_uids\\n }\\n media_gallery {\\n disabled\\n label\\n position\\n url\\n }\\n variant {\\n uid\\n sku\\n name\\n price_range {\\n ...PriceRangeFields\\n }\\n }\\n }\\n }\\n\\n ... on BundleProduct {\\n items {\\n position\\n required\\n sku\\n title\\n type\\n uid\\n options {\\n can_change_quantity\\n is_default\\n position\\n uid\\n quantity\\n product {\\n uid\\n sku\\n name\\n price_range {\\n ...PriceRangeFields\\n }\\n }\\n }\\n }\\n }\\n\\n ... on GroupedProduct {\\n items {\\n position\\n qty\\n product {\\n uid\\n sku\\n name\\n stock_status\\n only_x_left_in_stock\\n price_range {\\n maximum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n minimum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n }\\n thumbnail {\\n url\\n position\\n disabled\\n label\\n }\\n }\\n }\\n }\\n\\n }\\n }\\n }\\n \\n fragment PriceRangeFields on PriceRange {\\n maximum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n minimum_price {\\n final_price {\\n currency\\n value\\n }\\n regular_price {\\n currency\\n value\\n }\\n }\\n }\\n\\n","queryVariables":{"filter":{"sku":{"eq":"WSH11"}},"configurations":["${vars.index01}","${vars.index11}"]}}]`, + { + headers, + }, + ); + executeCommonChecks(res); + sleep(0.5); + }); + + group('Add product to the cart', () => { + res = http.post( + `${BASE_URL}/api/magento/createEmptyCart`, + '[]', + { + headers, + }, + ); + executeCommonChecks(res); + + [vars.cart_id] = jsonpath.query( + res.json(), + '$.data.createEmptyCart', + ); + + res = http.post( + `${BASE_URL}/api/magento/cart`, + `["${vars.cart_id}"]`, + { + headers, + }, + ); + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/addProductsToCart`, + `[{"cartId":"${vars.cart_id}","cartItems":[{"quantity":1,"sku":"WSH11","selected_options":["${vars.index01}","${vars.index11}"]}]},null]`, + { + headers, + }, + ); + executeCommonChecks(res); + sleep(3); + }); + + group('Go through the checkout', () => { + res = http.post( + `${BASE_URL}/api/magento/cart`, + `["${vars.cart_id}"]`, + { + headers, + }, + ); + executeCommonChecks(res); + sleep(5.3); + + res = http.post( + `${BASE_URL}/api/magento/setGuestEmailOnCart`, + `[{"email":"john.loadtest@gmail.com","cart_id":"${vars.cart_id}"},null]`, + { + headers, + }, + ); + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/cart`, + `["${vars.cart_id}"]`, + { + headers, + }, + ); + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/cart`, + `["${vars.cart_id}"]`, + { + headers, + }, + ); + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/countries`, + '[]', + { + headers, + }, + ); + executeCommonChecks(res); + sleep(2.2); + + res = http.post( + `${BASE_URL}/api/magento/country`, + '["PL",null]', + { + headers, + }, + ); + executeCommonChecks(res); + sleep(3.9); + + res = http.post( + `${BASE_URL}/api/magento/setShippingAddressesOnCart`, + `[{"cart_id":"${vars.cart_id}","shipping_addresses":[{"address":{"firstname":"john","lastname":"LoadTest","street":["Load Test 11","11"],"city":"Load Test","region":"PL-10","country_code":"PL","postcode":"11-111","telephone":"123123123","save_in_address_book":false}}]}]`, + { + headers, + }, + ); + executeCommonChecks(res); + sleep(1.6); + + res = http.post( + `${BASE_URL}/api/magento/setShippingMethodsOnCart`, + `[{"cart_id":"${vars.cart_id}","shipping_methods":[{"carrier_code":"flatrate","method_code":"flatrate"}]},null]`, + { + headers, + }, + ); + executeCommonChecks(res); + sleep(1.3); + + res = http.post( + `${BASE_URL}/api/magento/cart`, + `["${vars.cart_id}"]`, + { + headers, + }, + ); + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/cart`, + `["${vars.cart_id}"]`, + { + headers, + }, + ); + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/countries`, + '[]', + { + headers, + }, + ); + executeCommonChecks(res); + sleep(1.7); + + res = http.post( + `${BASE_URL}/api/magento/country`, + '["PL",null]', + { + headers, + }, + ); + + res = http.post( + `${BASE_URL}/api/magento/country`, + '["PL",null]', + { + headers, + }, + ); + executeCommonChecks(res); + sleep(1.4); + + res = http.post( + `${BASE_URL}/api/magento/setBillingAddressOnCart`, + `[{"cart_id":"${vars.cart_id}","billing_address":{"address":{"firstname":"john","lastname":"LoadTest","street":["Load Test 11","11"],"city":"Load Test","region":"PL-10","country_code":"PL","postcode":"11-111","telephone":"123123123","save_in_address_book":false},"same_as_shipping":true}},null]`, + { + headers, + }, + ); + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/setShippingMethodsOnCart`, + `[{"cart_id":"${vars.cart_id}","shipping_methods":[{"carrier_code":"flatrate","method_code":"flatrate"}]},null]`, + { + headers, + }, + ); + executeCommonChecks(res); + sleep(0.5); + + res = http.post( + `${BASE_URL}/api/magento/cart`, + `["${vars.cart_id}"]`, + { + headers, + }, + ); + + res = http.post( + `${BASE_URL}/api/magento/cart`, + `["${vars.cart_id}"]`, + { + headers, + }, + ); + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/getAvailablePaymentMethods`, + `[{"cartId":"${vars.cart_id}"},null]`, + { + headers, + }, + ); + executeCommonChecks(res); + sleep(1.2); + + res = http.post( + `${BASE_URL}/api/magento/setPaymentMethodOnCart`, + `[{"cart_id":"${vars.cart_id}","payment_method":{"code":"checkmo"}},null]`, + { + headers, + }, + ); + executeCommonChecks(res); + sleep(1.5); + }); + + group('Place the order', () => { + res = http.post( + `${BASE_URL}/api/magento/placeOrder`, + `[{"cart_id":"${vars.cart_id}"},null]`, + { + headers, + }, + ); + executeCommonChecks(res); + }); + }); +} diff --git a/packages/load-tests/src/tests/magento/utils/customerData.js b/packages/load-tests/src/utils/customerData.js similarity index 100% rename from packages/load-tests/src/tests/magento/utils/customerData.js rename to packages/load-tests/src/utils/customerData.js From 1ad60a4d1c367314a2e117cf15e8a899a06087a3 Mon Sep 17 00:00:00 2001 From: Bartosz Herba Date: Thu, 28 Jul 2022 08:55:08 +0200 Subject: [PATCH 33/89] feat: add i18n base url configuration - set baseUrl to env variable --- packages/theme/nuxt.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/theme/nuxt.config.js b/packages/theme/nuxt.config.js index 2a305497f..9eb8a6f23 100755 --- a/packages/theme/nuxt.config.js +++ b/packages/theme/nuxt.config.js @@ -135,6 +135,7 @@ export default () => { ], i18n: { country: 'US', + baseUrl: process.env.VSF_STORE_URL, strategy: 'prefix', locales: [ { From 6f4d14b801d5af2ac5ae718349427b55ba9dfbb8 Mon Sep 17 00:00:00 2001 From: Bartosz Herba Date: Wed, 27 Jul 2022 08:31:17 +0200 Subject: [PATCH 34/89] test: add load test for a new user registration --- .../tests/scenarios/newUserRegistration.js | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 packages/load-tests/src/tests/scenarios/newUserRegistration.js diff --git a/packages/load-tests/src/tests/scenarios/newUserRegistration.js b/packages/load-tests/src/tests/scenarios/newUserRegistration.js new file mode 100644 index 000000000..d35bf8c53 --- /dev/null +++ b/packages/load-tests/src/tests/scenarios/newUserRegistration.js @@ -0,0 +1,95 @@ +// Creator: k6 Browser Recorder 0.6.2 +import { check, sleep, group } from 'k6'; +import http from 'k6/http'; +import { setDefaultCookies } from './utils/setDefaultCookies.js'; +import { customerData } from '../../utils/customerData.js'; + +export const options = { + vus: 200, + duration: '5m', + thresholds: { + http_req_failed: ['rate<0.01'], // http errors should be less than 1% + }, +}; + +const { BASE_URL } = __ENV; + +if (BASE_URL === undefined) { + throw new Error('BASE_URL is not set'); +} + +const headers = { + accept: 'application/json, text/plain, */*', + 'content-type': 'application/json', + 'upgrade-insecure-requests': '1', + 'sec-ch-ua': '".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"macOS"', +}; + +const executeCommonChecks = (res) => { + check(res, { + 'is status 200': (r) => r.status === 200, + 'has no errors': (r) => !r.json().errors, + }); +}; + +export default function main() { + let res; + setDefaultCookies(BASE_URL); + + group( + `New user registration - page ${BASE_URL}`, + () => { + res = http.get( + `${BASE_URL}/default`, + { + headers, + }, + ); + sleep(0.6); + + group('Input user data', () => { + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + '[{"query":"\\n query storeConfig {\\n storeConfig {\\n store_code,\\n default_title,\\n store_name,\\n default_display_currency_code,\\n locale,\\n header_logo_src,\\n logo_width,\\n logo_height,\\n logo_alt\\n }\\n }\\n"}]', + { + headers, + }, + ); + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + '[{"query":"\\n query getStoresAndCurrencies {\\n availableStores {\\n store_code\\n }\\n currency {\\n available_currency_codes\\n }\\n }\\n"}]', + { + headers, + }, + ); + executeCommonChecks(res); + + res = http.post( + `${BASE_URL}/api/magento/customQuery`, + '[{"query":"\\n query getStoresAndCurrencies {\\n availableStores {\\n store_code\\n }\\n currency {\\n available_currency_codes\\n }\\n }\\n"}]', + { + headers, + }, + ); + executeCommonChecks(res); + sleep(8); + }); + + group('Save new user', () => { + res = http.post( + `${BASE_URL}/api/magento/createCustomer`, + `[{"email":"${customerData.getEmail()}","password":"Admin123!","recaptchaToken":"recaptcha_bypass_code","firstname":"load","lastname":"test","is_subscribed":false},{}]`, + { + headers, + }, + ); + }); + + executeCommonChecks(res); + }, + ); +} From b945e4c17ae4492ab2039c27ff79af20f1432283 Mon Sep 17 00:00:00 2001 From: Bartosz Herba Date: Wed, 27 Jul 2022 07:47:26 +0200 Subject: [PATCH 35/89] fix: update installation guide - change npm -> yarn because npm does not work for our app --- docs/installation-setup/installation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/installation-setup/installation.md b/docs/installation-setup/installation.md index ad4db862c..08a22e677 100644 --- a/docs/installation-setup/installation.md +++ b/docs/installation-setup/installation.md @@ -31,7 +31,7 @@ Go to the newly created directory and install the required dependencies: ```bash cd -npm install +yarn install ``` ### Step 2. Setup and configure Magento @@ -47,7 +47,7 @@ With the Magento instance setup and configured, you can connect your project to The project is now ready. You can start the application in development mode using the command below. You can read more about available commands and environments on the [Commands and deployment](https://nuxtjs.org/docs/2.x/get-started/commands/) page in Nuxt.js documentation. ```bash -npm run dev +yarn run dev ``` ## Recommended tools From ec4670bbad18b2c31be3d7b678e1beff151ee51b Mon Sep 17 00:00:00 2001 From: Bartosz Herba Date: Tue, 26 Jul 2022 09:17:21 +0200 Subject: [PATCH 36/89] refactor: remove style duplication in my account route components --- .../AddressesDetails/AddressEdit.vue | 8 ++---- .../MyAccount/AddressesDetails/AddressNew.vue | 7 +---- .../AddressesDetails/AddressesDetails.vue | 7 +---- .../customer/pages/MyAccount/MyNewsletter.vue | 8 +----- .../customer/pages/MyAccount/MyReviews.vue | 27 ++----------------- .../customer/pages/MyAccount/MyWishlist.vue | 9 +------ .../pages/MyAccount/ResetPassword.vue | 4 +++ .../modules/customer/pages/styles/shared.scss | 26 ++++++++++++++++++ 8 files changed, 38 insertions(+), 58 deletions(-) create mode 100644 packages/theme/modules/customer/pages/styles/shared.scss diff --git a/packages/theme/modules/customer/pages/MyAccount/AddressesDetails/AddressEdit.vue b/packages/theme/modules/customer/pages/MyAccount/AddressesDetails/AddressEdit.vue index a7df3bbed..2a93eefc0 100644 --- a/packages/theme/modules/customer/pages/MyAccount/AddressesDetails/AddressEdit.vue +++ b/packages/theme/modules/customer/pages/MyAccount/AddressesDetails/AddressEdit.vue @@ -69,10 +69,6 @@ export default defineComponent({ diff --git a/packages/theme/modules/customer/pages/MyAccount/AddressesDetails/AddressNew.vue b/packages/theme/modules/customer/pages/MyAccount/AddressesDetails/AddressNew.vue index 44fc40e46..b7f0cd0b6 100644 --- a/packages/theme/modules/customer/pages/MyAccount/AddressesDetails/AddressNew.vue +++ b/packages/theme/modules/customer/pages/MyAccount/AddressesDetails/AddressNew.vue @@ -43,10 +43,5 @@ export default defineComponent({ diff --git a/packages/theme/modules/customer/pages/MyAccount/AddressesDetails/AddressesDetails.vue b/packages/theme/modules/customer/pages/MyAccount/AddressesDetails/AddressesDetails.vue index f5efb8ccc..f50f59019 100644 --- a/packages/theme/modules/customer/pages/MyAccount/AddressesDetails/AddressesDetails.vue +++ b/packages/theme/modules/customer/pages/MyAccount/AddressesDetails/AddressesDetails.vue @@ -179,12 +179,7 @@ export default defineComponent({ -``` - -#### Using variables, mixins, and function in components - -Usually, to access style variables, mixins, and functions, we import them in every component separately. Thanks to the [@nuxtjs/style-resources](https://github.com/nuxt-community/style-resources-module#readme) module, we can register them in `nuxt.config.js` and access them without extra `@import` statements. - -:::danger Be careful -Stylesheets in `styleResources` should **only** contain variables, mixins, and functions. During the build process, the components import these stylesheets. Any **styles** declared in them are added to every component, significantly impacting the performance and application size. -::: - -We use this approach to have access to StorefrontUI helpers in all components: - -```javascript -// nuxt.config.js - -export default { - styleResources: { - scss: [ - require.resolve('@storefront-ui/shared/styles/_helpers.scss', { paths: [process.cwd()] }) - ] - }, -}; -``` diff --git a/docs/guide/graphql-get.md b/docs/guide/graphql-get.md index 88cb721f8..7d93a5994 100644 --- a/docs/guide/graphql-get.md +++ b/docs/guide/graphql-get.md @@ -1,12 +1,13 @@ # Use GET for GraphQL Queries -In Magento we can leverage the power of GET requests caching, to improve the performance of your GrpahQL API. In order to do this, you need to setup your Magento backend and configure the Vue Storefront Magento integration. +In Magento we can leverage the power of GET requests caching, to improve the performance of your GrpahQL API. In order to do this, you need to setup your Magento backend and configure the Vue Storefront Magento integration. ## Enabling GraphQL Caching on Magento with Varnish To enable the GraphQL caching on Magento, first you need to have installed the Varnish and have it configured into your environment. 1. Edit the `default.vcl` file on your system, and update the `vcl_hash` subroutine, to check whether the request URL contains `graphql`, as follows: + ``` sub vcl_hash { if (req.http.cookie ~ "X-Magento-Vary=") { @@ -30,7 +31,9 @@ sub vcl_hash { } } ``` + 2. Then you need to add the `process_graphql_headers` subroutine to the `default.vcl` file: + ``` sub process_graphql_headers { if (req.http.Store) { @@ -41,9 +44,10 @@ sub process_graphql_headers { } } ``` + > Query results should not be cached for logged in customers, because it cannot be guaranteed that these results are applicable to all customers. For example, you can create multiple customer groups and set up different product prices for each group. Caching results like these might cause customers to see the prices of another customer group. -You can find more information about this topic at [https://devdocs.magento.com/guides/v2.4/graphql/caching.html#caching-with-varnish] +You can find more information about this topic [on the Magento docs](https://devdocs.magento.com/guides/v2.4/graphql/caching.html#caching-with-varnish) 3. Open the `middleware.config.js` file, it should be located on the root folder of your store, there you will change the flag `useGETForQueries` to `true` to enable the usage of GET request for queries diff --git a/docs/guide/override-queries.md b/docs/guide/override-queries.md index e04ecfe1a..bf4f21b00 100644 --- a/docs/guide/override-queries.md +++ b/docs/guide/override-queries.md @@ -16,44 +16,43 @@ In order to query `cld_data`, you need to have [Cloudinary Magento extension](ht --- -1. Inside the theme's root let's create a `customQueries` directory, and [copy the content of the default `productsList` query from `vuestorefront/magento2/packages/api-client/src/api/products/productsList.ts` file](https://github.com/vuestorefront/magento2/blob/main/packages/api-client/src/api/products/productsList.ts) into the newly created directory. +1. Inside the theme's root let's create a `customQueries` directory, and copy the content of the default `productsList` query from the `/productsList.ts` file ([Source](https://github.com/vuestorefront/magento2/blob/main/packages/api-client/src/api/products/productsList.ts)) into the newly created directory. You can modify the query inside this file by adding `cld_data` with fields to the existing query as below: - ```typescript - import gql from 'graphql-tag'; +```typescript +import gql from 'graphql-tag'; - export default gql` - query productsList($search: String = "", $filter: ProductAttributeFilterInput, $pageSize: Int = 10, $currentPage: Int = 1, $sort: ProductAttributeSortInput) { - products(search: $search, filter: $filter, pageSize: $pageSize, currentPage: $currentPage, sort: $sort) { - aggregations { - attribute_code +export default gql` + query productsList($search: String = "", $filter: ProductAttributeFilterInput, $pageSize: Int = 10, $currentPage: Int = 1, $sort: ProductAttributeSortInput) { + products(search: $search, filter: $filter, pageSize: $pageSize, currentPage: $currentPage, sort: $sort) { + aggregations { + attribute_code + label + options { label - options { - label - value - count - } + value + count } - items { - //... - cld_data { - image - thumbnail - } - //... - } - page_info { - current_page - page_size - total_pages + } + items { + //... + cld_data { + image + thumbnail } - total_count + //... + } + page_info { + current_page + page_size + total_pages } + total_count } - `; - - ``` + } +`; +``` ::: warning Make sure you have `graphgl-tag` installed as dependency prior using this sample code. @@ -61,37 +60,37 @@ Make sure you have `graphgl-tag` installed as dependency prior using this sample 2. In `middleware.config.js`, import the modified query - ```js - import customProductsQuery from './customQueries/productList'; - ``` +```js +import customProductsQuery from './customQueries/productList'; +``` 3. Add a new property field `customQueries` under `integrations.magento` with the following code: - ```js - module.exports = { - integrations: { - magento: { - customQueries: { - /* This is where we override the default query */ - products: (context) => ({ - ...context, - query: customProductsQuery, // Your custom query - }) - }, - //... - }, +```js +module.exports = { + integrations: { + magento: { + customQueries: { + /* This is where we override the default query */ + products: (context) => ({ + ...context, + query: customProductsQuery, // Your custom query + }), }, - }; + //... + }, + }, +}; ``` 4. Now you can restart your dev environment and view the updated data queried. ::: warning -`thumbnail` is a must-have field to query. It is used for our default image rendering (for Nuxt image). DO NOT remove it from the query in any circumstance. +`thumbnail` is a must-have field to query. It is used for our default image rendering via Nuxt Image. Do not remove it from the query in any circumstance. ::: ### Important notes -**Only** attributes presented on `ProductInterface` are accessible via GraphQL without any additional modification on the Magento side. +Only attributes presented on `ProductInterface` are accessible via GraphQL without any additional modification on the Magento side. -To be able to get any custom attributes you must extend GraphQL schema in the Magento2. Follow [Magento 2 documentation](https://devdocs.magento.com/guides/v2.4/graphql/develop/extend-existing-schema.html) to achieve that. +To be able to get any custom attributes, you must extend the GraphQL schema in Magento 2. Follow [Magento 2 documentation](https://devdocs.magento.com/guides/v2.4/graphql/develop/extend-existing-schema.html) to achieve that. diff --git a/docs/guide/ssr.md b/docs/guide/ssr.md index 069d7d4ca..641994091 100644 --- a/docs/guide/ssr.md +++ b/docs/guide/ssr.md @@ -6,20 +6,22 @@ VueStorefront 2 - Magento 2 integrations use @vue-storefront/cache module that a rendered pages. ### What is cached + The cached pages are: -* Home page with the `Vhome` tag. -* All CMS pages with the `V${page.identifier}` tag -* Category page with the `Vcategory` tag and tags for products: `P${product.uid}` as well as categories `C${category.slug}` -* Product page with the `Vproduct-${route.value.params.id}` tag and tags for the main product `P${product.uid}` as well as categories `C${cat.id}` +- Home page with the `Vhome` tag. +- All CMS pages with the `V${page.identifier}` tag +- Category page with the `Vcategory` tag and tags for products: `P${product.uid}` as well as categories `C${category.slug}` +- Product page with the `Vproduct-${route.value.params.id}` tag and tags for the main product `P${product.uid}` as well as categories `C${cat.id}` ## Invalidating tags To invalidate a tag and remove pages associated with that tag, use the [Invalidation endpoint](https://docs.vuestorefront.io/v2/performance/ssr-cache.html#invalidating-tags). Go to the route configured in the `.env` file under the `VSF_REDIS_CACHE_INVALIDATE_KEY` key with two query parameters: -* `key` — string matching the `VSF_REDIS_CACHE_INVALIDATE_KEY` key in the `.env` file. -* `tags` — a comma-separated list of tags for invalidation. + +- `key` — string matching the `VSF_REDIS_CACHE_INVALIDATE_KEY` key in the `.env` file. +- `tags` — a comma-separated list of tags for invalidation. Assuming that you are running the application locally, the `VSF_REDIS_CACHE_INVALIDATE_URL` key is equal to `/cache-invalidate,` and the `VSF_REDIS_CACHE_INVALIDATE_KEY` key is equal to `secret_key`, and you want to invalidate the `Vhome` tag, the full URL will look like this: @@ -33,16 +35,16 @@ You don't need to add any additional packages to cache more pages — just add o ## Cache drivers -@vue-storefront/cache module is open source and provided Out Of The Box by Magento 2 integration. +`@vue-storefront/cache` module is open source and provided Out Of The Box by Magento 2 integration. To set up caching in your store, you must install and configure a cache driver. You can use our enterprise `@vsf-enterprise/redis-cache` module, or build your cache driver. ### Redis cache (enterprise) + Once you have access to the [Vue Storefront npm registry](https://docs.vuestorefront.io/v2/general/enterprise.htm), you can install the Redis cache driver by running this command in a console: -``yarn add @vsf-enterprise/redis-cache`` - +`yarn add @vsf-enterprise/redis-cache` #### redis cache configuration @@ -85,6 +87,6 @@ Then you have to update `nuxt.config.js file` and add this to the `modules` obje ## Useful links -- https://docs.vuestorefront.io/v2/performance/ssr-cache.html -- https://docs.vuestorefront.io/v2/integrations/redis-cache.html -- https://docs.vuestorefront.io/v2/integrate/cache-driver.html +- [Server Side Rendering Cache](https://docs.vuestorefront.io/v2/performance/ssr-cache.html) +- [Redis cache](https://docs.vuestorefront.io/v2/integrations/redis-cache.html) +- [Integrating cache driver](https://docs.vuestorefront.io/v2/integrate/cache-driver.html) diff --git a/docs/index.md b/docs/index.md index 07a8791d9..e2148b546 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,8 +1,3 @@ - - # Vue Storefront 2 for Magento Welcome to the documentation of Vue Storefront 2 integration for Magento 2. @@ -13,8 +8,8 @@ It's part of our ecosystem of integrations and extensions, which you can learn m To get started, see the following guides: -- [Introduction](/getting-started/introduction.html) to learn what is Vue Storefront, -- [Installation](/installation-setup/installation.html) to install and setup new Vue Storefront project. +- [Introduction](https://docs.vuestorefront.io/v2/getting-started/introduction.html) to learn what is Vue Storefront +- [Installation](/installation-setup/installation.html) to install and setup new Vue Storefront project for Magento 2. ## Demo diff --git a/docs/installation-setup/installation.md b/docs/installation-setup/installation.md index 08a22e677..ecd93b690 100644 --- a/docs/installation-setup/installation.md +++ b/docs/installation-setup/installation.md @@ -1,5 +1,9 @@ # Installation +If you prefer a video guide - here's a quick start guide to get your project up and running. + + + ## Prerequisites Before proceeding, make sure you have [Node 16](https://nodejs.org/en/) installed. You can check this by running the following command: diff --git a/docs/package.json b/docs/package.json index 9af3adf50..4f18a89e9 100755 --- a/docs/package.json +++ b/docs/package.json @@ -29,6 +29,6 @@ "dependencies": { "sass-loader": "^8.0.2", "vue-multiselect": "^2.1.6", - "vuepress-theme-vsf-docs": "^1.0.14" + "vuepress-theme-vsf-docs": "^1.0.16" } } diff --git a/docs/plugins/index.md b/docs/plugins/index.md index 096145217..377b6e083 100644 --- a/docs/plugins/index.md +++ b/docs/plugins/index.md @@ -10,20 +10,6 @@ It checks if locale in i18n module is changes and update `vsf-store` and `vsf-lo client and server side. ### Flow -1. Start: load middleware -2. Read current Magento Store Code from vsf-store cookie -3. Is store code found? - 2. No: Set default locale if isn't already set - 1. End -4. Yes: Check if current store code has corresponding locale in Nuxt.config.js - 1. No: Set default locale if isn't already set - 1. End -5. Yes: If corresponded locale is different than current locale - 1. No: End -6. Yes: set new locale -7. Go forward (load the page with correct locale and date) -8. End - ![i18n flow](./i18n-plugin-diagram.png) @@ -31,19 +17,22 @@ client and server side. We expose `$fc` (format currency) function as a plugin to allow you to convert any number or string into a formatted currency string. Under the hood plugins uses Intl.NumberFormat class to handle formatting and therefore exposes the same options configuration. Here are few examples of how you can use it in templates. + ```javascript -$fc(productGetters.getPrice(product).regular) // by default vsf-currency cookie is used to define target currency -$fc(productGetters.getPrice(product).regular, { currency: 'USD' }) // you can easily override this behaviour by passing configuration object +$fc(productGetters.getPrice(product).regular); // by default vsf-currency cookie is used to define target currency +$fc(productGetters.getPrice(product).regular, { currency: 'USD' }); // you can easily override this behaviour by passing configuration object ``` Configuration object is an interface Intl.NumberFormatOptions, check it for all available options. --- -***NOTE*** -Why we are not using built-in i18n package currency configuration and $n function to cover currency displaying? The answer is because we must be able to handle multiple currencies within one store but in i18n package, currency and locale are in 1:1 relation when in Magento one store can have multiple languages and currencies set. Currency and locale are necessarily disjointed which is not true for i18n plugin. +**_NOTE_** + +Why we are not using built-in i18n package currency configuration and $n function to cover currency displaying? + +The answer is because we must be able to handle multiple currencies within one store but in i18n package, currency and locale are in 1:1 relation when in Magento one store can have multiple languages and currencies set. Currency and locale are necessarily disjointed which is not true for i18n plugin. You can still use all i18n native functions to perform any formatting though. --- - diff --git a/docs/yarn.lock b/docs/yarn.lock index d63d8ffdc..4acd9b14b 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -8336,10 +8336,10 @@ vuepress-plugin-smooth-scroll@^0.0.3: dependencies: smoothscroll-polyfill "^0.4.3" -vuepress-theme-vsf-docs@^1.0.14: - version "1.0.14" - resolved "https://registry.yarnpkg.com/vuepress-theme-vsf-docs/-/vuepress-theme-vsf-docs-1.0.14.tgz#87e9a4fd079f34548140cad7647d4cf04a02dc59" - integrity sha512-m57TPCuaA8iyEsk/Kvgg0Wi+ByLqPXgbPF7dwGSgqjGlcIjjW2bMoaFrI7yNNLxnKdfyYXhgR0rLsPVQTPmwgw== +vuepress-theme-vsf-docs@^1.0.16: + version "1.0.16" + resolved "https://registry.yarnpkg.com/vuepress-theme-vsf-docs/-/vuepress-theme-vsf-docs-1.0.16.tgz#453225d147e1b3440ec05312f33b1877804cf3ad" + integrity sha512-qVb+TvW5y914S+SB9BhoX1ulo5xOw/2JS8pwqEWPoM8mAfdLwqglBgPUFb1HrRQhgY0I11rSI7couWl6ENh7mQ== dependencies: "@vuepress/plugin-active-header-links" "1.9.7" "@vuepress/plugin-nprogress" "1.9.7" From 438af64a9ec6cd022c9112ffa977af3fb35b00ce Mon Sep 17 00:00:00 2001 From: Artur Tagisow Date: Sat, 6 Aug 2022 12:26:52 +0200 Subject: [PATCH 68/89] ci: fix code not checked out --- .github/workflows/deploy-vue-storefront-cloud.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy-vue-storefront-cloud.yml b/.github/workflows/deploy-vue-storefront-cloud.yml index 4e56ba9ff..4a3c9ce91 100644 --- a/.github/workflows/deploy-vue-storefront-cloud.yml +++ b/.github/workflows/deploy-vue-storefront-cloud.yml @@ -20,6 +20,9 @@ jobs: environment-middleware-url: ${{ steps.determine-environment.outputs.middleware-url}} deployment_id: ${{ steps.deployment.outputs.deployment_id }} steps: + - name: Checkout code + uses: actions/checkout@v1 + - name: Determine environment-specific variables shell: bash run: | @@ -54,7 +57,7 @@ jobs: id: deployment uses: chrnorm/deployment-action@v2 with: - token: ${{ secrets.DEPLOYMENT_PERSONAL_ACCESS_TOKEN }} + token: ${{ github.token }} environment: ${{ env.ENVNAME }} initial-status: in_progress From dd853475a5aad923313c6fac00138d459bd368b7 Mon Sep 17 00:00:00 2001 From: GitHub actions Date: Mon, 1 Aug 2022 09:47:30 +0000 Subject: [PATCH 69/89] chore: release 1.0.2 --- .github/workflows/public_env_info/canary | 4 ++-- internals/eslint-import/package.json | 2 +- internals/eslint-jest/package.json | 2 +- internals/eslint-typescript/package.json | 2 +- internals/eslint-vue/package.json | 2 +- internals/eslint/package.json | 2 +- packages/api-client/package.json | 2 +- packages/load-tests/package.json | 2 +- packages/theme/package.json | 5 ++--- 9 files changed, 11 insertions(+), 12 deletions(-) diff --git a/.github/workflows/public_env_info/canary b/.github/workflows/public_env_info/canary index fddb3b3d7..2a931d140 100644 --- a/.github/workflows/public_env_info/canary +++ b/.github/workflows/public_env_info/canary @@ -1,5 +1,5 @@ ENVNAME=canary ENVCODE=demo-magento2-canary -BASE_URL=https://demo-magento2-canary.europe-west1.gcp.storefrontcloud.io -MIDDLEWARE_URL=https://demo-magento2-canary.europe-west1.gcp.storefrontcloud.io/api +BASE_URL=magento2stage.vuestorefront.io +MIDDLEWARE_URL=magento2stage.vuestorefront.io/api MAGENTO_GRAPHQL_URL=https://magento2-instance.vuestorefront.io:8443/graphql diff --git a/internals/eslint-import/package.json b/internals/eslint-import/package.json index 61a67f11f..45367031d 100644 --- a/internals/eslint-import/package.json +++ b/internals/eslint-import/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/eslint-config-import", - "version": "1.0.1", + "version": "1.0.2", "author": "Heitor Ramon Ribeiro ", "license": "MIT", "scripts": { diff --git a/internals/eslint-jest/package.json b/internals/eslint-jest/package.json index 4d215697a..16ac89b3f 100644 --- a/internals/eslint-jest/package.json +++ b/internals/eslint-jest/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/eslint-config-jest", - "version": "1.0.1", + "version": "1.0.2", "author": "Heitor Ramon Ribeiro ", "license": "MIT", "scripts": { diff --git a/internals/eslint-typescript/package.json b/internals/eslint-typescript/package.json index dd6184a71..6c4cda539 100644 --- a/internals/eslint-typescript/package.json +++ b/internals/eslint-typescript/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/eslint-config-typescript", - "version": "1.0.1", + "version": "1.0.2", "author": "Heitor Ramon Ribeiro ", "license": "MIT", "scripts": { diff --git a/internals/eslint-vue/package.json b/internals/eslint-vue/package.json index 046195b9b..cbc4e6fbb 100644 --- a/internals/eslint-vue/package.json +++ b/internals/eslint-vue/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/eslint-config-vue", - "version": "1.0.1", + "version": "1.0.2", "author": "Heitor Ramon Ribeiro ", "license": "MIT", "scripts": { diff --git a/internals/eslint/package.json b/internals/eslint/package.json index 6510e16f5..c92035777 100644 --- a/internals/eslint/package.json +++ b/internals/eslint/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/eslint-config-base", - "version": "1.0.1", + "version": "1.0.2", "author": "Heitor Ramon Ribeiro ", "license": "MIT", "scripts": { diff --git a/packages/api-client/package.json b/packages/api-client/package.json index 7c263a0f2..c9a2b9374 100644 --- a/packages/api-client/package.json +++ b/packages/api-client/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/magento-api", - "version": "1.0.1", + "version": "1.0.2", "sideEffects": false, "homepage": "https://github.com/vuestorefront/magento2", "bugs": { diff --git a/packages/load-tests/package.json b/packages/load-tests/package.json index 4d2c02840..d3e21ba3f 100644 --- a/packages/load-tests/package.json +++ b/packages/load-tests/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/magento-load-tests", - "version": "1.0.1", + "version": "1.0.2", "description": "Load tests for Magento 2 - VSF integration", "main": "index.js", "repository": "https://github.com/vuestorefront/magento2", diff --git a/packages/theme/package.json b/packages/theme/package.json index a5af98a3e..46592338a 100644 --- a/packages/theme/package.json +++ b/packages/theme/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/magento-theme", - "version": "1.0.1", + "version": "1.0.2", "private": true, "license": "MIT", "homepage": "https://github.com/vuestorefront/magento2", @@ -38,8 +38,7 @@ "@pinia/nuxt": "^0.1.9", "@storefront-ui/vue": "^0.13.3", "@vue-storefront/cache": "~2.7.1", - "@vue-storefront/http-cache": "^2.7.1", - "@vue-storefront/magento-api": "^1.0.1", + "@vue-storefront/magento-api": "^1.0.2", "@vue-storefront/middleware": "~2.7.1", "@vue-storefront/nuxt": "~2.7.1", "@vue-storefront/redis-cache": "^1.0.1", From e1a6e8081b341a1e2264456927255a04f0684389 Mon Sep 17 00:00:00 2001 From: Marcin Kwiatkowski Date: Mon, 1 Aug 2022 12:43:21 +0200 Subject: [PATCH 70/89] docs: added 1.0.2 release notes --- docs/index.md | 20 ++++++++++++- docs/migration-guides/1.0.2/index.md | 44 ++++++++++++++++++++++++++++ docs/migration-guides/index.md | 5 +++- 3 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 docs/migration-guides/1.0.2/index.md diff --git a/docs/index.md b/docs/index.md index e2148b546..383e13057 100644 --- a/docs/index.md +++ b/docs/index.md @@ -13,4 +13,22 @@ To get started, see the following guides: ## Demo -If you want to see the integration in action, check out our [demo environments](/guide/environments.html). +If you want to see the integration in action, we have three demo environments where you can see and test Magento 2 integration for Vue Storefront in action. If you find a bug in any of them, please [create an issue](https://github.com/vuestorefront/magento2/issues/new/choose) in our repository to let us know about it. + +### Production environment + +In the production environment, you can see the latest **released and stable** version of the integration. It should be visually and feature-wise identical to the new project installed using our CLI. + +[Production demo](https://demo-magento2.europe-west1.gcp.vuestorefront.cloud) + +### Staging environment + +In the staging environment, we are testing new releases. It should be **relatively stable**, but you might still encounter some bugs. + +[Staging demo](https://demo-magento2-canary.europe-west1.gcp.storefrontcloud.io) + +### Development environment + +In the development environment, we are testing the `develop` branch, which might contain unfinished or experimental features. It might be **unstable** both visually and feature-wise. + +[Development environment](https://demo-magento2-dev.europe-west1.gcp.storefrontcloud.io) diff --git a/docs/migration-guides/1.0.2/index.md b/docs/migration-guides/1.0.2/index.md new file mode 100644 index 000000000..024263032 --- /dev/null +++ b/docs/migration-guides/1.0.2/index.md @@ -0,0 +1,44 @@ +## Vue Storefront for Magento 1.0.2 + +Along with bug fixes and reactors, this release contains a few load test scenarios we use to perform load testing using K6. + +## Features +- feat: add i18n base URL configuration [#/1314](https://github.com/vuestorefront/magento2/pull/1314) + +### Bugfix + +- fix: header navigation "hasChildren" always returning true [#1315](https://github.com/vuestorefront/magento2/pull/1315) +- fix: command correction according to markshust script [#1305](https://github.com/vuestorefront/magento2/pull/1305) +- fix: images are not loaded properly with ipx [#1292](https://github.com/vuestorefront/magento2/pull/1292) +- fix: fix bug when media_gallery array is empty [#/1267](https://github.com/vuestorefront/magento2/pull/1267) +- fix: product review form offscreen issue [#1304](https://github.com/vuestorefront/magento2/pull/1304) + +### Refactors + +- refactor: remove style duplication in my account route components [#1310](https://github.com/vuestorefront/magento2/pull/1310) +- refactor: update yarn lock [#/1293](https://github.com/vuestorefront/magento2/pull/1293) +- refactor: improve typings [#1262](https://github.com/vuestorefront/magento2/pull/1262) + +### Chore + +- chore: added new contributors [#1316](https://github.com/vuestorefront/magento2/pull/1316) + +### Docs + +- docs: update installation guide [#1312](https://github.com/vuestorefront/magento2/pull/1312) +- docs: fix several oversights on 1.0.0-rc.10 breaking changes doc [#1308](https://github.com/vuestorefront/magento2/pull/1308) + +### Test + +- test: add load test for a new user registration [#1313](https://github.com/vuestorefront/magento2/pull/1313) +- test: add buy product as a guest user load test [#1311](https://github.com/vuestorefront/magento2/pull/1311) +- test: add search product load tests [#1309](https://github.com/vuestorefront/magento2/pull/1309) +- test: browsing product load test [#1306](https://github.com/vuestorefront/magento2/pull/1306) + +### Repository + +- ci: stop using personal access token for deployment API[#1303](https://github.com/vuestorefront/magento2/pull/1303) + +### Credits + +Huge thanks to [@bensinca](https://github.com/bensinca), [@sethidden](https://github.com/sethidden), [@bartoszherba](https://github.com/bartoszherba), [@konarshankar07](https://github.com/konarshankar07), [@filipsobol](https://github.com/filipsobol) and [@maaarghk](https://github.com/maaarghk) diff --git a/docs/migration-guides/index.md b/docs/migration-guides/index.md index 145e2ea4a..8e2e3da7f 100644 --- a/docs/migration-guides/index.md +++ b/docs/migration-guides/index.md @@ -1,6 +1,9 @@ # Migration guides - +## 1.0.x +- [1.0.2](./1.0.2/) - [1.0.1](./1.0.1/) - [1.0.0](./1.0.0/) + +## Release candidates - [1.0.0-rc.10](./1.0.0-rc.10/) - [1.0.0](./1.0.0/) From a3e5241fd5e3ea6d8880d1bf65eef200034bb049 Mon Sep 17 00:00:00 2001 From: Bartosz Herba Date: Mon, 29 Aug 2022 14:07:46 +0200 Subject: [PATCH 71/89] feat: add http-cache module --- packages/theme/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/theme/package.json b/packages/theme/package.json index 46592338a..3e569135e 100644 --- a/packages/theme/package.json +++ b/packages/theme/package.json @@ -38,7 +38,8 @@ "@pinia/nuxt": "^0.1.9", "@storefront-ui/vue": "^0.13.3", "@vue-storefront/cache": "~2.7.1", - "@vue-storefront/magento-api": "^1.0.2", + "@vue-storefront/http-cache": "^2.7.1", + "@vue-storefront/magento-api": "^1.0.1", "@vue-storefront/middleware": "~2.7.1", "@vue-storefront/nuxt": "~2.7.1", "@vue-storefront/redis-cache": "^1.0.1", From c5df4996a4188b5a2e7f0f7f68b7ce37b619ee0e Mon Sep 17 00:00:00 2001 From: Bartosz Herba Date: Wed, 31 Aug 2022 13:10:15 +0200 Subject: [PATCH 72/89] fix: revert docker image build and remove sentry module --- .vuestorefrontcloud/docker/Dockerfile | 22 +++++-------------- .../docker/nuxt.config.additional.js | 1 - 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/.vuestorefrontcloud/docker/Dockerfile b/.vuestorefrontcloud/docker/Dockerfile index cf4a100d3..097974dad 100644 --- a/.vuestorefrontcloud/docker/Dockerfile +++ b/.vuestorefrontcloud/docker/Dockerfile @@ -1,4 +1,4 @@ -FROM node:16-alpine +FROM node:16 ARG LAST_COMMIT ARG NPM_USER @@ -66,27 +66,17 @@ ENV VSF_RECAPTCHA_SITE_KEY=${VSF_RECAPTCHA_SITE_KEY} ENV VSF_RECAPTCHA_SECRET_KEY=${VSF_RECAPTCHA_SECRET_KEY} ENV VSF_MIDDLEWARE_URL=${VSF_MIDDLEWARE_URL} -RUN npm config set @vsf-enterprise:registry=https://registrynpm.storefrontcloud.io - -RUN npm install -g npm-cli-login \ - && npm-cli-login +RUN npm config set @vsf-enterprise:registry=https://registrynpm.storefrontcloud.io \ + && npm install -g npm-cli-login \ + && npm-cli-login WORKDIR /var/www COPY . . RUN mv /var/www/packages/theme/nuxt.config.js /var/www/packages/theme/base.nuxt.config.js && cp .vuestorefrontcloud/docker/nuxt.config.additional.js /var/www/packages/theme/nuxt.config.js -RUN npx yarn@1.19.0 workspace @vue-storefront/magento-theme add @sentry/tracing @nuxtjs/sentry - -## Install and build -RUN apk add --no-cache --virtual .gyp \ - python3 \ - make \ - g++ \ - && yarn install \ - && yarn cache clean --all \ - && apk del .gyp \ - && rm -rf ./packages/api-client/src + +RUN yarn install && yarn build && yarn cache clean --all COPY .vuestorefrontcloud/docker/vue-storefront.sh /usr/local/bin/ diff --git a/.vuestorefrontcloud/docker/nuxt.config.additional.js b/.vuestorefrontcloud/docker/nuxt.config.additional.js index 6fe2b8d3f..2a9bff20d 100755 --- a/.vuestorefrontcloud/docker/nuxt.config.additional.js +++ b/.vuestorefrontcloud/docker/nuxt.config.additional.js @@ -7,7 +7,6 @@ export default () => { ...baseDefaults, modules: [ ...baseDefaults.modules, - '@nuxtjs/sentry', ], sentry: { dsn: process.env.VSF_SENTRY_DSN, From e657d85aa625642c187513472bd31f54afe3b534 Mon Sep 17 00:00:00 2001 From: Bartosz Herba Date: Tue, 30 Aug 2022 10:08:58 +0200 Subject: [PATCH 73/89] fix: m2-938 fix issue with a store switching on the customer account --- .../MyAccount/AddressesDetails/AddressForm.vue | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/theme/modules/customer/pages/MyAccount/AddressesDetails/AddressForm.vue b/packages/theme/modules/customer/pages/MyAccount/AddressesDetails/AddressForm.vue index f050cd204..fcb5be29c 100644 --- a/packages/theme/modules/customer/pages/MyAccount/AddressesDetails/AddressForm.vue +++ b/packages/theme/modules/customer/pages/MyAccount/AddressesDetails/AddressForm.vue @@ -290,10 +290,7 @@ export default defineComponent({ const updateCountry = async (params: UseCountrySearchParams) => { country.value = await searchCountry(params); - form.value.region = { - // let region SfSelect know it should display initial state - ...(regionInformation.value.length > 0 ? { region_id: null } : {}), - }; + form.value.region = { region_id: null, region_code: '' }; }; watch(() => props.address, () => { @@ -318,9 +315,13 @@ export default defineComponent({ const submitForm = () => { const regionId = regionInformation.value.find((r) => r.abbreviation === form.value.region.region_code)?.id; - if (regionId) { - form.value.region.region_id = regionId; - } + form.value.region = regionId + ? { region_id: regionId } + : { + ...form.value.region, + region_code: '', + region_id: null, + }; emit('submit', { form: omitDeep(form.value, ['__typename']), From a6ae75c5e26046bd1ebaed2a99e8f6bab8aaf167 Mon Sep 17 00:00:00 2001 From: Bartosz Herba Date: Tue, 30 Aug 2022 13:12:43 +0200 Subject: [PATCH 74/89] fix: m2-941 product is not marked as added to the wishlist --- packages/theme/modules/catalog/pages/category.vue | 2 ++ packages/theme/modules/catalog/pages/product.vue | 8 +++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/theme/modules/catalog/pages/category.vue b/packages/theme/modules/catalog/pages/category.vue index 9cda3c279..8ea55deae 100644 --- a/packages/theme/modules/catalog/pages/category.vue +++ b/packages/theme/modules/catalog/pages/category.vue @@ -186,6 +186,7 @@ export default defineComponent({ isFilterSidebarOpen, } = useUiState(); const { + load: loadWishlist, addItem: addItemToWishlistBase, isInWishlist, removeItem: removeItemFromWishlist, @@ -237,6 +238,7 @@ export default defineComponent({ const isPriceLoaded = ref(false); onMounted(async () => { + loadWishlist(); const { getPricesBySku } = usePrice(); if (products.value.length > 0) { const skus = products.value.map((item) => item.sku); diff --git a/packages/theme/modules/catalog/pages/product.vue b/packages/theme/modules/catalog/pages/product.vue index 75fcc61bf..0013c3276 100644 --- a/packages/theme/modules/catalog/pages/product.vue +++ b/packages/theme/modules/catalog/pages/product.vue @@ -46,8 +46,8 @@ import { useProduct } from '~/modules/catalog/product/composables/useProduct'; import { getMetaInfo } from '~/helpers/getMetaInfo'; import { usePageStore } from '~/stores/page'; import { ProductTypeEnum } from '~/modules/catalog/product/enums/ProductTypeEnum'; +import { useWishlist, useApi } from '~/composables'; import LoadWhenVisible from '~/components/utils/LoadWhenVisible.vue'; -import { useApi } from '~/composables'; import type { Product } from '~/modules/catalog/product/types'; import type { ProductDetailsQuery } from '~/modules/GraphQL/types'; import ProductSkeleton from '~/modules/catalog/product/components/ProductSkeleton.vue'; @@ -79,7 +79,7 @@ export default defineComponent({ const route = useRoute(); const { getProductDetails, loading } = useProduct(); const { error: nuxtError } = useContext(); - + const { load: loadWishlist } = useWishlist(); const breadcrumbs = computed(() => { const productCategories = product.value?.categories ?? []; return getBreadcrumbs( @@ -139,7 +139,9 @@ export default defineComponent({ addTags([...tags, ...productTags]); }); - onMounted(async () => fetchProductExtendedData()); + onMounted(async () => { + await Promise.all([fetchProductExtendedData(), loadWishlist()]); + }); return { renderer, From 2af814801115f4d6f85054a7d5f44cc49adc5d5d Mon Sep 17 00:00:00 2001 From: Bartosz Herba Date: Wed, 31 Aug 2022 13:26:26 +0200 Subject: [PATCH 75/89] fix: add missing canary url prtocols --- .github/workflows/public_env_info/canary | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/public_env_info/canary b/.github/workflows/public_env_info/canary index 2a931d140..272ab76a2 100644 --- a/.github/workflows/public_env_info/canary +++ b/.github/workflows/public_env_info/canary @@ -1,5 +1,5 @@ ENVNAME=canary ENVCODE=demo-magento2-canary -BASE_URL=magento2stage.vuestorefront.io -MIDDLEWARE_URL=magento2stage.vuestorefront.io/api +BASE_URL=https://magento2stage.vuestorefront.io +MIDDLEWARE_URL=https://magento2stage.vuestorefront.io/api MAGENTO_GRAPHQL_URL=https://magento2-instance.vuestorefront.io:8443/graphql From 4fc51f34be52a5c4d78f50a3e8b09209548c13f3 Mon Sep 17 00:00:00 2001 From: Bartosz Herba Date: Wed, 31 Aug 2022 19:10:42 +0200 Subject: [PATCH 76/89] fix: m2-1050 pods does not get up after deployment - add ssrMiddlewareUrl to prevent make a call to unavailable external client --- .../workflows/deploy-vue-storefront-cloud.yml | 2 + .github/workflows/public_env_info/canary | 1 + .github/workflows/public_env_info/dev | 1 + .github/workflows/public_env_info/enterprise | 1 + .github/workflows/public_env_info/production | 1 + .../configure-integration.md | 58 +++++++++++++++++++ packages/theme/.env.example | 3 + .../modules/core/integrationPlugin/index.ts | 6 +- packages/theme/nuxt.config.js | 6 +- 9 files changed, 74 insertions(+), 5 deletions(-) diff --git a/.github/workflows/deploy-vue-storefront-cloud.yml b/.github/workflows/deploy-vue-storefront-cloud.yml index 4a3c9ce91..0d2c89cec 100644 --- a/.github/workflows/deploy-vue-storefront-cloud.yml +++ b/.github/workflows/deploy-vue-storefront-cloud.yml @@ -52,6 +52,7 @@ jobs: echo ::set-output name=name::${{ env.ENVNAME }} echo ::set-output name=code::${{ env.ENVCODE }} echo ::set-output name=middleware-url::${{ env.MIDDLEWARE_URL }} + echo ::set-output name=ssr-middleware-url::${{ env.SSR_MIDDLEWARE_URL }} - name: Create GitHub deployment id: deployment @@ -92,6 +93,7 @@ jobs: VSF_STORE_URL: '' VSF_MIDDLEWARE_URL: ${{ needs.create-deployment.outputs.environment-middleware-url }} + VSF_SSR_MIDDLEWARE_URL: ${{ needs.create-deployment.outputs.environment-ssr-middleware-url }} VSF_MAGENTO_BASE_URL: https://magento2-instance.vuestorefront.io/ VSF_MAGENTO_GRAPHQL_URL: https://magento2-instance.vuestorefront.io/graphql diff --git a/.github/workflows/public_env_info/canary b/.github/workflows/public_env_info/canary index 272ab76a2..9d0df301a 100644 --- a/.github/workflows/public_env_info/canary +++ b/.github/workflows/public_env_info/canary @@ -2,4 +2,5 @@ ENVNAME=canary ENVCODE=demo-magento2-canary BASE_URL=https://magento2stage.vuestorefront.io MIDDLEWARE_URL=https://magento2stage.vuestorefront.io/api +SSR_MIDDLEWARE_URL=http://localhost:3000/api MAGENTO_GRAPHQL_URL=https://magento2-instance.vuestorefront.io:8443/graphql diff --git a/.github/workflows/public_env_info/dev b/.github/workflows/public_env_info/dev index e3aec0cb5..6bcbb7083 100644 --- a/.github/workflows/public_env_info/dev +++ b/.github/workflows/public_env_info/dev @@ -2,4 +2,5 @@ ENVNAME=dev ENVCODE=demo-magento2-dev BASE_URL=https://demo-magento2-dev.europe-west1.gcp.storefrontcloud.io MIDDLEWARE_URL=https://demo-magento2-dev.europe-west1.gcp.storefrontcloud.io/api +SSR_MIDDLEWARE_URL=http://localhost:3000/api MAGENTO_GRAPHQL_URL=https://magento2-instance.vuestorefront.io:8443/graphql diff --git a/.github/workflows/public_env_info/enterprise b/.github/workflows/public_env_info/enterprise index 4d7efada1..d78b068e8 100644 --- a/.github/workflows/public_env_info/enterprise +++ b/.github/workflows/public_env_info/enterprise @@ -2,4 +2,5 @@ ENVNAME=enterprise ENVCODE=demo-magento2-enterprise BASE_URL=https://demo-magento2-enterprise.europe-west1.gcp.storefrontcloud.io MIDDLEWARE_URL=https://demo-magento2-enterprise.europe-west1.gcp.storefrontcloud.io/api +SSR_MIDDLEWARE_URL=http://localhost:3000/api MAGENTO_GRAPHQL_URL=https://magento2-instance.vuestorefront.io:8443/graphql diff --git a/.github/workflows/public_env_info/production b/.github/workflows/public_env_info/production index d9696b5f6..6f214e8b6 100644 --- a/.github/workflows/public_env_info/production +++ b/.github/workflows/public_env_info/production @@ -2,4 +2,5 @@ ENVNAME=production ENVCODE=demo-magento2 BASE_URL=https://demo-magento2.europe-west1.gcp.vuestorefront.cloud MIDDLEWARE_URL=https://demo-magento2.europe-west1.gcp.vuestorefront.cloud/api +SSR_MIDDLEWARE_URL=http://localhost:3000/api MAGENTO_GRAPHQL_URL=https://magento2-instance.vuestorefront.io:8443/graphql diff --git a/docs/installation-setup/configure-integration.md b/docs/installation-setup/configure-integration.md index f2e4e077b..eaa9c2466 100644 --- a/docs/installation-setup/configure-integration.md +++ b/docs/installation-setup/configure-integration.md @@ -24,6 +24,64 @@ After installation, the first step is configuring the integration using the envi 3. Update values in the `.env` file. +4. Explanation of env variables + + #### Nuxt application configuration options + ``` + VSF_NUXT_APP_ENV=development # application mode [production|development] + VSF_NUXT_APP_PORT=3000 # nuxt server port property + VSF_NUXT_APP_HOST=0.0.0.0 # nuxt server host property + ``` + + #### Storefront and middleware endpoints configuration + ``` + VSF_STORE_URL=https://localhost:3000 # external base url + VSF_MIDDLEWARE_URL=https://localhost:3000/api/ # external middleware base url + VSF_SSR_MIDDLEWARE_URL=http://localhost:3000/api/ # internal middleware base url + ``` + **NOTE**: *For many infrastructures `middleware_url` and `ssr_middleware_url` will be the same, but sometimes they might be different. For example, when it comes to deployment using a rolling-update strategy on the Kubernetes cluster, the Kubernetes is probing SSR if it's already up. SSR is trying to call middleware using an external URL (market...storefrontcloud.io) rather than localhost:3000/API, while the middleware isn't available publicly yet, because the SSR didn't respond with 200 in the first place.* + + #### Magento 2 endpoints configuration and others + ``` + VSF_MAGENTO_BASE_URL={YOUR_SITE_FRONT_URL} + VSF_MAGENTO_GRAPHQL_URL=https://{YOUR_SITE_FRONT_URL}/graphql + + VSF_MAGENTO_EXTERNAL_CHECKOUT_ENABLED=false + VSF_MAGENTO_EXTERNAL_CHECKOUT_URL=https://{YOUR_SITE_FRONT_URL} + VSF_MAGENTO_EXTERNAL_CHECKOUT_SYNC_PATH=/vue/cart/sync + ``` + + #### Image provider configuration + ``` + VSF_IMAGE_PROVIDER=cloudinary + VSF_IMAGE_PROVIDER_BASE_URL=https://res-4.cloudinary.com/{YOUR_ID}/image/upload/ + VSF_IMAGE_PROVIDER_DOMAIN=https://res-4.cloudinary.com + ``` + + #### Redis cache configuration + ``` + VSF_REDIS_ENABLED=false + VSF_REDIS_HOST=127.0.0.1 + VSF_REDIS_PORT=6379 + VSF_REDIS_KEY_PREFIX= + VSF_REDIS_CACHE_INVALIDATE_URL=/cache-invalidate + ``` + #### ReCaptcha configuration + ``` + VSF_RECAPTCHA_ENABLED=false + VSF_RECAPTCHA_SITE_KEY= + VSF_RECAPTCHA_SECRET_KEY= + VSF_RECAPTCHA_HIDE_BADGE= + VSF_RECAPTCHA_SIZE=invisible + VSF_RECAPTCHA_MIN_SCORE=0.5 + VSF_RECAPTCHA_VERSION=3 + ``` + + #### Other + ``` + NODE_TLS_REJECT_UNAUTHORIZED=0 # toggle TLS verification (eg. for a local development) +``` + ### 2. Setup store configuration The `plugins/storeConfigPlugin.ts` plugin loads store configuration data from Magento and saves it into the Pinia store under the `$state.storeConfig` property. By default, the amount of data loaded from Magento is minimal to avoid over-fetching, but as your application grows, you might need to pull more data. diff --git a/packages/theme/.env.example b/packages/theme/.env.example index a9f09937a..be92f46b3 100644 --- a/packages/theme/.env.example +++ b/packages/theme/.env.example @@ -1,8 +1,11 @@ VSF_NUXT_APP_ENV=development VSF_NUXT_APP_PORT=3000 +VSF_NUXT_APP_HOST=0.0.0.0 VSF_STORE_URL=https://localhost:3000 VSF_MIDDLEWARE_URL=https://localhost:3000/api/ +VSF_SSR_MIDDLEWARE_URL=http://localhost:3000/api/ + VSF_MAGENTO_BASE_URL={YOUR_SITE_FRONT_URL} VSF_MAGENTO_GRAPHQL_URL=https://{YOUR_SITE_FRONT_URL}/graphql diff --git a/packages/theme/modules/core/integrationPlugin/index.ts b/packages/theme/modules/core/integrationPlugin/index.ts index 86cc09c1a..6d481ec7f 100644 --- a/packages/theme/modules/core/integrationPlugin/index.ts +++ b/packages/theme/modules/core/integrationPlugin/index.ts @@ -33,10 +33,10 @@ export const integrationPlugin = (pluginFn: NuxtPluginWithIntegration) => (nuxtC const configure = (tag: string, configuration: { api: Record }) => { const injectInContext = createAddIntegrationToCtx({ tag, nuxtCtx, inject }); const config = getIntegrationConfig(nuxtCtx, configuration); - const { middlewareUrl } = (nuxtCtx as any).$config; + const { middlewareUrl, ssrMiddlewareUrl } = (nuxtCtx as any).$config; - if (middlewareUrl) { - config.axios.baseURL = middlewareUrl; + if (middlewareUrl || ssrMiddlewareUrl) { + config.axios.baseURL = process.server ? ssrMiddlewareUrl || middlewareUrl : middlewareUrl; } // eslint-disable-next-line @typescript-eslint/no-unsafe-argument diff --git a/packages/theme/nuxt.config.js b/packages/theme/nuxt.config.js index f62720cd4..7f919d3ee 100755 --- a/packages/theme/nuxt.config.js +++ b/packages/theme/nuxt.config.js @@ -33,7 +33,7 @@ export default () => { dev: process.env.VSF_NUXT_APP_ENV !== 'production', server: { port: process.env.VSF_NUXT_APP_PORT, - host: '0.0.0.0', + host: process.env.VSF_NUXT_APP_HOST || '0.0.0.0', }, head: { title: process.env.npm_package_name || '', @@ -250,9 +250,11 @@ export default () => { env: { VSF_MAGENTO_GRAPHQL_URL: process.env.VSF_MAGENTO_GRAPHQL_URL, }, - publicRuntimeConfig: { middlewareUrl: process.env.VSF_MIDDLEWARE_URL || 'http://localhost:3000/api/', + ssrMiddlewareUrl: process.env.VSF_SSR_MIDDLEWARE_URL + || process.env.VSF_MIDDLEWARE_URL + || 'http://localhost:3000/api/', }, }; From 7c01dd78998b89a026d89ecb4e09324f3c72ac00 Mon Sep 17 00:00:00 2001 From: Bartosz Herba Date: Tue, 30 Aug 2022 15:43:40 +0200 Subject: [PATCH 77/89] fix: m2-1017 logout doesn't work after reload of the MyAccount page --- .../customer/pages/MyAccount/MyAccount.vue | 15 +++++++++-- .../pages/MyAccount/useSidebarLinkGroups.ts | 27 ++++++++++++------- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/packages/theme/modules/customer/pages/MyAccount/MyAccount.vue b/packages/theme/modules/customer/pages/MyAccount/MyAccount.vue index f63ed99dc..fa29e1673 100644 --- a/packages/theme/modules/customer/pages/MyAccount/MyAccount.vue +++ b/packages/theme/modules/customer/pages/MyAccount/MyAccount.vue @@ -34,7 +34,7 @@ :label="$t(item.label)" :link="localeRoute(item.link)" class="sf-content-pages__menu" - v-on="item.listeners" + v-on="{ click: getHandler(item.id) }" /> @@ -83,17 +83,28 @@ export default defineComponent({ } }); - const { sidebarLinkGroups } = useSidebarLinkGroups(); + const { sidebarLinkGroups, logoutUser } = useSidebarLinkGroups(); const isOnSubpage = computed(() => route.value.matched.length > 1); const goToTopLevelRoute = () => router.push(localeRoute({ name: 'customer' })); const title = computed(() => i18n.t(route.value.matched.at(-1)?.meta.titleLabel as string)); + /** + * #tab-id: handler-name + */ + const handlers = { + 'log-out': logoutUser, + }; + + const getHandler = (id: string) => handlers[id] ?? {}; + return { sidebarLinkGroups, title, isOnSubpage, goToTopLevelRoute, + logoutUser, + getHandler, }; }, }); diff --git a/packages/theme/modules/customer/pages/MyAccount/useSidebarLinkGroups.ts b/packages/theme/modules/customer/pages/MyAccount/useSidebarLinkGroups.ts index d87113099..04b71eb88 100644 --- a/packages/theme/modules/customer/pages/MyAccount/useSidebarLinkGroups.ts +++ b/packages/theme/modules/customer/pages/MyAccount/useSidebarLinkGroups.ts @@ -1,34 +1,39 @@ import type { RawLocation } from 'vue-router'; + import { useRouter, useContext } from '@nuxtjs/composition-api'; import { useUser } from '~/modules/customer/composables/useUser'; import { useCart } from '~/modules/checkout/composables/useCart'; type LinkGroup = { title: string, items: LinkGroupItem[] }; -type LinkGroupItem = { label: string, link?: RawLocation, listeners?: Record (Promise | void)> }; +type LinkGroupItem = { id: string, label: string, link?: RawLocation }; export const useSidebarLinkGroups = () => { const { localeRoute } = useContext(); const { logout } = useUser(); const { clear } = useCart(); - const router = useRouter(); + const sidebarLinkGroups : LinkGroup[] = [ { title: 'Personal details', items: [ { + id: 'my-profile', label: 'My profile', link: { name: 'customer-my-profile' }, }, { + id: 'address-details', label: 'Addresses details', link: { name: 'customer-addresses-details' }, }, { + id: 'my-newsletter', label: 'My newsletter', link: { name: 'customer-my-newsletter' }, }, { + id: 'my-wishlist', label: 'My wishlist', link: { name: 'customer-my-wishlist' }, }, @@ -38,26 +43,28 @@ export const useSidebarLinkGroups = () => { title: 'Order details', items: [ { + id: 'order-history', label: 'Order history', link: { name: 'customer-order-history' }, }, { + id: 'my-reviews', label: 'My reviews', link: { name: 'customer-my-reviews' }, }, { + id: 'log-out', label: 'Log out', - listeners: { - click: async () => { - await logout({}); - await clear({}); - await router.push(localeRoute({ name: 'home' })); - }, - }, }, ], }, ]; - return { sidebarLinkGroups }; + const logoutUser = async () => { + await logout({}); + await clear({}); + await router.push(localeRoute({ name: 'home' })); + }; + + return { sidebarLinkGroups, logoutUser }; }; From c9fa18630b19d386d95478e58bf63c283ec188fc Mon Sep 17 00:00:00 2001 From: Bartosz Herba Date: Fri, 2 Sep 2022 09:13:08 +0200 Subject: [PATCH 78/89] fix: m2-930 product list page is sometimes unresponsive after the store switch --- packages/theme/modules/catalog/pages/category.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/theme/modules/catalog/pages/category.vue b/packages/theme/modules/catalog/pages/category.vue index 8ea55deae..d14d04949 100644 --- a/packages/theme/modules/catalog/pages/category.vue +++ b/packages/theme/modules/catalog/pages/category.vue @@ -207,7 +207,7 @@ export default defineComponent({ const { fetch } = useFetch(async () => { if (!activeCategory.value) { - loadCategoryTree(); + await loadCategoryTree(); } const categoryUid = routeData.uid; From ccf1704d163bf3beb3e81763e571260fe954ba7b Mon Sep 17 00:00:00 2001 From: Bartosz Herba Date: Fri, 2 Sep 2022 11:29:58 +0200 Subject: [PATCH 79/89] feat: make security connection optional by default --- .../workflows/deploy-vue-storefront-cloud.yml | 2 ++ .../configure-integration.md | 31 ++++++++++++++++--- packages/theme/.env.example | 7 ++++- packages/theme/middleware.config.js | 8 ++--- packages/theme/nuxt.config.js | 12 ------- 5 files changed, 39 insertions(+), 21 deletions(-) diff --git a/.github/workflows/deploy-vue-storefront-cloud.yml b/.github/workflows/deploy-vue-storefront-cloud.yml index 0d2c89cec..2b37681c3 100644 --- a/.github/workflows/deploy-vue-storefront-cloud.yml +++ b/.github/workflows/deploy-vue-storefront-cloud.yml @@ -119,6 +119,8 @@ jobs: VSF_RECAPTCHA_SITE_KEY: 6Ldce0EeAAAAAAGGtGWG-e-SygXiFub6PXHT5fKd VSF_RECAPTCHA_SECRET_KEY: ${{ secrets.RECAPTCHA_SECRET_KEY }} + VSF_COOKIE_SECURE: true + VSF_SENTRY_DSN: ${{ secrets.SENTRY_DSN }} LAST_COMMIT: ${{ github.sha }} diff --git a/docs/installation-setup/configure-integration.md b/docs/installation-setup/configure-integration.md index eaa9c2466..0d8662461 100644 --- a/docs/installation-setup/configure-integration.md +++ b/docs/installation-setup/configure-integration.md @@ -77,6 +77,14 @@ After installation, the first step is configuring the integration using the envi VSF_RECAPTCHA_VERSION=3 ``` + #### Cookies configuration + ``` + VSF_COOKIE_HTTP_ONLY= + VSF_COOKIE_SECURE= + VSF_COOKIE_SAME_SITE= + VSF_COOKIE_PATH= + ``` + #### Other ``` NODE_TLS_REJECT_UNAUTHORIZED=0 # toggle TLS verification (eg. for a local development) @@ -132,7 +140,7 @@ When working with translation in your application, you need to: ### 4. Configure default cookies settings -Vue Storefront app uses different cookies but all share the same default config. To adjust the configuration you have to modify `middleware.config.js`. +Vue Storefront app uses different cookies but all share the same default config. To adjust the configuration you have to add `env` variable, which is the recommended way, or modify `middleware.config.js`. Once done, rebuild your application. ```js @@ -143,8 +151,8 @@ module.exports = { /*...*/ // Here you can override default cookies options cookiesDefaultOpts: { - httpOnly: false, - secure: true, // Make sure that you have ssl configured, otherwise disable this flag + httpOnly: VSF_COOKIE_HTTP_ONLY || false, + secure: VSF_COOKIE_SECURE || true, // Make sure that you have ssl configured, otherwise disable this flag }, /*...*/ }, @@ -158,13 +166,28 @@ module.exports = { ### Install `mkcert` Please, follow the steps in the [official instruction](https://github.com/FiloSottile/mkcert). Different OS might require different steps to accomplish the task. -### Generate certificate for a local development +#### Update nuxt.config.js +In the `nuxt.config.js` add the certificate configuration + +``` +baseConfig.server = { + ...baseConfig.server, + https: { + key: fs.readFileSync(path.resolve(__dirname, 'localhost-key.pem')), + cert: fs.readFileSync(path.resolve(__dirname, 'localhost.pem')), + }, +}; +``` + + +#### Generate certificate for a local development If you set up your project from CLI run the command in the APP root directory. If you are a contributor and have cloned Vue Storefront repository, run the command in `packages/theme`. ``` mkcert localhost ``` + ### Start project ```bash yarn dev diff --git a/packages/theme/.env.example b/packages/theme/.env.example index be92f46b3..cb42a3b30 100644 --- a/packages/theme/.env.example +++ b/packages/theme/.env.example @@ -1,6 +1,6 @@ VSF_NUXT_APP_ENV=development VSF_NUXT_APP_PORT=3000 -VSF_NUXT_APP_HOST=0.0.0.0 +VSF_NUXT_APP_HOST=localhost VSF_STORE_URL=https://localhost:3000 VSF_MIDDLEWARE_URL=https://localhost:3000/api/ @@ -31,4 +31,9 @@ VSF_RECAPTCHA_SIZE=invisible VSF_RECAPTCHA_MIN_SCORE=0.5 VSF_RECAPTCHA_VERSION=3 +VSF_COOKIE_HTTP_ONLY= +VSF_COOKIE_SECURE= +VSF_COOKIE_SAME_SITE= +VSF_COOKIE_PATH= + NODE_TLS_REJECT_UNAUTHORIZED=0 diff --git a/packages/theme/middleware.config.js b/packages/theme/middleware.config.js index db33334e1..d9bad1390 100755 --- a/packages/theme/middleware.config.js +++ b/packages/theme/middleware.config.js @@ -29,10 +29,10 @@ module.exports = { ...cookieNames, }, cookiesDefaultOpts: { - httpOnly: false, - secure: true, - sameSite: 'Strict', - path: '/', + httpOnly: process.env.VSF_COOKIE_HTTP_ONLY || false, + secure: process.env.VSF_COOKIE_SECURE || false, + sameSite: process.env.VSF_COOKIE_SAME_SITE || 'Strict', + path: process.env.VSF_COOKIE_PATH || '/', }, defaultStore: 'default', externalCheckout: { diff --git a/packages/theme/nuxt.config.js b/packages/theme/nuxt.config.js index 7f919d3ee..901d9e901 100755 --- a/packages/theme/nuxt.config.js +++ b/packages/theme/nuxt.config.js @@ -2,8 +2,6 @@ /* eslint-disable unicorn/prefer-module */ // @core-development-only-end import webpack from 'webpack'; -import fs from 'fs'; -import path from 'path'; import middleware from './middleware.config'; import { getRoutes } from './routes'; @@ -296,15 +294,5 @@ export default () => { }; } - if (process.env.NODE_ENV === 'development' || process.env.VSF_NUXT_APP_ENV === 'development') { - baseConfig.server = { - ...baseConfig.server, - https: { - key: fs.readFileSync(path.resolve(__dirname, 'localhost-key.pem')), - cert: fs.readFileSync(path.resolve(__dirname, 'localhost.pem')), - }, - }; - } - return baseConfig; }; From 6c7f92ec9e57f9857f74b44dd5e5052cf0a3be3d Mon Sep 17 00:00:00 2001 From: Marcin Kwiatkowski Date: Wed, 31 Aug 2022 14:53:20 +0200 Subject: [PATCH 80/89] docs: fixed breaking change reference link --- docs/migration-guides/1.0.0/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/migration-guides/1.0.0/index.md b/docs/migration-guides/1.0.0/index.md index 4ebacf295..f1a8febff 100644 --- a/docs/migration-guides/1.0.0/index.md +++ b/docs/migration-guides/1.0.0/index.md @@ -2,7 +2,7 @@ Vue Storefront for Magento 1.0.0 contains backward-incompatible changes. To review these backward-incompatible changes, see -[1.0.0 **Backward incompatible changes reference**](./1.0.0-bic) +[1.0.0 **Backward incompatible changes reference**](./1.0.0-bic.md) ## Vue Storefront for Magento 1.0.0 highlights From 75f9608bdfb255bc8b4827190ac7e9c2f7e7db9f Mon Sep 17 00:00:00 2001 From: GitHub actions Date: Mon, 5 Sep 2022 08:04:19 +0000 Subject: [PATCH 81/89] chore: release 1.1.0 --- internals/eslint-import/package.json | 2 +- internals/eslint-jest/package.json | 2 +- internals/eslint-typescript/package.json | 2 +- internals/eslint-vue/package.json | 2 +- internals/eslint/package.json | 2 +- packages/api-client/package.json | 2 +- packages/load-tests/package.json | 2 +- packages/theme/package.json | 4 ++-- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/internals/eslint-import/package.json b/internals/eslint-import/package.json index 45367031d..770da1b85 100644 --- a/internals/eslint-import/package.json +++ b/internals/eslint-import/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/eslint-config-import", - "version": "1.0.2", + "version": "1.1.0", "author": "Heitor Ramon Ribeiro ", "license": "MIT", "scripts": { diff --git a/internals/eslint-jest/package.json b/internals/eslint-jest/package.json index 16ac89b3f..ebd040b33 100644 --- a/internals/eslint-jest/package.json +++ b/internals/eslint-jest/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/eslint-config-jest", - "version": "1.0.2", + "version": "1.1.0", "author": "Heitor Ramon Ribeiro ", "license": "MIT", "scripts": { diff --git a/internals/eslint-typescript/package.json b/internals/eslint-typescript/package.json index 6c4cda539..254e832f7 100644 --- a/internals/eslint-typescript/package.json +++ b/internals/eslint-typescript/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/eslint-config-typescript", - "version": "1.0.2", + "version": "1.1.0", "author": "Heitor Ramon Ribeiro ", "license": "MIT", "scripts": { diff --git a/internals/eslint-vue/package.json b/internals/eslint-vue/package.json index cbc4e6fbb..918b54422 100644 --- a/internals/eslint-vue/package.json +++ b/internals/eslint-vue/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/eslint-config-vue", - "version": "1.0.2", + "version": "1.1.0", "author": "Heitor Ramon Ribeiro ", "license": "MIT", "scripts": { diff --git a/internals/eslint/package.json b/internals/eslint/package.json index c92035777..4fc1e1a73 100644 --- a/internals/eslint/package.json +++ b/internals/eslint/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/eslint-config-base", - "version": "1.0.2", + "version": "1.1.0", "author": "Heitor Ramon Ribeiro ", "license": "MIT", "scripts": { diff --git a/packages/api-client/package.json b/packages/api-client/package.json index c9a2b9374..e7ad8aa7f 100644 --- a/packages/api-client/package.json +++ b/packages/api-client/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/magento-api", - "version": "1.0.2", + "version": "1.1.0", "sideEffects": false, "homepage": "https://github.com/vuestorefront/magento2", "bugs": { diff --git a/packages/load-tests/package.json b/packages/load-tests/package.json index d3e21ba3f..afdd90a8f 100644 --- a/packages/load-tests/package.json +++ b/packages/load-tests/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/magento-load-tests", - "version": "1.0.2", + "version": "1.1.0", "description": "Load tests for Magento 2 - VSF integration", "main": "index.js", "repository": "https://github.com/vuestorefront/magento2", diff --git a/packages/theme/package.json b/packages/theme/package.json index 3e569135e..4966f67cc 100644 --- a/packages/theme/package.json +++ b/packages/theme/package.json @@ -1,6 +1,6 @@ { "name": "@vue-storefront/magento-theme", - "version": "1.0.2", + "version": "1.1.0", "private": true, "license": "MIT", "homepage": "https://github.com/vuestorefront/magento2", @@ -39,7 +39,7 @@ "@storefront-ui/vue": "^0.13.3", "@vue-storefront/cache": "~2.7.1", "@vue-storefront/http-cache": "^2.7.1", - "@vue-storefront/magento-api": "^1.0.1", + "@vue-storefront/magento-api": "^1.1.0", "@vue-storefront/middleware": "~2.7.1", "@vue-storefront/nuxt": "~2.7.1", "@vue-storefront/redis-cache": "^1.0.1", From 5777e592dd0256d76d6635678e9ce6deb5b5171e Mon Sep 17 00:00:00 2001 From: Bartosz Herba Date: Thu, 8 Sep 2022 09:05:55 +0200 Subject: [PATCH 82/89] chore: add 1.1.0 migration guide --- docs/migration-guides/1.1.0/1.1.0-bic.md | 26 ++++++++++++ docs/migration-guides/1.1.0/index.md | 50 ++++++++++++++++++++++++ docs/migration-guides/index.md | 1 + 3 files changed, 77 insertions(+) create mode 100644 docs/migration-guides/1.1.0/1.1.0-bic.md create mode 100644 docs/migration-guides/1.1.0/index.md diff --git a/docs/migration-guides/1.1.0/1.1.0-bic.md b/docs/migration-guides/1.1.0/1.1.0-bic.md new file mode 100644 index 000000000..5a817413b --- /dev/null +++ b/docs/migration-guides/1.1.0/1.1.0-bic.md @@ -0,0 +1,26 @@ +# 1.1.0 Backward incompatible changes reference + +In this document, you can see crucial breaking changes in the `1.1.0` compared to `1.0.2` release. To see all changes, please take a look at [the release pull request.](https://github.com/vuestorefront/magento2/pull/1355) + +## feat!: implement Magento URL rewrites + +[https://github.com/vuestorefront/magento2/pull/1321/files](https://github.com/vuestorefront/magento2/pull/1321) + +| File | What was changed | +|--------------------------------------------------------------------------------------------| --- | +| **[!]** packages/theme/middleware/url-resolver.ts | A new, rewrite-aware URL resolver is added. | +| **[!]** packages/theme/modules/catalog/index.ts | Routes configuration is removed. | +| **[!]** packages/theme/stores/page.ts | Add Pinia PageStore to store route data state for pages. | +| packages/api-client/src/api/route/route.ts | The query data structure is modified: relative_url and redirect_code are removed. | +| packages/theme/composables/useUiHelpers/index.ts | The category prefix is removed from the category URL string. | +| packages/theme/modules/catalog/category/helpers/useTraverseCategory.ts | The category prefix is removed from the category URL string. | +| packages/theme/modules/catalog/product/composables/useProduct/useProduct.ts | Add getProductPath method. Get a product path from url_rewrites or url_key. | +| packages/theme/helpers/cart/addToCart.ts | GroupedProduct’s add-to-cart URL resolution is simplified and replaced with the getProductPath. | +| packages/theme/modules/catalog/category/components/views/useProductsWithCommonCardProps.ts | Product link URL resolution is simplified and replaced with the getProductPath. | +| packages/theme/modules/customer/pages/MyAccount/MyWishlist.vue | Product link URL resolution is simplified and replaced with the getProductPath. | +| packages/theme/modules/catalog/product/components/ProductsCarousel.vue | Product link URL resolution is simplified and replaced with the getProductPath. | +| packages/theme/modules/GraphQL/types.ts | Add missing optional fields on the RoutableInterface | + +***Notes:*** If you are using in your project old, prefixed URL or URL resolvers, replace them with the usage of the new **useProduct::getProductPath** + +***Notes:*** The old routing system is replaced with a Magento route **type** resolver. Previously, VSF was able to route to a CMS, Category, or Product page based on the URL prefix. Currently, the renderer type is resolved based on the GraphQL **route** query and the route **type** field. diff --git a/docs/migration-guides/1.1.0/index.md b/docs/migration-guides/1.1.0/index.md new file mode 100644 index 000000000..be3d02aee --- /dev/null +++ b/docs/migration-guides/1.1.0/index.md @@ -0,0 +1,50 @@ +# Vue Storefront for Magento 1.1.0 + +Vue Storefront for Magento 1.1.0 contains backward-incompatible changes. To review these backward-incompatible changes, see + +[1.1.0 **Backward incompatible changes reference** ](./1.1.0-bic.md) + +## Vue Storefront for Magento 1.1.0 highlights + +Vue Storefront for Magento 1.1.0 provides a few new features like SEO-friendly URLs, SEO meta tags, Google Cloud CDN support, and more. + +## Features + +- feat!: implement magento URL rewrites [https://github.com/vuestorefront/magento2/pull/1321](https://github.com/vuestorefront/magento2/pull/1321/files) +- feat: add GC CDN support [https://github.com/vuestorefront/magento2/pull/1338](https://github.com/vuestorefront/magento2/pull/1338) +- feat: implement a meta info on cms, product,category page [https://github.com/vuestorefront/magento2/pull/1326](https://github.com/vuestorefront/magento2/pull/1326) +- feat: implement add a grouped product to cart [https://github.com/vuestorefront/magento2/pull/1324](https://github.com/vuestorefront/magento2/pull/1324) +- feat: make security connection optional by default [https://github.com/vuestorefront/magento2/pull/1354](https://github.com/vuestorefront/magento2/pull/1354) + +### Bugfix + +- fix: product list page is sometimes unresponsive after the store switch [https://github.com/vuestorefront/magento2/pull/1352](https://github.com/vuestorefront/magento2/pull/1352) +- fix: logout doesn't work after reload of the MyAccount page [https://github.com/vuestorefront/magento2/pull/1347](https://github.com/vuestorefront/magento2/pull/1347) +- fix: pods do not get up after deployment [https://github.com/vuestorefront/magento2/pull/1351](https://github.com/vuestorefront/magento2/pull/1351) +- fix: add missing canary URL protocols [https://github.com/vuestorefront/magento2/pull/1349](https://github.com/vuestorefront/magento2/pull/1349) +- fix: product is not marked as added to the wishlist [https://github.com/vuestorefront/magento2/pull/1346](https://github.com/vuestorefront/magento2/pull/1346) +- fix: fix the issue with a store switching on the customer account [https://github.com/vuestorefront/magento2/pull/1345](https://github.com/vuestorefront/magento2/pull/1345) +- fix: fix a message about the submitted review [https://github.com/vuestorefront/magento2/pull/1331](https://github.com/vuestorefront/magento2/pull/1331) +- fix: vsf2 not working with docker-compose [https://github.com/vuestorefront/magento2/pull/1337](https://github.com/vuestorefront/magento2/pull/1337) +- fix: pods have warnings error after deployment [https://github.com/vuestorefront/magento2/pull/1335](https://github.com/vuestorefront/magento2/pull/1335) +- fix: fix product detail components [https://github.com/vuestorefront/magento2/pull/1330](https://github.com/vuestorefront/magento2/pull/1330) +- fix: downloadableProduct might not have been initialized [https://github.com/vuestorefront/magento2/pull/1325](https://github.com/vuestorefront/magento2/pull/1325) +- fix: getAvailableShippingMethods query variables [https://github.com/vuestorefront/magento2/pull/1318](https://github.com/vuestorefront/magento2/pull/1318) + +### Chore + +- chore: removed deprecated composables packages from the repository [https://github.com/vuestorefront/magento2/pull/1322](https://github.com/vuestorefront/magento2/pull/1322) + +### Docs + +- docs: fixed breaking change reference link [https://github.com/vuestorefront/magento2/pull/1350](https://github.com/vuestorefront/magento2/pull/1350) +- docs: fix wording + add installation video [https://github.com/vuestorefront/magento2/pull/1319](https://github.com/vuestorefront/magento2/pull/1319) + +### Repository + +- ci: fix code not checked out [https://github.com/vuestorefront/magento2/pull/1327](https://github.com/vuestorefront/magento2/pull/1327) +- ci: refactor k6 action to add new env vars [https://github.com/vuestorefront/magento2/pull/1287](https://github.com/vuestorefront/magento2/pull/1287) + +### Credits + +Huge thanks to @[sethidden](https://github.com/sethidden), [@sequensucks](https://github.com/sequensucks), [@Frodigo](https://github.com/Frodigo), [@bartoszherba](https://github.com/bartoszherba) diff --git a/docs/migration-guides/index.md b/docs/migration-guides/index.md index 8e2e3da7f..823f24933 100644 --- a/docs/migration-guides/index.md +++ b/docs/migration-guides/index.md @@ -1,5 +1,6 @@ # Migration guides ## 1.0.x +- [1.1.0](./1.1.0/) - [1.0.2](./1.0.2/) - [1.0.1](./1.0.1/) - [1.0.0](./1.0.0/) From 79e5ed507eb48c6eaac48426ff18282515819ede Mon Sep 17 00:00:00 2001 From: Bartosz Herba Date: Thu, 6 Oct 2022 07:56:22 +0200 Subject: [PATCH 83/89] fix: update CDN default configuration - exclude */customer*, */checkout* paths from being cached in the CDN --- packages/theme/nuxt.config.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/theme/nuxt.config.js b/packages/theme/nuxt.config.js index 901d9e901..30a4067cb 100755 --- a/packages/theme/nuxt.config.js +++ b/packages/theme/nuxt.config.js @@ -134,8 +134,8 @@ export default () => { default: 'max-age=300, s-maxage=3600, stale-while-revalidate=86400', matchRoute: { '/': 'max-age=1800, s-maxage=86400, stale-while-revalidate=86400', - '/my-account': 'none', - '/checkout*': 'none', + '*/customer*': 'none', + '*/checkout*': 'none', }, }], ], From c3e082ae9fbab3a21cb982148200b1a784348d64 Mon Sep 17 00:00:00 2001 From: Bartosz Herba Date: Thu, 6 Oct 2022 08:35:33 +0200 Subject: [PATCH 84/89] fix: getMagentoImage reading 'split' error --- packages/theme/composables/useImage/index.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/theme/composables/useImage/index.ts b/packages/theme/composables/useImage/index.ts index 2ea1f8ba0..aabd7498d 100644 --- a/packages/theme/composables/useImage/index.ts +++ b/packages/theme/composables/useImage/index.ts @@ -36,11 +36,13 @@ export function useImage(): UseImageInterface { /** * Extract image path from Magento URL. * - * @param fullImageUrl {string} + * @param fullImageUrl {string | null} * * @return {string} */ - const getMagentoImage = (fullImageUrl: string) => { + const getMagentoImage = (fullImageUrl: string | null) => { + if (!fullImageUrl) return ''; + // @ts-ignore const { imageProvider, magentoBaseUrl } = context.$vsf.$magento.config; From 7d564e22d6dbd179a31bf2cdfc91a4e4daebe0c8 Mon Sep 17 00:00:00 2001 From: Bartosz Herba Date: Tue, 11 Oct 2022 10:00:34 +0200 Subject: [PATCH 85/89] fix: product list page items on product page list page zero prices issues --- .../theme/modules/catalog/pages/category.vue | 22 ++++++++++++++----- .../catalog/product/getters/productGetters.ts | 2 +- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/packages/theme/modules/catalog/pages/category.vue b/packages/theme/modules/catalog/pages/category.vue index d14d04949..1dc0e8708 100644 --- a/packages/theme/modules/catalog/pages/category.vue +++ b/packages/theme/modules/catalog/pages/category.vue @@ -205,13 +205,13 @@ export default defineComponent({ const { activeCategory, loadCategoryTree } = useTraverseCategory(); const activeCategoryName = computed(() => activeCategory.value?.name ?? ''); + const categoryUid = routeData.uid; + const { fetch } = useFetch(async () => { if (!activeCategory.value) { await loadCategoryTree(); } - const categoryUid = routeData.uid; - const [content, categoryMetaData] = await Promise.all([ getContentData(categoryUid as string), loadCategoryMeta({ category_uid: routeData.value?.uid }), @@ -237,17 +237,27 @@ export default defineComponent({ }); const isPriceLoaded = ref(false); + onMounted(async () => { loadWishlist(); const { getPricesBySku } = usePrice(); if (products.value.length > 0) { const skus = products.value.map((item) => item.sku); const priceData = await getPricesBySku(skus, pagination.value.itemsPerPage); - products.value = products.value.map((product) => ({ - ...product, - price_range: priceData.items.find((item) => item.sku === product.sku)?.price_range, - })); + products.value = products.value.map((product) => { + const priceRange = priceData.items.find((item) => item.sku === product.sku)?.price_range; + + if (priceRange) { + return { + ...product, + price_range: priceRange, + }; + } + + return { ...product }; + }); } + isPriceLoaded.value = true; }); diff --git a/packages/theme/modules/catalog/product/getters/productGetters.ts b/packages/theme/modules/catalog/product/getters/productGetters.ts index 575e03a42..40c1bd176 100644 --- a/packages/theme/modules/catalog/product/getters/productGetters.ts +++ b/packages/theme/modules/catalog/product/getters/productGetters.ts @@ -92,7 +92,7 @@ export const getPrice = (product: ProductInterface): Price => { export const getGallery = (product: Product, maxGallerySize = 4): MediaGalleryItem[] => { const images = []; - if (!product?.media_gallery.length && !product?.configurable_product_options_selection?.media_gallery.length) { + if (!product?.media_gallery?.length && !product?.configurable_product_options_selection?.media_gallery?.length) { return images; } From 587014d81debf345d2a004e35f8d977bf858351b Mon Sep 17 00:00:00 2001 From: Bartosz Herba Date: Thu, 6 Oct 2022 12:03:03 +0200 Subject: [PATCH 86/89] fix: ssr reload on the grouped product page --- .../api/productDetail/productDetailsQuery.ts | 34 +++++++++++++++++++ packages/theme/lang/de.js | 1 + packages/theme/lang/en.js | 1 + .../grouped/GroupedProductSelector.vue | 2 +- 4 files changed, 37 insertions(+), 1 deletion(-) diff --git a/packages/api-client/src/api/productDetail/productDetailsQuery.ts b/packages/api-client/src/api/productDetail/productDetailsQuery.ts index 8fc21b46c..7dd0e79d9 100644 --- a/packages/api-client/src/api/productDetail/productDetailsQuery.ts +++ b/packages/api-client/src/api/productDetail/productDetailsQuery.ts @@ -131,8 +131,42 @@ export default gql` } ... on GroupedProduct { items { + position + qty product { + uid sku + name + stock_status + only_x_left_in_stock + price_range { + maximum_price { + final_price { + currency + value + } + regular_price { + currency + value + } + } + minimum_price { + final_price { + currency + value + } + regular_price { + currency + value + } + } + } + thumbnail { + url + position + disabled + label + } } } } diff --git a/packages/theme/lang/de.js b/packages/theme/lang/de.js index e10b0600b..47e159ecb 100644 --- a/packages/theme/lang/de.js +++ b/packages/theme/lang/de.js @@ -306,4 +306,5 @@ export default { "The user password was changed successfully updated!":"Das Benutzerpasswort wurde erfolgreich geändert aktualisiert!", "The user account data was successfully updated!":"Die Benutzerkontodaten wurden erfolgreich aktualisiert!", "You submitted your review for moderation.": "Sie haben Ihre Bewertung zur Moderation eingereicht.", + "Starting at": "Beginnt um", }; diff --git a/packages/theme/lang/en.js b/packages/theme/lang/en.js index f19f76cf8..81708eec4 100644 --- a/packages/theme/lang/en.js +++ b/packages/theme/lang/en.js @@ -304,4 +304,5 @@ export default { "The user password was changed successfully updated!":"The user password was changed successfully updated!", "The user account data was successfully updated!":"The user account data was successfully updated!", "You submitted your review for moderation.": "You submitted your review for moderation.", + "Starting at": "Starting at", }; diff --git a/packages/theme/modules/catalog/product/components/product-types/grouped/GroupedProductSelector.vue b/packages/theme/modules/catalog/product/components/product-types/grouped/GroupedProductSelector.vue index a10477d58..98676d39e 100644 --- a/packages/theme/modules/catalog/product/components/product-types/grouped/GroupedProductSelector.vue +++ b/packages/theme/modules/catalog/product/components/product-types/grouped/GroupedProductSelector.vue @@ -40,7 +40,7 @@ class="color-primary sf-button grouped_items--add-to-cart" @click="addToCart" > - {{ $t('Add to Cart') }} + {{ $t('Add to cart') }} Date: Thu, 6 Oct 2022 10:05:02 +0200 Subject: [PATCH 87/89] fix: product detail gallery is missing when browsing products using mobile chromium based browsers --- .../catalog/product/components/product-types/styles.scss | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/theme/modules/catalog/product/components/product-types/styles.scss b/packages/theme/modules/catalog/product/components/product-types/styles.scss index f20fd78ee..f98228d0d 100644 --- a/packages/theme/modules/catalog/product/components/product-types/styles.scss +++ b/packages/theme/modules/catalog/product/components/product-types/styles.scss @@ -162,6 +162,9 @@ } ::v-deep .sf-gallery__thumbs { + .sf-image { + position: relative; + } .sf-image-loaded { display: block; } From 96db2718cc236af653cdf6d40fd4fec767588d8a Mon Sep 17 00:00:00 2001 From: Bartosz Herba Date: Thu, 6 Oct 2022 08:42:18 +0200 Subject: [PATCH 88/89] fix: cart type error in the console after opening mini cart as a guest --- packages/theme/components/CartSidebar.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/theme/components/CartSidebar.vue b/packages/theme/components/CartSidebar.vue index c35b7a731..18c103a80 100644 --- a/packages/theme/components/CartSidebar.vue +++ b/packages/theme/components/CartSidebar.vue @@ -361,7 +361,7 @@ export default defineComponent({ const tempProduct = ref(); onMounted(() => { - if (!cart.value.id) { + if (!cart.value?.id) { loadCart(); } }); From ba9b8cf2125c65e66829148c2312d5616c915d75 Mon Sep 17 00:00:00 2001 From: Bartosz Herba Date: Wed, 19 Oct 2022 10:32:05 +0200 Subject: [PATCH 89/89] docs: update release 1.1.0 docs --- docs/migration-guides/1.1.0/index.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/migration-guides/1.1.0/index.md b/docs/migration-guides/1.1.0/index.md index be3d02aee..6de78c8a4 100644 --- a/docs/migration-guides/1.1.0/index.md +++ b/docs/migration-guides/1.1.0/index.md @@ -30,7 +30,13 @@ Vue Storefront for Magento 1.1.0 provides a few new features like SEO-friendly U - fix: fix product detail components [https://github.com/vuestorefront/magento2/pull/1330](https://github.com/vuestorefront/magento2/pull/1330) - fix: downloadableProduct might not have been initialized [https://github.com/vuestorefront/magento2/pull/1325](https://github.com/vuestorefront/magento2/pull/1325) - fix: getAvailableShippingMethods query variables [https://github.com/vuestorefront/magento2/pull/1318](https://github.com/vuestorefront/magento2/pull/1318) - +- fix: update CDN default configuration [https://github.com/vuestorefront/magento2/pull/1372](https://github.com/vuestorefront/magento2/pull/1372) +- fix: getMagentoImage reading 'split' error [https://github.com/vuestorefront/magento2/pull/1373](https://github.com/vuestorefront/magento2/pull/1373) +- fix: cart type error in the console after opening mini cart as a guest [https://github.com/vuestorefront/magento2/pull/1374](https://github.com/vuestorefront/magento2/pull/1374) +- fix: product detail gallery is missing when browsing products using mobile [https://github.com/vuestorefront/magento2/pull/1375](https://github.com/vuestorefront/magento2/pull/1375) +- fix: ssr reload on the grouped product page [https://github.com/vuestorefront/magento2/pull/1376](https://github.com/vuestorefront/magento2/pull/1376) +- fix: product list page items on product page list page zero prices issues [https://github.com/vuestorefront/magento2/pull/1379](https://github.com/vuestorefront/magento2/pull/1379) +- ### Chore - chore: removed deprecated composables packages from the repository [https://github.com/vuestorefront/magento2/pull/1322](https://github.com/vuestorefront/magento2/pull/1322) @@ -39,6 +45,7 @@ Vue Storefront for Magento 1.1.0 provides a few new features like SEO-friendly U - docs: fixed breaking change reference link [https://github.com/vuestorefront/magento2/pull/1350](https://github.com/vuestorefront/magento2/pull/1350) - docs: fix wording + add installation video [https://github.com/vuestorefront/magento2/pull/1319](https://github.com/vuestorefront/magento2/pull/1319) +- docs: removed outdated information about cors configuration [https://github.com/vuestorefront/magento2/pull/1378](https://github.com/vuestorefront/magento2/pull/1378) ### Repository