@salesforce/b2c-cli 2.3.1 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/dev.js +8 -8
- package/bin/run.js +5 -7
- package/content/guidance/b2c/b2c-business-manager-extensions/SKILL.md +361 -0
- package/content/guidance/b2c/b2c-business-manager-extensions/references/EXTENSIONS-XML.md +458 -0
- package/content/guidance/b2c/b2c-controllers/SKILL.md +301 -0
- package/content/guidance/b2c/b2c-controllers/references/CLASSIC-PATTERNS.md +335 -0
- package/content/guidance/b2c/b2c-controllers/references/SFRA-PATTERNS.md +400 -0
- package/content/guidance/b2c/b2c-custom-api-development/SKILL.md +281 -0
- package/content/guidance/b2c/b2c-custom-api-development/references/CONTRACT.md +142 -0
- package/content/guidance/b2c/b2c-custom-api-development/references/IMPLEMENTATION.md +153 -0
- package/content/guidance/b2c/b2c-custom-api-development/references/TESTING.md +118 -0
- package/content/guidance/b2c/b2c-custom-caches/SKILL.md +279 -0
- package/content/guidance/b2c/b2c-custom-job-steps/SKILL.md +520 -0
- package/content/guidance/b2c/b2c-custom-job-steps/references/CHUNK-ORIENTED.md +377 -0
- package/content/guidance/b2c/b2c-custom-job-steps/references/JOBS-XML.md +212 -0
- package/content/guidance/b2c/b2c-custom-job-steps/references/STEPTYPES-JSON.md +373 -0
- package/content/guidance/b2c/b2c-custom-job-steps/references/TASK-ORIENTED.md +344 -0
- package/content/guidance/b2c/b2c-custom-objects/SKILL.md +327 -0
- package/content/guidance/b2c/b2c-custom-objects/references/OCAPI-SEARCH.md +298 -0
- package/content/guidance/b2c/b2c-forms/SKILL.md +242 -0
- package/content/guidance/b2c/b2c-forms/references/FORM-XML.md +409 -0
- package/content/guidance/b2c/b2c-hooks/SKILL.md +500 -0
- package/content/guidance/b2c/b2c-hooks/references/OCAPI-SCAPI-HOOKS.md +403 -0
- package/content/guidance/b2c/b2c-hooks/references/ORDER-HOOK-LIFECYCLE.md +169 -0
- package/content/guidance/b2c/b2c-hooks/references/SYSTEM-HOOKS.md +433 -0
- package/content/guidance/b2c/b2c-isml/SKILL.md +320 -0
- package/content/guidance/b2c/b2c-isml/references/EXPRESSIONS.md +366 -0
- package/content/guidance/b2c/b2c-isml/references/TAGS.md +443 -0
- package/content/guidance/b2c/b2c-localization/SKILL.md +344 -0
- package/content/guidance/b2c/b2c-localization/references/PATTERNS.md +407 -0
- package/content/guidance/b2c/b2c-logging/SKILL.md +352 -0
- package/content/guidance/b2c/b2c-logging/references/LOG-FILES.md +282 -0
- package/content/guidance/b2c/b2c-metadata/SKILL.md +406 -0
- package/content/guidance/b2c/b2c-metadata/references/SYSTEM-OBJECTS.md +320 -0
- package/content/guidance/b2c/b2c-metadata/references/XML-EXAMPLES.md +366 -0
- package/content/guidance/b2c/b2c-onboarding/SKILL.md +154 -0
- package/content/guidance/b2c/b2c-ordering/SKILL.md +391 -0
- package/content/guidance/b2c/b2c-page-designer/SKILL.md +410 -0
- package/content/guidance/b2c/b2c-page-designer/references/ATTRIBUTE-TYPES.md +436 -0
- package/content/guidance/b2c/b2c-page-designer/references/META-DEFINITIONS.md +340 -0
- package/content/guidance/b2c/b2c-querying-data/SKILL.md +289 -0
- package/content/guidance/b2c/b2c-querying-data/references/PERFORMANCE-APIS.md +74 -0
- package/content/guidance/b2c/b2c-scapi-admin/SKILL.md +53 -0
- package/content/guidance/b2c/b2c-scapi-admin/references/CLIENT-EXAMPLES.md +440 -0
- package/content/guidance/b2c/b2c-scapi-admin/references/INTEGRATION-PATTERNS.md +518 -0
- package/content/guidance/b2c/b2c-scapi-admin/references/OAUTH-SCOPES.md +337 -0
- package/content/guidance/b2c/b2c-scapi-shopper/SKILL.md +56 -0
- package/content/guidance/b2c/b2c-scapi-shopper/references/CHECKOUT-FLOW.md +466 -0
- package/content/guidance/b2c/b2c-scapi-shopper/references/CLIENT-EXAMPLES.md +351 -0
- package/content/guidance/b2c/b2c-scapi-shopper/references/COMMON-PATTERNS.md +390 -0
- package/content/guidance/b2c/b2c-scapi-shopper/references/SCOPES.md +290 -0
- package/content/guidance/b2c/b2c-slas-auth-patterns/SKILL.md +420 -0
- package/content/guidance/b2c/b2c-slas-auth-patterns/references/PASSKEYS.md +126 -0
- package/content/guidance/b2c/b2c-slas-auth-patterns/references/SESSION-BRIDGE.md +267 -0
- package/content/guidance/b2c/b2c-slas-auth-patterns/references/TOKEN-LIFECYCLE.md +367 -0
- package/content/guidance/b2c/b2c-webservices/SKILL.md +318 -0
- package/content/guidance/b2c/b2c-webservices/references/FTP-SERVICES.md +524 -0
- package/content/guidance/b2c/b2c-webservices/references/HTTP-SERVICES.md +578 -0
- package/content/guidance/b2c/b2c-webservices/references/SERVICES-XML.md +351 -0
- package/content/guidance/b2c/b2c-webservices/references/SOAP-SERVICES.md +587 -0
- package/content/guidance/b2c-cli/b2c-am/SKILL.md +277 -0
- package/content/guidance/b2c-cli/b2c-bm-users-roles/SKILL.md +210 -0
- package/content/guidance/b2c-cli/b2c-cap/SKILL.md +131 -0
- package/content/guidance/b2c-cli/b2c-cip/SKILL.md +116 -0
- package/content/guidance/b2c-cli/b2c-cip/references/KNOWN_TABLES.md +105 -0
- package/content/guidance/b2c-cli/b2c-cip/references/SALES_ANALYSIS.md +50 -0
- package/content/guidance/b2c-cli/b2c-cip/references/STARTER_QUERIES.md +147 -0
- package/content/guidance/b2c-cli/b2c-code/SKILL.md +146 -0
- package/content/guidance/b2c-cli/b2c-config/SKILL.md +462 -0
- package/content/guidance/b2c-cli/b2c-content/SKILL.md +176 -0
- package/content/guidance/b2c-cli/b2c-debug/SKILL.md +138 -0
- package/content/guidance/b2c-cli/b2c-docs/SKILL.md +301 -0
- package/content/guidance/b2c-cli/b2c-ecdn/SKILL.md +135 -0
- package/content/guidance/b2c-cli/b2c-ecdn/references/ADVANCED.md +97 -0
- package/content/guidance/b2c-cli/b2c-ecdn/references/SECURITY.md +75 -0
- package/content/guidance/b2c-cli/b2c-import-set-migrations/SKILL.md +265 -0
- package/content/guidance/b2c-cli/b2c-job/SKILL.md +64 -0
- package/content/guidance/b2c-cli/b2c-job/references/EXPORT.md +121 -0
- package/content/guidance/b2c-cli/b2c-job/references/IMPORT.md +55 -0
- package/content/guidance/b2c-cli/b2c-job/references/RUN-AND-MONITOR.md +119 -0
- package/content/guidance/b2c-cli/b2c-logs/SKILL.md +249 -0
- package/content/guidance/b2c-cli/b2c-metrics/SKILL.md +315 -0
- package/content/guidance/b2c-cli/b2c-mrt/SKILL.md +207 -0
- package/content/guidance/b2c-cli/b2c-mrt/references/BUNDLE-COMMANDS.md +203 -0
- package/content/guidance/b2c-cli/b2c-mrt/references/ENVIRONMENT-COMMANDS.md +218 -0
- package/content/guidance/b2c-cli/b2c-mrt/references/PROJECT-COMMANDS.md +154 -0
- package/content/guidance/b2c-cli/b2c-sandbox/SKILL.md +112 -0
- package/content/guidance/b2c-cli/b2c-scapi-custom/SKILL.md +126 -0
- package/content/guidance/b2c-cli/b2c-scapi-schemas/SKILL.md +66 -0
- package/content/guidance/b2c-cli/b2c-scapi-schemas/references/CLI-EXAMPLES.md +108 -0
- package/content/guidance/b2c-cli/b2c-site-import-export/SKILL.md +57 -0
- package/content/guidance/b2c-cli/b2c-site-import-export/references/IMPORT-OPTIONS.md +118 -0
- package/content/guidance/b2c-cli/b2c-site-import-export/references/METADATA-XML.md +381 -0
- package/content/guidance/b2c-cli/b2c-site-import-export/references/WORKFLOWS.md +182 -0
- package/content/guidance/b2c-cli/b2c-sites/SKILL.md +112 -0
- package/content/guidance/b2c-cli/b2c-slas/SKILL.md +182 -0
- package/content/guidance/b2c-cli/b2c-webdav/SKILL.md +186 -0
- package/content/guidance/b2c-ops/b2c-checkout-triage/SKILL.md +68 -0
- package/content/guidance/b2c-ops/b2c-job-health/SKILL.md +75 -0
- package/content/guidance/b2c-ops/b2c-job-health/references/job-logs.md +21 -0
- package/content/guidance/b2c-ops/b2c-order-failure-triage/SKILL.md +66 -0
- package/content/guidance/b2c-ops/b2c-order-failure-triage/references/order-evidence.md +87 -0
- package/content/guidance/b2c-ops/b2c-production-triage/SKILL.md +87 -0
- package/content/guidance/b2c-ops/b2c-production-triage/references/escalation.md +57 -0
- package/content/guidance/index.json +1949 -0
- package/content/guidance/storefront-next/sfnext-accessibility/SKILL.md +103 -0
- package/content/guidance/storefront-next/sfnext-accessibility/references/checklist.md +64 -0
- package/content/guidance/storefront-next/sfnext-analytics-consent/SKILL.md +91 -0
- package/content/guidance/storefront-next/sfnext-analytics-consent/references/CUSTOM-ADAPTER.md +49 -0
- package/content/guidance/storefront-next/sfnext-authentication/SKILL.md +127 -0
- package/content/guidance/storefront-next/sfnext-authentication/references/COOKIES.md +39 -0
- package/content/guidance/storefront-next/sfnext-authentication/references/LOGIN-FLOWS.md +59 -0
- package/content/guidance/storefront-next/sfnext-commerce-features/SKILL.md +67 -0
- package/content/guidance/storefront-next/sfnext-commerce-features/references/FEATURE-PREREQUISITES.md +37 -0
- package/content/guidance/storefront-next/sfnext-components/SKILL.md +153 -0
- package/content/guidance/storefront-next/sfnext-components/references/COMPONENT-AUTHORING.md +118 -0
- package/content/guidance/storefront-next/sfnext-components/references/SHAPE-TOKENS.md +51 -0
- package/content/guidance/storefront-next/sfnext-components/references/STORYBOOK.md +54 -0
- package/content/guidance/storefront-next/sfnext-components/references/TOKEN-SYSTEM.md +53 -0
- package/content/guidance/storefront-next/sfnext-components/references/TROUBLESHOOTING.md +19 -0
- package/content/guidance/storefront-next/sfnext-configuration/SKILL.md +163 -0
- package/content/guidance/storefront-next/sfnext-configuration/references/ENV-VARIABLES.md +55 -0
- package/content/guidance/storefront-next/sfnext-configuration/references/MULTI-SITE-URLS.md +137 -0
- package/content/guidance/storefront-next/sfnext-data-fetching/SKILL.md +140 -0
- package/content/guidance/storefront-next/sfnext-data-fetching/references/ACTIONS.md +53 -0
- package/content/guidance/storefront-next/sfnext-data-fetching/references/API-CLIENTS.md +34 -0
- package/content/guidance/storefront-next/sfnext-data-fetching/references/LOADERS.md +73 -0
- package/content/guidance/storefront-next/sfnext-data-fetching/references/SCAPI-FETCHER.md +39 -0
- package/content/guidance/storefront-next/sfnext-deployment/SKILL.md +127 -0
- package/content/guidance/storefront-next/sfnext-deployment/references/MRT-DEPLOYMENT.md +59 -0
- package/content/guidance/storefront-next/sfnext-extensions/SKILL.md +118 -0
- package/content/guidance/storefront-next/sfnext-extensions/references/ACTION-HOOKS.md +57 -0
- package/content/guidance/storefront-next/sfnext-extensions/references/BASE-AUDIT.md +68 -0
- package/content/guidance/storefront-next/sfnext-extensions/references/CLI-AND-INSTALL.md +58 -0
- package/content/guidance/storefront-next/sfnext-extensions/references/EXTENSION-EXAMPLES.md +79 -0
- package/content/guidance/storefront-next/sfnext-hybrid-storefronts/SKILL.md +93 -0
- package/content/guidance/storefront-next/sfnext-hybrid-storefronts/references/HYBRID-PROXY-CONFIG.md +86 -0
- package/content/guidance/storefront-next/sfnext-i18n/SKILL.md +152 -0
- package/content/guidance/storefront-next/sfnext-i18n/references/locale-config.md +35 -0
- package/content/guidance/storefront-next/sfnext-overview/SKILL.md +101 -0
- package/content/guidance/storefront-next/sfnext-page-designer/SKILL.md +202 -0
- package/content/guidance/storefront-next/sfnext-page-designer/references/BUSINESS-MANAGER.md +46 -0
- package/content/guidance/storefront-next/sfnext-page-designer/references/COMPONENT-REGISTRY.md +111 -0
- package/content/guidance/storefront-next/sfnext-page-designer/references/DECORATOR-PATTERNS.md +168 -0
- package/content/guidance/storefront-next/sfnext-page-designer/references/REVIEW-CHECKLIST.md +83 -0
- package/content/guidance/storefront-next/sfnext-page-designer/references/TROUBLESHOOTING.md +35 -0
- package/content/guidance/storefront-next/sfnext-performance/SKILL.md +102 -0
- package/content/guidance/storefront-next/sfnext-performance/references/PERFORMANCE-REVIEW-CHECKLIST.md +85 -0
- package/content/guidance/storefront-next/sfnext-performance/references/SUSPENSE-AND-STREAMING.md +58 -0
- package/content/guidance/storefront-next/sfnext-project-setup/SKILL.md +147 -0
- package/content/guidance/storefront-next/sfnext-project-setup/references/PROJECT-STRUCTURE.md +61 -0
- package/content/guidance/storefront-next/sfnext-project-setup/references/SCRIPTS.md +47 -0
- package/content/guidance/storefront-next/sfnext-project-setup/references/SFNEXT-CLI.md +63 -0
- package/content/guidance/storefront-next/sfnext-quality-gates/SKILL.md +70 -0
- package/content/guidance/storefront-next/sfnext-quality-gates/references/lint-and-budgets.md +39 -0
- package/content/guidance/storefront-next/sfnext-revalidation/SKILL.md +121 -0
- package/content/guidance/storefront-next/sfnext-revalidation/references/POLICIES-AND-TAGS.md +55 -0
- package/content/guidance/storefront-next/sfnext-routing/SKILL.md +123 -0
- package/content/guidance/storefront-next/sfnext-routing/references/ROUTE-CONVENTIONS.md +65 -0
- package/content/guidance/storefront-next/sfnext-routing/references/URLS-AND-SEO-ROUTES.md +22 -0
- package/content/guidance/storefront-next/sfnext-scapi/SKILL.md +126 -0
- package/content/guidance/storefront-next/sfnext-scapi/references/WORKED-EXAMPLE.md +39 -0
- package/content/guidance/storefront-next/sfnext-security/SKILL.md +129 -0
- package/content/guidance/storefront-next/sfnext-security/references/COOKIE-DOMAIN.md +39 -0
- package/content/guidance/storefront-next/sfnext-security/references/TURNSTILE.md +43 -0
- package/content/guidance/storefront-next/sfnext-seo/SKILL.md +95 -0
- package/content/guidance/storefront-next/sfnext-seo/references/MULTI-DOMAIN-BASE-PATH.md +17 -0
- package/content/guidance/storefront-next/sfnext-seo/references/SEO-ROUTES.md +31 -0
- package/content/guidance/storefront-next/sfnext-state-management/SKILL.md +114 -0
- package/content/guidance/storefront-next/sfnext-state-management/references/PATTERNS.md +45 -0
- package/content/guidance/storefront-next/sfnext-testing/SKILL.md +151 -0
- package/content/guidance/storefront-next/sfnext-testing/references/E2E.md +38 -0
- package/content/guidance/storefront-next/sfnext-testing/references/STORYBOOK-PATTERNS.md +97 -0
- package/content/guidance/storefront-next/sfnext-testing/references/UNIT-AND-ROUTE-TESTS.md +60 -0
- package/content/guidance/storefront-next/sfnext-theming/SKILL.md +104 -0
- package/content/guidance/storefront-next/sfnext-theming/references/REBRAND-CHECKLIST.md +29 -0
- package/dist/commands/cap/install.d.ts +1 -0
- package/dist/commands/cap/list.d.ts +1 -0
- package/dist/commands/cap/pull.d.ts +1 -0
- package/dist/commands/cap/tasks.d.ts +1 -0
- package/dist/commands/cap/uninstall.d.ts +1 -0
- package/dist/commands/cip/describe.d.ts +1 -0
- package/dist/commands/cip/query.d.ts +1 -0
- package/dist/commands/cip/report/bot-traffic-share.d.ts +1 -0
- package/dist/commands/cip/report/checkout-funnel-dropoff.d.ts +1 -0
- package/dist/commands/cip/report/controller-error-rate-trend.d.ts +1 -0
- package/dist/commands/cip/report/controller-health-scorecard.d.ts +1 -0
- package/dist/commands/cip/report/customer-registration-trends.d.ts +1 -0
- package/dist/commands/cip/report/discount-depth-breakdown.d.ts +1 -0
- package/dist/commands/cip/report/inventory-stockout-by-location.d.ts +1 -0
- package/dist/commands/cip/report/new-vs-returning-buyer-revenue.d.ts +1 -0
- package/dist/commands/cip/report/ocapi-client-usage.d.ts +1 -0
- package/dist/commands/cip/report/ocapi-requests.d.ts +1 -0
- package/dist/commands/cip/report/payment-method-performance.d.ts +1 -0
- package/dist/commands/cip/report/product-co-purchase-analysis.d.ts +1 -0
- package/dist/commands/cip/report/promotion-discount-analysis.d.ts +1 -0
- package/dist/commands/cip/report/promotion-roi-leaderboard.d.ts +1 -0
- package/dist/commands/cip/report/recommender-effectiveness.d.ts +1 -0
- package/dist/commands/cip/report/remote-include-performance.d.ts +1 -0
- package/dist/commands/cip/report/revenue-by-channel.d.ts +1 -0
- package/dist/commands/cip/report/sales-analytics.d.ts +1 -0
- package/dist/commands/cip/report/sales-summary.d.ts +1 -0
- package/dist/commands/cip/report/scapi-cache-hit-ratio.d.ts +1 -0
- package/dist/commands/cip/report/scapi-error-rate-by-status.d.ts +1 -0
- package/dist/commands/cip/report/scapi-latency-distribution.d.ts +1 -0
- package/dist/commands/cip/report/scapi-traffic-latency.d.ts +1 -0
- package/dist/commands/cip/report/search-query-performance.d.ts +1 -0
- package/dist/commands/cip/report/top-referrers.d.ts +1 -0
- package/dist/commands/cip/report/top-selling-products.d.ts +1 -0
- package/dist/commands/cip/report/zero-result-searches.d.ts +1 -0
- package/dist/commands/cip/tables.d.ts +1 -0
- package/dist/commands/code/activate.d.ts +1 -0
- package/dist/commands/code/delete.d.ts +1 -0
- package/dist/commands/code/deploy.d.ts +1 -0
- package/dist/commands/code/download.d.ts +1 -0
- package/dist/commands/code/watch.d.ts +1 -0
- package/dist/commands/commands/search.d.ts +35 -0
- package/dist/commands/commands/search.js +85 -0
- package/dist/commands/commands/search.js.map +1 -0
- package/dist/commands/content/export.d.ts +1 -0
- package/dist/commands/content/list.d.ts +1 -0
- package/dist/commands/content/validate.d.ts +1 -0
- package/dist/commands/debug/cli.d.ts +1 -0
- package/dist/commands/debug/index.d.ts +1 -0
- package/dist/commands/docs/cache.d.ts +1 -0
- package/dist/commands/docs/download.d.ts +1 -0
- package/dist/commands/docs/read.d.ts +1 -0
- package/dist/commands/docs/schema.d.ts +1 -0
- package/dist/commands/docs/search.d.ts +1 -0
- package/dist/commands/docs/skill.d.ts +41 -0
- package/dist/commands/docs/skill.js +183 -0
- package/dist/commands/docs/skill.js.map +1 -0
- package/dist/commands/ecdn/cache/purge.d.ts +1 -0
- package/dist/commands/ecdn/certificates/add.d.ts +1 -0
- package/dist/commands/ecdn/certificates/delete.d.ts +1 -0
- package/dist/commands/ecdn/certificates/list.d.ts +1 -0
- package/dist/commands/ecdn/certificates/update.d.ts +1 -0
- package/dist/commands/ecdn/certificates/validate.d.ts +1 -0
- package/dist/commands/ecdn/cipher-suites/get.d.ts +1 -0
- package/dist/commands/ecdn/cipher-suites/update.d.ts +1 -0
- package/dist/commands/ecdn/firewall/create.d.ts +1 -0
- package/dist/commands/ecdn/firewall/delete.d.ts +1 -0
- package/dist/commands/ecdn/firewall/get.d.ts +1 -0
- package/dist/commands/ecdn/firewall/list.d.ts +1 -0
- package/dist/commands/ecdn/firewall/reorder.d.ts +1 -0
- package/dist/commands/ecdn/firewall/update.d.ts +1 -0
- package/dist/commands/ecdn/logpush/jobs/create.d.ts +1 -0
- package/dist/commands/ecdn/logpush/jobs/delete.d.ts +1 -0
- package/dist/commands/ecdn/logpush/jobs/get.d.ts +1 -0
- package/dist/commands/ecdn/logpush/jobs/list.d.ts +1 -0
- package/dist/commands/ecdn/logpush/jobs/update.d.ts +1 -0
- package/dist/commands/ecdn/logpush/ownership.d.ts +1 -0
- package/dist/commands/ecdn/mrt-rules/create.d.ts +1 -0
- package/dist/commands/ecdn/mrt-rules/delete.d.ts +1 -0
- package/dist/commands/ecdn/mrt-rules/get.d.ts +1 -0
- package/dist/commands/ecdn/mrt-rules/rules/delete.d.ts +1 -0
- package/dist/commands/ecdn/mrt-rules/rules/update.d.ts +1 -0
- package/dist/commands/ecdn/mrt-rules/update.d.ts +1 -0
- package/dist/commands/ecdn/mtls/create.d.ts +1 -0
- package/dist/commands/ecdn/mtls/delete.d.ts +1 -0
- package/dist/commands/ecdn/mtls/get.d.ts +1 -0
- package/dist/commands/ecdn/mtls/issue.d.ts +1 -0
- package/dist/commands/ecdn/mtls/list.d.ts +1 -0
- package/dist/commands/ecdn/mtls/setup.d.ts +1 -0
- package/dist/commands/ecdn/origin-headers/delete.d.ts +1 -0
- package/dist/commands/ecdn/origin-headers/get.d.ts +1 -0
- package/dist/commands/ecdn/origin-headers/set.d.ts +1 -0
- package/dist/commands/ecdn/page-shield/notifications/create.d.ts +1 -0
- package/dist/commands/ecdn/page-shield/notifications/delete.d.ts +1 -0
- package/dist/commands/ecdn/page-shield/notifications/list.d.ts +1 -0
- package/dist/commands/ecdn/page-shield/policies/create.d.ts +1 -0
- package/dist/commands/ecdn/page-shield/policies/delete.d.ts +1 -0
- package/dist/commands/ecdn/page-shield/policies/get.d.ts +1 -0
- package/dist/commands/ecdn/page-shield/policies/list.d.ts +1 -0
- package/dist/commands/ecdn/page-shield/policies/update.d.ts +1 -0
- package/dist/commands/ecdn/page-shield/scripts/get.d.ts +1 -0
- package/dist/commands/ecdn/page-shield/scripts/list.d.ts +1 -0
- package/dist/commands/ecdn/rate-limit/create.d.ts +1 -0
- package/dist/commands/ecdn/rate-limit/delete.d.ts +1 -0
- package/dist/commands/ecdn/rate-limit/get.d.ts +1 -0
- package/dist/commands/ecdn/rate-limit/list.d.ts +1 -0
- package/dist/commands/ecdn/rate-limit/update.d.ts +1 -0
- package/dist/commands/ecdn/security/get.d.ts +1 -0
- package/dist/commands/ecdn/security/update.d.ts +1 -0
- package/dist/commands/ecdn/speed/get.d.ts +1 -0
- package/dist/commands/ecdn/speed/update.d.ts +1 -0
- package/dist/commands/ecdn/waf/groups/list.d.ts +1 -0
- package/dist/commands/ecdn/waf/groups/update.d.ts +1 -0
- package/dist/commands/ecdn/waf/managed-rules/list.d.ts +1 -0
- package/dist/commands/ecdn/waf/managed-rules/update.d.ts +1 -0
- package/dist/commands/ecdn/waf/migrate.d.ts +1 -0
- package/dist/commands/ecdn/waf/owasp/get.d.ts +1 -0
- package/dist/commands/ecdn/waf/owasp/update.d.ts +1 -0
- package/dist/commands/ecdn/waf/rules/get.d.ts +1 -0
- package/dist/commands/ecdn/waf/rules/list.d.ts +1 -0
- package/dist/commands/ecdn/waf/rules/update.d.ts +1 -0
- package/dist/commands/ecdn/waf/rulesets/list.d.ts +1 -0
- package/dist/commands/ecdn/waf/rulesets/update.d.ts +1 -0
- package/dist/commands/ecdn/zones/create.d.ts +1 -0
- package/dist/commands/ecdn/zones/list.d.ts +1 -0
- package/dist/commands/job/execution/delete.d.ts +1 -0
- package/dist/commands/job/export.d.ts +1 -0
- package/dist/commands/job/import-set.d.ts +1 -0
- package/dist/commands/job/import.d.ts +1 -0
- package/dist/commands/job/log.d.ts +1 -0
- package/dist/commands/job/run.d.ts +1 -0
- package/dist/commands/job/search.d.ts +1 -0
- package/dist/commands/job/wait.d.ts +1 -0
- package/dist/commands/logs/get.d.ts +1 -0
- package/dist/commands/logs/list.d.ts +1 -0
- package/dist/commands/logs/tail.d.ts +1 -0
- package/dist/commands/metrics/controller.d.ts +1 -0
- package/dist/commands/metrics/ecdn.d.ts +1 -0
- package/dist/commands/metrics/mrt.d.ts +1 -0
- package/dist/commands/metrics/ocapi.d.ts +1 -0
- package/dist/commands/metrics/overall.d.ts +1 -0
- package/dist/commands/metrics/sales.d.ts +1 -0
- package/dist/commands/metrics/scapi-hooks.d.ts +1 -0
- package/dist/commands/metrics/scapi.d.ts +1 -0
- package/dist/commands/metrics/third-party.d.ts +1 -0
- package/dist/commands/mrt/bundle/delete.d.ts +1 -0
- package/dist/commands/mrt/bundle/deploy.d.ts +1 -0
- package/dist/commands/mrt/bundle/download.d.ts +1 -0
- package/dist/commands/mrt/bundle/history.d.ts +1 -0
- package/dist/commands/mrt/bundle/list.d.ts +1 -0
- package/dist/commands/mrt/bundle/save.d.ts +1 -0
- package/dist/commands/mrt/bundle/upload-v2.d.ts +1 -0
- package/dist/commands/mrt/env/access-control/list.d.ts +1 -0
- package/dist/commands/mrt/env/b2c.d.ts +1 -0
- package/dist/commands/mrt/env/clone.d.ts +1 -0
- package/dist/commands/mrt/env/create.d.ts +1 -0
- package/dist/commands/mrt/env/delete.d.ts +1 -0
- package/dist/commands/mrt/env/get.d.ts +1 -0
- package/dist/commands/mrt/env/invalidate.d.ts +1 -0
- package/dist/commands/mrt/env/list.d.ts +1 -0
- package/dist/commands/mrt/env/redirect/clone.d.ts +1 -0
- package/dist/commands/mrt/env/redirect/create.d.ts +1 -0
- package/dist/commands/mrt/env/redirect/delete.d.ts +1 -0
- package/dist/commands/mrt/env/redirect/list.d.ts +1 -0
- package/dist/commands/mrt/env/update.d.ts +1 -0
- package/dist/commands/mrt/env/var/delete.d.ts +1 -0
- package/dist/commands/mrt/env/var/list.d.ts +1 -0
- package/dist/commands/mrt/env/var/push.d.ts +1 -0
- package/dist/commands/mrt/env/var/set.d.ts +1 -0
- package/dist/commands/mrt/org/b2c.d.ts +1 -0
- package/dist/commands/mrt/org/cert/create.d.ts +1 -0
- package/dist/commands/mrt/org/cert/delete.d.ts +1 -0
- package/dist/commands/mrt/org/cert/get.d.ts +1 -0
- package/dist/commands/mrt/org/cert/list.d.ts +1 -0
- package/dist/commands/mrt/org/cert/restart-validation.d.ts +1 -0
- package/dist/commands/mrt/org/list.d.ts +1 -0
- package/dist/commands/mrt/org/member/add.d.ts +1 -0
- package/dist/commands/mrt/org/member/get.d.ts +1 -0
- package/dist/commands/mrt/org/member/list.d.ts +1 -0
- package/dist/commands/mrt/org/member/remove.d.ts +1 -0
- package/dist/commands/mrt/org/member/update.d.ts +1 -0
- package/dist/commands/mrt/project/create.d.ts +1 -0
- package/dist/commands/mrt/project/delete.d.ts +1 -0
- package/dist/commands/mrt/project/get.d.ts +1 -0
- package/dist/commands/mrt/project/list.d.ts +1 -0
- package/dist/commands/mrt/project/member/add.d.ts +1 -0
- package/dist/commands/mrt/project/member/get.d.ts +1 -0
- package/dist/commands/mrt/project/member/list.d.ts +1 -0
- package/dist/commands/mrt/project/member/remove.d.ts +1 -0
- package/dist/commands/mrt/project/member/update.d.ts +1 -0
- package/dist/commands/mrt/project/notification/delete.d.ts +1 -0
- package/dist/commands/mrt/project/notification/get.d.ts +1 -0
- package/dist/commands/mrt/project/update.d.ts +1 -0
- package/dist/commands/mrt/save-credentials.d.ts +1 -0
- package/dist/commands/mrt/tail-logs.d.ts +1 -0
- package/dist/commands/mrt/user/api-key.d.ts +1 -0
- package/dist/commands/mrt/user/email-prefs.d.ts +1 -0
- package/dist/commands/mrt/user/profile.d.ts +1 -0
- package/dist/commands/scaffold/init.js +2 -1
- package/dist/commands/scaffold/init.js.map +1 -1
- package/dist/commands/scapi/custom/status.d.ts +1 -0
- package/dist/commands/scapi/schemas/get.d.ts +1 -0
- package/dist/commands/scapi/schemas/list.d.ts +1 -0
- package/dist/commands/setup/ide/tsserver-plugin.d.ts +1 -0
- package/dist/commands/setup/ide/vscode-types.d.ts +1 -0
- package/dist/commands/setup/index.js +4 -3
- package/dist/commands/setup/index.js.map +1 -1
- package/dist/commands/setup/inspect.d.ts +1 -0
- package/dist/commands/setup/inspect.js +17 -2
- package/dist/commands/setup/inspect.js.map +1 -1
- package/dist/commands/setup/instance/create.d.ts +1 -0
- package/dist/commands/setup/instance/list.d.ts +1 -0
- package/dist/commands/setup/instance/remove.d.ts +1 -0
- package/dist/commands/setup/instance/set-active.d.ts +1 -0
- package/dist/commands/setup/openshell.d.ts +1 -0
- package/dist/commands/setup/skills.d.ts +1 -0
- package/dist/commands/slas/client/create.d.ts +1 -0
- package/dist/commands/slas/client/delete.d.ts +1 -0
- package/dist/commands/slas/client/get.d.ts +1 -0
- package/dist/commands/slas/client/list.d.ts +1 -0
- package/dist/commands/slas/client/open.d.ts +1 -0
- package/dist/commands/slas/client/update.d.ts +1 -0
- package/dist/commands/slas/token.d.ts +1 -0
- package/dist/commands/slas/token.js +2 -1
- package/dist/commands/slas/token.js.map +1 -1
- package/dist/commands/webdav/get.d.ts +1 -0
- package/dist/commands/webdav/rm.d.ts +1 -0
- package/dist/help.d.ts +25 -0
- package/dist/help.js +96 -0
- package/dist/help.js.map +1 -0
- package/dist/lib/scaffold/generate-helper.js +3 -2
- package/dist/lib/scaffold/generate-helper.js.map +1 -1
- package/dist/lib/skills.d.ts +19 -0
- package/dist/lib/skills.js +75 -0
- package/dist/lib/skills.js.map +1 -0
- package/dist/utils/cip/command.d.ts +1 -0
- package/dist/utils/ecdn/zone-command.d.ts +1 -0
- package/dist/utils/slas/client.d.ts +1 -0
- package/oclif.manifest.json +21814 -18473
- package/package.json +11 -5
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sfnext-testing
|
|
3
|
+
description: >-
|
|
4
|
+
Write and run tests for a Storefront Next project: Vitest + React Testing Library unit tests, route loader/action tests (createLoaderArgs, createTestContext), Storybook stories with snapshot, interaction (play) and a11y runs, and a pointer to the CodeceptJS/Playwright e2e suite. Use for "write a test for this component/loader", "add a story", pnpm test, pnpm storybook:test --type=snapshot|interaction|a11y, coverage thresholds, routeLoaderData / scapiMock / mockRoutes story parameters, MSW mocking, fixtures in @/components/__mocks__, failing snapshot updates, or pnpm e2e. Do not use for lint, typecheck, format, bundle-size or Lighthouse gates (use `storefront-next:sfnext-quality-gates`), accessibility rules and fixes (use `storefront-next:sfnext-accessibility`), or translations (use `storefront-next:sfnext-i18n`).
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Testing Storefront Next
|
|
8
|
+
|
|
9
|
+
Three layers, all shipped in your project (see `docs/README-TESTS.md`, `docs/README-STORYBOOK.md`, `AGENTS.md`):
|
|
10
|
+
|
|
11
|
+
| Layer | Tool | Files | Command |
|
|
12
|
+
|-------|------|-------|---------|
|
|
13
|
+
| Unit and route tests | Vitest, jsdom, Testing Library, MSW | `*.test.ts(x)` next to source | `pnpm test` |
|
|
14
|
+
| Component stories | Storybook: snapshot (Vitest), interaction and a11y (Playwright/Chromium) | `<component>/stories/*.stories.tsx` | `pnpm storybook:test --type=...` |
|
|
15
|
+
| End to end | CodeceptJS + Playwright | `e2e/` | `pnpm e2e` |
|
|
16
|
+
|
|
17
|
+
Prefer the cheapest layer that proves the behavior: pure logic and loaders in Vitest, rendered states and interactions in stories, cross-page shopper flows in e2e.
|
|
18
|
+
|
|
19
|
+
## Commands
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pnpm test # all unit tests (vitest run); does NOT collect coverage
|
|
23
|
+
pnpm test src/components/footer # one file or directory
|
|
24
|
+
pnpm test:watch # watch mode
|
|
25
|
+
pnpm test --coverage # coverage report (thresholds enforced)
|
|
26
|
+
pnpm test --ui # Vitest UI
|
|
27
|
+
|
|
28
|
+
pnpm storybook # dev server on :6006
|
|
29
|
+
pnpm exec playwright install chromium # once, for interaction/a11y runs
|
|
30
|
+
pnpm storybook:test --type=snapshot # add --update to rewrite snapshots
|
|
31
|
+
pnpm storybook:test --type=interaction # play() functions in real Chromium
|
|
32
|
+
pnpm storybook:test --type=a11y # axe checks
|
|
33
|
+
pnpm storybook:test --type=snapshot --stories=footer # narrow to matching story paths
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Add `--static` (optionally `--reuse-build` after `pnpm storybook:build`) to run interaction or a11y against a static build. `--coverage` with snapshot generates story tests and reports story coverage.
|
|
37
|
+
|
|
38
|
+
Coverage thresholds live inline in `vitest.config.ts` (`thresholds`), and `src/components/ui/**`, stories, snapshot fixtures and `__mocks__` are excluded from coverage. Do not chase 100%.
|
|
39
|
+
|
|
40
|
+
## Unit test
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
import { render, screen } from '@testing-library/react';
|
|
44
|
+
import { describe, expect, it } from 'vitest';
|
|
45
|
+
import { AllProvidersWrapper } from '@/test-utils/context-provider';
|
|
46
|
+
import MyThing from './index';
|
|
47
|
+
|
|
48
|
+
describe('MyThing', () => {
|
|
49
|
+
it('renders the label', () => {
|
|
50
|
+
render(<MyThing label="Hello" />, { wrapper: AllProvidersWrapper });
|
|
51
|
+
expect(screen.getByText('Hello')).toBeInTheDocument();
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
`vitest.setup.ts` already provides jest-dom matchers, i18next (`en-GB`), `window.__APP_CONFIG__`, a global mock of `@/hooks/use-analytics`, and a 10s async-util timeout; do not re-add them. Helpers, wrappers and the analytics caveat: [references/UNIT-AND-ROUTE-TESTS.md](references/UNIT-AND-ROUTE-TESTS.md).
|
|
57
|
+
|
|
58
|
+
## Route loader / action test
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
62
|
+
import { createLoaderArgs, createTestContext } from '@/lib/test-utils';
|
|
63
|
+
import { loader } from './resource.basket-products';
|
|
64
|
+
|
|
65
|
+
vi.mock('@/lib/api-clients.server', () => ({ createApiClients: vi.fn() }));
|
|
66
|
+
|
|
67
|
+
it('returns data', async () => {
|
|
68
|
+
const context = createTestContext({ authSession: { userType: 'guest' } });
|
|
69
|
+
const args = createLoaderArgs(new Request('http://localhost/x'), context, {
|
|
70
|
+
params: {},
|
|
71
|
+
pattern: '/' as never,
|
|
72
|
+
});
|
|
73
|
+
const result = await loader(args);
|
|
74
|
+
expect(result).toBeDefined();
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
`createActionArgs` is the action twin and `expectStatus(result, 400)` asserts `data()` statuses. Mock `@/lib/api-clients.server` (SCAPI) at the module boundary, or use MSW for HTTP-level tests. See `storefront-next:sfnext-data-fetching` for the loader patterns under test.
|
|
79
|
+
|
|
80
|
+
## Stories
|
|
81
|
+
|
|
82
|
+
Stories live in a `stories/` subfolder next to the component (required; coverage tooling only matches there):
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
src/components/footer/
|
|
86
|
+
├── index.tsx
|
|
87
|
+
├── index.test.tsx
|
|
88
|
+
└── stories/
|
|
89
|
+
├── index.stories.tsx
|
|
90
|
+
├── footer-snapshot.tsx # snapshot fixture, only where a snapshot test exists
|
|
91
|
+
└── __snapshots__/
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
```tsx
|
|
95
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
96
|
+
import { expect, within } from 'storybook/test';
|
|
97
|
+
import { waitForStorybookReady } from '@storybook/test-utils';
|
|
98
|
+
import { mockProductSearchItem } from '@/components/__mocks__/product-search-hit-data';
|
|
99
|
+
import ProductTile from '../index';
|
|
100
|
+
|
|
101
|
+
const meta: Meta<typeof ProductTile> = {
|
|
102
|
+
title: 'Products/Product Tile', // Domain/Component from the fixed sidebar groups
|
|
103
|
+
component: ProductTile,
|
|
104
|
+
tags: ['autodocs', 'interaction'],
|
|
105
|
+
};
|
|
106
|
+
export default meta;
|
|
107
|
+
type Story = StoryObj<typeof meta>;
|
|
108
|
+
|
|
109
|
+
export const Default: Story = {
|
|
110
|
+
args: { product: mockProductSearchItem },
|
|
111
|
+
play: async ({ canvasElement }) => {
|
|
112
|
+
await waitForStorybookReady(canvasElement);
|
|
113
|
+
await expect(within(canvasElement).getAllByRole('link')[0]).toBeInTheDocument();
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Rules of thumb:
|
|
119
|
+
|
|
120
|
+
- Every story is already wrapped by a global decorator (memory router + config, site, i18n, auth, basket providers). Do not add your own `ConfigProvider`. If you truly need one, import it from `@salesforce/storefront-next-runtime/config`.
|
|
121
|
+
- Import test helpers from `storybook/test` (not `@storybook/test`).
|
|
122
|
+
- Props first; mock at the route boundary with `parameters` (`routeLoaderData`, `scapiMock`, `miniCartData`, `mockRoutes`), never `vi.mock` of hooks inside a story. Args must be JSON-serializable.
|
|
123
|
+
- Tags: `autodocs` (docs page), `interaction` (included in interaction runs), `skip-a11y` (excluded from a11y runs; use sparingly and comment why).
|
|
124
|
+
- Use Storybook's viewport toolbar instead of separate mobile/desktop stories.
|
|
125
|
+
- Fixtures: `@/components/__mocks__` (barrel of curated fixtures) or `@/components/__mocks__/<file>` for ones not re-exported; shared with unit tests.
|
|
126
|
+
|
|
127
|
+
Full reference, including parameters, mock routes, taxonomy and argTypes: [references/STORYBOOK-PATTERNS.md](references/STORYBOOK-PATTERNS.md).
|
|
128
|
+
|
|
129
|
+
## End to end
|
|
130
|
+
|
|
131
|
+
`e2e/` is a separate CodeceptJS + Playwright project with its own `AGENTS.md`. Run `pnpm e2e` (add `--mode=local` to start the dev server, `--grep "@checkout"`, `--headed`). To author tests, use the skills shipped in your project at `e2e/.claude/skills/generate-storefront-e2e-test` and `e2e/.claude/skills/checkout-test-development`. Setup, env vars and the `pnpm a11y` scan: [references/E2E.md](references/E2E.md).
|
|
132
|
+
|
|
133
|
+
## Pitfalls
|
|
134
|
+
|
|
135
|
+
| Pitfall | Fix |
|
|
136
|
+
|---------|-----|
|
|
137
|
+
| Story outside `stories/` | Move it; coverage and generated snapshot tests only find `stories/*.stories.tsx`. |
|
|
138
|
+
| Interaction/a11y run fails to launch a browser | `pnpm exec playwright install chromium`. |
|
|
139
|
+
| Snapshot diff after an intentional DOM change | Review it, then `pnpm storybook:test --type=snapshot --update`. |
|
|
140
|
+
| Test passes but analytics never fires | `@/hooks/use-analytics` is mocked globally; `vi.unmock` it in the test to assert on track calls. |
|
|
141
|
+
| Portalled dialog/toast not found in a play function | Query `within(canvasElement.ownerDocument.body)`. |
|
|
142
|
+
| Mocking too deep | If an internal refactor forces story edits, push the mock to the route/fixture layer. |
|
|
143
|
+
|
|
144
|
+
## Related Skills
|
|
145
|
+
|
|
146
|
+
- `storefront-next:sfnext-quality-gates` - lint, typecheck, format and the pre-PR checklist
|
|
147
|
+
- `storefront-next:sfnext-accessibility` - a11y assertions in stories and the e2e axe scan
|
|
148
|
+
- `storefront-next:sfnext-components` - component conventions under test
|
|
149
|
+
- `storefront-next:sfnext-data-fetching` - loaders and actions
|
|
150
|
+
- `storefront-next:sfnext-page-designer` - testing Page Designer components
|
|
151
|
+
- `storefront-next:sfnext-i18n` - translations in tests
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# End-to-end tests
|
|
2
|
+
|
|
3
|
+
`e2e/` is a standalone CodeceptJS + Playwright project shipped with your storefront, with its own `e2e/AGENTS.md`, `e2e/README.md`, `e2e/docs/`, and in-project skills:
|
|
4
|
+
|
|
5
|
+
- `e2e/.claude/skills/generate-storefront-e2e-test/SKILL.md`: structured workflow for new specs, page objects, flows and self-healing recipes.
|
|
6
|
+
- `e2e/.claude/skills/checkout-test-development/`: checkout-specific E2E, debugging and performance guidance.
|
|
7
|
+
|
|
8
|
+
Use those skills when authoring or debugging e2e tests; this page only orients you.
|
|
9
|
+
|
|
10
|
+
## Setup
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
cp e2e/.env.sample e2e/.env # BASE_URL, SITE_ID, SITE_ALIAS, LOCALE, HEADLESS, ...
|
|
14
|
+
pnpm install # per e2e/README.md this also installs Playwright browsers; if not, pnpm exec playwright install chromium
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The storefront itself needs its own `.env` (see `storefront-next:sfnext-configuration`).
|
|
18
|
+
|
|
19
|
+
## Run
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pnpm e2e # against a running storefront (BASE_URL, default http://localhost:5173)
|
|
23
|
+
pnpm e2e --mode=local # start the dev server automatically
|
|
24
|
+
pnpm e2e --mode=remote # BASE_URL must point at the deployed storefront
|
|
25
|
+
pnpm e2e --grep "@checkout" # filter by tag or name
|
|
26
|
+
pnpm e2e --headed # show the browser
|
|
27
|
+
pnpm e2e --debug # Playwright Inspector
|
|
28
|
+
pnpm e2e:turnstile # Turnstile-specific suite
|
|
29
|
+
pnpm a11y # axe scans of key pages, desktop + mobile (see sfnext-accessibility)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The root scripts above delegate to `e2e/`; you do not need to run them from inside it.
|
|
33
|
+
|
|
34
|
+
## Keep in mind
|
|
35
|
+
|
|
36
|
+
- E2E runs against real backend data; prefer unit tests and stories for logic and visual states, and keep e2e for shopper journeys (search, PDP to cart, checkout, login).
|
|
37
|
+
- Optional AI healing is off unless you pass `--ai` and set `ANTHROPIC_API_KEY` in `e2e/.env`.
|
|
38
|
+
- `e2e/` is excluded from the root OxLint/Vitest runs and has its own `lint`, `format:check`, `typecheck` and `test` scripts (run from `e2e/`).
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Storybook patterns
|
|
2
|
+
|
|
3
|
+
Source of truth in your project: `docs/README-STORYBOOK.md`, `.storybook/`, and the existing `stories/` folders. Copy a neighbor story before inventing structure.
|
|
4
|
+
|
|
5
|
+
## Principles
|
|
6
|
+
|
|
7
|
+
1. Props first. Reach for the global provider/router stack only when the component reads global context (auth, basket, site, locale).
|
|
8
|
+
2. Mock at the boundary. Prefer `parameters.routeLoaderData`, `parameters.scapiMock`, `parameters.mockRoutes` over `vi.mock` of hooks.
|
|
9
|
+
3. Args are JSON-serializable. Promises, class instances and functions returning promises break the Controls panel and snapshot serialization; put them in `parameters`.
|
|
10
|
+
4. One reason to update a mock. If an internal refactor forces story edits, the mock is too deep.
|
|
11
|
+
|
|
12
|
+
## Decorator stack
|
|
13
|
+
|
|
14
|
+
`.storybook/preview.tsx` applies `decorators: [withRouter(StoryShell)]` to every story:
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
withRouter(StoryShell) in-memory React Router with default mock routes
|
|
18
|
+
StoryShell
|
|
19
|
+
StorybookWrapper config + site + i18n + auth + basket + storeLocator + checkoutOneClick
|
|
20
|
+
UITargetProviders
|
|
21
|
+
<Story />
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Files: `.storybook/decorators/{with-router,with-providers,with-ui-targets,mock-routes}.tsx|ts`. Because of this, a story usually needs no per-story `ConfigProvider` or `SiteProvider`. If you do need to override config for one story, wrap with `ConfigProvider` from `@salesforce/storefront-next-runtime/config` and `SiteProvider` from `@salesforce/storefront-next-runtime/site-context`, using `mockConfig`, `mockLocale`, `mockSiteObject` from `@/test-utils/config` (see `src/components/footer/stories/index.stories.tsx`).
|
|
25
|
+
|
|
26
|
+
## Story parameters
|
|
27
|
+
|
|
28
|
+
| Parameter | Use |
|
|
29
|
+
|-----------|-----|
|
|
30
|
+
| `routeLoaderData: Record<string, unknown>` | Wrap the story in ancestor routes so `useRouteLoaderData(routeId)` resolves. Required for components that read a parent route's loader data. |
|
|
31
|
+
| `scapiMock: { data?: unknown }` | Override the default `/resource/api/client/:resource` response, for stories whose `play()` asserts specific product data. |
|
|
32
|
+
| `miniCartData: { basket, productsById }` | Override what `/resource/basket-products` returns (for example an empty cart). |
|
|
33
|
+
| `mockRoutes: RouteObject[]` | Add story-specific `/resource/*` or `/action/*` routes. Must not shadow `/`, `*` or a default mock path; `withRouter` throws on conflicts. |
|
|
34
|
+
|
|
35
|
+
`buildDefaultMockRoutes` (in `.storybook/decorators/mock-routes.ts`) lists the default routes: basket enrichment, cart mutations, wishlist, OTP, product/bundle/set adds, site-context updates, tracking consent, place-order.
|
|
36
|
+
|
|
37
|
+
## Titles and sidebar
|
|
38
|
+
|
|
39
|
+
`meta.title` is `Domain/Component` or `Domain/Subgroup/Component`, Title Case With Spaces. Top-level groups: Account, Authentication, Cart, Category, Checkout, Content, Core, Design System, Extensions, Home, Layout, Products, Search. Pick the closest existing group by purpose, not by folder. This is a convention, not lint-enforced, and you may restructure it for your brand.
|
|
40
|
+
|
|
41
|
+
## Naming and layout
|
|
42
|
+
|
|
43
|
+
| Thing | Convention |
|
|
44
|
+
|-------|-----------|
|
|
45
|
+
| Story file | `*.stories.tsx` in `stories/` next to the component (required) |
|
|
46
|
+
| Story export | PascalCase state name: `Default`, `Loading`, `InvalidEmailError` |
|
|
47
|
+
| Snapshot fixture | `<name>-snapshot.tsx` next to the story, with `__snapshots__/` beside it |
|
|
48
|
+
| shadcn primitives in `src/components/ui/` | No stories or coverage requirement |
|
|
49
|
+
|
|
50
|
+
Default to one component per folder. Snapshot fixtures use `StoryTestWrapper` from `@storybook/test-utils`; copy an existing `*-snapshot.tsx` pair (for example under `src/components/footer/stories/`).
|
|
51
|
+
|
|
52
|
+
## argTypes
|
|
53
|
+
|
|
54
|
+
Expose only what visibly drives the canvas:
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
argTypes: {
|
|
58
|
+
label: { control: 'text', description: 'Label in the summary row' },
|
|
59
|
+
className: { control: false, table: { disable: true } },
|
|
60
|
+
onCancel: { action: 'cancel' },
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## play() functions
|
|
65
|
+
|
|
66
|
+
```tsx
|
|
67
|
+
import { expect, userEvent, within } from 'storybook/test';
|
|
68
|
+
import { waitForStorybookReady } from '@storybook/test-utils';
|
|
69
|
+
|
|
70
|
+
play: async ({ canvasElement }) => {
|
|
71
|
+
await waitForStorybookReady(canvasElement);
|
|
72
|
+
const canvas = within(canvasElement);
|
|
73
|
+
await userEvent.click(canvas.getByRole('button', { name: /add to cart/i }));
|
|
74
|
+
await expect(canvas.getByRole('status')).toHaveTextContent(/added/i);
|
|
75
|
+
},
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
- Tag the story `interaction` so it runs in `--type=interaction`.
|
|
79
|
+
- Dialogs, popovers and toasts render into `document.body`; use `within(canvasElement.ownerDocument.body)`.
|
|
80
|
+
- Assert outcomes (role, accessible name, focus, text), not CSS classes.
|
|
81
|
+
- To re-render a story when an arg changes (keyed state), key the component on that prop.
|
|
82
|
+
|
|
83
|
+
## Accessibility in stories
|
|
84
|
+
|
|
85
|
+
The a11y addon mode is `todo` (reports, does not fail) by default. `pnpm storybook:test --type=a11y` runs with `STORYBOOK_A11Y_TEST_MODE=error`. `STORYBOOK_DISABLE_A11Y=true` turns it off. Tag `skip-a11y` excludes a story from a11y runs. To make one file strict regardless, spread `{ a11y: { test: 'error' } }` into its `parameters` (see `src/components/checkout/storybook/checkout-strict-a11y-parameters.ts`). See `storefront-next:sfnext-accessibility`.
|
|
86
|
+
|
|
87
|
+
## Story coverage
|
|
88
|
+
|
|
89
|
+
Stories count toward component coverage when they match the component path (`cart/cart-content.tsx` maps to `cart/stories/cart-content.stories.tsx`; `index.tsx` maps to `stories/index.stories.tsx`). `pnpm storybook:test --type=snapshot --coverage` generates story tests and reports; details in `docs/README-STORY-COVERAGE.md`.
|
|
90
|
+
|
|
91
|
+
## Anti-patterns
|
|
92
|
+
|
|
93
|
+
- Recreating the component's data shape as a giant literal instead of passing a fixture.
|
|
94
|
+
- Promises in `args`.
|
|
95
|
+
- `vi.mock` of hooks inside a story.
|
|
96
|
+
- Separate Mobile/Tablet/Desktop stories (use the viewport toolbar).
|
|
97
|
+
- Novel top-level title groups.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Unit and route tests
|
|
2
|
+
|
|
3
|
+
## Environment (`vitest.config.ts`, `vitest.setup.ts`)
|
|
4
|
+
|
|
5
|
+
- jsdom, `globals: true`, `@/` alias, `testTimeout` 15s, Testing Library `asyncUtilTimeout` 10s, `pool: 'forks'` on Windows.
|
|
6
|
+
- Setup already: jest-dom matchers, `window.__APP_CONFIG__ = mockConfig`, i18next initialized with all locales (language `en-GB`), `vitest-localstorage-mock`, and a global mock of `@/hooks/use-analytics`.
|
|
7
|
+
- The global analytics mock means a missing `track*` call will not fail an ordinary test. To assert on tracking, call `vi.unmock('@/hooks/use-analytics')` in a `beforeEach` and provide your own spy implementation.
|
|
8
|
+
- Static assets and `virtual:action-hooks` are aliased to mocks.
|
|
9
|
+
|
|
10
|
+
## Helper inventory
|
|
11
|
+
|
|
12
|
+
`@/test-utils/*` (src/test-utils):
|
|
13
|
+
|
|
14
|
+
| Import | Provides |
|
|
15
|
+
|--------|----------|
|
|
16
|
+
| `@/test-utils/config` | `mockConfig`, `mockBuildConfig`, `mockSiteObject`, `mockAltSiteObject`, `mockLocale`, `getSitePrefix`, `ConfigWrapper`, `createConfigWrapper(overrides)` |
|
|
17
|
+
| `@/test-utils/context-provider` | `ConfigWrapper`, `AllProvidersWrapper` (config + site + store locator + UI targets; props `config`, `currency`) |
|
|
18
|
+
| `@/test-utils/auth` | `buildMockAccessToken`, `buildMockTokenResponse` |
|
|
19
|
+
| `@/test-utils/request-helpers` | `createFormDataRequest(url, method, data)` |
|
|
20
|
+
| `@/test-utils/wishlist` | `resetWishlistStore`, `seedWishlistStore` |
|
|
21
|
+
| `@/test-utils/page-designer-host-provider` | `PageDesignerHostProvider` |
|
|
22
|
+
|
|
23
|
+
`@/lib/test-utils` (src/lib/test-utils):
|
|
24
|
+
|
|
25
|
+
| Export | Use |
|
|
26
|
+
|--------|-----|
|
|
27
|
+
| `createTestContext(opts)` | A `RouterContextProvider` with auth, app config, i18n, site (locale/currency), maintenance and performance-timer contexts. Options: `authSession` (`null` for no session), `rejectAuth`/`authError`, `appConfig`, `locale` (default `en-GB`), `currency` (default `GBP`), `skipI18next`. |
|
|
28
|
+
| `createLoaderArgs(request, context, { params, pattern })` | Full `LoaderFunctionArgs`; pass `<Route.LoaderArgs>` as type parameter for typed loaders. |
|
|
29
|
+
| `createActionArgs(...)` | Same for actions. |
|
|
30
|
+
| `ROUTE_PATTERN` | Safe placeholder for `pattern`. |
|
|
31
|
+
| `expectStatus(result, 400)` | Assert status of a `data()` response (missing status counts as 200). |
|
|
32
|
+
|
|
33
|
+
Fixtures: `@/components/__mocks__` (and `@/components/__mocks__/<file>`), for example `basketWithOneItem`, `emptyBasket`, `masterProduct`, `mockStandardProductOrderable`, `mockCategories`.
|
|
34
|
+
|
|
35
|
+
## Loader/action pattern
|
|
36
|
+
|
|
37
|
+
Model new tests on `src/routes/resource.basket-products.test.ts` and the `_app.p.$.loader.test.ts` / `_app.cart.test.tsx` route tests:
|
|
38
|
+
|
|
39
|
+
1. `vi.mock('@/lib/api-clients.server', () => ({ createApiClients: vi.fn() }))` and return fake SCAPI clients per test.
|
|
40
|
+
2. Mock `@/middlewares/basket.server` (`getBasket`) or auth helpers if the route reads them.
|
|
41
|
+
3. Build context with `createTestContext`, args with `createLoaderArgs`/`createActionArgs`, call the exported `loader`/`action`.
|
|
42
|
+
4. Assert the returned object, thrown `Response`, or `expectStatus`.
|
|
43
|
+
5. For routes exporting `shouldRevalidate`, call it directly (see `docs/README-REVALIDATION.md`).
|
|
44
|
+
|
|
45
|
+
Use `createFormDataRequest` for action input.
|
|
46
|
+
|
|
47
|
+
## MSW
|
|
48
|
+
|
|
49
|
+
`msw` is a dev dependency. For HTTP-level tests use `setupServer` from `msw/node` and `http`/`HttpResponse` from `msw` (example: `src/components/checkout/checkout-flow.test.tsx`). Start the server in `beforeAll`, `resetHandlers` in `afterEach`, `close` in `afterAll`.
|
|
50
|
+
|
|
51
|
+
## Hooks and components
|
|
52
|
+
|
|
53
|
+
- Hooks: `renderHook(() => useX(), { wrapper: ConfigWrapper })` with the wrapper from `@/test-utils/config`.
|
|
54
|
+
- Components needing site/config/UI targets: `render(ui, { wrapper: AllProvidersWrapper })`.
|
|
55
|
+
- Component tests that mock `react-router` must provide every export the component tree uses.
|
|
56
|
+
- Prefer `userEvent` from `@testing-library/user-event` over `fireEvent`, and role-based queries.
|
|
57
|
+
|
|
58
|
+
## i18n in tests
|
|
59
|
+
|
|
60
|
+
See `storefront-next:sfnext-i18n`: i18next is initialized globally; use `createTestContext({ locale })` for loaders.
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sfnext-theming
|
|
3
|
+
description: >-
|
|
4
|
+
Re-brand and re-skin a Storefront Next storefront: change the color palette, corner radius and shadows (shape tokens), header and footer colors, typography and web fonts, logo, favicon, hero scrims, and brand copy, with WCAG contrast checks. Use when asked to rebrand or restyle the storefront, change the primary color, swap the font, make the header dark, make cards rounded or flat, replace the logo, edit src/theme, core.css, header.css, brand.css, tailwind.css, base.css, or src/lib/fonts.ts, or verify a theme change in the Design System Storybook stories. Do not use for building or styling an individual component (use `storefront-next:sfnext-components`), Figma kit sync (use `storefront-next-figma:sfnext-create-figma-kit`), or site configuration (use `storefront-next:sfnext-configuration`).
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Theming a Storefront Next Storefront
|
|
8
|
+
|
|
9
|
+
Your storefront has exactly one theme, in `src/theme/`, and it is yours to edit. Rebranding is mostly value changes in a few CSS files; components pick the new look up through token classes. Choose a starting look with `sfnext create-storefront --vertical <id>` (a starter theme) and then customize it as below.
|
|
10
|
+
|
|
11
|
+
## Where things live
|
|
12
|
+
|
|
13
|
+
| Concern | File |
|
|
14
|
+
|---|---|
|
|
15
|
+
| Entry point and Tailwind `@source` scoping | `src/theme/index.css` (imports `shared.css`, which sets import order) |
|
|
16
|
+
| Palette: background, foreground, primary, secondary, accent, muted, border, ring, destructive/success/warning/info | `src/theme/tokens/core.css` |
|
|
17
|
+
| Shape: `--ui-radius`, `--ui-shadow`, `--ui-border-width` | `src/theme/tokens/core.css` |
|
|
18
|
+
| Header, menu, footer, newsletter band, `--header-logo-filter` | `src/theme/tokens/header.css` |
|
|
19
|
+
| Status and feedback colors | `src/theme/tokens/status.css` |
|
|
20
|
+
| Swatches, sidebar, agentic UI, payment and cart extras, focus helpers | `tokens/swatch.css`, `sidebar.css`, `agentic.css`, `components.css`, `custom.css` |
|
|
21
|
+
| `--brand-*` color primitives and hero scrims (`--hero-overlay-*`, `--hero-scrim`) | `src/theme/tokens/brand.css` |
|
|
22
|
+
| Font stacks `--font-sans/-serif/-mono`; token-to-utility bridge | `src/theme/tailwind.css` (`@theme inline`) |
|
|
23
|
+
| `@font-face`, base layer, `.section-container`, section-scoped shape rules | `src/theme/base.css` |
|
|
24
|
+
| Component-level CSS (navigation, cart sheet, toasts, store locator) | `src/theme/overrides/*.css` |
|
|
25
|
+
| Font binding and preload | `public/fonts/*.woff2`, `src/lib/fonts.ts` (used by `src/root.tsx`) |
|
|
26
|
+
| Logo, favicon, hero and payment images | `public/images/`, `public/favicon.ico` |
|
|
27
|
+
| Site name and brand strings | `src/locales/<locale>/translations.json` (`common.defaultSiteName`) |
|
|
28
|
+
|
|
29
|
+
Palette values are not all derived from `brand.css`: `core.css` sets `--primary` and friends directly, so change them there. Token-to-class wiring and the full token file list are covered in `storefront-next:sfnext-components` (token system reference).
|
|
30
|
+
|
|
31
|
+
## Workflow
|
|
32
|
+
|
|
33
|
+
### 1. Read the current theme
|
|
34
|
+
|
|
35
|
+
Open `src/theme/index.css`, `tokens/core.css`, `tokens/header.css`, and `tailwind.css` before editing. Keep variable names; change values.
|
|
36
|
+
|
|
37
|
+
### 2. Palette
|
|
38
|
+
|
|
39
|
+
Edit `:root` in `tokens/core.css`: `--primary`/`--primary-foreground`, `--background`/`--foreground`, `--secondary`, `--accent`, `--muted`, borders, `--ring`. Comments in the file record WCAG contrast ratios for the current values; recompute for yours. Minimums: 4.5:1 for text (`--primary` on `--primary-foreground`, `--foreground` on `--background`, each status color on its `-foreground`), 3:1 for borders and focus rings against the surface.
|
|
40
|
+
|
|
41
|
+
Update `tokens/status.css` if semantic colors clash with the new palette, and `tokens/swatch.css`, `tokens/components.css` where defaults look off.
|
|
42
|
+
|
|
43
|
+
### 3. Header, footer, and newsletter chrome
|
|
44
|
+
|
|
45
|
+
`tokens/header.css` is deliberately decoupled from `--primary`, so changing the primary color does not recolor the header. Set `--header-background`/`--header-foreground`, menu hover/active colors, and `--footer-*` yourself. The logo is an image: for a dark header with a dark logo, set `--header-logo-filter` (for example `brightness(0) invert(1)` turns a black logo white; `none` leaves it alone). `--newsletter-background` defaults to `var(--primary)`.
|
|
46
|
+
|
|
47
|
+
### 4. Shape
|
|
48
|
+
|
|
49
|
+
Set `--ui-radius`, `--ui-shadow`, `--ui-border-width` in `core.css` to re-skin every shadcn primitive at once. Flat and square: `0`, `none`, `0`. Soft and raised: `var(--radius-xl)`, a light shadow, `0`. Do not edit primitives or add `rounded-*`/`shadow-*` classes, and never write `--radius-ui` / `--shadow-ui` (compile-time bridges, silent no-op). Scoped overrides, section rules, and the Card border exception are covered in `storefront-next:sfnext-components` (shape tokens reference). If your default border width is 0, the section rules at the bottom of `base.css` re-enable 1px Card borders on account, auth, and checkout pages; adjust those to taste.
|
|
50
|
+
|
|
51
|
+
### 5. Typography
|
|
52
|
+
|
|
53
|
+
Four touch points, all must agree:
|
|
54
|
+
|
|
55
|
+
1. Put the variable `.woff2` in `public/fonts/`.
|
|
56
|
+
2. `src/lib/fonts.ts`: `import font from '/fonts/<file>.woff2'; export const primaryFont = font;` (`root.tsx` preloads it).
|
|
57
|
+
3. `@font-face` in `src/theme/base.css` (same URL, weight range, `font-display: swap`).
|
|
58
|
+
4. `--font-sans` / `--font-serif` / `--font-mono` in `src/theme/tailwind.css`, with a fallback stack of similar metrics.
|
|
59
|
+
|
|
60
|
+
Self-host fonts (WOFF2, preloaded, no third-party CDN). Remove the old font file if unused.
|
|
61
|
+
|
|
62
|
+
### 6. Assets and copy
|
|
63
|
+
|
|
64
|
+
- Logo: replace `public/images/logo.svg` (the `Logo` component in `src/components/logo` renders it; you can replace that component for an inline-SVG logo).
|
|
65
|
+
- Favicon: `public/favicon.ico`.
|
|
66
|
+
- Hero and promo images: `public/images/` (and the Page Designer content that references them).
|
|
67
|
+
- Brand name: `common.defaultSiteName` in each `src/locales/<locale>/translations.json` you ship (used in page titles).
|
|
68
|
+
- Hero text scrims: `--brand-black`/`--brand-white` in `brand.css` feed `--hero-overlay-dark/-light` and `--hero-scrim`; update them with the brand so hero text stays legible.
|
|
69
|
+
|
|
70
|
+
### 7. Dark mode
|
|
71
|
+
|
|
72
|
+
The shipped theme has one palette and no `.dark` token block. Do not promise dark mode; it would be new work (a `.dark` scope for every token file).
|
|
73
|
+
|
|
74
|
+
### 8. Verify
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
pnpm dev # look at home, PLP, PDP, cart, checkout, account
|
|
78
|
+
pnpm storybook # Design System/Theme/Colors, Typography, Radius, Shadows
|
|
79
|
+
pnpm lint # color-linter flags hard-coded colors
|
|
80
|
+
pnpm typecheck
|
|
81
|
+
pnpm storybook:test --type=snapshot # add --update only after reviewing intended changes
|
|
82
|
+
pnpm storybook:test --type=a11y # contrast and ARIA via axe-core
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The `Design System/Theme/*` stories (`src/design-system/stories/`) render the live tokens and are the quickest visual check.
|
|
86
|
+
|
|
87
|
+
## Guardrails
|
|
88
|
+
|
|
89
|
+
- Change values in token files; do not sprinkle hex codes or `bg-[#...]` in components.
|
|
90
|
+
- Need a new token? Define it in a `tokens/*.css` file and bridge it in `@theme inline` in `tailwind.css` (see TOKEN-SYSTEM).
|
|
91
|
+
- Component-level CSS goes in `src/theme/overrides/*.css` (import it from `shared.css`) or `base.css`; prefer `[data-slot="..."]` selectors over utility-class selectors.
|
|
92
|
+
|
|
93
|
+
## Design handoff
|
|
94
|
+
|
|
95
|
+
If your designers work in Figma, keep the Figma variables and code tokens aligned with `storefront-next-figma:sfnext-create-figma-kit` (requires the Figma MCP server). Change the tokens in code first, then sync the kit.
|
|
96
|
+
|
|
97
|
+
## Related Skills
|
|
98
|
+
|
|
99
|
+
- `storefront-next:sfnext-components` - Build and style components with token classes and shape tokens
|
|
100
|
+
- `storefront-next:sfnext-accessibility` - Contrast, focus, and accessibility scans
|
|
101
|
+
- `storefront-next:sfnext-i18n` - Locale files that hold brand copy
|
|
102
|
+
- `storefront-next:sfnext-performance` - Font and image loading guidance
|
|
103
|
+
- `storefront-next:sfnext-page-designer` - Content and hero components authored in Page Designer
|
|
104
|
+
- `storefront-next-figma:sfnext-create-figma-kit` - Sync the Figma design kit with your tokens
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Rebrand Checklist
|
|
2
|
+
|
|
3
|
+
Work top to bottom; each item names the file to touch.
|
|
4
|
+
|
|
5
|
+
- [ ] `src/theme/tokens/core.css`: `--primary`, `--primary-foreground`, `--background`, `--foreground`, `--secondary`, `--accent`, `--muted`, `--border`, `--input`, `--ring`
|
|
6
|
+
- [ ] `src/theme/tokens/core.css`: contrast re-checked (text 4.5:1, borders and focus rings 3:1); update the ratio comments
|
|
7
|
+
- [ ] `src/theme/tokens/core.css`: `--ui-radius`, `--ui-shadow`, `--ui-border-width`
|
|
8
|
+
- [ ] `src/theme/base.css`: section-scoped Card border rules still match the chosen border width
|
|
9
|
+
- [ ] `src/theme/tokens/header.css`: header, menu, footer, newsletter colors; `--header-logo-filter`
|
|
10
|
+
- [ ] `src/theme/tokens/status.css`: status colors still readable against the new surfaces
|
|
11
|
+
- [ ] `src/theme/tokens/brand.css`: `--brand-*` primitives and hero scrims
|
|
12
|
+
- [ ] `src/theme/tokens/swatch.css`, `components.css`: swatch and badge defaults
|
|
13
|
+
- [ ] Font: `public/fonts/`, `src/lib/fonts.ts`, `@font-face` in `src/theme/base.css`, `--font-*` in `src/theme/tailwind.css`
|
|
14
|
+
- [ ] `public/images/logo.svg`, `public/favicon.ico`, hero images
|
|
15
|
+
- [ ] `common.defaultSiteName` in `src/locales/*/translations.json`
|
|
16
|
+
- [ ] Page Designer content referencing old imagery or colors
|
|
17
|
+
- [ ] `pnpm lint`, `pnpm typecheck`, `pnpm storybook:test --type=snapshot`, `--type=a11y`
|
|
18
|
+
- [ ] Visual pass: home, PLP, PDP, cart, checkout, account, error pages
|
|
19
|
+
|
|
20
|
+
## Common mistakes
|
|
21
|
+
|
|
22
|
+
| Mistake | Result |
|
|
23
|
+
|---|---|
|
|
24
|
+
| Editing only `brand.css` | Little changes; the palette is in `core.css` |
|
|
25
|
+
| Writing `--radius-ui` or `--shadow-ui` | Silent no-op; use `--ui-radius` / `--ui-shadow` |
|
|
26
|
+
| Changing the font file but not `base.css` `@font-face` | Old font still loads or fallback shows |
|
|
27
|
+
| Forgetting `--header-logo-filter` after a header color change | Logo unreadable |
|
|
28
|
+
| Hard-coding hex in components | `pnpm lint` fails (`custom/color-linter`) and the theme no longer controls it |
|
|
29
|
+
| Changing `--primary` and expecting the header to follow | Header tokens are independent; edit `header.css` |
|
|
@@ -44,6 +44,7 @@ export default class CapInstall extends JobCommand<typeof CapInstall> {
|
|
|
44
44
|
lang: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
45
45
|
config: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
46
46
|
instance: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
47
|
+
'dotenv-file': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
47
48
|
'project-directory': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
48
49
|
'extra-query': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
49
50
|
'extra-body': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -39,6 +39,7 @@ export default class CapList extends JobCommand<typeof CapList> {
|
|
|
39
39
|
lang: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
40
40
|
config: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
41
41
|
instance: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
42
|
+
'dotenv-file': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
42
43
|
'project-directory': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
43
44
|
'extra-query': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
44
45
|
'extra-body': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -40,6 +40,7 @@ export default class CapPull extends JobCommand<typeof CapPull> {
|
|
|
40
40
|
lang: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
41
41
|
config: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
42
42
|
instance: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
43
|
+
'dotenv-file': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
43
44
|
'project-directory': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
44
45
|
'extra-query': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
45
46
|
'extra-body': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -45,6 +45,7 @@ export default class CapTasks extends JobCommand<typeof CapTasks> {
|
|
|
45
45
|
lang: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
46
46
|
config: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
47
47
|
instance: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
48
|
+
'dotenv-file': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
48
49
|
'project-directory': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
49
50
|
'extra-query': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
50
51
|
'extra-body': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -39,6 +39,7 @@ export default class CapUninstall extends JobCommand<typeof CapUninstall> {
|
|
|
39
39
|
lang: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
40
40
|
config: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
41
41
|
instance: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
42
|
+
'dotenv-file': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
42
43
|
'project-directory': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
43
44
|
'extra-query': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
44
45
|
'extra-body': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -41,6 +41,7 @@ export default class CipDescribe extends CipCommand<typeof CipDescribe> {
|
|
|
41
41
|
lang: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
42
42
|
config: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
43
43
|
instance: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
44
|
+
'dotenv-file': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
44
45
|
'project-directory': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
45
46
|
'extra-query': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
46
47
|
'extra-body': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -38,6 +38,7 @@ export default class CipQuery extends CipCommand<typeof CipQuery> {
|
|
|
38
38
|
lang: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
39
39
|
config: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
40
40
|
instance: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
41
|
+
'dotenv-file': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
41
42
|
'project-directory': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
42
43
|
'extra-query': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
43
44
|
'extra-body': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -34,6 +34,7 @@ export default class CipReportBotTrafficShare extends CipReportCommand<typeof Ci
|
|
|
34
34
|
lang: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
35
35
|
config: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
36
36
|
instance: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
37
|
+
'dotenv-file': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
37
38
|
'project-directory': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
38
39
|
'extra-query': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
39
40
|
'extra-body': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -34,6 +34,7 @@ export default class CipReportCheckoutFunnelDropoff extends CipReportCommand<typ
|
|
|
34
34
|
lang: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
35
35
|
config: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
36
36
|
instance: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
37
|
+
'dotenv-file': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
37
38
|
'project-directory': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
38
39
|
'extra-query': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
39
40
|
'extra-body': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -34,6 +34,7 @@ export default class CipReportControllerErrorRateTrend extends CipReportCommand<
|
|
|
34
34
|
lang: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
35
35
|
config: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
36
36
|
instance: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
37
|
+
'dotenv-file': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
37
38
|
'project-directory': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
38
39
|
'extra-query': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
39
40
|
'extra-body': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -34,6 +34,7 @@ export default class CipReportControllerHealthScorecard extends CipReportCommand
|
|
|
34
34
|
lang: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
35
35
|
config: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
36
36
|
instance: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
37
|
+
'dotenv-file': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
37
38
|
'project-directory': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
38
39
|
'extra-query': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
39
40
|
'extra-body': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -34,6 +34,7 @@ export default class CipReportCustomerRegistrationTrends extends CipReportComman
|
|
|
34
34
|
lang: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
35
35
|
config: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
36
36
|
instance: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
37
|
+
'dotenv-file': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
37
38
|
'project-directory': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
38
39
|
'extra-query': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
39
40
|
'extra-body': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -34,6 +34,7 @@ export default class CipReportDiscountDepthBreakdown extends CipReportCommand<ty
|
|
|
34
34
|
lang: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
35
35
|
config: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
36
36
|
instance: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
37
|
+
'dotenv-file': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
37
38
|
'project-directory': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
38
39
|
'extra-query': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
39
40
|
'extra-body': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|