#
tokens: 47395/50000 9/825 files (page 25/61)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 25 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/yaml/get-sfra-document.full-mode.test.mcp.yml:
--------------------------------------------------------------------------------

```yaml
  1 | description: "Test get_sfra_document tool for retrieving SFRA documentation"
  2 | tests:
  3 |   # Smoke test - ensure tool is available and accessible
  4 |   - it: "should be available in tools list"
  5 |     request:
  6 |       jsonrpc: "2.0"
  7 |       id: "list-sfra-document-tool"
  8 |       method: "tools/list"
  9 |       params: {}
 10 |     expect:
 11 |       response:
 12 |         jsonrpc: "2.0"
 13 |         id: "list-sfra-document-tool"
 14 |         result:
 15 |           tools:
 16 |             match:arrayContains:name:get_sfra_document
 17 |       stderr: "toBeEmpty"
 18 | 
 19 |   # Valid document tests - Core SFRA classes
 20 |   - it: "should retrieve server document successfully"
 21 |     request:
 22 |       jsonrpc: "2.0"
 23 |       id: "get-server-doc"
 24 |       method: "tools/call"
 25 |       params:
 26 |         name: "get_sfra_document"
 27 |         arguments:
 28 |           documentName: "server"
 29 |     expect:
 30 |       response:
 31 |         jsonrpc: "2.0"
 32 |         id: "get-server-doc"
 33 |         result:
 34 |           content:
 35 |             - type: "text"
 36 |               text: "match:contains:Class Server"
 37 |           isError: false
 38 |       performance:
 39 |         maxResponseTime: "2000ms"
 40 |       stderr: "toBeEmpty"
 41 | 
 42 |   - it: "should retrieve request document successfully"
 43 |     request:
 44 |       jsonrpc: "2.0"
 45 |       id: "get-request-doc"
 46 |       method: "tools/call"
 47 |       params:
 48 |         name: "get_sfra_document"
 49 |         arguments:
 50 |           documentName: "request"
 51 |     expect:
 52 |       response:
 53 |         jsonrpc: "2.0"
 54 |         id: "get-request-doc"
 55 |         result:
 56 |           content:
 57 |             - type: "text"
 58 |               text: "match:contains:Class Request"
 59 |           isError: false
 60 |       performance:
 61 |         maxResponseTime: "2000ms"
 62 |       stderr: "toBeEmpty"
 63 | 
 64 |   - it: "should retrieve response document successfully"
 65 |     request:
 66 |       jsonrpc: "2.0"
 67 |       id: "get-response-doc"
 68 |       method: "tools/call"
 69 |       params:
 70 |         name: "get_sfra_document"
 71 |         arguments:
 72 |           documentName: "response"
 73 |     expect:
 74 |       response:
 75 |         jsonrpc: "2.0"
 76 |         id: "get-response-doc"
 77 |         result:
 78 |           content:
 79 |             - type: "text"
 80 |               text: "match:contains:Class Response"
 81 |           isError: false
 82 |       performance:
 83 |         maxResponseTime: "2000ms"
 84 |       stderr: "toBeEmpty"
 85 | 
 86 |   - it: "should retrieve querystring document successfully"
 87 |     request:
 88 |       jsonrpc: "2.0"
 89 |       id: "get-querystring-doc"
 90 |       method: "tools/call"
 91 |       params:
 92 |         name: "get_sfra_document"
 93 |         arguments:
 94 |           documentName: "querystring"
 95 |     expect:
 96 |       response:
 97 |         jsonrpc: "2.0"
 98 |         id: "get-querystring-doc"
 99 |         result:
100 |           content:
101 |             - type: "text"
102 |               text: "match:contains:QueryString"
103 |           isError: false
104 |       performance:
105 |         maxResponseTime: "2000ms"
106 |       stderr: "toBeEmpty"
107 | 
108 |   - it: "should retrieve render document successfully"
109 |     request:
110 |       jsonrpc: "2.0"
111 |       id: "get-render-doc"
112 |       method: "tools/call"
113 |       params:
114 |         name: "get_sfra_document"
115 |         arguments:
116 |           documentName: "render"
117 |     expect:
118 |       response:
119 |         jsonrpc: "2.0"
120 |         id: "get-render-doc"
121 |         result:
122 |           content:
123 |             - type: "text"
124 |               text: "match:contains:render"
125 |           isError: false
126 |       performance:
127 |         maxResponseTime: "2000ms"
128 |       stderr: "toBeEmpty"
129 | 
130 |   # Product model tests
131 |   - it: "should retrieve product-full document successfully"
132 |     request:
133 |       jsonrpc: "2.0"
134 |       id: "get-product-full-doc"
135 |       method: "tools/call"
136 |       params:
137 |         name: "get_sfra_document"
138 |         arguments:
139 |           documentName: "product-full"
140 |     expect:
141 |       response:
142 |         jsonrpc: "2.0"
143 |         id: "get-product-full-doc"
144 |         result:
145 |           content:
146 |             - type: "text"
147 |               text: "match:contains:product"
148 |           isError: false
149 |       performance:
150 |         maxResponseTime: "2000ms"
151 |       stderr: "toBeEmpty"
152 | 
153 |   - it: "should retrieve cart document successfully"
154 |     request:
155 |       jsonrpc: "2.0"
156 |       id: "get-cart-doc"
157 |       method: "tools/call"
158 |       params:
159 |         name: "get_sfra_document"
160 |         arguments:
161 |           documentName: "cart"
162 |     expect:
163 |       response:
164 |         jsonrpc: "2.0"
165 |         id: "get-cart-doc"
166 |         result:
167 |           content:
168 |             - type: "text"
169 |               text: "match:contains:cart"
170 |           isError: false
171 |       performance:
172 |         maxResponseTime: "2000ms"
173 |       stderr: "toBeEmpty"
174 | 
175 |   # Customer model tests
176 |   - it: "should retrieve account document successfully"
177 |     request:
178 |       jsonrpc: "2.0"
179 |       id: "get-account-doc"
180 |       method: "tools/call"
181 |       params:
182 |         name: "get_sfra_document"
183 |         arguments:
184 |           documentName: "account"
185 |     expect:
186 |       response:
187 |         jsonrpc: "2.0"
188 |         id: "get-account-doc"
189 |         result:
190 |           content:
191 |             - type: "text"
192 |               text: "match:contains:account"
193 |           isError: false
194 |       performance:
195 |         maxResponseTime: "2000ms"
196 |       stderr: "toBeEmpty"
197 | 
198 |   # Response format validation tests
199 |   - it: "should return properly structured JSON content"
200 |     request:
201 |       jsonrpc: "2.0"
202 |       id: "validate-server-structure"
203 |       method: "tools/call"
204 |       params:
205 |         name: "get_sfra_document"
206 |         arguments:
207 |           documentName: "server"
208 |     expect:
209 |       response:
210 |         jsonrpc: "2.0"
211 |         id: "validate-server-structure"
212 |         result:
213 |           content:
214 |             - type: "text"
215 |               text: "match:regex:\\{[\\s\\S]*title[\\s\\S]*sections[\\s\\S]*content[\\s\\S]*\\}"
216 |           isError: false
217 |       stderr: "toBeEmpty"
218 | 
219 |   - it: "should include document metadata"
220 |     request:
221 |       jsonrpc: "2.0"
222 |       id: "validate-metadata"
223 |       method: "tools/call"
224 |       params:
225 |         name: "get_sfra_document"
226 |         arguments:
227 |           documentName: "server"
228 |     expect:
229 |       response:
230 |         jsonrpc: "2.0"
231 |         id: "validate-metadata"
232 |         result:
233 |           content:
234 |             - type: "text"
235 |               text: "match:regex:[\\s\\S]*type[\\s\\S]*category[\\s\\S]*filename[\\s\\S]*lastModified[\\s\\S]*"
236 |           isError: false
237 |       stderr: "toBeEmpty"
238 | 
239 |   - it: "should include sections array"
240 |     request:
241 |       jsonrpc: "2.0"
242 |       id: "validate-sections"
243 |       method: "tools/call"
244 |       params:
245 |         name: "get_sfra_document"
246 |         arguments:
247 |           documentName: "server"
248 |     expect:
249 |       response:
250 |         jsonrpc: "2.0"
251 |         id: "validate-sections"
252 |         result:
253 |           content:
254 |             - type: "text"
255 |               text: "match:regex:[\\s\\S]*sections[\\s\\S]*\\[[\\s\\S]*\\][\\s\\S]*"
256 |           isError: false
257 |       stderr: "toBeEmpty"
258 | 
259 |   - it: "should include comprehensive content"
260 |     request:
261 |       jsonrpc: "2.0"
262 |       id: "validate-content-detail"
263 |       method: "tools/call"
264 |       params:
265 |         name: "get_sfra_document"
266 |         arguments:
267 |           documentName: "server"
268 |     expect:
269 |       response:
270 |         jsonrpc: "2.0"
271 |         id: "validate-content-detail"
272 |         result:
273 |           content:
274 |             - type: "text"
275 |               text: "match:regex:[\\s\\S]*Description[\\s\\S]*Method Summary[\\s\\S]*Method Detail[\\s\\S]*"
276 |           isError: false
277 |       stderr: "toBeEmpty"
278 | 
279 |   # Error handling tests
280 |   - it: "should handle nonexistent document gracefully"
281 |     request:
282 |       jsonrpc: "2.0"
283 |       id: "error-nonexistent"
284 |       method: "tools/call"
285 |       params:
286 |         name: "get_sfra_document"
287 |         arguments:
288 |           documentName: "nonexistent-document"
289 |     expect:
290 |       response:
291 |         jsonrpc: "2.0"
292 |         id: "error-nonexistent"
293 |         result:
294 |           content:
295 |             - type: "text"
296 |               text: "match:contains:not found"
297 |           isError: true
298 |       stderr: "toBeEmpty"
299 | 
300 |   - it: "should handle empty document name"
301 |     request:
302 |       jsonrpc: "2.0"
303 |       id: "error-empty-name"
304 |       method: "tools/call"
305 |       params:
306 |         name: "get_sfra_document"
307 |         arguments:
308 |           documentName: ""
309 |     expect:
310 |       response:
311 |         jsonrpc: "2.0"
312 |         id: "error-empty-name"
313 |         result:
314 |           content:
315 |             - type: "text"
316 |               text: "match:regex:(Error|not found|invalid)"
317 |           isError: true
318 |       stderr: "toBeEmpty"
319 | 
320 |   - it: "should handle invalid document name characters"
321 |     request:
322 |       jsonrpc: "2.0"
323 |       id: "error-invalid-chars"
324 |       method: "tools/call"
325 |       params:
326 |         name: "get_sfra_document"
327 |         arguments:
328 |           documentName: "invalid/document/name"
329 |     expect:
330 |       response:
331 |         jsonrpc: "2.0"
332 |         id: "error-invalid-chars"
333 |         result:
334 |           content:
335 |             - type: "text"
336 |               text: "match:regex:(Error|not found|invalid)"
337 |           isError: true
338 |       stderr: "toBeEmpty"
339 | 
340 |   - it: "should handle missing documentName parameter"
341 |     request:
342 |       jsonrpc: "2.0"
343 |       id: "error-missing-param"
344 |       method: "tools/call"
345 |       params:
346 |         name: "get_sfra_document"
347 |         arguments: {}
348 |     expect:
349 |       response:
350 |         jsonrpc: "2.0"
351 |         id: "error-missing-param"
352 |         result:
353 |           content:
354 |             - type: "text"
355 |               text: "match:regex:(Error|required|missing|documentName|non-empty string)"
356 |           isError: true
357 |       stderr: "toBeEmpty"
358 | 
359 |   # Case sensitivity tests - it appears the tool is case-insensitive
360 |   - it: "should handle case variations for document names"
361 |     request:
362 |       jsonrpc: "2.0"
363 |       id: "case-insensitive-upper"
364 |       method: "tools/call"
365 |       params:
366 |         name: "get_sfra_document"
367 |         arguments:
368 |           documentName: "SERVER"
369 |     expect:
370 |       response:
371 |         jsonrpc: "2.0"
372 |         id: "case-insensitive-upper"
373 |         result:
374 |           content:
375 |             - type: "text"
376 |               text: "match:contains:Class Server"
377 |           isError: false
378 |       stderr: "toBeEmpty"
379 | 
380 |   - it: "should handle mixed case document names"
381 |     request:
382 |       jsonrpc: "2.0"
383 |       id: "case-insensitive-mixed"
384 |       method: "tools/call"
385 |       params:
386 |         name: "get_sfra_document"
387 |         arguments:
388 |           documentName: "Server"
389 |     expect:
390 |       response:
391 |         jsonrpc: "2.0"
392 |         id: "case-insensitive-mixed"
393 |         result:
394 |           content:
395 |             - type: "text"
396 |               text: "match:contains:Class Server"
397 |           isError: false
398 |       stderr: "toBeEmpty"
399 | 
400 |   # Content quality tests
401 |   - it: "should provide meaningful content for server document"
402 |     request:
403 |       jsonrpc: "2.0"
404 |       id: "content-quality-server"
405 |       method: "tools/call"
406 |       params:
407 |         name: "get_sfra_document"
408 |         arguments:
409 |           documentName: "server"
410 |     expect:
411 |       response:
412 |         jsonrpc: "2.0"
413 |         id: "content-quality-server"
414 |         result:
415 |           content:
416 |             - type: "text"
417 |               text: "match:regex:[\\s\\S]*middleware[\\s\\S]*routing[\\s\\S]*HTTP[\\s\\S]*"
418 |           isError: false
419 |       stderr: "toBeEmpty"
420 | 
421 |   - it: "should provide meaningful content for request document"
422 |     request:
423 |       jsonrpc: "2.0"
424 |       id: "content-quality-request"
425 |       method: "tools/call"
426 |       params:
427 |         name: "get_sfra_document"
428 |         arguments:
429 |           documentName: "request"
430 |     expect:
431 |       response:
432 |         jsonrpc: "2.0"
433 |         id: "content-quality-request"
434 |         result:
435 |           content:
436 |             - type: "text"
437 |               text: "match:regex:[\\s\\S]*HTTP[\\s\\S]*session[\\s\\S]*customer[\\s\\S]*"
438 |           isError: false
439 |       stderr: "toBeEmpty"
440 | 
441 |   # Additional model document tests
442 |   - it: "should retrieve billing document successfully"
443 |     request:
444 |       jsonrpc: "2.0"
445 |       id: "get-billing-doc"
446 |       method: "tools/call"
447 |       params:
448 |         name: "get_sfra_document"
449 |         arguments:
450 |           documentName: "billing"
451 |     expect:
452 |       response:
453 |         jsonrpc: "2.0"
454 |         id: "get-billing-doc"
455 |         result:
456 |           content:
457 |             - type: "text"
458 |               text: "match:contains:billing"
459 |           isError: false
460 |       performance:
461 |         maxResponseTime: "2000ms"
462 |       stderr: "toBeEmpty"
463 | 
464 |   - it: "should retrieve shipping document successfully"
465 |     request:
466 |       jsonrpc: "2.0"
467 |       id: "get-shipping-doc"
468 |       method: "tools/call"
469 |       params:
470 |         name: "get_sfra_document"
471 |         arguments:
472 |           documentName: "shipping"
473 |     expect:
474 |       response:
475 |         jsonrpc: "2.0"
476 |         id: "get-shipping-doc"
477 |         result:
478 |           content:
479 |             - type: "text"
480 |               text: "match:contains:shipping"
481 |           isError: false
482 |       performance:
483 |         maxResponseTime: "2000ms"
484 |       stderr: "toBeEmpty"
485 | 
486 |   # Edge case tests
487 |   - it: "should handle document names with hyphens"
488 |     request:
489 |       jsonrpc: "2.0"
490 |       id: "hyphen-document"
491 |       method: "tools/call"
492 |       params:
493 |         name: "get_sfra_document"
494 |         arguments:
495 |           documentName: "product-full"
496 |     expect:
497 |       response:
498 |         jsonrpc: "2.0"
499 |         id: "hyphen-document"
500 |         result:
501 |           content:
502 |             - type: "text"
503 |               text: "match:type:string"
504 |           isError: false
505 |       stderr: "toBeEmpty"
506 | 
507 |   - it: "should handle very long nonexistent document names"
508 |     request:
509 |       jsonrpc: "2.0"
510 |       id: "long-nonexistent"
511 |       method: "tools/call"
512 |       params:
513 |         name: "get_sfra_document"
514 |         arguments:
515 |           documentName: "this-is-a-very-long-document-name-that-definitely-does-not-exist-anywhere"
516 |     expect:
517 |       response:
518 |         jsonrpc: "2.0"
519 |         id: "long-nonexistent"
520 |         result:
521 |           content:
522 |             - type: "text"
523 |               text: "match:regex:(Error|not found)"
524 |           isError: true
525 |       stderr: "toBeEmpty"
526 | 
```

