Skip to content

Commit

Permalink
feat(options): change logic on change options (#74)
Browse files Browse the repository at this point in the history
  • Loading branch information
smithoo authored Feb 6, 2024
1 parent e505218 commit d468803
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export default defineComponent({
inputValue.value = [];
}
const { getOptionLabel, getOptionValue } = useInputOption(options, optionLabel, optionValue, { onClear });
const { getOptionLabel, getOptionValue } = useInputOption(inputValue, options, optionLabel, optionValue);
function requiredCheck() {
return required.value && inputValue.value.length === 0 ? 'required' : '';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,26 +45,26 @@ describe('vs-checkbox-set', () => {
expect(wrapper.html()).toContain('C');
});

it('options가 변경되면 checkbox set value가 초기화 된다', async () => {
it('options가 변경되면 checkbox-set value 중 일치하는 값은 남는다', async () => {
// given
const wrapper: ReturnType<typeof mountComponent> = mount(VsCheckboxSet, {
props: {
modelValue: ['A'],
modelValue: ['B', 'C'],
'onUpdate:modelValue': (e) => wrapper.setProps({ modelValue: e }),
options: ['A', 'B', 'C'],
},
});

// when
await wrapper.setProps({ options: ['A', 'B', 'C', 'D'] });
await wrapper.setProps({ options: ['C', 'D', 'E'] });

// then
const updateModelValueEvent = wrapper.emitted('update:modelValue');
expect(updateModelValueEvent).toHaveLength(1);
expect(updateModelValueEvent?.[0]).toEqual([[]]);
expect(updateModelValueEvent?.[0]).toEqual([['C']]);
});

it('options가 변경되어도 이전 값과 deep equal 하면 checkbox set value가 그대로 유지된다', async () => {
it('options가 변경되어도 이전 값과 deep equal 하면 checkbox-set value가 그대로 유지된다', async () => {
// given
const wrapper: ReturnType<typeof mountComponent> = mount(VsCheckboxSet, {
props: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,15 @@
import { beforeEach, afterEach, describe, expect, it, vi } from 'vitest';
import { describe, expect, it } from 'vitest';
import { nextTick, ref } from 'vue';
import { useInputOption } from '@/composables';

describe('input option composable', () => {
let onClearSpy = vi.fn();

beforeEach(() => {
onClearSpy = vi.fn();
});

afterEach(() => {
vi.restoreAllMocks();
});

describe('getOptionLabel', () => {
it('option이 string이면 option 그대로 반환한다', () => {
// given
const options = ref(['test']);

// when
const { getOptionLabel } = useInputOption(options, ref(''), ref(''), { onClear: onClearSpy });
const { getOptionLabel } = useInputOption(ref('dummy'), options, ref(''), ref(''));

// then
expect(getOptionLabel(options.value[0])).toBe('test');
Expand All @@ -30,7 +20,7 @@ describe('input option composable', () => {
const options = ref([{ label: 'test' }]);

// when
const { getOptionLabel } = useInputOption(options, ref('label'), ref(''), { onClear: onClearSpy });
const { getOptionLabel } = useInputOption(ref('dummy'), options, ref('label'), ref(''));

// then
expect(getOptionLabel(options.value[0])).toBe('test');
Expand All @@ -41,7 +31,7 @@ describe('input option composable', () => {
const options = ref([{ label: 'test' }]);

// when
const { getOptionLabel } = useInputOption(options, ref(''), ref(''), { onClear: onClearSpy });
const { getOptionLabel } = useInputOption(ref('dummy'), options, ref(''), ref(''));

// then
expect(getOptionLabel(options.value[0])).toBe('{"label":"test"}');
Expand All @@ -52,7 +42,7 @@ describe('input option composable', () => {
const options = ref([{ label: { test: 'test' } }]);

// when
const { getOptionLabel } = useInputOption(options, ref('label.test'), ref(''), { onClear: onClearSpy });
const { getOptionLabel } = useInputOption(ref('dummy'), options, ref('label.test'), ref(''));

// then
expect(getOptionLabel(options.value[0])).toBe('test');
Expand All @@ -65,7 +55,7 @@ describe('input option composable', () => {
const options = ref(['test']);

// when
const { getOptionValue } = useInputOption(options, ref(''), ref(''), { onClear: onClearSpy });
const { getOptionValue } = useInputOption(ref('dummy'), options, ref(''), ref(''));

// then
expect(getOptionValue(options.value[0])).toBe('test');
Expand All @@ -76,7 +66,7 @@ describe('input option composable', () => {
const options = ref([{ label: 'test', value: 'test-value' }]);

// when
const { getOptionValue } = useInputOption(options, ref(''), ref('value'), { onClear: onClearSpy });
const { getOptionValue } = useInputOption(ref('dummy'), options, ref(''), ref('value'));

// then
expect(getOptionValue(options.value[0])).toBe('test-value');
Expand All @@ -87,7 +77,7 @@ describe('input option composable', () => {
const options = ref([{ label: 'test' }]);

// when
const { getOptionValue } = useInputOption(options, ref(''), ref(''), { onClear: onClearSpy });
const { getOptionValue } = useInputOption(ref('dummy'), options, ref(''), ref(''));

// then
expect(getOptionValue(options.value[0])).toBe(options.value[0]);
Expand All @@ -98,25 +88,72 @@ describe('input option composable', () => {
const options = ref([{ label: 'test', value: { test: 'test-value' } }]);

// when
const { getOptionValue } = useInputOption(options, ref(''), ref('value.test'), { onClear: onClearSpy });
const { getOptionValue } = useInputOption(ref('dummy'), options, ref(''), ref('value.test'));

// then
expect(getOptionValue(options.value[0])).toBe('test-value');
});
});

describe('onClear', () => {
it('options가 변경되면 onClear callback이 실행된다', async () => {
// given
const options = ref(['test']);

// when
useInputOption(options, ref(''), ref(''), { onClear: onClearSpy });
options.value = ['test2'];
await nextTick();
describe('options 변경 시', () => {
describe('inputValue가 array인 경우', () => {
it('빈 array인 경우 그대로 빈 array 값이 유지된다', async () => {
// given
const inputValue = ref([]);
const options = ref(['test1', 'test2', 'test3']);

// when
useInputOption(inputValue, options, ref(''), ref(''));
options.value = ['new-test1', 'new-test2', 'new-test3'];
await nextTick();

// then
expect(inputValue.value).toEqual([]);
});

it('바뀐 options 중에 inputValue에 포함된 값이 있다면 유지하고 없으면 제거한다', async () => {
// given
const inputValue = ref(['test1', 'test2']);
const options = ref(['test1', 'test2', 'test3']);

// when
useInputOption(inputValue, options, ref(''), ref(''));
options.value = ['test1', 'new-test2', 'new-test3'];
await nextTick();

// then
expect(inputValue.value).toEqual(['test1']);
});
});

// then
expect(onClearSpy).toHaveBeenCalledTimes(1);
describe('inputValue가 array가 아닌 경우', () => {
it('바뀐 options 중에 inputValue 값이 있다면 유지한다', async () => {
// given
const inputValue = ref('test1');
const options = ref(['test1', 'test2', 'test3']);

// when
useInputOption(inputValue, options, ref(''), ref(''));
options.value = ['test1', 'new-test2', 'new-test3'];
await nextTick();

// then
expect(inputValue.value).toBe('test1');
});

it('바뀐 options 중에 inputValue 값이 없다면 null을 할당한다', async () => {
// given
const inputValue = ref('test1');
const options = ref(['test1', 'test2', 'test3']);

// when
useInputOption(inputValue, options, ref(''), ref(''));
options.value = ['new-test1', 'new-test2', 'new-test3'];
await nextTick();

// then
expect(inputValue.value).toBe(null);
});
});
});
});
20 changes: 16 additions & 4 deletions packages/vlossom/src/composables/input-option-composable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,10 @@ export function getInputOptionProps() {
}

export function useInputOption(
inputValue: Ref<any>,
options: Ref<any[]>,
optionLabel: Ref<string>,
optionValue: Ref<string>,
callbacks: {
onClear: () => void;
},
) {
function getOptionLabel(option: any) {
if (typeof option === 'object') {
Expand Down Expand Up @@ -57,7 +55,21 @@ export function useInputOption(
return;
}

callbacks.onClear();
if (Array.isArray(inputValue.value)) {
inputValue.value = inputValue.value.filter((value) => {
return newOptions.some((o) => {
return getOptionValue(o) === value;
});
});
} else {
const option = newOptions.find((o) => {
return getOptionValue(o) === inputValue.value;
});

if (!option) {
inputValue.value = null;
}
}
});

return {
Expand Down

0 comments on commit d468803

Please sign in to comment.