Commit 2c67bd80 authored by Paul Gascou-Vaillancourt's avatar Paul Gascou-Vaillancourt Committed by Paul Gascou-Vaillancourt

Write spec for Vue component

parent 7fdbc180
......@@ -139,7 +139,7 @@ export default {
this.hideErrors();
},
handleArkoseLabsFailure(e) {
// eslint-disable-next-line no-console, @gitlab/require-i18n-strings
// eslint-disable-next-line no-console
console.error('ArkoseLabs initialization error', e);
this.showArkoseFailure = true;
},
......
import { nextTick } from 'vue';
import AxiosMockAdapter from 'axios-mock-adapter';
import { ArkoseLabs } from 'ee/arkose_labs/arkose_labs';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import SignInArkoseApp from 'ee/arkose_labs/components/sign_in_arkose_app.vue';
import axios from '~/lib/utils/axios_utils';
import waitForPromises from 'helpers/wait_for_promises';
describe('ArkoseLabs', () => {
let arkoseLabs;
import { initArkoseLabsScript } from 'ee/arkose_labs/init_arkose_labs_script';
// ArkoseLabs enforcement mocks
jest.mock('ee/arkose_labs/init_arkose_labs_script');
let onShown;
let onCompleted;
let onError;
initArkoseLabsScript.mockImplementation(() => ({
setConfig: ({ onShown: shownHandler, onCompleted: completedHandler, onError: errorHandler }) => {
onShown = shownHandler;
onCompleted = completedHandler;
onError = errorHandler;
},
}));
describe('SignInArkoseApp', () => {
let wrapper;
let axiosMock;
// Finders
const findByTestId = (testId) => document.querySelector(`[data-testid="${testId}"]`);
const findScriptTags = () => document.querySelectorAll('script');
const makeTestIdSelector = (testId) => `[data-testid="${testId}"]`;
const findByTestId = (testId) => document.querySelector(makeTestIdSelector(testId));
const findSignInForm = () => findByTestId('sign-in-form');
const findUsernameInput = () => findByTestId('username-field');
const findSignInButton = () => findByTestId('sign-in-button');
const findArkoseLabsChallengeContainer = () => findByTestId('arkose-labs-challenge');
const findArkoseLabsErrorMessage = () => findByTestId('arkose-labs-error-message');
const findArkoseLabsFailureAlert = () => findByTestId('arkose-labs-failure-alert');
const findArkoseLabsErrorMessage = () => wrapper.findByTestId('arkose-labs-error-message');
const findArkoseLabsVerificationTokenInput = () =>
document.querySelector('input[name="arkose_labs_token"]');
wrapper.find('input[name="arkose_labs_token"]');
// Helpers
const createForm = (username = '') => {
......@@ -26,7 +40,14 @@ describe('ArkoseLabs', () => {
};
const initArkoseLabs = (username) => {
createForm(username);
arkoseLabs = new ArkoseLabs();
wrapper = mountExtended(SignInArkoseApp, {
propsData: {
publicKey: 'arkose-labs-public-api-key',
formSelector: makeTestIdSelector('sign-in-form'),
usernameSelector: makeTestIdSelector('username-field'),
submitSelector: makeTestIdSelector('sign-in-button'),
},
});
};
const setUsername = (username) => {
const input = findUsernameInput();
......@@ -41,40 +62,38 @@ describe('ArkoseLabs', () => {
// Assertions
const itInitializesArkoseLabs = () => {
it("includes ArkoseLabs' script", () => {
expect(findScriptTags().length).toBe(1);
expect(initArkoseLabsScript).toHaveBeenCalled();
});
it('creates a hidden input for the verification token', () => {
const input = findArkoseLabsVerificationTokenInput();
expect(input).not.toBeNull();
expect(input.value).toBe('');
expect(input.exists()).toBe(true);
expect(input.element.value).toBe('');
});
};
const expectHiddenArkoseLabsError = () => {
expect(findArkoseLabsErrorMessage().classList.contains('gl-display-none')).toBe(true);
expect(findArkoseLabsErrorMessage().exists()).toBe(false);
};
beforeEach(() => {
axiosMock = new AxiosMockAdapter(axios);
});
it('skips the initialization if the login form is not present', () => {
expect(() => {
arkoseLabs = new ArkoseLabs();
}).not.toThrow();
expect(arkoseLabs.signInForm).toBeNull();
afterEach(() => {
wrapper?.destroy();
});
describe('when the username field is pre-filled', () => {
const username = 'invite-email-username';
it("does not include ArkoseLabs' script initially", () => {
expect(findScriptTags().length).toBe(0);
expect(initArkoseLabsScript).not.toHaveBeenCalled();
});
it('puts the sign-in button in the loading state', () => {
it('puts the sign-in button in the loading state', async () => {
initArkoseLabs(username);
await nextTick();
const signInButton = findSignInButton();
expect(signInButton.innerText).toMatchInterpolatedText('Loading');
......@@ -108,7 +127,7 @@ describe('ArkoseLabs', () => {
it('does not show ArkoseLabs error when submitting the form', () => {
submitForm();
expect(findArkoseLabsErrorMessage()).toBe(null);
expect(findArkoseLabsErrorMessage().exists()).toBe(false);
});
describe('if the challenge becomes needed', () => {
......@@ -131,85 +150,61 @@ describe('ArkoseLabs', () => {
itInitializesArkoseLabs();
it('shows ArkoseLabs error when submitting the form', () => {
it('shows ArkoseLabs error when submitting the form', async () => {
submitForm();
await nextTick();
expect(findArkoseLabsErrorMessage()).not.toBe(null);
expect(findArkoseLabsErrorMessage().exists()).toBe(true);
});
it('un-hides the challenge container once the iframe has been shown', () => {
let onShown;
arkoseLabs.setConfig({
setConfig: ({ onShown: handler }) => {
onShown = handler;
},
});
expect(findArkoseLabsChallengeContainer().classList.contains('gl-display-none!')).toBe(
true,
);
it('un-hides the challenge container once the iframe has been shown', async () => {
expect(wrapper.isVisible()).toBe(false);
onShown();
await nextTick();
expect(findArkoseLabsChallengeContainer().classList.contains('gl-display-none!')).toBe(
false,
);
expect(wrapper.isVisible()).toBe(true);
});
it('shows an error alert if the challenge fails to load', () => {
let onError;
arkoseLabs.setConfig({
setConfig: ({ onError: handler }) => {
onError = handler;
},
});
it('shows an error alert if the challenge fails to load', async () => {
jest.spyOn(console, 'error').mockImplementation(() => {});
expect(findArkoseLabsFailureAlert()).toBe(null);
expect(wrapper.text()).not.toContain(wrapper.vm.$options.MSG_ARKOSE_FAILURE_BODY);
onError();
const error = new Error();
onError(error);
expect(findArkoseLabsFailureAlert()).not.toBe(null);
// eslint-disable-next-line no-console
expect(console.error).toHaveBeenCalledWith('ArkoseLabs initialization error', error);
await nextTick();
expect(wrapper.text()).toContain(wrapper.vm.$options.MSG_ARKOSE_FAILURE_BODY);
});
describe.each`
handlerName
${'onCompleted'}
${'onSuppress'}
`(
'when ArkoseLabs calls `$handlerName` handler that has been configured',
({ handlerName }) => {
let handlerMock;
const enforcement = {
setConfig: ({ [handlerName]: handler }) => {
handlerMock = handler;
},
};
const response = { token: 'verification-token' };
beforeEach(() => {
submitForm();
arkoseLabs.setConfig(enforcement);
handlerMock(response);
});
it('removes ArkoseLabs error', () => {
expectHiddenArkoseLabsError();
});
it('does not show again the error when re-submitting the form', () => {
submitForm();
expectHiddenArkoseLabsError();
});
it("sets the verification token input's value", () => {
expect(findArkoseLabsVerificationTokenInput().value).toBe(response.token);
});
},
);
describe('when ArkoseLabs calls `onCompleted` handler that has been configured', () => {
const response = { token: 'verification-token' };
beforeEach(() => {
submitForm();
onCompleted(response);
});
it('removes ArkoseLabs error', () => {
expectHiddenArkoseLabsError();
});
it('does not show again the error when re-submitting the form', () => {
submitForm();
expectHiddenArkoseLabsError();
});
it("sets the verification token input's value", () => {
expect(findArkoseLabsVerificationTokenInput().element.value).toBe(response.token);
});
});
});
});
});
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