--------------------------------------------------------------------------------
/tests/mcp/node/get-log-file-contents.full-mode.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('get_log_file_contents - Optimized Programmatic Tests', () => {
  6 |   let client;
  7 |   let testFile;
  8 | 
  9 |   before(async () => {
 10 |     client = await connect('./aegis.config.with-dw.json');
 11 |     
 12 |     // Discover one working test file for optimization
 13 |     testFile = await discoverTestFile();
 14 |   });
 15 | 
 16 |   after(async () => {
 17 |     if (client?.connected) {
 18 |       await client.disconnect();
 19 |     }
 20 |   });
 21 | 
 22 |   beforeEach(() => {
 23 |     // CRITICAL: Clear all buffers to prevent leaking into next tests
 24 |     client.clearAllBuffers();
 25 |   });
 26 | 
 27 |   // === Helper Functions ===
 28 |   function assertValidMCPResponse(result) {
 29 |     assert.ok(result.content, 'Should have content');
 30 |     assert.ok(Array.isArray(result.content), 'Content should be array');
 31 |     assert.equal(typeof result.isError, 'boolean', 'isError should be boolean');
 32 |   }
 33 | 
 34 |   function parseResponseText(text) {
 35 |     return text.startsWith('"') && text.endsWith('"') ? JSON.parse(text) : text;
 36 |   }
 37 | 
 38 |   function assertTextContent(result, expectedSubstring) {
 39 |     assertValidMCPResponse(result);
 40 |     assert.equal(result.content[0].type, 'text');
 41 |     const actualText = parseResponseText(result.content[0].text);
 42 |     assert.ok(actualText.includes(expectedSubstring),
 43 |       `Expected "${expectedSubstring}" in response`);
 44 |   }
 45 | 
 46 |   function assertSuccessResponse(result) {
 47 |     assertValidMCPResponse(result);
 48 |     assert.equal(result.isError, false, 'Should not be an error response');
 49 |     assert.equal(result.content[0].type, 'text');
 50 |   }
 51 | 
 52 |   function assertErrorResponse(result, expectedErrorSubstring) {
 53 |     assertValidMCPResponse(result);
 54 |     assert.equal(result.isError, true, 'Should be an error response');
 55 |     if (expectedErrorSubstring) {
 56 |       assertTextContent(result, expectedErrorSubstring);
 57 |     }
 58 |   }
 59 | 
 60 |   async function discoverTestFile() {
 61 |     // Try to discover one working file using the job log tool
 62 |     try {
 63 |       const result = await client.callTool('get_latest_job_log_files', {});
 64 |       if (!result.isError) {
 65 |         const text = parseResponseText(result.content[0].text);
 66 |         const match = text.match(/File:\s+(.+\.log)/);
 67 |         if (match) {
 68 |           return `jobs/ImportCatalog/${match[1]}`;
 69 |         }
 70 |       }
 71 |     } catch {
 72 |       // Ignore discovery errors
 73 |     }
 74 |     
 75 |     // Fallback to expected file
 76 |     return 'jobs/ImportCatalog/Job-ImportCatalog-0987654321.log';
 77 |   }
 78 | 
 79 |   // === Core Functionality Tests ===
 80 |   describe('Core Functionality', () => {
 81 |     test('should read log file with complete metadata', async () => {
 82 |       const result = await client.callTool('get_log_file_contents', {
 83 |         filename: testFile
 84 |       });
 85 | 
 86 |       assertSuccessResponse(result);
 87 |       assertTextContent(result, 'Log File Contents:');
 88 |       assertTextContent(result, testFile);
 89 |       assertTextContent(result, 'Total lines:');
 90 |       assertTextContent(result, 'Content size:');
 91 |       
 92 |       // Validate SFCC timestamp pattern
 93 |       const content = parseResponseText(result.content[0].text);
 94 |       const timestampPattern = /\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3} GMT\]/;
 95 |       assert.ok(timestampPattern.test(content), 'Should contain SFCC timestamps');
 96 |     });
 97 | 
 98 |     test('should handle maxBytes parameter with content validation', async () => {
 99 |       const result = await client.callTool('get_log_file_contents', {
100 |         filename: testFile,
101 |         maxBytes: 500
102 |       });
103 | 
104 |       assertSuccessResponse(result);
105 |       assertTextContent(result, 'Content size: 500 bytes');
106 |       
107 |       // Should still include essential metadata despite size limit
108 |       assertTextContent(result, 'Log File Contents:');
109 |       assertTextContent(result, 'Total lines:');
110 |     });
111 | 
112 |     test('should handle tailOnly parameter correctly', async () => {
113 |       const fullResult = await client.callTool('get_log_file_contents', {
114 |         filename: testFile,
115 |         maxBytes: 1000
116 |       });
117 | 
118 |       const tailResult = await client.callTool('get_log_file_contents', {
119 |         filename: testFile,
120 |         maxBytes: 1000,
121 |         tailOnly: true
122 |       });
123 | 
124 |       assertSuccessResponse(fullResult);
125 |       assertSuccessResponse(tailResult);
126 |       
127 |       assertTextContent(tailResult, 'tail read');
128 |       assertTextContent(tailResult, 'Content size: 1000 bytes');
129 |     });
130 |   });
131 | 
132 |   // === Dynamic Validation Tests ===
133 |   describe('Dynamic Validation', () => {
134 |     test('should validate content structure consistency', async () => {
135 |       const testCases = [
136 |         { maxBytes: 200 },
137 |         { maxBytes: 1000 },
138 |         { tailOnly: true, maxBytes: 500 },
139 |         { tailOnly: false }
140 |       ];
141 | 
142 |       for (const params of testCases) {
143 |         const result = await client.callTool('get_log_file_contents', {
144 |           filename: testFile,
145 |           ...params
146 |         });
147 | 
148 |         assertSuccessResponse(result);
149 |         
150 |         // All responses should have consistent structure
151 |         assert.equal(result.content.length, 1, 'Should have one content element');
152 |         
153 |         const content = parseResponseText(result.content[0].text);
154 |         assert.ok(content.includes('Log File Contents:'), 'Should have header');
155 |         assert.ok(content.includes('Total lines:'), 'Should have line count');
156 |       }
157 |     });
158 | 
159 |     test('should handle parameter edge cases with validation', async () => {
160 |       const edgeCases = [
161 |         { name: 'minimal bytes', params: { maxBytes: 1 } },
162 |         { name: 'large bytes', params: { maxBytes: 50000 } },
163 |         { name: 'tail with small bytes', params: { tailOnly: true, maxBytes: 10 } }
164 |       ];
165 | 
166 |       for (const testCase of edgeCases) {
167 |         const result = await client.callTool('get_log_file_contents', {
168 |           filename: testFile,
169 |           ...testCase.params
170 |         });
171 | 
172 |         assertSuccessResponse(result);
173 |         
174 |         const content = parseResponseText(result.content[0].text);
175 |         
176 |         // Even with edge cases, should maintain structure
177 |         assert.ok(content.includes('Log File Contents:'), 
178 |           `${testCase.name} should maintain header structure`);
179 |       }
180 |     });
181 |   });
182 | 
183 |   // === Error Handling Tests ===
184 |   describe('Error Handling', () => {
185 |     test('should handle invalid parameters gracefully', async () => {
186 |       const errorCases = [
187 |         { args: {}, expectedError: 'filename' },
188 |         { args: { filename: '' }, expectedError: 'filename' },
189 |         { args: { filename: testFile, maxBytes: 0 }, expectedError: 'Invalid maxBytes' },
190 |         { args: { filename: testFile, maxBytes: -1 }, expectedError: 'Invalid maxBytes' }
191 |       ];
192 | 
193 |       for (const errorCase of errorCases) {
194 |         const result = await client.callTool('get_log_file_contents', errorCase.args);
195 |         
196 |         assertErrorResponse(result, errorCase.expectedError);
197 |       }
198 |     });
199 | 
200 |     test('should handle security-related filename patterns', async () => {
201 |       const securityTests = [
202 |         '../../../etc/passwd',
203 |         '/etc/passwd',
204 |         'file\x00.log',
205 |         'file|rm -rf /.log'
206 |       ];
207 | 
208 |       for (const filename of securityTests) {
209 |         const result = await client.callTool('get_log_file_contents', { filename });
210 |         
211 |         assertValidMCPResponse(result);
212 |         
213 |         // Should not return sensitive system content
214 |         if (!result.isError) {
215 |           const content = parseResponseText(result.content[0].text);
216 |           assert.ok(!content.includes('root:x:0:0'), 
217 |             'Should not return system password file content');
218 |         }
219 |       }
220 |     });
221 |   });
222 | 
223 |   // === Multi-Step Integration Tests ===
224 |   describe('Integration Workflows', () => {
225 |     test('should integrate with file discovery tools', async () => {
226 |       // Step 1: Discover available files
227 |       const listResult = await client.callTool('get_latest_job_log_files', {});
228 |       
229 |       if (!listResult.isError) {
230 |         const listText = parseResponseText(listResult.content[0].text);
231 |         
232 |         // Step 2: Extract a file path from the list
233 |         const fileMatch = listText.match(/File:\s+(.+\.log)/);
234 |         
235 |         if (fileMatch) {
236 |           const discoveredFile = `jobs/ImportCatalog/${fileMatch[1]}`;
237 |           
238 |           // Step 3: Read the discovered file
239 |           const contentResult = await client.callTool('get_log_file_contents', {
240 |             filename: discoveredFile
241 |           });
242 |           
243 |           assertSuccessResponse(contentResult);
244 |           assertTextContent(contentResult, discoveredFile);
245 |         }
246 |       }
247 |     });
248 | 
249 |     test('should support progressive content analysis workflow', async () => {
250 |       // Step 1: Get a sample of log content
251 |       const sampleResult = await client.callTool('get_log_file_contents', {
252 |         filename: testFile,
253 |         maxBytes: 1000
254 |       });
255 |       
256 |       assertSuccessResponse(sampleResult);
257 |       const sampleContent = parseResponseText(sampleResult.content[0].text);
258 |       
259 |       // Step 2: Based on sample, get full content if needed
260 |       if (sampleContent.includes('INFO')) {
261 |         const fullResult = await client.callTool('get_log_file_contents', {
262 |           filename: testFile,
263 |           maxBytes: 10000
264 |         });
265 |         
266 |         assertSuccessResponse(fullResult);
267 |         const fullContent = parseResponseText(fullResult.content[0].text);
268 |         
269 |         // Step 3: Validate that full content contains sample content structure
270 |         assert.ok(fullContent.includes('Log File Contents:'), 'Full content should have header');
271 |         assert.ok(fullContent.length >= sampleContent.length, 'Full content should be larger');
272 |       }
273 |     });
274 |   });
275 | 
276 |   // === Business Logic Validation ===
277 |   describe('Business Logic Validation', () => {
278 |     test('should validate log entry format and content', async () => {
279 |       const result = await client.callTool('get_log_file_contents', {
280 |         filename: testFile,
281 |         maxBytes: 2000
282 |       });
283 | 
284 |       assertSuccessResponse(result);
285 |       const content = parseResponseText(result.content[0].text);
286 |       
287 |       // Validate SFCC-specific log structure
288 |       const logEntryPattern = /\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3} GMT)\]\s+(INFO|WARN|ERROR|DEBUG)\s+(\w+)/;
289 |       const matches = content.match(logEntryPattern);
290 |       
291 |       if (matches) {
292 |         // Validate timestamp is recent - Fix timestamp parsing for SFCC format
293 |         // Convert "2025-09-22 12:00:00.000 GMT" to "2025-09-22T12:00:00.000Z"
294 |         const isoTimestamp = matches[1].replace(' ', 'T').replace(' GMT', 'Z');
295 |         const logDate = new Date(isoTimestamp);
296 |         const now = new Date();
297 |         const daysDiff = (now - logDate) / (1000 * 60 * 60 * 24);
298 |         
299 |         // Allow reasonable timeframe for test log data (within 1 day of current time)
300 |         assert.ok(Math.abs(daysDiff) < 1, 'Log timestamp should be within reasonable timeframe (±1 day)');
301 |         
302 |         // Validate log level
303 |         assert.ok(['INFO', 'WARN', 'ERROR', 'DEBUG'].includes(matches[2]), 'Should have valid log level');
304 |         
305 |         // Validate thread/component information
306 |         assert.ok(matches[3].length > 0, 'Should have thread/component information');
307 |       }
308 |     });
309 | 
310 |     test('should validate content size reporting accuracy', async () => {
311 |       const testSizes = [100, 500, 1000];
312 |       
313 |       for (const size of testSizes) {
314 |         const result = await client.callTool('get_log_file_contents', {
315 |           filename: testFile,
316 |           maxBytes: size
317 |         });
318 |         
319 |         assertSuccessResponse(result);
320 |         assertTextContent(result, `Content size: ${size} bytes`);
321 |         
322 |         // Validate that actual content respects the size limit
323 |         const content = parseResponseText(result.content[0].text);
324 |         const actualContentMatch = content.match(/---\n\n([\s\S]*)$/);
325 |         
326 |         if (actualContentMatch) {
327 |           const actualLogContent = actualContentMatch[1];
328 |           // Should be approximately the requested size (allowing for encoding differences)
329 |           assert.ok(actualLogContent.length <= size + 50, 
330 |             `Content should respect size limit: ${actualLogContent.length} <= ${size + 50}`);
331 |         }
332 |       }
333 |     });
334 |   });
335 | 
336 |   // === Reliability and State Management ===
337 |   describe('Reliability Testing', () => {
338 |     test('should maintain state consistency across requests', async () => {
339 |       const params = { filename: testFile, maxBytes: 1000 };
340 |       const results = [];
341 | 
342 |       // Make multiple identical requests
343 |       for (let i = 0; i < 3; i++) {
344 |         const result = await client.callTool('get_log_file_contents', params);
345 |         results.push(result);
346 |         assertSuccessResponse(result);
347 |       }
348 | 
349 |       // All results should be identical (no state leakage)
350 |       const firstContent = parseResponseText(results[0].content[0].text);
351 |       for (let i = 1; i < results.length; i++) {
352 |         const content = parseResponseText(results[i].content[0].text);
353 |         assert.equal(content, firstContent, `Request ${i} should match first request`);
354 |       }
355 |     });
356 | 
357 |     test('should handle alternating parameter patterns', async () => {
358 |       const patterns = [
359 |         { maxBytes: 500 },
360 |         { tailOnly: true, maxBytes: 300 },
361 |         { maxBytes: 1000 },
362 |         { tailOnly: false }
363 |       ];
364 | 
365 |       for (let i = 0; i < patterns.length; i++) {
366 |         const result = await client.callTool('get_log_file_contents', {
367 |           filename: testFile,
368 |           ...patterns[i]
369 |         });
370 | 
371 |         assertSuccessResponse(result);
372 |         
373 |         // Each request should succeed independently
374 |         const content = parseResponseText(result.content[0].text);
375 |         assert.ok(content.includes('Log File Contents:'), 
376 |           `Pattern ${i} should maintain proper structure`);
377 |       }
378 |     });
379 |   });
380 | });
381 |  
```

--------------------------------------------------------------------------------
/docs/dw_util/SecureFilter.md:
--------------------------------------------------------------------------------

```markdown
  1 | ## Package: dw.util
  2 | 
  3 | # Class SecureFilter
  4 | 
  5 | ## Inheritance Hierarchy
  6 | 
  7 | - Object
  8 |   - dw.util.SecureFilter
  9 | 
 10 | ## Description
 11 | 
 12 | SecureFilter contains many methods for manipulating untrusted data Strings into RFC-Compliant Strings for a given context by removing "bad" data from the untrusted data.
 13 | 
 14 | ## Constructor Summary
 15 | 
 16 | ## Method Summary
 17 | 
 18 | ### forHtmlContent
 19 | 
 20 | **Signature:** `static forHtmlContent(input : String) : String`
 21 | 
 22 | Filters illegal characters from a given input for use in a general HTML context.
 23 | 
 24 | ### forHtmlInDoubleQuoteAttribute
 25 | 
 26 | **Signature:** `static forHtmlInDoubleQuoteAttribute(input : String) : String`
 27 | 
 28 | Filters illegal characters from a given input for use in an HTML Attribute guarded by a double quote.
 29 | 
 30 | ### forHtmlInSingleQuoteAttribute
 31 | 
 32 | **Signature:** `static forHtmlInSingleQuoteAttribute(input : String) : String`
 33 | 
 34 | Filters illegal characters from a given input for use in an HTML Attribute guarded by a single quote.
 35 | 
 36 | ### forHtmlUnquotedAttribute
 37 | 
 38 | **Signature:** `static forHtmlUnquotedAttribute(input : String) : String`
 39 | 
 40 | Filters illegal characters from a given input for use in an HTML Attribute left unguarded.
 41 | 
 42 | ### forJavaScriptInAttribute
 43 | 
 44 | **Signature:** `static forJavaScriptInAttribute(input : String) : String`
 45 | 
 46 | Filters illegal characters from a given input for use in JavaScript inside an HTML attribute.
 47 | 
 48 | ### forJavaScriptInBlock
 49 | 
 50 | **Signature:** `static forJavaScriptInBlock(input : String) : String`
 51 | 
 52 | Filters illegal characters from a given input for use in JavaScript inside an HTML block.
 53 | 
 54 | ### forJavaScriptInHTML
 55 | 
 56 | **Signature:** `static forJavaScriptInHTML(input : String) : String`
 57 | 
 58 | Filters illegal characters from a given input for use in JavaScript inside an HTML context.
 59 | 
 60 | ### forJavaScriptInSource
 61 | 
 62 | **Signature:** `static forJavaScriptInSource(input : String) : String`
 63 | 
 64 | Filters illegal characters from a given input for use in JavaScript inside a JavaScript source file.
 65 | 
 66 | ### forJSONValue
 67 | 
 68 | **Signature:** `static forJSONValue(input : String) : String`
 69 | 
 70 | Filters illegal characters from a given input for use in a JSON Object Value to prevent escaping into a trusted context.
 71 | 
 72 | ### forUriComponent
 73 | 
 74 | **Signature:** `static forUriComponent(input : String) : String`
 75 | 
 76 | Filters illegal characters from a given input for use as a component of a URI.
 77 | 
 78 | ### forUriComponentStrict
 79 | 
 80 | **Signature:** `static forUriComponentStrict(input : String) : String`
 81 | 
 82 | Filters illegal characters from a given input for use as a component of a URI.
 83 | 
 84 | ### forXmlCommentContent
 85 | 
 86 | **Signature:** `static forXmlCommentContent(input : String) : String`
 87 | 
 88 | Filters illegal characters from a given input for use in an XML comments.
 89 | 
 90 | ### forXmlContent
 91 | 
 92 | **Signature:** `static forXmlContent(input : String) : String`
 93 | 
 94 | Filters illegal characters from a given input for use in a general XML context.
 95 | 
 96 | ### forXmlInDoubleQuoteAttribute
 97 | 
 98 | **Signature:** `static forXmlInDoubleQuoteAttribute(input : String) : String`
 99 | 
