Skip to content

Commit 9f6172c

Browse files
committed
implement executeAsync to allow for promise based execution dozoisch#72
1 parent 3785ff6 commit 9f6172c

File tree

2 files changed

+89
-3
lines changed

2 files changed

+89
-3
lines changed

src/recaptcha.js

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,14 @@ export default class ReCAPTCHA extends React.Component {
3434
}
3535
}
3636

37+
executeAsync() {
38+
return new Promise((resolve, reject) => {
39+
this.executionResolve = resolve;
40+
this.executionReject = reject;
41+
this.execute();
42+
})
43+
}
44+
3745
reset() {
3846
if (this.props.grecaptcha && this._widgetId !== undefined) {
3947
this.props.grecaptcha.reset(this._widgetId);
@@ -49,11 +57,25 @@ export default class ReCAPTCHA extends React.Component {
4957
}
5058

5159
handleErrored() {
52-
if (this.props.onErrored) this.props.onErrored();
60+
if (this.props.onErrored) {
61+
this.props.onErrored();
62+
}
63+
if(this.executionReject){
64+
this.executionReject();
65+
delete this.executionResolve;
66+
delete this.executionReject;
67+
}
5368
}
54-
69+
5570
handleChange(token) {
56-
if (this.props.onChange) this.props.onChange(token);
71+
if (this.props.onChange) {
72+
this.props.onChange(token);
73+
}
74+
if(this.executionResolve) {
75+
this.executionResolve(token);
76+
delete this.executionReject;
77+
delete this.executionResolve;
78+
}
5779
}
5880

5981
explicitRender() {

test/recaptcha.spec.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,70 @@ describe("ReCAPTCHA", () => {
8888
instance._internalRef.current.execute();
8989
expect(grecaptchaMock.execute).toBeCalledWith(WIDGET_ID);
9090
});
91+
it("executeAsync, should call grecaptcha.execute with the widget id", () => {
92+
const WIDGET_ID = "someWidgetId";
93+
const grecaptchaMock = {
94+
render() {
95+
return WIDGET_ID;
96+
},
97+
execute: jest.fn(),
98+
};
99+
// wrapping component example that applies a ref to ReCAPTCHA
100+
class WrappingComponent extends React.Component {
101+
constructor(props) {
102+
super(props);
103+
this._internalRef = React.createRef();
104+
}
105+
render() {
106+
return (
107+
<div>
108+
<ReCAPTCHA
109+
sitekey="xxx"
110+
size="invisible"
111+
grecaptcha={grecaptchaMock}
112+
onChange={jest.fn()}
113+
ref={this._internalRef}
114+
/>
115+
</div>
116+
);
117+
}
118+
}
119+
const instance = ReactTestUtils.renderIntoDocument(React.createElement(WrappingComponent));
120+
instance._internalRef.current.execute();
121+
expect(grecaptchaMock.execute).toBeCalledWith(WIDGET_ID);
122+
});
123+
it("executeAsync, should return a promise", () => {
124+
const WIDGET_ID = "someWidgetId";
125+
const grecaptchaMock = {
126+
render() {
127+
return WIDGET_ID;
128+
},
129+
execute: jest.fn(),
130+
};
131+
// wrapping component example that applies a ref to ReCAPTCHA
132+
class WrappingComponent extends React.Component {
133+
constructor(props) {
134+
super(props);
135+
this._internalRef = React.createRef();
136+
}
137+
render() {
138+
return (
139+
<div>
140+
<ReCAPTCHA
141+
sitekey="xxx"
142+
size="invisible"
143+
grecaptcha={grecaptchaMock}
144+
onChange={jest.fn()}
145+
ref={this._internalRef}
146+
/>
147+
</div>
148+
);
149+
}
150+
}
151+
const instance = ReactTestUtils.renderIntoDocument(React.createElement(WrappingComponent));
152+
let result = instance._internalRef.current.executeAsync();
153+
expect(result).toBeInstanceOf(Promise);
154+
});
91155
describe("Expired", () => {
92156
it("should call onChange with null when response is expired", () => {
93157
const WIDGET_ID = "someWidgetId";

0 commit comments

Comments
 (0)