Commit 323aade4 authored by Kushal Pandya's avatar Kushal Pandya

Merge branch 'cngo-refactor-tokens-to-use-base-token' into 'master'

Refactor filtered tokens to use BaseToken

See merge request gitlab-org/gitlab!68281
parents ea10c52c f421e409
<script>
import {
GlToken,
GlFilteredSearchToken,
GlFilteredSearchSuggestion,
GlDropdownDivider,
GlLoadingIcon,
} from '@gitlab/ui';
import { debounce } from 'lodash';
import { GlFilteredSearchSuggestion } from '@gitlab/ui';
import createFlash from '~/flash';
import { __ } from '~/locale';
import { DEBOUNCE_DELAY } from '../constants';
import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue';
export default {
components: {
GlToken,
GlFilteredSearchToken,
BaseToken,
GlFilteredSearchSuggestion,
GlDropdownDivider,
GlLoadingIcon,
},
props: {
active: {
type: Boolean,
required: true,
},
config: {
type: Object,
required: true,
......@@ -34,82 +26,62 @@ export default {
data() {
return {
branches: this.config.initialBranches || [],
defaultBranches: this.config.defaultBranches || [],
loading: true,
loading: false,
};
},
computed: {
currentValue() {
return this.value.data.toLowerCase();
},
activeBranch() {
return this.branches.find((branch) => branch.name.toLowerCase() === this.currentValue);
},
},
watch: {
active: {
immediate: true,
handler(newValue) {
if (!newValue && !this.branches.length) {
this.fetchBranchBySearchTerm(this.value.data);
}
},
defaultBranches() {
return this.config.defaultBranches || [];
},
},
methods: {
fetchBranchBySearchTerm(searchTerm) {
getActiveBranch(branches, data) {
return branches.find((branch) => branch.name.toLowerCase() === data.toLowerCase());
},
fetchBranches(searchTerm) {
this.loading = true;
this.config
.fetchBranches(searchTerm)
.then(({ data }) => {
this.branches = data;
})
.catch(() => createFlash({ message: __('There was a problem fetching branches.') }))
.catch(() => {
createFlash({ message: __('There was a problem fetching branches.') });
})
.finally(() => {
this.loading = false;
});
},
searchBranches: debounce(function debouncedSearch({ data }) {
this.fetchBranchBySearchTerm(data);
}, DEBOUNCE_DELAY),
},
};
</script>
<template>
<gl-filtered-search-token
<base-token
:active="active"
:config="config"
v-bind="{ ...$props, ...$attrs }"
:value="value"
:default-suggestions="defaultBranches"
:suggestions="branches"
:suggestions-loading="loading"
:get-active-token-value="getActiveBranch"
@fetch-suggestions="fetchBranches"
v-on="$listeners"
@input="searchBranches"
>
<template #view-token="{ inputValue }">
<gl-token variant="search-value">{{
activeBranch ? activeBranch.name : inputValue
}}</gl-token>
<template #view="{ viewTokenProps: { inputValue, activeTokenValue } }">
{{ activeTokenValue ? activeTokenValue.name : inputValue }}
</template>
<template #suggestions>
<template #suggestions-list="{ suggestions }">
<gl-filtered-search-suggestion
v-for="branch in defaultBranches"
:key="branch.value"
:value="branch.value"
>
{{ branch.text }}
</gl-filtered-search-suggestion>
<gl-dropdown-divider v-if="defaultBranches.length" />
<gl-loading-icon v-if="loading" size="sm" />
<template v-else>
<gl-filtered-search-suggestion
v-for="branch in branches"
v-for="branch in suggestions"
:key="branch.id"
:value="branch.name"
>
<div class="gl-display-flex">
<span class="gl-display-inline-block gl-mr-3 gl-p-3"></span>
<div>{{ branch.name }}</div>
{{ branch.name }}
</div>
</gl-filtered-search-suggestion>
</template>
</template>
</gl-filtered-search-token>
</base-token>
</template>
<script>
import {
GlFilteredSearchToken,
GlFilteredSearchSuggestion,
GlDropdownDivider,
GlLoadingIcon,
} from '@gitlab/ui';
import { debounce } from 'lodash';
import { GlFilteredSearchSuggestion } from '@gitlab/ui';
import createFlash from '~/flash';
import { __ } from '~/locale';
import { DEBOUNCE_DELAY, DEFAULT_NONE_ANY } from '../constants';
import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue';
import { DEFAULT_NONE_ANY } from '../constants';
import { stripQuotes } from '../filtered_search_utils';
export default {
components: {
GlFilteredSearchToken,
BaseToken,
GlFilteredSearchSuggestion,
GlDropdownDivider,
GlLoadingIcon,
},
props: {
active: {
type: Boolean,
required: true,
},
config: {
type: Object,
required: true,
......@@ -33,87 +28,63 @@ export default {
data() {
return {
emojis: this.config.initialEmojis || [],
defaultEmojis: this.config.defaultEmojis || DEFAULT_NONE_ANY,
loading: true,
loading: false,
};
},
computed: {
currentValue() {
return this.value.data.toLowerCase();
},
activeEmoji() {
return this.emojis.find(
(emoji) => emoji.name.toLowerCase() === stripQuotes(this.currentValue),
);
},
},
watch: {
active: {
immediate: true,
handler(newValue) {
if (!newValue && !this.emojis.length) {
this.fetchEmojiBySearchTerm(this.value.data);
}
},
defaultEmojis() {
return this.config.defaultEmojis || DEFAULT_NONE_ANY;
},
},
methods: {
fetchEmojiBySearchTerm(searchTerm) {
getActiveEmoji(emojis, data) {
return emojis.find((emoji) => emoji.name.toLowerCase() === stripQuotes(data).toLowerCase());
},
fetchEmojis(searchTerm) {
this.loading = true;
this.config
.fetchEmojis(searchTerm)
.then((res) => {
this.emojis = Array.isArray(res) ? res : res.data;
.then((response) => {
this.emojis = Array.isArray(response) ? response : response.data;
})
.catch(() => {
createFlash({ message: __('There was a problem fetching emojis.') });
})
.catch(() =>
createFlash({
message: __('There was a problem fetching emojis.'),
}),
)
.finally(() => {
this.loading = false;
});
},
searchEmojis: debounce(function debouncedSearch({ data }) {
this.fetchEmojiBySearchTerm(data);
}, DEBOUNCE_DELAY),
},
};
</script>
<template>
<gl-filtered-search-token
<base-token
:active="active"
:config="config"
v-bind="{ ...$props, ...$attrs }"
:value="value"
:default-suggestions="defaultEmojis"
:suggestions="emojis"
:suggestions-loading="loading"
:get-active-token-value="getActiveEmoji"
@fetch-suggestions="fetchEmojis"
v-on="$listeners"
@input="searchEmojis"
>
<template #view="{ inputValue }">
<gl-emoji v-if="activeEmoji" :data-name="activeEmoji.name" />
<span v-else>{{ inputValue }}</span>
<template #view="{ viewTokenProps: { inputValue, activeTokenValue } }">
<gl-emoji v-if="activeTokenValue" :data-name="activeTokenValue.name" />
<template v-else>{{ inputValue }}</template>
</template>
<template #suggestions>
<template #suggestions-list="{ suggestions }">
<gl-filtered-search-suggestion
v-for="emoji in defaultEmojis"
:key="emoji.value"
:value="emoji.value"
>
{{ emoji.value }}
</gl-filtered-search-suggestion>
<gl-dropdown-divider v-if="defaultEmojis.length" />
<gl-loading-icon v-if="loading" size="sm" />
<template v-else>
<gl-filtered-search-suggestion
v-for="emoji in emojis"
v-for="emoji in suggestions"
:key="emoji.name"
:value="emoji.name"
>
<div class="gl-display-flex">
<gl-emoji :data-name="emoji.name" />
<span class="gl-ml-3">{{ emoji.name }}</span>
<gl-emoji class="gl-mr-3" :data-name="emoji.name" />
{{ emoji.name }}
</div>
</gl-filtered-search-suggestion>
</template>
</template>
</gl-filtered-search-token>
</base-token>
</template>
<script>
import {
GlDropdownDivider,
GlFilteredSearchSuggestion,
GlFilteredSearchToken,
GlLoadingIcon,
} from '@gitlab/ui';
import { debounce } from 'lodash';
import { GlFilteredSearchSuggestion } from '@gitlab/ui';
import createFlash from '~/flash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { __ } from '~/locale';
import { DEBOUNCE_DELAY, DEFAULT_ITERATIONS } from '../constants';
import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue';
import { DEFAULT_ITERATIONS } from '../constants';
export default {
components: {
GlDropdownDivider,
BaseToken,
GlFilteredSearchSuggestion,
GlFilteredSearchToken,
GlLoadingIcon,
},
props: {
active: {
type: Boolean,
required: true,
},
config: {
type: Object,
required: true,
......@@ -35,84 +32,58 @@ export default {
};
},
computed: {
currentValue() {
return this.value.data;
},
activeIteration() {
return this.iterations.find(
(iteration) => getIdFromGraphQLId(iteration.id) === Number(this.currentValue),
);
},
defaultIterations() {
return this.config.defaultIterations || DEFAULT_ITERATIONS;
},
},
watch: {
active: {
immediate: true,
handler(newValue) {
if (!newValue && !this.iterations.length) {
this.fetchIterationBySearchTerm(this.currentValue);
}
},
},
},
methods: {
getValue(iteration) {
return String(getIdFromGraphQLId(iteration.id));
getActiveIteration(iterations, data) {
return iterations.find((iteration) => this.getValue(iteration) === data);
},
fetchIterationBySearchTerm(searchTerm) {
const fetchPromise = this.config.fetchPath
? this.config.fetchIterations(this.config.fetchPath, searchTerm)
: this.config.fetchIterations(searchTerm);
fetchIterations(searchTerm) {
this.loading = true;
fetchPromise
this.config
.fetchIterations(searchTerm)
.then((response) => {
this.iterations = Array.isArray(response) ? response : response.data;
})
.catch(() => createFlash({ message: __('There was a problem fetching iterations.') }))
.catch(() => {
createFlash({ message: __('There was a problem fetching iterations.') });
})
.finally(() => {
this.loading = false;
});
},
searchIterations: debounce(function debouncedSearch({ data }) {
this.fetchIterationBySearchTerm(data);
}, DEBOUNCE_DELAY),
getValue(iteration) {
return String(getIdFromGraphQLId(iteration.id));
},
},
};
</script>
<template>
<gl-filtered-search-token
<base-token
:active="active"
:config="config"
v-bind="{ ...$props, ...$attrs }"
:value="value"
:default-suggestions="defaultIterations"
:suggestions="iterations"
:suggestions-loading="loading"
:get-active-token-value="getActiveIteration"
@fetch-suggestions="fetchIterations"
v-on="$listeners"
@input="searchIterations"
>
<template #view="{ inputValue }">
{{ activeIteration ? activeIteration.title : inputValue }}
<template #view="{ viewTokenProps: { inputValue, activeTokenValue } }">
{{ activeTokenValue ? activeTokenValue.title : inputValue }}
</template>
<template #suggestions>
<template #suggestions-list="{ suggestions }">
<gl-filtered-search-suggestion
v-for="iteration in defaultIterations"
:key="iteration.value"
:value="iteration.value"
>
{{ iteration.text }}
</gl-filtered-search-suggestion>
<gl-dropdown-divider v-if="defaultIterations.length" />
<gl-loading-icon v-if="loading" size="sm" />
<template v-else>
<gl-filtered-search-suggestion
v-for="iteration in iterations"
v-for="iteration in suggestions"
:key="iteration.id"
:value="getValue(iteration)"
>
{{ iteration.title }}
</gl-filtered-search-suggestion>
</template>
</template>
</gl-filtered-search-token>
</base-token>
</template>
<script>
import {
GlFilteredSearchToken,
GlFilteredSearchSuggestion,
GlDropdownDivider,
GlLoadingIcon,
} from '@gitlab/ui';
import { debounce } from 'lodash';
import { GlFilteredSearchSuggestion } from '@gitlab/ui';
import createFlash from '~/flash';
import { __ } from '~/locale';
import { sortMilestonesByDueDate } from '~/milestones/milestone_utils';
import { DEFAULT_MILESTONES, DEBOUNCE_DELAY } from '../constants';
import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue';
import { DEFAULT_MILESTONES } from '../constants';
import { stripQuotes } from '../filtered_search_utils';
export default {
components: {
GlFilteredSearchToken,
BaseToken,
GlFilteredSearchSuggestion,
GlDropdownDivider,
GlLoadingIcon,
},
props: {
active: {
type: Boolean,
required: true,
},
config: {
type: Object,
required: true,
......@@ -34,36 +29,21 @@ export default {
data() {
return {
milestones: this.config.initialMilestones || [],
defaultMilestones: this.config.defaultMilestones || DEFAULT_MILESTONES,
loading: false,
};
},
computed: {
currentValue() {
return this.value.data.toLowerCase();
},
activeMilestone() {
return this.milestones.find(
(milestone) => milestone.title.toLowerCase() === stripQuotes(this.currentValue),
);
},
},
watch: {
active: {
immediate: true,
handler(newValue) {
if (!newValue && !this.milestones.length) {
this.fetchMilestoneBySearchTerm(this.value.data);
}
},
defaultMilestones() {
return this.config.defaultMilestones || DEFAULT_MILESTONES;
},
},
methods: {
fetchMilestoneBySearchTerm(searchTerm = '') {
if (this.loading) {
return;
}
getActiveMilestone(milestones, data) {
return milestones.find(
(milestone) => milestone.title.toLowerCase() === stripQuotes(data).toLowerCase(),
);
},
fetchMilestones(searchTerm) {
this.loading = true;
this.config
.fetchMilestones(searchTerm)
......@@ -71,47 +51,40 @@ export default {
const data = Array.isArray(response) ? response : response.data;
this.milestones = data.slice().sort(sortMilestonesByDueDate);
})
.catch(() => createFlash({ message: __('There was a problem fetching milestones.') }))
.catch(() => {
createFlash({ message: __('There was a problem fetching milestones.') });
})
.finally(() => {
this.loading = false;
});
},
searchMilestones: debounce(function debouncedSearch({ data }) {
this.fetchMilestoneBySearchTerm(data);
}, DEBOUNCE_DELAY),
},
};
</script>
<template>
<gl-filtered-search-token
<base-token
:active="active"
:config="config"
v-bind="{ ...$props, ...$attrs }"
:value="value"
:default-suggestions="defaultMilestones"
:suggestions="milestones"
:suggestions-loading="loading"
:get-active-token-value="getActiveMilestone"
@fetch-suggestions="fetchMilestones"
v-on="$listeners"
@input="searchMilestones"
>
<template #view="{ inputValue }">
<span>%{{ activeMilestone ? activeMilestone.title : inputValue }}</span>
<template #view="{ viewTokenProps: { inputValue, activeTokenValue } }">
%{{ activeTokenValue ? activeTokenValue.title : inputValue }}
</template>
<template #suggestions>
<template #suggestions-list="{ suggestions }">
<gl-filtered-search-suggestion
v-for="milestone in defaultMilestones"
:key="milestone.value"
:value="milestone.value"
>
{{ milestone.text }}
</gl-filtered-search-suggestion>
<gl-dropdown-divider v-if="defaultMilestones.length" />
<gl-loading-icon v-if="loading" size="sm" />
<template v-else>
<gl-filtered-search-suggestion
v-for="milestone in milestones"
v-for="milestone in suggestions"
:key="milestone.id"
:value="milestone.title"
>
<div>{{ milestone.title }}</div>
{{ milestone.title }}
</gl-filtered-search-suggestion>
</template>
</template>
</gl-filtered-search-token>
</base-token>
</template>
<script>
import { GlDropdownDivider, GlFilteredSearchSuggestion, GlFilteredSearchToken } from '@gitlab/ui';
import { GlFilteredSearchSuggestion } from '@gitlab/ui';
import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue';
import { DEFAULT_NONE_ANY, WEIGHT_TOKEN_SUGGESTIONS_SIZE } from '../constants';
const weights = Array.from(Array(WEIGHT_TOKEN_SUGGESTIONS_SIZE), (_, index) => index.toString());
export default {
components: {
GlDropdownDivider,
BaseToken,
GlFilteredSearchSuggestion,
GlFilteredSearchToken,
},
props: {
active: {
type: Boolean,
required: true,
},
config: {
type: Object,
required: true,
......@@ -23,12 +27,19 @@ export default {
data() {
return {
weights,
defaultWeights: this.config.defaultWeights || DEFAULT_NONE_ANY,
};
},
computed: {
defaultWeights() {
return this.config.defaultWeights || DEFAULT_NONE_ANY;
},
},
methods: {
updateWeights({ data }) {
const weight = parseInt(data, 10);
getActiveWeight(weightSuggestions, data) {
return weightSuggestions.find((weight) => weight === data);
},
updateWeights(searchTerm) {
const weight = parseInt(searchTerm, 10);
this.weights = Number.isNaN(weight) ? weights : [String(weight)];
},
},
......@@ -36,24 +47,20 @@ export default {
</script>
<template>
<gl-filtered-search-token
<base-token
:active="active"
:config="config"
v-bind="{ ...$props, ...$attrs }"
:value="value"
:default-suggestions="defaultWeights"
:suggestions="weights"
:get-active-token-value="getActiveWeight"
@fetch-suggestions="updateWeights"
v-on="$listeners"
@input="updateWeights"
>
<template #suggestions>
<gl-filtered-search-suggestion
v-for="weight in defaultWeights"
:key="weight.value"
:value="weight.value"
>
{{ weight.text }}
</gl-filtered-search-suggestion>
<gl-dropdown-divider v-if="defaultWeights.length" />
<gl-filtered-search-suggestion v-for="weight of weights" :key="weight" :value="weight">
<template #suggestions-list="{ suggestions }">
<gl-filtered-search-suggestion v-for="weight of suggestions" :key="weight" :value="weight">
{{ weight }}
</gl-filtered-search-suggestion>
</template>
</gl-filtered-search-token>
</base-token>
</template>
......@@ -61,40 +61,16 @@ describe('BranchToken', () => {
wrapper.destroy();
});
describe('computed', () => {
beforeEach(async () => {
wrapper = createComponent({ value: { data: mockBranches[0].name } });
wrapper.setData({
branches: mockBranches,
});
await wrapper.vm.$nextTick();
});
describe('currentValue', () => {
it('returns lowercase string for `value.data`', () => {
expect(wrapper.vm.currentValue).toBe('main');
});
});
describe('activeBranch', () => {
it('returns object for currently present `value.data`', () => {
expect(wrapper.vm.activeBranch).toEqual(mockBranches[0]);
});
});
});
describe('methods', () => {
beforeEach(() => {
wrapper = createComponent();
});
describe('fetchBranchBySearchTerm', () => {
describe('fetchBranches', () => {
it('calls `config.fetchBranches` with provided searchTerm param', () => {
jest.spyOn(wrapper.vm.config, 'fetchBranches');
wrapper.vm.fetchBranchBySearchTerm('foo');
wrapper.vm.fetchBranches('foo');
expect(wrapper.vm.config.fetchBranches).toHaveBeenCalledWith('foo');
});
......@@ -102,7 +78,7 @@ describe('BranchToken', () => {
it('sets response to `branches` when request is succesful', () => {
jest.spyOn(wrapper.vm.config, 'fetchBranches').mockResolvedValue({ data: mockBranches });
wrapper.vm.fetchBranchBySearchTerm('foo');
wrapper.vm.fetchBranches('foo');
return waitForPromises().then(() => {
expect(wrapper.vm.branches).toEqual(mockBranches);
......@@ -112,7 +88,7 @@ describe('BranchToken', () => {
it('calls `createFlash` with flash error message when request fails', () => {
jest.spyOn(wrapper.vm.config, 'fetchBranches').mockRejectedValue({});
wrapper.vm.fetchBranchBySearchTerm('foo');
wrapper.vm.fetchBranches('foo');
return waitForPromises().then(() => {
expect(createFlash).toHaveBeenCalledWith({
......@@ -124,7 +100,7 @@ describe('BranchToken', () => {
it('sets `loading` to false when request completes', () => {
jest.spyOn(wrapper.vm.config, 'fetchBranches').mockRejectedValue({});
wrapper.vm.fetchBranchBySearchTerm('foo');
wrapper.vm.fetchBranches('foo');
return waitForPromises().then(() => {
expect(wrapper.vm.loading).toBe(false);
......
......@@ -67,40 +67,16 @@ describe('EmojiToken', () => {
wrapper.destroy();
});
describe('computed', () => {
beforeEach(async () => {
wrapper = createComponent({ value: { data: mockEmojis[0].name } });
wrapper.setData({
emojis: mockEmojis,
});
await wrapper.vm.$nextTick();
});
describe('currentValue', () => {
it('returns lowercase string for `value.data`', () => {
expect(wrapper.vm.currentValue).toBe(mockEmojis[0].name);
});
});
describe('activeEmoji', () => {
it('returns object for currently present `value.data`', () => {
expect(wrapper.vm.activeEmoji).toEqual(mockEmojis[0]);
});
});
});
describe('methods', () => {
beforeEach(() => {
wrapper = createComponent();
});
describe('fetchEmojiBySearchTerm', () => {
describe('fetchEmojis', () => {
it('calls `config.fetchEmojis` with provided searchTerm param', () => {
jest.spyOn(wrapper.vm.config, 'fetchEmojis');
wrapper.vm.fetchEmojiBySearchTerm('foo');
wrapper.vm.fetchEmojis('foo');
expect(wrapper.vm.config.fetchEmojis).toHaveBeenCalledWith('foo');
});
......@@ -108,7 +84,7 @@ describe('EmojiToken', () => {
it('sets response to `emojis` when request is successful', () => {
jest.spyOn(wrapper.vm.config, 'fetchEmojis').mockResolvedValue(mockEmojis);
wrapper.vm.fetchEmojiBySearchTerm('foo');
wrapper.vm.fetchEmojis('foo');
return waitForPromises().then(() => {
expect(wrapper.vm.emojis).toEqual(mockEmojis);
......@@ -118,7 +94,7 @@ describe('EmojiToken', () => {
it('calls `createFlash` with flash error message when request fails', () => {
jest.spyOn(wrapper.vm.config, 'fetchEmojis').mockRejectedValue({});
wrapper.vm.fetchEmojiBySearchTerm('foo');
wrapper.vm.fetchEmojis('foo');
return waitForPromises().then(() => {
expect(createFlash).toHaveBeenCalledWith({
......@@ -130,7 +106,7 @@ describe('EmojiToken', () => {
it('sets `loading` to false when request completes', () => {
jest.spyOn(wrapper.vm.config, 'fetchEmojis').mockRejectedValue({});
wrapper.vm.fetchEmojiBySearchTerm('foo');
wrapper.vm.fetchEmojis('foo');
return waitForPromises().then(() => {
expect(wrapper.vm.loading).toBe(false);
......
import { GlFilteredSearchToken, GlFilteredSearchTokenSegment } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import waitForPromises from 'helpers/wait_for_promises';
import createFlash from '~/flash';
import IterationToken from '~/vue_shared/components/filtered_search_bar/tokens/iteration_token.vue';
import { mockIterationToken } from '../mock_data';
......@@ -13,6 +14,7 @@ describe('IterationToken', () => {
const createComponent = ({ config = mockIterationToken, value = { data: '' } } = {}) =>
mount(IterationToken, {
propsData: {
active: false,
config,
value,
},
......@@ -69,7 +71,7 @@ describe('IterationToken', () => {
config: { ...mockIterationToken, fetchIterations: fetchIterationsSpy },
});
await wrapper.vm.$nextTick();
await waitForPromises();
expect(createFlash).toHaveBeenCalledWith({
message: 'There was a problem fetching iterations.',
......
......@@ -14,12 +14,7 @@ import { sortMilestonesByDueDate } from '~/milestones/milestone_utils';
import { DEFAULT_MILESTONES } from '~/vue_shared/components/filtered_search_bar/constants';
import MilestoneToken from '~/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue';
import {
mockMilestoneToken,
mockMilestones,
mockRegularMilestone,
mockEscapedMilestone,
} from '../mock_data';
import { mockMilestoneToken, mockMilestones, mockRegularMilestone } from '../mock_data';
jest.mock('~/flash');
jest.mock('~/milestones/milestone_utils');
......@@ -70,37 +65,12 @@ describe('MilestoneToken', () => {
wrapper.destroy();
});
describe('computed', () => {
beforeEach(async () => {
// Milestone title with spaces is always enclosed in quotations by component.
wrapper = createComponent({ value: { data: `"${mockEscapedMilestone.title}"` } });
wrapper.setData({
milestones: mockMilestones,
});
await wrapper.vm.$nextTick();
});
describe('currentValue', () => {
it('returns lowercase string for `value.data`', () => {
expect(wrapper.vm.currentValue).toBe('"5.0 rc1"');
});
});
describe('activeMilestone', () => {
it('returns object for currently present `value.data`', () => {
expect(wrapper.vm.activeMilestone).toEqual(mockEscapedMilestone);
});
});
});
describe('methods', () => {
describe('fetchMilestoneBySearchTerm', () => {
describe('fetchMilestones', () => {
it('calls `config.fetchMilestones` with provided searchTerm param', () => {
jest.spyOn(wrapper.vm.config, 'fetchMilestones');
wrapper.vm.fetchMilestoneBySearchTerm('foo');
wrapper.vm.fetchMilestones('foo');
expect(wrapper.vm.config.fetchMilestones).toHaveBeenCalledWith('foo');
});
......@@ -110,7 +80,7 @@ describe('MilestoneToken', () => {
data: mockMilestones,
});
wrapper.vm.fetchMilestoneBySearchTerm();
wrapper.vm.fetchMilestones();
return waitForPromises().then(() => {
expect(wrapper.vm.milestones).toEqual(mockMilestones);
......@@ -121,7 +91,7 @@ describe('MilestoneToken', () => {
it('calls `createFlash` with flash error message when request fails', () => {
jest.spyOn(wrapper.vm.config, 'fetchMilestones').mockRejectedValue({});
wrapper.vm.fetchMilestoneBySearchTerm('foo');
wrapper.vm.fetchMilestones('foo');
return waitForPromises().then(() => {
expect(createFlash).toHaveBeenCalledWith({
......@@ -133,7 +103,7 @@ describe('MilestoneToken', () => {
it('sets `loading` to false when request completes', () => {
jest.spyOn(wrapper.vm.config, 'fetchMilestones').mockRejectedValue({});
wrapper.vm.fetchMilestoneBySearchTerm('foo');
wrapper.vm.fetchMilestones('foo');
return waitForPromises().then(() => {
expect(wrapper.vm.loading).toBe(false);
......
......@@ -12,6 +12,7 @@ describe('WeightToken', () => {
const createComponent = ({ config = mockWeightToken, value = { data: '' } } = {}) =>
mount(WeightToken, {
propsData: {
active: false,
config,
value,
},
......
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