debian-mirror-gitlab/spec/frontend/environments/environments_app_spec.js

430 lines
13 KiB
JavaScript
Raw Normal View History

2022-05-07 20:08:51 +05:30
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import { GlPagination } from '@gitlab/ui';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import setWindowLocation from 'helpers/set_window_location_helper';
import { sprintf, __, s__ } from '~/locale';
2020-04-08 14:13:33 +05:30
import EnvironmentsApp from '~/environments/components/environments_app.vue';
2022-05-07 20:08:51 +05:30
import EnvironmentsFolder from '~/environments/components/environment_folder.vue';
import EnvironmentsItem from '~/environments/components/new_environment_item.vue';
import EmptyState from '~/environments/components/empty_state.vue';
import StopEnvironmentModal from '~/environments/components/stop_environment_modal.vue';
import CanaryUpdateModal from '~/environments/components/canary_update_modal.vue';
import { resolvedEnvironmentsApp, resolvedFolder, resolvedEnvironment } from './graphql/mock_data';
2020-04-08 14:13:33 +05:30
2022-05-07 20:08:51 +05:30
Vue.use(VueApollo);
2020-04-08 14:13:33 +05:30
2022-05-07 20:08:51 +05:30
describe('~/environments/components/environments_app.vue', () => {
let wrapper;
let environmentAppMock;
let environmentFolderMock;
let paginationMock;
let environmentToStopMock;
let environmentToChangeCanaryMock;
let weightMock;
const createApolloProvider = () => {
const mockResolvers = {
Query: {
environmentApp: environmentAppMock,
folder: environmentFolderMock,
pageInfo: paginationMock,
environmentToStop: environmentToStopMock,
environmentToDelete: jest.fn().mockResolvedValue(resolvedEnvironment),
environmentToRollback: jest.fn().mockResolvedValue(resolvedEnvironment),
environmentToChangeCanary: environmentToChangeCanaryMock,
weight: weightMock,
},
};
return createMockApollo([], mockResolvers);
2020-04-08 14:13:33 +05:30
};
2022-05-07 20:08:51 +05:30
const createWrapper = ({ provide = {}, apolloProvider } = {}) =>
mountExtended(EnvironmentsApp, {
provide: {
newEnvironmentPath: '/environments/new',
canCreateEnvironment: true,
defaultBranchName: 'main',
helpPagePath: '/help',
projectId: '1',
2022-10-11 01:57:18 +05:30
projectPath: '/1',
2022-05-07 20:08:51 +05:30
...provide,
},
apolloProvider,
2020-04-08 14:13:33 +05:30
});
2022-05-07 20:08:51 +05:30
const createWrapperWithMocked = async ({
provide = {},
environmentsApp,
folder,
environmentToStop = {},
environmentToChangeCanary = {},
weight = 0,
pageInfo = {
total: 20,
perPage: 5,
nextPage: 3,
page: 2,
previousPage: 1,
__typename: 'LocalPageInfo',
},
2022-11-25 23:54:43 +05:30
location = '?scope=available&page=2&search=prod',
2022-05-07 20:08:51 +05:30
}) => {
setWindowLocation(location);
environmentAppMock.mockReturnValue(environmentsApp);
environmentFolderMock.mockReturnValue(folder);
paginationMock.mockReturnValue(pageInfo);
environmentToStopMock.mockReturnValue(environmentToStop);
environmentToChangeCanaryMock.mockReturnValue(environmentToChangeCanary);
weightMock.mockReturnValue(weight);
const apolloProvider = createApolloProvider();
wrapper = createWrapper({ apolloProvider, provide });
await waitForPromises();
await nextTick();
2020-04-08 14:13:33 +05:30
};
beforeEach(() => {
2022-05-07 20:08:51 +05:30
environmentAppMock = jest.fn();
environmentFolderMock = jest.fn();
environmentToStopMock = jest.fn();
environmentToChangeCanaryMock = jest.fn();
weightMock = jest.fn();
paginationMock = jest.fn();
2020-04-08 14:13:33 +05:30
});
2022-05-07 20:08:51 +05:30
it('should request available environments if the scope is invalid', async () => {
await createWrapperWithMocked({
environmentsApp: resolvedEnvironmentsApp,
folder: resolvedFolder,
2022-11-25 23:54:43 +05:30
location: '?scope=bad&page=2&search=prod',
2022-05-07 20:08:51 +05:30
});
2020-04-08 14:13:33 +05:30
2022-05-07 20:08:51 +05:30
expect(environmentAppMock).toHaveBeenCalledWith(
expect.anything(),
expect.objectContaining({ scope: 'available', page: 2 }),
expect.anything(),
expect.anything(),
);
});
it('should show all the folders that are fetched', async () => {
await createWrapperWithMocked({
environmentsApp: resolvedEnvironmentsApp,
folder: resolvedFolder,
2020-04-08 14:13:33 +05:30
});
2022-05-07 20:08:51 +05:30
const text = wrapper.findAllComponents(EnvironmentsFolder).wrappers.map((w) => w.text());
2020-04-08 14:13:33 +05:30
2022-05-07 20:08:51 +05:30
expect(text).toContainEqual(expect.stringMatching('review'));
expect(text).not.toContainEqual(expect.stringMatching('production'));
});
2020-04-08 14:13:33 +05:30
2022-05-07 20:08:51 +05:30
it('should show all the environments that are fetched', async () => {
await createWrapperWithMocked({
environmentsApp: resolvedEnvironmentsApp,
folder: resolvedFolder,
});
2020-04-08 14:13:33 +05:30
2022-05-07 20:08:51 +05:30
const text = wrapper.findAllComponents(EnvironmentsItem).wrappers.map((w) => w.text());
2020-04-08 14:13:33 +05:30
2022-05-07 20:08:51 +05:30
expect(text).not.toContainEqual(expect.stringMatching('review'));
expect(text).toContainEqual(expect.stringMatching('production'));
});
2021-03-08 18:12:59 +05:30
2022-05-07 20:08:51 +05:30
it('should show an empty state with no environments', async () => {
await createWrapperWithMocked({
environmentsApp: { ...resolvedEnvironmentsApp, environments: [] },
2020-04-08 14:13:33 +05:30
});
2022-05-07 20:08:51 +05:30
expect(wrapper.findComponent(EmptyState).exists()).toBe(true);
2020-04-08 14:13:33 +05:30
});
2022-05-07 20:08:51 +05:30
it('should show a button to create a new environment', async () => {
await createWrapperWithMocked({
environmentsApp: resolvedEnvironmentsApp,
folder: resolvedFolder,
2020-04-08 14:13:33 +05:30
});
2022-05-07 20:08:51 +05:30
const button = wrapper.findByRole('link', { name: s__('Environments|New environment') });
expect(button.attributes('href')).toBe('/environments/new');
2020-04-08 14:13:33 +05:30
});
2022-05-07 20:08:51 +05:30
it('should not show a button to create a new environment if the user has no permissions', async () => {
await createWrapperWithMocked({
environmentsApp: resolvedEnvironmentsApp,
folder: resolvedFolder,
provide: { canCreateEnvironment: false, newEnvironmentPath: '' },
});
2020-04-08 14:13:33 +05:30
2022-05-07 20:08:51 +05:30
const button = wrapper.findByRole('link', { name: s__('Environments|New environment') });
expect(button.exists()).toBe(false);
});
2020-04-08 14:13:33 +05:30
2022-05-07 20:08:51 +05:30
it('should show a button to open the review app modal', async () => {
await createWrapperWithMocked({
environmentsApp: resolvedEnvironmentsApp,
folder: resolvedFolder,
2020-04-08 14:13:33 +05:30
});
2022-05-07 20:08:51 +05:30
const button = wrapper.findByRole('button', { name: s__('Environments|Enable review app') });
button.trigger('click');
2020-04-08 14:13:33 +05:30
2022-05-07 20:08:51 +05:30
await nextTick();
2020-04-08 14:13:33 +05:30
2022-05-07 20:08:51 +05:30
expect(wrapper.findByText(s__('ReviewApp|Enable Review App')).exists()).toBe(true);
});
2020-04-08 14:13:33 +05:30
2022-05-07 20:08:51 +05:30
it('should not show a button to open the review app modal if review apps are configured', async () => {
await createWrapperWithMocked({
environmentsApp: {
...resolvedEnvironmentsApp,
reviewApp: { canSetupReviewApp: false },
},
folder: resolvedFolder,
2020-04-08 14:13:33 +05:30
});
2022-05-07 20:08:51 +05:30
const button = wrapper.findByRole('button', { name: s__('Environments|Enable review app') });
expect(button.exists()).toBe(false);
2020-04-08 14:13:33 +05:30
});
2021-01-03 14:25:43 +05:30
2023-04-23 21:23:45 +05:30
it('should not show a button to clean up environments if the user has no permissions', async () => {
await createWrapperWithMocked({
environmentsApp: {
...resolvedEnvironmentsApp,
canStopStaleEnvironments: false,
},
folder: resolvedFolder,
});
const button = wrapper.findByRole('button', {
name: s__('Environments|Clean up environments'),
});
expect(button.exists()).toBe(false);
});
it('should show a button to clean up environments if the user has permissions', async () => {
await createWrapperWithMocked({
environmentsApp: {
...resolvedEnvironmentsApp,
canStopStaleEnvironments: true,
},
folder: resolvedFolder,
});
const button = wrapper.findByRole('button', {
name: s__('Environments|Clean up environments'),
});
expect(button.exists()).toBe(true);
});
2022-05-07 20:08:51 +05:30
describe('tabs', () => {
it('should show tabs for available and stopped environmets', async () => {
await createWrapperWithMocked({
environmentsApp: resolvedEnvironmentsApp,
folder: resolvedFolder,
2021-01-03 14:25:43 +05:30
});
2022-05-07 20:08:51 +05:30
const [available, stopped] = wrapper.findAllByRole('tab').wrappers;
expect(available.text()).toContain(__('Available'));
2022-08-13 15:12:31 +05:30
expect(available.text()).toContain(resolvedEnvironmentsApp.availableCount.toString());
2022-05-07 20:08:51 +05:30
expect(stopped.text()).toContain(__('Stopped'));
2022-08-13 15:12:31 +05:30
expect(stopped.text()).toContain(resolvedEnvironmentsApp.stoppedCount.toString());
2022-05-07 20:08:51 +05:30
});
it('should change the requested scope on tab change', async () => {
await createWrapperWithMocked({
environmentsApp: resolvedEnvironmentsApp,
folder: resolvedFolder,
});
const stopped = wrapper.findByRole('tab', {
name: `${__('Stopped')} ${resolvedEnvironmentsApp.stoppedCount}`,
2021-01-03 14:25:43 +05:30
});
2022-05-07 20:08:51 +05:30
stopped.trigger('click');
await nextTick();
await waitForPromises();
expect(environmentAppMock).toHaveBeenCalledWith(
expect.anything(),
expect.objectContaining({ scope: 'stopped', page: 1 }),
expect.anything(),
expect.anything(),
);
2021-01-03 14:25:43 +05:30
});
2022-05-07 20:08:51 +05:30
});
2021-01-03 14:25:43 +05:30
2022-05-07 20:08:51 +05:30
describe('modals', () => {
it('should pass the environment to stop to the stop environment modal', async () => {
await createWrapperWithMocked({
environmentsApp: resolvedEnvironmentsApp,
folder: resolvedFolder,
environmentToStop: resolvedEnvironment,
2021-01-03 14:25:43 +05:30
});
2022-05-07 20:08:51 +05:30
const modal = wrapper.findComponent(StopEnvironmentModal);
expect(modal.props('environment')).toMatchObject(resolvedEnvironment);
});
it('should pass the environment to change canary to the canary update modal', async () => {
await createWrapperWithMocked({
environmentsApp: resolvedEnvironmentsApp,
folder: resolvedFolder,
environmentToChangeCanary: resolvedEnvironment,
weight: 10,
2021-01-03 14:25:43 +05:30
});
2022-05-07 20:08:51 +05:30
const modal = wrapper.findComponent(CanaryUpdateModal);
expect(modal.props('environment')).toMatchObject(resolvedEnvironment);
2021-01-03 14:25:43 +05:30
});
});
2022-05-07 20:08:51 +05:30
describe('pagination', () => {
it('should sync page from query params on load', async () => {
await createWrapperWithMocked({
environmentsApp: resolvedEnvironmentsApp,
folder: resolvedFolder,
2021-01-03 14:25:43 +05:30
});
2022-05-07 20:08:51 +05:30
expect(wrapper.findComponent(GlPagination).props('value')).toBe(2);
});
2021-01-03 14:25:43 +05:30
2022-05-07 20:08:51 +05:30
it('should change the requested page on next page click', async () => {
await createWrapperWithMocked({
environmentsApp: resolvedEnvironmentsApp,
folder: resolvedFolder,
});
const next = wrapper.findByRole('link', {
name: __('Go to next page'),
2021-01-03 14:25:43 +05:30
});
2022-05-07 20:08:51 +05:30
next.trigger('click');
await nextTick();
await waitForPromises();
expect(environmentAppMock).toHaveBeenCalledWith(
expect.anything(),
expect.objectContaining({ page: 3 }),
expect.anything(),
expect.anything(),
);
2021-01-03 14:25:43 +05:30
});
2022-05-07 20:08:51 +05:30
it('should change the requested page on previous page click', async () => {
await createWrapperWithMocked({
environmentsApp: resolvedEnvironmentsApp,
folder: resolvedFolder,
});
const prev = wrapper.findByRole('link', {
name: __('Go to previous page'),
2021-01-03 14:25:43 +05:30
});
2022-05-07 20:08:51 +05:30
prev.trigger('click');
await nextTick();
await waitForPromises();
expect(environmentAppMock).toHaveBeenCalledWith(
expect.anything(),
expect.objectContaining({ page: 1 }),
expect.anything(),
expect.anything(),
);
});
it('should change the requested page on specific page click', async () => {
await createWrapperWithMocked({
environmentsApp: resolvedEnvironmentsApp,
folder: resolvedFolder,
2021-01-03 14:25:43 +05:30
});
2022-05-07 20:08:51 +05:30
const page = 1;
const pageButton = wrapper.findByRole('link', {
name: sprintf(__('Go to page %{page}'), { page }),
2021-01-03 14:25:43 +05:30
});
2021-09-30 23:02:18 +05:30
2022-05-07 20:08:51 +05:30
pageButton.trigger('click');
await nextTick();
await waitForPromises();
expect(environmentAppMock).toHaveBeenCalledWith(
expect.anything(),
expect.objectContaining({ page }),
expect.anything(),
expect.anything(),
);
2021-09-30 23:02:18 +05:30
});
2022-05-07 20:08:51 +05:30
it('should sync the query params to the new page', async () => {
await createWrapperWithMocked({
environmentsApp: resolvedEnvironmentsApp,
folder: resolvedFolder,
});
const next = wrapper.findByRole('link', {
name: __('Go to next page'),
});
next.trigger('click');
await nextTick();
2022-11-25 23:54:43 +05:30
expect(window.location.search).toBe('?scope=available&page=3&search=prod');
});
});
describe('search', () => {
let searchBox;
const waitForDebounce = async () => {
await nextTick();
jest.runOnlyPendingTimers();
};
beforeEach(async () => {
await createWrapperWithMocked({
environmentsApp: resolvedEnvironmentsApp,
folder: resolvedFolder,
});
searchBox = wrapper.findByRole('searchbox', {
name: s__('Environments|Search by environment name'),
});
});
it('should sync the query params to the new search', async () => {
searchBox.setValue('hello');
await waitForDebounce();
expect(window.location.search).toBe('?scope=available&page=1&search=hello');
});
it('should query for the entered parameter', async () => {
const search = 'hello';
searchBox.setValue(search);
await waitForDebounce();
await waitForPromises();
expect(environmentAppMock).toHaveBeenCalledWith(
expect.anything(),
expect.objectContaining({ search }),
expect.anything(),
expect.anything(),
);
});
2023-06-20 00:43:36 +05:30
it('should sync search term from query params on load', () => {
2022-11-25 23:54:43 +05:30
expect(searchBox.element.value).toBe('prod');
2021-09-30 23:02:18 +05:30
});
});
2020-04-08 14:13:33 +05:30
});