Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/environments/environment_details')
-rw-r--r--spec/frontend/environments/environment_details/deployment_job_spec.js49
-rw-r--r--spec/frontend/environments/environment_details/deployment_status_link_spec.js57
-rw-r--r--spec/frontend/environments/environment_details/deployment_triggerer_spec.js51
-rw-r--r--spec/frontend/environments/environment_details/empty_state_spec.js39
-rw-r--r--spec/frontend/environments/environment_details/page_spec.js69
-rw-r--r--spec/frontend/environments/environment_details/pagination_spec.js157
6 files changed, 422 insertions, 0 deletions
diff --git a/spec/frontend/environments/environment_details/deployment_job_spec.js b/spec/frontend/environments/environment_details/deployment_job_spec.js
new file mode 100644
index 00000000000..9bb61abb293
--- /dev/null
+++ b/spec/frontend/environments/environment_details/deployment_job_spec.js
@@ -0,0 +1,49 @@
+import { GlTruncate, GlLink, GlBadge } from '@gitlab/ui';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import DeploymentJob from '~/environments/environment_details/components/deployment_job.vue';
+
+describe('app/assets/javascripts/environments/environment_details/components/deployment_job.vue', () => {
+ const jobData = {
+ webPath: 'http://example.com',
+ label: 'example job',
+ };
+ let wrapper;
+
+ const createWrapper = ({ job }) => {
+ return mountExtended(DeploymentJob, {
+ propsData: {
+ job,
+ },
+ });
+ };
+
+ describe('when the job data exists', () => {
+ beforeEach(() => {
+ wrapper = createWrapper({ job: jobData });
+ });
+
+ it('should render a link with a correct href', () => {
+ const jobLink = wrapper.findComponent(GlLink);
+ expect(jobLink.exists()).toBe(true);
+ expect(jobLink.attributes().href).toBe(jobData.webPath);
+ });
+ it('should render a truncated label', () => {
+ const truncatedLabel = wrapper.findComponent(GlTruncate);
+ expect(truncatedLabel.exists()).toBe(true);
+ expect(truncatedLabel.props().text).toBe(jobData.label);
+ });
+ });
+
+ describe('when the job data does not exist', () => {
+ beforeEach(() => {
+ wrapper = createWrapper({ job: null });
+ });
+
+ it('should render a badge with the text "API"', () => {
+ const badge = wrapper.findComponent(GlBadge);
+ expect(badge.exists()).toBe(true);
+ expect(badge.props().variant).toBe('info');
+ expect(badge.text()).toBe('API');
+ });
+ });
+});
diff --git a/spec/frontend/environments/environment_details/deployment_status_link_spec.js b/spec/frontend/environments/environment_details/deployment_status_link_spec.js
new file mode 100644
index 00000000000..5db7740423a
--- /dev/null
+++ b/spec/frontend/environments/environment_details/deployment_status_link_spec.js
@@ -0,0 +1,57 @@
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import DeploymentStatusLink from '~/environments/environment_details/components/deployment_status_link.vue';
+import DeploymentStatusBadge from '~/environments/components/deployment_status_badge.vue';
+
+describe('app/assets/javascripts/environments/environment_details/components/deployment_status_link.vue', () => {
+ const testData = {
+ webPath: 'http://example.com',
+ status: 'success',
+ };
+ let wrapper;
+
+ const createWrapper = (props) => {
+ return mountExtended(DeploymentStatusLink, {
+ propsData: props,
+ });
+ };
+
+ describe('when the job link exists', () => {
+ beforeEach(() => {
+ wrapper = createWrapper({
+ deploymentJob: { webPath: testData.webPath },
+ status: testData.status,
+ });
+ });
+
+ it('should render a link with a correct href', () => {
+ const jobLink = wrapper.findByTestId('deployment-status-job-link');
+ expect(jobLink.exists()).toBe(true);
+ expect(jobLink.attributes().href).toBe(testData.webPath);
+ });
+
+ it('should render a status badge', () => {
+ const statusBadge = wrapper.findComponent(DeploymentStatusBadge);
+ expect(statusBadge.exists()).toBe(true);
+ expect(statusBadge.props().status).toBe(testData.status);
+ });
+ });
+
+ describe('when no deployment job is provided', () => {
+ beforeEach(() => {
+ wrapper = createWrapper({
+ status: testData.status,
+ });
+ });
+
+ it('should render a link with a correct href', () => {
+ const jobLink = wrapper.findByTestId('deployment-status-job-link');
+ expect(jobLink.exists()).toBe(false);
+ });
+
+ it('should render only a status badge', () => {
+ const statusBadge = wrapper.findComponent(DeploymentStatusBadge);
+ expect(statusBadge.exists()).toBe(true);
+ expect(statusBadge.props().status).toBe(testData.status);
+ });
+ });
+});
diff --git a/spec/frontend/environments/environment_details/deployment_triggerer_spec.js b/spec/frontend/environments/environment_details/deployment_triggerer_spec.js
new file mode 100644
index 00000000000..48af82661bf
--- /dev/null
+++ b/spec/frontend/environments/environment_details/deployment_triggerer_spec.js
@@ -0,0 +1,51 @@
+import { GlAvatar, GlAvatarLink } from '@gitlab/ui';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import DeploymentTriggerer from '~/environments/environment_details/components/deployment_triggerer.vue';
+
+describe('app/assets/javascripts/environments/environment_details/components/deployment_triggerer.vue', () => {
+ const triggererData = {
+ id: 'gid://gitlab/User/1',
+ webUrl: 'http://gdk.test:3000/root',
+ name: 'Administrator',
+ avatarUrl: 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ };
+ let wrapper;
+
+ const createWrapper = ({ triggerer }) => {
+ return mountExtended(DeploymentTriggerer, {
+ propsData: {
+ triggerer,
+ },
+ });
+ };
+
+ describe('when the triggerer data exists', () => {
+ beforeEach(() => {
+ wrapper = createWrapper({ triggerer: triggererData });
+ });
+
+ it('should render an avatar link with a correct href', () => {
+ const triggererAvatarLink = wrapper.findComponent(GlAvatarLink);
+ expect(triggererAvatarLink.exists()).toBe(true);
+ expect(triggererAvatarLink.attributes().href).toBe(triggererData.webUrl);
+ });
+
+ it('should render an avatar', () => {
+ const triggererAvatar = wrapper.findComponent(GlAvatar);
+ expect(triggererAvatar.exists()).toBe(true);
+ expect(triggererAvatar.attributes().title).toBe(triggererData.name);
+ expect(triggererAvatar.props().src).toBe(triggererData.avatarUrl);
+ });
+ });
+
+ describe('when the triggerer data does not exist', () => {
+ beforeEach(() => {
+ wrapper = createWrapper({ triggerer: null });
+ });
+
+ it('should render nothing', () => {
+ const avatarLink = wrapper.findComponent(GlAvatarLink);
+ expect(avatarLink.exists()).toBe(false);
+ });
+ });
+});
diff --git a/spec/frontend/environments/environment_details/empty_state_spec.js b/spec/frontend/environments/environment_details/empty_state_spec.js
new file mode 100644
index 00000000000..aaf597d68ed
--- /dev/null
+++ b/spec/frontend/environments/environment_details/empty_state_spec.js
@@ -0,0 +1,39 @@
+import { GlEmptyState } from '@gitlab/ui';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import EmptyState from '~/environments/environment_details/empty_state.vue';
+import {
+ translations,
+ environmentsHelpPagePath,
+ codeBlockPlaceholders,
+} from '~/environments/environment_details/constants';
+
+describe('~/environments/environment_details/empty_state.vue', () => {
+ let wrapper;
+
+ const createWrapper = () => {
+ return mountExtended(EmptyState);
+ };
+
+ describe('when Empty State is rendered for environment details page', () => {
+ beforeEach(() => {
+ wrapper = createWrapper();
+ });
+
+ it('should render the proper title', () => {
+ expect(wrapper.text()).toContain(translations.emptyStateTitle);
+ });
+
+ it('should render GlEmptyState component with correct props', () => {
+ const glEmptyStateComponent = wrapper.findComponent(GlEmptyState);
+ expect(glEmptyStateComponent.props().primaryButtonText).toBe(
+ translations.emptyStatePrimaryButton,
+ );
+ expect(glEmptyStateComponent.props().primaryButtonLink).toBe(environmentsHelpPagePath);
+ });
+
+ it('should render formatted description', () => {
+ expect(wrapper.text()).not.toContain(codeBlockPlaceholders.code[0]);
+ expect(wrapper.text()).not.toContain(codeBlockPlaceholders.code[1]);
+ });
+ });
+});
diff --git a/spec/frontend/environments/environment_details/page_spec.js b/spec/frontend/environments/environment_details/page_spec.js
new file mode 100644
index 00000000000..3a1a3238abe
--- /dev/null
+++ b/spec/frontend/environments/environment_details/page_spec.js
@@ -0,0 +1,69 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { GlLoadingIcon, GlTableLite } from '@gitlab/ui';
+import resolvedEnvironmentDetails from 'test_fixtures/graphql/environments/graphql/queries/environment_details.query.graphql.json';
+import emptyEnvironmentDetails from 'test_fixtures/graphql/environments/graphql/queries/environment_details.query.graphql.empty.json';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import EnvironmentsDetailPage from '~/environments/environment_details/index.vue';
+import EmptyState from '~/environments/environment_details/empty_state.vue';
+import getEnvironmentDetails from '~/environments/graphql/queries/environment_details.query.graphql';
+import createMockApollo from '../../__helpers__/mock_apollo_helper';
+import waitForPromises from '../../__helpers__/wait_for_promises';
+
+describe('~/environments/environment_details/page.vue', () => {
+ Vue.use(VueApollo);
+
+ let wrapper;
+
+ const defaultWrapperParameters = {
+ resolvedData: resolvedEnvironmentDetails,
+ };
+
+ const createWrapper = ({ resolvedData } = defaultWrapperParameters) => {
+ const mockApollo = createMockApollo([
+ [getEnvironmentDetails, jest.fn().mockResolvedValue(resolvedData)],
+ ]);
+
+ return mountExtended(EnvironmentsDetailPage, {
+ apolloProvider: mockApollo,
+ propsData: {
+ projectFullPath: 'gitlab-group/test-project',
+ environmentName: 'test-environment-name',
+ },
+ });
+ };
+
+ describe('when fetching data', () => {
+ it('should show a loading indicator', () => {
+ wrapper = createWrapper();
+
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlTableLite).exists()).not.toBe(true);
+ });
+ });
+
+ describe('when data is fetched', () => {
+ describe('and there are deployments', () => {
+ beforeEach(async () => {
+ wrapper = createWrapper();
+ await waitForPromises();
+ });
+ it('should render a table when query is loaded', async () => {
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).not.toBe(true);
+ expect(wrapper.findComponent(GlTableLite).exists()).toBe(true);
+ });
+ });
+
+ describe('and there are no deployments', () => {
+ beforeEach(async () => {
+ wrapper = createWrapper({ resolvedData: emptyEnvironmentDetails });
+ await waitForPromises();
+ });
+
+ it('should render empty state component', async () => {
+ expect(wrapper.findComponent(GlTableLite).exists()).toBe(false);
+ expect(wrapper.findComponent(EmptyState).exists()).toBe(true);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/environments/environment_details/pagination_spec.js b/spec/frontend/environments/environment_details/pagination_spec.js
new file mode 100644
index 00000000000..107f3c3dd5e
--- /dev/null
+++ b/spec/frontend/environments/environment_details/pagination_spec.js
@@ -0,0 +1,157 @@
+import { GlKeysetPagination } from '@gitlab/ui';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import Pagination from '~/environments/environment_details/pagination.vue';
+
+describe('~/environments/environment_details/pagniation.vue', () => {
+ const mockRouter = {
+ push: jest.fn(),
+ };
+
+ const pageInfo = {
+ startCursor: 'eyJpZCI6IjE2In0',
+ endCursor: 'eyJpZCI6IjIifQ',
+ hasNextPage: true,
+ hasPreviousPage: true,
+ };
+ let wrapper;
+
+ const createWrapper = (pageInfoProp) => {
+ return mountExtended(Pagination, {
+ propsData: {
+ pageInfo: pageInfoProp,
+ },
+ mocks: {
+ $router: mockRouter,
+ },
+ });
+ };
+
+ describe('when neither next nor previous page exists', () => {
+ beforeEach(() => {
+ const emptyPageInfo = { ...pageInfo, hasPreviousPage: false, hasNextPage: false };
+ wrapper = createWrapper(emptyPageInfo);
+ });
+
+ it('should not render pagination component', () => {
+ expect(wrapper.html()).toBe('');
+ });
+ });
+
+ describe('when Pagination is rendered for environment details page', () => {
+ beforeEach(() => {
+ wrapper = createWrapper(pageInfo);
+ });
+
+ it('should pass correct props to keyset pagination', () => {
+ const glPagination = wrapper.findComponent(GlKeysetPagination);
+ expect(glPagination.exists()).toBe(true);
+ expect(glPagination.props()).toEqual(expect.objectContaining(pageInfo));
+ });
+
+ describe.each([
+ {
+ testPageInfo: pageInfo,
+ expectedAfter: `after=${pageInfo.endCursor}`,
+ expectedBefore: `before=${pageInfo.startCursor}`,
+ },
+ {
+ testPageInfo: { ...pageInfo, hasNextPage: true, hasPreviousPage: false },
+ expectedAfter: `after=${pageInfo.endCursor}`,
+ expectedBefore: '',
+ },
+ {
+ testPageInfo: { ...pageInfo, hasNextPage: false, hasPreviousPage: true },
+ expectedAfter: '',
+ expectedBefore: `before=${pageInfo.startCursor}`,
+ },
+ ])(
+ 'button links generation for $testPageInfo',
+ ({ testPageInfo, expectedAfter, expectedBefore }) => {
+ beforeEach(() => {
+ wrapper = createWrapper(testPageInfo);
+ });
+
+ it(`should have button links defined as ${expectedAfter || 'empty'} and
+ ${expectedBefore || 'empty'}`, () => {
+ const glPagination = wrapper.findComponent(GlKeysetPagination);
+ expect(glPagination.props().prevButtonLink).toContain(expectedBefore);
+ expect(glPagination.props().nextButtonLink).toContain(expectedAfter);
+ });
+ },
+ );
+
+ describe.each([
+ {
+ clickEvent: {
+ shiftKey: false,
+ ctrlKey: false,
+ altKey: false,
+ metaKey: false,
+ },
+ isDefaultPrevented: true,
+ },
+ {
+ clickEvent: {
+ shiftKey: true,
+ ctrlKey: false,
+ altKey: false,
+ metaKey: false,
+ },
+ isDefaultPrevented: false,
+ },
+ {
+ clickEvent: {
+ shiftKey: false,
+ ctrlKey: true,
+ altKey: false,
+ metaKey: false,
+ },
+ isDefaultPrevented: false,
+ },
+ {
+ clickEvent: {
+ shiftKey: false,
+ ctrlKey: false,
+ altKey: true,
+ metaKey: false,
+ },
+ isDefaultPrevented: false,
+ },
+ {
+ clickEvent: {
+ shiftKey: false,
+ ctrlKey: false,
+ altKey: false,
+ metaKey: true,
+ },
+ isDefaultPrevented: false,
+ },
+ ])(
+ 'when a pagination button is clicked with $clickEvent',
+ ({ clickEvent, isDefaultPrevented }) => {
+ let clickEventMock;
+ beforeEach(() => {
+ clickEventMock = { ...clickEvent, preventDefault: jest.fn() };
+ });
+
+ it(`should ${isDefaultPrevented ? '' : 'not '}prevent default event`, () => {
+ const pagination = wrapper.findComponent(GlKeysetPagination);
+ pagination.vm.$emit('click', clickEventMock);
+ expect(clickEventMock.preventDefault).toHaveBeenCalledTimes(isDefaultPrevented ? 1 : 0);
+ });
+ },
+ );
+
+ it('should navigate to a correct previous page', () => {
+ const pagination = wrapper.findComponent(GlKeysetPagination);
+ pagination.vm.$emit('prev', pageInfo.startCursor);
+ expect(mockRouter.push).toHaveBeenCalledWith({ query: { before: pageInfo.startCursor } });
+ });
+
+ it('should navigate to a correct next page', () => {
+ const pagination = wrapper.findComponent(GlKeysetPagination);
+ pagination.vm.$emit('next', pageInfo.endCursor);
+ expect(mockRouter.push).toHaveBeenCalledWith({ query: { after: pageInfo.endCursor } });
+ });
+ });
+});