Commit bb9bd05e authored by Simon Knox's avatar Simon Knox

Merge branch...

Merge branch '223084-display-a-default-list-when-adding-environments-to-feature-flag-strategies' into 'master'

Make environments dropdown fetch results as soon as it's focused

See merge request gitlab-org/gitlab!40624
parents becb7685 4c48e6be
<script> <script>
import { isEmpty } from 'lodash'; import { debounce } from 'lodash';
import { GlLoadingIcon, GlDeprecatedButton, GlIcon } from '@gitlab/ui'; import { GlDeprecatedButton, GlSearchBoxByType } from '@gitlab/ui';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale'; import { __ } from '~/locale';
import { deprecatedCreateFlash as createFlash } from '~/flash'; import { deprecatedCreateFlash as createFlash } from '~/flash';
...@@ -9,8 +9,8 @@ import { deprecatedCreateFlash as createFlash } from '~/flash'; ...@@ -9,8 +9,8 @@ import { deprecatedCreateFlash as createFlash } from '~/flash';
* Creates a searchable input for environments. * Creates a searchable input for environments.
* *
* When given a value, it will render it as selected value * When given a value, it will render it as selected value
* Otherwise it will render a placeholder for the search * Otherwise it will render a placeholder for the search input.
* input. * It will fetch the available environments on focus.
* *
* When the user types, it will trigger an event to allow * When the user types, it will trigger an event to allow
* for API queries outside of the component. * for API queries outside of the component.
...@@ -29,8 +29,7 @@ export default { ...@@ -29,8 +29,7 @@ export default {
name: 'EnvironmentsSearchableInput', name: 'EnvironmentsSearchableInput',
components: { components: {
GlDeprecatedButton, GlDeprecatedButton,
GlLoadingIcon, GlSearchBoxByType,
GlIcon,
}, },
props: { props: {
endpoint: { endpoint: {
...@@ -60,7 +59,7 @@ export default { ...@@ -60,7 +59,7 @@ export default {
}, },
data() { data() {
return { return {
filter: this.value || '', environmentSearch: this.value,
results: [], results: [],
showSuggestions: false, showSuggestions: false,
isLoading: false, isLoading: false,
...@@ -72,49 +71,28 @@ export default { ...@@ -72,49 +71,28 @@ export default {
* @returns {String} * @returns {String}
*/ */
composedCreateButtonLabel() { composedCreateButtonLabel() {
return `${this.createButtonLabel} ${this.filter}`; return `${this.createButtonLabel} ${this.environmentSearch}`;
}, },
/**
* Create button is available when
* - loading is false, filter is set and no results are available
* @returns Boolean
*/
shouldRenderCreateButton() { shouldRenderCreateButton() {
return !isEmpty(this.filter) && !this.isLoading && !this.results.length; return !this.isLoading && !this.results.length;
},
},
watch: {
value(newVal) {
this.filter = newVal;
}, },
}, },
methods: { methods: {
/** fetchEnvironments: debounce(function debouncedFetchEnvironments() {
* On each input event, it updates the filter value and fetches the
* list of environments based on the value typed.
*
* Since we need to update the input value both with the value provided by the parent
* and the value typed by the user, we can't use v-model.
*/
fetchEnvironments(evt) {
this.filter = evt.target.value;
this.isLoading = true; this.isLoading = true;
this.openSuggestions(); this.openSuggestions();
axios
return axios .get(this.endpoint, { params: { query: this.environmentSearch } })
.get(this.endpoint, { params: { query: this.filter } })
.then(({ data }) => { .then(({ data }) => {
this.results = data; this.results = data || [];
this.isLoading = false; this.isLoading = false;
}) })
.catch(() => { .catch(() => {
this.isLoading = false; this.isLoading = false;
this.closeSuggestions(); this.closeSuggestions();
createFlash(__('Something went wrong on our end. Please try again.')); createFlash(__('Something went wrong on our end. Please try again.'));
}); });
}, }, 250),
/** /**
* Opens the list of suggestions * Opens the list of suggestions
*/ */
...@@ -126,7 +104,7 @@ export default { ...@@ -126,7 +104,7 @@ export default {
*/ */
closeSuggestions() { closeSuggestions() {
this.showSuggestions = false; this.showSuggestions = false;
this.results = []; this.environmentSearch = '';
}, },
/** /**
* On click, it will: * On click, it will:
...@@ -135,7 +113,6 @@ export default { ...@@ -135,7 +113,6 @@ export default {
* 3. emit an event * 3. emit an event
*/ */
clearInput() { clearInput() {
this.filter = '';
this.closeSuggestions(); this.closeSuggestions();
this.$emit('clearInput'); this.$emit('clearInput');
}, },
...@@ -150,19 +127,16 @@ export default { ...@@ -150,19 +127,16 @@ export default {
*/ */
selectEnvironment(selected) { selectEnvironment(selected) {
this.$emit('selectEnvironment', selected); this.$emit('selectEnvironment', selected);
this.results = [];
this.filter = '';
this.closeSuggestions(); this.closeSuggestions();
}, },
/** /**
* When the user clicks the create button * When the user clicks the create button
* it emits an event with the filter value * it emits an event with the filter value
* Clears the input and closes the list of suggestions.
*/ */
createClicked() { createClicked() {
this.$emit('createClicked', this.filter); this.$emit('createClicked', this.environmentSearch);
this.filter = '';
this.closeSuggestions(); this.closeSuggestions();
}, },
}, },
...@@ -171,44 +145,31 @@ export default { ...@@ -171,44 +145,31 @@ export default {
<template> <template>
<div> <div>
<div class="dropdown position-relative"> <div class="dropdown position-relative">
<gl-icon name="search" class="search-icon-input" /> <gl-search-box-by-type
v-model.trim="environmentSearch"
<input class="js-env-search"
type="text"
class="form-control pl-4 js-env-input"
:aria-label="placeholder" :aria-label="placeholder"
:value="filter"
:placeholder="placeholder" :placeholder="placeholder"
:disabled="disabled" :disabled="disabled"
@input="fetchEnvironments" :is-loading="isLoading"
@focus="fetchEnvironments"
@keyup="fetchEnvironments"
/> />
<gl-deprecated-button
v-if="!disabled"
class="js-clear-search-input btn-transparent clear-search-input position-right-0"
@click="clearInput"
>
<gl-icon name="clear" :aria-label="__('Clear input')" />
</gl-deprecated-button>
<div <div
v-if="showSuggestions" v-if="showSuggestions"
class="dropdown-menu d-block dropdown-menu-selectable dropdown-menu-full-width" class="dropdown-menu d-block dropdown-menu-selectable dropdown-menu-full-width"
> >
<div class="dropdown-content"> <div class="dropdown-content">
<gl-loading-icon v-if="isLoading" /> <ul v-if="results.length">
<ul v-else-if="results.length">
<li v-for="(result, i) in results" :key="i"> <li v-for="(result, i) in results" :key="i">
<gl-deprecated-button class="btn-transparent" @click="selectEnvironment(result)">{{ <gl-deprecated-button class="btn-transparent" @click="selectEnvironment(result)">{{
result result
}}</gl-deprecated-button> }}</gl-deprecated-button>
</li> </li>
</ul> </ul>
<div v-else-if="!results.length" class="text-secondary p-2"> <div v-else-if="!results.length" class="text-secondary gl-p-3">
{{ __('No matching results') }} {{ __('No matching results') }}
</div> </div>
<div v-if="shouldRenderCreateButton" class="dropdown-footer"> <div v-if="shouldRenderCreateButton" class="dropdown-footer">
<gl-deprecated-button <gl-deprecated-button
class="js-create-button btn-blank dropdown-item" class="js-create-button btn-blank dropdown-item"
......
...@@ -410,7 +410,7 @@ export default { ...@@ -410,7 +410,7 @@ export default {
class="col-12" class="col-12"
:value="scope.environmentScope" :value="scope.environmentScope"
:endpoint="environmentsEndpoint" :endpoint="environmentsEndpoint"
:disabled="!canUpdateScope(scope)" :disabled="!canUpdateScope(scope) || scope.environmentScope !== ''"
@selectEnvironment="env => (scope.environmentScope = env)" @selectEnvironment="env => (scope.environmentScope = env)"
@createClicked="env => (scope.environmentScope = env)" @createClicked="env => (scope.environmentScope = env)"
@clearInput="env => (scope.environmentScope = '')" @clearInput="env => (scope.environmentScope = '')"
......
<script> <script>
import { debounce } from 'lodash';
import { import {
GlNewDropdown, GlNewDropdown,
GlNewDropdownDivider, GlNewDropdownDivider,
...@@ -30,7 +31,6 @@ export default { ...@@ -30,7 +31,6 @@ export default {
return { return {
environmentSearch: '', environmentSearch: '',
results: [], results: [],
filter: '',
isLoading: false, isLoading: false,
}; };
}, },
...@@ -40,23 +40,21 @@ export default { ...@@ -40,23 +40,21 @@ export default {
}, },
computed: { computed: {
createEnvironmentLabel() { createEnvironmentLabel() {
return sprintf(__('Create %{environment}'), { environment: this.filter }); return sprintf(__('Create %{environment}'), { environment: this.environmentSearch });
}, },
}, },
methods: { methods: {
addEnvironment(newEnvironment) { addEnvironment(newEnvironment) {
this.$emit('add', newEnvironment); this.$emit('add', newEnvironment);
this.environmentSearch = ''; this.environmentSearch = '';
this.filter = ''; this.results = [];
}, },
fetchEnvironments() { fetchEnvironments: debounce(function debouncedFetchEnvironments() {
this.filter = this.environmentSearch;
this.isLoading = true; this.isLoading = true;
axios axios
.get(this.endpoint, { params: { query: this.filter } }) .get(this.endpoint, { params: { query: this.environmentSearch } })
.then(({ data }) => { .then(({ data }) => {
this.results = data; this.results = data || [];
}) })
.catch(() => { .catch(() => {
createFlash(__('Something went wrong on our end. Please try again.')); createFlash(__('Something went wrong on our end. Please try again.'));
...@@ -64,12 +62,15 @@ export default { ...@@ -64,12 +62,15 @@ export default {
.finally(() => { .finally(() => {
this.isLoading = false; this.isLoading = false;
}); });
}, 250),
setFocus() {
this.$refs.searchBox.focusInput();
}, },
}, },
}; };
</script> </script>
<template> <template>
<gl-new-dropdown class="js-new-environments-dropdown"> <gl-new-dropdown class="js-new-environments-dropdown" @shown="setFocus">
<template #button-content> <template #button-content>
<span class="d-md-none mr-1"> <span class="d-md-none mr-1">
{{ $options.translations.addEnvironmentsLabel }} {{ $options.translations.addEnvironmentsLabel }}
...@@ -77,9 +78,11 @@ export default { ...@@ -77,9 +78,11 @@ export default {
<gl-icon class="d-none d-md-inline-flex" name="plus" /> <gl-icon class="d-none d-md-inline-flex" name="plus" />
</template> </template>
<gl-search-box-by-type <gl-search-box-by-type
ref="searchBox"
v-model.trim="environmentSearch" v-model.trim="environmentSearch"
class="gl-m-3" class="gl-m-3"
@input="fetchEnvironments" @focus="fetchEnvironments"
@keyup="fetchEnvironments"
/> />
<gl-loading-icon v-if="isLoading" /> <gl-loading-icon v-if="isLoading" />
<gl-new-dropdown-item <gl-new-dropdown-item
...@@ -90,12 +93,12 @@ export default { ...@@ -90,12 +93,12 @@ export default {
> >
{{ environment }} {{ environment }}
</gl-new-dropdown-item> </gl-new-dropdown-item>
<template v-else-if="filter.length"> <template v-else-if="environmentSearch.length">
<span ref="noResults" class="text-secondary p-2"> <span ref="noResults" class="text-secondary gl-p-3">
{{ $options.translations.noMatchingResults }} {{ $options.translations.noMatchingResults }}
</span> </span>
<gl-new-dropdown-divider /> <gl-new-dropdown-divider />
<gl-new-dropdown-item @click="addEnvironment(filter)"> <gl-new-dropdown-item @click="addEnvironment(environmentSearch)">
{{ createEnvironmentLabel }} {{ createEnvironmentLabel }}
</gl-new-dropdown-item> </gl-new-dropdown-item>
</template> </template>
......
---
title: Make environments dropdown fetch results as soon as it's focused
merge_request: 40624
author:
type: changed
...@@ -130,7 +130,7 @@ RSpec.describe 'User creates feature flag', :js do ...@@ -130,7 +130,7 @@ RSpec.describe 'User creates feature flag', :js do
within_scope_row(2) do within_scope_row(2) do
within_environment_spec do within_environment_spec do
find('.js-env-input').set("review/*") find('.js-env-search > input').set("review/*")
find('.js-create-button').click find('.js-create-button').click
end end
end end
...@@ -164,7 +164,7 @@ RSpec.describe 'User creates feature flag', :js do ...@@ -164,7 +164,7 @@ RSpec.describe 'User creates feature flag', :js do
within_scope_row(2) do within_scope_row(2) do
within_environment_spec do within_environment_spec do
find('.js-env-input').set('prod') find('.js-env-search > input').set('prod')
click_button 'production' click_button 'production'
end end
end end
......
...@@ -137,7 +137,7 @@ RSpec.describe 'User updates feature flag', :js do ...@@ -137,7 +137,7 @@ RSpec.describe 'User updates feature flag', :js do
before do before do
within_scope_row(3) do within_scope_row(3) do
within_environment_spec do within_environment_spec do
find('.js-env-input').set('production') find('.js-env-search > input').set('production')
find('.js-create-button').click find('.js-create-button').click
end end
end end
......
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import { GlLoadingIcon, GlDeprecatedButton } from '@gitlab/ui'; import { GlLoadingIcon, GlDeprecatedButton, GlSearchBoxByType } from '@gitlab/ui';
import EnvironmentsDropdown from 'ee/feature_flags/components/environments_dropdown.vue'; import EnvironmentsDropdown from 'ee/feature_flags/components/environments_dropdown.vue';
import { TEST_HOST } from 'spec/test_constants'; import { TEST_HOST } from 'spec/test_constants';
import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import httpStatusCodes from '~/lib/utils/http_status';
describe('Feature flags > Environments dropdown ', () => { describe('Feature flags > Environments dropdown ', () => {
let wrapper; let wrapper;
let mock; let mock;
const results = ['production', 'staging'];
const factory = props => { const factory = props => {
wrapper = shallowMount(EnvironmentsDropdown, { wrapper = shallowMount(EnvironmentsDropdown, {
propsData: { propsData: {
...@@ -18,6 +20,9 @@ describe('Feature flags > Environments dropdown ', () => { ...@@ -18,6 +20,9 @@ describe('Feature flags > Environments dropdown ', () => {
}); });
}; };
const findEnvironmentSearchInput = () => wrapper.find(GlSearchBoxByType);
const findDropdownMenu = () => wrapper.find('.dropdown-menu');
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
mock.restore(); mock.restore();
...@@ -30,98 +35,111 @@ describe('Feature flags > Environments dropdown ', () => { ...@@ -30,98 +35,111 @@ describe('Feature flags > Environments dropdown ', () => {
describe('without value', () => { describe('without value', () => {
it('renders the placeholder', () => { it('renders the placeholder', () => {
factory(); factory();
expect(findEnvironmentSearchInput().vm.$attrs.placeholder).toBe('Search an environment spec');
expect(wrapper.find('input').attributes('placeholder')).toEqual('Search an environment spec');
}); });
}); });
describe('with value', () => { describe('with value', () => {
it('sets filter to equal the value', () => { it('sets filter to equal the value', () => {
factory({ value: 'production' }); factory({ value: 'production' });
expect(findEnvironmentSearchInput().props('value')).toBe('production');
});
});
expect(wrapper.vm.filter).toEqual('production'); describe('on focus', () => {
it('sets results with the received data', async () => {
mock.onGet(`${TEST_HOST}/environments.json'`).replyOnce(httpStatusCodes.OK, results);
factory();
findEnvironmentSearchInput().vm.$emit('focus');
await waitForPromises();
await wrapper.vm.$nextTick();
expect(wrapper.find('.dropdown-content > ul').exists()).toBe(true);
expect(wrapper.findAll('.dropdown-content > ul > li').exists()).toBe(true);
});
});
describe('on keyup', () => {
it('sets results with the received data', async () => {
mock.onGet(`${TEST_HOST}/environments.json'`).replyOnce(httpStatusCodes.OK, results);
factory();
findEnvironmentSearchInput().vm.$emit('keyup');
await waitForPromises();
await wrapper.vm.$nextTick();
expect(wrapper.find('.dropdown-content > ul').exists()).toBe(true);
expect(wrapper.findAll('.dropdown-content > ul > li').exists()).toBe(true);
}); });
}); });
describe('on input change', () => { describe('on input change', () => {
const results = ['production', 'staging'];
describe('on success', () => { describe('on success', () => {
beforeEach(() => { beforeEach(async () => {
mock.onGet(`${TEST_HOST}/environments.json'`).replyOnce(200, results); mock.onGet(`${TEST_HOST}/environments.json'`).replyOnce(httpStatusCodes.OK, results);
factory(); factory();
findEnvironmentSearchInput().vm.$emit('focus');
wrapper.find('input').setValue('production'); findEnvironmentSearchInput().vm.$emit('input', 'production');
await waitForPromises();
await wrapper.vm.$nextTick();
}); });
it('sets filter value', () => { it('sets filter value', () => {
expect(wrapper.vm.filter).toEqual('production'); expect(findEnvironmentSearchInput().props('value')).toBe('production');
}); });
describe('with received data', () => { describe('with received data', () => {
beforeEach(done => setImmediate(() => done()));
it('sets is loading to false', () => { it('sets is loading to false', () => {
expect(wrapper.vm.isLoading).toEqual(false); expect(wrapper.vm.isLoading).toBe(false);
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
expect(wrapper.find(GlLoadingIcon).exists()).toEqual(false);
});
it('sets results with the received data', () => {
expect(wrapper.vm.results).toEqual(results);
}); });
it('sets showSuggestions to true', () => { it('shows the suggestions', () => {
expect(wrapper.vm.showSuggestions).toEqual(true); expect(findDropdownMenu().exists()).toBe(true);
}); });
it('emits event when a suggestion is clicked', () => { it('emits event when a suggestion is clicked', async () => {
const button = wrapper const button = wrapper
.findAll(GlDeprecatedButton) .findAll(GlDeprecatedButton)
.filter(b => b.text() === 'production') .filter(b => b.text() === 'production')
.at(0); .at(0);
button.vm.$emit('click'); button.vm.$emit('click');
await wrapper.vm.$nextTick();
return wrapper.vm.$nextTick().then(() => { expect(wrapper.emitted('selectEnvironment')).toEqual([['production']]);
expect(wrapper.emitted('selectEnvironment')).toEqual([['production']]);
});
}); });
}); });
describe('on click clear button', () => { describe('on click clear button', () => {
beforeEach(() => { beforeEach(async () => {
wrapper.find(GlDeprecatedButton).vm.$emit('click'); wrapper.find(GlDeprecatedButton).vm.$emit('click');
await wrapper.vm.$nextTick();
}); });
it('resets filter value', () => { it('resets filter value', () => {
expect(wrapper.vm.filter).toEqual(''); expect(findEnvironmentSearchInput().props('value')).toBe('');
}); });
it('closes list of suggestions', () => { it('closes list of suggestions', () => {
expect(wrapper.vm.showSuggestions).toEqual(false); expect(wrapper.vm.showSuggestions).toBe(false);
}); });
}); });
}); });
}); });
describe('on click create button', () => { describe('on click create button', () => {
beforeEach(done => { beforeEach(async () => {
mock.onGet(`${TEST_HOST}/environments.json'`).replyOnce(200, []); mock.onGet(`${TEST_HOST}/environments.json'`).replyOnce(httpStatusCodes.OK, []);
factory(); factory();
findEnvironmentSearchInput().vm.$emit('focus');
wrapper.find('input').setValue('production'); findEnvironmentSearchInput().vm.$emit('input', 'production');
await waitForPromises();
setImmediate(() => done()); await wrapper.vm.$nextTick();
}); });
it('emits create event', () => { it('emits create event', async () => {
wrapper wrapper
.findAll(GlDeprecatedButton) .findAll(GlDeprecatedButton)
.at(1) .at(0)
.vm.$emit('click'); .vm.$emit('click');
await wrapper.vm.$nextTick();
return wrapper.vm.$nextTick().then(() => { expect(wrapper.emitted('createClicked')).toEqual([['production']]);
expect(wrapper.emitted('createClicked')).toEqual([['production']]);
});
}); });
}); });
}); });
...@@ -3,6 +3,7 @@ import MockAdapter from 'axios-mock-adapter'; ...@@ -3,6 +3,7 @@ import MockAdapter from 'axios-mock-adapter';
import { GlLoadingIcon, GlSearchBoxByType, GlNewDropdownItem } from '@gitlab/ui'; import { GlLoadingIcon, GlSearchBoxByType, GlNewDropdownItem } from '@gitlab/ui';
import NewEnvironmentsDropdown from 'ee/feature_flags/components/new_environments_dropdown.vue'; import NewEnvironmentsDropdown from 'ee/feature_flags/components/new_environments_dropdown.vue';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import httpStatusCodes from '~/lib/utils/http_status';
const TEST_HOST = '/test'; const TEST_HOST = '/test';
const TEST_SEARCH = 'production'; const TEST_SEARCH = 'production';
...@@ -29,14 +30,15 @@ describe('New Environments Dropdown', () => { ...@@ -29,14 +30,15 @@ describe('New Environments Dropdown', () => {
axiosMock.onGet(TEST_HOST).reply(() => { axiosMock.onGet(TEST_HOST).reply(() => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true); expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
}); });
wrapper.find(GlSearchBoxByType).vm.$emit('input', TEST_SEARCH); wrapper.find(GlSearchBoxByType).vm.$emit('focus');
return axios.waitForAll(); return axios.waitForAll();
}); });
it('should not show any dropdown items', () => { it('should not show any dropdown items', () => {
axiosMock.onGet(TEST_HOST).reply(() => { axiosMock.onGet(TEST_HOST).reply(() => {
expect(wrapper.findAll(GlNewDropdownItem)).toHaveLength(0); expect(wrapper.findAll(GlNewDropdownItem)).toHaveLength(0);
}); });
wrapper.find(GlSearchBoxByType).vm.$emit('input', TEST_SEARCH); wrapper.find(GlSearchBoxByType).vm.$emit('focus');
return axios.waitForAll(); return axios.waitForAll();
}); });
}); });
...@@ -45,6 +47,7 @@ describe('New Environments Dropdown', () => { ...@@ -45,6 +47,7 @@ describe('New Environments Dropdown', () => {
let item; let item;
beforeEach(() => { beforeEach(() => {
axiosMock.onGet(TEST_HOST).reply(200, []); axiosMock.onGet(TEST_HOST).reply(200, []);
wrapper.find(GlSearchBoxByType).vm.$emit('focus');
wrapper.find(GlSearchBoxByType).vm.$emit('input', TEST_SEARCH); wrapper.find(GlSearchBoxByType).vm.$emit('input', TEST_SEARCH);
return axios return axios
.waitForAll() .waitForAll()
...@@ -71,23 +74,28 @@ describe('New Environments Dropdown', () => { ...@@ -71,23 +74,28 @@ describe('New Environments Dropdown', () => {
describe('with results', () => { describe('with results', () => {
let items; let items;
beforeEach(() => { beforeEach(() => {
axiosMock.onGet(TEST_HOST).reply(200, ['prod', 'production']); axiosMock.onGet(TEST_HOST).reply(httpStatusCodes.OK, ['prod', 'production']);
wrapper.find(GlSearchBoxByType).vm.$emit('focus');
wrapper.find(GlSearchBoxByType).vm.$emit('input', 'prod'); wrapper.find(GlSearchBoxByType).vm.$emit('input', 'prod');
return axios.waitForAll().then(() => { return axios.waitForAll().then(() => {
items = wrapper.findAll(GlNewDropdownItem); items = wrapper.findAll(GlNewDropdownItem);
}); });
}); });
it('should display one item per result', () => { it('should display one item per result', () => {
expect(items).toHaveLength(2); expect(items).toHaveLength(2);
}); });
it('should emit an add if an item is clicked', () => { it('should emit an add if an item is clicked', () => {
items.at(0).vm.$emit('click'); items.at(0).vm.$emit('click');
expect(wrapper.emitted('add')).toEqual([['prod']]); expect(wrapper.emitted('add')).toEqual([['prod']]);
}); });
it('should not display a create label', () => { it('should not display a create label', () => {
items = items.filter(i => i.text().startsWith('Create')); items = items.filter(i => i.text().startsWith('Create'));
expect(items).toHaveLength(0); expect(items).toHaveLength(0);
}); });
it('should not display a message about no results', () => { it('should not display a message about no results', () => {
expect(wrapper.find({ ref: 'noResults' }).exists()).toBe(false); expect(wrapper.find({ ref: 'noResults' }).exists()).toBe(false);
}); });
......
...@@ -5054,9 +5054,6 @@ msgstr "" ...@@ -5054,9 +5054,6 @@ msgstr ""
msgid "Clear due date" msgid "Clear due date"
msgstr "" msgstr ""
msgid "Clear input"
msgstr ""
msgid "Clear recent searches" msgid "Clear recent searches"
msgstr "" msgstr ""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment