diff options
Diffstat (limited to 'app/assets/javascripts/captcha/init_recaptcha_script.js')
-rw-r--r-- | app/assets/javascripts/captcha/init_recaptcha_script.js | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/app/assets/javascripts/captcha/init_recaptcha_script.js b/app/assets/javascripts/captcha/init_recaptcha_script.js new file mode 100644 index 00000000000..f546eef7d84 --- /dev/null +++ b/app/assets/javascripts/captcha/init_recaptcha_script.js @@ -0,0 +1,48 @@ +// NOTE: This module will be used in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52044 +import { memoize } from 'lodash'; + +export const RECAPTCHA_API_URL_PREFIX = 'https://www.google.com/recaptcha/api.js'; +export const RECAPTCHA_ONLOAD_CALLBACK_NAME = 'recaptchaOnloadCallback'; + +/** + * Adds the Google reCAPTCHA script tag to the head of the document, and + * returns a promise of the grecaptcha object + * (https://developers.google.com/recaptcha/docs/display#js_api). + * + * It is memoized, so there will only be one instance of the script tag ever + * added to the document. + * + * See the reCAPTCHA documentation for more details: + * + * https://developers.google.com/recaptcha/docs/display#explicit_render + * + */ +export const initRecaptchaScript = memoize(() => { + // Appends the the reCAPTCHA script tag to the head of document + const appendRecaptchaScript = () => { + const script = document.createElement('script'); + script.src = `${RECAPTCHA_API_URL_PREFIX}?onload=${RECAPTCHA_ONLOAD_CALLBACK_NAME}&render=explicit`; + script.classList.add('js-recaptcha-script'); + document.head.appendChild(script); + }; + + return new Promise((resolve) => { + // This global callback resolves the Promise and is passed by name to the reCAPTCHA script. + window[RECAPTCHA_ONLOAD_CALLBACK_NAME] = () => { + // Let's clean up after ourselves. This is also important for testing, because `window` is NOT cleared between tests. + // https://github.com/facebook/jest/issues/1224#issuecomment-444586798. + delete window[RECAPTCHA_ONLOAD_CALLBACK_NAME]; + resolve(window.grecaptcha); + }; + appendRecaptchaScript(); + }); +}); + +/** + * Clears the cached memoization of the default manager. + * + * This is needed for determinism in tests. + */ +export const clearMemoizeCache = () => { + initRecaptchaScript.cache.clear(); +}; |