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/clusters/agents')
-rw-r--r--spec/frontend/clusters/agents/components/create_token_button_spec.js257
-rw-r--r--spec/frontend/clusters/agents/components/token_table_spec.js43
2 files changed, 288 insertions, 12 deletions
diff --git a/spec/frontend/clusters/agents/components/create_token_button_spec.js b/spec/frontend/clusters/agents/components/create_token_button_spec.js
new file mode 100644
index 00000000000..b9a3a851e57
--- /dev/null
+++ b/spec/frontend/clusters/agents/components/create_token_button_spec.js
@@ -0,0 +1,257 @@
+import { GlButton, GlTooltip, GlModal, GlFormInput, GlFormTextarea, GlAlert } from '@gitlab/ui';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import { mockTracking } from 'helpers/tracking_helper';
+import {
+ EVENT_LABEL_MODAL,
+ EVENT_ACTIONS_OPEN,
+ TOKEN_NAME_LIMIT,
+ TOKEN_STATUS_ACTIVE,
+ MAX_LIST_COUNT,
+} from '~/clusters/agents/constants';
+import createNewAgentToken from '~/clusters/agents/graphql/mutations/create_new_agent_token.mutation.graphql';
+import getClusterAgentQuery from '~/clusters/agents/graphql/queries/get_cluster_agent.query.graphql';
+import AgentToken from '~/clusters_list/components/agent_token.vue';
+import CreateTokenButton from '~/clusters/agents/components/create_token_button.vue';
+import {
+ clusterAgentToken,
+ getTokenResponse,
+ createAgentTokenErrorResponse,
+} from '../../mock_data';
+
+Vue.use(VueApollo);
+
+describe('CreateTokenButton', () => {
+ let wrapper;
+ let apolloProvider;
+ let trackingSpy;
+ let createResponse;
+
+ const clusterAgentId = 'cluster-agent-id';
+ const cursor = {
+ first: MAX_LIST_COUNT,
+ last: null,
+ };
+ const agentName = 'cluster-agent';
+ const projectPath = 'path/to/project';
+
+ const defaultProvide = {
+ agentName,
+ projectPath,
+ canAdminCluster: true,
+ };
+ const propsData = {
+ clusterAgentId,
+ cursor,
+ };
+
+ const findModal = () => wrapper.findComponent(GlModal);
+ const findBtn = () => wrapper.findComponent(GlButton);
+ const findInput = () => wrapper.findComponent(GlFormInput);
+ const findTextarea = () => wrapper.findComponent(GlFormTextarea);
+ const findAlert = () => wrapper.findComponent(GlAlert);
+ const findTooltip = () => wrapper.findComponent(GlTooltip);
+ const findAgentInstructions = () => findModal().findComponent(AgentToken);
+ const findButtonByVariant = (variant) =>
+ findModal()
+ .findAll(GlButton)
+ .wrappers.find((button) => button.props('variant') === variant);
+ const findActionButton = () => findButtonByVariant('confirm');
+ const findCancelButton = () => wrapper.findByTestId('agent-token-close-button');
+
+ const expectDisabledAttribute = (element, disabled) => {
+ if (disabled) {
+ expect(element.attributes('disabled')).toBe('true');
+ } else {
+ expect(element.attributes('disabled')).toBeUndefined();
+ }
+ };
+
+ const createMockApolloProvider = ({ mutationResponse }) => {
+ createResponse = jest.fn().mockResolvedValue(mutationResponse);
+
+ return createMockApollo([[createNewAgentToken, createResponse]]);
+ };
+
+ const writeQuery = () => {
+ apolloProvider.clients.defaultClient.cache.writeQuery({
+ query: getClusterAgentQuery,
+ data: getTokenResponse.data,
+ variables: {
+ agentName,
+ projectPath,
+ tokenStatus: TOKEN_STATUS_ACTIVE,
+ ...cursor,
+ },
+ });
+ };
+
+ const createWrapper = async ({ provideData = {} } = {}) => {
+ wrapper = shallowMountExtended(CreateTokenButton, {
+ apolloProvider,
+ provide: {
+ ...defaultProvide,
+ ...provideData,
+ },
+ propsData,
+ stubs: {
+ GlModal,
+ GlTooltip,
+ },
+ });
+ wrapper.vm.$refs.modal.hide = jest.fn();
+
+ trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
+ };
+
+ const mockCreatedResponse = (mutationResponse) => {
+ apolloProvider = createMockApolloProvider({ mutationResponse });
+ writeQuery();
+
+ createWrapper();
+
+ findInput().vm.$emit('input', 'new-token');
+ findTextarea().vm.$emit('input', 'new-token-description');
+ findActionButton().vm.$emit('click');
+
+ return waitForPromises();
+ };
+
+ beforeEach(() => {
+ createWrapper();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ apolloProvider = null;
+ createResponse = null;
+ });
+
+ describe('create agent token action', () => {
+ it('displays create agent token button', () => {
+ expect(findBtn().text()).toBe('Create token');
+ });
+
+ describe('when user cannot create token', () => {
+ beforeEach(() => {
+ createWrapper({ provideData: { canAdminCluster: false } });
+ });
+
+ it('disabled the button', () => {
+ expect(findBtn().attributes('disabled')).toBe('true');
+ });
+
+ it('shows a disabled tooltip', () => {
+ expect(findTooltip().attributes('title')).toBe(
+ 'Requires a Maintainer or greater role to perform these actions',
+ );
+ });
+ });
+
+ describe('when user can create a token and clicks the button', () => {
+ beforeEach(() => {
+ findBtn().vm.$emit('click');
+ });
+
+ it('displays a token creation modal', () => {
+ expect(findModal().isVisible()).toBe(true);
+ });
+
+ describe('initial state', () => {
+ it('renders an input for the token name', () => {
+ expect(findInput().exists()).toBe(true);
+ expectDisabledAttribute(findInput(), false);
+ expect(findInput().attributes('max-length')).toBe(TOKEN_NAME_LIMIT.toString());
+ });
+
+ it('renders a textarea for the token description', () => {
+ expect(findTextarea().exists()).toBe(true);
+ expectDisabledAttribute(findTextarea(), false);
+ });
+
+ it('renders a cancel button', () => {
+ expect(findCancelButton().isVisible()).toBe(true);
+ expectDisabledAttribute(findCancelButton(), false);
+ });
+
+ it('renders a disabled next button', () => {
+ expect(findActionButton().text()).toBe('Create token');
+ expectDisabledAttribute(findActionButton(), true);
+ });
+
+ it('sends tracking event for modal shown', () => {
+ findModal().vm.$emit('show');
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, EVENT_ACTIONS_OPEN, {
+ label: EVENT_LABEL_MODAL,
+ });
+ });
+ });
+
+ describe('when user inputs the token name', () => {
+ beforeEach(() => {
+ expectDisabledAttribute(findActionButton(), true);
+ findInput().vm.$emit('input', 'new-token');
+ });
+
+ it('enables the next button', () => {
+ expectDisabledAttribute(findActionButton(), false);
+ });
+ });
+
+ describe('when user clicks the create-token button', () => {
+ beforeEach(async () => {
+ const loadingResponse = new Promise(() => {});
+ await mockCreatedResponse(loadingResponse);
+
+ findInput().vm.$emit('input', 'new-token');
+ findActionButton().vm.$emit('click');
+ });
+
+ it('disables the create-token button', () => {
+ expectDisabledAttribute(findActionButton(), true);
+ });
+
+ it('hides the cancel button', () => {
+ expect(findCancelButton().exists()).toBe(false);
+ });
+ });
+
+ describe('creating a new token', () => {
+ beforeEach(async () => {
+ await mockCreatedResponse(clusterAgentToken);
+ });
+
+ it('creates a token', () => {
+ expect(createResponse).toHaveBeenCalledWith({
+ input: { clusterAgentId, name: 'new-token', description: 'new-token-description' },
+ });
+ });
+
+ it('shows agent instructions', () => {
+ expect(findAgentInstructions().exists()).toBe(true);
+ });
+
+ it('renders a close button', () => {
+ expect(findActionButton().isVisible()).toBe(true);
+ expect(findActionButton().text()).toBe('Close');
+ expectDisabledAttribute(findActionButton(), false);
+ });
+ });
+
+ describe('error creating a new token', () => {
+ beforeEach(async () => {
+ await mockCreatedResponse(createAgentTokenErrorResponse);
+ });
+
+ it('displays the error message', async () => {
+ expect(findAlert().text()).toBe(
+ createAgentTokenErrorResponse.data.clusterAgentTokenCreate.errors[0],
+ );
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/clusters/agents/components/token_table_spec.js b/spec/frontend/clusters/agents/components/token_table_spec.js
index 47ff944dd84..f6baaf87fa4 100644
--- a/spec/frontend/clusters/agents/components/token_table_spec.js
+++ b/spec/frontend/clusters/agents/components/token_table_spec.js
@@ -1,8 +1,10 @@
-import { GlEmptyState, GlLink, GlTooltip, GlTruncate } from '@gitlab/ui';
+import { GlEmptyState, GlTooltip, GlTruncate } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import TokenTable from '~/clusters/agents/components/token_table.vue';
+import CreateTokenButton from '~/clusters/agents/components/create_token_button.vue';
import { useFakeDate } from 'helpers/fake_date';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import { MAX_LIST_COUNT } from '~/clusters/agents/constants';
describe('ClusterAgentTokenTable', () => {
let wrapper;
@@ -28,13 +30,26 @@ describe('ClusterAgentTokenTable', () => {
name: 'token-2',
},
];
+ const clusterAgentId = 'cluster-agent-id';
+ const cursor = {
+ first: MAX_LIST_COUNT,
+ last: null,
+ };
+
+ const provide = {
+ agentName: 'cluster-agent',
+ projectPath: 'path/to/project',
+ canAdminCluster: true,
+ };
const createComponent = (tokens) => {
- wrapper = extendedWrapper(mount(TokenTable, { propsData: { tokens } }));
+ wrapper = extendedWrapper(
+ mount(TokenTable, { propsData: { tokens, clusterAgentId, cursor }, provide }),
+ );
};
- const findEmptyState = () => wrapper.find(GlEmptyState);
- const findLink = () => wrapper.find(GlLink);
+ const findEmptyState = () => wrapper.findComponent(GlEmptyState);
+ const findCreateTokenBtn = () => wrapper.findComponent(CreateTokenButton);
beforeEach(() => {
return createComponent(defaultTokens);
@@ -44,11 +59,15 @@ describe('ClusterAgentTokenTable', () => {
wrapper.destroy();
});
- it('displays a learn more link', () => {
- const learnMoreLink = findLink();
+ it('displays the create token button', () => {
+ expect(findCreateTokenBtn().exists()).toBe(true);
+ });
- expect(learnMoreLink.exists()).toBe(true);
- expect(learnMoreLink.text()).toBe(TokenTable.i18n.learnMore);
+ it('passes the correct params to the create token component', () => {
+ expect(findCreateTokenBtn().props()).toMatchObject({
+ clusterAgentId,
+ cursor,
+ });
});
it.each`
@@ -56,7 +75,7 @@ describe('ClusterAgentTokenTable', () => {
${'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 tokens = wrapper.findAllByTestId('agent-token-name');
const token = tokens.at(lineNumber);
expect(token.text()).toBe(name);
@@ -83,7 +102,7 @@ describe('ClusterAgentTokenTable', () => {
`(
'displays created information "$createdText" for line "$lineNumber"',
({ createdText, lineNumber }) => {
- const tokens = wrapper.findAll('[data-testid="agent-token-created-time"]');
+ const tokens = wrapper.findAllByTestId('agent-token-created-time');
const token = tokens.at(lineNumber);
expect(token.text()).toBe(createdText);
@@ -97,7 +116,7 @@ describe('ClusterAgentTokenTable', () => {
`(
'displays creator information "$createdBy" for line "$lineNumber"',
({ createdBy, lineNumber }) => {
- const tokens = wrapper.findAll('[data-testid="agent-token-created-user"]');
+ const tokens = wrapper.findAllByTestId('agent-token-created-user');
const token = tokens.at(lineNumber);
expect(token.text()).toBe(createdBy);
@@ -111,7 +130,7 @@ describe('ClusterAgentTokenTable', () => {
`(
'displays description information "$description" for line "$lineNumber"',
({ description, truncatesText, hasTooltip, lineNumber }) => {
- const tokens = wrapper.findAll('[data-testid="agent-token-description"]');
+ const tokens = wrapper.findAllByTestId('agent-token-description');
const token = tokens.at(lineNumber);
expect(token.text()).toContain(description);