Skip to content

Commit

Permalink
feat(select): add adapter unit-test
Browse files Browse the repository at this point in the history
  • Loading branch information
adenvt committed Jun 6, 2022
1 parent 110df42 commit 760d2ab
Show file tree
Hide file tree
Showing 28 changed files with 766 additions and 130 deletions.
22 changes: 18 additions & 4 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,24 @@ module.exports = {
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/explicit-function-return-type' : 'off',
'@typescript-eslint/strict-boolean-expressions' : 'off',
'align-assignments/align-assignments' : [2, { requiresOnly: false }],
'vue/multi-word-component-names' : 'off',
'vue/no-reserved-component-names' : 'off',
'vue/html-closing-bracket-newline' : [
'@typescript-eslint/member-delimiter-style' : [
'error',
{
multiline: {
delimiter : 'comma',
requireLast: true,
},
singleline: {
delimiter : 'comma',
requireLast: false,
},
multilineDetection: 'brackets',
},
],
'align-assignments/align-assignments': [2, { requiresOnly: false }],
'vue/multi-word-component-names' : 'off',
'vue/no-reserved-component-names' : 'off',
'vue/html-closing-bracket-newline' : [
'error',
{
singleline: 'never',
Expand Down
4 changes: 3 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@
"eslint.packageManager": "yarn",
"eslint.run": "onSave",
"eslint.lintTask.options": "--cache .",
"eslint.lintTask.enable": true
"eslint.lintTask.enable": true,
"volar.autoCompleteRefs": false,
"volar.vueserver.useSecondServer": true,
}
2 changes: 0 additions & 2 deletions components/.vitepress/config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { defineConfig } from 'vitepress'
import fonts from 'vite-plugin-fonts'

export default defineConfig({
base : process.env.BASE_URL ?? '/design-system/',
Expand All @@ -14,7 +13,6 @@ export default defineConfig({
nextLinks : false,
prevLinks : false,
lastUpdated : 'Last Updated',
smoothScroll: true,
nav : [],
sidebar : [
{
Expand Down
4 changes: 1 addition & 3 deletions components/avatar/Avatar.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@ import Avatar from './Avatar.vue'
import IconUser from '@carbon/icons-vue/lib/events/20'
import MockImage from './__mocks__/image'
import { vi } from 'vitest'
import { delay } from 'nanodelay'

vi.stubGlobal('Image', MockImage)

// eslint-disable-next-line @typescript-eslint/promise-function-async
const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))

it('should render properly', () => {
const screen = render({
components: { Avatar },
Expand Down
12 changes: 10 additions & 2 deletions components/calendar/Calendar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,18 @@ import Button from '../button/Button.vue'
import IconNext from '@carbon/icons-vue/lib/chevron--right/20'
import IconBack from '@carbon/icons-vue/lib/chevron--left/20'
import {
defineComponent, ref, computed, watch, toRef, PropType,
defineComponent,
ref,
computed,
watch,
toRef,
PropType,
} from 'vue-demi'
import {
CalendarAdapter, CalendarFormat, CalendarItem, CalendarMode,
CalendarAdapter,
CalendarFormat,
CalendarItem,
CalendarMode,
} from './adapter/adapter'
import DateAdapter from './adapter/date'
import MonthAdapter from './adapter/month'
Expand Down
30 changes: 15 additions & 15 deletions components/calendar/adapter/adapter.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
import { Ref } from 'vue-demi'

export interface CalendarItem {
value: Date
text: string
disabled: boolean
readonly: boolean
active: boolean
value: Date,
text: string,
disabled: boolean,
readonly: boolean,
active: boolean,
}

export interface CalendarContext {
cursor: Ref<Date>
model: Ref<Date>
max: Ref<Date | undefined>
min: Ref<Date | undefined>
cursor: Ref<Date>,
model: Ref<Date>,
max: Ref<Date | undefined>,
min: Ref<Date | undefined>,
}

export interface CalendarAdapter {
getItems: (this: this, context: CalendarContext) => CalendarItem[]
getTitle: (this: this, context: CalendarContext) => string
getNextCursor: (this: this, context: CalendarContext) => Date
getPrevCursor: (this: this, context: CalendarContext) => Date
getItems: (this: this, context: CalendarContext) => CalendarItem[],
getTitle: (this: this, context: CalendarContext) => string,
getNextCursor: (this: this, context: CalendarContext) => Date,
getPrevCursor: (this: this, context: CalendarContext) => Date,

canNext: (this: this, context: CalendarContext) => boolean
canPrev: (this: this, context: CalendarContext) => boolean
canNext: (this: this, context: CalendarContext) => boolean,
canPrev: (this: this, context: CalendarContext) => boolean,
}

export const CalendarFormat = [
Expand Down
24 changes: 12 additions & 12 deletions components/checkbox/use-checkbox.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { syncRef } from '@vueuse/shared'
import {
computed, getCurrentInstance, ref,
computed,
getCurrentInstance,
ref,
} from 'vue-demi'
import { InputProps } from '../input/use-input'
import { valueIn, isEqual } from '../utils/value'
Expand All @@ -12,9 +14,9 @@ function isChecked (modelValue: unknown, checked: unknown): boolean {
}

export interface CheckboxProps extends InputProps<unknown> {
checked: boolean
value: unknown
uncheckedValue: unknown
checked: boolean,
value: unknown,
uncheckedValue: unknown,
}

export function useVModel (props: CheckboxProps) {
Expand All @@ -32,14 +34,12 @@ export function useVModel (props: CheckboxProps) {

if (Array.isArray(props.modelValue)) {
if (value) {
if (!valueIn(props.modelValue, newValue)) emit('update:modelValue', [...props.modelValue, newValue])
} else {
emit(
'update:modelValue',
props.modelValue.filter((old) => !isEqual(old, checked)),
)
}
} else emit('update:modelValue', newValue)
if (!valueIn(props.modelValue, newValue))
emit('update:modelValue', [...props.modelValue, newValue])
} else
emit('update:modelValue', props.modelValue.filter((old) => !isEqual(old, checked)))
} else
emit('update:modelValue', newValue)

emit('change', value)
},
Expand Down
2 changes: 1 addition & 1 deletion components/dropdown/DropdownGroup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export default defineComponent({
},
},
setup (props, { slots }) {
const context = inject(DROPDOWN_TREE)
const context = inject(DROPDOWN_TREE, undefined, true)
const transition = ref<'slide-left' | 'slide-right' | 'none'>('slide-left')
const isRoot = computed(() => {
Expand Down
2 changes: 1 addition & 1 deletion components/input/use-input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
} from 'vue-demi'

export interface InputProps<V = string> {
modelValue: V
modelValue: V,
}

export function useVModel<V> (props: InputProps<V>): Ref<V> {
Expand Down
4 changes: 1 addition & 3 deletions components/overlay/utils/use-loading.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { vi } from 'vitest'
import { nextTick } from 'vue-demi'
import useLoading from './use-loading'

// eslint-disable-next-line @typescript-eslint/promise-function-async
const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))
import { delay } from 'nanodelay'

beforeEach(() => {
vi.useFakeTimers()
Expand Down
2 changes: 1 addition & 1 deletion components/overlay/utils/use-loading.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { tryOnMounted } from '@vueuse/shared'
import { computed, ref } from 'vue-demi'

export interface LoadingOptions {
elapsed: number | boolean
elapsed: number | boolean,
}

export default function useLoading (options_?: LoadingOptions) {
Expand Down
17 changes: 13 additions & 4 deletions components/select/Select.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
v-model="isOpen"
class="select"
data-testid="select"
aria-label="select"
:class="classNames">
<template #activator>
<Input
v-model="search"
data-testid="select-search"
class="select__search"
:placeholder="placeholder"
:disabled="disabled"
Expand All @@ -15,7 +17,9 @@
</template>

<template v-if="!isLoading && items.length === 0">
<div class="select__empty">
<div
data-testid="select-item"
class="select__empty">
<slot name="empty">
No Data
</slot>
Expand All @@ -26,13 +30,16 @@
<DropdownItem
v-for="(item, i) in items"
:key="i"
data-testid="select-item"
:class="{ selected: isSelected(item) }"
@click="select(item)">
<slot
name="option"
:item="item">
<div class="select__option">
<span class="select__option-text">{{ item.text }}</span>
<span class="select__option-text">
{{ item.text }}
</span>
<IconCheck
class="select__option-checked" />
</div>
Expand All @@ -41,7 +48,9 @@
</template>

<template v-if="isLoading">
<div class="select__loading">
<div
data-testid="select-loading"
class="select__loading">
<slot name="loading">
<IconLoading
width="14"
Expand Down Expand Up @@ -126,7 +135,7 @@ export default defineComponent({
setup (props, { emit }) {
const keyword = ref('')
const isOpen = ref(false)
const isLoading = useLoading()
const isLoading = useLoading({ elapsed: false })
const context = {
props,
keyword,
Expand Down
10 changes: 10 additions & 0 deletions components/select/__mocks__/use-on-scroll.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export const handlers: Array<() => void> = []

export function triggerScroll () {
for (const handler of handlers)
handler()
}

export function onScrollBottom (_: unknown, handler: () => void): void {
handlers.push(handler)
}
88 changes: 88 additions & 0 deletions components/select/adapter/adapter.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { SelectProps, SelectItem } from '../use-select'
import { useOptionsProp } from './adapter'

it('should be able to convert Array of String into Array of SelectItem', () => {
const props: SelectProps = {
modelValue: undefined,
selected : undefined,
options : [
'Apple',
'Grape',
'Orange',
],
}

const result = useOptionsProp(props)
const expected: SelectItem[] = [
{
text : 'Apple',
value: 'Apple',
},
{
text : 'Grape',
value: 'Grape',
},
{
text : 'Orange',
value: 'Orange',
},
]

expect(result.value).toBeArray()
expect(result.value).toStrictEqual(expected)
})

it('should be return as is if options is already an Array of SelectItem', () => {
const props: SelectProps = {
modelValue: undefined,
selected : undefined,
options : [
{
text : 'Apple',
value: 'Apple',
},
{
text : 'Grape',
value: 'Grape',
},
{
text : 'Orange',
value: 'Orange',
},
],
}

const result = useOptionsProp(props)
const expected: SelectItem[] = [
{
text : 'Apple',
value: 'Apple',
},
{
text : 'Grape',
value: 'Grape',
},
{
text : 'Orange',
value: 'Orange',
},
]

expect(result.value).toBeArray()
expect(result.value).toStrictEqual(expected)
})

it('should return empty array if props is not valid array', () => {
const props: SelectProps = {
modelValue: undefined,
selected : undefined,
// @ts-expect-error
options : {},
}

const result = useOptionsProp(props)
const expected: SelectItem[] = []

expect(result.value).toBeArray()
expect(result.value).toStrictEqual(expected)
})
10 changes: 5 additions & 5 deletions components/select/adapter/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import { computed, Ref } from 'vue-demi'
import { SelectItem, SelectProps } from '../use-select'

export interface AdapterContext {
props: SelectProps
keyword: Ref<string>
isOpen: Ref<boolean>
isLoading: Ref<boolean>
props: SelectProps,
keyword: Ref<string>,
isOpen: Ref<boolean>,
isLoading: Ref<boolean>,
}

export interface Adapter {
setup: (context: AdapterContext) => Ref<SelectItem[]>
setup: (context: AdapterContext) => Ref<SelectItem[]>,
}

/**
Expand Down
Loading

0 comments on commit 760d2ab

Please sign in to comment.