/spec/frontend/vue_shared/components/metric_images/metric_images_table_spec.js

https://gitlab.com/zillemarco/gitlab · JavaScript · 230 lines · 175 code · 55 blank · 0 comment · 3 complexity · 8ca0ce230b621fa5e280f8404d1093b3 MD5 · raw file

  1. import { GlLink, GlModal } from '@gitlab/ui';
  2. import { shallowMount, mount } from '@vue/test-utils';
  3. import Vue from 'vue';
  4. import merge from 'lodash/merge';
  5. import Vuex from 'vuex';
  6. import createStore from '~/vue_shared/components/metric_images/store';
  7. import MetricsImageTable from '~/vue_shared/components/metric_images/metric_images_table.vue';
  8. import waitForPromises from 'helpers/wait_for_promises';
  9. const defaultProps = {
  10. id: 1,
  11. filePath: 'test_file_path',
  12. filename: 'test_file_name',
  13. };
  14. const mockEvent = { preventDefault: jest.fn() };
  15. Vue.use(Vuex);
  16. describe('Metrics upload item', () => {
  17. let wrapper;
  18. let store;
  19. const mountComponent = (options = {}, mountMethod = mount) => {
  20. store = createStore();
  21. wrapper = mountMethod(
  22. MetricsImageTable,
  23. merge(
  24. {
  25. store,
  26. propsData: {
  27. ...defaultProps,
  28. },
  29. provide: { canUpdate: true },
  30. },
  31. options,
  32. ),
  33. );
  34. };
  35. afterEach(() => {
  36. if (wrapper) {
  37. wrapper.destroy();
  38. wrapper = null;
  39. }
  40. });
  41. const findImageLink = () => wrapper.findComponent(GlLink);
  42. const findLabelTextSpan = () => wrapper.find('[data-testid="metric-image-label-span"]');
  43. const findCollapseButton = () => wrapper.find('[data-testid="collapse-button"]');
  44. const findMetricImageBody = () => wrapper.find('[data-testid="metric-image-body"]');
  45. const findModal = () => wrapper.findComponent(GlModal);
  46. const findEditModal = () => wrapper.find('[data-testid="metric-image-edit-modal"]');
  47. const findDeleteButton = () => wrapper.find('[data-testid="delete-button"]');
  48. const findEditButton = () => wrapper.find('[data-testid="edit-button"]');
  49. const findImageTextInput = () => wrapper.find('[data-testid="metric-image-text-field"]');
  50. const findImageUrlInput = () => wrapper.find('[data-testid="metric-image-url-field"]');
  51. const closeModal = () => findModal().vm.$emit('hidden');
  52. const submitModal = () => findModal().vm.$emit('primary', mockEvent);
  53. const deleteImage = () => findDeleteButton().vm.$emit('click');
  54. const closeEditModal = () => findEditModal().vm.$emit('hidden');
  55. const submitEditModal = () => findEditModal().vm.$emit('primary', mockEvent);
  56. const editImage = () => findEditButton().vm.$emit('click');
  57. it('render the metrics image component', () => {
  58. mountComponent({}, shallowMount);
  59. expect(wrapper.element).toMatchSnapshot();
  60. });
  61. it('shows a link with the correct url', () => {
  62. const testUrl = 'test_url';
  63. mountComponent({ propsData: { url: testUrl } });
  64. expect(findImageLink().attributes('href')).toBe(testUrl);
  65. expect(findImageLink().text()).toBe(defaultProps.filename);
  66. });
  67. it('shows a link with the url text, if url text is present', () => {
  68. const testUrl = 'test_url';
  69. const testUrlText = 'test_url_text';
  70. mountComponent({ propsData: { url: testUrl, urlText: testUrlText } });
  71. expect(findImageLink().attributes('href')).toBe(testUrl);
  72. expect(findImageLink().text()).toBe(testUrlText);
  73. });
  74. it('shows the url text with no url, if no url is present', () => {
  75. const testUrlText = 'test_url_text';
  76. mountComponent({ propsData: { urlText: testUrlText } });
  77. expect(findLabelTextSpan().text()).toBe(testUrlText);
  78. });
  79. describe('expand and collapse', () => {
  80. beforeEach(() => {
  81. mountComponent();
  82. });
  83. it('the card is expanded by default', () => {
  84. expect(findMetricImageBody().isVisible()).toBe(true);
  85. });
  86. it('the card is collapsed when clicked', async () => {
  87. findCollapseButton().trigger('click');
  88. await waitForPromises();
  89. expect(findMetricImageBody().isVisible()).toBe(false);
  90. });
  91. });
  92. describe('delete functionality', () => {
  93. it('should open the delete modal when clicked', async () => {
  94. mountComponent({ stubs: { GlModal: true } });
  95. deleteImage();
  96. await waitForPromises();
  97. expect(findModal().attributes('visible')).toBe('true');
  98. });
  99. describe('when the modal is open', () => {
  100. beforeEach(() => {
  101. mountComponent(
  102. {
  103. data() {
  104. return { modalVisible: true };
  105. },
  106. },
  107. shallowMount,
  108. );
  109. });
  110. it('should close the modal when cancelled', async () => {
  111. closeModal();
  112. await waitForPromises();
  113. expect(findModal().attributes('visible')).toBeFalsy();
  114. });
  115. it('should delete the image when selected', async () => {
  116. const dispatchSpy = jest.spyOn(store, 'dispatch').mockImplementation(jest.fn());
  117. submitModal();
  118. await waitForPromises();
  119. expect(dispatchSpy).toHaveBeenCalledWith('deleteImage', defaultProps.id);
  120. });
  121. });
  122. describe('canUpdate permission', () => {
  123. it('delete button is hidden when user lacks update permissions', () => {
  124. mountComponent({ provide: { canUpdate: false } });
  125. expect(findDeleteButton().exists()).toBe(false);
  126. });
  127. });
  128. });
  129. describe('edit functionality', () => {
  130. it('should open the delete modal when clicked', async () => {
  131. mountComponent({ stubs: { GlModal: true } });
  132. editImage();
  133. await waitForPromises();
  134. expect(findEditModal().attributes('visible')).toBe('true');
  135. });
  136. describe('when the modal is open', () => {
  137. beforeEach(() => {
  138. mountComponent({
  139. data() {
  140. return { editModalVisible: true };
  141. },
  142. propsData: { urlText: 'test' },
  143. stubs: { GlModal: true },
  144. });
  145. });
  146. it('should close the modal when cancelled', async () => {
  147. closeEditModal();
  148. await waitForPromises();
  149. expect(findEditModal().attributes('visible')).toBeFalsy();
  150. });
  151. it('should delete the image when selected', async () => {
  152. const dispatchSpy = jest.spyOn(store, 'dispatch').mockImplementation(jest.fn());
  153. submitEditModal();
  154. await waitForPromises();
  155. expect(dispatchSpy).toHaveBeenCalledWith('updateImage', {
  156. imageId: defaultProps.id,
  157. url: null,
  158. urlText: 'test',
  159. });
  160. });
  161. it('should clear edits when the modal is closed', async () => {
  162. await findImageTextInput().setValue('test value');
  163. await findImageUrlInput().setValue('http://www.gitlab.com');
  164. expect(findImageTextInput().element.value).toBe('test value');
  165. expect(findImageUrlInput().element.value).toBe('http://www.gitlab.com');
  166. closeEditModal();
  167. await waitForPromises();
  168. editImage();
  169. await waitForPromises();
  170. expect(findImageTextInput().element.value).toBe('test');
  171. expect(findImageUrlInput().element.value).toBe('');
  172. });
  173. });
  174. });
  175. });