Improve ArkoseLabs challenge UX

This does a few UX improvements to the ArkoseLabs challenge:
- We now show the "complete challenge" error only if the ArkoseLabs
  iframe was actually shown. This prevents the container from showing up
  in cases where the challenge is being suppressed.
- If the verification process was triggered as a result of submitting
  the form, we now re-submit the form if the chalenge is being
  suppressed. This fixes weird states where you might have to manually
  submit the form twice if you had filled in your information fast
  enough.
parent fd00d069
...@@ -58,11 +58,8 @@ export default { ...@@ -58,11 +58,8 @@ export default {
}; };
}, },
computed: { computed: {
isVisible() {
return this.arkoseLabsIframeShown || this.showErrorContainer;
},
showErrorContainer() { showErrorContainer() {
return this.showArkoseNeededError || this.showArkoseFailure; return (this.arkoseLabsIframeShown && this.showArkoseNeededError) || this.showArkoseFailure;
}, },
}, },
watch: { watch: {
...@@ -91,6 +88,7 @@ export default { ...@@ -91,6 +88,7 @@ export default {
} }
e.preventDefault(); e.preventDefault();
this.submitOnSuppress = true;
if (!this.arkoseInitialized) { if (!this.arkoseInitialized) {
// If the challenge hasn't been initialized yet, we trigger a check now to make sure it // If the challenge hasn't been initialized yet, we trigger a check now to make sure it
// wasn't skipped by submitting the form without the username field ever losing the focus. // wasn't skipped by submitting the form without the username field ever losing the focus.
...@@ -102,7 +100,6 @@ export default { ...@@ -102,7 +100,6 @@ export default {
} }
}, },
async checkAndSubmit(form) { async checkAndSubmit(form) {
this.submitOnSuppress = true;
await this.checkIfNeedsChallenge(); await this.checkIfNeedsChallenge();
if (!this.arkoseInitialized) { if (!this.arkoseInitialized) {
// If the challenge still hasn't been initialized, the user definitely doesn't need one and // If the challenge still hasn't been initialized, the user definitely doesn't need one and
...@@ -194,16 +191,17 @@ export default { ...@@ -194,16 +191,17 @@ export default {
</script> </script>
<template> <template>
<div v-show="isVisible"> <div>
<dom-element-listener :selector="usernameSelector" @blur="checkIfNeedsChallenge" />
<dom-element-listener :selector="formSelector" @submit="onSubmit" />
<input <input
v-if="arkoseInitialized" v-if="arkoseInitialized"
:name="$options.VERIFICATION_TOKEN_INPUT_NAME" :name="$options.VERIFICATION_TOKEN_INPUT_NAME"
type="hidden" type="hidden"
:value="arkoseToken" :value="arkoseToken"
/> />
<dom-element-listener :selector="usernameSelector" @blur="checkIfNeedsChallenge" />
<dom-element-listener :selector="formSelector" @submit="onSubmit" />
<div <div
v-show="arkoseLabsIframeShown"
class="gl-display-flex gl-justify-content-center gl-mt-3 gl-mb-n3" class="gl-display-flex gl-justify-content-center gl-mt-3 gl-mb-n3"
:class="arkoseContainerClass" :class="arkoseContainerClass"
data-testid="arkose-labs-challenge" data-testid="arkose-labs-challenge"
......
...@@ -41,6 +41,7 @@ describe('SignInArkoseApp', () => { ...@@ -41,6 +41,7 @@ describe('SignInArkoseApp', () => {
const findSignInForm = () => findByTestId('sign-in-form'); const findSignInForm = () => findByTestId('sign-in-form');
const findUsernameInput = () => findByTestId('username-field'); const findUsernameInput = () => findByTestId('username-field');
const findSignInButton = () => findByTestId('sign-in-button'); const findSignInButton = () => findByTestId('sign-in-button');
const findChallengeContainer = () => wrapper.findByTestId('arkose-labs-challenge');
const findArkoseLabsErrorMessage = () => wrapper.findByTestId('arkose-labs-error-message'); const findArkoseLabsErrorMessage = () => wrapper.findByTestId('arkose-labs-error-message');
const findArkoseLabsVerificationTokenInput = () => const findArkoseLabsVerificationTokenInput = () =>
wrapper.find('input[name="arkose_labs_token"]'); wrapper.find('input[name="arkose_labs_token"]');
...@@ -211,6 +212,7 @@ describe('SignInArkoseApp', () => { ...@@ -211,6 +212,7 @@ describe('SignInArkoseApp', () => {
itInitializesArkoseLabs(); itInitializesArkoseLabs();
it('shows ArkoseLabs error when submitting the form', async () => { it('shows ArkoseLabs error when submitting the form', async () => {
onShown();
submitForm(); submitForm();
await nextTick(); await nextTick();
...@@ -219,12 +221,12 @@ describe('SignInArkoseApp', () => { ...@@ -219,12 +221,12 @@ describe('SignInArkoseApp', () => {
}); });
it('un-hides the challenge container once the iframe has been shown', async () => { it('un-hides the challenge container once the iframe has been shown', async () => {
expect(wrapper.isVisible()).toBe(false); expect(findChallengeContainer().isVisible()).toBe(false);
onShown(); onShown();
await nextTick(); await nextTick();
expect(wrapper.isVisible()).toBe(true); expect(findChallengeContainer().isVisible()).toBe(true);
}); });
it('shows an error alert if the challenge fails to load', async () => { it('shows an error alert if the challenge fails to load', async () => {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment