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