251 lines
7.7 KiB
JavaScript
251 lines
7.7 KiB
JavaScript
import { GlButton, GlModal, GlFormInput } from '@gitlab/ui';
|
|
import Vue, { nextTick } from 'vue';
|
|
import VueApollo from 'vue-apollo';
|
|
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
|
import { ENTER_KEY } from '~/lib/utils/keys';
|
|
import getAgentsQuery from '~/clusters_list/graphql/queries/get_agents.query.graphql';
|
|
import deleteAgentMutation from '~/clusters_list/graphql/mutations/delete_agent.mutation.graphql';
|
|
import createMockApollo from 'helpers/mock_apollo_helper';
|
|
import waitForPromises from 'helpers/wait_for_promises';
|
|
import DeleteAgentButton from '~/clusters_list/components/delete_agent_button.vue';
|
|
import { MAX_LIST_COUNT, DELETE_AGENT_BUTTON } from '~/clusters_list/constants';
|
|
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
|
|
import { getAgentResponse, mockDeleteResponse, mockErrorDeleteResponse } from '../mocks/apollo';
|
|
|
|
Vue.use(VueApollo);
|
|
|
|
const projectPath = 'path/to/project';
|
|
const defaultBranchName = 'default';
|
|
const maxAgents = MAX_LIST_COUNT;
|
|
const agent = {
|
|
id: 'agent-id',
|
|
name: 'agent-name',
|
|
webPath: 'agent-webPath',
|
|
};
|
|
|
|
describe('DeleteAgentButton', () => {
|
|
let wrapper;
|
|
let toast;
|
|
let apolloProvider;
|
|
let deleteResponse;
|
|
|
|
const findModal = () => wrapper.findComponent(GlModal);
|
|
const findDeleteBtn = () => wrapper.findComponent(GlButton);
|
|
const findInput = () => wrapper.findComponent(GlFormInput);
|
|
const findPrimaryAction = () => findModal().props('actionPrimary');
|
|
const findPrimaryActionAttributes = (attr) => findPrimaryAction().attributes[0][attr];
|
|
const findDeleteAgentButtonTooltip = () => wrapper.findByTestId('delete-agent-button-tooltip');
|
|
const getTooltipText = (el) => {
|
|
const binding = getBinding(el, 'gl-tooltip');
|
|
|
|
return binding.value;
|
|
};
|
|
|
|
const createMockApolloProvider = ({ mutationResponse }) => {
|
|
deleteResponse = jest.fn().mockResolvedValue(mutationResponse);
|
|
|
|
return createMockApollo([[deleteAgentMutation, deleteResponse]]);
|
|
};
|
|
|
|
const writeQuery = () => {
|
|
apolloProvider.clients.defaultClient.cache.writeQuery({
|
|
query: getAgentsQuery,
|
|
variables: {
|
|
projectPath,
|
|
defaultBranchName,
|
|
first: maxAgents,
|
|
last: null,
|
|
},
|
|
data: getAgentResponse.data,
|
|
});
|
|
};
|
|
|
|
const createWrapper = async ({
|
|
mutationResponse = mockDeleteResponse,
|
|
provideData = {},
|
|
} = {}) => {
|
|
apolloProvider = createMockApolloProvider({ mutationResponse });
|
|
const defaultProvide = {
|
|
projectPath,
|
|
canAdminCluster: true,
|
|
};
|
|
const propsData = {
|
|
defaultBranchName,
|
|
maxAgents,
|
|
agent,
|
|
};
|
|
|
|
toast = jest.fn();
|
|
|
|
wrapper = shallowMountExtended(DeleteAgentButton, {
|
|
apolloProvider,
|
|
provide: {
|
|
...defaultProvide,
|
|
...provideData,
|
|
},
|
|
directives: {
|
|
GlTooltip: createMockDirective(),
|
|
},
|
|
propsData,
|
|
mocks: { $toast: { show: toast } },
|
|
stubs: { GlModal },
|
|
});
|
|
wrapper.vm.$refs.modal.hide = jest.fn();
|
|
|
|
writeQuery();
|
|
await nextTick();
|
|
};
|
|
|
|
const submitAgentToDelete = async () => {
|
|
findDeleteBtn().vm.$emit('click');
|
|
findInput().vm.$emit('input', agent.name);
|
|
await findModal().vm.$emit('primary');
|
|
await waitForPromises();
|
|
};
|
|
|
|
beforeEach(() => {
|
|
return createWrapper({});
|
|
});
|
|
|
|
afterEach(() => {
|
|
wrapper.destroy();
|
|
apolloProvider = null;
|
|
deleteResponse = null;
|
|
toast = null;
|
|
});
|
|
|
|
describe('delete agent action', () => {
|
|
it('displays a delete button', () => {
|
|
expect(findDeleteBtn().attributes('aria-label')).toBe(DELETE_AGENT_BUTTON.deleteButton);
|
|
});
|
|
|
|
it('shows a tooltip for the button', () => {
|
|
expect(getTooltipText(findDeleteAgentButtonTooltip().element)).toBe(
|
|
DELETE_AGENT_BUTTON.deleteButton,
|
|
);
|
|
});
|
|
|
|
describe('when clicking the delete button', () => {
|
|
beforeEach(() => {
|
|
findDeleteBtn().vm.$emit('click');
|
|
});
|
|
|
|
it('displays a delete confirmation modal', () => {
|
|
expect(findModal().isVisible()).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('when user cannot delete clusters', () => {
|
|
beforeEach(() => {
|
|
createWrapper({ provideData: { canAdminCluster: false } });
|
|
});
|
|
|
|
it('disables the button', () => {
|
|
expect(findDeleteBtn().attributes('disabled')).toBe('true');
|
|
});
|
|
|
|
it('shows a disabled tooltip', () => {
|
|
expect(getTooltipText(findDeleteAgentButtonTooltip().element)).toBe(
|
|
DELETE_AGENT_BUTTON.disabledHint,
|
|
);
|
|
});
|
|
});
|
|
|
|
describe.each`
|
|
condition | agentName | isDisabled | mutationCalled
|
|
${'the input with agent name is missing'} | ${''} | ${true} | ${false}
|
|
${'the input with agent name is incorrect'} | ${'wrong-name'} | ${true} | ${false}
|
|
${'the input with agent name is correct'} | ${agent.name} | ${false} | ${true}
|
|
`('when $condition', ({ agentName, isDisabled, mutationCalled }) => {
|
|
beforeEach(() => {
|
|
findDeleteBtn().vm.$emit('click');
|
|
findInput().vm.$emit('input', agentName);
|
|
});
|
|
|
|
it(`${isDisabled ? 'disables' : 'enables'} the modal primary button`, () => {
|
|
expect(findPrimaryActionAttributes('disabled')).toBe(isDisabled);
|
|
});
|
|
|
|
describe('when user clicks the modal primary button', () => {
|
|
beforeEach(async () => {
|
|
await findModal().vm.$emit('primary');
|
|
});
|
|
|
|
if (mutationCalled) {
|
|
it('calls the delete mutation', () => {
|
|
expect(deleteResponse).toHaveBeenCalledWith({ input: { id: agent.id } });
|
|
});
|
|
} else {
|
|
it("doesn't call the delete mutation", () => {
|
|
expect(deleteResponse).not.toHaveBeenCalled();
|
|
});
|
|
}
|
|
});
|
|
|
|
describe('when user presses the enter button', () => {
|
|
beforeEach(async () => {
|
|
await findInput().vm.$emit('keydown', new KeyboardEvent({ key: ENTER_KEY }));
|
|
});
|
|
|
|
if (mutationCalled) {
|
|
it('calls the delete mutation', () => {
|
|
expect(deleteResponse).toHaveBeenCalledWith({ input: { id: agent.id } });
|
|
});
|
|
} else {
|
|
it("doesn't call the delete mutation", () => {
|
|
expect(deleteResponse).not.toHaveBeenCalled();
|
|
});
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('when agent was deleted successfully', () => {
|
|
beforeEach(async () => {
|
|
await submitAgentToDelete();
|
|
});
|
|
|
|
it('calls the toast action', () => {
|
|
expect(toast).toHaveBeenCalledWith(`${agent.name} successfully deleted`);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('when getting an error deleting agent', () => {
|
|
beforeEach(async () => {
|
|
await createWrapper({ mutationResponse: mockErrorDeleteResponse });
|
|
await submitAgentToDelete();
|
|
});
|
|
|
|
it('displays the error message', () => {
|
|
expect(toast).toHaveBeenCalledWith('could not delete agent');
|
|
});
|
|
});
|
|
|
|
describe('when the delete modal was closed', () => {
|
|
beforeEach(async () => {
|
|
const loadingResponse = new Promise(() => {});
|
|
await createWrapper({ mutationResponse: loadingResponse });
|
|
|
|
await submitAgentToDelete();
|
|
});
|
|
|
|
it('reenables the button', async () => {
|
|
expect(findPrimaryActionAttributes('loading')).toBe(true);
|
|
expect(findDeleteBtn().attributes('disabled')).toBe('true');
|
|
|
|
await findModal().vm.$emit('hide');
|
|
|
|
expect(findPrimaryActionAttributes('loading')).toBe(false);
|
|
expect(findDeleteBtn().attributes('disabled')).toBeUndefined();
|
|
});
|
|
|
|
it('clears the agent name input', async () => {
|
|
expect(findInput().attributes('value')).toBe(agent.name);
|
|
|
|
await findModal().vm.$emit('hide');
|
|
|
|
expect(findInput().attributes('value')).toBeUndefined();
|
|
});
|
|
});
|
|
});
|