Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support dynamic js api attributes #3

Merged
merged 4 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.idea
**/node_modules
**/dist
coverage
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,11 +225,10 @@ If you would like to programmatically call the `render()` method, you can set `a
### API Attributes

These attributes are optional.
These attributes are used at web component creation time and thus, cannot be dynamic.

| Attribute | Values/Type | Default | Description |
|-------------------|----------------------------|---------|--------------------------------------------------------------------------------------------------------------------|
| `reCaptchaCompat` | Boolean | `true` | Disable drop-in replacement for reCAPTCHA with `false` to prevent hCaptcha from injecting into window.grecaptcha. |
| `recaptchacompat` | Boolean | `true` | Disable drop-in replacement for reCAPTCHA with `false` to prevent hCaptcha from injecting into window.grecaptcha. |
| `hl` | String (ISO 639-2 code) | - | hCaptcha auto-detects language via the user's browser. This overrides that to set a default UI language. |
| `jsapi` | String | - | See Enterprise docs. |
| `endpoint` | String | - | See Enterprise docs. |
Expand Down
8 changes: 8 additions & 0 deletions examples/cdn/angularjs.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
<script>
angular.module('angularjsApp', [])
.controller('ExampleController', function ($scope) {
$scope.jsapi = "https://js.hcaptcha.com/1/api.js";
$scope.recaptchacompat = "true";
$scope.siteKey = "781559eb-513a-4bae-8d29-d4af340e3624";
$scope.onCaptchaVerified = function (e) {
console.log('verified event', e);
Expand All @@ -26,6 +28,8 @@
{{token}}
<div style="margin-top: 40px">size: normal, theme: dark</div>
<h-captcha sitekey="{{siteKey}}"
jsapi="{{jsapi}}"
recaptchacompat="{{recaptchacompat}}"
host="example.com"
size="normal"
theme="dark"
Expand All @@ -35,6 +39,8 @@

<div style="margin-top: 20px">size: compact, theme: light</div>
<h-captcha sitekey="{{siteKey}}"
jsapi="{{jsapi}}"
recaptchacompat="{{recaptchacompat}}"
host="example.com"
size="compact"
theme="light"
Expand All @@ -45,6 +51,8 @@
<div style="margin-top: 20px">size: invisible</div>
<h-captcha ng-ref="invCaptcha"
sitekey="{{siteKey}}"
jsapi="{{jsapi}}"
recaptchacompat="{{recaptchacompat}}"
host="example.com"
size="invisible"
ng-on-verified="onCaptchaVerified($event)"
Expand Down
2 changes: 1 addition & 1 deletion examples/cdn/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
"test": "echo Examples have no tests."
},
"dependencies": {
"@hcaptcha/vanilla-hcaptcha": "1.0.2"
"@hcaptcha/vanilla-hcaptcha": "link:../../packages/vanilla-hcaptcha"
}
}
10 changes: 8 additions & 2 deletions examples/cdn/preact.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
<script src="https://unpkg.com/preact/dist/preact.umd.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>

<script src="https://unpkg.com/vanilla-hcaptcha" async defer></script>
<!-- <script src="/node_modules/@hcaptcha/vanilla-hcaptcha/dist/index.min.js"></script>-->
<!-- <script src="https://unpkg.com/@hcaptcha/vanilla-hcaptcha" async defer></script>-->
<script src="/node_modules/@hcaptcha/vanilla-hcaptcha/dist/index.min.js"></script>
</head>
<body>

Expand All @@ -22,6 +22,9 @@
super(props);
this.state = {
sitekey: "781559eb-513a-4bae-8d29-d4af340e3624",
jsapi: "https://js.hcaptcha.com/1/api.js",
recaptchacompat: true,
sentry: true,
token: "",
};
this.captchaRef = preact.createRef();
Expand All @@ -45,6 +48,9 @@
<h-captcha
ref={this.captchaRef}
sitekey={this.state.sitekey}
jsapi={this.state.jsapi}
recaptchacompat={this.state.recaptchacompat}
sentry={this.state.sentry}
host="example.com"
size="normal"
theme="dark"
Expand Down
10 changes: 8 additions & 2 deletions examples/cdn/react.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>

<script src="https://unpkg.com/@hcaptcha/vanilla-hcaptcha" async defer></script>
<!-- <script src="/node_modules/@hcaptcha/vanilla-hcaptcha/dist/index.min.js"></script>-->
<!-- <script src="https://unpkg.com/@hcaptcha/vanilla-hcaptcha" async defer></script>-->
<script src="/node_modules/@hcaptcha/vanilla-hcaptcha/dist/index.min.js"></script>
</head>
<body>

Expand All @@ -19,6 +19,9 @@
super(props);
this.state = {
sitekey: "781559eb-513a-4bae-8d29-d4af340e3624",
jsapi: "https://js.hcaptcha.com/1/api.js",
recaptchacompat: true,
sentry: true,
token: "",
};
this.captchaRef = React.createRef();
Expand All @@ -42,6 +45,9 @@
<h-captcha
ref={this.captchaRef}
sitekey={this.state.sitekey}
jsapi={this.state.jsapi}
recaptchacompat={this.state.recaptchacompat}
sentry={this.state.sentry}
host="example.com"
size="normal"
theme="dark"
Expand Down
2 changes: 2 additions & 0 deletions examples/cdn/vanilla.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
<script>
const signupCaptcha = document.getElementById('signupCaptcha');

signupCaptcha.setAttribute("jsapi", "https://js.hcaptcha.com/1/api.js");

signupCaptcha.addEventListener('loaded', () => {
console.log('hCaptcha Component Loaded');
// Safe to call `execute` once component is loaded
Expand Down
4 changes: 4 additions & 0 deletions examples/cdn/vue.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
ref="captcha1"
host="example.com"
:sitekey="sitekey"
:jsapi="jsapi"
size="normal"
theme="dark"
@verified="onVerify"
Expand All @@ -31,6 +32,7 @@
<h-captcha
host="example.com"
:sitekey="sitekey"
:jsapi="jsapi"
size="compact"
theme="light"
@verified="onVerify"
Expand All @@ -44,6 +46,7 @@
ref="invCaptcha"
host="example.com"
:sitekey="sitekey"
:jsapi="jsapi"
size="invisible"
theme="light"
@verified="onVerify"
Expand All @@ -60,6 +63,7 @@
data() {
return {
sitekey: "781559eb-513a-4bae-8d29-d4af340e3624",
jsapi: "https://js.hcaptcha.com/1/api.js",
token: ""
};
},
Expand Down
31 changes: 31 additions & 0 deletions packages/vanilla-hcaptcha/__tests__/unit/hcaptcha.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,35 @@ describe('hCaptcha Vanilla Web Component', () => {
hCaptchaEl2.addEventListener('loaded', () => done());
});

it('should use dynamic jsapi attribute', async () => {
const hcaptcha = window.hcaptcha;
delete window.hcaptcha;
delete window._hCaptchaOnLoadPromise;

const scriptElement = document.createElement("script");

jest.spyOn(document, "createElement").mockImplementation((tagName) => {
if (tagName === 'script') {
// Simulate js api onload.
window._hCaptchaOnLoad();
window.hcaptcha = hcaptcha;
return scriptElement;
}
throw new Error("Unexpected tag name to be mocked.");
});

document.body.innerHTML = `<h-captcha id="signupCaptcha2" site-key="10000000-ffff-ffff-ffff-000000000001"></h-captcha>`;

document.getElementById("signupCaptcha2").setAttribute("jsapi", "https://example.hcaptcha.com/1/api.js");

const hCaptchaEl2 = document.getElementById('signupCaptcha2');

await new Promise((resolve, reject) => {
hCaptchaEl2.addEventListener("loaded", () => resolve());
setTimeout(() => reject("failed to load js api in time"), 1);
});

expect(scriptElement.src).toEqual("https://example.hcaptcha.com/1/api.js?render=explicit&onload=_hCaptchaOnLoad&sentry=true");
});

});
12 changes: 6 additions & 6 deletions packages/vanilla-hcaptcha/jest.config.mjs
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
const unitConfig = {
collectCoverage : true,
displayName : "unit",
verbose : true,
silent : false,
displayName: "unit",
moduleDirectories: [
".",
"<rootDir>",
"src",
"node_modules"
],
testEnvironment: "jsdom",
testMatch: [
"<rootDir>/__tests__/unit/**/*.test.js"
]
};

export default {
verbose : true,
verbose: true,
collectCoverage: true,
silent: false,
projects: [
unitConfig
]
Expand Down
11 changes: 6 additions & 5 deletions packages/vanilla-hcaptcha/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"license": "MIT",
"private": false,
"publishConfig": {
"registry":"https://registry.npmjs.org",
"registry": "https://registry.npmjs.org/",
"access": "public"
},
"repository": {
Expand All @@ -32,14 +32,15 @@
"@babel/core": "^7.18.0",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/preset-env": "^7.18.0",
"@hcaptcha/types": "^1.0.1",
"@hcaptcha/types": "^1.0.3",
"@rollup/plugin-typescript": "^8.3.2",
"jest": "^26.6.3",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"rollup": "^2.74.1",
"rollup-plugin-filesize": "^9.1.2",
"rollup-plugin-terser": "^7.0.2",
"tslib": "^2.4.0",
"typescript": "^4.6.4"
"tslib": "^2.6.2",
"typescript": "^5.4.5"
},
"keywords": [
"captcha",
Expand Down
6 changes: 3 additions & 3 deletions packages/vanilla-hcaptcha/src/api-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export function loadJsApiIfNotAlready(config: VanillaHCaptchaJsApiConfig): Promi
if (window._hCaptchaOnLoadPromise) {
return window._hCaptchaOnLoadPromise;
} else if (window.hcaptcha) {
console.warn("[vanilla-hcaptcha] hCaptcha JS API detected to be externally loaded. " +
console.warn("[@hcaptcha/vanilla-hcaptcha]: hCaptcha JS API detected to be externally loaded. " +
"Unless you know what are you doing, this task should be delegated to this web component.");
window._hCaptchaOnLoadPromise = Promise.resolve();
return window._hCaptchaOnLoadPromise;
Expand Down Expand Up @@ -53,10 +53,10 @@ function getScriptSrc(config: VanillaHCaptchaJsApiConfig) {
let scriptSrc = config.jsapi;
scriptSrc = addQueryParamIfDefined(scriptSrc, 'render', 'explicit');
scriptSrc = addQueryParamIfDefined(scriptSrc, 'onload', '_hCaptchaOnLoad');
scriptSrc = addQueryParamIfDefined(scriptSrc, 'recaptchacompat', config.reCaptchaCompat === false ? 'off' : null);
scriptSrc = addQueryParamIfDefined(scriptSrc, 'recaptchacompat', config.recaptchacompat === 'false' ? 'off' : null);
scriptSrc = addQueryParamIfDefined(scriptSrc, 'host', config.host);
scriptSrc = addQueryParamIfDefined(scriptSrc, 'hl', config.hl);
scriptSrc = addQueryParamIfDefined(scriptSrc, 'sentry', JSON.stringify(config.sentry));
scriptSrc = addQueryParamIfDefined(scriptSrc, 'sentry', config.sentry === 'false' ? 'false' : 'true');
scriptSrc = addQueryParamIfDefined(scriptSrc, 'endpoint', config.endpoint);
scriptSrc = addQueryParamIfDefined(scriptSrc, 'assethost', config.assethost);
scriptSrc = addQueryParamIfDefined(scriptSrc, 'imghost', config.imghost);
Expand Down
Loading