summaryrefslogtreecommitdiff
path: root/spec/frontend/invite_members/components/members_token_select_spec.js
blob: fb0bd6bb19567a0fedb4621b61409b3a9b35e3f1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import { GlTokenSelector } from '@gitlab/ui';
import waitForPromises from 'helpers/wait_for_promises';
import Api from '~/api';
import MembersTokenSelect from '~/invite_members/components/members_token_select.vue';

const label = 'testgroup';
const placeholder = 'Search for a member';
const user1 = { id: 1, name: 'Name One', username: 'one_1', avatar_url: '' };
const user2 = { id: 2, name: 'Name Two', username: 'two_2', avatar_url: '' };
const allUsers = [user1, user2];

const createComponent = () => {
  return shallowMount(MembersTokenSelect, {
    propsData: {
      ariaLabelledby: label,
      placeholder,
    },
  });
};

describe('MembersTokenSelect', () => {
  let wrapper;

  beforeEach(() => {
    jest.spyOn(Api, 'users').mockResolvedValue({ data: allUsers });
    wrapper = createComponent();
  });

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

  const findTokenSelector = () => wrapper.find(GlTokenSelector);

  describe('rendering the token-selector component', () => {
    it('renders with the correct props', () => {
      const expectedProps = {
        ariaLabelledby: label,
        placeholder,
      };

      expect(findTokenSelector().props()).toEqual(expect.objectContaining(expectedProps));
    });
  });

  describe('users', () => {
    describe('when input is focused for the first time (modal auto-focus)', () => {
      it('does not call the API', async () => {
        findTokenSelector().vm.$emit('focus');

        await waitForPromises();

        expect(Api.users).not.toHaveBeenCalled();
      });
    });

    describe('when input is manually focused', () => {
      it('calls the API and sets dropdown items as request result', async () => {
        const tokenSelector = findTokenSelector();

        tokenSelector.vm.$emit('focus');
        tokenSelector.vm.$emit('blur');
        tokenSelector.vm.$emit('focus');

        await waitForPromises();

        expect(tokenSelector.props('dropdownItems')).toMatchObject(allUsers);
        expect(tokenSelector.props('hideDropdownWithNoItems')).toBe(false);
      });
    });

    describe('when text input is typed in', () => {
      it('calls the API with search parameter', async () => {
        const searchParam = 'One';
        const tokenSelector = findTokenSelector();

        tokenSelector.vm.$emit('text-input', searchParam);

        await waitForPromises();

        expect(Api.users).toHaveBeenCalledWith(searchParam, wrapper.vm.$options.queryOptions);
        expect(tokenSelector.props('hideDropdownWithNoItems')).toBe(false);
      });
    });

    describe('when user is selected', () => {
      it('emits `input` event with selected users', () => {
        findTokenSelector().vm.$emit('input', [
          { id: 1, name: 'John Smith' },
          { id: 2, name: 'Jane Doe' },
        ]);

        expect(wrapper.emitted().input[0][0]).toBe('1,2');
      });
    });
  });

  describe('when text input is blurred', () => {
    it('clears text input', async () => {
      const tokenSelector = findTokenSelector();

      tokenSelector.vm.$emit('blur');

      await nextTick();

      expect(tokenSelector.props('hideDropdownWithNoItems')).toBe(false);
    });
  });
});