This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Each component has its own CLAUDE.md with detailed guidance. These are automatically loaded when working in that directory.
Core: client, hosted-fields, three-d-secure, data-collector, lib/frame-service
Digital Wallets: apple-pay, google-payment
Alternative Payment Methods: paypal-checkout, paypal-checkout-v6, venmo, us-bank-account, sepa, local-payment
Card Networks: american-express, unionpay
Services: instant-verification, payment-ready, payment-request, vault-manager, fastlane
Deprecated (Do Not Use): paypal (use paypal-checkout), masterpass, visa-checkout, preferred-payment-methods
Storybook: See /.storybook/CLAUDE.md for interactive component development, visual testing, integration testing, SDK version management, and writing stories.
npm run build- Build all componentsnpm run build <component>- Build a single component (e.g.,npm run build client)
npm run build:integration- Build SDK, copy to Storybook static dir, build Storybook, and start HTTPS server at https://127.0.0.1:8080npm run storybook:dev-local- Start Storybook with your local builds (copies build files automatically)npm run storybook:copy-local-build- Copy local builds to Storybook static directory
npm test- Run all testsnpm test <component>- Run tests for a single component (e.g.,npm test client)npm test lib- Run tests for the lib directoryjest <path-to-file>- Run a single test file (requires jest installed globally)
npm run lint- Lint all codenpm run lint <component>- Lint a single componentnpm run prettier- Format all code with Prettier
npm run jsdoc- Generate JSDoc documentationnpm run storybook:dev- Start Storybook development server on port 6006npm run storybook:build- Build Storybook static filesnpm run test:integration- Run BrowserStack integration tests with CDN versionsnpm run test:integration:local- Run tests with your local build (LOCAL_BUILD=true)npm run test:integration -- --spec .storybook/tests/your-test.test.ts- Run single test file
src/- Source code organized by payment method componentssrc/lib/- Shared utilities and core functionalitysrc/index.js- Main entry point that exports all payment method modulestasks/- Gulp build tasks, one per componenttest/- Test files mirroring the src/ structurecomponents.json- List of all payment method components
- Uses Gulp with component-specific tasks in
tasks/directory - Each component defined in
components.jsongets its own build task - Browserify for bundling with environment variable transforms
- Outputs to
dist/with separate npm and hosted (CDN) builds
- Jest for unit testing with component-specific configurations
- Tests mirror src/ structure in test/ directory
- Integration tests using WebDriver with Browserstack
- Storybook for component development and testing
All components follow this lifecycle pattern:
- Basic Verification - Using
basicComponentVerification.verify() - Client Creation - Either use provided client or create deferred client
- Configuration Check - Verify component is enabled in gateway config
- Component Initialization - Create and return component instance
// src/<component>/index.js
function create(options) {
return basicComponentVerification
.verify({
name: "ComponentName",
client: options.client,
authorization: options.authorization,
})
.then(function () {
return createDeferredClient.create({
authorization: options.authorization,
client: options.client,
assetsUrl: createAssetsUrl.create(options.authorization),
name: "ComponentName",
});
})
.then(function (client) {
// Check gateway configuration
// Initialize component
// Return component instance
});
}Use BraintreeError for all error conditions:
var BraintreeError = require("../lib/braintree-error");
// Create error with proper type classification
new BraintreeError({
type: BraintreeError.types.MERCHANT, // CUSTOMER, MERCHANT, NETWORK, INTERNAL, UNKNOWN
code: "COMPONENT_SPECIFIC_ERROR_CODE",
message: "User-friendly error message",
details: { originalError: err }, // Optional additional info
});- Environment Transform -
envifyreplacesprocess.envvariables - Code Removal -
removeIf(production)blocks stripped in production - Derequire - Prevents global require conflicts
- Minification - UglifyJS for production builds
dist/npm/- CommonJS modules for npm packagedist/hosted/- CDN-ready files with versioned paths
Each component in components.json gets:
build:<component>- Build single componentlint:<component>- Lint single component- Individual gulp task in
tasks/<component>.js
- Tests mirror
src/structure intest/directory - Each component has its own Jest configuration
- Global test timeout: 4 seconds
test/helpers/promise-helper.js- Promise testing utilitiestest/helpers/components.js- Component-specific helpersrejectIfResolves()- Helper for testing promise rejectionswait(time)- Helper for async testing delays
# All tests for a component
npm test client
# Single test file
jest test/client/unit/client.js
# With coverage
BRAINTREE_JS_ENV=development jest --coverageCreate .env file with development settings:
BRAINTREE_JS_API_HOST=development.gateway.hostname
BRAINTREE_JS_API_PORT=443
BRAINTREE_JS_API_PROTOCOL=https
STORYBOOK_BRAINTREE_TOKENIZATION_KEY=your_sandbox_keyComponents send analytics events for debugging:
var analytics = require("../lib/analytics");
// Send event for debugging
analytics.sendEvent(client, "component.action.started");CLIENT_AUTHORIZATION_INVALID- Invalid/expired authorizationINCOMPATIBLE_VERSIONS- Version mismatch between componentsCOMPONENT_NOT_ENABLED- Component disabled in gateway configCLIENT_SCRIPT_FAILED_TO_LOAD- Network/CDN loading issues
For components using Frame Service (PayPal, Venmo, SEPA, Local Payment), see /src/lib/frame-service/CLAUDE.md for detailed debugging guidance.
For Hosted Fields iframe issues, see /src/hosted-fields/CLAUDE.md.
General debugging:
- Check browser console for framebus errors
- Verify iframe URLs are loading correctly
- Ensure proper domain configuration for cross-origin
- Test with
BRAINTREE_JS_ENV=developmentfor detailed logging
Integration tests use WebDriverIO with BrowserStack across multiple browsers:
- Chrome (Windows 10)
- Safari (macOS Monterey)
- Firefox (macOS Monterey)
- Edge (Windows 10)
Commands are registered via loadHelpers() in .storybook/tests/helpers/browser-commands/index.ts:
Common Commands:
browser.getResult()- Extract success/failure from result div
Hosted Fields Commands:
browser.waitForHostedFieldsReady()- Wait for SDK and all hosted field iframesbrowser.hostedFieldSendInput(key, value)- Type into hosted field iframebrowser.submitPay()- Submit form and wait for result
PayPal Commands:
completePayPalCheckoutFlow()- Full PayPal login and approval flowswitchToPayPalPopup()- Switch to PayPal popup window
Network Interception:
- Uses
wdio-intercept-servicefor network request verification browser.setupInterceptor()- Setup network interceptionbrowser.getRequests()- Get intercepted HTTP requests
import { browser } from "@wdio/globals";
import { expect } from "chai";
import { getWorkflowUrl } from "./helpers/url-utils";
import { loadHelpers } from "./helpers/browser-commands";
describe("Component Integration", () => {
before(() => loadHelpers());
it("should complete flow", async () => {
const url = getWorkflowUrl("/iframe.html?id=story-id");
await browser.url(url);
await browser.setupInterceptor();
// Test implementation
const requests = await browser.getRequests();
expect(requests).to.have.length.greaterThan(0);
});
});# All tests
npm run test:integration
# With local build
npm run test:integration:local
# Single test file
npm run test:integration -- --spec .storybook/tests/your-test.test.tsRequired in .env file:
# Local development(not committed to git)
BRAINTREE_JS_API_HOST=development.gateway.hostname
BRAINTREE_JS_API_PORT=443
BRAINTREE_JS_API_PROTOCOL=https
STORYBOOK_BRAINTREE_TOKENIZATION_KEY=sandbox_xxxxx_yyyyyy
# For integration tests only
BROWSERSTACK_USERNAME=your_username
BROWSERSTACK_ACCESS_KEY=your_access_key
PAYPAL_SANDBOX_BUYER_EMAIL=buyer@example.com
PAYPAL_SANDBOX_OTP_CODE=111111- 2-space indentation, semicolons at end of statements, single quotes for strings
- ES5 syntax (for browser compatibility) - use
functionnot arrow functions,varnotconst/let - ES5 Promises for functional code; async/await allowed only in tests
- Use
===and!==for equality checks (never==/!=) - Trailing commas in multi-line objects and arrays
- JSDoc comments for public APIs
- Prettier for consistent formatting; ESLint with Braintree configuration
- Never use emojis in code or comments
camelCasefor variables and functionsPascalCasefor classesUPPER_SNAKE_CASEfor constants- Boolean variables: prefix with
is,has,can, orshould - Event handlers: prefix with
on(e.g.,onClick) - CRUD functions: prefix with
create,update,delete, orfetch - Initialization functions: use
initorinitialize
- Core dependencies are minimal browser-compatible libraries
- Custom Braintree packages prefixed with
@braintree/ - Uses framebus for iframe communication (see Frame Service and Hosted Fields docs)
- Cardinal Commerce Songbird.js for 3D Secure (loaded dynamically)
- SJCL crypto library (custom build) for data-collector component
Branch names are validated by pre-push hooks and CI. Valid formats:
- Standard:
lowercase-kebab-case(e.g.,fix-payment-bug) - Jira:
TICKET-123-lowercase-kebab-case(e.g.,DTBTWEB-123-fix-bug) - Versioned:
feature-name.1orTICKET-123-feature.1
Jira prefix must be uppercase (DTBTWEB-123, not dtbtweb-123). Validate manually with: node scripts/validate-branch-name.js "your-branch-name"
- Run
npm testafter making changes (includes linting) - Use
npm run build <component>to build specific components during development - Test integration scenarios in Storybook
- Follow existing patterns when adding new components or features
- Use
scripts/npm-to-gulpwrapper for component-specific commands - Check version compatibility with
basicComponentVerification - Verify environment variables are set correctly for local development
- For components requiring secure UI (popups/modals), use Frame Service (see
/src/lib/frame-service/CLAUDE.md) - For components requiring card input, use Hosted Fields (see
/src/hosted-fields/CLAUDE.md) - For transactions requiring 3DS authentication, integrate with 3D Secure component (see
/src/three-d-secure/CLAUDE.md)