// ====== tests import { nextTick } from 'vue' import { mount } from '../framework' import { FilterPosts } from '../app/FilterPosts' describe('FilterPosts', () => { it('renders today posts by default', async () => { const wrapper = mount(FilterPosts) expect(wrapper.find('.post').text()).toBe('In the news today...') expect(wrapper.findAll('.post')).toHaveLength(1) }) it('toggles the filter', async () => { const wrapper = mount(FilterPosts) wrapper.findAll('button')[1].trigger('click') await nextTick() expect(wrapper.findAll('.post')).toHaveLength(2) expect(wrapper.find('h1').text()).toBe('Posts from this week') expect(wrapper.findAll('.post')[0].text()).toBe('In the news today...') expect(wrapper.findAll('.post')[1].text()).toBe('In the news this week...') }) }) // ====== component import { defineComponent, ref, h, computed } from 'vue' import moment, { Moment } from 'moment' interface Post { id: number title: string created: Moment } const posts: Post[] = [ { id: 1, title: 'In the news today...', created: moment() }, { id: 2, title: 'In the news this week...', created: moment().add(4 ,'days') } ] export const NewsPost = defineComponent({ props: { post: { type: Object as () => Post, required: true }, }, setup(props) { return () => h('div', { className: 'post' }, props.post.title) } }) type FilterPeriod = 'today' | 'this week' const filters: FilterPeriod[] = ['today', 'this week'] export const Filter = defineComponent({ props: { filter: { type: String as () => FilterPeriod, required: true } }, setup(props, ctx) { return () => h('button', { onClick: () => ctx.emit('select', props.filter) }, props.filter) } }) export const FilterPosts = defineComponent({ setup() { const selectedFilter = ref<FilterPeriod>('today') const filteredPosts = computed(() => { return posts.filter(post => { if (selectedFilter.value === 'today') { return post.created.isSameOrBefore(moment().add(0, 'days')) } if (selectedFilter.value === 'this week') { return post.created.isSameOrBefore(moment().add(1, 'week')) } return post }) }) return () => h('div', [ h('h1', `Posts from ${selectedFilter.value}`), filters.map(filter => h(Filter, { filter, onSelect: filter => selectedFilter.value = filter })), filteredPosts.value.map(post => h(NewsPost, { post })) ] ) } })