100 | Filters illegal characters from a given input for use in an XML attribute guarded by a double quote.
101 | 
102 | ### forXmlInSingleQuoteAttribute
103 | 
104 | **Signature:** `static forXmlInSingleQuoteAttribute(input : String) : String`
105 | 
106 | Filters illegal characters from a given input for use in an XML attribute guarded by a single quote.
107 | 
108 | ## Method Detail
109 | 
110 | ## Method Details
111 | 
112 | ### forHtmlContent
113 | 
114 | **Signature:** `static forHtmlContent(input : String) : String`
115 | 
116 | **Description:** Filters illegal characters from a given input for use in a general HTML context. E.g. text content and text attributes. This method takes the UNION of allowed characters among all contexts, so may be more imprecise that the more specific contexts. Generally, this method is preferred unless you specifically understand the context in which untrusted data will be output. Example Usage: <div>${SecureFilter.forHtmlContent(unsafeData)}</div> <input value="${SecureFilter.forHtmlContent(unsafeData)}" /> Flow: Allow AlphaNumerics and some Special characters Remove all other characters
117 | 
118 | **Parameters:**
119 | 
120 | - `input`: untrusted input to be filtered, if necessary
121 | 
122 | **Returns:**
123 | 
124 | a properly filtered string for the given input
125 | 
126 | ---
127 | 
128 | ### forHtmlInDoubleQuoteAttribute
129 | 
130 | **Signature:** `static forHtmlInDoubleQuoteAttribute(input : String) : String`
131 | 
132 | **Description:** Filters illegal characters from a given input for use in an HTML Attribute guarded by a double quote. This method is preferred if you understand exactly how the output of this will be used in the HTML document. Example Usage: <div id="${SecureFilter.forHtmlInDoubleQuoteAttribute(unsafeData)}"></div> Flow: Allow AlphaNumerics and some Special characters Remove all other characters
133 | 
134 | **Parameters:**
135 | 
136 | - `input`: untrusted input to be filtered, if necessary
137 | 
138 | **Returns:**
139 | 
140 | a properly filtered string for the given input
141 | 
142 | ---
143 | 
144 | ### forHtmlInSingleQuoteAttribute
145 | 
146 | **Signature:** `static forHtmlInSingleQuoteAttribute(input : String) : String`
147 | 
148 | **Description:** Filters illegal characters from a given input for use in an HTML Attribute guarded by a single quote. This method is preferred if you understand exactly how the output of this will be used in the HTML document. Example Usage: <div id='${SecureFilter.forHtmlInSingleQuoteAttribute(unsafeData)}'></div> Flow: Allow AlphaNumerics and some Special characters Remove all other characters
149 | 
150 | **Parameters:**
151 | 
152 | - `input`: untrusted input to be filterd, if necessary
153 | 
154 | **Returns:**
155 | 
156 | a properly filtered string for the given input
157 | 
158 | ---
159 | 
160 | ### forHtmlUnquotedAttribute
161 | 
162 | **Signature:** `static forHtmlUnquotedAttribute(input : String) : String`
163 | 
164 | **Description:** Filters illegal characters from a given input for use in an HTML Attribute left unguarded. This method is preferred if you understand exactly how the output of this will be used in the HTML document. Example Usage: <div id=${SecureFilter.forHtmlUnquotedAttribute(unsafeData)}></div> Flow: Allow AlphaNumerics and some Special characters Remove all other characters
165 | 
166 | **Parameters:**
167 | 
168 | - `input`: untrusted input to be filtered, if necessary
169 | 
170 | **Returns:**
171 | 
172 | a properly filtered string for the given input
173 | 
174 | ---
175 | 
176 | ### forJavaScriptInAttribute
177 | 
178 | **Signature:** `static forJavaScriptInAttribute(input : String) : String`
179 | 
180 | **Description:** Filters illegal characters from a given input for use in JavaScript inside an HTML attribute. This method is preferred if you understand exactly how the output of the will be used in the page Example Usage: <button onclick="alert('${SecureFilter.forJavaScriptInAttribute(unsafeData)}');"> Flow: Allow AlphaNumerics and some Special characters Remove all other characters
181 | 
182 | **Parameters:**
183 | 
184 | - `input`: untrusted input to be filtered, if necessary
185 | 
186 | **Returns:**
187 | 
188 | a properly filtered string for the given input
189 | 
190 | ---
191 | 
192 | ### forJavaScriptInBlock
193 | 
194 | **Signature:** `static forJavaScriptInBlock(input : String) : String`
195 | 
196 | **Description:** Filters illegal characters from a given input for use in JavaScript inside an HTML block. This method is preferred if you understand exactly how the output of the will be used in the page Example Usage: <script type="text/javascript"> var data = "${SecureFilter.forJavaScriptInBlock(unsafeData)}"; </script> Flow: Allow AlphaNumerics and some Special characters Remove all other characters
197 | 
198 | **Parameters:**
199 | 
200 | - `input`: untrusted input to be filtered, if necessary
201 | 
202 | **Returns:**
203 | 
204 | a properly filtered string for the given input
205 | 
206 | ---
207 | 
208 | ### forJavaScriptInHTML
209 | 
210 | **Signature:** `static forJavaScriptInHTML(input : String) : String`
211 | 
212 | **Description:** Filters illegal characters from a given input for use in JavaScript inside an HTML context. This method takes the UNION of allowed characters among the other contexts, so may be more imprecise that the more specific contexts. Generally, this method is preferred unless you specifically understand the context in which untrusted data will be output. Example Usage: <script type="text/javascript"> var data = "${SecureFilter.forJavaScriptInHTML(unsafeData)}"; </script> <button onclick="alert('${SecureFilter.forJavaScriptInHTML(unsafeData)}');"> Flow: Allow AlphaNumerics and some Special characters Remove all other characters
213 | 
214 | **Parameters:**
215 | 
216 | - `input`: untrusted input to be filtered, if necessary
217 | 
218 | **Returns:**
219 | 
220 | a properly filtered string for the given input
221 | 
222 | ---
223 | 
224 | ### forJavaScriptInSource
225 | 
226 | **Signature:** `static forJavaScriptInSource(input : String) : String`
227 | 
228 | **Description:** Filters illegal characters from a given input for use in JavaScript inside a JavaScript source file. This method is preferred if you understand exactly how the output of the will be used in the page Example Usage: <...inside foobar.js...> var data = "${SecureFilter.forJavaScriptInSource(unsafeData)}"; Flow: Allow AlphaNumerics and some Special characters Remove all other characters
229 | 
230 | **Parameters:**
231 | 
232 | - `input`: untrusted input to be filtered, if necessary
233 | 
234 | **Returns:**
235 | 
236 | a properly filtered string for the given input
237 | 
238 | ---
239 | 
240 | ### forJSONValue
241 | 
242 | **Signature:** `static forJSONValue(input : String) : String`
243 | 
244 | **Description:** Filters illegal characters from a given input for use in a JSON Object Value to prevent escaping into a trusted context. Example Usage: var json = {"trusted_data" : SecureFilter.forJSONValue(unsafeData)}; return JSON.stringify(json); Flow: Allow AlphaNumerics Remove all other characters
245 | 
246 | **Parameters:**
247 | 
248 | - `input`: ed input to be filtered, if necessary
249 | 
250 | **Returns:**
251 | 
252 | a properly filtered string for the given input
253 | 
254 | ---
255 | 
256 | ### forUriComponent
257 | 
258 | **Signature:** `static forUriComponent(input : String) : String`
259 | 
260 | **Description:** Filters illegal characters from a given input for use as a component of a URI. This is equivalent to javascript's filterURIComponent and does a realistic job of encoding. Example Usage: <a href="http://host.com?value=${SecureFilter.forUriComponent(unsafeData)}"/> Allows: A-Z, a-z, 0-9, -, _, ., ~, !, *, ', (, ) Flow: Allow AlphaNumerics and some Special characters Remove all other characters
261 | 
262 | **Parameters:**
263 | 
264 | - `input`: untrusted input to be filtered, if necessary
265 | 
266 | **Returns:**
267 | 
268 | a properly filtered string for the given input
269 | 
270 | ---
271 | 
272 | ### forUriComponentStrict
273 | 
274 | **Signature:** `static forUriComponentStrict(input : String) : String`
275 | 
276 | **Description:** Filters illegal characters from a given input for use as a component of a URI. This is a strict filter and fully complies with RFC3986. Example Usage: <a href="http://host.com?value=${SecureFilter.forUriComponentStrict(unsafeData)}"/> Allows: A-Z, a-z, 0-9, -, _, ., ~ Flow: Allow AlphaNumerics and some Special characters Remove all other characters
277 | 
278 | **Parameters:**
279 | 
280 | - `input`: untrusted input to be filtered, if necessary
281 | 
282 | **Returns:**
283 | 
284 | a properly filtered string for the given input
285 | 
286 | ---
287 | 
288 | ### forXmlCommentContent
289 | 
290 | **Signature:** `static forXmlCommentContent(input : String) : String`
291 | 
292 | **Description:** Filters illegal characters from a given input for use in an XML comments. This method is preferred if you understand the context in which untrusted data will be output. Note: It is recommended that you use a real parser, as this method can be misused, but is left here if a parser is unavailable to you Example Usage: <!-- ${SecureFilter.forXmlCommentContent(unsafeData)} --> Flow: Allow AlphaNumerics and some Special characters Remove all other characters
293 | 
294 | **Parameters:**
295 | 
296 | - `input`: untrusted input to be filtered, if necessary
297 | 
298 | **Returns:**
299 | 
300 | a properly filtered string for the given input
301 | 
302 | ---
303 | 
304 | ### forXmlContent
305 | 
306 | **Signature:** `static forXmlContent(input : String) : String`
307 | 
308 | **Description:** Filters illegal characters from a given input for use in a general XML context. E.g. text content and text attributes. This method takes the UNION of allowed characters between the other contexts, so may be more imprecise that the more specific contexts. Generally, this method is preferred unless you specifically understand the context in which untrusted data will be output. Note: It is recommended that you use a real parser, as this method can be misused, but is left here if a parser is unavailable to you Example Usage: <foo>${SecureFilter.forXmlContent(unsafeData)}</foo> <bar attr="${SecureFilter.forXmlContent(unsafeData)}"></bar> Flow: Allow AlphaNumerics and some Special characters Remove all other characters
309 | 
310 | **Parameters:**
311 | 
312 | - `input`: untrusted input to be filtered, if necessary
313 | 
314 | **Returns:**
315 | 
316 | a properly filtered string for the given input
317 | 
318 | ---
319 | 
320 | ### forXmlInDoubleQuoteAttribute
321 | 
322 | **Signature:** `static forXmlInDoubleQuoteAttribute(input : String) : String`
323 | 
324 | **Description:** Filters illegal characters from a given input for use in an XML attribute guarded by a double quote. This method is preferred if you understand the context in which untrusted data will be output. Note: It is recommended that you use a real parser, as this method can be misused, but is left here if a parser is unavailable to you Example Usage: <bar attr="${SecureFilter.forXmlInDoubleQuoteAttribute(unsafeData)}"></bar> Flow: Allow AlphaNumerics and some Special characters Remove all other characters
325 | 
326 | **Parameters:**
327 | 
328 | - `input`: untrusted input to be filtered, if necessary
329 | 
330 | **Returns:**
331 | 
332 | a properly filtered string for the given input
333 | 
334 | ---
335 | 
336 | ### forXmlInSingleQuoteAttribute
337 | 
338 | **Signature:** `static forXmlInSingleQuoteAttribute(input : String) : String`
339 | 
340 | **Description:** Filters illegal characters from a given input for use in an XML attribute guarded by a single quote. This method is preferred if you understand the context in which untrusted data will be output. Note: It is recommended that you use a real parser, as this method can be misused, but is left here if a parser is unavailable to you Example Usage: <bar attr='${SecureFilter.forXmlInSingleQuoteAttribute(unsafeData)}'></bar> Flow: Allow AlphaNumerics and some Special characters Remove all other characters
341 | 
342 | **Parameters:**
343 | 
344 | - `input`: untrusted input to be filtered, if necessary
345 | 
346 | **Returns:**
347 | 
348 | a properly filtered string for the given input
349 | 
350 | ---
```

--------------------------------------------------------------------------------
/tests/mcp/node/get-latest-debug.full-mode.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 | // Optimized programmatic tests focusing on complex business logic, dynamic validation, and integration scenarios
  6 | // Basic functional testing is handled by the YAML tests for better CI reliability
  7 | describe('get_latest_debug - Full Mode Programmatic Tests (Optimized)', () => {
  8 |   let client;
  9 | 
 10 |   before(async () => {
 11 |     client = await connect('./aegis.config.with-dw.json');
 12 |   });
 13 | 
 14 |   after(async () => {
 15 |     if (client?.connected) {
 16 |       await client.disconnect();
 17 |     }
 18 |   });
 19 | 
 20 |   beforeEach(() => {
 21 |     // CRITICAL: Clear all buffers to prevent leaking into next tests
 22 |     client.clearAllBuffers(); // Recommended - comprehensive protection
 23 |   });
 24 | 
 25 |   // Enhanced helper functions for complex validations
 26 |   function assertValidMCPResponse(result) {
 27 |     assert.ok(result.content, 'Should have content');
 28 |     assert.ok(Array.isArray(result.content), 'Content should be array');
 29 |     assert.equal(typeof result.isError, 'boolean', 'isError should be boolean');
 30 |   }
 31 | 
 32 | 
 33 | 
 34 |   function assertSuccessResponse(result) {
 35 |     assertValidMCPResponse(result);
 36 |     assert.equal(result.isError, false, 'Should not be an error response');
 37 |     assert.equal(result.content[0].type, 'text');
 38 |   }
 39 | 
 40 |   function validateDebugLogStructure(result, expectedLimit) {
 41 |     assertSuccessResponse(result);
 42 |     const text = result.content[0].text;
 43 |     
 44 |     // Validate essential debug log components
 45 |     assert.ok(text.includes(`Latest ${expectedLimit} debug messages`),
 46 |       `Should mention "${expectedLimit}" debug messages`);
 47 |     assert.ok(/debug-blade-\d{8}-\d{6}\.log/.test(text),
 48 |       'Should contain debug log file name pattern');
 49 |     assert.ok(text.includes('DEBUG'), 'Should contain DEBUG level entries');
 50 |     assert.ok(/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3} GMT/.test(text),
 51 |       'Should contain GMT timestamp pattern');
 52 |   }
 53 | 
 54 |   function getCurrentDateString() {
 55 |     const now = new Date();
 56 |     const year = now.getFullYear();
 57 |     const month = String(now.getMonth() + 1).padStart(2, '0');
 58 |     const day = String(now.getDate()).padStart(2, '0');
 59 |     return `${year}${month}${day}`;
 60 |   }
 61 | 
 62 |   // ========================================
 63 |   // COMPLEX BUSINESS LOGIC VALIDATION
 64 |   // ========================================
 65 | 
 66 |   describe('Business Logic and Content Analysis', () => {
 67 |     test('should parse and validate SFCC debug log structure comprehensively', async () => {
 68 |       const result = await client.callTool('get_latest_debug', { limit: 5 });
 69 |       
 70 |       validateDebugLogStructure(result, 5);
 71 |       
 72 |       const text = result.content[0].text;
 73 |       
 74 |       // Validate SFCC-specific patterns that require complex logic
 75 |       const sfccPatterns = [
 76 |         /PipelineCallServlet|SystemJobThread/,
 77 |         /Sites-RefArchGlobal-Site/,
 78 |         /PipelineCall|custom \[\]/,
 79 |         /---/ // Entry separators
 80 |       ];
 81 |       
 82 |       sfccPatterns.forEach((pattern, index) => {
 83 |         assert.ok(pattern.test(text), 
 84 |           `Should contain SFCC pattern ${index}: ${pattern.toString()}`);
 85 |       });
 86 |       
 87 |       // Validate chronological ordering (newest first) - complex logic
 88 |       const entries = text.split('---').filter(entry => entry.trim());
 89 |       if (entries.length > 1) {
 90 |         const timestamps = entries.map(entry => {
 91 |           const match = entry.match(/\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3} GMT)\]/);
 92 |           return match ? new Date(match[1]) : null;
 93 |         }).filter(Boolean);
 94 |         
 95 |         for (let i = 1; i < timestamps.length; i++) {
 96 |           assert.ok(timestamps[i-1] >= timestamps[i], 
 97 |             'Debug entries should be in chronological order (newest first)');
 98 |         }
 99 |       }
100 |     });
101 | 
102 |     test('should validate complex parameter combinations with business rules', async () => {
103 |       const testScenarios = [
104 |         { 
105 |           params: { limit: 1 }, 
106 |           validator: (result) => {
107 |             assert.ok(result.content[0].text.includes('Latest 1 debug messages'));
108 |             assert.ok(!result.content[0].text.includes('---'), 
109 |               'Single entry should not have separators');
110 |           }
111 |         },
112 |         { 
113 |           params: { limit: 3, date: getCurrentDateString() }, 
114 |           validator: (result) => {
115 |             assert.ok(result.content[0].text.includes('Latest 3 debug messages'));
116 |             const separatorCount = (result.content[0].text.match(/---/g) || []).length;
117 |             assert.ok(separatorCount >= 1, 'Multiple entries should have separators');
118 |           }
119 |         },
120 |         { 
121 |           params: { limit: 20 }, 
122 |           validator: (result) => {
123 |             assert.ok(result.content[0].text.includes('Latest 20 debug messages'));
124 |             // Should handle larger limits gracefully
125 |             assert.ok(result.content[0].text.length > 1000, 
126 |               'Large limit should return substantial content');
127 |           }
128 |         }
129 |       ];
130 | 
131 |       for (const scenario of testScenarios) {
132 |         const result = await client.callTool('get_latest_debug', scenario.params);
133 |         assertSuccessResponse(result);
134 |         scenario.validator(result);
135 |       }
136 |     });
137 |   });
138 | 
139 |   // ========================================
140 |   // DYNAMIC PARAMETER VALIDATION
141 |   // ========================================
142 | 
143 |   describe('Dynamic Parameter Validation', () => {
144 |     test('should validate parameter types with complex edge case matrix', async () => {
145 |       const testMatrix = [
146 |         // Valid scenarios
147 |         { params: { limit: 5 }, expectSuccess: true, description: 'valid number limit' },
148 |         { params: { date: '20240101' }, expectSuccess: true, description: 'valid date format' },
149 |         { params: { limit: 1, date: getCurrentDateString() }, expectSuccess: true, description: 'valid combination' },
150 |         
151 |         // Invalid scenarios requiring dynamic validation
152 |         { params: { limit: '5' }, expectSuccess: false, expectedError: 'Invalid limit \'5\'', description: 'string limit' },
153 |         { params: { limit: 0 }, expectSuccess: false, expectedError: 'Invalid limit \'0\'', description: 'zero limit' },
154 |         { params: { limit: -1 }, expectSuccess: false, expectedError: 'Invalid limit', description: 'negative limit' },
155 |         { params: { limit: 9999 }, expectSuccess: false, expectedError: 'Invalid limit', description: 'excessive limit' },
156 |         
157 |         // Complex type scenarios
158 |         { params: { limit: null }, expectSuccess: true, description: 'null limit (uses default)' },
159 |         { params: { limit: [] }, expectSuccess: false, description: 'array limit' },
160 |         { params: { limit: {} }, expectSuccess: false, description: 'object limit' },
161 |       ];
162 | 
163 |       for (const testCase of testMatrix) {
164 |         const result = await client.callTool('get_latest_debug', testCase.params);
165 |         assertValidMCPResponse(result);
166 |         
167 |         if (testCase.expectSuccess) {
168 |           assert.equal(result.isError, false, 
169 |             `Should succeed for ${testCase.description}: ${JSON.stringify(testCase.params)}`);
170 |         } else {
171 |           assert.equal(result.isError, true, 
172 |             `Should fail for ${testCase.description}: ${JSON.stringify(testCase.params)}`);
173 |           
174 |           if (testCase.expectedError) {
175 |             assert.ok(result.content[0].text.includes(testCase.expectedError),
176 |               `Should contain expected error for ${testCase.description}`);
177 |           }
178 |         }
179 |       }
180 |     });
181 | 
182 |     test('should handle date parameter edge cases with business logic', async () => {
183 |       const dateScenarios = [
184 |         { date: 'invalid-date', expectMessage: 'No debug log files found' },
185 |         { date: '20261231', expectSuccess: true }, // Future date
186 |         { date: '20240101', expectSuccess: true }, // Past date
187 |         { date: 123, expectSuccess: true }, // Number converted to string
188 |       ];
189 | 
190 |       for (const scenario of dateScenarios) {
191 |         const result = await client.callTool('get_latest_debug', { 
192 |           date: scenario.date, 
193 |           limit: 1 
194 |         });
195 |         
196 |         assertValidMCPResponse(result);
197 |         
198 |         if (scenario.expectSuccess) {
199 |           assert.equal(result.isError, false, 
200 |             `Date ${scenario.date} should be handled gracefully`);
201 |         }
202 |         
203 |         if (scenario.expectMessage) {
204 |           assert.ok(result.content[0].text.includes(scenario.expectMessage),
205 |             `Should contain expected message for date ${scenario.date}`);
206 |         }
207 |       }
208 |     });
209 |   });
210 | 
211 |   // ========================================
212 |   // INTEGRATION AND WORKFLOW TESTING
213 |   // ========================================
214 | 
215 |   describe('Integration and Multi-Step Workflows', () => {
216 |     test('should integrate with MCP protocol and tool ecosystem', async () => {
217 |       // Step 1: Verify tool discovery
218 |       const tools = await client.listTools();
219 |       const debugTool = tools.find(tool => tool.name === 'get_latest_debug');
220 |       
221 |       assert.ok(debugTool, 'get_latest_debug tool should be available');
222 |       assert.ok(debugTool.description, 'Tool should have description');
223 |       assert.ok(debugTool.inputSchema, 'Tool should have input schema');
224 |       assert.equal(debugTool.inputSchema.type, 'object');
225 |       
226 |       // Step 2: Validate schema properties
227 |       const properties = debugTool.inputSchema.properties;
228 |       assert.ok(properties.limit, 'Should have limit parameter in schema');
229 |       assert.ok(properties.date, 'Should have date parameter in schema');
230 |       
231 |       // Step 3: Verify execution matches schema
232 |       const result = await client.callTool('get_latest_debug', {});
233 |       assertValidMCPResponse(result);
234 |     });
235 | 
236 |     test('should maintain consistency with related log tools', async () => {
237 |       // Get results from multiple log tools for comparison
238 |       const debugResult = await client.callTool('get_latest_debug', { limit: 3 });
239 |       const infoResult = await client.callTool('get_latest_info', { limit: 3 });
240 |       
241 |       assertValidMCPResponse(debugResult);
242 |       assertValidMCPResponse(infoResult);
243 |       
244 |       // Validate structural consistency
245 |       assert.equal(debugResult.content.length, infoResult.content.length,
246 |         'Debug and info tools should have similar response structure');
247 |       assert.equal(typeof debugResult.isError, typeof infoResult.isError,
248 |         'Both tools should handle errors consistently');
249 |       assert.equal(debugResult.content[0].type, infoResult.content[0].type,
250 |         'Content types should be consistent across log tools');
251 |     });
252 | 
253 |     test('should support progressive parameter refinement workflow', async () => {
254 |       // Workflow: Start broad, then narrow down
255 |       
256 |       // Step 1: Get initial debug overview
257 |       const broadResult = await client.callTool('get_latest_debug', { limit: 10 });
258 |       assertSuccessResponse(broadResult);
259 |       
260 |       // Step 2: Narrow down to specific recent entries
261 |       const recentResult = await client.callTool('get_latest_debug', { 
262 |         limit: 3, 
263 |         date: getCurrentDateString() 
264 |       });
265 |       assertSuccessResponse(recentResult);
266 |       
267 |       // Step 3: Focus on single most recent entry
268 |       const focusedResult = await client.callTool('get_latest_debug', { limit: 1 });
269 |       assertSuccessResponse(focusedResult);
270 |       
271 |       // Validate progressive refinement logic
272 |       assert.ok(broadResult.content[0].text.length >= recentResult.content[0].text.length,
273 |         'Broader search should return more content');
274 |       assert.ok(recentResult.content[0].text.length >= focusedResult.content[0].text.length,
275 |         'More focused search should return less content');
276 |     });
277 |   });
278 | 
279 |   // ========================================
280 |   // ERROR RECOVERY AND RESILIENCE
281 |   // ========================================
282 | 
283 |   describe('Error Recovery and Resilience', () => {
284 |     test('should recover gracefully from various error conditions', async () => {
285 |       // Test sequence of various error conditions followed by recovery
286 |       const errorSequence = [
287 |         { limit: 'invalid-string' },
288 |         { limit: -50 },
289 |         { limit: null },
290 |         { date: null, limit: 'bad' },
291 |         { unknownParam: 'test', limit: [] }
292 |       ];
293 |       
294 |       // Execute error sequence - should not break the server
295 |       for (const errorParams of errorSequence) {
296 |         const result = await client.callTool('get_latest_debug', errorParams);
297 |         assertValidMCPResponse(result);
298 |         // Don't assert success/failure as some may be handled gracefully
299 |       }
300 |       
301 |       // Verify server recovers and works normally
302 |       const recoveryResult = await client.callTool('get_latest_debug', { limit: 2 });
303 |       assertSuccessResponse(recoveryResult);
304 |       validateDebugLogStructure(recoveryResult, 2);
305 |     });
306 | 
307 |     test('should maintain state consistency across sequential operations', async () => {
308 |       // Test that multiple operations don't interfere with each other
309 |       const operations = [
310 |         { limit: 1 },
311 |         { limit: 5 },
312 |         { date: getCurrentDateString(), limit: 2 },
313 |         { limit: 10 },
314 |         { date: '20240101', limit: 1 }
315 |       ];
316 |       
317 |       const results = [];
318 |       
319 |       // Execute operations sequentially (no concurrent requests per AGENTS.md)
320 |       for (const params of operations) {
321 |         const result = await client.callTool('get_latest_debug', params);
322 |         results.push({ params, result });
323 |       }
324 |       
325 |       // Validate each operation succeeded independently
326 |       results.forEach(({ params, result }, index) => {
327 |         assertValidMCPResponse(result);
328 |         assert.equal(result.isError, false, 
329 |           `Operation ${index + 1} should succeed: ${JSON.stringify(params)}`);
330 |         
331 |         // Validate response format consistency
332 |         assert.equal(result.content.length, 1, 'Should have exactly one content item');
333 |         assert.equal(result.content[0].type, 'text', 'Content type should be text');
334 |         assert.ok(result.content[0].text.length > 0, 'Content should not be empty');
335 |       });
336 |     });
337 |   });
338 | });
339 | 
```

