item_spec.js 4.8 KB
Newer Older
1 2 3
import { createLocalVue, shallowMount } from '@vue/test-utils';
import { GlIcon, GlLoadingIcon, GlIntersectionObserver } from '@gitlab/ui';
import VueRouter from 'vue-router';
4
import Item from '~/design_management_legacy/components/list/item.vue';
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

const localVue = createLocalVue();
localVue.use(VueRouter);
const router = new VueRouter();

// Referenced from: doc/api/graphql/reference/gitlab_schema.graphql:DesignVersionEvent
const DESIGN_VERSION_EVENT = {
  CREATION: 'CREATION',
  DELETION: 'DELETION',
  MODIFICATION: 'MODIFICATION',
  NO_CHANGE: 'NONE',
};

describe('Design management list item component', () => {
  let wrapper;

21
  const findDesignEvent = () => wrapper.find('[data-testid="designEvent"]');
22
  const findEventIcon = () => findDesignEvent().find(GlIcon);
23 24
  const findLoadingIcon = () => wrapper.find(GlLoadingIcon);

25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
  function createComponent({
    notesCount = 0,
    event = DESIGN_VERSION_EVENT.NO_CHANGE,
    isUploading = false,
    imageLoading = false,
  } = {}) {
    wrapper = shallowMount(Item, {
      localVue,
      router,
      propsData: {
        id: 1,
        filename: 'test',
        image: 'http://via.placeholder.com/300',
        isUploading,
        event,
        notesCount,
        updatedAt: '01-01-2019',
      },
      data() {
        return {
          imageLoading,
        };
      },
      stubs: ['router-link'],
    });
  }

  afterEach(() => {
    wrapper.destroy();
  });

  describe('when item is not in view', () => {
    it('image is not rendered', () => {
      createComponent();

      const image = wrapper.find('img');
      expect(image.attributes('src')).toBe('');
    });
  });

  describe('when item appears in view', () => {
    let image;
    let glIntersectionObserver;

    beforeEach(() => {
      createComponent();
      image = wrapper.find('img');
      glIntersectionObserver = wrapper.find(GlIntersectionObserver);

      glIntersectionObserver.vm.$emit('appear');
      return wrapper.vm.$nextTick();
    });

    describe('before image is loaded', () => {
      it('renders loading spinner', () => {
        expect(wrapper.find(GlLoadingIcon)).toExist();
      });
    });

    describe('after image is loaded', () => {
      beforeEach(() => {
        image.trigger('load');
        return wrapper.vm.$nextTick();
      });

      it('renders an image', () => {
        expect(image.attributes('src')).toBe('http://via.placeholder.com/300');
        expect(image.isVisible()).toBe(true);
      });

      it('renders media broken icon when image onerror triggered', () => {
        image.trigger('error');
        return wrapper.vm.$nextTick().then(() => {
          expect(image.isVisible()).toBe(false);
          expect(wrapper.find(GlIcon).element).toMatchSnapshot();
        });
      });

      describe('when imageV432x230 and image provided', () => {
        it('renders imageV432x230 image', () => {
          const mockSrc = 'mock-imageV432x230-url';
          wrapper.setProps({ imageV432x230: mockSrc });

          return wrapper.vm.$nextTick().then(() => {
            expect(image.attributes('src')).toBe(mockSrc);
          });
        });
      });

      describe('when image disappears from view and then reappears', () => {
        beforeEach(() => {
          glIntersectionObserver.vm.$emit('appear');
          return wrapper.vm.$nextTick();
        });

        it('renders an image', () => {
          expect(image.isVisible()).toBe(true);
        });
      });
    });
  });

  describe('with notes', () => {
    it('renders item with single comment', () => {
      createComponent({ notesCount: 1 });

      expect(wrapper.element).toMatchSnapshot();
    });

    it('renders item with multiple comments', () => {
      createComponent({ notesCount: 2 });

      expect(wrapper.element).toMatchSnapshot();
    });
  });

141 142
  it('renders loading spinner when isUploading is true', () => {
    createComponent({ isUploading: true });
143

144 145
    expect(findLoadingIcon().exists()).toBe(true);
  });
146

147 148
  it('renders item with no status icon for none event', () => {
    createComponent();
149

150 151
    expect(findDesignEvent().exists()).toBe(false);
  });
152

153 154 155 156 157 158 159 160 161 162 163 164 165
  describe('with associated event', () => {
    it.each`
      event                                | icon                     | className
      ${DESIGN_VERSION_EVENT.MODIFICATION} | ${'file-modified-solid'} | ${'text-primary-500'}
      ${DESIGN_VERSION_EVENT.DELETION}     | ${'file-deletion-solid'} | ${'text-danger-500'}
      ${DESIGN_VERSION_EVENT.CREATION}     | ${'file-addition-solid'} | ${'text-success-500'}
    `('renders item with correct status icon for $event event', ({ event, icon, className }) => {
      createComponent({ event });
      const eventIcon = findEventIcon();

      expect(eventIcon.exists()).toBe(true);
      expect(eventIcon.props('name')).toBe(icon);
      expect(eventIcon.classes()).toContain(className);
166 167 168
    });
  });
});