debian-mirror-gitlab/spec/frontend/releases/components/app_edit_new_spec.js

266 lines
7.5 KiB
JavaScript
Raw Normal View History

2019-12-21 20:55:43 +05:30
import { mount } from '@vue/test-utils';
2020-10-24 23:57:45 +05:30
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
2021-03-11 19:13:27 +05:30
import { merge } from 'lodash';
import Vuex from 'vuex';
2021-01-03 14:25:43 +05:30
import { getJSONFixture } from 'helpers/fixtures';
2021-10-27 15:23:28 +05:30
import setWindowLocation from 'helpers/set_window_location_helper';
2021-07-02 01:05:55 +05:30
import { TEST_HOST } from 'helpers/test_constants';
2020-04-08 14:13:33 +05:30
import * as commonUtils from '~/lib/utils/common_utils';
2021-03-11 19:13:27 +05:30
import ReleaseEditNewApp from '~/releases/components/app_edit_new.vue';
2020-04-22 19:07:51 +05:30
import AssetLinksForm from '~/releases/components/asset_links_form.vue';
2021-03-11 19:13:27 +05:30
import { BACK_URL_PARAM } from '~/releases/constants';
2019-12-21 20:55:43 +05:30
2021-01-03 14:25:43 +05:30
const originalRelease = getJSONFixture('api/releases/release.json');
const originalMilestones = originalRelease.milestones;
2021-07-02 01:05:55 +05:30
const releasesPagePath = 'path/to/releases/page';
2021-01-03 14:25:43 +05:30
2020-10-24 23:57:45 +05:30
describe('Release edit/new component', () => {
2019-12-21 20:55:43 +05:30
let wrapper;
2020-04-08 14:13:33 +05:30
let release;
2019-12-21 20:55:43 +05:30
let actions;
2020-04-22 19:07:51 +05:30
let getters;
2019-12-26 22:10:19 +05:30
let state;
2020-05-24 23:13:21 +05:30
let mock;
2019-12-21 20:55:43 +05:30
2021-01-03 14:25:43 +05:30
const factory = async ({ featureFlags = {}, store: storeUpdates = {} } = {}) => {
2019-12-26 22:10:19 +05:30
state = {
2020-04-08 14:13:33 +05:30
release,
2019-12-21 20:55:43 +05:30
markdownDocsPath: 'path/to/markdown/docs',
2021-07-02 01:05:55 +05:30
releasesPagePath,
2020-05-24 23:13:21 +05:30
projectId: '8',
2021-01-29 00:20:46 +05:30
groupId: '42',
groupMilestonesAvailable: true,
2019-12-21 20:55:43 +05:30
};
actions = {
2020-10-24 23:57:45 +05:30
initializeRelease: jest.fn(),
saveRelease: jest.fn(),
2020-04-22 19:07:51 +05:30
addEmptyAssetLink: jest.fn(),
2019-12-21 20:55:43 +05:30
};
2020-04-22 19:07:51 +05:30
getters = {
isValid: () => true,
2020-10-24 23:57:45 +05:30
isExistingRelease: () => true,
2020-04-22 19:07:51 +05:30
validationErrors: () => ({
assets: {
links: [],
2020-03-13 15:44:24 +05:30
},
2020-04-22 19:07:51 +05:30
}),
};
const store = new Vuex.Store(
merge(
{
modules: {
2021-04-29 21:17:54 +05:30
editNew: {
2020-04-22 19:07:51 +05:30
namespaced: true,
actions,
state,
getters,
},
},
},
storeUpdates,
),
);
2020-03-13 15:44:24 +05:30
2020-10-24 23:57:45 +05:30
wrapper = mount(ReleaseEditNewApp, {
2020-03-13 15:44:24 +05:30
store,
2020-04-22 19:07:51 +05:30
provide: {
glFeatures: featureFlags,
},
2020-03-13 15:44:24 +05:30
});
2020-10-24 23:57:45 +05:30
2021-01-03 14:25:43 +05:30
await wrapper.vm.$nextTick();
2021-03-08 18:12:59 +05:30
wrapper.element.querySelectorAll('input').forEach((input) => jest.spyOn(input, 'focus'));
2020-04-08 14:13:33 +05:30
};
2019-12-21 20:55:43 +05:30
2020-04-08 14:13:33 +05:30
beforeEach(() => {
2021-10-27 15:23:28 +05:30
setWindowLocation(TEST_HOST);
2021-07-02 01:05:55 +05:30
2020-05-24 23:13:21 +05:30
mock = new MockAdapter(axios);
2020-04-08 14:13:33 +05:30
gon.api_version = 'v4';
2019-12-21 20:55:43 +05:30
2020-05-24 23:13:21 +05:30
mock.onGet('/api/v4/projects/8/milestones').reply(200, originalMilestones);
2020-04-08 14:13:33 +05:30
release = commonUtils.convertObjectPropsToCamelCase(originalRelease, { deep: true });
2019-12-21 20:55:43 +05:30
});
2020-04-08 14:13:33 +05:30
afterEach(() => {
wrapper.destroy();
wrapper = null;
2019-12-21 20:55:43 +05:30
});
2020-04-22 19:07:51 +05:30
const findSubmitButton = () => wrapper.find('button[type=submit]');
2020-10-24 23:57:45 +05:30
const findForm = () => wrapper.find('form');
2020-04-22 19:07:51 +05:30
2020-04-08 14:13:33 +05:30
describe(`basic functionality tests: all tests unrelated to the "${BACK_URL_PARAM}" parameter`, () => {
2021-01-03 14:25:43 +05:30
beforeEach(async () => {
await factory();
});
2020-10-24 23:57:45 +05:30
it('calls initializeRelease when the component is created', () => {
expect(actions.initializeRelease).toHaveBeenCalledTimes(1);
2020-04-08 14:13:33 +05:30
});
2019-12-21 20:55:43 +05:30
2020-10-24 23:57:45 +05:30
it('focuses the first non-disabled input element once the page is shown', () => {
const firstEnabledInput = wrapper.element.querySelector('input:enabled');
const allInputs = wrapper.element.querySelectorAll('input');
2021-03-08 18:12:59 +05:30
allInputs.forEach((input) => {
2020-10-24 23:57:45 +05:30
const expectedFocusCalls = input === firstEnabledInput ? 1 : 0;
expect(input.focus).toHaveBeenCalledTimes(expectedFocusCalls);
});
2020-04-08 14:13:33 +05:30
});
2019-12-26 22:10:19 +05:30
2020-04-08 14:13:33 +05:30
it('renders the description text at the top of the page', () => {
expect(wrapper.find('.js-subtitle-text').text()).toBe(
2021-04-29 21:17:54 +05:30
'Releases are based on Git tags. We recommend tags that use semantic versioning, for example v1.0.0, v2.1.0-pre.',
2020-04-08 14:13:33 +05:30
);
});
2019-12-21 20:55:43 +05:30
2020-04-08 14:13:33 +05:30
it('renders the correct release title in the "Release title" field', () => {
expect(wrapper.find('#release-title').element.value).toBe(release.name);
});
it('renders the release notes in the "Release notes" textarea', () => {
expect(wrapper.find('#release-notes').element.value).toBe(release.description);
});
it('renders the "Save changes" button as type="submit"', () => {
2020-04-22 19:07:51 +05:30
expect(findSubmitButton().attributes('type')).toBe('submit');
2020-04-08 14:13:33 +05:30
});
2019-12-21 20:55:43 +05:30
2020-10-24 23:57:45 +05:30
it('calls saveRelease when the form is submitted', () => {
findForm().trigger('submit');
expect(actions.saveRelease).toHaveBeenCalledTimes(1);
2020-04-08 14:13:33 +05:30
});
2019-12-21 20:55:43 +05:30
});
2020-04-08 14:13:33 +05:30
describe(`when the URL does not contain a "${BACK_URL_PARAM}" parameter`, () => {
2021-01-03 14:25:43 +05:30
beforeEach(async () => {
await factory();
});
2020-04-08 14:13:33 +05:30
it(`renders a "Cancel" button with an href pointing to "${BACK_URL_PARAM}"`, () => {
const cancelButton = wrapper.find('.js-cancel-button');
expect(cancelButton.attributes().href).toBe(state.releasesPagePath);
});
2019-12-21 20:55:43 +05:30
});
2021-07-02 01:05:55 +05:30
// eslint-disable-next-line no-script-url
const xssBackUrl = 'javascript:alert(1)';
describe.each`
backUrl | expectedHref
${`${TEST_HOST}/back/url`} | ${`${TEST_HOST}/back/url`}
${`/back/url?page=2`} | ${`/back/url?page=2`}
${`back/url?page=3`} | ${`back/url?page=3`}
${'http://phishing.test/back/url'} | ${releasesPagePath}
${'//phishing.test/back/url'} | ${releasesPagePath}
${xssBackUrl} | ${releasesPagePath}
`(
`when the URL contains a "${BACK_URL_PARAM}=$backUrl" parameter`,
({ backUrl, expectedHref }) => {
beforeEach(async () => {
2021-10-27 15:23:28 +05:30
setWindowLocation(`${TEST_HOST}?${BACK_URL_PARAM}=${encodeURIComponent(backUrl)}`);
2021-07-02 01:05:55 +05:30
await factory();
});
2020-04-08 14:13:33 +05:30
2021-07-02 01:05:55 +05:30
it(`renders a "Cancel" button with an href pointing to ${expectedHref}`, () => {
const cancelButton = wrapper.find('.js-cancel-button');
expect(cancelButton.attributes().href).toBe(expectedHref);
});
},
);
2020-04-22 19:07:51 +05:30
2020-10-24 23:57:45 +05:30
describe('when creating a new release', () => {
2021-01-03 14:25:43 +05:30
beforeEach(async () => {
await factory({
2020-10-24 23:57:45 +05:30
store: {
modules: {
2021-04-29 21:17:54 +05:30
editNew: {
2020-10-24 23:57:45 +05:30
getters: {
isExistingRelease: () => false,
},
},
},
},
});
});
it('renders the submit button with the text "Create release"', () => {
expect(findSubmitButton().text()).toBe('Create release');
});
});
describe('when editing an existing release', () => {
2021-01-03 14:25:43 +05:30
beforeEach(async () => {
await factory();
});
2020-10-24 23:57:45 +05:30
it('renders the submit button with the text "Save changes"', () => {
expect(findSubmitButton().text()).toBe('Save changes');
});
});
2020-04-22 19:07:51 +05:30
describe('asset links form', () => {
2021-01-03 14:25:43 +05:30
beforeEach(factory);
2020-04-22 19:07:51 +05:30
2021-01-03 14:25:43 +05:30
it('renders the asset links portion of the form', () => {
expect(wrapper.find(AssetLinksForm).exists()).toBe(true);
2020-04-22 19:07:51 +05:30
});
});
describe('validation', () => {
describe('when the form is valid', () => {
2021-01-03 14:25:43 +05:30
beforeEach(async () => {
await factory({
2020-04-22 19:07:51 +05:30
store: {
modules: {
2021-04-29 21:17:54 +05:30
editNew: {
2020-04-22 19:07:51 +05:30
getters: {
isValid: () => true,
},
},
},
},
});
});
it('renders the submit button as enabled', () => {
expect(findSubmitButton().attributes('disabled')).toBeUndefined();
});
});
describe('when the form is invalid', () => {
2021-01-03 14:25:43 +05:30
beforeEach(async () => {
await factory({
2020-04-22 19:07:51 +05:30
store: {
modules: {
2021-04-29 21:17:54 +05:30
editNew: {
2020-04-22 19:07:51 +05:30
getters: {
isValid: () => false,
},
},
},
},
});
});
it('renders the submit button as disabled', () => {
expect(findSubmitButton().attributes('disabled')).toBe('disabled');
});
2020-10-24 23:57:45 +05:30
it('does not allow the form to be submitted', () => {
findForm().trigger('submit');
expect(actions.saveRelease).not.toHaveBeenCalled();
});
2020-04-22 19:07:51 +05:30
});
});
2019-12-21 20:55:43 +05:30
});