From 9bc4d7c7805ec8653a859995fe83184d98f64ef8 Mon Sep 17 00:00:00 2001 From: Brad Peters Date: Tue, 27 Jun 2023 13:45:47 -0700 Subject: [PATCH 1/3] fix(mount): Handle multiple calls to mount --- src/{index.js => index.jsx} | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) rename src/{index.js => index.jsx} (94%) diff --git a/src/index.js b/src/index.jsx similarity index 94% rename from src/index.js rename to src/index.jsx index 2eb0dbe..d872d57 100644 --- a/src/index.js +++ b/src/index.jsx @@ -192,8 +192,12 @@ class HCaptcha extends React.Component { } renderCaptcha(onReady) { - const { isApiReady } = this.state; - if (!isApiReady) return; + const { isApiReady, captchaId } = this.state; + + // Prevent calling hCaptcha render on two conditions: + // • API is not ready + // • Component has already been mounted + if (!isApiReady || captchaId) return; const renderParams = Object.assign({ "open-callback" : this.handleOpen, @@ -209,9 +213,9 @@ class HCaptcha extends React.Component { const hcaptcha = this._hcaptcha; //Render hCaptcha widget and provide necessary callbacks - hCaptcha - const captchaId = hcaptcha.render(this.ref.current, renderParams); + const id = hcaptcha.render(this.ref.current, renderParams); - this.setState({ isRemoved: false, captchaId }, () => { + this.setState({ isRemoved: false, captchaId: id }, () => { onReady && onReady(); }); } @@ -341,6 +345,17 @@ class HCaptcha extends React.Component { return hcaptcha.execute(captchaId, opts); } + close() { + const { captchaId } = this.state; + const hcaptcha = this._hcaptcha; + + if (!this.isReady()) { + return; + } + + return hcaptcha.close(captchaId); + } + setData (data) { const { captchaId } = this.state; const hcaptcha = this._hcaptcha; From 408eebea3a070c810815176cf5a0b2c89b1ffc47 Mon Sep 17 00:00:00 2001 From: Brad Peters Date: Tue, 27 Jun 2023 13:46:45 -0700 Subject: [PATCH 2/3] update: change file extension back --- src/{index.jsx => index.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{index.jsx => index.js} (100%) diff --git a/src/index.jsx b/src/index.js similarity index 100% rename from src/index.jsx rename to src/index.js From 833ae04f7452897366e1d1fe161e6d6ecd11abed Mon Sep 17 00:00:00 2001 From: Brad Peters Date: Tue, 27 Jun 2023 14:19:08 -0700 Subject: [PATCH 3/3] fix(tests): Update tests and add potential new prop --- src/index.js | 6 ++++-- tests/hcaptcha.spec.js | 15 ++++++++++----- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/index.js b/src/index.js index d872d57..ddbb64f 100644 --- a/src/index.js +++ b/src/index.js @@ -191,8 +191,9 @@ class HCaptcha extends React.Component { this.apiScriptRequested = true; } - renderCaptcha(onReady) { + renderCaptcha(onRender) { const { isApiReady, captchaId } = this.state; + const { onReady } = this.props; // Prevent calling hCaptcha render on two conditions: // • API is not ready @@ -216,7 +217,8 @@ class HCaptcha extends React.Component { const id = hcaptcha.render(this.ref.current, renderParams); this.setState({ isRemoved: false, captchaId: id }, () => { - onReady && onReady(); + onRender && onRender(); + onReady && onReady(); }); } diff --git a/tests/hcaptcha.spec.js b/tests/hcaptcha.spec.js index 2a8dcec..50530d4 100644 --- a/tests/hcaptcha.spec.js +++ b/tests/hcaptcha.spec.js @@ -154,12 +154,19 @@ describe("hCaptcha", () => { expect(window.hcaptcha.setData.mock.calls[0][1]).toBe(dataObj); }); - it("emits onLoad event", () => { + it("should emit onLoad event if no hCaptcha ID is stored", () => { + instance.state.captchaId = ''; expect(mockFns.onLoad.mock.calls.length).toBe(0); instance.handleOnLoad(); expect(mockFns.onLoad.mock.calls.length).toBe(1); }); + it("should not emit onLoad event if hCapthcha ID is found", () => { + instance.handleOnLoad(); + expect(mockFns.onLoad.mock.calls.length).toBe(0); + }); + + it("emits verify with token and eKey", () => { expect(mockFns.onVerify.mock.calls.length).toBe(0); instance.handleSubmit(); @@ -324,7 +331,7 @@ describe("hCaptcha", () => { it("should not set id if no id prop is passed", (done) => { - const onLoad = jest.fn(() => { + const onReady = jest.fn(() => { expect(instance.state.captchaId).toBe(MOCK_WIDGET_ID); done(); }); @@ -332,11 +339,9 @@ describe("hCaptcha", () => { instance = ReactTestUtils.renderIntoDocument( , ); - - instance.handleOnLoad(); });