This is page 42 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 -------------------------------------------------------------------------------- /tests/mcp/node/search-sfra-documentation.docs-only.programmatic.test.js: -------------------------------------------------------------------------------- ```javascript 1 | import { test, describe, before, after, beforeEach } from 'node:test'; 2 | import { strict as assert } from 'node:assert'; 3 | import { connect } from 'mcp-aegis'; 4 | 5 | describe('search_sfra_documentation Tool Programmatic Tests', () => { 6 | let client; 7 | 8 | before(async () => { 9 | client = await connect('./aegis.config.docs-only.json'); 10 | }); 11 | 12 | after(async () => { 13 | if (client?.connected) { 14 | await client.disconnect(); 15 | } 16 | }); 17 | 18 | beforeEach(() => { 19 | // CRITICAL: Clear all buffers to prevent leaking into next tests 20 | client.clearAllBuffers(); 21 | }); 22 | 23 | describe('Valid Search Queries', () => { 24 | test('should return structured search results for "render" query', async () => { 25 | const result = await client.callTool('search_sfra_documentation', { query: 'render' }); 26 | 27 | assert.equal(result.isError, false, 'Should not be an error'); 28 | assert.ok(result.content, 'Should have content'); 29 | assert.equal(result.content.length, 1, 'Should have one content item'); 30 | assert.equal(result.content[0].type, 'text', 'Content should be text type'); 31 | 32 | // Parse the JSON response 33 | const searchResults = JSON.parse(result.content[0].text); 34 | assert.ok(Array.isArray(searchResults), 'Results should be an array'); 35 | assert.ok(searchResults.length > 0, 'Should have search results for "render"'); 36 | 37 | // Validate structure of first result 38 | const firstResult = searchResults[0]; 39 | assert.ok(firstResult.document, 'Should have document field'); 40 | assert.ok(firstResult.title, 'Should have title field'); 41 | assert.ok(firstResult.category, 'Should have category field'); 42 | assert.ok(firstResult.type, 'Should have type field'); 43 | assert.ok(typeof firstResult.relevanceScore === 'number', 'Should have numeric relevance score'); 44 | assert.ok(Array.isArray(firstResult.matches), 'Should have matches array'); 45 | }); 46 | 47 | test('should return results with different document types', async () => { 48 | const result = await client.callTool('search_sfra_documentation', { query: 'server' }); 49 | 50 | assert.equal(result.isError, false, 'Should not be an error'); 51 | 52 | const searchResults = JSON.parse(result.content[0].text); 53 | assert.ok(searchResults.length > 0, 'Should have results for "server"'); 54 | 55 | // Check that results include various document types 56 | const documentTypes = searchResults.map(r => r.type); 57 | const uniqueTypes = [...new Set(documentTypes)]; 58 | assert.ok(uniqueTypes.length > 0, 'Should have at least one document type'); 59 | 60 | // Verify known SFRA types are present (class, module, model) 61 | const validTypes = ['class', 'module', 'model']; 62 | const hasValidType = searchResults.some(r => validTypes.includes(r.type)); 63 | assert.ok(hasValidType, 'Should include valid SFRA document types'); 64 | }); 65 | 66 | test('should include relevance scoring and matches', async () => { 67 | const result = await client.callTool('search_sfra_documentation', { query: 'response' }); 68 | 69 | assert.equal(result.isError, false, 'Should not be an error'); 70 | 71 | const searchResults = JSON.parse(result.content[0].text); 72 | assert.ok(searchResults.length > 0, 'Should have results for "response"'); 73 | 74 | // Validate relevance scoring 75 | for (const searchResult of searchResults) { 76 | assert.ok(typeof searchResult.relevanceScore === 'number', 'Each result should have numeric relevance score'); 77 | assert.ok(searchResult.relevanceScore >= 0, 'Relevance score should be non-negative'); 78 | 79 | // Validate matches structure 80 | assert.ok(Array.isArray(searchResult.matches), 'Should have matches array'); 81 | if (searchResult.matches.length > 0) { 82 | const firstMatch = searchResult.matches[0]; 83 | assert.ok(firstMatch.section, 'Match should have section field'); 84 | assert.ok(firstMatch.content, 'Match should have content field'); 85 | assert.ok(typeof firstMatch.lineNumber === 'number', 'Match should have numeric line number'); 86 | } 87 | } 88 | }); 89 | 90 | test('should return results ordered by relevance', async () => { 91 | const result = await client.callTool('search_sfra_documentation', { query: 'product' }); 92 | 93 | assert.equal(result.isError, false, 'Should not be an error'); 94 | 95 | const searchResults = JSON.parse(result.content[0].text); 96 | assert.ok(searchResults.length > 1, 'Should have multiple results to test ordering'); 97 | 98 | // Check that results are ordered by relevance score (descending) 99 | for (let i = 1; i < searchResults.length; i++) { 100 | assert.ok( 101 | searchResults[i - 1].relevanceScore >= searchResults[i].relevanceScore, 102 | `Results should be ordered by relevance: ${searchResults[i - 1].relevanceScore} >= ${searchResults[i].relevanceScore}` 103 | ); 104 | } 105 | }); 106 | 107 | test('should categorize documents appropriately', async () => { 108 | const result = await client.callTool('search_sfra_documentation', { query: 'model' }); 109 | 110 | assert.equal(result.isError, false, 'Should not be an error'); 111 | 112 | const searchResults = JSON.parse(result.content[0].text); 113 | assert.ok(searchResults.length > 0, 'Should have results for "model"'); 114 | 115 | // Verify categories are valid SFRA categories 116 | const validCategories = ['core', 'product', 'order', 'customer', 'pricing', 'store', 'other']; 117 | for (const searchResult of searchResults) { 118 | assert.ok( 119 | validCategories.includes(searchResult.category), 120 | `Category "${searchResult.category}" should be one of: ${validCategories.join(', ')}` 121 | ); 122 | } 123 | }); 124 | 125 | test('should handle special characters in search queries', async () => { 126 | const result = await client.callTool('search_sfra_documentation', { query: 'dw.util' }); 127 | 128 | assert.equal(result.isError, false, 'Should not be an error'); 129 | 130 | const searchResults = JSON.parse(result.content[0].text); 131 | // Results may be empty or contain matches - both are valid for this query 132 | assert.ok(Array.isArray(searchResults), 'Should return an array even for special character queries'); 133 | }); 134 | }); 135 | 136 | describe('Edge Cases and Error Handling', () => { 137 | test('should return empty array for queries with no matches', async () => { 138 | const result = await client.callTool('search_sfra_documentation', { query: 'zzznothingfound' }); 139 | 140 | assert.equal(result.isError, false, 'Should not be an error for no matches'); 141 | assert.equal(result.content[0].text, '[]', 'Should return empty JSON array'); 142 | }); 143 | 144 | test('should handle empty query with validation error', async () => { 145 | const result = await client.callTool('search_sfra_documentation', { query: '' }); 146 | 147 | assert.equal(result.isError, true, 'Should be an error for empty query'); 148 | assert.ok(result.content[0].text.includes('query must be a non-empty string'), 'Should have appropriate error message'); 149 | }); 150 | 151 | test('should handle missing query parameter', async () => { 152 | const result = await client.callTool('search_sfra_documentation', {}); 153 | 154 | assert.equal(result.isError, true, 'Should be an error for missing query'); 155 | assert.ok(result.content[0].text.includes('query must be a non-empty string'), 'Should indicate query is required'); 156 | }); 157 | 158 | test('should handle whitespace-only query as invalid', async () => { 159 | const result = await client.callTool('search_sfra_documentation', { query: ' ' }); 160 | 161 | assert.equal(result.isError, true, 'Should be an error for whitespace-only query'); 162 | assert.ok(result.content[0].text.includes('query must be a non-empty string'), 'Should have appropriate error message'); 163 | }); 164 | }); 165 | 166 | 167 | describe('Search Result Quality', () => { 168 | test('should return relevant results for core SFRA concepts', async () => { 169 | const coreTerms = ['server', 'request', 'response', 'render']; 170 | 171 | for (const term of coreTerms) { 172 | const result = await client.callTool('search_sfra_documentation', { query: term }); 173 | 174 | assert.equal(result.isError, false, `Should not be an error for term: ${term}`); 175 | 176 | const searchResults = JSON.parse(result.content[0].text); 177 | assert.ok(searchResults.length > 0, `Should have results for core term: ${term}`); 178 | 179 | // Verify that the search term appears in at least one match 180 | const hasTermInMatches = searchResults.some(sr => 181 | sr.matches.some(match => 182 | match.content.toLowerCase().includes(term.toLowerCase()) || 183 | match.section.toLowerCase().includes(term.toLowerCase()) 184 | ) 185 | ); 186 | assert.ok(hasTermInMatches, `Search results should contain relevant matches for term: ${term}`); 187 | } 188 | }); 189 | 190 | test('should provide useful context in match content', async () => { 191 | const result = await client.callTool('search_sfra_documentation', { query: 'template' }); 192 | 193 | assert.equal(result.isError, false, 'Should not be an error'); 194 | 195 | const searchResults = JSON.parse(result.content[0].text); 196 | assert.ok(searchResults.length > 0, 'Should have results for "template"'); 197 | 198 | // Check that matches provide useful context 199 | for (const searchResult of searchResults) { 200 | for (const match of searchResult.matches) { 201 | assert.ok(match.content.length > 10, 'Match content should provide substantial context'); 202 | assert.ok(match.section && match.section.length > 0, 'Match should have meaningful section information'); 203 | } 204 | } 205 | }); 206 | 207 | test('should return appropriate number of results', async () => { 208 | const result = await client.callTool('search_sfra_documentation', { query: 'product' }); 209 | 210 | assert.equal(result.isError, false, 'Should not be an error'); 211 | 212 | const searchResults = JSON.parse(result.content[0].text); 213 | 214 | // Should return a reasonable number of results (not too few, not too many) 215 | assert.ok(searchResults.length >= 1, 'Should have at least 1 result for broad term'); 216 | assert.ok(searchResults.length <= 50, 'Should not return excessive number of results'); 217 | }); 218 | }); 219 | 220 | describe('Dynamic Validation', () => { 221 | test('should validate all required fields are present in search results', async () => { 222 | const result = await client.callTool('search_sfra_documentation', { query: 'price' }); 223 | 224 | assert.equal(result.isError, false, 'Should not be an error'); 225 | 226 | const searchResults = JSON.parse(result.content[0].text); 227 | 228 | const requiredFields = ['document', 'title', 'category', 'type', 'relevanceScore', 'matches']; 229 | const requiredMatchFields = ['section', 'content', 'lineNumber']; 230 | 231 | for (const searchResult of searchResults) { 232 | // Validate main result structure 233 | for (const field of requiredFields) { 234 | assert.ok(field in searchResult, `Search result should have ${field} field`); 235 | } 236 | 237 | // Validate matches structure 238 | for (const match of searchResult.matches) { 239 | for (const field of requiredMatchFields) { 240 | assert.ok(field in match, `Match should have ${field} field`); 241 | } 242 | } 243 | } 244 | }); 245 | }); 246 | 247 | describe('Advanced Search Scenarios', () => { 248 | test('should handle complex multi-term searches effectively', async () => { 249 | const complexQueries = [ 250 | 'render template isml', 251 | 'request response middleware', 252 | 'product cart pricing', 253 | 'server routing controller' 254 | ]; 255 | 256 | for (const query of complexQueries) { 257 | const result = await client.callTool('search_sfra_documentation', { query }); 258 | 259 | assert.equal(result.isError, false, `Should handle complex query: "${query}"`); 260 | 261 | const searchResults = JSON.parse(result.content[0].text); 262 | // Complex queries should return results (may be empty but shouldn't error) 263 | assert.ok(Array.isArray(searchResults), `Should return array for query: "${query}"`); 264 | } 265 | }); 266 | 267 | test('should find specific SFRA document types by search', async () => { 268 | const documentTypeQueries = [ 269 | { query: 'server', expectedType: 'class' }, 270 | { query: 'render', expectedType: 'module' }, 271 | { query: 'product-full', expectedType: 'model' }, 272 | { query: 'response', expectedType: 'class' } 273 | ]; 274 | 275 | for (const { query, expectedType } of documentTypeQueries) { 276 | const result = await client.callTool('search_sfra_documentation', { query }); 277 | 278 | assert.equal(result.isError, false, `Should not error for query: "${query}"`); 279 | 280 | const searchResults = JSON.parse(result.content[0].text); 281 | if (searchResults.length > 0) { 282 | const hasExpectedType = searchResults.some(r => r.type === expectedType); 283 | assert.ok(hasExpectedType, `Should find ${expectedType} documents for query: "${query}"`); 284 | } 285 | } 286 | }); 287 | 288 | test('should maintain search result consistency across calls', async () => { 289 | const query = 'cart'; 290 | const results = []; 291 | 292 | // Perform same search multiple times 293 | for (let i = 0; i < 3; i++) { 294 | const result = await client.callTool('search_sfra_documentation', { query }); 295 | assert.equal(result.isError, false, `Call ${i + 1} should not error`); 296 | results.push(JSON.parse(result.content[0].text)); 297 | } 298 | 299 | // All results should have same length 300 | const lengths = results.map(r => r.length); 301 | const allSameLength = lengths.every(len => len === lengths[0]); 302 | assert.ok(allSameLength, 'All search calls should return same number of results'); 303 | 304 | // First result should have same document in all calls 305 | if (results[0].length > 0) { 306 | const firstDocuments = results.map(r => r[0].document); 307 | const allSameFirstDoc = firstDocuments.every(doc => doc === firstDocuments[0]); 308 | assert.ok(allSameFirstDoc, 'First result should be consistent across calls'); 309 | } 310 | }); 311 | 312 | test('should handle category-specific searches', async () => { 313 | const categoryQueries = [ 314 | { query: 'server request response', expectedCategory: 'core' }, 315 | { query: 'product bundle variant', expectedCategory: 'product' }, 316 | { query: 'cart checkout billing', expectedCategory: 'order' }, 317 | { query: 'customer account profile', expectedCategory: 'customer' } 318 | ]; 319 | 320 | for (const { query, expectedCategory } of categoryQueries) { 321 | const result = await client.callTool('search_sfra_documentation', { query }); 322 | 323 | assert.equal(result.isError, false, `Should not error for category query: "${query}"`); 324 | 325 | const searchResults = JSON.parse(result.content[0].text); 326 | if (searchResults.length > 0) { 327 | const hasExpectedCategory = searchResults.some(r => r.category === expectedCategory); 328 | assert.ok(hasExpectedCategory, `Should find ${expectedCategory} documents for query: "${query}"`); 329 | } 330 | } 331 | }); 332 | 333 | test('should handle case-insensitive searches correctly', async () => { 334 | const casePairs = [ 335 | { lower: 'product', upper: 'PRODUCT' }, 336 | { lower: 'render', upper: 'RENDER' }, 337 | { lower: 'server', upper: 'SERVER' } 338 | ]; 339 | 340 | for (const { lower, upper } of casePairs) { 341 | const lowerResult = await client.callTool('search_sfra_documentation', { query: lower }); 342 | const upperResult = await client.callTool('search_sfra_documentation', { query: upper }); 343 | 344 | assert.equal(lowerResult.isError, false, `Lowercase "${lower}" should not error`); 345 | assert.equal(upperResult.isError, false, `Uppercase "${upper}" should not error`); 346 | 347 | const lowerResults = JSON.parse(lowerResult.content[0].text); 348 | const upperResults = JSON.parse(upperResult.content[0].text); 349 | 350 | // Results should be identical for case variations 351 | assert.equal(lowerResults.length, upperResults.length, 352 | `Case insensitive search should return same number of results for "${lower}" vs "${upper}"`); 353 | } 354 | }); 355 | 356 | test('should provide meaningful search result context', async () => { 357 | const result = await client.callTool('search_sfra_documentation', { query: 'template' }); 358 | 359 | assert.equal(result.isError, false, 'Should not be an error'); 360 | 361 | const searchResults = JSON.parse(result.content[0].text); 362 | assert.ok(searchResults.length > 0, 'Should have results for "template"'); 363 | 364 | for (const searchResult of searchResults) { 365 | // Validate document metadata quality 366 | assert.ok(searchResult.title.length > 0, 'Title should not be empty'); 367 | assert.ok(searchResult.document.length > 0, 'Document name should not be empty'); 368 | 369 | // Validate matches provide good context 370 | for (const match of searchResult.matches) { 371 | assert.ok(match.content.length > 20, 'Match content should be substantial'); 372 | assert.ok(match.section.length > 0, 'Match section should be specified'); 373 | assert.ok(match.lineNumber > 0, 'Line number should be positive'); 374 | 375 | // Content should contain search term or related context 376 | const hasRelevantContent = match.content.toLowerCase().includes('template') || 377 | match.content.toLowerCase().includes('render') || 378 | match.content.toLowerCase().includes('view'); 379 | assert.ok(hasRelevantContent, 'Match content should be relevant to search term'); 380 | } 381 | } 382 | }); 383 | }); 384 | 385 | describe('Boundary Condition Testing', () => { 386 | test('should handle very short queries', async () => { 387 | const shortQueries = ['a', 'b', 'c', '1', '2']; 388 | 389 | for (const query of shortQueries) { 390 | const result = await client.callTool('search_sfra_documentation', { query }); 391 | 392 | assert.equal(result.isError, false, `Short query "${query}" should not error`); 393 | 394 | const searchResults = JSON.parse(result.content[0].text); 395 | assert.ok(Array.isArray(searchResults), `Should return array for short query: "${query}"`); 396 | // Short queries may return many or few results - both are valid 397 | } 398 | }); 399 | 400 | test('should handle queries with special characters', async () => { 401 | const specialQueries = [ 402 | 'dw.util.Collection', 403 | 'product.price', 404 | 'server-response', 405 | 'cart_model', 406 | 'request/response', 407 | 'template.isml' 408 | ]; 409 | 410 | for (const query of specialQueries) { 411 | const result = await client.callTool('search_sfra_documentation', { query }); 412 | 413 | assert.equal(result.isError, false, `Special character query "${query}" should not error`); 414 | 415 | const searchResults = JSON.parse(result.content[0].text); 416 | assert.ok(Array.isArray(searchResults), `Should return array for special query: "${query}"`); 417 | } 418 | }); 419 | 420 | test('should handle extremely long queries gracefully', async () => { 421 | const longQuery = 'template rendering isml view data processing controller middleware response request server router navigation menu product catalog pricing cart checkout billing shipping customer account profile management'.repeat(3); 422 | 423 | const result = await client.callTool('search_sfra_documentation', { query: longQuery }); 424 | 425 | assert.equal(result.isError, false, 'Very long query should not error'); 426 | 427 | const searchResults = JSON.parse(result.content[0].text); 428 | assert.ok(Array.isArray(searchResults), 'Should return array for very long query'); 429 | }); 430 | 431 | test('should handle numeric and mixed alphanumeric queries', async () => { 432 | const numericQueries = ['200', '404', '500', 'v1.2', 'api2', 'html5']; 433 | 434 | for (const query of numericQueries) { 435 | const result = await client.callTool('search_sfra_documentation', { query }); 436 | 437 | assert.equal(result.isError, false, `Numeric query "${query}" should not error`); 438 | 439 | const searchResults = JSON.parse(result.content[0].text); 440 | assert.ok(Array.isArray(searchResults), `Should return array for numeric query: "${query}"`); 441 | } 442 | }); 443 | }); 444 | 445 | describe('Search Quality and Relevance', () => { 446 | test('should prioritize exact matches in relevance scoring', async () => { 447 | const result = await client.callTool('search_sfra_documentation', { query: 'render' }); 448 | 449 | assert.equal(result.isError, false, 'Should not be an error'); 450 | 451 | const searchResults = JSON.parse(result.content[0].text); 452 | assert.ok(searchResults.length > 0, 'Should have results for "render"'); 453 | 454 | // Find results with "render" in document name vs those without 455 | const exactMatches = searchResults.filter(r => r.document.toLowerCase().includes('render')); 456 | const otherMatches = searchResults.filter(r => !r.document.toLowerCase().includes('render')); 457 | 458 | if (exactMatches.length > 0 && otherMatches.length > 0) { 459 | // Exact matches should generally have higher relevance scores 460 | const avgExactScore = exactMatches.reduce((sum, r) => sum + r.relevanceScore, 0) / exactMatches.length; 461 | const avgOtherScore = otherMatches.reduce((sum, r) => sum + r.relevanceScore, 0) / otherMatches.length; 462 | 463 | assert.ok(avgExactScore >= avgOtherScore, 'Exact matches should have higher average relevance score'); 464 | } 465 | }); 466 | 467 | test('should return comprehensive results for broad searches', async () => { 468 | const broadQueries = ['model', 'data', 'api', 'object']; 469 | 470 | for (const query of broadQueries) { 471 | const result = await client.callTool('search_sfra_documentation', { query }); 472 | 473 | assert.equal(result.isError, false, `Broad query "${query}" should not error`); 474 | 475 | const searchResults = JSON.parse(result.content[0].text); 476 | 477 | if (searchResults.length > 0) { 478 | // Should find multiple document types for broad searches 479 | const documentTypes = new Set(searchResults.map(r => r.type)); 480 | const categories = new Set(searchResults.map(r => r.category)); 481 | 482 | // Broad searches should span multiple types/categories 483 | assert.ok(documentTypes.size >= 1, `Broad query "${query}" should find at least 1 document type`); 484 | assert.ok(categories.size >= 1, `Broad query "${query}" should find at least 1 category`); 485 | } 486 | } 487 | }); 488 | 489 | test('should provide specific results for narrow searches', async () => { 490 | const narrowQueries = ['applyRenderings', 'viewData', 'pageMetaData', 'isJson']; 491 | 492 | for (const query of narrowQueries) { 493 | const result = await client.callTool('search_sfra_documentation', { query }); 494 | 495 | assert.equal(result.isError, false, `Narrow query "${query}" should not error`); 496 | 497 | const searchResults = JSON.parse(result.content[0].text); 498 | 499 | // For narrow/specific searches, results should be highly relevant 500 | for (const searchResult of searchResults) { 501 | const hasRelevantMatch = searchResult.matches.some(match => 502 | match.content.toLowerCase().includes(query.toLowerCase()) || 503 | match.section.toLowerCase().includes(query.toLowerCase()) 504 | ); 505 | assert.ok(hasRelevantMatch, `Search result should contain relevant match for specific query: "${query}"`); 506 | } 507 | } 508 | }); 509 | 510 | test('should handle related term searches effectively', async () => { 511 | const relatedTermSets = [ 512 | ['cart', 'basket', 'shopping'], 513 | ['template', 'view', 'render'], 514 | ['product', 'item', 'catalog'], 515 | ['customer', 'user', 'account'] 516 | ]; 517 | 518 | for (const termSet of relatedTermSets) { 519 | const results = []; 520 | 521 | for (const term of termSet) { 522 | const result = await client.callTool('search_sfra_documentation', { query: term }); 523 | assert.equal(result.isError, false, `Related term "${term}" should not error`); 524 | results.push(JSON.parse(result.content[0].text)); 525 | } 526 | 527 | // Related terms should have some overlap in documents found 528 | const allDocuments = results.flatMap(r => r.map(doc => doc.document)); 529 | const uniqueDocuments = new Set(allDocuments); 530 | 531 | // Should find some documents across related terms 532 | assert.ok(uniqueDocuments.size > 0, `Related terms ${termSet.join(', ')} should find some documents`); 533 | } 534 | }); 535 | }); 536 | 537 | describe('Stress and Load Testing', () => { 538 | test('should handle rapid sequential searches efficiently', async () => { 539 | const queries = ['server', 'request', 'response', 'render', 'model', 'cart', 'product', 'price']; 540 | 541 | for (const query of queries) { 542 | const result = await client.callTool('search_sfra_documentation', { query }); 543 | assert.equal(result.isError, false, `Sequential query "${query}" should not error`); 544 | } 545 | }); 546 | 547 | test('should maintain performance consistency across different query types', async () => { 548 | const queryTypes = [ 549 | { type: 'short', queries: ['a', 'b', 'c'] }, 550 | { type: 'medium', queries: ['render', 'server', 'model'] }, 551 | { type: 'long', queries: ['template rendering', 'product catalog', 'customer account'] }, 552 | { type: 'complex', queries: ['server request response middleware', 'product cart pricing checkout'] } 553 | ]; 554 | 555 | for (const { type, queries } of queryTypes) { 556 | for (const query of queries) { 557 | const result = await client.callTool('search_sfra_documentation', { query }); 558 | assert.equal(result.isError, false, `${type} query "${query}" should not error`); 559 | } 560 | } 561 | }); 562 | }); 563 | }); 564 | ``` -------------------------------------------------------------------------------- /tests/documentation-scanner.test.ts: -------------------------------------------------------------------------------- ```typescript 1 | import { DocumentationScanner } from '../src/clients/docs/documentation-scanner.js'; 2 | import { Logger } from '../src/utils/logger.js'; 3 | import fs from 'fs/promises'; 4 | import path from 'path'; 5 | 6 | // Mock fs module 7 | jest.mock('fs/promises'); 8 | jest.mock('path'); 9 | 10 | const mockFs = fs as jest.Mocked<typeof fs>; 11 | const mockPath = path as jest.Mocked<typeof path>; 12 | 13 | describe('DocumentationScanner', () => { 14 | let mockLogger: jest.Mocked<Logger>; 15 | let scanner: DocumentationScanner; 16 | 17 | beforeEach(() => { 18 | mockLogger = { 19 | debug: jest.fn(), 20 | log: jest.fn(), 21 | error: jest.fn(), 22 | timing: jest.fn(), 23 | methodEntry: jest.fn(), 24 | methodExit: jest.fn(), 25 | warn: jest.fn(), 26 | } as any; 27 | 28 | // Setup Logger mock before creating scanner 29 | jest.spyOn(Logger, 'getChildLogger').mockReturnValue(mockLogger); 30 | 31 | // Now create the scanner instance 32 | scanner = new DocumentationScanner(); 33 | 34 | // Reset all mocks 35 | jest.clearAllMocks(); 36 | 37 | // Setup default path mock behavior 38 | mockPath.join.mockImplementation((...segments) => segments.join('/')); 39 | mockPath.resolve.mockImplementation((filePath) => `/resolved/${filePath}`); 40 | }); 41 | 42 | afterEach(() => { 43 | jest.clearAllMocks(); 44 | }); 45 | 46 | describe('constructor', () => { 47 | it('should create logger with correct name', () => { 48 | // Re-mock and create a new instance to verify logger creation 49 | const loggerSpy = jest.spyOn(Logger, 'getChildLogger').mockReturnValue(mockLogger); 50 | new DocumentationScanner(); 51 | 52 | expect(loggerSpy).toHaveBeenCalledWith('DocumentationScanner'); 53 | 54 | loggerSpy.mockRestore(); 55 | }); 56 | }); 57 | 58 | describe('scanDocumentation', () => { 59 | it('should scan SFCC directories and return class cache', async () => { 60 | const mockDirent = (name: string, isDir: boolean = true) => ({ 61 | name, 62 | isDirectory: () => isDir, 63 | isFile: () => !isDir, 64 | isSymbolicLink: () => false, 65 | isBlockDevice: () => false, 66 | isCharacterDevice: () => false, 67 | isFIFO: () => false, 68 | isSocket: () => false, 69 | }); 70 | 71 | // Mock readdir for main docs directory 72 | mockFs.readdir.mockResolvedValueOnce([ 73 | mockDirent('dw_catalog'), 74 | mockDirent('dw_content'), 75 | mockDirent('TopLevel'), 76 | mockDirent('best-practices'), // Should be excluded 77 | mockDirent('sfra'), // Should be excluded 78 | mockDirent('other-dir'), // Should be excluded 79 | mockDirent('readme.md', false), // File, should be skipped 80 | ] as any); 81 | 82 | // Mock readdir for package directories in specific order 83 | mockFs.readdir 84 | .mockResolvedValueOnce([ 85 | 'Product.md', 86 | 'Category.md', 87 | 'readme.txt', // non-.md file to be skipped 88 | ] as any) // dw_catalog 89 | .mockResolvedValueOnce([ 90 | 'ContentMgr.md', 91 | 'Content.md', 92 | ] as any) // dw_content 93 | .mockResolvedValueOnce([ 94 | 'String.md', 95 | 'Number.md', 96 | ] as any); // TopLevel 97 | 98 | // Mock file reading in the expected order based on directory scanning 99 | mockFs.readFile 100 | .mockResolvedValueOnce('# Class Product\n\nProduct documentation content') // dw_catalog/Product.md 101 | .mockResolvedValueOnce('# Class Category\n\nCategory documentation content') // dw_catalog/Category.md 102 | .mockResolvedValueOnce('# Class ContentMgr\n\nContentMgr documentation content') // dw_content/ContentMgr.md 103 | .mockResolvedValueOnce('# Class Content\n\nContent documentation content') // dw_content/Content.md 104 | .mockResolvedValueOnce('# Class String\n\nString documentation content') // TopLevel/String.md 105 | .mockResolvedValueOnce('# Class Number\n\nNumber documentation content'); // TopLevel/Number.md 106 | 107 | // Mock path validation to ensure all paths are considered valid 108 | mockPath.resolve.mockImplementation((filePath) => { 109 | // For the main docs path 110 | if (filePath === '/docs') { 111 | return '/resolved/docs'; 112 | } 113 | 114 | // For package directories 115 | if (filePath === '/docs/dw_catalog') { 116 | return '/resolved/docs/dw_catalog'; 117 | } 118 | if (filePath === '/docs/dw_content') { 119 | return '/resolved/docs/dw_content'; 120 | } 121 | if (filePath === '/docs/TopLevel') { 122 | return '/resolved/docs/TopLevel'; 123 | } 124 | 125 | // For specific files - ensure they're within the package and docs paths 126 | if (filePath === '/docs/dw_catalog/Product.md') { 127 | return '/resolved/docs/dw_catalog/Product.md'; 128 | } 129 | if (filePath === '/docs/dw_catalog/Category.md') { 130 | return '/resolved/docs/dw_catalog/Category.md'; 131 | } 132 | if (filePath === '/docs/dw_content/ContentMgr.md') { 133 | return '/resolved/docs/dw_content/ContentMgr.md'; 134 | } 135 | if (filePath === '/docs/dw_content/Content.md') { 136 | return '/resolved/docs/dw_content/Content.md'; 137 | } 138 | if (filePath === '/docs/TopLevel/String.md') { 139 | return '/resolved/docs/TopLevel/String.md'; 140 | } 141 | if (filePath === '/docs/TopLevel/Number.md') { 142 | return '/resolved/docs/TopLevel/Number.md'; 143 | } 144 | 145 | // Default fallback 146 | return `/resolved${filePath}`; 147 | }); 148 | 149 | const result = await scanner.scanDocumentation('/docs'); 150 | 151 | expect(result).toBeInstanceOf(Map); 152 | expect(result.size).toBe(6); // Should have 6 .md files total 153 | 154 | // Check that SFCC directories were processed 155 | expect(result.has('dw_catalog.Product')).toBe(true); 156 | expect(result.has('dw_catalog.Category')).toBe(true); 157 | expect(result.has('dw_content.ContentMgr')).toBe(true); 158 | expect(result.has('dw_content.Content')).toBe(true); 159 | expect(result.has('TopLevel.String')).toBe(true); 160 | expect(result.has('TopLevel.Number')).toBe(true); 161 | 162 | // Verify structure of one cached item 163 | const productInfo = result.get('dw_catalog.Product'); 164 | expect(productInfo).toEqual({ 165 | className: 'Product', 166 | packageName: 'dw_catalog', 167 | filePath: '/docs/dw_catalog/Product.md', 168 | content: '# Class Product\n\nProduct documentation content', 169 | }); 170 | }); 171 | 172 | it('should handle empty docs directory', async () => { 173 | mockFs.readdir.mockResolvedValueOnce([]); 174 | 175 | const result = await scanner.scanDocumentation('/empty-docs'); 176 | 177 | expect(result).toBeInstanceOf(Map); 178 | expect(result.size).toBe(0); 179 | }); 180 | 181 | it('should skip non-SFCC directories', async () => { 182 | const mockDirent = (name: string, isDir: boolean = true) => ({ 183 | name, 184 | isDirectory: () => isDir, 185 | isFile: () => !isDir, 186 | isSymbolicLink: () => false, 187 | isBlockDevice: () => false, 188 | isCharacterDevice: () => false, 189 | isFIFO: () => false, 190 | isSocket: () => false, 191 | }); 192 | 193 | mockFs.readdir.mockResolvedValueOnce([ 194 | mockDirent('best-practices'), 195 | mockDirent('sfra'), 196 | mockDirent('random-dir'), 197 | mockDirent('another_dir'), 198 | ] as any); 199 | 200 | const result = await scanner.scanDocumentation('/docs'); 201 | 202 | expect(result).toBeInstanceOf(Map); 203 | expect(result.size).toBe(0); 204 | }); 205 | 206 | it('should handle directory read errors gracefully', async () => { 207 | mockFs.readdir.mockRejectedValueOnce(new Error('Permission denied')); 208 | 209 | await expect(scanner.scanDocumentation('/forbidden-docs')).rejects.toThrow('Permission denied'); 210 | }); 211 | }); 212 | 213 | describe('directory classification (isSFCCDirectory)', () => { 214 | // Test the isSFCCDirectory logic through scanDocumentation behavior 215 | it('should include dw_ prefixed directories', async () => { 216 | const mockDirent = (name: string) => ({ 217 | name, 218 | isDirectory: () => true, 219 | isFile: () => false, 220 | isSymbolicLink: () => false, 221 | isBlockDevice: () => false, 222 | isCharacterDevice: () => false, 223 | isFIFO: () => false, 224 | isSocket: () => false, 225 | }); 226 | 227 | mockFs.readdir.mockResolvedValueOnce([ 228 | mockDirent('dw_catalog'), 229 | mockDirent('dw_content'), 230 | mockDirent('dw_system'), 231 | mockDirent('dw_order'), 232 | ] as any); 233 | 234 | mockFs.readdir 235 | .mockResolvedValueOnce([]) // dw_catalog 236 | .mockResolvedValueOnce([]) // dw_content 237 | .mockResolvedValueOnce([]) // dw_system 238 | .mockResolvedValueOnce([]); // dw_order 239 | 240 | await scanner.scanDocumentation('/docs'); 241 | 242 | // Verify that readdir was called for each dw_ directory 243 | expect(mockFs.readdir).toHaveBeenCalledTimes(5); // 1 for main + 4 for packages 244 | }); 245 | 246 | it('should include TopLevel directory', async () => { 247 | const mockDirent = (name: string) => ({ 248 | name, 249 | isDirectory: () => true, 250 | isFile: () => false, 251 | isSymbolicLink: () => false, 252 | isBlockDevice: () => false, 253 | isCharacterDevice: () => false, 254 | isFIFO: () => false, 255 | isSocket: () => false, 256 | }); 257 | 258 | mockFs.readdir.mockResolvedValueOnce([mockDirent('TopLevel')] as any); 259 | mockFs.readdir.mockResolvedValueOnce([]); // TopLevel contents 260 | 261 | await scanner.scanDocumentation('/docs'); 262 | 263 | expect(mockFs.readdir).toHaveBeenCalledTimes(2); // 1 for main + 1 for TopLevel 264 | }); 265 | 266 | it('should exclude best-practices directory', async () => { 267 | const mockDirent = (name: string) => ({ 268 | name, 269 | isDirectory: () => true, 270 | isFile: () => false, 271 | isSymbolicLink: () => false, 272 | isBlockDevice: () => false, 273 | isCharacterDevice: () => false, 274 | isFIFO: () => false, 275 | isSocket: () => false, 276 | }); 277 | 278 | mockFs.readdir.mockResolvedValueOnce([mockDirent('best-practices')] as any); 279 | 280 | await scanner.scanDocumentation('/docs'); 281 | 282 | expect(mockFs.readdir).toHaveBeenCalledTimes(1); // Only main directory 283 | }); 284 | 285 | it('should exclude sfra directory', async () => { 286 | const mockDirent = (name: string) => ({ 287 | name, 288 | isDirectory: () => true, 289 | isFile: () => false, 290 | isSymbolicLink: () => false, 291 | isBlockDevice: () => false, 292 | isCharacterDevice: () => false, 293 | isFIFO: () => false, 294 | isSocket: () => false, 295 | }); 296 | 297 | mockFs.readdir.mockResolvedValueOnce([mockDirent('sfra')] as any); 298 | 299 | await scanner.scanDocumentation('/docs'); 300 | 301 | expect(mockFs.readdir).toHaveBeenCalledTimes(1); // Only main directory 302 | }); 303 | }); 304 | 305 | describe('file name validation', () => { 306 | it('should process valid markdown files', async () => { 307 | const mockDirent = (name: string) => ({ 308 | name, 309 | isDirectory: () => true, 310 | isFile: () => false, 311 | isSymbolicLink: () => false, 312 | isBlockDevice: () => false, 313 | isCharacterDevice: () => false, 314 | isFIFO: () => false, 315 | isSocket: () => false, 316 | }); 317 | 318 | mockFs.readdir.mockResolvedValueOnce([mockDirent('dw_catalog')] as any); 319 | mockFs.readdir.mockResolvedValueOnce([ 320 | 'Product.md', 321 | 'Valid_File-Name.md', 322 | 'File123.md', 323 | ] as any); 324 | 325 | mockFs.readFile 326 | .mockResolvedValueOnce('Valid content') 327 | .mockResolvedValueOnce('Valid content') 328 | .mockResolvedValueOnce('Valid content'); 329 | 330 | const result = await scanner.scanDocumentation('/docs'); 331 | 332 | expect(result.size).toBe(3); 333 | expect(result.has('dw_catalog.Product')).toBe(true); 334 | expect(result.has('dw_catalog.Valid_File-Name')).toBe(true); 335 | expect(result.has('dw_catalog.File123')).toBe(true); 336 | }); 337 | 338 | it('should reject files with path traversal sequences', async () => { 339 | const mockDirent = (name: string) => ({ 340 | name, 341 | isDirectory: () => true, 342 | isFile: () => false, 343 | isSymbolicLink: () => false, 344 | isBlockDevice: () => false, 345 | isCharacterDevice: () => false, 346 | isFIFO: () => false, 347 | isSocket: () => false, 348 | }); 349 | 350 | mockFs.readdir.mockResolvedValueOnce([mockDirent('dw_catalog')] as any); 351 | mockFs.readdir.mockResolvedValueOnce([ 352 | '../evil.md', 353 | '..\\evil.md', 354 | 'path/traversal.md', 355 | ] as any); 356 | 357 | const result = await scanner.scanDocumentation('/docs'); 358 | 359 | expect(result.size).toBe(0); 360 | expect(mockLogger.warn).toHaveBeenCalledWith(expect.stringContaining('path traversal')); 361 | }); 362 | 363 | it('should reject files with null bytes', async () => { 364 | const mockDirent = (name: string) => ({ 365 | name, 366 | isDirectory: () => true, 367 | isFile: () => false, 368 | isSymbolicLink: () => false, 369 | isBlockDevice: () => false, 370 | isCharacterDevice: () => false, 371 | isFIFO: () => false, 372 | isSocket: () => false, 373 | }); 374 | 375 | mockFs.readdir.mockResolvedValueOnce([mockDirent('dw_catalog')] as any); 376 | mockFs.readdir.mockResolvedValueOnce([ 377 | 'evil\0.md', 378 | 'evil\x00.md', 379 | ] as any); 380 | 381 | const result = await scanner.scanDocumentation('/docs'); 382 | 383 | expect(result.size).toBe(0); 384 | expect(mockLogger.warn).toHaveBeenCalledWith(expect.stringContaining('null bytes')); 385 | }); 386 | 387 | it('should reject files with invalid characters', async () => { 388 | const mockDirent = (name: string) => ({ 389 | name, 390 | isDirectory: () => true, 391 | isFile: () => false, 392 | isSymbolicLink: () => false, 393 | isBlockDevice: () => false, 394 | isCharacterDevice: () => false, 395 | isFIFO: () => false, 396 | isSocket: () => false, 397 | }); 398 | 399 | mockFs.readdir.mockResolvedValueOnce([mockDirent('dw_catalog')] as any); 400 | mockFs.readdir.mockResolvedValueOnce([ 401 | '[email protected]', 402 | 'file#invalid.md', 403 | 'file$invalid.md', 404 | ] as any); 405 | 406 | const result = await scanner.scanDocumentation('/docs'); 407 | 408 | expect(result.size).toBe(0); 409 | expect(mockLogger.warn).toHaveBeenCalledWith(expect.stringContaining('invalid characters')); 410 | }); 411 | 412 | it('should reject invalid file name types', async () => { 413 | const mockDirent = (name: string) => ({ 414 | name, 415 | isDirectory: () => true, 416 | isFile: () => false, 417 | isSymbolicLink: () => false, 418 | isBlockDevice: () => false, 419 | isCharacterDevice: () => false, 420 | isFIFO: () => false, 421 | isSocket: () => false, 422 | }); 423 | 424 | mockFs.readdir.mockResolvedValueOnce([mockDirent('dw_catalog')] as any); 425 | mockFs.readdir.mockResolvedValueOnce(['', null, undefined] as any); 426 | 427 | const result = await scanner.scanDocumentation('/docs'); 428 | 429 | expect(result.size).toBe(0); 430 | expect(mockLogger.warn).toHaveBeenCalledWith(expect.stringContaining('Invalid file name type')); 431 | }); 432 | }); 433 | 434 | describe('file path validation', () => { 435 | it('should validate file paths are within allowed directories', async () => { 436 | const mockDirent = (name: string) => ({ 437 | name, 438 | isDirectory: () => true, 439 | isFile: () => false, 440 | isSymbolicLink: () => false, 441 | isBlockDevice: () => false, 442 | isCharacterDevice: () => false, 443 | isFIFO: () => false, 444 | isSocket: () => false, 445 | }); 446 | 447 | mockFs.readdir.mockResolvedValueOnce([mockDirent('dw_catalog')] as any); 448 | mockFs.readdir.mockResolvedValueOnce(['Product.md'] as any); 449 | 450 | // Mock path.resolve to simulate path outside allowed directory 451 | mockPath.resolve.mockImplementation((filePath) => { 452 | if (filePath.includes('Product.md')) { 453 | return '/outside/docs/Product.md'; 454 | } 455 | if (filePath.includes('dw_catalog')) { 456 | return '/resolved/docs/dw_catalog'; 457 | } 458 | return '/resolved/docs'; 459 | }); 460 | 461 | const result = await scanner.scanDocumentation('/docs'); 462 | 463 | expect(result.size).toBe(0); 464 | expect(mockLogger.warn).toHaveBeenCalledWith(expect.stringContaining('outside allowed directory')); 465 | }); 466 | 467 | it('should validate files end with .md extension', async () => { 468 | const mockDirent = (name: string) => ({ 469 | name, 470 | isDirectory: () => true, 471 | isFile: () => false, 472 | isSymbolicLink: () => false, 473 | isBlockDevice: () => false, 474 | isCharacterDevice: () => false, 475 | isFIFO: () => false, 476 | isSocket: () => false, 477 | }); 478 | 479 | mockFs.readdir.mockResolvedValueOnce([mockDirent('dw_catalog')] as any); 480 | mockFs.readdir.mockResolvedValueOnce(['Product.md'] as any); 481 | 482 | // Mock path.resolve to simulate file without .md extension after resolution 483 | mockPath.resolve.mockImplementation((filePath) => { 484 | if (filePath.includes('Product.md')) { 485 | return '/resolved/docs/dw_catalog/Product.txt'; 486 | } 487 | if (filePath.includes('dw_catalog')) { 488 | return '/resolved/docs/dw_catalog'; 489 | } 490 | return '/resolved/docs'; 491 | }); 492 | 493 | const result = await scanner.scanDocumentation('/docs'); 494 | 495 | expect(result.size).toBe(0); 496 | expect(mockLogger.warn).toHaveBeenCalledWith(expect.stringContaining('does not reference a markdown file')); 497 | }); 498 | }); 499 | 500 | describe('file content validation', () => { 501 | it('should reject empty file content', async () => { 502 | const mockDirent = (name: string) => ({ 503 | name, 504 | isDirectory: () => true, 505 | isFile: () => false, 506 | isSymbolicLink: () => false, 507 | isBlockDevice: () => false, 508 | isCharacterDevice: () => false, 509 | isFIFO: () => false, 510 | isSocket: () => false, 511 | }); 512 | 513 | mockFs.readdir.mockResolvedValueOnce([mockDirent('dw_catalog')] as any); 514 | mockFs.readdir.mockResolvedValueOnce(['Product.md'] as any); 515 | mockFs.readFile.mockResolvedValueOnce(' \n\t \n '); // Only whitespace 516 | 517 | const result = await scanner.scanDocumentation('/docs'); 518 | 519 | expect(result.size).toBe(0); 520 | expect(mockLogger.warn).toHaveBeenCalledWith(expect.stringContaining('Empty documentation file')); 521 | }); 522 | 523 | it('should reject binary content', async () => { 524 | const mockDirent = (name: string) => ({ 525 | name, 526 | isDirectory: () => true, 527 | isFile: () => false, 528 | isSymbolicLink: () => false, 529 | isBlockDevice: () => false, 530 | isCharacterDevice: () => false, 531 | isFIFO: () => false, 532 | isSocket: () => false, 533 | }); 534 | 535 | mockFs.readdir.mockResolvedValueOnce([mockDirent('dw_catalog')] as any); 536 | mockFs.readdir.mockResolvedValueOnce(['Product.md'] as any); 537 | mockFs.readFile.mockResolvedValueOnce('Valid content\0binary data'); // Contains null byte 538 | 539 | const result = await scanner.scanDocumentation('/docs'); 540 | 541 | expect(result.size).toBe(0); 542 | expect(mockLogger.warn).toHaveBeenCalledWith(expect.stringContaining('Binary content detected')); 543 | }); 544 | 545 | it('should accept valid file content', async () => { 546 | const mockDirent = (name: string) => ({ 547 | name, 548 | isDirectory: () => true, 549 | isFile: () => false, 550 | isSymbolicLink: () => false, 551 | isBlockDevice: () => false, 552 | isCharacterDevice: () => false, 553 | isFIFO: () => false, 554 | isSocket: () => false, 555 | }); 556 | 557 | mockFs.readdir.mockResolvedValueOnce([mockDirent('dw_catalog')] as any); 558 | mockFs.readdir.mockResolvedValueOnce(['Product.md'] as any); 559 | mockFs.readFile.mockResolvedValueOnce('# Class Product\n\nValid markdown content with special chars: éñ中文'); 560 | 561 | const result = await scanner.scanDocumentation('/docs'); 562 | 563 | expect(result.size).toBe(1); 564 | expect(result.has('dw_catalog.Product')).toBe(true); 565 | 566 | const productInfo = result.get('dw_catalog.Product'); 567 | expect(productInfo?.content).toBe('# Class Product\n\nValid markdown content with special chars: éñ中文'); 568 | }); 569 | }); 570 | 571 | describe('file reading error handling', () => { 572 | it('should handle file read errors gracefully', async () => { 573 | const mockDirent = (name: string) => ({ 574 | name, 575 | isDirectory: () => true, 576 | isFile: () => false, 577 | isSymbolicLink: () => false, 578 | isBlockDevice: () => false, 579 | isCharacterDevice: () => false, 580 | isFIFO: () => false, 581 | isSocket: () => false, 582 | }); 583 | 584 | mockFs.readdir.mockResolvedValueOnce([mockDirent('dw_catalog')] as any); 585 | mockFs.readdir.mockResolvedValueOnce(['Product.md', 'Category.md'] as any); 586 | 587 | // First file fails to read, second succeeds 588 | mockFs.readFile 589 | .mockRejectedValueOnce(new Error('Permission denied')) 590 | .mockResolvedValueOnce('# Class Category\n\nValid content'); 591 | 592 | const result = await scanner.scanDocumentation('/docs'); 593 | 594 | expect(result.size).toBe(1); 595 | expect(result.has('dw_catalog.Category')).toBe(true); 596 | expect(result.has('dw_catalog.Product')).toBe(false); 597 | expect(mockLogger.warn).toHaveBeenCalledWith(expect.stringContaining('Could not read file Product.md')); 598 | }); 599 | 600 | it('should handle package directory read errors gracefully', async () => { 601 | const mockDirent = (name: string) => ({ 602 | name, 603 | isDirectory: () => true, 604 | isFile: () => false, 605 | isSymbolicLink: () => false, 606 | isBlockDevice: () => false, 607 | isCharacterDevice: () => false, 608 | isFIFO: () => false, 609 | isSocket: () => false, 610 | }); 611 | 612 | mockFs.readdir.mockResolvedValueOnce([ 613 | mockDirent('dw_catalog'), 614 | mockDirent('dw_content'), 615 | ] as any); 616 | 617 | // First package directory fails to read, second succeeds 618 | mockFs.readdir 619 | .mockRejectedValueOnce(new Error('Directory not accessible')) 620 | .mockResolvedValueOnce(['ContentMgr.md'] as any); 621 | 622 | mockFs.readFile.mockResolvedValueOnce('# Class ContentMgr\n\nValid content'); 623 | 624 | const result = await scanner.scanDocumentation('/docs'); 625 | 626 | expect(result.size).toBe(1); 627 | expect(result.has('dw_content.ContentMgr')).toBe(true); 628 | expect(mockLogger.warn).toHaveBeenCalledWith(expect.stringContaining('Could not read package dw_catalog')); 629 | }); 630 | }); 631 | 632 | describe('markdown file filtering', () => { 633 | it('should only process .md files', async () => { 634 | const mockDirent = (name: string) => ({ 635 | name, 636 | isDirectory: () => true, 637 | isFile: () => false, 638 | isSymbolicLink: () => false, 639 | isBlockDevice: () => false, 640 | isCharacterDevice: () => false, 641 | isFIFO: () => false, 642 | isSocket: () => false, 643 | }); 644 | 645 | mockFs.readdir.mockResolvedValueOnce([mockDirent('dw_catalog')] as any); 646 | mockFs.readdir.mockResolvedValueOnce([ 647 | 'Product.md', 648 | 'readme.txt', 649 | 'documentation.html', 650 | 'Category.md', 651 | 'config.json', 652 | 'index.js', 653 | ] as any); 654 | 655 | mockFs.readFile 656 | .mockResolvedValueOnce('# Class Product\n\nProduct content') 657 | .mockResolvedValueOnce('# Class Category\n\nCategory content'); 658 | 659 | const result = await scanner.scanDocumentation('/docs'); 660 | 661 | expect(result.size).toBe(2); 662 | expect(result.has('dw_catalog.Product')).toBe(true); 663 | expect(result.has('dw_catalog.Category')).toBe(true); 664 | 665 | // Verify only .md files were processed 666 | expect(mockFs.readFile).toHaveBeenCalledTimes(2); 667 | }); 668 | }); 669 | 670 | describe('class name extraction', () => { 671 | it('should extract class names correctly from file names', async () => { 672 | const mockDirent = (name: string) => ({ 673 | name, 674 | isDirectory: () => true, 675 | isFile: () => false, 676 | isSymbolicLink: () => false, 677 | isBlockDevice: () => false, 678 | isCharacterDevice: () => false, 679 | isFIFO: () => false, 680 | isSocket: () => false, 681 | }); 682 | 683 | mockFs.readdir.mockResolvedValueOnce([mockDirent('dw_catalog')] as any); 684 | mockFs.readdir.mockResolvedValueOnce(['Product.md', 'Product_Manager.md', 'Product-Utils.md'] as any); 685 | 686 | mockFs.readFile 687 | .mockResolvedValueOnce('Content 1') 688 | .mockResolvedValueOnce('Content 2') 689 | .mockResolvedValueOnce('Content 3'); 690 | 691 | const result = await scanner.scanDocumentation('/docs'); 692 | 693 | expect(result.size).toBe(3); 694 | expect(result.has('dw_catalog.Product')).toBe(true); 695 | expect(result.has('dw_catalog.Product_Manager')).toBe(true); 696 | expect(result.has('dw_catalog.Product-Utils')).toBe(true); 697 | 698 | // Verify class names are extracted correctly 699 | expect(result.get('dw_catalog.Product')?.className).toBe('Product'); 700 | expect(result.get('dw_catalog.Product_Manager')?.className).toBe('Product_Manager'); 701 | expect(result.get('dw_catalog.Product-Utils')?.className).toBe('Product-Utils'); 702 | }); 703 | }); 704 | 705 | describe('cache key generation', () => { 706 | it('should generate correct cache keys', async () => { 707 | const mockDirent = (name: string) => ({ 708 | name, 709 | isDirectory: () => true, 710 | isFile: () => false, 711 | isSymbolicLink: () => false, 712 | isBlockDevice: () => false, 713 | isCharacterDevice: () => false, 714 | isFIFO: () => false, 715 | isSocket: () => false, 716 | }); 717 | 718 | mockFs.readdir.mockResolvedValueOnce([ 719 | mockDirent('dw_catalog'), 720 | mockDirent('TopLevel'), 721 | ] as any); 722 | 723 | mockFs.readdir 724 | .mockResolvedValueOnce(['Product.md'] as any) 725 | .mockResolvedValueOnce(['String.md'] as any); 726 | 727 | mockFs.readFile 728 | .mockResolvedValueOnce('Product content') 729 | .mockResolvedValueOnce('String content'); 730 | 731 | const result = await scanner.scanDocumentation('/docs'); 732 | 733 | expect(result.size).toBe(2); 734 | expect(result.has('dw_catalog.Product')).toBe(true); 735 | expect(result.has('TopLevel.String')).toBe(true); 736 | 737 | // Verify full structure of cached items 738 | const productInfo = result.get('dw_catalog.Product'); 739 | expect(productInfo).toEqual({ 740 | className: 'Product', 741 | packageName: 'dw_catalog', 742 | filePath: '/docs/dw_catalog/Product.md', 743 | content: 'Product content', 744 | }); 745 | 746 | const stringInfo = result.get('TopLevel.String'); 747 | expect(stringInfo).toEqual({ 748 | className: 'String', 749 | packageName: 'TopLevel', 750 | filePath: '/docs/TopLevel/String.md', 751 | content: 'String content', 752 | }); 753 | }); 754 | }); 755 | }); 756 | ``` -------------------------------------------------------------------------------- /docs/dw_extensions.payments/SalesforcePaymentRequest.md: -------------------------------------------------------------------------------- ```markdown 1 | ## Package: dw.extensions.payments 2 | 3 | # Class SalesforcePaymentRequest 4 | 5 | ## Inheritance Hierarchy 6 | 7 | - Object 8 | - dw.extensions.payments.SalesforcePaymentRequest 9 | 10 | ## Description 11 | 12 | Salesforce Payments request for a shopper to make payment. See Salesforce Payments documentation for how to gain access and configure it for use on your sites. A request is required to render payment methods and/or express checkout buttons using <ispayment> or <isbuynow>. You can call methods on the payment request to configure which payment methods and/or express checkout buttons may be presented, and customize their visual presentation. When used with <isbuynow> you must provide the necessary data to prepare the shopper basket to buy the product, and the necessary payment request options for the browser payment app. 13 | 14 | ## Constants 15 | 16 | ### ELEMENT_AFTERPAY_CLEARPAY_MESSAGE 17 | 18 | **Type:** String = "afterpayClearpayMessage" 19 | 20 | Element for the Stripe Afterpay/Clearpay message "afterpayClearpayMessage". 21 | 22 | ### ELEMENT_CARD_CVC 23 | 24 | **Type:** String = "cardCvc" 25 | 26 | Element for the Stripe credit card CVC field "cardCvc". 27 | 28 | ### ELEMENT_CARD_EXPIRY 29 | 30 | **Type:** String = "cardExpiry" 31 | 32 | Element for the Stripe credit card expiration date field "cardExpiry". 33 | 34 | ### ELEMENT_CARD_NUMBER 35 | 36 | **Type:** String = "cardNumber" 37 | 38 | Element for the Stripe credit card number field "cardNumber". 39 | 40 | ### ELEMENT_EPS_BANK 41 | 42 | **Type:** String = "epsBank" 43 | 44 | Element for the Stripe EPS bank selection field "epsBank". 45 | 46 | ### ELEMENT_IBAN 47 | 48 | **Type:** String = "iban" 49 | 50 | Element for the Stripe IBAN field "iban". 51 | 52 | ### ELEMENT_IDEAL_BANK 53 | 54 | **Type:** String = "idealBank" 55 | 56 | Element for the Stripe iDEAL bank selection field "idealBank". 57 | 58 | ### ELEMENT_PAYMENT_REQUEST_BUTTON 59 | 60 | **Type:** String = "paymentRequestButton" 61 | 62 | Element for the Stripe payment request button "paymentRequestButton". 63 | 64 | ### ELEMENT_TYPE_AFTERPAY_CLEARPAY 65 | 66 | **Type:** String = "afterpay_clearpay" 67 | 68 | Element type name for Afterpay. 69 | 70 | ### ELEMENT_TYPE_AFTERPAY_CLEARPAY_MESSAGE 71 | 72 | **Type:** String = "afterpayclearpaymessage" 73 | 74 | Element type name for Afterpay/Clearpay message. 75 | 76 | ### ELEMENT_TYPE_APPLEPAY 77 | 78 | **Type:** String = "applepay" 79 | 80 | Element type name for Apple Pay payment request buttons. 81 | 82 | ### ELEMENT_TYPE_BANCONTACT 83 | 84 | **Type:** String = "bancontact" 85 | 86 | Element type name for Bancontact. 87 | 88 | ### ELEMENT_TYPE_CARD 89 | 90 | **Type:** String = "card" 91 | 92 | Element type name for credit cards. 93 | 94 | ### ELEMENT_TYPE_EPS 95 | 96 | **Type:** String = "eps" 97 | 98 | Element type name for EPS. 99 | 100 | ### ELEMENT_TYPE_IDEAL 101 | 102 | **Type:** String = "ideal" 103 | 104 | Element type name for iDEAL. 105 | 106 | ### ELEMENT_TYPE_PAYMENTREQUEST 107 | 108 | **Type:** String = "paymentrequest" 109 | 110 | Element type name for other payment request buttons besides Apple Pay, like Google Pay. 111 | 112 | ### ELEMENT_TYPE_PAYPAL 113 | 114 | **Type:** String = "paypal" 115 | 116 | Element type name for PayPal in multi-step checkout. 117 | 118 | ### ELEMENT_TYPE_PAYPAL_EXPRESS 119 | 120 | **Type:** String = "paypalexpress" 121 | 122 | Element type name for PayPal in express checkout. 123 | 124 | ### ELEMENT_TYPE_PAYPAL_MESSAGE 125 | 126 | **Type:** String = "paypalmessage" 127 | 128 | Element type name for the PayPal messages component. 129 | 130 | ### ELEMENT_TYPE_SEPA_DEBIT 131 | 132 | **Type:** String = "sepa_debit" 133 | 134 | Element type name for SEPA debit. 135 | 136 | ### ELEMENT_TYPE_VENMO 137 | 138 | **Type:** String = "venmo" 139 | 140 | Element type name for Venmo in multi-step checkout. 141 | 142 | ### ELEMENT_TYPE_VENMO_EXPRESS 143 | 144 | **Type:** String = "venmoexpress" 145 | 146 | Element type name for Venmo in express checkout. 147 | 148 | ### PAYPAL_SHIPPING_PREFERENCE_GET_FROM_FILE 149 | 150 | **Type:** String = "GET_FROM_FILE" 151 | 152 | PayPal application context shipping_preference value "GET_FROM_FILE", to use the customer-provided shipping address on the PayPal site. 153 | 154 | ### PAYPAL_SHIPPING_PREFERENCE_NO_SHIPPING 155 | 156 | **Type:** String = "NO_SHIPPING" 157 | 158 | PayPal application context shipping_preference value "NO_SHIPPING", to redact the shipping address from the PayPal site. Recommended for digital goods. 159 | 160 | ### PAYPAL_SHIPPING_PREFERENCE_SET_PROVIDED_ADDRESS 161 | 162 | **Type:** String = "SET_PROVIDED_ADDRESS" 163 | 164 | PayPal application context shipping_preference value "SET_PROVIDED_ADDRESS", to use the merchant-provided address. The customer cannot change this address on the PayPal site. 165 | 166 | ### PAYPAL_USER_ACTION_CONTINUE 167 | 168 | **Type:** String = "CONTINUE" 169 | 170 | PayPal application context user_action value "CONTINUE". Use this option when the final amount is not known when the checkout flow is initiated and you want to redirect the customer to the merchant page without processing the payment. 171 | 172 | ### PAYPAL_USER_ACTION_PAY_NOW 173 | 174 | **Type:** String = "PAY_NOW" 175 | 176 | PayPal application context user_action value "PAY_NOW". Use this option when the final amount is known when the checkout is initiated and you want to process the payment immediately when the customer clicks Pay Now. 177 | 178 | ## Properties 179 | 180 | ### basketData 181 | 182 | **Type:** Object 183 | 184 | A JS object containing the data used to prepare the shopper basket when a Buy Now button is tapped. 185 | 186 | ### billingDetails 187 | 188 | **Type:** Object 189 | 190 | A JS object containing the billing details to use when a Stripe PaymentMethod is created. 191 | 192 | ### cardCaptureAutomatic 193 | 194 | **Type:** boolean 195 | 196 | Returns true if the credit card payment should be automatically captured at the time of the sale, or 197 | false if the credit card payment should be captured later. 198 | 199 | ### exclude 200 | 201 | **Type:** Set (Read Only) 202 | 203 | Returns a set containing the element types to be explicitly excluded from mounted components. See the element 204 | type constants in this class for the full list of supported element types. 205 | 206 | 207 | Note: if an element type is both explicitly included and excluded, it will not be presented. 208 | 209 | ### ID 210 | 211 | **Type:** String (Read Only) 212 | 213 | The identifier of this payment request. 214 | 215 | ### include 216 | 217 | **Type:** Set (Read Only) 218 | 219 | Returns a set containing the specific element types to include in mounted components. If the set is 220 | empty then all applicable and enabled element types will be included by default. See the element type constants 221 | in this class for the full list of supported element types. 222 | 223 | 224 | Note: if an element type is both explicitly included and excluded, it will not be presented. 225 | 226 | ### selector 227 | 228 | **Type:** String (Read Only) 229 | 230 | The DOM element selector where to mount payment methods and/or express checkout buttons. 231 | 232 | ### setupFutureUsage 233 | 234 | **Type:** boolean 235 | 236 | Returns true if the payment method should be always saved for future use off session, or 237 | false if the payment method should be only saved for future use on session when appropriate. 238 | 239 | ### statementDescriptor 240 | 241 | **Type:** String 242 | 243 | The complete description that appears on your customers' statements for payments made by this request, or 244 | null if the default statement descriptor for your account will be used. 245 | 246 | ## Constructor Summary 247 | 248 | SalesforcePaymentRequest(id : String, selector : String) Constructs a payment request using the given identifiers. 249 | 250 | ## Method Summary 251 | 252 | ### addExclude 253 | 254 | **Signature:** `addExclude(elementType : String) : void` 255 | 256 | Adds the given element type to explicitly exclude from mounted components. 257 | 258 | ### addInclude 259 | 260 | **Signature:** `addInclude(elementType : String) : void` 261 | 262 | Adds the given element type to include in mounted components. 263 | 264 | ### calculatePaymentRequestOptions 265 | 266 | **Signature:** `static calculatePaymentRequestOptions(basket : Basket, options : Object) : Object` 267 | 268 | Returns a JS object containing the payment request options to use when a Pay Now button is tapped, in the appropriate format for use in client side JavaScript, with data calculated from the given basket. 269 | 270 | ### format 271 | 272 | **Signature:** `static format(options : Object) : Object` 273 | 274 | Returns a JS object containing the payment request options to use when a Buy Now button is tapped, in the appropriate format for use in client side JavaScript. 275 | 276 | ### getBasketData 277 | 278 | **Signature:** `getBasketData() : Object` 279 | 280 | Returns a JS object containing the data used to prepare the shopper basket when a Buy Now button is tapped. 281 | 282 | ### getBillingDetails 283 | 284 | **Signature:** `getBillingDetails() : Object` 285 | 286 | Returns a JS object containing the billing details to use when a Stripe PaymentMethod is created. 287 | 288 | ### getCardCaptureAutomatic 289 | 290 | **Signature:** `getCardCaptureAutomatic() : boolean` 291 | 292 | Returns true if the credit card payment should be automatically captured at the time of the sale, or false if the credit card payment should be captured later. 293 | 294 | ### getExclude 295 | 296 | **Signature:** `getExclude() : Set` 297 | 298 | Returns a set containing the element types to be explicitly excluded from mounted components. 299 | 300 | ### getID 301 | 302 | **Signature:** `getID() : String` 303 | 304 | Returns the identifier of this payment request. 305 | 306 | ### getInclude 307 | 308 | **Signature:** `getInclude() : Set` 309 | 310 | Returns a set containing the specific element types to include in mounted components. 311 | 312 | ### getSelector 313 | 314 | **Signature:** `getSelector() : String` 315 | 316 | Returns the DOM element selector where to mount payment methods and/or express checkout buttons. 317 | 318 | ### getSetupFutureUsage 319 | 320 | **Signature:** `getSetupFutureUsage() : boolean` 321 | 322 | Returns true if the payment method should be always saved for future use off session, or false if the payment method should be only saved for future use on session when appropriate. 323 | 324 | ### getStatementDescriptor 325 | 326 | **Signature:** `getStatementDescriptor() : String` 327 | 328 | Returns the complete description that appears on your customers' statements for payments made by this request, or null if the default statement descriptor for your account will be used. 329 | 330 | ### setBasketData 331 | 332 | **Signature:** `setBasketData(basketData : Object) : void` 333 | 334 | Sets the data used to prepare the shopper basket when a Buy Now button is tapped. 335 | 336 | ### setBillingDetails 337 | 338 | **Signature:** `setBillingDetails(billingDetails : Object) : void` 339 | 340 | Sets the billing details to use when a Stripe PaymentMethod is created. 341 | 342 | ### setCardCaptureAutomatic 343 | 344 | **Signature:** `setCardCaptureAutomatic(cardCaptureAutomatic : boolean) : void` 345 | 346 | Sets if the credit card payment should be automatically captured at the time of the sale. 347 | 348 | ### setOptions 349 | 350 | **Signature:** `setOptions(options : Object) : void` 351 | 352 | Sets the payment request options to use when a Buy Now button is tapped. 353 | 354 | ### setPayPalButtonsOptions 355 | 356 | **Signature:** `setPayPalButtonsOptions(options : Object) : void` 357 | 358 | Sets the the options to pass into the paypal.Buttons call. 359 | 360 | ### setPayPalShippingPreference 361 | 362 | **Signature:** `setPayPalShippingPreference(shippingPreference : String) : void` 363 | 364 | Sets the PayPal order application context shipping_preference value. 365 | 366 | ### setPayPalUserAction 367 | 368 | **Signature:** `setPayPalUserAction(userAction : String) : void` 369 | 370 | Sets the PayPal order application context user_action value. 371 | 372 | ### setReturnController 373 | 374 | **Signature:** `setReturnController(returnController : String) : void` 375 | 376 | Sets the controller to which to redirect when the shopper returns from a 3rd party payment website. 377 | 378 | ### setSavePaymentMethodEnabled 379 | 380 | **Signature:** `setSavePaymentMethodEnabled(savePaymentMethodEnabled : boolean) : void` 381 | 382 | Sets if mounted components may provide a control for the shopper to save their payment method for later use. 383 | 384 | ### setSetupFutureUsage 385 | 386 | **Signature:** `setSetupFutureUsage(setupFutureUsage : boolean) : void` 387 | 388 | Sets if the payment method should be always saved for future use off session. 389 | 390 | ### setStatementDescriptor 391 | 392 | **Signature:** `setStatementDescriptor(statementDescriptor : String) : void` 393 | 394 | Sets the complete description that appears on your customers' statements for payments made by this request. 395 | 396 | ### setStripeCreateElementOptions 397 | 398 | **Signature:** `setStripeCreateElementOptions(element : String, options : Object) : void` 399 | 400 | Sets the the options to pass into the Stripe elements.create call for the given element type. 401 | 402 | ### setStripeElementsOptions 403 | 404 | **Signature:** `setStripeElementsOptions(options : Object) : void` 405 | 406 | Sets the the options to pass into the stripe.elements call. 407 | 408 | ## Constructor Detail 409 | 410 | ## Method Detail 411 | 412 | ## Method Details 413 | 414 | ### addExclude 415 | 416 | **Signature:** `addExclude(elementType : String) : void` 417 | 418 | **Description:** Adds the given element type to explicitly exclude from mounted components. It is not necessary to explicitly exclude element types that are not enabled for the site, or are not applicable for the current shopper and/or their basket. See the element type constants in this class for the full list of supported element types. Note: if an element type is both explicitly included and excluded, it will not be presented. 419 | 420 | **Parameters:** 421 | 422 | - `elementType`: element type 423 | 424 | **See Also:** 425 | 426 | getExclude() 427 | 428 | --- 429 | 430 | ### addInclude 431 | 432 | **Signature:** `addInclude(elementType : String) : void` 433 | 434 | **Description:** Adds the given element type to include in mounted components. Call this method to include only a specific list of element types to be presented when applicable and enabled for the site. See the element type constants in this class for the full list of supported element types. Note: if an element type is both explicitly included and excluded, it will not be presented. 435 | 436 | **Parameters:** 437 | 438 | - `elementType`: element type 439 | 440 | **See Also:** 441 | 442 | getInclude() 443 | 444 | --- 445 | 446 | ### calculatePaymentRequestOptions 447 | 448 | **Signature:** `static calculatePaymentRequestOptions(basket : Basket, options : Object) : Object` 449 | 450 | **Description:** Returns a JS object containing the payment request options to use when a Pay Now button is tapped, in the appropriate format for use in client side JavaScript, with data calculated from the given basket. This method is provided as a convenience to calculate updated payment request options when the shopper basket has changed. Data in the given options object like total, displayItems, and shippingOptions will be replaced in the returned object by values recalculated from the given basket and applicable shipping methods. The following example shows the resulting output for a basket and sample options. SalesforcePaymentRequest.calculatePaymentRequestOptions(basket, { requestPayerName: true, requestPayerEmail: true, requestPayerPhone: false, requestShipping: true }); returns { currency: 'gbp', total: { label: 'Total', amount: '2644' }, displayItems: [{ label: 'Subtotal', amount: '1919' }, { label: 'Tax', amount: '126' }, { label: 'Ground', amount: '599' }], requestPayerName: true, requestPayerEmail: true, requestPayerPhone: false, requestShipping: true, shippingOptions: [{ id: 'GBP001', label: 'Ground', detail: 'Order received within 7-10 business days', amount: '599' },{ id: 'GBP002', label: 'Express', detail: 'Order received within 2-4 business days', amount: '999' }] } 451 | 452 | **Parameters:** 453 | 454 | - `basket`: No Comment In JavaDoc 455 | - `options`: JS object containing payment request options in B2C Commerce API standard format 456 | 457 | **Returns:** 458 | 459 | JS object containing equivalent payment request options in Stripe JS API format 460 | 461 | --- 462 | 463 | ### format 464 | 465 | **Signature:** `static format(options : Object) : Object` 466 | 467 | **Description:** Returns a JS object containing the payment request options to use when a Buy Now button is tapped, in the appropriate format for use in client side JavaScript. This method is provided as a convenience to adjust values in B2C Commerce API standard formats to their equivalents as expected by Stripe JS APIs. The following example shows options set in B2C Commerce API format, and the resulting output. SalesforcePaymentRequest.format({ currency: 'GBP', total: { label: 'Total', amount: '26.44' }, displayItems: [{ label: 'Subtotal', amount: '19.19' }, { label: 'Tax', amount: '1.26' }, { label: 'Ground', amount: '5.99' }], requestPayerPhone: false, shippingOptions: [{ id: 'GBP001', label: 'Ground', detail: 'Order received within 7-10 business days', amount: '5.99' }] }); returns { currency: 'gbp', total: { label: 'Total', amount: '2644' }, displayItems: [{ label: 'Subtotal', amount: '1919' }, { label: 'Tax', amount: '126' }, { label: 'Ground', amount: '599' }], requestPayerPhone: false, shippingOptions: [{ id: 'GBP001', label: 'Ground', detail: 'Order received within 7-10 business days', amount: '599' }] } 468 | 469 | **Parameters:** 470 | 471 | - `options`: JS object containing payment request options in B2C Commerce API standard format 472 | 473 | **Returns:** 474 | 475 | JS object containing equivalent payment request options in Stripe JS API format 476 | 477 | --- 478 | 479 | ### getBasketData 480 | 481 | **Signature:** `getBasketData() : Object` 482 | 483 | **Description:** Returns a JS object containing the data used to prepare the shopper basket when a Buy Now button is tapped. 484 | 485 | **Returns:** 486 | 487 | JS object containing the basket data 488 | 489 | **See Also:** 490 | 491 | setBasketData(Object) 492 | 493 | --- 494 | 495 | ### getBillingDetails 496 | 497 | **Signature:** `getBillingDetails() : Object` 498 | 499 | **Description:** Returns a JS object containing the billing details to use when a Stripe PaymentMethod is created. 500 | 501 | **Returns:** 502 | 503 | JS object containing the billing details 504 | 505 | **See Also:** 506 | 507 | setBillingDetails(Object) 508 | 509 | --- 510 | 511 | ### getCardCaptureAutomatic 512 | 513 | **Signature:** `getCardCaptureAutomatic() : boolean` 514 | 515 | **Description:** Returns true if the credit card payment should be automatically captured at the time of the sale, or false if the credit card payment should be captured later. 516 | 517 | **Returns:** 518 | 519 | true if the credit card payment should be automatically captured at the time of the sale, false if the credit card payment should be captured later. 520 | 521 | --- 522 | 523 | ### getExclude 524 | 525 | **Signature:** `getExclude() : Set` 526 | 527 | **Description:** Returns a set containing the element types to be explicitly excluded from mounted components. See the element type constants in this class for the full list of supported element types. Note: if an element type is both explicitly included and excluded, it will not be presented. 528 | 529 | **Returns:** 530 | 531 | set of element types 532 | 533 | **See Also:** 534 | 535 | addExclude(String) 536 | 537 | --- 538 | 539 | ### getID 540 | 541 | **Signature:** `getID() : String` 542 | 543 | **Description:** Returns the identifier of this payment request. 544 | 545 | **Returns:** 546 | 547 | payment request identifier 548 | 549 | --- 550 | 551 | ### getInclude 552 | 553 | **Signature:** `getInclude() : Set` 554 | 555 | **Description:** Returns a set containing the specific element types to include in mounted components. If the set is empty then all applicable and enabled element types will be included by default. See the element type constants in this class for the full list of supported element types. Note: if an element type is both explicitly included and excluded, it will not be presented. 556 | 557 | **Returns:** 558 | 559 | set of element types 560 | 561 | **See Also:** 562 | 563 | addInclude(String) 564 | 565 | --- 566 | 567 | ### getSelector 568 | 569 | **Signature:** `getSelector() : String` 570 | 571 | **Description:** Returns the DOM element selector where to mount payment methods and/or express checkout buttons. 572 | 573 | **Returns:** 574 | 575 | DOM element selector 576 | 577 | --- 578 | 579 | ### getSetupFutureUsage 580 | 581 | **Signature:** `getSetupFutureUsage() : boolean` 582 | 583 | **Description:** Returns true if the payment method should be always saved for future use off session, or false if the payment method should be only saved for future use on session when appropriate. 584 | 585 | **Returns:** 586 | 587 | true if the payment method should be always saved for future use off session, false if the payment method should be only saved for future use on session when appropriate. 588 | 589 | --- 590 | 591 | ### getStatementDescriptor 592 | 593 | **Signature:** `getStatementDescriptor() : String` 594 | 595 | **Description:** Returns the complete description that appears on your customers' statements for payments made by this request, or null if the default statement descriptor for your account will be used. 596 | 597 | **Returns:** 598 | 599 | statement descriptor for payments made by this request, or null if the account default will be used 600 | 601 | --- 602 | 603 | ### setBasketData 604 | 605 | **Signature:** `setBasketData(basketData : Object) : void` 606 | 607 | **Description:** Sets the data used to prepare the shopper basket when a Buy Now button is tapped. For convenience this method accepts a JS object to set all of the following properties at once: sku - SKU of the product to add exclusively to the basket (required) quantity - integer quantity of the product, default is 1 shippingMethod - ID of the shipping method to set on the shipment, default is the site default shipping method for the basket currency options - JS array containing one JS object per selected product option, default is no selected options id - product option ID valueId - product option value ID The following example shows how to set all of the supported basket data. request.setBasketData({ sku: 'tv-pdp-6010fdM', quantity: 1, shippingMethod: '001', options: [{ id: 'tvWarranty', valueId: '000' }] }); 608 | 609 | **Parameters:** 610 | 611 | - `basketData`: JS object containing the basket data 612 | 613 | **See Also:** 614 | 615 | getBasketData() 616 | 617 | --- 618 | 619 | ### setBillingDetails 620 | 621 | **Signature:** `setBillingDetails(billingDetails : Object) : void` 622 | 623 | **Description:** Sets the billing details to use when a Stripe PaymentMethod is created. For convenience this method accepts a JS object to set all details at once. The following example shows how to set details including address. request.setBillingDetails({ address: { city: 'Wien', country: 'AT', line1: 'Opernring 2', postal_code: '1010' }, email: '[email protected]', name: 'Johann Hummel' }); For more information on the available billing details see the Stripe create PaymentMethod API documentation. 624 | 625 | **Parameters:** 626 | 627 | - `billingDetails`: JS object containing the billing details 628 | 629 | --- 630 | 631 | ### setCardCaptureAutomatic 632 | 633 | **Signature:** `setCardCaptureAutomatic(cardCaptureAutomatic : boolean) : void` 634 | 635 | **Description:** Sets if the credit card payment should be automatically captured at the time of the sale. 636 | 637 | **Parameters:** 638 | 639 | - `cardCaptureAutomatic`: true if the credit card payment should be automatically captured at the time of the sale, or false if the credit card payment should be captured later. 640 | 641 | --- 642 | 643 | ### setOptions 644 | 645 | **Signature:** `setOptions(options : Object) : void` 646 | 647 | **Description:** Sets the payment request options to use when a Buy Now button is tapped. For convenience this method accepts a JS object to set all options at once. The following example shows how to set options including currency, labels, and amounts, in B2C Commerce API format. request.setOptions({ currency: 'GBP', total: { label: 'Total', amount: '26.44' }, displayItems: [{ label: 'Subtotal', amount: '19.19' }, { label: 'Tax', amount: '1.26' }, { label: 'Ground', amount: '5.99' }], requestPayerPhone: false, shippingOptions: [{ id: 'GBP001', label: 'Ground', detail: 'Order received within 7-10 business days', amount: '5.99' }] }); The total option must match the total that will result from preparing the shopper basket using the data provided to setBasketData(Object) in this request. The id of each JS object in the shippingOptions array must equal the ID of the corresponding site shipping method that the shopper may select in the browser payment app. For more information on the available payment request options see the Stripe Payment Request object API documentation. Note: The Stripe Payment Request country option will be set automatically to the country of the Salesforce Payments account associated with the Commerce Cloud instance and is not included here. 648 | 649 | **Parameters:** 650 | 651 | - `options`: JS object containing the payment request options 652 | 653 | --- 654 | 655 | ### setPayPalButtonsOptions 656 | 657 | **Signature:** `setPayPalButtonsOptions(options : Object) : void` 658 | 659 | **Description:** Sets the the options to pass into the paypal.Buttons call. For more information see the PayPal Buttons API documentation. 660 | 661 | **Parameters:** 662 | 663 | - `options`: JS object containing the options 664 | 665 | --- 666 | 667 | ### setPayPalShippingPreference 668 | 669 | **Signature:** `setPayPalShippingPreference(shippingPreference : String) : void` 670 | 671 | **Description:** Sets the PayPal order application context shipping_preference value. For more information see the PayPal Orders API documentation. 672 | 673 | **Parameters:** 674 | 675 | - `shippingPreference`: constant indicating the shipping preference 676 | 677 | **See Also:** 678 | 679 | PAYPAL_SHIPPING_PREFERENCE_GET_FROM_FILE 680 | PAYPAL_SHIPPING_PREFERENCE_NO_SHIPPING 681 | PAYPAL_SHIPPING_PREFERENCE_SET_PROVIDED_ADDRESS 682 | 683 | --- 684 | 685 | ### setPayPalUserAction 686 | 687 | **Signature:** `setPayPalUserAction(userAction : String) : void` 688 | 689 | **Description:** Sets the PayPal order application context user_action value. For more information see the PayPal Orders API documentation. 690 | 691 | **Parameters:** 692 | 693 | - `userAction`: constant indicating the user action 694 | 695 | **See Also:** 696 | 697 | PAYPAL_USER_ACTION_CONTINUE 698 | PAYPAL_USER_ACTION_PAY_NOW 699 | 700 | --- 701 | 702 | ### setReturnController 703 | 704 | **Signature:** `setReturnController(returnController : String) : void` 705 | 706 | **Description:** Sets the controller to which to redirect when the shopper returns from a 3rd party payment website. Default is the controller for the current page. 707 | 708 | **Parameters:** 709 | 710 | - `returnController`: return controller, such as "Cart-Show" 711 | 712 | --- 713 | 714 | ### setSavePaymentMethodEnabled 715 | 716 | **Signature:** `setSavePaymentMethodEnabled(savePaymentMethodEnabled : boolean) : void` 717 | 718 | **Description:** Sets if mounted components may provide a control for the shopper to save their payment method for later use. When set to false no control will be provided. When set to true a control may be provided, if applicable for the shopper and presented payment method, but is not guaranteed. 719 | 720 | **Parameters:** 721 | 722 | - `savePaymentMethodEnabled`: if mounted components may provide a control for the shopper to save their payment method 723 | 724 | --- 725 | 726 | ### setSetupFutureUsage 727 | 728 | **Signature:** `setSetupFutureUsage(setupFutureUsage : boolean) : void` 729 | 730 | **Description:** Sets if the payment method should be always saved for future use off session. 731 | 732 | **Parameters:** 733 | 734 | - `setupFutureUsage`: true if the payment method should be always saved for future use off session, or false if the payment method should be only saved for future use on session when appropriate. 735 | 736 | --- 737 | 738 | ### setStatementDescriptor 739 | 740 | **Signature:** `setStatementDescriptor(statementDescriptor : String) : void` 741 | 742 | **Description:** Sets the complete description that appears on your customers' statements for payments made by this request. Set this to null to use the default statement descriptor for your account. 743 | 744 | **Parameters:** 745 | 746 | - `statementDescriptor`: statement descriptor for payments made by this request, or null to use the account default 747 | 748 | --- 749 | 750 | ### setStripeCreateElementOptions 751 | 752 | **Signature:** `setStripeCreateElementOptions(element : String, options : Object) : void` 753 | 754 | **Description:** Sets the the options to pass into the Stripe elements.create call for the given element type. For more information see the Stripe Elements API documentation. 755 | 756 | **Parameters:** 757 | 758 | - `element`: name of the Stripe element whose creation to configure 759 | - `options`: JS object containing the options 760 | 761 | **See Also:** 762 | 763 | ELEMENT_AFTERPAY_CLEARPAY_MESSAGE 764 | ELEMENT_CARD_CVC 765 | ELEMENT_CARD_EXPIRY 766 | ELEMENT_CARD_NUMBER 767 | ELEMENT_EPS_BANK 768 | ELEMENT_IBAN 769 | ELEMENT_IDEAL_BANK 770 | ELEMENT_PAYMENT_REQUEST_BUTTON 771 | 772 | --- 773 | 774 | ### setStripeElementsOptions 775 | 776 | **Signature:** `setStripeElementsOptions(options : Object) : void` 777 | 778 | **Description:** Sets the the options to pass into the stripe.elements call. For more information see the Stripe Elements API documentation. 779 | 780 | **Parameters:** 781 | 782 | - `options`: JS object containing the options 783 | 784 | --- ``` -------------------------------------------------------------------------------- /docs/dw_catalog/Variant.md: -------------------------------------------------------------------------------- ```markdown 1 | ## Package: dw.catalog 2 | 3 | # Class Variant 4 | 5 | ## Inheritance Hierarchy 6 | 7 | - Object 8 | - dw.object.PersistentObject 9 | - dw.object.ExtensibleObject 10 | - dw.catalog.Product 11 | - dw.catalog.Variant 12 | 13 | ## Description 14 | 15 | Represents a variant of a product variation. If the variant does not define an own value, the value is retrieved by fallback from variation groups (sorted by their position) or the variation master. 16 | 17 | ## Properties 18 | 19 | ### allProductLinks 20 | 21 | **Type:** Collection (Read Only) 22 | 23 | All product links of the product variant. 24 | 25 | If the variant does not define any product links, the product links are retrieved 26 | from the assigned variation groups, sorted by their position. 27 | 28 | If none of the variation groups define any product links, the product links are 29 | retrieved from the master product. 30 | 31 | ### brand 32 | 33 | **Type:** String (Read Only) 34 | 35 | The brand of the product variant. 36 | 37 | If the variant does not define an own value for 'brand', the value is retrieved 38 | from the assigned variation groups, sorted by their position. 39 | 40 | If none of the variation groups define a value for 'brand', the value of 41 | the master product is returned. 42 | 43 | ### classificationCategory 44 | 45 | **Type:** Category (Read Only) 46 | 47 | The classification category of the product variant. 48 | 49 | Please note that the classification category is always inherited 50 | from the master and cannot be overridden by the variant. 51 | 52 | ### custom 53 | 54 | **Type:** CustomAttributes (Read Only) 55 | 56 | The custom attributes of the variant. 57 | 58 | Custom attributes are inherited from the master product and can 59 | be overridden by the variant. 60 | 61 | ### EAN 62 | 63 | **Type:** String (Read Only) 64 | 65 | The EAN of the product variant. 66 | 67 | If the variant does not define an own value for 'EAN', the value is retrieved 68 | from the assigned variation groups, sorted by their position. 69 | 70 | If none of the variation groups define a value for 'EAN', the value of 71 | the master product is returned. 72 | 73 | ### image 74 | 75 | **Type:** MediaFile (Read Only) 76 | 77 | The image of the product variant. 78 | 79 | If the variant does not define an own value for 'image', the value is retrieved 80 | from the assigned variation groups, sorted by their position. 81 | 82 | If none of the variation groups define a value for 'image', the value of 83 | the master product is returned. 84 | 85 | ### longDescription 86 | 87 | **Type:** MarkupText (Read Only) 88 | 89 | The long description of the product variant. 90 | 91 | If the variant does not define an own value for 'longDescription', the value is retrieved 92 | from the assigned variation groups, sorted by their position. 93 | 94 | If none of the variation groups define a value for 'longDescription', the value of 95 | the master product is returned. 96 | 97 | ### manufacturerName 98 | 99 | **Type:** String (Read Only) 100 | 101 | The manufacturer name of the product variant. 102 | 103 | If the variant does not define an own value for 'manufacturerName', the value is retrieved 104 | from the assigned variation groups, sorted by their position. 105 | 106 | If none of the variation groups define a value for 'manufacturerName', the value of 107 | the master product is returned. 108 | 109 | ### manufacturerSKU 110 | 111 | **Type:** String (Read Only) 112 | 113 | The manufacturer sku of the product variant. 114 | 115 | If the variant does not define an own value for 'manufacturerSKU', the value is retrieved 116 | from the assigned variation groups, sorted by their position. 117 | 118 | If none of the variation groups define a value for 'manufacturerSKU', the value of 119 | the master product is returned. 120 | 121 | ### masterProduct 122 | 123 | **Type:** Product (Read Only) 124 | 125 | The ProductMaster for this mastered product. 126 | 127 | ### name 128 | 129 | **Type:** String (Read Only) 130 | 131 | The name of the product variant. 132 | 133 | If the variant does not define an own value for 'name', the value is retrieved 134 | from the assigned variation groups, sorted by their position. 135 | 136 | If none of the variation groups define a value for 'name', the value of 137 | the master product is returned. 138 | 139 | ### onlineFrom 140 | 141 | **Type:** Date (Read Only) 142 | 143 | The onlineFrom date of the product variant. 144 | 145 | If the variant does not define an own value for 'onlineFrom', the value is retrieved 146 | from the assigned variation groups, sorted by their position. 147 | 148 | If none of the variation groups define a value for 'onlineFrom', the value of 149 | the master product is returned. 150 | 151 | ### onlineTo 152 | 153 | **Type:** Date (Read Only) 154 | 155 | The onlineTo date of the product variant. 156 | 157 | If the variant does not define an own value for 'onlineTo', the value is retrieved 158 | from the assigned variation groups, sorted by their position. 159 | 160 | If none of the variation groups define a value for 'onlineTo', the value of 161 | the master product is returned. 162 | 163 | ### optionProduct 164 | 165 | **Type:** boolean (Read Only) 166 | 167 | Returns 'true' if the variant has any options, otherwise 'false'. 168 | Method also returns 'true' if the variant has not any options, 169 | but the related variation groups (sorted by position) or 170 | master product has options. 171 | 172 | ### pageDescription 173 | 174 | **Type:** String (Read Only) 175 | 176 | The pageDescription of the product variant. 177 | 178 | If the variant does not define an own value for 'pageDescription', the value is retrieved 179 | from the assigned variation groups, sorted by their position. 180 | 181 | If none of the variation groups define a value for 'pageDescription', the value of 182 | the master product is returned. 183 | 184 | ### pageKeywords 185 | 186 | **Type:** String (Read Only) 187 | 188 | The pageKeywords of the product variant. 189 | 190 | If the variant does not define an own value for 'pageKeywords', the value is retrieved 191 | from the assigned variation groups, sorted by their position. 192 | 193 | If none of the variation groups define a value for 'pageKeywords', the value of 194 | the master product is returned. 195 | 196 | ### pageTitle 197 | 198 | **Type:** String (Read Only) 199 | 200 | The pageTitle of the product variant. 201 | 202 | If the variant does not define an own value for 'pageTitle', the value is retrieved 203 | from the assigned variation groups, sorted by their position. 204 | 205 | If none of the variation groups define a value for 'pageTitle', the value of 206 | the master product is returned. 207 | 208 | ### pageURL 209 | 210 | **Type:** String (Read Only) 211 | 212 | The pageURL of the product variant. 213 | 214 | If the variant does not define an own value for 'pageURL', the value is retrieved 215 | from the assigned variation groups, sorted by their position. 216 | 217 | If none of the variation groups define a value for 'pageURL', the value of 218 | the master product is returned. 219 | 220 | ### productLinks 221 | 222 | **Type:** Collection (Read Only) 223 | 224 | All product links of the product variant for which the target 225 | product is assigned to the current site catalog. 226 | 227 | If the variant does not define any product links, the product links are retrieved 228 | from the assigned variation groups, sorted by their position 229 | 230 | If none of the variation groups define any product links, the product links are retrieved 231 | from the master product. 232 | 233 | ### shortDescription 234 | 235 | **Type:** MarkupText (Read Only) 236 | 237 | The short description of the product variant. 238 | 239 | If the variant does not define an own value for 'shortDescription', the value is retrieved 240 | from the assigned variation groups, sorted by their position. 241 | 242 | If none of the variation groups define a value for 'shortDescription', the value of 243 | the master product is returned. 244 | 245 | ### taxClassID 246 | 247 | **Type:** String (Read Only) 248 | 249 | The tax class id of the product variant. 250 | 251 | If the variant does not define an own value for 'taxClassID', the value is retrieved 252 | from the assigned variation groups, sorted by their position. 253 | 254 | If none of the variation groups define a value for 'taxClassID', the value of 255 | the master product is returned. 256 | 257 | ### template 258 | 259 | **Type:** String (Read Only) 260 | 261 | The rendering template name of the product variant. 262 | 263 | If the variant does not define an own value for 'template', the value is retrieved 264 | from the assigned variation groups, sorted by their position. 265 | 266 | If none of the variation groups define a value for 'template', the value of 267 | the master product is returned. 268 | 269 | ### thumbnail 270 | 271 | **Type:** MediaFile (Read Only) 272 | 273 | The thumbnail image of the product variant. 274 | 275 | If the variant does not define an own value for 'thumbnail', the value is retrieved 276 | from the assigned variation groups, sorted by their position. 277 | 278 | If none of the variation groups define a value for 'thumbnail', the value of 279 | the master product is returned. 280 | 281 | ### unit 282 | 283 | **Type:** String (Read Only) 284 | 285 | The sales unit of the product variant as defined by the 286 | master product. 287 | 288 | If the variant does not define an own value for 'unit', the value is retrieved 289 | from the assigned variation groups, sorted by their position. 290 | 291 | If none of the variation groups define a value for 'unit', the value of 292 | the master product is returned. 293 | 294 | ### unitQuantity 295 | 296 | **Type:** Quantity (Read Only) 297 | 298 | The unitQuantity of the product variant as defined by the 299 | master product. 300 | 301 | If the variant does not define an own value for 'unitQuantity', the value is retrieved 302 | from the assigned variation groups, sorted by their position. 303 | 304 | If none of the variation groups define a value for 'unitQuantity', the value of 305 | the master product is returned. 306 | 307 | ### UPC 308 | 309 | **Type:** String (Read Only) 310 | 311 | The UPC of the product variant. 312 | 313 | If the variant does not define an own value for 'UPC', the value is retrieved 314 | from the assigned variation groups, sorted by their position. 315 | 316 | If none of the variation groups define a value for 'UPC', the value of 317 | the master product is returned. 318 | 319 | ## Constructor Summary 320 | 321 | ## Method Summary 322 | 323 | ### getAllProductLinks 324 | 325 | **Signature:** `getAllProductLinks() : Collection` 326 | 327 | Returns all product links of the product variant. 328 | 329 | ### getAllProductLinks 330 | 331 | **Signature:** `getAllProductLinks(type : Number) : Collection` 332 | 333 | Returns all product links of the specified type of the product variant. 334 | 335 | ### getBrand 336 | 337 | **Signature:** `getBrand() : String` 338 | 339 | Returns the brand of the product variant. 340 | 341 | ### getClassificationCategory 342 | 343 | **Signature:** `getClassificationCategory() : Category` 344 | 345 | Returns the classification category of the product variant. 346 | 347 | ### getCustom 348 | 349 | **Signature:** `getCustom() : CustomAttributes` 350 | 351 | Returns the custom attributes of the variant. 352 | 353 | ### getEAN 354 | 355 | **Signature:** `getEAN() : String` 356 | 357 | Returns the EAN of the product variant. 358 | 359 | ### getImage 360 | 361 | **Signature:** `getImage() : MediaFile` 362 | 363 | Returns the image of the product variant. 364 | 365 | ### getLongDescription 366 | 367 | **Signature:** `getLongDescription() : MarkupText` 368 | 369 | Returns the long description of the product variant. 370 | 371 | ### getManufacturerName 372 | 373 | **Signature:** `getManufacturerName() : String` 374 | 375 | Returns the manufacturer name of the product variant. 376 | 377 | ### getManufacturerSKU 378 | 379 | **Signature:** `getManufacturerSKU() : String` 380 | 381 | Returns the manufacturer sku of the product variant. 382 | 383 | ### getMasterProduct 384 | 385 | **Signature:** `getMasterProduct() : Product` 386 | 387 | Returns the ProductMaster for this mastered product. 388 | 389 | ### getName 390 | 391 | **Signature:** `getName() : String` 392 | 393 | Returns the name of the product variant. 394 | 395 | ### getOnlineFrom 396 | 397 | **Signature:** `getOnlineFrom() : Date` 398 | 399 | Returns the onlineFrom date of the product variant. 400 | 401 | ### getOnlineTo 402 | 403 | **Signature:** `getOnlineTo() : Date` 404 | 405 | Returns the onlineTo date of the product variant. 406 | 407 | ### getPageDescription 408 | 409 | **Signature:** `getPageDescription() : String` 410 | 411 | Returns the pageDescription of the product variant. 412 | 413 | ### getPageKeywords 414 | 415 | **Signature:** `getPageKeywords() : String` 416 | 417 | Returns the pageKeywords of the product variant. 418 | 419 | ### getPageTitle 420 | 421 | **Signature:** `getPageTitle() : String` 422 | 423 | Returns the pageTitle of the product variant. 424 | 425 | ### getPageURL 426 | 427 | **Signature:** `getPageURL() : String` 428 | 429 | Returns the pageURL of the product variant. 430 | 431 | ### getProductLinks 432 | 433 | **Signature:** `getProductLinks() : Collection` 434 | 435 | Returns all product links of the product variant for which the target product is assigned to the current site catalog. 436 | 437 | ### getProductLinks 438 | 439 | **Signature:** `getProductLinks(type : Number) : Collection` 440 | 441 | Returns all product links of the specified type of the product variant for which the target product is assigned to the current site catalog. 442 | 443 | ### getRecommendations 444 | 445 | **Signature:** `getRecommendations(type : Number) : Collection` 446 | 447 | Retrieve the sorted collection of recommendations of the specified type for this product variant. 448 | 449 | ### getShortDescription 450 | 451 | **Signature:** `getShortDescription() : MarkupText` 452 | 453 | Returns the short description of the product variant. 454 | 455 | ### getTaxClassID 456 | 457 | **Signature:** `getTaxClassID() : String` 458 | 459 | Returns the tax class id of the product variant. 460 | 461 | ### getTemplate 462 | 463 | **Signature:** `getTemplate() : String` 464 | 465 | Returns the rendering template name of the product variant. 466 | 467 | ### getThumbnail 468 | 469 | **Signature:** `getThumbnail() : MediaFile` 470 | 471 | Returns the thumbnail image of the product variant. 472 | 473 | ### getUnit 474 | 475 | **Signature:** `getUnit() : String` 476 | 477 | Returns the sales unit of the product variant as defined by the master product. 478 | 479 | ### getUnitQuantity 480 | 481 | **Signature:** `getUnitQuantity() : Quantity` 482 | 483 | Returns the unitQuantity of the product variant as defined by the master product. 484 | 485 | ### getUPC 486 | 487 | **Signature:** `getUPC() : String` 488 | 489 | Returns the UPC of the product variant. 490 | 491 | ### isOptionProduct 492 | 493 | **Signature:** `isOptionProduct() : boolean` 494 | 495 | Returns 'true' if the variant has any options, otherwise 'false'. 496 | 497 | ## Method Detail 498 | 499 | ## Method Details 500 | 501 | ### getAllProductLinks 502 | 503 | **Signature:** `getAllProductLinks() : Collection` 504 | 505 | **Description:** Returns all product links of the product variant. If the variant does not define any product links, the product links are retrieved from the assigned variation groups, sorted by their position. If none of the variation groups define any product links, the product links are retrieved from the master product. 506 | 507 | **Returns:** 508 | 509 | All product links of the variant, variation group or master 510 | 511 | --- 512 | 513 | ### getAllProductLinks 514 | 515 | **Signature:** `getAllProductLinks(type : Number) : Collection` 516 | 517 | **Description:** Returns all product links of the specified type of the product variant. If the variant does not define any product links of the specified type, the product links are retrieved for the specified type from the assigned variation groups, sorted by their position. If none of the variation groups define any product links of the specified type, the product links are retrieved for the specified type from the master product. 518 | 519 | **Parameters:** 520 | 521 | - `type`: Type of the product link 522 | 523 | **Returns:** 524 | 525 | Product links of specified type of the variant, variation group or master 526 | 527 | --- 528 | 529 | ### getBrand 530 | 531 | **Signature:** `getBrand() : String` 532 | 533 | **Description:** Returns the brand of the product variant. If the variant does not define an own value for 'brand', the value is retrieved from the assigned variation groups, sorted by their position. If none of the variation groups define a value for 'brand', the value of the master product is returned. 534 | 535 | **Returns:** 536 | 537 | The brand of the variant, variation group or master 538 | 539 | --- 540 | 541 | ### getClassificationCategory 542 | 543 | **Signature:** `getClassificationCategory() : Category` 544 | 545 | **Description:** Returns the classification category of the product variant. Please note that the classification category is always inherited from the master and cannot be overridden by the variant. 546 | 547 | **Returns:** 548 | 549 | The classification category as defined for the master product of the variant 550 | 551 | --- 552 | 553 | ### getCustom 554 | 555 | **Signature:** `getCustom() : CustomAttributes` 556 | 557 | **Description:** Returns the custom attributes of the variant. Custom attributes are inherited from the master product and can be overridden by the variant. 558 | 559 | **Returns:** 560 | 561 | the custom attributes of the variant. 562 | 563 | --- 564 | 565 | ### getEAN 566 | 567 | **Signature:** `getEAN() : String` 568 | 569 | **Description:** Returns the EAN of the product variant. If the variant does not define an own value for 'EAN', the value is retrieved from the assigned variation groups, sorted by their position. If none of the variation groups define a value for 'EAN', the value of the master product is returned. 570 | 571 | **Returns:** 572 | 573 | The EAN of the variant, variation group or master 574 | 575 | --- 576 | 577 | ### getImage 578 | 579 | **Signature:** `getImage() : MediaFile` 580 | 581 | **Description:** Returns the image of the product variant. If the variant does not define an own value for 'image', the value is retrieved from the assigned variation groups, sorted by their position. If none of the variation groups define a value for 'image', the value of the master product is returned. 582 | 583 | **Returns:** 584 | 585 | The image of the variant, variation group or master 586 | 587 | --- 588 | 589 | ### getLongDescription 590 | 591 | **Signature:** `getLongDescription() : MarkupText` 592 | 593 | **Description:** Returns the long description of the product variant. If the variant does not define an own value for 'longDescription', the value is retrieved from the assigned variation groups, sorted by their position. If none of the variation groups define a value for 'longDescription', the value of the master product is returned. 594 | 595 | **Returns:** 596 | 597 | The long description of the variant, variation group or master 598 | 599 | --- 600 | 601 | ### getManufacturerName 602 | 603 | **Signature:** `getManufacturerName() : String` 604 | 605 | **Description:** Returns the manufacturer name of the product variant. If the variant does not define an own value for 'manufacturerName', the value is retrieved from the assigned variation groups, sorted by their position. If none of the variation groups define a value for 'manufacturerName', the value of the master product is returned. 606 | 607 | **Returns:** 608 | 609 | The manufacturer name of the variant, variation group or master 610 | 611 | --- 612 | 613 | ### getManufacturerSKU 614 | 615 | **Signature:** `getManufacturerSKU() : String` 616 | 617 | **Description:** Returns the manufacturer sku of the product variant. If the variant does not define an own value for 'manufacturerSKU', the value is retrieved from the assigned variation groups, sorted by their position. If none of the variation groups define a value for 'manufacturerSKU', the value of the master product is returned. 618 | 619 | **Returns:** 620 | 621 | The manufacturer sku of the variant, variation group or master 622 | 623 | --- 624 | 625 | ### getMasterProduct 626 | 627 | **Signature:** `getMasterProduct() : Product` 628 | 629 | **Description:** Returns the ProductMaster for this mastered product. 630 | 631 | **Returns:** 632 | 633 | the ProductMaster of this mastered product 634 | 635 | --- 636 | 637 | ### getName 638 | 639 | **Signature:** `getName() : String` 640 | 641 | **Description:** Returns the name of the product variant. If the variant does not define an own value for 'name', the value is retrieved from the assigned variation groups, sorted by their position. If none of the variation groups define a value for 'name', the value of the master product is returned. 642 | 643 | **Returns:** 644 | 645 | The name of the variant, variation group or master 646 | 647 | --- 648 | 649 | ### getOnlineFrom 650 | 651 | **Signature:** `getOnlineFrom() : Date` 652 | 653 | **Description:** Returns the onlineFrom date of the product variant. If the variant does not define an own value for 'onlineFrom', the value is retrieved from the assigned variation groups, sorted by their position. If none of the variation groups define a value for 'onlineFrom', the value of the master product is returned. 654 | 655 | **Returns:** 656 | 657 | The onlineFrom date of the variant, variation group or master 658 | 659 | --- 660 | 661 | ### getOnlineTo 662 | 663 | **Signature:** `getOnlineTo() : Date` 664 | 665 | **Description:** Returns the onlineTo date of the product variant. If the variant does not define an own value for 'onlineTo', the value is retrieved from the assigned variation groups, sorted by their position. If none of the variation groups define a value for 'onlineTo', the value of the master product is returned. 666 | 667 | **Returns:** 668 | 669 | The onlineTo date of the variant, variation group or master 670 | 671 | --- 672 | 673 | ### getPageDescription 674 | 675 | **Signature:** `getPageDescription() : String` 676 | 677 | **Description:** Returns the pageDescription of the product variant. If the variant does not define an own value for 'pageDescription', the value is retrieved from the assigned variation groups, sorted by their position. If none of the variation groups define a value for 'pageDescription', the value of the master product is returned. 678 | 679 | **Returns:** 680 | 681 | The pageDescription of the variant, variation group or master 682 | 683 | --- 684 | 685 | ### getPageKeywords 686 | 687 | **Signature:** `getPageKeywords() : String` 688 | 689 | **Description:** Returns the pageKeywords of the product variant. If the variant does not define an own value for 'pageKeywords', the value is retrieved from the assigned variation groups, sorted by their position. If none of the variation groups define a value for 'pageKeywords', the value of the master product is returned. 690 | 691 | **Returns:** 692 | 693 | The pageKeywords of the variant, variation group or master 694 | 695 | --- 696 | 697 | ### getPageTitle 698 | 699 | **Signature:** `getPageTitle() : String` 700 | 701 | **Description:** Returns the pageTitle of the product variant. If the variant does not define an own value for 'pageTitle', the value is retrieved from the assigned variation groups, sorted by their position. If none of the variation groups define a value for 'pageTitle', the value of the master product is returned. 702 | 703 | **Returns:** 704 | 705 | The pageTitle of the variant, variation group or master 706 | 707 | --- 708 | 709 | ### getPageURL 710 | 711 | **Signature:** `getPageURL() : String` 712 | 713 | **Description:** Returns the pageURL of the product variant. If the variant does not define an own value for 'pageURL', the value is retrieved from the assigned variation groups, sorted by their position. If none of the variation groups define a value for 'pageURL', the value of the master product is returned. 714 | 715 | **Returns:** 716 | 717 | The pageURL of the variant, variation group or master 718 | 719 | --- 720 | 721 | ### getProductLinks 722 | 723 | **Signature:** `getProductLinks() : Collection` 724 | 725 | **Description:** Returns all product links of the product variant for which the target product is assigned to the current site catalog. If the variant does not define any product links, the product links are retrieved from the assigned variation groups, sorted by their position If none of the variation groups define any product links, the product links are retrieved from the master product. 726 | 727 | **Returns:** 728 | 729 | Product links of the variant, variation group or master 730 | 731 | --- 732 | 733 | ### getProductLinks 734 | 735 | **Signature:** `getProductLinks(type : Number) : Collection` 736 | 737 | **Description:** Returns all product links of the specified type of the product variant for which the target product is assigned to the current site catalog. If the variant does not define any product links of the specified type, the product links are retrieved for the specified type from the assigned variation groups, sorted by their position If none of the variation groups define any product links of the specified type, the product links are retrieved for the specified type from the master product. 738 | 739 | **Parameters:** 740 | 741 | - `type`: Type of the product link 742 | 743 | **Returns:** 744 | 745 | Product links of specified type of the variant, variation group or master 746 | 747 | --- 748 | 749 | ### getRecommendations 750 | 751 | **Signature:** `getRecommendations(type : Number) : Collection` 752 | 753 | **Description:** Retrieve the sorted collection of recommendations of the specified type for this product variant. The types (cross-sell, up-sell, etc) are enumerated in the dw.catalog.Recommendation class. Only recommendations which are stored in the current site catalog are returned. Furthermore, a recommendation is only returned if the target of the recommendation is assigned to the current site catalog. If the variant does not define any recommendations, recommendations are retrieved from the assigned variation groups, sorted by their position. If none of the variation groups define any recommendations, the recommendations of the master are returned. 754 | 755 | **Parameters:** 756 | 757 | - `type`: the recommendation type 758 | 759 | **Returns:** 760 | 761 | the sorted collection, never null but possibly empty. 762 | 763 | --- 764 | 765 | ### getShortDescription 766 | 767 | **Signature:** `getShortDescription() : MarkupText` 768 | 769 | **Description:** Returns the short description of the product variant. If the variant does not define an own value for 'shortDescription', the value is retrieved from the assigned variation groups, sorted by their position. If none of the variation groups define a value for 'shortDescription', the value of the master product is returned. 770 | 771 | **Returns:** 772 | 773 | The short description of the variant, variation group or master 774 | 775 | --- 776 | 777 | ### getTaxClassID 778 | 779 | **Signature:** `getTaxClassID() : String` 780 | 781 | **Description:** Returns the tax class id of the product variant. If the variant does not define an own value for 'taxClassID', the value is retrieved from the assigned variation groups, sorted by their position. If none of the variation groups define a value for 'taxClassID', the value of the master product is returned. 782 | 783 | **Returns:** 784 | 785 | The tax class id of the variant, variation group or master 786 | 787 | --- 788 | 789 | ### getTemplate 790 | 791 | **Signature:** `getTemplate() : String` 792 | 793 | **Description:** Returns the rendering template name of the product variant. If the variant does not define an own value for 'template', the value is retrieved from the assigned variation groups, sorted by their position. If none of the variation groups define a value for 'template', the value of the master product is returned. 794 | 795 | **Returns:** 796 | 797 | The rendering template name of the variant, variation group or master 798 | 799 | --- 800 | 801 | ### getThumbnail 802 | 803 | **Signature:** `getThumbnail() : MediaFile` 804 | 805 | **Description:** Returns the thumbnail image of the product variant. If the variant does not define an own value for 'thumbnail', the value is retrieved from the assigned variation groups, sorted by their position. If none of the variation groups define a value for 'thumbnail', the value of the master product is returned. 806 | 807 | **Returns:** 808 | 809 | The thumbnail image of the variant, variation group or master 810 | 811 | --- 812 | 813 | ### getUnit 814 | 815 | **Signature:** `getUnit() : String` 816 | 817 | **Description:** Returns the sales unit of the product variant as defined by the master product. If the variant does not define an own value for 'unit', the value is retrieved from the assigned variation groups, sorted by their position. If none of the variation groups define a value for 'unit', the value of the master product is returned. 818 | 819 | **Returns:** 820 | 821 | The sales unit of the variant, variation group or master 822 | 823 | --- 824 | 825 | ### getUnitQuantity 826 | 827 | **Signature:** `getUnitQuantity() : Quantity` 828 | 829 | **Description:** Returns the unitQuantity of the product variant as defined by the master product. If the variant does not define an own value for 'unitQuantity', the value is retrieved from the assigned variation groups, sorted by their position. If none of the variation groups define a value for 'unitQuantity', the value of the master product is returned. 830 | 831 | **Returns:** 832 | 833 | The unitQuantity of the variant, variation group or master 834 | 835 | --- 836 | 837 | ### getUPC 838 | 839 | **Signature:** `getUPC() : String` 840 | 841 | **Description:** Returns the UPC of the product variant. If the variant does not define an own value for 'UPC', the value is retrieved from the assigned variation groups, sorted by their position. If none of the variation groups define a value for 'UPC', the value of the master product is returned. 842 | 843 | **Returns:** 844 | 845 | The UPC of the variant, variation group or master 846 | 847 | --- 848 | 849 | ### isOptionProduct 850 | 851 | **Signature:** `isOptionProduct() : boolean` 852 | 853 | **Description:** Returns 'true' if the variant has any options, otherwise 'false'. Method also returns 'true' if the variant has not any options, but the related variation groups (sorted by position) or master product has options. 854 | 855 | **Returns:** 856 | 857 | true if the variant has any options, false otherwise. 858 | 859 | --- ``` -------------------------------------------------------------------------------- /docs/TopLevel/XML.md: -------------------------------------------------------------------------------- ```markdown 1 | ## Package: TopLevel 2 | 3 | # Class XML 4 | 5 | ## Inheritance Hierarchy 6 | 7 | - Object 8 | - XML 9 | 10 | ## Description 11 | 12 | The XML object contains functions and properties for working with XML instances. The XML object implements the powerful XML-handling standards defined in the ECMA-357 specification (known as "E4X"). Use the toXMLString() method to return a string representation of the XML object regardless of whether the XML object has simple content or complex content. Do not create large XML objects in memory to avoid out-of-memory conditions. When dealing with XML streams use XMLStreamReader and XMLStreamWriter. The following example shows how: var id : String = "p42"; var pname : String = "a product"; // use E4X syntax var product : XML = <product id={id}> <name>{pname}</name> <shortdesc></shortdesc> </product>; product.shortdesc = "a fine product"; product.longdesc = "this is a fine product"; var xmlString = product.toXMLString(); fileWriter.write(xmlString); The code above will write the following to file: <product id="p42"> <name>a product</name> <shortdesc>a fine product</shortdesc> <longdesc>this is a fine product</longdesc> </product> Do not create large XML objects in memory to avoid out-of-memory conditions. When dealing with XML streams use XMLStreamReader and XMLStreamWriter. 13 | 14 | ## Properties 15 | 16 | ## Constructor Summary 17 | 18 | XML() Creates a new XML object. 19 | 20 | XML(value : Object) Creates a new XML object. 21 | 22 | ## Method Summary 23 | 24 | ### addNamespace 25 | 26 | **Signature:** `addNamespace(ns : Object) : XML` 27 | 28 | Adds a namespace to the set of in-scope namespaces for the XML object. 29 | 30 | ### appendChild 31 | 32 | **Signature:** `appendChild(child : Object) : XML` 33 | 34 | Appends the specified child to the end of the object's properties. 35 | 36 | ### attribute 37 | 38 | **Signature:** `attribute(attributeName : String) : XMLList` 39 | 40 | Returns the attribute associated with this XML object that is identified by the specified name. 41 | 42 | ### attributes 43 | 44 | **Signature:** `attributes() : XMLList` 45 | 46 | Returns an XMList of the attributes in this XML Object. 47 | 48 | ### child 49 | 50 | **Signature:** `child(propertyName : Object) : XMLList` 51 | 52 | Returns the children of the XML object based on the specified property name. 53 | 54 | ### childIndex 55 | 56 | **Signature:** `childIndex() : Number` 57 | 58 | Identifies the zero-based index of this XML object within the context of its parent, or -1 if this object has no parent. 59 | 60 | ### children 61 | 62 | **Signature:** `children() : XMLList` 63 | 64 | Returns an XMLList containing the children of this XML object, maintaing the sequence in which they appear. 65 | 66 | ### comments 67 | 68 | **Signature:** `comments() : XMLList` 69 | 70 | Returns the properties of the XML object that contain comments. 71 | 72 | ### contains 73 | 74 | **Signature:** `contains(value : XML) : boolean` 75 | 76 | Returns true if this XML object contains the specified XML object, false otherwise. 77 | 78 | ### copy 79 | 80 | **Signature:** `copy() : XML` 81 | 82 | Returns a copy of the this XML object including duplicate copies of the entire tree of nodes. 83 | 84 | ### defaultSettings 85 | 86 | **Signature:** `static defaultSettings() : Object` 87 | 88 | Returns a new Object with the following properties set to the default values: ignoreComments, ignoreProcessingInstructions, ignoreWhitespace, prettyIndent, and prettyPrinting. 89 | 90 | ### descendants 91 | 92 | **Signature:** `descendants() : XMLList` 93 | 94 | Returns all descendents of the XML object. 95 | 96 | ### descendants 97 | 98 | **Signature:** `descendants(name : String) : XMLList` 99 | 100 | Returns all descendents of the XML object that have the specified name parameter. 101 | 102 | ### elements 103 | 104 | **Signature:** `elements() : XMLList` 105 | 106 | Returns a list of all of the elements of the XML object. 107 | 108 | ### elements 109 | 110 | **Signature:** `elements(name : Object) : XMLList` 111 | 112 | Returns a list of the elements of the XML object using the specified name to constrain the list. 113 | 114 | ### hasComplexContent 115 | 116 | **Signature:** `hasComplexContent() : boolean` 117 | 118 | Returns a Boolean value indicating whether this XML object contains complex content. 119 | 120 | ### hasOwnProperty 121 | 122 | **Signature:** `hasOwnProperty(prop : String) : boolean` 123 | 124 | Returns a Boolean value indicating whether this object has the property specified by prop. 125 | 126 | ### hasSimpleContent 127 | 128 | **Signature:** `hasSimpleContent() : boolean` 129 | 130 | Returns a Boolean value indicating whether this XML object contains simple content. 131 | 132 | ### inScopeNamespaces 133 | 134 | **Signature:** `inScopeNamespaces() : Array` 135 | 136 | Returns an Array of Namespace objects representing the namespaces in scope for this XML object in the context of its parent. 137 | 138 | ### insertChildAfter 139 | 140 | **Signature:** `insertChildAfter(child1 : Object, child2 : Object) : XML` 141 | 142 | Inserts the specified child2 after the specified child1 in this XML object and returns this XML object. 143 | 144 | ### insertChildBefore 145 | 146 | **Signature:** `insertChildBefore(child1 : Object, child2 : Object) : XML` 147 | 148 | Inserts the specified child2 before the specified child1 in this XML object and returns this XML object. 149 | 150 | ### length 151 | 152 | **Signature:** `length() : Number` 153 | 154 | Returns a value of 1 for XML objects. 155 | 156 | ### localName 157 | 158 | **Signature:** `localName() : Object` 159 | 160 | Returns the local name portion of the qualified name of the XML object. 161 | 162 | ### name 163 | 164 | **Signature:** `name() : Object` 165 | 166 | Returns the qualified name for the XML object. 167 | 168 | ### namespace 169 | 170 | **Signature:** `namespace() : Object` 171 | 172 | Returns the namespace associated with the qualified name of this XML object. 173 | 174 | ### namespace 175 | 176 | **Signature:** `namespace(prefix : String) : Object` 177 | 178 | Returns the namespace that matches the specified prefix and that is in scope for the XML object. 179 | 180 | ### namespaceDeclarations 181 | 182 | **Signature:** `namespaceDeclarations() : Array` 183 | 184 | Returns an Array of namespace declarations associated with the XML Obnject in the context of its parent. 185 | 186 | ### nodeKind 187 | 188 | **Signature:** `nodeKind() : String` 189 | 190 | Returns the type of the XML object, such as text, comment, processing-instruction, or attribute. 191 | 192 | ### normalize 193 | 194 | **Signature:** `normalize() : XML` 195 | 196 | Merges adjacent text nodes and eliminates and eliminates empty text nodes for this XML object and all its descendents. 197 | 198 | ### parent 199 | 200 | **Signature:** `parent() : Object` 201 | 202 | Returns the parent of the XML object or null if the XML object does not have a parent. 203 | 204 | ### prependChild 205 | 206 | **Signature:** `prependChild(value : Object) : XML` 207 | 208 | Inserts the specified child into this XML object prior to its existing XML properties and then returns this XML object. 209 | 210 | ### processingInstructions 211 | 212 | **Signature:** `processingInstructions() : XMLList` 213 | 214 | Returns an XMLList containing all the children of this XML object that are processing-instructions. 215 | 216 | ### processingInstructions 217 | 218 | **Signature:** `processingInstructions(name : String) : XMLList` 219 | 220 | Returns an XMLList containing all the children of this XML object that are processing-instructions with the specified name. 221 | 222 | ### propertyIsEnumerable 223 | 224 | **Signature:** `propertyIsEnumerable(property : String) : boolean` 225 | 226 | Returns a Boolean indicating whether the specified property will be included in the set of properties iterated over when this XML object is used in a for..in statement. 227 | 228 | ### removeNamespace 229 | 230 | **Signature:** `removeNamespace(ns : Namespace) : XML` 231 | 232 | Removes the specified namespace from the in scope namespaces of this object and all its descendents, then returns a copy of this XML object. 233 | 234 | ### replace 235 | 236 | **Signature:** `replace(propertyName : String, value : Object) : XML` 237 | 238 | Replaces the XML properties of this XML object specified by propertyName with value and returns this updated XML object. 239 | 240 | ### setChildren 241 | 242 | **Signature:** `setChildren(value : Object) : XML` 243 | 244 | Replaces the XML properties of this XML object with a new set of XML properties from value. 245 | 246 | ### setLocalName 247 | 248 | **Signature:** `setLocalName(name : String) : void` 249 | 250 | Replaces the local name of this XML object with a string constructed from the specified name. 251 | 252 | ### setName 253 | 254 | **Signature:** `setName(name : String) : void` 255 | 256 | Replaces the name of this XML object with a QName or AttributeName constructed from the specified name. 257 | 258 | ### setNamespace 259 | 260 | **Signature:** `setNamespace(ns : Namespace) : void` 261 | 262 | Replaces the namespace associated with the name of this XML object with the specified namespace. 263 | 264 | ### setSettings 265 | 266 | **Signature:** `static setSettings() : void` 267 | 268 | Restores the default settings for the following XML properties: XML.ignoreComments = true XML.ignoreProcessingInstructions = true XML.ignoreWhitespace = true XML.prettyIndent = 2 XML.prettyPrinting = true 269 | 270 | ### setSettings 271 | 272 | **Signature:** `static setSettings(settings : Object) : void` 273 | 274 | Updates the collection of global XML properties: ignoreComments, ignoreProcessingInstructions, ignoreWhitespace, prettyPrinting, prettyIndent, and prettyPrinting. 275 | 276 | ### settings 277 | 278 | **Signature:** `static settings() : Object` 279 | 280 | Returns the collection of global XML properties: ignoreComments, ignoreProcessingInstructions, ignoreWhitespace, prettyPrinting, prettyIndent, and prettyPrinting. 281 | 282 | ### text 283 | 284 | **Signature:** `text() : XMLList` 285 | 286 | Returns an XMLList containing all XML properties of this XML object that represent XML text nodes. 287 | 288 | ### toString 289 | 290 | **Signature:** `toString() : String` 291 | 292 | Returns the String representation of the XML object. 293 | 294 | ### toXMLString 295 | 296 | **Signature:** `toXMLString() : String` 297 | 298 | Returns a XML-encoded String representation of the XML object, including tag and attributed delimiters. 299 | 300 | ### valueOf 301 | 302 | **Signature:** `valueOf() : XML` 303 | 304 | Returns this XML object. 305 | 306 | ## Constructor Detail 307 | 308 | ## Method Detail 309 | 310 | ## Method Details 311 | 312 | ### addNamespace 313 | 314 | **Signature:** `addNamespace(ns : Object) : XML` 315 | 316 | **Description:** Adds a namespace to the set of in-scope namespaces for the XML object. If the namespace already exists in the in-scope namespaces for the XML object, then the prefix of the existing namespace is set to undefined. If ns is a Namespace instance, it is used directly. However, if ns is a QName instance, the input parameter's URI is used to create a new namespace. If ns is not a Namespace or QName instance, ns is converted to a String and a namespace is created from the String. 317 | 318 | **Parameters:** 319 | 320 | - `ns`: the namespace to add to the XML object. 321 | 322 | **Returns:** 323 | 324 | a new XML object, with the namespace added. 325 | 326 | --- 327 | 328 | ### appendChild 329 | 330 | **Signature:** `appendChild(child : Object) : XML` 331 | 332 | **Description:** Appends the specified child to the end of the object's properties. child should be a XML object, an XMLList object or any other data type that will then be converted to a String. 333 | 334 | **Parameters:** 335 | 336 | - `child`: the object to append to this XML object. 337 | 338 | **Returns:** 339 | 340 | the XML object with the child appended. 341 | 342 | --- 343 | 344 | ### attribute 345 | 346 | **Signature:** `attribute(attributeName : String) : XMLList` 347 | 348 | **Description:** Returns the attribute associated with this XML object that is identified by the specified name. 349 | 350 | **Parameters:** 351 | 352 | - `attributeName`: the name of the attribute. 353 | 354 | **Returns:** 355 | 356 | the value of the attribute as either an XMLList or an empty XMLList 357 | 358 | --- 359 | 360 | ### attributes 361 | 362 | **Signature:** `attributes() : XMLList` 363 | 364 | **Description:** Returns an XMList of the attributes in this XML Object. 365 | 366 | **Returns:** 367 | 368 | an XMList of the attributes in this XML Object. 369 | 370 | --- 371 | 372 | ### child 373 | 374 | **Signature:** `child(propertyName : Object) : XMLList` 375 | 376 | **Description:** Returns the children of the XML object based on the specified property name. 377 | 378 | **Parameters:** 379 | 380 | - `propertyName`: the property name representing the children of this XML object. 381 | 382 | **Returns:** 383 | 384 | an XMLList of children that match the property name parameter. 385 | 386 | --- 387 | 388 | ### childIndex 389 | 390 | **Signature:** `childIndex() : Number` 391 | 392 | **Description:** Identifies the zero-based index of this XML object within the context of its parent, or -1 if this object has no parent. 393 | 394 | **Returns:** 395 | 396 | the index of this XML object in the context of its parent, or -1 if this object has no parent. 397 | 398 | --- 399 | 400 | ### children 401 | 402 | **Signature:** `children() : XMLList` 403 | 404 | **Description:** Returns an XMLList containing the children of this XML object, maintaing the sequence in which they appear. 405 | 406 | **Returns:** 407 | 408 | an XMLList containing the children of this XML object. 409 | 410 | --- 411 | 412 | ### comments 413 | 414 | **Signature:** `comments() : XMLList` 415 | 416 | **Description:** Returns the properties of the XML object that contain comments. 417 | 418 | **Returns:** 419 | 420 | properties of the XML object that contain comments. 421 | 422 | --- 423 | 424 | ### contains 425 | 426 | **Signature:** `contains(value : XML) : boolean` 427 | 428 | **Description:** Returns true if this XML object contains the specified XML object, false otherwise. 429 | 430 | **Parameters:** 431 | 432 | - `value`: the object to locate in this XML object. 433 | 434 | **Returns:** 435 | 436 | true if this XML object contains the specified XML object, false otherwise. 437 | 438 | --- 439 | 440 | ### copy 441 | 442 | **Signature:** `copy() : XML` 443 | 444 | **Description:** Returns a copy of the this XML object including duplicate copies of the entire tree of nodes. The copied XML object has no parent. 445 | 446 | **Returns:** 447 | 448 | the copy of the object. 449 | 450 | --- 451 | 452 | ### defaultSettings 453 | 454 | **Signature:** `static defaultSettings() : Object` 455 | 456 | **Description:** Returns a new Object with the following properties set to the default values: ignoreComments, ignoreProcessingInstructions, ignoreWhitespace, prettyIndent, and prettyPrinting. The default values are as follows: ignoreComments = true ignoreProcessingInstructions = true ignoreWhitespace = true prettyIndent = 2 prettyPrinting = true Be aware that this method does not apply the settings to an existing instance of an XML object. Instead, this method returns an Object containing the default settings. 457 | 458 | **Returns:** 459 | 460 | an Object with properties set to the default settings. 461 | 462 | --- 463 | 464 | ### descendants 465 | 466 | **Signature:** `descendants() : XMLList` 467 | 468 | **Description:** Returns all descendents of the XML object. 469 | 470 | **Returns:** 471 | 472 | a list of all descendents of the XML object. 473 | 474 | --- 475 | 476 | ### descendants 477 | 478 | **Signature:** `descendants(name : String) : XMLList` 479 | 480 | **Description:** Returns all descendents of the XML object that have the specified name parameter. To return all descendents, use * as the name parameter. 481 | 482 | **Parameters:** 483 | 484 | - `name`: the name of the element to match. To return all descendents, use * as the name parameter. 485 | 486 | **Returns:** 487 | 488 | a list of all descendents constrained by the name parameter. 489 | 490 | --- 491 | 492 | ### elements 493 | 494 | **Signature:** `elements() : XMLList` 495 | 496 | **Description:** Returns a list of all of the elements of the XML object. 497 | 498 | --- 499 | 500 | ### elements 501 | 502 | **Signature:** `elements(name : Object) : XMLList` 503 | 504 | **Description:** Returns a list of the elements of the XML object using the specified name to constrain the list. name can be a QName, String, or any other data type that will be converted to a string prior to performing the search for elements of that name. To list all objects use * for the value of name. 505 | 506 | **Parameters:** 507 | 508 | - `name`: the name of the elements to return or an * to return all elements. 509 | 510 | **Returns:** 511 | 512 | a list of the elements of the XML object using the specified name to constrain the list. 513 | 514 | --- 515 | 516 | ### hasComplexContent 517 | 518 | **Signature:** `hasComplexContent() : boolean` 519 | 520 | **Description:** Returns a Boolean value indicating whether this XML object contains complex content. An XML object is considered to contain complex content if it represents an XML element that has child elements. XML objects representing attributes, comments, processing instructions and text nodes do not have complex content. The existence of attributes, comments, processing instructions and text nodes within an XML object is not significant in determining if it has complex content. 521 | 522 | **Returns:** 523 | 524 | a Boolean value indicating whether this XML object contains complex content. 525 | 526 | --- 527 | 528 | ### hasOwnProperty 529 | 530 | **Signature:** `hasOwnProperty(prop : String) : boolean` 531 | 532 | **Description:** Returns a Boolean value indicating whether this object has the property specified by prop. 533 | 534 | **Parameters:** 535 | 536 | - `prop`: the property to locate. 537 | 538 | **Returns:** 539 | 540 | true if the property exists, false otherwise. 541 | 542 | --- 543 | 544 | ### hasSimpleContent 545 | 546 | **Signature:** `hasSimpleContent() : boolean` 547 | 548 | **Description:** Returns a Boolean value indicating whether this XML object contains simple content. An XML object is considered to contain simple content if it represents a text node, represents an attribute node or if it represents an XML element that has no child elements. XML objects representing comments and processing instructions do not have simple content. The existence of attributes, comments, processing instructions and text nodes within an XML object is not significant in determining if it has simple content. 549 | 550 | **Returns:** 551 | 552 | a Boolean value indicating whether this XML object contains simple content. 553 | 554 | --- 555 | 556 | ### inScopeNamespaces 557 | 558 | **Signature:** `inScopeNamespaces() : Array` 559 | 560 | **Description:** Returns an Array of Namespace objects representing the namespaces in scope for this XML object in the context of its parent. If the parent of this XML object is modified, the associated namespace declarations may change. The set of namespaces returned by this method may be a super set of the namespaces used by this value 561 | 562 | **Returns:** 563 | 564 | an Array of Namespace objects representing the namespaces in scope for this XML object in the context of its parent. 565 | 566 | --- 567 | 568 | ### insertChildAfter 569 | 570 | **Signature:** `insertChildAfter(child1 : Object, child2 : Object) : XML` 571 | 572 | **Description:** Inserts the specified child2 after the specified child1 in this XML object and returns this XML object. If child1 is null, inserts child2 before all children of this XML object. If child1 does not exist in this XML object, it returns without modifying this XML object. 573 | 574 | **Parameters:** 575 | 576 | - `child1`: the child after which child2 is inserted. 577 | - `child2`: the child to insert into this XML object. 578 | 579 | **Returns:** 580 | 581 | the updated XML object. 582 | 583 | --- 584 | 585 | ### insertChildBefore 586 | 587 | **Signature:** `insertChildBefore(child1 : Object, child2 : Object) : XML` 588 | 589 | **Description:** Inserts the specified child2 before the specified child1 in this XML object and returns this XML object. If child1 is null, inserts child2 after all children of this XML object. If child1 does not exist in this XML object, it returns without modifying this XML object. 590 | 591 | **Parameters:** 592 | 593 | - `child1`: the child before which child2 is inserted. 594 | - `child2`: the child to insert into this XML object. 595 | 596 | **Returns:** 597 | 598 | the updated XML object. 599 | 600 | --- 601 | 602 | ### length 603 | 604 | **Signature:** `length() : Number` 605 | 606 | **Description:** Returns a value of 1 for XML objects. 607 | 608 | **Returns:** 609 | 610 | the value of 1. 611 | 612 | --- 613 | 614 | ### localName 615 | 616 | **Signature:** `localName() : Object` 617 | 618 | **Description:** Returns the local name portion of the qualified name of the XML object. 619 | 620 | **Returns:** 621 | 622 | the local name as either a String or null. 623 | 624 | --- 625 | 626 | ### name 627 | 628 | **Signature:** `name() : Object` 629 | 630 | **Description:** Returns the qualified name for the XML object. 631 | 632 | **Returns:** 633 | 634 | the qualified name as either a QName or null. 635 | 636 | --- 637 | 638 | ### namespace 639 | 640 | **Signature:** `namespace() : Object` 641 | 642 | **Description:** Returns the namespace associated with the qualified name of this XML object. 643 | 644 | **Returns:** 645 | 646 | the namespace associated with the qualified name of this XML object. 647 | 648 | --- 649 | 650 | ### namespace 651 | 652 | **Signature:** `namespace(prefix : String) : Object` 653 | 654 | **Description:** Returns the namespace that matches the specified prefix and that is in scope for the XML object. if there is no such namespace, the method returns undefined. 655 | 656 | **Parameters:** 657 | 658 | - `prefix`: the prefix to use when attempting to locate a namespace. 659 | 660 | **Returns:** 661 | 662 | the namespace that matches the specified prefix and that is in scope for the XML object. If specified namespace does not exist, the method returns undefined. 663 | 664 | --- 665 | 666 | ### namespaceDeclarations 667 | 668 | **Signature:** `namespaceDeclarations() : Array` 669 | 670 | **Description:** Returns an Array of namespace declarations associated with the XML Obnject in the context of its parent. 671 | 672 | **Returns:** 673 | 674 | an Array of namespace declarations associated with the XML Obnject in the context of its parent. 675 | 676 | --- 677 | 678 | ### nodeKind 679 | 680 | **Signature:** `nodeKind() : String` 681 | 682 | **Description:** Returns the type of the XML object, such as text, comment, processing-instruction, or attribute. 683 | 684 | **Returns:** 685 | 686 | the type of the XML object. 687 | 688 | --- 689 | 690 | ### normalize 691 | 692 | **Signature:** `normalize() : XML` 693 | 694 | **Description:** Merges adjacent text nodes and eliminates and eliminates empty text nodes for this XML object and all its descendents. 695 | 696 | **Returns:** 697 | 698 | the normalized XML object. 699 | 700 | --- 701 | 702 | ### parent 703 | 704 | **Signature:** `parent() : Object` 705 | 706 | **Description:** Returns the parent of the XML object or null if the XML object does not have a parent. 707 | 708 | **Returns:** 709 | 710 | the parent of the XML object of null if the XML object does not have a parent. 711 | 712 | --- 713 | 714 | ### prependChild 715 | 716 | **Signature:** `prependChild(value : Object) : XML` 717 | 718 | **Description:** Inserts the specified child into this XML object prior to its existing XML properties and then returns this XML object. 719 | 720 | **Parameters:** 721 | 722 | - `value`: the child to prepend to this XML object. 723 | 724 | **Returns:** 725 | 726 | the XML object updated with the prepended child. 727 | 728 | --- 729 | 730 | ### processingInstructions 731 | 732 | **Signature:** `processingInstructions() : XMLList` 733 | 734 | **Description:** Returns an XMLList containing all the children of this XML object that are processing-instructions. 735 | 736 | **Returns:** 737 | 738 | an XMLList containing all the children of this XML object that are processing-instructions. 739 | 740 | --- 741 | 742 | ### processingInstructions 743 | 744 | **Signature:** `processingInstructions(name : String) : XMLList` 745 | 746 | **Description:** Returns an XMLList containing all the children of this XML object that are processing-instructions with the specified name. If you use * for the name, all processing-instructions are returned. 747 | 748 | **Parameters:** 749 | 750 | - `name`: the name representing the processing-instructions you want to retreive. 751 | 752 | **Returns:** 753 | 754 | an XMLList containing all the children of this XML object that are processing-instructions with the specified name. 755 | 756 | --- 757 | 758 | ### propertyIsEnumerable 759 | 760 | **Signature:** `propertyIsEnumerable(property : String) : boolean` 761 | 762 | **Description:** Returns a Boolean indicating whether the specified property will be included in the set of properties iterated over when this XML object is used in a for..in statement. 763 | 764 | **Parameters:** 765 | 766 | - `property`: the property to test. 767 | 768 | **Returns:** 769 | 770 | true when the property can be iterated in a for..in statement, false otherwise. 771 | 772 | --- 773 | 774 | ### removeNamespace 775 | 776 | **Signature:** `removeNamespace(ns : Namespace) : XML` 777 | 778 | **Description:** Removes the specified namespace from the in scope namespaces of this object and all its descendents, then returns a copy of this XML object. This method will not remove a namespace from an object when it is referenced by that object's QName or the ONames of that object's attributes. 779 | 780 | **Parameters:** 781 | 782 | - `ns`: the namespace to remove. 783 | 784 | **Returns:** 785 | 786 | a copy of this XML object with the namespace removed. 787 | 788 | --- 789 | 790 | ### replace 791 | 792 | **Signature:** `replace(propertyName : String, value : Object) : XML` 793 | 794 | **Description:** Replaces the XML properties of this XML object specified by propertyName with value and returns this updated XML object. If this XML object contains no properties that match propertyName, the replace method returns without modifying this XML object. The propertyName parameter may be a numeric property name, an unqualified name for a set of XML elements, a qualified name for a set of XML elements or the properties wildcard *. When the propertyName parameter is an unqualified name, it identifies XML elements in the default namespace. The value parameter may be an XML object, XMLList object or any value that may be converted to a String. 795 | 796 | **Parameters:** 797 | 798 | - `propertyName`: a numeric property name, an unqualified name for a set of XML elements, a qualified name for a set of XML elements or the properties wildcard *. 799 | - `value`: an XML object, XMLList object or any value that may be converted to a String. 800 | 801 | **Returns:** 802 | 803 | the updated XML object. 804 | 805 | --- 806 | 807 | ### setChildren 808 | 809 | **Signature:** `setChildren(value : Object) : XML` 810 | 811 | **Description:** Replaces the XML properties of this XML object with a new set of XML properties from value. 812 | 813 | **Parameters:** 814 | 815 | - `value`: a single XML object or an XMLList. 816 | 817 | **Returns:** 818 | 819 | the updated XML object. 820 | 821 | --- 822 | 823 | ### setLocalName 824 | 825 | **Signature:** `setLocalName(name : String) : void` 826 | 827 | **Description:** Replaces the local name of this XML object with a string constructed from the specified name. 828 | 829 | **Parameters:** 830 | 831 | - `name`: the new local name. 832 | 833 | --- 834 | 835 | ### setName 836 | 837 | **Signature:** `setName(name : String) : void` 838 | 839 | **Description:** Replaces the name of this XML object with a QName or AttributeName constructed from the specified name. 840 | 841 | **Parameters:** 842 | 843 | - `name`: the new name of this XML object. 844 | 845 | --- 846 | 847 | ### setNamespace 848 | 849 | **Signature:** `setNamespace(ns : Namespace) : void` 850 | 851 | **Description:** Replaces the namespace associated with the name of this XML object with the specified namespace. 852 | 853 | **Parameters:** 854 | 855 | - `ns`: the namespace to associated with the name of thix XML object. 856 | 857 | --- 858 | 859 | ### setSettings 860 | 861 | **Signature:** `static setSettings() : void` 862 | 863 | **Description:** Restores the default settings for the following XML properties: XML.ignoreComments = true XML.ignoreProcessingInstructions = true XML.ignoreWhitespace = true XML.prettyIndent = 2 XML.prettyPrinting = true 864 | 865 | --- 866 | 867 | ### setSettings 868 | 869 | **Signature:** `static setSettings(settings : Object) : void` 870 | 871 | **Description:** Updates the collection of global XML properties: ignoreComments, ignoreProcessingInstructions, ignoreWhitespace, prettyPrinting, prettyIndent, and prettyPrinting. 872 | 873 | **Parameters:** 874 | 875 | - `settings`: an object with each of the following properties: ignoreComments, ignoreProcessingInstructions, ignoreWhitespace, prettyIndent, and prettyPrinting. 876 | 877 | --- 878 | 879 | ### settings 880 | 881 | **Signature:** `static settings() : Object` 882 | 883 | **Description:** Returns the collection of global XML properties: ignoreComments, ignoreProcessingInstructions, ignoreWhitespace, prettyPrinting, prettyIndent, and prettyPrinting. 884 | 885 | **Returns:** 886 | 887 | an object with each of the following properties: ignoreComments, ignoreProcessingInstructions, ignoreWhitespace, prettyIndent, and prettyPrinting. 888 | 889 | --- 890 | 891 | ### text 892 | 893 | **Signature:** `text() : XMLList` 894 | 895 | **Description:** Returns an XMLList containing all XML properties of this XML object that represent XML text nodes. 896 | 897 | **Returns:** 898 | 899 | an XMLList containing all XML properties of this XML object that represent XML text nodes. 900 | 901 | --- 902 | 903 | ### toString 904 | 905 | **Signature:** `toString() : String` 906 | 907 | **Description:** Returns the String representation of the XML object. If the object contains simple content, this method returns a String with tag, attributes, and namespace declarations removed. However, if the object contains complex content, this method returns an XML encoded String representing the entire XML object. If you want to return the entire XML object regardless of content complexity, use the toXMLString() method. 908 | 909 | **Returns:** 910 | 911 | the String representation of the XML object. 912 | 913 | --- 914 | 915 | ### toXMLString 916 | 917 | **Signature:** `toXMLString() : String` 918 | 919 | **Description:** Returns a XML-encoded String representation of the XML object, including tag and attributed delimiters. 920 | 921 | **Returns:** 922 | 923 | the string representation of the XML object. 924 | 925 | --- 926 | 927 | ### valueOf 928 | 929 | **Signature:** `valueOf() : XML` 930 | 931 | **Description:** Returns this XML object. 932 | 933 | **Returns:** 934 | 935 | this XML object. 936 | 937 | --- ```