diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-12-23 00:08:40 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-12-23 00:08:40 +0300 |
commit | 5f66b796766f79f48b5c53a38aa9bfb7f951143b (patch) | |
tree | 21c8329f92fed0463f6fd33f2ff512ab7e446f56 /spec/frontend/environments | |
parent | b486760a6332905cd2ac94b3fade5cbc6a55d21e (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend/environments')
7 files changed, 422 insertions, 50 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 } }); + }); + }); +}); diff --git a/spec/frontend/environments/environment_details_page_spec.js b/spec/frontend/environments/environment_details_page_spec.js deleted file mode 100644 index 5a02b34250f..00000000000 --- a/spec/frontend/environments/environment_details_page_spec.js +++ /dev/null @@ -1,50 +0,0 @@ -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 { mountExtended } from 'helpers/vue_test_utils_helper'; -import createMockApollo from '../__helpers__/mock_apollo_helper'; -import waitForPromises from '../__helpers__/wait_for_promises'; -import EnvironmentsDetailPage from '../../../app/assets/javascripts/environments/environment_details/index.vue'; -import getEnvironmentDetails from '../../../app/assets/javascripts/environments/graphql/queries/environment_details.query.graphql'; - -describe('~/environments/environment_details/page.vue', () => { - Vue.use(VueApollo); - - let wrapper; - - const createWrapper = () => { - const mockApollo = createMockApollo([ - [getEnvironmentDetails, jest.fn().mockResolvedValue(resolvedEnvironmentDetails)], - ]); - - return mountExtended(EnvironmentsDetailPage, { - apolloProvider: mockApollo, - propsData: { - projectFullPath: resolvedEnvironmentDetails.data.project.fullPath, - environmentName: resolvedEnvironmentDetails.data.project.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', () => { - 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); - }); - }); -}); |