--------------------------------------------------------------------------------
/tests/mcp/yaml/list-sfcc-classes.full-mode.test.mcp.yml:
--------------------------------------------------------------------------------

```yaml
  1 | # ==================================================================================
  2 | # SFCC MCP Server - list_sfcc_classes Tool YAML Tests
  3 | # Comprehensive testing for SFCC class listing functionality
  4 | # Tests both successful responses and performance validation
  5 | # 
  6 | # Quick Test Commands:
  7 | # aegis "tests/mcp/yaml/list-sfcc-classes.full-mode.test.mcp.yml" --config "aegis.config.with-dw.json" --verbose
  8 | # aegis "tests/mcp/yaml/list-sfcc-classes.full-mode.test.mcp.yml" --config "aegis.config.with-dw.json" --debug --timing
  9 | # aegis query list_sfcc_classes '{}' --config "aegis.config.with-dw.json"
 10 | # ==================================================================================
 11 | description: "SFCC MCP Server list_sfcc_classes tool - comprehensive validation"
 12 | 
 13 | # ==================================================================================
 14 | # BASIC TOOL STRUCTURE VALIDATION
 15 | # ==================================================================================
 16 | tests:
 17 |   - it: "should list list_sfcc_classes tool in available tools"
 18 |     request:
 19 |       jsonrpc: "2.0"
 20 |       id: "tool-available"
 21 |       method: "tools/list"
 22 |       params: {}
 23 |     expect:
 24 |       response:
 25 |         jsonrpc: "2.0"
 26 |         id: "tool-available"
 27 |         result:
 28 |           match:extractField: "tools.*.name"
 29 |           value: "match:arrayContains:list_sfcc_classes"
 30 |       stderr: "toBeEmpty"
 31 | 
 32 |   - it: "should have list_sfcc_classes in tools list with proper structure"
 33 |     request:
 34 |       jsonrpc: "2.0"
 35 |       id: "tool-metadata"
 36 |       method: "tools/list"
 37 |       params: {}
 38 |     expect:
 39 |       response:
 40 |         jsonrpc: "2.0"
 41 |         id: "tool-metadata"
 42 |         result:
 43 |           tools: "match:arrayContains:name:list_sfcc_classes"
 44 |       stderr: "toBeEmpty"
 45 | 
 46 | # ==================================================================================
 47 | # SUCCESSFUL EXECUTION TESTS - NO PARAMETERS NEEDED
 48 | # ==================================================================================
 49 | 
 50 |   - it: "should execute with no parameters (empty object)"
 51 |     request:
 52 |       jsonrpc: "2.0"
 53 |       id: "exec-no-params"
 54 |       method: "tools/call"
 55 |       params:
 56 |         name: "list_sfcc_classes"
 57 |         arguments: {}
 58 |     expect:
 59 |       response:
 60 |         jsonrpc: "2.0"
 61 |         id: "exec-no-params"
 62 |         result:
 63 |           content:
 64 |             - type: "text"
 65 |               text: "match:type:string"
 66 |           isError: false
 67 |       stderr: "toBeEmpty"
 68 | 
 69 |   - it: "should return comprehensive class list structure"
 70 |     request:
 71 |       jsonrpc: "2.0"
 72 |       id: "exec-structure-validation"
 73 |       method: "tools/call"
 74 |       params:
 75 |         name: "list_sfcc_classes"
 76 |         arguments: {}
 77 |     expect:
 78 |       response:
 79 |         jsonrpc: "2.0"
 80 |         id: "exec-structure-validation"
 81 |         result:
 82 |           content:
 83 |             - type: "text"
 84 |               text: "match:contains:TopLevel"
 85 |           isError: false
 86 |       stderr: "toBeEmpty"
 87 | 
 88 |   - it: "should include core SFCC classes in response"
 89 |     request:
 90 |       jsonrpc: "2.0"
 91 |       id: "exec-core-classes"
 92 |       method: "tools/call"
 93 |       params:
 94 |         name: "list_sfcc_classes"
 95 |         arguments: {}
 96 |     expect:
 97 |       response:
 98 |         jsonrpc: "2.0"
 99 |         id: "exec-core-classes"
100 |         result:
101 |           content:
102 |             - type: "text"
103 |               text: "match:contains:dw.catalog"
104 |           isError: false
105 |       stderr: "toBeEmpty"
106 | 
107 |   - it: "should include system classes in response"
108 |     request:
109 |       jsonrpc: "2.0"
110 |       id: "exec-system-classes"
111 |       method: "tools/call"
112 |       params:
113 |         name: "list_sfcc_classes"
114 |         arguments: {}
115 |     expect:
116 |       response:
117 |         jsonrpc: "2.0"
118 |         id: "exec-system-classes"
119 |         result:
120 |           content:
121 |             - type: "text"
122 |               text: "match:contains:dw.system"
123 |           isError: false
124 |       stderr: "toBeEmpty"
125 | 
126 |   - it: "should include order classes in response"
127 |     request:
128 |       jsonrpc: "2.0"
129 |       id: "exec-order-classes"
130 |       method: "tools/call"
131 |       params:
132 |         name: "list_sfcc_classes"
133 |         arguments: {}
134 |     expect:
135 |       response:
136 |         jsonrpc: "2.0"
137 |         id: "exec-order-classes"
138 |         result:
139 |           content:
140 |             - type: "text"
141 |               text: "match:contains:dw.order"
142 |           isError: false
143 |       stderr: "toBeEmpty"
144 | 
145 |   - it: "should include customer classes in response"
146 |     request:
147 |       jsonrpc: "2.0"
148 |       id: "exec-customer-classes"
149 |       method: "tools/call"
150 |       params:
151 |         name: "list_sfcc_classes"
152 |         arguments: {}
153 |     expect:
154 |       response:
155 |         jsonrpc: "2.0"
156 |         id: "exec-customer-classes"
157 |         result:
158 |           content:
159 |             - type: "text"
160 |               text: "match:contains:dw.customer"
161 |           isError: false
162 |       stderr: "toBeEmpty"
163 | 
164 | # ==================================================================================
165 | # RESPONSE CONTENT VALIDATION
166 | # ==================================================================================
167 | 
168 |   - it: "should return substantial class list (not empty)"
169 |     request:
170 |       jsonrpc: "2.0"
171 |       id: "content-substantial"
172 |       method: "tools/call"
173 |       params:
174 |         name: "list_sfcc_classes"
175 |         arguments: {}
176 |     expect:
177 |       response:
178 |         jsonrpc: "2.0"
179 |         id: "content-substantial"
180 |         result:
181 |           content:
182 |             - type: "text"
183 |               text: "match:contains:dw.catalog.Product"  # Should contain specific class
184 |           isError: false
185 |       stderr: "toBeEmpty"
186 | 
187 |   - it: "should contain structured class information"
188 |     request:
189 |       jsonrpc: "2.0"
190 |       id: "content-structured"
191 |       method: "tools/call"
192 |       params:
193 |         name: "list_sfcc_classes"
194 |         arguments: {}
195 |     expect:
196 |       response:
197 |         jsonrpc: "2.0"
198 |         id: "content-structured"
199 |         result:
200 |           content:
201 |             - type: "text"
202 |               text: "match:regex:dw\\.[a-zA-Z]+"  # Should contain dw.* patterns
203 |           isError: false
204 |       stderr: "toBeEmpty"
205 | 
206 |   - it: "should include SFCC namespace classes"
207 |     request:
208 |       jsonrpc: "2.0"
209 |       id: "content-hierarchy"
210 |       method: "tools/call"
211 |       params:
212 |         name: "list_sfcc_classes"
213 |         arguments: {}
214 |     expect:
215 |       response:
216 |         jsonrpc: "2.0"
217 |         id: "content-hierarchy"
218 |         result:
219 |           content:
220 |             - type: "text"
221 |               text: "match:contains:dw.catalog"
222 |           isError: false
223 |       stderr: "toBeEmpty"
224 | 
225 | # ==================================================================================
226 | # PERFORMANCE VALIDATION
227 | # ==================================================================================
228 | 
229 |   - it: "should complete class listing within reasonable time (metadata operation)"
230 |     request:
231 |       jsonrpc: "2.0"
232 |       id: "perf-metadata-fast"
233 |       method: "tools/call"
234 |       params:
235 |         name: "list_sfcc_classes"
236 |         arguments: {}
237 |     expect:
238 |       response:
239 |         jsonrpc: "2.0"
240 |         id: "perf-metadata-fast"
241 |         result:
242 |           content:
243 |             - type: "text"
244 |               text: "match:type:string"
245 |           isError: false
246 |       performance:
247 |         maxResponseTime: "1000ms"  # Should be fast for metadata
248 |       stderr: "toBeEmpty"
249 | 
250 |   - it: "should handle class listing efficiently"
251 |     request:
252 |       jsonrpc: "2.0"
253 |       id: "perf-efficient"
254 |       method: "tools/call"
255 |       params:
256 |         name: "list_sfcc_classes"
257 |         arguments: {}
258 |     expect:
259 |       response:
260 |         jsonrpc: "2.0"
261 |         id: "perf-efficient"
262 |         result:
263 |           content: "match:type:array"
264 |           isError: false
265 |       performance:
266 |         maxResponseTime: "2000ms"  # Generous for comprehensive listing
267 |       stderr: "toBeEmpty"
268 | 
269 | # ==================================================================================
270 | # CONTENT QUALITY VALIDATION
271 | # ==================================================================================
272 | 
273 |   - it: "should include comprehensive namespace coverage"
274 |     request:
275 |       jsonrpc: "2.0"
276 |       id: "namespace-coverage"
277 |       method: "tools/call"
278 |       params:
279 |         name: "list_sfcc_classes"
280 |         arguments: {}
281 |     expect:
282 |       response:
283 |         jsonrpc: "2.0"
284 |         id: "namespace-coverage"
285 |         result:
286 |           content:
287 |             - type: "text"
288 |               text: "match:contains:dw.web"
289 |           isError: false
290 |       stderr: "toBeEmpty"
291 | 
292 |   - it: "should include utility classes"
293 |     request:
294 |       jsonrpc: "2.0"
295 |       id: "utility-classes"
296 |       method: "tools/call"
297 |       params:
298 |         name: "list_sfcc_classes"
299 |         arguments: {}
300 |     expect:
301 |       response:
302 |         jsonrpc: "2.0"
303 |         id: "utility-classes"
304 |         result:
305 |           content:
306 |             - type: "text"
307 |               text: "match:contains:dw.util"
308 |           isError: false
309 |       stderr: "toBeEmpty"
310 | 
311 |   - it: "should include IO classes"
312 |     request:
313 |       jsonrpc: "2.0"
314 |       id: "io-classes"
315 |       method: "tools/call"
316 |       params:
317 |         name: "list_sfcc_classes"
318 |         arguments: {}
319 |     expect:
320 |       response:
321 |         jsonrpc: "2.0"
322 |         id: "io-classes"
323 |         result:
324 |           content:
325 |             - type: "text"
326 |               text: "match:contains:dw.io"
327 |           isError: false
328 |       stderr: "toBeEmpty"
329 | 
330 |   - it: "should include service classes"
331 |     request:
332 |       jsonrpc: "2.0"
333 |       id: "service-classes"
334 |       method: "tools/call"
335 |       params:
336 |         name: "list_sfcc_classes"
337 |         arguments: {}
338 |     expect:
339 |       response:
340 |         jsonrpc: "2.0"
341 |         id: "service-classes"
342 |         result:
343 |           content:
344 |             - type: "text"
345 |               text: "match:contains:dw.svc"
346 |           isError: false
347 |       stderr: "toBeEmpty"
348 | 
349 | # ==================================================================================
350 | # ERROR HANDLING & EDGE CASES
351 | # ==================================================================================
352 | 
353 |   - it: "should handle call with empty arguments gracefully"
354 |     request:
355 |       jsonrpc: "2.0"
356 |       id: "empty-args"
357 |       method: "tools/call"
358 |       params:
359 |         name: "list_sfcc_classes"
360 |         arguments: {}
361 |     expect:
362 |       response:
363 |         jsonrpc: "2.0"
364 |         id: "empty-args"
365 |         result:
366 |           content:
367 |             - type: "text"
368 |               text: "match:type:string"
369 |           isError: false
370 |       stderr: "toBeEmpty"
371 | 
372 |   - it: "should handle empty arguments object consistently"
373 |     request:
374 |       jsonrpc: "2.0"
375 |       id: "empty-args-consistent"
376 |       method: "tools/call"
377 |       params:
378 |         name: "list_sfcc_classes"
379 |         arguments: {}
380 |     expect:
381 |       response:
382 |         jsonrpc: "2.0"
383 |         id: "empty-args-consistent"
384 |         result:
385 |           content:
386 |             - type: "text"
387 |               text: "match:not:contains:error"
388 |           isError: false
389 |       stderr: "toBeEmpty"
390 | 
391 |   - it: "should ignore additional parameters gracefully"
392 |     request:
393 |       jsonrpc: "2.0"
394 |       id: "extra-params"
395 |       method: "tools/call"
396 |       params:
397 |         name: "list_sfcc_classes"
398 |         arguments:
399 |           unexpectedParam: "should be ignored"
400 |           anotherParam: 123
401 |     expect:
402 |       response:
403 |         jsonrpc: "2.0"
404 |         id: "extra-params"
405 |         result:
406 |           content:
407 |             - type: "text"
408 |               text: "match:type:string"
409 |           isError: false
410 |       stderr: "toBeEmpty"
411 | 
412 | # ==================================================================================
413 | # COMPREHENSIVE CONTENT VALIDATION
414 | # ==================================================================================
415 | 
416 |   - it: "should provide educational content for new developers"
417 |     request:
418 |       jsonrpc: "2.0"
419 |       id: "educational-content"
420 |       method: "tools/call"
421 |       params:
422 |         name: "list_sfcc_classes"
423 |         arguments: {}
424 |     expect:
425 |       response:
426 |         jsonrpc: "2.0"
427 |         id: "educational-content"
428 |         result:
429 |           content:
430 |             - type: "text"
431 |               text: "match:contains:dw."
432 |           isError: false
433 |       stderr: "toBeEmpty"
434 | 
435 |   - it: "should include discovery-friendly information"
436 |     request:
437 |       jsonrpc: "2.0"
438 |       id: "discovery-friendly"
439 |       method: "tools/call"
440 |       params:
441 |         name: "list_sfcc_classes"
442 |         arguments: {}
443 |     expect:
444 |       response:
445 |         jsonrpc: "2.0"
446 |         id: "discovery-friendly"
447 |         result:
448 |           content:
449 |             - type: "text"
450 |               text: "match:not:contains:undefined"
451 |           isError: false
452 |       stderr: "toBeEmpty"
453 | 
454 |   - it: "should be useful for SFCC API exploration"
455 |     request:
456 |       jsonrpc: "2.0"
457 |       id: "api-exploration"
458 |       method: "tools/call"
459 |       params:
460 |         name: "list_sfcc_classes"
461 |         arguments: {}
462 |     expect:
463 |       response:
464 |         jsonrpc: "2.0"
465 |         id: "api-exploration"
466 |         result:
467 |           content:
468 |             - type: "text"
469 |               text: "match:contains:dw.system.Site"  # Should contain specific class
470 |           isError: false
471 |       stderr: "toBeEmpty"
472 | 
473 | # ==================================================================================
474 | # FINAL INTEGRATION VALIDATION
475 | # ==================================================================================
476 | 
477 |   - it: "should provide consistent response structure across calls"
478 |     request:
479 |       jsonrpc: "2.0"
480 |       id: "consistency-check"
481 |       method: "tools/call"
482 |       params:
483 |         name: "list_sfcc_classes"
484 |         arguments: {}
485 |     expect:
486 |       response:
487 |         jsonrpc: "2.0"
488 |         id: "consistency-check"
489 |         result:
490 |           content: "match:type:array"
491 |           isError: false
492 |       stderr: "toBeEmpty"
493 | 
494 |   - it: "should serve as good starting point for SFCC development"
495 |     request:
496 |       jsonrpc: "2.0"
497 |       id: "development-starting-point"
498 |       method: "tools/call"
499 |       params:
500 |         name: "list_sfcc_classes"
501 |         arguments: {}
502 |     expect:
503 |       response:
504 |         jsonrpc: "2.0"
505 |         id: "development-starting-point"
506 |         result:
507 |           content:
508 |             - type: "text"
509 |               text: "match:contains:TopLevel"
510 |           isError: false
511 |       stderr: "toBeEmpty"
512 | 
```

