diff options
Diffstat (limited to 'spec/frontend/clusters')
3 files changed, 332 insertions, 16 deletions
diff --git a/spec/frontend/clusters/agents/components/show_spec.js b/spec/frontend/clusters/agents/components/show_spec.js new file mode 100644 index 00000000000..fd04ff8b3e7 --- /dev/null +++ b/spec/frontend/clusters/agents/components/show_spec.js @@ -0,0 +1,195 @@ +import { GlAlert, GlKeysetPagination, GlLoadingIcon, GlSprintf, GlTab } from '@gitlab/ui'; +import { createLocalVue, shallowMount } from '@vue/test-utils'; +import VueApollo from 'vue-apollo'; +import ClusterAgentShow from '~/clusters/agents/components/show.vue'; +import TokenTable from '~/clusters/agents/components/token_table.vue'; +import getAgentQuery from '~/clusters/agents/graphql/queries/get_cluster_agent.query.graphql'; +import { useFakeDate } from 'helpers/fake_date'; +import createMockApollo from 'helpers/mock_apollo_helper'; +import waitForPromises from 'helpers/wait_for_promises'; +import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; + +const localVue = createLocalVue(); +localVue.use(VueApollo); + +describe('ClusterAgentShow', () => { + let wrapper; + useFakeDate([2021, 2, 15]); + + const propsData = { + agentName: 'cluster-agent', + projectPath: 'path/to/project', + }; + + const defaultClusterAgent = { + id: '1', + createdAt: '2021-02-13T00:00:00Z', + createdByUser: { + name: 'user-1', + }, + name: 'token-1', + tokens: { + count: 1, + nodes: [], + pageInfo: null, + }, + }; + + const createWrapper = ({ clusterAgent, queryResponse = null }) => { + const agentQueryResponse = + queryResponse || jest.fn().mockResolvedValue({ data: { project: { clusterAgent } } }); + const apolloProvider = createMockApollo([[getAgentQuery, agentQueryResponse]]); + + wrapper = shallowMount(ClusterAgentShow, { + localVue, + apolloProvider, + propsData, + stubs: { GlSprintf, TimeAgoTooltip, GlTab }, + }); + }; + + const createWrapperWithoutApollo = ({ clusterAgent, loading = false }) => { + const $apollo = { queries: { clusterAgent: { loading } } }; + + wrapper = shallowMount(ClusterAgentShow, { + propsData, + mocks: { $apollo, clusterAgent }, + stubs: { GlTab }, + }); + }; + + const findCreatedText = () => wrapper.find('[data-testid="cluster-agent-create-info"]').text(); + const findLoadingIcon = () => wrapper.find(GlLoadingIcon); + const findPaginationButtons = () => wrapper.find(GlKeysetPagination); + const findTokenCount = () => wrapper.find('[data-testid="cluster-agent-token-count"]').text(); + + afterEach(() => { + wrapper.destroy(); + }); + + describe('default behaviour', () => { + beforeEach(() => { + return createWrapper({ clusterAgent: defaultClusterAgent }); + }); + + it('displays the agent name', () => { + expect(wrapper.text()).toContain(propsData.agentName); + }); + + it('displays agent create information', () => { + expect(findCreatedText()).toMatchInterpolatedText('Created by user-1 2 days ago'); + }); + + it('displays token count', () => { + expect(findTokenCount()).toMatchInterpolatedText( + `${ClusterAgentShow.i18n.tokens} ${defaultClusterAgent.tokens.count}`, + ); + }); + + it('renders token table', () => { + expect(wrapper.find(TokenTable).exists()).toBe(true); + }); + + it('should not render pagination buttons when there are no additional pages', () => { + expect(findPaginationButtons().exists()).toBe(false); + }); + }); + + describe('when create user is unknown', () => { + const missingUser = { + ...defaultClusterAgent, + createdByUser: null, + }; + + beforeEach(() => { + return createWrapper({ clusterAgent: missingUser }); + }); + + it('displays agent create information with unknown user', () => { + expect(findCreatedText()).toMatchInterpolatedText('Created by Unknown user 2 days ago'); + }); + }); + + describe('when token count is missing', () => { + const missingTokens = { + ...defaultClusterAgent, + tokens: null, + }; + + beforeEach(() => { + return createWrapper({ clusterAgent: missingTokens }); + }); + + it('displays token header with no count', () => { + expect(findTokenCount()).toMatchInterpolatedText(`${ClusterAgentShow.i18n.tokens}`); + }); + }); + + describe('when the token list has additional pages', () => { + const pageInfo = { + hasNextPage: true, + hasPreviousPage: false, + startCursor: 'prev', + endCursor: 'next', + }; + + const tokenPagination = { + ...defaultClusterAgent, + tokens: { + ...defaultClusterAgent.tokens, + pageInfo, + }, + }; + + beforeEach(() => { + return createWrapper({ clusterAgent: tokenPagination }); + }); + + it('should render pagination buttons', () => { + expect(findPaginationButtons().exists()).toBe(true); + }); + + it('should pass pageInfo to the pagination component', () => { + expect(findPaginationButtons().props()).toMatchObject(pageInfo); + }); + }); + + describe('when the agent query is loading', () => { + describe('when the clusterAgent is missing', () => { + beforeEach(() => { + return createWrapper({ + clusterAgent: null, + queryResponse: jest.fn().mockReturnValue(new Promise(() => {})), + }); + }); + + it('displays a loading icon and hides the token tab', () => { + expect(findLoadingIcon().exists()).toBe(true); + expect(wrapper.text()).not.toContain(ClusterAgentShow.i18n.tokens); + }); + }); + + describe('when the clusterAgent is present', () => { + beforeEach(() => { + createWrapperWithoutApollo({ clusterAgent: defaultClusterAgent, loading: true }); + }); + + it('displays a loading icon and token tab', () => { + expect(findLoadingIcon().exists()).toBe(true); + expect(wrapper.text()).toContain(ClusterAgentShow.i18n.tokens); + }); + }); + }); + + describe('when the agent query has errored', () => { + beforeEach(() => { + createWrapper({ clusterAgent: null, queryResponse: jest.fn().mockRejectedValue() }); + return waitForPromises(); + }); + + it('displays an alert message', () => { + expect(wrapper.find(GlAlert).exists()).toBe(true); + expect(wrapper.text()).toContain(ClusterAgentShow.i18n.loadingError); + }); + }); +}); diff --git a/spec/frontend/clusters/agents/components/token_table_spec.js b/spec/frontend/clusters/agents/components/token_table_spec.js new file mode 100644 index 00000000000..47ff944dd84 --- /dev/null +++ b/spec/frontend/clusters/agents/components/token_table_spec.js @@ -0,0 +1,135 @@ +import { GlEmptyState, GlLink, GlTooltip, GlTruncate } from '@gitlab/ui'; +import { mount } from '@vue/test-utils'; +import TokenTable from '~/clusters/agents/components/token_table.vue'; +import { useFakeDate } from 'helpers/fake_date'; +import { extendedWrapper } from 'helpers/vue_test_utils_helper'; + +describe('ClusterAgentTokenTable', () => { + let wrapper; + useFakeDate([2021, 2, 15]); + + const defaultTokens = [ + { + id: '1', + createdAt: '2021-02-13T00:00:00Z', + description: 'Description of token 1', + createdByUser: { + name: 'user-1', + }, + lastUsedAt: '2021-02-13T00:00:00Z', + name: 'token-1', + }, + { + id: '2', + createdAt: '2021-02-10T00:00:00Z', + description: null, + createdByUser: null, + lastUsedAt: null, + name: 'token-2', + }, + ]; + + const createComponent = (tokens) => { + wrapper = extendedWrapper(mount(TokenTable, { propsData: { tokens } })); + }; + + const findEmptyState = () => wrapper.find(GlEmptyState); + const findLink = () => wrapper.find(GlLink); + + beforeEach(() => { + return createComponent(defaultTokens); + }); + + afterEach(() => { + wrapper.destroy(); + }); + + it('displays a learn more link', () => { + const learnMoreLink = findLink(); + + expect(learnMoreLink.exists()).toBe(true); + expect(learnMoreLink.text()).toBe(TokenTable.i18n.learnMore); + }); + + it.each` + name | lineNumber + ${'token-1'} | ${0} + ${'token-2'} | ${1} + `('displays token name "$name" for line "$lineNumber"', ({ name, lineNumber }) => { + const tokens = wrapper.findAll('[data-testid="agent-token-name"]'); + const token = tokens.at(lineNumber); + + expect(token.text()).toBe(name); + }); + + it.each` + lastContactText | lineNumber + ${'2 days ago'} | ${0} + ${'Never'} | ${1} + `( + 'displays last contact information "$lastContactText" for line "$lineNumber"', + ({ lastContactText, lineNumber }) => { + const tokens = wrapper.findAllByTestId('agent-token-used'); + const token = tokens.at(lineNumber); + + expect(token.text()).toBe(lastContactText); + }, + ); + + it.each` + createdText | lineNumber + ${'2 days ago'} | ${0} + ${'5 days ago'} | ${1} + `( + 'displays created information "$createdText" for line "$lineNumber"', + ({ createdText, lineNumber }) => { + const tokens = wrapper.findAll('[data-testid="agent-token-created-time"]'); + const token = tokens.at(lineNumber); + + expect(token.text()).toBe(createdText); + }, + ); + + it.each` + createdBy | lineNumber + ${'user-1'} | ${0} + ${'Unknown user'} | ${1} + `( + 'displays creator information "$createdBy" for line "$lineNumber"', + ({ createdBy, lineNumber }) => { + const tokens = wrapper.findAll('[data-testid="agent-token-created-user"]'); + const token = tokens.at(lineNumber); + + expect(token.text()).toBe(createdBy); + }, + ); + + it.each` + description | truncatesText | hasTooltip | lineNumber + ${'Description of token 1'} | ${true} | ${true} | ${0} + ${''} | ${false} | ${false} | ${1} + `( + 'displays description information "$description" for line "$lineNumber"', + ({ description, truncatesText, hasTooltip, lineNumber }) => { + const tokens = wrapper.findAll('[data-testid="agent-token-description"]'); + const token = tokens.at(lineNumber); + + expect(token.text()).toContain(description); + expect(token.find(GlTruncate).exists()).toBe(truncatesText); + expect(token.find(GlTooltip).exists()).toBe(hasTooltip); + }, + ); + + describe('when there are no tokens', () => { + beforeEach(() => { + return createComponent([]); + }); + + it('displays an empty state', () => { + const emptyState = findEmptyState(); + + expect(emptyState.exists()).toBe(true); + expect(emptyState.text()).toContain(TokenTable.i18n.noTokens); + }); + }); +}); diff --git a/spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap b/spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap index b34265b7234..42d81900911 100644 --- a/spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap +++ b/spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap @@ -33,7 +33,7 @@ exports[`Remove cluster confirmation modal renders splitbutton with modal includ <span class="sr-only" > - Toggle Dropdown + Toggle dropdown </span> </button> <ul @@ -46,21 +46,7 @@ exports[`Remove cluster confirmation modal renders splitbutton with modal includ > <!----> - <div - class="gl-display-flex gl-flex-direction-row gl-justify-content-space-between gl-align-items-center gl-px-5" - > - <div - class="gl-display-flex" - > - <!----> - </div> - - <div - class="gl-display-flex" - > - <!----> - </div> - </div> + <!----> <div class="gl-new-dropdown-contents" |