summaryrefslogtreecommitdiff
path: root/spec/javascripts/vue_shared/components/project_selector/project_selector_spec.js
blob: 3ba0033171e6099555a20bbec8e692b9a4b8b34f (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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import Vue from 'vue';
import _ from 'underscore';
import ProjectSelector from '~/vue_shared/components/project_selector/project_selector.vue';
import ProjectListItem from '~/vue_shared/components/project_selector/project_list_item.vue';
import { shallowMount } from '@vue/test-utils';
import { trimText } from 'spec/helpers/vue_component_helper';

describe('ProjectSelector component', () => {
  let wrapper;
  let vm;
  loadJSONFixtures('static/projects.json');
  const allProjects = getJSONFixture('static/projects.json');
  const searchResults = allProjects.slice(0, 5);
  let selected = [];
  selected = selected.concat(allProjects.slice(0, 3)).concat(allProjects.slice(5, 8));

  beforeEach(() => {
    jasmine.clock().install();

    wrapper = shallowMount(Vue.extend(ProjectSelector), {
      propsData: {
        projectSearchResults: searchResults,
        selectedProjects: selected,
        showNoResultsMessage: false,
        showMinimumSearchQueryMessage: false,
        showLoadingIndicator: false,
        showSearchErrorMessage: false,
      },
      attachToDocument: true,
    });

    ({ vm } = wrapper);
  });

  afterEach(() => {
    jasmine.clock().uninstall();
    vm.$destroy();
  });

  it('renders the search results', () => {
    expect(wrapper.findAll('.js-project-list-item').length).toBe(5);
  });

  it(`triggers a (debounced) search when the search input value changes`, () => {
    spyOn(vm, '$emit');
    const query = 'my test query!';
    const searchInput = wrapper.find('.js-project-selector-input');
    searchInput.setValue(query);
    searchInput.trigger('input');

    expect(vm.$emit).not.toHaveBeenCalledWith();
    jasmine.clock().tick(501);

    expect(vm.$emit).toHaveBeenCalledWith('searched', query);
  });

  it(`debounces the search input`, () => {
    spyOn(vm, '$emit');
    const searchInput = wrapper.find('.js-project-selector-input');

    const updateSearchQuery = (count = 0) => {
      if (count === 10) {
        jasmine.clock().tick(101);

        expect(vm.$emit).toHaveBeenCalledTimes(1);
        expect(vm.$emit).toHaveBeenCalledWith('searched', `search query #9`);
      } else {
        searchInput.setValue(`search query #${count}`);
        searchInput.trigger('input');

        jasmine.clock().tick(400);
        updateSearchQuery(count + 1);
      }
    };

    updateSearchQuery();
  });

  it(`includes a placeholder in the search box`, () => {
    expect(wrapper.find('.js-project-selector-input').attributes('placeholder')).toBe(
      'Search your projects',
    );
  });

  it(`triggers a "projectClicked" event when a project is clicked`, () => {
    spyOn(vm, '$emit');
    wrapper.find(ProjectListItem).vm.$emit('click', _.first(searchResults));

    expect(vm.$emit).toHaveBeenCalledWith('projectClicked', _.first(searchResults));
  });

  it(`shows a "no results" message if showNoResultsMessage === true`, () => {
    wrapper.setProps({ showNoResultsMessage: true });

    expect(wrapper.contains('.js-no-results-message')).toBe(true);

    const noResultsEl = wrapper.find('.js-no-results-message');

    expect(trimText(noResultsEl.text())).toEqual('Sorry, no projects matched your search');
  });

  it(`shows a "minimum search query" message if showMinimumSearchQueryMessage === true`, () => {
    wrapper.setProps({ showMinimumSearchQueryMessage: true });

    expect(wrapper.contains('.js-minimum-search-query-message')).toBe(true);

    const minimumSearchEl = wrapper.find('.js-minimum-search-query-message');

    expect(trimText(minimumSearchEl.text())).toEqual('Enter at least three characters to search');
  });

  it(`shows a error message if showSearchErrorMessage === true`, () => {
    wrapper.setProps({ showSearchErrorMessage: true });

    expect(wrapper.contains('.js-search-error-message')).toBe(true);

    const errorMessageEl = wrapper.find('.js-search-error-message');

    expect(trimText(errorMessageEl.text())).toEqual(
      'Something went wrong, unable to search projects',
    );
  });

  it(`focuses the input element when the focusSearchInput() method is called`, () => {
    const input = wrapper.find('.js-project-selector-input');

    expect(document.activeElement).not.toBe(input.element);
    vm.focusSearchInput();

    expect(document.activeElement).toBe(input.element);
  });
});