--------------------------------------------------------------------------------
/tests/mcp/yaml/list-sfcc-classes.docs-only.test.mcp.yml:
--------------------------------------------------------------------------------

```yaml
  1 | # ==================================================================================
  2 | # SFCC MCP Server - list_sfcc_classes Tool YAML Tests
  3 | # Comprehensive testing for SFCC class listing functionality
  4 | # Tests both successful responses and performance validation
  5 | # 
  6 | # Quick Test Commands:
  7 | # aegis "tests/mcp/yaml/list-sfcc-classes.docs-only.test.mcp.yml" --config "aegis.config.docs-only.json" --verbose
  8 | # aegis "tests/mcp/yaml/list-sfcc-classes.docs-only.test.mcp.yml" --config "aegis.config.docs-only.json" --debug --timing
  9 | # aegis query list_sfcc_classes '{}' --config "aegis.config.docs-only.json"
 10 | # ==================================================================================
 11 | description: "SFCC MCP Server list_sfcc_classes tool - comprehensive validation"
 12 | 
 13 | # ==================================================================================
 14 | # BASIC TOOL STRUCTURE VALIDATION
 15 | # ==================================================================================
 16 | tests:
 17 |   - it: "should list list_sfcc_classes tool in available tools"
 18 |     request:
 19 |       jsonrpc: "2.0"
 20 |       id: "tool-available"
 21 |       method: "tools/list"
 22 |       params: {}
 23 |     expect:
 24 |       response:
 25 |         jsonrpc: "2.0"
 26 |         id: "tool-available"
 27 |         result:
 28 |           match:extractField: "tools.*.name"
 29 |           value: "match:arrayContains:list_sfcc_classes"
 30 |       stderr: "toBeEmpty"
 31 | 
 32 |   - it: "should have list_sfcc_classes in tools list with proper structure"
 33 |     request:
 34 |       jsonrpc: "2.0"
 35 |       id: "tool-metadata"
 36 |       method: "tools/list"
 37 |       params: {}
 38 |     expect:
 39 |       response:
 40 |         jsonrpc: "2.0"
 41 |         id: "tool-metadata"
 42 |         result:
 43 |           tools: "match:arrayContains:name:list_sfcc_classes"
 44 |       stderr: "toBeEmpty"
 45 | 
 46 | # ==================================================================================
 47 | # SUCCESSFUL EXECUTION TESTS - NO PARAMETERS NEEDED
 48 | # ==================================================================================
 49 | 
 50 |   - it: "should execute with no parameters (empty object)"
 51 |     request:
 52 |       jsonrpc: "2.0"
 53 |       id: "exec-no-params"
 54 |       method: "tools/call"
 55 |       params:
 56 |         name: "list_sfcc_classes"
 57 |         arguments: {}
 58 |     expect:
 59 |       response:
 60 |         jsonrpc: "2.0"
 61 |         id: "exec-no-params"
 62 |         result:
 63 |           content:
 64 |             - type: "text"
 65 |               text: "match:type:string"
 66 |           isError: false
 67 |       stderr: "toBeEmpty"
 68 | 
 69 |   - it: "should return comprehensive class list structure"
 70 |     request:
 71 |       jsonrpc: "2.0"
 72 |       id: "exec-structure-validation"
 73 |       method: "tools/call"
 74 |       params:
 75 |         name: "list_sfcc_classes"
 76 |         arguments: {}
 77 |     expect:
 78 |       response:
 79 |         jsonrpc: "2.0"
 80 |         id: "exec-structure-validation"
 81 |         result:
 82 |           content:
 83 |             - type: "text"
 84 |               text: "match:contains:TopLevel"
 85 |           isError: false
 86 |       stderr: "toBeEmpty"
 87 | 
 88 |   - it: "should include core SFCC classes in response"
 89 |     request:
 90 |       jsonrpc: "2.0"
 91 |       id: "exec-core-classes"
 92 |       method: "tools/call"
 93 |       params:
 94 |         name: "list_sfcc_classes"
 95 |         arguments: {}
 96 |     expect:
 97 |       response:
 98 |         jsonrpc: "2.0"
 99 |         id: "exec-core-classes"
100 |         result:
101 |           content:
102 |             - type: "text"
103 |               text: "match:contains:dw.catalog"
104 |           isError: false
105 |       stderr: "toBeEmpty"
106 | 
107 |   - it: "should include system classes in response"
108 |     request:
109 |       jsonrpc: "2.0"
110 |       id: "exec-system-classes"
111 |       method: "tools/call"
112 |       params:
113 |         name: "list_sfcc_classes"
114 |         arguments: {}
115 |     expect:
116 |       response:
117 |         jsonrpc: "2.0"
118 |         id: "exec-system-classes"
119 |         result:
120 |           content:
121 |             - type: "text"
122 |               text: "match:contains:dw.system"
123 |           isError: false
124 |       stderr: "toBeEmpty"
125 | 
126 |   - it: "should include order classes in response"
127 |     request:
128 |       jsonrpc: "2.0"
129 |       id: "exec-order-classes"
130 |       method: "tools/call"
131 |       params:
132 |         name: "list_sfcc_classes"
133 |         arguments: {}
134 |     expect:
135 |       response:
136 |         jsonrpc: "2.0"
137 |         id: "exec-order-classes"
138 |         result:
139 |           content:
140 |             - type: "text"
141 |               text: "match:contains:dw.order"
142 |           isError: false
143 |       stderr: "toBeEmpty"
144 | 
145 |   - it: "should include customer classes in response"
146 |     request:
147 |       jsonrpc: "2.0"
148 |       id: "exec-customer-classes"
149 |       method: "tools/call"
150 |       params:
151 |         name: "list_sfcc_classes"
152 |         arguments: {}
153 |     expect:
154 |       response:
155 |         jsonrpc: "2.0"
156 |         id: "exec-customer-classes"
157 |         result:
158 |           content:
159 |             - type: "text"
160 |               text: "match:contains:dw.customer"
161 |           isError: false
162 |       stderr: "toBeEmpty"
163 | 
164 | # ==================================================================================
165 | # RESPONSE CONTENT VALIDATION
166 | # ==================================================================================
167 | 
168 |   - it: "should return substantial class list (not empty)"
169 |     request:
170 |       jsonrpc: "2.0"
171 |       id: "content-substantial"
172 |       method: "tools/call"
173 |       params:
174 |         name: "list_sfcc_classes"
175 |         arguments: {}
176 |     expect:
177 |       response:
178 |         jsonrpc: "2.0"
179 |         id: "content-substantial"
180 |         result:
181 |           content:
182 |             - type: "text"
183 |               text: "match:contains:dw.catalog.Product"  # Should contain specific class
184 |           isError: false
185 |       stderr: "toBeEmpty"
186 | 
187 |   - it: "should contain structured class information"
188 |     request:
189 |       jsonrpc: "2.0"
190 |       id: "content-structured"
191 |       method: "tools/call"
192 |       params:
193 |         name: "list_sfcc_classes"
194 |         arguments: {}
195 |     expect:
196 |       response:
197 |         jsonrpc: "2.0"
198 |         id: "content-structured"
199 |         result:
200 |           content:
201 |             - type: "text"
202 |               text: "match:regex:dw\\.[a-zA-Z]+"  # Should contain dw.* patterns
203 |           isError: false
204 |       stderr: "toBeEmpty"
205 | 
206 |   - it: "should include SFCC namespace classes"
207 |     request:
208 |       jsonrpc: "2.0"
209 |       id: "content-hierarchy"
210 |       method: "tools/call"
211 |       params:
212 |         name: "list_sfcc_classes"
213 |         arguments: {}
214 |     expect:
215 |       response:
216 |         jsonrpc: "2.0"
217 |         id: "content-hierarchy"
218 |         result:
219 |           content:
220 |             - type: "text"
221 |               text: "match:contains:dw.catalog"
222 |           isError: false
223 |       stderr: "toBeEmpty"
224 | 
225 | # ==================================================================================
226 | # PERFORMANCE VALIDATION
227 | # ==================================================================================
228 | 
229 |   - it: "should complete class listing within reasonable time (metadata operation)"
230 |     request:
231 |       jsonrpc: "2.0"
232 |       id: "perf-metadata-fast"
233 |       method: "tools/call"
234 |       params:
235 |         name: "list_sfcc_classes"
236 |         arguments: {}
237 |     expect:
238 |       response:
239 |         jsonrpc: "2.0"
240 |         id: "perf-metadata-fast"
241 |         result:
242 |           content:
243 |             - type: "text"
244 |               text: "match:type:string"
245 |           isError: false
246 |       performance:
247 |         maxResponseTime: "1000ms"  # Should be fast for metadata
248 |       stderr: "toBeEmpty"
249 | 
250 |   - it: "should handle class listing efficiently"
251 |     request:
252 |       jsonrpc: "2.0"
253 |       id: "perf-efficient"
254 |       method: "tools/call"
255 |       params:
256 |         name: "list_sfcc_classes"
257 |         arguments: {}
258 |     expect:
259 |       response:
260 |         jsonrpc: "2.0"
261 |         id: "perf-efficient"
262 |         result:
263 |           content: "match:type:array"
264 |           isError: false
265 |       performance:
266 |         maxResponseTime: "2000ms"  # Generous for comprehensive listing
267 |       stderr: "toBeEmpty"
268 | 
269 | # ==================================================================================
270 | # CONTENT QUALITY VALIDATION
271 | # ==================================================================================
272 | 
273 |   - it: "should include comprehensive namespace coverage"
274 |     request:
275 |       jsonrpc: "2.0"
276 |       id: "namespace-coverage"
277 |       method: "tools/call"
278 |       params:
279 |         name: "list_sfcc_classes"
280 |         arguments: {}
281 |     expect:
282 |       response:
283 |         jsonrpc: "2.0"
284 |         id: "namespace-coverage"
285 |         result:
286 |           content:
287 |             - type: "text"
288 |               text: "match:contains:dw.web"
289 |           isError: false
290 |       stderr: "toBeEmpty"
291 | 
292 |   - it: "should include utility classes"
293 |     request:
294 |       jsonrpc: "2.0"
295 |       id: "utility-classes"
296 |       method: "tools/call"
297 |       params:
298 |         name: "list_sfcc_classes"
299 |         arguments: {}
300 |     expect:
301 |       response:
302 |         jsonrpc: "2.0"
303 |         id: "utility-classes"
304 |         result:
305 |           content:
306 |             - type: "text"
307 |               text: "match:contains:dw.util"
308 |           isError: false
309 |       stderr: "toBeEmpty"
310 | 
311 |   - it: "should include IO classes"
312 |     request:
313 |       jsonrpc: "2.0"
314 |       id: "io-classes"
315 |       method: "tools/call"
316 |       params:
317 |         name: "list_sfcc_classes"
318 |         arguments: {}
319 |     expect:
320 |       response:
321 |         jsonrpc: "2.0"
322 |         id: "io-classes"
323 |         result:
324 |           content:
325 |             - type: "text"
326 |               text: "match:contains:dw.io"
327 |           isError: false
328 |       stderr: "toBeEmpty"
329 | 
330 |   - it: "should include service classes"
331 |     request:
332 |       jsonrpc: "2.0"
333 |       id: "service-classes"
334 |       method: "tools/call"
335 |       params:
336 |         name: "list_sfcc_classes"
337 |         arguments: {}
338 |     expect:
339 |       response:
340 |         jsonrpc: "2.0"
341 |         id: "service-classes"
342 |         result:
343 |           content:
344 |             - type: "text"
345 |               text: "match:contains:dw.svc"
346 |           isError: false
347 |       stderr: "toBeEmpty"
348 | 
349 | # ==================================================================================
350 | # ERROR HANDLING & EDGE CASES
351 | # ==================================================================================
352 | 
353 |   - it: "should handle call with empty arguments gracefully"
354 |     request:
355 |       jsonrpc: "2.0"
356 |       id: "empty-args"
357 |       method: "tools/call"
358 |       params:
359 |         name: "list_sfcc_classes"
360 |         arguments: {}
361 |     expect:
362 |       response:
363 |         jsonrpc: "2.0"
364 |         id: "empty-args"
365 |         result:
366 |           content:
367 |             - type: "text"
368 |               text: "match:type:string"
369 |           isError: false
370 |       stderr: "toBeEmpty"
371 | 
372 |   - it: "should handle empty arguments object consistently"
373 |     request:
374 |       jsonrpc: "2.0"
375 |       id: "empty-args-consistent"
376 |       method: "tools/call"
377 |       params:
378 |         name: "list_sfcc_classes"
379 |         arguments: {}
380 |     expect:
381 |       response:
382 |         jsonrpc: "2.0"
383 |         id: "empty-args-consistent"
384 |         result:
385 |           content:
386 |             - type: "text"
387 |               text: "match:not:contains:error"
388 |           isError: false
389 |       stderr: "toBeEmpty"
390 | 
391 |   - it: "should ignore additional parameters gracefully"
392 |     request:
393 |       jsonrpc: "2.0"
394 |       id: "extra-params"
395 |       method: "tools/call"
396 |       params:
397 |         name: "list_sfcc_classes"
398 |         arguments:
399 |           unexpectedParam: "should be ignored"
400 |           anotherParam: 123
401 |     expect:
402 |       response:
403 |         jsonrpc: "2.0"
404 |         id: "extra-params"
405 |         result:
406 |           content:
407 |             - type: "text"
408 |               text: "match:type:string"
409 |           isError: false
410 |       stderr: "toBeEmpty"
411 | 
412 | # ==================================================================================
413 | # COMPREHENSIVE CONTENT VALIDATION
414 | # ==================================================================================
415 | 
416 |   - it: "should provide educational content for new developers"
417 |     request:
418 |       jsonrpc: "2.0"
419 |       id: "educational-content"
420 |       method: "tools/call"
421 |       params:
422 |         name: "list_sfcc_classes"
423 |         arguments: {}
424 |     expect:
425 |       response:
426 |         jsonrpc: "2.0"
427 |         id: "educational-content"
428 |         result:
429 |           content:
430 |             - type: "text"
431 |               text: "match:contains:dw."
432 |           isError: false
433 |       stderr: "toBeEmpty"
434 | 
435 |   - it: "should include discovery-friendly information"
436 |     request:
437 |       jsonrpc: "2.0"
438 |       id: "discovery-friendly"
439 |       method: "tools/call"
440 |       params:
441 |         name: "list_sfcc_classes"
442 |         arguments: {}
443 |     expect:
444 |       response:
445 |         jsonrpc: "2.0"
446 |         id: "discovery-friendly"
447 |         result:
448 |           content:
449 |             - type: "text"
450 |               text: "match:not:contains:undefined"
451 |           isError: false
452 |       stderr: "toBeEmpty"
453 | 
454 |   - it: "should be useful for SFCC API exploration"
455 |     request:
456 |       jsonrpc: "2.0"
457 |       id: "api-exploration"
458 |       method: "tools/call"
459 |       params:
460 |         name: "list_sfcc_classes"
461 |         arguments: {}
462 |     expect:
463 |       response:
464 |         jsonrpc: "2.0"
465 |         id: "api-exploration"
466 |         result:
467 |           content:
468 |             - type: "text"
469 |               text: "match:contains:dw.system.Site"  # Should contain specific class
470 |           isError: false
471 |       stderr: "toBeEmpty"
472 | 
473 | # ==================================================================================
474 | # FINAL INTEGRATION VALIDATION
475 | # ==================================================================================
476 | 
477 |   - it: "should provide consistent response structure across calls"
478 |     request:
479 |       jsonrpc: "2.0"
480 |       id: "consistency-check"
481 |       method: "tools/call"
482 |       params:
483 |         name: "list_sfcc_classes"
484 |         arguments: {}
485 |     expect:
486 |       response:
487 |         jsonrpc: "2.0"
488 |         id: "consistency-check"
489 |         result:
490 |           content: "match:type:array"
491 |           isError: false
492 |       stderr: "toBeEmpty"
493 | 
494 |   - it: "should serve as good starting point for SFCC development"
495 |     request:
496 |       jsonrpc: "2.0"
497 |       id: "development-starting-point"
498 |       method: "tools/call"
499 |       params:
500 |         name: "list_sfcc_classes"
501 |         arguments: {}
502 |     expect:
503 |       response:
504 |         jsonrpc: "2.0"
505 |         id: "development-starting-point"
506 |         result:
507 |           content:
508 |             - type: "text"
509 |               text: "match:contains:TopLevel"
510 |           isError: false
511 |       stderr: "toBeEmpty"
512 | 
```

