This is page 44 of 61. Use http://codebase.md/taurgis/sfcc-dev-mcp?lines=true&page={x} to view the full context. # Directory Structure ``` ├── .DS_Store ├── .github │ ├── dependabot.yml │ ├── instructions │ │ ├── mcp-node-tests.instructions.md │ │ └── mcp-yml-tests.instructions.md │ ├── ISSUE_TEMPLATE │ │ ├── bug_report.yml │ │ ├── config.yml │ │ ├── documentation.yml │ │ ├── feature_request.yml │ │ └── question.yml │ ├── PULL_REQUEST_TEMPLATE │ │ ├── bug_fix.md │ │ ├── documentation.md │ │ └── new_tool.md │ ├── pull_request_template.md │ └── workflows │ ├── ci.yml │ ├── deploy-pages.yml │ ├── publish.yml │ └── update-docs.yml ├── .gitignore ├── .husky │ └── pre-commit ├── aegis.config.docs-only.json ├── aegis.config.json ├── aegis.config.with-dw.json ├── AGENTS.md ├── ai-instructions │ ├── claude-desktop │ │ └── claude_custom_instructions.md │ ├── cursor │ │ └── .cursor │ │ └── rules │ │ ├── debugging-workflows.mdc │ │ ├── hooks-development.mdc │ │ ├── isml-templates.mdc │ │ ├── job-framework.mdc │ │ ├── performance-optimization.mdc │ │ ├── scapi-endpoints.mdc │ │ ├── security-patterns.mdc │ │ ├── sfcc-development.mdc │ │ ├── sfra-controllers.mdc │ │ ├── sfra-models.mdc │ │ ├── system-objects.mdc │ │ └── testing-patterns.mdc │ └── github-copilot │ └── copilot-instructions.md ├── CHANGELOG.md ├── CONTRIBUTING.md ├── docs │ ├── best-practices │ │ ├── cartridge_creation.md │ │ ├── isml_templates.md │ │ ├── job_framework.md │ │ ├── localserviceregistry.md │ │ ├── ocapi_hooks.md │ │ ├── performance.md │ │ ├── scapi_custom_endpoint.md │ │ ├── scapi_hooks.md │ │ ├── security.md │ │ ├── sfra_client_side_js.md │ │ ├── sfra_controllers.md │ │ ├── sfra_models.md │ │ └── sfra_scss.md │ ├── dw_campaign │ │ ├── ABTest.md │ │ ├── ABTestMgr.md │ │ ├── ABTestSegment.md │ │ ├── AmountDiscount.md │ │ ├── ApproachingDiscount.md │ │ ├── BonusChoiceDiscount.md │ │ ├── BonusDiscount.md │ │ ├── Campaign.md │ │ ├── CampaignMgr.md │ │ ├── CampaignStatusCodes.md │ │ ├── Coupon.md │ │ ├── CouponMgr.md │ │ ├── CouponRedemption.md │ │ ├── CouponStatusCodes.md │ │ ├── Discount.md │ │ ├── DiscountPlan.md │ │ ├── FixedPriceDiscount.md │ │ ├── FixedPriceShippingDiscount.md │ │ ├── FreeDiscount.md │ │ ├── FreeShippingDiscount.md │ │ ├── PercentageDiscount.md │ │ ├── PercentageOptionDiscount.md │ │ ├── PriceBookPriceDiscount.md │ │ ├── Promotion.md │ │ ├── PromotionMgr.md │ │ ├── PromotionPlan.md │ │ ├── SlotContent.md │ │ ├── SourceCodeGroup.md │ │ ├── SourceCodeInfo.md │ │ ├── SourceCodeStatusCodes.md │ │ └── TotalFixedPriceDiscount.md │ ├── dw_catalog │ │ ├── Catalog.md │ │ ├── CatalogMgr.md │ │ ├── Category.md │ │ ├── CategoryAssignment.md │ │ ├── CategoryLink.md │ │ ├── PriceBook.md │ │ ├── PriceBookMgr.md │ │ ├── Product.md │ │ ├── ProductActiveData.md │ │ ├── ProductAttributeModel.md │ │ ├── ProductAvailabilityLevels.md │ │ ├── ProductAvailabilityModel.md │ │ ├── ProductInventoryList.md │ │ ├── ProductInventoryMgr.md │ │ ├── ProductInventoryRecord.md │ │ ├── ProductLink.md │ │ ├── ProductMgr.md │ │ ├── ProductOption.md │ │ ├── ProductOptionModel.md │ │ ├── ProductOptionValue.md │ │ ├── ProductPriceInfo.md │ │ ├── ProductPriceModel.md │ │ ├── ProductPriceTable.md │ │ ├── ProductSearchHit.md │ │ ├── ProductSearchModel.md │ │ ├── ProductSearchRefinementDefinition.md │ │ ├── ProductSearchRefinements.md │ │ ├── ProductSearchRefinementValue.md │ │ ├── ProductVariationAttribute.md │ │ ├── ProductVariationAttributeValue.md │ │ ├── ProductVariationModel.md │ │ ├── Recommendation.md │ │ ├── SearchModel.md │ │ ├── SearchRefinementDefinition.md │ │ ├── SearchRefinements.md │ │ ├── SearchRefinementValue.md │ │ ├── SortingOption.md │ │ ├── SortingRule.md │ │ ├── Store.md │ │ ├── StoreGroup.md │ │ ├── StoreInventoryFilter.md │ │ ├── StoreInventoryFilterValue.md │ │ ├── StoreMgr.md │ │ ├── Variant.md │ │ └── VariationGroup.md │ ├── dw_content │ │ ├── Content.md │ │ ├── ContentMgr.md │ │ ├── ContentSearchModel.md │ │ ├── ContentSearchRefinementDefinition.md │ │ ├── ContentSearchRefinements.md │ │ ├── ContentSearchRefinementValue.md │ │ ├── Folder.md │ │ ├── Library.md │ │ ├── MarkupText.md │ │ └── MediaFile.md │ ├── dw_crypto │ │ ├── CertificateRef.md │ │ ├── CertificateUtils.md │ │ ├── Cipher.md │ │ ├── Encoding.md │ │ ├── JWE.md │ │ ├── JWEHeader.md │ │ ├── JWS.md │ │ ├── JWSHeader.md │ │ ├── KeyRef.md │ │ ├── Mac.md │ │ ├── MessageDigest.md │ │ ├── SecureRandom.md │ │ ├── Signature.md │ │ ├── WeakCipher.md │ │ ├── WeakMac.md │ │ ├── WeakMessageDigest.md │ │ ├── WeakSignature.md │ │ └── X509Certificate.md │ ├── dw_customer │ │ ├── AddressBook.md │ │ ├── AgentUserMgr.md │ │ ├── AgentUserStatusCodes.md │ │ ├── AuthenticationStatus.md │ │ ├── Credentials.md │ │ ├── Customer.md │ │ ├── CustomerActiveData.md │ │ ├── CustomerAddress.md │ │ ├── CustomerCDPData.md │ │ ├── CustomerContextMgr.md │ │ ├── CustomerGroup.md │ │ ├── CustomerList.md │ │ ├── CustomerMgr.md │ │ ├── CustomerPasswordConstraints.md │ │ ├── CustomerPaymentInstrument.md │ │ ├── CustomerStatusCodes.md │ │ ├── EncryptedObject.md │ │ ├── ExternalProfile.md │ │ ├── OrderHistory.md │ │ ├── ProductList.md │ │ ├── ProductListItem.md │ │ ├── ProductListItemPurchase.md │ │ ├── ProductListMgr.md │ │ ├── ProductListRegistrant.md │ │ ├── Profile.md │ │ └── Wallet.md │ ├── dw_extensions.applepay │ │ ├── ApplePayHookResult.md │ │ └── ApplePayHooks.md │ ├── dw_extensions.facebook │ │ ├── FacebookFeedHooks.md │ │ └── FacebookProduct.md │ ├── dw_extensions.paymentrequest │ │ ├── PaymentRequestHookResult.md │ │ └── PaymentRequestHooks.md │ ├── dw_extensions.payments │ │ ├── SalesforceBancontactPaymentDetails.md │ │ ├── SalesforceCardPaymentDetails.md │ │ ├── SalesforceEpsPaymentDetails.md │ │ ├── SalesforceIdealPaymentDetails.md │ │ ├── SalesforceKlarnaPaymentDetails.md │ │ ├── SalesforcePaymentDetails.md │ │ ├── SalesforcePaymentIntent.md │ │ ├── SalesforcePaymentMethod.md │ │ ├── SalesforcePaymentRequest.md │ │ ├── SalesforcePaymentsHooks.md │ │ ├── SalesforcePaymentsMgr.md │ │ ├── SalesforcePaymentsSiteConfiguration.md │ │ ├── SalesforcePayPalOrder.md │ │ ├── SalesforcePayPalOrderAddress.md │ │ ├── SalesforcePayPalOrderPayer.md │ │ ├── SalesforcePayPalPaymentDetails.md │ │ ├── SalesforceSepaDebitPaymentDetails.md │ │ └── SalesforceVenmoPaymentDetails.md │ ├── dw_extensions.pinterest │ │ ├── PinterestAvailability.md │ │ ├── PinterestFeedHooks.md │ │ ├── PinterestOrder.md │ │ ├── PinterestOrderHooks.md │ │ └── PinterestProduct.md │ ├── dw_io │ │ ├── CSVStreamReader.md │ │ ├── CSVStreamWriter.md │ │ ├── File.md │ │ ├── FileReader.md │ │ ├── FileWriter.md │ │ ├── InputStream.md │ │ ├── OutputStream.md │ │ ├── PrintWriter.md │ │ ├── RandomAccessFileReader.md │ │ ├── Reader.md │ │ ├── StringWriter.md │ │ ├── Writer.md │ │ ├── XMLIndentingStreamWriter.md │ │ ├── XMLStreamConstants.md │ │ ├── XMLStreamReader.md │ │ └── XMLStreamWriter.md │ ├── dw_job │ │ ├── JobExecution.md │ │ └── JobStepExecution.md │ ├── dw_net │ │ ├── FTPClient.md │ │ ├── FTPFileInfo.md │ │ ├── HTTPClient.md │ │ ├── HTTPRequestPart.md │ │ ├── Mail.md │ │ ├── SFTPClient.md │ │ ├── SFTPFileInfo.md │ │ ├── WebDAVClient.md │ │ └── WebDAVFileInfo.md │ ├── dw_object │ │ ├── ActiveData.md │ │ ├── CustomAttributes.md │ │ ├── CustomObject.md │ │ ├── CustomObjectMgr.md │ │ ├── Extensible.md │ │ ├── ExtensibleObject.md │ │ ├── Note.md │ │ ├── ObjectAttributeDefinition.md │ │ ├── ObjectAttributeGroup.md │ │ ├── ObjectAttributeValueDefinition.md │ │ ├── ObjectTypeDefinition.md │ │ ├── PersistentObject.md │ │ ├── SimpleExtensible.md │ │ └── SystemObjectMgr.md │ ├── dw_order │ │ ├── AbstractItem.md │ │ ├── AbstractItemCtnr.md │ │ ├── Appeasement.md │ │ ├── AppeasementItem.md │ │ ├── Basket.md │ │ ├── BasketMgr.md │ │ ├── BonusDiscountLineItem.md │ │ ├── CouponLineItem.md │ │ ├── CreateAgentBasketLimitExceededException.md │ │ ├── CreateBasketFromOrderException.md │ │ ├── CreateCouponLineItemException.md │ │ ├── CreateOrderException.md │ │ ├── CreateTemporaryBasketLimitExceededException.md │ │ ├── GiftCertificate.md │ │ ├── GiftCertificateLineItem.md │ │ ├── GiftCertificateMgr.md │ │ ├── GiftCertificateStatusCodes.md │ │ ├── Invoice.md │ │ ├── InvoiceItem.md │ │ ├── LineItem.md │ │ ├── LineItemCtnr.md │ │ ├── Order.md │ │ ├── OrderAddress.md │ │ ├── OrderItem.md │ │ ├── OrderMgr.md │ │ ├── OrderPaymentInstrument.md │ │ ├── OrderProcessStatusCodes.md │ │ ├── PaymentCard.md │ │ ├── PaymentInstrument.md │ │ ├── PaymentMethod.md │ │ ├── PaymentMgr.md │ │ ├── PaymentProcessor.md │ │ ├── PaymentStatusCodes.md │ │ ├── PaymentTransaction.md │ │ ├── PriceAdjustment.md │ │ ├── PriceAdjustmentLimitTypes.md │ │ ├── ProductLineItem.md │ │ ├── ProductShippingCost.md │ │ ├── ProductShippingLineItem.md │ │ ├── ProductShippingModel.md │ │ ├── Return.md │ │ ├── ReturnCase.md │ │ ├── ReturnCaseItem.md │ │ ├── ReturnItem.md │ │ ├── Shipment.md │ │ ├── ShipmentShippingCost.md │ │ ├── ShipmentShippingModel.md │ │ ├── ShippingLineItem.md │ │ ├── ShippingLocation.md │ │ ├── ShippingMethod.md │ │ ├── ShippingMgr.md │ │ ├── ShippingOrder.md │ │ ├── ShippingOrderItem.md │ │ ├── SumItem.md │ │ ├── TaxGroup.md │ │ ├── TaxItem.md │ │ ├── TaxMgr.md │ │ ├── TrackingInfo.md │ │ └── TrackingRef.md │ ├── dw_order.hooks │ │ ├── CalculateHooks.md │ │ ├── OrderHooks.md │ │ ├── PaymentHooks.md │ │ ├── ReturnHooks.md │ │ └── ShippingOrderHooks.md │ ├── dw_rpc │ │ ├── SOAPUtil.md │ │ ├── Stub.md │ │ └── WebReference.md │ ├── dw_suggest │ │ ├── BrandSuggestions.md │ │ ├── CategorySuggestions.md │ │ ├── ContentSuggestions.md │ │ ├── CustomSuggestions.md │ │ ├── ProductSuggestions.md │ │ ├── SearchPhraseSuggestions.md │ │ ├── SuggestedCategory.md │ │ ├── SuggestedContent.md │ │ ├── SuggestedPhrase.md │ │ ├── SuggestedProduct.md │ │ ├── SuggestedTerm.md │ │ ├── SuggestedTerms.md │ │ ├── Suggestions.md │ │ └── SuggestModel.md │ ├── dw_svc │ │ ├── FTPService.md │ │ ├── FTPServiceDefinition.md │ │ ├── HTTPFormService.md │ │ ├── HTTPFormServiceDefinition.md │ │ ├── HTTPService.md │ │ ├── HTTPServiceDefinition.md │ │ ├── LocalServiceRegistry.md │ │ ├── Result.md │ │ ├── Service.md │ │ ├── ServiceCallback.md │ │ ├── ServiceConfig.md │ │ ├── ServiceCredential.md │ │ ├── ServiceDefinition.md │ │ ├── ServiceProfile.md │ │ ├── ServiceRegistry.md │ │ ├── SOAPService.md │ │ └── SOAPServiceDefinition.md │ ├── dw_system │ │ ├── AgentUserStatusCodes.md │ │ ├── Cache.md │ │ ├── CacheMgr.md │ │ ├── HookMgr.md │ │ ├── InternalObject.md │ │ ├── JobProcessMonitor.md │ │ ├── Log.md │ │ ├── Logger.md │ │ ├── LogNDC.md │ │ ├── OrganizationPreferences.md │ │ ├── Pipeline.md │ │ ├── PipelineDictionary.md │ │ ├── RemoteInclude.md │ │ ├── Request.md │ │ ├── RequestHooks.md │ │ ├── Response.md │ │ ├── RESTErrorResponse.md │ │ ├── RESTResponseMgr.md │ │ ├── RESTSuccessResponse.md │ │ ├── SearchStatus.md │ │ ├── Session.md │ │ ├── Site.md │ │ ├── SitePreferences.md │ │ ├── Status.md │ │ ├── StatusItem.md │ │ ├── System.md │ │ └── Transaction.md │ ├── dw_util │ │ ├── ArrayList.md │ │ ├── Assert.md │ │ ├── BigInteger.md │ │ ├── Bytes.md │ │ ├── Calendar.md │ │ ├── Collection.md │ │ ├── Currency.md │ │ ├── DateUtils.md │ │ ├── Decimal.md │ │ ├── FilteringCollection.md │ │ ├── Geolocation.md │ │ ├── HashMap.md │ │ ├── HashSet.md │ │ ├── Iterator.md │ │ ├── LinkedHashMap.md │ │ ├── LinkedHashSet.md │ │ ├── List.md │ │ ├── Locale.md │ │ ├── Map.md │ │ ├── MapEntry.md │ │ ├── MappingKey.md │ │ ├── MappingMgr.md │ │ ├── PropertyComparator.md │ │ ├── SecureEncoder.md │ │ ├── SecureFilter.md │ │ ├── SeekableIterator.md │ │ ├── Set.md │ │ ├── SortedMap.md │ │ ├── SortedSet.md │ │ ├── StringUtils.md │ │ ├── Template.md │ │ └── UUIDUtils.md │ ├── dw_value │ │ ├── EnumValue.md │ │ ├── MimeEncodedText.md │ │ ├── Money.md │ │ └── Quantity.md │ ├── dw_web │ │ ├── ClickStream.md │ │ ├── ClickStreamEntry.md │ │ ├── Cookie.md │ │ ├── Cookies.md │ │ ├── CSRFProtection.md │ │ ├── Form.md │ │ ├── FormAction.md │ │ ├── FormElement.md │ │ ├── FormElementValidationResult.md │ │ ├── FormField.md │ │ ├── FormFieldOption.md │ │ ├── FormFieldOptions.md │ │ ├── FormGroup.md │ │ ├── FormList.md │ │ ├── FormListItem.md │ │ ├── Forms.md │ │ ├── HttpParameter.md │ │ ├── HttpParameterMap.md │ │ ├── LoopIterator.md │ │ ├── PageMetaData.md │ │ ├── PageMetaTag.md │ │ ├── PagingModel.md │ │ ├── Resource.md │ │ ├── URL.md │ │ ├── URLAction.md │ │ ├── URLParameter.md │ │ ├── URLRedirect.md │ │ ├── URLRedirectMgr.md │ │ └── URLUtils.md │ ├── sfra │ │ ├── account.md │ │ ├── address.md │ │ ├── billing.md │ │ ├── cart.md │ │ ├── categories.md │ │ ├── content.md │ │ ├── locale.md │ │ ├── order.md │ │ ├── payment.md │ │ ├── price-default.md │ │ ├── price-range.md │ │ ├── price-tiered.md │ │ ├── product-bundle.md │ │ ├── product-full.md │ │ ├── product-line-items.md │ │ ├── product-search.md │ │ ├── product-tile.md │ │ ├── querystring.md │ │ ├── render.md │ │ ├── request.md │ │ ├── response.md │ │ ├── server.md │ │ ├── shipping.md │ │ ├── store.md │ │ ├── stores.md │ │ └── totals.md │ └── TopLevel │ ├── APIException.md │ ├── arguments.md │ ├── Array.md │ ├── ArrayBuffer.md │ ├── BigInt.md │ ├── Boolean.md │ ├── ConversionError.md │ ├── DataView.md │ ├── Date.md │ ├── Error.md │ ├── ES6Iterator.md │ ├── EvalError.md │ ├── Fault.md │ ├── Float32Array.md │ ├── Float64Array.md │ ├── Function.md │ ├── Generator.md │ ├── global.md │ ├── Int16Array.md │ ├── Int32Array.md │ ├── Int8Array.md │ ├── InternalError.md │ ├── IOError.md │ ├── Iterable.md │ ├── Iterator.md │ ├── JSON.md │ ├── Map.md │ ├── Math.md │ ├── Module.md │ ├── Namespace.md │ ├── Number.md │ ├── Object.md │ ├── QName.md │ ├── RangeError.md │ ├── ReferenceError.md │ ├── RegExp.md │ ├── Set.md │ ├── StopIteration.md │ ├── String.md │ ├── Symbol.md │ ├── SyntaxError.md │ ├── SystemError.md │ ├── TypeError.md │ ├── Uint16Array.md │ ├── Uint32Array.md │ ├── Uint8Array.md │ ├── Uint8ClampedArray.md │ ├── URIError.md │ ├── WeakMap.md │ ├── WeakSet.md │ ├── XML.md │ ├── XMLList.md │ └── XMLStreamError.md ├── docs-site │ ├── .gitignore │ ├── App.tsx │ ├── components │ │ ├── Badge.tsx │ │ ├── BreadcrumbSchema.tsx │ │ ├── CodeBlock.tsx │ │ ├── Collapsible.tsx │ │ ├── ConfigBuilder.tsx │ │ ├── ConfigHero.tsx │ │ ├── ConfigModeTabs.tsx │ │ ├── icons.tsx │ │ ├── Layout.tsx │ │ ├── LightCodeContainer.tsx │ │ ├── NewcomerCTA.tsx │ │ ├── NextStepsStrip.tsx │ │ ├── OnThisPage.tsx │ │ ├── Search.tsx │ │ ├── SEO.tsx │ │ ├── Sidebar.tsx │ │ ├── StructuredData.tsx │ │ ├── ToolCard.tsx │ │ ├── ToolFilters.tsx │ │ ├── Typography.tsx │ │ └── VersionBadge.tsx │ ├── constants.tsx │ ├── index.html │ ├── main.tsx │ ├── metadata.json │ ├── package-lock.json │ ├── package.json │ ├── pages │ │ ├── AIInterfacesPage.tsx │ │ ├── ConfigurationPage.tsx │ │ ├── DevelopmentPage.tsx │ │ ├── ExamplesPage.tsx │ │ ├── FeaturesPage.tsx │ │ ├── HomePage.tsx │ │ ├── SecurityPage.tsx │ │ ├── ToolsPage.tsx │ │ └── TroubleshootingPage.tsx │ ├── postcss.config.js │ ├── public │ │ ├── .well-known │ │ │ └── security.txt │ │ ├── 404.html │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-512x512.png │ │ ├── apple-touch-icon.png │ │ ├── explain-product-pricing-methods-no-mcp.png │ │ ├── explain-product-pricing-methods.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon.ico │ │ ├── llms.txt │ │ ├── robots.txt │ │ ├── site.webmanifest │ │ └── sitemap.xml │ ├── README.md │ ├── scripts │ │ ├── generate-search-index.js │ │ ├── generate-sitemap.js │ │ └── search-dev.js │ ├── src │ │ └── styles │ │ ├── input.css │ │ └── prism-theme.css │ ├── tailwind.config.js │ ├── tsconfig.json │ ├── types.ts │ ├── utils │ │ ├── search.ts │ │ └── toolsData.ts │ └── vite.config.ts ├── eslint.config.js ├── jest.config.js ├── LICENSE ├── package-lock.json ├── package.json ├── README.md ├── scripts │ └── convert-docs.js ├── SECURITY.md ├── server.json ├── src │ ├── clients │ │ ├── base │ │ │ ├── http-client.ts │ │ │ ├── oauth-token.ts │ │ │ └── ocapi-auth-client.ts │ │ ├── best-practices-client.ts │ │ ├── cartridge-generation-client.ts │ │ ├── docs │ │ │ ├── class-content-parser.ts │ │ │ ├── class-name-resolver.ts │ │ │ ├── documentation-scanner.ts │ │ │ ├── index.ts │ │ │ └── referenced-types-extractor.ts │ │ ├── docs-client.ts │ │ ├── log-client.ts │ │ ├── logs │ │ │ ├── index.ts │ │ │ ├── log-analyzer.ts │ │ │ ├── log-client.ts │ │ │ ├── log-constants.ts │ │ │ ├── log-file-discovery.ts │ │ │ ├── log-file-reader.ts │ │ │ ├── log-formatter.ts │ │ │ ├── log-processor.ts │ │ │ ├── log-types.ts │ │ │ └── webdav-client-manager.ts │ │ ├── ocapi │ │ │ ├── code-versions-client.ts │ │ │ ├── site-preferences-client.ts │ │ │ └── system-objects-client.ts │ │ ├── ocapi-client.ts │ │ └── sfra-client.ts │ ├── config │ │ ├── configuration-factory.ts │ │ └── dw-json-loader.ts │ ├── core │ │ ├── handlers │ │ │ ├── abstract-log-tool-handler.ts │ │ │ ├── base-handler.ts │ │ │ ├── best-practices-handler.ts │ │ │ ├── cartridge-handler.ts │ │ │ ├── client-factory.ts │ │ │ ├── code-version-handler.ts │ │ │ ├── docs-handler.ts │ │ │ ├── job-log-handler.ts │ │ │ ├── job-log-tool-config.ts │ │ │ ├── log-handler.ts │ │ │ ├── log-tool-config.ts │ │ │ ├── sfra-handler.ts │ │ │ ├── system-object-handler.ts │ │ │ └── validation-helpers.ts │ │ ├── server.ts │ │ └── tool-definitions.ts │ ├── index.ts │ ├── main.ts │ ├── services │ │ ├── file-system-service.ts │ │ ├── index.ts │ │ └── path-service.ts │ ├── tool-configs │ │ ├── best-practices-tool-config.ts │ │ ├── cartridge-tool-config.ts │ │ ├── code-version-tool-config.ts │ │ ├── docs-tool-config.ts │ │ ├── job-log-tool-config.ts │ │ ├── log-tool-config.ts │ │ ├── sfra-tool-config.ts │ │ └── system-object-tool-config.ts │ ├── types │ │ └── types.ts │ └── utils │ ├── cache.ts │ ├── job-log-tool-config.ts │ ├── job-log-utils.ts │ ├── log-cache.ts │ ├── log-tool-config.ts │ ├── log-tool-constants.ts │ ├── log-tool-utils.ts │ ├── logger.ts │ ├── ocapi-url-builder.ts │ ├── path-resolver.ts │ ├── query-builder.ts │ ├── utils.ts │ └── validator.ts ├── tests │ ├── __mocks__ │ │ ├── docs-client.ts │ │ ├── src │ │ │ └── clients │ │ │ └── base │ │ │ └── http-client.js │ │ └── webdav.js │ ├── base-handler.test.ts │ ├── base-http-client.test.ts │ ├── best-practices-handler.test.ts │ ├── cache.test.ts │ ├── cartridge-handler.test.ts │ ├── class-content-parser.test.ts │ ├── class-name-resolver.test.ts │ ├── client-factory.test.ts │ ├── code-version-handler.test.ts │ ├── code-versions-client.test.ts │ ├── config.test.ts │ ├── configuration-factory.test.ts │ ├── docs-handler.test.ts │ ├── documentation-scanner.test.ts │ ├── file-system-service.test.ts │ ├── job-log-handler.test.ts │ ├── job-log-utils.test.ts │ ├── log-client.test.ts │ ├── log-handler.test.ts │ ├── log-processor.test.ts │ ├── logger.test.ts │ ├── mcp │ │ ├── AGENTS.md │ │ ├── node │ │ │ ├── activate-code-version-advanced.full-mode.programmatic.test.js │ │ │ ├── code-versions.full-mode.programmatic.test.js │ │ │ ├── generate-cartridge-structure.docs-only.programmatic.test.js │ │ │ ├── get-available-best-practice-guides.docs-only.programmatic.test.js │ │ │ ├── get-available-sfra-documents.programmatic.test.js │ │ │ ├── get-best-practice-guide.docs-only.programmatic.test.js │ │ │ ├── get-hook-reference.docs-only.programmatic.test.js │ │ │ ├── get-job-execution-summary.full-mode.programmatic.test.js │ │ │ ├── get-job-log-entries.full-mode.programmatic.test.js │ │ │ ├── get-latest-debug.full-mode.programmatic.test.js │ │ │ ├── get-latest-error.full-mode.programmatic.test.js │ │ │ ├── get-latest-info.full-mode.programmatic.test.js │ │ │ ├── get-latest-job-log-files.full-mode.programmatic.test.js │ │ │ ├── get-latest-warn.full-mode.programmatic.test.js │ │ │ ├── get-log-file-contents.full-mode.programmatic.test.js │ │ │ ├── get-sfcc-class-documentation.docs-only.programmatic.test.js │ │ │ ├── get-sfcc-class-info.docs-only.programmatic.test.js │ │ │ ├── get-sfra-categories.docs-only.programmatic.test.js │ │ │ ├── get-sfra-document.programmatic.test.js │ │ │ ├── get-sfra-documents-by-category.docs-only.programmatic.test.js │ │ │ ├── get-system-object-definition.full-mode.programmatic.test.js │ │ │ ├── get-system-object-definitions.docs-only.programmatic.test.js │ │ │ ├── get-system-object-definitions.full-mode.programmatic.test.js │ │ │ ├── list-log-files.full-mode.programmatic.test.js │ │ │ ├── list-sfcc-classes.docs-only.programmatic.test.js │ │ │ ├── search-best-practices.docs-only.programmatic.test.js │ │ │ ├── search-custom-object-attribute-definitions.full-mode.programmatic.test.js │ │ │ ├── search-job-logs-by-name.full-mode.programmatic.test.js │ │ │ ├── search-job-logs.full-mode.programmatic.test.js │ │ │ ├── search-logs.full-mode.programmatic.test.js │ │ │ ├── search-sfcc-classes.docs-only.programmatic.test.js │ │ │ ├── search-sfcc-methods.docs-only.programmatic.test.js │ │ │ ├── search-sfra-documentation.docs-only.programmatic.test.js │ │ │ ├── search-site-preferences.full-mode.programmatic.test.js │ │ │ ├── search-system-object-attribute-definitions.full-mode.programmatic.test.js │ │ │ ├── search-system-object-attribute-groups.full-mode.programmatic.test.js │ │ │ ├── summarize-logs.full-mode.programmatic.test.js │ │ │ ├── tools.docs-only.programmatic.test.js │ │ │ └── tools.full-mode.programmatic.test.js │ │ ├── README.md │ │ ├── test-fixtures │ │ │ └── dw.json │ │ └── yaml │ │ ├── activate-code-version.docs-only.test.mcp.yml │ │ ├── activate-code-version.full-mode.test.mcp.yml │ │ ├── get_latest_error.test.mcp.yml │ │ ├── get-available-best-practice-guides.docs-only.test.mcp.yml │ │ ├── get-available-best-practice-guides.full-mode.test.mcp.yml │ │ ├── get-available-sfra-documents.docs-only.test.mcp.yml │ │ ├── get-available-sfra-documents.full-mode.test.mcp.yml │ │ ├── get-best-practice-guide.docs-only.test.mcp.yml │ │ ├── get-best-practice-guide.full-mode.test.mcp.yml │ │ ├── get-code-versions.docs-only.test.mcp.yml │ │ ├── get-code-versions.full-mode.test.mcp.yml │ │ ├── get-hook-reference.docs-only.test.mcp.yml │ │ ├── get-hook-reference.full-mode.test.mcp.yml │ │ ├── get-job-execution-summary.full-mode.test.mcp.yml │ │ ├── get-job-log-entries.full-mode.test.mcp.yml │ │ ├── get-latest-debug.full-mode.test.mcp.yml │ │ ├── get-latest-error.full-mode.test.mcp.yml │ │ ├── get-latest-info.full-mode.test.mcp.yml │ │ ├── get-latest-job-log-files.full-mode.test.mcp.yml │ │ ├── get-latest-warn.full-mode.test.mcp.yml │ │ ├── get-log-file-contents.full-mode.test.mcp.yml │ │ ├── get-sfcc-class-documentation.docs-only.test.mcp.yml │ │ ├── get-sfcc-class-documentation.full-mode.test.mcp.yml │ │ ├── get-sfcc-class-info.docs-only.test.mcp.yml │ │ ├── get-sfcc-class-info.full-mode.test.mcp.yml │ │ ├── get-sfra-categories.docs-only.test.mcp.yml │ │ ├── get-sfra-categories.full-mode.test.mcp.yml │ │ ├── get-sfra-document.docs-only.test.mcp.yml │ │ ├── get-sfra-document.full-mode.test.mcp.yml │ │ ├── get-sfra-documents-by-category.docs-only.test.mcp.yml │ │ ├── get-sfra-documents-by-category.full-mode.test.mcp.yml │ │ ├── get-system-object-definition.docs-only.test.mcp.yml │ │ ├── get-system-object-definition.full-mode.test.mcp.yml │ │ ├── get-system-object-definitions.docs-only.test.mcp.yml │ │ ├── get-system-object-definitions.full-mode.test.mcp.yml │ │ ├── list-log-files.full-mode.test.mcp.yml │ │ ├── list-sfcc-classes.docs-only.test.mcp.yml │ │ ├── list-sfcc-classes.full-mode.test.mcp.yml │ │ ├── search-best-practices.docs-only.test.mcp.yml │ │ ├── search-best-practices.full-mode.test.mcp.yml │ │ ├── search-custom-object-attribute-definitions.docs-only.test.mcp.yml │ │ ├── search-custom-object-attribute-definitions.test.mcp.yml │ │ ├── search-job-logs-by-name.full-mode.test.mcp.yml │ │ ├── search-job-logs.full-mode.test.mcp.yml │ │ ├── search-logs.full-mode.test.mcp.yml │ │ ├── search-sfcc-classes.docs-only.test.mcp.yml │ │ ├── search-sfcc-classes.full-mode.test.mcp.yml │ │ ├── search-sfcc-methods.docs-only.test.mcp.yml │ │ ├── search-sfcc-methods.full-mode.test.mcp.yml │ │ ├── search-sfra-documentation.docs-only.test.mcp.yml │ │ ├── search-sfra-documentation.full-mode.test.mcp.yml │ │ ├── search-site-preferences.docs-only.test.mcp.yml │ │ ├── search-site-preferences.full-mode.test.mcp.yml │ │ ├── search-system-object-attribute-definitions.docs-only.test.mcp.yml │ │ ├── search-system-object-attribute-definitions.full-mode.test.mcp.yml │ │ ├── search-system-object-attribute-groups.docs-only.test.mcp.yml │ │ ├── search-system-object-attribute-groups.full-mode.test.mcp.yml │ │ ├── summarize-logs.full-mode.test.mcp.yml │ │ ├── tools.docs-only.test.mcp.yml │ │ └── tools.full-mode.test.mcp.yml │ ├── oauth-token.test.ts │ ├── ocapi-auth-client.test.ts │ ├── ocapi-client.test.ts │ ├── path-service.test.ts │ ├── query-builder.test.ts │ ├── referenced-types-extractor.test.ts │ ├── servers │ │ ├── sfcc-mock-server │ │ │ ├── mock-data │ │ │ │ └── ocapi │ │ │ │ ├── code-versions.json │ │ │ │ ├── custom-object-attributes-customapi.json │ │ │ │ ├── custom-object-attributes-globalsettings.json │ │ │ │ ├── custom-object-attributes-versionhistory.json │ │ │ │ ├── site-preferences-ccv.json │ │ │ │ ├── site-preferences-fastforward.json │ │ │ │ ├── site-preferences-sfra.json │ │ │ │ ├── site-preferences-storefront.json │ │ │ │ ├── site-preferences-system.json │ │ │ │ ├── system-object-attribute-groups-campaign.json │ │ │ │ ├── system-object-attribute-groups-category.json │ │ │ │ ├── system-object-attribute-groups-order.json │ │ │ │ ├── system-object-attribute-groups-product.json │ │ │ │ ├── system-object-attribute-groups-sitepreferences.json │ │ │ │ ├── system-object-attributes-customeraddress.json │ │ │ │ ├── system-object-attributes-product-expanded.json │ │ │ │ ├── system-object-attributes-product.json │ │ │ │ ├── system-object-definition-category.json │ │ │ │ ├── system-object-definition-customer.json │ │ │ │ ├── system-object-definition-customeraddress.json │ │ │ │ ├── system-object-definition-order.json │ │ │ │ ├── system-object-definition-product.json │ │ │ │ ├── system-object-definitions-old.json │ │ │ │ └── system-object-definitions.json │ │ │ ├── package-lock.json │ │ │ ├── package.json │ │ │ ├── README.md │ │ │ ├── scripts │ │ │ │ └── setup-logs.js │ │ │ ├── server.js │ │ │ └── src │ │ │ ├── app.js │ │ │ ├── config │ │ │ │ └── server-config.js │ │ │ ├── middleware │ │ │ │ ├── auth.js │ │ │ │ ├── cors.js │ │ │ │ └── logging.js │ │ │ ├── routes │ │ │ │ ├── ocapi │ │ │ │ │ ├── code-versions-handler.js │ │ │ │ │ ├── oauth-handler.js │ │ │ │ │ ├── ocapi-error-utils.js │ │ │ │ │ ├── ocapi-utils.js │ │ │ │ │ ├── site-preferences-handler.js │ │ │ │ │ └── system-objects-handler.js │ │ │ │ ├── ocapi.js │ │ │ │ └── webdav.js │ │ │ └── utils │ │ │ ├── mock-data-loader.js │ │ │ └── webdav-xml.js │ │ └── sfcc-mock-server-manager.ts │ ├── sfcc-mock-server.test.ts │ ├── site-preferences-client.test.ts │ ├── system-objects-client.test.ts │ ├── utils.test.ts │ ├── validation-helpers.test.ts │ └── validator.test.ts ├── tsconfig.json └── tsconfig.test.json ``` # Files -------------------------------------------------------------------------------- /docs/dw_extensions.facebook/FacebookProduct.md: -------------------------------------------------------------------------------- ```markdown 1 | ## Package: dw.extensions.facebook 2 | 3 | # Class FacebookProduct 4 | 5 | ## Inheritance Hierarchy 6 | 7 | - Object 8 | - dw.extensions.facebook.FacebookProduct 9 | 10 | ## Description 11 | 12 | Represents a row in the Facebook catalog feed export. 13 | 14 | ## Constants 15 | 16 | ### AGE_GROUP_ADULT 17 | 18 | **Type:** String = "adult" 19 | 20 | Indicates that the product is for adults. 21 | 22 | ### AGE_GROUP_INFANT 23 | 24 | **Type:** String = "infant" 25 | 26 | Indicates that the product is for infant children. 27 | 28 | ### AGE_GROUP_KIDS 29 | 30 | **Type:** String = "kids" 31 | 32 | Indicates that the product is for children. 33 | 34 | ### AGE_GROUP_NEWBORN 35 | 36 | **Type:** String = "newborn" 37 | 38 | Indicates that the product is for newborn children. 39 | 40 | ### AGE_GROUP_TODDLER 41 | 42 | **Type:** String = "toddler" 43 | 44 | Indicates that the product is for toddler children. 45 | 46 | ### AVAILABILITY_AVAILABLE_FOR_ORDER 47 | 48 | **Type:** String = "available 49 | 50 | Indicates that the product can be ordered for later shipment. 51 | 52 | ### AVAILABILITY_IN_STOCK 53 | 54 | **Type:** String = "in 55 | 56 | Indicates that the product is available to ship immediately. 57 | 58 | ### AVAILABILITY_OUT_OF_STOCK 59 | 60 | **Type:** String = "out 61 | 62 | Indicates that the product is out of stock. 63 | 64 | ### AVAILABILITY_PREORDER 65 | 66 | **Type:** String = "preorder" 67 | 68 | Indicates that the product will be available in the future. 69 | 70 | ### CONDITION_NEW 71 | 72 | **Type:** String = "new" 73 | 74 | Indicates that the product is new. 75 | 76 | ### CONDITION_REFURBISHED 77 | 78 | **Type:** String = "refurbished" 79 | 80 | Indicates that the product is used but has been refurbished. 81 | 82 | ### CONDITION_USED 83 | 84 | **Type:** String = "used" 85 | 86 | Indicates that the product has been used. 87 | 88 | ### GENDER_FEMALE 89 | 90 | **Type:** String = "female" 91 | 92 | Indicates that the product is for females. 93 | 94 | ### GENDER_MALE 95 | 96 | **Type:** String = "male" 97 | 98 | Indicates that the product is for males. 99 | 100 | ### GENDER_UNISEX 101 | 102 | **Type:** String = "unisex" 103 | 104 | Indicates that the product is for both males and females. 105 | 106 | ### SHIPPING_SIZE_UNIT_CM 107 | 108 | **Type:** String = "cm" 109 | 110 | Indicates that the product is measured in centimeters. 111 | 112 | ### SHIPPING_SIZE_UNIT_FT 113 | 114 | **Type:** String = "ft" 115 | 116 | Indicates that the product is measured in feet. 117 | 118 | ### SHIPPING_SIZE_UNIT_IN 119 | 120 | **Type:** String = "in" 121 | 122 | Indicates that the product is measured in inches. 123 | 124 | ### SHIPPING_SIZE_UNIT_M 125 | 126 | **Type:** String = "m" 127 | 128 | Indicates that the product is measured in meters. 129 | 130 | ### SHIPPING_WEIGHT_UNIT_G 131 | 132 | **Type:** String = "g" 133 | 134 | Indicates that the product is weighed in grams. 135 | 136 | ### SHIPPING_WEIGHT_UNIT_KG 137 | 138 | **Type:** String = "kg" 139 | 140 | Indicates that the product is weighed in kilograms. 141 | 142 | ### SHIPPING_WEIGHT_UNIT_LB 143 | 144 | **Type:** String = "lb" 145 | 146 | Indicates that the product is weighed in pounds. 147 | 148 | ### SHIPPING_WEIGHT_UNIT_OZ 149 | 150 | **Type:** String = "oz" 151 | 152 | Indicates that the product is weighed in ounces. 153 | 154 | ## Properties 155 | 156 | ### ageGroup 157 | 158 | **Type:** String 159 | 160 | The age group for the Facebook product. 161 | 162 | ### availability 163 | 164 | **Type:** String 165 | 166 | The availability of the Facebook product. 167 | 168 | ### brand 169 | 170 | **Type:** String 171 | 172 | The Facebook brand of the product. 173 | 174 | ### color 175 | 176 | **Type:** String 177 | 178 | The Facebook color value label of the product. 179 | 180 | ### condition 181 | 182 | **Type:** String 183 | 184 | The condition of the Facebook product. 185 | 186 | ### customLabel0 187 | 188 | **Type:** String 189 | 190 | The Facebook custom label 0 value of the product. 191 | 192 | ### customLabel1 193 | 194 | **Type:** String 195 | 196 | The Facebook custom label 1 value of the product. 197 | 198 | ### customLabel2 199 | 200 | **Type:** String 201 | 202 | The Facebook custom label 2 value of the product. 203 | 204 | ### customLabel3 205 | 206 | **Type:** String 207 | 208 | The Facebook custom label 3 value of the product. 209 | 210 | ### customLabel4 211 | 212 | **Type:** String 213 | 214 | The Facebook custom label 4 value of the product. 215 | 216 | ### description 217 | 218 | **Type:** String 219 | 220 | The description of the Facebook product. 221 | 222 | ### expirationDate 223 | 224 | **Type:** Date 225 | 226 | The Facebook expiration date of the product. If the product is expired it will not be shown. 227 | 228 | ### gender 229 | 230 | **Type:** String 231 | 232 | The gender for the Facebook product. 233 | 234 | ### googleProductCategory 235 | 236 | **Type:** String 237 | 238 | The category of this product in the Google category taxonomy. If the value is longer than 250 characters 239 | it is truncated. 240 | 241 | ### gtin 242 | 243 | **Type:** String 244 | 245 | The Facebook GTIN of the product. 246 | 247 | ### ID 248 | 249 | **Type:** String (Read Only) 250 | 251 | The ID of the Facebook product. This is the same as the ID of the Demandware product. 252 | 253 | ### imageLinks 254 | 255 | **Type:** List 256 | 257 | A list containing the URLs of the images to show in Facebook for the product. 258 | 259 | ### itemGroupID 260 | 261 | **Type:** String 262 | 263 | The ID of the Facebook item group for the product, that is, its master product. 264 | 265 | ### link 266 | 267 | **Type:** URL 268 | 269 | The URL of the Demandware storefront link to the product. 270 | 271 | ### material 272 | 273 | **Type:** String 274 | 275 | The Facebook material value label of the product. 276 | 277 | ### mpn 278 | 279 | **Type:** String 280 | 281 | The Facebook MPN of the product. 282 | 283 | ### pattern 284 | 285 | **Type:** String 286 | 287 | The Facebook pattern value label of the product. 288 | 289 | ### price 290 | 291 | **Type:** Money 292 | 293 | The price to show in Facebook for the product. 294 | 295 | ### productType 296 | 297 | **Type:** String 298 | 299 | The Facebook product type. This is the retailer-defined category of the item. 300 | 301 | ### salePrice 302 | 303 | **Type:** Money 304 | 305 | The sale price to show in Facebook for the product. 306 | 307 | ### salePriceEffectiveDateEnd 308 | 309 | **Type:** Date 310 | 311 | The end date of the Facebook sale price of the product. 312 | 313 | ### salePriceEffectiveDateStart 314 | 315 | **Type:** Date 316 | 317 | The start date of the Facebook sale price of the product. 318 | 319 | ### shippingHeight 320 | 321 | **Type:** Number 322 | 323 | The shipping height of the product. 324 | 325 | ### shippingLength 326 | 327 | **Type:** Number 328 | 329 | The shipping length of the product. 330 | 331 | ### shippingSizeUnit 332 | 333 | **Type:** String 334 | 335 | The shipping size unit of the product. 336 | 337 | ### shippingWeight 338 | 339 | **Type:** Quantity 340 | 341 | The shipping weight for the product. 342 | 343 | ### shippingWidth 344 | 345 | **Type:** Number 346 | 347 | The shipping width of the product. 348 | 349 | ### size 350 | 351 | **Type:** String 352 | 353 | The Facebook size value label of the product. 354 | 355 | ### title 356 | 357 | **Type:** String 358 | 359 | The title of the Facebook product. 360 | 361 | ## Constructor Summary 362 | 363 | ## Method Summary 364 | 365 | ### getAgeGroup 366 | 367 | **Signature:** `getAgeGroup() : String` 368 | 369 | Returns the age group for the Facebook product. 370 | 371 | ### getAvailability 372 | 373 | **Signature:** `getAvailability() : String` 374 | 375 | Returns the availability of the Facebook product. 376 | 377 | ### getBrand 378 | 379 | **Signature:** `getBrand() : String` 380 | 381 | Returns the Facebook brand of the product. 382 | 383 | ### getColor 384 | 385 | **Signature:** `getColor() : String` 386 | 387 | Returns the Facebook color value label of the product. 388 | 389 | ### getCondition 390 | 391 | **Signature:** `getCondition() : String` 392 | 393 | Returns the condition of the Facebook product. 394 | 395 | ### getCustomLabel0 396 | 397 | **Signature:** `getCustomLabel0() : String` 398 | 399 | Returns the Facebook custom label 0 value of the product. 400 | 401 | ### getCustomLabel1 402 | 403 | **Signature:** `getCustomLabel1() : String` 404 | 405 | Returns the Facebook custom label 1 value of the product. 406 | 407 | ### getCustomLabel2 408 | 409 | **Signature:** `getCustomLabel2() : String` 410 | 411 | Returns the Facebook custom label 2 value of the product. 412 | 413 | ### getCustomLabel3 414 | 415 | **Signature:** `getCustomLabel3() : String` 416 | 417 | Returns the Facebook custom label 3 value of the product. 418 | 419 | ### getCustomLabel4 420 | 421 | **Signature:** `getCustomLabel4() : String` 422 | 423 | Returns the Facebook custom label 4 value of the product. 424 | 425 | ### getDescription 426 | 427 | **Signature:** `getDescription() : String` 428 | 429 | Returns the description of the Facebook product. 430 | 431 | ### getExpirationDate 432 | 433 | **Signature:** `getExpirationDate() : Date` 434 | 435 | Returns the Facebook expiration date of the product. 436 | 437 | ### getGender 438 | 439 | **Signature:** `getGender() : String` 440 | 441 | Returns the gender for the Facebook product. 442 | 443 | ### getGoogleProductCategory 444 | 445 | **Signature:** `getGoogleProductCategory() : String` 446 | 447 | Returns the category of this product in the Google category taxonomy. 448 | 449 | ### getGtin 450 | 451 | **Signature:** `getGtin() : String` 452 | 453 | Returns the Facebook GTIN of the product. 454 | 455 | ### getID 456 | 457 | **Signature:** `getID() : String` 458 | 459 | Returns the ID of the Facebook product. 460 | 461 | ### getImageLinks 462 | 463 | **Signature:** `getImageLinks() : List` 464 | 465 | Returns a list containing the URLs of the images to show in Facebook for the product. 466 | 467 | ### getItemGroupID 468 | 469 | **Signature:** `getItemGroupID() : String` 470 | 471 | Returns the ID of the Facebook item group for the product, that is, its master product. 472 | 473 | ### getLink 474 | 475 | **Signature:** `getLink() : URL` 476 | 477 | Returns the URL of the Demandware storefront link to the product. 478 | 479 | ### getMaterial 480 | 481 | **Signature:** `getMaterial() : String` 482 | 483 | Returns the Facebook material value label of the product. 484 | 485 | ### getMpn 486 | 487 | **Signature:** `getMpn() : String` 488 | 489 | Returns the Facebook MPN of the product. 490 | 491 | ### getPattern 492 | 493 | **Signature:** `getPattern() : String` 494 | 495 | Returns the Facebook pattern value label of the product. 496 | 497 | ### getPrice 498 | 499 | **Signature:** `getPrice() : Money` 500 | 501 | Returns the price to show in Facebook for the product. 502 | 503 | ### getProductType 504 | 505 | **Signature:** `getProductType() : String` 506 | 507 | Returns the Facebook product type. 508 | 509 | ### getSalePrice 510 | 511 | **Signature:** `getSalePrice() : Money` 512 | 513 | Returns the sale price to show in Facebook for the product. 514 | 515 | ### getSalePriceEffectiveDateEnd 516 | 517 | **Signature:** `getSalePriceEffectiveDateEnd() : Date` 518 | 519 | Returns the end date of the Facebook sale price of the product. 520 | 521 | ### getSalePriceEffectiveDateStart 522 | 523 | **Signature:** `getSalePriceEffectiveDateStart() : Date` 524 | 525 | Returns the start date of the Facebook sale price of the product. 526 | 527 | ### getShippingHeight 528 | 529 | **Signature:** `getShippingHeight() : Number` 530 | 531 | Returns the shipping height of the product. 532 | 533 | ### getShippingLength 534 | 535 | **Signature:** `getShippingLength() : Number` 536 | 537 | Returns the shipping length of the product. 538 | 539 | ### getShippingSizeUnit 540 | 541 | **Signature:** `getShippingSizeUnit() : String` 542 | 543 | Returns the shipping size unit of the product. 544 | 545 | ### getShippingWeight 546 | 547 | **Signature:** `getShippingWeight() : Quantity` 548 | 549 | Returns the shipping weight for the product. 550 | 551 | ### getShippingWidth 552 | 553 | **Signature:** `getShippingWidth() : Number` 554 | 555 | Returns the shipping width of the product. 556 | 557 | ### getSize 558 | 559 | **Signature:** `getSize() : String` 560 | 561 | Returns the Facebook size value label of the product. 562 | 563 | ### getTitle 564 | 565 | **Signature:** `getTitle() : String` 566 | 567 | Returns the title of the Facebook product. 568 | 569 | ### setAgeGroup 570 | 571 | **Signature:** `setAgeGroup(ageGroup : String) : void` 572 | 573 | Sets the age group for the Facebook product. 574 | 575 | ### setAvailability 576 | 577 | **Signature:** `setAvailability(availability : String) : void` 578 | 579 | Sets the availability of the Facebook product. 580 | 581 | ### setBrand 582 | 583 | **Signature:** `setBrand(brand : String) : void` 584 | 585 | Sets the Facebook brand of the product. 586 | 587 | ### setColor 588 | 589 | **Signature:** `setColor(color : String) : void` 590 | 591 | Sets the Facebook color value label of the product. 592 | 593 | ### setCondition 594 | 595 | **Signature:** `setCondition(condition : String) : void` 596 | 597 | Sets the condition of the Facebook product. 598 | 599 | ### setCustomLabel0 600 | 601 | **Signature:** `setCustomLabel0(customLabel0 : String) : void` 602 | 603 | Sets the Facebook custom label 0 value of the product. 604 | 605 | ### setCustomLabel1 606 | 607 | **Signature:** `setCustomLabel1(customLabel1 : String) : void` 608 | 609 | Sets the Facebook custom label 1 value of the product. 610 | 611 | ### setCustomLabel2 612 | 613 | **Signature:** `setCustomLabel2(customLabel2 : String) : void` 614 | 615 | Sets the Facebook custom label 2 value of the product. 616 | 617 | ### setCustomLabel3 618 | 619 | **Signature:** `setCustomLabel3(customLabel3 : String) : void` 620 | 621 | Sets the Facebook custom label 3 value of the product. 622 | 623 | ### setCustomLabel4 624 | 625 | **Signature:** `setCustomLabel4(customLabel4 : String) : void` 626 | 627 | Sets the Facebook custom label 4 value of the product. 628 | 629 | ### setDescription 630 | 631 | **Signature:** `setDescription(description : String) : void` 632 | 633 | Sets the description of the Facebook product. 634 | 635 | ### setExpirationDate 636 | 637 | **Signature:** `setExpirationDate(expirationDate : Date) : void` 638 | 639 | Sets the Facebook expiration date of the product. 640 | 641 | ### setGender 642 | 643 | **Signature:** `setGender(gender : String) : void` 644 | 645 | Sets the gender for the Facebook product. 646 | 647 | ### setGoogleProductCategory 648 | 649 | **Signature:** `setGoogleProductCategory(googleProductCategory : String) : void` 650 | 651 | Sets the category of this product in the Google category taxonomy. 652 | 653 | ### setGtin 654 | 655 | **Signature:** `setGtin(gtin : String) : void` 656 | 657 | Sets the Facebook GTIN of the product. 658 | 659 | ### setImageLinks 660 | 661 | **Signature:** `setImageLinks(imageLinks : List) : void` 662 | 663 | Sets the list of URLs of images to show in Facebook for the product. 664 | 665 | ### setItemGroupID 666 | 667 | **Signature:** `setItemGroupID(itemGroupID : String) : void` 668 | 669 | Sets the ID of the Facebook item group for the product, that is, its master product. 670 | 671 | ### setLink 672 | 673 | **Signature:** `setLink(link : URL) : void` 674 | 675 | Sets the URL of the Demandware storefront link to the product. 676 | 677 | ### setMaterial 678 | 679 | **Signature:** `setMaterial(material : String) : void` 680 | 681 | Sets the Facebook material value label of the product. 682 | 683 | ### setMpn 684 | 685 | **Signature:** `setMpn(mpn : String) : void` 686 | 687 | Sets the Facebook MPN of the product. 688 | 689 | ### setPattern 690 | 691 | **Signature:** `setPattern(pattern : String) : void` 692 | 693 | Sets the Facebook pattern value label of the product. 694 | 695 | ### setPrice 696 | 697 | **Signature:** `setPrice(price : Money) : void` 698 | 699 | Sets the price to show in Facebook for the product. 700 | 701 | ### setProductType 702 | 703 | **Signature:** `setProductType(productType : String) : void` 704 | 705 | Sets the Facebook product type. 706 | 707 | ### setSalePrice 708 | 709 | **Signature:** `setSalePrice(salePrice : Money) : void` 710 | 711 | Sets the sale price to show in Facebook for the product. 712 | 713 | ### setSalePriceEffectiveDateEnd 714 | 715 | **Signature:** `setSalePriceEffectiveDateEnd(salePriceEffectiveDateEnd : Date) : void` 716 | 717 | Sets the end date of the Facebook sale price of the product. 718 | 719 | ### setSalePriceEffectiveDateStart 720 | 721 | **Signature:** `setSalePriceEffectiveDateStart(salePriceEffectiveDateStart : Date) : void` 722 | 723 | Sets the start date of the Facebook sale price of the product. 724 | 725 | ### setShippingHeight 726 | 727 | **Signature:** `setShippingHeight(shippingHeight : Number) : void` 728 | 729 | Sets the shipping height of the product. 730 | 731 | ### setShippingLength 732 | 733 | **Signature:** `setShippingLength(shippingLength : Number) : void` 734 | 735 | Sets the shipping length of the product. 736 | 737 | ### setShippingSizeUnit 738 | 739 | **Signature:** `setShippingSizeUnit(shippingSizeUnit : String) : void` 740 | 741 | Sets the shipping size unit of the product. 742 | 743 | ### setShippingWeight 744 | 745 | **Signature:** `setShippingWeight(shippingWeight : Quantity) : void` 746 | 747 | Sets the shipping weight for the product. 748 | 749 | ### setShippingWidth 750 | 751 | **Signature:** `setShippingWidth(shippingWidth : Number) : void` 752 | 753 | Sets the shipping width of the product. 754 | 755 | ### setSize 756 | 757 | **Signature:** `setSize(size : String) : void` 758 | 759 | Sets the Facebook size value label of the product. 760 | 761 | ### setTitle 762 | 763 | **Signature:** `setTitle(title : String) : void` 764 | 765 | Sets the title of the Facebook product. 766 | 767 | ## Method Detail 768 | 769 | ## Method Details 770 | 771 | ### getAgeGroup 772 | 773 | **Signature:** `getAgeGroup() : String` 774 | 775 | **Description:** Returns the age group for the Facebook product. 776 | 777 | **Returns:** 778 | 779 | product age group 780 | 781 | --- 782 | 783 | ### getAvailability 784 | 785 | **Signature:** `getAvailability() : String` 786 | 787 | **Description:** Returns the availability of the Facebook product. 788 | 789 | **Returns:** 790 | 791 | product availability 792 | 793 | --- 794 | 795 | ### getBrand 796 | 797 | **Signature:** `getBrand() : String` 798 | 799 | **Description:** Returns the Facebook brand of the product. 800 | 801 | **Returns:** 802 | 803 | the brand 804 | 805 | --- 806 | 807 | ### getColor 808 | 809 | **Signature:** `getColor() : String` 810 | 811 | **Description:** Returns the Facebook color value label of the product. 812 | 813 | **Returns:** 814 | 815 | the color value label 816 | 817 | --- 818 | 819 | ### getCondition 820 | 821 | **Signature:** `getCondition() : String` 822 | 823 | **Description:** Returns the condition of the Facebook product. 824 | 825 | **Returns:** 826 | 827 | product condition 828 | 829 | --- 830 | 831 | ### getCustomLabel0 832 | 833 | **Signature:** `getCustomLabel0() : String` 834 | 835 | **Description:** Returns the Facebook custom label 0 value of the product. 836 | 837 | **Returns:** 838 | 839 | the custom label 0 value 840 | 841 | --- 842 | 843 | ### getCustomLabel1 844 | 845 | **Signature:** `getCustomLabel1() : String` 846 | 847 | **Description:** Returns the Facebook custom label 1 value of the product. 848 | 849 | **Returns:** 850 | 851 | the custom label 1 value 852 | 853 | --- 854 | 855 | ### getCustomLabel2 856 | 857 | **Signature:** `getCustomLabel2() : String` 858 | 859 | **Description:** Returns the Facebook custom label 2 value of the product. 860 | 861 | **Returns:** 862 | 863 | the custom label 2 value 864 | 865 | --- 866 | 867 | ### getCustomLabel3 868 | 869 | **Signature:** `getCustomLabel3() : String` 870 | 871 | **Description:** Returns the Facebook custom label 3 value of the product. 872 | 873 | **Returns:** 874 | 875 | the custom label 3 value 876 | 877 | --- 878 | 879 | ### getCustomLabel4 880 | 881 | **Signature:** `getCustomLabel4() : String` 882 | 883 | **Description:** Returns the Facebook custom label 4 value of the product. 884 | 885 | **Returns:** 886 | 887 | the custom label 4 value 888 | 889 | --- 890 | 891 | ### getDescription 892 | 893 | **Signature:** `getDescription() : String` 894 | 895 | **Description:** Returns the description of the Facebook product. 896 | 897 | **Returns:** 898 | 899 | product description 900 | 901 | --- 902 | 903 | ### getExpirationDate 904 | 905 | **Signature:** `getExpirationDate() : Date` 906 | 907 | **Description:** Returns the Facebook expiration date of the product. If the product is expired it will not be shown. 908 | 909 | **Returns:** 910 | 911 | the expiration date 912 | 913 | --- 914 | 915 | ### getGender 916 | 917 | **Signature:** `getGender() : String` 918 | 919 | **Description:** Returns the gender for the Facebook product. 920 | 921 | **Returns:** 922 | 923 | product gender 924 | 925 | --- 926 | 927 | ### getGoogleProductCategory 928 | 929 | **Signature:** `getGoogleProductCategory() : String` 930 | 931 | **Description:** Returns the category of this product in the Google category taxonomy. If the value is longer than 250 characters it is truncated. 932 | 933 | **Returns:** 934 | 935 | the category of this product in the Google category taxonomy 936 | 937 | --- 938 | 939 | ### getGtin 940 | 941 | **Signature:** `getGtin() : String` 942 | 943 | **Description:** Returns the Facebook GTIN of the product. 944 | 945 | **Returns:** 946 | 947 | the GTIN 948 | 949 | --- 950 | 951 | ### getID 952 | 953 | **Signature:** `getID() : String` 954 | 955 | **Description:** Returns the ID of the Facebook product. This is the same as the ID of the Demandware product. 956 | 957 | **Returns:** 958 | 959 | product ID 960 | 961 | --- 962 | 963 | ### getImageLinks 964 | 965 | **Signature:** `getImageLinks() : List` 966 | 967 | **Description:** Returns a list containing the URLs of the images to show in Facebook for the product. 968 | 969 | **Returns:** 970 | 971 | the URLs of the images 972 | 973 | --- 974 | 975 | ### getItemGroupID 976 | 977 | **Signature:** `getItemGroupID() : String` 978 | 979 | **Description:** Returns the ID of the Facebook item group for the product, that is, its master product. 980 | 981 | **Returns:** 982 | 983 | the ID of the Facebook item group 984 | 985 | --- 986 | 987 | ### getLink 988 | 989 | **Signature:** `getLink() : URL` 990 | 991 | **Description:** Returns the URL of the Demandware storefront link to the product. 992 | 993 | **Returns:** 994 | 995 | the URL of the storefront link 996 | 997 | --- 998 | 999 | ### getMaterial 1000 | 1001 | **Signature:** `getMaterial() : String` 1002 | 1003 | **Description:** Returns the Facebook material value label of the product. 1004 | 1005 | **Returns:** 1006 | 1007 | the material value label 1008 | 1009 | --- 1010 | 1011 | ### getMpn 1012 | 1013 | **Signature:** `getMpn() : String` 1014 | 1015 | **Description:** Returns the Facebook MPN of the product. 1016 | 1017 | **Returns:** 1018 | 1019 | the MPN 1020 | 1021 | --- 1022 | 1023 | ### getPattern 1024 | 1025 | **Signature:** `getPattern() : String` 1026 | 1027 | **Description:** Returns the Facebook pattern value label of the product. 1028 | 1029 | **Returns:** 1030 | 1031 | the pattern value label 1032 | 1033 | --- 1034 | 1035 | ### getPrice 1036 | 1037 | **Signature:** `getPrice() : Money` 1038 | 1039 | **Description:** Returns the price to show in Facebook for the product. 1040 | 1041 | **Returns:** 1042 | 1043 | the price to show in Facebook 1044 | 1045 | --- 1046 | 1047 | ### getProductType 1048 | 1049 | **Signature:** `getProductType() : String` 1050 | 1051 | **Description:** Returns the Facebook product type. This is the retailer-defined category of the item. 1052 | 1053 | **Returns:** 1054 | 1055 | the Facebook product type 1056 | 1057 | --- 1058 | 1059 | ### getSalePrice 1060 | 1061 | **Signature:** `getSalePrice() : Money` 1062 | 1063 | **Description:** Returns the sale price to show in Facebook for the product. 1064 | 1065 | **Returns:** 1066 | 1067 | the sale price to show in Facebook 1068 | 1069 | --- 1070 | 1071 | ### getSalePriceEffectiveDateEnd 1072 | 1073 | **Signature:** `getSalePriceEffectiveDateEnd() : Date` 1074 | 1075 | **Description:** Returns the end date of the Facebook sale price of the product. 1076 | 1077 | **Returns:** 1078 | 1079 | the end date of the Facebook sale price 1080 | 1081 | --- 1082 | 1083 | ### getSalePriceEffectiveDateStart 1084 | 1085 | **Signature:** `getSalePriceEffectiveDateStart() : Date` 1086 | 1087 | **Description:** Returns the start date of the Facebook sale price of the product. 1088 | 1089 | **Returns:** 1090 | 1091 | the start date of the Facebook sale price 1092 | 1093 | --- 1094 | 1095 | ### getShippingHeight 1096 | 1097 | **Signature:** `getShippingHeight() : Number` 1098 | 1099 | **Description:** Returns the shipping height of the product. 1100 | 1101 | **Returns:** 1102 | 1103 | the shipping height 1104 | 1105 | **See Also:** 1106 | 1107 | getShippingLength() 1108 | getShippingWidth() 1109 | getShippingSizeUnit() 1110 | 1111 | --- 1112 | 1113 | ### getShippingLength 1114 | 1115 | **Signature:** `getShippingLength() : Number` 1116 | 1117 | **Description:** Returns the shipping length of the product. 1118 | 1119 | **Returns:** 1120 | 1121 | the shipping length 1122 | 1123 | **See Also:** 1124 | 1125 | getShippingWidth() 1126 | getShippingHeight() 1127 | getShippingSizeUnit() 1128 | 1129 | --- 1130 | 1131 | ### getShippingSizeUnit 1132 | 1133 | **Signature:** `getShippingSizeUnit() : String` 1134 | 1135 | **Description:** Returns the shipping size unit of the product. 1136 | 1137 | **Returns:** 1138 | 1139 | the shipping size unit 1140 | 1141 | **See Also:** 1142 | 1143 | getShippingLength() 1144 | getShippingWidth() 1145 | getShippingHeight() 1146 | 1147 | --- 1148 | 1149 | ### getShippingWeight 1150 | 1151 | **Signature:** `getShippingWeight() : Quantity` 1152 | 1153 | **Description:** Returns the shipping weight for the product. 1154 | 1155 | **Returns:** 1156 | 1157 | the shipping weight 1158 | 1159 | --- 1160 | 1161 | ### getShippingWidth 1162 | 1163 | **Signature:** `getShippingWidth() : Number` 1164 | 1165 | **Description:** Returns the shipping width of the product. 1166 | 1167 | **Returns:** 1168 | 1169 | the shipping width 1170 | 1171 | **See Also:** 1172 | 1173 | getShippingLength() 1174 | getShippingHeight() 1175 | getShippingSizeUnit() 1176 | 1177 | --- 1178 | 1179 | ### getSize 1180 | 1181 | **Signature:** `getSize() : String` 1182 | 1183 | **Description:** Returns the Facebook size value label of the product. 1184 | 1185 | **Returns:** 1186 | 1187 | the size value label 1188 | 1189 | --- 1190 | 1191 | ### getTitle 1192 | 1193 | **Signature:** `getTitle() : String` 1194 | 1195 | **Description:** Returns the title of the Facebook product. 1196 | 1197 | **Returns:** 1198 | 1199 | product title 1200 | 1201 | --- 1202 | 1203 | ### setAgeGroup 1204 | 1205 | **Signature:** `setAgeGroup(ageGroup : String) : void` 1206 | 1207 | **Description:** Sets the age group for the Facebook product. Possible values are AGE_GROUP_ADULT, AGE_GROUP_INFANT, AGE_GROUP_KIDS, AGE_GROUP_NEWBORN, AGE_GROUP_TODDLER, or null. 1208 | 1209 | **Parameters:** 1210 | 1211 | - `ageGroup`: the ageGroup to set for this product 1212 | 1213 | --- 1214 | 1215 | ### setAvailability 1216 | 1217 | **Signature:** `setAvailability(availability : String) : void` 1218 | 1219 | **Description:** Sets the availability of the Facebook product. Possible values are AVAILABILITY_AVAILABLE_FOR_ORDER, AVAILABILITY_IN_STOCK, AVAILABILITY_OUT_OF_STOCK, or AVAILABILITY_PREORDER 1220 | 1221 | **Parameters:** 1222 | 1223 | - `availability`: the availability status to set for this product 1224 | 1225 | --- 1226 | 1227 | ### setBrand 1228 | 1229 | **Signature:** `setBrand(brand : String) : void` 1230 | 1231 | **Description:** Sets the Facebook brand of the product. If the value is longer than 70 characters it is truncated. 1232 | 1233 | **Parameters:** 1234 | 1235 | - `brand`: Facebook brand, up to 70 characters 1236 | 1237 | --- 1238 | 1239 | ### setColor 1240 | 1241 | **Signature:** `setColor(color : String) : void` 1242 | 1243 | **Description:** Sets the Facebook color value label of the product. If the value is longer than 100 characters it is truncated. 1244 | 1245 | **Parameters:** 1246 | 1247 | - `color`: Facebook color value label, up to 100 characters 1248 | 1249 | --- 1250 | 1251 | ### setCondition 1252 | 1253 | **Signature:** `setCondition(condition : String) : void` 1254 | 1255 | **Description:** Sets the condition of the Facebook product. Possible values are CONDITION_NEW, CONDITION_REFURBISHED, or CONDITION_USED. 1256 | 1257 | **Parameters:** 1258 | 1259 | - `condition`: the condition status to set for this product 1260 | 1261 | --- 1262 | 1263 | ### setCustomLabel0 1264 | 1265 | **Signature:** `setCustomLabel0(customLabel0 : String) : void` 1266 | 1267 | **Description:** Sets the Facebook custom label 0 value of the product. 1268 | 1269 | **Parameters:** 1270 | 1271 | - `customLabel0`: custom label 0 value 1272 | 1273 | --- 1274 | 1275 | ### setCustomLabel1 1276 | 1277 | **Signature:** `setCustomLabel1(customLabel1 : String) : void` 1278 | 1279 | **Description:** Sets the Facebook custom label 1 value of the product. 1280 | 1281 | **Parameters:** 1282 | 1283 | - `customLabel1`: custom label 1 value 1284 | 1285 | --- 1286 | 1287 | ### setCustomLabel2 1288 | 1289 | **Signature:** `setCustomLabel2(customLabel2 : String) : void` 1290 | 1291 | **Description:** Sets the Facebook custom label 2 value of the product. 1292 | 1293 | **Parameters:** 1294 | 1295 | - `customLabel2`: custom label 2 value 1296 | 1297 | --- 1298 | 1299 | ### setCustomLabel3 1300 | 1301 | **Signature:** `setCustomLabel3(customLabel3 : String) : void` 1302 | 1303 | **Description:** Sets the Facebook custom label 3 value of the product. 1304 | 1305 | **Parameters:** 1306 | 1307 | - `customLabel3`: custom label 3 value 1308 | 1309 | --- 1310 | 1311 | ### setCustomLabel4 1312 | 1313 | **Signature:** `setCustomLabel4(customLabel4 : String) : void` 1314 | 1315 | **Description:** Sets the Facebook custom label 4 value of the product. 1316 | 1317 | **Parameters:** 1318 | 1319 | - `customLabel4`: custom label 4 value 1320 | 1321 | --- 1322 | 1323 | ### setDescription 1324 | 1325 | **Signature:** `setDescription(description : String) : void` 1326 | 1327 | **Description:** Sets the description of the Facebook product. If the value is longer than 5000 characters it is truncated. 1328 | 1329 | **Parameters:** 1330 | 1331 | - `description`: product description, up to 5000 characters 1332 | 1333 | --- 1334 | 1335 | ### setExpirationDate 1336 | 1337 | **Signature:** `setExpirationDate(expirationDate : Date) : void` 1338 | 1339 | **Description:** Sets the Facebook expiration date of the product. 1340 | 1341 | **Parameters:** 1342 | 1343 | - `expirationDate`: Facebook expiration date 1344 | 1345 | --- 1346 | 1347 | ### setGender 1348 | 1349 | **Signature:** `setGender(gender : String) : void` 1350 | 1351 | **Description:** Sets the gender for the Facebook product. Possible values are GENDER_MALE, GENDER_FEMALE, GENDER_UNISEX, or null. 1352 | 1353 | **Parameters:** 1354 | 1355 | - `gender`: the gender to set for this product 1356 | 1357 | --- 1358 | 1359 | ### setGoogleProductCategory 1360 | 1361 | **Signature:** `setGoogleProductCategory(googleProductCategory : String) : void` 1362 | 1363 | **Description:** Sets the category of this product in the Google category taxonomy. 1364 | 1365 | **Parameters:** 1366 | 1367 | - `googleProductCategory`: Google product category 1368 | 1369 | --- 1370 | 1371 | ### setGtin 1372 | 1373 | **Signature:** `setGtin(gtin : String) : void` 1374 | 1375 | **Description:** Sets the Facebook GTIN of the product. If the value is longer than 70 characters it is truncated. 1376 | 1377 | **Parameters:** 1378 | 1379 | - `gtin`: Facebook GTIN, up to 70 characters 1380 | 1381 | --- 1382 | 1383 | ### setImageLinks 1384 | 1385 | **Signature:** `setImageLinks(imageLinks : List) : void` 1386 | 1387 | **Description:** Sets the list of URLs of images to show in Facebook for the product. 1388 | 1389 | **Parameters:** 1390 | 1391 | - `imageLinks`: links to the product images 1392 | 1393 | --- 1394 | 1395 | ### setItemGroupID 1396 | 1397 | **Signature:** `setItemGroupID(itemGroupID : String) : void` 1398 | 1399 | **Description:** Sets the ID of the Facebook item group for the product, that is, its master product. 1400 | 1401 | **Parameters:** 1402 | 1403 | - `itemGroupID`: ID of Facebook item group 1404 | 1405 | --- 1406 | 1407 | ### setLink 1408 | 1409 | **Signature:** `setLink(link : URL) : void` 1410 | 1411 | **Description:** Sets the URL of the Demandware storefront link to the product. 1412 | 1413 | **Parameters:** 1414 | 1415 | - `link`: Demandware storefront link to the product 1416 | 1417 | --- 1418 | 1419 | ### setMaterial 1420 | 1421 | **Signature:** `setMaterial(material : String) : void` 1422 | 1423 | **Description:** Sets the Facebook material value label of the product. If the value is longer than 200 characters it is truncated. 1424 | 1425 | **Parameters:** 1426 | 1427 | - `material`: Facebook material value label, up to 200 characters 1428 | 1429 | --- 1430 | 1431 | ### setMpn 1432 | 1433 | **Signature:** `setMpn(mpn : String) : void` 1434 | 1435 | **Description:** Sets the Facebook MPN of the product. If the value is longer than 70 characters it is truncated. 1436 | 1437 | **Parameters:** 1438 | 1439 | - `mpn`: Facebook MPN, up to 70 characters 1440 | 1441 | --- 1442 | 1443 | ### setPattern 1444 | 1445 | **Signature:** `setPattern(pattern : String) : void` 1446 | 1447 | **Description:** Sets the Facebook pattern value label of the product. If the value is longer than 100 characters it is truncated. 1448 | 1449 | **Parameters:** 1450 | 1451 | - `pattern`: Facebook pattern value label, up to 100 characters 1452 | 1453 | --- 1454 | 1455 | ### setPrice 1456 | 1457 | **Signature:** `setPrice(price : Money) : void` 1458 | 1459 | **Description:** Sets the price to show in Facebook for the product. 1460 | 1461 | **Parameters:** 1462 | 1463 | - `price`: Facebook price 1464 | 1465 | --- 1466 | 1467 | ### setProductType 1468 | 1469 | **Signature:** `setProductType(productType : String) : void` 1470 | 1471 | **Description:** Sets the Facebook product type. If the value is longer than 750 characters it is truncated. 1472 | 1473 | **Parameters:** 1474 | 1475 | - `productType`: Facebook product type, up to 750 characters 1476 | 1477 | --- 1478 | 1479 | ### setSalePrice 1480 | 1481 | **Signature:** `setSalePrice(salePrice : Money) : void` 1482 | 1483 | **Description:** Sets the sale price to show in Facebook for the product. 1484 | 1485 | **Parameters:** 1486 | 1487 | - `salePrice`: Facebook sale price 1488 | 1489 | --- 1490 | 1491 | ### setSalePriceEffectiveDateEnd 1492 | 1493 | **Signature:** `setSalePriceEffectiveDateEnd(salePriceEffectiveDateEnd : Date) : void` 1494 | 1495 | **Description:** Sets the end date of the Facebook sale price of the product. 1496 | 1497 | **Parameters:** 1498 | 1499 | - `salePriceEffectiveDateEnd`: end date of Facebook sale price 1500 | 1501 | --- 1502 | 1503 | ### setSalePriceEffectiveDateStart 1504 | 1505 | **Signature:** `setSalePriceEffectiveDateStart(salePriceEffectiveDateStart : Date) : void` 1506 | 1507 | **Description:** Sets the start date of the Facebook sale price of the product. 1508 | 1509 | **Parameters:** 1510 | 1511 | - `salePriceEffectiveDateStart`: start date of Facebook sale price 1512 | 1513 | --- 1514 | 1515 | ### setShippingHeight 1516 | 1517 | **Signature:** `setShippingHeight(shippingHeight : Number) : void` 1518 | 1519 | **Description:** Sets the shipping height of the product. If the value is negative it is truncated to 0. 1520 | 1521 | **Parameters:** 1522 | 1523 | - `shippingHeight`: shipping height, may not be negative 1524 | 1525 | **See Also:** 1526 | 1527 | setShippingLength(Number) 1528 | setShippingWidth(Number) 1529 | setShippingSizeUnit(String) 1530 | 1531 | --- 1532 | 1533 | ### setShippingLength 1534 | 1535 | **Signature:** `setShippingLength(shippingLength : Number) : void` 1536 | 1537 | **Description:** Sets the shipping length of the product. If the value is negative it is truncated to 0. 1538 | 1539 | **Parameters:** 1540 | 1541 | - `shippingLength`: shipping length, may not be negative 1542 | 1543 | **See Also:** 1544 | 1545 | setShippingWidth(Number) 1546 | setShippingHeight(Number) 1547 | setShippingSizeUnit(String) 1548 | 1549 | --- 1550 | 1551 | ### setShippingSizeUnit 1552 | 1553 | **Signature:** `setShippingSizeUnit(shippingSizeUnit : String) : void` 1554 | 1555 | **Description:** Sets the shipping size unit of the product. 1556 | 1557 | **Parameters:** 1558 | 1559 | - `shippingSizeUnit`: shipping size unit 1560 | 1561 | **See Also:** 1562 | 1563 | setShippingLength(Number) 1564 | setShippingWidth(Number) 1565 | setShippingHeight(Number) 1566 | 1567 | --- 1568 | 1569 | ### setShippingWeight 1570 | 1571 | **Signature:** `setShippingWeight(shippingWeight : Quantity) : void` 1572 | 1573 | **Description:** Sets the shipping weight for the product. Possible unit values are SHIPPING_WEIGHT_UNIT_LB, SHIPPING_WEIGHT_UNIT_OZ, SHIPPING_WEIGHT_UNIT_G, or SHIPPING_WEIGHT_UNIT_KG. 1574 | 1575 | **Parameters:** 1576 | 1577 | - `shippingWeight`: product shipping weight 1578 | 1579 | --- 1580 | 1581 | ### setShippingWidth 1582 | 1583 | **Signature:** `setShippingWidth(shippingWidth : Number) : void` 1584 | 1585 | **Description:** Sets the shipping width of the product. If the value is negative it is truncated to 0. 1586 | 1587 | **Parameters:** 1588 | 1589 | - `shippingWidth`: shipping width, may not be negative 1590 | 1591 | **See Also:** 1592 | 1593 | setShippingLength(Number) 1594 | setShippingHeight(Number) 1595 | setShippingSizeUnit(String) 1596 | 1597 | --- 1598 | 1599 | ### setSize 1600 | 1601 | **Signature:** `setSize(size : String) : void` 1602 | 1603 | **Description:** Sets the Facebook size value label of the product. If the value is longer than 100 characters it is truncated. 1604 | 1605 | **Parameters:** 1606 | 1607 | - `size`: Facebook size value label, up to 100 characters 1608 | 1609 | --- 1610 | 1611 | ### setTitle 1612 | 1613 | **Signature:** `setTitle(title : String) : void` 1614 | 1615 | **Description:** Sets the title of the Facebook product. If the value is longer than 100 characters it is truncated. 1616 | 1617 | **Parameters:** 1618 | 1619 | - `title`: product title, up to 100 characters 1620 | 1621 | --- ``` -------------------------------------------------------------------------------- /tests/mcp/node/activate-code-version-advanced.full-mode.programmatic.test.js: -------------------------------------------------------------------------------- ```javascript 1 | // ================================================================================== 2 | // SFCC MCP Server - activate_code_version Advanced Programmatic Tests (Full Mode) 3 | // Comprehensive testing for complex scenarios, workflows, and edge cases 4 | // 5 | // Test Coverage: 6 | // - Multi-step code version management workflows 7 | // - Error recovery and resilience testing 8 | // - Integration with get_code_versions tool 9 | // - Advanced parameter validation and edge cases 10 | // - State consistency and transaction-like behavior 11 | // - Performance characteristics under various loads 12 | // - Complex business logic validation 13 | // 14 | // Usage: 15 | // node --test tests/mcp/node/activate-code-version-advanced.full-mode.programmatic.test.js 16 | // npm run test:mcp:node 17 | // ================================================================================== 18 | 19 | import { test, describe, before, after, beforeEach } from 'node:test'; 20 | import { strict as assert } from 'node:assert'; 21 | import { connect } from 'mcp-aegis'; 22 | 23 | describe('activate_code_version Advanced Programmatic Tests (Full Mode)', () => { 24 | let client; 25 | 26 | before(async () => { 27 | client = await connect('./aegis.config.with-dw.json'); 28 | assert.ok(client.connected, 'Client should be connected to server'); 29 | }); 30 | 31 | after(async () => { 32 | if (client?.connected) { 33 | await client.disconnect(); 34 | } 35 | }); 36 | 37 | beforeEach(() => { 38 | // CRITICAL: Clear all buffers to prevent test interference 39 | client.clearAllBuffers(); 40 | }); 41 | 42 | // ================================================================================== 43 | // TOOL AVAILABILITY AND SCHEMA VALIDATION 44 | // ================================================================================== 45 | describe('Tool Availability and Schema Validation', () => { 46 | test('should have activate_code_version tool available in full mode', async () => { 47 | const tools = await client.listTools(); 48 | const activateTool = tools.find(tool => tool.name === 'activate_code_version'); 49 | 50 | assert.ok(activateTool, 'activate_code_version tool should be available'); 51 | assert.equal(activateTool.name, 'activate_code_version'); 52 | assert.ok(activateTool.description.includes('Activate a specific code version')); 53 | 54 | // Validate input schema 55 | assert.equal(activateTool.inputSchema.type, 'object'); 56 | assert.ok(activateTool.inputSchema.properties.codeVersionId); 57 | assert.equal(activateTool.inputSchema.properties.codeVersionId.type, 'string'); 58 | assert.ok(Array.isArray(activateTool.inputSchema.required)); 59 | assert.ok(activateTool.inputSchema.required.includes('codeVersionId')); 60 | }); 61 | 62 | test('should have companion get_code_versions tool for workflow integration', async () => { 63 | const tools = await client.listTools(); 64 | const getCodeVersionsTool = tools.find(tool => tool.name === 'get_code_versions'); 65 | 66 | assert.ok(getCodeVersionsTool, 'get_code_versions tool should be available for workflow integration'); 67 | assert.equal(getCodeVersionsTool.inputSchema.type, 'object'); 68 | }); 69 | }); 70 | 71 | // ================================================================================== 72 | // COMPREHENSIVE PARAMETER VALIDATION 73 | // ================================================================================== 74 | describe('Comprehensive Parameter Validation', () => { 75 | test('should validate codeVersionId parameter types and formats', async () => { 76 | // Test missing parameter 77 | const missingResult = await client.callTool('activate_code_version', {}); 78 | assert.equal(missingResult.isError, true); 79 | assert.ok(missingResult.content[0].text.includes('codeVersionId must be a non-empty string')); 80 | 81 | // Test empty string 82 | const emptyResult = await client.callTool('activate_code_version', { codeVersionId: '' }); 83 | assert.equal(emptyResult.isError, true); 84 | assert.ok(emptyResult.content[0].text.includes('codeVersionId must be a non-empty string')); 85 | 86 | // Test null value 87 | const nullResult = await client.callTool('activate_code_version', { codeVersionId: null }); 88 | assert.equal(nullResult.isError, true); 89 | assert.ok(nullResult.content[0].text.includes('codeVersionId must be a non-empty string')); 90 | 91 | // Test undefined value 92 | const undefinedResult = await client.callTool('activate_code_version', { codeVersionId: undefined }); 93 | assert.equal(undefinedResult.isError, true); 94 | assert.ok(undefinedResult.content[0].text.includes('codeVersionId must be a non-empty string')); 95 | }); 96 | 97 | test('should handle various invalid codeVersionId formats gracefully', async () => { 98 | const invalidFormats = [ 99 | 123, // number 100 | true, // boolean 101 | [], // array 102 | {}, // object 103 | ' ', // whitespace only 104 | '\n\t', // whitespace characters 105 | ]; 106 | 107 | for (const invalidFormat of invalidFormats) { 108 | const result = await client.callTool('activate_code_version', { codeVersionId: invalidFormat }); 109 | assert.equal(result.isError, true, `Should reject ${typeof invalidFormat}: ${JSON.stringify(invalidFormat)}`); 110 | assert.ok(result.content[0].text.includes('codeVersionId must be a non-empty string')); 111 | } 112 | }); 113 | 114 | test('should handle edge case codeVersionId values', async () => { 115 | const edgeCases = [ 116 | 'a'.repeat(1000), // Very long ID 117 | 'test-version-with-special-chars!@#$%^&*()', // Special characters 118 | 'version with spaces', // Spaces 119 | 'UPPERCASE-VERSION', // Case variations 120 | 'version_nonexistent_test', // Non-existent version 121 | 'version.with.dots', // Dots 122 | '123-numeric-start', // Starting with numbers 123 | 'unicode-测试-version', // Unicode characters 124 | ]; 125 | 126 | for (const edgeCase of edgeCases) { 127 | const result = await client.callTool('activate_code_version', { codeVersionId: edgeCase }); 128 | assert.equal(result.isError, true, `Should handle edge case: ${edgeCase}`); 129 | 130 | // Should get 404 or similar SFCC error, not parameter validation error 131 | assert.ok( 132 | result.content[0].text.includes('404') || 133 | result.content[0].text.includes('not found') || 134 | result.content[0].text.includes('InvalidParameterException'), 135 | `Should get SFCC API error for edge case: ${edgeCase}, got: ${result.content[0].text}` 136 | ); 137 | } 138 | }); 139 | }); 140 | 141 | // ================================================================================== 142 | // SFCC API ERROR HANDLING AND RESPONSE PARSING 143 | // ================================================================================== 144 | describe('SFCC API Error Handling and Response Parsing', () => { 145 | test('should parse and format SFCC API errors correctly', async () => { 146 | const result = await client.callTool('activate_code_version', { 147 | codeVersionId: 'nonexistent-test-version-12345' 148 | }); 149 | 150 | assert.equal(result.isError, true); 151 | assert.equal(result.content.length, 1); 152 | assert.equal(result.content[0].type, 'text'); 153 | 154 | const errorText = result.content[0].text; 155 | assert.ok(errorText.startsWith('Error:'), 'Error should start with Error:'); 156 | 157 | // Should contain SFCC fault information 158 | assert.ok( 159 | errorText.includes('404') || 160 | errorText.includes('not found') || 161 | errorText.includes('InvalidParameterException'), 162 | `Should contain SFCC fault info, got: ${errorText}` 163 | ); 164 | }); 165 | 166 | test('should handle different types of SFCC API errors consistently', async () => { 167 | const testVersions = [ 168 | 'definitely-nonexistent-version', 169 | 'another-invalid-version-name', 170 | 'test-error-scenario-version' 171 | ]; 172 | 173 | const errorResponses = []; 174 | 175 | for (const versionId of testVersions) { 176 | const result = await client.callTool('activate_code_version', { codeVersionId: versionId }); 177 | assert.equal(result.isError, true); 178 | errorResponses.push(result.content[0].text); 179 | } 180 | 181 | // All errors should follow similar format 182 | errorResponses.forEach(errorText => { 183 | assert.ok(errorText.startsWith('Error:'), 'All errors should start with Error:'); 184 | assert.ok(errorText.length > 20, 'Error messages should be reasonably detailed'); 185 | }); 186 | }); 187 | 188 | test('should handle malformed SFCC API responses gracefully', async () => { 189 | // Test with version ID that might cause unusual API responses 190 | const result = await client.callTool('activate_code_version', { 191 | codeVersionId: 'test-malformed-response-handling' 192 | }); 193 | 194 | assert.equal(result.isError, true); 195 | assert.ok(result.content, 'Should always return content array'); 196 | assert.ok(result.content[0].text, 'Should always return text content'); 197 | assert.equal(typeof result.content[0].text, 'string', 'Error text should be string'); 198 | }); 199 | }); 200 | 201 | // ================================================================================== 202 | // INTEGRATION WITH GET_CODE_VERSIONS WORKFLOW 203 | // ================================================================================== 204 | describe('Integration with get_code_versions Workflow', () => { 205 | test('should integrate with get_code_versions for complete workflow', async () => { 206 | // Step 1: Get list of available code versions 207 | const versionsResult = await client.callTool('get_code_versions', {}); 208 | assert.equal(versionsResult.isError, false, 'get_code_versions should succeed'); 209 | 210 | // Parse the response to understand available versions 211 | const versionsText = versionsResult.content[0].text; 212 | assert.ok(versionsText.length > 0, 'Should return version information'); 213 | 214 | // Step 2: Try to activate a clearly non-existent version 215 | const activateResult = await client.callTool('activate_code_version', { 216 | codeVersionId: 'workflow-test-nonexistent-version' 217 | }); 218 | assert.equal(activateResult.isError, true, 'Should fail for non-existent version'); 219 | 220 | // Step 3: Verify error handling doesn't affect subsequent get_code_versions calls 221 | const versionsResult2 = await client.callTool('get_code_versions', {}); 222 | assert.equal(versionsResult2.isError, false, 'get_code_versions should still work after failed activation'); 223 | }); 224 | 225 | test('should maintain consistent state across multiple tool calls', async () => { 226 | const operations = [ 227 | { tool: 'get_code_versions', args: {} }, 228 | { tool: 'activate_code_version', args: { codeVersionId: 'test-state-consistency-1' } }, 229 | { tool: 'get_code_versions', args: {} }, 230 | { tool: 'activate_code_version', args: { codeVersionId: 'test-state-consistency-2' } }, 231 | { tool: 'get_code_versions', args: {} }, 232 | ]; 233 | 234 | const results = []; 235 | 236 | for (const operation of operations) { 237 | const result = await client.callTool(operation.tool, operation.args); 238 | results.push({ operation, result }); 239 | 240 | // Each operation should return proper response structure 241 | assert.ok(result.content, `${operation.tool} should return content`); 242 | assert.ok(Array.isArray(result.content), `${operation.tool} content should be array`); 243 | assert.equal(typeof result.isError, 'boolean', `${operation.tool} should have isError boolean`); 244 | } 245 | 246 | // Verify get_code_versions calls succeeded while activate calls failed (expected for non-existent versions) 247 | const getVersionsResults = results.filter(r => r.operation.tool === 'get_code_versions'); 248 | const activateResults = results.filter(r => r.operation.tool === 'activate_code_version'); 249 | 250 | getVersionsResults.forEach((r, index) => { 251 | assert.equal(r.result.isError, false, `get_code_versions call ${index + 1} should succeed`); 252 | }); 253 | 254 | activateResults.forEach((r, index) => { 255 | assert.equal(r.result.isError, true, `activate_code_version call ${index + 1} should fail for non-existent version`); 256 | }); 257 | }); 258 | }); 259 | 260 | // ================================================================================== 261 | // ERROR RECOVERY AND RESILIENCE TESTING 262 | // ================================================================================== 263 | describe('Error Recovery and Resilience Testing', () => { 264 | test('should recover gracefully from various error scenarios', async () => { 265 | const errorScenarios = [ 266 | { description: 'Empty codeVersionId', args: { codeVersionId: '' } }, 267 | { description: 'Very long codeVersionId', args: { codeVersionId: 'x'.repeat(500) } }, 268 | { description: 'Special characters', args: { codeVersionId: '!@#$%^&*()_+{}|:"<>?[]\\;\',./' } }, 269 | { description: 'Unicode characters', args: { codeVersionId: '测试版本号码' } }, 270 | { description: 'SQL injection attempt', args: { codeVersionId: "'; DROP TABLE versions; --" } }, 271 | ]; 272 | 273 | for (const scenario of errorScenarios) { 274 | const result = await client.callTool('activate_code_version', scenario.args); 275 | 276 | // Should handle all scenarios gracefully without throwing 277 | assert.equal(result.isError, true, `${scenario.description} should return error`); 278 | assert.ok(result.content, `${scenario.description} should return content`); 279 | assert.ok(result.content[0].text, `${scenario.description} should return error text`); 280 | 281 | // Verify server is still responsive after error 282 | const recoveryTest = await client.listTools(); 283 | assert.ok(recoveryTest.length > 0, `Server should be responsive after ${scenario.description}`); 284 | } 285 | }); 286 | 287 | test('should handle rapid sequential activation attempts', async () => { 288 | const rapidRequests = Array.from({ length: 10 }, (_, i) => ({ 289 | codeVersionId: `rapid-test-version-${i}` 290 | })); 291 | 292 | const results = []; 293 | 294 | // Execute requests sequentially (MCP doesn't support concurrent requests) 295 | for (const request of rapidRequests) { 296 | const result = await client.callTool('activate_code_version', request); 297 | results.push(result); 298 | } 299 | 300 | // All requests should be handled properly 301 | results.forEach((result, index) => { 302 | assert.equal(result.isError, true, `Rapid request ${index} should fail for non-existent version`); 303 | assert.ok(result.content[0].text.length > 0, `Rapid request ${index} should have error message`); 304 | }); 305 | 306 | // Server should still be responsive 307 | const finalTest = await client.listTools(); 308 | assert.ok(finalTest.length > 0, 'Server should be responsive after rapid requests'); 309 | }); 310 | 311 | test('should maintain error isolation between requests', async () => { 312 | // Generate error 313 | const errorResult = await client.callTool('activate_code_version', { codeVersionId: '' }); 314 | assert.equal(errorResult.isError, true); 315 | 316 | // Verify normal operation still works 317 | const normalResult = await client.callTool('get_code_versions', {}); 318 | assert.equal(normalResult.isError, false, 'Normal operations should work after errors'); 319 | 320 | // Generate different error 321 | const errorResult2 = await client.callTool('activate_code_version', { codeVersionId: 'another-error-test' }); 322 | assert.equal(errorResult2.isError, true); 323 | 324 | // Verify isolation - errors should be different 325 | assert.notEqual(errorResult.content[0].text, errorResult2.content[0].text, 'Different errors should produce different messages'); 326 | }); 327 | }); 328 | 329 | // ================================================================================== 330 | // RESPONSE FORMAT AND STRUCTURE VALIDATION 331 | // ================================================================================== 332 | describe('Response Format and Structure Validation', () => { 333 | test('should return consistent response structure across all scenarios', async () => { 334 | const testScenarios = [ 335 | { name: 'missing parameter', args: {} }, 336 | { name: 'empty parameter', args: { codeVersionId: '' } }, 337 | { name: 'valid format nonexistent version', args: { codeVersionId: 'test-structure-validation' } }, 338 | { name: 'special characters', args: { codeVersionId: 'test!@#$' } }, 339 | ]; 340 | 341 | for (const scenario of testScenarios) { 342 | const result = await client.callTool('activate_code_version', scenario.args); 343 | 344 | // Validate MCP response structure 345 | assert.ok('content' in result, `${scenario.name}: Should have content property`); 346 | assert.ok('isError' in result, `${scenario.name}: Should have isError property`); 347 | assert.ok(Array.isArray(result.content), `${scenario.name}: Content should be array`); 348 | assert.equal(typeof result.isError, 'boolean', `${scenario.name}: isError should be boolean`); 349 | 350 | // Validate content structure 351 | assert.equal(result.content.length, 1, `${scenario.name}: Should have exactly one content item`); 352 | assert.equal(result.content[0].type, 'text', `${scenario.name}: Content should be text type`); 353 | assert.ok(typeof result.content[0].text === 'string', `${scenario.name}: Text should be string`); 354 | assert.ok(result.content[0].text.length > 0, `${scenario.name}: Text should not be empty`); 355 | 356 | // All test scenarios should return errors for these test cases 357 | assert.equal(result.isError, true, `${scenario.name}: Should be error for test cases`); 358 | } 359 | }); 360 | 361 | test('should format error messages consistently', async () => { 362 | const results = []; 363 | 364 | // Collect various error responses 365 | const errorCases = [ 366 | 'format-test-version-1', 367 | 'format-test-version-2', 368 | 'format-test-version-3' 369 | ]; 370 | 371 | for (const versionId of errorCases) { 372 | const result = await client.callTool('activate_code_version', { codeVersionId: versionId }); 373 | results.push(result.content[0].text); 374 | } 375 | 376 | // All errors should start with "Error:" 377 | results.forEach((errorText, index) => { 378 | assert.ok(errorText.startsWith('Error:'), `Error ${index + 1} should start with 'Error:'`); 379 | assert.ok(errorText.length > 10, `Error ${index + 1} should be reasonably detailed`); 380 | }); 381 | }); 382 | }); 383 | 384 | // ================================================================================== 385 | // BUSINESS LOGIC AND WORKFLOW VALIDATION 386 | // ================================================================================== 387 | describe('Business Logic and Workflow Validation', () => { 388 | test('should enforce code version management business rules', async () => { 389 | // Test that we get appropriate error for non-existent versions 390 | const result = await client.callTool('activate_code_version', { 391 | codeVersionId: 'business-logic-test-version' 392 | }); 393 | 394 | assert.equal(result.isError, true); 395 | 396 | // Error should indicate version not found, not generic failure 397 | const errorText = result.content[0].text.toLowerCase(); 398 | assert.ok( 399 | errorText.includes('not found') || 400 | errorText.includes('404') || 401 | errorText.includes('does not exist') || 402 | errorText.includes('invalidparameterexception'), 403 | `Error should indicate version not found: ${result.content[0].text}` 404 | ); 405 | }); 406 | 407 | test('should validate code version activation preconditions', async () => { 408 | // According to tool description: "Only inactive code versions can be activated" 409 | // For non-existent versions, we should get appropriate error 410 | 411 | const result = await client.callTool('activate_code_version', { 412 | codeVersionId: 'precondition-test-version' 413 | }); 414 | 415 | assert.equal(result.isError, true); 416 | 417 | // Should get proper SFCC API error about version not existing 418 | assert.ok(result.content[0].text.includes('Error:')); 419 | }); 420 | 421 | test('should provide informative error messages for troubleshooting', async () => { 422 | const result = await client.callTool('activate_code_version', { 423 | codeVersionId: 'troubleshooting-test-version' 424 | }); 425 | 426 | assert.equal(result.isError, true); 427 | 428 | const errorText = result.content[0].text; 429 | 430 | // Error should be helpful for developers 431 | assert.ok(errorText.length > 30, 'Error message should be detailed enough for troubleshooting'); 432 | assert.ok(errorText.includes('Error:'), 'Should clearly indicate this is an error'); 433 | 434 | // Should contain either version-specific info or general API error info 435 | assert.ok( 436 | errorText.includes('version') || 437 | errorText.includes('404') || 438 | errorText.includes('not found') || 439 | errorText.includes('Request failed'), 440 | 'Should contain helpful error context' 441 | ); 442 | }); 443 | }); 444 | 445 | // ================================================================================== 446 | // PERFORMANCE AND RELIABILITY CHARACTERISTICS 447 | // ================================================================================== 448 | describe('Performance and Reliability Characteristics', () => { 449 | test('should handle operations within reasonable time bounds', async () => { 450 | const startTime = Date.now(); 451 | 452 | const result = await client.callTool('activate_code_version', { 453 | codeVersionId: 'performance-test-version' 454 | }); 455 | 456 | const duration = Date.now() - startTime; 457 | 458 | // Should complete within reasonable time (lenient for CI environments) 459 | assert.ok(duration < 10000, `Operation should complete within 10 seconds, took ${duration}ms`); 460 | 461 | // Should still return proper response 462 | assert.ok(result.content, 'Should return response even under timing constraints'); 463 | }); 464 | 465 | test('should maintain consistent response times across multiple calls', async () => { 466 | const durations = []; 467 | const testCalls = 5; 468 | 469 | for (let i = 0; i < testCalls; i++) { 470 | const startTime = Date.now(); 471 | 472 | await client.callTool('activate_code_version', { 473 | codeVersionId: `consistency-test-${i}` 474 | }); 475 | 476 | durations.push(Date.now() - startTime); 477 | } 478 | 479 | // All calls should complete within reasonable bounds 480 | durations.forEach((duration, index) => { 481 | assert.ok(duration < 10000, `Call ${index + 1} should complete within 10 seconds, took ${duration}ms`); 482 | }); 483 | 484 | // Calculate variance (should not be extreme) 485 | const maxVariation = Math.max(...durations) / Math.min(...durations); 486 | 487 | // Lenient variance check for CI environments 488 | assert.ok(maxVariation < 50, `Response time variation should be reasonable, got ${maxVariation}x variation`); 489 | }); 490 | 491 | test('should handle stress scenarios gracefully', async () => { 492 | // Test with various payload sizes and complexity 493 | const stressTests = [ 494 | { name: 'Long version ID', codeVersionId: 'stress-test-' + 'x'.repeat(200) }, 495 | { name: 'Complex characters', codeVersionId: 'stress-测试-🔥-version-!@#$%^&*()' }, 496 | { name: 'JSON-like string', codeVersionId: '{"version": "test", "data": [1,2,3]}' }, 497 | { name: 'XML-like string', codeVersionId: '<version>test</version><data>stress</data>' }, 498 | ]; 499 | 500 | for (const stressTest of stressTests) { 501 | const result = await client.callTool('activate_code_version', { 502 | codeVersionId: stressTest.codeVersionId 503 | }); 504 | 505 | // Should handle gracefully without crashing 506 | assert.ok(result.content, `${stressTest.name}: Should return content`); 507 | assert.equal(typeof result.isError, 'boolean', `${stressTest.name}: Should return boolean isError`); 508 | 509 | // Server should remain responsive 510 | const healthCheck = await client.listTools(); 511 | assert.ok(healthCheck.length > 0, `${stressTest.name}: Server should remain responsive`); 512 | } 513 | }); 514 | }); 515 | 516 | // ================================================================================== 517 | // EDGE CASES AND BOUNDARY CONDITIONS 518 | // ================================================================================== 519 | describe('Edge Cases and Boundary Conditions', () => { 520 | test('should handle maximum length version IDs', async () => { 521 | // Test various length boundaries 522 | const lengthTests = [ 523 | { length: 100, name: '100 characters' }, 524 | { length: 255, name: '255 characters (common limit)' }, 525 | { length: 500, name: '500 characters' }, 526 | { length: 1000, name: '1000 characters' }, 527 | ]; 528 | 529 | for (const lengthTest of lengthTests) { 530 | const longVersionId = 'test-' + 'x'.repeat(lengthTest.length - 5); 531 | 532 | const result = await client.callTool('activate_code_version', { 533 | codeVersionId: longVersionId 534 | }); 535 | 536 | // Should handle gracefully (expect error for non-existent version) 537 | assert.equal(result.isError, true, `${lengthTest.name}: Should handle long version ID`); 538 | assert.ok(result.content[0].text.length > 0, `${lengthTest.name}: Should return error message`); 539 | } 540 | }); 541 | 542 | test('should handle unusual character encodings and formats', async () => { 543 | const encodingTests = [ 544 | { name: 'Unicode characters', value: 'version-测试-版本-号码' }, 545 | { name: 'Emoji characters', value: 'version-🚀-💻-🔥' }, 546 | { name: 'Control characters', value: 'version\n\t\r\b\f' }, 547 | { name: 'High unicode', value: 'version-𝕧𝕖𝕣𝕤𝕚𝕠𝕟' }, 548 | { name: 'Mixed scripts', value: 'version-αβγ-أبج-中文-🌍' }, 549 | ]; 550 | 551 | for (const encodingTest of encodingTests) { 552 | const result = await client.callTool('activate_code_version', { 553 | codeVersionId: encodingTest.value 554 | }); 555 | 556 | // Should handle without server errors 557 | assert.ok(result.content, `${encodingTest.name}: Should return content`); 558 | assert.equal(typeof result.isError, 'boolean', `${encodingTest.name}: Should return boolean isError`); 559 | 560 | // Check server responsiveness 561 | const healthCheck = await client.listTools(); 562 | assert.ok(healthCheck.length > 0, `${encodingTest.name}: Server should remain responsive`); 563 | } 564 | }); 565 | 566 | test('should validate parameter completeness and format', async () => { 567 | // Test various parameter scenarios 568 | const parameterTests = [ 569 | { name: 'Extra parameters', args: { codeVersionId: 'test', extraParam: 'should-be-ignored' } }, 570 | { name: 'Case variations', args: { CodeVersionId: 'test-case' } }, // Wrong case 571 | { name: 'Nested object', args: { codeVersionId: { nested: 'test' } } }, 572 | { name: 'Array value', args: { codeVersionId: ['test', 'array'] } }, 573 | ]; 574 | 575 | for (const paramTest of parameterTests) { 576 | const result = await client.callTool('activate_code_version', paramTest.args); 577 | 578 | // Should handle parameter variations appropriately 579 | assert.ok(result.content, `${paramTest.name}: Should return content`); 580 | assert.equal(typeof result.isError, 'boolean', `${paramTest.name}: Should return boolean isError`); 581 | 582 | if (paramTest.name === 'Extra parameters') { 583 | // Extra parameters might be acceptable if codeVersionId is valid string 584 | // We expect error because version doesn't exist, not parameter error 585 | assert.ok( 586 | result.content[0].text.includes('404') || 587 | result.content[0].text.includes('not found') || 588 | result.content[0].text.includes('codeVersionId must be a non-empty string'), 589 | `${paramTest.name}: Should handle extra parameters gracefully` 590 | ); 591 | } else { 592 | // Other cases should fail parameter validation 593 | assert.equal(result.isError, true, `${paramTest.name}: Should fail validation`); 594 | } 595 | } 596 | }); 597 | }); 598 | 599 | // ================================================================================== 600 | // MOCK VALIDATION AND TESTING ENVIRONMENT 601 | // ================================================================================== 602 | describe('Mock Validation and Testing Environment', () => { 603 | test('should validate we are testing against mock/sandbox environment', async () => { 604 | // Ensure we're not accidentally testing against production 605 | const result = await client.callTool('activate_code_version', { 606 | codeVersionId: 'PRODUCTION-SAFETY-CHECK-DO-NOT-ACTIVATE' 607 | }); 608 | 609 | // Should fail (which is expected for non-existent version in sandbox) 610 | assert.equal(result.isError, true, 'Should fail for test version in sandbox environment'); 611 | 612 | // Verify we get sandbox-appropriate error (not production access denied) 613 | const errorText = result.content[0].text.toLowerCase(); 614 | assert.ok( 615 | errorText.includes('not found') || 616 | errorText.includes('404') || 617 | errorText.includes('invalidparameterexception'), 618 | `Should get sandbox error, not production access error: ${result.content[0].text}` 619 | ); 620 | }); 621 | 622 | test('should have consistent mock behavior across test runs', async () => { 623 | const testVersion = 'consistent-mock-test-version'; 624 | 625 | // Call the same operation multiple times 626 | const results = []; 627 | for (let i = 0; i < 3; i++) { 628 | const result = await client.callTool('activate_code_version', { 629 | codeVersionId: testVersion 630 | }); 631 | results.push(result); 632 | } 633 | 634 | // All results should be consistent 635 | results.forEach((result, index) => { 636 | assert.equal(result.isError, true, `Call ${index + 1}: Should consistently return error`); 637 | assert.ok(result.content[0].text.length > 0, `Call ${index + 1}: Should have error message`); 638 | }); 639 | 640 | // Error messages should be similar (allowing for some variation in timing/IDs) 641 | const errorTexts = results.map(r => r.content[0].text); 642 | 643 | errorTexts.forEach((errorText, index) => { 644 | assert.ok( 645 | errorText.startsWith('Error:'), 646 | `Call ${index + 1}: Should have consistent error format` 647 | ); 648 | }); 649 | }); 650 | }); 651 | }); ``` -------------------------------------------------------------------------------- /tests/mcp/yaml/search-sfcc-classes.full-mode.test.mcp.yml: -------------------------------------------------------------------------------- ```yaml 1 | # ================================================================================== 2 | # SFCC MCP Server - search_sfcc_classes Tool YAML Tests 3 | # Comprehensive testing for SFCC class search functionality 4 | # Tests both successful responses and error handling scenarios 5 | # 6 | # Quick Test Commands: 7 | # aegis "tests/mcp/yaml/search-sfcc-classes.full-mode.test.mcp.yml" --config "aegis.config.with-dw.json" --verbose 8 | # aegis "tests/mcp/yaml/search-sfcc-classes.full-mode.test.mcp.yml" --config "aegis.config.with-dw.json" --debug --timing 9 | # aegis query search_sfcc_classes '{"query": "catalog"}' --config "aegis.config.with-dw.json" 10 | # aegis query search_sfcc_classes '{"query": "product"}' --config "aegis.config.with-dw.json" 11 | # ================================================================================== 12 | description: "SFCC MCP Server search_sfcc_classes tool - comprehensive validation" 13 | 14 | # ================================================================================== 15 | # BASIC TOOL STRUCTURE VALIDATION 16 | # ================================================================================== 17 | tests: 18 | - it: "should list search_sfcc_classes tool in available tools" 19 | request: 20 | jsonrpc: "2.0" 21 | id: "tool-available" 22 | method: "tools/list" 23 | params: {} 24 | expect: 25 | response: 26 | jsonrpc: "2.0" 27 | id: "tool-available" 28 | result: 29 | match:extractField: "tools.*.name" 30 | value: "match:arrayContains:search_sfcc_classes" 31 | stderr: "toBeEmpty" 32 | 33 | - it: "should have search_sfcc_classes in tools list with proper structure" 34 | request: 35 | jsonrpc: "2.0" 36 | id: "tool-metadata" 37 | method: "tools/list" 38 | params: {} 39 | expect: 40 | response: 41 | jsonrpc: "2.0" 42 | id: "tool-metadata" 43 | result: 44 | tools: "match:arrayContains:name:search_sfcc_classes" 45 | stderr: "toBeEmpty" 46 | 47 | - it: "should have tool with meaningful description" 48 | request: 49 | jsonrpc: "2.0" 50 | id: "tool-description-quality" 51 | method: "tools/list" 52 | params: {} 53 | expect: 54 | response: 55 | jsonrpc: "2.0" 56 | id: "tool-description-quality" 57 | result: 58 | tools: "match:arrayContains:name:search_sfcc_classes" 59 | stderr: "toBeEmpty" 60 | 61 | - it: "should have proper inputSchema structure for search_sfcc_classes" 62 | request: 63 | jsonrpc: "2.0" 64 | id: "tool-schema-structure" 65 | method: "tools/list" 66 | params: {} 67 | expect: 68 | response: 69 | jsonrpc: "2.0" 70 | id: "tool-schema-structure" 71 | result: 72 | tools: 73 | match:arrayElements: 74 | match:partial: 75 | name: "match:type:string" 76 | inputSchema: 77 | type: "object" 78 | properties: "match:type:object" 79 | 80 | stderr: "toBeEmpty" 81 | 82 | # ================================================================================== 83 | # SUCCESSFUL EXECUTION TESTS - COMMON SEARCH TERMS 84 | # ================================================================================== 85 | 86 | - it: "should execute with catalog search term" 87 | request: 88 | jsonrpc: "2.0" 89 | id: "exec-catalog-search" 90 | method: "tools/call" 91 | params: 92 | name: "search_sfcc_classes" 93 | arguments: 94 | query: "catalog" 95 | expect: 96 | response: 97 | jsonrpc: "2.0" 98 | id: "exec-catalog-search" 99 | result: 100 | content: 101 | - type: "text" 102 | text: "match:contains:catalog" 103 | isError: false 104 | stderr: "toBeEmpty" 105 | 106 | - it: "should return JSON array structure for product search" 107 | request: 108 | jsonrpc: "2.0" 109 | id: "exec-product-json" 110 | method: "tools/call" 111 | params: 112 | name: "search_sfcc_classes" 113 | arguments: 114 | query: "product" 115 | expect: 116 | response: 117 | jsonrpc: "2.0" 118 | id: "exec-product-json" 119 | result: 120 | content: 121 | - type: "text" 122 | text: "match:regex:\\[[\\s\\S]*\\]" # Valid JSON array structure 123 | isError: false 124 | stderr: "toBeEmpty" 125 | 126 | - it: "should find customer-related classes" 127 | request: 128 | jsonrpc: "2.0" 129 | id: "exec-customer-search" 130 | method: "tools/call" 131 | params: 132 | name: "search_sfcc_classes" 133 | arguments: 134 | query: "customer" 135 | expect: 136 | response: 137 | jsonrpc: "2.0" 138 | id: "exec-customer-search" 139 | result: 140 | content: 141 | - type: "text" 142 | text: "match:contains:customer" 143 | isError: false 144 | stderr: "toBeEmpty" 145 | 146 | - it: "should find order-related classes" 147 | request: 148 | jsonrpc: "2.0" 149 | id: "exec-order-search" 150 | method: "tools/call" 151 | params: 152 | name: "search_sfcc_classes" 153 | arguments: 154 | query: "order" 155 | expect: 156 | response: 157 | jsonrpc: "2.0" 158 | id: "exec-order-search" 159 | result: 160 | content: 161 | - type: "text" 162 | text: "match:contains:order" 163 | isError: false 164 | stderr: "toBeEmpty" 165 | 166 | - it: "should find system-related classes" 167 | request: 168 | jsonrpc: "2.0" 169 | id: "exec-system-search" 170 | method: "tools/call" 171 | params: 172 | name: "search_sfcc_classes" 173 | arguments: 174 | query: "system" 175 | expect: 176 | response: 177 | jsonrpc: "2.0" 178 | id: "exec-system-search" 179 | result: 180 | content: 181 | - type: "text" 182 | text: "match:contains:system" 183 | isError: false 184 | stderr: "toBeEmpty" 185 | 186 | - it: "should find web-related classes" 187 | request: 188 | jsonrpc: "2.0" 189 | id: "exec-web-search" 190 | method: "tools/call" 191 | params: 192 | name: "search_sfcc_classes" 193 | arguments: 194 | query: "web" 195 | expect: 196 | response: 197 | jsonrpc: "2.0" 198 | id: "exec-web-search" 199 | result: 200 | content: 201 | - type: "text" 202 | text: "match:contains:web" 203 | isError: false 204 | stderr: "toBeEmpty" 205 | 206 | - it: "should find util-related classes" 207 | request: 208 | jsonrpc: "2.0" 209 | id: "exec-util-search" 210 | method: "tools/call" 211 | params: 212 | name: "search_sfcc_classes" 213 | arguments: 214 | query: "util" 215 | expect: 216 | response: 217 | jsonrpc: "2.0" 218 | id: "exec-util-search" 219 | result: 220 | content: 221 | - type: "text" 222 | text: "match:contains:util" 223 | isError: false 224 | stderr: "toBeEmpty" 225 | 226 | # ================================================================================== 227 | # SEARCH RESULT STRUCTURE VALIDATION 228 | # ================================================================================== 229 | 230 | - it: "should return JSON array in results" 231 | request: 232 | jsonrpc: "2.0" 233 | id: "validate-array-structure" 234 | method: "tools/call" 235 | params: 236 | name: "search_sfcc_classes" 237 | arguments: 238 | query: "catalog" 239 | expect: 240 | response: 241 | jsonrpc: "2.0" 242 | id: "validate-array-structure" 243 | result: 244 | content: 245 | - type: "text" 246 | text: "match:regex:\\[[\\s\\S]*\\]" 247 | isError: false 248 | stderr: "toBeEmpty" 249 | 250 | - it: "should return class names in array format" 251 | request: 252 | jsonrpc: "2.0" 253 | id: "validate-class-names" 254 | method: "tools/call" 255 | params: 256 | name: "search_sfcc_classes" 257 | arguments: 258 | query: "catalog" 259 | expect: 260 | response: 261 | jsonrpc: "2.0" 262 | id: "validate-class-names" 263 | result: 264 | content: 265 | - type: "text" 266 | text: "match:contains:dw.catalog.Product" 267 | isError: false 268 | stderr: "toBeEmpty" 269 | 270 | - it: "should include multiple matching classes" 271 | request: 272 | jsonrpc: "2.0" 273 | id: "validate-multiple-classes" 274 | method: "tools/call" 275 | params: 276 | name: "search_sfcc_classes" 277 | arguments: 278 | query: "catalog" 279 | expect: 280 | response: 281 | jsonrpc: "2.0" 282 | id: "validate-multiple-classes" 283 | result: 284 | content: 285 | - type: "text" 286 | text: "match:contains:dw.catalog.Catalog" 287 | isError: false 288 | stderr: "toBeEmpty" 289 | 290 | - it: "should format class names with quotes" 291 | request: 292 | jsonrpc: "2.0" 293 | id: "validate-quoted-names" 294 | method: "tools/call" 295 | params: 296 | name: "search_sfcc_classes" 297 | arguments: 298 | query: "product" 299 | expect: 300 | response: 301 | jsonrpc: "2.0" 302 | id: "validate-quoted-names" 303 | result: 304 | content: 305 | - type: "text" 306 | text: "match:regex:\"dw\\.catalog\\.Product\"" 307 | isError: false 308 | stderr: "toBeEmpty" 309 | 310 | # ================================================================================== 311 | # CASE SENSITIVITY AND SEARCH VARIATIONS 312 | # ================================================================================== 313 | 314 | - it: "should handle uppercase search terms" 315 | request: 316 | jsonrpc: "2.0" 317 | id: "search-uppercase" 318 | method: "tools/call" 319 | params: 320 | name: "search_sfcc_classes" 321 | arguments: 322 | query: "CATALOG" 323 | expect: 324 | response: 325 | jsonrpc: "2.0" 326 | id: "search-uppercase" 327 | result: 328 | content: 329 | - type: "text" 330 | text: "match:regex:\\[[\\s\\S]*\\]" 331 | isError: false 332 | stderr: "toBeEmpty" 333 | 334 | - it: "should handle mixed case search terms" 335 | request: 336 | jsonrpc: "2.0" 337 | id: "search-mixedcase" 338 | method: "tools/call" 339 | params: 340 | name: "search_sfcc_classes" 341 | arguments: 342 | query: "Product" 343 | expect: 344 | response: 345 | jsonrpc: "2.0" 346 | id: "search-mixedcase" 347 | result: 348 | content: 349 | - type: "text" 350 | text: "match:regex:\\[[\\s\\S]*\\]" 351 | isError: false 352 | stderr: "toBeEmpty" 353 | 354 | - it: "should handle partial class names" 355 | request: 356 | jsonrpc: "2.0" 357 | id: "search-partial" 358 | method: "tools/call" 359 | params: 360 | name: "search_sfcc_classes" 361 | arguments: 362 | query: "cat" # Should find catalog classes 363 | expect: 364 | response: 365 | jsonrpc: "2.0" 366 | id: "search-partial" 367 | result: 368 | content: 369 | - type: "text" 370 | text: "match:regex:\\[[\\s\\S]*\\]" 371 | isError: false 372 | stderr: "toBeEmpty" 373 | 374 | - it: "should handle single character searches" 375 | request: 376 | jsonrpc: "2.0" 377 | id: "search-single-char" 378 | method: "tools/call" 379 | params: 380 | name: "search_sfcc_classes" 381 | arguments: 382 | query: "c" 383 | expect: 384 | response: 385 | jsonrpc: "2.0" 386 | id: "search-single-char" 387 | result: 388 | content: 389 | - type: "text" 390 | text: "match:regex:\\[[\\s\\S]*\\]" 391 | isError: false 392 | stderr: "toBeEmpty" 393 | 394 | # ================================================================================== 395 | # SPECIFIC SFCC DOMAIN SEARCHES 396 | # ================================================================================== 397 | 398 | - it: "should find dw.catalog namespace classes" 399 | request: 400 | jsonrpc: "2.0" 401 | id: "domain-catalog" 402 | method: "tools/call" 403 | params: 404 | name: "search_sfcc_classes" 405 | arguments: 406 | query: "catalog" 407 | expect: 408 | response: 409 | jsonrpc: "2.0" 410 | id: "domain-catalog" 411 | result: 412 | content: 413 | - type: "text" 414 | text: "match:contains:dw.catalog" 415 | isError: false 416 | stderr: "toBeEmpty" 417 | 418 | - it: "should find dw.customer namespace classes" 419 | request: 420 | jsonrpc: "2.0" 421 | id: "domain-customer" 422 | method: "tools/call" 423 | params: 424 | name: "search_sfcc_classes" 425 | arguments: 426 | query: "customer" 427 | expect: 428 | response: 429 | jsonrpc: "2.0" 430 | id: "domain-customer" 431 | result: 432 | content: 433 | - type: "text" 434 | text: "match:contains:dw.customer" 435 | isError: false 436 | stderr: "toBeEmpty" 437 | 438 | - it: "should find dw.order namespace classes" 439 | request: 440 | jsonrpc: "2.0" 441 | id: "domain-order" 442 | method: "tools/call" 443 | params: 444 | name: "search_sfcc_classes" 445 | arguments: 446 | query: "order" 447 | expect: 448 | response: 449 | jsonrpc: "2.0" 450 | id: "domain-order" 451 | result: 452 | content: 453 | - type: "text" 454 | text: "match:contains:dw.order" 455 | isError: false 456 | stderr: "toBeEmpty" 457 | 458 | - it: "should find dw.system namespace classes" 459 | request: 460 | jsonrpc: "2.0" 461 | id: "domain-system" 462 | method: "tools/call" 463 | params: 464 | name: "search_sfcc_classes" 465 | arguments: 466 | query: "system" 467 | expect: 468 | response: 469 | jsonrpc: "2.0" 470 | id: "domain-system" 471 | result: 472 | content: 473 | - type: "text" 474 | text: "match:contains:dw.system" 475 | isError: false 476 | stderr: "toBeEmpty" 477 | 478 | - it: "should find dw.web namespace classes" 479 | request: 480 | jsonrpc: "2.0" 481 | id: "domain-web" 482 | method: "tools/call" 483 | params: 484 | name: "search_sfcc_classes" 485 | arguments: 486 | query: "web" 487 | expect: 488 | response: 489 | jsonrpc: "2.0" 490 | id: "domain-web" 491 | result: 492 | content: 493 | - type: "text" 494 | text: "match:contains:dw.web" 495 | isError: false 496 | stderr: "toBeEmpty" 497 | 498 | - it: "should find dw.util namespace classes" 499 | request: 500 | jsonrpc: "2.0" 501 | id: "domain-util" 502 | method: "tools/call" 503 | params: 504 | name: "search_sfcc_classes" 505 | arguments: 506 | query: "util" 507 | expect: 508 | response: 509 | jsonrpc: "2.0" 510 | id: "domain-util" 511 | result: 512 | content: 513 | - type: "text" 514 | text: "match:contains:dw.util" 515 | isError: false 516 | stderr: "toBeEmpty" 517 | 518 | # ================================================================================== 519 | # FUNCTIONAL SEARCH TESTS 520 | # ================================================================================== 521 | 522 | - it: "should find inventory-related classes" 523 | request: 524 | jsonrpc: "2.0" 525 | id: "func-inventory" 526 | method: "tools/call" 527 | params: 528 | name: "search_sfcc_classes" 529 | arguments: 530 | query: "inventory" 531 | expect: 532 | response: 533 | jsonrpc: "2.0" 534 | id: "func-inventory" 535 | result: 536 | content: 537 | - type: "text" 538 | text: "match:contains:ProductInventoryList" 539 | isError: false 540 | stderr: "toBeEmpty" 541 | 542 | - it: "should find price-related classes" 543 | request: 544 | jsonrpc: "2.0" 545 | id: "func-price" 546 | method: "tools/call" 547 | params: 548 | name: "search_sfcc_classes" 549 | arguments: 550 | query: "price" 551 | expect: 552 | response: 553 | jsonrpc: "2.0" 554 | id: "func-price" 555 | result: 556 | content: 557 | - type: "text" 558 | text: "match:contains:PriceBook" 559 | isError: false 560 | stderr: "toBeEmpty" 561 | 562 | - it: "should find basket-related classes" 563 | request: 564 | jsonrpc: "2.0" 565 | id: "func-basket" 566 | method: "tools/call" 567 | params: 568 | name: "search_sfcc_classes" 569 | arguments: 570 | query: "basket" 571 | expect: 572 | response: 573 | jsonrpc: "2.0" 574 | id: "func-basket" 575 | result: 576 | content: 577 | - type: "text" 578 | text: "match:contains:Basket" 579 | isError: false 580 | stderr: "toBeEmpty" 581 | 582 | - it: "should find payment-related classes" 583 | request: 584 | jsonrpc: "2.0" 585 | id: "func-payment" 586 | method: "tools/call" 587 | params: 588 | name: "search_sfcc_classes" 589 | arguments: 590 | query: "payment" 591 | expect: 592 | response: 593 | jsonrpc: "2.0" 594 | id: "func-payment" 595 | result: 596 | content: 597 | - type: "text" 598 | text: "match:contains:Payment" 599 | isError: false 600 | stderr: "toBeEmpty" 601 | 602 | - it: "should find shipping-related classes" 603 | request: 604 | jsonrpc: "2.0" 605 | id: "func-shipping" 606 | method: "tools/call" 607 | params: 608 | name: "search_sfcc_classes" 609 | arguments: 610 | query: "shipping" 611 | expect: 612 | response: 613 | jsonrpc: "2.0" 614 | id: "func-shipping" 615 | result: 616 | content: 617 | - type: "text" 618 | text: "match:contains:Shipping" 619 | isError: false 620 | stderr: "toBeEmpty" 621 | 622 | # ================================================================================== 623 | # ERROR HANDLING TESTS 624 | # ================================================================================== 625 | 626 | - it: "should handle empty query gracefully" 627 | request: 628 | jsonrpc: "2.0" 629 | id: "error-empty-query" 630 | method: "tools/call" 631 | params: 632 | name: "search_sfcc_classes" 633 | arguments: 634 | query: "" 635 | expect: 636 | response: 637 | jsonrpc: "2.0" 638 | id: "error-empty-query" 639 | result: 640 | content: 641 | - type: "text" 642 | text: "match:contains:Error" 643 | isError: true 644 | stderr: "toBeEmpty" 645 | 646 | - it: "should handle missing query parameter" 647 | request: 648 | jsonrpc: "2.0" 649 | id: "error-missing-query" 650 | method: "tools/call" 651 | params: 652 | name: "search_sfcc_classes" 653 | arguments: {} 654 | expect: 655 | response: 656 | jsonrpc: "2.0" 657 | id: "error-missing-query" 658 | result: 659 | content: 660 | - type: "text" 661 | text: "match:contains:query" 662 | isError: true 663 | stderr: "toBeEmpty" 664 | 665 | - it: "should handle non-existent terms gracefully" 666 | request: 667 | jsonrpc: "2.0" 668 | id: "search-nonexistent" 669 | method: "tools/call" 670 | params: 671 | name: "search_sfcc_classes" 672 | arguments: 673 | query: "zzznothingfound" 674 | expect: 675 | response: 676 | jsonrpc: "2.0" 677 | id: "search-nonexistent" 678 | result: 679 | content: 680 | - type: "text" 681 | text: "match:regex:^\\[\\s*\\]$" 682 | isError: false 683 | stderr: "toBeEmpty" 684 | 685 | - it: "should handle special characters in query" 686 | request: 687 | jsonrpc: "2.0" 688 | id: "search-special-chars" 689 | method: "tools/call" 690 | params: 691 | name: "search_sfcc_classes" 692 | arguments: 693 | query: "!@#$%" 694 | expect: 695 | response: 696 | jsonrpc: "2.0" 697 | id: "search-special-chars" 698 | result: 699 | content: 700 | - type: "text" 701 | text: "match:regex:\\[[\\s\\S]*\\]" 702 | isError: false 703 | stderr: "toBeEmpty" 704 | 705 | - it: "should handle very long query strings" 706 | request: 707 | jsonrpc: "2.0" 708 | id: "search-long-query" 709 | method: "tools/call" 710 | params: 711 | name: "search_sfcc_classes" 712 | arguments: 713 | query: "verylongquerystringthatdoesnotmatchanythingbutshouldbetreatedgracefully" 714 | expect: 715 | response: 716 | jsonrpc: "2.0" 717 | id: "search-long-query" 718 | result: 719 | content: 720 | - type: "text" 721 | text: "match:regex:^\\[\\s*\\]$" 722 | isError: false 723 | stderr: "toBeEmpty" 724 | 725 | # ================================================================================== 726 | # RESPONSE FORMAT VALIDATION 727 | # ================================================================================== 728 | 729 | - it: "should return consistent MCP content structure" 730 | request: 731 | jsonrpc: "2.0" 732 | id: "format-content-structure" 733 | method: "tools/call" 734 | params: 735 | name: "search_sfcc_classes" 736 | arguments: 737 | query: "catalog" 738 | expect: 739 | response: 740 | jsonrpc: "2.0" 741 | id: "format-content-structure" 742 | result: 743 | content: 744 | match:arrayElements: 745 | match:partial: 746 | type: "text" 747 | text: "match:type:string" 748 | isError: false 749 | stderr: "toBeEmpty" 750 | 751 | - it: "should return single content item for successful calls" 752 | request: 753 | jsonrpc: "2.0" 754 | id: "format-single-content" 755 | method: "tools/call" 756 | params: 757 | name: "search_sfcc_classes" 758 | arguments: 759 | query: "product" 760 | expect: 761 | response: 762 | jsonrpc: "2.0" 763 | id: "format-single-content" 764 | result: 765 | content: "match:arrayLength:1" 766 | isError: false 767 | stderr: "toBeEmpty" 768 | 769 | - it: "should not set isError flag for successful responses" 770 | request: 771 | jsonrpc: "2.0" 772 | id: "format-no-error-flag" 773 | method: "tools/call" 774 | params: 775 | name: "search_sfcc_classes" 776 | arguments: 777 | query: "customer" 778 | expect: 779 | response: 780 | jsonrpc: "2.0" 781 | id: "format-no-error-flag" 782 | result: 783 | content: "match:type:array" 784 | isError: false 785 | stderr: "toBeEmpty" 786 | 787 | # ================================================================================== 788 | # EDGE CASES AND SEARCH BEHAVIOR 789 | # ================================================================================== 790 | 791 | - it: "should handle numeric query terms" 792 | request: 793 | jsonrpc: "2.0" 794 | id: "edge-numeric-query" 795 | method: "tools/call" 796 | params: 797 | name: "search_sfcc_classes" 798 | arguments: 799 | query: "123" 800 | expect: 801 | response: 802 | jsonrpc: "2.0" 803 | id: "edge-numeric-query" 804 | result: 805 | content: 806 | - type: "text" 807 | text: "match:regex:\\[[\\s\\S]*\\]" 808 | isError: false 809 | stderr: "toBeEmpty" 810 | 811 | - it: "should handle whitespace in query" 812 | request: 813 | jsonrpc: "2.0" 814 | id: "edge-whitespace" 815 | method: "tools/call" 816 | params: 817 | name: "search_sfcc_classes" 818 | arguments: 819 | query: " catalog " 820 | expect: 821 | response: 822 | jsonrpc: "2.0" 823 | id: "edge-whitespace" 824 | result: 825 | content: 826 | - type: "text" 827 | text: "match:regex:\\[[\\s\\S]*\\]" 828 | isError: false 829 | stderr: "toBeEmpty" 830 | 831 | - it: "should handle common abbreviations" 832 | request: 833 | jsonrpc: "2.0" 834 | id: "edge-abbreviations" 835 | method: "tools/call" 836 | params: 837 | name: "search_sfcc_classes" 838 | arguments: 839 | query: "mgr" # Should find manager classes 840 | expect: 841 | response: 842 | jsonrpc: "2.0" 843 | id: "edge-abbreviations" 844 | result: 845 | content: 846 | - type: "text" 847 | text: "match:regex:\\[[\\s\\S]*\\]" 848 | isError: false 849 | stderr: "toBeEmpty" 850 | 851 | - it: "should handle dots in search terms" 852 | request: 853 | jsonrpc: "2.0" 854 | id: "edge-dots" 855 | method: "tools/call" 856 | params: 857 | name: "search_sfcc_classes" 858 | arguments: 859 | query: "dw.catalog" 860 | expect: 861 | response: 862 | jsonrpc: "2.0" 863 | id: "edge-dots" 864 | result: 865 | content: 866 | - type: "text" 867 | text: "match:regex:\\[[\\s\\S]*\\]" 868 | isError: false 869 | stderr: "toBeEmpty" 870 | 871 | # ================================================================================== 872 | # PERFORMANCE AND CONSISTENCY VALIDATION 873 | # ================================================================================== 874 | 875 | - it: "should respond consistently for repeated searches" 876 | request: 877 | jsonrpc: "2.0" 878 | id: "perf-consistent-1" 879 | method: "tools/call" 880 | params: 881 | name: "search_sfcc_classes" 882 | arguments: 883 | query: "catalog" 884 | expect: 885 | response: 886 | jsonrpc: "2.0" 887 | id: "perf-consistent-1" 888 | result: 889 | content: 890 | - type: "text" 891 | text: "match:regex:\\[[\\s\\S]*\\]" 892 | isError: false 893 | stderr: "toBeEmpty" 894 | 895 | - it: "should respond consistently for repeated searches (second time)" 896 | request: 897 | jsonrpc: "2.0" 898 | id: "perf-consistent-2" 899 | method: "tools/call" 900 | params: 901 | name: "search_sfcc_classes" 902 | arguments: 903 | query: "catalog" 904 | expect: 905 | response: 906 | jsonrpc: "2.0" 907 | id: "perf-consistent-2" 908 | result: 909 | content: 910 | - type: "text" 911 | text: "match:regex:\\[[\\s\\S]*\\]" 912 | isError: false 913 | stderr: "toBeEmpty" 914 | 915 | # ================================================================================== 916 | # PERFORMANCE TIMING TESTS 917 | # ================================================================================== 918 | 919 | - it: "should return search results within acceptable time" 920 | request: 921 | jsonrpc: "2.0" 922 | id: "perf-basic-timing" 923 | method: "tools/call" 924 | params: 925 | name: "search_sfcc_classes" 926 | arguments: 927 | query: "catalog" 928 | expect: 929 | response: 930 | jsonrpc: "2.0" 931 | id: "perf-basic-timing" 932 | result: 933 | content: 934 | - type: "text" 935 | text: "match:regex:\\[[\\s\\S]*\\]" 936 | isError: false 937 | performance: 938 | maxResponseTime: "200ms" # Search should be fast 939 | stderr: "toBeEmpty" 940 | 941 | - it: "should handle complex searches efficiently" 942 | request: 943 | jsonrpc: "2.0" 944 | id: "perf-complex-search" 945 | method: "tools/call" 946 | params: 947 | name: "search_sfcc_classes" 948 | arguments: 949 | query: "product" 950 | expect: 951 | response: 952 | jsonrpc: "2.0" 953 | id: "perf-complex-search" 954 | result: 955 | content: 956 | - type: "text" 957 | text: "match:regex:\\[[\\s\\S]*\\]" 958 | isError: false 959 | performance: 960 | maxResponseTime: "100ms" # Even complex searches should be under 100ms 961 | stderr: "toBeEmpty" 962 | 963 | - it: "should handle partial searches quickly" 964 | request: 965 | jsonrpc: "2.0" 966 | id: "perf-partial-search" 967 | method: "tools/call" 968 | params: 969 | name: "search_sfcc_classes" 970 | arguments: 971 | query: "cat" 972 | expect: 973 | response: 974 | jsonrpc: "2.0" 975 | id: "perf-partial-search" 976 | result: 977 | content: 978 | - type: "text" 979 | text: "match:regex:\\[[\\s\\S]*\\]" 980 | isError: false 981 | performance: 982 | maxResponseTime: "100ms" # Partial searches should be fast 983 | stderr: "toBeEmpty" 984 | 985 | - it: "should handle no-result searches efficiently" 986 | request: 987 | jsonrpc: "2.0" 988 | id: "perf-no-results" 989 | method: "tools/call" 990 | params: 991 | name: "search_sfcc_classes" 992 | arguments: 993 | query: "zzznothingfound" 994 | expect: 995 | response: 996 | jsonrpc: "2.0" 997 | id: "perf-no-results" 998 | result: 999 | content: 1000 | - type: "text" 1001 | text: "match:regex:^\\[\\s*\\]$" 1002 | isError: false 1003 | performance: 1004 | maxResponseTime: "150ms" # No results should be very fast 1005 | stderr: "toBeEmpty" 1006 | 1007 | - it: "should handle error cases quickly" 1008 | request: 1009 | jsonrpc: "2.0" 1010 | id: "perf-error-timing" 1011 | method: "tools/call" 1012 | params: 1013 | name: "search_sfcc_classes" 1014 | arguments: 1015 | query: "" 1016 | expect: 1017 | response: 1018 | jsonrpc: "2.0" 1019 | id: "perf-error-timing" 1020 | result: 1021 | content: 1022 | - type: "text" 1023 | text: "match:contains:Error" 1024 | isError: true 1025 | performance: 1026 | maxResponseTime: "150ms" # Error handling should be very fast 1027 | stderr: "toBeEmpty" 1028 | 1029 | - it: "should handle cached results quickly" 1030 | request: 1031 | jsonrpc: "2.0" 1032 | id: "perf-cached-search" 1033 | method: "tools/call" 1034 | params: 1035 | name: "search_sfcc_classes" 1036 | arguments: 1037 | query: "catalog" # Same as first test - should be cached 1038 | expect: 1039 | response: 1040 | jsonrpc: "2.0" 1041 | id: "perf-cached-search" 1042 | result: 1043 | content: 1044 | - type: "text" 1045 | text: "match:regex:\\[[\\s\\S]*\\]" 1046 | isError: false 1047 | performance: 1048 | maxResponseTime: "150ms" # Cached responses should be extremely fast 1049 | stderr: "toBeEmpty" 1050 | 1051 | - it: "should handle single character searches within timeout" 1052 | request: 1053 | jsonrpc: "2.0" 1054 | id: "perf-single-char-timing" 1055 | method: "tools/call" 1056 | params: 1057 | name: "search_sfcc_classes" 1058 | arguments: 1059 | query: "c" 1060 | expect: 1061 | response: 1062 | jsonrpc: "2.0" 1063 | id: "perf-single-char-timing" 1064 | result: 1065 | content: 1066 | - type: "text" 1067 | text: "match:regex:\\[[\\s\\S]*\\]" 1068 | isError: false 1069 | performance: 1070 | maxResponseTime: "100ms" # Single char searches might return many results 1071 | stderr: "toBeEmpty" 1072 | 1073 | - it: "should handle long queries efficiently" 1074 | request: 1075 | jsonrpc: "2.0" 1076 | id: "perf-long-query-timing" 1077 | method: "tools/call" 1078 | params: 1079 | name: "search_sfcc_classes" 1080 | arguments: 1081 | query: "verylongquerystringthatdoesnotmatchanythingbutshouldbetreatedgracefully" 1082 | expect: 1083 | response: 1084 | jsonrpc: "2.0" 1085 | id: "perf-long-query-timing" 1086 | result: 1087 | content: 1088 | - type: "text" 1089 | text: "match:regex:^\\[\\s*\\]$" 1090 | isError: false 1091 | performance: 1092 | maxResponseTime: "150ms" # Long queries with no results should be fast 1093 | stderr: "toBeEmpty" 1094 | 1095 | # ================================================================================== 1096 | # SEARCH QUALITY AND RELEVANCE TESTS 1097 | # ================================================================================== 1098 | 1099 | - it: "should prioritize exact matches for common terms" 1100 | request: 1101 | jsonrpc: "2.0" 1102 | id: "quality-exact-match" 1103 | method: "tools/call" 1104 | params: 1105 | name: "search_sfcc_classes" 1106 | arguments: 1107 | query: "Product" 1108 | expect: 1109 | response: 1110 | jsonrpc: "2.0" 1111 | id: "quality-exact-match" 1112 | result: 1113 | content: 1114 | - type: "text" 1115 | text: "match:contains:dw.catalog.Product" 1116 | isError: false 1117 | stderr: "toBeEmpty" 1118 | 1119 | - it: "should find classes by functionality" 1120 | request: 1121 | jsonrpc: "2.0" 1122 | id: "quality-functionality" 1123 | method: "tools/call" 1124 | params: 1125 | name: "search_sfcc_classes" 1126 | arguments: 1127 | query: "inventory" 1128 | expect: 1129 | response: 1130 | jsonrpc: "2.0" 1131 | id: "quality-functionality" 1132 | result: 1133 | content: 1134 | - type: "text" 1135 | text: "match:contains:ProductInventoryList" 1136 | isError: false 1137 | stderr: "toBeEmpty" 1138 | 1139 | - it: "should include relevant namespace classes" 1140 | request: 1141 | jsonrpc: "2.0" 1142 | id: "quality-namespace" 1143 | method: "tools/call" 1144 | params: 1145 | name: "search_sfcc_classes" 1146 | arguments: 1147 | query: "system" 1148 | expect: 1149 | response: 1150 | jsonrpc: "2.0" 1151 | id: "quality-namespace" 1152 | result: 1153 | content: 1154 | - type: "text" 1155 | text: "match:regex:dw\\.system\\." 1156 | isError: false 1157 | stderr: "toBeEmpty" 1158 | ```