Skip to content

Commit 56ddaa5

Browse files
authored
Use paypal-sdk-constants for Stand Alone Buttons & Marks (#17)
1 parent 743fdce commit 56ddaa5

11 files changed

+171
-36
lines changed

__mocks__/@paypal/paypal-js.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { loadScript as loadScriptOriginal } from "@paypal/paypal-js";
2+
3+
export function loadScript(options) {
4+
return new Promise((resolve) => {
5+
loadScriptOriginal(options);
6+
process.nextTick(() => resolve({}));
7+
});
8+
}

package-lock.json

+31-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828
"url": "git://github.com/paypal/react-paypal-js.git"
2929
},
3030
"dependencies": {
31-
"@paypal/paypal-js": "^1.0.0",
31+
"@paypal/paypal-js": "^1.0.3",
32+
"@paypal/sdk-constants": "^1.0.75",
3233
"prop-types": "^15.7.2"
3334
},
3435
"devDependencies": {

src/ScriptContext.test.js

+5-12
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,18 @@
11
import React from "react";
22
import { render, waitFor } from "@testing-library/react";
3-
import * as payPalJS from "@paypal/paypal-js";
43
import { ScriptProvider, useScriptReducer } from "./ScriptContext";
54

65
describe("<ScriptProvider />", () => {
7-
let loadScriptBackup = payPalJS.loadScript;
8-
96
beforeEach(() => {
107
document.head.innerHTML = "";
11-
12-
// eslint-disable-next-line no-import-assign
13-
payPalJS.loadScript = jest.fn().mockImplementation((options) => {
14-
return new Promise((resolve) => {
15-
loadScriptBackup(options);
16-
process.nextTick(() => resolve());
17-
});
18-
});
198
});
209

2110
test("should add the JS SDK <script> to the DOM", () => {
22-
render(<ScriptProvider options={{ "client-id": "sb" }} />);
11+
render(
12+
<ScriptProvider options={{ "client-id": "sb" }}>
13+
<></>
14+
</ScriptProvider>
15+
);
2316

2417
const script = document.querySelector("head script");
2518
expect(script).toBeTruthy();

src/components/PayPalButtons.js

+5
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ PayPalButtons.propTypes = {
5454
* Sets up a subscription. Called when the buyer clicks the PayPal button.
5555
*/
5656
createSubscription: PropTypes.func,
57+
/**
58+
* The individual button to render. Use the `FUNDING` constant exported by this library to set this value. The full list can be found [here](https://developer.paypal.com/docs/checkout/integration-features/standalone-buttons/#complete-your-integration).
59+
*/
60+
fundingSource: PropTypes.string,
61+
5762
/**
5863
* Approved styling options for customizing layout, color, shape, and labels.
5964
*/

src/components/PayPalButtons.test.js

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import React from "react";
2+
import { render, waitFor } from "@testing-library/react";
3+
4+
import { ScriptProvider } from "../ScriptContext";
5+
import PayPalButtons from "./PayPalButtons";
6+
import { FUNDING } from "@paypal/sdk-constants";
7+
8+
describe("<PayPalButtons />", () => {
9+
beforeEach(() => {
10+
window.paypal = {
11+
Buttons: function () {
12+
return {
13+
close: jest.fn(),
14+
isEligible: jest.fn(),
15+
render: jest.fn(),
16+
};
17+
},
18+
};
19+
});
20+
21+
test("should pass props to window.paypal.Buttons()", async () => {
22+
const spyOnButtons = jest.spyOn(window.paypal, "Buttons");
23+
24+
render(
25+
<ScriptProvider options={{ "client-id": "sb" }}>
26+
<PayPalButtons
27+
fundingSource={FUNDING.CREDIT}
28+
style={{ layout: "horizontal" }}
29+
shippingPreference="GET_FROM_FILE"
30+
/>
31+
</ScriptProvider>
32+
);
33+
34+
await waitFor(() =>
35+
expect(spyOnButtons).toHaveBeenCalledWith({
36+
shippingPreference: "GET_FROM_FILE",
37+
style: { layout: "horizontal" },
38+
fundingSource: FUNDING.CREDIT,
39+
})
40+
);
41+
});
42+
});

src/components/PayPalMarks.js

+12-10
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,27 @@ import { useScriptReducer } from "../ScriptContext";
99
* <PayPalMarks />
1010
* ```
1111
*
12-
* It can also be configured to use a single funding source similar to the [standalone buttons](https://developer.paypal.com/docs/checkout/integration-features/standalone-buttons/) approach using the `fundingSource` prop.
12+
* This component can also be configured to use a single funding source similar to the [standalone buttons](https://developer.paypal.com/docs/checkout/integration-features/standalone-buttons/) approach.
13+
* A `FUNDING` object is exported by this library which has a key for every available funding source option.
14+
*
15+
* ```js
16+
* import { FUNDING } from '@paypal/react-paypal-js'
17+
* ```
18+
*
19+
* Use this `FUNDING` constant to set the `fundingSource` prop.
1320
*
1421
* ```jsx
15-
* <PayPalMarks fundingSource="paypal"/>
22+
* <PayPalMarks fundingSource={FUNDING.PAYPAL}/>
1623
* ```
1724
*/
18-
export default function Marks({ fundingSource }) {
25+
export default function Marks(props) {
1926
const [{ isLoaded }] = useScriptReducer();
2027
const markContainerRef = useRef(null);
2128
const mark = useRef(null);
2229

2330
useEffect(() => {
2431
if (isLoaded && !mark.current) {
25-
// support either key or value for funding source
26-
if (window.paypal.FUNDING[fundingSource]) {
27-
fundingSource = window.paypal.FUNDING[fundingSource];
28-
}
29-
30-
mark.current = window.paypal.Marks({ fundingSource });
32+
mark.current = window.paypal.Marks({ ...props });
3133

3234
if (mark.current.isEligible()) {
3335
mark.current.render(markContainerRef.current);
@@ -40,7 +42,7 @@ export default function Marks({ fundingSource }) {
4042

4143
Marks.propTypes = {
4244
/**
43-
* The individual mark to render. The full list can be found [here](https://developer.paypal.com/docs/checkout/integration-features/standalone-buttons/#complete-your-integration).
45+
* The individual mark to render. Use the `FUNDING` constant exported by this library to set this value. The full list can be found [here](https://developer.paypal.com/docs/checkout/integration-features/standalone-buttons/#complete-your-integration).
4446
*/
4547
fundingSource: PropTypes.string,
4648
};

src/components/PayPalMarks.test.js

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import React from "react";
2+
import { render, waitFor } from "@testing-library/react";
3+
4+
import { ScriptProvider } from "../ScriptContext";
5+
import PayPalMarks from "./PayPalMarks";
6+
import { FUNDING } from "@paypal/sdk-constants";
7+
8+
describe("<PayPalMarks />", () => {
9+
beforeEach(() => {
10+
window.paypal = {
11+
Marks: function () {
12+
return {
13+
isEligible: jest.fn(),
14+
render: jest.fn(),
15+
};
16+
},
17+
};
18+
});
19+
20+
test("should pass props to window.paypal.Marks()", async () => {
21+
const spyOnMarks = jest.spyOn(window.paypal, "Marks");
22+
23+
render(
24+
<ScriptProvider options={{ "client-id": "sb" }}>
25+
<PayPalMarks fundingSource={FUNDING.CREDIT} />
26+
</ScriptProvider>
27+
);
28+
29+
await waitFor(() =>
30+
expect(spyOnMarks).toHaveBeenCalledWith({
31+
fundingSource: FUNDING.CREDIT,
32+
})
33+
);
34+
});
35+
});

src/index.js

+2
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@ export {
55
ScriptProvider as PayPalScriptProvider,
66
useScriptReducer as usePayPalScriptReducer,
77
} from "./ScriptContext";
8+
9+
export { FUNDING } from "@paypal/sdk-constants";

src/stories/PayPalButtons.stories.js

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from "react";
2-
import { PayPalScriptProvider, PayPalButtons } from "../index";
2+
import { FUNDING, PayPalScriptProvider, PayPalButtons } from "../index";
33

44
export default {
55
title: "Example/PayPalButtons",
@@ -73,3 +73,14 @@ CustomStyle.parameters = {
7373
},
7474
},
7575
};
76+
77+
export const StandAlone = Template.bind({});
78+
StandAlone.args = { fundingSource: FUNDING.PAYLATER };
79+
80+
StandAlone.parameters = {
81+
docs: {
82+
source: {
83+
code: "<PayPalButtons fundingSource={FUNDING.PAYLATER} />",
84+
},
85+
},
86+
};

src/stories/PayPalMarks.stories.js

+17-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import React, { useState } from "react";
2-
import { PayPalScriptProvider, PayPalMarks, PayPalButtons } from "../index";
2+
import {
3+
PayPalScriptProvider,
4+
PayPalMarks,
5+
PayPalButtons,
6+
FUNDING,
7+
} from "../index";
38

49
export default {
510
title: "Example/PayPalMarks",
@@ -9,7 +14,10 @@ export default {
914
function Template(args) {
1015
return (
1116
<PayPalScriptProvider
12-
options={{ "client-id": "sb", components: "marks" }}
17+
options={{
18+
"client-id": "sb",
19+
components: "buttons,marks,funding-eligibility",
20+
}}
1321
>
1422
<PayPalMarks {...args} />
1523
</PayPalScriptProvider>
@@ -20,10 +28,10 @@ export const Default = Template.bind({});
2028
Default.args = {};
2129

2230
export const StandAlone = Template.bind({});
23-
StandAlone.args = { fundingSource: "paypal" };
31+
StandAlone.args = { fundingSource: FUNDING.PAYPAL };
2432

2533
function RadioButtonTemplate() {
26-
const [fundingSource, setFundingSource] = useState("paypal");
34+
const [fundingSource, setFundingSource] = useState(FUNDING.PAYPAL);
2735

2836
function onClick(event) {
2937
setFundingSource(event.target.value);
@@ -42,7 +50,7 @@ function RadioButtonTemplate() {
4250
onClick={onClick}
4351
type="radio"
4452
name="fundingSource"
45-
value="paypal"
53+
value={FUNDING.PAYPAL}
4654
defaultChecked
4755
/>
4856
<PayPalMarks fundingSource="paypal" />
@@ -53,19 +61,19 @@ function RadioButtonTemplate() {
5361
onClick={onClick}
5462
type="radio"
5563
name="fundingSource"
56-
value="card"
64+
value={FUNDING.CARD}
5765
/>
58-
<PayPalMarks fundingSource="card" />
66+
<PayPalMarks fundingSource={FUNDING.CARD} />
5967
</label>
6068

6169
<label className="mark">
6270
<input
6371
onClick={onClick}
6472
type="radio"
6573
name="fundingSource"
66-
value="credit"
74+
value={FUNDING.CREDIT}
6775
/>
68-
<PayPalMarks fundingSource="credit" />
76+
<PayPalMarks fundingSource={FUNDING.CREDIT} />
6977
</label>
7078
</form>
7179
<PayPalButtons fundingSource={fundingSource} />

0 commit comments

Comments
 (0)