--------------------------------------------------------------------------------
/docs/dw_io/XMLStreamWriter.md:
--------------------------------------------------------------------------------

```markdown
  1 | ## Package: dw.io
  2 | 
  3 | # Class XMLStreamWriter
  4 | 
  5 | ## Inheritance Hierarchy
  6 | 
  7 | - Object
  8 |   - dw.io.XMLStreamWriter
  9 | 
 10 | ## Description
 11 | 
 12 | The XMLStreamWriter can be used to write small and large XML feeds. Note: when this class is used with sensitive data, be careful in persisting sensitive information to disk. The XMLStreamWriter does not perform well-formedness checking on its input. However the writeCharacters method escapes '&' , '<' and '>'. For attribute values the writeAttribute method escapes the above characters plus '"' to ensure that all character content and attribute values are well formed. The following example illustrates how to use this class: var fileWriter : FileWriter = new FileWriter(file, "UTF-8"); var xsw : XMLStreamWriter = new XMLStreamWriter(fileWriter); xsw.writeStartDocument(); xsw.writeStartElement("products"); xsw.writeStartElement("product"); xsw.writeAttribute("id", "p42"); xsw.writeStartElement("name"); xsw.writeCharacters("blue t-shirt"); xsw.writeEndElement(); xsw.writeStartElement("rating"); xsw.writeCharacters("2.0"); xsw.writeEndElement(); xsw.writeEndElement(); xsw.writeEndElement(); xsw.writeEndDocument(); xsw.close(); fileWriter.close(); The code above will write the following to file: <?xml version="1.0" ?> <products> <product id="p42"> <name>a blue t-shirt</name> <rating>2.0</rating> </product> </products> Note: This output has been formatted for readability. See XMLIndentingStreamWriter.
 13 | 
 14 | ## Properties
 15 | 
 16 | ### defaultNamespace
 17 | 
 18 | **Type:** String
 19 | 
 20 | The current default name space.
 21 | 
 22 | ## Constructor Summary
 23 | 
 24 | XMLStreamWriter(writer : Writer) Constructs the XMLStreamWriter for a writer.
 25 | 
 26 | ## Method Summary
 27 | 
 28 | ### close
 29 | 
 30 | **Signature:** `close() : void`
 31 | 
 32 | Close this writer and free any resources associated with the writer.
 33 | 
 34 | ### flush
 35 | 
 36 | **Signature:** `flush() : void`
 37 | 
 38 | Write any cached data to the underlying output mechanism.
 39 | 
 40 | ### getDefaultNamespace
 41 | 
 42 | **Signature:** `getDefaultNamespace() : String`
 43 | 
 44 | Returns the current default name space.
 45 | 
 46 | ### getPrefix
 47 | 
 48 | **Signature:** `getPrefix(uri : String) : String`
 49 | 
 50 | Gets the prefix the URI is bound to.
 51 | 
 52 | ### setDefaultNamespace
 53 | 
 54 | **Signature:** `setDefaultNamespace(uri : String) : void`
 55 | 
 56 | Binds a URI to the default namespace.
 57 | 
 58 | ### setPrefix
 59 | 
 60 | **Signature:** `setPrefix(prefix : String, uri : String) : void`
 61 | 
 62 | Sets the prefix the uri is bound to.
 63 | 
 64 | ### writeAttribute
 65 | 
 66 | **Signature:** `writeAttribute(localName : String, value : String) : void`
 67 | 
 68 | Writes an attribute to the output stream without a prefix.
 69 | 
 70 | ### writeAttribute
 71 | 
 72 | **Signature:** `writeAttribute(prefix : String, namespaceURI : String, localName : String, value : String) : void`
 73 | 
 74 | Writes an attribute to the output stream.
 75 | 
 76 | ### writeAttribute
 77 | 
 78 | **Signature:** `writeAttribute(namespaceURI : String, localName : String, value : String) : void`
 79 | 
 80 | Writes an attribute to the output stream.
 81 | 
 82 | ### writeCData
 83 | 
 84 | **Signature:** `writeCData(data : String) : void`
 85 | 
 86 | Writes a CData section.
 87 | 
 88 | ### writeCharacters
 89 | 
 90 | **Signature:** `writeCharacters(text : String) : void`
 91 | 
 92 | Write text to the output.
 93 | 
 94 | ### writeComment
 95 | 
 96 | **Signature:** `writeComment(data : String) : void`
 97 | 
 98 | Writes an XML comment with the data enclosed.
 99 | 
100 | ### writeDefaultNamespace
101 | 
102 | **Signature:** `writeDefaultNamespace(namespaceURI : String) : void`
103 | 
104 | Writes the default namespace to the stream.
105 | 
106 | ### writeDTD
107 | 
108 | **Signature:** `writeDTD(dtd : String) : void`
109 | 
110 | Write a DTD section.
111 | 
112 | ### writeEmptyElement
113 | 
114 | **Signature:** `writeEmptyElement(namespaceURI : String, localName : String) : void`
115 | 
116 | Writes an empty element tag to the output.
117 | 
118 | ### writeEmptyElement
119 | 
120 | **Signature:** `writeEmptyElement(prefix : String, localName : String, namespaceURI : String) : void`
121 | 
122 | Writes an empty element tag to the output.
123 | 
124 | ### writeEmptyElement
125 | 
126 | **Signature:** `writeEmptyElement(localName : String) : void`
127 | 
128 | Writes an empty element tag to the output.
129 | 
130 | ### writeEndDocument
131 | 
132 | **Signature:** `writeEndDocument() : void`
133 | 
134 | Closes any start tags and writes corresponding end tags.
135 | 
136 | ### writeEndElement
137 | 
138 | **Signature:** `writeEndElement() : void`
139 | 
140 | Writes an end tag to the output relying on the internal state of the writer to determine the prefix and local name of the event.
141 | 
142 | ### writeEntityRef
143 | 
144 | **Signature:** `writeEntityRef(name : String) : void`
145 | 
146 | Writes an entity reference.
147 | 
148 | ### writeNamespace
149 | 
150 | **Signature:** `writeNamespace(prefix : String, namespaceURI : String) : void`
151 | 
152 | Writes a namespace to the output stream.
153 | 
154 | ### writeProcessingInstruction
155 | 
156 | **Signature:** `writeProcessingInstruction(target : String) : void`
157 | 
158 | Writes a processing instruction.
159 | 
160 | ### writeProcessingInstruction
161 | 
162 | **Signature:** `writeProcessingInstruction(target : String, data : String) : void`
163 | 
164 | Writes a processing instruction.
165 | 
166 | ### writeRaw
167 | 
168 | **Signature:** `writeRaw(raw : String) : void`
169 | 
170 | Writes the given string directly into the output stream.
171 | 
172 | ### writeStartDocument
173 | 
174 | **Signature:** `writeStartDocument() : void`
175 | 
176 | Write the XML Declaration.
177 | 
178 | ### writeStartDocument
179 | 
180 | **Signature:** `writeStartDocument(version : String) : void`
181 | 
182 | Write the XML Declaration.
183 | 
184 | ### writeStartDocument
185 | 
186 | **Signature:** `writeStartDocument(encoding : String, version : String) : void`
187 | 
188 | Write the XML Declaration.
189 | 
190 | ### writeStartElement
191 | 
192 | **Signature:** `writeStartElement(localName : String) : void`
193 | 
194 | Writes a start tag to the output.
195 | 
196 | ### writeStartElement
197 | 
198 | **Signature:** `writeStartElement(namespaceURI : String, localName : String) : void`
199 | 
200 | Writes a start tag to the output.
201 | 
202 | ### writeStartElement
203 | 
204 | **Signature:** `writeStartElement(prefix : String, localName : String, namespaceURI : String) : void`
205 | 
206 | Writes a start tag to the output.
207 | 
208 | ## Constructor Detail
209 | 
210 | ## Method Detail
211 | 
212 | ## Method Details
213 | 
214 | ### close
215 | 
216 | **Signature:** `close() : void`
217 | 
218 | **Description:** Close this writer and free any resources associated with the writer. This method does not close the underlying writer.
219 | 
220 | ---
221 | 
222 | ### flush
223 | 
224 | **Signature:** `flush() : void`
225 | 
226 | **Description:** Write any cached data to the underlying output mechanism.
227 | 
228 | ---
229 | 
230 | ### getDefaultNamespace
231 | 
232 | **Signature:** `getDefaultNamespace() : String`
233 | 
234 | **Description:** Returns the current default name space.
235 | 
236 | **Returns:**
237 | 
238 | the current default name space.
239 | 
240 | ---
241 | 
242 | ### getPrefix
243 | 
244 | **Signature:** `getPrefix(uri : String) : String`
245 | 
246 | **Description:** Gets the prefix the URI is bound to.
247 | 
248 | **Parameters:**
249 | 
250 | - `uri`: the URI to use.
251 | 
252 | **Returns:**
253 | 
254 | the prefix or null.
255 | 
256 | ---
257 | 
258 | ### setDefaultNamespace
259 | 
260 | **Signature:** `setDefaultNamespace(uri : String) : void`
261 | 
262 | **Description:** Binds a URI to the default namespace. This URI is bound in the scope of the current START_ELEMENT / END_ELEMENT pair. If this method is called before a START_ELEMENT has been written the uri is bound in the root scope.
263 | 
264 | **Parameters:**
265 | 
266 | - `uri`: the uri to bind to the default namespace, may be null.
267 | 
268 | ---
269 | 
270 | ### setPrefix
271 | 
272 | **Signature:** `setPrefix(prefix : String, uri : String) : void`
273 | 
274 | **Description:** Sets the prefix the uri is bound to. This prefix is bound in the scope of the current START_ELEMENT / END_ELEMENT pair. If this method is called before a START_ELEMENT has been written the prefix is bound in the root scope.
275 | 
276 | **Parameters:**
277 | 
278 | - `prefix`: the prefix to bind to the uri, may not be null.
279 | - `uri`: the uri to bind to the prefix, may be null.
280 | 
281 | ---
282 | 
283 | ### writeAttribute
284 | 
285 | **Signature:** `writeAttribute(localName : String, value : String) : void`
286 | 
287 | **Description:** Writes an attribute to the output stream without a prefix.
288 | 
289 | **Parameters:**
290 | 
291 | - `localName`: the local name of the attribute.
292 | - `value`: the value of the attribute.
293 | 
294 | ---
295 | 
296 | ### writeAttribute
297 | 
298 | **Signature:** `writeAttribute(prefix : String, namespaceURI : String, localName : String, value : String) : void`
299 | 
300 | **Description:** Writes an attribute to the output stream.
301 | 
302 | **Parameters:**
303 | 
304 | - `prefix`: the prefix for this attribute.
305 | - `namespaceURI`: the uri of the prefix for this attribute.
306 | - `localName`: the local name of the attribute.
307 | - `value`: the value of the attribute.
308 | 
309 | ---
310 | 
311 | ### writeAttribute
312 | 
313 | **Signature:** `writeAttribute(namespaceURI : String, localName : String, value : String) : void`
314 | 
315 | **Description:** Writes an attribute to the output stream.
316 | 
317 | **Parameters:**
318 | 
319 | - `namespaceURI`: the uri of the prefix for this attribute.
320 | - `localName`: the local name of the attribute.
321 | - `value`: the value of the attribute.
322 | 
323 | ---
324 | 
325 | ### writeCData
326 | 
327 | **Signature:** `writeCData(data : String) : void`
328 | 
329 | **Description:** Writes a CData section.
330 | 
331 | **Parameters:**
332 | 
333 | - `data`: the data contained in the CData Section, may not be null.
334 | 
335 | ---
336 | 
337 | ### writeCharacters
338 | 
339 | **Signature:** `writeCharacters(text : String) : void`
340 | 
341 | **Description:** Write text to the output.
342 | 
343 | **Parameters:**
344 | 
345 | - `text`: the value to write.
346 | 
347 | ---
348 | 
349 | ### writeComment
350 | 
351 | **Signature:** `writeComment(data : String) : void`
352 | 
353 | **Description:** Writes an XML comment with the data enclosed.
354 | 
355 | **Parameters:**
356 | 
357 | - `data`: the data contained in the comment, may be null.
358 | 
359 | ---
360 | 
361 | ### writeDefaultNamespace
362 | 
363 | **Signature:** `writeDefaultNamespace(namespaceURI : String) : void`
364 | 
365 | **Description:** Writes the default namespace to the stream.
366 | 
367 | **Parameters:**
368 | 
369 | - `namespaceURI`: the uri to bind the default namespace to.
370 | 
371 | ---
372 | 
373 | ### writeDTD
374 | 
375 | **Signature:** `writeDTD(dtd : String) : void`
376 | 
377 | **Description:** Write a DTD section. This string represents the entire doctypedecl production from the XML 1.0 specification.
378 | 
379 | **Parameters:**
380 | 
381 | - `dtd`: the DTD to be written.
382 | 
383 | ---
384 | 
385 | ### writeEmptyElement
386 | 
387 | **Signature:** `writeEmptyElement(namespaceURI : String, localName : String) : void`
388 | 
389 | **Description:** Writes an empty element tag to the output.
390 | 
391 | **Parameters:**
392 | 
393 | - `namespaceURI`: the uri to bind the tag to, may not be null.
394 | - `localName`: local name of the tag, may not be null.
395 | 
396 | ---
397 | 
398 | ### writeEmptyElement
399 | 
400 | **Signature:** `writeEmptyElement(prefix : String, localName : String, namespaceURI : String) : void`
401 | 
402 | **Description:** Writes an empty element tag to the output.
403 | 
404 | **Parameters:**
405 | 
406 | - `prefix`: the prefix of the tag, may not be null.
407 | - `localName`: local name of the tag, may not be null.
408 | - `namespaceURI`: the uri to bind the tag to, may not be null.
409 | 
410 | ---
411 | 
412 | ### writeEmptyElement
413 | 
414 | **Signature:** `writeEmptyElement(localName : String) : void`
415 | 
416 | **Description:** Writes an empty element tag to the output.
417 | 
418 | **Parameters:**
419 | 
420 | - `localName`: local name of the tag, may not be null.
421 | 
422 | ---
423 | 
424 | ### writeEndDocument
425 | 
426 | **Signature:** `writeEndDocument() : void`
427 | 
428 | **Description:** Closes any start tags and writes corresponding end tags.
429 | 
430 | ---
431 | 
432 | ### writeEndElement
433 | 
434 | **Signature:** `writeEndElement() : void`
435 | 
436 | **Description:** Writes an end tag to the output relying on the internal state of the writer to determine the prefix and local name of the event.
437 | 
438 | ---
439 | 
440 | ### writeEntityRef
441 | 
442 | **Signature:** `writeEntityRef(name : String) : void`
443 | 
444 | **Description:** Writes an entity reference.
445 | 
446 | **Parameters:**
447 | 
448 | - `name`: the name of the entity.
449 | 
450 | ---
451 | 
452 | ### writeNamespace
453 | 
454 | **Signature:** `writeNamespace(prefix : String, namespaceURI : String) : void`
455 | 
456 | **Description:** Writes a namespace to the output stream. If the prefix argument to this method is the empty string, "xmlns", or null this method will delegate to writeDefaultNamespace.
457 | 
458 | **Parameters:**
459 | 
460 | - `prefix`: the prefix to bind this namespace to.
461 | - `namespaceURI`: the uri to bind the prefix to.
462 | 
463 | ---
464 | 
465 | ### writeProcessingInstruction
466 | 
467 | **Signature:** `writeProcessingInstruction(target : String) : void`
468 | 
469 | **Description:** Writes a processing instruction.
470 | 
471 | **Parameters:**
472 | 
473 | - `target`: the target of the processing instruction, may not be null.
474 | 
475 | ---
476 | 
477 | ### writeProcessingInstruction
478 | 
479 | **Signature:** `writeProcessingInstruction(target : String, data : String) : void`
480 | 
481 | **Description:** Writes a processing instruction.
482 | 
483 | **Parameters:**
484 | 
485 | - `target`: the target of the processing instruction, may not be null.
486 | - `data`: the data contained in the processing instruction, may not be null.
487 | 
488 | ---
489 | 
490 | ### writeRaw
491 | 
492 | **Signature:** `writeRaw(raw : String) : void`
493 | 
494 | **Description:** Writes the given string directly into the output stream. No checks regarding the correctness of the XML are done. The caller must ensure that the final result is a correct XML.
495 | 
496 | **Parameters:**
497 | 
498 | - `raw`: the string to write to the output stream.
499 | 
500 | ---
501 | 
502 | ### writeStartDocument
503 | 
504 | **Signature:** `writeStartDocument() : void`
505 | 
506 | **Description:** Write the XML Declaration. Defaults the XML version to 1.0, and the encoding to utf-8
507 | 
508 | ---
509 | 
510 | ### writeStartDocument
511 | 
512 | **Signature:** `writeStartDocument(version : String) : void`
513 | 
514 | **Description:** Write the XML Declaration. Defaults the XML version to 1.0
515 | 
516 | **Parameters:**
517 | 
518 | - `version`: version of the xml document.
519 | 
520 | ---
521 | 
522 | ### writeStartDocument
523 | 
524 | **Signature:** `writeStartDocument(encoding : String, version : String) : void`
525 | 
526 | **Description:** Write the XML Declaration. Note that the encoding parameter does not set the actual encoding of the underlying output. That must be set when the instance of the XMLStreamWriter is created using the XMLOutputFactory.
527 | 
528 | **Parameters:**
529 | 
530 | - `encoding`: encoding of the xml declaration.
531 | - `version`: version of the xml document.
532 | 
533 | ---
534 | 
535 | ### writeStartElement
536 | 
537 | **Signature:** `writeStartElement(localName : String) : void`
538 | 
539 | **Description:** Writes a start tag to the output. All writeStartElement methods open a new scope in the internal namespace context. Writing the corresponding EndElement causes the scope to be closed.
540 | 
541 | **Parameters:**
542 | 
543 | - `localName`: local name of the tag, may not be null.
544 | 
545 | ---
546 | 
547 | ### writeStartElement
548 | 
549 | **Signature:** `writeStartElement(namespaceURI : String, localName : String) : void`
550 | 
551 | **Description:** Writes a start tag to the output.
552 | 
553 | **Parameters:**
554 | 
555 | - `namespaceURI`: the namespaceURI of the prefix to use, may not be null.
556 | - `localName`: local name of the tag, may not be null.
557 | 
558 | ---
559 | 
560 | ### writeStartElement
561 | 
562 | **Signature:** `writeStartElement(prefix : String, localName : String, namespaceURI : String) : void`
563 | 
564 | **Description:** Writes a start tag to the output.
565 | 
566 | **Parameters:**
567 | 
568 | - `prefix`: the prefix of the tag, may not be null.
569 | - `localName`: local name of the tag, may not be null.
570 | - `namespaceURI`: the uri to bind the prefix to, may not be null.
571 | 
572 | ---
```

