Skip to content

Commit

Permalink
#26 add missing props (#35)
Browse files Browse the repository at this point in the history
* feat(api): add missing props (#26)

* chore(ci): use npm instead yarn on CI

* chore(test): ignore actual rn version in tests

* chore(test): explicitly pass jest configuration

* chore(test): ignore react-native-hcaptcha tests during example testing

* Apply suggestions from code review

chore(naming): use better name JS URL jsSdkPath instead apiEndpoint

Co-authored-by: e271828- <[email protected]>

* chore(naming): use jsSrc instead jsSdkPath for consistency across platforms

---------

Co-authored-by: e271828- <[email protected]>
  • Loading branch information
CAMOBAP and e271828- authored Feb 13, 2023
1 parent 1569dc2 commit 16fe55f
Show file tree
Hide file tree
Showing 12 changed files with 459 additions and 35 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: yarn
- run: yarn test
- run: npm install
- run: npm test
test-yarn:
needs: build
runs-on: ubuntu-latest
Expand Down Expand Up @@ -49,7 +49,7 @@ jobs:
working-directory: rnexample
- run: cat package.json
working-directory: rnexample
- run: yarn test
- run: yarn test --config ./jest.config.js
working-directory: rnexample
- run: npx --yes check-peer-dependencies --yarn --runOnlyOnRootDependencies
working-directory: rnexample
Expand Down Expand Up @@ -83,7 +83,7 @@ jobs:
working-directory: rnexample
- run: cat package.json
working-directory: rnexample
- run: npm run test --testPathPattern __tests__/App.test.js
- run: npm run test -- --config ./jest.config.js
working-directory: rnexample
- run: npx --yes check-peer-dependencies --npm --runOnlyOnRootDependencies
working-directory: rnexample
Expand Down
2 changes: 2 additions & 0 deletions Example.jest.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
module.exports = {
preset: 'react-native',
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
testPathIgnorePatterns: ['/node_modules/'],
modulePathIgnorePatterns: ['<rootDir>/react-native-hcaptcha/'],
transformIgnorePatterns: [
"node_modules/(?!(react-native"
+ "|@react-native"
Expand Down
49 changes: 43 additions & 6 deletions Hcaptcha.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,26 @@ import { StyleProp, ViewStyle } from "react-native";
import { WebViewMessageEvent } from "react-native-webview";

type HcaptchaProps = {
/**
* The callback function that runs after receiving a response, error, or when user cancels.
*/
onMessage?: (event: WebViewMessageEvent) => void;
/**
* The size of the checkbox.
*/
size: 'invisible' | 'normal' | 'compact';
/**
* The hCaptcha siteKey
*/
siteKey: string;
/**
* The url domain defined on your hCaptcha. You generally will not need to change this.
* The webview style
*/
url?: string;
style?: StyleProp<ViewStyle>
/**
* The callback function that runs after receiving a response, error, or when user cancels.
* The url domain defined on your hCaptcha. You generally will not need to change this.
*/
onMessage?: (event: WebViewMessageEvent) => void;
url?: string;
/**
* Default language for hCaptcha; overrides phone defaults.
* A complete list of supported languages and their codes can be found [here](https://docs.hcaptcha.com/languages/)
Expand All @@ -41,9 +49,38 @@ type HcaptchaProps = {
*/
rqdata?: string;
/**
* The webview style
* Enable / Disable sentry error reporting.
*/
style?: StyleProp<ViewStyle>
sentry?: boolean;
/**
* The url of api.js
* Default: https://js.hcaptcha.com/1/api.js (Override only if using first-party hosting feature.)
*/
jsSrc?: string;
/**
* Point hCaptcha JS Ajax Requests to alternative API Endpoint.
* Default: https://api.hcaptcha.com (Override only if using first-party hosting feature.)
*/
endpoint?: string;
/**
* Point hCaptcha Bug Reporting Request to alternative API Endpoint.
* Default: https://accounts.hcaptcha.com (Override only if using first-party hosting feature.)
*/
reportapi?: string;
/**
* Points loaded hCaptcha assets to a user defined asset location, used for proxies.
* Default: https://newassets.hcaptcha.com (Override only if using first-party hosting feature.)
*/
assethost?: string;
/**
* Points loaded hCaptcha challenge images to a user defined image location, used for proxies.
* Default: https://imgs.hcaptcha.com (Override only if using first-party hosting feature.)
*/
imghost?: string;
/**
* hCaptcha SDK host identifier. null value means that it will be generated by SDK
*/
host?: string;
}

export default class Hcaptcha extends React.Component<HcaptchaProps> {}
49 changes: 36 additions & 13 deletions Hcaptcha.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,33 +20,49 @@ const patchPostMessageJsCode = `(${String(function () {
window.ReactNativeWebView.postMessage = patchedPostMessage;
})})();`;

const buildHcaptchaApiUrl = (siteKey, languageCode, theme) => {
var url = 'https://hcaptcha.com/1/api.js?render=explicit&onload=onloadCallback';
url += `&host=${siteKey || 'missing-sitekey'}.react-native.hcaptcha.com`;
if (languageCode) {
url += '&hl=' + languageCode;
const buildHcaptchaApiUrl = (jsSrc, siteKey, hl, theme, host, sentry, endpoint, assethost, imghost, reportapi) => {
var url = `${jsSrc || "https://hcaptcha.com/1/api.js"}?render=explicit&onload=onloadCallback`;

let effectiveHost;
if (host) {
host = encodeURIComponent(host);
} else {
host = (siteKey || 'missing-sitekey') + '.react-native.hcaptcha.com';
}
if (typeof theme === 'object') {
url += '&custom=true';

for (let [key, value] of Object.entries({ host, hl, custom: typeof theme === 'object', sentry, endpoint, assethost, imghost, reportapi })) {
if (value) {
url += `&${key}=${encodeURIComponent(value)}`
}
}

return url;
};

/**
*
* @param {*} onMessage: callback after receiving response, error, or when user cancels
* @param {*} siteKey: your hCaptcha sitekey
* @param {string} size: The size of the checkbox, can be 'invisible', 'compact' or 'checkbox', Default: 'invisible'
* @param {*} style: custom style
* @param {*} url: base url
* @param {*} languageCode: can be found at https://docs.hcaptcha.com/languages
* @param {*} showLoading: loading indicator for webview till hCaptcha web content loads
* @param {*} loadingIndicatorColor: color for the ActivityIndicator
* @param {*} backgroundColor: backgroundColor which can be injected into HTML to alter css backdrop colour
* @param {*} theme: can be 'light', 'dark', 'contrast' or custom theme object
* @param {*} rqdata: see Enterprise docs
* @param {string|object} theme: can be 'light', 'dark', 'contrast' or custom theme object
* @param {string} rqdata: see Enterprise docs
* @param {boolean} sentry: sentry error reporting
* @param {string} jsSrc: The url of api.js. Default: https://js.hcaptcha.com/1/api.js (Override only if using first-party hosting feature.)
* @param {string} endpoint: Point hCaptcha JS Ajax Requests to alternative API Endpoint. Default: https://api.hcaptcha.com (Override only if using first-party hosting feature.)
* @param {string} reportapi: Point hCaptcha Bug Reporting Request to alternative API Endpoint. Default: https://accounts.hcaptcha.com (Override only if using first-party hosting feature.)
* @param {string} assethost: Points loaded hCaptcha assets to a user defined asset location, used for proxies. Default: https://newassets.hcaptcha.com (Override only if using first-party hosting feature.)
* @param {string} imghost: Points loaded hCaptcha challenge images to a user defined image location, used for proxies. Default: https://imgs.hcaptcha.com (Override only if using first-party hosting feature.)
* @param {string} host: hCaptcha SDK host identifier. null value means that it will be generated by SDK
*/
const Hcaptcha = ({
onMessage,
size,
siteKey,
style,
url,
Expand All @@ -56,8 +72,15 @@ const Hcaptcha = ({
backgroundColor,
theme,
rqdata,
sentry,
jsSrc,
endpoint,
reportapi,
assethost,
imghost,
host,
}) => {
const apiUrl = buildHcaptchaApiUrl(siteKey, languageCode, theme);
const apiUrl = buildHcaptchaApiUrl(jsSrc, siteKey, languageCode, theme, host, sentry, endpoint, assethost, imghost, reportapi);

if (theme && typeof theme === 'string') {
theme = `"${theme}"`;
Expand Down Expand Up @@ -100,7 +123,7 @@ const Hcaptcha = ({
var onloadCallback = function() {
try {
console.log("challenge onload starting");
hcaptcha.render("submit", getRenderConfig("${siteKey || ''}", ${theme}));
hcaptcha.render("submit", getRenderConfig("${siteKey || ''}", ${theme}, "${size || 'invisible'}"));
// have loaded by this point; render is sync.
console.log("challenge render complete");
} catch (e) {
Expand Down Expand Up @@ -132,10 +155,10 @@ const Hcaptcha = ({
console.log("challenge error callback fired");
window.ReactNativeWebView.postMessage("error");
};
const getRenderConfig = function(siteKey, theme) {
const getRenderConfig = function(siteKey, theme, size) {
var config = {
sitekey: siteKey,
size: "invisible",
size: size,
callback: onDataCallback,
"close-callback": onCancel,
"open-callback": onOpen,
Expand Down
2 changes: 1 addition & 1 deletion MAINTAINER.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ Starting a Gradle Daemon (subsequent builds will be faster)
java.lang.NoClassDefFoundError: Could not initialize class org.codehaus.groovy.vmplugin.v7.Java7
```

Solution: make sure that you use Java 1.8
Solution: make sure that you use Java 1.8 or above

---

Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,18 +108,27 @@ Otherwise, you should pass in the preferred device locale, e.g. fetched from `ge
| **Name** | **Type** | **Description** |
|:---|:---|:---|
| siteKey _(required)_ | string | The hCaptcha siteKey |
| size | string | The size of the checkbox, can be 'invisible', 'compact' or 'checkbox', Default: 'invisible' |
| onMessage | Function (see [here](https://github.com/react-native-webview/react-native-webview/blob/master/src/WebViewTypes.ts#L299)) | The callback function that runs after receiving a response, error, or when user cancels. |
| languageCode | string | Default language for hCaptcha; overrides phone defaults. A complete list of supported languages and their codes can be found [here](https://docs.hcaptcha.com/languages/) |
| showLoading | boolean | Whether to show a loading indicator while the hCaptcha web content loads |
| loadingIndicatorColor | string | Color of the ActivityIndicator |
| backgroundColor | string | The background color code that will be applied to the main HTML element |
| theme | string\|object | The theme can be 'light', 'dark', 'contrast' or a custom theme object (see Enterprise docs) |
| rqdata | string | Hcaptcha execution options (see Enterprise docs) |
| sentry | boolean | sentry error reporting (see Enterprise docs) |
| jsSrc | string | The url of api.js. Default: https://js.hcaptcha.com/1/api.js (Override only if using first-party hosting feature.) |
| endpoint | string | Point hCaptcha JS Ajax Requests to alternative API Endpoint. Default: https://api.hcaptcha.com (Override only if using first-party hosting feature.) |
| reportapi | string | Point hCaptcha Bug Reporting Request to alternative API Endpoint. Default: https://accounts.hcaptcha.com (Override only if using first-party hosting feature.) |
| assethost | string | Points loaded hCaptcha assets to a user defined asset location, used for proxies. Default: https://newassets.hcaptcha.com (Override only if using first-party hosting feature.) |
| imghost | string | Points loaded hCaptcha challenge images to a user defined image location, used for proxies. Default: https://imgs.hcaptcha.com (Override only if using first-party hosting feature.) |
| host | string | hCaptcha SDK host identifier. null value means that it will be generated by SDK |
| url _(inline component only)_ | string | The url domain defined on your hCaptcha. You generally will not need to change this. |
| style _(inline component only)_ | ViewStyle (see [here](https://reactnative.dev/docs/view-style-props)) | The webview style |
| baseUrl _(modal component only)_ | string | The url domain defined on your hCaptcha. You generally will not need to change this. |
| passiveSiteKey _(modal component only)_ | boolean | Indicates whether the passive mode is enabled; when true, the modal won't be shown at all |


## Status

Fully functional, but additional releases will be made in the near term.
Expand Down
6 changes: 5 additions & 1 deletion __mocks__/global.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,8 @@ jest.mock('react', () => {
.mockImplementation(ActualReact.useMemo)
.mockImplementationOnce(() => ActualReact.useMemo(() => ["test_key"], []))
}
});
});
jest.mock('react-native/Libraries/Core/ReactNativeVersion', () => {
return { version: { major: 0, minor: 0, patch: 0 } };
});
jest.mock('../md5', () => () => "mocked-md5");
24 changes: 24 additions & 0 deletions __tests__/ConfirmHcaptcha.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,28 @@ describe('ConfirmHcaptcha snapshot tests', () => {
);
expect(component).toMatchSnapshot();
});

it('renders ConfirmHcaptcha with all props', () => {
const component = renderer.create(
<ConfirmHcaptcha
size="compact"
siteKey="00000000-0000-0000-0000-000000000000"
baseUrl="https://hcaptcha.com"
languageCode="en"
showLoading={false}
loadingIndicatorColor="#999999"
backgroundColor="rgba(0.1, 0.1, 0.1, 0.4)"
theme="light"
rqdata='{"some": "data"}'
sentry={true}
jsSrc="https://all.props/api-endpoint"
endpoint="https://all.props/endpoint"
reportapi="https://all.props/reportapi"
assethost="https://all.props/assethost"
imghost="https://all.props/imghost"
host="all-props-host"
/>
);
expect(component).toMatchSnapshot();
});
});
27 changes: 24 additions & 3 deletions __tests__/Hcaptcha.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,30 @@ import renderer from 'react-test-renderer';
import Hcaptcha from '../Hcaptcha';

describe('Hcaptcha snapshot tests', () => {
let snapshot;
it('renders Hcaptcha with minimum props', () => {
snapshot = renderer.create(<Hcaptcha url="https://hcaptcha.com" />);
expect(snapshot).toMatchSnapshot();
const component = renderer.create(<Hcaptcha url="https://hcaptcha.com" />);
expect(component).toMatchSnapshot();
});

it('renders Hcaptcha with all props', () => {
const component = renderer.create(
<Hcaptcha
siteKey="00000000-0000-0000-0000-000000000000"
url="https://hcaptcha.com"
size="normal"
languageCode="fr"
showLoading={true}
loadingIndicatorColor="#123456"
backgroundColor="rgba(0.1, 0.1, 0.1, 0.4)"
theme="contrast"
rqdata="{}"
sentry={false}
jsSrc="https://all.props/api-endpoint"
endpoint="https://all.props/endpoint"
reportapi="https://all.props/reportapi"
assethost="https://all.props/assethost"
imghost="https://all.props/imghost"
host="all-props-host" />);
expect(component).toMatchSnapshot();
});
});
Loading

0 comments on commit 16fe55f

Please sign in to comment.