Skip to content

Commit 256f109

Browse files
committed
Release braintree-web 3.134.0 source
1 parent 18e594c commit 256f109

File tree

94 files changed

+20620
-2333
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

94 files changed

+20620
-2333
lines changed

.claude/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"hooks": {}
3+
}

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ coverage/
1212

1313
*storybook.log
1414
storybook-static
15-
.storybook/static/local-build/
15+
.storybook/static
16+
.storybook/static/local-build
17+
.storybook/versions.json
1618

1719
cert.pem
1820
key.pem

.storybook/CLAUDE.md

Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Overview
6+
7+
Storybook is used in this project for:
8+
9+
- **Interactive Component Development** - Develop and test payment components in isolation
10+
- **Visual Testing** - Manually verify component behavior across different SDK versions
11+
- **Integration Testing** - Automated BrowserStack tests for real browser environments
12+
- **Documentation** - Living documentation with interactive examples
13+
14+
## Commands
15+
16+
### Development
17+
18+
- `npm run storybook:dev` - Start Storybook development server on port 6006
19+
- `npm run storybook:dev-local` - Start Storybook with local build (requires `npm run build` first)
20+
- `npm run storybook:docs` - Start Storybook in documentation mode
21+
22+
### Building
23+
24+
- `npm run storybook:build` - Build static Storybook site to `storybook-static/`
25+
- `npm run storybook:run-build` - Serve built Storybook on https://127.0.0.1:8080
26+
- `npm run storybook:copy-local-build` - Copy local build to static directory (requires `npm run build` first)
27+
28+
### Testing
29+
30+
- `npm run test:integration` - Run WebDriverIO integration tests on BrowserStack
31+
- `npm run test:integration:local` - Run tests with local build (`LOCAL_BUILD=true`)
32+
33+
## Architecture
34+
35+
### Directory Structure
36+
37+
```
38+
.storybook/
39+
├── main.ts # Storybook configuration
40+
├── preview.ts # Global decorators, loaders, and version toolbar
41+
├── constants.ts # Shared constants (success messages, test values)
42+
├── versions.json # List of available SDK versions for toolbar
43+
├── wdio.conf.ts # WebDriverIO test configuration
44+
45+
├── css/
46+
│ └── main.css # Shared styles (imported globally in preview.ts)
47+
48+
├── stories/ # Story files organized by component
49+
│ ├── HostedFields/
50+
│ ├── PayPalCheckout/
51+
│ ├── ApplePay/
52+
│ ├── ThreeDSecure/
53+
│ ├── VaultManager/
54+
│ ├── Venmo/
55+
│ └── LocalPaymentMethods/
56+
57+
├── utils/ # Utility functions
58+
│ ├── BraintreeWebSDKLoader.ts # SDK loading singleton class
59+
│ ├── story-helper.ts # createSimpleBraintreeStory helper
60+
│ ├── braintree-globals.ts # URL construction, window.braintree utilities
61+
│ ├── script-loader.ts # Script tag loading/removal
62+
│ ├── sdk-config.ts # Version config, authorization token
63+
│ ├── sdk-metadata.ts # Version metadata management
64+
│ ├── local-build-manager.ts # Local build detection
65+
│ ├── version-fetcher.ts # NPM registry version fetching
66+
│ └── test-data.ts # Test card data
67+
68+
├── tests/ # WebDriverIO integration tests
69+
│ ├── helper.ts # Test helper commands
70+
│ └── *.test.ts # Test files
71+
72+
├── types/ # TypeScript type definitions
73+
74+
└── static/local-build/ # Local SDK builds (created by script)
75+
```
76+
77+
### SDK Version Management
78+
79+
The Storybook toolbar allows switching between SDK versions:
80+
81+
1. **"dev"** - Local build from `.storybook/static/local-build/`
82+
2. **Production versions** - CDN-hosted builds (e.g., "3.133.0")
83+
84+
Version selection:
85+
86+
- URL parameter: `?globals=sdkVersion:3.133.0`
87+
- Storybook globals toolbar
88+
- Default: `"dev"` (local build)
89+
90+
### SDK Loading Flow
91+
92+
1. **preview.ts loader** - Pre-loads SDK based on selected version and `parameters.braintreeScripts`
93+
2. **story-helper.ts** - `createSimpleBraintreeStory` ensures required scripts are loaded
94+
3. **BraintreeWebSDKLoader.ts** - Singleton that manages script loading, version switching, cleanup
95+
96+
## Writing Stories
97+
98+
### Basic Story Structure
99+
100+
```typescript
101+
import type { Meta, StoryObj } from "@storybook/html";
102+
import { createSimpleBraintreeStory } from "../../utils/story-helper";
103+
import { getAuthorizationToken } from "../../utils/sdk-config";
104+
import "./componentName.css";
105+
106+
const meta: Meta = {
107+
title: "Braintree/Component Name",
108+
parameters: {
109+
layout: "centered",
110+
braintreeScripts: ["component-name"], // Scripts for preview loader to pre-load
111+
docs: {
112+
description: {
113+
component: `Component description in markdown`,
114+
},
115+
},
116+
},
117+
};
118+
119+
export default meta;
120+
121+
export const BasicExample: StoryObj = {
122+
render: createSimpleBraintreeStory(
123+
(container, args) => {
124+
// Your render code - window.braintree is available
125+
const authorization = getAuthorizationToken();
126+
// ...
127+
},
128+
["client.min.js", "component-name.min.js"] // Scripts this story needs
129+
),
130+
argTypes: {
131+
optionName: {
132+
control: { type: "boolean" },
133+
description: "Option description",
134+
},
135+
},
136+
args: {
137+
optionName: true,
138+
},
139+
};
140+
```
141+
142+
### Key Points
143+
144+
1. **`parameters.braintreeScripts`** - Array of script names (without `.min.js`) for the preview loader to pre-load
145+
2. **`createSimpleBraintreeStory` second arg** - Array of full script filenames the story requires
146+
3. **`getAuthorizationToken()`** - Returns `import.meta.env.STORYBOOK_BRAINTREE_TOKENIZATION_KEY`
147+
4. **Shared styles** - Already imported globally via `preview.ts`, no need to import in stories
148+
149+
### Result Display Pattern
150+
151+
```typescript
152+
// Success
153+
resultDiv.classList.add("shared-result--visible", "shared-result--success");
154+
resultDiv.innerHTML = `<strong>Success!</strong><small>Nonce: ${payload.nonce}</small>`;
155+
156+
// Error
157+
resultDiv.classList.add("shared-result--visible", "shared-result--error");
158+
resultDiv.innerHTML = `<strong>Error:</strong> ${error.message}`;
159+
```
160+
161+
### Test Data
162+
163+
```typescript
164+
import { TEST_CARDS } from "../../utils/test-data";
165+
166+
// Cards available: visa, mastercard, amex, discover, etc.
167+
const cardData = TEST_CARDS.visa;
168+
// { number: "4111111111111111", cvv: "123", expirationDate: "MM/YY", postalCode: "12345" }
169+
```
170+
171+
## Integration Testing
172+
173+
### Test Configuration
174+
175+
- **Framework:** Mocha with WebDriverIO
176+
- **Browsers:** Chrome (Windows 10), Safari (macOS Monterey)
177+
- **Base URL:** `https://127.0.0.1:8080`
178+
179+
### Custom Browser Commands
180+
181+
Defined in `tests/helper.ts`:
182+
183+
- `browser.waitForHostedFieldsReady()` - Wait for SDK and all hosted field iframes
184+
- `browser.waitForHostedField(key)` - Wait for specific hosted field
185+
- `browser.hostedFieldSendInput(key, value)` - Type into hosted field iframe
186+
- `browser.waitForFormReady()` - Wait for submit button to be enabled
187+
- `browser.submitPay()` - Submit form and wait for result
188+
- `browser.getResult()` - Extract success/failure from result div
189+
- `getWorkflowUrl(path)` - Build story URL with version param
190+
191+
### Writing Tests
192+
193+
```typescript
194+
import { browser, $ } from "@wdio/globals";
195+
import { expect } from "chai";
196+
import { getWorkflowUrl, loadHelpers } from "./helper";
197+
198+
describe("Component Integration", () => {
199+
before(() => loadHelpers());
200+
201+
it("should complete flow", async () => {
202+
const url = getWorkflowUrl(
203+
"/iframe.html?id=braintree-component--story-name"
204+
);
205+
await browser.url(url);
206+
207+
await browser.waitForHostedFieldsReady();
208+
await browser.hostedFieldSendInput("number", "4111111111111111");
209+
// ...
210+
211+
const result = await browser.getResult();
212+
expect(result.success).to.be.true;
213+
});
214+
});
215+
```
216+
217+
## Environment Variables
218+
219+
Required in `.env`:
220+
221+
```bash
222+
STORYBOOK_BRAINTREE_TOKENIZATION_KEY=sandbox_xxxxx_yyyyyy
223+
224+
# For integration tests only:
225+
BROWSERSTACK_USERNAME=your_username
226+
BROWSERSTACK_ACCESS_KEY=your_access_key
227+
```
228+
229+
## Using Local Builds
230+
231+
```bash
232+
npm run build # Build SDK
233+
npm run storybook:copy-local-build # Copy to static directory
234+
npm run storybook:dev-local # Start with local build
235+
```
236+
237+
Or combined: `npm run storybook:dev-local` (runs copy-local-build first)
238+
239+
## Troubleshooting
240+
241+
### Local Build Not Appearing
242+
243+
1. Run `npm run build`
244+
2. Run `npm run storybook:copy-local-build`
245+
3. Check `.storybook/static/local-build/js/` for `.js` files
246+
247+
### SDK Loading Errors
248+
249+
1. Check browser console for script loading errors
250+
2. Verify `STORYBOOK_BRAINTREE_TOKENIZATION_KEY` in `.env`
251+
3. Try switching to a CDN version in toolbar
252+
4. For local builds, ensure build was run first
253+
254+
### Version Switching Issues
255+
256+
1. Hard refresh (Cmd+Shift+R / Ctrl+Shift+R)
257+
2. Check URL has correct `globals` parameter
258+
3. Check console for version selection logs

.storybook/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,5 @@ export const DEFAULT_HOSTED_FIELDS_VALUES = {
1111
cvv: "123",
1212
postalCode: "12345",
1313
};
14+
15+
export const BASE_URL = "https://127.0.0.1:8080";

0 commit comments

Comments
 (0)