--------------------------------------------------------------------------------
/tests/mcp/node/summarize-logs.full-mode.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('summarize_logs - Full Mode Programmatic Tests', () => {
  6 |   let client;
  7 | 
  8 |   before(async () => {
  9 |     client = await connect('./aegis.config.with-dw.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(); // Recommended - comprehensive protection
 21 |   });
 22 | 
 23 |   // Helper function to get current date in YYYYMMDD format
 24 |   function getCurrentDateString() {
 25 |     const now = new Date();
 26 |     const year = now.getFullYear();
 27 |     const month = String(now.getMonth() + 1).padStart(2, '0');
 28 |     const day = String(now.getDate()).padStart(2, '0');
 29 |     return `${year}${month}${day}`;
 30 |   }
 31 | 
 32 |   // Comprehensive helper functions for complex validation
 33 |   function assertValidMCPResponse(result) {
 34 |     assert.ok(result.content, 'Should have content');
 35 |     assert.ok(Array.isArray(result.content), 'Content should be array');
 36 |     assert.equal(typeof result.isError, 'boolean', 'isError should be boolean');
 37 |   }
 38 | 
 39 |   function assertSuccessResponse(result) {
 40 |     assertValidMCPResponse(result);
 41 |     assert.equal(result.isError, false, 'Should not be an error response');
 42 |     assert.equal(result.content[0].type, 'text');
 43 |   }
 44 | 
 45 |   function validateCompleteLogSummary(result, expectedDate = null) {
 46 |     assertSuccessResponse(result);
 47 |     const text = result.content[0].text;
 48 |     
 49 |     // Validate header format
 50 |     if (expectedDate) {
 51 |       assert.ok(text.includes(`Log Summary for ${expectedDate}`),
 52 |         `Should contain "Log Summary for ${expectedDate}"`);
 53 |     } else {
 54 |       assert.ok(/Log Summary for \d{8}/.test(text),
 55 |         'Should contain "Log Summary for YYYYMMDD" pattern');
 56 |     }
 57 |     
 58 |     // Validate all required sections with complex logic
 59 |     const requiredSections = ['📊 Counts:', '📁 Log Files', '🔥 Key Issues:'];
 60 |     const missingSections = requiredSections.filter(section => !text.includes(section));
 61 |     assert.equal(missingSections.length, 0, 
 62 |       `Missing required sections: ${missingSections.join(', ')}`);
 63 |     
 64 |     // Validate numeric count patterns with regex precision
 65 |     const countPatterns = [
 66 |       { pattern: /- Errors: \d+/, name: 'Errors' },
 67 |       { pattern: /- Warnings: \d+/, name: 'Warnings' },
 68 |       { pattern: /- Info: \d+/, name: 'Info' },
 69 |       { pattern: /- Debug: \d+/, name: 'Debug' }
 70 |     ];
 71 |     
 72 |     const failedCounts = countPatterns.filter(({ pattern, name }) => {
 73 |       const matches = pattern.test(text);
 74 |       if (!matches) {
 75 |         console.log(`Failed count validation for ${name}: pattern ${pattern} not found in text`);
 76 |       }
 77 |       return !matches;
 78 |     });
 79 |     
 80 |     assert.equal(failedCounts.length, 0,
 81 |       `Failed count validations: ${failedCounts.map(f => f.name).join(', ')}`);
 82 |     
 83 |     return { text, sections: requiredSections };
 84 |   }
 85 | 
 86 |   function validateLogFileSection(text) {
 87 |     // Complex validation for log file section format
 88 |     const logFileMatch = text.match(/📁 Log Files \((\d+)\):/);
 89 |     if (logFileMatch) {
 90 |       const fileCount = parseInt(logFileMatch[1], 10);
 91 |       
 92 |       // Count actual log file entries
 93 |       const logFilePatterns = [
 94 |         /error-blade-\d{8}-\d{6}\.log/g,
 95 |         /warn-blade-\d{8}-\d{6}\.log/g,
 96 |         /info-blade-\d{8}-\d{6}\.log/g,
 97 |         /debug-blade-\d{8}-\d{6}\.log/g
 98 |       ];
 99 |       
100 |       let actualFileCount = 0;
101 |       logFilePatterns.forEach(pattern => {
102 |         const matches = text.match(pattern) || [];
103 |         actualFileCount += matches.length;
104 |       });
105 |       
106 |       return { declaredCount: fileCount, actualCount: actualFileCount };
107 |     }
108 |     return null;
109 |   }
110 | 
111 |   function validateKeyIssuesSection(text) {
112 |     // Extract and validate key issues content
113 |     const keyIssuesSplit = text.split('🔥 Key Issues:');
114 |     if (keyIssuesSplit.length > 1) {
115 |       const keyIssuesContent = keyIssuesSplit[1].trim();
116 |       
117 |       // Should not be empty
118 |       assert.ok(keyIssuesContent.length > 0, 'Key issues section should not be empty');
119 |       
120 |       // Should contain meaningful assessment patterns
121 |       const assessmentPatterns = [
122 |         /No major issues detected/i,
123 |         /Key issues identified/i,
124 |         /Critical errors found/i,
125 |         /\d+ error/i,
126 |         /\d+ warning/i,
127 |         /detected/i,
128 |         /found/i
129 |       ];
130 |       
131 |       const hasValidAssessment = assessmentPatterns.some(pattern => pattern.test(keyIssuesContent));
132 |       assert.ok(hasValidAssessment, 
133 |         `Key issues should contain meaningful assessment. Content: "${keyIssuesContent}"`);
134 |       
135 |       return keyIssuesContent;
136 |     }
137 |     return null;
138 |   }
139 | 
140 |   // Core functionality - comprehensive validation
141 |   describe('Comprehensive Functionality Validation', () => {
142 |     test('should provide complete log summary with all sections and cross-validation', async () => {
143 |       const result = await client.callTool('summarize_logs', {});
144 |       const validation = validateCompleteLogSummary(result);
145 |       
146 |       // Advanced cross-section validation
147 |       const fileValidation = validateLogFileSection(validation.text);
148 |       if (fileValidation) {
149 |         // Log file count should be reasonable (not negative, not excessively high)
150 |         assert.ok(fileValidation.declaredCount >= 0, 'File count should not be negative');
151 |         assert.ok(fileValidation.declaredCount <= 100, 'File count should be reasonable (<=100)');
152 |         
153 |         // If we have specific file entries, count should match or be reasonable
154 |         if (fileValidation.actualCount > 0) {
155 |           assert.ok(fileValidation.declaredCount >= fileValidation.actualCount,
156 |             `Declared count (${fileValidation.declaredCount}) should be >= actual entries (${fileValidation.actualCount})`);
157 |         }
158 |       }
159 |       
160 |       // Validate key issues assessment quality
161 |       const keyIssuesContent = validateKeyIssuesSection(validation.text);
162 |       assert.ok(keyIssuesContent, 'Should have key issues section');
163 |     });
164 | 
165 |     test('should handle both log scenarios with appropriate responses', async () => {
166 |       const result = await client.callTool('summarize_logs', {});
167 |       assertValidMCPResponse(result);
168 |       
169 |       const text = result.content[0].text;
170 |       const hasLogSummary = text.includes('📊 Counts:');
171 |       const noLogsFound = text.includes('No log files found');
172 |       
173 |       assert.ok(hasLogSummary || noLogsFound, 
174 |         'Should either show log summary or no logs message');
175 |       
176 |       if (hasLogSummary) {
177 |         // Comprehensive validation for log summary scenario
178 |         validateCompleteLogSummary(result);
179 |       } else {
180 |         // Validation for no logs scenario
181 |         assert.ok(/No log files found for date \d{8}/.test(text),
182 |           'No logs message should include specific date in YYYYMMDD format');
183 |       }
184 |     });
185 |   });
186 | 
187 |   // Dynamic date validation with cross-scenario consistency
188 |   describe('Dynamic Date Validation and Consistency', () => {
189 |     test('should maintain consistent response format across multiple date scenarios', async () => {
190 |       const testScenarios = [
191 |         { date: getCurrentDateString(), description: 'current date' },
192 |         { date: '20220101', description: 'old date' },
193 |         { date: '20301231', description: 'future date' },
194 |         { date: 'invalid-format', description: 'invalid format' },
195 |         { date: '2024-01-01', description: 'wrong format' },
196 |         { date: '', description: 'empty string' }
197 |       ];
198 |       
199 |       const results = [];
200 |       
201 |       // Sequential execution to avoid buffer conflicts
202 |       for (const scenario of testScenarios) {
203 |         const result = await client.callTool('summarize_logs', { date: scenario.date });
204 |         assertValidMCPResponse(result);
205 |         
206 |         results.push({
207 |           ...scenario,
208 |           result,
209 |           text: result.content[0].text,
210 |           isError: result.isError,
211 |           hasLogSummary: result.content[0].text.includes('📊 Counts:'),
212 |           isNoLogsMessage: result.content[0].text.includes('No log files found')
213 |         });
214 |       }
215 |       
216 |       // Cross-scenario validation
217 |       results.forEach(({ date, description, result, text, isError, hasLogSummary, isNoLogsMessage }) => {
218 |         // All should follow same response structure
219 |         assert.equal(result.content.length, 1, 
220 |           `${description} should have exactly one content element`);
221 |         assert.equal(result.content[0].type, 'text',
222 |           `${description} content type should be text`);
223 |         assert.equal(isError, false,
224 |           `${description} should not be marked as error`);
225 |         
226 |         // Should either have log summary or no logs message
227 |         assert.ok(hasLogSummary || isNoLogsMessage,
228 |           `${description} should either show summary or no logs message`);
229 |         
230 |         // Date format validation in response
231 |         if (hasLogSummary) {
232 |           if (date === '') {
233 |             // Empty string date results in "Log Summary for :" format
234 |             assert.ok(text.includes('Log Summary for :'),
235 |               `${description} with empty date should include "Log Summary for :"`);
236 |           } else {
237 |             assert.ok(/Log Summary for \d{8}/.test(text),
238 |               `${description} summary should include YYYYMMDD date`);
239 |           }
240 |         } else if (isNoLogsMessage) {
241 |           assert.ok(text.includes(`No log files found for date ${date}`),
242 |             `${description} should include the exact date parameter in no-logs message`);
243 |         }
244 |       });
245 |       
246 |       // Validate consistent behavior for invalid dates
247 |       const invalidDateResults = results.filter(r => 
248 |         ['invalid-format', 'wrong format'].includes(r.description)); // Removed 'empty string' since it acts like default
249 |       
250 |       invalidDateResults.forEach(({ description, isNoLogsMessage }) => {
251 |         assert.ok(isNoLogsMessage, 
252 |           `${description} should result in no logs message`);
253 |       });
254 |     });
255 | 
256 |     test('should handle parameter variations and edge cases dynamically', async () => {
257 |       const parameterVariations = [
258 |         { args: {}, description: 'empty object' },
259 |         { args: undefined, description: 'undefined args' },
260 |         { args: { date: null }, description: 'null date' },
261 |         { args: { date: getCurrentDateString(), extra: 'ignored' }, description: 'extra parameters' }
262 |       ];
263 |       
264 |       for (const { args, description } of parameterVariations) {
265 |         const result = await client.callTool('summarize_logs', args);
266 |         assertValidMCPResponse(result);
267 |         
268 |         // Should handle gracefully without errors
269 |         assert.equal(result.isError, false, 
270 |           `${description} should not cause error response`);
271 |         
272 |         const text = result.content[0].text;
273 |         const hasValidResponse = text.includes('📊 Counts:') || 
274 |                                text.includes('No log files found');
275 |         
276 |         assert.ok(hasValidResponse, 
277 |           `${description} should produce valid response format`);
278 |       }
279 |     });
280 |   });
281 | 
282 |   // Advanced content analysis and business logic validation
283 |   describe('Advanced Content Analysis', () => {
284 |     test('should validate log count arithmetic and consistency', async () => {
285 |       const result = await client.callTool('summarize_logs', {});
286 |       assertSuccessResponse(result);
287 |       
288 |       const text = result.content[0].text;
289 |       
290 |       if (text.includes('📊 Counts:')) {
291 |         // Extract all numeric counts
292 |         const countMatches = {
293 |           errors: text.match(/- Errors: (\d+)/),
294 |           warnings: text.match(/- Warnings: (\d+)/),
295 |           info: text.match(/- Info: (\d+)/),
296 |           debug: text.match(/- Debug: (\d+)/)
297 |         };
298 |         
299 |         // Validate all counts were found
300 |         Object.entries(countMatches).forEach(([level, match]) => {
301 |           assert.ok(match, `Should find ${level} count in response`);
302 |           
303 |           const count = parseInt(match[1], 10);
304 |           assert.ok(count >= 0, `${level} count should not be negative`);
305 |           assert.ok(count < 1000000, `${level} count should be reasonable (<1M)`);
306 |         });
307 |         
308 |         // Advanced business logic: total log entries should be reasonable
309 |         const totalEntries = Object.values(countMatches)
310 |           .map(match => parseInt(match[1], 10))
311 |           .reduce((sum, count) => sum + count, 0);
312 |         
313 |         assert.ok(totalEntries >= 0, 'Total log entries should not be negative');
314 |         
315 |         // If we have log entries, we should have log files
316 |         if (totalEntries > 0) {
317 |           assert.ok(text.includes('📁 Log Files'), 
318 |             'Should have log files section when log entries exist');
319 |         }
320 |       }
321 |     });
322 | 
323 |     test('should validate emoji consistency and section ordering', async () => {
324 |       const result = await client.callTool('summarize_logs', {});
325 |       assertSuccessResponse(result);
326 |       
327 |       const text = result.content[0].text;
328 |       
329 |       if (text.includes('📊 Counts:')) {
330 |         // Validate section ordering by finding their positions
331 |         const sectionPositions = {
332 |           counts: text.indexOf('📊 Counts:'),
333 |           files: text.indexOf('📁 Log Files'),
334 |           issues: text.indexOf('🔥 Key Issues:')
335 |         };
336 |         
337 |         // All sections should be found
338 |         Object.entries(sectionPositions).forEach(([section, position]) => {
339 |           assert.ok(position >= 0, `Should find ${section} section`);
340 |         });
341 |         
342 |         // Validate logical ordering: counts -> files -> issues
343 |         assert.ok(sectionPositions.counts < sectionPositions.files,
344 |           'Counts section should come before files section');
345 |         assert.ok(sectionPositions.files < sectionPositions.issues,
346 |           'Files section should come before issues section');
347 |         
348 |         // Validate consistent emoji usage
349 |         const expectedEmojis = ['📊', '📁', '🔥'];
350 |         expectedEmojis.forEach(emoji => {
351 |           assert.ok(text.includes(emoji), 
352 |             `Should use ${emoji} emoji consistently`);
353 |         });
354 |       }
355 |     });
356 |   });
357 | });
358 | 
```

--------------------------------------------------------------------------------
/docs/dw_suggest/SuggestModel.md:
--------------------------------------------------------------------------------

```markdown
  1 | ## Package: dw.suggest
  2 | 
  3 | # Class SuggestModel
  4 | 
  5 | ## Inheritance Hierarchy
  6 | 
  7 | - Object
  8 |   - dw.suggest.SuggestModel
  9 | 
 10 | ## Description
 11 | 
 12 | The Suggest model provides methods and functions to access search suggestions. The search suggestion feature basically covers two functional areas. First is just to suggest words, based on the users input, utilizing spell correction or prediction (also known as auto completion). The second functional area is also often referred to as search-as-you-type, where, based on the users input, specific items are already looked up, before the user actually has completed typing a word or even fired up the search. This model combines both functional areas and provides access to both - the suggested words and the items found while using the predicted words. This model supports various types of items that are being suggested, like products, categories, brands, content pages as well merchant provided search phrases. For each type, there is a Suggestions implementation available and accessible through this model: ProductSuggestions, CategorySuggestions, BrandSuggestions, ContentSuggestions, and CustomSuggestions. For each type of suggestions, the actual suggested items (like products) can by obtained, and, on the other hand, a list of terms is provided which were used to lookup the found items. The terms can be used to present a advanced user experience in the storefront, e.g. show auto completed words, spell corrections and so on. The SuggestModel script API will always create suggestions with Autocorrections regardless of the value of "Search Autocorrections" search preference.
 13 | 
 14 | ## Constants
 15 | 
 16 | ### MAX_SUGGESTIONS
 17 | 
 18 | **Type:** Number = 10
 19 | 
 20 | The maximum number of suggestions that can be obtain from this model: 10
 21 | 
 22 | ## Properties
 23 | 
 24 | ### brandSuggestions
 25 | 
 26 | **Type:** BrandSuggestions (Read Only)
 27 | 
 28 | A BrandSuggestions container for the current search phrase.
 29 |  The BrandSuggestions container provides access to the found brands (if any) and
 30 |  the terms suggested by the system with respect to the known product brands in the catalog.
 31 | 
 32 | ### categorySuggestions
 33 | 
 34 | **Type:** CategorySuggestions (Read Only)
 35 | 
 36 | A CategorySuggestions container for the current search phrase.
 37 |  The CategorySuggestions container provides access to the found categories (if any) and
 38 |  the terms suggested by the system with respect to the known categories in the catalog.
 39 | 
 40 | ### contentSuggestions
 41 | 
 42 | **Type:** ContentSuggestions (Read Only)
 43 | 
 44 | A ContentSuggestions container for the current search phrase.
 45 |  The ContentSuggestions container provides access to the found content pages (if any) and
 46 |  the terms suggested by the system with respect to the known content in the library.
 47 | 
 48 | ### customSuggestions
 49 | 
 50 | **Type:** CustomSuggestions (Read Only)
 51 | 
 52 | A CustomSuggestions container for the current search phrase.
 53 |  The CustomSuggestions container provides access to matching
 54 |  custom phrases (if any) and the terms suggested
 55 |  by the system with respect to the merchant provided custom phrases.
 56 | 
 57 | ### filteredByFolder
 58 | 
 59 | **Type:** boolean
 60 | 
 61 | The method returns true, if the search suggestions are filtered by the folder. If this returns true it is not
 62 |  possible for search suggestions to contain Page Designer content as it belongs to no folder.
 63 | 
 64 | ### popularSearchPhrases
 65 | 
 66 | **Type:** Iterator (Read Only)
 67 | 
 68 | Use this method to obtain a list of search phrases
 69 |  that currently are very popular among all users across the Site.
 70 | 
 71 |  The search phrases are specific to the region (based on user's IP address),
 72 |  language (locale) and the user's browser type (agent).
 73 | 
 74 | ### productSuggestions
 75 | 
 76 | **Type:** ProductSuggestions (Read Only)
 77 | 
 78 | A ProductSuggestions container for the current search phrase.
 79 |  The ProductSuggestions container provides access to the found products (if any) and
 80 |  the terms suggested by the system with respect to the known products in the catalog.
 81 | 
 82 | ### recentSearchPhrases
 83 | 
 84 | **Type:** Iterator (Read Only)
 85 | 
 86 | Use this method to obtain a list of personalized search phrases
 87 |  that the current user entered recently.
 88 | 
 89 |  The user is being identified by the CQuotient tracking cookie.
 90 | 
 91 | ## Constructor Summary
 92 | 
 93 | SuggestModel() Constructs a new SuggestModel.
 94 | 
 95 | ## Method Summary
 96 | 
 97 | ### addRefinementValues
 98 | 
 99 | **Signature:** `addRefinementValues(attributeID : String, values : String) : void`
100 | 
101 | Adds a refinement for product suggestions.
102 | 
103 | ### getBrandSuggestions
104 | 
105 | **Signature:** `getBrandSuggestions() : BrandSuggestions`
106 | 
107 | Returns a BrandSuggestions container for the current search phrase.
108 | 
109 | ### getCategorySuggestions
110 | 
111 | **Signature:** `getCategorySuggestions() : CategorySuggestions`
112 | 
113 | Returns a CategorySuggestions container for the current search phrase.
114 | 
115 | ### getContentSuggestions
116 | 
117 | **Signature:** `getContentSuggestions() : ContentSuggestions`
118 | 
119 | Returns a ContentSuggestions container for the current search phrase.
120 | 
121 | ### getCustomSuggestions
122 | 
123 | **Signature:** `getCustomSuggestions() : CustomSuggestions`
124 | 
125 | Returns a CustomSuggestions container for the current search phrase.
126 | 
127 | ### getPopularSearchPhrases
128 | 
129 | **Signature:** `getPopularSearchPhrases() : Iterator`
130 | 
131 | Use this method to obtain a list of search phrases that currently are very popular among all users across the Site.
132 | 
133 | ### getProductSuggestions
134 | 
135 | **Signature:** `getProductSuggestions() : ProductSuggestions`
136 | 
137 | Returns a ProductSuggestions container for the current search phrase.
138 | 
139 | ### getRecentSearchPhrases
140 | 
141 | **Signature:** `getRecentSearchPhrases() : Iterator`
142 | 
143 | Use this method to obtain a list of personalized search phrases that the current user entered recently.
144 | 
145 | ### isFilteredByFolder
146 | 
147 | **Signature:** `isFilteredByFolder() : boolean`
148 | 
149 | The method returns true, if the search suggestions are filtered by the folder.
150 | 
151 | ### removeRefinementValues
152 | 
153 | **Signature:** `removeRefinementValues(attributeID : String, values : String) : void`
154 | 
155 | Removes a refinement.
156 | 
157 | ### setCategoryID
158 | 
159 | **Signature:** `setCategoryID(categoryID : String) : void`
160 | 
161 | Apply a category ID to filter product, brand and category suggestions.
162 | 
163 | ### setFilteredByFolder
164 | 
165 | **Signature:** `setFilteredByFolder(filteredByFolder : boolean) : void`
166 | 
167 | Set a flag to indicate if the search suggestions filter for elements that do not belong to a folder.
168 | 
169 | ### setMaxSuggestions
170 | 
171 | **Signature:** `setMaxSuggestions(maxSuggestions : Number) : void`
172 | 
173 | Use this method to setup the maximum number of returned suggested items.
174 | 
175 | ### setRefinementValues
176 | 
177 | **Signature:** `setRefinementValues(attributeID : String, values : String) : void`
178 | 
179 | Sets product suggestion refinement values for an attribute.
180 | 
181 | ### setSearchPhrase
182 | 
183 | **Signature:** `setSearchPhrase(searchPhrase : String) : void`
184 | 
185 | Sets the user input search phrase.
186 | 
187 | ## Constructor Detail
188 | 
189 | ## Method Detail
190 | 
191 | ## Method Details
192 | 
193 | ### addRefinementValues
194 | 
195 | **Signature:** `addRefinementValues(attributeID : String, values : String) : void`
196 | 
197 | **Description:** Adds a refinement for product suggestions. The method can be called to add an additional query parameter specified as name-value pair. The values string may encode multiple values delimited by the pipe symbol ('|').
198 | 
199 | **Parameters:**
200 | 
201 | - `attributeID`: The ID of the refinement attribute.
202 | - `values`: the refinement value to set
203 | 
204 | ---
205 | 
206 | ### getBrandSuggestions
207 | 
208 | **Signature:** `getBrandSuggestions() : BrandSuggestions`
209 | 
210 | **Description:** Returns a BrandSuggestions container for the current search phrase. The BrandSuggestions container provides access to the found brands (if any) and the terms suggested by the system with respect to the known product brands in the catalog.
211 | 
212 | **Returns:**
213 | 
214 | a brand suggestions container for the current search phrase, returns null for insufficient search input
215 | 
216 | **See Also:**
217 | 
218 | setMaxSuggestions(Number)
219 | setSearchPhrase(String)
220 | 
221 | ---
222 | 
223 | ### getCategorySuggestions
224 | 
225 | **Signature:** `getCategorySuggestions() : CategorySuggestions`
226 | 
227 | **Description:** Returns a CategorySuggestions container for the current search phrase. The CategorySuggestions container provides access to the found categories (if any) and the terms suggested by the system with respect to the known categories in the catalog.
228 | 
229 | **Returns:**
230 | 
231 | a category suggestions container for the current search phrase, returns null for insufficient search input
232 | 
233 | **See Also:**
234 | 
235 | setMaxSuggestions(Number)
236 | setSearchPhrase(String)
237 | 
238 | ---
239 | 
240 | ### getContentSuggestions
241 | 
242 | **Signature:** `getContentSuggestions() : ContentSuggestions`
243 | 
244 | **Description:** Returns a ContentSuggestions container for the current search phrase. The ContentSuggestions container provides access to the found content pages (if any) and the terms suggested by the system with respect to the known content in the library.
245 | 
246 | **Returns:**
247 | 
248 | a content suggestions container for the current search phrase, returns null for insufficient search input
249 | 
250 | **See Also:**
251 | 
252 | setMaxSuggestions(Number)
253 | setSearchPhrase(String)
254 | 
255 | ---
256 | 
257 | ### getCustomSuggestions
258 | 
259 | **Signature:** `getCustomSuggestions() : CustomSuggestions`
260 | 
261 | **Description:** Returns a CustomSuggestions container for the current search phrase. The CustomSuggestions container provides access to matching custom phrases (if any) and the terms suggested by the system with respect to the merchant provided custom phrases.
262 | 
263 | **Returns:**
264 | 
265 | a custom suggestions container for the current search phrase, returns null for insufficient search input
266 | 
267 | **See Also:**
268 | 
269 | setMaxSuggestions(Number)
270 | setSearchPhrase(String)
271 | 
272 | ---
273 | 
274 | ### getPopularSearchPhrases
275 | 
276 | **Signature:** `getPopularSearchPhrases() : Iterator`
277 | 
278 | **Description:** Use this method to obtain a list of search phrases that currently are very popular among all users across the Site. The search phrases are specific to the region (based on user's IP address), language (locale) and the user's browser type (agent).
279 | 
280 | **Returns:**
281 | 
282 | a list of personalized popular search phrases
283 | 
284 | ---
285 | 
286 | ### getProductSuggestions
287 | 
288 | **Signature:** `getProductSuggestions() : ProductSuggestions`
289 | 
290 | **Description:** Returns a ProductSuggestions container for the current search phrase. The ProductSuggestions container provides access to the found products (if any) and the terms suggested by the system with respect to the known products in the catalog.
291 | 
292 | **Returns:**
293 | 
294 | a product suggestions container for the current search phrase, returns null for insufficient search input
295 | 
296 | **See Also:**
297 | 
298 | setMaxSuggestions(Number)
299 | setSearchPhrase(String)
300 | 
301 | ---
302 | 
303 | ### getRecentSearchPhrases
304 | 
305 | **Signature:** `getRecentSearchPhrases() : Iterator`
306 | 
307 | **Description:** Use this method to obtain a list of personalized search phrases that the current user entered recently. The user is being identified by the CQuotient tracking cookie.
308 | 
309 | **Returns:**
310 | 
311 | a list of recent search phrases of the current user
312 | 
313 | ---
314 | 
315 | ### isFilteredByFolder
316 | 
317 | **Signature:** `isFilteredByFolder() : boolean`
318 | 
319 | **Description:** The method returns true, if the search suggestions are filtered by the folder. If this returns true it is not possible for search suggestions to contain Page Designer content as it belongs to no folder.
320 | 
321 | **Returns:**
322 | 
323 | True if search suggestions are filtered by the folder of the content asset.
324 | 
325 | ---
326 | 
327 | ### removeRefinementValues
328 | 
329 | **Signature:** `removeRefinementValues(attributeID : String, values : String) : void`
330 | 
331 | **Description:** Removes a refinement. The method can be called to remove previously added refinement values. The values string may encode multiple values delimited by the pipe symbol ('|').
332 | 
333 | **Parameters:**
334 | 
335 | - `attributeID`: The ID of the refinement attribute.
336 | - `values`: the refinement value to remove or null to remove all values
337 | 
338 | ---
339 | 
340 | ### setCategoryID
341 | 
342 | **Signature:** `setCategoryID(categoryID : String) : void`
343 | 
344 | **Description:** Apply a category ID to filter product, brand and category suggestions. Suggested products, brands and categories, as well as corrected and completed terms are specific to the given category or one of it's sub categories. For example, in the specified category "television", the search term "pla" will be auto completed to "plasma" (instead of e.g. "player") and only televisions will be included in the list of suggested products.
345 | 
346 | **Parameters:**
347 | 
348 | - `categoryID`: the category to filter suggestions for
349 | 
350 | ---
351 | 
352 | ### setFilteredByFolder
353 | 
354 | **Signature:** `setFilteredByFolder(filteredByFolder : boolean) : void`
355 | 
356 | **Description:** Set a flag to indicate if the search suggestions filter for elements that do not belong to a folder. Must be set to false to return content assets that do not belong to any folder.
357 | 
358 | **Parameters:**
359 | 
360 | - `filteredByFolder`: filter the search suggestions by folder
361 | 
362 | ---
363 | 
364 | ### setMaxSuggestions
365 | 
366 | **Signature:** `setMaxSuggestions(maxSuggestions : Number) : void`
367 | 
368 | **Description:** Use this method to setup the maximum number of returned suggested items. For example, set this to 3 in order to only retrieve the 3 most relevant suggested products. The maximum number of suggestions that can be queried are defined as MAX_SUGGESTIONS.
369 | 
370 | **Parameters:**
371 | 
372 | - `maxSuggestions`: the number of suggested items to be returned by this model instance
373 | 
374 | ---
375 | 
376 | ### setRefinementValues
377 | 
378 | **Signature:** `setRefinementValues(attributeID : String, values : String) : void`
379 | 
380 | **Description:** Sets product suggestion refinement values for an attribute. The method can be called to set an additional query parameter specified as name-value pair. The value string may encode multiple values delimited by the pipe symbol ('|'). Existing refinement values for the attribute will be removed.
381 | 
382 | **Parameters:**
383 | 
384 | - `attributeID`: The ID of the refinement attribute.
385 | - `values`: the refinement values to set (delimited by '|') or null to remove all values
386 | 
387 | ---
388 | 
389 | ### setSearchPhrase
390 | 
391 | **Signature:** `setSearchPhrase(searchPhrase : String) : void`
392 | 
393 | **Description:** Sets the user input search phrase. This search phrase is being processed by applying auto completion, spell correction and enhancement with alternative similar search terms. The resulting search phrase is used to lookup the actual items, like products or categories (search-as-you-type). In order to access the processed terms, one can use the SearchPhraseSuggestions.getSuggestedTerms() method of each of the respective results returned by the methods in this model.
394 | 
395 | **Parameters:**
396 | 
397 | - `searchPhrase`: the user input search phrase
398 | 
399 | **See Also:**
400 | 
401 | SearchPhraseSuggestions.getSuggestedTerms()
402 | 
403 | ---
```
Page 25/61FirstPrevNextLast