2022-05-23 09:08:01 +00:00
|
|
|
import { GlAlert } from '@gitlab/ui';
|
|
|
|
import { nextTick } from 'vue';
|
|
|
|
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
|
2022-06-07 15:08:12 +00:00
|
|
|
import { mountExtended } from 'helpers/vue_test_utils_helper';
|
2022-05-23 09:08:01 +00:00
|
|
|
import NewAccessTokenApp from '~/access_tokens/components/new_access_token_app.vue';
|
|
|
|
import { createAlert, VARIANT_INFO } from '~/flash';
|
|
|
|
import { __, sprintf } from '~/locale';
|
|
|
|
import DomElementListener from '~/vue_shared/components/dom_element_listener.vue';
|
|
|
|
import InputCopyToggleVisibility from '~/vue_shared/components/form/input_copy_toggle_visibility.vue';
|
|
|
|
|
|
|
|
jest.mock('~/flash');
|
|
|
|
|
|
|
|
describe('~/access_tokens/components/new_access_token_app', () => {
|
|
|
|
let wrapper;
|
|
|
|
|
|
|
|
const accessTokenType = 'personal access token';
|
|
|
|
|
|
|
|
const createComponent = (provide = { accessTokenType }) => {
|
2022-06-07 15:08:12 +00:00
|
|
|
wrapper = mountExtended(NewAccessTokenApp, {
|
2022-05-23 09:08:01 +00:00
|
|
|
provide,
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
const triggerSuccess = async (newToken = 'new token') => {
|
|
|
|
wrapper
|
|
|
|
.find(DomElementListener)
|
|
|
|
.vm.$emit('ajax:success', { detail: [{ new_token: newToken }] });
|
|
|
|
await nextTick();
|
|
|
|
};
|
|
|
|
|
|
|
|
const triggerError = async (errors = ['1', '2']) => {
|
|
|
|
wrapper.find(DomElementListener).vm.$emit('ajax:error', { detail: [{ errors }] });
|
|
|
|
await nextTick();
|
|
|
|
};
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
// NewAccessTokenApp observes a form element
|
|
|
|
setHTMLFixture('<form id="js-new-access-token-form"><input type="submit"/></form>');
|
|
|
|
|
|
|
|
createComponent();
|
|
|
|
});
|
|
|
|
|
|
|
|
afterEach(() => {
|
|
|
|
resetHTMLFixture();
|
|
|
|
wrapper.destroy();
|
|
|
|
createAlert.mockClear();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should render nothing', () => {
|
|
|
|
expect(wrapper.findComponent(InputCopyToggleVisibility).exists()).toBe(false);
|
|
|
|
expect(wrapper.findComponent(GlAlert).exists()).toBe(false);
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('on success', () => {
|
|
|
|
it('should render `InputCopyToggleVisibility` component', async () => {
|
|
|
|
const newToken = '12345';
|
|
|
|
await triggerSuccess(newToken);
|
|
|
|
|
|
|
|
expect(wrapper.findComponent(GlAlert).exists()).toBe(false);
|
|
|
|
|
|
|
|
const InputCopyToggleVisibilityComponent = wrapper.findComponent(InputCopyToggleVisibility);
|
|
|
|
expect(InputCopyToggleVisibilityComponent.props('value')).toBe(newToken);
|
|
|
|
expect(InputCopyToggleVisibilityComponent.props('copyButtonTitle')).toBe(
|
|
|
|
sprintf(__('Copy %{accessTokenType}'), { accessTokenType }),
|
|
|
|
);
|
|
|
|
expect(InputCopyToggleVisibilityComponent.props('initialVisibility')).toBe(true);
|
|
|
|
expect(InputCopyToggleVisibilityComponent.attributes('label')).toBe(
|
|
|
|
sprintf(__('Your new %{accessTokenType}'), { accessTokenType }),
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
it('input field should contain QA-related selectors', async () => {
|
|
|
|
const newToken = '12345';
|
|
|
|
await triggerSuccess(newToken);
|
|
|
|
|
|
|
|
expect(wrapper.findComponent(GlAlert).exists()).toBe(false);
|
|
|
|
|
|
|
|
const inputAttributes = wrapper
|
|
|
|
.findByLabelText(sprintf(__('Your new %{accessTokenType}'), { accessTokenType }))
|
|
|
|
.attributes();
|
|
|
|
expect(inputAttributes).toMatchObject({
|
|
|
|
class: expect.stringContaining('qa-created-access-token'),
|
|
|
|
'data-qa-selector': 'created_access_token_field',
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2022-05-23 09:08:01 +00:00
|
|
|
it('should render an info alert', async () => {
|
|
|
|
await triggerSuccess();
|
|
|
|
|
|
|
|
expect(createAlert).toHaveBeenCalledWith({
|
|
|
|
message: sprintf(__('Your new %{accessTokenType} has been created.'), {
|
|
|
|
accessTokenType,
|
|
|
|
}),
|
|
|
|
variant: VARIANT_INFO,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should reset the form', async () => {
|
|
|
|
const resetSpy = jest.spyOn(wrapper.vm.form, 'reset');
|
|
|
|
|
|
|
|
await triggerSuccess();
|
|
|
|
|
|
|
|
expect(resetSpy).toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('on error', () => {
|
|
|
|
it('should render an error alert', async () => {
|
|
|
|
await triggerError(['first', 'second']);
|
|
|
|
|
|
|
|
expect(wrapper.findComponent(InputCopyToggleVisibility).exists()).toBe(false);
|
|
|
|
|
|
|
|
let GlAlertComponent = wrapper.findComponent(GlAlert);
|
|
|
|
expect(GlAlertComponent.props('title')).toBe(__('The form contains the following errors:'));
|
|
|
|
expect(GlAlertComponent.props('variant')).toBe('danger');
|
|
|
|
let itemEls = wrapper.findAll('li');
|
|
|
|
expect(itemEls).toHaveLength(2);
|
|
|
|
expect(itemEls.at(0).text()).toBe('first');
|
|
|
|
expect(itemEls.at(1).text()).toBe('second');
|
|
|
|
|
|
|
|
await triggerError(['one']);
|
|
|
|
|
|
|
|
GlAlertComponent = wrapper.findComponent(GlAlert);
|
|
|
|
expect(GlAlertComponent.props('title')).toBe(__('The form contains the following error:'));
|
|
|
|
expect(GlAlertComponent.props('variant')).toBe('danger');
|
|
|
|
itemEls = wrapper.findAll('li');
|
|
|
|
expect(itemEls).toHaveLength(1);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('the error alert should be dismissible', async () => {
|
|
|
|
await triggerError();
|
|
|
|
|
|
|
|
const GlAlertComponent = wrapper.findComponent(GlAlert);
|
|
|
|
expect(GlAlertComponent.exists()).toBe(true);
|
|
|
|
|
|
|
|
GlAlertComponent.vm.$emit('dismiss');
|
|
|
|
await nextTick();
|
|
|
|
|
|
|
|
expect(wrapper.findComponent(GlAlert).exists()).toBe(false);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('before error or success', () => {
|
|
|
|
it('should scroll to the container', async () => {
|
|
|
|
const containerEl = wrapper.vm.$refs.container;
|
|
|
|
const scrollIntoViewSpy = jest.spyOn(containerEl, 'scrollIntoView');
|
|
|
|
|
|
|
|
await triggerSuccess();
|
|
|
|
|
|
|
|
expect(scrollIntoViewSpy).toHaveBeenCalledWith(false);
|
|
|
|
expect(scrollIntoViewSpy).toHaveBeenCalledTimes(1);
|
|
|
|
|
|
|
|
await triggerError();
|
|
|
|
|
|
|
|
expect(scrollIntoViewSpy).toHaveBeenCalledWith(false);
|
|
|
|
expect(scrollIntoViewSpy).toHaveBeenCalledTimes(2);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should dismiss the info alert', async () => {
|
|
|
|
const dismissSpy = jest.fn();
|
|
|
|
createAlert.mockReturnValue({ dismiss: dismissSpy });
|
|
|
|
|
|
|
|
await triggerSuccess();
|
|
|
|
await triggerError();
|
|
|
|
|
|
|
|
expect(dismissSpy).toHaveBeenCalled();
|
|
|
|
expect(dismissSpy).toHaveBeenCalledTimes(1);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|